aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2021-10-07 15:28:36 -0700
committerIan Lance Taylor <iant@golang.org>2021-10-07 15:28:36 -0700
commit0b6b70a0733672600644c8df96942cda5bf86d3d (patch)
tree9a1fbd7f782c54df55ab225ed1be057e3f3b0b8a
parenta5b5cabc91c38710adbe5c8a2b53882abe994441 (diff)
parentfba228e259dd5112851527f2dbb62c5601100985 (diff)
downloadgcc-0b6b70a0733672600644c8df96942cda5bf86d3d.zip
gcc-0b6b70a0733672600644c8df96942cda5bf86d3d.tar.gz
gcc-0b6b70a0733672600644c8df96942cda5bf86d3d.tar.bz2
Merge from trunk revision fba228e259dd5112851527f2dbb62c5601100985.
-rw-r--r--ChangeLog16
-rw-r--r--MAINTAINERS4
-rw-r--r--Makefile.def14
-rw-r--r--Makefile.in8
-rwxr-xr-xconfigure10
-rw-r--r--configure.ac10
-rw-r--r--contrib/ChangeLog5
-rwxr-xr-xcontrib/filter-clang-warnings.py1
-rw-r--r--gcc/ChangeLog1356
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/ChangeLog1731
-rw-r--r--gcc/ada/adaint.c1
-rw-r--r--gcc/ada/ali-util.adb1
-rw-r--r--gcc/ada/ali.adb20
-rw-r--r--gcc/ada/ali.ads6
-rw-r--r--gcc/ada/aspects.ads16
-rw-r--r--gcc/ada/atree.adb709
-rw-r--r--gcc/ada/atree.ads76
-rw-r--r--gcc/ada/atree.h71
-rw-r--r--gcc/ada/bcheck.adb134
-rw-r--r--gcc/ada/checks.adb25
-rw-r--r--gcc/ada/checks.ads25
-rw-r--r--gcc/ada/clean.adb2
-rw-r--r--gcc/ada/comperr.adb7
-rw-r--r--gcc/ada/contracts.adb1569
-rw-r--r--gcc/ada/contracts.ads25
-rw-r--r--gcc/ada/debug.adb19
-rw-r--r--gcc/ada/doc/gnat_rm.rst1
-rw-r--r--gcc/ada/doc/gnat_rm/about_this_guide.rst3
-rw-r--r--gcc/ada/doc/gnat_rm/implementation_defined_characteristics.rst702
-rw-r--r--gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst88
-rw-r--r--gcc/ada/doc/gnat_rm/security_hardening_features.rst89
-rw-r--r--gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst38
-rw-r--r--gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst7
-rw-r--r--gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst14
-rw-r--r--gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst18
-rw-r--r--gcc/ada/doc/gnat_ugn/platform_specific_information.rst5
-rw-r--r--gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst71
-rw-r--r--gcc/ada/einfo-utils.adb65
-rw-r--r--gcc/ada/einfo-utils.ads2
-rw-r--r--gcc/ada/einfo.ads103
-rw-r--r--gcc/ada/err_vars.ads17
-rw-r--r--gcc/ada/errout.adb20
-rw-r--r--gcc/ada/erroutc.adb48
-rw-r--r--gcc/ada/exp_aggr.adb248
-rw-r--r--gcc/ada/exp_attr.adb17
-rw-r--r--gcc/ada/exp_ch3.adb92
-rw-r--r--gcc/ada/exp_ch4.adb248
-rw-r--r--gcc/ada/exp_ch5.adb147
-rw-r--r--gcc/ada/exp_ch6.adb388
-rw-r--r--gcc/ada/exp_ch6.ads3
-rw-r--r--gcc/ada/exp_ch7.adb8
-rw-r--r--gcc/ada/exp_ch9.adb29
-rw-r--r--gcc/ada/exp_dbug.adb4
-rw-r--r--gcc/ada/exp_disp.adb236
-rw-r--r--gcc/ada/exp_intr.adb2
-rw-r--r--gcc/ada/exp_prag.adb16
-rw-r--r--gcc/ada/exp_smem.adb2
-rw-r--r--gcc/ada/exp_util.adb275
-rw-r--r--gcc/ada/exp_util.ads58
-rw-r--r--gcc/ada/fe.h2
-rw-r--r--gcc/ada/freeze.adb624
-rw-r--r--gcc/ada/freeze.ads9
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in2
-rw-r--r--gcc/ada/gcc-interface/cuintp.c1
-rw-r--r--gcc/ada/gcc-interface/decl.c8
-rw-r--r--gcc/ada/gcc-interface/gigi.h2
-rw-r--r--gcc/ada/gcc-interface/targtyps.c1
-rw-r--r--gcc/ada/gcc-interface/trans.c14
-rw-r--r--gcc/ada/gcc-interface/utils.c12
-rw-r--r--gcc/ada/gen_il-fields.ads25
-rw-r--r--gcc/ada/gen_il-gen-gen_entities.adb34
-rw-r--r--gcc/ada/gen_il-gen-gen_nodes.adb66
-rw-r--r--gcc/ada/gen_il-gen.adb985
-rw-r--r--gcc/ada/gen_il-internals.adb2
-rw-r--r--gcc/ada/gen_il-internals.ads345
-rw-r--r--gcc/ada/gen_il-types.ads15
-rw-r--r--gcc/ada/ghost.adb9
-rw-r--r--gcc/ada/gnat1drv.adb4
-rw-r--r--gcc/ada/gnat_cuda.adb202
-rw-r--r--gcc/ada/gnat_cuda.ads10
-rw-r--r--gcc/ada/gnat_rm.texi2875
-rw-r--r--gcc/ada/gnat_ugn.texi85
-rw-r--r--gcc/ada/gnatbind.adb2
-rw-r--r--gcc/ada/gnatfind.adb5
-rw-r--r--gcc/ada/gnatlink.adb1
-rw-r--r--gcc/ada/gnatls.adb1
-rw-r--r--gcc/ada/gnatxref.adb5
-rw-r--r--gcc/ada/impunit.adb16
-rw-r--r--gcc/ada/init.c1
-rw-r--r--gcc/ada/libgnarl/a-tasini.adb12
-rw-r--r--gcc/ada/libgnarl/a-tasini.ads9
-rw-r--r--gcc/ada/libgnarl/s-interr__vxworks.adb37
-rw-r--r--gcc/ada/libgnarl/s-osinte__vxworks.adb18
-rw-r--r--gcc/ada/libgnarl/s-osinte__vxworks.ads84
-rw-r--r--gcc/ada/libgnarl/s-taprop__vxworks.adb101
-rw-r--r--gcc/ada/libgnarl/s-taskin.ads8
-rw-r--r--gcc/ada/libgnarl/s-tassta.adb9
-rw-r--r--gcc/ada/libgnarl/s-tpopsp__vxworks-rtp.adb5
-rw-r--r--gcc/ada/libgnarl/s-tpopsp__vxworks.adb5
-rw-r--r--gcc/ada/libgnarl/s-vxwext.adb6
-rw-r--r--gcc/ada/libgnarl/s-vxwext.ads16
-rw-r--r--gcc/ada/libgnarl/s-vxwext__kernel-smp.adb20
-rw-r--r--gcc/ada/libgnarl/s-vxwext__kernel.adb22
-rw-r--r--gcc/ada/libgnarl/s-vxwext__kernel.ads26
-rw-r--r--gcc/ada/libgnarl/s-vxwext__rtp-smp.adb18
-rw-r--r--gcc/ada/libgnarl/s-vxwext__rtp.adb22
-rw-r--r--gcc/ada/libgnarl/s-vxwext__rtp.ads26
-rw-r--r--gcc/ada/libgnat/a-cbdlli.ads8
-rw-r--r--gcc/ada/libgnat/a-cbhama.ads11
-rw-r--r--gcc/ada/libgnat/a-cbhase.ads9
-rw-r--r--gcc/ada/libgnat/a-cbmutr.ads8
-rw-r--r--gcc/ada/libgnat/a-cborma.ads11
-rw-r--r--gcc/ada/libgnat/a-cborse.ads9
-rw-r--r--gcc/ada/libgnat/a-cfdlli.ads1
-rw-r--r--gcc/ada/libgnat/a-cfhama.ads1
-rw-r--r--gcc/ada/libgnat/a-cfhase.ads1
-rw-r--r--gcc/ada/libgnat/a-cfinve.ads1
-rw-r--r--gcc/ada/libgnat/a-cforma.ads1
-rw-r--r--gcc/ada/libgnat/a-cforse.ads1
-rw-r--r--gcc/ada/libgnat/a-chahan.adb122
-rw-r--r--gcc/ada/libgnat/a-chahan.ads359
-rw-r--r--gcc/ada/libgnat/a-coboho.ads4
-rw-r--r--gcc/ada/libgnat/a-cobove.ads9
-rw-r--r--gcc/ada/libgnat/a-cofove.ads1
-rw-r--r--gcc/ada/libgnat/a-except.adb90
-rw-r--r--gcc/ada/libgnat/a-except.ads9
-rw-r--r--gcc/ada/libgnat/a-strbou.adb2
-rw-r--r--gcc/ada/libgnat/a-strbou.ads2152
-rw-r--r--gcc/ada/libgnat/a-strfix.adb20
-rw-r--r--gcc/ada/libgnat/a-strfix.ads91
-rw-r--r--gcc/ada/libgnat/a-strmap.adb337
-rw-r--r--gcc/ada/libgnat/a-strmap.ads127
-rw-r--r--gcc/ada/libgnat/a-strsea.ads6
-rw-r--r--gcc/ada/libgnat/a-strsup.adb1163
-rw-r--r--gcc/ada/libgnat/a-strsup.ads2383
-rw-r--r--gcc/ada/libgnat/a-strunb.ads8
-rw-r--r--gcc/ada/libgnat/a-strunb__shared.ads3
-rw-r--r--gcc/ada/libgnat/a-textio.adb1
-rw-r--r--gcc/ada/libgnat/a-textio.ads6
-rw-r--r--gcc/ada/libgnat/a-zchhan.adb34
-rw-r--r--gcc/ada/libgnat/a-zchhan.ads29
-rw-r--r--gcc/ada/libgnat/a-zchuni.adb19
-rw-r--r--gcc/ada/libgnat/a-zchuni.ads12
-rw-r--r--gcc/ada/libgnat/g-forstr.adb6
-rw-r--r--gcc/ada/libgnat/i-vxwork.ads9
-rw-r--r--gcc/ada/libgnat/i-vxwork__x86.ads9
-rw-r--r--gcc/ada/libgnat/memtrack.adb127
-rw-r--r--gcc/ada/libgnat/s-arit128.ads7
-rw-r--r--gcc/ada/libgnat/s-arit64.ads7
-rw-r--r--gcc/ada/libgnat/s-imenne.adb170
-rw-r--r--gcc/ada/libgnat/s-imenne.ads85
-rw-r--r--gcc/ada/libgnat/s-imglli.ads4
-rw-r--r--gcc/ada/libgnat/s-parame__vxworks.ads4
-rw-r--r--gcc/ada/libgnat/s-regpat.adb63
-rw-r--r--gcc/ada/libgnat/s-regpat.ads11
-rw-r--r--gcc/ada/libgnat/s-secsta.ads5
-rw-r--r--gcc/ada/live.adb3
-rw-r--r--gcc/ada/make.adb4
-rw-r--r--gcc/ada/opt.ads16
-rw-r--r--gcc/ada/osint-c.adb4
-rw-r--r--gcc/ada/osint.adb6
-rw-r--r--gcc/ada/output.adb26
-rw-r--r--gcc/ada/output.ads1
-rw-r--r--gcc/ada/par-ch4.adb88
-rw-r--r--gcc/ada/par-prag.adb1
-rw-r--r--gcc/ada/par_sco.adb31
-rw-r--r--gcc/ada/pprint.adb59
-rw-r--r--gcc/ada/prep.adb25
-rw-r--r--gcc/ada/repinfo.adb7
-rw-r--r--gcc/ada/scng.adb6
-rw-r--r--gcc/ada/scos.ads2
-rw-r--r--gcc/ada/sem.adb9
-rw-r--r--gcc/ada/sem.ads4
-rw-r--r--gcc/ada/sem_aggr.adb162
-rw-r--r--gcc/ada/sem_attr.adb101
-rw-r--r--gcc/ada/sem_aux.adb25
-rw-r--r--gcc/ada/sem_aux.ads4
-rw-r--r--gcc/ada/sem_case.adb337
-rw-r--r--gcc/ada/sem_ch12.adb2
-rw-r--r--gcc/ada/sem_ch13.adb625
-rw-r--r--gcc/ada/sem_ch3.adb59
-rw-r--r--gcc/ada/sem_ch5.adb17
-rw-r--r--gcc/ada/sem_ch6.adb53
-rw-r--r--gcc/ada/sem_ch7.adb41
-rw-r--r--gcc/ada/sem_ch8.adb26
-rw-r--r--gcc/ada/sem_disp.adb180
-rw-r--r--gcc/ada/sem_disp.ads4
-rw-r--r--gcc/ada/sem_elab.adb11
-rw-r--r--gcc/ada/sem_eval.adb3
-rw-r--r--gcc/ada/sem_prag.adb91
-rw-r--r--gcc/ada/sem_prag.ads3
-rw-r--r--gcc/ada/sem_res.adb286
-rw-r--r--gcc/ada/sem_type.adb16
-rw-r--r--gcc/ada/sem_util.adb669
-rw-r--r--gcc/ada/sem_util.ads139
-rw-r--r--gcc/ada/sinfo-utils.adb12
-rw-r--r--gcc/ada/sinfo-utils.ads2
-rw-r--r--gcc/ada/sinfo.ads4
-rw-r--r--gcc/ada/snames.ads-tmpl18
-rw-r--r--gcc/ada/socket.c4
-rw-r--r--gcc/ada/sprint.adb10
-rw-r--r--gcc/ada/sysdep.c4
-rw-r--r--gcc/ada/treepr.adb58
-rw-r--r--gcc/ada/types.ads9
-rw-r--r--gcc/btfout.c8
-rw-r--r--gcc/c-family/ChangeLog72
-rw-r--r--gcc/c-family/c-common.c47
-rw-r--r--gcc/c-family/c-common.h1
-rw-r--r--gcc/c-family/c-cppbuiltin.c4
-rw-r--r--gcc/c-family/c-format.c2
-rw-r--r--gcc/c-family/c-omp.c56
-rw-r--r--gcc/c-family/c-opts.c1
-rw-r--r--gcc/c-family/c-ubsan.c49
-rw-r--r--gcc/c-family/c-warn.c32
-rw-r--r--gcc/c-family/c.opt4
-rw-r--r--gcc/c/ChangeLog44
-rw-r--r--gcc/c/c-parser.c169
-rw-r--r--gcc/c/c-tree.h2
-rw-r--r--gcc/c/c-typeck.c171
-rw-r--r--gcc/c/gimple-parser.c14
-rw-r--r--gcc/cfgcleanup.c8
-rw-r--r--gcc/cfghooks.c13
-rw-r--r--gcc/common.opt3
-rw-r--r--gcc/common/config/avr/avr-common.c3
-rw-r--r--gcc/config.gcc1
-rw-r--r--gcc/config.in44
-rw-r--r--gcc/config/aarch64/aarch64-arches.def2
-rw-r--r--gcc/config/aarch64/aarch64-builtins.c12
-rw-r--r--gcc/config/aarch64/aarch64-cores.def9
-rw-r--r--gcc/config/aarch64/aarch64-option-extensions.def3
-rw-r--r--gcc/config/aarch64/aarch64-simd-builtins.def4
-rw-r--r--gcc/config/aarch64/aarch64-tune.md2
-rw-r--r--gcc/config/aarch64/aarch64.c67
-rw-r--r--gcc/config/aarch64/aarch64.h15
-rw-r--r--gcc/config/aarch64/arm_neon.h32
-rw-r--r--gcc/config/arm/arm-cpus.in10
-rw-r--r--gcc/config/arm/arm-tables.opt3
-rw-r--r--gcc/config/arm/arm-tune.md2
-rw-r--r--gcc/config/darwin.h2
-rw-r--r--gcc/config/gcn/gcn-hsa.h65
-rw-r--r--gcc/config/gcn/gcn-valu.md16
-rw-r--r--gcc/config/gcn/gcn.c50
-rw-r--r--gcc/config/gcn/mkoffload.c112
-rw-r--r--gcc/config/i386/avx512fp16intrin.h1127
-rw-r--r--gcc/config/i386/avx512fp16vlintrin.h500
-rw-r--r--gcc/config/i386/i386-builtin-types.def5
-rw-r--r--gcc/config/i386/i386-builtin.def40
-rw-r--r--gcc/config/i386/i386-expand.c10
-rw-r--r--gcc/config/i386/i386-features.c15
-rw-r--r--gcc/config/i386/i386.c28
-rw-r--r--gcc/config/i386/i386.h13
-rw-r--r--gcc/config/i386/i386.md151
-rw-r--r--gcc/config/i386/mmx.md72
-rw-r--r--gcc/config/i386/sse.md608
-rw-r--r--gcc/config/i386/subst.md102
-rw-r--r--gcc/config/lm32/uclinux-elf.h1
-rw-r--r--gcc/config/pa/pa.c10
-rw-r--r--gcc/config/pru/constraints.md5
-rw-r--r--gcc/config/pru/predicates.md19
-rw-r--r--gcc/config/pru/pru-pragma.c2
-rw-r--r--gcc/config/pru/pru-protos.h3
-rw-r--r--gcc/config/pru/pru.c156
-rw-r--r--gcc/config/pru/pru.h5
-rw-r--r--gcc/config/pru/pru.md102
-rw-r--r--gcc/config/riscv/riscv.md10
-rw-r--r--gcc/config/rs6000/darwin.h5
-rw-r--r--gcc/config/rs6000/rs6000-call.c64
-rw-r--r--gcc/config/rs6000/rs6000.c22
-rw-r--r--gcc/config/rs6000/rs6000.opt38
-rw-r--r--gcc/config/rs6000/vxworks.h4
-rw-r--r--gcc/config/s390/s390.c10
-rw-r--r--gcc/config/s390/tpf.md6
-rwxr-xr-xgcc/configure273
-rw-r--r--gcc/configure.ac110
-rw-r--r--gcc/cp/ChangeLog234
-rw-r--r--gcc/cp/class.c13
-rw-r--r--gcc/cp/constexpr.c66
-rw-r--r--gcc/cp/coroutines.cc80
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c9
-rw-r--r--gcc/cp/init.c11
-rw-r--r--gcc/cp/method.c244
-rw-r--r--gcc/cp/name-lookup.c7
-rw-r--r--gcc/cp/parser.c130
-rw-r--r--gcc/cp/pt.c85
-rw-r--r--gcc/cp/ptree.c10
-rw-r--r--gcc/cp/semantics.c40
-rw-r--r--gcc/cp/tree.c13
-rw-r--r--gcc/cp/typeck.c115
-rw-r--r--gcc/ctfc.c9
-rw-r--r--gcc/d/ChangeLog17
-rw-r--r--gcc/d/d-attribs.cc8
-rw-r--r--gcc/d/d-spec.cc49
-rw-r--r--gcc/dbgcnt.c8
-rw-r--r--gcc/dbgcnt.h1
-rw-r--r--gcc/defaults.h15
-rw-r--r--gcc/doc/extend.texi38
-rw-r--r--gcc/doc/invoke.texi113
-rw-r--r--gcc/doc/md.texi6
-rw-r--r--gcc/doc/rtl.texi12
-rw-r--r--gcc/dumpfile.c1
-rw-r--r--gcc/dumpfile.h52
-rw-r--r--gcc/dwarf2out.c2
-rw-r--r--gcc/explow.c9
-rw-r--r--gcc/expr.c4
-rw-r--r--gcc/expr.h3
-rw-r--r--gcc/fortran/ChangeLog183
-rw-r--r--gcc/fortran/array.c5
-rw-r--r--gcc/fortran/check.c4
-rw-r--r--gcc/fortran/cpp.c9
-rw-r--r--gcc/fortran/cpp.h2
-rw-r--r--gcc/fortran/decl.c14
-rw-r--r--gcc/fortran/dump-parse-tree.c2
-rw-r--r--gcc/fortran/expr.c32
-rw-r--r--gcc/fortran/f95-lang.c4
-rw-r--r--gcc/fortran/gfortran.h8
-rw-r--r--gcc/fortran/interface.c39
-rw-r--r--gcc/fortran/openmp.c5
-rw-r--r--gcc/fortran/options.c19
-rw-r--r--gcc/fortran/resolve.c13
-rw-r--r--gcc/fortran/scanner.c87
-rw-r--r--gcc/fortran/simplify.c5
-rw-r--r--gcc/fortran/trans-array.c166
-rw-r--r--gcc/fortran/trans-array.h2
-rw-r--r--gcc/fortran/trans-decl.c14
-rw-r--r--gcc/fortran/trans-expr.c77
-rw-r--r--gcc/fortran/trans-intrinsic.c246
-rw-r--r--gcc/fortran/trans-openmp.c7
-rw-r--r--gcc/fortran/trans-stmt.c7
-rw-r--r--gcc/fortran/trans.h6
-rw-r--r--gcc/gengtype.c4
-rw-r--r--gcc/gimple-fold.c5
-rw-r--r--gcc/gimple-isel.cc3
-rw-r--r--gcc/gimple-pretty-print.c21
-rw-r--r--gcc/gimple-range-cache.cc14
-rw-r--r--gcc/gimple-range-cache.h2
-rw-r--r--gcc/gimple-range-edge.cc7
-rw-r--r--gcc/gimple-range-edge.h3
-rw-r--r--gcc/gimple-range-fold.cc30
-rw-r--r--gcc/gimple-range-gori.cc9
-rw-r--r--gcc/gimple-range-gori.h7
-rw-r--r--gcc/gimple-range-path.cc95
-rw-r--r--gcc/gimple-range-path.h18
-rw-r--r--gcc/gimple-range.cc28
-rw-r--r--gcc/gimple-range.h2
-rw-r--r--gcc/gimple-ssa-evrp-analyze.h7
-rw-r--r--gcc/gimple-ssa-evrp.c12
-rw-r--r--gcc/gimple-ssa-warn-alloca.c7
-rw-r--r--gcc/gimplify.c24
-rw-r--r--gcc/go/ChangeLog5
-rw-r--r--gcc/go/go-lang.c1
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.h4
-rw-r--r--gcc/go/gofrontend/types.cc77
-rw-r--r--gcc/go/gofrontend/types.h13
-rw-r--r--gcc/internal-fn.c31
-rw-r--r--gcc/ipa-modref-tree.h8
-rw-r--r--gcc/ipa-prop.c40
-rw-r--r--gcc/ira-build.c13
-rw-r--r--gcc/lto-wrapper.c10
-rw-r--r--gcc/lto/ChangeLog5
-rw-r--r--gcc/lto/lto-lang.c1
-rw-r--r--gcc/match.pd30
-rw-r--r--gcc/omp-expand.c10
-rw-r--r--gcc/omp-general.c16
-rw-r--r--gcc/omp-low.c48
-rw-r--r--gcc/opts.c14
-rw-r--r--gcc/output.h85
-rw-r--r--gcc/params.opt4
-rw-r--r--gcc/passes.def6
-rw-r--r--gcc/poly-int.h4
-rw-r--r--gcc/range-op.cc26
-rw-r--r--gcc/real.c6
-rw-r--r--gcc/rtl.def5
-rw-r--r--gcc/simplify-rtx.c75
-rw-r--r--gcc/testsuite/ChangeLog880
-rw-r--r--gcc/testsuite/c-c++-common/Waddress-3.c125
-rw-r--r--gcc/testsuite/c-c++-common/Waddress-4.c106
-rw-r--r--gcc/testsuite/c-c++-common/Warray-compare-1.c44
-rw-r--r--gcc/testsuite/c-c++-common/Warray-compare-2.c44
-rw-r--r--gcc/testsuite/c-c++-common/gomp/allocate-6.c84
-rw-r--r--gcc/testsuite/c-c++-common/gomp/allocate-7.c41
-rw-r--r--gcc/testsuite/c-c++-common/gomp/scope-3.c21
-rw-r--r--gcc/testsuite/c-c++-common/gomp/scope-4.c11
-rw-r--r--gcc/testsuite/c-c++-common/pr102285.c10
-rw-r--r--gcc/testsuite/c-c++-common/tsan/atomic_stack.c3
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/div-by-zero-3.c2
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/div-by-zero-4.c2
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c2
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/float-div-by-zero-2.c18
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/overflow-div-1.c17
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/overflow-div-2.c41
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/overflow-div-3.c41
-rw-r--r--gcc/testsuite/g++.dg/Walloca2.C6
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr100673.C18
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr101133.C31
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr101765.C45
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr102454.C38
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr99575.C35
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr99710.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp/elifdef-1.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp/elifdef-2.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp/elifdef-3.C62
-rw-r--r--gcc/testsuite/g++.dg/cpp/elifdef-4.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp/elifdef-5.C63
-rw-r--r--gcc/testsuite/g++.dg/cpp/elifdef-6.C65
-rw-r--r--gcc/testsuite/g++.dg/cpp/elifdef-7.C65
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-partial2.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-partial2a.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-label.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction12.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction99.C35
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/nontype4.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/nontype4a.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp23/charlit-encoding1.C33
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C68
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C54
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit3.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C57
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C57
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-nondep2.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-nondep3.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-ttp3.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-ttp4.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/consteval3.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-float2.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-eq11.C43
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-eq12.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-eq13.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth12.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth13.C29
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth14.C26
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth8.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth8a.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-virtual1.C20
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/constexpr1.C6
-rw-r--r--gcc/testsuite/g++.dg/ext/is_constructible6.C10
-rw-r--r--gcc/testsuite/g++.dg/ext/is_trivially_constructible7.C17
-rw-r--r--gcc/testsuite/g++.dg/gomp/allocate-4.C108
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-14.C4
-rw-r--r--gcc/testsuite/g++.dg/gomp/simd-3.C16
-rw-r--r--gcc/testsuite/g++.dg/parse/pr101783.C5
-rw-r--r--gcc/testsuite/g++.dg/pr102359_1.C13
-rw-r--r--gcc/testsuite/g++.dg/pr102359_2.C13
-rw-r--r--gcc/testsuite/g++.dg/spellcheck-pr77565.C12
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-15.C7
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-16.C6
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-17.C5
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-18.C6
-rw-r--r--gcc/testsuite/g++.dg/template/dependent-name15.C18
-rw-r--r--gcc/testsuite/g++.dg/template/dependent-name16.C14
-rw-r--r--gcc/testsuite/g++.dg/template/param6.C32
-rw-r--r--gcc/testsuite/g++.dg/tls/pr102496-1.C20
-rw-r--r--gcc/testsuite/g++.dg/tls/pr102496-2.C6
-rw-r--r--gcc/testsuite/g++.dg/torture/pr102581.C51
-rw-r--r--gcc/testsuite/g++.dg/warn/Waddress-5.C115
-rw-r--r--gcc/testsuite/g++.dg/warn/Waddress-6.C79
-rw-r--r--gcc/testsuite/g++.dg/warn/Winit-list5.C61
-rw-r--r--gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C4
-rw-r--r--gcc/testsuite/g++.dg/warn/pr101219.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/nontype5.C2
-rw-r--r--gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-minmax.C25
-rw-r--r--gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-vec.C70
-rw-r--r--gcc/testsuite/g++.target/i386/pr102548.C12
-rw-r--r--gcc/testsuite/g++.target/powerpc/pr102024.C23
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/920826-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/920831-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/attr-complex-method-2.c11
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/attr-complex-method.c11
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr27863.c4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr70190.c2
-rw-r--r--gcc/testsuite/gcc.dg/Waddress-3.c35
-rw-r--r--gcc/testsuite/gcc.dg/Waddress.c2
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/torture/asm-x86-linux-rdmsr.c2
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-hardreg-1.c9
-rw-r--r--gcc/testsuite/gcc.dg/comp-goto-5.c11
-rw-r--r--gcc/testsuite/gcc.dg/comp-goto-6.c6
-rw-r--r--gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-2.c63
-rw-r--r--gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-3.c65
-rw-r--r--gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-4.c65
-rw-r--r--gcc/testsuite/gcc.dg/fold-negate-1.c58
-rw-r--r--gcc/testsuite/gcc.dg/gimplefe-46.c23
-rw-r--r--gcc/testsuite/gcc.dg/gimplefe-47.c27
-rw-r--r--gcc/testsuite/gcc.dg/guality/example.c2
-rw-r--r--gcc/testsuite/gcc.dg/out-of-bounds-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr102087.c35
-rw-r--r--gcc/testsuite/gcc.dg/pr102463.c21
-rw-r--r--gcc/testsuite/gcc.dg/pr102511.c21
-rw-r--r--gcc/testsuite/gcc.dg/pr78408-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr94726.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr102518.c12
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr55107.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr89135.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr90071.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/20030714-2.c7
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr102546.c23
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr102563.c16
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr21559.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr59597.c13
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c10
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr71437.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr99793.c14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.c7
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.h33
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-47.c9
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-48.c9
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-49.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-50.c10
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-51.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-14.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c8
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c6
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-95.c25
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-96.c14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-33.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-valid.c39
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-vrp-thread-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp106.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp55.c6
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-16.c7
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr97709.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/cpymem-size.c29
-rw-r--r--gcc/testsuite/gcc.target/aarch64/memset-corner-cases-2.c30
-rw-r--r--gcc/testsuite/gcc.target/aarch64/memset-strict-align-1.c10
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pr102587-1.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pr102587-2.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/attr-optimize.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-2.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-3.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-4.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-5.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-3.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-7.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-8.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-9.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-1.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-5.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vect-rebuild.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-13.c140
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-14.c85
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-1.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-2.c75
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-1.c40
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-2.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-builtin-minmax-1.c35
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-builtin-round-1.c45
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-builtin-sqrt-1.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-complex-constraints.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-conjugation-1.c34
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-floatvnhf.c61
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-fma-1.c69
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-helper.h9
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-1.c132
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-2.c96
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-3.c91
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-trunc-extendvnhf.c55
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-trunchf.c59
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-truncvnhf.c61
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-1.c70
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-2.c143
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vec_cmpmn.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1b.c133
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1b.c78
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1a.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1b.c111
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1a.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1b.c71
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1b.c131
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1b.c77
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1a.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1b.c115
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1a.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1b.c71
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-builtin-sqrt-1.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-conjugation-1.c55
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-1.c70
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-vectorize-1.c45
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-reduce-op-1.c244
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1a.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1a.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-pr95046.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-1.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-1.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-1.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102230.c38
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102498.c59
-rw-r--r--gcc/testsuite/gcc.target/i386/pr89954.c45
-rw-r--r--gcc/testsuite/gcc.target/i386/pr92658-avx512f.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/pr92658-avx512vl.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-13.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-14.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-22.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-23.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-paddsb-2.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-paddusb-2.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psubsb-2.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psubusb-2.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-pr101059.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/sse3-pr101059.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-alignment-peeling-1.c90
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-alignment-peeling-2.c90
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-pr82426.c31
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-pr97352.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-rebuild.c2
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-as-pointer-2.c11
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-as-pointer.c11
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-decl-2.c13
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-decl-3.c19
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-decl-4.c17
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-decl.c15
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-di.c9
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-hi.c9
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-qi.c9
-rw-r--r--gcc/testsuite/gcc.target/pru/regio.c58
-rw-r--r--gcc/testsuite/gcc.target/pru/regio.h7
-rw-r--r--gcc/testsuite/gcc.target/s390/pr102222.c16
-rw-r--r--gcc/testsuite/gcc.target/s390/pr80725.c2
-rw-r--r--gcc/testsuite/gdc.dg/pr102476.d3
-rw-r--r--gcc/testsuite/gfortran.dg/associated_assumed_rank.f90126
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_rank_18.f905
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_rank_22.f90169
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_rank_22_aux.c68
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_rank_23.f9016
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_type_10.f905
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_type_11.f905
-rw-r--r--gcc/testsuite/gfortran.dg/attr_deprecated-2.f9022
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/assumed-type-dummy.f902
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c407c-1.f904
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c516.f9046
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c535b-1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c535b-2.f905
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c535b-3.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-5-c.c1
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-6.f902
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/size.f902
-rw-r--r--gcc/testsuite/gfortran.dg/coarray/coarray_allocated.f9055
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/order-5.f908
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/pr43711.f908
-rw-r--r--gcc/testsuite/gfortran.dg/include_14.f907
-rw-r--r--gcc/testsuite/gfortran.dg/include_15.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/include_16.f902
-rw-r--r--gcc/testsuite/gfortran.dg/include_17.f904
-rw-r--r--gcc/testsuite/gfortran.dg/include_18.f904
-rw-r--r--gcc/testsuite/gfortran.dg/include_19.f902
-rw-r--r--gcc/testsuite/gfortran.dg/include_23.f904
-rw-r--r--gcc/testsuite/gfortran.dg/include_24.f904
-rw-r--r--gcc/testsuite/gfortran.dg/include_9.f901
-rw-r--r--gcc/testsuite/gfortran.dg/intrinsic_size_3.f902
-rw-r--r--gcc/testsuite/gfortran.dg/pr102458.f9042
-rw-r--r--gcc/testsuite/gfortran.dg/pr102458b.f9021
-rw-r--r--gcc/testsuite/gfortran.dg/pr102520.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/predict-2.f904
-rw-r--r--gcc/testsuite/gfortran.dg/size_optional_dim_1.f904
-rw-r--r--gcc/testsuite/gfortran.dg/transpose_optimization_2.f902
-rw-r--r--gcc/testsuite/gfortran.dg/unlimited_polymorphic_1.f0317
-rw-r--r--gcc/testsuite/gfortran.dg/unlimited_polymorphic_32.f90254
-rw-r--r--gcc/timevar.def1
-rw-r--r--gcc/toplev.c73
-rw-r--r--gcc/toplev.h1
-rw-r--r--gcc/tree-cfg.c14
-rw-r--r--gcc/tree-inline.c6
-rw-r--r--gcc/tree-object-size.c42
-rw-r--r--gcc/tree-object-size.h3
-rw-r--r--gcc/tree-pass.h1
-rw-r--r--gcc/tree-pretty-print.c45
-rw-r--r--gcc/tree-ssa-dom.c151
-rw-r--r--gcc/tree-ssa-dse.c5
-rw-r--r--gcc/tree-ssa-loop-niter.c16
-rw-r--r--gcc/tree-ssa-pre.c27
-rw-r--r--gcc/tree-ssa-reassoc.c125
-rw-r--r--gcc/tree-ssa-sccvn.c147
-rw-r--r--gcc/tree-ssa-sccvn.h3
-rw-r--r--gcc/tree-ssa-threadbackward.c8
-rw-r--r--gcc/tree-ssa-threadedge.c372
-rw-r--r--gcc/tree-ssa-threadedge.h74
-rw-r--r--gcc/tree-ssa-threadupdate.c102
-rw-r--r--gcc/tree-ssa-threadupdate.h1
-rw-r--r--gcc/tree-ssanames.c19
-rw-r--r--gcc/tree-vect-data-refs.c277
-rw-r--r--gcc/tree-vect-slp.c59
-rw-r--r--gcc/tree-vect-stmts.c77
-rw-r--r--gcc/tree-vectorizer.h32
-rw-r--r--gcc/tree-vrp.c400
-rw-r--r--gcc/tree.c2
-rw-r--r--gcc/tree.h6
-rw-r--r--gcc/value-range.cc69
-rw-r--r--gcc/value-range.h16
-rw-r--r--gcc/varasm.c5
-rw-r--r--gcc/vr-values.c24
-rw-r--r--gcc/vr-values.h8
-rw-r--r--gotools/ChangeLog5
-rw-r--r--include/ChangeLog9
-rw-r--r--include/floatformat.h2
-rw-r--r--include/obstack.h6
-rw-r--r--libcpp/ChangeLog9
-rw-r--r--libcpp/directives.c43
-rw-r--r--libcpp/init.c4
-rw-r--r--libgcc/ChangeLog16
-rw-r--r--libgcc/config/i386/libgcc-darwin.ver5
-rw-r--r--libgcc/config/i386/sfp-machine.h2
-rw-r--r--libgcc/libgcc2.c15
-rw-r--r--libgfortran/ChangeLog24
-rwxr-xr-xlibgfortran/configure2
-rw-r--r--libgfortran/configure.ac2
-rw-r--r--libgfortran/intrinsics/associated.c3
-rw-r--r--libgfortran/intrinsics/size.c4
-rw-r--r--libgomp/ChangeLog128
-rw-r--r--libgomp/affinity-fmt.c3
-rw-r--r--libgomp/allocator.c398
-rwxr-xr-xlibgomp/configure16
-rw-r--r--libgomp/configure.ac16
-rw-r--r--libgomp/env.c2
-rw-r--r--libgomp/fortran.c1
-rw-r--r--libgomp/icv-device.c17
-rw-r--r--libgomp/icv.c2
-rw-r--r--libgomp/libgomp.map4
-rw-r--r--libgomp/libgomp.texi2
-rw-r--r--libgomp/omp.h.in25
-rw-r--r--libgomp/omp_lib.f90.in43
-rw-r--r--libgomp/omp_lib.h.in46
-rw-r--r--libgomp/team.c2
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/alloc-4.c20
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/alloc-5.c159
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/alloc-6.c58
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/alloc-7.c182
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/alloc-8.c184
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/alloc-9.c271
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/allocate-2.c37
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/allocate-3.c405
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/order-reproducible-1.c63
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/order-reproducible-2.c28
-rw-r--r--libgomp/testsuite/libgomp.fortran/alloc-10.f90199
-rw-r--r--libgomp/testsuite/libgomp.fortran/alloc-11.f90301
-rw-r--r--libgomp/testsuite/libgomp.fortran/alloc-6.f9045
-rw-r--r--libgomp/testsuite/libgomp.fortran/alloc-7.c5
-rw-r--r--libgomp/testsuite/libgomp.fortran/alloc-7.f90175
-rw-r--r--libgomp/testsuite/libgomp.fortran/alloc-8.f9058
-rw-r--r--libgomp/testsuite/libgomp.fortran/alloc-9.f90197
-rw-r--r--libgomp/testsuite/libgomp.fortran/fortran.exp3
-rw-r--r--libgomp/testsuite/libgomp.fortran/my-usleep.c9
-rw-r--r--libgomp/testsuite/libgomp.fortran/order-reproducible-1.f9072
-rw-r--r--libgomp/testsuite/libgomp.fortran/order-reproducible-2.f9037
-rw-r--r--libgomp/testsuite/libgomp.graphite/force-parallel-4.c2
-rw-r--r--libgomp/testsuite/libgomp.graphite/force-parallel-8.c2
-rw-r--r--libgomp/testsuite/libgomp.oacc-fortran/fortran.exp3
-rw-r--r--libgomp/testsuite/libgomp.oacc-fortran/if-1.f906
-rw-r--r--libgomp/testsuite/libgomp.oacc-fortran/privatized-ref-2.f904
-rw-r--r--libiberty/ChangeLog14
-rw-r--r--libiberty/d-demangle.c4
-rw-r--r--libiberty/testsuite/d-demangle-expected4
-rw-r--r--libphobos/ChangeLog34
-rw-r--r--libphobos/libdruntime/__main.di14
-rw-r--r--libphobos/libdruntime/core/runtime.d14
-rw-r--r--libphobos/libdruntime/gcc/backtrace.d24
-rw-r--r--libphobos/libdruntime/gcc/deh.d79
-rw-r--r--libphobos/libdruntime/gcc/unwind/generic.d22
-rw-r--r--libsanitizer/ChangeLog8
-rw-r--r--libsanitizer/LOCAL_PATCHES2
-rw-r--r--libsanitizer/MERGE2
-rw-r--r--libsanitizer/asan/asan_allocator.cpp15
-rw-r--r--libsanitizer/asan/asan_allocator.h2
-rw-r--r--libsanitizer/asan/asan_debugging.cpp5
-rw-r--r--libsanitizer/asan/asan_fuchsia.cpp35
-rw-r--r--libsanitizer/asan/asan_globals.cpp14
-rw-r--r--libsanitizer/asan/asan_interceptors.cpp18
-rw-r--r--libsanitizer/asan/asan_interceptors.h45
-rw-r--r--libsanitizer/asan/asan_report.cpp10
-rw-r--r--libsanitizer/asan/asan_rtl.cpp18
-rw-r--r--libsanitizer/asan/asan_stats.cpp14
-rw-r--r--libsanitizer/asan/asan_thread.cpp4
-rw-r--r--libsanitizer/asan/libtool-version2
-rw-r--r--libsanitizer/hwasan/Makefile.am3
-rw-r--r--libsanitizer/hwasan/Makefile.in12
-rw-r--r--libsanitizer/hwasan/hwasan.cpp7
-rw-r--r--libsanitizer/hwasan/hwasan.h25
-rw-r--r--libsanitizer/hwasan/hwasan_allocation_functions.cpp24
-rw-r--r--libsanitizer/hwasan/hwasan_allocator.cpp58
-rw-r--r--libsanitizer/hwasan/hwasan_dynamic_shadow.cpp9
-rw-r--r--libsanitizer/hwasan/hwasan_fuchsia.cpp23
-rw-r--r--libsanitizer/hwasan/hwasan_interceptors.cpp70
-rw-r--r--libsanitizer/hwasan/hwasan_interface_internal.h48
-rw-r--r--libsanitizer/hwasan/hwasan_linux.cpp147
-rw-r--r--libsanitizer/hwasan/hwasan_report.cpp82
-rw-r--r--libsanitizer/hwasan/hwasan_setjmp_aarch64.S (renamed from libsanitizer/hwasan/hwasan_setjmp.S)21
-rw-r--r--libsanitizer/hwasan/hwasan_setjmp_x86_64.S82
-rw-r--r--libsanitizer/hwasan/hwasan_thread.cpp2
-rw-r--r--libsanitizer/hwasan/hwasan_type_test.cpp2
-rw-r--r--libsanitizer/include/sanitizer/asan_interface.h2
-rw-r--r--libsanitizer/include/sanitizer/common_interface_defs.h2
-rw-r--r--libsanitizer/include/sanitizer/dfsan_interface.h3
-rw-r--r--libsanitizer/include/sanitizer/linux_syscall_hooks.h2120
-rw-r--r--libsanitizer/include/sanitizer/tsan_interface.h3
-rw-r--r--libsanitizer/interception/interception_win.cpp48
-rw-r--r--libsanitizer/lsan/lsan_allocator.h2
-rw-r--r--libsanitizer/lsan/lsan_common.cpp68
-rw-r--r--libsanitizer/lsan/lsan_common.h3
-rw-r--r--libsanitizer/sanitizer_common/sancov_flags.inc2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_addrhashmap.h2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_allocator_primary64.h14
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_allocator_size_class_map.h8
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_asm.h8
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_atomic_clang_mips.h2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_chained_origin_depot.cpp11
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_chained_origin_depot.h9
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common.h20
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc652
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_interceptors_format.inc10
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_interceptors_netbsd_compat.inc4
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S1
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S1
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_libcdep.cpp20
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_nolibc.cpp1
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc1559
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_coverage_fuchsia.cpp8
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_coverage_libcdep_new.cpp65
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_file.cpp15
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_file.h2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_flag_parser.h2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_flags.inc4
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_fuchsia.cpp41
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_hash.h24
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_interface_internal.h7
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_internal_defs.h46
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_libc.cpp12
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_libc.h5
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_libignore.cpp33
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_libignore.h37
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_linux.cpp83
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_local_address_space_view.h2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_mac.cpp29
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_mutex.cpp186
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_mutex.h325
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform.h25
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h31
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.cpp25
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.h180
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp56
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.cpp1
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.h1
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp25
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h30
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.cpp1
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.h1
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_posix.h7
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_printf.cpp37
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_signal_interceptors.inc12
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_solaris.cpp22
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stackdepot.cpp49
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stackdepot.h10
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stackdepotbase.h9
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stacktrace.cpp5
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cpp2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stacktrace_printer.cpp11
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stacktrace_sparc.cpp2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer.h6
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer_internal.h2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer_libcdep.cpp12
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_syscall_linux_hexagon.inc131
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_thread_registry.cpp22
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_thread_registry.h2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_tls_get_addr.cpp19
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_win.cpp24
-rw-r--r--libsanitizer/tsan/Makefile.am4
-rw-r--r--libsanitizer/tsan/Makefile.in13
-rw-r--r--libsanitizer/tsan/libtool-version2
-rw-r--r--libsanitizer/tsan/tsan_clock.cpp10
-rw-r--r--libsanitizer/tsan/tsan_clock.h2
-rw-r--r--libsanitizer/tsan/tsan_debugging.cpp10
-rw-r--r--libsanitizer/tsan/tsan_defs.h66
-rw-r--r--libsanitizer/tsan/tsan_dense_alloc.h35
-rw-r--r--libsanitizer/tsan/tsan_external.cpp19
-rw-r--r--libsanitizer/tsan/tsan_fd.cpp24
-rw-r--r--libsanitizer/tsan/tsan_fd.h2
-rw-r--r--libsanitizer/tsan/tsan_flags.cpp1
-rw-r--r--libsanitizer/tsan/tsan_flags.inc1
-rw-r--r--libsanitizer/tsan/tsan_ignoreset.cpp12
-rw-r--r--libsanitizer/tsan/tsan_ignoreset.h13
-rw-r--r--libsanitizer/tsan/tsan_ilist.h189
-rw-r--r--libsanitizer/tsan/tsan_interceptors.h41
-rw-r--r--libsanitizer/tsan/tsan_interceptors_mac.cpp6
-rw-r--r--libsanitizer/tsan/tsan_interceptors_posix.cpp430
-rw-r--r--libsanitizer/tsan/tsan_interface.cpp101
-rw-r--r--libsanitizer/tsan/tsan_interface.h10
-rw-r--r--libsanitizer/tsan/tsan_interface.inc182
-rw-r--r--libsanitizer/tsan/tsan_interface_ann.cpp172
-rw-r--r--libsanitizer/tsan/tsan_interface_atomic.cpp323
-rw-r--r--libsanitizer/tsan/tsan_interface_inl.h133
-rw-r--r--libsanitizer/tsan/tsan_interface_java.cpp291
-rw-r--r--libsanitizer/tsan/tsan_mman.cpp10
-rw-r--r--libsanitizer/tsan/tsan_mman.h49
-rw-r--r--libsanitizer/tsan/tsan_mutex.cpp280
-rw-r--r--libsanitizer/tsan/tsan_mutex.h87
-rw-r--r--libsanitizer/tsan/tsan_mutexset.cpp47
-rw-r--r--libsanitizer/tsan/tsan_mutexset.h29
-rw-r--r--libsanitizer/tsan/tsan_platform.h1089
-rw-r--r--libsanitizer/tsan/tsan_platform_linux.cpp101
-rw-r--r--libsanitizer/tsan/tsan_platform_mac.cpp84
-rw-r--r--libsanitizer/tsan/tsan_platform_posix.cpp37
-rw-r--r--libsanitizer/tsan/tsan_platform_windows.cpp3
-rw-r--r--libsanitizer/tsan/tsan_report.cpp77
-rw-r--r--libsanitizer/tsan/tsan_report.h36
-rw-r--r--libsanitizer/tsan/tsan_rtl.cpp485
-rw-r--r--libsanitizer/tsan/tsan_rtl.h508
-rw-r--r--libsanitizer/tsan/tsan_rtl_amd64.S6
-rw-r--r--libsanitizer/tsan/tsan_rtl_mutex.cpp419
-rw-r--r--libsanitizer/tsan/tsan_rtl_report.cpp328
-rw-r--r--libsanitizer/tsan/tsan_rtl_thread.cpp306
-rw-r--r--libsanitizer/tsan/tsan_shadow.h233
-rw-r--r--libsanitizer/tsan/tsan_stack_trace.cpp12
-rw-r--r--libsanitizer/tsan/tsan_symbolize.cpp3
-rw-r--r--libsanitizer/tsan/tsan_sync.cpp58
-rw-r--r--libsanitizer/tsan/tsan_sync.h36
-rw-r--r--libsanitizer/tsan/tsan_trace.h153
-rw-r--r--libsanitizer/tsan/tsan_update_shadow_word.inc (renamed from libsanitizer/tsan/tsan_update_shadow_word_inl.h)2
-rw-r--r--libsanitizer/tsan/tsan_vector_clock.cpp126
-rw-r--r--libsanitizer/tsan/tsan_vector_clock.h51
-rw-r--r--libsanitizer/ubsan/ubsan_diag.cpp8
-rw-r--r--libstdc++-v3/ChangeLog703
-rw-r--r--libstdc++-v3/include/Makefile.am10
-rw-r--r--libstdc++-v3/include/Makefile.in10
-rw-r--r--libstdc++-v3/include/bits/atomic_base.h2
-rw-r--r--libstdc++-v3/include/bits/atomic_futex.h3
-rw-r--r--libstdc++-v3/include/bits/atomic_timed_wait.h11
-rw-r--r--libstdc++-v3/include/bits/atomic_wait.h23
-rw-r--r--libstdc++-v3/include/bits/basic_string.h2
-rw-r--r--libstdc++-v3/include/bits/boost_concept_check.h111
-rw-r--r--libstdc++-v3/include/bits/c++config5
-rw-r--r--libstdc++-v3/include/bits/chrono.h1392
-rw-r--r--libstdc++-v3/include/bits/cow_string.h22
-rw-r--r--libstdc++-v3/include/bits/forward_list.h6
-rw-r--r--libstdc++-v3/include/bits/fs_fwd.h2
-rw-r--r--libstdc++-v3/include/bits/fs_path.h4
-rw-r--r--libstdc++-v3/include/bits/hashtable.h14
-rw-r--r--libstdc++-v3/include/bits/hashtable_policy.h39
-rw-r--r--libstdc++-v3/include/bits/list.tcc182
-rw-r--r--libstdc++-v3/include/bits/mofunc_impl.h200
-rw-r--r--libstdc++-v3/include/bits/move.h8
-rw-r--r--libstdc++-v3/include/bits/move_only_function.h204
-rw-r--r--libstdc++-v3/include/bits/parse_numbers.h6
-rw-r--r--libstdc++-v3/include/bits/ptr_traits.h2
-rw-r--r--libstdc++-v3/include/bits/range_access.h4
-rw-r--r--libstdc++-v3/include/bits/ranges_algobase.h18
-rw-r--r--libstdc++-v3/include/bits/ranges_base.h33
-rw-r--r--libstdc++-v3/include/bits/ranges_util.h6
-rw-r--r--libstdc++-v3/include/bits/refwrap.h4
-rw-r--r--libstdc++-v3/include/bits/regex.h116
-rw-r--r--libstdc++-v3/include/bits/regex_automaton.h27
-rw-r--r--libstdc++-v3/include/bits/regex_compiler.h76
-rw-r--r--libstdc++-v3/include/bits/regex_compiler.tcc18
-rw-r--r--libstdc++-v3/include/bits/regex_constants.h27
-rw-r--r--libstdc++-v3/include/bits/regex_error.h4
-rw-r--r--libstdc++-v3/include/bits/regex_executor.h70
-rw-r--r--libstdc++-v3/include/bits/regex_executor.tcc2
-rw-r--r--libstdc++-v3/include/bits/regex_scanner.h11
-rw-r--r--libstdc++-v3/include/bits/regex_scanner.tcc13
-rw-r--r--libstdc++-v3/include/bits/semaphore_base.h4
-rw-r--r--libstdc++-v3/include/bits/shared_ptr_base.h4
-rw-r--r--libstdc++-v3/include/bits/std_function.h18
-rw-r--r--libstdc++-v3/include/bits/stl_algo.h37
-rw-r--r--libstdc++-v3/include/bits/stl_algobase.h52
-rw-r--r--libstdc++-v3/include/bits/stl_bvector.h4
-rw-r--r--libstdc++-v3/include/bits/stl_deque.h4
-rw-r--r--libstdc++-v3/include/bits/stl_iterator.h106
-rw-r--r--libstdc++-v3/include/bits/stl_list.h106
-rw-r--r--libstdc++-v3/include/bits/stl_map.h4
-rw-r--r--libstdc++-v3/include/bits/stl_multimap.h5
-rw-r--r--libstdc++-v3/include/bits/stl_multiset.h5
-rw-r--r--libstdc++-v3/include/bits/stl_pair.h21
-rw-r--r--libstdc++-v3/include/bits/stl_queue.h103
-rw-r--r--libstdc++-v3/include/bits/stl_set.h4
-rw-r--r--libstdc++-v3/include/bits/stl_stack.h37
-rw-r--r--libstdc++-v3/include/bits/stl_tree.h8
-rw-r--r--libstdc++-v3/include/bits/stl_vector.h4
-rw-r--r--libstdc++-v3/include/bits/stream_iterator.h25
-rw-r--r--libstdc++-v3/include/bits/this_thread_sleep.h4
-rw-r--r--libstdc++-v3/include/bits/unique_lock.h2
-rw-r--r--libstdc++-v3/include/bits/unique_ptr.h12
-rw-r--r--libstdc++-v3/include/bits/uses_allocator.h8
-rw-r--r--libstdc++-v3/include/bits/utility.h11
-rw-r--r--libstdc++-v3/include/bits/vector.tcc8
-rw-r--r--libstdc++-v3/include/debug/deque4
-rw-r--r--libstdc++-v3/include/debug/functions.h6
-rw-r--r--libstdc++-v3/include/debug/list4
-rw-r--r--libstdc++-v3/include/debug/map.h4
-rw-r--r--libstdc++-v3/include/debug/multimap.h5
-rw-r--r--libstdc++-v3/include/debug/multiset.h5
-rw-r--r--libstdc++-v3/include/debug/set.h4
-rw-r--r--libstdc++-v3/include/debug/vector4
-rw-r--r--libstdc++-v3/include/experimental/any10
-rw-r--r--libstdc++-v3/include/experimental/bits/fs_fwd.h2
-rw-r--r--libstdc++-v3/include/experimental/chrono2
-rw-r--r--libstdc++-v3/include/experimental/deque8
-rw-r--r--libstdc++-v3/include/experimental/executor2
-rw-r--r--libstdc++-v3/include/experimental/functional6
-rw-r--r--libstdc++-v3/include/experimental/io_context2
-rw-r--r--libstdc++-v3/include/experimental/map10
-rw-r--r--libstdc++-v3/include/experimental/netfwd2
-rw-r--r--libstdc++-v3/include/experimental/set10
-rw-r--r--libstdc++-v3/include/experimental/timer2
-rw-r--r--libstdc++-v3/include/experimental/unordered_map12
-rw-r--r--libstdc++-v3/include/experimental/unordered_set11
-rw-r--r--libstdc++-v3/include/experimental/vector8
-rw-r--r--libstdc++-v3/include/std/any10
-rw-r--r--libstdc++-v3/include/std/chrono1380
-rw-r--r--libstdc++-v3/include/std/condition_variable3
-rw-r--r--libstdc++-v3/include/std/deque28
-rw-r--r--libstdc++-v3/include/std/functional9
-rw-r--r--libstdc++-v3/include/std/map10
-rw-r--r--libstdc++-v3/include/std/mutex2
-rw-r--r--libstdc++-v3/include/std/ostream7
-rw-r--r--libstdc++-v3/include/std/ranges10
-rw-r--r--libstdc++-v3/include/std/set10
-rw-r--r--libstdc++-v3/include/std/shared_mutex2
-rw-r--r--libstdc++-v3/include/std/string18
-rw-r--r--libstdc++-v3/include/std/string_view2
-rw-r--r--libstdc++-v3/include/std/thread26
-rw-r--r--libstdc++-v3/include/std/tuple28
-rw-r--r--libstdc++-v3/include/std/type_traits36
-rw-r--r--libstdc++-v3/include/std/unordered_map12
-rw-r--r--libstdc++-v3/include/std/unordered_set11
-rw-r--r--libstdc++-v3/include/std/variant147
-rw-r--r--libstdc++-v3/include/std/vector28
-rw-r--r--libstdc++-v3/include/std/version4
-rw-r--r--libstdc++-v3/src/c++11/functexcept.cc8
-rw-r--r--libstdc++-v3/src/c++11/snprintf_lite.cc11
-rw-r--r--libstdc++-v3/src/c++11/system_error.cc222
-rw-r--r--libstdc++-v3/src/c++17/fs_ops.cc52
-rw-r--r--libstdc++-v3/src/c++98/list.cc2
-rw-r--r--libstdc++-v3/src/filesystem/ops-common.h67
-rw-r--r--libstdc++-v3/src/filesystem/ops.cc44
-rw-r--r--libstdc++-v3/testsuite/19_diagnostics/error_category/102425.cc18
-rw-r--r--libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc18
-rw-r--r--libstdc++-v3/testsuite/19_diagnostics/headers/system_error/93151.cc1
-rw-r--r--libstdc++-v3/testsuite/19_diagnostics/system_error/cons-1.cc6
-rw-r--r--libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/forward/c_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/forward/f_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/integer_comparisons/greater.cc61
-rw-r--r--libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.h4
-rw-r--r--libstdc++-v3/testsuite/20_util/is_swappable/value.h11
-rw-r--r--libstdc++-v3/testsuite/20_util/is_trivially_constructible/value.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/move_only_function/call.cc199
-rw-r--r--libstdc++-v3/testsuite/20_util/move_only_function/cons.cc98
-rw-r--r--libstdc++-v3/testsuite/20_util/move_only_function/move.cc109
-rw-r--r--libstdc++-v3/testsuite/20_util/move_only_function/version.cc10
-rw-r--r--libstdc++-v3/testsuite/20_util/specialized_algorithms/memory_management_tools/destroy_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/variant/visit_inherited.cc36
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/cons/char/nullptr.cc4
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string_view/cons/char/nonnull.cc2
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string_view/cons/wchar_t/nonnull.cc2
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/trivially_copyable.cc11
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/cons/deduction.cc29
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/requirements/explicit_instantiation/3.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/cons/deduction.cc29
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/3.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/cons/deduction.cc29
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/operations/66742.cc55
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/requirements/explicit_instantiation/3.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/requirements/explicit_instantiation/5.cc3
-rw-r--r--libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc36
-rw-r--r--libstdc++-v3/testsuite/23_containers/map/requirements/explicit_instantiation/3.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/map/requirements/explicit_instantiation/5.cc3
-rw-r--r--libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc36
-rw-r--r--libstdc++-v3/testsuite/23_containers/multimap/requirements/explicit_instantiation/3.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/multimap/requirements/explicit_instantiation/5.cc3
-rw-r--r--libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc35
-rw-r--r--libstdc++-v3/testsuite/23_containers/multiset/requirements/explicit_instantiation/3.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/multiset/requirements/explicit_instantiation/5.cc3
-rw-r--r--libstdc++-v3/testsuite/23_containers/priority_queue/deduction.cc37
-rw-r--r--libstdc++-v3/testsuite/23_containers/priority_queue/lwg3506.cc54
-rw-r--r--libstdc++-v3/testsuite/23_containers/priority_queue/lwg3522.cc24
-rw-r--r--libstdc++-v3/testsuite/23_containers/priority_queue/lwg3529.cc13
-rw-r--r--libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1.cc11
-rw-r--r--libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1_c++98.cc11
-rw-r--r--libstdc++-v3/testsuite/23_containers/queue/cons_from_iters.cc68
-rw-r--r--libstdc++-v3/testsuite/23_containers/queue/deduction.cc34
-rw-r--r--libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1_c++98.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc35
-rw-r--r--libstdc++-v3/testsuite/23_containers/set/requirements/explicit_instantiation/3.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/set/requirements/explicit_instantiation/5.cc3
-rw-r--r--libstdc++-v3/testsuite/23_containers/span/trivially_copyable.cc13
-rw-r--r--libstdc++-v3/testsuite/23_containers/stack/cons_from_iters.cc65
-rw-r--r--libstdc++-v3/testsuite/23_containers/stack/deduction.cc3
-rw-r--r--libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1_c++98.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/requirements/explicit_instantiation/3.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/requirements/explicit_instantiation/3.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc37
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/requirements/explicit_instantiation/3.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc37
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/requirements/explicit_instantiation/3.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/cons/deduction.cc75
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/ext_pointer/explicit_instantiation/3.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/explicit_instantiation/3.cc2
-rw-r--r--libstdc++-v3/testsuite/24_iterators/normal_iterator/to_address.cc6
-rw-r--r--libstdc++-v3/testsuite/24_iterators/operations/prev_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/24_iterators/output/concept.cc2
-rw-r--r--libstdc++-v3/testsuite/24_iterators/range_operations/lwg3392.cc30
-rw-r--r--libstdc++-v3/testsuite/24_iterators/reverse_iterator/noexcept.cc92
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/copy/34595.cc5
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/is_permutation/2.cc1
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/unique_copy/check_type.cc22
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/volatile_ptr.cc15
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/multiline.cc74
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/84110.cc39
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/assign/exception_safety.cc20
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/other.cc37
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/grammar.cc53
-rw-r--r--libstdc++-v3/testsuite/30_threads/jthread/100612.cc24
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/cons/3.cc5
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/cons/4.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/cons/5.cc4
-rw-r--r--libstdc++-v3/testsuite/ext/pb_ds/example/basic_multimap.cc4
-rw-r--r--libstdc++-v3/testsuite/ext/pb_ds/example/erase_if.cc4
-rw-r--r--libstdc++-v3/testsuite/ext/pb_ds/example/hash_illegal_resize.cc4
-rw-r--r--libstdc++-v3/testsuite/ext/pb_ds/example/hash_initial_size.cc4
-rw-r--r--libstdc++-v3/testsuite/ext/pb_ds/example/hash_load_set_change.cc4
-rw-r--r--libstdc++-v3/testsuite/ext/pb_ds/example/hash_mod.cc4
-rw-r--r--libstdc++-v3/testsuite/ext/pb_ds/example/hash_resize.cc4
-rw-r--r--libstdc++-v3/testsuite/ext/pb_ds/example/hash_shift_mask.cc4
-rw-r--r--libstdc++-v3/testsuite/ext/pb_ds/example/priority_queue_dijkstra.cc4
-rw-r--r--libstdc++-v3/testsuite/ext/pb_ds/example/ranged_hash.cc1
-rw-r--r--libstdc++-v3/testsuite/ext/pb_ds/example/store_hash.cc4
1166 files changed, 53940 insertions, 16816 deletions
diff --git a/ChangeLog b/ChangeLog
index 810b906..913f9a6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2021-09-29 Jonathan Wakely <jwakely@redhat.com>
+
+ * MAINTAINERS: Add myself to DCO section.
+
+2021-09-28 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * configure: Regenerate.
+ * configure.ac (skipdirs): Add the contents of target_configdirs if
+ we are not building gcc.
+
+2021-09-24 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * Makefile.def: Back-port commits ba4d88ad892f and
+ 755ba58ebef0 from binutils-gdb repository.
+ * Makefile.in: Regenerated.
+
2021-09-20 Harald Anlauf <anlauf@gmx.de>
* MAINTAINERS (Reviewers): Add myself as Fortran reviewer.
diff --git a/MAINTAINERS b/MAINTAINERS
index 06b00a5..bf4006c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -569,7 +569,7 @@ Nicolas Pitre <nico@cam.org>
Michael Ploujnikov <michael.ploujnikov@oracle.com>
Paul Pluzhnikov <ppluzhnikov@google.com>
Antoniu Pop <antoniu.pop@gmail.com>
-Siddhesh Poyarekar <siddhesh@sourceware.org>
+Siddhesh Poyarekar <siddhesh@gotplt.org>
Vidya Praveen <vidyapraveen@arm.com>
Thomas Preud'homme <thomas.preudhomme@celest.fr>
Vladimir Prus <vladimir@codesourcery.com>
@@ -708,6 +708,8 @@ information.
Matthias Kretz <m.kretz@gsi.de>
Jeff Law <jeffreyalaw@gmail.com>
Jeff Law <jlaw@tachyum.com>
+ Jonathan Wakely <jwakely@redhat.com>
Gaius Mulley <gaius.mulley@southwales.ac.uk>
+ Siddhesh Poyarekar <siddhesh@gotplt.org>
Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
Petter Tomner <tomner@kth.se>
diff --git a/Makefile.def b/Makefile.def
index 1bed8c1..e015a7a 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -471,6 +471,14 @@ dependencies = { module=all-ld; on=all-libctf; };
dependencies = { module=install-binutils; on=install-opcodes; };
dependencies = { module=install-strip-binutils; on=install-strip-opcodes; };
+// Likewise for ld, libctf, and bfd.
+dependencies = { module=install-libctf; on=install-bfd; };
+dependencies = { module=install-ld; on=install-bfd; };
+dependencies = { module=install-ld; on=install-libctf; };
+dependencies = { module=install-strip-libctf; on=install-strip-bfd; };
+dependencies = { module=install-strip-ld; on=install-strip-bfd; };
+dependencies = { module=install-strip-ld; on=install-strip-libctf; };
+
// libopcodes depends on libbfd
dependencies = { module=install-opcodes; on=install-bfd; };
dependencies = { module=install-strip-opcodes; on=install-strip-bfd; };
@@ -564,6 +572,12 @@ dependencies = { module=configure-libctf; on=all-zlib; };
dependencies = { module=configure-libctf; on=all-libiconv; };
dependencies = { module=check-libctf; on=all-ld; };
+// The Makefiles in gdb and gdbserver pull in a file that configure
+// generates in the gnulib directory, so distclean gnulib only after
+// gdb and gdbserver.
+dependencies = { module=distclean-gnulib; on=distclean-gdb; };
+dependencies = { module=distclean-gnulib; on=distclean-gdbserver; };
+
// Warning, these are not well tested.
dependencies = { module=all-bison; on=all-intl; };
dependencies = { module=all-bison; on=all-build-texinfo; };
diff --git a/Makefile.in b/Makefile.in
index dd63afc..9219ebf 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -60771,6 +60771,12 @@ all-stageautoprofile-ld: maybe-all-stageautoprofile-libctf
all-stageautofeedback-ld: maybe-all-stageautofeedback-libctf
install-binutils: maybe-install-opcodes
install-strip-binutils: maybe-install-strip-opcodes
+install-libctf: maybe-install-bfd
+install-ld: maybe-install-bfd
+install-ld: maybe-install-libctf
+install-strip-libctf: maybe-install-strip-bfd
+install-strip-ld: maybe-install-strip-bfd
+install-strip-ld: maybe-install-strip-libctf
install-opcodes: maybe-install-bfd
install-strip-opcodes: maybe-install-strip-bfd
configure-gas: maybe-configure-intl
@@ -61139,6 +61145,8 @@ check-stagetrain-libctf: maybe-all-stagetrain-ld
check-stagefeedback-libctf: maybe-all-stagefeedback-ld
check-stageautoprofile-libctf: maybe-all-stageautoprofile-ld
check-stageautofeedback-libctf: maybe-all-stageautofeedback-ld
+distclean-gnulib: maybe-distclean-gdb
+distclean-gnulib: maybe-distclean-gdbserver
all-bison: maybe-all-build-texinfo
all-flex: maybe-all-build-bison
all-flex: maybe-all-m4
diff --git a/configure b/configure
index 85ab991..785498e 100755
--- a/configure
+++ b/configure
@@ -8874,6 +8874,16 @@ case ,${enable_languages}, in
;;
esac
+# If gcc/ is not in the source tree then we'll not be building a
+# target compiler, assume in that case we don't want to build any
+# target libraries or tools.
+#
+# This was added primarily for the benefit for binutils-gdb who reuse
+# this configure script, but don't always have target tools available.
+if test ! -d ${srcdir}/gcc; then
+ skipdirs="${skipdirs} ${target_configdirs}"
+fi
+
# Remove the entries in $skipdirs and $noconfigdirs from $configdirs,
# $build_configdirs and $target_configdirs.
# If we have the source for $noconfigdirs entries, add them to $notsupp.
diff --git a/configure.ac b/configure.ac
index 1df038b..c523083 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2272,6 +2272,16 @@ case ,${enable_languages}, in
;;
esac
+# If gcc/ is not in the source tree then we'll not be building a
+# target compiler, assume in that case we don't want to build any
+# target libraries or tools.
+#
+# This was added primarily for the benefit for binutils-gdb who reuse
+# this configure script, but don't always have target tools available.
+if test ! -d ${srcdir}/gcc; then
+ skipdirs="${skipdirs} ${target_configdirs}"
+fi
+
# Remove the entries in $skipdirs and $noconfigdirs from $configdirs,
# $build_configdirs and $target_configdirs.
# If we have the source for $noconfigdirs entries, add them to $notsupp.
diff --git a/contrib/ChangeLog b/contrib/ChangeLog
index 6521f96..156a61b 100644
--- a/contrib/ChangeLog
+++ b/contrib/ChangeLog
@@ -1,3 +1,8 @@
+2021-10-02 Martin Liska <mliska@suse.cz>
+
+ * filter-clang-warnings.py: Filter out -Wtautological-compare
+ for the file.
+
2021-09-20 Richard Biener <rguenther@suse.de>
* config-list.mk: --enable-obsolete for hppa2.0-hpux10.1 and
diff --git a/contrib/filter-clang-warnings.py b/contrib/filter-clang-warnings.py
index 72b5bbe..361a5c6 100755
--- a/contrib/filter-clang-warnings.py
+++ b/contrib/filter-clang-warnings.py
@@ -47,6 +47,7 @@ def skip_warning(filename, message):
'i386.md': ['-Wparentheses-equality', '-Wtautological-compare',
'-Wtautological-overlap-compare'],
'sse.md': ['-Wparentheses-equality', '-Wtautological-compare'],
+ 'mmx.md': ['-Wtautological-compare'],
'genautomata.c': ['-Wstring-plus-int'],
'gfortran.texi': [''],
'libtool': ['']
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index acbbb71..f9b93b2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,1359 @@
+2021-10-06 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-cache.cc (non_null_ref::adjust_range): Call new
+ intersect routine.
+ * gimple-range-fold.cc (adjust_pointer_diff_expr): Ditto.
+ (adjust_imagpart_expr): Ditto.
+ * value-range.cc (irange::irange_intersect): Call new routine if
+ RHS is a single pair.
+ (irange::intersect): New wide_int version.
+ * value-range.h (class irange): New prototype.
+
+2021-10-06 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-edge.cc (gimple_outgoing_range::gimple_outgoing_range):
+ Add parameter to limit size when recognizing switches.
+ (gimple_outgoing_range::edge_range_p): Check size limit.
+ * gimple-range-edge.h (gimple_outgoing_range): Add size field.
+ * gimple-range-gori.cc (gori_map::calculate_gori): Ignore switches
+ that exceed the size limit.
+ (gori_compute::gori_compute): Add initializer.
+ * params.opt (evrp-switch-limit): New.
+ * doc/invoke.texi: Update docs.
+
+2021-10-06 Andrew MacLeod <amacleod@redhat.com>
+
+ * value-range.h (irange::set_varying): Use TYPE_MIN_VALUE and
+ TYPE_MAX_VALUE instead of creating new trees when possible.
+
+2021-10-06 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-cache.cc (non_null_ref::adjust_range): Check for
+ zero and non-zero more efficently.
+
+2021-10-06 Richard Biener <rguenther@suse.de>
+
+ PR c/102605
+ * dumpfile.h (TDF_GIMPLE_VAL): New.
+ (dump_flag): Re-order and adjust TDF_* flags. Make
+ the enum uint32_t. Use std::underlying_type in the
+ operator overloads.
+ (optgroup_flag): Likewise for the operator overloads.
+ * tree-pretty-print.c (dump_generic_node): Wrap ADDR_EXPR
+ in _Literal if TDF_GIMPLE_VAL.
+ * gimple-pretty-print.c (dump_gimple_assign): Add
+ TDF_GIMPLE_VAL to flags when dumping operands where only
+ is_gimple_val are allowed.
+ (dump_gimple_cond): Likewise.
+
+2021-10-06 prathamesh.kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * gimple-isel.cc (gimple_expand_vec_cond_expr): Remove redundant if
+ condition.
+
+2021-10-05 qing zhao <qing.zhao@oracle.com>
+
+ PR middle-end/102359
+ * gimplify.c (gimplify_decl_expr): Not add initialization for an
+ auto variable when it has been initialized by frontend.
+
+2021-10-05 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadupdate.c (jt_path_registry::cancel_invalid_paths):
+ Loosen restrictions
+
+2021-10-05 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * common/config/avr/avr-common.c (avr_handle_option): Mark
+ argument as ATTRIBUTE_UNUSED.
+
+2021-10-05 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * config/lm32/uclinux-elf.h (LINK_GCC_C_SEQUENCE_SPEC):
+ Undefine before redefinition.
+
+2021-10-05 Richard Biener <rguenther@suse.de>
+
+ * toplev.c (no_backend): Remove global var.
+ (process_options): Pass in no_backend, move post_options
+ langhook call to toplev::main.
+ (do_compile): Pass in no_backend, move process_options call
+ to toplev::main.
+ (toplev::run_self_tests): Check no_backend at the caller.
+ (toplev::main): Call post_options and process_options
+ split out from do_compile, do self-tests only if
+ no_backend is initialized.
+
+2021-10-05 Richard Biener <rguenther@suse.de>
+
+ * tree-cfg.c (dump_function_to_file): Dump the UID of the
+ function as part of the name when requested.
+ * tree-pretty-print.c (dump_function_name): Dump the UID when
+ requested and the langhook produced the actual name.
+
+2021-10-05 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102587
+ PR middle-end/102285
+ * internal-fn.c (expand_DEFERRED_INIT): Fall back to
+ zero-initialization as last resort, use the constant
+ size as given by the DEFERRED_INIT argument to build
+ the initializer.
+
+2021-10-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * doc/invoke.texi: Document -Warray-compare.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ * gimplify.c (is_var_need_auto_init): DECL_HARD_REGISTER
+ variables are not to be initialized.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ * expr.h (non_mem_decl_p): Declare.
+ (mem_ref_refers_to_non_mem_p): Likewise.
+ * expr.c (non_mem_decl_p): Export.
+ (mem_ref_refers_to_non_mem_p): Likewise.
+ * internal-fn.c (expand_DEFERRED_INIT): Do not expand the LHS
+ but check the base with mem_ref_refers_to_non_mem_p
+ and non_mem_decl_p.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102570
+ * tree-ssa-sccvn.h (vn_reference_op_struct): Document
+ we are using clique for the internal function code.
+ * tree-ssa-sccvn.c (vn_reference_op_eq): Compare the
+ internal function code.
+ (print_vn_reference_ops): Print the internal function code.
+ (vn_reference_op_compute_hash): Hash it.
+ (copy_reference_ops_from_call): Record it.
+ (visit_stmt): Remove the restriction around internal function
+ calls.
+ (fully_constant_vn_reference_p): Use fold_const_call and handle
+ internal functions.
+ (vn_reference_eq): Compare call return types.
+ * tree-ssa-pre.c (create_expression_by_pieces): Handle
+ generating calls to internal functions.
+ (compute_avail): Remove the restriction around internal function
+ calls.
+
+2021-10-04 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/102560
+ * gimple-ssa-warn-alloca.c (alloca_call_type): Remove static
+ marker for invalid_range.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102587
+ * internal-fn.c (expand_DEFERRED_INIT): Guard register
+ initialization path an avoid initializing VLA registers
+ with it.
+
+2021-10-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/rs6000/vxworks.h (TARGET_INIT_LIBFUNCS): Delete.
+
+2021-10-03 Martin Liska <mliska@suse.cz>
+
+ * toplev.c (toplev::main): Check opt_index if it is a part
+ of cl_options.
+
+2021-10-02 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/102563
+ * range-op.cc (operator_lshift::op1_range): Do not clobber
+ range.
+
+2021-10-02 Martin Liska <mliska@suse.cz>
+
+ * toplev.c (toplev::main): save_decoded_options[0] is program
+ name and so it should be skipped.
+
+2021-10-01 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/102546
+ * range-op.cc (operator_lshift::op1_range): Teach range-ops that
+ X << Y is non-zero implies X is also non-zero.
+
+2021-10-01 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/aarch64/aarch64-cores.def (AARCH64_CORE): New
+ Cortex-X2 core.
+ * config/aarch64/aarch64-tune.md: Regenerate.
+ * doc/invoke.texi: Update docs.
+
+2021-10-01 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/aarch64/aarch64-cores.def (AARCH64_CORE): New
+ Cortex-A710 core.
+ * config/aarch64/aarch64-tune.md: Regenerate.
+ * doc/invoke.texi: Update docs.
+
+2021-10-01 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/aarch64/aarch64-cores.def (AARCH64_CORE): New
+ Cortex-A510 core.
+ * config/aarch64/aarch64-tune.md: Regenerate.
+ * doc/invoke.texi: Update docs.
+
+2021-10-01 Martin Sebor <msebor@redhat.com>
+
+ PR c/102103
+ * doc/invoke.texi (-Waddress): Update.
+ * gengtype.c (write_types): Avoid -Waddress.
+ * poly-int.h (POLY_SET_COEFF): Avoid using null.
+
+2021-10-01 John David Anglin <danglin@gcc.gnu.org>
+
+ PR debug/102373
+ * config/pa/pa.c (pa_option_override): Default to dwarf version 4
+ on hppa64-hpux.
+
+2021-10-01 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/aarch64/aarch64.h (AARCH64_FL_V9): Update value.
+
+2021-10-01 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::compute_ranges): Use
+ get_path_oracle.
+ * gimple-range-path.h (class path_range_query): Remove shadowed
+ m_oracle field.
+ (path_range_query::get_path_oracle): New.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+ Richard Biener <rguenther@suse.de>
+
+ PR sanitizer/102515
+ * doc/invoke.texi (-fsanitize=integer-divide-by-zero): Remove
+ INT_MIN / -1 division detection from here ...
+ (-fsanitize=signed-integer-overflow): ... and add it here.
+
+2021-10-01 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/aarch64/aarch64-arches.def (AARCH64_ARCH): Added
+ armv9-a.
+ * config/aarch64/aarch64.h (AARCH64_FL_V9): New.
+ (AARCH64_FL_FOR_ARCH9): New flags for Armv9-A.
+ (AARCH64_ISA_V9): New ISA flag.
+ * doc/invoke.texi: Update docs.
+
+2021-10-01 Martin Liska <mliska@suse.cz>
+
+ * toplev.c (toplev::main): Save decoded optimization options.
+ * toplev.h (save_opt_decoded_options): New.
+ * doc/extend.texi: Be more clear about optimize and target
+ attributes.
+
+2021-10-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * explow.c: Include langhooks.h.
+ (set_stack_check_libfunc): Build a proper function type.
+
+2021-10-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR c++/64697
+ * config/i386/i386.c (legitimate_pic_address_disp_p): For PE-COFF do
+ not return true for external weak function symbols in medium model.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * tree.h (OMP_CLAUSE_ORDER_REPRODUCIBLE): Define.
+ * tree-pretty-print.c (dump_omp_clause) <case OMP_CLAUSE_ORDER>: Print
+ reproducible: for OMP_CLAUSE_ORDER_REPRODUCIBLE.
+ * omp-general.c (omp_extract_for_data): If OMP_CLAUSE_ORDER is seen
+ without OMP_CLAUSE_ORDER_UNCONSTRAINED, overwrite sched_kind to
+ OMP_CLAUSE_SCHEDULE_STATIC.
+
+2021-10-01 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102518
+ * tree-inline.c (setup_one_parameter): Avoid substituting
+ an invariant into contexts where a GIMPLE register is not valid.
+
+2021-09-30 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/arm/arm-cpus.in: Add Cortex-R52+ CPU.
+ * config/arm/arm-tables.opt: Regenerate.
+ * config/arm/arm-tune.md: Regenerate.
+ * doc/invoke.texi: Update docs.
+
+2021-09-30 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/89954
+ * config/i386/i386.md
+ (sign_extend:WIDE (any_logic:NARROW (memory, immediate)) splitters):
+ New splitters.
+
+2021-09-30 Tobias Burnus <tobias@codesourcery.com>
+
+ * omp-low.c (omp_runtime_api_call): Add omp_aligned_{,c}alloc and
+ omp_{c,re}alloc, fix omp_alloc/omp_free.
+
+2021-09-30 Martin Liska <mliska@suse.cz>
+
+ * defaults.h (ASM_OUTPUT_ASCII): Do not hide global variable
+ asm_out_file and stream directly to MYFILE.
+
+2021-09-30 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.c (vect_update_misalignment_for_peel):
+ Restore and fix condition under which we apply npeel to
+ the DRs misalignment value.
+
+2021-09-30 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.c (vect_update_misalignment_for_peel):
+ Fix npeel check for variable amount of peeling.
+
+2021-09-30 Aldy Hernandez <aldyh@redhat.com>
+
+ * lto-wrapper.c (run_gcc): Plug snprintf overflow.
+
+2021-09-30 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range.cc (gimple_ranger::debug): New.
+ * gimple-range.h (class gimple_ranger): Add debug.
+
+2021-09-30 Aldy Hernandez <aldyh@redhat.com>
+
+ PR middle-end/102519
+ * tree-vrp.c (hybrid_threader::~hybrid_threader): Free m_query.
+
+2021-09-29 Indu Bhagat <indu.bhagat@oracle.com>
+
+ PR debug/102507
+ * btfout.c (GTY): Add GTY (()) albeit for cosmetic only purpose.
+ (btf_finalize): Empty the hash_map btf_var_ids.
+
+2021-09-29 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (thread_through_all_blocks): Return bool.
+ (execute_vrp_threader): Return TODO_* flags.
+ (pass_data_vrp_threader): Set todo_flags_finish to 0.
+
+2021-09-29 Aldy Hernandez <aldyh@redhat.com>
+
+ * timevar.def (TV_TREE_VRP_THREADER): New.
+ * tree-vrp.c: Use TV_TREE_VRP_THREADER for VRP threader pass.
+
+2021-09-29 David Faust <david.faust@oracle.com>
+
+ * config.gcc (bpf-*-*): Do not overwrite extra_headers.
+
+2021-09-29 Jonathan Wright <jonathan.wright@arm.com>
+
+ * config/aarch64/aarch64-builtins.c (TYPES_BINOP_PPU): Define
+ new type qualifier enum.
+ (TYPES_TERNOP_SSSU): Likewise.
+ (TYPES_TERNOP_PPPU): Likewise.
+ * config/aarch64/aarch64-simd-builtins.def: Define PPU, SSU,
+ PPPU and SSSU builtin generator macros for qtbl1 and qtbx1
+ Neon builtins.
+ * config/aarch64/arm_neon.h (vqtbl1_p8): Use type-qualified
+ builtin and remove casts.
+ (vqtbl1_s8): Likewise.
+ (vqtbl1q_p8): Likewise.
+ (vqtbl1q_s8): Likewise.
+ (vqtbx1_s8): Likewise.
+ (vqtbx1_p8): Likewise.
+ (vqtbx1q_s8): Likewise.
+ (vqtbx1q_p8): Likewise.
+ (vtbl1_p8): Likewise.
+ (vtbl2_p8): Likewise.
+ (vtbx2_p8): Likewise.
+
+2021-09-29 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.c (vect_dr_misalign_for_aligned_access):
+ New helper.
+ (vect_update_misalignment_for_peel): Use it to update
+ misaligned to the value necessary for an aligned access.
+ (vect_get_peeling_costs_all_drs): Likewise.
+ (vect_enhance_data_refs_alignment): Likewise.
+
+2021-09-29 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_expand_cpymem): Count number of
+ emitted operations and adjust heuristic for code size.
+
+2021-09-29 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_expand_setmem): Count number of
+ emitted operations and adjust heuristic for code size.
+
+2021-09-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/102504
+ * gimplify.c (gimplify_scan_omp_clauses): Use omp_check_private even
+ in OMP_SCOPE clauses, not just on worksharing construct clauses.
+
+2021-09-28 Geng Qi <gengqi@linux.alibaba.com>
+
+ * config/riscv/riscv.md (mulv<mode>4): Call gen_smul<mode>3_highpart.
+ (<u>mulditi3): Call <su>muldi3_highpart.
+ (<u>muldi3_highpart): Rename to <su>muldi3_highpart.
+ (<u>mulsidi3): Call <su>mulsi3_highpart.
+ (<u>mulsi3_highpart): Rename to <su>mulsi3_highpart.
+
+2021-09-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.h (DSYMUTIL_SPEC): Recognize D sources.
+
+2021-09-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/rs6000/darwin.h (FIXED_R13): Add for PPC64.
+ (FIRST_SAVED_GP_REGNO): Save from R13 even when it is one
+ of the fixed regs.
+
+2021-09-28 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.h (AARCH64_FL_LS64): Define
+ (AARCH64_FL_V8_7): Likewise.
+ (AARCH64_FL_FOR_ARCH8_7): Likewise.
+ * config/aarch64/aarch64-arches.def (armv8.7-a): Define.
+ * config/aarch64/aarch64-option-extensions.def (ls64): Define.
+ * doc/invoke.texi: Document the above.
+
+2021-09-28 Aldy Hernandez <aldyh@redhat.com>
+
+ * dbgcnt.c (dbg_cnt_counter): New.
+ * dbgcnt.h (dbg_cnt_counter): New.
+ * dumpfile.c (dump_options): Add entry for TDF_THREADING.
+ * dumpfile.h (enum dump_flag): Add TDF_THREADING.
+ * gimple-range-path.cc (DEBUG_SOLVER): Use TDF_THREADING.
+ * tree-ssa-threadupdate.c (dump_jump_thread_path): Dump out
+ debug counter.
+
+2021-09-28 Aldy Hernandez <aldyh@redhat.com>
+
+ * cfgcleanup.c (pass_jump::execute): Check
+ flag_expensive_optimizations.
+ (pass_jump_after_combine::gate): Same.
+ * doc/invoke.texi (-fthread-jumps): Enable for -O1.
+ * opts.c (default_options_table): Enable -fthread-jumps at -O1.
+ * tree-ssa-threadupdate.c
+ (fwd_jt_path_registry::remove_jump_threads_including): Bail unless
+ flag_thread_jumps.
+
+2021-09-28 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * tree-ssa-reassoc.c (biased_names): New global.
+ (propagate_bias_p): New function.
+ (loop_carried_phi): Remove.
+ (propagate_rank): Propagate bias along single uses.
+ (get_rank): Update biased_names when needed.
+
+2021-09-28 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * passes.def (pass_reassoc): Rename parameter to early_p.
+ * tree-ssa-reassoc.c (reassoc_bias_loop_carried_phi_ranks_p):
+ New variable.
+ (phi_rank): Don't bias loop-carried phi ranks
+ before vectorization pass.
+ (execute_reassoc): Add bias_loop_carried_phi_ranks_p parameter.
+ (pass_reassoc::pass_reassoc): Add bias_loop_carried_phi_ranks_p
+ initializer.
+ (pass_reassoc::set_param): Set bias_loop_carried_phi_ranks_p
+ value.
+ (pass_reassoc::execute): Pass bias_loop_carried_phi_ranks_p to
+ execute_reassoc.
+ (pass_reassoc::bias_loop_carried_phi_ranks_p): New member.
+
+2021-09-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/102498
+ * config/i386/i386.c (standard_80387_constant_p): Don't recognize
+ special 80387 instruction XFmode constants if flag_rounding_math.
+
+2021-09-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/100112
+ * tree-ssa-sccvn.c (visit_reference_op_load): Record the
+ referece into the hashtable twice in case last_vuse is
+ different from the original vuse on the stmt.
+
+2021-09-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/102492
+ * gimplify.c (gimplify_adjust_omp_clauses_1): Don't call the
+ omp_finish_clause langhook on implicitly added OMP_CLAUSE_PRIVATE
+ clauses on SIMD constructs.
+
+2021-09-28 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/102511
+ * gimple-range-path.cc (path_range_query::range_on_path_entry):
+ Return VARYING when nothing found.
+
+2021-09-28 Hongyu Wang <hongyu.wang@intel.com>
+
+ PR target/102230
+ * config/i386/i386.h (VALID_AVX512FP16_REG_MODE): Add
+ V2HF mode check.
+ (VALID_SSE2_REG_VHF_MODE): Add V4HFmode and V2HFmode.
+ (VALID_MMX_REG_MODE): Add V4HFmode.
+ (SSE_REG_MODE_P): Replace VALID_AVX512FP16_REG_MODE with
+ vector mode condition.
+ * config/i386/i386.c (classify_argument): Parse V4HF/V2HF
+ via sse regs.
+ (function_arg_32): Add V4HFmode.
+ (function_arg_advance_32): Likewise.
+ * config/i386/i386.md (mode): Add V4HF/V2HF.
+ (MODE_SIZE): Likewise.
+ * config/i386/mmx.md (MMXMODE): Add V4HF mode.
+ (V_32): Add V2HF mode.
+ (VHF_32_64): New mode iterator.
+ (*mov<mode>_internal): Adjust sse alternatives to support
+ V4HF mode move.
+ (*mov<mode>_internal): Adjust sse alternatives to support
+ V2HF mode move.
+ (<insn><mode>3): New define_insn for add/sub/mul/div.
+
+2021-09-28 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadbackward.c (pass_thread_jumps::gate): Check
+ flag_thread_jumps.
+ (pass_early_thread_jumps::gate): Same.
+ * tree-ssa-threadedge.c (jump_threader::thread_outgoing_edges):
+ Return if !flag_thread_jumps.
+ * tree-ssa-threadupdate.c
+ (jt_path_registry::register_jump_thread): Assert that
+ flag_thread_jumps is true.
+
+2021-09-28 liuhongt <hongtao.liu@intel.com>
+
+ * simplify-rtx.c
+ (simplify_context::simplify_binary_operation_1): Relax
+ condition of simplifying (vec_concat:M (vec_select op0
+ index0)(vec_select op1 index1)) to allow different modes
+ between op0 and M, but have same inner mode.
+
+2021-09-28 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386-expand.c (emit_reduc_half): Handle
+ V8HF/V16HF/V32HFmode.
+ * config/i386/sse.md (REDUC_SSE_PLUS_MODE): Add V8HF.
+ (REDUC_SSE_SMINMAX_MODE): Ditto.
+ (REDUC_PLUS_MODE): Add V16HF and V32HF.
+ (REDUC_SMINMAX_MODE): Ditto.
+
+2021-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc
+ (path_range_query::precompute_ranges_in_block): Rename to...
+ (path_range_query::compute_ranges_in_block): ...this.
+ (path_range_query::precompute_ranges): Rename to...
+ (path_range_query::compute_ranges): ...this.
+ (path_range_query::precompute_relations): Rename to...
+ (path_range_query::compute_relations): ...this.
+ (path_range_query::precompute_phi_relations): Rename to...
+ (path_range_query::compute_phi_relations): ...this.
+ * gimple-range-path.h: Rename precompute* to compute*.
+ * tree-ssa-threadbackward.c
+ (back_threader::find_taken_edge_switch): Same.
+ (back_threader::find_taken_edge_cond): Same.
+ * tree-ssa-threadedge.c
+ (hybrid_jt_simplifier::compute_ranges_from_state): Same.
+ (hybrid_jt_state::register_equivs_stmt): Inline...
+ * tree-ssa-threadedge.h: ...here.
+
+2021-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (lhs_of_dominating_assert): Remove.
+ (class vrp_jt_state): Remove.
+ (class vrp_jt_simplifier): Remove.
+ (vrp_jt_simplifier::simplify): Remove.
+ (class vrp_jump_threader): Remove.
+ (vrp_jump_threader::vrp_jump_threader): Remove.
+ (vrp_jump_threader::~vrp_jump_threader): Remove.
+ (vrp_jump_threader::before_dom_children): Remove.
+ (vrp_jump_threader::after_dom_children): Remove.
+
+2021-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * passes.def (pass_vrp_threader): New.
+ * tree-pass.h (make_pass_vrp_threader): Add make_pass_vrp_threader.
+ * tree-ssa-threadedge.c (hybrid_jt_state::register_equivs_stmt): New.
+ (hybrid_jt_simplifier::hybrid_jt_simplifier): New.
+ (hybrid_jt_simplifier::simplify): New.
+ (hybrid_jt_simplifier::compute_ranges_from_state): New.
+ * tree-ssa-threadedge.h (class hybrid_jt_state): New.
+ (class hybrid_jt_simplifier): New.
+ * tree-vrp.c (execute_vrp): Remove ASSERT_EXPR based jump
+ threader.
+ (class hybrid_threader): New.
+ (hybrid_threader::hybrid_threader): New.
+ (hybrid_threader::~hybrid_threader): New.
+ (hybrid_threader::before_dom_children): New.
+ (hybrid_threader::after_dom_children): New.
+ (execute_vrp_threader): New.
+ (class pass_vrp_threader): New.
+ (make_pass_vrp_threader): New.
+
+2021-09-27 Martin Liska <mliska@suse.cz>
+
+ * output.h (enum section_flag): New.
+ (SECTION_FORGET): Remove.
+ (SECTION_ENTSIZE): Make it (1UL << 8) - 1.
+ (SECTION_STYLE_MASK): Define it based on other enum
+ values.
+ * varasm.c (switch_to_section): Remove unused handling of
+ SECTION_FORGET.
+
+2021-09-27 Martin Liska <mliska@suse.cz>
+
+ * common.opt: Add new variable flag_default_complex_method.
+ * opts.c (finish_options): Handle flags related to
+ x_flag_complex_method.
+ * toplev.c (process_options): Remove option handling related
+ to flag_complex_method.
+
+2021-09-27 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102450
+ * gimple-fold.c (gimple_fold_builtin_memory_op): Avoid using
+ type_for_size, instead use int_mode_for_size.
+
+2021-09-27 Andrew Pinski <apinski@marvell.com>
+
+ PR c/94726
+ * gimplify.c (gimplify_save_expr): Return early
+ if the type of val is error_mark_node.
+
+2021-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssanames.c (ssa_name_has_boolean_range): Use
+ get_range_query.
+
+2021-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-ssa-evrp-analyze.h (class evrp_range_analyzer): Remove
+ vrp_visit_cond_stmt.
+ * tree-ssa-dom.c (cprop_operand): Convert to range_query API.
+ (cprop_into_stmt): Same.
+ (dom_opt_dom_walker::optimize_stmt): Same.
+
+2021-09-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97351
+ PR tree-optimization/97352
+ PR tree-optimization/82426
+ * tree-vectorizer.h (dr_misalignment): Add vector type
+ argument.
+ (aligned_access_p): Likewise.
+ (known_alignment_for_access_p): Likewise.
+ (vect_supportable_dr_alignment): Likewise.
+ (vect_known_alignment_in_bytes): Likewise. Refactor.
+ (DR_MISALIGNMENT): Remove.
+ (vect_update_shared_vectype): Likewise.
+ * tree-vect-data-refs.c (dr_misalignment): Refactor, handle
+ a vector type with larger alignment requirement and apply
+ the negative step adjustment here.
+ (vect_calculate_target_alignment): Remove.
+ (vect_compute_data_ref_alignment): Get explicit vector type
+ argument, do not apply a negative step alignment adjustment
+ here.
+ (vect_slp_analyze_node_alignment): Re-analyze alignment
+ when we re-visit the DR with a bigger desired alignment but
+ keep more precise results from smaller alignments.
+ * tree-vect-slp.c (vect_update_shared_vectype): Remove.
+ (vect_slp_analyze_node_operations_1): Do not update the
+ shared vector type on stmts.
+ * tree-vect-stmts.c (vect_analyze_stmt): Push/pop the
+ vector type of an SLP node to the representative stmt-info.
+ (vect_transform_stmt): Likewise.
+
+2021-09-27 liuhongt <hongtao.liu@intel.com>
+
+ Revert:
+ 2021-09-09 liuhongt <hongtao.liu@intel.com>
+
+ PR target/101059
+ * config/i386/sse.md (reduc_plus_scal_<mode>): Split to ..
+ (reduc_plus_scal_v4sf): .. this, New define_expand.
+ (reduc_plus_scal_v2df): .. and this, New define_expand.
+
+2021-09-26 liuhongt <hongtao.liu@intel.com>
+
+ * doc/extend.texi (Half-Precision): Remove storage only
+ description for _Float16 w/o avx512fp16.
+
+2021-09-25 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * config/pru/constraints.md (Rrio): New constraint.
+ * config/pru/predicates.md (regio_operand): New predicate.
+ * config/pru/pru-pragma.c (pru_register_pragmas): Register
+ the __regio_symbol address space.
+ * config/pru/pru-protos.h (pru_symref2ioregno): Declaration.
+ * config/pru/pru.c (pru_symref2ioregno): New helper function.
+ (pru_legitimate_address_p): Remove.
+ (pru_addr_space_legitimate_address_p): Use the address space
+ aware hook variant.
+ (pru_nongeneric_pointer_addrspace): New helper function.
+ (pru_insert_attributes): New function to validate __regio_symbol
+ usage.
+ (TARGET_INSERT_ATTRIBUTES): New macro.
+ (TARGET_LEGITIMATE_ADDRESS_P): Remove.
+ (TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P): New macro.
+ * config/pru/pru.h (enum reg_class): Add REGIO_REGS class.
+ * config/pru/pru.md (*regio_readsi): New pattern to read I/O
+ registers.
+ (*regio_nozext_writesi): New pattern to write to I/O registers.
+ (*regio_zext_write_r30<EQS0:mode>): Ditto.
+ * doc/extend.texi: Document the new PRU Named Address Space.
+
+2021-09-24 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/98216
+ PR c++/91292
+ * real.c (encode_ieee_double): Avoid unwanted sign extension.
+ (encode_ieee_quad): Likewise.
+
+2021-09-24 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/102147
+ * ira-build.c (ira_conflict_vector_profitable_p): Make
+ profitability calculation independent of host compiler pointer and
+ IRA_INT_BITS sizes.
+
+2021-09-24 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::path_range_query):
+ Move debugging header...
+ (path_range_query::precompute_ranges): ...here.
+ (path_range_query::internal_range_of_expr): Do not call
+ range_on_path_entry if NAME is defined in the current block.
+
+2021-09-24 Richard Biener <rguenther@suse.de>
+
+ * cfghooks.c (verify_flow_info): Verify unallocated BB and
+ edge flags are not set.
+
+2021-09-24 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadupdate.c (jt_path_registry::cancel_invalid_paths):
+ New.
+ (jt_path_registry::register_jump_thread): Call
+ cancel_invalid_paths.
+ * tree-ssa-threadupdate.h (class jt_path_registry): Add
+ cancel_invalid_paths.
+
+2021-09-24 Feng Xue <fxue@os.amperecomputing.com>
+
+ PR tree-optimization/102400
+ * tree-ssa-sccvn.c (vn_reference_insert_pieces): Initialize
+ result_vdef to zero value.
+
+2021-09-24 Feng Xue <fxue@os.amperecomputing.com>
+
+ PR tree-optimization/102451
+ * tree-ssa-dse.c (delete_dead_or_redundant_call): Record bb of stmt
+ before removal.
+
+2021-09-24 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/sse.md (cond_<insn><mode>): Extend to support
+ vector HFmodes.
+ (cond_mul<mode>): Likewise.
+ (cond_div<mode>): Likewise.
+ (cond_<code><mode>): Likewise.
+ (cond_fma<mode>): Likewise.
+ (cond_fms<mode>): Likewise.
+ (cond_fnma<mode>): Likewise.
+ (cond_fnms<mode>): Likewise.
+
+2021-09-23 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/102463
+ * gimple-range-fold.cc (fold_using_range::relation_fold_and_or): If
+ there is no range-ops handler, don't look for a relation.
+
+2021-09-23 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-cache.cc (ranger_cache::ranger_cache): Take
+ non-executable_edge flag as parameter.
+ * gimple-range-cache.h (ranger_cache): Adjust prototype.
+ * gimple-range-gori.cc (gori_compute::gori_compute): Take
+ non-executable_edge flag as parameter.
+ (gori_compute::outgoing_edge_range_p): Check new flag.
+ * gimple-range-gori.h (gori_compute): Adjust prototype.
+ * gimple-range.cc (gimple_ranger::gimple_ranger): Create new flag.
+ (gimple_ranger::range_on_edge): Check new flag.
+ * gimple-range.h (gimple_ranger::non_executable_edge_flag): New.
+ * gimple-ssa-evrp.c (rvrp_folder): Pass ranger flag to simplifer.
+ (hybrid_folder::hybrid_folder): Set ranger non-executable flag value.
+ (hybrid_folder::fold_stmt): Set flag value in the simplifer.
+ * vr-values.c (simplify_using_ranges::set_and_propagate_unexecutable):
+ Use not_executable flag if provided inmstead of EDGE_EXECUTABLE.
+ (simplify_using_ranges::simplify_switch_using_ranges): Clear
+ EDGE_EXECUTABLE like it originally did.
+ (simplify_using_ranges::cleanup_edges_and_switches): Clear any
+ NON_EXECUTABLE flags.
+ (simplify_using_ranges::simplify_using_ranges): Adjust.
+ * vr-values.h (class simplify_using_ranges): Adjust.
+ (simplify_using_ranges::set_range_query): Add non-executable flag param.
+
+2021-09-23 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ PR target/102024
+ * config/rs6000/rs6000-call.c (rs6000_aggregate_candidate): Detect
+ zero-width bit fields and return indicator.
+ (rs6000_discover_homogeneous_aggregate): Diagnose when the
+ presence of a zero-width bit field changes parameter passing in
+ GCC 12.
+
+2021-09-23 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-fold.cc (fold_using_range::range_of_phi):
+ Remove dominator check.
+
+2021-09-23 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::precompute_relations):
+ Hoist edge calculations before using EDGE_SUCC.
+
+2021-09-23 Jonathan Wakely <jwakely@redhat.com>
+
+ * configure.ac: Fix --with-multilib-list description.
+ * configure: Regenerate.
+
+2021-09-23 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102448
+ * tree-vect-data-refs.c (vect_duplicate_ssa_name_ptr_info):
+ Clear alignment info copied from DR_PTR_INFO.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/i386-expand.c (ix86_use_mask_cmp_p): Enable
+ HFmode mask_cmp.
+ * config/i386/sse.md (sseintvecmodelower): Add HF vector modes.
+ (<avx512>_store<mode>_mask): Extend to support HF vector modes.
+ (vec_cmp<mode><avx512fmaskmodelower>): Likewise.
+ (vcond_mask_<mode><avx512fmaskmodelower>): Likewise.
+ (vcond<mode><mode>): New expander.
+ (vcond<mode><sseintvecmodelower>): Likewise.
+ (vcond<sseintvecmodelower><mode>): Likewise.
+ (vcondu<mode><sseintvecmodelower>): Likewise.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/sse.md (extend<ssePHmodelower><mode>2):
+ New expander.
+ (extendv4hf<mode>2): Likewise.
+ (extendv2hfv2df2): Likewise.
+ (trunc<mode><ssePHmodelower>2): Likewise.
+ (avx512fp16_vcvt<castmode>2ph_<mode>): Rename to ...
+ (trunc<mode>v4hf2): ... this, and drop constraints.
+ (avx512fp16_vcvtpd2ph_v2df): Rename to ...
+ (truncv2dfv2hf2): ... this, and likewise.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/sse.md (float<floatunssuffix><mode><ssePHmodelower>2):
+ New expander.
+ (avx512fp16_vcvt<floatsuffix><sseintconvert>2ph_<mode>):
+ Rename to ...
+ (float<floatunssuffix><mode>v4hf2): ... this, and drop constraints.
+ (avx512fp16_vcvt<floatsuffix>qq2ph_v2di): Rename to ...
+ (float<floatunssuffix>v2div2hf2): ... this, and likewise.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/i386.md (fix<fixunssuffix>_trunchf<mode>2): New expander.
+ (fixuns_trunchfhi2): Likewise.
+ (*fixuns_trunchfsi2zext): New define_insn.
+ * config/i386/sse.md (ssePHmodelower): New mode_attr.
+ (fix<fixunssuffix>_trunc<ssePHmodelower><mode>2):
+ New expander for same element vector fix_truncate.
+ (fix<fixunssuffix>_trunc<ssePHmodelower><mode>2):
+ Likewise for V4HF to V4SI/V4DI fix_truncate.
+ (fix<fixunssuffix>_truncv2hfv2di2):
+ Likeise for V2HF to V2DI fix_truncate.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/i386.md (<code>hf3): New expander.
+
+2021-09-23 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/sse.md (FMAMODEM): extend to handle FP16.
+ (VFH_SF_AVX512VL): Extend to handle HFmode.
+ (VF_SF_AVX512VL): Deleted.
+
+2021-09-23 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386.md (rinthf2): New expander.
+ (nearbyinthf2): New expander.
+
+2021-09-23 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-dom.c (class dom_jump_threader_simplifier): Rename...
+ (class dom_jt_state): ...this and provide virtual overrides.
+ (dom_jt_state::register_equiv): New.
+ (class dom_jt_simplifier): Rename from
+ dom_jump_threader_simplifier.
+ (dom_jump_threader_simplifier::simplify): Rename...
+ (dom_jt_simplifier::simplify): ...to this.
+ (pass_dominator::execute): Use dom_jt_simplifier and
+ dom_jt_state.
+ * tree-ssa-threadedge.c (jump_threader::jump_threader):
+ Clean-up.
+ (jt_state::register_equivs_stmt): Abstract out...
+ (jump_threader::record_temporary_equivalences_from_stmts_at_dest):
+ ...from here.
+ (jump_threader::thread_around_empty_blocks): Update state.
+ (jump_threader::thread_through_normal_block): Same.
+ (jt_state::jt_state): Remove.
+ (jt_state::push): Remove pass specific bits. Keep block vector
+ updated.
+ (jt_state::append_path): New.
+ (jt_state::pop): Remove pass specific bits.
+ (jt_state::register_equiv): Same.
+ (jt_state::record_ranges_from_stmt): Same.
+ (jt_state::register_equivs_on_edge): Same. Rename...
+ (jt_state::register_equivs_edge): ...to this.
+ (jt_state::dump): New.
+ (jt_state::debug): New.
+ (jump_threader_simplifier::simplify): Remove.
+ (jt_state::get_path): New.
+ * tree-ssa-threadedge.h (class jt_simplifier): Make into a base
+ class. Expose common functionality as virtual methods.
+ (class jump_threader_simplifier): Same. Rename...
+ (class jt_simplifier): ...to this.
+ * tree-vrp.c (class vrp_jump_threader_simplifier): Rename...
+ (class vrp_jt_simplifier): ...to this. Provide pass specific
+ overrides.
+ (class vrp_jt_state): New.
+ (vrp_jump_threader_simplifier::simplify): Rename...
+ (vrp_jt_simplifier::simplify): ...to this. Inline code from
+ what used to be the base class.
+ (vrp_jump_threader::vrp_jump_threader): Use vrp_jt_state and
+ vrp_jt_simplifier.
+
+2021-09-22 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * doc/invoke.texi (-Wno-missing-include-dirs.): Document Fortran
+ behavior.
+
+2021-09-22 Roger Sayle <roger@nextmovesoftware.com>
+ Richard Biener <rguenther@suse.de>
+
+ * match.pd (negation simplifications): Implement some negation
+ folding transformations from fold-const.c's fold_negate_expr.
+ * tree-ssa-sccvn.c (vn_nary_build_or_lookup_1): Add a SIMPLIFY
+ argument, to control whether the op should be simplified prior
+ to looking up/assigning a value number.
+ (vn_nary_build_or_lookup): Update call to vn_nary_build_or_lookup_1.
+ (vn_nary_simplify): Likewise.
+ (visit_nary_op): Likewise, but when constructing a NEGATE_EXPR
+ now call vn_nary_build_or_lookup_1 disabling simplification.
+
+2021-09-22 Jiufu Guo <guojiufu@linux.ibm.com>
+
+ PR tree-optimization/102087
+ * tree-ssa-loop-niter.c (number_of_iterations_until_wrap):
+ Update bound/cmp/control for niter.
+
+2021-09-22 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-fold.cc (fold_using_range::range_of_range_op):
+ Move check for non-empty BB here.
+ (fur_source::register_outgoing_edges): ...from here.
+
+2021-09-22 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::internal_range_of_expr):
+ Remove call to improve_range_with_equivs.
+ (path_range_query::improve_range_with_equivs): Remove
+ * gimple-range-path.h: Remove improve_range_with_equivs.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * config/i386/avx512fp16intrin.h:
+ (_mm512_mask_blend_ph): New intrinsic.
+ (_mm512_permutex2var_ph): Ditto.
+ (_mm512_permutexvar_ph): Ditto.
+ * config/i386/avx512fp16vlintrin.h:
+ (_mm256_mask_blend_ph): New intrinsic.
+ (_mm256_permutex2var_ph): Ditto.
+ (_mm256_permutexvar_ph): Ditto.
+ (_mm_mask_blend_ph): Ditto.
+ (_mm_permutex2var_ph): Ditto.
+ (_mm_permutexvar_ph): Ditto.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * config/i386/avx512fp16intrin.h: Add new intrinsics.
+ (_mm512_conj_pch): New intrinsic.
+ (_mm512_mask_conj_pch): Ditto.
+ (_mm512_maskz_conj_pch): Ditto.
+ * config/i386/avx512fp16vlintrin.h: Add new intrinsics.
+ (_mm256_conj_pch): New intrinsic.
+ (_mm256_mask_conj_pch): Ditto.
+ (_mm256_maskz_conj_pch): Ditto.
+ (_mm_conj_pch): Ditto.
+ (_mm_mask_conj_pch): Ditto.
+ (_mm_maskz_conj_pch): Ditto.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_MM512_REDUCE_OP): New macro
+ (_mm512_reduce_add_ph): New intrinsic.
+ (_mm512_reduce_mul_ph): Ditto.
+ (_mm512_reduce_min_ph): Ditto.
+ (_mm512_reduce_max_ph): Ditto.
+ * config/i386/avx512fp16vlintrin.h
+ (_MM256_REDUCE_OP/_MM_REDUCE_OP): New macro.
+ (_mm256_reduce_add_ph): New intrinsic.
+ (_mm256_reduce_mul_ph): Ditto.
+ (_mm256_reduce_min_ph): Ditto.
+ (_mm256_reduce_max_ph): Ditto.
+ (_mm_reduce_add_ph): Ditto.
+ (_mm_reduce_mul_ph): Ditto.
+ (_mm_reduce_min_ph): Ditto.
+ (_mm_reduce_max_ph): Ditto.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (__m512h_u, __m256h_u,
+ __m128h_u): New typedef.
+ (_mm512_load_ph): New intrinsic.
+ (_mm256_load_ph): Ditto.
+ (_mm_load_ph): Ditto.
+ (_mm512_loadu_ph): Ditto.
+ (_mm256_loadu_ph): Ditto.
+ (_mm_loadu_ph): Ditto.
+ (_mm512_store_ph): Ditto.
+ (_mm256_store_ph): Ditto.
+ (_mm_store_ph): Ditto.
+ (_mm512_storeu_ph): Ditto.
+ (_mm256_storeu_ph): Ditto.
+ (_mm_storeu_ph): Ditto.
+ (_mm512_abs_ph): Ditto.
+ * config/i386/avx512fp16vlintrin.h
+ (_mm_abs_ph): Ditto.
+ (_mm256_abs_ph): Ditto.
+
+2021-09-22 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * config/s390/tpf.md (prologue_tpf, epilogue_tpf): Add cc clobber.
+
+2021-09-22 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ PR target/102222
+ * config/s390/s390.c (s390_expand_insv): Emit a normal move if it
+ is actually a full copy of the source operand into the target.
+ Don't emit a strict low part move if source and target mode match.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/102415
+ * omp-expand.c (expand_omp_single): If region->exit is NULL,
+ assert region->entry is GIMPLE_OMP_SCOPE region and return.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ * tree.h (OMP_CLAUSE_ALLOCATE_ALIGN): Define.
+ * tree.c (omp_clause_num_ops): Change number of OMP_CLAUSE_ALLOCATE
+ arguments from 2 to 3.
+ * tree-pretty-print.c (dump_omp_clause): Print allocator() around
+ allocate clause allocator and print align if present.
+ * omp-low.c (scan_sharing_clauses): Force allocate_map entry even
+ for omp_default_mem_alloc if align modifier is present. If align
+ modifier is present, use TREE_LIST to encode both allocator and
+ align.
+ (lower_private_allocate, lower_rec_input_clauses, create_task_copyfn):
+ Handle align modifier on allocator clause if present.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386.md (define_attr "isa"): Add
+ fma_or_avx512vl.
+ (define_attr "enabled"): Correspond fma_or_avx512vl to
+ TARGET_FMA || TARGET_AVX512VL.
+ * config/i386/mmx.md (fmav2sf4): Extend to AVX512 fma.
+ (fmsv2sf4): Ditto.
+ (fnmav2sf4): Ditto.
+ (fnmsv2sf4): Ditto.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386.md (cstorehf3): New define_expand.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386.md (<rounding_insn>hf2): New expander.
+ (sse4_1_round<mode>2): Extend from MODEF to MODEFH.
+ * config/i386/sse.md (*sse4_1_round<ssescalarmodesuffix>):
+ Extend from VF_128 to VFH_128.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386-features.c (i386-features.c): Handle
+ E_HFmode.
+ * config/i386/i386.md (sqrthf2): New expander.
+ (*sqrthf2): New define_insn.
+ * config/i386/sse.md
+ (*<sse>_vmsqrt<mode>2<mask_scalar_name><round_scalar_name>):
+ Extend to VFH_128.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm_mask_fcmadd_sch):
+ New intrinsic.
+ (_mm_mask3_fcmadd_sch): Likewise.
+ (_mm_maskz_fcmadd_sch): Likewise.
+ (_mm_fcmadd_sch): Likewise.
+ (_mm_mask_fmadd_sch): Likewise.
+ (_mm_mask3_fmadd_sch): Likewise.
+ (_mm_maskz_fmadd_sch): Likewise.
+ (_mm_fmadd_sch): Likewise.
+ (_mm_mask_fcmadd_round_sch): Likewise.
+ (_mm_mask3_fcmadd_round_sch): Likewise.
+ (_mm_maskz_fcmadd_round_sch): Likewise.
+ (_mm_fcmadd_round_sch): Likewise.
+ (_mm_mask_fmadd_round_sch): Likewise.
+ (_mm_mask3_fmadd_round_sch): Likewise.
+ (_mm_maskz_fmadd_round_sch): Likewise.
+ (_mm_fmadd_round_sch): Likewise.
+ (_mm_fcmul_sch): Likewise.
+ (_mm_mask_fcmul_sch): Likewise.
+ (_mm_maskz_fcmul_sch): Likewise.
+ (_mm_fmul_sch): Likewise.
+ (_mm_mask_fmul_sch): Likewise.
+ (_mm_maskz_fmul_sch): Likewise.
+ (_mm_fcmul_round_sch): Likewise.
+ (_mm_mask_fcmul_round_sch): Likewise.
+ (_mm_maskz_fcmul_round_sch): Likewise.
+ (_mm_fmul_round_sch): Likewise.
+ (_mm_mask_fmul_round_sch): Likewise.
+ (_mm_maskz_fmul_round_sch): Likewise.
+ * config/i386/i386-builtin.def: Add corresponding new builtins.
+ * config/i386/sse.md
+ (avx512fp16_fmaddcsh_v8hf_maskz<round_expand_name>): New expander.
+ (avx512fp16_fcmaddcsh_v8hf_maskz<round_expand_name>): Ditto.
+ (avx512fp16_fma_<complexopname>sh_v8hf<mask_scalarcz_name><round_scalarcz_name>):
+ New define insn.
+ (avx512fp16_<complexopname>sh_v8hf_mask<round_name>): Ditto.
+ (avx512fp16_<complexopname>sh_v8hf<mask_scalarc_name><round_scalarcz_name>):
+ Ditto.
+ * config/i386/subst.md (mask_scalarcz_name): New.
+ (mask_scalarc_name): Ditto.
+ (mask_scalarc_operand3): Ditto.
+ (mask_scalarcz_operand4): Ditto.
+ (round_scalarcz_name): Ditto.
+ (round_scalarc_mask_operand3): Ditto.
+ (round_scalarcz_mask_operand4): Ditto.
+ (round_scalarc_mask_op3): Ditto.
+ (round_scalarcz_mask_op4): Ditto.
+ (round_scalarcz_constraint): Ditto.
+ (round_scalarcz_nimm_predicate): Ditto.
+ (mask_scalarcz): Ditto.
+ (mask_scalarc): Ditto.
+ (round_scalarcz): Ditto.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm512_fcmadd_pch):
+ New intrinsic.
+ (_mm512_mask_fcmadd_pch): Likewise.
+ (_mm512_mask3_fcmadd_pch): Likewise.
+ (_mm512_maskz_fcmadd_pch): Likewise.
+ (_mm512_fmadd_pch): Likewise.
+ (_mm512_mask_fmadd_pch): Likewise.
+ (_mm512_mask3_fmadd_pch): Likewise.
+ (_mm512_maskz_fmadd_pch): Likewise.
+ (_mm512_fcmadd_round_pch): Likewise.
+ (_mm512_mask_fcmadd_round_pch): Likewise.
+ (_mm512_mask3_fcmadd_round_pch): Likewise.
+ (_mm512_maskz_fcmadd_round_pch): Likewise.
+ (_mm512_fmadd_round_pch): Likewise.
+ (_mm512_mask_fmadd_round_pch): Likewise.
+ (_mm512_mask3_fmadd_round_pch): Likewise.
+ (_mm512_maskz_fmadd_round_pch): Likewise.
+ (_mm512_fcmul_pch): Likewise.
+ (_mm512_mask_fcmul_pch): Likewise.
+ (_mm512_maskz_fcmul_pch): Likewise.
+ (_mm512_fmul_pch): Likewise.
+ (_mm512_mask_fmul_pch): Likewise.
+ (_mm512_maskz_fmul_pch): Likewise.
+ (_mm512_fcmul_round_pch): Likewise.
+ (_mm512_mask_fcmul_round_pch): Likewise.
+ (_mm512_maskz_fcmul_round_pch): Likewise.
+ (_mm512_fmul_round_pch): Likewise.
+ (_mm512_mask_fmul_round_pch): Likewise.
+ (_mm512_maskz_fmul_round_pch): Likewise.
+ * config/i386/avx512fp16vlintrin.h (_mm_fmadd_pch):
+ New intrinsic.
+ (_mm_mask_fmadd_pch): Likewise.
+ (_mm_mask3_fmadd_pch): Likewise.
+ (_mm_maskz_fmadd_pch): Likewise.
+ (_mm256_fmadd_pch): Likewise.
+ (_mm256_mask_fmadd_pch): Likewise.
+ (_mm256_mask3_fmadd_pch): Likewise.
+ (_mm256_maskz_fmadd_pch): Likewise.
+ (_mm_fcmadd_pch): Likewise.
+ (_mm_mask_fcmadd_pch): Likewise.
+ (_mm_mask3_fcmadd_pch): Likewise.
+ (_mm_maskz_fcmadd_pch): Likewise.
+ (_mm256_fcmadd_pch): Likewise.
+ (_mm256_mask_fcmadd_pch): Likewise.
+ (_mm256_mask3_fcmadd_pch): Likewise.
+ (_mm256_maskz_fcmadd_pch): Likewise.
+ (_mm_fmul_pch): Likewise.
+ (_mm_mask_fmul_pch): Likewise.
+ (_mm_maskz_fmul_pch): Likewise.
+ (_mm256_fmul_pch): Likewise.
+ (_mm256_mask_fmul_pch): Likewise.
+ (_mm256_maskz_fmul_pch): Likewise.
+ (_mm_fcmul_pch): Likewise.
+ (_mm_mask_fcmul_pch): Likewise.
+ (_mm_maskz_fcmul_pch): Likewise.
+ (_mm256_fcmul_pch): Likewise.
+ (_mm256_mask_fcmul_pch): Likewise.
+ (_mm256_maskz_fcmul_pch): Likewise.
+ * config/i386/i386-builtin-types.def (V8HF_FTYPE_V8HF_V8HF_V8HF,
+ V8HF_FTYPE_V16HF_V16HF_V16HF, V16HF_FTYPE_V16HF_V16HF_V16HF_UQI,
+ V32HF_FTYPE_V32HF_V32HF_V32HF_INT,
+ V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT): Add new builtin types.
+ * config/i386/i386-builtin.def: Add new builtins.
+ * config/i386/i386-expand.c: Handle new builtin types.
+ * config/i386/subst.md (SUBST_CV): New.
+ (maskc_name): Ditto.
+ (maskc_operand3): Ditto.
+ (maskc): Ditto.
+ (sdc_maskz_name): Ditto.
+ (sdc_mask_op4): Ditto.
+ (sdc_mask_op5): Ditto.
+ (sdc_mask_mode512bit_condition): Ditto.
+ (sdc): Ditto.
+ (round_maskc_operand3): Ditto.
+ (round_sdc_mask_operand4): Ditto.
+ (round_maskc_op3): Ditto.
+ (round_sdc_mask_op4): Ditto.
+ (round_saeonly_sdc_mask_operand5): Ditto.
+ * config/i386/sse.md (unspec): Add complex fma unspecs.
+ (avx512fmaskcmode): New.
+ (UNSPEC_COMPLEX_F_C_MA): Ditto.
+ (UNSPEC_COMPLEX_F_C_MUL): Ditto.
+ (complexopname): Ditto.
+ (<avx512>_fmaddc_<mode>_maskz<round_expand_name>): New expander.
+ (<avx512>_fcmaddc_<mode>_maskz<round_expand_name>): Ditto.
+ (fma_<complexopname>_<mode><sdc_maskz_name><round_name>): New
+ define insn.
+ (<avx512>_<complexopname>_<mode>_mask<round_name>): Ditto.
+ (<avx512>_<complexopname>_<mode><maskc_name><round_name>): Ditto.
+
+2021-09-22 Kewen Lin <linkw@linux.ibm.com>
+
+ * config/rs6000/rs6000.opt (rs6000-density-pct-threshold,
+ rs6000-density-size-threshold, rs6000-density-penalty,
+ rs6000-density-load-pct-threshold,
+ rs6000-density-load-num-threshold): New parameter.
+ * config/rs6000/rs6000.c (rs6000_density_test): Adjust with
+ corresponding parameters.
+
+2021-09-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::defined_outside_path):
+ New.
+ (path_range_query::range_on_path_entry): New.
+ (path_range_query::internal_range_of_expr): Resolve unknowns
+ with ranger.
+ (path_range_query::improve_range_with_equivs): New.
+ (path_range_query::ssa_range_in_phi): Resolve unknowns with
+ ranger.
+ * gimple-range-path.h (class path_range_query): Add
+ defined_outside_path, range_on_path_entry, and
+ improve_range_with_equivs.
+
+2021-09-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::add_to_imports): New.
+ (path_range_query::add_copies_to_imports): New.
+ (path_range_query::precompute_ranges): Call
+ add_copies_to_imports.
+ * gimple-range-path.h (class path_range_query): Add prototypes
+ for add_copies_to_imports and add_to_imports.
+
+2021-09-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::range_defined_in_block):
+ Remove useless code.
+
+2021-09-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-fold.h (class fur_source): Make oracle protected.
+ * gimple-range-path.cc (path_range_query::path_range_query): Add
+ resolve argument. Initialize oracle.
+ (path_range_query::~path_range_query): Delete oracle.
+ (path_range_query::range_of_stmt): Adapt to use relations.
+ (path_range_query::precompute_ranges): Pre-compute relations.
+ (class jt_fur_source): New
+ (jt_fur_source::jt_fur_source): New.
+ (jt_fur_source::register_relation): New.
+ (jt_fur_source::query_relation): New.
+ (path_range_query::precompute_relations): New.
+ (path_range_query::precompute_phi_relations): New.
+ * gimple-range-path.h (path_range_query): Add resolve argument.
+ Add oracle, precompute_relations, precompute_phi_relations.
+ * tree-ssa-threadbackward.c (back_threader::back_threader): Pass
+ resolve argument to solver.
+
+2021-09-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-fold.cc (fold_using_range::range_of_range_op):
+ Rename postfold_gcond_edges to register_outgoing_edges and
+ adapt.
+ (fold_using_range::postfold_gcond_edges): Rename...
+ (fur_source::register_outgoing_edges): ...to this.
+ * gimple-range-fold.h (postfold_gcond_edges): Rename to
+ register_outgoing_edges and move to fur_source.
+
+2021-09-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-fold.cc (fold_using_range::range_of_phi): Check
+ dom_info_available_p.
+
+2021-09-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-cache.cc (non_null_ref::non_null_ref): Use create
+ and quick_grow_cleared instead of safe_grow_cleared.
+
+2021-09-21 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR other/102408
+ * omp-oacc-neuter-broadcast.cc (oacc_do_neutering): Evaluate
+ 'random ()' to '0'.
+
+2021-09-21 Richard Earnshaw <rearnsha@arm.com>
+
+ * configure.ac: Detect when the assembler supports new-style
+ architecture extensions.
+ * common/config/arm/arm-common.c (arm_rewrite_mcpu): Return
+ the full CPU string if the assembler can grok it.
+ (arm_rewrite_march): Likewise but for the architecture.
+ * config.in: Regenerate.
+ * configure: Regenerate.
+
+2021-09-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102421
+ * tree-vect-loop.c (vect_dissolve_slp_only_groups): Copy and
+ adjust alignment info.
+
+2021-09-21 Kewen Lin <linkw@linux.ibm.com>
+
+ * ipa-fnsummary.c (ipa_fn_summary_write): Remove inconsistent
+ bitfield stream out.
+
2021-09-20 Andrew MacLeod <amacleod@redhat.com>
* gimple-range-fold.cc (fold_using_range::range_of_phi): Ignore
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index ed865cb..e528add 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20210921
+20211007
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 56d9baf..feadd5e 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,1734 @@
+2021-10-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (gnat_to_gnu): Do not wrap boolean values
+ referenced in pragmas.
+
+2021-10-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Subprogram_Body_to_gnu): Do not set the
+ DECL_DISREGARD_INLINE_LIMITS flag if -gnatd.8 is specified.
+
+2021-10-05 Bob Duff <duff@adacore.com>
+
+ * gcc-interface/trans.c (set_end_locus_from_node): Check that
+ Handled_Statement_Sequence is not Empty before calling
+ End_Label, because the Empty node has no End_Label, and
+ depending on the exact node layout chosen by gen_il, calling
+ End_Label might crash, or might work OK by accident.
+
+2021-10-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/cuintp.c: Adjust placement of include directive.
+ * gcc-interface/targtyps.c: Likewise.
+
+2021-10-05 Alexandre Oliva <oliva@adacore.com>
+
+ * doc/gnat_rm.rst: Add...
+ * doc/gnat_rm/security_hardening_features.rst: New.
+ * doc/gnat_rm/about_this_guide.rst: Link to new chapter.
+ * gnat_rm.texi: Regenerate.
+ * gcc-interface/utils.c (handle_strub_attribute): New.
+ (gnat_internal_attribute_table): Add strub.
+ * libgnat/a-except.adb: Make Rcheck_CE_* strub-callable.
+ * libgnat/a-except.ads (Raise_Exception): Likewise.
+ (Raise_Exception_Always): Likewise.
+ * libgnat/s-arit128.ads (Multiply_With_Ovflo_Check128):
+ Likewise.
+ * libgnat/s-arit64.ads (Multiply_With_Ovflo_Check64):
+ Likewise.
+ * libgnat/s-secsta.ads (SS_Allocate, SS_Mark, SS_Release):
+ Likewise.
+
+2021-10-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_ch9.adb (Install_Private_Data_Declarations): Copy the Sloc of
+ components for the local renamings as well as the Comes_From_Source
+ flag, and also set Warnings_Off on them. Use Nam local variable.
+
+2021-10-05 Arnaud Charlet <charlet@adacore.com>
+
+ * libgnarl/a-tasini.ads (Set_Initialization_Handler): Update
+ comments.
+
+2021-10-05 Corentin Gay <gay@adacore.com>
+
+ * init.c (QNX): Add #include errno.h.
+
+2021-10-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_attr.adb (Expand_Fpt_Attribute): Likewise.
+ * snames.ads-tmpl (Name_Unaligned_Valid): Delete.
+
+2021-10-05 Etienne Servais <servais@adacore.com>
+
+ * sem_prag.adb (Analyze_Pragma): Forbid use of
+ Compile_Time_(Error|Warning) as configuration pragma.
+ * doc/gnat_ugn/the_gnat_compilation_model.rst:
+ Compile_Time_(Error|Warning) and Compiler_Unit(_Warning) are not
+ configuration pragmas and shall not be listed as such. The
+ following pragmas are either obsolete or undocumented:
+ No_Run_Time, Propagate_Exceptions, Rational, Ravenscar,
+ Restricted_Run_Time, Short_Descriptors, Universal_Data. Fix
+ some typos (notably on Restriction_Warnings).
+ * doc/gnat_rm/implementation_defined_pragmas.rst: Move
+ Rename_Pragma documentation to alphabetical order.
+ * gnat_rm.texi, gnat_ugn.texi: Regenerate.
+
+2021-10-05 Corentin Gay <gay@adacore.com>
+
+ * adaint.c (QNX): Add #include for sys/time.h.
+
+2021-10-05 Pascal Obry <obry@adacore.com>
+
+ * libgnat/g-forstr.adb (Next_Format): When there is no more
+ format specifier found issue a proper error message instead of
+ raising a contraint error.
+
+2021-10-05 Pascal Obry <obry@adacore.com>
+
+ * libgnat/g-forstr.adb (Get_Formatted): Fix computation of the
+ number of zero to use in the formatted string. This was a wrong
+ copy/paste.
+
+2021-10-05 Pascal Obry <obry@adacore.com>
+
+ * libgnat/g-forstr.adb (Get_Formatted): Minor code clean-up.
+
+2021-10-05 Etienne Servais <servais@adacore.com>
+
+ * libgnat/a-zchhan.ads, libgnat/a-zchhan.adb
+ (Character_Set_Version, Is_Basic, To_Basic): New.
+ * libgnat/a-zchuni.ads, libgnat/a-zchuni.adb (Is_Basic,
+ To_Basic): New.
+
+2021-10-05 Yannick Moy <moy@adacore.com>
+
+ * sem_aggr.adb (Resolve_Array_Aggregate): Improve error message.
+
+2021-10-05 Gary Dismukes <dismukes@adacore.com>
+
+ * aspects.ads (type Aspect_Id): Add
+ Aspect_Designated_Storage_Model and Aspect_Storage_Model_Type.
+ (Aspect_Argument): Add associations for the above new aspects.
+ (Is_Representation_Aspect): Likewise.
+ (Aspect_Names, Aspect_Delay): Likewise.
+ * exp_ch4.adb (Expand_N_Allocator): Call Find_Storage_Op rather
+ than Find_Prim_Op.
+ * exp_intr.adb (Expand_Unc_Deallocation): Likewise.
+ * exp_util.ads (Find_Storage_Op): New function that locates
+ either a primitive operation of a storage pool or an operation
+ of a storage-model type specified in its Storage_Model_Type
+ aspect.
+ * exp_util.adb (Find_Storage_Op): New function that calls either
+ Find_Prim_Op or Get_Storage_Model_Type_Entity to locate a
+ storage-related operation that is associated with a type.
+ * sem_ch13.adb (Analyze_Aspects_At_Freeze_Point): Analyzes,
+ resolves, and validates the arguments of aspect
+ Designated_Storage_Model_Type.
+ (Analyze_Aspect_Specifications): Sets delay-related flags on
+ storage-model aspects when Delay_Required. Checks that aspect
+ Designated_Storage_Model is only specified for an access type
+ and that aspect Storage_Model_Type is only specified on an
+ immutably limited type. Also records such aspects for their
+ associated types.
+ (Check_Aspect_At_Freeze_Point): Resolve each of the argument
+ associations given for a Storage_Model_Type aspect.
+ (Resolve_Storage_Model_Type_Argument): New procedure that
+ resolves an argument given in the association for a given entity
+ name associated with a type with aspect Storage_Model_Type,
+ ensuring that it has the proper kind or profile.
+ (Validate_Storage_Model_Type_Aspect): New procedure that checks
+ the legality and completeness of the entity associations given
+ in a Storage_Model_Type aspect.
+ * sem_util.ads (package Storage_Model_Support): New nested
+ package that encapsulates a set of convenient utility functions
+ for retrieving entities, etc. associated with
+ storage-model-related types and objects.
+ (Get_Storage_Model_Type_Entity): New function to return a
+ specified entity associated with a type that has aspect
+ Storage_Model_Type.
+ (Has_Designated_Storage_Model_Aspect): New function that returns
+ whether a type has aspect Designated_Storage_Model.
+ (Has_Storage_Model_Type_Aspect): New function that returns
+ whether a type has aspect Storage_Model_Type.
+ (Storage_Model_Object): New function that returns the object
+ Entity_Id associated with a type's Designated_Storage_Model
+ aspect.
+ (Storage_Model_Type): New function that returns the type
+ associated with a storage-model object (when the object's type
+ specifies Storage_Model_Type).
+ (Storage_Model_Address_Type): New function that returns the
+ Address_Type associated with a type that has aspect
+ Storage_Model_Type.
+ (Storage_Model_Null_Address): New function that returns the
+ Null_Address constant associated with a type that has aspect
+ Storage_Model_Type.
+ (Storage_Model_Allocate): New function that returns the Allocate
+ procedure associated with a type that has aspect
+ Storage_Model_Type.
+ (Storage_Model_Deallocate): New function that returns the
+ Deallocate procedure associated with a type that has aspect
+ Storage_Model_Type.
+ (Storage_Model_Copy_From): New function that returns the
+ Copy_From procedure associated with a type that has aspect
+ Storage_Model_Type.
+ (Storage_Model_Copy_To): New function that returns the Copy_To
+ procedure associated with a type that has aspect
+ Storage_Model_Type.
+ (Storage_Model_Storage_Size): New function that returns the
+ Storage_Size function associated with a type that has aspect
+ Storage_Model_Type.
+ * sem_util.adb (package Storage_Model_Support): Body of new
+ nested package that contains the implementations the utility
+ functions declared in the spec of this package.
+ * snames.ads-tmpl: Add new names Name_Designated_Storage_Pool,
+ Name_Storage_Model, Name_Storage_Model_Type, Name_Address_Type,
+ Name_Copy_From, Name_Copy_To, and Name_Null_Address for the new
+ aspects and associated aspect arguments.
+
+2021-10-05 Richard Kenner <kenner@adacore.com>
+
+ * debug.adb: Add documentation for -gnatd_t.
+
+2021-10-05 Corentin Gay <gay@adacore.com>
+
+ * sysdep.c (__gnat_is_file_not_found_error): Add else if case.
+
+2021-10-05 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_util.adb (Build_Class_Wide_Expression): Replace entities
+ of both identifiers and operator symbols.
+
+2021-10-05 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch3.adb (Derive_Subprogram): Copy ghost status from parent
+ to derived subprogram.
+
+2021-10-05 Joffrey Huguet <huguet@adacore.com>
+
+ * libgnat/a-strunb.ads, libgnat/a-strunb__shared.ads: Add
+ Default_Initial_Condition to Unbounded_String.
+
+2021-10-05 Claire Dross <dross@adacore.com>
+
+ * libgnat/a-cfdlli.ads: Use pragma Assertion_Policy to disable
+ contract cases at execution.
+ * libgnat/a-cfinve.ads: Idem.
+ * libgnat/a-cofove.ads: Idem.
+ * libgnat/a-cfhase.ads: Idem.
+ * libgnat/a-cfhama.ads: Idem.
+ * libgnat/a-cforse.ads: Idem.
+ * libgnat/a-cforma.ads: Idem.
+
+2021-10-05 Bob Duff <duff@adacore.com>
+
+ * par-ch4.adb (P_Iterated_Component_Association): Parse these
+ features the same way in all language versions. Move the call
+ to Error_Msg_Ada_2022_Feature into semantic analysis.
+ * sem_aggr.adb (Resolve_Iterated_Component_Association,
+ Resolve_Iterated_Association): Move the call to
+ Error_Msg_Ada_2022_Feature here from par-ch4.adb.
+
+2021-10-05 Yannick Moy <moy@adacore.com>
+
+ * sem_res.adb (Resolve): Recognize specially that case.
+
+2021-10-05 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-strmap.adb: Add ghost code for proof.
+ (To_Range): This is the most involved proof, as it requires
+ creating the result of the call to To_Domain as a ghost
+ variable, and show the unicity of this result in order to prove
+ the postcondition.
+ * libgnat/a-strmap.ads: (SPARK_Proof_Sorted_Character_Sequence):
+ New ghost function.
+ (To_Domain): Add postcondition regarding sorting of result.
+ (To_Range): Fix postcondition that should compare Length instead
+ of Last for the results of To_Domain and To_Range, as the value
+ of Last for an empty result is not specified in the Ada RM.
+
+2021-10-05 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-chahan.adb: Add loop invariants as needed to prove
+ subprograms. Also use extended return statements where
+ appropriate and not done already. Mark data with
+ Relaxed_Initialization where needed for initialization by parts.
+ Convert regular functions to expression functions where needed
+ for proof.
+ * libgnat/a-chahan.ads: Add postconditions.
+ * libgnat/a-strmap.ads (Model): New ghost function to create a
+ publicly visible model of the private data Character_Mapping,
+ needed in order to prove subprograms in Ada.Characters.Handling.
+
+2021-10-04 Justin Squirek <squirek@adacore.com>
+
+ * doc/gnat_rm/standard_and_implementation_defined_restrictions.rst:
+ Add new entry for No_Dynamic_Accessibility_Checks documenting
+ behavior.
+ * gnat_rm.texi: Regenerate.
+ * exp_ch4.adb (Expand_N_In): Perform special expansion for
+ membership tests when No_Dynamic_Accessibility_Checks is active.
+ * sem_attr.adb (Resolve_Attribute): Skip static accessibility
+ check on actuals for anonymous access type formal parameters,
+ and add constants for readability.
+ * sem_util.adb (Function_Call_Or_Allocator_Level): Use the
+ innermost master for determining the level for function calls
+ within the alternative accessibility model.
+ (Type_Access_Level): Properly get the level for anonymous access
+ function result types.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * doc/gnat_ugn/building_executable_programs_with_gnat.rst
+ (gnateA): This switch no longer looks at the formal parameter
+ type being composite (as originally mandated by SPARK), but in
+ the parameter passing mechanism being not specified (as
+ currently mandated by Ada).
+ * gnat_ugn.texi: Regenerate.
+
+2021-10-04 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch6.adb (Analyze_Operator_Symbol): Recognize strings as
+ operator names when they are the value of one of the Ada2022
+ aspects for User_Defined_Literals.
+ * sem_ch13.adb (Analyze_One_Aspect): Handle an aspect value
+ given by an Operator_Name.
+ (Validate_Literal_Aspect): Call Analyze_Operator_Symbol when
+ needed.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * gen_il-gen.adb (Put_Make_Spec): Don't emit the LF character in
+ the middle of a string, because the Put routine won't indent it
+ properly.
+
+2021-10-04 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * gnat_cuda.adb (Remove_CUDA_Device_Entities): New function.
+ (Expand_CUDA_Package): Call Remove_CUDA_Device_Entities.
+ * gnat_cuda.ads (Expand_CUDA_Package): Expand documentation.
+ * sem_prag.adb (Analyze_Pragma): Remove warning about
+ CUDA_Device not being implemented.
+
+2021-10-04 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_ch7.adb (Analyze_Package_Specification): For types marked
+ as Must_Have_Preelab_Init, we now check for the presence of a
+ Preelaborable_Initialization aspect on the type, and pass the
+ aspect's expression (if any) on the call to
+ Has_Preelaborable_Initialization (or pass Empty if the type has
+ no such aspect or the aspect has no associated expression).
+ * sem_util.ads (Has_Preelaborable_Initialization): Change
+ Boolean formal parameter Formal_Types_Have_Preelab_Init to
+ instead be a formal of type Node_Id (named Preelab_Init_Expr),
+ to allow passing an expression that may be a conjunction of
+ Preelaborable_Initialization aspects. Revise spec comment
+ accordingly (and remove ??? comment).
+ * sem_util.adb (Type_Named_In_Preelab_Init_Expression): New
+ nested function with a result indicating whether a given type is
+ named as the prefix of a Preelaborable_Initialization attribute
+ in the expression of a corresponding P_I aspect.
+ (Has_Preelaborable_Initialization): For generic formal derived
+ and private types, test whether the type is named in the
+ expression Preelab_Init_Expr (by calling
+ Type_Named_In_Preelab_Init_Expression), and if so, treat the
+ formal type as having preelaborable initialization (returning
+ True).
+ * libgnat/a-cobove.ads (Vector): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as Element_Type'Preelaborable_Initialization.
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+ * libgnat/a-cbdlli.ads (List): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as Element_Type'Preelaborable_Initialization.
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+ * libgnat/a-cbhama.ads (Map): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as (Element_Type'Preelaborable_Initialization and
+ Key_Type'Preelaborable_Initialization).
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+ * libgnat/a-cborma.ads (Map): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as (Element_Type'Preelaborable_Initialization and
+ Key_Type'Preelaborable_Initialization).
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+ * libgnat/a-cbhase.ads (Set): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as Element_Type'Preelaborable_Initialization.
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+ * libgnat/a-cborse.ads (Set): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as Element_Type'Preelaborable_Initialization.
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+ * libgnat/a-cbmutr.ads (Tree): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as Element_Type'Preelaborable_Initialization.
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+ * libgnat/a-coboho.ads (Holder): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as Element_Type'Preelaborable_Initialization.
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+
+2021-10-04 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-textio.adb: Mark body out of SPARK.
+ * libgnat/a-textio.ads: Mark spec in SPARK and private part out
+ of SPARK.
+ * sem.adb (Semantics.Do_Analyze): Similar to ghost code
+ attributes, save and restore value of
+ Ignore_SPARK_Mode_Pragmas_In_Instance.
+
+2021-10-04 Bob Duff <duff@adacore.com>
+
+ * libgnat/s-regpat.ads: Change Data_First to Data'First. Change
+ "still" to "always". Similar changes for Data_Last.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * sprint.adb (Sprint_Node_Actual): Refactor code for generic
+ package and subprogram declarations.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_res.adb (Resolve_Indexed_Component, Resolve_Slice): Rename
+ the local constant Name to Pref; remove repeated calls to
+ Prefix.
+
+2021-10-04 Matthieu Eyraud <eyraud@adacore.com>
+
+ * scos.ads: Extend the documentation.
+ * par_sco.adb (Process_Decisions): Emit specific SCOs for
+ quantified expressions.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * checks.adb (Selected_Range_Checks): Fix style.
+ * exp_ch4.adb (Expand_N_Slice): Fix style and comment.
+ * sem_res.adb (Resolve_Indexed_Component): Fix style.
+
+2021-10-04 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-strbou.ads: Add comments.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Eval_Attribute): Evaluation of attribute
+ Leading_Part with illegal second parameter is now similar to
+ evaluation of Remainder with its second parameter being zero.
+
+2021-10-04 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_res.adb (Resolve_Declare_Expression): Use tree traversals
+ to perform name capture of local entities in the expression of
+ the construct.
+ * exp_util.adb (Possible_Side_Effects_In_SPARK): Do not apply to
+ the prefix of an attribute reference Reduce when that prefix is
+ an aggregate, because it will be expanded into a loop, and has
+ no identifiable type.
+
+2021-10-04 Javier Miranda <miranda@adacore.com>
+
+ * sem_ch8.adb (Build_Class_Wide_Wrapper): Fix handling of
+ class-wide subtypes; required to handle chains of
+ instantiations. Adding also code to identify these wrappers and
+ properly resolve instantiations where the wrapper and a tagged
+ type primitive are visible.
+ * einfo.ads (Is_Class_Wide_Wrapper): Adding documentation.
+ * gen_il-fields.ads (Opt_Field_Enum): Adding
+ Is_Class_Wide_Wrapper.
+ * gen_il-gen-gen_entities.adb (Root_Entity_Type): Adding
+ semantic flag Is_Class_Wide_Wrapper.
+
+2021-10-04 Bob Duff <duff@adacore.com>
+
+ * einfo.ads (Declaration_Node): Document that Declaration_Node
+ for Itypes.
+ * einfo-utils.adb (Declaration_Node): Make it return Empty for
+ Itypes, or a proper type or subtype declaration.
+ * gen_il-gen.adb: Minor comment improvement.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_res.adb (Resolve_Slice): Fix application of range checks
+ to slice range given as a subtype name.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_res.adb (Resolve_Slice): Handle range given as a subtype
+ indication.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_res.adb (Resolve_Slice): Add custom handling of attribute
+ Image and similar in CodePeer mode. This complements the
+ existing custom handling of these attributes in
+ Expand_N_Attribute_Reference.
+
+2021-10-04 Justin Squirek <squirek@adacore.com>
+
+ * sem_util.adb (Is_Variable): Add check for implicitly
+ dereferenced access types
+ (Is_Dependent_Component_Of_Mutable_Object): Set Prefix_Type when
+ not specified.
+
+2021-10-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_ugn/the_gnat_compilation_model.rst (Binding generation):
+ Document specific behavior for /include/-ending paths and update.
+ * gnat_ugn.texi: Regenerate.
+
+2021-10-04 Arnaud Charlet <charlet@adacore.com>
+
+ PR ada/102073
+ * socket.c (__gnat_gethostbyaddr, __gnat_inet_pton): Add missing
+ return statements.
+
+2021-10-04 Justin Squirek <squirek@adacore.com>
+
+ * sem_util.adb (Function_Or_Allocator_Level): Properly handle
+ direct function calls in the default alternative accessibility
+ checking mode.
+
+2021-10-04 Javier Miranda <miranda@adacore.com>
+
+ * sem_util.adb (Is_Library_Level_Entity): Return False for
+ entities defined in E_Loop scopes. This change is not required
+ by the frontend; it is required by tools that depend on the
+ frontend sources.
+ * einfo-utils.adb (Is_Dynamic_Scope): Code cleanup.
+
+2021-10-04 Justin Squirek <squirek@adacore.com>
+
+ * sem_util.adb (Accessibility_Level): Add a case to handle
+ renamed subprograms in addition to renamed objects.
+
+2021-10-04 Doug Rupp <rupp@adacore.com>
+
+ * libgnarl/s-osinte__vxworks.ads (tlsKeyCreate): Return int.
+ * libgnarl/s-tpopsp__vxworks-rtp.adb (ERROR): Declare from
+ System.VxWorks.Ext.ERROR.
+ (Initialize): Declare IERR. Assert it.
+ * libgnarl/s-tpopsp__vxworks.adb (ERROR): Declare from
+ System.VxWorks.Ext.ERROR.
+ (Is_Valid_Task): Declare IERR. Test return.
+ * libgnarl/s-vxwext__kernel.adb (semDelete): Return STATUS.
+
+2021-10-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_disp.adb (Make_DT): Copy the Needs_Debug_Info flag from the
+ type onto the TSD object.
+
+2021-10-04 Steve Baird <baird@adacore.com>
+
+ * sem_util.adb (Is_Repeatedly_Evaluated): Handle the case of an
+ Old attribute reference that occurs within what was originally a
+ quantified expression but which expansion has transformed into
+ an Expression_With_Actions.
+
+2021-10-04 Steve Baird <baird@adacore.com>
+
+ * exp_ch4.adb (Expand_N_Indexed_Component): The two improvements
+ described above.
+
+2021-10-01 Bob Duff <duff@adacore.com>
+
+ * exp_ch6.adb (Expand_Call_Helper): Do not call
+ Check_Subprogram_Variant if the subprogram is an ignored ghost
+ entity. Otherwise the compiler crashes (in debug builds) or
+ gives strange error messages (in production builds).
+
+2021-10-01 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * gnat_cuda.adb (Empty_CUDA_Global_Subprograms): New procedure.
+ (Expand_CUDA_Package): Call Empty_CUDA_Global_Subprograms.
+
+2021-10-01 Steve Baird <baird@adacore.com>
+
+ * checks.ads: Define a type Dimension_Set. Add an out-mode
+ parameter of this new type to Generate_Index_Checks so that
+ callers can know for which dimensions a check was generated. Add
+ an in-mode parameter of this new type to
+ Apply_Subscript_Validity_Checks so that callers can indicate
+ that no check is needed for certain dimensions.
+ * checks.adb (Generate_Index_Checks): Implement new
+ Checks_Generated parameter.
+ (Apply_Subscript_Validity_Checks): Implement new No_Check_Needed
+ parameter.
+ * exp_ch4.adb (Expand_N_Indexed_Component): Call
+ Apply_Subscript_Validity_Checks in more cases than before. This
+ includes declaring two new local functions,
+ (Is_Renamed_Variable_Name,
+ Type_Requires_Subscript_Validity_Checks_For_Reads): To help in
+ deciding whether to call Apply_Subscript_Validity_Checks.
+ Adjust to parameter profile changes in Generate_Index_Checks and
+ Apply_Subscript_Validity_Checks.
+
+2021-10-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_characteristics.rst: Document
+ the rounding mode assumed for dynamic computations as per 3.5.7(16).
+ * gnat_rm.texi: Regenerate.
+
+2021-10-01 Bob Duff <duff@adacore.com>
+
+ * table.ads (Table_Type): Remove "aliased"; no longer needed by
+ Atree. Besides it contradicted the comment a few lines above,
+ "-- Note: We do not make the table components aliased...".
+ * types.ads: Move type Slot to Atree.
+ * atree.ads: Move type Slot fromt Types to here. Move type
+ Node_Header from Seinfo to here.
+ * atree.adb: Avoid the need for aliased components of the Slots
+ table. Instead of 'Access, use a getter and setter. Misc
+ cleanups.
+ (Print_Statistics): Print statistics about node and entity kind
+ frequencies. Give 3 digit fractions instead of percentages.
+ * (Get_Original_Node_Count, Set_Original_Node_Count): Statistics
+ for calls to Original_Node and Set_Original_Node.
+ (Original_Node, Set_Original_Node): Gather statistics by calling
+ the above.
+ (Print_Field_Statistics): Print Original_Node statistics.
+ (Update_Kind_Statistics): Remove, and put all statistics
+ gathering under "if Atree_Statistics_Enabled", which is a flag
+ generated in Seinfo by Gen_IL.
+ * gen_il-gen.adb (Compute_Field_Offsets): Choose offsets of
+ Nkind, Ekind, and Homonym first. This causes a slight efficiency
+ improvement. Misc cleanups. Do not generate Node_Header; it is
+ now hand-written in Atree. When choosing the order in which to
+ assign offsets, weight by the frequency of the node type, so the
+ more common nodes get their field offsets assigned earlier. Add
+ more special cases.
+ (Compute_Type_Sizes): Remove this and related things.
+ There was a comment: "At some point we can instrument Atree to
+ print out accurate size statistics, and remove this code." We
+ have Atree statistics, so we now remove this code.
+ (Put_Seinfo): Generate Atree_Statistics_Enabled, which is equal
+ to Statistics_Enabled. This allows Atree to say "if
+ Atree_Statistics_Enabled then <gather statistics>" for
+ efficiency. When Atree_Statistics_Enabled is False, the "if ..."
+ will be optimized away.
+ * gen_il-internals.ads (Type_Frequency): New table of kind
+ frequencies.
+ * gen_il-internals.adb: Minor comment improvement.
+ * gen_il-fields.ads: Remove unused subtypes. Suppress style
+ checks in the Type_Frequency table. If we regenerate this
+ table (see -gnatd.A) we don't want to have to fiddle with
+ casing.
+ * impunit.adb: Minor.
+ * sinfo-utils.adb: Minor.
+ * debug.adb: Minor comment improvement.
+
+2021-10-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * sem_type.adb (Specific_Type): Check that the type is tagged
+ before calling Interface_Present_In_Ancestor on it.
+
+2021-10-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * debug.adb (d.8): Document usage.
+ * fe.h (Debug_Flag_Dot_8): Declare.
+
+2021-10-01 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_util.adb (Enter_Name): Suppress hiding warning when in an
+ instance.
+
+2021-10-01 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute, case Type_Key): Attribute can
+ be applied to a formal type.
+ * sem_ch5.adb (Analyze_Case_Statement): If Extensions_Allowed is
+ not enabled, verify that the type of the expression is discrete.
+
+2021-10-01 Justin Squirek <squirek@adacore.com>
+
+ * exp_dbug.adb (Debug_Renaming_Declaration): Add check for
+ Entity present for Ren to prevent looking at unanalyzed nodes
+
+2021-10-01 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * atree.adb (Print_Statistics): Help CodePeer see Total as
+ greater than zero.
+ * gen_il-gen.adb (One_Comp): Annotate Field_Table as Modified.
+
+2021-10-01 Richard Kenner <kenner@adacore.com>
+
+ * gen_il-gen-gen_entities.adb (Evaluable_Kind,
+ Global_Name_Kind): Add.
+ * gen_il-types.ads (Evaluable_Kind, Global_Name_Kind): Likewise.
+
+2021-10-01 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * aspects.ads: Add CUDA_Device aspect.
+ * gnat_cuda.ads (Add_CUDA_Device_Entity): New subprogram.
+ * gnat_cuda.adb:
+ (Add_CUDA_Device_Entity): New subprogram.
+ (CUDA_Device_Entities_Table): New hashmap for CUDA_Device
+ entities.
+ (Get_CUDA_Device_Entities): New internal subprogram.
+ (Set_CUDA_Device_Entities): New internal subprogram.
+ * par-prag.adb (Prag): Handle pragma id Pragma_CUDA_Device.
+ * sem_prag.ads (Aspect_Specifying_Pragma): Mark CUDA_Device as
+ being both aspect and pragma.
+ * sem_prag.adb (Analyze_Pragma): Add CUDA_Device entities to
+ list of CUDA_Entities belonging to package N.
+ (Sig_Flags): Signal CUDA_Device entities as referenced.
+ * snames.ads-tmpl: Create CUDA_Device names and pragmas.
+
+2021-10-01 Gary Dismukes <dismukes@adacore.com>
+
+ * exp_util.adb (Build_DIC_Procedure_Body): Remove inappropriate
+ Assert pragma. Remove unneeded and dead code related to derived
+ private types.
+
+2021-10-01 Richard Kenner <kenner@adacore.com>
+
+ * gen_il-gen-gen_nodes.adb (N_Alternative, N_Is_Case_Choice):
+ Add.
+ (N_Is_Exception_Choice, N_Is_Range): Likewise.
+ * gen_il-types.ads: Add above names.
+ * gen_il-gen.adb (Put_Union_Membership): Write both declarations
+ and definitions of union functions.
+
+2021-10-01 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_aggr.adb (Expand_Array_Aggregate,
+ Two_Pass_Aggregate_Expansion): Increment index for element
+ insertion within the loop, only if upper bound has not been
+ reached.
+
+2021-10-01 Javier Miranda <miranda@adacore.com>
+
+ * contracts.ads (Make_Class_Precondition_Subps): New subprogram.
+ (Merge_Class_Conditions): New subprogram.
+ (Process_Class_Conditions_At_Freeze_Point): New subprogram.
+ * contracts.adb (Check_Class_Condition): New subprogram.
+ (Set_Class_Condition): New subprogram.
+ (Analyze_Contracts): Remove code analyzing class-wide-clone
+ subprogram since it is no longer built.
+ (Process_Spec_Postconditions): Avoid processing twice seen
+ subprograms.
+ (Process_Preconditions): Simplify its functionality to
+ non-class-wide preconditions.
+ (Process_Preconditions_For): No action needed for wrappers and
+ helpers.
+ (Make_Class_Precondition_Subps): New subprogram.
+ (Process_Class_Conditions_At_Freeze_Point): New subprogram.
+ (Merge_Class_Conditions): New subprogram.
+ * exp_ch6.ads (Install_Class_Preconditions_Check): New
+ subprogram.
+ * exp_ch6.adb (Expand_Call_Helper): Install class-wide
+ preconditions check on dispatching primitives that have or
+ inherit class-wide preconditions.
+ (Freeze_Subprogram): Remove code for null procedures with
+ preconditions.
+ (Install_Class_Preconditions_Check): New subprogram.
+ * exp_util.ads (Build_Class_Wide_Expression): Lower the
+ complexity of this subprogram; out-mode formal Needs_Wrapper
+ since this functionality is now provided by a new subprogram.
+ (Get_Mapped_Entity): New subprogram.
+ (Map_Formals): New subprogram.
+ * exp_util.adb (Build_Class_Wide_Expression): Lower the
+ complexity of this subprogram. Its previous functionality is now
+ provided by subprograms Needs_Wrapper and Check_Class_Condition.
+ (Add_Parent_DICs): Map the overridden primitive to the
+ overriding one.
+ (Get_Mapped_Entity): New subprogram.
+ (Map_Formals): New subprogram.
+ (Update_Primitives_Mapping): Adding assertion.
+ * freeze.ads (Check_Inherited_Conditions): Subprogram made
+ public with added formal to support late overriding.
+ * freeze.adb (Check_Inherited_Conditions): New implementation;
+ builds the dispatch table wrapper required for class-wide
+ pre/postconditions; added support for late overriding.
+ (Needs_Wrapper): New subprogram.
+ * sem.ads (Inside_Class_Condition_Preanalysis): New global
+ variable.
+ * sem_disp.ads (Covered_Interface_Primitives): New subprogram.
+ * sem_disp.adb (Covered_Interface_Primitives): New subprogram.
+ (Check_Dispatching_Context): Skip checking context of
+ dispatching calls during preanalysis of class-wide conditions
+ since at that stage the expression is not installed yet on its
+ definite context.
+ (Check_Dispatching_Call): Skip checking 6.1.1(18.2/5) by
+ AI12-0412 on helpers and wrappers internally built for
+ supporting class-wide conditions; for late-overriding
+ subprograms call Check_Inherited_Conditions to build the
+ dispatch-table wrapper (if required).
+ (Propagate_Tag): Adding call to
+ Install_Class_Preconditions_Check.
+ * sem_util.ads (Build_Class_Wide_Clone_Body): Removed.
+ (Build_Class_Wide_Clone_Call): Removed.
+ (Build_Class_Wide_Clone_Decl): Removed.
+ (Class_Condition): New subprogram.
+ (Nearest_Class_Condition_Subprogram): New subprogram.
+ * sem_util.adb (Build_Class_Wide_Clone_Body): Removed.
+ (Build_Class_Wide_Clone_Call): Removed.
+ (Build_Class_Wide_Clone_Decl): Removed.
+ (Class_Condition): New subprogram.
+ (Nearest_Class_Condition_Subprogram): New subprogram.
+ (Eligible_For_Conditional_Evaluation): No need to evaluate
+ class-wide conditions during preanalysis since the expression is
+ not installed on its definite context.
+ * einfo.ads (Class_Wide_Clone): Removed.
+ (Class_Postconditions): New attribute.
+ (Class_Preconditions): New attribute.
+ (Class_Preconditions_Subprogram): New attribute.
+ (Dynamic_Call_Helper): New attribute.
+ (Ignored_Class_Postconditions): New attribute.
+ (Ignored_Class_Preconditions): New attribute.
+ (Indirect_Call_Wrapper): New attribute.
+ (Is_Dispatch_Table_Wrapper): New attribute.
+ (Static_Call_Helper): New attribute.
+ * exp_attr.adb (Expand_N_Attribute_Reference): When the prefix
+ is of an access-to-subprogram type that has class-wide
+ preconditions and an indirect-call wrapper of such subprogram is
+ available, replace the prefix by the wrapper.
+ * exp_ch3.adb (Build_Class_Condition_Subprograms): New
+ subprogram.
+ (Register_Dispatch_Table_Wrappers): New subprogram.
+ * exp_disp.adb (Build_Class_Wide_Check): Removed; class-wide
+ precondition checks now rely on internally built helpers.
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Set initial
+ value of attributes Class_Preconditions, Class_Postconditions,
+ Ignored_Class_Preconditions and Ignored_Class_Postconditions.
+ These values are later updated with the full pre/postcondition
+ by Merge_Class_Conditions.
+ (Freeze_Entity_Checks): Call
+ Process_Class_Conditions_At_Freeze_Point.
+ * sem_ch6.adb (Analyze_Subprogram_Body_Helper): Remove code
+ building the body of the class-wide clone subprogram since it is
+ no longer required.
+ (Install_Entity): Adding assertion.
+ * sem_prag.adb (Analyze_Pre_Post_Condition_In_Decl_Part): Remove
+ code building and analyzing the class-wide clone subprogram; no
+ longer required.
+ (Build_Pragma_Check_Equivalent): Adjust call to
+ Build_Class_Wide_Expression since the formal named Needs_Wrapper
+ has been removed.
+ * sem_attr.adb (Analyze_Attribute_Old_Result): Skip processing
+ these attributes during preanalysis of class-wide conditions
+ since at that stage the expression is not installed yet on its
+ definite context.
+ * sem_res.adb (Resolve_Actuals): Skip applying RM 3.9.2(9/1) and
+ SPARK RM 6.1.7(3) on actuals of internal helpers and wrappers
+ built to support class-wide preconditions.
+ * sem_ch5.adb (Process_Bounds): Do not generate a constant
+ declaration for the bounds when we are preanalyzing a class-wide
+ condition.
+ (Analyze_Loop_Parameter_Specification): Handle preanalysis of
+ quantified expression placed in the outermost expression of a
+ class-wide condition.
+ * ghost.adb (Check_Ghost_Context): No check required during
+ preanalysis of class-wide conditions.
+ * gen_il-fields.ads (Opt_Field_Enum): Adding
+ Class_Postconditions, Class_Preconditions,
+ Class_Preconditions_Subprogram, Dynamic_Call_Helper,
+ Ignored_Class_Postconditions, Ignored_Class_Preconditions,
+ Indirect_Call_Wrapper, Is_Dispatch_Table_Wrapper,
+ Static_Call_Helper.
+ * gen_il-gen-gen_entities.adb (Is_Dispatch_Table_Wrapper):
+ Adding semantic flag Is_Dispatch_Table_Wrapper; removing
+ semantic field Class_Wide_Clone; adding semantic fields for
+ Class_Postconditions, Class_Preconditions,
+ Class_Preconditions_Subprogram, Dynamic_Call_Helper,
+ Ignored_Class_Postconditions, Indirect_Call_Wrapper,
+ Ignored_Class_Preconditions, and Static_Call_Helper.
+
+2021-10-01 Piotr Trojanek <trojanek@adacore.com>
+
+ * comperr.adb (Delete_SCIL_Files): Handle generic subprogram
+ declarations and renaming just like generic package declarations
+ and renamings, respectively; handle
+ N_Subprogram_Renaming_Declaration.
+
+2021-10-01 Steve Baird <baird@adacore.com>
+
+ * bcheck.adb (Check_Versions): Add support for the case where
+ the .ali file contains both a primary and a secondary version
+ number, as in "GNAT Lib v22.20210809".
+
+2021-10-01 Steve Baird <baird@adacore.com>
+
+ * sem_res.adb (Resolve): Two separate fixes. In the case where
+ Find_Aspect for a literal aspect returns the aspect for a
+ different (ancestor) type, call Corresponding_Primitive_Op to
+ get the right callee. In the case where a downward tagged type
+ conversion appears to be needed, generate a null extension
+ aggregate instead, as per Ada RM 3.4(27).
+ * sem_util.ads, sem_util.adb: Add new Corresponding_Primitive_Op
+ function. It maps a primitive op of a tagged type and a
+ descendant type of that tagged type to the corresponding
+ primitive op of the descendant type. The body of this function
+ was written by Javier Miranda.
+
+2021-10-01 Bob Duff <duff@adacore.com>
+
+ * atree.adb: Gather and print statistics about frequency of
+ getter and setter calls.
+ * atree.ads (Print_Statistics): New procedure for printing
+ statistics.
+ * debug.adb: Document -gnatd.A switch.
+ * gen_il-gen.adb: Generate code for statistics gathering.
+ Choose the offset of Homonym early. Misc cleanup. Put more
+ comments in the generated code.
+ * gen_il-internals.ads (Unknown_Offset): New value to indicate
+ that the offset has not yet been chosen.
+ * gnat1drv.adb: Call Print_Statistics.
+ * libgnat/s-imglli.ads: Minor comment fix.
+ * output.ads (Write_Int_64): New procedure to write a 64-bit
+ value. Needed for new statistics, and could come in handy
+ elsewhere.
+ * output.adb (Write_Int_64): Likewise.
+ * sinfo.ads: Remove obsolete comment. The xtreeprs program no
+ longer exists.
+ * types.ads: New 64-bit types needed for new statistics.
+
+2021-10-01 Dmitriy Anisimkov <anisimko@adacore.com>
+
+ * libgnat/memtrack.adb (Putc): New routine wrapped around fputc
+ with error check.
+ (Write): New routine wrapped around fwrite with error check.
+ Remove bound functions fopen, fwrite, fputs, fclose, OS_Exit.
+ Use the similar routines from System.CRTL and System.OS_Lib.
+
+2021-10-01 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_aggr.adb (Must_Slide): If the aggregate only contains an
+ others_clause no sliding id involved. Otherwise sliding is
+ required if any bound of the aggregate or the context subtype is
+ non-static.
+
+2021-10-01 Richard Kenner <kenner@adacore.com>
+
+ * gen_il-gen-gen_nodes.adb (N_Is_Decl): Add.
+ * gen_il-types.ads (N_Is_Decl): Likewise.
+
+2021-10-01 Richard Kenner <kenner@adacore.com>
+
+ * gen_il-gen-gen_nodes.adb (N_Entity_Name): Add.
+ * gen_il-types.ads (N_Entity_Name): Likewise.
+
+2021-10-01 Steve Baird <baird@adacore.com>
+
+ * bcheck.adb (Check_Versions): In the case of an ali file
+ version mismatch, if distinct integer values can be extracted
+ from the two version strings then include those values in the
+ generated error message.
+
+2021-10-01 Steve Baird <baird@adacore.com>
+
+ * sem_elab.adb (Is_Safe_Call): Return True in the case of a
+ (possibly rewritten) call to an expression function.
+
+2021-10-01 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * sem_aggr.adb (Resolve_Iterated_Component_Association):
+ Initialize Id_Typ to Any_Type by default.
+
+2021-10-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_ugn/gnat_and_program_execution.rst (gnatmem): Document
+ that it works only with fixed-position executables.
+
+2021-10-01 Doug Rupp <rupp@adacore.com>
+
+ * libgnat/s-parame__vxworks.ads (time_t_bits): Change to
+ Long_Long_Integer'Size.
+
+2021-09-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity): Fix comment.
+
+2021-09-23 Richard Kenner <kenner@adacore.com>
+
+ * gen_il-gen-gen_entities.adb (Subprogram_Body_Or_Type): Add.
+ * gen_il-types.ads (Subprogram_Body_Or_Type): Likewise.
+
+2021-09-23 Richard Kenner <kenner@adacore.com>
+
+ * einfo-utils.adb (Next_Index): Verify input and output are
+ N_Is_Index.
+ * gen_il-gen-gen_nodes.adb (N_Has_Bounds, N_Is_Index): Add.
+ * gen_il-types.ads (N_Has_Bounds, N_Is_Index): Likewise.
+ * sem_ch3.adb (Array_Type_Declaration): Use Next, not
+ Next_Index.
+ * sem_ch12.adb (Formal_Dimensions): Likewise.
+ * sem_util.adb (Is_Valid_Renaming): Likewise.
+
+2021-09-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_ugn/gnat_utility_programs.rst (gnatsymbolize):
+ Document new --load option and -g1 as minimal compilation
+ requirement.
+
+2021-09-23 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_aggr.adb (Resolve_Array_Aggregate): Only keep the bounds
+ for internally generated attributes; otherwise, compute them
+ anew.
+
+2021-09-23 Javier Miranda <miranda@adacore.com>
+
+ * sem_ch3.adb (Build_Access_Subprogram_Wrapper): Decorate the
+ wrapper with attribute Is_Wrapper, and move its declaration to
+ the freezing actions of its type declaration; done to facilitate
+ identifying it at later stages to avoid handling it as a
+ primitive operation of a tagged type; otherwise it may be
+ handled as a dispatching operation and erroneously registered in
+ a dispatch table.
+ (Make_Index): Add missing decoration of field Parent.
+ * sem_disp.adb (Check_Dispatching_Operation): Complete
+ decoration of late-overriding dispatching primitives.
+ (Is_Access_To_Subprogram_Wrapper): New subprogram.
+ (Inherited_Subprograms): Prevent cascaded errors; adding missing
+ support for private types.
+ * sem_type.adb (Add_One_Interp): Add missing support for the
+ first interpretation of a primitive of an inmediate ancestor
+ interface.
+ * sem_util.adb (Check_Result_And_Post_State_In_Pragma): Do not
+ report missing reference in postcondition placed in internally
+ built wrappers.
+ * exp_disp.adb (Expand_Dispatching_Call): Adding assertion.
+
+2021-09-23 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_aggr.adb (Resolve_Array_Aggregate): Check the validity of
+ an array aggregate all of whose components are iterated
+ component associations.
+ * exp_aggr.adb (Expand_Array_Aggregate,
+ Two_Pass_Aggregate_Expansion): implement two-pass algorithm and
+ replace original aggregate with resulting temporary, to ensure
+ that a proper length check is performed if context is
+ constrained. Use attributes Pos and Val to handle index types of
+ any discrete type.
+
+2021-09-23 Bob Duff <duff@adacore.com>
+
+ * gen_il-gen.adb: Set the number of concrete nodes that have the
+ Homonym field to a higher number than any other field. This
+ isn't true, but it forces Homonym's offset to be chosen first,
+ so it will be at offset zero and hence slot zero.
+
+2021-09-23 Richard Kenner <kenner@adacore.com>
+
+ * atree.adb (Relocate_Node): If relocating a subprgram call and
+ we're doing unnesting, make a new Parameter_Associations, if
+ any.
+
+2021-09-23 Piotr Trojanek <trojanek@adacore.com>
+
+ * libgnat/a-strbou.ads (Generic_Bounded_Length): Remove explicit
+ Initializes contract.
+
+2021-09-23 Bob Duff <duff@adacore.com>
+
+ * gen_il-gen.adb: Generate getters and setters with much of the
+ code inlined. Generate code for storing a few fields in the node
+ header, to avoid the extra level of indirection for those
+ fields. We generate the header type, so we don't have to
+ duplicate hand-written Ada and C code to depend on the number of
+ header fields. Declare constants for slot size. Use short names
+ because these are used all over. Remove
+ Put_Low_Level_Accessor_Instantiations, Put_Low_Level_C_Getter,
+ which are no longer needed. Rename
+ Put_High_Level_C_Getter-->Put_C_Getter.
+ * atree.ads, atree.adb: Take into account the header slots.
+ Take into account the single Node_Or_Entity_Field type. Remove
+ "pragma Assertion_Policy (Ignore);", because the routines in
+ this package are no longer efficiency critical.
+ * atree.h: Remove low-level getters, which are no longer used by
+ sinfo.h and einfo.h.
+ * einfo-utils.adb: Avoid crash in Known_Alignment.
+ * live.adb, sem_eval.adb: Remove code that prevents Node_Id from
+ having a predicate. We don't actually add a predicate to
+ Node_Id, but we want to be able to for temporary debugging.
+ * sinfo-utils.adb: Remove code that prevents Node_Id from having
+ a predicate. Take into account the single Node_Or_Entity_Field
+ type.
+ * sinfo-utils.ads: Minor.
+ * table.ads (Table_Type): Make the components aliased, because
+ low-level setters in Atree need to take 'Access.
+ * treepr.adb: Take into account the single Node_Or_Entity_Field
+ type. Make some code more robust, so we can print out
+ half-baked nodes.
+ * types.ads: Move types here for visibility purposes.
+ * gcc-interface/gigi.h, gcc-interface/trans.c: Take into account
+ the Node_Header change in the GNAT front end.
+ * gcc-interface/cuintp.c, gcc-interface/targtyps.c: Add because
+ gigi.h now refers to type Node_Header, which is in sinfo.h.
+
+2021-09-23 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-strfix.adb (Delete, Insert, Overwrite,
+ Replace_Slice): Remove SPARK_Mode Off.
+ * libgnat/a-strfix.ads (Insert, Overwrite, Replace_Slice):
+ Strengthen precondition.
+
+2021-09-23 Piotr Trojanek <trojanek@adacore.com>
+
+ * libgnat/a-strbou.ads (Generic_Bounded_Length): Remove non-null
+ Global contracts.
+
+2021-09-23 Steve Baird <baird@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_characteristics.rst: Update
+ this section to reflect the current version of Ada RM M.2.
+ * gnat_rm.texi: Regenerate.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-strfix.ads (Trim): Simplify contracts.
+ * libgnat/a-strfix.adb (Trim): Remove white space.
+
+2021-09-22 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch4.adb (Expand_N_Op_Eq): Reuse Is_Attribute_Result.
+ * exp_prag.adb (Expand_Attributes): Reuse Is_Attribute_Old.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * sem_ch3.adb (Analyze_Object_Declaration): Do not insert a
+ predicate check after a deferred constant declaration.
+
+2021-09-22 Bob Duff <duff@adacore.com>
+
+ * contracts.adb, einfo-utils.adb, einfo-utils.ads, exp_ch7.adb,
+ exp_ch9.adb, exp_disp.adb, exp_prag.adb, exp_smem.adb,
+ exp_util.adb, freeze.adb, sem_aggr.adb, sem_attr.adb,
+ sem_ch8.adb, sem_prag.ads, sem_util.adb, sem_util.ads: Fix
+ conformance errors.
+ * errout.adb, erroutc.adb: Remove pragmas Suppress.
+ * err_vars.ads: Initialize variables that were previously being
+ read uninitialized.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-strunb.ads: Mark package in SPARK with private part
+ not in SPARK.
+ (Free): Mark not in SPARK.
+
+2021-09-22 Arnaud Charlet <charlet@adacore.com>
+
+ * snames.ads-tmpl: Update status of some attributes.
+
+2021-09-22 Doug Rupp <rupp@adacore.com>
+
+ * libgnarl/s-interr__vxworks.adb (Interfaces.C): Remove as
+ unused.
+ (System.VxWorks.Ext): Import.
+ (System.VxWorks.Ext.STATUS): use type.
+ (STATUS): New subtype.
+ (OK): New constant.
+ (Interrupt_Connector): Return STATUS type vice int.
+ (Interrupt_Connect, Notify_Interrupt, Unbind_Handler,
+ Interrupt_Server_Task): Rename Status to Result. Assert Result =
+ OK.
+ * libgnarl/s-osinte__vxworks.adb (To_Clock_Ticks): Define constant
+ IERR, and return it vice ERROR.
+ (Binary_Semaphore_Delete): Return STATUS type vice int.
+ (Binary_Semaphore_Obtain): Likewise.
+ (Binary_Semaphore_Release): Likewise.
+ (Binary_Semaphore_Flush): Likewise.
+ * libgnarl/s-osinte__vxworks.ads (SVE): Renaming of
+ System.VxWorks.Ext.
+ (STATUS): Use SVE in declaration of subtype.
+ (BOOL): Likewise.
+ (vx_freq_t): Likewise.
+ (t_id): Likewise.
+ (gitpid): Use SVE in renaming of subprogram
+ (Task_Stop): Likewise.
+ (Task_Cont): Likewise.
+ (Int_Lock): Likewise.
+ (Int_Unlock): Likewise.
+ (Set_Time_Slice): Likewise.
+ (semDelete): Likewise.
+ (taskCpuAffinitySet): Likewise.
+ (taskMaskAffinitySet): Likewise.
+ (sigset_t): Use SVE in declaration of type.
+ (OK): Remove as unused.
+ (ERROR): Likewise.
+ (taskOptionsGet): return STATUS vice int.
+ (taskSuspend): Likewise.
+ (taskResume): Likewise.
+ (taskDelay): Likewise.
+ (taskVarAdd): Likewise.
+ (taskVarDelete): Likewise.
+ (taskVarSet): Likewise.
+ (tlkKeyCreate): Likewise.
+ (taskPrioritySet): Likewise.
+ (semGive): Likewise.
+ (semTake): Likewise.
+ (Binary_Semaphore_Delete): Likewise.
+ (Binary_Semaphore_Obtain): Likewise.
+ (Binary_Semaphore_Release): Likewise.
+ (Binary_Semaphore_Flush): Likewise.
+ (Interrupt_Connect): Likewise.
+ * libgnarl/s-taprop__vxworks.adb
+ (System.VxWorks.Ext.STATUS): use type.
+ (int): Syntactically align subtype.
+ (STATUS): New subtype.
+ (OK): New constant.
+ (Finalize_Lock): Check STATUS vice int. Assert OK.
+ (Finalize_Lock): Likewise.
+ (Write_Lock): Likewise.
+ (Write_Lock): Likewise.
+ (Write_Lock): Likewise.
+ (Unlock): Likewise.
+ (Unlock): Likewise.
+ (Unlock): Likewise.
+ (Unlock): Likewise.
+ (Sleep): Likewise.
+ (Sleep): Likewise.
+ (Sleep): Likewise.
+ (Timed_Sleep): Likewise and test Result.
+ (Timed_Delay): Likewise and test Result.
+ (Wakeup): Likewise.
+ (Yield): Likewise.
+ (Finalize_TCB): Likewise.
+ (Suspend_Until_True): Check OK.
+ (Stop_All_Tasks): Declare Dummy STATUS vice in. Check OK.
+ (Is_Task_Context): Use OSI renaming.
+ (Initialize): Use STATUS vice int.
+ * libgnarl/s-vxwext.adb
+ (IERR): Renamed from ERROR.
+ (taskCpuAffinitySet): Return IERR (int).
+ (taskMaskAffinitySet): Likewise.
+ * libgnarl/s-vxwext.ads
+ (STATUS): New subtype.
+ (OK): New STATUS constant.
+ (ERROR): Likewise.
+ * libgnarl/s-vxwext__kernel-smp.adb
+ (IERR): Renamed from ERROR.
+ (Int_Lock): Return IERR.
+ (semDelete): Return STATUS.
+ (Task_Cont): Likewise.
+ (Task_Stop): Likewise.
+ * libgnarl/s-vxwext__kernel.adb
+ (IERR): Renamed from ERROR.
+ (semDelete): Return STATUS.
+ (Task_Cont): Likewise.
+ (Task_Stop): Likewise.
+ (taskCpuAffinitySet): Return IERR (int)
+ (taskMaskAffinitySet): Likewise.
+ * libgnarl/s-vxwext__kernel.ads
+ (STATUS): New subtype.
+ (OK): New STATUS constant.
+ (ERROR): Likewise.
+ (Interrupt_Connect): Return STATUS
+ (semDelete): Likewise.
+ (Task_Cont): Likewise.
+ (Task_Stop): Likewise.
+ (Set_Time_Slice): Likewise.
+ * libgnarl/s-vxwext__rtp-smp.adb
+ (IERR): Renamed from ERROR.
+ (Int_Lock): return IERR constant vice ERROR.
+ (Interrupt_Connect): Return STATUS.
+ (semDelete): Likewise.
+ (Set_Time_Slice): Likewise.
+ * libgnarl/s-vxwext__rtp.adb
+ (IERR): Renamed from ERROR.
+ (Int_Lock): return IERR constant vice ERROR.
+ (Int_Unlock): Return STATUS.
+ (semDelete): Likewise.
+ (Set_Time_Slice): Likewise.
+ (taskCpuAffinitySet): Return IERR (int)
+ (taskMaskAffinitySet): Likewise.
+ * libgnarl/s-vxwext__rtp.ads
+ (STATUS): New subtype.
+ (OK): New STATUS constant.
+ (ERROR): Likewise.
+ (Interrupt_Connect): Return STATUS
+ (semDelete): Likewise.
+ (Task_Cont): Likewise.
+ (Task_Stop): Likewise.
+ (Set_Time_Slice): Likewise.
+
+2021-09-22 Arnaud Charlet <charlet@adacore.com>
+
+ * prep.adb (Preprocess): Allow for more flexibility when
+ Relaxed_RM_Semantics is set.
+
+2021-09-22 Pierre-Alexandre Bazin <bazin@adacore.com>
+
+ * libgnat/a-strbou.adb: Turn SPARK_Mode on.
+ * libgnat/a-strbou.ads: Write contracts.
+ * libgnat/a-strfix.ads (Index): Fix grammar error in a comment.
+ * libgnat/a-strsea.ads (Index): Likewise.
+ * libgnat/a-strsup.adb: Rewrite the body to take into account
+ the new definition of Super_String using Relaxed_Initialization
+ and a predicate.
+ (Super_Replicate, Super_Translate, Times): Added loop
+ invariants, and ghost lemmas for Super_Replicate and Times.
+ (Super_Trim): Rewrite the body using search functions to
+ determine the cutting points.
+ (Super_Element, Super_Length, Super_Slice, Super_To_String):
+ Remove (now written as expression functions in a-strsup.ads).
+ * libgnat/a-strsup.ads: Added contracts.
+ (Super_Element, Super_Length, Super_Slice, Super_To_String):
+ Rewrite as expression functions.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * sem_ch13.adb (Build_Predicate_Functions): Add guard.
+
+2021-09-22 Doug Rupp <rupp@adacore.com>
+
+ * libgnarl/s-vxwext.ads (BOOL): New int type.
+ (Interrupt_Context): Change return type to BOOL.
+ * libgnarl/s-vxwext__kernel.ads: Likewise.
+ * libgnarl/s-vxwext__rtp-smp.adb: Likewise.
+ * libgnarl/s-vxwext__rtp.adb: Likewise.
+ * libgnarl/s-vxwext__rtp.ads: Likewise.
+ * libgnarl/s-osinte__vxworks.adb (Interrupt_Context): Change
+ return type to BOOL.
+ * libgnarl/s-osinte__vxworks.ads (BOOL) New subtype.
+ (taskIsSuspended): Change return type to BOOL.
+ (Interrupt_Context): Change return type to BOOL. Adjust comments
+ accordingly.
+ * libgnarl/s-taprop__vxworks.adb (System.VxWorks.Ext.BOOL):
+ use type.
+ (Is_Task_Context): Test Interrupt_Context against 0.
+ * libgnat/i-vxwork.ads (BOOL): New int.
+ (intContext): Change return type to BOOL. Adjust comments.
+ * libgnat/i-vxwork__x86.ads: Likewise.
+
+2021-09-22 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_aux.adb, sem_aux.ads (Package_Body): Moved from GNATprove.
+ * sem_elab.adb (Spec_And_Body_From_Entity): Refine type of parameter.
+
+2021-09-22 Arnaud Charlet <charlet@adacore.com>
+
+ * doc/gnat_ugn/platform_specific_information.rst: Improve doc
+ on permission and containers.
+ * gnat_ugn.texi: Regenerate.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * atree.adb (Rewrite): Fix parent node of shared aspects.
+ * atree.ads (Rewrite): Add ??? comment on incorrect
+ documentation.
+ * einfo-utils.adb (Known_Esize): Fix logic.
+ * sem_ch13.adb (Alignment_Check_For_Size_Change,
+ Analyze_Attribute_Definition_Clause): Protect against unset
+ Size.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * freeze.adb (Build_Renamed_Body): Special case for GNATprove.
+ * sem_ch6.adb (Analyze_Expression_Function): Remove useless test
+ for a node to come from source, which becomes harmful otherwise.
+
+2021-09-22 Justin Squirek <squirek@adacore.com>
+
+ * ali.adb, ali.ads (Scan_ALI): Remove use of deprecated
+ parameter Ignore_ED, and all specification for Lower in call to
+ Get_File_Name.
+ * ali-util.adb (Read_Withed_ALIs): Modify call to Scan_ALI.
+ * clean.adb (Clean_Executables): Likewise.
+ * gnatbind.adb (Add_Artificial_ALI_File, Executable section):
+ Likewise.
+ * gnatlink.adb (Executable section): Likewise.
+ * gnatls.adb (Executable section): Likewise.
+ * make.adb (Check, Wait_For_Available_Slot): Likewise.
+ * aspects.ads: Add Aspect_No_Controlled_Parts to
+ Nonoverridable_Aspect_Id
+ * opt.ads: Remove function pointers used as a workaround for
+ ASIS.
+ * osint-c.adb (Executable section): Remove setting of function
+ pointer workarounds needed for ASIS.
+ * osint.adb (Read_Default_Search_Dirs): Correct behavior to
+ detect EOL characters.
+ * par_sco.adb (Output_Header): Remove comment regarding use of
+ First_Sloc.
+ (Traverse_Sync_Definition): Renamed to
+ Traverse_Protected_Or_Task_Definition.
+ * pprint.adb (Interal_List_Name): Add description about purpose,
+ and refactor conditional statement.
+ (Prepend): Removed.
+ * repinfo.adb (List_Rep_Info, Write_Info_Line): Remove use of
+ subprogram pointer.
+ * scng.adb (Scan): Remove CODEFIX question, and minor comment
+ change.
+ * sem_attr.adb (Analyze_Image_Attribute): Remove special
+ processing for 'Img.
+ * sem_ch6.adb (Check_Untagged_Equality): Add RM reference.
+ (FCE): Add comment describing behavior.
+ (Is_Non_Overriding_Operation): Minor comment formatting change.
+ * sem_type.adb (Is_Actual_Subprogram): Add comment about
+ Comes_From_Source test.
+ (Matching_Types): Describe non-matching cases.
+ * sem_util.adb (Is_Confirming): Add stub case for
+ No_Controlled_Parts.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * sem_ch13.adb (Build_Predicate_Functions): Access
+ Predicated_Parent only on subtypes.
+
+2021-09-22 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_prag.adb (Process_Import_Or_Interface): Relax error when
+ Relaxed_RM_Semantics.
+
+2021-09-22 Steve Baird <baird@adacore.com>
+
+ * libgnat/s-regpat.adb (Match): Handle the case where Self.First
+ is not NUL (so we know the first character we are looking for),
+ but case-insensitive matching has
+ been specified.
+ (Optimize): In the case of an EXACTF Op, set Self.First as is
+ done in the EXACT case, except with the addition of a call to
+ Lower_Case.
+
+2021-09-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-imenne.ads, libgnat/s-imenne.adb: Delete.
+ * gcc-interface/Make-lang.in (GNAT_ADA_OBJS): Remove s-imenne.o.
+ (GNATBIND_OBJS): Likewise.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * einfo.ads: Fix comments.
+ * exp_aggr.adb: Fix variable name.
+ * exp_util.adb: Fix comments.
+ * sem_ch13.adb: Fix comments.
+ * sem_ch3.adb: Fix comments and variable name.
+
+2021-09-22 Doug Rupp <rupp@adacore.com>
+
+ * libgnarl/s-osinte__vxworks.ads: Make procedure vice function.
+ * libgnarl/s-vxwext.ads: Likewise.
+ * libgnarl/s-vxwext__kernel-smp.adb: Likewise.
+ * libgnarl/s-vxwext__kernel.adb: Likewise.
+ * libgnarl/s-vxwext__kernel.ads: Likewise.
+ * libgnarl/s-vxwext__rtp-smp.adb: Likewise.
+ * libgnarl/s-vxwext__rtp.adb: Likewise.
+ * libgnarl/s-vxwext__rtp.ads: Likewise.
+ * libgnarl/s-taprop__vxworks.adb (Stop_All_Tasks): Call
+ Int_Unlock as a procedure.
+
+2021-09-22 Doug Rupp <rupp@adacore.com>
+
+ * libgnarl/s-osinte__vxworks.ads (SVE): New package renaming
+ (vx_freq_t): New subtype.
+ (sysClkRateGet): Return vx_freq_t.
+ * libgnarl/s-vxwext.ads (vx_freq_t): New type.
+ * libgnarl/s-vxwext__kernel.ads: Likewise.
+ * libgnarl/s-vxwext__rtp.ads: Likewise.
+
+2021-09-22 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * sem_case.adb (Composite_Case_Ops): Replace 'Image with
+ Error_Msg_Uint.
+
+2021-09-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_ch4.adb (Expand_N_If_Expression): Generate an intermediate
+ temporary when the expression is a condition in an outer decision
+ and control-flow optimizations are suppressed.
+
+2021-09-22 Steve Baird <baird@adacore.com>
+
+ * exp_ch5.adb (Expand_General_Case_Statement.Pattern_Match): Add
+ new function Indexed_Element to handle array element
+ comparisons. Handle case choices that are array aggregates,
+ string literals, or names denoting constants.
+ * sem_case.adb (Composite_Case_Ops.Array_Case_Ops): New package
+ providing utilities needed for casing on arrays.
+ (Composite_Case_Ops.Choice_Analysis): If necessary, include
+ array length as a "component" (like a discriminant) when
+ traversing components. We do not (yet) partition choice analysis
+ to deal with unequal length choices separately. Instead, we
+ embed everything in the minimum-dimensionality Cartesian product
+ space needed to handle all choices properly; this is determined
+ by the length of the longest choice pattern.
+ (Composite_Case_Ops.Choice_Analysis.Traverse_Discrete_Parts):
+ Include length as a "component" in the traversal if necessary.
+ (Composite_Case_Ops.Choice_Analysis.Parse_Choice.Traverse_Choice):
+ Add support for case choices that are string literals or names
+ denoting constants.
+ (Composite_Case_Ops.Choice_Analysis): Include length as a
+ "component" in the analysis if necessary.
+ (Check_Choices.Check_Case_Pattern_Choices.Ops.Value_Sets.Value_Index_Count):
+ Improve error message when capacity exceeded.
+ * doc/gnat_rm/implementation_defined_pragmas.rst: Update
+ documentation to reflect current implementation status.
+ * gnat_rm.texi: Regenerate.
+
+2021-09-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * freeze.adb (Check_Component_Storage_Order): Give a specific error
+ message for non-byte-aligned component in the packed case. Replace
+ "composite" with "record" in both cases.
+
+2021-09-22 Arnaud Charlet <charlet@adacore.com>
+
+ * libgnarl/a-tasini.ads, libgnarl/a-tasini.adb: Make compatible
+ with No_Elaboration_Code_All.
+ * libgnarl/s-taskin.ads, libgnarl/s-tassta.adb: Adjust
+ accordingly.
+
+2021-09-22 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_ch6.adb (Check_Returns): Change message on missing return.
+
+2021-09-22 Arnaud Charlet <charlet@adacore.com>
+
+ * gnatfind.adb, gnatxref.adb: Mark these tools as obsolete
+ before removing them completely.
+
+2021-09-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (range_cannot_be_superflat): Tweak comments.
+
+2021-09-21 Doug Rupp <rupp@adacore.com>
+
+ * init.c (__gnat_error_handler) [LynxOS]: Add a comment about
+ missing optional args.
+
+2021-09-21 Yannick Moy <moy@adacore.com>
+
+ * gen_il-gen.adb (Put_Opt_Subtype): Add suffix.
+
+2021-09-21 Justin Squirek <squirek@adacore.com>
+
+ * sem_util.adb (Accessibility_Level): Remove spurious special
+ case for protected type components.
+ * exp_ch4.adb (Generate_Accessibility_Check): Use general
+ Accessibility_Level instead of the low-level function
+ Type_Access_Level.
+
+2021-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat_ugn.texi: Regenerate.
+
+2021-09-21 Matthieu Eyraud <eyraud@adacore.com>
+
+ * par_sco.adb (Traverse_One): Add support for pragma Invariant /
+ Type_Invariant.
+
+2021-09-21 Bob Duff <duff@adacore.com>
+
+ * gen_il-gen.adb (Put_Opt_Subtype): Print out subtypes of the
+ form:
+ subtype Opt_N_Declaration is
+ Node_Id with Predicate =>
+ Opt_N_Declaration = Empty or else
+ Opt_N_Declaration in N_Declaration_Id;
+ One for each node or entity type, with the predicate allowing
+ Empty.
+ * atree.adb (Parent, Set_Parent): Remove unnecessary "Atree.".
+
+2021-09-21 Patrick Bernardi <bernardi@adacore.com>
+
+ * bindgen.adb (Gen_Adainit): For targets that suppress the
+ standard library: set the default stack size global variable if
+ a value is provided via the -d switch, and generate a call to
+ __gnat_initialize_stack_limit if stack checking using stack
+ limits is enabled.
+
+2021-09-21 Bob Duff <duff@adacore.com>
+
+ * sem_ch13.adb (Stream_Size): Print message about allowed stream
+ sizes even if other error were already found. This avoids
+ falling into the 'else', which prints "Stream_Size cannot be
+ given for...", which is misleading -- the Size COULD be given if
+ it were correct.
+
+2021-09-21 Daniel Mercier <mercier@adacore.com>
+
+ * exp_util.adb (Build_Temporary): In case of an external DISCR
+ symbol, set the related expression for CodePeer so that a more
+ comprehensible message can be emitted to the user.
+
+2021-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-dwalin.adb (Parse_Header): Tweak comments.
+ (Read_Entry_Format_Array): Tweak exception message.
+ (Symbolic_Address.Set_Result): Likewise.
+
+2021-09-21 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_ch7.adb (Make_Init_Call): Add guard to protect against a
+ missing initialization procedure for a type.
+
+2021-09-21 Doug Rupp <rupp@adacore.com>
+
+ * Makefile.rtl: Remove unused VxWorks sections.
+ * libgnarl/s-vxwext__noints.adb: Remove.
+ * libgnarl/s-vxwext__vthreads.ads: Remove.
+ * libgnat/a-elchha__vxworks-ppc-full.adb: Remove.
+ * libgnat/s-osprim__vxworks.adb: Remove.
+ * libgnat/s-osvers__vxworks-653.ads: Remove.
+ * libgnat/system-vxworks-e500-vthread.ads: Remove.
+ * libgnat/system-vxworks-ppc-vthread.ads: Remove.
+ * libgnat/system-vxworks-x86-vthread.ads: Remove.
+
+2021-09-21 Bob Duff <duff@adacore.com>
+
+ * uintp.ads, uintp.adb (UI_Is_In_Int_Range): Change the type of
+ the formal parameter to Valid_Uint. Remove code that preserved
+ the previous behavior, and replace it with an assertion. The
+ previous behavior is no longer needed given the recent change to
+ gigi.
+ (No, Present): Add comment.
+
+2021-09-21 Bob Duff <duff@adacore.com>
+
+ * sem_eval.adb (Fold_Shift): Replace an if_expression with an
+ if_statement.
+
+2021-09-21 Bob Duff <duff@adacore.com>
+
+ * uintp.ads, uintp.adb: Add assertions.
+ (Ubool, Opt_Ubool): New "boolean" subtypes.
+ (UI_Is_In_Int_Range): The parameter should probably be
+ Valid_Uint, but we don't change that for now, because it causes
+ failures in gigi.
+ * sem_util.ads, sem_util.adb (Is_True, Is_False,
+ Static_Boolean): Use Opt_Ubool subtype. Document the fact that
+ Is_True (No_Uint) = True. Implement Is_False in terms of
+ Is_True. We considered changing Static_Boolean to return Uint_1
+ in case of error, but that doesn't fit in well with
+ Static_Integer.
+ (Has_Compatible_Alignment_Internal): Deal with cases where Offs
+ is No_Uint. Change one "and" to "and then" to ensure we don't
+ pass No_Uint to ">", which would violate the new assertions.
+ * exp_util.adb, freeze.adb, sem_ch13.adb: Avoid violating new
+ assertions in Uintp.
+
+2021-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-dwalin.adb (To_File_Name): Fetch only the last string
+ from the .debug_line_str section.
+ (Symbolic_Address.Set_Result): Likewise.
+
+2021-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-dwalin.adb (Skip_Form): Fix cases of DW_FORM_addrx
+ and DW_FORM_implicit_const. Replace Constraint_Error with
+ Dwarf_Error.
+
+2021-09-21 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * exp_pakd.adb (Expand_Packed_Not): Replace expression with
+ statement.
+
+2021-09-21 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * sem_eval.adb (Is_Static_Subtype): Take predicates created
+ through "predicate" pragma into account.
+
+2021-09-21 Frederic Konrad <konrad@adacore.com>
+
+ * Makefile.rtl (aarch64-rtems*): Add GNATRTL_128BIT_PAIRS to
+ the LIBGNAT_TARGET_PAIRS list and also GNATRTL_128BIT_OBJS to
+ the EXTRA_GNATRTL_NONTASKING_OBJS list.
+
+2021-09-21 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_ch4.adb (Remove_Abstract_Operations): Add condition to
+ test for an E_Operator as part of criteria for setting
+ Abstract_Op on interpretations involving predefined operators.
+
+2021-09-21 Javier Miranda <miranda@adacore.com>
+
+ * exp_ch6.adb (Expand_Simple_Function_Return): For explicit
+ dereference of type conversion, enable code that ensures that
+ the tag of the result is that of the result type.
+
+2021-09-21 Bob Duff <duff@adacore.com>
+
+ * einfo-utils.adb: Add support (currently disabled) for using
+ "initial zero" instead of "Uint_0" to represent "unknown". Call
+ Known_ functions, instead of evilly duplicating their code
+ inline.
+ * fe.h (No_Uint_To_0): New function to convert No_Uint to
+ Uint_0, in order to preserve existing behavior.
+ (Copy_Esize, Copy_RM_Size): New imports from Einfo.Utils.
+ * cstand.adb: Set size fields of Standard_Debug_Renaming_Type
+ and Standard_Exception_Type.
+ * checks.adb, exp_attr.adb, exp_ch3.adb, exp_ch5.adb,
+ exp_ch6.adb, exp_pakd.adb, exp_util.adb, freeze.adb, itypes.adb,
+ layout.adb, repinfo.adb, sem_attr.adb, sem_ch12.adb,
+ sem_ch13.adb, sem_ch13.ads, sem_ch3.adb, sem_ch7.adb,
+ sem_util.adb: Protect calls with Known_..., use Copy_... Remove
+ assumption that Uint_0 represents "unknown".
+ * types.ads (Nonzero_Int): New subtype.
+ * gcc-interface/decl.c, gcc-interface/trans.c: Protect calls
+ with Known_... and use Copy_... as appropriate, to avoid
+ blowing up in unknown cases. Similarly, call No_Uint_To_0 to
+ preserve existing behavior.
+
+2021-09-21 Steve Baird <baird@adacore.com>
+
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Add a new nested
+ function, Directly_Specified, and then use it in the
+ implementation of the required check.
+
+2021-09-21 Steve Baird <baird@adacore.com>
+
+ * libgnat/a-costso.ads, libgnat/a-costso.adb: A new library
+ unit, Ada.Containers.Stable_Sorting, which exports a pair of
+ generics (one within the other) which are instantiated by each
+ of the 5 doubly-linked list container generics to implement
+ their respective Sort procedures. We use a pair of generics,
+ rather than a single generic, in order to further reduce code
+ duplication. The outer generic takes a formal private Node_Ref
+ type representing a reference to a linked list element. For some
+ instances, the corresponding actual parameter will be an access
+ type; for others, it will be the index type for an array.
+ * Makefile.rtl: Include new Ada.Containers.Stable_Sorting unit.
+ * libgnat/a-cbdlli.adb, libgnat/a-cdlili.adb,
+ libgnat/a-cfdlli.adb, libgnat/a-cidlli.adb, libgnat/a-crdlli.adb
+ (Sort): Replace existing Sort implementation with a call to an
+ instance of
+ Ada.Containers.Stable_Sorting.Doubly_Linked_List_Sort. Declare
+ the (trivial) actual parameters needed to declare that instance.
+ * libgnat/a-cfdlli.ads: Fix a bug encountered during testing in
+ the postcondition for M_Elements_Sorted. With a partial
+ ordering, it is possible for all three of (X < Y), (Y < X),
+ and (X = Y) to be simultaneously false, so that case needs to
+ handled correctly.
+
+2021-09-21 Piotr Trojanek <trojanek@adacore.com>
+
+ * errout.adb (Error_Msg_Internal): Fix references to Sptr and
+ Optr in comment; fix grammar of "low-level" where it is used as
+ an adjective.
+
+2021-09-21 Piotr Trojanek <trojanek@adacore.com>
+
+ * errout.adb (Write_Source_Code_Lines): Use Cur_Loc before
+ incrementing it, so that we don't need to decrement it.
+
+2021-09-21 Yannick Moy <moy@adacore.com>
+
+ * errout.adb (Get_Line_End): Do not allow the result to go past
+ the end of the buffer.
+
+2021-09-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch3.adb (Process_Discriminant_Expressions): If the
+ constraint is for a Component_Definition that appears in a
+ Component_Declaration, the entity to be used to create the
+ potentially global symbol is the Defining_Identifier of the
+ Component_Declaration.
+
+2021-09-21 Bob Duff <duff@adacore.com>
+
+ * libgnat/a-stbufi.ads, libgnat/a-stbufi.adb: Change all
+ occurrences of GNAT.OS_Lib to System.OS_Lib.
+
2021-09-20 Piotr Trojanek <trojanek@adacore.com>
* inline.adb (Has_Excluded_Declaration): Remove redundant guard;
diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c
index d4445f0..60cfa93 100644
--- a/gcc/ada/adaint.c
+++ b/gcc/ada/adaint.c
@@ -98,6 +98,7 @@
#ifdef __QNX__
#include <sys/syspage.h>
+#include <sys/time.h>
#endif
#ifdef IN_RTS
diff --git a/gcc/ada/ali-util.adb b/gcc/ada/ali-util.adb
index 9074a9a..6c567c3 100644
--- a/gcc/ada/ali-util.adb
+++ b/gcc/ada/ali-util.adb
@@ -249,7 +249,6 @@ package body ALI.Util is
Scan_ALI
(F => Afile,
T => Text,
- Ignore_ED => False,
Err => False);
Free (Text);
diff --git a/gcc/ada/ali.adb b/gcc/ada/ali.adb
index 24f1677..3815a70 100644
--- a/gcc/ada/ali.adb
+++ b/gcc/ada/ali.adb
@@ -892,7 +892,6 @@ package body ALI is
function Scan_ALI
(F : File_Name_Type;
T : Text_Buffer_Ptr;
- Ignore_ED : Boolean;
Err : Boolean;
Ignore_Lines : String := "X";
Ignore_Errors : Boolean := False;
@@ -1319,8 +1318,7 @@ package body ALI is
exit when Nextc = ',';
-- Terminate if left bracket not part of wide char
- -- sequence Note that we only recognize brackets
- -- notation so far ???
+ -- sequence.
exit when Nextc = '[' and then T (P + 1) /= '"';
@@ -2938,9 +2936,7 @@ package body ALI is
-- Store AD indication unless ignore required
- if not Ignore_ED then
- Withs.Table (Withs.Last).Elab_All_Desirable := True;
- end if;
+ Withs.Table (Withs.Last).Elab_All_Desirable := True;
elsif Nextc = 'E' then
P := P + 1;
@@ -2957,12 +2953,9 @@ package body ALI is
Checkc ('D');
Check_At_End_Of_Field;
- -- Store ED indication unless ignore required
+ -- Store ED indication
- if not Ignore_ED then
- Withs.Table (Withs.Last).Elab_Desirable :=
- True;
- end if;
+ Withs.Table (Withs.Last).Elab_Desirable := True;
end if;
else
@@ -3213,13 +3206,10 @@ package body ALI is
Skip_Space;
Sdep.Increment_Last;
- -- In the following call, Lower is not set to True, this is either
- -- a bug, or it deserves a special comment as to why this is so???
-
-- The file/path name may be quoted
Sdep.Table (Sdep.Last).Sfile :=
- Get_File_Name (May_Be_Quoted => True);
+ Get_File_Name (Lower => True, May_Be_Quoted => True);
Sdep.Table (Sdep.Last).Stamp := Get_Stamp;
Sdep.Table (Sdep.Last).Dummy_Entry :=
diff --git a/gcc/ada/ali.ads b/gcc/ada/ali.ads
index 3ac9f0e..175aea9 100644
--- a/gcc/ada/ali.ads
+++ b/gcc/ada/ali.ads
@@ -1389,7 +1389,6 @@ package ALI is
function Scan_ALI
(F : File_Name_Type;
T : Text_Buffer_Ptr;
- Ignore_ED : Boolean;
Err : Boolean;
Ignore_Lines : String := "X";
Ignore_Errors : Boolean := False;
@@ -1399,11 +1398,6 @@ package ALI is
-- table. Switch settings may be modified as described above in the
-- switch description settings.
--
- -- Ignore_ED is normally False. If set to True, it indicates that
- -- all AD/ED (elaboration desirable) indications in the ALI file are
- -- to be ignored. This parameter is obsolete now that the -f switch
- -- is removed from gnatbind, and should be removed ???
- --
-- Err determines the action taken on an incorrectly formatted file.
-- If Err is False, then an error message is output, and the program
-- is terminated. If Err is True, then no error message is output,
diff --git a/gcc/ada/aspects.ads b/gcc/ada/aspects.ads
index 0f9ed23..ab11bfd 100644
--- a/gcc/ada/aspects.ads
+++ b/gcc/ada/aspects.ads
@@ -89,6 +89,7 @@ package Aspects is
Aspect_Default_Storage_Pool,
Aspect_Default_Value,
Aspect_Depends, -- GNAT
+ Aspect_Designated_Storage_Model, -- GNAT
Aspect_Dimension, -- GNAT
Aspect_Dimension_System, -- GNAT
Aspect_Dispatching_Domain,
@@ -147,6 +148,7 @@ package Aspects is
Aspect_SPARK_Mode, -- GNAT
Aspect_Stable_Properties,
Aspect_Static_Predicate,
+ Aspect_Storage_Model_Type, -- GNAT
Aspect_Storage_Pool,
Aspect_Storage_Size,
Aspect_Stream_Size,
@@ -187,6 +189,7 @@ package Aspects is
Aspect_Atomic_Components,
Aspect_Disable_Controlled, -- GNAT
Aspect_Discard_Names,
+ Aspect_CUDA_Device, -- GNAT
Aspect_CUDA_Global, -- GNAT
Aspect_Exclusive_Functions,
Aspect_Export,
@@ -233,7 +236,7 @@ package Aspects is
Aspect_Implicit_Dereference | Aspect_Constant_Indexing |
Aspect_Variable_Indexing | Aspect_Aggregate |
Aspect_Max_Entry_Queue_Length
- -- | Aspect_No_Controlled_Parts
+ | Aspect_No_Controlled_Parts
-- ??? No_Controlled_Parts not yet in Aspect_Id enumeration
; -- see RM 13.1.1(18.7)
@@ -379,6 +382,7 @@ package Aspects is
Aspect_Default_Storage_Pool => Expression,
Aspect_Default_Value => Expression,
Aspect_Depends => Expression,
+ Aspect_Designated_Storage_Model => Name,
Aspect_Dimension => Expression,
Aspect_Dimension_System => Expression,
Aspect_Dispatching_Domain => Expression,
@@ -437,6 +441,7 @@ package Aspects is
Aspect_SPARK_Mode => Optional_Name,
Aspect_Stable_Properties => Expression,
Aspect_Static_Predicate => Expression,
+ Aspect_Storage_Model_Type => Expression,
Aspect_Storage_Pool => Name,
Aspect_Storage_Size => Expression,
Aspect_Stream_Size => Expression,
@@ -476,6 +481,7 @@ package Aspects is
Aspect_Contract_Cases => False,
Aspect_Convention => True,
Aspect_CPU => False,
+ Aspect_CUDA_Device => False,
Aspect_CUDA_Global => False,
Aspect_Default_Component_Value => True,
Aspect_Default_Initial_Condition => False,
@@ -483,6 +489,7 @@ package Aspects is
Aspect_Default_Storage_Pool => True,
Aspect_Default_Value => True,
Aspect_Depends => False,
+ Aspect_Designated_Storage_Model => True,
Aspect_Dimension => False,
Aspect_Dimension_System => False,
Aspect_Dispatching_Domain => False,
@@ -542,6 +549,7 @@ package Aspects is
Aspect_SPARK_Mode => False,
Aspect_Stable_Properties => False,
Aspect_Static_Predicate => False,
+ Aspect_Storage_Model_Type => False,
Aspect_Storage_Pool => True,
Aspect_Storage_Size => True,
Aspect_Stream_Size => True,
@@ -627,6 +635,7 @@ package Aspects is
Aspect_Contract_Cases => Name_Contract_Cases,
Aspect_Convention => Name_Convention,
Aspect_CPU => Name_CPU,
+ Aspect_CUDA_Device => Name_CUDA_Device,
Aspect_CUDA_Global => Name_CUDA_Global,
Aspect_Default_Component_Value => Name_Default_Component_Value,
Aspect_Default_Initial_Condition => Name_Default_Initial_Condition,
@@ -634,6 +643,7 @@ package Aspects is
Aspect_Default_Storage_Pool => Name_Default_Storage_Pool,
Aspect_Default_Value => Name_Default_Value,
Aspect_Depends => Name_Depends,
+ Aspect_Designated_Storage_Model => Name_Designated_Storage_Model,
Aspect_Dimension => Name_Dimension,
Aspect_Dimension_System => Name_Dimension_System,
Aspect_Disable_Controlled => Name_Disable_Controlled,
@@ -723,6 +733,7 @@ package Aspects is
Aspect_Stable_Properties => Name_Stable_Properties,
Aspect_Static => Name_Static,
Aspect_Static_Predicate => Name_Static_Predicate,
+ Aspect_Storage_Model_Type => Name_Storage_Model_Type,
Aspect_Storage_Pool => Name_Storage_Pool,
Aspect_Storage_Size => Name_Storage_Size,
Aspect_Stream_Size => Name_Stream_Size,
@@ -872,11 +883,13 @@ package Aspects is
Aspect_Attach_Handler => Always_Delay,
Aspect_Constant_Indexing => Always_Delay,
Aspect_CPU => Always_Delay,
+ Aspect_CUDA_Device => Always_Delay,
Aspect_CUDA_Global => Always_Delay,
Aspect_Default_Iterator => Always_Delay,
Aspect_Default_Storage_Pool => Always_Delay,
Aspect_Default_Value => Always_Delay,
Aspect_Default_Component_Value => Always_Delay,
+ Aspect_Designated_Storage_Model => Always_Delay,
Aspect_Discard_Names => Always_Delay,
Aspect_Dispatching_Domain => Always_Delay,
Aspect_Dynamic_Predicate => Always_Delay,
@@ -928,6 +941,7 @@ package Aspects is
Aspect_Simple_Storage_Pool => Always_Delay,
Aspect_Simple_Storage_Pool_Type => Always_Delay,
Aspect_Static_Predicate => Always_Delay,
+ Aspect_Storage_Model_Type => Always_Delay,
Aspect_Storage_Pool => Always_Delay,
Aspect_Stream_Size => Always_Delay,
Aspect_String_Literal => Always_Delay,
diff --git a/gcc/ada/atree.adb b/gcc/ada/atree.adb
index 540d4ff..98614e8 100644
--- a/gcc/ada/atree.adb
+++ b/gcc/ada/atree.adb
@@ -23,20 +23,12 @@
-- --
------------------------------------------------------------------------------
--- Assertions in this package are too slow, and are mostly needed when working
--- on this package itself, or on gen_il, so we disable them.
--- To debug low-level bugs in this area, comment out the following pragma,
--- and run with -gnatd_v.
-
-pragma Assertion_Policy (Ignore);
-
with Aspects; use Aspects;
with Debug; use Debug;
with Namet; use Namet;
with Nlists; use Nlists;
with Opt; use Opt;
with Output; use Output;
-with Seinfo; use Seinfo;
with Sinfo.Utils; use Sinfo.Utils;
with System.Storage_Elements;
@@ -153,7 +145,11 @@ package body Atree is
function Size_In_Slots (N : Node_Or_Entity_Id) return Slot_Count;
-- Number of slots belonging to N. This can be less than
- -- Size_In_Slots_To_Alloc for entities.
+ -- Size_In_Slots_To_Alloc for entities. Includes both header
+ -- and dynamic slots.
+
+ function Size_In_Slots_Dynamic (N : Node_Or_Entity_Id) return Slot_Count;
+ -- Just counts the number of dynamic slots
function Size_In_Slots_To_Alloc (N : Node_Or_Entity_Id) return Slot_Count;
function Size_In_Slots_To_Alloc (Kind : Node_Kind) return Slot_Count;
@@ -161,35 +157,47 @@ package body Atree is
-- to allocate the max, because we don't know the Ekind when this is
-- called.
- function Off_0 (N : Node_Id) return Node_Offset;
- -- Offset of the first slot of N (offset 0) in Slots.Table
+ function Off_F (N : Node_Id) return Node_Offset with Inline;
+ -- Offset of the first dynamic slot of N in Slots.Table.
+ -- The actual offset of this slot from the start of the node
+ -- is not 0; this is logically the first slot after the header
+ -- slots.
- function Off_L (N : Node_Id) return Node_Offset;
+ function Off_0 (N : Node_Id) return Node_Offset'Base with Inline;
+ -- This is for zero-origin addressing of the dynamic slots.
+ -- It points to slot 0 of N in Slots.Table, which does not exist,
+ -- because the first few slots are stored in the header.
+
+ function Off_L (N : Node_Id) return Node_Offset with Inline;
-- Offset of the last slot of N in Slots.Table
- procedure Zero_Slots (First, Last : Node_Offset) with Inline;
- -- Set slots in the range F..L to zero
+ procedure Zero_Dynamic_Slots (First, Last : Node_Offset'Base) with Inline;
+ -- Set dynamic slots in the range First..Last to zero
+
+ procedure Zero_Header_Slots (N : Node_Or_Entity_Id) with Inline;
+ -- Zero the header slots belonging to N
procedure Zero_Slots (N : Node_Or_Entity_Id) with Inline;
- -- Zero the slots belonging to N
+ -- Zero the slots belonging to N (both header and dynamic)
- procedure Copy_Slots (From, To : Node_Offset; Num_Slots : Slot_Count)
+ procedure Copy_Dynamic_Slots
+ (From, To : Node_Offset; Num_Slots : Slot_Count)
with Inline;
-- Copy Num_Slots slots from From to To. Caller is responsible for ensuring
-- that the Num_Slots at To are a reasonable place to copy to.
procedure Copy_Slots (Source, Destination : Node_Id) with Inline;
- -- Copies the slots of Source to Destination; uses the node kind to
- -- determine the Num_Slots.
+ -- Copies the slots (both header and dynamic) of Source to Destination;
+ -- uses the node kind to determine the Num_Slots.
function Get_Field_Value
- (N : Node_Id; Field : Node_Field) return Field_Size_32_Bit;
+ (N : Node_Id; Field : Node_Or_Entity_Field) return Field_Size_32_Bit;
-- Get any field value as a Field_Size_32_Bit. If the field is smaller than
-- 32 bits, convert it to Field_Size_32_Bit. The Field must be present in
-- the Nkind of N.
procedure Set_Field_Value
- (N : Node_Id; Field : Node_Field; Val : Field_Size_32_Bit);
+ (N : Node_Id; Field : Node_Or_Entity_Field; Val : Field_Size_32_Bit);
-- Set any field value as a Field_Size_32_Bit. If the field is smaller than
-- 32 bits, convert it from Field_Size_32_Bit, and Val had better be small
-- enough. The Field must be present in the Nkind of N.
@@ -199,10 +207,6 @@ package body Atree is
-- Called whenever Nkind is modified. Raises an exception if not all
-- vanishing fields are in their initial zero state.
- function Get_Field_Value
- (N : Entity_Id; Field : Entity_Field) return Field_Size_32_Bit;
- procedure Set_Field_Value
- (N : Entity_Id; Field : Entity_Field; Val : Field_Size_32_Bit);
procedure Check_Vanishing_Fields
(Old_N : Entity_Id; New_Kind : Entity_Kind);
-- Above are the same as the ones for nodes, but for entities
@@ -405,7 +409,8 @@ package body Atree is
pragma Assert (N'Valid);
pragma Assert (N <= Node_Offsets.Last);
- pragma Assert (Off_0 (N) <= Off_L (N));
+ pragma Assert (Off_L (N) >= Off_0 (N));
+ pragma Assert (Off_L (N) >= Off_F (N) - 1);
pragma Assert (Off_L (N) <= Slots.Last);
pragma Assert (Nkind (N)'Valid);
pragma Assert (Nkind (N) /= N_Unused_At_End);
@@ -469,8 +474,9 @@ package body Atree is
function Cast is new
Unchecked_Conversion (Field_Size_1_Bit, Field_Type);
+ Val : constant Field_Size_1_Bit := Get_1_Bit_Val (N, Offset);
begin
- return Cast (Get_1_Bit_Val (N, Offset));
+ return Cast (Val);
end Get_1_Bit_Field;
function Get_2_Bit_Field
@@ -480,8 +486,9 @@ package body Atree is
function Cast is new
Unchecked_Conversion (Field_Size_2_Bit, Field_Type);
+ Val : constant Field_Size_2_Bit := Get_2_Bit_Val (N, Offset);
begin
- return Cast (Get_2_Bit_Val (N, Offset));
+ return Cast (Val);
end Get_2_Bit_Field;
function Get_4_Bit_Field
@@ -491,8 +498,9 @@ package body Atree is
function Cast is new
Unchecked_Conversion (Field_Size_4_Bit, Field_Type);
+ Val : constant Field_Size_4_Bit := Get_4_Bit_Val (N, Offset);
begin
- return Cast (Get_4_Bit_Val (N, Offset));
+ return Cast (Val);
end Get_4_Bit_Field;
function Get_8_Bit_Field
@@ -502,8 +510,9 @@ package body Atree is
function Cast is new
Unchecked_Conversion (Field_Size_8_Bit, Field_Type);
+ Val : constant Field_Size_8_Bit := Get_8_Bit_Val (N, Offset);
begin
- return Cast (Get_8_Bit_Val (N, Offset));
+ return Cast (Val);
end Get_8_Bit_Field;
function Get_32_Bit_Field
@@ -514,7 +523,8 @@ package body Atree is
function Cast is new
Unchecked_Conversion (Field_Size_32_Bit, Field_Type);
- Result : constant Field_Type := Cast (Get_32_Bit_Val (N, Offset));
+ Val : constant Field_Size_32_Bit := Get_32_Bit_Val (N, Offset);
+ Result : constant Field_Type := Cast (Val);
-- Note: declaring Result here instead of directly returning
-- Cast (...) helps CodePeer understand that there are no issues
-- around uninitialized variables.
@@ -612,138 +622,228 @@ package body Atree is
Set_32_Bit_Val (N, Offset, Cast (Val));
end Set_32_Bit_Field;
+ pragma Style_Checks ("M90");
+
+ -----------------------------------
+ -- Low-level getters and setters --
+ -----------------------------------
+
+ -- In the getters and setters below, we use shifting and masking to
+ -- simulate packed arrays. F_Size is the field size in bits. Mask is
+ -- that number of 1 bits in the low-order bits. F_Per_Slot is the number
+ -- of fields per slot. Slot_Off is the offset of the slot of interest.
+ -- S is the slot at that offset. V is the amount to shift by.
+
+ function In_NH (Slot_Off : Field_Offset) return Boolean is
+ (Slot_Off < N_Head);
+ -- In_NH stands for "in Node_Header", not "in New Hampshire"
+
+ function Get_Slot
+ (N : Node_Or_Entity_Id; Slot_Off : Field_Offset)
+ return Slot is
+ (if In_NH (Slot_Off) then
+ Node_Offsets.Table (N).Slots (Slot_Off)
+ else Slots.Table (Node_Offsets.Table (N).Offset + Slot_Off));
+ -- Get the slot value, either directly from the node header, or
+ -- indirectly from the Slots table.
+
+ procedure Set_Slot
+ (N : Node_Or_Entity_Id; Slot_Off : Field_Offset; S : Slot);
+ -- Set the slot value, either directly from the node header, or
+ -- indirectly from the Slots table, to S.
+
function Get_1_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset) return Field_Size_1_Bit
is
- -- We wish we were using packed arrays, but instead we're simulating
- -- them with modular integers. L here (and elsewhere) is the 'Length
- -- of that simulated array.
- L : constant Field_Offset := Slot_Size / 1;
-
- pragma Debug (Validate_Node_And_Offset (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 1;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset (N, Slot_Off));
+ Raw : constant Field_Size_1_Bit :=
+ Field_Size_1_Bit (Shift_Right (S, V) and Mask);
begin
- return Field_Size_1_Bit (Shift_Right (S, V) and 1);
+ return Raw;
end Get_1_Bit_Val;
function Get_2_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset) return Field_Size_2_Bit
is
- L : constant Field_Offset := Slot_Size / 2;
-
- pragma Debug (Validate_Node_And_Offset (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 2;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset (N, Slot_Off));
+ Raw : constant Field_Size_2_Bit :=
+ Field_Size_2_Bit (Shift_Right (S, V) and Mask);
begin
- return Field_Size_2_Bit (Shift_Right (S, V) and 3);
+ return Raw;
end Get_2_Bit_Val;
function Get_4_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset) return Field_Size_4_Bit
is
- L : constant Field_Offset := Slot_Size / 4;
-
- pragma Debug (Validate_Node_And_Offset (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 4;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset (N, Slot_Off));
+ Raw : constant Field_Size_4_Bit :=
+ Field_Size_4_Bit (Shift_Right (S, V) and Mask);
begin
- return Field_Size_4_Bit (Shift_Right (S, V) and 15);
+ return Raw;
end Get_4_Bit_Val;
function Get_8_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset) return Field_Size_8_Bit
is
- L : constant Field_Offset := Slot_Size / 8;
-
- pragma Debug (Validate_Node_And_Offset (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 8;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset (N, Slot_Off));
+ Raw : constant Field_Size_8_Bit :=
+ Field_Size_8_Bit (Shift_Right (S, V) and Mask);
begin
- return Field_Size_8_Bit (Shift_Right (S, V) and 255);
+ return Raw;
end Get_8_Bit_Val;
function Get_32_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset) return Field_Size_32_Bit
is
- pragma Debug (Validate_Node_And_Offset (N, Offset));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset);
+ F_Size : constant := 32;
+ -- No Mask needed
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ pragma Debug (Validate_Node_And_Offset (N, Slot_Off));
+ Raw : constant Field_Size_32_Bit :=
+ Field_Size_32_Bit (S);
begin
- return Field_Size_32_Bit (S);
+ return Raw;
end Get_32_Bit_Val;
+ procedure Set_Slot
+ (N : Node_Or_Entity_Id; Slot_Off : Field_Offset; S : Slot) is
+ begin
+ if In_NH (Slot_Off) then
+ Node_Offsets.Table (N).Slots (Slot_Off) := S;
+ else
+ Slots.Table (Node_Offsets.Table (N).Offset + Slot_Off) := S;
+ end if;
+ end Set_Slot;
+
procedure Set_1_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset; Val : Field_Size_1_Bit)
is
- L : constant Field_Offset := Slot_Size / 1;
-
- pragma Debug (Validate_Node_And_Offset_Write (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 1;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset_Write (N, Slot_Off));
begin
- S := (S and not Shift_Left (1, V)) or Shift_Left (Slot (Val), V);
+ Set_Slot
+ (N, Slot_Off,
+ (S and not Shift_Left (Mask, V)) or Shift_Left (Slot (Val), V));
end Set_1_Bit_Val;
procedure Set_2_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset; Val : Field_Size_2_Bit)
is
- L : constant Field_Offset := Slot_Size / 2;
-
- pragma Debug (Validate_Node_And_Offset_Write (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 2;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset_Write (N, Slot_Off));
begin
- S := (S and not Shift_Left (3, V)) or Shift_Left (Slot (Val), V);
+ Set_Slot
+ (N, Slot_Off,
+ (S and not Shift_Left (Mask, V)) or Shift_Left (Slot (Val), V));
end Set_2_Bit_Val;
procedure Set_4_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset; Val : Field_Size_4_Bit)
is
- L : constant Field_Offset := Slot_Size / 4;
-
- pragma Debug (Validate_Node_And_Offset_Write (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 4;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset_Write (N, Slot_Off));
begin
- S := (S and not Shift_Left (15, V)) or Shift_Left (Slot (Val), V);
+ Set_Slot
+ (N, Slot_Off,
+ (S and not Shift_Left (Mask, V)) or Shift_Left (Slot (Val), V));
end Set_4_Bit_Val;
procedure Set_8_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset; Val : Field_Size_8_Bit)
is
- L : constant Field_Offset := Slot_Size / 8;
-
- pragma Debug (Validate_Node_And_Offset_Write (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 8;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset_Write (N, Slot_Off));
begin
- S := (S and not Shift_Left (255, V)) or Shift_Left (Slot (Val), V);
+ Set_Slot
+ (N, Slot_Off,
+ (S and not Shift_Left (Mask, V)) or Shift_Left (Slot (Val), V));
end Set_8_Bit_Val;
procedure Set_32_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset; Val : Field_Size_32_Bit)
is
- pragma Debug (Validate_Node_And_Offset_Write (N, Offset));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset);
+ F_Size : constant := 32;
+ -- No Mask needed; this one doesn't do read-modify-write
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ pragma Debug (Validate_Node_And_Offset_Write (N, Slot_Off));
begin
- S := Slot (Val);
+ Set_Slot (N, Slot_Off, Slot (Val));
end Set_32_Bit_Val;
+ ----------------------
+ -- Print_Atree_Info --
+ ----------------------
+
+ procedure Print_Atree_Info (N : Node_Or_Entity_Id) is
+ function Cast is new Unchecked_Conversion (Slot, Int);
+ begin
+ Write_Int (Int (Size_In_Slots (N)));
+ Write_Str (" slots (");
+ Write_Int (Int (Off_0 (N)));
+ Write_Str (" .. ");
+ Write_Int (Int (Off_L (N)));
+ Write_Str ("):");
+
+ for Off in Off_0 (N) .. Off_L (N) loop
+ Write_Str (" ");
+ Write_Int (Cast (Get_Slot (N, Off)));
+ end loop;
+
+ Write_Eol;
+ end Print_Atree_Info;
+
end Atree_Private_Part;
- ---------------
- -- Set_Field --
- ---------------
+ ---------------------
+ -- Get_Field_Value --
+ ---------------------
function Get_Node_Field_Union is new Get_32_Bit_Field (Union_Id)
with Inline;
@@ -751,10 +851,9 @@ package body Atree is
-- etc.
function Get_Field_Value
- (N : Node_Id; Field : Node_Field) return Field_Size_32_Bit
+ (N : Node_Id; Field : Node_Or_Entity_Field) return Field_Size_32_Bit
is
- pragma Assert (Field_Checking.Field_Present (Nkind (N), Field));
- Desc : Field_Descriptor renames Node_Field_Descriptors (Field);
+ Desc : Field_Descriptor renames Field_Descriptors (Field);
begin
case Field_Size (Desc.Kind) is
@@ -766,11 +865,14 @@ package body Atree is
end case;
end Get_Field_Value;
+ ---------------------
+ -- Set_Field_Value --
+ ---------------------
+
procedure Set_Field_Value
- (N : Node_Id; Field : Node_Field; Val : Field_Size_32_Bit)
+ (N : Node_Id; Field : Node_Or_Entity_Field; Val : Field_Size_32_Bit)
is
- pragma Assert (Field_Checking.Field_Present (Nkind (N), Field));
- Desc : Field_Descriptor renames Node_Field_Descriptors (Field);
+ Desc : Field_Descriptor renames Field_Descriptors (Field);
begin
case Field_Size (Desc.Kind) is
@@ -782,13 +884,15 @@ package body Atree is
end case;
end Set_Field_Value;
- procedure Reinit_Field_To_Zero (N : Node_Id; Field : Node_Field) is
+ procedure Reinit_Field_To_Zero
+ (N : Node_Id; Field : Node_Or_Entity_Field)
+ is
begin
Set_Field_Value (N, Field, 0);
end Reinit_Field_To_Zero;
function Field_Is_Initial_Zero
- (N : Node_Id; Field : Node_Field) return Boolean is
+ (N : Node_Id; Field : Node_Or_Entity_Field) return Boolean is
begin
return Get_Field_Value (N, Field) = 0;
end Field_Is_Initial_Zero;
@@ -814,7 +918,7 @@ package body Atree is
Old_Kind : constant Node_Kind := Nkind (Old_N);
-- If this fails, it means you need to call Reinit_Field_To_Zero before
- -- calling Set_Nkind.
+ -- calling Mutate_Nkind.
begin
for J in Node_Field_Table (Old_Kind)'Range loop
@@ -839,47 +943,6 @@ package body Atree is
end loop;
end Check_Vanishing_Fields;
- function Get_Field_Value
- (N : Entity_Id; Field : Entity_Field) return Field_Size_32_Bit
- is
- pragma Assert (Field_Checking.Field_Present (Ekind (N), Field));
- Desc : Field_Descriptor renames Entity_Field_Descriptors (Field);
- begin
- case Field_Size (Desc.Kind) is
- when 1 => return Field_Size_32_Bit (Get_1_Bit_Val (N, Desc.Offset));
- when 2 => return Field_Size_32_Bit (Get_2_Bit_Val (N, Desc.Offset));
- when 4 => return Field_Size_32_Bit (Get_4_Bit_Val (N, Desc.Offset));
- when 8 => return Field_Size_32_Bit (Get_8_Bit_Val (N, Desc.Offset));
- when others => return Get_32_Bit_Val (N, Desc.Offset); -- 32
- end case;
- end Get_Field_Value;
-
- procedure Set_Field_Value
- (N : Entity_Id; Field : Entity_Field; Val : Field_Size_32_Bit)
- is
- pragma Assert (Field_Checking.Field_Present (Ekind (N), Field));
- Desc : Field_Descriptor renames Entity_Field_Descriptors (Field);
- begin
- case Field_Size (Desc.Kind) is
- when 1 => Set_1_Bit_Val (N, Desc.Offset, Field_Size_1_Bit (Val));
- when 2 => Set_2_Bit_Val (N, Desc.Offset, Field_Size_2_Bit (Val));
- when 4 => Set_4_Bit_Val (N, Desc.Offset, Field_Size_4_Bit (Val));
- when 8 => Set_8_Bit_Val (N, Desc.Offset, Field_Size_8_Bit (Val));
- when others => Set_32_Bit_Val (N, Desc.Offset, Val); -- 32
- end case;
- end Set_Field_Value;
-
- procedure Reinit_Field_To_Zero (N : Node_Id; Field : Entity_Field) is
- begin
- Set_Field_Value (N, Field, 0);
- end Reinit_Field_To_Zero;
-
- function Field_Is_Initial_Zero
- (N : Entity_Id; Field : Entity_Field) return Boolean is
- begin
- return Get_Field_Value (N, Field) = 0;
- end Field_Is_Initial_Zero;
-
procedure Check_Vanishing_Fields
(Old_N : Entity_Id; New_Kind : Entity_Kind)
is
@@ -918,13 +981,17 @@ package body Atree is
end Check_Vanishing_Fields;
Nkind_Offset : constant Field_Offset :=
- Node_Field_Descriptors (F_Nkind).Offset;
+ Field_Descriptors (F_Nkind).Offset;
procedure Set_Node_Kind_Type is new Set_8_Bit_Field (Node_Kind) with Inline;
procedure Init_Nkind (N : Node_Id; Val : Node_Kind) is
pragma Assert (Field_Is_Initial_Zero (N, F_Nkind));
begin
+ if Atree_Statistics_Enabled then
+ Set_Count (F_Nkind) := Set_Count (F_Nkind) + 1;
+ end if;
+
Set_Node_Kind_Type (N, Nkind_Offset, Val);
end Init_Nkind;
@@ -943,35 +1010,47 @@ package body Atree is
if Old_Size < New_Size then
declare
Old_Last_Slot : constant Node_Offset := Slots.Last;
- Old_Off_0 : constant Node_Offset := Off_0 (N);
+ Old_Off_F : constant Node_Offset := Off_F (N);
begin
- if Old_Last_Slot = Old_Off_0 + Old_Size - 1 then
+ if Old_Last_Slot = Old_Off_F + Old_Size - 1 then
-- In this case, the slots are at the end of Slots.Table, so we
-- don't need to move them.
Slots.Set_Last (Old_Last_Slot + New_Size - Old_Size);
else
-- Move the slots
- All_Node_Offsets (N) := Alloc_Slots (New_Size);
- Copy_Slots (Old_Off_0, Off_0 (N), Old_Size);
- pragma Debug (Zero_Slots (Old_Off_0, Old_Off_0 + Old_Size - 1));
+
+ declare
+ New_Off_F : constant Node_Offset := Alloc_Slots (New_Size);
+ begin
+ All_Node_Offsets (N).Offset := New_Off_F - N_Head;
+ Copy_Dynamic_Slots (Old_Off_F, New_Off_F, Old_Size);
+ pragma Debug
+ (Zero_Dynamic_Slots (Old_Off_F, Old_Off_F + Old_Size - 1));
+ end;
end if;
end;
- Zero_Slots (Off_0 (N) + Old_Size, Slots.Last);
+ Zero_Dynamic_Slots (Off_F (N) + Old_Size, Slots.Last);
+ end if;
+
+ if Atree_Statistics_Enabled then
+ Set_Count (F_Nkind) := Set_Count (F_Nkind) + 1;
end if;
Set_Node_Kind_Type (N, Nkind_Offset, Val);
pragma Debug (Validate_Node_Write (N));
+
+ New_Node_Debugging_Output (N);
end Mutate_Nkind;
procedure Mutate_Nkind (N : Node_Id; Val : Node_Kind) is
begin
- Mutate_Nkind (N, Val, Old_Size => Size_In_Slots (N));
+ Mutate_Nkind (N, Val, Old_Size => Size_In_Slots_Dynamic (N));
end Mutate_Nkind;
Ekind_Offset : constant Field_Offset :=
- Entity_Field_Descriptors (F_Ekind).Offset;
+ Field_Descriptors (F_Ekind).Offset;
procedure Set_Entity_Kind_Type is new Set_8_Bit_Field (Entity_Kind)
with Inline;
@@ -991,8 +1070,14 @@ package body Atree is
-- For now, we are allocating all entities with the same size, so we
-- don't need to reallocate slots here.
+ if Atree_Statistics_Enabled then
+ Set_Count (F_Nkind) := Set_Count (F_Ekind) + 1;
+ end if;
+
Set_Entity_Kind_Type (N, Ekind_Offset, Val);
pragma Debug (Validate_Node_Write (N));
+
+ New_Node_Debugging_Output (N);
end Mutate_Ekind;
-----------------------
@@ -1006,8 +1091,9 @@ package body Atree is
Sz : constant Slot_Count := Size_In_Slots_To_Alloc (Kind);
Sl : constant Node_Offset := Alloc_Slots (Sz);
begin
- Node_Offsets.Table (Result) := Sl;
- Zero_Slots (Sl, Sl + Sz - 1);
+ Node_Offsets.Table (Result).Offset := Sl - N_Head;
+ Zero_Dynamic_Slots (Sl, Sl + Sz - 1);
+ Zero_Header_Slots (Result);
end;
Init_Nkind (Result, Kind);
@@ -1045,7 +1131,7 @@ package body Atree is
pragma Assert (Nkind (N) not in N_Entity);
pragma Assert (New_Kind not in N_Entity);
- Old_Size : constant Slot_Count := Size_In_Slots (N);
+ Old_Size : constant Slot_Count := Size_In_Slots_Dynamic (N);
New_Size : constant Slot_Count := Size_In_Slots_To_Alloc (New_Kind);
Save_Sloc : constant Source_Ptr := Sloc (N);
@@ -1068,15 +1154,16 @@ package body Atree is
New_Offset : constant Field_Offset := Alloc_Slots (New_Size);
begin
pragma Debug (Zero_Slots (N));
- Node_Offsets.Table (N) := New_Offset;
- Zero_Slots (New_Offset, New_Offset + New_Size - 1);
+ Node_Offsets.Table (N).Offset := New_Offset - N_Head;
+ Zero_Dynamic_Slots (New_Offset, New_Offset + New_Size - 1);
+ Zero_Header_Slots (N);
end;
else
Zero_Slots (N);
end if;
- Mutate_Nkind (N, New_Kind, Old_Size);
+ Init_Nkind (N, New_Kind); -- Not Mutate, because of Zero_Slots above
Set_Sloc (N, Save_Sloc);
Set_In_List (N, Save_In_List);
@@ -1095,8 +1182,10 @@ package body Atree is
-- Copy_Slots --
----------------
- procedure Copy_Slots (From, To : Node_Offset; Num_Slots : Slot_Count) is
- pragma Assert (From /= To);
+ procedure Copy_Dynamic_Slots
+ (From, To : Node_Offset; Num_Slots : Slot_Count)
+ is
+ pragma Assert (if Num_Slots /= 0 then From /= To);
All_Slots : Slots.Table_Type renames
Slots.Table (Slots.First .. Slots.Last);
@@ -1109,21 +1198,21 @@ package body Atree is
begin
Destination_Slots := Source_Slots;
- end Copy_Slots;
+ end Copy_Dynamic_Slots;
procedure Copy_Slots (Source, Destination : Node_Id) is
pragma Debug (Validate_Node (Source));
- pragma Debug (Validate_Node_Write (Destination));
pragma Assert (Source /= Destination);
- S_Size : constant Slot_Count := Size_In_Slots (Source);
+ S_Size : constant Slot_Count := Size_In_Slots_Dynamic (Source);
All_Node_Offsets : Node_Offsets.Table_Type renames
Node_Offsets.Table (Node_Offsets.First .. Node_Offsets.Last);
begin
- Copy_Slots
- (All_Node_Offsets (Source), All_Node_Offsets (Destination), S_Size);
+ Copy_Dynamic_Slots
+ (Off_F (Source), Off_F (Destination), S_Size);
+ All_Node_Offsets (Destination).Slots := All_Node_Offsets (Source).Slots;
end Copy_Slots;
---------------
@@ -1152,14 +1241,14 @@ package body Atree is
if D_Size < S_Size then
pragma Debug (Zero_Slots (Destination)); -- destroy old slots
- Node_Offsets.Table (Destination) := Alloc_Slots (S_Size);
+ Node_Offsets.Table (Destination).Offset :=
+ Alloc_Slots (S_Size) - N_Head;
end if;
Copy_Slots (Source, Destination);
Set_In_List (Destination, Save_In_List);
Set_Link (Destination, Save_Link);
-
Set_Paren_Count_Of_Copy (Target => Destination, Source => Source);
end Copy_Node;
@@ -1371,7 +1460,7 @@ package body Atree is
(Is_Entity (E1) and then Is_Entity (E2)
and then not In_List (E1) and then not In_List (E2));
- Old_E1 : constant Node_Offset := Node_Offsets.Table (E1);
+ Old_E1 : constant Node_Header := Node_Offsets.Table (E1);
begin
Node_Offsets.Table (E1) := Node_Offsets.Table (E2);
@@ -1404,6 +1493,7 @@ package body Atree is
pragma Assert (not Is_Entity (Source));
Old_Kind : constant Node_Kind := Nkind (Source);
+ pragma Assert (Old_Kind in N_Direct_Name);
New_Kind : constant Node_Kind :=
(case Old_Kind is
when N_Character_Literal => N_Defining_Character_Literal,
@@ -1469,8 +1559,7 @@ package body Atree is
begin
for J in Fields'Range loop
declare
- Desc : Field_Descriptor renames
- Node_Field_Descriptors (Fields (J));
+ Desc : Field_Descriptor renames Field_Descriptors (Fields (J));
begin
if Desc.Kind in Node_Id_Field | List_Id_Field then
Fix_Parent (Get_Node_Field_Union (Fix_Node, Desc.Offset));
@@ -1620,7 +1709,8 @@ package body Atree is
end if;
return New_Id : constant Node_Id := Alloc_Node_Id do
- Node_Offsets.Table (New_Id) := Alloc_Slots (S_Size);
+ Node_Offsets.Table (New_Id).Offset :=
+ Alloc_Slots (S_Size) - N_Head;
Orig_Nodes.Append (New_Id);
Copy_Slots (Source, New_Id);
@@ -1676,7 +1766,7 @@ package body Atree is
-- source nodes, then reset Current_Error_Node. This is useful
-- if we bomb during parsing to get a error location for the bomb.
- if New_Sloc > No_Location and then Comes_From_Source_Default then
+ if New_Sloc > No_Location and then Comes_From_Source_Default then
Current_Error_Node := New_Id;
end if;
@@ -1765,16 +1855,25 @@ package body Atree is
-- Off_0 --
-----------
- function Off_0 (N : Node_Id) return Node_Offset is
+ function Off_0 (N : Node_Id) return Node_Offset'Base is
pragma Debug (Validate_Node (N));
All_Node_Offsets : Node_Offsets.Table_Type renames
Node_Offsets.Table (Node_Offsets.First .. Node_Offsets.Last);
begin
- return All_Node_Offsets (N);
+ return All_Node_Offsets (N).Offset;
end Off_0;
-----------
+ -- Off_F --
+ -----------
+
+ function Off_F (N : Node_Id) return Node_Offset is
+ begin
+ return Off_0 (N) + N_Head;
+ end Off_F;
+
+ -----------
-- Off_L --
-----------
@@ -1784,7 +1883,7 @@ package body Atree is
All_Node_Offsets : Node_Offsets.Table_Type renames
Node_Offsets.Table (Node_Offsets.First .. Node_Offsets.Last);
begin
- return All_Node_Offsets (N) + Size_In_Slots (N) - 1;
+ return All_Node_Offsets (N).Offset + Size_In_Slots (N) - 1;
end Off_L;
-------------------
@@ -1794,6 +1893,9 @@ package body Atree is
function Original_Node (Node : Node_Id) return Node_Id is
begin
pragma Debug (Validate_Node (Node));
+ if Atree_Statistics_Enabled then
+ Get_Original_Node_Count := Get_Original_Node_Count + 1;
+ end if;
return Orig_Nodes.Table (Node);
end Original_Node;
@@ -1855,28 +1957,6 @@ package body Atree is
Set_Comes_From_Source (NewN, Comes_From_Source (OldN));
end Preserve_Comes_From_Source;
- ----------------------
- -- Print_Atree_Info --
- ----------------------
-
- procedure Print_Atree_Info (N : Node_Or_Entity_Id) is
- function Cast is new Unchecked_Conversion (Slot, Int);
- begin
- Write_Int (Int (Size_In_Slots (N)));
- Write_Str (" slots (");
- Write_Int (Int (Off_0 (N)));
- Write_Str (" .. ");
- Write_Int (Int (Off_L (N)));
- Write_Str ("):");
-
- for Off in Off_0 (N) .. Off_L (N) loop
- Write_Str (" ");
- Write_Int (Cast (Slots.Table (Off)));
- end loop;
-
- Write_Eol;
- end Print_Atree_Info;
-
-------------------
-- Relocate_Node --
-------------------
@@ -1908,6 +1988,22 @@ package body Atree is
Set_Original_Node (New_Node, Original_Node (Source));
end if;
+ -- If we're relocating a subprogram call and we're doing
+ -- unnesting, be sure we make a new copy of any parameter associations
+ -- so that we don't share them.
+
+ if Nkind (Source) in N_Subprogram_Call
+ and then Opt.Unnest_Subprogram_Mode
+ and then Present (Parameter_Associations (Source))
+ then
+ declare
+ New_Assoc : constant List_Id := Parameter_Associations (Source);
+ begin
+ Set_Parent (New_Assoc, New_Node);
+ Set_Parameter_Associations (New_Node, New_Assoc);
+ end;
+ end if;
+
return New_Node;
end Relocate_Node;
@@ -1926,7 +2022,7 @@ package body Atree is
procedure Destroy_New_Node is
begin
Zero_Slots (New_Node);
- Node_Offsets.Table (New_Node) := Field_Offset'Base'Last;
+ Node_Offsets.Table (New_Node).Offset := Field_Offset'Base'Last;
end Destroy_New_Node;
begin
@@ -2025,10 +2121,16 @@ package body Atree is
-- Both the old and new copies of the node will share the same list
-- of aspect specifications if aspect specifications are present.
+ -- Restore the parent link of the aspect list to the old node, which
+ -- is the one linked in the tree.
if Old_Has_Aspects then
- Set_Aspect_Specifications
- (Sav_Node, Aspect_Specifications (Old_Node));
+ declare
+ Aspects : constant List_Id := Aspect_Specifications (Old_Node);
+ begin
+ Set_Aspect_Specifications (Sav_Node, Aspects);
+ Set_Parent (Aspects, Old_Node);
+ end;
end if;
end if;
@@ -2089,6 +2191,9 @@ package body Atree is
procedure Set_Original_Node (N : Node_Id; Val : Node_Id) is
begin
pragma Debug (Validate_Node_Write (N));
+ if Atree_Statistics_Enabled then
+ Set_Original_Node_Count := Set_Original_Node_Count + 1;
+ end if;
Orig_Nodes.Table (N) := Val;
end Set_Original_Node;
@@ -2176,11 +2281,15 @@ package body Atree is
Rewriting_Proc := Proc;
end Set_Rewriting_Proc;
+ ----------------------------
+ -- Size_In_Slots_To_Alloc --
+ ----------------------------
+
function Size_In_Slots_To_Alloc (Kind : Node_Kind) return Slot_Count is
begin
return
(if Kind in N_Entity then Einfo.Entities.Max_Entity_Size
- else Sinfo.Nodes.Size (Kind));
+ else Sinfo.Nodes.Size (Kind)) - N_Head;
-- Unfortunately, we don't know the Entity_Kind, so we have to use the
-- max.
end Size_In_Slots_To_Alloc;
@@ -2191,6 +2300,10 @@ package body Atree is
return Size_In_Slots_To_Alloc (Nkind (N));
end Size_In_Slots_To_Alloc;
+ -------------------
+ -- Size_In_Slots --
+ -------------------
+
function Size_In_Slots (N : Node_Or_Entity_Id) return Slot_Count is
begin
pragma Assert (Nkind (N) /= N_Unused_At_Start);
@@ -2199,6 +2312,15 @@ package body Atree is
else Sinfo.Nodes.Size (Nkind (N)));
end Size_In_Slots;
+ ---------------------------
+ -- Size_In_Slots_Dynamic --
+ ---------------------------
+
+ function Size_In_Slots_Dynamic (N : Node_Or_Entity_Id) return Slot_Count is
+ begin
+ return Size_In_Slots (N) - N_Head;
+ end Size_In_Slots_Dynamic;
+
-------------------
-- Traverse_Func --
-------------------
@@ -2366,14 +2488,179 @@ package body Atree is
-- Zero_Slots --
----------------
- procedure Zero_Slots (First, Last : Node_Offset) is
+ procedure Zero_Dynamic_Slots (First, Last : Node_Offset'Base) is
begin
Slots.Table (First .. Last) := (others => 0);
- end Zero_Slots;
+ end Zero_Dynamic_Slots;
+
+ procedure Zero_Header_Slots (N : Node_Or_Entity_Id) is
+ All_Node_Offsets : Node_Offsets.Table_Type renames
+ Node_Offsets.Table (Node_Offsets.First .. Node_Offsets.Last);
+ begin
+ All_Node_Offsets (N).Slots := (others => 0);
+ end Zero_Header_Slots;
procedure Zero_Slots (N : Node_Or_Entity_Id) is
begin
- Zero_Slots (Off_0 (N), Off_L (N));
+ Zero_Dynamic_Slots (Off_F (N), Off_L (N));
+ Zero_Header_Slots (N);
end Zero_Slots;
+ ----------------------
+ -- Print_Statistics --
+ ----------------------
+
+ procedure Print_Node_Statistics;
+ procedure Print_Field_Statistics;
+ -- Helpers for Print_Statistics
+
+ procedure Write_Ratio (X : Nat_64; Y : Pos_64);
+ -- Write the value of (X/Y) without using 'Image (approximately)
+
+ procedure Write_Ratio (X : Nat_64; Y : Pos_64) is
+ pragma Assert (X <= Y);
+ Ratio : constant Nat := Nat ((Long_Float (X) / Long_Float (Y)) * 1000.0);
+ begin
+ Write_Str (" (");
+
+ if Ratio = 0 then
+ Write_Str ("0.000");
+ elsif Ratio in 1 .. 9 then
+ Write_Str ("0.00");
+ Write_Int (Ratio);
+ elsif Ratio in 10 .. 99 then
+ Write_Str ("0.0");
+ Write_Int (Ratio);
+ elsif Ratio in 100 .. 999 then
+ Write_Str ("0.");
+ Write_Int (Ratio);
+ else
+ Write_Int (Ratio / 1000);
+ end if;
+
+ Write_Str (")");
+ end Write_Ratio;
+
+ procedure Print_Node_Statistics is
+ subtype Count is Nat_64;
+ Node_Counts : array (Node_Kind) of Count := (others => 0);
+ Entity_Counts : array (Entity_Kind) of Count := (others => 0);
+
+ All_Node_Offsets : Node_Offsets.Table_Type renames
+ Node_Offsets.Table (Node_Offsets.First .. Node_Offsets.Last);
+ begin
+ Write_Int (Int (Node_Offsets.Last));
+ Write_Line (" nodes (including entities)");
+ Write_Int (Int (Slots.Last));
+ Write_Line (" non-header slots");
+
+ for N in All_Node_Offsets'Range loop
+ declare
+ K : constant Node_Kind := Nkind (N);
+
+ begin
+ Node_Counts (K) := Node_Counts (K) + 1;
+
+ if K in N_Entity then
+ Entity_Counts (Ekind (N)) := Entity_Counts (Ekind (N)) + 1;
+ end if;
+ end;
+ end loop;
+
+ for K in Node_Kind loop
+ declare
+ Count : constant Nat_64 := Node_Counts (K);
+ begin
+ Write_Int_64 (Count);
+ Write_Ratio (Count, Int_64 (Node_Offsets.Last));
+ Write_Str (" ");
+ Write_Str (Node_Kind'Image (K));
+ Write_Str (" ");
+ Write_Int (Int (Sinfo.Nodes.Size (K)));
+ Write_Str (" slots");
+ Write_Eol;
+ end;
+ end loop;
+
+ for K in Entity_Kind loop
+ declare
+ Count : constant Nat_64 := Entity_Counts (K);
+ begin
+ Write_Int_64 (Count);
+ Write_Ratio (Count, Int_64 (Node_Offsets.Last));
+ Write_Str (" ");
+ Write_Str (Entity_Kind'Image (K));
+ Write_Str (" ");
+ Write_Int (Int (Einfo.Entities.Size (K)));
+ Write_Str (" slots");
+ Write_Eol;
+ end;
+ end loop;
+ end Print_Node_Statistics;
+
+ procedure Print_Field_Statistics is
+ Total, G_Total, S_Total : Call_Count := 0;
+ begin
+ Write_Int_64 (Get_Original_Node_Count);
+ Write_Str (" + ");
+ Write_Int_64 (Set_Original_Node_Count);
+ Write_Eol;
+ Write_Line (" Original_Node_Count getter and setter calls");
+ Write_Eol;
+
+ Write_Line ("Frequency of field getter and setter calls:");
+
+ for Field in Node_Or_Entity_Field loop
+ G_Total := G_Total + Get_Count (Field);
+ S_Total := S_Total + Set_Count (Field);
+ Total := G_Total + S_Total;
+ end loop;
+
+ -- This assertion helps CodePeer understand that Total cannot be 0 (this
+ -- is true because GNAT does not attempt to compile empty files).
+ pragma Assert (Total > 0);
+
+ Write_Int_64 (Total);
+ Write_Str (" (100%) = ");
+ Write_Int_64 (G_Total);
+ Write_Str (" + ");
+ Write_Int_64 (S_Total);
+ Write_Line (" total getter and setter calls");
+
+ for Field in Node_Or_Entity_Field loop
+ declare
+ G : constant Call_Count := Get_Count (Field);
+ S : constant Call_Count := Set_Count (Field);
+ GS : constant Call_Count := G + S;
+
+ Desc : Field_Descriptor renames Field_Descriptors (Field);
+ Slot : constant Field_Offset :=
+ (Field_Size (Desc.Kind) * Desc.Offset) / Slot_Size;
+
+ begin
+ Write_Int_64 (GS);
+ Write_Ratio (GS, Total);
+ Write_Str (" = ");
+ Write_Int_64 (G);
+ Write_Str (" + ");
+ Write_Int_64 (S);
+ Write_Str (" ");
+ Write_Str (Node_Or_Entity_Field'Image (Field));
+ Write_Str (" in slot ");
+ Write_Int (Int (Slot));
+ Write_Str (" size ");
+ Write_Int (Int (Field_Size (Desc.Kind)));
+ Write_Eol;
+ end;
+ end loop;
+ end Print_Field_Statistics;
+
+ procedure Print_Statistics is
+ begin
+ Write_Eol;
+ Write_Eol;
+ Print_Node_Statistics;
+ Print_Field_Statistics;
+ end Print_Statistics;
+
end Atree;
diff --git a/gcc/ada/atree.ads b/gcc/ada/atree.ads
index 6fb5aa6..2f3ca40 100644
--- a/gcc/ada/atree.ads
+++ b/gcc/ada/atree.ads
@@ -48,6 +48,7 @@ with Alloc;
with Sinfo.Nodes; use Sinfo.Nodes;
with Einfo.Entities; use Einfo.Entities;
with Types; use Types;
+with Seinfo; use Seinfo;
with System; use System;
with Table;
with Unchecked_Conversion;
@@ -501,6 +502,7 @@ package Atree is
-- the contents of these two nodes fixing up the parent pointers of the
-- replaced node (we do not attempt to preserve parent pointers for the
-- original node). Neither Old_Node nor New_Node can be extended nodes.
+ -- ??? The above explanation is incorrect, instead Copy_Node is called.
--
-- Note: New_Node may not contain references to Old_Node, for example as
-- descendants, since the rewrite would make such references invalid. If
@@ -565,10 +567,9 @@ package Atree is
type Entity_Field_Set is array (Entity_Field) of Boolean with Pack;
- procedure Reinit_Field_To_Zero (N : Node_Id; Field : Node_Field);
- procedure Reinit_Field_To_Zero (N : Node_Id; Field : Entity_Field);
+ procedure Reinit_Field_To_Zero (N : Node_Id; Field : Node_Or_Entity_Field);
-- When a node is created, all fields are initialized to zero, even if zero
- -- is not a valid value of the field type. These procedures put the field
+ -- is not a valid value of the field type. This procedure puts the field
-- back to its initial zero value. Note that you can't just do something
-- like Set_Some_Field (N, 0), if Some_Field is of (say) type Uintp,
-- because Uintp is a subrange that does not include 0.
@@ -582,9 +583,7 @@ package Atree is
-- this.
function Field_Is_Initial_Zero
- (N : Node_Id; Field : Node_Field) return Boolean;
- function Field_Is_Initial_Zero
- (N : Entity_Id; Field : Entity_Field) return Boolean;
+ (N : Node_Id; Field : Node_Or_Entity_Field) return Boolean;
-- True if the field value is the initial zero value
procedure Mutate_Nkind (N : Node_Id; Val : Node_Kind) with Inline;
@@ -610,10 +609,6 @@ package Atree is
-- always the same; for example we change from E_Void, to E_Variable, to
-- E_Void, to E_Constant.
- procedure Print_Atree_Info (N : Node_Or_Entity_Id);
- -- Called from Treepr to print out information about N that is private to
- -- Atree.
-
-----------------------------
-- Private Part Subpackage --
-----------------------------
@@ -638,7 +633,7 @@ package Atree is
-- The nodes of the tree are stored in two tables (i.e. growable
-- arrays).
- -- A Node_Id points to an element of Nodes, which contains a
+ -- A Node_Id points to an element of Node_Offsets, which contains a
-- Field_Offset that points to an element of Slots. Each slot can
-- contain a single 32-bit field, or multiple smaller fields.
-- An n-bit field is aligned on an n-bit boundary. The size of a node is
@@ -648,12 +643,40 @@ package Atree is
-- The reason for the extra level of indirection is that Copy_Node,
-- Exchange_Entities, and Rewrite all assume that nodes can be modified
-- in place.
+ --
+ -- As an optimization, we store a few slots directly in the Node_Offsets
+ -- table (see type Node_Header) rather than requiring the extra level of
+ -- indirection for accessing those slots. N_Head is the number of slots
+ -- stored in the Node_Header. N_Head can be adjusted by modifying
+ -- Gen_IL.Gen. If N_Head is (say) 3, then a node containing 7 slots will
+ -- have slots 0..2 in the header, and 3..6 stored indirect in the Slots
+ -- table. We use zero-origin addressing, so the Offset into the Slots
+ -- table will point 3 slots before slot 3.
+
+ pragma Assert (N_Head <= Min_Node_Size);
+ pragma Assert (N_Head <= Min_Entity_Size);
- subtype Node_Offset is Field_Offset'Base
- range 1 .. Field_Offset'Base'Last;
+ Slot_Size : constant := 32;
+ type Slot is mod 2**Slot_Size;
+ for Slot'Size use Slot_Size;
+
+ -- The type Slot is defined in Types as a 32-bit modular integer. It
+ -- is logically split into the appropriate numbers of components of
+ -- appropriate size, but this splitting is not explicit because packed
+ -- arrays cannot be properly interfaced in C/C++ and packed records are
+ -- way too slow.
+
+ type Node_Header_Slots is
+ array (Field_Offset range 0 .. N_Head - 1) of Slot;
+ type Node_Header is record
+ Slots : Node_Header_Slots;
+ Offset : Node_Offset'Base;
+ end record;
+ pragma Assert (Node_Header'Size = (N_Head + 1) * Slot_Size);
+ pragma Assert (Node_Header'Size = 16 * 8);
package Node_Offsets is new Table.Table
- (Table_Component_Type => Node_Offset,
+ (Table_Component_Type => Node_Header,
Table_Index_Type => Node_Id'Base,
Table_Low_Bound => First_Node_Id,
Table_Initial => Alloc.Node_Offsets_Initial,
@@ -667,15 +690,6 @@ package Atree is
-- Short names for use in gdb, not used in real code. Note that gdb
-- can't find Node_Offsets.Table without a full expanded name.
- -- We define the type Slot as a 32-bit modular integer. It is logically
- -- split into the appropriate numbers of components of appropriate size,
- -- but this splitting is not explicit because packed arrays cannot be
- -- properly interfaced in C/C++ and packed records are way too slow.
-
- Slot_Size : constant := 32;
- type Slot is mod 2**Slot_Size;
- for Slot'Size use Slot_Size;
-
function Shift_Left (S : Slot; V : Natural) return Slot;
pragma Import (Intrinsic, Shift_Left);
@@ -855,6 +869,22 @@ package Atree is
function Is_Valid_Node (U : Union_Id) return Boolean;
-- True if U is within the range of Node_Offsets
+ procedure Print_Atree_Info (N : Node_Or_Entity_Id);
+ -- Called from Treepr to print out information about N that is private
+ -- to Atree.
+
end Atree_Private_Part;
+ -- Statistics:
+
+ subtype Call_Count is Nat_64;
+ Get_Count, Set_Count : array (Node_Or_Entity_Field) of Call_Count :=
+ (others => 0);
+ -- Number of calls to each getter and setter. See documentaton for
+ -- -gnatd.A.
+
+ Get_Original_Node_Count, Set_Original_Node_Count : Call_Count := 0;
+
+ procedure Print_Statistics;
+
end Atree;
diff --git a/gcc/ada/atree.h b/gcc/ada/atree.h
index 08b791c..7fb3bcb 100644
--- a/gcc/ada/atree.h
+++ b/gcc/ada/atree.h
@@ -65,77 +65,6 @@ Present (Tree_Id N)
#define Current_Error_Node atree__current_error_node
extern Node_Id Current_Error_Node;
-/* The following code corresponds to the Get_n_Bit_Field functions (for
- various n) in package Atree. The low-level getters in sinfo.h call
- these even-lower-level getters. */
-
-extern Field_Offset *Node_Offsets_Ptr;
-extern any_slot *Slots_Ptr;
-
-INLINE unsigned int Get_1_Bit_Field (Node_Id, Field_Offset);
-INLINE unsigned int Get_2_Bit_Field (Node_Id, Field_Offset);
-INLINE unsigned int Get_4_Bit_Field (Node_Id, Field_Offset);
-INLINE unsigned int Get_8_Bit_Field (Node_Id, Field_Offset);
-INLINE unsigned int Get_32_Bit_Field (Node_Id, Field_Offset);
-INLINE unsigned int Get_32_Bit_Field_With_Default (Node_Id, Field_Offset,
- unsigned int);
-INLINE unsigned int Get_Valid_32_Bit_Field (Node_Id, Field_Offset);
-
-INLINE unsigned int
-Get_1_Bit_Field (Node_Id N, Field_Offset Offset)
-{
- const Field_Offset L = Slot_Size / 1;
- any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset / L);
- return (slot >> (Offset % L) * (Slot_Size / L)) & 1;
-}
-
-INLINE unsigned int
-Get_2_Bit_Field (Node_Id N, Field_Offset Offset)
-{
- const Field_Offset L = Slot_Size / 2;
- any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset / L);
- return (slot >> (Offset % L) * (Slot_Size / L)) & 3;
-}
-
-INLINE unsigned int
-Get_4_Bit_Field (Node_Id N, Field_Offset Offset)
-{
- const Field_Offset L = Slot_Size / 4;
- any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset / L);
- return (slot >> (Offset % L) * (Slot_Size / L)) & 15;
-}
-
-INLINE unsigned int
-Get_8_Bit_Field (Node_Id N, Field_Offset Offset)
-{
- const Field_Offset L = Slot_Size / 8;
- any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset / L);
- return (slot >> (Offset % L) * (Slot_Size / L)) & 255;
-}
-
-INLINE unsigned int
-Get_32_Bit_Field (Node_Id N, Field_Offset Offset)
-{
- any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset);
- return slot;
-}
-
-INLINE unsigned int
-Get_32_Bit_Field_With_Default (Node_Id N, Field_Offset Offset,
- unsigned int Default_Value)
-{
- any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset);
- return slot == Empty ? Default_Value : slot;
-}
-
-INLINE unsigned int
-Get_Valid_32_Bit_Field (Node_Id N, Field_Offset Offset)
-{
- any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset);
- gcc_assert (slot != Empty);
- return slot;
-}
-
#ifdef __cplusplus
}
#endif
diff --git a/gcc/ada/bcheck.adb b/gcc/ada/bcheck.adb
index 804e2fd..38bf2c2 100644
--- a/gcc/ada/bcheck.adb
+++ b/gcc/ada/bcheck.adb
@@ -29,6 +29,7 @@ with Binderr; use Binderr;
with Butil; use Butil;
with Casing; use Casing;
with Fname; use Fname;
+with Gnatvsn;
with Namet; use Namet;
with Opt; use Opt;
with Osint;
@@ -1324,11 +1325,136 @@ package body Bcheck is
or else ALIs.Table (A).Ver (1 .. VL) /=
ALIs.Table (ALIs.First).Ver (1 .. VL)
then
- Error_Msg_File_1 := ALIs.Table (A).Sfile;
- Error_Msg_File_2 := ALIs.Table (ALIs.First).Sfile;
+ -- Version mismatch found; generate error message.
- Consistency_Error_Msg
- ("{ and { compiled with different GNAT versions");
+ declare
+ use Gnatvsn;
+
+ Prefix : constant String :=
+ Verbose_Library_Version
+ (1 .. Verbose_Library_Version'Length
+ - Library_Version'Length);
+
+ type ALI_Version is record
+ Primary, Secondary : Int range -1 .. Int'Last;
+ end record;
+
+ No_Version : constant ALI_Version := (-1, -1);
+
+ function Remove_Prefix (S : String) return String is
+ (S (S'First + Prefix'Length .. S'Last));
+
+ function Extract_Version (S : String) return ALI_Version;
+ -- Attempts to extract and return a pair of nonnegative library
+ -- version numbers from the given string; if unsuccessful,
+ -- then returns No_Version.
+
+ ---------------------
+ -- Extract_Version --
+ ---------------------
+
+ function Extract_Version (S : String) return ALI_Version is
+ pragma Assert (S'First = 1);
+
+ function Int_Value (Img : String) return Int;
+ -- Using Int'Value leads to complications in
+ -- building the binder, so DIY.
+
+ ---------------
+ -- Int_Value --
+ ---------------
+
+ function Int_Value (Img : String) return Int is
+ Result : Nat := 0;
+ begin
+ if Img'Length in 1 .. 9
+ and then (for all C of Img => C in '0' .. '9')
+ then
+ for C of Img loop
+ Result := (10 * Result) +
+ (Character'Pos (C) - Character'Pos ('0'));
+ end loop;
+ return Result;
+ else
+ return -1;
+ end if;
+ end Int_Value;
+
+ begin
+ if S'Length > Prefix'Length
+ and then S (1 .. Prefix'Length) = Prefix
+ then
+ declare
+ Suffix : constant String := Remove_Prefix (S);
+ Dot_Found : Boolean := False;
+ Primary, Secondary : Int;
+ begin
+ for Dot_Index in Suffix'Range loop
+ if Suffix (Dot_Index) = '.' then
+ Dot_Found := True;
+ Primary :=
+ Int_Value (Suffix (Suffix'First
+ .. Dot_Index - 1));
+ Secondary :=
+ Int_Value (Suffix (Dot_Index + 1
+ .. Suffix'Last));
+ exit;
+ end if;
+ end loop;
+
+ if not Dot_Found then
+ Primary := Int_Value (Suffix);
+ Secondary := 0;
+ end if;
+
+ if (Primary /= -1) and (Secondary /= -1) then
+ return (Primary => Primary,
+ Secondary => Secondary);
+ end if;
+ end;
+ end if;
+ return No_Version;
+ end Extract_Version;
+
+ -- Local constants
+
+ V1_Text : constant String :=
+ ALIs.Table (A).Ver (1 .. ALIs.Table (A).Ver_Len);
+ V2_Text : constant String :=
+ ALIs.Table (ALIs.First).Ver (1 .. VL);
+ V1 : constant ALI_Version := Extract_Version (V1_Text);
+ V2 : constant ALI_Version := Extract_Version (V2_Text);
+
+ Include_Version_Numbers_In_Message : constant Boolean :=
+ (V1 /= V2) and (V1 /= No_Version) and (V2 /= No_Version);
+ begin
+ Error_Msg_File_1 := ALIs.Table (A).Sfile;
+ Error_Msg_File_2 := ALIs.Table (ALIs.First).Sfile;
+
+ if Include_Version_Numbers_In_Message then
+ if V1.Secondary = V2.Secondary then
+ -- Excluding equal secondary values from error
+ -- message text matters for generating reproducible
+ -- regression test outputs.
+
+ Error_Msg_Nat_1 := V1.Primary;
+ Error_Msg_Nat_2 := V2.Primary;
+ Consistency_Error_Msg
+ ("{ and { compiled with different GNAT versions"
+ & ", v# and v#");
+ else
+ Consistency_Error_Msg
+ ("{ and { compiled with different GNAT versions"
+ & ", v"
+ & Remove_Prefix (V1_Text)
+ & " and v"
+ & Remove_Prefix (V2_Text));
+ end if;
+ else
+ Consistency_Error_Msg
+ ("{ and { compiled with different GNAT versions");
+ end if;
+ end;
end if;
end loop;
end Check_Versions;
diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb
index 8f5c0b0..a58a495 100644
--- a/gcc/ada/checks.adb
+++ b/gcc/ada/checks.adb
@@ -3552,9 +3552,12 @@ package body Checks is
-- Apply_Subscript_Validity_Checks --
-------------------------------------
- procedure Apply_Subscript_Validity_Checks (Expr : Node_Id) is
+ procedure Apply_Subscript_Validity_Checks
+ (Expr : Node_Id;
+ No_Check_Needed : Dimension_Set := Empty_Dimension_Set) is
Sub : Node_Id;
+ Dimension : Pos := 1;
begin
pragma Assert (Nkind (Expr) = N_Indexed_Component);
@@ -3568,11 +3571,16 @@ package body Checks is
-- for the subscript, and that convert will do the necessary validity
-- check.
- Ensure_Valid (Sub, Holes_OK => True);
+ if (No_Check_Needed = Empty_Dimension_Set)
+ or else not No_Check_Needed.Elements (Dimension)
+ then
+ Ensure_Valid (Sub, Holes_OK => True);
+ end if;
-- Move to next subscript
Next (Sub);
+ Dimension := Dimension + 1;
end loop;
end Apply_Subscript_Validity_Checks;
@@ -7233,7 +7241,10 @@ package body Checks is
-- Generate_Index_Checks --
---------------------------
- procedure Generate_Index_Checks (N : Node_Id) is
+ procedure Generate_Index_Checks
+ (N : Node_Id;
+ Checks_Generated : out Dimension_Set)
+ is
function Entity_Of_Prefix return Entity_Id;
-- Returns the entity of the prefix of N (or Empty if not found)
@@ -7268,6 +7279,8 @@ package body Checks is
-- Start of processing for Generate_Index_Checks
begin
+ Checks_Generated.Elements := (others => False);
+
-- Ignore call if the prefix is not an array since we have a serious
-- error in the sources. Ignore it also if index checks are suppressed
-- for array object or type.
@@ -7330,6 +7343,8 @@ package body Checks is
Prefix => New_Occurrence_Of (Etype (A), Loc),
Attribute_Name => Name_Range)),
Reason => CE_Index_Check_Failed));
+
+ Checks_Generated.Elements (1) := True;
end if;
-- General case
@@ -7416,6 +7431,8 @@ package body Checks is
Duplicate_Subexpr_Move_Checks (Sub)),
Right_Opnd => Range_N),
Reason => CE_Index_Check_Failed));
+
+ Checks_Generated.Elements (Ind) := True;
end if;
Next_Index (A_Idx);
@@ -10383,7 +10400,7 @@ package body Checks is
Exptyp : Entity_Id;
Cond : Node_Id := Empty;
Do_Access : Boolean := False;
- Wnode : Node_Id := Warn_Node;
+ Wnode : Node_Id := Warn_Node;
Ret_Result : Check_Result := (Empty, Empty);
Num_Checks : Natural := 0;
diff --git a/gcc/ada/checks.ads b/gcc/ada/checks.ads
index 3b97bd0..6df752f 100644
--- a/gcc/ada/checks.ads
+++ b/gcc/ada/checks.ads
@@ -44,6 +44,14 @@ with Urealp; use Urealp;
package Checks is
+ type Bit_Vector is array (Pos range <>) of Boolean;
+ type Dimension_Set (Dimensions : Nat) is
+ record
+ Elements : Bit_Vector (1 .. Dimensions);
+ end record;
+ Empty_Dimension_Set : constant Dimension_Set
+ := (Dimensions => 0, Elements => (others => <>));
+
procedure Initialize;
-- Called for each new main source program, to initialize internal
-- variables used in the package body of the Checks unit.
@@ -721,11 +729,16 @@ package Checks is
-- Do_Range_Check flag, and if it is set, this routine is called, which
-- turns the flag off in code-generation mode.
- procedure Generate_Index_Checks (N : Node_Id);
+ procedure Generate_Index_Checks
+ (N : Node_Id;
+ Checks_Generated : out Dimension_Set);
-- This procedure is called to generate index checks on the subscripts for
-- the indexed component node N. Each subscript expression is examined, and
-- if the Do_Range_Check flag is set, an appropriate index check is
-- generated and the flag is reset.
+ -- The out-mode parameter Checks_Generated indicates the dimensions for
+ -- which checks were generated. Checks_Generated.Dimensions must match
+ -- the number of dimensions of the array type.
-- Similarly, we set the flag Do_Discriminant_Check in the semantic
-- analysis to indicate that a discriminant check is required for selected
@@ -858,10 +871,14 @@ package Checks is
-- The following procedures are used in handling validity checking
- procedure Apply_Subscript_Validity_Checks (Expr : Node_Id);
+ procedure Apply_Subscript_Validity_Checks
+ (Expr : Node_Id;
+ No_Check_Needed : Dimension_Set := Empty_Dimension_Set);
-- Expr is the node for an indexed component. If validity checking and
- -- range checking are enabled, all subscripts for this indexed component
- -- are checked for validity.
+ -- range checking are enabled, each subscript for this indexed component
+ -- whose dimension does not belong to the No_Check_Needed set is checked
+ -- for validity. No_Check_Needed.Dimensions must match the number of
+ -- dimensions of the array type or be zero.
procedure Check_Valid_Lvalue_Subscripts (Expr : Node_Id);
-- Expr is a lvalue, i.e. an expression representing the target of an
diff --git a/gcc/ada/clean.adb b/gcc/ada/clean.adb
index 03ca7a4..830a994 100644
--- a/gcc/ada/clean.adb
+++ b/gcc/ada/clean.adb
@@ -217,7 +217,7 @@ package body Clean is
if Text /= null then
The_ALI :=
- Scan_ALI (Lib_File, Text, Ignore_ED => False, Err => True);
+ Scan_ALI (Lib_File, Text, Err => True);
Free (Text);
-- If no error was produced while loading this ALI file,
diff --git a/gcc/ada/comperr.adb b/gcc/ada/comperr.adb
index 064fae0..e009c58 100644
--- a/gcc/ada/comperr.adb
+++ b/gcc/ada/comperr.adb
@@ -478,6 +478,7 @@ package body Comperr is
when N_Package_Declaration
| N_Subprogram_Body
| N_Subprogram_Declaration
+ | N_Subprogram_Renaming_Declaration
=>
Unit_Name := Defining_Unit_Name (Specification (Main));
@@ -489,10 +490,10 @@ package body Comperr is
=>
Unit_Name := Defining_Unit_Name (Main);
- -- No SCIL file generated for generic package declarations
+ -- No SCIL file generated for generic unit declarations
- when N_Generic_Package_Declaration
- | N_Generic_Package_Renaming_Declaration
+ when N_Generic_Declaration
+ | N_Generic_Renaming_Declaration
=>
return;
diff --git a/gcc/ada/contracts.adb b/gcc/ada/contracts.adb
index e37e092..2726486 100644
--- a/gcc/ada/contracts.adb
+++ b/gcc/ada/contracts.adb
@@ -47,6 +47,8 @@ with Sem_Ch12; use Sem_Ch12;
with Sem_Ch13; use Sem_Ch13;
with Sem_Disp; use Sem_Disp;
with Sem_Prag; use Sem_Prag;
+with Sem_Res; use Sem_Res;
+with Sem_Type; use Sem_Type;
with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
with Sinfo.Nodes; use Sinfo.Nodes;
@@ -66,6 +68,16 @@ package body Contracts is
--
-- Part_Of
+ procedure Check_Class_Condition
+ (Cond : Node_Id;
+ Subp : Entity_Id;
+ Par_Subp : Entity_Id;
+ Is_Precondition : Boolean);
+ -- Perform checking of class-wide pre/postcondition Cond inherited by Subp
+ -- from Par_Subp. Is_Precondition enables check specific for preconditions.
+ -- In SPARK_Mode, an inherited operation that is not overridden but has
+ -- inherited modified conditions pre/postconditions is illegal.
+
procedure Check_Type_Or_Object_External_Properties
(Type_Or_Obj_Id : Entity_Id);
-- Perform checking of external properties pragmas that is common to both
@@ -77,6 +89,12 @@ package body Contracts is
-- well as Contract_Cases, Subprogram_Variant, invariants and predicates.
-- Body_Id denotes the entity of the subprogram body.
+ procedure Set_Class_Condition
+ (Kind : Condition_Kind;
+ Subp : Entity_Id;
+ Cond : Node_Id);
+ -- Set the class-wide Kind condition of Subp
+
-----------------------
-- Add_Contract_Item --
-----------------------
@@ -386,23 +404,7 @@ package body Contracts is
| N_Generic_Subprogram_Declaration
| N_Subprogram_Declaration
then
- declare
- Subp_Id : constant Entity_Id := Defining_Entity (Decl);
-
- begin
- Analyze_Entry_Or_Subprogram_Contract (Subp_Id);
-
- -- If analysis of a class-wide pre/postcondition indicates
- -- that a class-wide clone is needed, analyze its declaration
- -- now. Its body is created when the body of the original
- -- operation is analyzed (and rewritten).
-
- if Is_Subprogram (Subp_Id)
- and then Present (Class_Wide_Clone (Subp_Id))
- then
- Analyze (Unit_Declaration_Node (Class_Wide_Clone (Subp_Id)));
- end if;
- end;
+ Analyze_Entry_Or_Subprogram_Contract (Defining_Entity (Decl));
-- Entry or subprogram bodies
@@ -1491,6 +1493,141 @@ package body Contracts is
(Type_Or_Obj_Id => Type_Id);
end Analyze_Type_Contract;
+ ---------------------------
+ -- Check_Class_Condition --
+ ---------------------------
+
+ procedure Check_Class_Condition
+ (Cond : Node_Id;
+ Subp : Entity_Id;
+ Par_Subp : Entity_Id;
+ Is_Precondition : Boolean)
+ is
+ function Check_Entity (N : Node_Id) return Traverse_Result;
+ -- Check reference to formal of inherited operation or to primitive
+ -- operation of root type.
+
+ ------------------
+ -- Check_Entity --
+ ------------------
+
+ function Check_Entity (N : Node_Id) return Traverse_Result is
+ New_E : Entity_Id;
+ Orig_E : Entity_Id;
+
+ begin
+ if Nkind (N) = N_Identifier
+ and then Present (Entity (N))
+ and then
+ (Is_Formal (Entity (N)) or else Is_Subprogram (Entity (N)))
+ and then
+ (Nkind (Parent (N)) /= N_Attribute_Reference
+ or else Attribute_Name (Parent (N)) /= Name_Class)
+ then
+ -- These checks do not apply to dispatching calls within the
+ -- condition, but only to calls whose static tag is that of
+ -- the parent type.
+
+ if Is_Subprogram (Entity (N))
+ and then Nkind (Parent (N)) = N_Function_Call
+ and then Present (Controlling_Argument (Parent (N)))
+ then
+ return OK;
+ end if;
+
+ -- Determine whether entity has a renaming
+
+ Orig_E := Entity (N);
+ New_E := Get_Mapped_Entity (Orig_E);
+
+ if Present (New_E) then
+
+ -- AI12-0166: A precondition for a protected operation
+ -- cannot include an internal call to a protected function
+ -- of the type. In the case of an inherited condition for an
+ -- overriding operation, both the operation and the function
+ -- are given by primitive wrappers.
+
+ if Is_Precondition
+ and then Ekind (New_E) = E_Function
+ and then Is_Primitive_Wrapper (New_E)
+ and then Is_Primitive_Wrapper (Subp)
+ and then Scope (Subp) = Scope (New_E)
+ then
+ Error_Msg_Node_2 := Wrapped_Entity (Subp);
+ Error_Msg_NE
+ ("internal call to& cannot appear in inherited "
+ & "precondition of protected operation&",
+ Subp, Wrapped_Entity (New_E));
+ end if;
+ end if;
+
+ -- Check that there are no calls left to abstract operations if
+ -- the current subprogram is not abstract.
+
+ if Present (New_E)
+ and then Nkind (Parent (N)) = N_Function_Call
+ and then N = Name (Parent (N))
+ then
+ if not Is_Abstract_Subprogram (Subp)
+ and then Is_Abstract_Subprogram (New_E)
+ then
+ Error_Msg_Sloc := Sloc (Current_Scope);
+ Error_Msg_Node_2 := Subp;
+
+ if Comes_From_Source (Subp) then
+ Error_Msg_NE
+ ("cannot call abstract subprogram & in inherited "
+ & "condition for&#", Subp, New_E);
+ else
+ Error_Msg_NE
+ ("cannot call abstract subprogram & in inherited "
+ & "condition for inherited&#", Subp, New_E);
+ end if;
+
+ -- In SPARK mode, report error on inherited condition for an
+ -- inherited operation if it contains a call to an overriding
+ -- operation, because this implies that the pre/postconditions
+ -- of the inherited operation have changed silently.
+
+ elsif SPARK_Mode = On
+ and then Warn_On_Suspicious_Contract
+ and then Present (Alias (Subp))
+ and then Present (New_E)
+ and then Comes_From_Source (New_E)
+ then
+ Error_Msg_N
+ ("cannot modify inherited condition (SPARK RM 6.1.1(1))",
+ Parent (Subp));
+ Error_Msg_Sloc := Sloc (New_E);
+ Error_Msg_Node_2 := Subp;
+ Error_Msg_NE
+ ("\overriding of&# forces overriding of&",
+ Parent (Subp), New_E);
+ end if;
+ end if;
+ end if;
+
+ return OK;
+ end Check_Entity;
+
+ procedure Check_Condition_Entities is
+ new Traverse_Proc (Check_Entity);
+
+ -- Start of processing for Check_Class_Condition
+
+ begin
+ -- No check required if the subprograms match
+
+ if Par_Subp = Subp then
+ return;
+ end if;
+
+ Update_Primitives_Mapping (Par_Subp, Subp);
+ Map_Formals (Par_Subp, Subp);
+ Check_Condition_Entities (Cond);
+ end Check_Class_Condition;
+
-----------------------------
-- Create_Generic_Contract --
-----------------------------
@@ -1900,7 +2037,7 @@ package body Contracts is
procedure Add_Stable_Property_Contracts
(Subp_Id : Entity_Id; Class_Present : Boolean)
is
- Loc : constant Source_Ptr := Sloc (Subp_Id);
+ Loc : constant Source_Ptr := Sloc (Subp_Id);
procedure Insert_Stable_Property_Check
(Formal : Entity_Id; Property_Function : Entity_Id);
@@ -2552,13 +2689,38 @@ package body Contracts is
---------------------------------
procedure Process_Spec_Postconditions is
- Subps : constant Subprogram_List :=
- Inherited_Subprograms (Spec_Id);
+ Subps : constant Subprogram_List :=
+ Inherited_Subprograms (Spec_Id);
+ Seen : Subprogram_List (Subps'Range) := (others => Empty);
+
+ function Seen_Subp (Subp_Id : Entity_Id) return Boolean;
+ -- Return True if the contract of subprogram Subp_Id has been
+ -- processed.
+
+ ---------------
+ -- Seen_Subp --
+ ---------------
+
+ function Seen_Subp (Subp_Id : Entity_Id) return Boolean is
+ begin
+ for Index in Seen'Range loop
+ if Seen (Index) = Subp_Id then
+ return True;
+ end if;
+ end loop;
+
+ return False;
+ end Seen_Subp;
+
+ -- Local variables
+
Item : Node_Id;
Items : Node_Id;
Prag : Node_Id;
Subp_Id : Entity_Id;
+ -- Start of processing for Process_Spec_Postconditions
+
begin
-- Process the contract
@@ -2589,7 +2751,7 @@ package body Contracts is
Subp_Id := Ultimate_Alias (Subp_Id);
end if;
- -- Wrappers of class-wide pre/post conditions reference the
+ -- Wrappers of class-wide pre/postconditions reference the
-- parent primitive that has the inherited contract.
if Is_Wrapper (Subp_Id)
@@ -2600,7 +2762,9 @@ package body Contracts is
Items := Contract (Subp_Id);
- if Present (Items) then
+ if not Seen_Subp (Subp_Id) and then Present (Items) then
+ Seen (Index) := Subp_Id;
+
Prag := Pre_Post_Conditions (Items);
while Present (Prag) loop
if Pragma_Name (Prag) = Name_Postcondition
@@ -2657,10 +2821,6 @@ package body Contracts is
---------------------------
procedure Process_Preconditions is
- Class_Pre : Node_Id := Empty;
- -- The sole [inherited] class-wide precondition pragma that applies
- -- to the subprogram.
-
Insert_Node : Node_Id := Empty;
-- The insertion node after which all pragma Check equivalents are
-- inserted.
@@ -2669,21 +2829,12 @@ package body Contracts is
-- Determine whether arbitrary declaration Decl denotes a renaming of
-- a discriminant or protection field _object.
- procedure Merge_Preconditions (From : Node_Id; Into : Node_Id);
- -- Merge two class-wide preconditions by "or else"-ing them. The
- -- changes are accumulated in parameter Into. Update the error
- -- message of Into.
-
procedure Prepend_To_Decls (Item : Node_Id);
-- Prepend a single item to the declarations of the subprogram body
- procedure Prepend_To_Decls_Or_Save (Prag : Node_Id);
- -- Save a class-wide precondition into Class_Pre, or prepend a normal
- -- precondition to the declarations of the body and analyze it.
-
- procedure Process_Inherited_Preconditions;
- -- Collect all inherited class-wide preconditions and merge them into
- -- one big precondition to be evaluated as pragma Check.
+ procedure Prepend_Pragma_To_Decls (Prag : Node_Id);
+ -- Prepend a normal precondition to the declarations of the body and
+ -- analyze it.
procedure Process_Preconditions_For (Subp_Id : Entity_Id);
-- Collect all preconditions of subprogram Subp_Id and prepend their
@@ -2737,78 +2888,6 @@ package body Contracts is
return False;
end Is_Prologue_Renaming;
- -------------------------
- -- Merge_Preconditions --
- -------------------------
-
- procedure Merge_Preconditions (From : Node_Id; Into : Node_Id) is
- function Expression_Arg (Prag : Node_Id) return Node_Id;
- -- Return the boolean expression argument of a precondition while
- -- updating its parentheses count for the subsequent merge.
-
- function Message_Arg (Prag : Node_Id) return Node_Id;
- -- Return the message argument of a precondition
-
- --------------------
- -- Expression_Arg --
- --------------------
-
- function Expression_Arg (Prag : Node_Id) return Node_Id is
- Args : constant List_Id := Pragma_Argument_Associations (Prag);
- Arg : constant Node_Id := Get_Pragma_Arg (Next (First (Args)));
-
- begin
- if Paren_Count (Arg) = 0 then
- Set_Paren_Count (Arg, 1);
- end if;
-
- return Arg;
- end Expression_Arg;
-
- -----------------
- -- Message_Arg --
- -----------------
-
- function Message_Arg (Prag : Node_Id) return Node_Id is
- Args : constant List_Id := Pragma_Argument_Associations (Prag);
- begin
- return Get_Pragma_Arg (Last (Args));
- end Message_Arg;
-
- -- Local variables
-
- From_Expr : constant Node_Id := Expression_Arg (From);
- From_Msg : constant Node_Id := Message_Arg (From);
- Into_Expr : constant Node_Id := Expression_Arg (Into);
- Into_Msg : constant Node_Id := Message_Arg (Into);
- Loc : constant Source_Ptr := Sloc (Into);
-
- -- Start of processing for Merge_Preconditions
-
- begin
- -- Merge the two preconditions by "or else"-ing them
-
- Rewrite (Into_Expr,
- Make_Or_Else (Loc,
- Right_Opnd => Relocate_Node (Into_Expr),
- Left_Opnd => From_Expr));
-
- -- Merge the two error messages to produce a single message of the
- -- form:
-
- -- failed precondition from ...
- -- also failed inherited precondition from ...
-
- if not Exception_Locations_Suppressed then
- Start_String (Strval (Into_Msg));
- Store_String_Char (ASCII.LF);
- Store_String_Chars (" also ");
- Store_String_Chars (Strval (From_Msg));
-
- Set_Strval (Into_Msg, End_String);
- end if;
- end Merge_Preconditions;
-
----------------------
-- Prepend_To_Decls --
----------------------
@@ -2829,28 +2908,27 @@ package body Contracts is
Prepend_To (Decls, Item);
end Prepend_To_Decls;
- ------------------------------
- -- Prepend_To_Decls_Or_Save --
- ------------------------------
+ -----------------------------
+ -- Prepend_Pragma_To_Decls --
+ -----------------------------
- procedure Prepend_To_Decls_Or_Save (Prag : Node_Id) is
+ procedure Prepend_Pragma_To_Decls (Prag : Node_Id) is
Check_Prag : Node_Id;
begin
- Check_Prag := Build_Pragma_Check_Equivalent (Prag);
-
- -- Save the sole class-wide precondition (if any) for the next
- -- step, where it will be merged with inherited preconditions.
+ -- Skip the sole class-wide precondition (if any) since it is
+ -- processed by Merge_Class_Conditions.
if Class_Present (Prag) then
- pragma Assert (No (Class_Pre));
- Class_Pre := Check_Prag;
+ null;
-- Accumulate the corresponding Check pragmas at the top of the
-- declarations. Prepending the items ensures that they will be
-- evaluated in their original order.
else
+ Check_Prag := Build_Pragma_Check_Equivalent (Prag);
+
if Present (Insert_Node) then
Insert_After (Insert_Node, Check_Prag);
else
@@ -2859,87 +2937,7 @@ package body Contracts is
Analyze (Check_Prag);
end if;
- end Prepend_To_Decls_Or_Save;
-
- -------------------------------------
- -- Process_Inherited_Preconditions --
- -------------------------------------
-
- procedure Process_Inherited_Preconditions is
- Subps : constant Subprogram_List :=
- Inherited_Subprograms (Spec_Id);
-
- Item : Node_Id;
- Items : Node_Id;
- Prag : Node_Id;
- Subp_Id : Entity_Id;
-
- begin
- -- Process the contracts of all inherited subprograms, looking for
- -- class-wide preconditions.
-
- for Index in Subps'Range loop
- Subp_Id := Subps (Index);
-
- if Present (Alias (Subp_Id)) then
- Subp_Id := Ultimate_Alias (Subp_Id);
- end if;
-
- -- Wrappers of class-wide pre/post conditions reference the
- -- parent primitive that has the inherited contract.
-
- if Is_Wrapper (Subp_Id)
- and then Present (LSP_Subprogram (Subp_Id))
- then
- Subp_Id := LSP_Subprogram (Subp_Id);
- end if;
-
- Items := Contract (Subp_Id);
-
- if Present (Items) then
- Prag := Pre_Post_Conditions (Items);
- while Present (Prag) loop
- if Pragma_Name (Prag) = Name_Precondition
- and then Class_Present (Prag)
- then
- Item :=
- Build_Pragma_Check_Equivalent
- (Prag => Prag,
- Subp_Id => Spec_Id,
- Inher_Id => Subp_Id);
-
- -- The pragma Check equivalent of the class-wide
- -- precondition is still created even though the
- -- pragma may be ignored because the equivalent
- -- performs semantic checks.
-
- if Is_Checked (Prag) then
-
- -- The spec of an inherited subprogram already
- -- yielded a class-wide precondition. Merge the
- -- existing precondition with the current one
- -- using "or else".
-
- if Present (Class_Pre) then
- Merge_Preconditions (Item, Class_Pre);
- else
- Class_Pre := Item;
- end if;
- end if;
- end if;
-
- Prag := Next_Pragma (Prag);
- end loop;
- end if;
- end loop;
-
- -- Add the merged class-wide preconditions
-
- if Present (Class_Pre) then
- Prepend_To_Decls (Class_Pre);
- Analyze (Class_Pre);
- end if;
- end Process_Inherited_Preconditions;
+ end Prepend_Pragma_To_Decls;
-------------------------------
-- Process_Preconditions_For --
@@ -2983,7 +2981,7 @@ package body Contracts is
N => Body_Decl);
end if;
- Prepend_To_Decls_Or_Save (Prag);
+ Prepend_Pragma_To_Decls (Prag);
end if;
Prag := Next_Pragma (Prag);
@@ -3008,7 +3006,7 @@ package body Contracts is
if Pragma_Name (Decl) = Name_Precondition
and then Is_Checked (Decl)
then
- Prepend_To_Decls_Or_Save (Decl);
+ Prepend_Pragma_To_Decls (Decl);
end if;
-- Skip internally generated code
@@ -3073,22 +3071,21 @@ package body Contracts is
Next (Decl);
end loop;
- end if;
- -- The processing of preconditions is done in reverse order (body
- -- first), because each pragma Check equivalent is inserted at the
- -- top of the declarations. This ensures that the final order is
- -- consistent with following diagram:
+ -- The processing of preconditions is done in reverse order (body
+ -- first), because each pragma Check equivalent is inserted at the
+ -- top of the declarations. This ensures that the final order is
+ -- consistent with following diagram:
- -- <inherited preconditions>
- -- <preconditions from spec>
- -- <preconditions from body>
+ -- <inherited preconditions>
+ -- <preconditions from spec>
+ -- <preconditions from body>
- Process_Preconditions_For (Body_Id);
+ Process_Preconditions_For (Body_Id);
+ end if;
if Present (Spec_Id) then
Process_Preconditions_For (Spec_Id);
- Process_Inherited_Preconditions;
end if;
end Process_Preconditions;
@@ -3139,6 +3136,12 @@ package body Contracts is
elsif Is_Ignored_Ghost_Entity (Subp_Id) then
return;
+ -- No action needed for helpers and indirect-call wrapper built to
+ -- support class-wide preconditions.
+
+ elsif Present (Class_Preconditions_Subprogram (Subp_Id)) then
+ return;
+
-- Do not re-expand the same contract. This scenario occurs when a
-- construct is rewritten into something else during its analysis
-- (expression functions for instance).
@@ -3440,7 +3443,7 @@ package body Contracts is
-- Get_Postcond_Enabled --
--------------------------
- function Get_Postcond_Enabled (Subp : Entity_Id) return Node_Id is
+ function Get_Postcond_Enabled (Subp : Entity_Id) return Entity_Id is
Decl : Node_Id;
begin
Decl :=
@@ -3465,7 +3468,7 @@ package body Contracts is
------------------------------------
function Get_Result_Object_For_Postcond
- (Subp : Entity_Id) return Node_Id
+ (Subp : Entity_Id) return Entity_Id
is
Decl : Node_Id;
begin
@@ -3490,7 +3493,7 @@ package body Contracts is
-- Get_Return_Success_For_Postcond --
-------------------------------------
- function Get_Return_Success_For_Postcond (Subp : Entity_Id) return Node_Id
+ function Get_Return_Success_For_Postcond (Subp : Entity_Id) return Entity_Id
is
Decl : Node_Id;
begin
@@ -3605,6 +3608,1112 @@ package body Contracts is
end if;
end Instantiate_Subprogram_Contract;
+ -----------------------------------
+ -- Make_Class_Precondition_Subps --
+ -----------------------------------
+
+ procedure Make_Class_Precondition_Subps
+ (Subp_Id : Entity_Id;
+ Late_Overriding : Boolean := False)
+ is
+ Loc : constant Source_Ptr := Sloc (Subp_Id);
+ Tagged_Type : constant Entity_Id := Find_Dispatching_Type (Subp_Id);
+
+ procedure Add_Indirect_Call_Wrapper;
+ -- Build the indirect-call wrapper and append it to the freezing actions
+ -- of Tagged_Type.
+
+ procedure Add_Call_Helper
+ (Helper_Id : Entity_Id;
+ Is_Dynamic : Boolean);
+ -- Factorizes code for building a call helper with the given identifier
+ -- and append it to the freezing actions of Tagged_Type. Is_Dynamic
+ -- controls building the static or dynamic version of the helper.
+
+ -------------------------------
+ -- Add_Indirect_Call_Wrapper --
+ -------------------------------
+
+ procedure Add_Indirect_Call_Wrapper is
+
+ function Build_ICW_Body return Node_Id;
+ -- Build the body of the indirect call wrapper
+
+ function Build_ICW_Decl return Node_Id;
+ -- Build the declaration of the indirect call wrapper
+
+ --------------------
+ -- Build_ICW_Body --
+ --------------------
+
+ function Build_ICW_Body return Node_Id is
+ ICW_Id : constant Entity_Id := Indirect_Call_Wrapper (Subp_Id);
+ Spec : constant Node_Id := Parent (ICW_Id);
+ Body_Spec : Node_Id;
+ Call : Node_Id;
+ ICW_Body : Node_Id;
+
+ begin
+ Body_Spec := Copy_Subprogram_Spec (Spec);
+
+ -- Build call to wrapped subprogram
+
+ declare
+ Actuals : constant List_Id := Empty_List;
+ Formal_Spec : Entity_Id :=
+ First (Parameter_Specifications (Spec));
+ begin
+ -- Build parameter association & call
+
+ while Present (Formal_Spec) loop
+ Append_To (Actuals,
+ New_Occurrence_Of
+ (Defining_Identifier (Formal_Spec), Loc));
+ Next (Formal_Spec);
+ end loop;
+
+ if Ekind (ICW_Id) = E_Procedure then
+ Call :=
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Occurrence_Of (Subp_Id, Loc),
+ Parameter_Associations => Actuals);
+ else
+ Call :=
+ Make_Simple_Return_Statement (Loc,
+ Expression =>
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Subp_Id, Loc),
+ Parameter_Associations => Actuals));
+ end if;
+ end;
+
+ ICW_Body :=
+ Make_Subprogram_Body (Loc,
+ Specification => Body_Spec,
+ Declarations => New_List,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Call)));
+
+ -- The new operation is internal and overriding indicators do not
+ -- apply.
+
+ Set_Must_Override (Body_Spec, False);
+
+ return ICW_Body;
+ end Build_ICW_Body;
+
+ --------------------
+ -- Build_ICW_Decl --
+ --------------------
+
+ function Build_ICW_Decl return Node_Id is
+ ICW_Id : constant Entity_Id :=
+ Make_Defining_Identifier (Loc,
+ New_External_Name (Chars (Subp_Id),
+ Suffix => "ICW",
+ Suffix_Index => Source_Offset (Loc)));
+ Decl : Node_Id;
+ Spec : Node_Id;
+
+ begin
+ Spec := Copy_Subprogram_Spec (Parent (Subp_Id));
+ Set_Must_Override (Spec, False);
+ Set_Must_Not_Override (Spec, False);
+ Set_Defining_Unit_Name (Spec, ICW_Id);
+ Mutate_Ekind (ICW_Id, Ekind (Subp_Id));
+ Set_Is_Public (ICW_Id);
+
+ -- The indirect call wrapper is commonly used for indirect calls
+ -- but inlined for direct calls performed from the DTW.
+
+ Set_Is_Inlined (ICW_Id);
+
+ if Nkind (Spec) = N_Procedure_Specification then
+ Set_Null_Present (Spec, False);
+ end if;
+
+ Decl := Make_Subprogram_Declaration (Loc, Spec);
+
+ -- Link original subprogram to indirect wrapper and vice versa
+
+ Set_Indirect_Call_Wrapper (Subp_Id, ICW_Id);
+ Set_Class_Preconditions_Subprogram (ICW_Id, Subp_Id);
+
+ -- Inherit debug info flag to allow debugging the wrapper
+
+ if Needs_Debug_Info (Subp_Id) then
+ Set_Debug_Info_Needed (ICW_Id);
+ end if;
+
+ return Decl;
+ end Build_ICW_Decl;
+
+ -- Local Variables
+
+ ICW_Body : Node_Id;
+ ICW_Decl : Node_Id;
+
+ -- Start of processing for Add_Indirect_Call_Wrapper
+
+ begin
+ pragma Assert (No (Indirect_Call_Wrapper (Subp_Id)));
+
+ ICW_Decl := Build_ICW_Decl;
+
+ Ensure_Freeze_Node (Tagged_Type);
+ Append_Freeze_Action (Tagged_Type, ICW_Decl);
+ Analyze (ICW_Decl);
+
+ ICW_Body := Build_ICW_Body;
+ Append_Freeze_Action (Tagged_Type, ICW_Body);
+
+ -- We cannot defer the analysis of this ICW wrapper when it is
+ -- built as a consequence of building its partner DTW wrapper
+ -- at the freezing point of the tagged type.
+
+ if Is_Dispatch_Table_Wrapper (Subp_Id) then
+ Analyze (ICW_Body);
+ end if;
+ end Add_Indirect_Call_Wrapper;
+
+ ---------------------
+ -- Add_Call_Helper --
+ ---------------------
+
+ procedure Add_Call_Helper
+ (Helper_Id : Entity_Id;
+ Is_Dynamic : Boolean)
+ is
+ function Build_Call_Helper_Body return Node_Id;
+ -- Build the body of a call helper
+
+ function Build_Call_Helper_Decl return Node_Id;
+ -- Build the declaration of a call helper
+
+ function Build_Call_Helper_Spec (Spec_Id : Entity_Id) return Node_Id;
+ -- Build the specification of the helper
+
+ ----------------------------
+ -- Build_Call_Helper_Body --
+ ----------------------------
+
+ function Build_Call_Helper_Body return Node_Id is
+
+ function Copy_And_Update_References
+ (Expr : Node_Id) return Node_Id;
+ -- Copy Expr updating references to formals of Helper_Id; update
+ -- also references to loop identifiers of quantified expressions.
+
+ --------------------------------
+ -- Copy_And_Update_References --
+ --------------------------------
+
+ function Copy_And_Update_References
+ (Expr : Node_Id) return Node_Id
+ is
+ Assoc_List : constant Elist_Id := New_Elmt_List;
+
+ procedure Map_Quantified_Expression_Loop_Identifiers;
+ -- Traverse Expr and append to Assoc_List the mapping of loop
+ -- identifers of quantified expressions with its new copy.
+
+ ------------------------------------------------
+ -- Map_Quantified_Expression_Loop_Identifiers --
+ ------------------------------------------------
+
+ procedure Map_Quantified_Expression_Loop_Identifiers is
+ function Map_Loop_Param (N : Node_Id) return Traverse_Result;
+ -- Append to Assoc_List the mapping of loop identifers of
+ -- quantified expressions with its new copy.
+
+ --------------------
+ -- Map_Loop_Param --
+ --------------------
+
+ function Map_Loop_Param (N : Node_Id) return Traverse_Result
+ is
+ begin
+ if Nkind (N) = N_Loop_Parameter_Specification
+ and then Nkind (Parent (N)) = N_Quantified_Expression
+ then
+ declare
+ Def_Id : constant Entity_Id :=
+ Defining_Identifier (N);
+ begin
+ Append_Elmt (Def_Id, Assoc_List);
+ Append_Elmt (New_Copy (Def_Id), Assoc_List);
+ end;
+ end if;
+
+ return OK;
+ end Map_Loop_Param;
+
+ procedure Map_Quantified_Expressions is
+ new Traverse_Proc (Map_Loop_Param);
+
+ begin
+ Map_Quantified_Expressions (Expr);
+ end Map_Quantified_Expression_Loop_Identifiers;
+
+ -- Local variables
+
+ Subp_Formal_Id : Entity_Id := First_Formal (Subp_Id);
+ Helper_Formal_Id : Entity_Id := First_Formal (Helper_Id);
+
+ -- Start of processing for Copy_And_Update_References
+
+ begin
+ while Present (Subp_Formal_Id) loop
+ Append_Elmt (Subp_Formal_Id, Assoc_List);
+ Append_Elmt (Helper_Formal_Id, Assoc_List);
+
+ Next_Formal (Subp_Formal_Id);
+ Next_Formal (Helper_Formal_Id);
+ end loop;
+
+ Map_Quantified_Expression_Loop_Identifiers;
+
+ return New_Copy_Tree (Expr, Map => Assoc_List);
+ end Copy_And_Update_References;
+
+ -- Local variables
+
+ Helper_Decl : constant Node_Id := Parent (Parent (Helper_Id));
+ Body_Id : Entity_Id;
+ Body_Spec : Node_Id;
+ Body_Stmts : Node_Id;
+ Helper_Body : Node_Id;
+ Return_Expr : Node_Id;
+
+ -- Start of processing for Build_Call_Helper_Body
+
+ begin
+ pragma Assert (Analyzed (Unit_Declaration_Node (Helper_Id)));
+ pragma Assert (No (Corresponding_Body (Helper_Decl)));
+
+ Body_Id := Make_Defining_Identifier (Loc, Chars (Helper_Id));
+ Body_Spec := Build_Call_Helper_Spec (Body_Id);
+
+ Set_Corresponding_Body (Helper_Decl, Body_Id);
+ Set_Must_Override (Body_Spec, False);
+
+ if Present (Class_Preconditions (Subp_Id)) then
+ Return_Expr :=
+ Copy_And_Update_References (Class_Preconditions (Subp_Id));
+
+ -- When the subprogram is compiled with assertions disabled the
+ -- helper just returns True; done to avoid reporting errors at
+ -- link time since a unit may be compiled with assertions disabled
+ -- and another (which depends on it) compiled with assertions
+ -- enabled.
+
+ else
+ pragma Assert (Present (Ignored_Class_Preconditions (Subp_Id)));
+ Return_Expr := New_Occurrence_Of (Standard_True, Loc);
+ end if;
+
+ Body_Stmts :=
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (
+ Make_Simple_Return_Statement (Loc, Return_Expr)));
+
+ Helper_Body :=
+ Make_Subprogram_Body (Loc,
+ Specification => Body_Spec,
+ Declarations => New_List,
+ Handled_Statement_Sequence => Body_Stmts);
+
+ return Helper_Body;
+ end Build_Call_Helper_Body;
+
+ ----------------------------
+ -- Build_Call_Helper_Decl --
+ ----------------------------
+
+ function Build_Call_Helper_Decl return Node_Id is
+ Decl : Node_Id;
+ Spec : Node_Id;
+
+ begin
+ Spec := Build_Call_Helper_Spec (Helper_Id);
+ Set_Must_Override (Spec, False);
+ Set_Must_Not_Override (Spec, False);
+ Set_Is_Inlined (Helper_Id);
+ Set_Is_Public (Helper_Id);
+
+ Decl := Make_Subprogram_Declaration (Loc, Spec);
+
+ -- Inherit debug info flag from Subp_Id to Helper_Id to allow
+ -- debugging of the helper subprogram.
+
+ if Needs_Debug_Info (Subp_Id) then
+ Set_Debug_Info_Needed (Helper_Id);
+ end if;
+
+ return Decl;
+ end Build_Call_Helper_Decl;
+
+ ----------------------------
+ -- Build_Call_Helper_Spec --
+ ----------------------------
+
+ function Build_Call_Helper_Spec (Spec_Id : Entity_Id) return Node_Id
+ is
+ Spec : constant Node_Id := Parent (Subp_Id);
+ Def_Id : constant Node_Id := Defining_Unit_Name (Spec);
+ Formal : Entity_Id;
+ Func_Formals : constant List_Id := New_List;
+ P_Spec : constant List_Id := Parameter_Specifications (Spec);
+ Par_Formal : Node_Id;
+ Param : Node_Id;
+ Param_Type : Node_Id;
+
+ begin
+ -- Create a list of formal parameters with the same types as the
+ -- original subprogram but changing the controlling formal.
+
+ Param := First (P_Spec);
+ Formal := First_Formal (Def_Id);
+ while Present (Formal) loop
+ Par_Formal := Parent (Formal);
+
+ if Is_Dynamic and then Is_Controlling_Formal (Formal) then
+ if Nkind (Parameter_Type (Par_Formal))
+ = N_Access_Definition
+ then
+ Param_Type :=
+ Copy_Separate_Tree (Parameter_Type (Par_Formal));
+ Rewrite (Subtype_Mark (Param_Type),
+ Make_Attribute_Reference (Loc,
+ Prefix => Relocate_Node (Subtype_Mark (Param_Type)),
+ Attribute_Name => Name_Class));
+
+ else
+ Param_Type :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Etype (Formal), Loc),
+ Attribute_Name => Name_Class);
+ end if;
+ else
+ Param_Type := New_Occurrence_Of (Etype (Formal), Loc);
+ end if;
+
+ Append_To (Func_Formals,
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, Chars (Formal)),
+ In_Present => In_Present (Par_Formal),
+ Out_Present => Out_Present (Par_Formal),
+ Null_Exclusion_Present => Null_Exclusion_Present
+ (Par_Formal),
+ Parameter_Type => Param_Type));
+
+ Next (Param);
+ Next_Formal (Formal);
+ end loop;
+
+ return
+ Make_Function_Specification (Loc,
+ Defining_Unit_Name => Spec_Id,
+ Parameter_Specifications => Func_Formals,
+ Result_Definition =>
+ New_Occurrence_Of (Standard_Boolean, Loc));
+ end Build_Call_Helper_Spec;
+
+ -- Local variables
+
+ Helper_Body : Node_Id;
+ Helper_Decl : Node_Id;
+
+ -- Start of processing for Add_Call_Helper
+
+ begin
+ Helper_Decl := Build_Call_Helper_Decl;
+ Mutate_Ekind (Helper_Id, Ekind (Subp_Id));
+
+ -- Add the helper to the freezing actions of the tagged type
+
+ Ensure_Freeze_Node (Tagged_Type);
+ Append_Freeze_Action (Tagged_Type, Helper_Decl);
+ Analyze (Helper_Decl);
+
+ Helper_Body := Build_Call_Helper_Body;
+ Append_Freeze_Action (Tagged_Type, Helper_Body);
+
+ -- If this helper is built as part of building the DTW at the
+ -- freezing point of its tagged type then we cannot defer
+ -- its analysis.
+
+ if Late_Overriding then
+ pragma Assert (Is_Dispatch_Table_Wrapper (Subp_Id));
+ Analyze (Helper_Body);
+ end if;
+ end Add_Call_Helper;
+
+ -- Local variables
+
+ Helper_Id : Entity_Id;
+
+ -- Start of processing for Make_Class_Precondition_Subps
+
+ begin
+ if Present (Class_Preconditions (Subp_Id))
+ or Present (Ignored_Class_Preconditions (Subp_Id))
+ then
+ pragma Assert
+ (Comes_From_Source (Subp_Id)
+ or else Is_Dispatch_Table_Wrapper (Subp_Id));
+
+ if No (Dynamic_Call_Helper (Subp_Id)) then
+
+ -- Build and add to the freezing actions of Tagged_Type its
+ -- dynamic-call helper.
+
+ Helper_Id :=
+ Make_Defining_Identifier (Loc,
+ New_External_Name (Chars (Subp_Id),
+ Suffix => "DP",
+ Suffix_Index => Source_Offset (Loc)));
+ Add_Call_Helper (Helper_Id, Is_Dynamic => True);
+
+ -- Link original subprogram to helper and vice versa
+
+ Set_Dynamic_Call_Helper (Subp_Id, Helper_Id);
+ Set_Class_Preconditions_Subprogram (Helper_Id, Subp_Id);
+ end if;
+
+ if not Is_Abstract_Subprogram (Subp_Id)
+ and then No (Static_Call_Helper (Subp_Id))
+ then
+ -- Build and add to the freezing actions of Tagged_Type its
+ -- static-call helper.
+
+ Helper_Id :=
+ Make_Defining_Identifier (Loc,
+ New_External_Name (Chars (Subp_Id),
+ Suffix => "SP",
+ Suffix_Index => Source_Offset (Loc)));
+
+ Add_Call_Helper (Helper_Id, Is_Dynamic => False);
+
+ -- Link original subprogram to helper and vice versa
+
+ Set_Static_Call_Helper (Subp_Id, Helper_Id);
+ Set_Class_Preconditions_Subprogram (Helper_Id, Subp_Id);
+
+ -- Build and add to the freezing actions of Tagged_Type the
+ -- indirect-call wrapper.
+
+ Add_Indirect_Call_Wrapper;
+ end if;
+ end if;
+ end Make_Class_Precondition_Subps;
+
+ ----------------------------------------------
+ -- Process_Class_Conditions_At_Freeze_Point --
+ ----------------------------------------------
+
+ procedure Process_Class_Conditions_At_Freeze_Point (Typ : Entity_Id) is
+
+ procedure Check_Class_Conditions (Spec_Id : Entity_Id);
+ -- Check class-wide pre/postconditions of Spec_Id
+
+ function Has_Class_Postconditions_Subprogram
+ (Spec_Id : Entity_Id) return Boolean;
+ -- Return True if Spec_Id has (or inherits) a postconditions subprogram.
+
+ function Has_Class_Preconditions_Subprogram
+ (Spec_Id : Entity_Id) return Boolean;
+ -- Return True if Spec_Id has (or inherits) a preconditions subprogram.
+
+ ----------------------------
+ -- Check_Class_Conditions --
+ ----------------------------
+
+ procedure Check_Class_Conditions (Spec_Id : Entity_Id) is
+ Par_Subp : Entity_Id;
+
+ begin
+ for Kind in Condition_Kind loop
+ Par_Subp := Nearest_Class_Condition_Subprogram (Kind, Spec_Id);
+
+ if Present (Par_Subp) then
+ Check_Class_Condition
+ (Cond => Class_Condition (Kind, Par_Subp),
+ Subp => Spec_Id,
+ Par_Subp => Par_Subp,
+ Is_Precondition => Kind in Ignored_Class_Precondition
+ | Class_Precondition);
+ end if;
+ end loop;
+ end Check_Class_Conditions;
+
+ -----------------------------------------
+ -- Has_Class_Postconditions_Subprogram --
+ -----------------------------------------
+
+ function Has_Class_Postconditions_Subprogram
+ (Spec_Id : Entity_Id) return Boolean is
+ begin
+ return
+ Present (Nearest_Class_Condition_Subprogram
+ (Spec_Id => Spec_Id,
+ Kind => Class_Postcondition))
+ or else
+ Present (Nearest_Class_Condition_Subprogram
+ (Spec_Id => Spec_Id,
+ Kind => Ignored_Class_Postcondition));
+ end Has_Class_Postconditions_Subprogram;
+
+ ----------------------------------------
+ -- Has_Class_Preconditions_Subprogram --
+ ----------------------------------------
+
+ function Has_Class_Preconditions_Subprogram
+ (Spec_Id : Entity_Id) return Boolean is
+ begin
+ return
+ Present (Nearest_Class_Condition_Subprogram
+ (Spec_Id => Spec_Id,
+ Kind => Class_Precondition))
+ or else
+ Present (Nearest_Class_Condition_Subprogram
+ (Spec_Id => Spec_Id,
+ Kind => Ignored_Class_Precondition));
+ end Has_Class_Preconditions_Subprogram;
+
+ -- Local variables
+
+ Prim_Elmt : Elmt_Id := First_Elmt (Primitive_Operations (Typ));
+ Prim : Entity_Id;
+
+ -- Start of processing for Process_Class_Conditions_At_Freeze_Point
+
+ begin
+ while Present (Prim_Elmt) loop
+ Prim := Node (Prim_Elmt);
+
+ if Has_Class_Preconditions_Subprogram (Prim)
+ or else Has_Class_Postconditions_Subprogram (Prim)
+ then
+ if Comes_From_Source (Prim) then
+ if Has_Significant_Contract (Prim) then
+ Merge_Class_Conditions (Prim);
+ end if;
+
+ -- Handle wrapper of protected operation
+
+ elsif Is_Primitive_Wrapper (Prim) then
+ Merge_Class_Conditions (Prim);
+
+ -- Check inherited class-wide conditions, excluding internal
+ -- entities built for mapping of interface primitives.
+
+ elsif Is_Derived_Type (Typ)
+ and then Present (Alias (Prim))
+ and then No (Interface_Alias (Prim))
+ then
+ Check_Class_Conditions (Prim);
+ end if;
+ end if;
+
+ Next_Elmt (Prim_Elmt);
+ end loop;
+ end Process_Class_Conditions_At_Freeze_Point;
+
+ ----------------------------
+ -- Merge_Class_Conditions --
+ ----------------------------
+
+ procedure Merge_Class_Conditions (Spec_Id : Entity_Id) is
+
+ procedure Preanalyze_Condition
+ (Subp : Entity_Id;
+ Expr : Node_Id);
+ -- Preanalyze the class-wide condition Expr of Subp
+
+ procedure Process_Inherited_Conditions (Kind : Condition_Kind);
+ -- Collect all inherited class-wide conditions of Spec_Id and merge
+ -- them into one big condition.
+
+ --------------------------
+ -- Preanalyze_Condition --
+ --------------------------
+
+ procedure Preanalyze_Condition
+ (Subp : Entity_Id;
+ Expr : Node_Id)
+ is
+ procedure Clear_Unset_References;
+ -- Clear unset references on formals of Subp since preanalysis
+ -- occurs in a place unrelated to the actual code.
+
+ procedure Remove_Controlling_Arguments;
+ -- Traverse Expr and clear the Controlling_Argument of calls to
+ -- nonabstract functions.
+
+ procedure Remove_Formals (Id : Entity_Id);
+ -- Remove formals from homonym chains and make them not visible
+
+ ----------------------------
+ -- Clear_Unset_References --
+ ----------------------------
+
+ procedure Clear_Unset_References is
+ F : Entity_Id := First_Formal (Subp);
+
+ begin
+ while Present (F) loop
+ Set_Unset_Reference (F, Empty);
+ Next_Formal (F);
+ end loop;
+ end Clear_Unset_References;
+
+ ----------------------------------
+ -- Remove_Controlling_Arguments --
+ ----------------------------------
+
+ procedure Remove_Controlling_Arguments is
+ function Remove_Ctrl_Arg (N : Node_Id) return Traverse_Result;
+ -- Reset the Controlling_Argument of calls to nonabstract
+ -- function calls.
+
+ ---------------------
+ -- Remove_Ctrl_Arg --
+ ---------------------
+
+ function Remove_Ctrl_Arg (N : Node_Id) return Traverse_Result is
+ begin
+ if Nkind (N) = N_Function_Call
+ and then Present (Controlling_Argument (N))
+ and then not Is_Abstract_Subprogram (Entity (Name (N)))
+ then
+ Set_Controlling_Argument (N, Empty);
+ end if;
+
+ return OK;
+ end Remove_Ctrl_Arg;
+
+ procedure Remove_Ctrl_Args is new Traverse_Proc (Remove_Ctrl_Arg);
+ begin
+ Remove_Ctrl_Args (Expr);
+ end Remove_Controlling_Arguments;
+
+ --------------------
+ -- Remove_Formals --
+ --------------------
+
+ procedure Remove_Formals (Id : Entity_Id) is
+ F : Entity_Id := First_Formal (Id);
+
+ begin
+ while Present (F) loop
+ Set_Is_Immediately_Visible (F, False);
+ Remove_Homonym (F);
+ Next_Formal (F);
+ end loop;
+ end Remove_Formals;
+
+ -- Start of processing for Preanalyze_Condition
+
+ begin
+ pragma Assert (Present (Expr));
+ pragma Assert (Inside_Class_Condition_Preanalysis = False);
+
+ Push_Scope (Subp);
+ Install_Formals (Subp);
+ Inside_Class_Condition_Preanalysis := True;
+
+ Preanalyze_And_Resolve (Expr, Standard_Boolean);
+
+ Inside_Class_Condition_Preanalysis := False;
+ Remove_Formals (Subp);
+ Pop_Scope;
+
+ -- Traverse Expr and clear the Controlling_Argument of calls to
+ -- nonabstract functions. Required since the preanalyzed condition
+ -- is not yet installed on its definite context and will be cloned
+ -- and extended in derivations with additional conditions.
+
+ Remove_Controlling_Arguments;
+
+ -- Clear also attribute Unset_Reference; again because preanalysis
+ -- occurs in a place unrelated to the actual code.
+
+ Clear_Unset_References;
+ end Preanalyze_Condition;
+
+ ----------------------------------
+ -- Process_Inherited_Conditions --
+ ----------------------------------
+
+ procedure Process_Inherited_Conditions (Kind : Condition_Kind) is
+ Tag_Typ : constant Entity_Id := Find_Dispatching_Type (Spec_Id);
+ Subps : constant Subprogram_List := Inherited_Subprograms (Spec_Id);
+ Seen : Subprogram_List (Subps'Range) := (others => Empty);
+
+ function Inherit_Condition
+ (Par_Subp : Entity_Id;
+ Subp : Entity_Id) return Node_Id;
+ -- Inherit the class-wide condition from Par_Subp to Subp and adjust
+ -- all the references to formals in the inherited condition.
+
+ procedure Merge_Conditions (From : Node_Id; Into : Node_Id);
+ -- Merge two class-wide preconditions or postconditions (the former
+ -- are merged using "or else", and the latter are merged using "and-
+ -- then"). The changes are accumulated in parameter Into.
+
+ function Seen_Subp (Id : Entity_Id) return Boolean;
+ -- Return True if the contract of subprogram Id has been processed
+
+ -----------------------
+ -- Inherit_Condition --
+ -----------------------
+
+ function Inherit_Condition
+ (Par_Subp : Entity_Id;
+ Subp : Entity_Id) return Node_Id
+ is
+ Installed_Calls : constant Elist_Id := New_Elmt_List;
+
+ procedure Install_Original_Selected_Component (Expr : Node_Id);
+ -- Traverse the given expression searching for dispatching calls
+ -- to functions whose original nodes was a selected component,
+ -- and replacing them temporarily by a copy of their original
+ -- node. Modified calls are stored in the list Installed_Calls
+ -- (to undo this work later).
+
+ procedure Restore_Dispatching_Calls (Expr : Node_Id);
+ -- Undo the work done by Install_Original_Selected_Component.
+
+ -----------------------------------------
+ -- Install_Original_Selected_Component --
+ -----------------------------------------
+
+ procedure Install_Original_Selected_Component (Expr : Node_Id) is
+ function Install_Node (N : Node_Id) return Traverse_Result;
+ -- Process a single node
+
+ ------------------
+ -- Install_Node --
+ ------------------
+
+ function Install_Node (N : Node_Id) return Traverse_Result is
+ New_N : Node_Id;
+ Orig_Nod : Node_Id;
+
+ begin
+ if Nkind (N) = N_Function_Call
+ and then Nkind (Original_Node (N)) = N_Selected_Component
+ and then Is_Dispatching_Operation (Entity (Name (N)))
+ then
+ Orig_Nod := Original_Node (N);
+
+ -- Temporarily use the original node field to keep the
+ -- reference to this node (to undo this work later!).
+
+ New_N := New_Copy (N);
+ Set_Original_Node (New_N, Orig_Nod);
+ Append_Elmt (New_N, Installed_Calls);
+
+ Rewrite (N, Orig_Nod);
+ Set_Original_Node (N, New_N);
+ end if;
+
+ return OK;
+ end Install_Node;
+
+ procedure Install_Nodes is new Traverse_Proc (Install_Node);
+
+ begin
+ Install_Nodes (Expr);
+ end Install_Original_Selected_Component;
+
+ -------------------------------
+ -- Restore_Dispatching_Calls --
+ -------------------------------
+
+ procedure Restore_Dispatching_Calls (Expr : Node_Id) is
+ function Restore_Node (N : Node_Id) return Traverse_Result;
+ -- Process a single node
+
+ ------------------
+ -- Restore_Node --
+ ------------------
+
+ function Restore_Node (N : Node_Id) return Traverse_Result is
+ Orig_Sel_N : Node_Id;
+
+ begin
+ if Nkind (N) = N_Selected_Component
+ and then Nkind (Original_Node (N)) = N_Function_Call
+ and then Contains (Installed_Calls, Original_Node (N))
+ then
+ Orig_Sel_N := Original_Node (Original_Node (N));
+ pragma Assert (Nkind (Orig_Sel_N) = N_Selected_Component);
+ Rewrite (N, Original_Node (N));
+ Set_Original_Node (N, Orig_Sel_N);
+ end if;
+
+ return OK;
+ end Restore_Node;
+
+ procedure Restore_Nodes is new Traverse_Proc (Restore_Node);
+
+ begin
+ Restore_Nodes (Expr);
+ end Restore_Dispatching_Calls;
+
+ -- Local variables
+
+ Assoc_List : constant Elist_Id := New_Elmt_List;
+ Par_Formal_Id : Entity_Id := First_Formal (Par_Subp);
+ Subp_Formal_Id : Entity_Id := First_Formal (Subp);
+ New_Expr : Node_Id;
+ Class_Cond : Node_Id;
+
+ -- Start of processing for Inherit_Condition
+
+ begin
+ while Present (Par_Formal_Id) loop
+ Append_Elmt (Par_Formal_Id, Assoc_List);
+ Append_Elmt (Subp_Formal_Id, Assoc_List);
+
+ Next_Formal (Par_Formal_Id);
+ Next_Formal (Subp_Formal_Id);
+ end loop;
+
+ -- In order to properly preanalyze an inherited preanalyzed
+ -- condition that has occurrences of the Object.Operation
+ -- notation we must restore the original node; otherwise we
+ -- would report spurious errors.
+
+ Class_Cond := Class_Condition (Kind, Par_Subp);
+
+ Install_Original_Selected_Component (Class_Cond);
+ New_Expr := New_Copy_Tree (Class_Cond);
+ Restore_Dispatching_Calls (Class_Cond);
+
+ return New_Copy_Tree (New_Expr, Map => Assoc_List);
+ end Inherit_Condition;
+
+ ----------------------
+ -- Merge_Conditions --
+ ----------------------
+
+ procedure Merge_Conditions (From : Node_Id; Into : Node_Id) is
+ function Expression_Arg (Expr : Node_Id) return Node_Id;
+ -- Return the boolean expression argument of a condition while
+ -- updating its parentheses count for the subsequent merge.
+
+ --------------------
+ -- Expression_Arg --
+ --------------------
+
+ function Expression_Arg (Expr : Node_Id) return Node_Id is
+ begin
+ if Paren_Count (Expr) = 0 then
+ Set_Paren_Count (Expr, 1);
+ end if;
+
+ return Expr;
+ end Expression_Arg;
+
+ -- Local variables
+
+ From_Expr : constant Node_Id := Expression_Arg (From);
+ Into_Expr : constant Node_Id := Expression_Arg (Into);
+ Loc : constant Source_Ptr := Sloc (Into);
+
+ -- Start of processing for Merge_Conditions
+
+ begin
+ case Kind is
+
+ -- Merge the two preconditions by "or else"-ing them
+
+ when Ignored_Class_Precondition
+ | Class_Precondition
+ =>
+ Rewrite (Into_Expr,
+ Make_Or_Else (Loc,
+ Right_Opnd => Relocate_Node (Into_Expr),
+ Left_Opnd => From_Expr));
+
+ -- Merge the two postconditions by "and then"-ing them
+
+ when Ignored_Class_Postcondition
+ | Class_Postcondition
+ =>
+ Rewrite (Into_Expr,
+ Make_And_Then (Loc,
+ Right_Opnd => Relocate_Node (Into_Expr),
+ Left_Opnd => From_Expr));
+ end case;
+ end Merge_Conditions;
+
+ ---------------
+ -- Seen_Subp --
+ ---------------
+
+ function Seen_Subp (Id : Entity_Id) return Boolean is
+ begin
+ for Index in Seen'Range loop
+ if Seen (Index) = Id then
+ return True;
+ end if;
+ end loop;
+
+ return False;
+ end Seen_Subp;
+
+ -- Local variables
+
+ Class_Cond : Node_Id;
+ Cond : Node_Id;
+ Subp_Id : Entity_Id;
+ Par_Prim : Entity_Id := Empty;
+ Par_Iface_Prims : Elist_Id := No_Elist;
+
+ -- Start of processing for Process_Inherited_Conditions
+
+ begin
+ Class_Cond := Class_Condition (Kind, Spec_Id);
+
+ -- Process parent primitives looking for nearest ancestor with
+ -- class-wide conditions.
+
+ for Index in Subps'Range loop
+ Subp_Id := Subps (Index);
+
+ if No (Par_Prim)
+ and then Is_Ancestor (Find_Dispatching_Type (Subp_Id), Tag_Typ)
+ then
+ if Present (Alias (Subp_Id)) then
+ Subp_Id := Ultimate_Alias (Subp_Id);
+ end if;
+
+ -- Wrappers of class-wide pre/postconditions reference the
+ -- parent primitive that has the inherited contract and help
+ -- us to climb fast.
+
+ if Is_Wrapper (Subp_Id)
+ and then Present (LSP_Subprogram (Subp_Id))
+ then
+ Subp_Id := LSP_Subprogram (Subp_Id);
+ end if;
+
+ if not Seen_Subp (Subp_Id)
+ and then Present (Class_Condition (Kind, Subp_Id))
+ then
+ Seen (Index) := Subp_Id;
+ Par_Prim := Subp_Id;
+ Par_Iface_Prims := Covered_Interface_Primitives (Par_Prim);
+
+ Cond := Inherit_Condition
+ (Subp => Spec_Id,
+ Par_Subp => Subp_Id);
+
+ if Present (Class_Cond) then
+ Merge_Conditions (Cond, Class_Cond);
+ else
+ Class_Cond := Cond;
+ end if;
+
+ Check_Class_Condition
+ (Cond => Class_Cond,
+ Subp => Spec_Id,
+ Par_Subp => Subp_Id,
+ Is_Precondition => Kind in Ignored_Class_Precondition
+ | Class_Precondition);
+ Build_Class_Wide_Expression
+ (Pragma_Or_Expr => Class_Cond,
+ Subp => Spec_Id,
+ Par_Subp => Subp_Id,
+ Adjust_Sloc => False);
+
+ -- We are done as soon as we process the nearest ancestor
+
+ exit;
+ end if;
+ end if;
+ end loop;
+
+ -- Process the contract of interface primitives not covered by
+ -- the nearest ancestor.
+
+ for Index in Subps'Range loop
+ Subp_Id := Subps (Index);
+
+ if Is_Interface (Find_Dispatching_Type (Subp_Id)) then
+ if Present (Alias (Subp_Id)) then
+ Subp_Id := Ultimate_Alias (Subp_Id);
+ end if;
+
+ if not Seen_Subp (Subp_Id)
+ and then Present (Class_Condition (Kind, Subp_Id))
+ and then not Contains (Par_Iface_Prims, Subp_Id)
+ then
+ Seen (Index) := Subp_Id;
+
+ Cond := Inherit_Condition
+ (Subp => Spec_Id,
+ Par_Subp => Subp_Id);
+
+ Check_Class_Condition
+ (Cond => Cond,
+ Subp => Spec_Id,
+ Par_Subp => Subp_Id,
+ Is_Precondition => Kind in Ignored_Class_Precondition
+ | Class_Precondition);
+ Build_Class_Wide_Expression
+ (Pragma_Or_Expr => Cond,
+ Subp => Spec_Id,
+ Par_Subp => Subp_Id,
+ Adjust_Sloc => False);
+
+ if Present (Class_Cond) then
+ Merge_Conditions (Cond, Class_Cond);
+ else
+ Class_Cond := Cond;
+ end if;
+ end if;
+ end if;
+ end loop;
+
+ Set_Class_Condition (Kind, Spec_Id, Class_Cond);
+ end Process_Inherited_Conditions;
+
+ -- Local variables
+
+ Cond : Node_Id;
+
+ -- Start of processing for Merge_Class_Conditions
+
+ begin
+ for Kind in Condition_Kind loop
+ Cond := Class_Condition (Kind, Spec_Id);
+
+ -- If this subprogram has class-wide conditions then preanalyze
+ -- them before processing inherited conditions since conditions
+ -- are checked and merged from right to left.
+
+ if Present (Cond) then
+ Preanalyze_Condition (Spec_Id, Cond);
+ end if;
+
+ Process_Inherited_Conditions (Kind);
+
+ -- Preanalyze merged inherited conditions
+
+ if Cond /= Class_Condition (Kind, Spec_Id) then
+ Preanalyze_Condition (Spec_Id,
+ Class_Condition (Kind, Spec_Id));
+ end if;
+ end loop;
+ end Merge_Class_Conditions;
+
----------------------------------------
-- Save_Global_References_In_Contract --
----------------------------------------
@@ -3622,10 +4731,9 @@ package body Contracts is
------------------------------------
procedure Save_Global_References_In_List (First_Prag : Node_Id) is
- Prag : Node_Id;
+ Prag : Node_Id := First_Prag;
begin
- Prag := First_Prag;
while Present (Prag) loop
if Is_Generic_Contract_Pragma (Prag) then
Save_Global_References (Prag);
@@ -3662,4 +4770,29 @@ package body Contracts is
Pop_Scope;
end Save_Global_References_In_Contract;
+ -------------------------
+ -- Set_Class_Condition --
+ -------------------------
+
+ procedure Set_Class_Condition
+ (Kind : Condition_Kind;
+ Subp : Entity_Id;
+ Cond : Node_Id)
+ is
+ begin
+ case Kind is
+ when Class_Postcondition =>
+ Set_Class_Postconditions (Subp, Cond);
+
+ when Class_Precondition =>
+ Set_Class_Preconditions (Subp, Cond);
+
+ when Ignored_Class_Postcondition =>
+ Set_Ignored_Class_Postconditions (Subp, Cond);
+
+ when Ignored_Class_Precondition =>
+ Set_Ignored_Class_Preconditions (Subp, Cond);
+ end case;
+ end Set_Class_Condition;
+
end Contracts;
diff --git a/gcc/ada/contracts.ads b/gcc/ada/contracts.ads
index bfd482e..eb26ebf 100644
--- a/gcc/ada/contracts.ads
+++ b/gcc/ada/contracts.ads
@@ -216,6 +216,31 @@ package Contracts is
-- subprogram declaration template denoted by Templ. The instantiated
-- pragmas are added to list L.
+ procedure Make_Class_Precondition_Subps
+ (Subp_Id : Entity_Id;
+ Late_Overriding : Boolean := False);
+ -- Build helpers that at run time evaluate statically and dynamically the
+ -- class-wide preconditions of Subp_Id; build also the indirect-call
+ -- wrapper (ICW) required to check class-wide preconditions when the
+ -- subprogram is invoked through an access-to-subprogram, or when it
+ -- overrides an inherited class-wide precondition (see AI12-0195-1).
+ -- Late_Overriding enables special handling required for late-overriding
+ -- subprograms.
+
+ procedure Merge_Class_Conditions (Spec_Id : Entity_Id);
+ -- Merge and preanalyze all class-wide conditions of Spec_Id (class-wide
+ -- preconditions merged with operator or-else; class-wide postconditions
+ -- merged with operator and-then). Ignored pre/postconditions are also
+ -- merged since, although they are not required to generate code, their
+ -- preanalysis is required to perform semantic checks. Resulting merged
+ -- expressions are later installed by the expander in helper subprograms
+ -- which are invoked from the caller side; they are also used to build
+ -- the dispatch-table wrapper (DTW), if required.
+
+ procedure Process_Class_Conditions_At_Freeze_Point (Typ : Entity_Id);
+ -- Merge, preanalyze, and check class-wide pre/postconditions of Typ
+ -- primitives.
+
procedure Save_Global_References_In_Contract
(Templ : Node_Id;
Gen_Id : Entity_Id);
diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb
index 5245feb3..8873000 100644
--- a/gcc/ada/debug.adb
+++ b/gcc/ada/debug.adb
@@ -112,7 +112,7 @@ package body Debug is
-- d.y Disable implicit pragma Elaborate_All on task bodies
-- d.z Restore previous support for frontend handling of Inline_Always
- -- d.A
+ -- d.A Enable statistics printing in Atree
-- d.B Generate a bug box on abort_statement
-- d.C Generate concatenation call, do not generate inline code
-- d.D Disable errors on use of overriding keyword in Ada 95 mode
@@ -158,7 +158,7 @@ package body Debug is
-- d_q
-- d_r
-- d_s Stop elaboration checks on synchronous suspension
- -- d_t
+ -- d_t In LLVM-based CCG, dump LLVM IR after transformations are done
-- d_u
-- d_v Enable additional checks and debug printouts in Atree
-- d_w
@@ -210,7 +210,7 @@ package body Debug is
-- d.5 Do not generate imported subprogram definitions in C code
-- d.6 Do not avoid declaring unreferenced types in C code
-- d.7 Disable unsound heuristics in gnat2scil (for CP as SPARK prover)
- -- d.8
+ -- d.8 Disable unconditional inlining of expression functions
-- d.9 Disable build-in-place for nonlimited types
-- d_1
@@ -830,6 +830,11 @@ package body Debug is
-- handling of Inline_Always by the front end on such targets. For the
-- targets that do not use the GCC back end, this switch is ignored.
+ -- d.A Enable statistics printing in Atree. First set Statistics_Enabled
+ -- in gen_il-gen.adb to True, then rebuild, then run the compiler
+ -- with -gnatd.A. You might want to apply "sort -nr" to parts of the
+ -- output.
+
-- d.B Generate a bug box when we see an abort_statement, even though
-- there is no bug. Useful for testing Comperr.Compiler_Abort: write
-- some code containing an abort_statement, and compile it with
@@ -992,6 +997,10 @@ package body Debug is
-- a call to routine Ada.Synchronous_Task_Control.Suspend_Until_True
-- or Ada.Synchronous_Barriers.Wait_For_Release.
+ -- d_t In the LLVM-based CCG, do an additional dump of the LLVM IR
+ -- after the pass that does transformations to the IR into a
+ -- filename ending with .trans.ll.
+
-- d_v Enable additional checks and debug printouts in Atree
-- d_x The compiler does not expand in line the Image attribute for user-
@@ -1101,6 +1110,10 @@ package body Debug is
-- issues (e.g., assuming that a low bound of an array parameter
-- of an unconstrained subtype belongs to the index subtype).
+ -- d.8 By default calls to expression functions are always inlined.
+ -- This debug flag turns off this behavior, making them subject
+ -- to the usual inlining heuristics of the code generator.
+
-- d.9 Disable build-in-place for function calls returning nonlimited
-- types.
diff --git a/gcc/ada/doc/gnat_rm.rst b/gcc/ada/doc/gnat_rm.rst
index 97f7e4d..7743ef8 100644
--- a/gcc/ada/doc/gnat_rm.rst
+++ b/gcc/ada/doc/gnat_rm.rst
@@ -55,6 +55,7 @@ GNAT Reference Manual
gnat_rm/specialized_needs_annexes
gnat_rm/implementation_of_specific_ada_features
gnat_rm/implementation_of_ada_2012_features
+ gnat_rm/security_hardening_features
gnat_rm/obsolescent_features
gnat_rm/compatibility_and_porting_guide
diff --git a/gcc/ada/doc/gnat_rm/about_this_guide.rst b/gcc/ada/doc/gnat_rm/about_this_guide.rst
index b48785ee..9defee8 100644
--- a/gcc/ada/doc/gnat_rm/about_this_guide.rst
+++ b/gcc/ada/doc/gnat_rm/about_this_guide.rst
@@ -96,6 +96,9 @@ This reference manual contains the following chapters:
* :ref:`Implementation_of_Ada_2012_Features`, describes the status of the
GNAT implementation of the Ada 2012 language standard.
+* :ref:`Security_Hardening_Features` documents GNAT extensions aimed
+ at security hardening.
+
* :ref:`Obsolescent_Features` documents implementation dependent features,
including pragmas and attributes, which are considered obsolescent, since
there are other preferred ways of achieving the same results. These
diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_characteristics.rst b/gcc/ada/doc/gnat_rm/implementation_defined_characteristics.rst
index 8d0be38..c5c7dfb 100644
--- a/gcc/ada/doc/gnat_rm/implementation_defined_characteristics.rst
+++ b/gcc/ada/doc/gnat_rm/implementation_defined_characteristics.rst
@@ -53,7 +53,8 @@ Any *code_statement* can potentially cause external interactions.
See separate section on source representation.
*
- "The control functions allowed in comments. See 2.1(14)."
+ "The semantics of an Ada program whose text is not in
+ Normalization Form C. See 2.1(4)."
See separate section on source representation.
@@ -86,14 +87,14 @@ parameter, checks that the optimization flag is set, and aborts if it is
not.
*
- "The sequence of characters of the value returned by
- ``S'Image`` when some of the graphic characters of
- ``S'Wide_Image`` are not defined in ``Character``. See
- 3.5(37)."
+ "The message string associated with the Assertion_Error exception raised
+ by the failure of a predicate check if there is no applicable
+ Predicate_Failure aspect. See 3.2.4(31)."
-The sequence of characters is as defined by the wide character encoding
-method used for the source. See section on source representation for
-further details.
+In the case of a Dynamic_Predicate aspect, the string is
+"Dynamic_Predicate failed at <source position>", where
+"<source position>" might be something like "foo.adb:123".
+The Static_Predicate case is handled analogously.
*
"The predefined integer types declared in
@@ -146,12 +147,12 @@ Type Representation
IEEE 80-bit Extended on x86 architecture
====================== ===============================================
-The default rounding mode specified by the IEEE 754 Standard is assumed for
-static computations, i.e. round to nearest, ties to even. The input routines
-yield correctly rounded values for Short_Float, Float and Long_Float at least.
-The output routines can compute up to twice as many exact digits as the value
-of ``T'Digits`` for any type, for example 30 digits for Long_Float; if more
-digits are requested, zeros are printed.
+The default rounding mode specified by the IEEE 754 Standard is assumed both
+for static and dynamic computations (that is, round to nearest, ties to even).
+The input routines yield correctly rounded values for Short_Float, Float, and
+Long_Float at least. The output routines can compute up to twice as many exact
+digits as the value of ``T'Digits`` for any type, for example 30 digits for
+Long_Float; if more digits are requested, zeros are printed.
*
"The small of an ordinary fixed point type. See 3.5.9(8)."
@@ -192,24 +193,79 @@ Block numbers of the form :samp:`B{nnn}`, where *nnn* is a
decimal integer are allocated.
*
+ "The sequence of characters of the value returned by Tags.Expanded_Name
+ (respectively, Tags.Wide_Expanded_Name) when some of the graphic
+ characters of Tags.Wide_Wide_Expanded_Name are not defined in Character
+ (respectively, Wide_Character). See 3.9(10.1)."
+
+This is handled in the same way as the implementation-defined behavior
+referenced in A.4.12(34).
+
+*
"Implementation-defined attributes. See 4.1.4(12)."
See :ref:`Implementation_Defined_Attributes`.
*
+ "The value of the parameter to Empty for some container aggregates.
+ See 4.3.5(40)."
+
+As per the suggestion given in the Annotated Ada RM, the default value
+of the formal parameter is used if one exists and zero is used otherwise.
+
+*
+ "The maximum number of chunks for a parallel reduction expression without
+ a chunk_specification. See 4.5.10(21)."
+
+Feature unimplemented.
+
+*
+ "Rounding of real static expressions which are exactly half-way between
+ two machine numbers. See 4.9(38)."
+
+Round to even is used in all such cases.
+
+*
+ "The maximum number of chunks for a parallel generalized iterator without
+ a chunk_specification. See 5.5.2(10)."
+
+Feature unimplemented.
+
+*
+ "The number of chunks for an array component iterator. See 5.5.2(11)."
+
+Feature unimplemented.
+
+*
+ "Any extensions of the Global aspect. See 6.1.2(43)."
+
+Feature unimplemented.
+
+*
+ "The circumstances the implementation passes in the null value for a view
+ conversion of an access type used as an out parameter. See 6.4.1(19)."
+
+Difficult to characterize.
+
+*
+ "Any extensions of the Default_Initial_Condition aspect. See 7.3.3(11)."
+
+SPARK allows specifying *null* as the Default_Initial_Condition
+aspect of a type. See the SPARK reference manual for further details.
+
+*
"Any implementation-defined time types. See 9.6(6)."
There are no implementation-defined time types.
*
- "The time base associated with relative delays."
+ "The time base associated with relative delays. See 9.6(20)."
See 9.6(20). The time base used is that provided by the C library
function ``gettimeofday``.
*
- "The time base of the type ``Calendar.Time``. See
- 9.6(23)."
+ "The time base of the type ``Calendar.Time``. See 9.6(23)."
The time base used is that provided by the C library function
``gettimeofday``.
@@ -229,13 +285,15 @@ setting for local time, as accessed by the C library function
There are no such limits.
*
- "Whether or not two non-overlapping parts of a composite
- object are independently addressable, in the case where packing, record
- layout, or ``Component_Size`` is specified for the object. See
- 9.10(1)."
+ "The result of Calendar.Formatting.Image if its argument represents more
+ than 100 hours. See 9.6.1(86)."
+
+Calendar.Time_Error is raised.
+
+*
+ "Implementation-defined conflict check policies. See 9.10.1(5)."
-Separate components are independently addressable if they do not share
-overlapping storage units.
+There are no implementation-defined conflict check policies.
*
"The representation for a compilation. See 10.1(2)."
@@ -281,9 +339,8 @@ options, refer to *GNAT Make Program gnatmake* in the
:title:`GNAT User's Guide`.
*
- "The implementation-defined means, if any, of specifying
- which compilation units are needed by a given compilation unit. See
- 10.2(2)."
+ "The implementation-defined means, if any, of specifying which compilation
+ units are needed by a given compilation unit. See 10.2(2)."
The units needed by a given compilation unit are as defined in
the Ada Reference Manual section 10.2(2-6). There are no
@@ -298,17 +355,13 @@ The main program is designated by providing the name of the
corresponding :file:`ALI` file as the input parameter to the binder.
*
- "The order of elaboration of *library_items*. See
- 10.2(18)."
+ "The order of elaboration of *library_items*. See 10.2(18)."
The first constraint on ordering is that it meets the requirements of
Chapter 10 of the Ada Reference Manual. This still leaves some
-implementation dependent choices, which are resolved by first
-elaborating bodies as early as possible (i.e., in preference to specs
-where there is a choice), and second by evaluating the immediate with
-clauses of a unit to determine the probably best choice, and
-third by elaborating in alphabetical order of unit names
-where a choice still remains.
+implementation-dependent choices, which are resolved by analyzing
+the elaboration code of each unit and identifying implicit
+elaboration-order dependencies.
*
"Parameter passing and function return for the main
@@ -320,13 +373,12 @@ value is the return code of the program (overriding any value that
may have been set by a call to ``Ada.Command_Line.Set_Exit_Status``).
*
- "The mechanisms for building and running partitions. See
- 10.2(24)."
+ "The mechanisms for building and running partitions. See 10.2(24)."
-GNAT itself supports programs with only a single partition. The GNATDIST
+GNAT itself supports programs with only a single partition. The GNATDIST
tool provided with the GLADE package (which also includes an implementation
of the PCS) provides a completely flexible method for building and running
-programs consisting of multiple partitions. See the separate GLADE manual
+programs consisting of multiple partitions. See the separate GLADE manual
for details.
*
@@ -340,12 +392,11 @@ See separate section on compilation model.
implementation. See 10.2(28)."
Passive partitions are supported on targets where shared memory is
-provided by the operating system. See the GLADE reference manual for
+provided by the operating system. See the GLADE reference manual for
further details.
*
- "The information returned by ``Exception_Message``. See
- 11.4.1(10)."
+ "The information returned by ``Exception_Message``. See 11.4.1(10)."
Exception message returns the null string unless a specific message has
been passed by the program.
@@ -391,6 +442,38 @@ where
the last line is a single ``LF`` character (``16#0A#``).
*
+ "The sequence of characters of the value returned by
+ Exceptions.Exception_Name (respectively, Exceptions.Wide_Exception_Name)
+ when some of the graphic characters of Exceptions.Wide_Wide_Exception_Name
+ are not defined in Character (respectively, Wide_Character).
+ See 11.4.1(12.1)."
+
+This is handled in the same way as the implementation-defined behavior
+referenced in A.4.12(34).
+
+*
+ "The information returned by Exception_Information. See 11.4.1(13)."
+
+The exception name and the source location at which the exception was
+raised are included.
+
+*
+ "Implementation-defined policy_identifiers and assertion_aspect_marks
+ allowed in a pragma Assertion_Policy. See 11.4.2(9)."
+
+Implementation-defined assertion_aspect_marks include Assert_And_Cut,
+Assume, Contract_Cases, Debug, Ghost, Initial_Condition, Loop_Invariant,
+Loop_Variant, Postcondition, Precondition, Predicate, Refined_Post,
+Statement_Assertions, and Subprogram_Variant. Implementation-defined
+policy_identifiers include Ignore and Suppressible.
+
+*
+ "The default assertion policy. See 11.4.2(10)."
+
+The default assertion policy is Ignore, although this can be overridden
+via compiler switches such as "-gnata".
+
+*
"Implementation-defined check names. See 11.5(27)."
The implementation defined check names include Alignment_Check,
@@ -400,28 +483,54 @@ program can add implementation-defined check names by means of the pragma
Check_Name. See the description of pragma ``Suppress`` for full details.
*
- "The interpretation of each aspect of representation. See
- 13.1(20)."
+ "Existence and meaning of second parameter of pragma Unsuppress.
+ See 11.5(27.1)."
+
+The legality rules for and semantics of the second parameter of pragma
+Unsuppress match those for the second argument of pragma Suppress.
+
+*
+ "The cases that cause conflicts between the representation of the
+ ancestors of a type_declaration. See 13.1(13.1)."
+
+No such cases exist.
+
+*
+ "The interpretation of each representation aspect. See 13.1(20)."
See separate section on data representations.
*
- "Any restrictions placed upon representation items. See
- 13.1(20)."
+ "Any restrictions placed upon the specification of representation aspects.
+ See 13.1(20)."
See separate section on data representations.
*
- "The meaning of ``Size`` for indefinite subtypes. See
- 13.3(48)."
+ "Implementation-defined aspects, including the syntax for specifying
+ such aspects and the legality rules for such aspects. See 13.1.1(38)."
+
+See :ref:`Implementation_Defined_Aspects`.
+
+*
+ "The set of machine scalars. See 13.3(8.1)."
+
+See separate section on data representations.
+
+*
+ "The meaning of ``Size`` for indefinite subtypes. See 13.3(48)."
+
+The Size attribute of an indefinite subtype is not less than the Size
+attribute of any object of that type.
+
+*
+ "The meaning of Object_Size for indefinite subtypes. See 13.3(58)."
-Size for an indefinite subtype is the maximum possible size, except that
-for the case of a subprogram parameter, the size of the parameter object
-is the actual size.
+The Object_Size attribute of an indefinite subtype is not less than the
+Object_Size attribute of any object of that type.
*
- "The default external representation for a type tag. See
- 13.3(75)."
+ "The default external representation for a type tag. See 13.3(75)."
The default external representation for a type tag is the fully expanded
name of the type in upper case letters.
@@ -448,12 +557,10 @@ implementation, so no non-default bit ordering is supported. The default
bit ordering corresponds to the natural endianness of the target architecture.
*
- "The contents of the visible part of package ``System``
- and its language-defined children. See 13.7(2)."
+ "The contents of the visible part of package ``System``. See 13.7(2)."
-See the definition of these packages in files :file:`system.ads` and
-:file:`s-stoele.ads`. Note that two declarations are added to package
-System.
+See the definition of package System in :file:`system.ads`.
+Note that two declarations are added to package System.
.. code-block:: ada
@@ -461,14 +568,21 @@ System.
Max_Interrupt_Priority : constant Positive := Interrupt_Priority'Last;
*
- "The contents of the visible part of package
- ``System.Machine_Code``, and the meaning of
- *code_statements*. See 13.8(7)."
+ "The range of Storage_Elements.Storage_Offset, the modulus of
+ Storage_Elements.Storage_Element, and the declaration of
+ Storage_Elements.Integer_Address. See 13.7.1(11)."
+
+See the definition of package System.Storage_Elements in :file:`s-stoele.ads`.
+
+*
+ "The contents of the visible part of package ``System.Machine_Code``,
+ and the meaning of *code_statements*. See 13.8(7)."
See the definition and documentation in file :file:`s-maccod.ads`.
*
- "The effect of unchecked conversion. See 13.9(11)."
+ "The result of unchecked conversion for instances with scalar result
+ types whose result is not defined by the language. See 13.9(11)."
Unchecked conversion between types of the same size
results in an uninterpreted transmission of the bits from one type
@@ -485,69 +599,43 @@ greater than the source alignment, then a copy of the result is
made with appropriate alignment
*
- "The semantics of operations on invalid representations.
- See 13.9.2(10-11)."
-
-For assignments and other operations where the use of invalid values cannot
-result in erroneous behavior, the compiler ignores the possibility of invalid
-values. An exception is raised at the point where an invalid value would
-result in erroneous behavior. For example executing:
+ "The result of unchecked conversion for instances with nonscalar result
+ types whose result is not defined by the language. See 13.9(11)."
-.. code-block:: ada
-
- procedure invalidvals is
- X : Integer := -1;
- Y : Natural range 1 .. 10;
- for Y'Address use X'Address;
- Z : Natural range 1 .. 10;
- A : array (Natural range 1 .. 10) of Integer;
- begin
- Z := Y; -- no exception
- A (Z) := 3; -- exception raised;
- end;
-
-As indicated, an exception is raised on the array assignment, but not
-on the simple assignment of the invalid negative value from Y to Z.
+See preceding definition for the scalar result case.
*
- "The manner of choosing a storage pool for an access type
- when ``Storage_Pool`` is not specified for the type. See 13.11(17)."
+ "Whether or not the implementation provides user-accessible
+ names for the standard pool type(s). See 13.11(17)."
There are 3 different standard pools used by the compiler when
``Storage_Pool`` is not specified depending whether the type is local
to a subprogram or defined at the library level and whether
-``Storage_Size``is specified or not. See documentation in the runtime
+``Storage_Size``is specified or not. See documentation in the runtime
library units ``System.Pool_Global``, ``System.Pool_Size`` and
``System.Pool_Local`` in files :file:`s-poosiz.ads`,
:file:`s-pooglo.ads` and :file:`s-pooloc.ads` for full details on the
-default pools used.
-
-*
- "Whether or not the implementation provides user-accessible
- names for the standard pool type(s). See 13.11(17)."
-
-See documentation in the sources of the run time mentioned in the previous
-paragraph. All these pools are accessible by means of `with`\ ing
+default pools used. All these pools are accessible by means of `with`\ ing
these units.
*
- "The meaning of ``Storage_Size``. See 13.11(18)."
+ "The meaning of ``Storage_Size`` when neither the Storage_Size nor the
+ Storage_Pool is specified for an access type. See 13.11(18)."
``Storage_Size`` is measured in storage units, and refers to the
total space available for an access type collection, or to the primary
stack space for a task.
*
- "Implementation-defined aspects of storage pools. See
- 13.11(22)."
+ "The effect of specifying aspect Default_Storage_Pool on an instance
+ of a language-defined generic unit. See 13.11.3(5)."
-See documentation in the sources of the run time mentioned in the
-paragraph about standard storage pools above
-for details on GNAT-defined aspects of storage pools.
+Instances of language-defined generic units are treated the same as other
+instances with respect to the Default_Storage_Pool aspect.
*
- "The set of restrictions allowed in a pragma
- ``Restrictions``. See 13.12(7)."
+ "Implementation-defined restrictions allowed in a pragma
+ ``Restrictions``. See 13.12(8.7)."
See :ref:`Standard_and_Implementation_Defined_Restrictions`.
@@ -555,14 +643,19 @@ See :ref:`Standard_and_Implementation_Defined_Restrictions`.
"The consequences of violating limitations on
``Restrictions`` pragmas. See 13.12(9)."
-Restrictions that can be checked at compile time result in illegalities
-if violated. Currently there are no other consequences of violating
-restrictions.
+Restrictions that can be checked at compile time are enforced at
+compile time; violations are illegal. For other restrictions, any
+violation during program execution results in erroneous execution.
*
- "The representation used by the ``Read`` and
- ``Write`` attributes of elementary types in terms of stream
- elements. See 13.13.2(9)."
+ "Implementation-defined usage profiles allowed in a pragma Profile.
+ See 13.12(15)."
+
+See :ref:`Implementation_Defined_Pragmas`.
+
+*
+ "The contents of the stream elements read and written by the Read and
+ Write attributes of elementary types. See 13.13.2(9)."
The representation is the in-memory representation of the base type of
the type, using the number of bits corresponding to the
@@ -575,12 +668,29 @@ the type, using the number of bits corresponding to the
See items describing the integer and floating-point types supported.
*
- "The string returned by ``Character_Set_Version``.
- See A.3.5(3)."
+ "The values returned by Strings.Hash. See A.4.9(3)."
+
+This hash function has predictable collisions and is subject to
+equivalent substring attacks. It is not suitable for construction of a
+hash table keyed on possibly malicious user input.
+
+*
+ "The value returned by a call to a Text_Buffer Get procedure if any
+ character in the returned sequence is not defined in Character.
+ See A.4.12(34)."
+
+The contents of a buffer is represented internally as a UTF_8 string.
+The value return by Text_Buffer.Get is the result of passing that
+UTF_8 string to UTF_Encoding.Strings.Decode.
+
+*
+ "The value returned by a call to a Text_Buffer Wide_Get procedure if
+ any character in the returned sequence is not defined in Wide_Character.
+ See A.4.12(34)."
-``Ada.Wide_Characters.Handling.Character_Set_Version`` returns
-the string "Unicode 4.0", referring to version 4.0 of the
-Unicode specification.
+The contents of a buffer is represented internally as a UTF_8 string.
+The value return by Text_Buffer.Wide_Get is the result of passing that
+UTF_8 string to UTF_Encoding.Wide_Strings.Decode.
*
"The accuracy actually achieved by the elementary
@@ -610,14 +720,6 @@ Maximum image width is 6864, see library file :file:`s-rannum.ads`.
Maximum image width is 6864, see library file :file:`s-rannum.ads`.
*
- "The algorithms for random number generation. See
- A.5.2(32)."
-
-The algorithm is the Mersenne Twister, as documented in the source file
-:file:`s-rannum.adb`. This version of the algorithm has a period of
-2**19937-1.
-
-*
"The string representation of a random number generator's
state. See A.5.2(38)."
@@ -626,32 +728,16 @@ the fixed-width decimal representations of the 624 32-bit integers
of the state vector.
*
- "The minimum time interval between calls to the
- time-dependent Reset procedure that are guaranteed to initiate different
- random number sequences. See A.5.2(45)."
-
-The minimum period between reset calls to guarantee distinct series of
-random numbers is one microsecond.
-
-*
"The values of the ``Model_Mantissa``,
``Model_Emin``, ``Model_Epsilon``, ``Model``,
``Safe_First``, and ``Safe_Last`` attributes, if the Numerics
Annex is not supported. See A.5.3(72)."
-Run the compiler with *-gnatS* to produce a listing of package
-``Standard``, has the values of all numeric attributes.
+Running the compiler with *-gnatS* to produce a listing of package
+``Standard`` displays the values of these attributes.
*
- "Any implementation-defined characteristics of the
- input-output packages. See A.7(14)."
-
-There are no special implementation defined characteristics for these
-packages.
-
-*
- "The value of ``Buffer_Size`` in ``Storage_IO``. See
- A.9(10)."
+ "The value of ``Buffer_Size`` in ``Storage_IO``. See A.9(10)."
All type representations are contiguous, and the ``Buffer_Size`` is
the value of ``type'Size`` rounded up to the next storage unit
@@ -662,17 +748,22 @@ boundary.
standard error See A.10(5)."
These files are mapped onto the files provided by the C streams
-libraries. See source file :file:`i-cstrea.ads` for further details.
+libraries. See source file :file:`i-cstrea.ads` for further details.
*
- "The accuracy of the value produced by ``Put``. See
- A.10.9(36)."
+ "The accuracy of the value produced by ``Put``. See A.10.9(36)."
If more digits are requested in the output than are represented by the
precision of the value, zeroes are output in the corresponding least
significant digit positions.
*
+ "Current size for a stream file for which positioning is not supported.
+ See A.12.1(1.1)."
+
+Positioning is supported.
+
+*
"The meaning of ``Argument_Count``, ``Argument``, and
``Command_Name``. See A.15(1)."
@@ -680,80 +771,66 @@ These are mapped onto the ``argv`` and ``argc`` parameters of the
main program in the natural manner.
*
- "The interpretation of the ``Form`` parameter in procedure
- ``Create_Directory``. See A.16(56)."
+ "The interpretation of file names and directory names. See A.16(46)."
-The ``Form`` parameter is not used.
+These names are interpreted consistently with the underlying file system.
*
- "The interpretation of the ``Form`` parameter in procedure
- ``Create_Path``. See A.16(60)."
+ "The maxium value for a file size in Directories. See A.16(87)."
-The ``Form`` parameter is not used.
+Directories.File_Size'Last is equal to Long_Long_Integer'Last .
*
- "The interpretation of the ``Form`` parameter in procedure
- ``Copy_File``. See A.16(68)."
+ "The result for Directories.Size for a directory or special file.
+ See A.16(93)."
-The ``Form`` parameter is case-insensitive.
-Two fields are recognized in the ``Form`` parameter::
+Name_Error is raised.
- *preserve=<value>*
- *mode=<value>*
+*
+ "The result for Directories.Modification_Time for a directory or special file.
+ See A.16(93)."
-<value> starts immediately after the character '=' and ends with the
-character immediately preceding the next comma (',') or with the last
-character of the parameter.
+Name_Error is raised.
-The only possible values for preserve= are:
+*
+ "The interpretation of a nonnull search pattern in Directories.
+ See A.16(104)."
-================== ===================================================================
-Value Meaning
-================== ===================================================================
-*no_attributes* Do not try to preserve any file attributes. This is the
- default if no preserve= is found in Form.
-*all_attributes* Try to preserve all file attributes (timestamps, access rights).
-*timestamps* Preserve the timestamp of the copied file, but not the other
- file attributes.
-================== ===================================================================
+When the ``Pattern`` parameter is not the null string, it is interpreted
+according to the syntax of regular expressions as defined in the
+``GNAT.Regexp`` package.
-The only possible values for mode= are:
+See :ref:`GNAT.Regexp_(g-regexp.ads)`.
-============== ===============================================================================
-Value Meaning
-============== ===============================================================================
-*copy* Only do the copy if the destination file does not already exist.
- If it already exists, Copy_File fails.
-*overwrite* Copy the file in all cases. Overwrite an already existing destination file.
-*append* Append the original file to the destination file. If the destination file
- does not exist, the destination file is a copy of the source file.
- When mode=append, the field preserve=, if it exists, is not taken into account.
-============== ===============================================================================
+*
+ "The results of a Directories search if the contents of the directory are
+ altered while a search is in progress. See A.16(110)."
-If the Form parameter includes one or both of the fields and the value or
-values are incorrect, Copy_file fails with Use_Error.
+The effect of a call to Get_Next_Entry is determined by the current
+state of the directory.
-Examples of correct Forms::
+*
+ "The definition and meaning of an environment variable. See A.17(1)."
- Form => "preserve=no_attributes,mode=overwrite" (the default)
- Form => "mode=append"
- Form => "mode=copy, preserve=all_attributes"
+This definition is determined by the underlying operating system.
-Examples of incorrect Forms::
+*
+ "The circumstances where an environment variable cannot be defined.
+ See A.17(16)."
- Form => "preserve=junk"
- Form => "mode=internal, preserve=timestamps"
+ There are no such implementation-defined circumstances.
*
- "The interpretation of the ``Pattern`` parameter, when not the null string,
- in the ``Start_Search`` and ``Search`` procedures.
- See A.16(104) and A.16(112)."
+ "Environment names for which Set has the effect of Clear. See A.17(17)."
-When the ``Pattern`` parameter is not the null string, it is interpreted
-according to the syntax of regular expressions as defined in the
-``GNAT.Regexp`` package.
+There are no such names.
-See :ref:`GNAT.Regexp_(g-regexp.ads)`.
+*
+ "The value of Containers.Hash_Type'Modulus. The value of
+ Containers.Count_Type'Last. See A.18.1(7)."
+
+Containers.Hash_Type'Modulus is 2**32.
+Containers.Count_Type'Last is 2**31 - 1.
*
"Implementation-defined convention names. See B.1(11)."
@@ -806,9 +883,8 @@ Convention Name Interpretation
Link names are the actual names used by the linker.
*
- "The manner of choosing link names when neither the link
- name nor the address of an imported or exported entity is specified. See
- B.1(36)."
+ "The manner of choosing link names when neither the link name nor the
+ address of an imported or exported entity is specified. See B.1(36)."
The default linker name is that which would be assigned by the relevant
external language, interpreting the Ada name as being in all lower case
@@ -845,6 +921,12 @@ See files with prefix :file:`i-` in the distributed library.
See files with prefix :file:`i-` in the distributed library.
*
+ "The definitions of certain types and constants in Interfaces.C.
+ See B.3(41)."
+
+See source file :file:`i-c.ads`.
+
+*
"The types ``Floating``, ``Long_Floating``,
``Binary``, ``Long_Binary``, ``Decimal_ Element``, and
``COBOL_Character``; and the initialization of the variables
@@ -865,45 +947,54 @@ COBOL Ada
For initialization, see the file :file:`i-cobol.ads` in the distributed library.
*
- "Support for access to machine instructions. See C.1(1)."
+ "The types Fortran_Integer, Real, Double_Precision, and Character_Set
+ in Interfaces.Fortran. See B.5(17)."
-See documentation in file :file:`s-maccod.ads` in the distributed library.
+See source file :file:`i-fortra.ads`. These types are derived, respectively,
+from Integer, Float, Long_Float, and Character.
*
- "Implementation-defined aspects of access to machine
- operations. See C.1(9)."
+ "Implementation-defined intrinsic subprograms. See C.1(1)."
-See documentation in file :file:`s-maccod.ads` in the distributed library.
+See separate section on Intrinsic Subprograms.
*
- "Implementation-defined aspects of interrupts. See C.3(2)."
+ "Any restrictions on a protected procedure or its containing type when an
+ aspect Attach_handler or Interrupt_Handler is specified. See C.3.1(17)."
-Interrupts are mapped to signals or conditions as appropriate. See
-definition of unit
-``Ada.Interrupt_Names`` in source file :file:`a-intnam.ads` for details
-on the interrupts supported on a particular target.
+There are no such restrictions.
*
- "Implementation-defined aspects of pre-elaboration. See
- C.4(13)."
+ "Any other forms of interrupt handler supported by the Attach_Handler and
+ Interrupt_Handler aspects. See C.3.1(19)."
-GNAT does not permit a partition to be restarted without reloading,
-except under control of the debugger.
+There are no such forms.
*
- "The semantics of pragma ``Discard_Names``. See C.5(7)."
+ "The semantics of some attributes and functions of an entity for which
+ aspect Discard_Names is True. See C.5(7)."
-Pragma ``Discard_Names`` causes names of enumeration literals to
-be suppressed. In the presence of this pragma, the Image attribute
+If Discard_Names is True for an enumeration type, the Image attribute
provides the image of the Pos of the literal, and Value accepts
Pos values.
-For tagged types, when pragmas ``Discard_Names`` and ``No_Tagged_Streams``
-simultaneously apply, their Expanded_Name and External_Tag are initialized
-with empty strings. This is useful to avoid exposing entity names at binary
+If both of the aspects``Discard_Names`` and ``No_Tagged_Streams`` are true
+for a tagged type, its Expanded_Name and External_Tag values are
+empty strings. This is useful to avoid exposing entity names at binary
level.
*
+ "The modulus and size of Test_and_Set_Flag. See C.6.3(8)."
+
+The modulus is 2**8. The size is 8.
+
+*
+ "The value used to represent the set value for Atomic_Test_and_Set.
+ See C.6.3(10)."
+
+The value is 1.
+
+*
"The result of the ``Task_Identification.Image``
attribute. See C.7.1(7)."
@@ -939,32 +1030,11 @@ Protected entries or interrupt handlers can be executed by any
convenient thread, so the value of ``Current_Task`` is undefined.
*
- "The effect of calling ``Current_Task`` from an entry
- body or interrupt handler. See C.7.1(19)."
+ "Granularity of locking for Task_Attributes. See C.7.2(16)."
-When GNAT can determine statically that ``Current_Task`` is called directly in
-the body of an entry (or barrier) then a warning is emitted and ``Program_Error``
-is raised at run time. Otherwise, the effect of calling ``Current_Task`` from an
-entry body or interrupt handler is to return the identification of the task
-currently executing the code.
-
-*
- "Implementation-defined aspects of
- ``Task_Attributes``. See C.7.2(19)."
-
-There are no implementation-defined aspects of ``Task_Attributes``.
-
-*
- "Values of all ``Metrics``. See D(2)."
-
-The metrics information for GNAT depends on the performance of the
-underlying operating system. The sources of the run-time for tasking
-implementation, together with the output from *-gnatG* can be
-used to determine the exact sequence of operating systems calls made
-to implement various tasking constructs. Together with appropriate
-information on the performance of the underlying operating system,
-on the exact target in use, this information can be used to determine
-the required metrics.
+No locking is needed if the formal type Attribute has the size and
+alignment of either Integer or System.Address and the bit representation
+of Initial_Value is all zeroes. Otherwise, locking is performed.
*
"The declarations of ``Any_Priority`` and
@@ -993,23 +1063,14 @@ and appropriate, these threads correspond to native threads of the
underlying operating system.
*
- "Implementation-defined *policy_identifiers* allowed
- in a pragma ``Task_Dispatching_Policy``. See D.2.2(3)."
-
-There are no implementation-defined policy-identifiers allowed in this
-pragma.
-
-*
- "Implementation-defined aspects of priority inversion. See
- D.2.2(16)."
+ "Implementation-defined task dispatching policies. See D.2.2(3)."
-Execution of a task cannot be preempted by the implementation processing
-of delay expirations for lower priority tasks.
+There are no implementation-defined task dispatching policies.
*
- "Implementation-defined task dispatching. See D.2.2(18)."
+ "The value of Default_Quantum in Dispatching.Round_Robin. See D.2.5(4)."
-The policy is the same as that of the underlying threads implementation.
+The value is 10 milliseconds.
*
"Implementation-defined *policy_identifiers* allowed
@@ -1045,12 +1106,9 @@ The ceiling priority of internal protected objects is
There are no implementation-defined queuing policies.
*
- "On a multiprocessor, any conditions that cause the
- completion of an aborted construct to be delayed later than what is
- specified for a single processor. See D.6(3)."
+ "Implementation-defined admission policies. See D.4.1(1)."
-The semantics for abort on a multi-processor is the same as on a single
-processor, there are no further delays.
+There are no implementation-defined admission policies.
*
"Any operations that implicitly require heap storage
@@ -1060,43 +1118,75 @@ The only operation that implicitly requires heap storage allocation is
task creation.
*
- "What happens when a task terminates in the presence of
- pragma ``No_Task_Termination``. See D.7(15)."
+ "When restriction No_Dynamic_CPU_Assignment applies to a partition, the
+ processor on which a task with a CPU value of a Not_A_Specific_CPU will
+ execute. See D.7(10)."
+
+Unknown.
+
+*
+ "When restriction No_Task_Termination applies to a partition, what happens
+ when a task terminates. See D.7(15.1)."
+
+Execution is erroneous in that case.
+
+*
+ "The behavior when restriction Max_Storage_At_Blocking is violated.
+ See D.7(17)."
+
+Execution is erroneous in that case.
+
+*
+ "The behavior when restriction Max_Asynchronous_Select_Nesting is violated.
+ See D.7(18)."
+
+Execution is erroneous in that case.
+
+*
+ "The behavior when restriction Max_Tasks is violated. See D.7(19)."
Execution is erroneous in that case.
+* "Whether the use of pragma Restrictions results in a reduction in program
+ code or data size or execution time. See D.7(20)."
+
+ Yes it can, but the precise circumstances and properties of such reductions
+ are difficult to characterize.
+
+*
+ "The value of Barrier_Limit'Last in Synchronous_Barriers. See D.10.1(4)."
+
+Synchronous_Barriers.Barrier_Limit'Last is Integer'Last .
+
*
- "Implementation-defined aspects of pragma
- ``Restrictions``. See D.7(20)."
+ "When an aborted task that is waiting on a Synchronous_Barrier is aborted.
+ See D.10.1(13)."
-There are no such implementation-defined aspects.
+Difficult to characterize.
*
- "Implementation-defined aspects of package
- ``Real_Time``. See D.8(17)."
+ "The value of Min_Handler_Ceiling in Execution_Time.Group_Budgets.
+ See D.14.2(7)."
-There are no implementation defined aspects of package ``Real_Time``.
+See source file :file:`a-etgrbu.ads`.
*
- "Implementation-defined aspects of
- *delay_statements*. See D.9(8)."
+ "The value of CPU_Range'Last in System.Multiprocessors. See D.16(4)."
-Any difference greater than one microsecond will cause the task to be
-delayed (see D.9(7)).
+See source file :file:`s-multip.ads`.
*
- "The upper bound on the duration of interrupt blocking
- caused by the implementation. See D.12(5)."
+ "The processor on which the environment task executes in the absence
+ of a value for the aspect CPU. See D.16(13)."
-The upper bound is determined by the underlying operating system. In
-no cases is it more than 10 milliseconds.
+Unknown.
*
"The means for creating and executing distributed
programs. See E(5)."
The GLADE package provides a utility GNATDIST for creating and executing
-distributed programs. See the GLADE reference manual for further details.
+distributed programs. See the GLADE reference manual for further details.
*
"Any events that can result in a partition becoming
@@ -1105,24 +1195,13 @@ distributed programs. See the GLADE reference manual for further details.
See the GLADE reference manual for full details on such events.
*
- "The scheduling policies, treatment of priorities, and
- management of shared resources between partitions in certain cases. See
- E.1(11)."
+ "The scheduling policies, treatment of priorities, and management of
+ shared resources between partitions in certain cases. See E.1(11)."
See the GLADE reference manual for full details on these aspects of
multi-partition execution.
*
- "Events that cause the version of a compilation unit to
- change. See E.3(5)."
-
-Editing the source file of a compilation unit, or the source files of
-any units on which it is dependent in a significant way cause the version
-to change. No other actions cause the version number to change. All changes
-are significant except those which affect only layout, capitalization or
-comments.
-
-*
"Whether the execution of the remote subprogram is
immediately aborted as a result of cancellation. See E.4(13)."
@@ -1130,14 +1209,12 @@ See the GLADE reference manual for details on the effect of abort in
a distributed application.
*
- "Implementation-defined aspects of the PCS. See E.5(25)."
+ "The range of type System.RPC.Partition_Id. See E.5(14)."
-See the GLADE reference manual for a full description of all implementation
-defined aspects of the PCS.
+System.RPC.Partion_ID'Last is Integer'Last. See source file :file:`s-rpc.ads`.
*
- "Implementation-defined interfaces in the PCS. See
- E.5(26)."
+ "Implementation-defined interfaces in the PCS. See E.5(26)."
See the GLADE reference manual for a full description of all
implementation defined interfaces.
@@ -1228,9 +1305,8 @@ properly generated.
Not relevant, division is IEEE exact.
*
- "The definition of close result set, which determines the
- accuracy of certain fixed point multiplications and divisions. See
- G.2.3(5)."
+ "The definition of close result set, which determines the accuracy of
+ certain fixed point multiplications and divisions. See G.2.3(5)."
Operations in the close result set are performed using IEEE long format
floating-point arithmetic. The input operands are converted to
@@ -1291,28 +1367,20 @@ IEEE infinite and Nan values are produced as appropriate.
Information on those subjects is not yet available.
*
- "Information regarding bounded errors and erroneous
- execution. See H.2(1)."
-
-Information on this subject is not yet available.
-
-*
- "Implementation-defined aspects of pragma
- ``Inspection_Point``. See H.3.2(8)."
+ "The accuracy requirements for the subprograms Solve, Inverse,
+ Determinant, Eigenvalues and Eigensystem for type Real_Matrix.
+ See G.3.1(81)."
-Pragma ``Inspection_Point`` ensures that the variable is live and can
-be examined by the debugger at the inspection point.
+Information on those subjects is not yet available.
*
- "Implementation-defined aspects of pragma
- ``Restrictions``. See H.4(25)."
+ "The accuracy requirements for the subprograms Solve, Inverse,
+ Determinant, Eigenvalues and Eigensystem for type Complex_Matrix.
+ See G.3.2(149)."
-There are no implementation-defined aspects of pragma ``Restrictions``. The
-use of pragma ``Restrictions [No_Exceptions]`` has no effect on the
-generated code. Checks must suppressed by use of pragma ``Suppress``.
+Information on those subjects is not yet available.
*
- "Any restrictions on pragma ``Restrictions``. See
- H.4(27)."
+ "The consequences of violating No_Hidden_Indirect_Globals. See H.4(23.9)."
-There are no restrictions on pragma ``Restrictions``.
+Execution is erroneous in that case.
diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst
index 6c81ca7..0375982 100644
--- a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst
+++ b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst
@@ -2270,8 +2270,15 @@ of GNAT specific extensions are recognized as follows:
values of the composite type shall be covered. The composite type of the
selector shall be a nonlimited untagged (but possibly discriminated)
record type, all of whose subcomponent subtypes are either static discrete
- subtypes or record types that meet the same restrictions. Support for arrays
- is planned, but not yet implemented.
+ subtypes or record types that meet the same restrictions.
+
+ Support for casing on arrays (and on records that contain arrays) is
+ currently subject to some restrictions. Non-positional
+ array aggregates are not supported as (or within) case choices. Likewise
+ for array type and subtype names. The current implementation exceeds
+ compile-time capacity limits in some annoyingly common scenarios; the
+ message generated in such cases is usually "Capacity exceeded in compiling
+ case statement with composite selector type".
In addition, pattern bindings are supported. This is a mechanism
for binding a name to a component of a matching value for use within
@@ -2280,7 +2287,8 @@ of GNAT specific extensions are recognized as follows:
"is <identifier>". In the special case of a "box" component association,
the identifier may instead be provided within the box. Either of these
indicates that the given identifer denotes (a constant view of) the matching
- subcomponent of the case selector.
+ subcomponent of the case selector. Binding is not yet supported for arrays
+ or subcomponents thereof.
Consider this example (which uses type Rec from the previous example):
@@ -4908,43 +4916,6 @@ aspects, but is prepared to ignore the pragmas. The assertion
policy that controls this pragma is ``Post'Class``, not
``Post_Class``.
-Pragma Rename_Pragma
-============================
-.. index:: Pragmas, synonyms
-
-Syntax:
-
-
-::
-
- pragma Rename_Pragma (
- [New_Name =>] IDENTIFIER,
- [Renamed =>] pragma_IDENTIFIER);
-
-This pragma provides a mechanism for supplying new names for existing
-pragmas. The ``New_Name`` identifier can subsequently be used as a synonym for
-the Renamed pragma. For example, suppose you have code that was originally
-developed on a compiler that supports Inline_Only as an implementation defined
-pragma. And suppose the semantics of pragma Inline_Only are identical to (or at
-least very similar to) the GNAT implementation defined pragma
-Inline_Always. You could globally replace Inline_Only with Inline_Always.
-
-However, to avoid that source modification, you could instead add a
-configuration pragma:
-
-.. code-block:: ada
-
- pragma Rename_Pragma (
- New_Name => Inline_Only,
- Renamed => Inline_Always);
-
-
-Then GNAT will treat "pragma Inline_Only ..." as if you had written
-"pragma Inline_Always ...".
-
-Pragma Inline_Only will not necessarily mean the same thing as the other Ada
-compiler; it's up to you to make sure the semantics are close enough.
-
Pragma Pre
==========
.. index:: Pre
@@ -5729,6 +5700,43 @@ In the generic unit, the formal type is subject to all restrictions
pertaining to remote access to class-wide types. At instantiation, the
actual type must be a remote access to class-wide type.
+Pragma Rename_Pragma
+============================
+.. index:: Pragmas, synonyms
+
+Syntax:
+
+
+::
+
+ pragma Rename_Pragma (
+ [New_Name =>] IDENTIFIER,
+ [Renamed =>] pragma_IDENTIFIER);
+
+This pragma provides a mechanism for supplying new names for existing
+pragmas. The ``New_Name`` identifier can subsequently be used as a synonym for
+the Renamed pragma. For example, suppose you have code that was originally
+developed on a compiler that supports Inline_Only as an implementation defined
+pragma. And suppose the semantics of pragma Inline_Only are identical to (or at
+least very similar to) the GNAT implementation defined pragma
+Inline_Always. You could globally replace Inline_Only with Inline_Always.
+
+However, to avoid that source modification, you could instead add a
+configuration pragma:
+
+.. code-block:: ada
+
+ pragma Rename_Pragma (
+ New_Name => Inline_Only,
+ Renamed => Inline_Always);
+
+
+Then GNAT will treat "pragma Inline_Only ..." as if you had written
+"pragma Inline_Always ...".
+
+Pragma Inline_Only will not necessarily mean the same thing as the other Ada
+compiler; it's up to you to make sure the semantics are close enough.
+
Pragma Restricted_Run_Time
==========================
diff --git a/gcc/ada/doc/gnat_rm/security_hardening_features.rst b/gcc/ada/doc/gnat_rm/security_hardening_features.rst
new file mode 100644
index 0000000..1c46e3a4
--- /dev/null
+++ b/gcc/ada/doc/gnat_rm/security_hardening_features.rst
@@ -0,0 +1,89 @@
+.. _Security_Hardening_Features:
+
+***************************
+Security Hardening Features
+***************************
+
+This chapter describes Ada extensions aimed at security hardening that
+are provided by GNAT.
+
+.. Register Scrubbing:
+
+Register Scrubbing
+==================
+
+GNAT can generate code to zero-out hardware registers before returning
+from a subprogram.
+
+It can be enabled with the *-fzero-call-used-regs* command line
+option, to affect all subprograms in a compilation, and with a
+:samp:`Machine_Attribute` pragma, to affect only specific subprograms.
+
+.. code-block:: ada
+
+ procedure Foo;
+ pragma Machine_Attribute (Foo, "zero_call_used_regs", "used");
+ -- Before returning, Foo scrubs only call-clobbered registers
+ -- that it uses itself.
+
+ function Bar return Integer;
+ pragma Machine_Attribute (Bar, "zero_call_used_regs", "all");
+ -- Before returning, Bar scrubs all call-clobbered registers.
+
+
+For usage and more details on the command line option, and on the
+``zero_call_used_regs`` attribute, see :title:`Using the GNU Compiler
+Collection (GCC)`.
+
+
+.. Stack Scrubbing:
+
+Stack Scrubbing
+===============
+
+GNAT can generate code to zero-out stack frames used by subprograms.
+
+It can be activated with the :samp:`Machine_Attribute` pragma, on
+specific subprograms and variables.
+
+.. code-block:: ada
+
+ function Foo returns Integer;
+ pragma Machine_Attribute (Foo, "strub");
+ -- Foo and its callers are modified so as to scrub the stack
+ -- space used by Foo after it returns.
+
+ procedure Bar;
+ pragma Machine_Attribute (Bar, "strub", "internal");
+ -- Bar is turned into a wrapper for its original body,
+ -- and they scrub the stack used by the original body.
+
+ Var : Integer;
+ pragma Machine_Attribute (Var, "strub");
+ -- Reading from Var in a subprogram enables stack scrubbing
+ -- of the stack space used by the subprogram.
+
+
+There are also *-fstrub* command line options to control default
+settings. For usage and more details on the command line option, and
+on the ``strub`` attribute, see :title:`Using the GNU Compiler
+Collection (GCC)`.
+
+Note that Ada secondary stacks are not scrubbed. The restriction
+``No_Secondary_Stack`` avoids their use, and thus their accidental
+preservation of data that should be scrubbed.
+
+Also note that the machine attribute is not integrated in the Ada type
+system. Though it may modify subprogram and variable interfaces, it
+is not fully reflected in Ada types, ``Access`` attributes, renaming
+and overriding. Every access type, renaming, and overriding and
+overridden dispatching operations that may refer to an entity with an
+attribute-modified interface must be annotated with the same
+interface-modifying attribute, or with an interface-compatible one.
+
+Even then, the pragma is currently only functional when applied to
+subprograms and scalar variables; other uses, such as directly on
+types and subtypes, may be silently ignored. Specifically, it is not
+currently recommended to rely on any effects this pragma might be
+expected to have when calling subprograms through access-to-subprogram
+variables.
diff --git a/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst b/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst
index 3e7dc051..cbd780b 100644
--- a/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst
+++ b/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst
@@ -870,6 +870,44 @@ used, the compiler is allowed to suppress the elaboration counter normally
associated with the unit. This counter is typically used to check for access
before elaboration and to control multiple elaboration attempts.
+No_Dynamic_Accessibility_Checks
+-------------------------------
+.. index:: No_Dynamic_Accessibility_Checks
+
+[GNAT] No dynamic accessibility checks are generated when this restriction is
+in effect. Instead, dangling references are prevented via more conservative
+compile-time checking. More specifically, existing compile-time checks are
+enforced but with more conservative assumptions about the accessibility levels
+of the relevant entities. These conservative assumptions eliminate the need for
+dynamic accessibility checks.
+
+These new rules for computing (at compile-time) the accessibility level of an
+anonymous access type T are as follows:
+
+*
+ If T is a function result type then, from the caller's perspective, its level
+ is that of the innermost master enclosing the function call. From the callee's
+ perspective, the level of parameters and local variables of the callee is
+ statically deeper than the level of T.
+
+ For any other accessibility level L such that the level of parameters and local
+ variables of the callee is statically deeper than L, the level of T (from the
+ callee's perspective) is also statically deeper than L.
+*
+ If T is the type of a formal parameter then, from the caller's perspective,
+ its level is at least as deep as that of the type of the corresponding actual
+ parameter (whatever that actual parameter might be). From the callee's
+ perspective, the level of parameters and local variables of the callee is
+ statically deeper than the level of T.
+*
+ If T is the type of a discriminant then its level is that of the discriminated
+ type.
+*
+ If T is the type of a stand-alone object then its level is the level of the
+ object.
+*
+ In all other cases, the level of T is as defined by the existing rules of Ada.
+
No_Dynamic_Sized_Objects
------------------------
.. index:: No_Dynamic_Sized_Objects
diff --git a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
index 5a69967..67fd130 100644
--- a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
+++ b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
@@ -1497,9 +1497,10 @@ Alphabetical List of All Switches
:switch:`-gnateA`
Check that the actual parameters of a subprogram call are not aliases of one
- another. To qualify as aliasing, the actuals must denote objects of a composite
- type, their memory locations must be identical or overlapping, and at least one
- of the corresponding formal parameters must be of mode OUT or IN OUT.
+ another. To qualify as aliasing, their memory locations must be identical or
+ overlapping, at least one of the corresponding formal parameters must be of
+ mode OUT or IN OUT, and at least one of the corresponding formal parameters
+ must have its parameter passing mechanism not specified.
.. code-block:: ada
diff --git a/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst b/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst
index c4f186e..24ef9d6 100644
--- a/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst
+++ b/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst
@@ -3680,8 +3680,9 @@ execution of this erroneous program:
The ``gnatmem`` utility monitors dynamic allocation and
deallocation activity in a program, and displays information about
incorrect deallocations and possible sources of memory leaks.
- It is designed to work in association with a static runtime library
- only and in this context provides three types of information:
+ It is designed to work for fixed-position executables in association
+ with a static runtime library only and in this context provides three
+ types of information:
* General information concerning memory management, such as the total
number of allocations and deallocations, the amount of allocated
@@ -3711,15 +3712,16 @@ execution of this erroneous program:
$ gnatmem [ switches ] [ DEPTH ] user_program
- The program must have been linked with the instrumented version of the
+ The user program must be linked with the instrumented version of the
allocation and deallocation routines. This is done by linking with the
:file:`libgmem.a` library. For correct symbolic backtrace information,
- the user program should be compiled with debugging options
- (see :ref:`Switches_for_gcc`). For example to build :file:`my_program`:
+ the user program should also both be compiled with debugging options
+ (see :ref:`Switches_for_gcc`) and be linked at a fixed position. For
+ example to build :file:`my_program` with ``gnatmake``:
::
- $ gnatmake -g my_program -largs -lgmem
+ $ gnatmake -g my_program -largs -lgmem -no-pie
As library :file:`libgmem.a` contains an alternate body for package
``System.Memory``, :file:`s-memory.adb` should not be compiled and linked
diff --git a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst
index f152ce3..d030cd4 100644
--- a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst
+++ b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst
@@ -4294,10 +4294,13 @@ building specialized scripts.
Standard Output. Has no effect otherwise.
:switch:`--count={N}`
- If specified, compute the symbolic traceback ``N`` times in a row.
- This option is mostly useful for measuring the performance of
- ``gnatsymbolize``, particularly in the case where the cache is
- being used.
+ Compute the symbolic traceback ``N`` times in a row. This option
+ is mostly useful for measuring the performance of ``gnatsymbolize``,
+ particularly in the case where the cache is being used.
+
+ :switch:`--load`
+ Interpret the first address as the load address of the executable.
+ This is needed for position-independent executables on Windows.
Requirements for Correct Operation
----------------------------------
@@ -4311,12 +4314,7 @@ building specialized scripts.
This program provides a functionality similar to ``addr2line``.
It has fewer options to tailor its output, but has been designed
to require fewer of the DWARF sections to be present in the
- executable. In particular, the following sections can be
- stripped from the executable without impact to ``gnatsymbolize``'s
- functionality:
-
- * ``.debug_str``
- * ``.debug_ranges``
+ executable. In particular, it works for code compiled with ``-g1``.
.. only:: PRO or GPL
diff --git a/gcc/ada/doc/gnat_ugn/platform_specific_information.rst b/gcc/ada/doc/gnat_ugn/platform_specific_information.rst
index 13993b8..4f68d25 100644
--- a/gcc/ada/doc/gnat_ugn/platform_specific_information.rst
+++ b/gcc/ada/doc/gnat_ugn/platform_specific_information.rst
@@ -217,7 +217,10 @@ this in a library package body in your application:
(if geteuid = 0 then True else raise Program_Error with "must be root");
It gets the effective user id, and if it's not 0 (i.e. root), it raises
-Program_Error.
+Program_Error. Note that if you re running the code in a container, this may
+not be sufficient, as you may have sufficient priviledge on the container,
+but not on the host machine running the container, so check that you also
+have sufficient priviledge for running the container image.
.. index:: Linux
.. index:: GNU/Linux
diff --git a/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst b/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst
index 39b9ca1..4a3b84d 100644
--- a/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst
+++ b/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst
@@ -1409,16 +1409,12 @@ recognized by GNAT::
Check_Float_Overflow
Check_Name
Check_Policy
- Compile_Time_Error
- Compile_Time_Warning
- Compiler_Unit
- Compiler_Unit_Warning
Component_Alignment
Convention_Identifier
Debug_Policy
- Detect_Blocking
Default_Scalar_Storage_Order
Default_Storage_Pool
+ Detect_Blocking
Disable_Atomic_Synchronization
Discard_Names
Elaboration_Checks
@@ -1437,7 +1433,6 @@ recognized by GNAT::
Locking_Policy
No_Component_Reordering
No_Heap_Finalization
- No_Run_Time
No_Strict_Aliasing
Normalize_Scalars
Optimize_Alignment
@@ -1449,17 +1444,12 @@ recognized by GNAT::
Priority_Specific_Dispatching
Profile
Profile_Warnings
- Propagate_Exceptions
Queuing_Policy
- Rational
- Ravenscar
Rename_Pragma
- Restricted_Run_Time
Restrictions
- Restrictions_Warnings
+ Restriction_Warnings
Reviewable
Short_Circuit_And_Or
- Short_Descriptors
Source_File_Name
Source_File_Name_Project
SPARK_Mode
@@ -1468,7 +1458,6 @@ recognized by GNAT::
Suppress_Exception_Locations
Task_Dispatching_Policy
Unevaluated_Use_Of_Old
- Universal_Data
Unsuppress
Use_VADS_Size
Validity_Checks
@@ -1514,7 +1503,7 @@ only to the unit in which the pragma appears, and not to any other units.
The exception is No_Elaboration_Code which always applies to the entire
object file from a compilation, i.e. to the body, spec, and all subunits.
This restriction can be specified in a configuration pragma file, or it
-can be on the body and/or the spec (in eithe case it applies to all the
+can be on the body and/or the spec (in either case it applies to all the
relevant units). It can appear on a subunit only if it has previously
appeared in the body of spec.
@@ -4526,8 +4515,8 @@ Some of the known limitations include:
constants. Function macros (macros with arguments) are partially translated
as comments, to be completed manually if needed.
* some extensions (e.g. vector types) are not supported
-* pointers to pointers or complex structures are mapped to System.Address
-* identifiers with identical name (except casing) will generate compilation
+* pointers to pointers are mapped to System.Address
+* identifiers with identical name (except casing) may generate compilation
errors (e.g. ``shm_get`` vs ``SHM_GET``).
The code is generated using Ada 2012 syntax, which makes it easier to interface
@@ -4546,14 +4535,17 @@ header files needed by these files transitively. For example:
.. code-block:: sh
- $ g++ -c -fdump-ada-spec -C /usr/include/time.h
+ $ gcc -c -fdump-ada-spec -C /usr/include/time.h
$ gcc -c *.ads
will generate, under GNU/Linux, the following files: :file:`time_h.ads`,
:file:`bits_time_h.ads`, :file:`stddef_h.ads`, :file:`bits_types_h.ads` which
correspond to the files :file:`/usr/include/time.h`,
-:file:`/usr/include/bits/time.h`, etc..., and will then compile these Ada specs
-in Ada 2005 mode.
+:file:`/usr/include/bits/time.h`, etc..., and then compile these Ada specs.
+That is to say, the name of the Ada specs is in keeping with the relative path
+under :file:`/usr/include/` of the header files. This behavior is specific to
+paths ending with :file:`/include/`; in all the other cases, the name of the
+Ada specs is derived from the simple name of the header files instead.
The :switch:`-C` switch tells ``gcc`` to extract comments from headers,
and will attempt to generate corresponding Ada comments.
@@ -4564,39 +4556,8 @@ can use instead the :switch:`-fdump-ada-spec-slim` switch.
You can optionally specify a parent unit, of which all generated units will
be children, using :switch:`-fada-spec-parent={unit}`.
-Note that we recommend when possible to use the *g++* driver to
-generate bindings, even for most C headers, since this will in general
-generate better Ada specs. For generating bindings for C++ headers, it is
-mandatory to use the *g++* command, or *gcc -x c++* which
-is equivalent in this case. If *g++* cannot work on your C headers
-because of incompatibilities between C and C++, then you can fallback to
-``gcc`` instead.
-
-For an example of better bindings generated from the C++ front-end,
-the name of the parameters (when available) are actually ignored by the C
-front-end. Consider the following C header:
-
-.. code-block:: c
-
- extern void foo (int variable);
-
-with the C front-end, ``variable`` is ignored, and the above is handled as:
-
-.. code-block:: c
-
- extern void foo (int);
-
-generating a generic:
-
-.. code-block:: ada
-
- procedure foo (param1 : int);
-
-with the C++ front-end, the name is available, and we generate:
-
-.. code-block:: ada
-
- procedure foo (variable : int);
+The simple ``gcc```-based command works only for C headers. For C++ headers
+you need to use either the ``g++`` command or the combination ``gcc -x c++```.
In some cases, the generated bindings will be more complete or more meaningful
when defining some macros, which you can do via the :switch:`-D` switch. This
@@ -4604,7 +4565,7 @@ is for example the case with :file:`Xlib.h` under GNU/Linux:
.. code-block:: sh
- $ g++ -c -fdump-ada-spec -DXLIB_ILLEGAL_ACCESS -C /usr/include/X11/Xlib.h
+ $ gcc -c -fdump-ada-spec -DXLIB_ILLEGAL_ACCESS -C /usr/include/X11/Xlib.h
The above will generate more complete bindings than a straight call without
the :switch:`-DXLIB_ILLEGAL_ACCESS` switch.
@@ -4626,7 +4587,7 @@ and then generate Ada bindings from this file:
.. code-block:: sh
- $ g++ -c -fdump-ada-spec readline1.h
+ $ gcc -c -fdump-ada-spec readline1.h
.. _Generating_bindings_for_C++_headers:
@@ -4851,7 +4812,7 @@ GNAT and Other Compilation Models
=================================
This section compares the GNAT model with the approaches taken in
-other environents, first the C/C++ model and then the mechanism that
+other environments, first the C/C++ model and then the mechanism that
has been used in other Ada systems, in particular those traditionally
used for Ada 83.
diff --git a/gcc/ada/einfo-utils.adb b/gcc/ada/einfo-utils.adb
index 15bd9e8..0274e6b 100644
--- a/gcc/ada/einfo-utils.adb
+++ b/gcc/ada/einfo-utils.adb
@@ -364,7 +364,9 @@ package body Einfo.Utils is
function Known_Alignment (E : Entity_Id) return B is
begin
- return not Field_Is_Initial_Zero (E, F_Alignment);
+ -- For some reason, Empty is passed to this sometimes
+
+ return No (E) or else not Field_Is_Initial_Zero (E, F_Alignment);
end Known_Alignment;
procedure Reinit_Alignment (Id : E) is
@@ -414,8 +416,7 @@ package body Einfo.Utils is
if Use_New_Unknown_Rep then
return not Field_Is_Initial_Zero (E, F_Esize);
else
- return Esize (E) /= Uint_0
- and then Present (Esize (E));
+ return Present (Esize (E)) and then Esize (E) /= Uint_0;
end if;
end Known_Esize;
@@ -654,16 +655,21 @@ package body Einfo.Utils is
P := Parent (Id);
end if;
+ while Nkind (P) in N_Selected_Component | N_Expanded_Name
+ or else (Nkind (P) = N_Defining_Program_Unit_Name
+ and then Is_Child_Unit (Id))
loop
- if Nkind (P) in N_Selected_Component | N_Expanded_Name
- or else (Nkind (P) = N_Defining_Program_Unit_Name
- and then Is_Child_Unit (Id))
- then
- P := Parent (P);
- else
- return P;
- end if;
+ P := Parent (P);
end loop;
+
+ if Is_Itype (Id)
+ and then Nkind (P) not in
+ N_Full_Type_Declaration | N_Subtype_Declaration
+ then
+ P := Empty;
+ end if;
+
+ return P;
end Declaration_Node;
---------------------
@@ -702,7 +708,7 @@ package body Einfo.Utils is
-- Entry_Index_Type --
----------------------
- function Entry_Index_Type (Id : E) return N is
+ function Entry_Index_Type (Id : E) return E is
begin
pragma Assert (Ekind (Id) = E_Entry_Family);
return Etype (Discrete_Subtype_Definition (Parent (Id)));
@@ -1424,26 +1430,19 @@ package body Einfo.Utils is
function Is_Dynamic_Scope (Id : E) return B is
begin
- return
- Ekind (Id) = E_Block
- or else
- Ekind (Id) = E_Function
- or else
- Ekind (Id) = E_Procedure
- or else
- Ekind (Id) = E_Subprogram_Body
- or else
- Ekind (Id) = E_Task_Type
- or else
- (Ekind (Id) = E_Limited_Private_Type
- and then Present (Full_View (Id))
- and then Ekind (Full_View (Id)) = E_Task_Type)
- or else
- Ekind (Id) = E_Entry
- or else
- Ekind (Id) = E_Entry_Family
+ return Ekind (Id) in E_Block
+ -- Including an E_Block that came from an N_Expression_With_Actions
+ | E_Entry
+ | E_Entry_Family
+ | E_Function
+ | E_Procedure
+ | E_Return_Statement
+ | E_Subprogram_Body
+ | E_Task_Type
or else
- Ekind (Id) = E_Return_Statement;
+ (Ekind (Id) = E_Limited_Private_Type
+ and then Present (Full_View (Id))
+ and then Ekind (Full_View (Id)) = E_Task_Type);
end Is_Dynamic_Scope;
--------------------
@@ -1746,7 +1745,7 @@ package body Einfo.Utils is
-- Link_Entities --
-------------------
- procedure Link_Entities (First : Entity_Id; Second : Node_Id) is
+ procedure Link_Entities (First, Second : Entity_Id) is
begin
if Present (Second) then
Set_Prev_Entity (Second, First); -- First <-- Second
@@ -1975,6 +1974,8 @@ package body Einfo.Utils is
function Next_Index (Id : Node_Id) return Node_Id is
begin
+ pragma Assert (Nkind (Id) in N_Is_Index);
+ pragma Assert (No (Next (Id)) or else Nkind (Next (Id)) in N_Is_Index);
return Next (Id);
end Next_Index;
diff --git a/gcc/ada/einfo-utils.ads b/gcc/ada/einfo-utils.ads
index 4eca35e..8046722 100644
--- a/gcc/ada/einfo-utils.ads
+++ b/gcc/ada/einfo-utils.ads
@@ -625,7 +625,7 @@ package Einfo.Utils is
-- WARNING: There is a matching C declaration of this subprogram in fe.h
- procedure Link_Entities (First : Entity_Id; Second : Entity_Id);
+ procedure Link_Entities (First, Second : Entity_Id);
-- Link entities First and Second in one entity chain.
--
-- NOTE: No updates are done to the First_Entity and Last_Entity fields
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index 39ddd66..0239a70 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -610,12 +610,23 @@ package Einfo is
-- tables must be consulted to determine if there actually is an active
-- Suppress or Unsuppress pragma that applies to the entity.
--- Class_Wide_Clone
--- Defined on subprogram entities. Set if the subprogram has a class-wide
--- pre- or postcondition, and the expression contains calls to other
--- primitive funtions of the type. Used to implement properly the
--- semantics of inherited operations whose class-wide condition may
--- be different from that of the ancestor (See AI012-0195).
+-- Class_Postconditions
+-- Defined on subprogram entities. Set if the subprogram has class-wide
+-- postconditions. Denotes the (and-then) expression built by merging
+-- inherited class-wide postconditions with its own class-wide
+-- postconditions.
+
+-- Class_Preconditions
+-- Defined on subprogram entities. Set if the subprogram has class-wide
+-- preconditions. Denotes the (or-else) expression built by merging
+-- inherited class-wide preconditions with its own class-wide
+-- preconditions.
+
+-- Class_Preconditions_Subprogram
+-- Defined on subprogram entities. Set on subprogram helpers and also on
+-- the indirect-call wrapper internally built for subprograms that have
+-- class-wide preconditions. References the subprogram that has the
+-- class-wide preconditions.
-- Class_Wide_Type
-- Defined in all type entities. For a tagged type or subtype, returns
@@ -746,9 +757,9 @@ package Einfo is
-- Corresponding_Record_Component
-- Defined in components of a derived untagged record type, including
--- discriminants. For a regular component or a girder discriminant,
+-- discriminants. For a regular component or a stored discriminant,
-- points to the corresponding component in the parent type. Set to
--- Empty for a non-girder discriminant. It is used by the back end to
+-- Empty for a non-stored discriminant. It is used by the back end to
-- ensure the layout of the derived type matches that of the parent
-- type when there is no representation clause on the derived type.
@@ -818,7 +829,9 @@ package Einfo is
-- a private type, then we obtain the declaration node denoted by the
-- full type, i.e. the full type declaration node. Also note that for
-- subprograms, this returns the {function,procedure}_specification, not
--- the subprogram_declaration.
+-- the subprogram_declaration. If the parent of an Itype is a type or
+-- subtype declaration, we return the declaration node as for any other
+-- type. For other Itypes, we return Empty.
-- Default_Aspect_Component_Value [base type only]
-- Defined in array types. Holds the static value specified in a
@@ -1029,6 +1042,11 @@ package Einfo is
-- associated with the tagged type. For an untagged record, contains
-- No_Elist.
+-- Dynamic_Call_Helper
+-- Defined on subprogram entities. Set if the subprogram has class-wide
+-- preconditions. Denotes the helper that evaluates at run time the
+-- class-wide preconditions performing dispatching calls.
+
-- DTC_Entity
-- Defined in function and procedure entities. Set to Empty unless
-- the subprogram is dispatching in which case it references the
@@ -2182,6 +2200,18 @@ package Einfo is
-- "off" and indicates that all SPARK_Mode pragmas found within must
-- be ignored.
+-- Ignored_Class_Postconditions
+-- Defined on subprogram entities. Set if the subprogram has class-wide
+-- postconditions. Denotes the (and-then) expression built by merging
+-- inherited ignored class-wide postconditions with its own ignored
+-- class-wide postconditions.
+
+-- Ignored_Class_Preconditions
+-- Defined on subprogram entities. Set if the subprogram has class-wide
+-- preconditions. Denotes the (or-else) expression built by merging
+-- inherited ignored class-wide preconditions with its own ignored
+-- class-wide preconditions.
+
-- Implementation_Base_Type (synthesized)
-- Applies to all entities. For types, similar to Base_Type, but never
-- returns a private type when applied to a non-private type. Instead in
@@ -2216,6 +2246,12 @@ package Einfo is
-- is relocated to the corresponding package body, which must have a
-- corresponding nonlimited with_clause.
+-- Indirect_Call_Wrapper
+-- Defined on subprogram entities. Set if the subprogram has class-wide
+-- preconditions. Denotes the internal wrapper that checks preconditions
+-- and invokes the subprogram body. Subp'Access points to the indirect
+-- call wrapper if available.
+
-- Initialization_Statements
-- Defined in constants and variables. For a composite object initialized
-- with an aggregate that has been converted to a sequence of
@@ -2393,6 +2429,11 @@ package Einfo is
-- Is_Class_Wide_Type (synthesized)
-- Applies to all entities, true for class wide types and subtypes
+-- Is_Class_Wide_Wrapper
+-- Defined in subprogram entities. Indicates that it has been created as
+-- a wrapper in a generic/instance scenario involving a formal type and
+-- a generic primitive operation when the actual is a class-wide type.
+
-- Is_Compilation_Unit
-- Defined in all entities. Set if the entity is a package or subprogram
-- entity for a compilation unit other than a subunit (since we treat
@@ -2400,11 +2441,11 @@ package Einfo is
-- parent, we do not consider them to be separate units for this flag).
-- Is_Completely_Hidden
--- Defined on discriminants. Only set on girder discriminants of
--- untagged types. When set, the entity is a girder discriminant of a
+-- Defined on discriminants. Only set on stored discriminants of
+-- untagged types. When set, the entity is a stored discriminant of a
-- derived untagged type which is not directly visible in the derived
-- type because the derived type or one of its ancestors have renamed the
--- discriminants in the root type. Note: there are girder discriminants
+-- discriminants in the root type. Note: there are stored discriminants
-- which are not Completely_Hidden (e.g. discriminants of a root type).
-- Is_Composite_Type (synthesized)
@@ -2507,6 +2548,11 @@ package Einfo is
-- Applies to all entities. Set to indicate to the backend that this
-- entity is associated with a dispatch table.
+-- Is_Dispatch_Table_Wrapper
+-- Applies to all entities. Set on wrappers built when the subprogram has
+-- class-wide preconditions or class-wide postconditions affected by
+-- overriding (AI12-0195).
+
-- Is_Dispatching_Operation
-- Defined in all entities. Set for procedures, functions, generic
-- procedures, and generic functions if the corresponding operation
@@ -3652,7 +3698,7 @@ package Einfo is
-- Next_Discriminant (synthesized)
-- Applies to discriminants returned by First/Next_Discriminant. Returns
--- the next language-defined (i.e. perhaps non-girder) discriminant by
+-- the next language-defined (i.e. perhaps non-stored) discriminant by
-- following the chain of declared entities as long as the kind of the
-- entity corresponds to a discriminant. Note that the discriminants
-- might be the only components of the record. Returns Empty if there
@@ -3842,8 +3888,8 @@ package Einfo is
-- Rec_Ext.Comp -> Rec_Ext.Parent. ... .Parent.Comp
--
-- In base untagged types:
--- Always points to itself except for non-girder discriminants, where
--- it points to the girder discriminant it renames.
+-- Always points to itself except for non-stored discriminants, where
+-- it points to the stored discriminant it renames.
--
-- In subtypes (tagged and untagged):
-- Points to the component in the base type.
@@ -4401,6 +4447,11 @@ package Einfo is
-- Default_Scalar_Storage_Order (High_Order_First) was active at the time
-- the record or array was declared and therefore applies to it.
+-- Static_Call_Helper
+-- Defined on subprogram entities. Set if the subprogram has class-wide
+-- preconditions. Denotes the helper that evaluates at runtime the
+-- class-wide preconditions performing static calls.
+
-- Static_Discrete_Predicate
-- Defined in discrete types/subtypes with static predicates (with the
-- two flags Has_Predicates and Has_Static_Predicate set). Set if the
@@ -4878,6 +4929,7 @@ package Einfo is
-- Is_Discrim_SO_Function
-- Is_Discriminant_Check_Function
-- Is_Dispatch_Table_Entity
+ -- Is_Dispatch_Table_Wrapper
-- Is_Dispatching_Operation
-- Is_Entry_Formal
-- Is_Exported
@@ -5484,7 +5536,14 @@ package Einfo is
-- Linker_Section_Pragma
-- Contract
-- Import_Pragma (non-generic case only)
- -- Class_Wide_Clone
+ -- Class_Postconditions
+ -- Class_Preconditions
+ -- Class_Preconditions_Subprogram
+ -- Dynamic_Call_Helper
+ -- Ignored_Class_Preconditions
+ -- Ignored_Class_Postconditions
+ -- Indirect_Call_Wrapper
+ -- Static_Call_Helper
-- Protected_Subprogram (non-generic case only)
-- SPARK_Pragma
-- Original_Protected_Subprogram
@@ -5508,6 +5567,7 @@ package Einfo is
-- Ignore_SPARK_Mode_Pragmas
-- Is_Abstract_Subprogram (non-generic case only)
-- Is_Called (non-generic case only)
+ -- Is_Class_Wide_Wrapper
-- Is_Constructor
-- Is_CUDA_Kernel (non-generic case only)
-- Is_DIC_Procedure (non-generic case only)
@@ -5680,6 +5740,7 @@ package Einfo is
-- Default_Expressions_Processed
-- Has_Nested_Subprogram
-- Ignore_SPARK_Mode_Pragmas
+ -- Is_Class_Wide_Wrapper
-- Is_Elaboration_Checks_OK_Id
-- Is_Elaboration_Warnings_OK_Id
-- Is_Intrinsic_Subprogram
@@ -5840,7 +5901,14 @@ package Einfo is
-- Linker_Section_Pragma
-- Contract
-- Import_Pragma (non-generic case only)
- -- Class_Wide_Clone
+ -- Class_Postconditions
+ -- Class_Preconditions
+ -- Class_Preconditions_Subprogram
+ -- Dynamic_Call_Helper
+ -- Ignored_Class_Preconditions
+ -- Ignored_Class_Postconditions
+ -- Indirect_Call_Wrapper
+ -- Static_Call_Helper
-- Protected_Subprogram (non-generic case only)
-- SPARK_Pragma
-- Original_Protected_Subprogram
@@ -5863,6 +5931,7 @@ package Einfo is
-- Is_Abstract_Subprogram (non-generic case only)
-- Is_Asynchronous
-- Is_Called (non-generic case only)
+ -- Is_Class_Wide_Wrapper
-- Is_Constructor
-- Is_CUDA_Kernel
-- Is_DIC_Procedure (non-generic case only)
diff --git a/gcc/ada/err_vars.ads b/gcc/ada/err_vars.ads
index 366df62..819d1ad 100644
--- a/gcc/ada/err_vars.ads
+++ b/gcc/ada/err_vars.ads
@@ -105,12 +105,15 @@ package Err_Vars is
-- of the following global variables to appropriate values before making a
-- call to one of the error message routines with a string containing the
-- insertion character to get the value inserted in an appropriate format.
+ --
+ -- Some of these are initialized below, because they are read before being
+ -- set by clients.
Error_Msg_Col : Column_Number;
-- Column for @ insertion character in message
Error_Msg_Uint_1 : Uint;
- Error_Msg_Uint_2 : Uint;
+ Error_Msg_Uint_2 : Uint := No_Uint;
-- Uint values for ^ insertion characters in message
-- WARNING: There is a matching C declaration of these variables in fe.h
@@ -119,21 +122,21 @@ package Err_Vars is
-- Source location for # insertion character in message
Error_Msg_Name_1 : Name_Id;
- Error_Msg_Name_2 : Name_Id;
- Error_Msg_Name_3 : Name_Id;
+ Error_Msg_Name_2 : Name_Id := No_Name;
+ Error_Msg_Name_3 : Name_Id := No_Name;
-- Name_Id values for % insertion characters in message
Error_Msg_File_1 : File_Name_Type;
- Error_Msg_File_2 : File_Name_Type;
- Error_Msg_File_3 : File_Name_Type;
+ Error_Msg_File_2 : File_Name_Type := No_File;
+ Error_Msg_File_3 : File_Name_Type := No_File;
-- File_Name_Type values for { insertion characters in message
Error_Msg_Unit_1 : Unit_Name_Type;
- Error_Msg_Unit_2 : Unit_Name_Type;
+ Error_Msg_Unit_2 : Unit_Name_Type := No_Unit_Name;
-- Unit_Name_Type values for $ insertion characters in message
Error_Msg_Node_1 : Node_Id;
- Error_Msg_Node_2 : Node_Id;
+ Error_Msg_Node_2 : Node_Id := Empty;
-- Node_Id values for & insertion characters in message
Error_Msg_Warn : Boolean;
diff --git a/gcc/ada/errout.adb b/gcc/ada/errout.adb
index 99c7f9a..05a8266 100644
--- a/gcc/ada/errout.adb
+++ b/gcc/ada/errout.adb
@@ -3602,15 +3602,9 @@ package body Errout is
end if;
-- The following assignment ensures that a second ampersand insertion
- -- character will correspond to the Error_Msg_Node_2 parameter. We
- -- suppress possible validity checks in case operating in -gnatVa mode,
- -- and Error_Msg_Node_2 is not needed and has not been set.
+ -- character will correspond to the Error_Msg_Node_2 parameter.
- declare
- pragma Suppress (Range_Check);
- begin
- Error_Msg_Node_1 := Error_Msg_Node_2;
- end;
+ Error_Msg_Node_1 := Error_Msg_Node_2;
end Set_Msg_Insertion_Node;
--------------------------------------
@@ -3790,15 +3784,9 @@ package body Errout is
end if;
-- The following assignment ensures that a second percent insertion
- -- character will correspond to the Error_Msg_Unit_2 parameter. We
- -- suppress possible validity checks in case operating in -gnatVa mode,
- -- and Error_Msg_Unit_2 is not needed and has not been set.
+ -- character will correspond to the Error_Msg_Unit_2 parameter.
- declare
- pragma Suppress (Range_Check);
- begin
- Error_Msg_Unit_1 := Error_Msg_Unit_2;
- end;
+ Error_Msg_Unit_1 := Error_Msg_Unit_2;
end Set_Msg_Insertion_Unit_Name;
------------------
diff --git a/gcc/ada/erroutc.adb b/gcc/ada/erroutc.adb
index a2cd3c3..9e67b92 100644
--- a/gcc/ada/erroutc.adb
+++ b/gcc/ada/erroutc.adb
@@ -1119,17 +1119,11 @@ package body Erroutc is
end if;
-- The following assignments ensure that the second and third {
- -- insertion characters will correspond to the Error_Msg_File_2 and
- -- Error_Msg_File_3 values and We suppress possible validity checks in
- -- case operating in -gnatVa mode, and Error_Msg_File_2 or
- -- Error_Msg_File_3 is not needed and has not been set.
+ -- insertion characters will correspond to the Error_Msg_File_2
+ -- and Error_Msg_File_3 values.
- declare
- pragma Suppress (Range_Check);
- begin
- Error_Msg_File_1 := Error_Msg_File_2;
- Error_Msg_File_2 := Error_Msg_File_3;
- end;
+ Error_Msg_File_1 := Error_Msg_File_2;
+ Error_Msg_File_2 := Error_Msg_File_3;
end Set_Msg_Insertion_File_Name;
-----------------------------------
@@ -1299,16 +1293,10 @@ package body Erroutc is
-- The following assignments ensure that the second and third percent
-- insertion characters will correspond to the Error_Msg_Name_2 and
- -- Error_Msg_Name_3 as required. We suppress possible validity checks in
- -- case operating in -gnatVa mode, and Error_Msg_Name_1/2 is not needed
- -- and has not been set.
+ -- Error_Msg_Name_3 as required.
- declare
- pragma Suppress (Range_Check);
- begin
- Error_Msg_Name_1 := Error_Msg_Name_2;
- Error_Msg_Name_2 := Error_Msg_Name_3;
- end;
+ Error_Msg_Name_1 := Error_Msg_Name_2;
+ Error_Msg_Name_2 := Error_Msg_Name_3;
end Set_Msg_Insertion_Name;
------------------------------------
@@ -1334,16 +1322,10 @@ package body Erroutc is
-- The following assignments ensure that the second and third % or %%
-- insertion characters will correspond to the Error_Msg_Name_2 and
- -- Error_Msg_Name_3 values and We suppress possible validity checks in
- -- case operating in -gnatVa mode, and Error_Msg_Name_2 or
- -- Error_Msg_Name_3 is not needed and has not been set.
+ -- Error_Msg_Name_3 values.
- declare
- pragma Suppress (Range_Check);
- begin
- Error_Msg_Name_1 := Error_Msg_Name_2;
- Error_Msg_Name_2 := Error_Msg_Name_3;
- end;
+ Error_Msg_Name_1 := Error_Msg_Name_2;
+ Error_Msg_Name_2 := Error_Msg_Name_3;
end Set_Msg_Insertion_Name_Literal;
-------------------------------------
@@ -1427,15 +1409,9 @@ package body Erroutc is
end loop;
-- The following assignment ensures that a second caret insertion
- -- character will correspond to the Error_Msg_Uint_2 parameter. We
- -- suppress possible validity checks in case operating in -gnatVa mode,
- -- and Error_Msg_Uint_2 is not needed and has not been set.
+ -- character will correspond to the Error_Msg_Uint_2 parameter.
- declare
- pragma Suppress (Range_Check);
- begin
- Error_Msg_Uint_1 := Error_Msg_Uint_2;
- end;
+ Error_Msg_Uint_1 := Error_Msg_Uint_2;
end Set_Msg_Insertion_Uint;
-----------------
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index 88303c9..71bad3c 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -124,7 +124,8 @@ package body Exp_Aggr is
-- constants that are done in place.
function Must_Slide
- (Obj_Type : Entity_Id;
+ (Aggr : Node_Id;
+ Obj_Type : Entity_Id;
Typ : Entity_Id) return Boolean;
-- A static array aggregate in an object declaration can in most cases be
-- expanded in place. The one exception is when the aggregate is given
@@ -1776,7 +1777,7 @@ package body Exp_Aggr is
if Nkind (Parent (N)) = N_Assignment_Statement
and then Is_Array_Type (Comp_Typ)
and then Present (Component_Associations (Expr_Q))
- and then Must_Slide (Comp_Typ, Etype (Expr_Q))
+ and then Must_Slide (N, Comp_Typ, Etype (Expr_Q))
then
Set_Expansion_Delayed (Expr_Q, False);
Set_Analyzed (Expr_Q, False);
@@ -5718,6 +5719,15 @@ package body Exp_Aggr is
-- built directly into the target of the assignment it must be free
-- of side effects. N is the LHS of an assignment.
+ procedure Two_Pass_Aggregate_Expansion (N : Node_Id);
+ -- If the aggregate consists only of iterated associations then the
+ -- aggregate is constructed in two steps:
+ -- a) Build an expression to compute the number of elements
+ -- generated by each iterator, and use the expression to allocate
+ -- the destination aggregate.
+ -- b) Generate the loops corresponding to each iterator to insert
+ -- the elements in their proper positions.
+
----------------------------
-- Build_Constrained_Type --
----------------------------
@@ -6334,6 +6344,197 @@ package body Exp_Aggr is
end if;
end Safe_Left_Hand_Side;
+ ----------------------------------
+ -- Two_Pass_Aggregate_Expansion --
+ ----------------------------------
+
+ procedure Two_Pass_Aggregate_Expansion (N : Node_Id) is
+ Loc : constant Source_Ptr := Sloc (N);
+ Comp_Type : constant Entity_Id := Etype (N);
+ Index_Id : constant Entity_Id := Make_Temporary (Loc, 'I', N);
+ Index_Type : constant Entity_Id := Etype (First_Index (Etype (N)));
+ Size_Id : constant Entity_Id := Make_Temporary (Loc, 'I', N);
+ TmpE : constant Entity_Id := Make_Temporary (Loc, 'A', N);
+
+ Assoc : Node_Id := First (Component_Associations (N));
+ Incr : Node_Id;
+ Iter : Node_Id;
+ New_Comp : Node_Id;
+ One_Loop : Node_Id;
+
+ Size_Expr_Code : List_Id;
+ Insertion_Code : List_Id := New_List;
+
+ begin
+ Size_Expr_Code := New_List (
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Size_Id,
+ Object_Definition => New_Occurrence_Of (Standard_Integer, Loc),
+ Expression => Make_Integer_Literal (Loc, 0)));
+
+ -- First pass: execute the iterators to count the number of elements
+ -- that will be generated.
+
+ while Present (Assoc) loop
+ Iter := Iterator_Specification (Assoc);
+ Incr := Make_Assignment_Statement (Loc,
+ Name => New_Occurrence_Of (Size_Id, Loc),
+ Expression =>
+ Make_Op_Add (Loc,
+ Left_Opnd => New_Occurrence_Of (Size_Id, Loc),
+ Right_Opnd => Make_Integer_Literal (Loc, 1)));
+
+ One_Loop := Make_Loop_Statement (Loc,
+ Iteration_Scheme =>
+ Make_Iteration_Scheme (Loc,
+ Iterator_Specification => New_Copy_Tree (Iter)),
+ Statements => New_List (Incr));
+
+ Append (One_Loop, Size_Expr_Code);
+ Next (Assoc);
+ end loop;
+
+ Insert_Actions (N, Size_Expr_Code);
+
+ -- Build a constrained subtype with the calculated length
+ -- and declare the proper bounded aggregate object.
+ -- The index type is some discrete type, so the bounds of the
+ -- constructed array are computed as T'Val (T'Pos (ineger bound));
+
+ declare
+ Pos_Lo : constant Node_Id :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Index_Type, Loc),
+ Attribute_Name => Name_Pos,
+ Expressions => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Index_Type, Loc),
+ Attribute_Name => Name_First)));
+
+ Aggr_Lo : constant Node_Id :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Index_Type, Loc),
+ Attribute_Name => Name_Val,
+ Expressions => New_List (New_Copy_Tree (Pos_Lo)));
+
+ -- Hi = Index_type'Pos (Lo + Size -1).
+
+ Pos_Hi : constant Node_Id :=
+ Make_Op_Add (Loc,
+ Left_Opnd => New_Copy_Tree (Pos_Lo),
+ Right_Opnd =>
+ Make_Op_Subtract (Loc,
+ Left_Opnd => New_Occurrence_Of (Size_Id, Loc),
+ Right_Opnd => Make_Integer_Literal (Loc, 1)));
+
+ -- Corresponding index value
+
+ Aggr_Hi : constant Node_Id :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Index_Type, Loc),
+ Attribute_Name => Name_Val,
+ Expressions => New_List (New_Copy_Tree (Pos_Hi)));
+
+ SubE : constant Entity_Id := Make_Temporary (Loc, 'T');
+ SubD : constant Node_Id :=
+ Make_Subtype_Declaration (Loc,
+ Defining_Identifier => SubE,
+ Subtype_Indication =>
+ Make_Subtype_Indication (Loc,
+ Subtype_Mark =>
+ New_Occurrence_Of (Etype (Comp_Type), Loc),
+ Constraint =>
+ Make_Index_Or_Discriminant_Constraint
+ (Loc,
+ Constraints =>
+ New_List (Make_Range (Loc, Aggr_Lo, Aggr_Hi)))));
+
+ -- Create a temporary array of the above subtype which
+ -- will be used to capture the aggregate assignments.
+
+ TmpD : constant Node_Id :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => TmpE,
+ Object_Definition => New_Occurrence_Of (SubE, Loc));
+ begin
+ Insert_Actions (N, New_List (SubD, TmpD));
+ end;
+
+ -- Second pass: use the iterators to generate the elements of the
+ -- aggregate. Insertion index starts at Index_Type'First. We
+ -- assume that the second evaluation of each iterator generates
+ -- the same number of elements as the first pass, and consider
+ -- that the execution is erroneous (even if the RM does not state
+ -- this explicitly) if the number of elements generated differs
+ -- between first and second pass.
+
+ Assoc := First (Component_Associations (N));
+
+ -- Initialize insertion position to first array component.
+
+ Insertion_Code := New_List (
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Index_Id,
+ Object_Definition =>
+ New_Occurrence_Of (Index_Type, Loc),
+ Expression =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Index_Type, Loc),
+ Attribute_Name => Name_First)));
+
+ while Present (Assoc) loop
+ Iter := Iterator_Specification (Assoc);
+ New_Comp := Make_Assignment_Statement (Loc,
+ Name =>
+ Make_Indexed_Component (Loc,
+ Prefix => New_Occurrence_Of (TmpE, Loc),
+ Expressions =>
+ New_List (New_Occurrence_Of (Index_Id, Loc))),
+ Expression => New_Copy_Tree (Expression (Assoc)));
+
+ -- Advance index position for insertion.
+
+ Incr := Make_Assignment_Statement (Loc,
+ Name => New_Occurrence_Of (Index_Id, Loc),
+ Expression =>
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ New_Occurrence_Of (Index_Type, Loc),
+ Attribute_Name => Name_Succ,
+ Expressions =>
+ New_List (New_Occurrence_Of (Index_Id, Loc))));
+
+ -- Add guard to skip last increment when upper bound is reached.
+
+ Incr := Make_If_Statement (Loc,
+ Condition =>
+ Make_Op_Ne (Loc,
+ Left_Opnd => New_Occurrence_Of (Index_Id, Loc),
+ Right_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Index_Type, Loc),
+ Attribute_Name => Name_Last)),
+ Then_Statements => New_List (Incr));
+
+ One_Loop := Make_Loop_Statement (Loc,
+ Iteration_Scheme =>
+ Make_Iteration_Scheme (Loc,
+ Iterator_Specification => Copy_Separate_Tree (Iter)),
+ Statements => New_List (New_Comp, Incr));
+
+ Append (One_Loop, Insertion_Code);
+ Next (Assoc);
+ end loop;
+
+ Insert_Actions (N, Insertion_Code);
+
+ -- Depending on context this may not work for build-in-place
+ -- arrays ???
+
+ Rewrite (N, New_Occurrence_Of (TmpE, Loc));
+
+ end Two_Pass_Aggregate_Expansion;
+
-- Local variables
Tmp : Entity_Id;
@@ -6371,6 +6572,15 @@ package body Exp_Aggr is
then
return;
+ elsif Present (Component_Associations (N))
+ and then Nkind (First (Component_Associations (N))) =
+ N_Iterated_Component_Association
+ and then
+ Present (Iterator_Specification (First (Component_Associations (N))))
+ then
+ Two_Pass_Aggregate_Expansion (N);
+ return;
+
-- Do not attempt expansion if error already detected. We may reach this
-- point in spite of previous errors when compiling with -gnatq, to
-- force all possible errors (this is the usual ACATS mode).
@@ -6657,7 +6867,7 @@ package body Exp_Aggr is
and then Parent_Kind = N_Object_Declaration
and then Present (Expression (Parent_Node))
and then not
- Must_Slide (Etype (Defining_Identifier (Parent_Node)), Typ)
+ Must_Slide (N, Etype (Defining_Identifier (Parent_Node)), Typ)
and then not Is_Bit_Packed_Array (Typ)
then
In_Place_Assign_OK_For_Declaration := True;
@@ -7038,6 +7248,9 @@ package body Exp_Aggr is
-- or Element_Association with non-static bounds, build an expression
-- to be used as the allocated size of the container. This may be an
-- overestimate if a filter is present, but is a safe approximation.
+ -- If bounds are dynamic the aggregate is created in two passes, and
+ -- the first generates a loop for the sole purpose of computing the
+ -- number of elements that will be generated on the seocnd pass.
procedure Expand_Iterated_Component (Comp : Node_Id);
-- Handle iterated_component_association and iterated_Element
@@ -7185,7 +7398,11 @@ package body Exp_Aggr is
return Build_Siz_Exp (First (Discrete_Choices (Comp)));
elsif Nkind (Comp) = N_Iterated_Element_Association then
- return -1; -- ??? build expression for size of the domain
+ return -1;
+
+ -- ??? Need to create code for a loop and add to generated code,
+ -- as is done for array aggregates with iterated element
+ -- associations, instead of using Append operations.
else
return -1;
@@ -7217,7 +7434,7 @@ package body Exp_Aggr is
if Present (Iterator_Specification (Comp)) then
- -- Either an Iterator_Specification of a Loop_Parameter_
+ -- Either an Iterator_Specification or a Loop_Parameter_
-- Specification is present.
L_Iteration_Scheme :=
@@ -8046,7 +8263,7 @@ package body Exp_Aggr is
Discr : Entity_Id;
Decl : Node_Id;
Num_Disc : Nat := 0;
- Num_Gird : Nat := 0;
+ Num_Stor : Nat := 0;
-- Start of processing for Generate_Aggregate_For_Derived_Type
@@ -8082,13 +8299,13 @@ package body Exp_Aggr is
Discr := First_Stored_Discriminant (Base_Type (Typ));
while Present (Discr) loop
- Num_Gird := Num_Gird + 1;
+ Num_Stor := Num_Stor + 1;
Next_Stored_Discriminant (Discr);
end loop;
-- Case of more stored discriminants than new discriminants
- if Num_Gird > Num_Disc then
+ if Num_Stor > Num_Disc then
-- Create a proper subtype of the parent type, which is the
-- proper implementation type for the aggregate, and convert
@@ -9411,13 +9628,16 @@ package body Exp_Aggr is
----------------
function Must_Slide
- (Obj_Type : Entity_Id;
+ (Aggr : Node_Id;
+ Obj_Type : Entity_Id;
Typ : Entity_Id) return Boolean
is
begin
-- No sliding if the type of the object is not established yet, if it is
-- an unconstrained type whose actual subtype comes from the aggregate,
- -- or if the two types are identical.
+ -- or if the two types are identical. If the aggregate contains only
+ -- an Others_Clause it gets its type from the context and no sliding
+ -- is involved either.
if not Is_Array_Type (Obj_Type) then
return False;
@@ -9428,8 +9648,13 @@ package body Exp_Aggr is
elsif Typ = Obj_Type then
return False;
+ elsif Is_Others_Aggregate (Aggr) then
+ return False;
+
else
-- Sliding can only occur along the first dimension
+ -- If any the bounds of non-static sliding is required
+ -- to force potential range checks.
declare
Bounds1 : constant Range_Nodes :=
@@ -9443,7 +9668,8 @@ package body Exp_Aggr is
not Is_OK_Static_Expression (Bounds1.Last) or else
not Is_OK_Static_Expression (Bounds2.Last)
then
- return False;
+ return True;
+
else
return Expr_Value (Bounds1.First) /= Expr_Value (Bounds2.First)
or else
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb
index c962c2a..096671f 100644
--- a/gcc/ada/exp_attr.adb
+++ b/gcc/ada/exp_attr.adb
@@ -165,8 +165,7 @@ package body Exp_Attr is
-- the appropriate instantiation of System.Fat_Gen. Float arguments in Args
-- have already been converted to the floating-point type for which Pkg was
-- instantiated. The Nam argument is the relevant attribute processing
- -- routine to be called. This is the same as the attribute name, except in
- -- the Unaligned_Valid case.
+ -- routine to be called. This is the same as the attribute name.
procedure Expand_Fpt_Attribute_R (N : Node_Id);
-- This procedure expands a call to a floating-point attribute function
@@ -2216,6 +2215,20 @@ package body Exp_Attr is
if Is_Access_Protected_Subprogram_Type (Btyp) then
Expand_Access_To_Protected_Op (N, Pref, Typ);
+ -- If prefix is a subprogram that has class-wide preconditions and
+ -- an indirect-call wrapper (ICW) of such subprogram is available
+ -- then replace the prefix by the ICW.
+
+ elsif Is_Access_Subprogram_Type (Btyp)
+ and then Is_Entity_Name (Pref)
+ and then Present (Class_Preconditions (Entity (Pref)))
+ and then Present (Indirect_Call_Wrapper (Entity (Pref)))
+ then
+ Rewrite (Pref,
+ New_Occurrence_Of
+ (Indirect_Call_Wrapper (Entity (Pref)), Loc));
+ Analyze_And_Resolve (N, Typ);
+
-- If prefix is a type name, this is a reference to the current
-- instance of the type, within its initialization procedure.
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index 45d5baf..418306f 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -26,6 +26,7 @@
with Aspects; use Aspects;
with Atree; use Atree;
with Checks; use Checks;
+with Contracts; use Contracts;
with Einfo; use Einfo;
with Einfo.Entities; use Einfo.Entities;
with Einfo.Utils; use Einfo.Utils;
@@ -5352,10 +5353,66 @@ package body Exp_Ch3 is
-------------------------------
procedure Expand_Freeze_Record_Type (N : Node_Id) is
+
+ procedure Build_Class_Condition_Subprograms (Typ : Entity_Id);
+ -- Create internal subprograms of Typ primitives that have class-wide
+ -- preconditions or postconditions; they are invoked by the caller to
+ -- evaluate the conditions.
+
procedure Build_Variant_Record_Equality (Typ : Entity_Id);
-- Create An Equality function for the untagged variant record Typ and
-- attach it to the TSS list.
+ procedure Register_Dispatch_Table_Wrappers (Typ : Entity_Id);
+ -- Register dispatch-table wrappers in the dispatch table of Typ
+
+ ---------------------------------------
+ -- Build_Class_Condition_Subprograms --
+ ---------------------------------------
+
+ procedure Build_Class_Condition_Subprograms (Typ : Entity_Id) is
+ Prim_List : constant Elist_Id := Primitive_Operations (Typ);
+ Prim_Elmt : Elmt_Id := First_Elmt (Prim_List);
+ Prim : Entity_Id;
+
+ begin
+ while Present (Prim_Elmt) loop
+ Prim := Node (Prim_Elmt);
+
+ -- Primitive with class-wide preconditions
+
+ if Comes_From_Source (Prim)
+ and then Has_Significant_Contract (Prim)
+ and then
+ (Present (Class_Preconditions (Prim))
+ or else Present (Ignored_Class_Preconditions (Prim)))
+ then
+ if Expander_Active then
+ Make_Class_Precondition_Subps (Prim);
+ end if;
+
+ -- Wrapper of a primitive that has or inherits class-wide
+ -- preconditions.
+
+ elsif Is_Primitive_Wrapper (Prim)
+ and then
+ (Present (Nearest_Class_Condition_Subprogram
+ (Spec_Id => Prim,
+ Kind => Class_Precondition))
+ or else
+ Present (Nearest_Class_Condition_Subprogram
+ (Spec_Id => Prim,
+ Kind => Ignored_Class_Precondition)))
+ then
+ if Expander_Active then
+ Make_Class_Precondition_Subps (Prim);
+ end if;
+ end if;
+
+ Next_Elmt (Prim_Elmt);
+ end loop;
+ end Build_Class_Condition_Subprograms;
+
-----------------------------------
-- Build_Variant_Record_Equality --
-----------------------------------
@@ -5417,6 +5474,27 @@ package body Exp_Ch3 is
end if;
end Build_Variant_Record_Equality;
+ --------------------------------------
+ -- Register_Dispatch_Table_Wrappers --
+ --------------------------------------
+
+ procedure Register_Dispatch_Table_Wrappers (Typ : Entity_Id) is
+ Elmt : Elmt_Id := First_Elmt (Primitive_Operations (Typ));
+ Subp : Entity_Id;
+
+ begin
+ while Present (Elmt) loop
+ Subp := Node (Elmt);
+
+ if Is_Dispatch_Table_Wrapper (Subp) then
+ Append_Freeze_Actions (Typ,
+ Register_Primitive (Sloc (Subp), Subp));
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+ end Register_Dispatch_Table_Wrappers;
+
-- Local variables
Typ : constant Node_Id := Entity (N);
@@ -5666,6 +5744,13 @@ package body Exp_Ch3 is
if not Building_Static_DT (Typ) then
Append_Freeze_Actions (Typ, Make_DT (Typ));
+
+ -- Register dispatch table wrappers in the dispatch table.
+ -- It could not be done when these wrappers were built
+ -- because, at that stage, the dispatch table was not
+ -- available.
+
+ Register_Dispatch_Table_Wrappers (Typ);
end if;
end if;
@@ -5857,6 +5942,13 @@ package body Exp_Ch3 is
end loop;
end;
end if;
+
+ -- Build internal subprograms of primitives with class-wide
+ -- pre/postconditions.
+
+ if Is_Tagged_Type (Typ) then
+ Build_Class_Condition_Subprograms (Typ);
+ end if;
end Expand_Freeze_Record_Type;
------------------------------------
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 497a52b..8dcfa85 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -23,6 +23,7 @@
-- --
------------------------------------------------------------------------------
+with Aspects; use Aspects;
with Atree; use Atree;
with Checks; use Checks;
with Debug; use Debug;
@@ -4703,7 +4704,7 @@ package body Exp_Ch4 is
else
Set_Procedure_To_Call (N,
- Find_Prim_Op (Etype (Pool), Name_Allocate));
+ Find_Storage_Op (Etype (Pool), Name_Allocate));
end if;
end if;
end if;
@@ -6253,6 +6254,46 @@ package body Exp_Ch4 is
return;
end if;
+ -- For the sake of GNATcoverage, generate an intermediate temporary in
+ -- the case where the if-expression is a condition in an outer decision,
+ -- in order to make sure that no branch is shared between the decisions.
+
+ elsif Opt.Suppress_Control_Flow_Optimizations
+ and then Nkind (Original_Node (Parent (N))) in N_Case_Expression
+ | N_Case_Statement
+ | N_If_Expression
+ | N_If_Statement
+ | N_Goto_When_Statement
+ | N_Loop_Statement
+ | N_Return_When_Statement
+ | N_Short_Circuit
+ then
+ declare
+ Cnn : constant Entity_Id := Make_Temporary (Loc, 'C');
+ Acts : List_Id;
+
+ begin
+ -- Generate:
+ -- do
+ -- Cnn : constant Typ := N;
+ -- in Cnn end
+
+ Acts := New_List (
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Cnn,
+ Constant_Present => True,
+ Object_Definition => New_Occurrence_Of (Typ, Loc),
+ Expression => Relocate_Node (N)));
+
+ Rewrite (N,
+ Make_Expression_With_Actions (Loc,
+ Expression => New_Occurrence_Of (Cnn, Loc),
+ Actions => Acts));
+
+ Analyze_And_Resolve (N, Typ);
+ return;
+ end;
+
-- If no actions then no expansion needed, gigi will handle it using the
-- same approach as a C conditional expression.
@@ -6870,7 +6911,6 @@ package body Exp_Ch4 is
if Ada_Version >= Ada_2012
and then Is_Acc
and then Ekind (Ltyp) = E_Anonymous_Access_Type
- and then not No_Dynamic_Accessibility_Checks_Enabled (Lop)
then
declare
Expr_Entity : Entity_Id := Empty;
@@ -6887,11 +6927,26 @@ package body Exp_Ch4 is
end if;
end if;
+ -- When restriction No_Dynamic_Accessibility_Checks is in
+ -- effect, expand the membership test to a static value
+ -- since we cannot rely on dynamic levels.
+
+ if No_Dynamic_Accessibility_Checks_Enabled (Lop) then
+ if Static_Accessibility_Level
+ (Lop, Object_Decl_Level)
+ > Type_Access_Level (Rtyp)
+ then
+ Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
+ else
+ Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
+ end if;
+ Analyze_And_Resolve (N, Restyp);
+
-- If a conversion of the anonymous access value to the
-- tested type would be illegal, then the result is False.
- if not Valid_Conversion
- (Lop, Rtyp, Lop, Report_Errs => False)
+ elsif not Valid_Conversion
+ (Lop, Rtyp, Lop, Report_Errs => False)
then
Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
Analyze_And_Resolve (N, Restyp);
@@ -7047,11 +7102,123 @@ package body Exp_Ch4 is
--------------------------------
procedure Expand_N_Indexed_Component (N : Node_Id) is
+
+ Wild_Reads_May_Have_Bad_Side_Effects : Boolean
+ renames Validity_Check_Subscripts;
+ -- This Boolean needs to be True if reading from a bad address can
+ -- have a bad side effect (e.g., a segmentation fault that is not
+ -- transformed into a Storage_Error exception, or interactions with
+ -- memory-mapped I/O) that needs to be prevented. This refers to the
+ -- act of reading itself, not to any damage that might be caused later
+ -- by making use of whatever value was read. We assume here that
+ -- Validity_Check_Subscripts meets this requirement, but introduce
+ -- this declaration in order to document this assumption.
+
+ function Is_Renamed_Variable_Name (N : Node_Id) return Boolean;
+ -- Returns True if the given name occurs as part of the renaming
+ -- of a variable. In this case, the indexing operation should be
+ -- treated as a write, rather than a read, with respect to validity
+ -- checking. This is because the renamed variable can later be
+ -- written to.
+
+ function Type_Requires_Subscript_Validity_Checks_For_Reads
+ (Typ : Entity_Id) return Boolean;
+ -- If Wild_Reads_May_Have_Bad_Side_Effects is False and we are indexing
+ -- into an array of characters in order to read an element, it is ok
+ -- if an invalid index value goes undetected. But if it is an array of
+ -- pointers or an array of tasks, the consequences of such a read are
+ -- potentially more severe and so we want to detect an invalid index
+ -- value. This function captures that distinction; this is intended to
+ -- be consistent with the "but does not by itself lead to erroneous
+ -- ... execution" rule of RM 13.9.1(11).
+
+ ------------------------------
+ -- Is_Renamed_Variable_Name --
+ ------------------------------
+
+ function Is_Renamed_Variable_Name (N : Node_Id) return Boolean is
+ Rover : Node_Id := N;
+ begin
+ if Is_Variable (N) then
+ loop
+ declare
+ Rover_Parent : constant Node_Id := Parent (Rover);
+ begin
+ case Nkind (Rover_Parent) is
+ when N_Object_Renaming_Declaration =>
+ return Rover = Name (Rover_Parent);
+
+ when N_Indexed_Component
+ | N_Slice
+ | N_Selected_Component
+ =>
+ exit when Rover /= Prefix (Rover_Parent);
+ Rover := Rover_Parent;
+
+ -- No need to check for qualified expressions or type
+ -- conversions here, mostly because of the Is_Variable
+ -- test. It is possible to have a view conversion for
+ -- which Is_Variable yields True and which occurs as
+ -- part of an object renaming, but only if the type is
+ -- tagged; in that case this function will not be called.
+
+ when others =>
+ exit;
+ end case;
+ end;
+ end loop;
+ end if;
+ return False;
+ end Is_Renamed_Variable_Name;
+
+ -------------------------------------------------------
+ -- Type_Requires_Subscript_Validity_Checks_For_Reads --
+ -------------------------------------------------------
+
+ function Type_Requires_Subscript_Validity_Checks_For_Reads
+ (Typ : Entity_Id) return Boolean
+ is
+ -- a shorter name for recursive calls
+ function Needs_Check (Typ : Entity_Id) return Boolean renames
+ Type_Requires_Subscript_Validity_Checks_For_Reads;
+ begin
+ if Is_Access_Type (Typ)
+ or else Is_Tagged_Type (Typ)
+ or else Is_Concurrent_Type (Typ)
+ or else (Is_Array_Type (Typ)
+ and then Needs_Check (Component_Type (Typ)))
+ or else (Is_Scalar_Type (Typ)
+ and then Has_Aspect (Typ, Aspect_Default_Value))
+ then
+ return True;
+ end if;
+
+ if Is_Record_Type (Typ) then
+ declare
+ Comp : Entity_Id := First_Component_Or_Discriminant (Typ);
+ begin
+ while Present (Comp) loop
+ if Needs_Check (Etype (Comp)) then
+ return True;
+ end if;
+
+ Next_Component_Or_Discriminant (Comp);
+ end loop;
+ end;
+ end if;
+
+ return False;
+ end Type_Requires_Subscript_Validity_Checks_For_Reads;
+
+ -- Local constants
+
Loc : constant Source_Ptr := Sloc (N);
Typ : constant Entity_Id := Etype (N);
P : constant Node_Id := Prefix (N);
T : constant Entity_Id := Etype (P);
+ -- Start of processing for Expand_N_Indexed_Component
+
begin
-- A special optimization, if we have an indexed component that is
-- selecting from a slice, then we can eliminate the slice, since, for
@@ -7101,11 +7268,67 @@ package body Exp_Ch4 is
-- Generate index and validity checks
- Generate_Index_Checks (N);
+ declare
+ Dims_Checked : Dimension_Set (Dimensions =>
+ (if Is_Array_Type (T)
+ then Number_Dimensions (T)
+ else 1));
+ -- Dims_Checked is used to avoid generating two checks (one in
+ -- Generate_Index_Checks, one in Apply_Subscript_Validity_Checks)
+ -- for the same index value in cases where the index check eliminates
+ -- the need for the validity check. The Is_Array_Type test avoids
+ -- cascading errors.
- if Validity_Checks_On and then Validity_Check_Subscripts then
- Apply_Subscript_Validity_Checks (N);
- end if;
+ begin
+ Generate_Index_Checks (N, Checks_Generated => Dims_Checked);
+
+ if Validity_Checks_On
+ and then (Validity_Check_Subscripts
+ or else Wild_Reads_May_Have_Bad_Side_Effects
+ or else Type_Requires_Subscript_Validity_Checks_For_Reads
+ (Typ)
+ or else Is_Renamed_Variable_Name (N))
+ then
+ if Validity_Check_Subscripts then
+ -- If we index into an array with an uninitialized variable
+ -- and we generate an index check that passes at run time,
+ -- passing that check does not ensure that the variable is
+ -- valid (although it does in the common case where the
+ -- object's subtype matches the index subtype).
+ -- Consider an uninitialized variable with subtype 1 .. 10
+ -- used to index into an array with bounds 1 .. 20 when the
+ -- value of the uninitialized variable happens to be 15.
+ -- The index check will succeed but the variable is invalid.
+ -- If Validity_Check_Subscripts is True then we need to
+ -- ensure validity, so we adjust Dims_Checked accordingly.
+ Dims_Checked.Elements := (others => False);
+
+ elsif Is_Array_Type (T) then
+ -- We are only adding extra validity checks here to
+ -- deal with uninitialized variables (but this includes
+ -- assigning one uninitialized variable to another). Other
+ -- ways of producing invalid objects imply erroneousness, so
+ -- the compiler can do whatever it wants for those cases.
+ -- If an index type has the Default_Value aspect specified,
+ -- then we don't have to worry about the possibility of an
+ -- uninitialized variable, so no need for these extra
+ -- validity checks.
+
+ declare
+ Idx : Node_Id := First_Index (T);
+ begin
+ for No_Check_Needed of Dims_Checked.Elements loop
+ No_Check_Needed := No_Check_Needed
+ or else Has_Aspect (Etype (Idx), Aspect_Default_Value);
+ Next_Index (Idx);
+ end loop;
+ end;
+ end if;
+
+ Apply_Subscript_Validity_Checks
+ (N, No_Check_Needed => Dims_Checked);
+ end if;
+ end;
-- If selecting from an array with atomic components, and atomic sync
-- is not suppressed for this array type, set atomic sync flag.
@@ -8569,8 +8792,7 @@ package body Exp_Ch4 is
-- f'Machine (expr) to eliminate surprise from extra precision.
if Is_Floating_Point_Type (Typl)
- and then Nkind (Original_Node (Lhs)) = N_Attribute_Reference
- and then Attribute_Name (Original_Node (Lhs)) = Name_Result
+ and then Is_Attribute_Result (Original_Node (Lhs))
then
-- Stick in the Typ'Machine call if not already there
@@ -11338,7 +11560,7 @@ package body Exp_Ch4 is
then
Par := Parent (Par);
- -- Any other case is not what we are looking for
+ -- Any other case is not what we are looking for
else
return False;
@@ -11374,7 +11596,7 @@ package body Exp_Ch4 is
-- Local variables
- Pref : constant Node_Id := Prefix (N);
+ Pref : constant Node_Id := Prefix (N);
-- Start of processing for Expand_N_Slice
@@ -11400,7 +11622,7 @@ package body Exp_Ch4 is
-- situation correctly in the assignment statement expansion).
-- 2. Prefix of indexed component (the slide is optimized away in this
- -- case, see the start of Expand_N_Slice.)
+ -- case, see the start of Expand_N_Indexed_Component.)
-- 3. Object renaming declaration, since we want the name of the
-- slice, not the value.
diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb
index 9827326..21ac2a2 100644
--- a/gcc/ada/exp_ch5.adb
+++ b/gcc/ada/exp_ch5.adb
@@ -31,7 +31,6 @@ with Einfo; use Einfo;
with Einfo.Entities; use Einfo.Entities;
with Einfo.Utils; use Einfo.Utils;
with Elists; use Elists;
-with Errout; use Errout;
with Exp_Aggr; use Exp_Aggr;
with Exp_Ch6; use Exp_Ch6;
with Exp_Ch7; use Exp_Ch7;
@@ -3365,6 +3364,30 @@ package body Exp_Ch5 is
renames Pattern_Match;
-- convenient rename for recursive calls
+ function Indexed_Element (Idx : Pos) return Node_Id;
+ -- Returns the Nth (well, ok, the Idxth) element of Object
+
+ ---------------------
+ -- Indexed_Element --
+ ---------------------
+
+ function Indexed_Element (Idx : Pos) return Node_Id is
+ Obj_Index : constant Node_Id :=
+ Make_Op_Add (Loc,
+ Left_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Attribute_Name => Name_First,
+ Prefix => New_Copy_Tree (Object)),
+ Right_Opnd =>
+ Make_Integer_Literal (Loc, Idx - 1));
+ begin
+ return Make_Indexed_Component (Loc,
+ Prefix => New_Copy_Tree (Object),
+ Expressions => New_List (Obj_Index));
+ end Indexed_Element;
+
+ -- Start of processing for Pattern_Match
+
begin
if Choice_Index /= 0 and not Suppress_Choice_Index_Update then
pragma Assert (Present (Choice_Index_Decl));
@@ -3399,16 +3422,51 @@ package body Exp_Ch5 is
case Nkind (Pattern) is
when N_Aggregate =>
- return Result : Node_Id :=
- New_Occurrence_Of (Standard_True, Loc)
- do
+ declare
+ Result : Node_Id;
+ begin
if Is_Array_Type (Etype (Pattern)) then
- -- Calling Error_Msg_N during expansion is usually a
- -- mistake but is ok for an "unimplemented" message.
- Error_Msg_N
- ("array-valued case choices unimplemented",
- Pattern);
- return;
+
+ -- Nonpositional aggregates currently unimplemented.
+ -- We flag that case during analysis, so an assertion
+ -- is ok here.
+ --
+ pragma Assert
+ (not Is_Non_Empty_List
+ (Component_Associations (Pattern)));
+
+ declare
+ Agg_Length : constant Node_Id :=
+ Make_Integer_Literal (Loc,
+ List_Length (Expressions (Pattern)));
+
+ Obj_Length : constant Node_Id :=
+ Make_Attribute_Reference (Loc,
+ Attribute_Name => Name_Length,
+ Prefix => New_Copy_Tree (Object));
+ begin
+ Result := Make_Op_Eq (Loc,
+ Left_Opnd => Obj_Length,
+ Right_Opnd => Agg_Length);
+ end;
+
+ declare
+ Expr : Node_Id := First (Expressions (Pattern));
+ Idx : Pos := 1;
+ begin
+ while Present (Expr) loop
+ Result :=
+ Make_And_Then (Loc,
+ Left_Opnd => Result,
+ Right_Opnd =>
+ PM (Pattern => Expr,
+ Object => Indexed_Element (Idx)));
+ Next (Expr);
+ Idx := Idx + 1;
+ end loop;
+ end;
+
+ return Result;
end if;
-- positional notation should have been normalized
@@ -3425,6 +3483,8 @@ package body Exp_Ch5 is
Selector_Name => New_Occurrence_Of
(Entity (Choice), Loc)));
begin
+ Result := New_Occurrence_Of (Standard_True, Loc);
+
while Present (Component_Assoc) loop
Choice := First (Choices (Component_Assoc));
while Present (Choice) loop
@@ -3530,27 +3590,82 @@ package body Exp_Ch5 is
Next (Component_Assoc);
end loop;
end;
+ return Result;
+ end;
+
+ when N_String_Literal =>
+ return Result : Node_Id do
+ declare
+ Char_Type : constant Entity_Id :=
+ Root_Type (Component_Type (Etype (Pattern)));
+
+ -- If the component type is not a standard character
+ -- type then this string lit should have already been
+ -- transformed into an aggregate in
+ -- Resolve_String_Literal.
+ --
+ pragma Assert (Is_Standard_Character_Type (Char_Type));
+
+ Str : constant String_Id := Strval (Pattern);
+ Strlen : constant Nat := String_Length (Str);
+
+ Lit_Length : constant Node_Id :=
+ Make_Integer_Literal (Loc, Strlen);
+
+ Obj_Length : constant Node_Id :=
+ Make_Attribute_Reference (Loc,
+ Attribute_Name => Name_Length,
+ Prefix => New_Copy_Tree (Object));
+ begin
+ Result := Make_Op_Eq (Loc,
+ Left_Opnd => Obj_Length,
+ Right_Opnd => Lit_Length);
+
+ for Idx in 1 .. Strlen loop
+ declare
+ C : constant Char_Code :=
+ Get_String_Char (Str, Idx);
+ Obj_Element : constant Node_Id :=
+ Indexed_Element (Idx);
+ Char_Lit : Node_Id;
+ begin
+ Set_Character_Literal_Name (C);
+ Char_Lit :=
+ Make_Character_Literal (Loc,
+ Chars => Name_Find,
+ Char_Literal_Value => UI_From_CC (C));
+
+ Result :=
+ Make_And_Then (Loc,
+ Left_Opnd => Result,
+ Right_Opnd =>
+ Make_Op_Eq (Loc,
+ Left_Opnd => Obj_Element,
+ Right_Opnd => Char_Lit));
+ end;
+ end loop;
+ end;
end return;
when N_Qualified_Expression =>
- -- Make a copy for one of the two uses of Object; the choice
- -- of where to use the original and where to use the copy
- -- is arbitrary.
-
return Make_And_Then (Loc,
Left_Opnd => Make_In (Loc,
Left_Opnd => New_Copy_Tree (Object),
Right_Opnd => New_Copy_Tree (Subtype_Mark (Pattern))),
Right_Opnd =>
PM (Pattern => Expression (Pattern),
- Object => Object));
+ Object => New_Copy_Tree (Object)));
when N_Identifier | N_Expanded_Name =>
if Is_Type (Entity (Pattern)) then
return Make_In (Loc,
- Left_Opnd => Object,
+ Left_Opnd => New_Copy_Tree (Object),
Right_Opnd => New_Occurrence_Of
(Entity (Pattern), Loc));
+ elsif Ekind (Entity (Pattern)) = E_Constant then
+ return PM (Pattern =>
+ Expression (Parent (Entity (Pattern))),
+ Object => Object);
end if;
when N_Others_Choice =>
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index 7717fa7..ce0bb80 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -73,8 +73,10 @@ with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
with Sinfo.Nodes; use Sinfo.Nodes;
with Sinfo.Utils; use Sinfo.Utils;
+with Sinput; use Sinput;
with Snames; use Snames;
with Stand; use Stand;
+with Stringt; use Stringt;
with Tbuild; use Tbuild;
with Uintp; use Uintp;
with Validsw; use Validsw;
@@ -4065,7 +4067,7 @@ package body Exp_Ch6 is
end;
end if;
- -- If the formal is class wide and the actual is an aggregate, force
+ -- If the formal is class-wide and the actual is an aggregate, force
-- evaluation so that the back end who does not know about class-wide
-- type, does not generate a temporary of the wrong size.
@@ -4250,6 +4252,16 @@ package body Exp_Ch6 is
Expand_Interface_Actuals (Call_Node);
end if;
+ -- Install class-wide preconditions runtime check when this is a
+ -- dispatching primitive that has or inherits class-wide preconditions;
+ -- otherwise no runtime check is installed.
+
+ if Nkind (Call_Node) in N_Subprogram_Call
+ and then Is_Dispatching_Operation (Subp)
+ then
+ Install_Class_Preconditions_Check (Call_Node);
+ end if;
+
-- Deals with Dispatch_Call if we still have a call, before expanding
-- extra actuals since this will be done on the re-analysis of the
-- dispatching call. Note that we do not try to shorten the actual list
@@ -4380,6 +4392,7 @@ package body Exp_Ch6 is
-- the current subprogram is called.
if Is_Subprogram (Subp)
+ and then not Is_Ignored_Ghost_Entity (Subp)
and then Same_Or_Aliased_Subprograms (Subp, Current_Scope)
then
Check_Subprogram_Variant;
@@ -7855,18 +7868,6 @@ package body Exp_Ch6 is
-- returned type may not be known yet (for private types).
Compute_Returns_By_Ref (Subp);
-
- -- When freezing a null procedure, analyze its delayed aspects now
- -- because we may not have reached the end of the declarative list when
- -- delayed aspects are normally analyzed. This ensures that dispatching
- -- calls are properly rewritten when the generated _Postcondition
- -- procedure is analyzed in the null procedure body.
-
- if Nkind (Parent (Subp)) = N_Procedure_Specification
- and then Null_Present (Parent (Subp))
- then
- Analyze_Entry_Or_Subprogram_Contract (Subp);
- end if;
end Freeze_Subprogram;
--------------------------
@@ -8101,6 +8102,367 @@ package body Exp_Ch6 is
end if;
end Insert_Post_Call_Actions;
+ ---------------------------------------
+ -- Install_Class_Preconditions_Check --
+ ---------------------------------------
+
+ procedure Install_Class_Preconditions_Check (Call_Node : Node_Id) is
+ Loc : constant Source_Ptr := Sloc (Call_Node);
+
+ function Build_Dynamic_Check_Helper_Call return Node_Id;
+ -- Build call to the helper runtime function of the nearest ancestor
+ -- of the target subprogram that dynamically evaluates the merged
+ -- or-else preconditions.
+
+ function Build_Error_Message (Subp_Id : Entity_Id) return Node_Id;
+ -- Build message associated with the class-wide precondition of Subp_Id
+ -- indicating the call that caused it.
+
+ function Build_Static_Check_Helper_Call return Node_Id;
+ -- Build call to the helper runtime function of the nearest ancestor
+ -- of the target subprogram that dynamically evaluates the merged
+ -- or-else preconditions.
+
+ function Class_Preconditions_Subprogram
+ (Spec_Id : Entity_Id;
+ Dynamic : Boolean) return Node_Id;
+ -- Return the nearest ancestor of Spec_Id defining a helper function
+ -- that evaluates a combined or-else expression containing all the
+ -- inherited class-wide preconditions; Dynamic enables searching for
+ -- the helper that dynamically evaluates preconditions using dispatching
+ -- calls; if False it searches for the helper that statically evaluates
+ -- preconditions; return Empty when not available (which means that no
+ -- preconditions check is required).
+
+ -------------------------------------
+ -- Build_Dynamic_Check_Helper_Call --
+ -------------------------------------
+
+ function Build_Dynamic_Check_Helper_Call return Node_Id is
+ Spec_Id : constant Entity_Id := Entity (Name (Call_Node));
+ CW_Subp : constant Entity_Id :=
+ Class_Preconditions_Subprogram (Spec_Id,
+ Dynamic => True);
+ Helper_Id : constant Entity_Id :=
+ Dynamic_Call_Helper (CW_Subp);
+ Actuals : constant List_Id := New_List;
+ A : Node_Id := First_Actual (Call_Node);
+ F : Entity_Id := First_Formal (Helper_Id);
+
+ begin
+ while Present (A) loop
+
+ -- Ensure that the evaluation of the actuals will not produce
+ -- side effects.
+
+ Remove_Side_Effects (A);
+
+ Append_To (Actuals, New_Copy_Tree (A));
+ Next_Formal (F);
+ Next_Actual (A);
+ end loop;
+
+ return
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Helper_Id, Loc),
+ Parameter_Associations => Actuals);
+ end Build_Dynamic_Check_Helper_Call;
+
+ -------------------------
+ -- Build_Error_Message --
+ -------------------------
+
+ function Build_Error_Message (Subp_Id : Entity_Id) return Node_Id is
+
+ procedure Append_Message
+ (Id : Entity_Id;
+ Is_First : in out Boolean);
+ -- Build the fragment of the message associated with subprogram Id;
+ -- Is_First facilitates identifying continuation messages.
+
+ --------------------
+ -- Append_Message --
+ --------------------
+
+ procedure Append_Message
+ (Id : Entity_Id;
+ Is_First : in out Boolean)
+ is
+ Prag : constant Node_Id := Get_Class_Wide_Pragma (Id,
+ Pragma_Precondition);
+ Msg : Node_Id;
+ Str_Id : String_Id;
+
+ begin
+ if No (Prag) or else Is_Ignored (Prag) then
+ return;
+ end if;
+
+ Msg := Expression (Last (Pragma_Argument_Associations (Prag)));
+ Str_Id := Strval (Msg);
+
+ if Is_First then
+ Is_First := False;
+
+ Append (Global_Name_Buffer, Strval (Msg));
+
+ if Id /= Subp_Id
+ and then Name_Buffer (1 .. 19) = "failed precondition"
+ then
+ Insert_Str_In_Name_Buffer ("inherited ", 8);
+ end if;
+
+ else
+ declare
+ Str : constant String := To_String (Str_Id);
+ From_Idx : Integer;
+
+ begin
+ Append (Global_Name_Buffer, ASCII.LF);
+ Append (Global_Name_Buffer, " or ");
+
+ From_Idx := Name_Len;
+ Append (Global_Name_Buffer, Str_Id);
+
+ if Str (1 .. 19) = "failed precondition" then
+ Insert_Str_In_Name_Buffer ("inherited ", From_Idx + 8);
+ end if;
+ end;
+ end if;
+ end Append_Message;
+
+ -- Local variables
+
+ Str_Loc : constant String := Build_Location_String (Loc);
+ Subps : constant Subprogram_List :=
+ Inherited_Subprograms (Subp_Id);
+ Is_First : Boolean := True;
+
+ -- Start of processing for Build_Error_Message
+
+ begin
+ Name_Len := 0;
+ Append_Message (Subp_Id, Is_First);
+
+ for Index in Subps'Range loop
+ Append_Message (Subps (Index), Is_First);
+ end loop;
+
+ if Present (Controlling_Argument (Call_Node)) then
+ Append (Global_Name_Buffer, " in dispatching call at ");
+ else
+ Append (Global_Name_Buffer, " in call at ");
+ end if;
+
+ Append (Global_Name_Buffer, Str_Loc);
+
+ return Make_String_Literal (Loc, Name_Buffer (1 .. Name_Len));
+ end Build_Error_Message;
+
+ ------------------------------------
+ -- Build_Static_Check_Helper_Call --
+ ------------------------------------
+
+ function Build_Static_Check_Helper_Call return Node_Id is
+ Actuals : constant List_Id := New_List;
+ A : Node_Id;
+ Helper_Id : Entity_Id;
+ F : Entity_Id;
+ CW_Subp : Entity_Id;
+ Spec_Id : constant Entity_Id := Entity (Name (Call_Node));
+
+ begin
+ -- The target is the wrapper built to support inheriting body but
+ -- overriding pre/postconditions (AI12-0195).
+
+ if Is_Dispatch_Table_Wrapper (Spec_Id) then
+ CW_Subp := Spec_Id;
+
+ -- Common case
+
+ else
+ CW_Subp := Class_Preconditions_Subprogram (Spec_Id,
+ Dynamic => False);
+ end if;
+
+ Helper_Id := Static_Call_Helper (CW_Subp);
+
+ F := First_Formal (Helper_Id);
+ A := First_Actual (Call_Node);
+ while Present (A) loop
+
+ -- Ensure that the evaluation of the actuals will not produce
+ -- side effects.
+
+ Remove_Side_Effects (A);
+
+ if Is_Controlling_Actual (A)
+ and then Etype (F) /= Etype (A)
+ then
+ Append_To (Actuals,
+ Make_Unchecked_Type_Conversion (Loc,
+ New_Occurrence_Of (Etype (F), Loc),
+ New_Copy_Tree (A)));
+ else
+ Append_To (Actuals, New_Copy_Tree (A));
+ end if;
+
+ Next_Formal (F);
+ Next_Actual (A);
+ end loop;
+
+ return
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Helper_Id, Loc),
+ Parameter_Associations => Actuals);
+ end Build_Static_Check_Helper_Call;
+
+ ------------------------------------
+ -- Class_Preconditions_Subprogram --
+ ------------------------------------
+
+ function Class_Preconditions_Subprogram
+ (Spec_Id : Entity_Id;
+ Dynamic : Boolean) return Node_Id
+ is
+ Subp_Id : constant Entity_Id := Ultimate_Alias (Spec_Id);
+
+ begin
+ -- Prevent cascaded errors
+
+ if not Is_Dispatching_Operation (Subp_Id) then
+ return Empty;
+
+ -- No need to search if this subprogram has the helper we are
+ -- searching
+
+ elsif Dynamic then
+ if Present (Dynamic_Call_Helper (Subp_Id)) then
+ return Subp_Id;
+ end if;
+ else
+ if Present (Static_Call_Helper (Subp_Id)) then
+ return Subp_Id;
+ end if;
+ end if;
+
+ -- Process inherited subprograms looking for class-wide
+ -- preconditions.
+
+ declare
+ Subps : constant Subprogram_List :=
+ Inherited_Subprograms (Subp_Id);
+ Subp_Id : Entity_Id;
+
+ begin
+ for Index in Subps'Range loop
+ Subp_Id := Subps (Index);
+
+ if Present (Alias (Subp_Id)) then
+ Subp_Id := Ultimate_Alias (Subp_Id);
+ end if;
+
+ -- Wrappers of class-wide pre/postconditions reference the
+ -- parent primitive that has the inherited contract.
+
+ if Is_Wrapper (Subp_Id)
+ and then Present (LSP_Subprogram (Subp_Id))
+ then
+ Subp_Id := LSP_Subprogram (Subp_Id);
+ end if;
+
+ if Dynamic then
+ if Present (Dynamic_Call_Helper (Subp_Id)) then
+ return Subp_Id;
+ end if;
+ else
+ if Present (Static_Call_Helper (Subp_Id)) then
+ return Subp_Id;
+ end if;
+ end if;
+ end loop;
+ end;
+
+ return Empty;
+ end Class_Preconditions_Subprogram;
+
+ -- Local variables
+
+ Dynamic_Check : constant Boolean :=
+ Present (Controlling_Argument (Call_Node));
+ Class_Subp : Entity_Id;
+ Cond : Node_Id;
+ Subp : Entity_Id;
+
+ -- Start of processing for Install_Class_Preconditions_Check
+
+ begin
+ -- Do not expand the check if we are compiling under restriction
+ -- No_Dispatching_Calls; the semantic analyzer has previously
+ -- notified the violation of this restriction.
+
+ if Dynamic_Check
+ and then Restriction_Active (No_Dispatching_Calls)
+ then
+ return;
+
+ -- Class-wide precondition check not needed in interface thunks since
+ -- they are installed in the dispatching call that caused invoking the
+ -- thunk.
+
+ elsif Is_Thunk (Current_Scope) then
+ return;
+ end if;
+
+ Subp := Entity (Name (Call_Node));
+
+ -- No check needed for this subprogram call if no class-wide
+ -- preconditions apply (or if the unique available preconditions
+ -- are ignored preconditions).
+
+ Class_Subp := Class_Preconditions_Subprogram (Subp, Dynamic_Check);
+
+ if No (Class_Subp)
+ or else No (Class_Preconditions (Class_Subp))
+ then
+ return;
+ end if;
+
+ -- Build and install the check
+
+ if Dynamic_Check then
+ Cond := Build_Dynamic_Check_Helper_Call;
+ else
+ Cond := Build_Static_Check_Helper_Call;
+ end if;
+
+ if Exception_Locations_Suppressed then
+ Insert_Action (Call_Node,
+ Make_If_Statement (Loc,
+ Condition => Make_Op_Not (Loc, Cond),
+ Then_Statements => New_List (
+ Make_Raise_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (RTE (RE_Assert_Failure), Loc)))));
+
+ -- Failed check with message indicating the failed precondition and the
+ -- call that caused it.
+
+ else
+ Insert_Action (Call_Node,
+ Make_If_Statement (Loc,
+ Condition => Make_Op_Not (Loc, Cond),
+ Then_Statements => New_List (
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (RTE (RE_Raise_Assert_Failure), Loc),
+ Parameter_Associations =>
+ New_List (Build_Error_Message (Subp))))));
+ end if;
+ end Install_Class_Preconditions_Check;
+
-----------------------------------
-- Is_Build_In_Place_Result_Type --
-----------------------------------
diff --git a/gcc/ada/exp_ch6.ads b/gcc/ada/exp_ch6.ads
index 76cec4d..196f7e6 100644
--- a/gcc/ada/exp_ch6.ads
+++ b/gcc/ada/exp_ch6.ads
@@ -121,6 +121,9 @@ package Exp_Ch6 is
-- The returned node is the root of the procedure body which will replace
-- the original function body, which is not needed for the C program.
+ procedure Install_Class_Preconditions_Check (Call_Node : Node_Id);
+ -- Install check of class-wide preconditions on the caller.
+
function Is_Build_In_Place_Entity (E : Entity_Id) return Boolean;
-- Ada 2005 (AI-318-02): Returns True if E is a BIP entity.
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index 8d08ff1..71cad98 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -486,11 +486,11 @@ package body Exp_Ch7 is
function Make_Deep_Proc
(Prim : Final_Primitives;
Typ : Entity_Id;
- Stmts : List_Id) return Node_Id;
+ Stmts : List_Id) return Entity_Id;
-- This function generates the tree for Deep_Initialize, Deep_Adjust or
- -- Deep_Finalize procedures according to the first parameter, these
- -- procedures operate on the type Typ. The Stmts parameter gives the body
- -- of the procedure.
+ -- Deep_Finalize procedures according to the first parameter. These
+ -- procedures operate on the type Typ. The Stmts parameter gives the
+ -- body of the procedure.
function Make_Deep_Array_Body
(Prim : Final_Primitives;
diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb
index 427b430..694cf90 100644
--- a/gcc/ada/exp_ch9.adb
+++ b/gcc/ada/exp_ch9.adb
@@ -145,7 +145,7 @@ package body Exp_Ch9 is
function Build_Corresponding_Record
(N : Node_Id;
- Ctyp : Node_Id;
+ Ctyp : Entity_Id;
Loc : Source_Ptr) return Node_Id;
-- Common to tasks and protected types. Copy discriminant specifications,
-- build record declaration. N is the type declaration, Ctyp is the
@@ -1583,9 +1583,9 @@ package body Exp_Ch9 is
--------------------------------
function Build_Corresponding_Record
- (N : Node_Id;
- Ctyp : Entity_Id;
- Loc : Source_Ptr) return Node_Id
+ (N : Node_Id;
+ Ctyp : Entity_Id;
+ Loc : Source_Ptr) return Node_Id
is
Rec_Ent : constant Entity_Id :=
Make_Defining_Identifier
@@ -13796,14 +13796,15 @@ package body Exp_Ch9 is
Comp : Node_Id;
Comp_Id : Entity_Id;
Decl_Id : Entity_Id;
+ Nam : Name_Id;
begin
Comp := First (Private_Declarations (Def));
while Present (Comp) loop
if Nkind (Comp) = N_Component_Declaration then
Comp_Id := Defining_Identifier (Comp);
- Decl_Id :=
- Make_Defining_Identifier (Loc, Chars (Comp_Id));
+ Nam := Chars (Comp_Id);
+ Decl_Id := Make_Defining_Identifier (Sloc (Comp_Id), Nam);
-- Minimal decoration
@@ -13818,6 +13819,14 @@ package body Exp_Ch9 is
Set_Is_Aliased (Decl_Id, Is_Aliased (Comp_Id));
Set_Is_Independent (Decl_Id, Is_Independent (Comp_Id));
+ -- Copy the Comes_From_Source flag of the component, as
+ -- the renaming may be the only entity directly seen by
+ -- the user in the context, but do not warn for it.
+
+ Set_Comes_From_Source
+ (Decl_Id, Comes_From_Source (Comp_Id));
+ Set_Warnings_Off (Decl_Id);
+
-- Generate:
-- comp_name : comp_typ renames _object.comp_name;
@@ -13828,10 +13837,8 @@ package body Exp_Ch9 is
New_Occurrence_Of (Etype (Comp_Id), Loc),
Name =>
Make_Selected_Component (Loc,
- Prefix =>
- New_Occurrence_Of (Obj_Ent, Loc),
- Selector_Name =>
- Make_Identifier (Loc, Chars (Comp_Id))));
+ Prefix => New_Occurrence_Of (Obj_Ent, Loc),
+ Selector_Name => Make_Identifier (Loc, Nam)));
Add (Decl);
end if;
@@ -14867,7 +14874,7 @@ package body Exp_Ch9 is
Actuals : List_Id;
Formals : List_Id;
Decls : List_Id;
- Stmts : List_Id) return Node_Id
+ Stmts : List_Id) return Entity_Id
is
Actual : Entity_Id;
Expr : Node_Id := Empty;
diff --git a/gcc/ada/exp_dbug.adb b/gcc/ada/exp_dbug.adb
index a375169..96d78cc 100644
--- a/gcc/ada/exp_dbug.adb
+++ b/gcc/ada/exp_dbug.adb
@@ -409,7 +409,9 @@ package body Exp_Dbug is
when N_Expanded_Name
| N_Identifier
=>
- if not Present (Renamed_Object (Entity (Ren))) then
+ if No (Entity (Ren))
+ or else not Present (Renamed_Object (Entity (Ren)))
+ then
exit;
end if;
diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb
index bac6492..6ade54b 100644
--- a/gcc/ada/exp_disp.adb
+++ b/gcc/ada/exp_disp.adb
@@ -63,7 +63,6 @@ with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
with Sinfo.Nodes; use Sinfo.Nodes;
with Sinfo.Utils; use Sinfo.Utils;
-with Sinput; use Sinput;
with Snames; use Snames;
with Stand; use Stand;
with Stringt; use Stringt;
@@ -348,7 +347,7 @@ package body Exp_Disp is
-- Build_Static_Dispatch_Tables --
----------------------------------
- procedure Build_Static_Dispatch_Tables (N : Entity_Id) is
+ procedure Build_Static_Dispatch_Tables (N : Node_Id) is
Target_List : List_Id;
procedure Build_Dispatch_Tables (List : List_Id);
@@ -697,233 +696,11 @@ package body Exp_Disp is
Eq_Prim_Op : Entity_Id := Empty;
Controlling_Tag : Node_Id;
- procedure Build_Class_Wide_Check (E : Entity_Id);
- -- If the denoted subprogram has a class-wide precondition, generate a
- -- check using that precondition before the dispatching call, because
- -- this is the only class-wide precondition that applies to the call;
- -- otherwise climb to the ancestors searching for the enclosing
- -- overridden primitive of E that has a class-wide precondition (and
- -- use it to generate the check).
-
function New_Value (From : Node_Id) return Node_Id;
-- From is the original Expression. New_Value is equivalent to a call
-- to Duplicate_Subexpr with an explicit dereference when From is an
-- access parameter.
- ----------------------------
- -- Build_Class_Wide_Check --
- ----------------------------
-
- procedure Build_Class_Wide_Check (E : Entity_Id) is
- Subp : Entity_Id := E;
-
- function Has_Class_Wide_Precondition
- (Subp : Entity_Id) return Boolean;
- -- Evaluates if the dispatching subprogram Subp has a class-wide
- -- precondition.
-
- function Replace_Formals (N : Node_Id) return Traverse_Result;
- -- Replace occurrences of the formals of the subprogram by the
- -- corresponding actuals in the call, given that this check is
- -- performed outside of the body of the subprogram.
-
- -- If the dispatching call appears in the same scope as the
- -- declaration of the dispatching subprogram (for example in
- -- the expression of a local expression function), the spec
- -- has not been analyzed yet, in which case we use the Chars
- -- field to recognize intended occurrences of the formals.
-
- ---------------------------------
- -- Has_Class_Wide_Precondition --
- ---------------------------------
-
- function Has_Class_Wide_Precondition
- (Subp : Entity_Id) return Boolean
- is
- Prec : Node_Id := Empty;
-
- begin
- if Present (Contract (Subp))
- and then Present (Pre_Post_Conditions (Contract (Subp)))
- then
- Prec := Pre_Post_Conditions (Contract (Subp));
-
- while Present (Prec) loop
- exit when Pragma_Name (Prec) = Name_Precondition
- and then Class_Present (Prec);
- Prec := Next_Pragma (Prec);
- end loop;
- end if;
-
- return Present (Prec)
- and then not Is_Ignored (Prec);
- end Has_Class_Wide_Precondition;
-
- ---------------------
- -- Replace_Formals --
- ---------------------
-
- function Replace_Formals (N : Node_Id) return Traverse_Result is
- A : Node_Id;
- F : Entity_Id;
- begin
- if Is_Entity_Name (N) then
- F := First_Formal (Subp);
- A := First_Actual (Call_Node);
-
- if Present (Entity (N)) and then Is_Formal (Entity (N)) then
- while Present (F) loop
- if F = Entity (N) then
- if not Is_Controlling_Actual (N) then
- Rewrite (N, New_Copy_Tree (A));
-
- -- If the formal is class-wide, and thus not a
- -- controlling argument, preserve its type because
- -- it may appear in a nested call with a class-wide
- -- parameter.
-
- if Is_Class_Wide_Type (Etype (F)) then
- Set_Etype (N, Etype (F));
-
- -- Conversely, if this is a controlling argument
- -- (in a dispatching call in the condition) that
- -- is a dereference, the source is an access-to-
- -- -class-wide type, so preserve the dispatching
- -- nature of the call in the rewritten condition.
-
- elsif Nkind (Parent (N)) = N_Explicit_Dereference
- and then Is_Controlling_Actual (Parent (N))
- then
- Set_Controlling_Argument (Parent (Parent (N)),
- Parent (N));
- end if;
-
- -- Ensure that the type of the controlling actual
- -- matches the type of the controlling formal of the
- -- parent primitive Subp defining the class-wide
- -- precondition.
-
- elsif Is_Class_Wide_Type (Etype (A)) then
- Rewrite (N,
- Convert_To
- (Class_Wide_Type (Etype (F)),
- New_Copy_Tree (A)));
-
- else
- Rewrite (N,
- Convert_To
- (Etype (F),
- New_Copy_Tree (A)));
- end if;
-
- exit;
- end if;
-
- Next_Formal (F);
- Next_Actual (A);
- end loop;
-
- -- If the node is not analyzed, recognize occurrences of a
- -- formal by name, as would be done when resolving the aspect
- -- expression in the context of the subprogram.
-
- elsif not Analyzed (N)
- and then Nkind (N) = N_Identifier
- and then No (Entity (N))
- then
- while Present (F) loop
- if Chars (N) = Chars (F) then
- Rewrite (N, New_Copy_Tree (A));
- return Skip;
- end if;
-
- Next_Formal (F);
- Next_Actual (A);
- end loop;
- end if;
- end if;
-
- return OK;
- end Replace_Formals;
-
- procedure Update is new Traverse_Proc (Replace_Formals);
-
- -- Local variables
-
- Str_Loc : constant String := Build_Location_String (Loc);
-
- A : Node_Id;
- Cond : Node_Id;
- Msg : Node_Id;
- Prec : Node_Id;
-
- -- Start of processing for Build_Class_Wide_Check
-
- begin
- -- Climb searching for the enclosing class-wide precondition
-
- while not Has_Class_Wide_Precondition (Subp)
- and then Present (Overridden_Operation (Subp))
- loop
- Subp := Overridden_Operation (Subp);
- end loop;
-
- -- Locate class-wide precondition, if any
-
- if Present (Contract (Subp))
- and then Present (Pre_Post_Conditions (Contract (Subp)))
- then
- Prec := Pre_Post_Conditions (Contract (Subp));
-
- while Present (Prec) loop
- exit when Pragma_Name (Prec) = Name_Precondition
- and then Class_Present (Prec);
- Prec := Next_Pragma (Prec);
- end loop;
-
- if No (Prec) or else Is_Ignored (Prec) then
- return;
- end if;
-
- -- Ensure that the evaluation of the actuals will not produce side
- -- effects (since the check will use a copy of the actuals).
-
- A := First_Actual (Call_Node);
- while Present (A) loop
- Remove_Side_Effects (A);
- Next_Actual (A);
- end loop;
-
- -- The expression for the precondition is analyzed within the
- -- generated pragma. The message text is the last parameter of
- -- the generated pragma, indicating source of precondition.
-
- Cond :=
- New_Copy_Tree
- (Expression (First (Pragma_Argument_Associations (Prec))));
- Update (Cond);
-
- -- Build message indicating the failed precondition and the
- -- dispatching call that caused it.
-
- Msg := Expression (Last (Pragma_Argument_Associations (Prec)));
- Name_Len := 0;
- Append (Global_Name_Buffer, Strval (Msg));
- Append (Global_Name_Buffer, " in dispatching call at ");
- Append (Global_Name_Buffer, Str_Loc);
- Msg := Make_String_Literal (Loc, Name_Buffer (1 .. Name_Len));
-
- Insert_Action (Call_Node,
- Make_If_Statement (Loc,
- Condition => Make_Op_Not (Loc, Cond),
- Then_Statements => New_List (
- Make_Procedure_Call_Statement (Loc,
- Name =>
- New_Occurrence_Of (RTE (RE_Raise_Assert_Failure), Loc),
- Parameter_Associations => New_List (Msg)))));
- end if;
- end Build_Class_Wide_Check;
-
---------------
-- New_Value --
---------------
@@ -984,8 +761,6 @@ package body Exp_Disp is
Subp := Alias (Subp);
end if;
- Build_Class_Wide_Check (Subp);
-
-- Definition of the class-wide type and the tagged type
-- If the controlling argument is itself a tag rather than a tagged
@@ -1016,6 +791,10 @@ package body Exp_Disp is
Typ := Find_Specific_Type (CW_Typ);
+ -- The tagged type of a dispatching call must be frozen at this stage
+
+ pragma Assert (Is_Frozen (Typ));
+
if not Is_Limited_Type (Typ) then
Eq_Prim_Op := Find_Prim_Op (Typ, Name_Op_Eq);
end if;
@@ -5924,6 +5703,11 @@ package body Exp_Disp is
Set_Is_True_Constant (TSD, Building_Static_DT (Typ));
+ -- The debugging information for type Ada.Tags.Type_Specific_Data is
+ -- needed by the debugger in order to display values of tagged types.
+
+ Set_Needs_Debug_Info (TSD, Needs_Debug_Info (Typ));
+
-- Initialize or declare the dispatch table object
if not Has_DT (Typ) then
diff --git a/gcc/ada/exp_intr.adb b/gcc/ada/exp_intr.adb
index 45de0fb..86cb702 100644
--- a/gcc/ada/exp_intr.adb
+++ b/gcc/ada/exp_intr.adb
@@ -1151,7 +1151,7 @@ package body Exp_Intr is
else
Set_Procedure_To_Call
- (Free_Nod, Find_Prim_Op (Etype (Pool), Name_Deallocate));
+ (Free_Nod, Find_Storage_Op (Etype (Pool), Name_Deallocate));
end if;
end if;
diff --git a/gcc/ada/exp_prag.adb b/gcc/ada/exp_prag.adb
index 43ecdcd..27b4e7d 100644
--- a/gcc/ada/exp_prag.adb
+++ b/gcc/ada/exp_prag.adb
@@ -752,10 +752,10 @@ package body Exp_Prag is
-- value of which is Init_Val if present or null if not.
function Build_Simple_Declaration_With_Default
- (Decl_Id : Entity_Id;
- Init_Val : Entity_Id;
- Typ : Entity_Id;
- Default_Val : Entity_Id) return Node_Id;
+ (Decl_Id : Entity_Id;
+ Init_Val : Node_Id;
+ Typ : Node_Id;
+ Default_Val : Node_Id) return Node_Id;
-- Build a declaration the Defining_Identifier of which is Decl_Id, the
-- Object_Definition of which is Typ, the value of which is Init_Val if
-- present or Default otherwise.
@@ -983,7 +983,7 @@ package body Exp_Prag is
function Build_Simple_Declaration_With_Default
(Decl_Id : Entity_Id;
Init_Val : Node_Id;
- Typ : Entity_Id;
+ Typ : Node_Id;
Default_Val : Node_Id) return Node_Id
is
Value : Node_Id := Init_Val;
@@ -1525,9 +1525,7 @@ package body Exp_Prag is
begin
-- Attribute 'Old
- if Nkind (N) = N_Attribute_Reference
- and then Attribute_Name (N) = Name_Old
- then
+ if Is_Attribute_Old (N) then
Pref := Prefix (N);
Indirect := Indirect_Temp_Needed (Etype (Pref));
@@ -2862,7 +2860,7 @@ package body Exp_Prag is
procedure Expand_Pragma_Subprogram_Variant
(Prag : Node_Id;
- Subp_Id : Node_Id;
+ Subp_Id : Entity_Id;
Body_Decls : List_Id)
is
Curr_Decls : List_Id;
diff --git a/gcc/ada/exp_smem.adb b/gcc/ada/exp_smem.adb
index 45db487..216065f5 100644
--- a/gcc/ada/exp_smem.adb
+++ b/gcc/ada/exp_smem.adb
@@ -86,7 +86,7 @@ package body Exp_Smem is
function Build_Shared_Var_Proc_Call
(Loc : Source_Ptr;
- E : Node_Id;
+ E : Entity_Id;
N : Name_Id) return Node_Id;
-- Build a call to support procedure N for shared object E (provided by the
-- instance of System.Shared_Storage.Shared_Var_Procs associated to E).
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index ad5a6fa..cb18096 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -1270,11 +1270,10 @@ package body Exp_Util is
---------------------------------
procedure Build_Class_Wide_Expression
- (Prag : Node_Id;
- Subp : Entity_Id;
- Par_Subp : Entity_Id;
- Adjust_Sloc : Boolean;
- Needs_Wrapper : out Boolean)
+ (Pragma_Or_Expr : Node_Id;
+ Subp : Entity_Id;
+ Par_Subp : Entity_Id;
+ Adjust_Sloc : Boolean)
is
function Replace_Entity (N : Node_Id) return Traverse_Result;
-- Replace reference to formal of inherited operation or to primitive
@@ -1294,7 +1293,7 @@ package body Exp_Util is
Adjust_Inherited_Pragma_Sloc (N);
end if;
- if Nkind (N) = N_Identifier
+ if Nkind (N) in N_Identifier | N_Operator_Symbol
and then Present (Entity (N))
and then
(Is_Formal (Entity (N)) or else Is_Subprogram (Entity (N)))
@@ -1319,84 +1318,6 @@ package body Exp_Util is
if Present (New_E) then
Rewrite (N, New_Occurrence_Of (New_E, Sloc (N)));
-
- -- AI12-0166: a precondition for a protected operation
- -- cannot include an internal call to a protected function
- -- of the type. In the case of an inherited condition for an
- -- overriding operation, both the operation and the function
- -- are given by primitive wrappers.
- -- Move this check to sem???
-
- if Ekind (New_E) = E_Function
- and then Is_Primitive_Wrapper (New_E)
- and then Is_Primitive_Wrapper (Subp)
- and then Scope (Subp) = Scope (New_E)
- and then Chars (Pragma_Identifier (Prag)) = Name_Precondition
- then
- Error_Msg_Node_2 := Wrapped_Entity (Subp);
- Error_Msg_NE
- ("internal call to& cannot appear in inherited "
- & "precondition of protected operation&",
- N, Wrapped_Entity (New_E));
- end if;
-
- -- If the entity is an overridden primitive and we are not
- -- in GNATprove mode, we must build a wrapper for the current
- -- inherited operation. If the reference is the prefix of an
- -- attribute such as 'Result (or others ???) there is no need
- -- for a wrapper: the condition is just rewritten in terms of
- -- the inherited subprogram.
-
- if Is_Subprogram (New_E)
- and then Nkind (Parent (N)) /= N_Attribute_Reference
- and then not GNATprove_Mode
- then
- Needs_Wrapper := True;
- end if;
- end if;
-
- -- Check that there are no calls left to abstract operations if
- -- the current subprogram is not abstract.
- -- Move this check to sem???
-
- if Nkind (Parent (N)) = N_Function_Call
- and then N = Name (Parent (N))
- then
- if not Is_Abstract_Subprogram (Subp)
- and then Is_Abstract_Subprogram (Entity (N))
- then
- Error_Msg_Sloc := Sloc (Current_Scope);
- Error_Msg_Node_2 := Subp;
- if Comes_From_Source (Subp) then
- Error_Msg_NE
- ("cannot call abstract subprogram & in inherited "
- & "condition for&#", Subp, Entity (N));
- else
- Error_Msg_NE
- ("cannot call abstract subprogram & in inherited "
- & "condition for inherited&#", Subp, Entity (N));
- end if;
-
- -- In SPARK mode, reject an inherited condition for an
- -- inherited operation if it contains a call to an overriding
- -- operation, because this implies that the pre/postconditions
- -- of the inherited operation have changed silently.
-
- elsif SPARK_Mode = On
- and then Warn_On_Suspicious_Contract
- and then Present (Alias (Subp))
- and then Present (New_E)
- and then Comes_From_Source (New_E)
- then
- Error_Msg_N
- ("cannot modify inherited condition (SPARK RM 6.1.1(1))",
- Parent (Subp));
- Error_Msg_Sloc := Sloc (New_E);
- Error_Msg_Node_2 := Subp;
- Error_Msg_NE
- ("\overriding of&# forces overriding of&",
- Parent (Subp), New_E);
- end if;
end if;
-- Update type of function call node, which should be the same as
@@ -1422,26 +1343,17 @@ package body Exp_Util is
-- Local variables
- Par_Formal : Entity_Id;
- Subp_Formal : Entity_Id;
+ Par_Typ : constant Entity_Id := Find_Dispatching_Type (Par_Subp);
+ Subp_Typ : constant Entity_Id := Find_Dispatching_Type (Subp);
-- Start of processing for Build_Class_Wide_Expression
begin
- Needs_Wrapper := False;
+ pragma Assert (Par_Typ /= Subp_Typ);
- -- Add mapping from old formals to new formals
-
- Par_Formal := First_Formal (Par_Subp);
- Subp_Formal := First_Formal (Subp);
-
- while Present (Par_Formal) and then Present (Subp_Formal) loop
- Type_Map.Set (Par_Formal, Subp_Formal);
- Next_Formal (Par_Formal);
- Next_Formal (Subp_Formal);
- end loop;
-
- Replace_Condition_Entities (Prag);
+ Update_Primitives_Mapping (Par_Subp, Subp);
+ Map_Formals (Par_Subp, Subp);
+ Replace_Condition_Entities (Pragma_Or_Expr);
end Build_Class_Wide_Expression;
--------------------
@@ -1895,7 +1807,33 @@ package body Exp_Util is
Priv_Typ : Entity_Id;
-- The partial view of Par_Typ
+ Op_Node : Elmt_Id;
+ Par_Prim : Entity_Id;
+ Prim : Entity_Id;
+
begin
+ -- Map the overridden primitive to the overriding one; required by
+ -- Replace_References (called by Add_Inherited_DICs) to handle calls
+ -- to parent primitives.
+
+ Op_Node := First_Elmt (Primitive_Operations (T));
+ while Present (Op_Node) loop
+ Prim := Node (Op_Node);
+
+ if Present (Overridden_Operation (Prim))
+ and then Comes_From_Source (Prim)
+ then
+ Par_Prim := Overridden_Operation (Prim);
+
+ -- Create a mapping of the form:
+ -- parent type primitive -> derived type primitive
+
+ Type_Map.Set (Par_Prim, Prim);
+ end if;
+
+ Next_Elmt (Op_Node);
+ end loop;
+
-- Climb the parent type chain
Curr_Typ := T;
@@ -2097,14 +2035,11 @@ package body Exp_Util is
Stmts => Stmts);
end if;
- -- Otherwise the "full" DIC procedure verifies the DICs of the full
- -- view, well as DICs inherited from parent types. In addition, it
- -- indirectly verifies the DICs of the partial view by calling the
- -- "partial" DIC procedure.
+ -- Otherwise, the "full" DIC procedure verifies the DICs inherited from
+ -- parent types, as well as indirectly verifying the DICs of the partial
+ -- view by calling the "partial" DIC procedure.
else
- pragma Assert (Present (Full_Typ));
-
-- Check the DIC of the partial view by calling the "partial" DIC
-- procedure, unless the partial DIC body is empty. Generate:
@@ -2118,44 +2053,6 @@ package body Exp_Util is
New_Occurrence_Of (Obj_Id, Loc))));
end if;
- -- Derived subtypes do not have a partial view
-
- if Present (Priv_Typ) then
-
- -- The processing of the "full" DIC procedure intentionally
- -- skips the partial view because a) this may result in changes of
- -- visibility and b) lead to duplicate checks. However, when the
- -- full view is the underlying full view of an untagged derived
- -- type whose parent type is private, partial DICs appear on
- -- the rep item chain of the partial view only.
-
- -- package Pack_1 is
- -- type Root ... is private;
- -- private
- -- <full view of Root>
- -- end Pack_1;
-
- -- with Pack_1;
- -- package Pack_2 is
- -- type Child is new Pack_1.Root with Type_DIC => ...;
- -- <underlying full view of Child>
- -- end Pack_2;
-
- -- As a result, the processing of the full view must also consider
- -- all DICs of the partial view.
-
- if Is_Untagged_Private_Derivation (Priv_Typ, Full_Typ) then
- null;
-
- -- Otherwise the DICs of the partial view are ignored
-
- else
- -- Ignore the DICs of the partial view by eliminating the view
-
- Priv_Typ := Empty;
- end if;
- end if;
-
-- Process inherited Default_Initial_Conditions for all parent types
Add_Parent_DICs (Work_Typ, Obj_Id, Stmts);
@@ -4914,7 +4811,7 @@ package body Exp_Util is
-- Convert_To_Actual_Subtype --
-------------------------------
- procedure Convert_To_Actual_Subtype (Exp : Entity_Id) is
+ procedure Convert_To_Actual_Subtype (Exp : Node_Id) is
Act_ST : Entity_Id;
begin
@@ -6359,6 +6256,32 @@ package body Exp_Util is
raise Program_Error;
end Find_Protection_Type;
+ function Find_Storage_Op
+ (Typ : Entity_Id;
+ Nam : Name_Id) return Entity_Id
+ is
+ use Sem_Util.Storage_Model_Support;
+
+ begin
+ if Has_Storage_Model_Type_Aspect (Typ) then
+ declare
+ SMT_Op : constant Entity_Id :=
+ Get_Storage_Model_Type_Entity (Typ, Nam);
+ begin
+ if not Present (SMT_Op) then
+ raise Program_Error;
+ else
+ return SMT_Op;
+ end if;
+ end;
+
+ -- Otherwise we assume that Typ is a descendant of Root_Storage_Pool
+
+ else
+ return Find_Prim_Op (Typ, Nam);
+ end if;
+ end Find_Storage_Op;
+
-----------------------
-- Find_Hook_Context --
-----------------------
@@ -7048,7 +6971,7 @@ package body Exp_Util is
-- Get_Index_Subtype --
-----------------------
- function Get_Index_Subtype (N : Node_Id) return Node_Id is
+ function Get_Index_Subtype (N : Node_Id) return Entity_Id is
P_Type : Entity_Id := Etype (Prefix (N));
Indx : Node_Id;
J : Int;
@@ -7073,6 +6996,15 @@ package body Exp_Util is
return Etype (Indx);
end Get_Index_Subtype;
+ -----------------------
+ -- Get_Mapped_Entity --
+ -----------------------
+
+ function Get_Mapped_Entity (E : Entity_Id) return Entity_Id is
+ begin
+ return Type_Map.Get (E);
+ end Get_Mapped_Entity;
+
---------------------
-- Get_Stream_Size --
---------------------
@@ -10350,6 +10282,36 @@ package body Exp_Util is
end if;
end Make_Variant_Comparison;
+ -----------------
+ -- Map_Formals --
+ -----------------
+
+ procedure Map_Formals
+ (Parent_Subp : Entity_Id;
+ Derived_Subp : Entity_Id;
+ Force_Update : Boolean := False)
+ is
+ Par_Formal : Entity_Id := First_Formal (Parent_Subp);
+ Subp_Formal : Entity_Id := First_Formal (Derived_Subp);
+
+ begin
+ if Force_Update then
+ Type_Map.Set (Parent_Subp, Derived_Subp);
+ end if;
+
+ -- At this stage either we are under regular processing and the caller
+ -- has previously ensured that these primitives are already mapped (by
+ -- means of calling previously to Update_Primitives_Mapping), or we are
+ -- processing a late-overriding primitive and Force_Update updated above
+ -- the mapping of these primitives.
+
+ while Present (Par_Formal) and then Present (Subp_Formal) loop
+ Type_Map.Set (Par_Formal, Subp_Formal);
+ Next_Formal (Par_Formal);
+ Next_Formal (Subp_Formal);
+ end loop;
+ end Map_Formals;
+
---------------
-- Map_Types --
---------------
@@ -10645,7 +10607,7 @@ package body Exp_Util is
end if;
-- Otherwise the constraint denotes a reference to some name
- -- which results in a Girder discriminant:
+ -- which results in a Stored discriminant:
-- vvvv
-- Name : ...;
@@ -10666,7 +10628,7 @@ package body Exp_Util is
return Find_Constraint_Value (Entity (Constr));
-- Otherwise the current constraint is an expression which yields
- -- a Girder discriminant:
+ -- a Stored discriminant:
-- type Typ (D1 : ...; DN : ...) is
-- new Anc (Discr => <expression>) with ...
@@ -10741,7 +10703,7 @@ package body Exp_Util is
-- that D_2 constrains D_1, therefore if the algorithm finds the
-- value of D_2, then this would also be the value for D_1.
- -- 2.2) The constraint is a name (aka Girder):
+ -- 2.2) The constraint is a name (aka Stored):
-- Name : ...
-- type Ancestor_1 (D_1 : ...) is tagged ...
@@ -10750,7 +10712,7 @@ package body Exp_Util is
-- In this case the name is the final value of D_1 because the
-- discriminant cannot be further constrained.
- -- 2.3) The constraint is an expression (aka Girder):
+ -- 2.3) The constraint is an expression (aka Stored):
-- type Ancestor_1 (D_1 : ...) is tagged ...
-- type Ancestor_2 is new Ancestor_1 (D_1 => 1 + 2) ...
@@ -10861,7 +10823,7 @@ package body Exp_Util is
-- they relate to the primitives of the parent type. If there is a
-- meaningful relation, create a mapping of the form:
- -- parent type primitive -> perived type primitive
+ -- parent type primitive -> derived type primitive
if Present (Direct_Primitive_Operations (Deriv_Typ)) then
Prim_Elmt := First_Elmt (Direct_Primitive_Operations (Deriv_Typ));
@@ -11801,10 +11763,15 @@ package body Exp_Util is
-- case and it is better not to make an additional one for the attribute
-- itself, because the return type of many of them is universal integer,
-- which is a very large type for a temporary.
+ -- The prefix of an attribute reference Reduce may be syntactically an
+ -- aggregate, but will be expanded into a loop, so no need to remove
+ -- side-effects.
if Nkind (Exp) = N_Attribute_Reference
and then Side_Effect_Free_Attribute (Attribute_Name (Exp))
and then Side_Effect_Free (Expressions (Exp), Name_Req, Variable_Ref)
+ and then (Attribute_Name (Exp) /= Name_Reduce
+ or else Nkind (Prefix (Exp)) /= N_Aggregate)
and then not Is_Name_Reference (Prefix (Exp))
then
Remove_Side_Effects (Prefix (Exp), Name_Req, Variable_Ref);
@@ -14123,10 +14090,12 @@ package body Exp_Util is
(Inher_Id : Entity_Id;
Subp_Id : Entity_Id)
is
+ Parent_Type : constant Entity_Id := Find_Dispatching_Type (Inher_Id);
+ Derived_Type : constant Entity_Id := Find_Dispatching_Type (Subp_Id);
+
begin
- Map_Types
- (Parent_Type => Find_Dispatching_Type (Inher_Id),
- Derived_Type => Find_Dispatching_Type (Subp_Id));
+ pragma Assert (Parent_Type /= Derived_Type);
+ Map_Types (Parent_Type, Derived_Type);
end Update_Primitives_Mapping;
----------------------------------
diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads
index 56ff61f..2b61132 100644
--- a/gcc/ada/exp_util.ads
+++ b/gcc/ada/exp_util.ads
@@ -270,28 +270,16 @@ package Exp_Util is
-- not install a call to Abort_Defer.
procedure Build_Class_Wide_Expression
- (Prag : Node_Id;
- Subp : Entity_Id;
- Par_Subp : Entity_Id;
- Adjust_Sloc : Boolean;
- Needs_Wrapper : out Boolean);
- -- Build the expression for an inherited class-wide condition. Prag is
- -- the pragma constructed from the corresponding aspect of the parent
- -- subprogram, and Subp is the overriding operation, and Par_Subp is
- -- the overridden operation that has the condition. Adjust_Sloc is True
- -- when the sloc of nodes traversed should be adjusted for the inherited
- -- pragma. The routine is also called to check whether an inherited
- -- operation that is not overridden but has inherited conditions needs
- -- a wrapper, because the inherited condition includes calls to other
- -- primitives that have been overridden. In that case the first argument
- -- is the expression of the original class-wide aspect. In SPARK_Mode, such
- -- operation which are just inherited but have modified pre/postconditions
- -- are illegal.
- -- If there are calls to overridden operations in the condition, and the
- -- pragma applies to an inherited operation, a wrapper must be built for
- -- it to capture the new inherited condition. The flag Needs_Wrapper is
- -- set in that case so that the wrapper can be built, when the controlling
- -- type is frozen.
+ (Pragma_Or_Expr : Node_Id;
+ Subp : Entity_Id;
+ Par_Subp : Entity_Id;
+ Adjust_Sloc : Boolean);
+ -- Build the expression for an inherited class-wide condition. Pragma_Or_
+ -- _Expr is either the pragma constructed from the corresponding aspect of
+ -- the parent subprogram or the class-wide pre/postcondition built from the
+ -- parent, Subp is the overriding operation, and Par_Subp is the overridden
+ -- operation that has the condition. Adjust_Sloc is True when the sloc of
+ -- nodes traversed should be adjusted for the inherited pragma.
function Build_DIC_Call
(Loc : Source_Ptr;
@@ -612,7 +600,7 @@ package Exp_Util is
function Find_Prim_Op (T : Entity_Id; Name : Name_Id) return Entity_Id;
-- Find the first primitive operation of a tagged type T with name Name.
-- This function allows the use of a primitive operation which is not
- -- directly visible. If T is a class wide type, then the reference is to an
+ -- directly visible. If T is a class-wide type, then the reference is to an
-- operation of the corresponding root type. It is an error if no primitive
-- operation with the given name is found.
@@ -640,6 +628,16 @@ package Exp_Util is
-- Given a protected type or its corresponding record, find the type of
-- field _object.
+ function Find_Storage_Op
+ (Typ : Entity_Id;
+ Nam : Name_Id) return Entity_Id;
+ -- Given type Typ that's either a descendant of Root_Storage_Pool or else
+ -- specifies aspect Storage_Model_Type, returns the Entity_Id of the
+ -- subprogram associated with Nam, which must either be a primitive op of
+ -- the type in the case of a storage pool, or the operation corresponding
+ -- to Nam as specified in the aspect Storage_Model_Type. It is an error if
+ -- no operation corresponding to the given name is found.
+
function Find_Hook_Context (N : Node_Id) return Node_Id;
-- Determine a suitable node on which to attach actions related to N that
-- need to be elaborated unconditionally. In general this is the topmost
@@ -739,6 +737,10 @@ package Exp_Util is
-- Used for First, Last, and Length, when the prefix is an array type.
-- Obtains the corresponding index subtype.
+ function Get_Mapped_Entity (E : Entity_Id) return Entity_Id;
+ -- Return the mapped entity of E; used to check inherited class-wide
+ -- pre/postconditions.
+
function Get_Stream_Size (E : Entity_Id) return Uint;
-- Return the stream size value of the subtype E
@@ -918,6 +920,15 @@ package Exp_Util is
-- Subprogram_Variant. Generate a comparison between Curr_Val and Old_Val
-- depending on the variant mode (Increases / Decreases).
+ procedure Map_Formals
+ (Parent_Subp : Entity_Id;
+ Derived_Subp : Entity_Id;
+ Force_Update : Boolean := False);
+ -- Establish the mapping from the formals of Parent_Subp to the formals
+ -- of Derived_Subp; if Force_Update is True then mapping of Parent_Subp to
+ -- Derived_Subp is also updated; used to update mapping of late-overriding
+ -- primitives of a tagged type.
+
procedure Map_Types (Parent_Type : Entity_Id; Derived_Type : Entity_Id);
-- Establish the following mapping between the attributes of tagged parent
-- type Parent_Type and tagged derived type Derived_Type.
@@ -1205,5 +1216,6 @@ package Exp_Util is
private
pragma Inline (Duplicate_Subexpr);
pragma Inline (Force_Evaluation);
+ pragma Inline (Get_Mapped_Entity);
pragma Inline (Is_Library_Level_Tagged_Type);
end Exp_Util;
diff --git a/gcc/ada/fe.h b/gcc/ada/fe.h
index 488e811..957f40b 100644
--- a/gcc/ada/fe.h
+++ b/gcc/ada/fe.h
@@ -61,10 +61,12 @@ extern void Compiler_Abort (String_Pointer, String_Pointer, Boolean) ATTRIBUTE_N
#define Debug_Flag_Dot_KK debug__debug_flag_dot_kk
#define Debug_Flag_Dot_R debug__debug_flag_dot_r
+#define Debug_Flag_Dot_8 debug__debug_flag_dot_8
#define Debug_Flag_NN debug__debug_flag_nn
extern Boolean Debug_Flag_Dot_KK;
extern Boolean Debug_Flag_Dot_R;
+extern Boolean Debug_Flag_Dot_8;
extern Boolean Debug_Flag_NN;
/* einfo: */
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index 15ce832..5f81d9e 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -35,6 +35,7 @@ with Elists; use Elists;
with Errout; use Errout;
with Exp_Ch3; use Exp_Ch3;
with Exp_Ch7; use Exp_Ch7;
+with Exp_Disp; use Exp_Disp;
with Exp_Pakd; use Exp_Pakd;
with Exp_Util; use Exp_Util;
with Exp_Tss; use Exp_Tss;
@@ -56,6 +57,7 @@ with Sem_Ch6; use Sem_Ch6;
with Sem_Ch7; use Sem_Ch7;
with Sem_Ch8; use Sem_Ch8;
with Sem_Ch13; use Sem_Ch13;
+with Sem_Disp; use Sem_Disp;
with Sem_Eval; use Sem_Eval;
with Sem_Mech; use Sem_Mech;
with Sem_Prag; use Sem_Prag;
@@ -132,11 +134,6 @@ package body Freeze is
-- Attribute references to outer types are freeze points for those types;
-- this routine generates the required freeze nodes for them.
- procedure Check_Inherited_Conditions (R : Entity_Id);
- -- For a tagged derived type, create wrappers for inherited operations
- -- that have a class-wide condition, so it can be properly rewritten if
- -- it involves calls to other overriding primitives.
-
procedure Check_Strict_Alignment (E : Entity_Id);
-- E is a base type. If E is tagged or has a component that is aliased
-- or tagged or contains something this is aliased or tagged, set
@@ -160,7 +157,7 @@ package body Freeze is
procedure Freeze_Enumeration_Type (Typ : Entity_Id);
-- Freeze enumeration type. The Esize field is set as processing
-- proceeds (i.e. set by default when the type is declared and then
- -- adjusted by rep clauses. What this procedure does is to make sure
+ -- adjusted by rep clauses). What this procedure does is to make sure
-- that if a foreign convention is specified, and no specific size
-- is given, then the size must be at least Integer'Size.
@@ -284,11 +281,11 @@ package body Freeze is
-- Full_View or Corresponding_Record_Type.
procedure Warn_Overlay (Expr : Node_Id; Typ : Entity_Id; Nam : Node_Id);
- -- Expr is the expression for an address clause for entity Nam whose type
- -- is Typ. If Typ has a default initialization, and there is no explicit
- -- initialization in the source declaration, check whether the address
- -- clause might cause overlaying of an entity, and emit a warning on the
- -- side effect that the initialization will cause.
+ -- Expr is the expression for an address clause for the entity denoted by
+ -- Nam whose type is Typ. If Typ has a default initialization, and there is
+ -- no explicit initialization in the source declaration, check whether the
+ -- address clause might cause overlaying of an entity, and emit a warning
+ -- on the side effect that the initialization will cause.
-------------------------------
-- Adjust_Esize_For_Alignment --
@@ -636,13 +633,26 @@ package body Freeze is
Next (Param_Spec);
end loop;
- Body_Node :=
- Make_Subprogram_Body (Loc,
- Specification => Spec,
- Declarations => New_List,
- Handled_Statement_Sequence =>
- Make_Handled_Sequence_Of_Statements (Loc,
- Statements => New_List (Call_Node)));
+ -- In GNATprove, prefer to generate an expression function whenever
+ -- possible, to benefit from the more precise analysis in that case
+ -- (as if an implicit postcondition had been generated).
+
+ if GNATprove_Mode
+ and then Nkind (Call_Node) = N_Simple_Return_Statement
+ then
+ Body_Node :=
+ Make_Expression_Function (Loc,
+ Specification => Spec,
+ Expression => Expression (Call_Node));
+ else
+ Body_Node :=
+ Make_Subprogram_Body (Loc,
+ Specification => Spec,
+ Declarations => New_List,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Call_Node)));
+ end if;
if Nkind (Decl) /= N_Subprogram_Declaration then
Rewrite (N,
@@ -1352,9 +1362,15 @@ package body Freeze is
elsif Is_Record_Type (Encl_Base)
and then not Comp_Byte_Aligned
then
- Error_Msg_N
- ("type of non-byte-aligned component must have same scalar "
- & "storage order as enclosing composite", Err_Node);
+ if Present (Component_Clause (Comp)) then
+ Error_Msg_N
+ ("type of non-byte-aligned component must have same scalar"
+ & " storage order as enclosing record", Err_Node);
+ else
+ Error_Msg_N
+ ("type of packed component must have same scalar"
+ & " storage order as enclosing record", Err_Node);
+ end if;
-- Warn if specified only for the outer composite
@@ -1464,90 +1480,322 @@ package body Freeze is
-- Check_Inherited_Conditions --
--------------------------------
- procedure Check_Inherited_Conditions (R : Entity_Id) is
- Prim_Ops : constant Elist_Id := Primitive_Operations (R);
- Decls : List_Id;
- Needs_Wrapper : Boolean;
- Op_Node : Elmt_Id;
- Par_Prim : Entity_Id;
- Prim : Entity_Id;
-
- procedure Build_Inherited_Condition_Pragmas (Subp : Entity_Id);
+ procedure Check_Inherited_Conditions
+ (R : Entity_Id;
+ Late_Overriding : Boolean := False)
+ is
+ Prim_Ops : constant Elist_Id := Primitive_Operations (R);
+ Decls : List_Id;
+ Op_Node : Elmt_Id;
+ Par_Prim : Entity_Id;
+ Prim : Entity_Id;
+ Wrapper_Needed : Boolean;
+
+ function Build_DTW_Body
+ (Loc : Source_Ptr;
+ DTW_Spec : Node_Id;
+ DTW_Decls : List_Id;
+ Par_Prim : Entity_Id;
+ Wrapped_Subp : Entity_Id) return Node_Id;
+ -- Build the body of the dispatch table wrapper containing the given
+ -- spec and declarations; the call to the wrapped subprogram includes
+ -- the proper type conversion.
+
+ function Build_DTW_Spec (Par_Prim : Entity_Id) return Node_Id;
+ -- Build the spec of the dispatch table wrapper
+
+ procedure Build_Inherited_Condition_Pragmas
+ (Subp : Entity_Id;
+ Wrapper_Needed : out Boolean);
-- Build corresponding pragmas for an operation whose ancestor has
- -- class-wide pre/postconditions. If the operation is inherited, the
- -- pragmas force the creation of a wrapper for the inherited operation.
- -- If the ancestor is being overridden, the pragmas are constructed only
- -- to verify their legality, in case they contain calls to other
- -- primitives that may have been overridden.
+ -- class-wide pre/postconditions. If the operation is inherited then
+ -- Wrapper_Needed is returned True to force the creation of a wrapper
+ -- for the inherited operation. If the ancestor is being overridden,
+ -- the pragmas are constructed only to verify their legality, in case
+ -- they contain calls to other primitives that may have been overridden.
+
+ function Needs_Wrapper
+ (Class_Cond : Node_Id;
+ Subp : Entity_Id;
+ Par_Subp : Entity_Id) return Boolean;
+ -- Checks whether the dispatch-table wrapper (DTW) for Subp must be
+ -- built to evaluate the given class-wide condition.
+
+ --------------------
+ -- Build_DTW_Body --
+ --------------------
+
+ function Build_DTW_Body
+ (Loc : Source_Ptr;
+ DTW_Spec : Node_Id;
+ DTW_Decls : List_Id;
+ Par_Prim : Entity_Id;
+ Wrapped_Subp : Entity_Id) return Node_Id
+ is
+ Par_Typ : constant Entity_Id := Find_Dispatching_Type (Par_Prim);
+ Actuals : constant List_Id := Empty_List;
+ Call : Node_Id;
+ Formal : Entity_Id := First_Formal (Par_Prim);
+ New_F_Spec : Entity_Id := First (Parameter_Specifications (DTW_Spec));
+ New_Formal : Entity_Id;
+
+ begin
+ -- Build parameter association for call to wrapped subprogram
+
+ while Present (Formal) loop
+ New_Formal := Defining_Identifier (New_F_Spec);
+
+ -- If the controlling argument is inherited, add conversion to
+ -- parent type for the call.
+
+ if Etype (Formal) = Par_Typ
+ and then Is_Controlling_Formal (Formal)
+ then
+ Append_To (Actuals,
+ Make_Type_Conversion (Loc,
+ New_Occurrence_Of (Par_Typ, Loc),
+ New_Occurrence_Of (New_Formal, Loc)));
+ else
+ Append_To (Actuals, New_Occurrence_Of (New_Formal, Loc));
+ end if;
+
+ Next_Formal (Formal);
+ Next (New_F_Spec);
+ end loop;
+
+ if Ekind (Wrapped_Subp) = E_Procedure then
+ Call :=
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Occurrence_Of (Wrapped_Subp, Loc),
+ Parameter_Associations => Actuals);
+ else
+ Call :=
+ Make_Simple_Return_Statement (Loc,
+ Expression =>
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Wrapped_Subp, Loc),
+ Parameter_Associations => Actuals));
+ end if;
+
+ return
+ Make_Subprogram_Body (Loc,
+ Specification => Copy_Subprogram_Spec (DTW_Spec),
+ Declarations => DTW_Decls,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Call),
+ End_Label => Make_Identifier (Loc,
+ Chars (Defining_Entity (DTW_Spec)))));
+ end Build_DTW_Body;
+
+ --------------------
+ -- Build_DTW_Spec --
+ --------------------
+
+ function Build_DTW_Spec (Par_Prim : Entity_Id) return Node_Id is
+ DTW_Id : Entity_Id;
+ DTW_Spec : Node_Id;
+
+ begin
+ DTW_Spec := Build_Overriding_Spec (Par_Prim, R);
+ DTW_Id := Defining_Entity (DTW_Spec);
+
+ -- Add minimal decoration of fields
+
+ Mutate_Ekind (DTW_Id, Ekind (Par_Prim));
+ Set_LSP_Subprogram (DTW_Id, Par_Prim);
+ Set_Is_Dispatch_Table_Wrapper (DTW_Id);
+ Set_Is_Wrapper (DTW_Id);
+
+ -- The DTW wrapper is never a null procedure
+
+ if Nkind (DTW_Spec) = N_Procedure_Specification then
+ Set_Null_Present (DTW_Spec, False);
+ end if;
+
+ return DTW_Spec;
+ end Build_DTW_Spec;
---------------------------------------
-- Build_Inherited_Condition_Pragmas --
---------------------------------------
- procedure Build_Inherited_Condition_Pragmas (Subp : Entity_Id) is
- A_Post : Node_Id;
- A_Pre : Node_Id;
- New_Prag : Node_Id;
+ procedure Build_Inherited_Condition_Pragmas
+ (Subp : Entity_Id;
+ Wrapper_Needed : out Boolean)
+ is
+ Class_Pre : constant Node_Id :=
+ Class_Preconditions (Ultimate_Alias (Subp));
+ Class_Post : Node_Id := Class_Postconditions (Par_Prim);
+ A_Post : Node_Id;
+ New_Prag : Node_Id;
begin
- A_Pre := Get_Class_Wide_Pragma (Par_Prim, Pragma_Precondition);
+ Wrapper_Needed := False;
- if Present (A_Pre) then
- New_Prag := New_Copy_Tree (A_Pre);
- Build_Class_Wide_Expression
- (Prag => New_Prag,
- Subp => Prim,
- Par_Subp => Par_Prim,
- Adjust_Sloc => False,
- Needs_Wrapper => Needs_Wrapper);
-
- if Needs_Wrapper
- and then not Comes_From_Source (Subp)
- and then Expander_Active
- then
- Append (New_Prag, Decls);
- end if;
+ if No (Class_Pre) and then No (Class_Post) then
+ return;
end if;
- A_Post := Get_Class_Wide_Pragma (Par_Prim, Pragma_Postcondition);
+ -- For class-wide preconditions we just evaluate whether the wrapper
+ -- is needed; there is no need to build the pragma since the check
+ -- is performed on the caller side.
- if Present (A_Post) then
- New_Prag := New_Copy_Tree (A_Post);
+ if Present (Class_Pre)
+ and then Needs_Wrapper (Class_Pre, Subp, Par_Prim)
+ then
+ Wrapper_Needed := True;
+ end if;
+
+ -- For class-wide postconditions we evaluate whether the wrapper is
+ -- needed and we build the class-wide postcondition pragma to install
+ -- it in the wrapper.
+
+ if Present (Class_Post)
+ and then Needs_Wrapper (Class_Post, Subp, Par_Prim)
+ then
+ Wrapper_Needed := True;
+
+ -- Update the class-wide postcondition
+
+ Class_Post := New_Copy_Tree (Class_Post);
Build_Class_Wide_Expression
- (Prag => New_Prag,
- Subp => Prim,
+ (Pragma_Or_Expr => Class_Post,
+ Subp => Subp,
Par_Subp => Par_Prim,
- Adjust_Sloc => False,
- Needs_Wrapper => Needs_Wrapper);
+ Adjust_Sloc => False);
- if Needs_Wrapper
- and then not Comes_From_Source (Subp)
- and then Expander_Active
- then
- Append (New_Prag, Decls);
+ -- Install the updated class-wide postcondition in a copy of the
+ -- pragma postcondition defined for the nearest ancestor.
+
+ A_Post := Get_Class_Wide_Pragma (Par_Prim,
+ Pragma_Postcondition);
+
+ if No (A_Post) then
+ declare
+ Subps : constant Subprogram_List :=
+ Inherited_Subprograms (Subp);
+ begin
+ for Index in Subps'Range loop
+ A_Post := Get_Class_Wide_Pragma (Subps (Index),
+ Pragma_Postcondition);
+ exit when Present (A_Post);
+ end loop;
+ end;
end if;
+
+ New_Prag := New_Copy_Tree (A_Post);
+ Rewrite
+ (Expression (First (Pragma_Argument_Associations (New_Prag))),
+ Class_Post);
+ Append (New_Prag, Decls);
end if;
end Build_Inherited_Condition_Pragmas;
+ -------------------
+ -- Needs_Wrapper --
+ -------------------
+
+ function Needs_Wrapper
+ (Class_Cond : Node_Id;
+ Subp : Entity_Id;
+ Par_Subp : Entity_Id) return Boolean
+ is
+ Result : Boolean := False;
+
+ function Check_Entity (N : Node_Id) return Traverse_Result;
+ -- Check calls to overridden primitives
+
+ --------------------
+ -- Replace_Entity --
+ --------------------
+
+ function Check_Entity (N : Node_Id) return Traverse_Result is
+ New_E : Entity_Id;
+
+ begin
+ if Nkind (N) = N_Identifier
+ and then Present (Entity (N))
+ and then
+ (Is_Formal (Entity (N)) or else Is_Subprogram (Entity (N)))
+ and then
+ (Nkind (Parent (N)) /= N_Attribute_Reference
+ or else Attribute_Name (Parent (N)) /= Name_Class)
+ then
+ -- The check does not apply to dispatching calls within the
+ -- condition, but only to calls whose static tag is that of
+ -- the parent type.
+
+ if Is_Subprogram (Entity (N))
+ and then Nkind (Parent (N)) = N_Function_Call
+ and then Present (Controlling_Argument (Parent (N)))
+ then
+ return OK;
+ end if;
+
+ -- Determine whether entity has a renaming
+
+ New_E := Get_Mapped_Entity (Entity (N));
+
+ -- If the entity is an overridden primitive and we are not
+ -- in GNATprove mode, we must build a wrapper for the current
+ -- inherited operation. If the reference is the prefix of an
+ -- attribute such as 'Result (or others ???) there is no need
+ -- for a wrapper: the condition is just rewritten in terms of
+ -- the inherited subprogram.
+
+ if Present (New_E)
+ and then Comes_From_Source (New_E)
+ and then Is_Subprogram (New_E)
+ and then Nkind (Parent (N)) /= N_Attribute_Reference
+ and then not GNATprove_Mode
+ then
+ Result := True;
+ return Abandon;
+ end if;
+ end if;
+
+ return OK;
+ end Check_Entity;
+
+ procedure Check_Condition_Entities is
+ new Traverse_Proc (Check_Entity);
+
+ -- Start of processing for Needs_Wrapper
+
+ begin
+ Update_Primitives_Mapping (Par_Subp, Subp);
+
+ Map_Formals (Par_Subp, Subp);
+ Check_Condition_Entities (Class_Cond);
+
+ return Result;
+ end Needs_Wrapper;
+
-- Start of processing for Check_Inherited_Conditions
begin
- Op_Node := First_Elmt (Prim_Ops);
- while Present (Op_Node) loop
- Prim := Node (Op_Node);
+ if Late_Overriding then
+ Op_Node := First_Elmt (Prim_Ops);
+ while Present (Op_Node) loop
+ Prim := Node (Op_Node);
- -- Map the overridden primitive to the overriding one. This takes
- -- care of all overridings and is done only once.
+ -- Map the overridden primitive to the overriding one
- if Present (Overridden_Operation (Prim))
- and then Comes_From_Source (Prim)
- then
- Par_Prim := Overridden_Operation (Prim);
- Update_Primitives_Mapping (Par_Prim, Prim);
- end if;
+ if Present (Overridden_Operation (Prim))
+ and then Comes_From_Source (Prim)
+ then
+ Par_Prim := Overridden_Operation (Prim);
+ Update_Primitives_Mapping (Par_Prim, Prim);
- Next_Elmt (Op_Node);
- end loop;
+ -- Force discarding previous mappings of its formals
+
+ Map_Formals (Par_Prim, Prim, Force_Update => True);
+ end if;
+
+ Next_Elmt (Op_Node);
+ end loop;
+ end if;
-- Perform validity checks on the inherited conditions of overriding
-- operations, for conformance with LSP, and apply SPARK-specific
@@ -1583,12 +1831,6 @@ package body Freeze is
if GNATprove_Mode then
Collect_Inherited_Class_Wide_Conditions (Prim);
-
- -- Otherwise build the corresponding pragmas to check for legality
- -- of the inherited condition.
-
- else
- Build_Inherited_Condition_Pragmas (Prim);
end if;
end if;
@@ -1602,12 +1844,17 @@ package body Freeze is
Op_Node := First_Elmt (Prim_Ops);
while Present (Op_Node) loop
- Decls := Empty_List;
- Prim := Node (Op_Node);
- Needs_Wrapper := False;
+ Decls := Empty_List;
+ Prim := Node (Op_Node);
+ Wrapper_Needed := False;
- if not Comes_From_Source (Prim) and then Present (Alias (Prim)) then
- Par_Prim := Alias (Prim);
+ -- Skip internal entities built for mapping interface primitives
+
+ if not Comes_From_Source (Prim)
+ and then Present (Alias (Prim))
+ and then No (Interface_Alias (Prim))
+ then
+ Par_Prim := Ultimate_Alias (Prim);
-- When the primitive is an LSP wrapper we climb to the parent
-- primitive that has the inherited contract.
@@ -1625,39 +1872,39 @@ package body Freeze is
-- in the loop above.
Analyze_Entry_Or_Subprogram_Contract (Par_Prim);
- Build_Inherited_Condition_Pragmas (Prim);
+ Build_Inherited_Condition_Pragmas (Prim, Wrapper_Needed);
end if;
- if Needs_Wrapper
+ if Wrapper_Needed
and then not Is_Abstract_Subprogram (Par_Prim)
and then Expander_Active
then
- -- We need to build a new primitive that overrides the inherited
- -- one, and whose inherited expression has been updated above.
- -- These expressions are the arguments of pragmas that are part
- -- of the declarations of the wrapper. The wrapper holds a single
- -- statement that is a call to the class-wide clone, where the
- -- controlling actuals are conversions to the corresponding type
- -- in the parent primitive:
-
- -- procedure New_Prim (F1 : T1; ...);
- -- procedure New_Prim (F1 : T1; ...) is
- -- pragma Check (Precondition, Expr);
- -- begin
- -- Par_Prim_Clone (Par_Type (F1), ...);
- -- end;
-
- -- If the primitive is a function the statement is a return
- -- statement with a call.
+ -- Build the dispatch-table wrapper (DTW). The support for
+ -- AI12-0195 relies on two kind of wrappers: one for indirect
+ -- calls (also used for AI12-0220), and one for putting in the
+ -- dispatch table:
+ --
+ -- 1) "indirect-call wrapper" (ICW) is needed anytime there are
+ -- class-wide preconditions. Prim'Access will point directly
+ -- at the ICW if any, or at the "pristine" body if Prim has
+ -- no class-wide preconditions.
+ --
+ -- 2) "dispatch-table wrapper" (DTW) is needed anytime the class
+ -- wide preconditions *or* the class-wide postconditions are
+ -- affected by overriding.
+ --
+ -- The DTW holds a single statement that is a single call where
+ -- the controlling actuals are conversions to the corresponding
+ -- type in the parent primitive. If the primitive is a function
+ -- the statement is a return statement with a call.
declare
Alias_Id : constant Entity_Id := Ultimate_Alias (Prim);
Loc : constant Source_Ptr := Sloc (R);
- Par_R : constant Node_Id := Parent (R);
- New_Body : Node_Id;
- New_Decl : Node_Id;
- New_Id : Entity_Id;
- New_Spec : Node_Id;
+ DTW_Body : Node_Id;
+ DTW_Decl : Node_Id;
+ DTW_Id : Entity_Id;
+ DTW_Spec : Node_Id;
begin
-- The wrapper must be analyzed in the scope of its wrapped
@@ -1665,47 +1912,130 @@ package body Freeze is
Push_Scope (Scope (Prim));
- New_Spec := Build_Overriding_Spec (Par_Prim, R);
- New_Id := Defining_Entity (New_Spec);
- New_Decl :=
- Make_Subprogram_Declaration (Loc,
- Specification => New_Spec);
-
- -- Insert the declaration and the body of the wrapper after
- -- type declaration that generates inherited operation. For
- -- a null procedure, the declaration implies a null body.
+ DTW_Spec := Build_DTW_Spec (Par_Prim);
+ DTW_Id := Defining_Entity (DTW_Spec);
+ DTW_Decl := Make_Subprogram_Declaration (Loc,
+ Specification => DTW_Spec);
+
+ -- For inherited class-wide preconditions the DTW wrapper
+ -- reuses the ICW of the parent (which checks the parent
+ -- interpretation of the class-wide preconditions); the
+ -- interpretation of the class-wide preconditions for the
+ -- inherited subprogram is checked at the caller side.
+
+ -- When the subprogram inherits class-wide postconditions
+ -- the DTW also checks the interpretation of the class-wide
+ -- postconditions for the inherited subprogram, and the body
+ -- of the parent checks its interpretation of the parent for
+ -- the class-wide postconditions.
+
+ -- procedure Prim (F1 : T1; ...) is
+ -- [ pragma Check (Postcondition, Expr); ]
+ -- begin
+ -- Par_Prim_ICW (Par_Type (F1), ...);
+ -- end;
+
+ if Present (Indirect_Call_Wrapper (Par_Prim)) then
+ DTW_Body :=
+ Build_DTW_Body (Loc,
+ DTW_Spec => DTW_Spec,
+ DTW_Decls => Decls,
+ Par_Prim => Par_Prim,
+ Wrapped_Subp => Indirect_Call_Wrapper (Par_Prim));
+
+ -- For subprograms that only inherit class-wide postconditions
+ -- the DTW wrapper calls the parent primitive (which on its
+ -- body checks the interpretation of the class-wide post-
+ -- conditions for the parent subprogram), and the DTW checks
+ -- the interpretation of the class-wide postconditions for the
+ -- inherited subprogram.
+
+ -- procedure Prim (F1 : T1; ...) is
+ -- pragma Check (Postcondition, Expr);
+ -- begin
+ -- Par_Prim (Par_Type (F1), ...);
+ -- end;
- -- Before insertion, do some minimal decoration of fields
+ else
+ DTW_Body :=
+ Build_DTW_Body (Loc,
+ DTW_Spec => DTW_Spec,
+ DTW_Decls => Decls,
+ Par_Prim => Par_Prim,
+ Wrapped_Subp => Par_Prim);
+ end if;
- Mutate_Ekind (New_Id, Ekind (Par_Prim));
- Set_LSP_Subprogram (New_Id, Par_Prim);
- Set_Is_Wrapper (New_Id);
+ -- Insert the declaration of the wrapper before the freezing
+ -- node of the record type declaration to ensure that it will
+ -- override the internal primitive built by Derive_Subprogram.
- if Nkind (New_Spec) = N_Procedure_Specification
- and then Null_Present (New_Spec)
- then
- Insert_After_And_Analyze (Par_R, New_Decl);
+ Ensure_Freeze_Node (R);
+ if Late_Overriding then
+ Insert_Before_And_Analyze (Freeze_Node (R), DTW_Decl);
else
- -- Build body as wrapper to a call to the already built
- -- class-wide clone.
+ Append_Freeze_Action (R, DTW_Decl);
+ end if;
+
+ Analyze (DTW_Decl);
+
+ -- Insert the body of the wrapper in the freeze actions of
+ -- its record type declaration to ensure that it is placed
+ -- in the scope of its declaration but not too early to cause
+ -- premature freezing of other entities.
+
+ Append_Freeze_Action (R, DTW_Body);
+ Analyze (DTW_Body);
+
+ -- Ensure correct decoration
+
+ pragma Assert (Is_Dispatching_Operation (DTW_Id));
+ pragma Assert (Present (Overridden_Operation (DTW_Id)));
+ pragma Assert (Overridden_Operation (DTW_Id) = Alias_Id);
- New_Body :=
- Build_Class_Wide_Clone_Call
- (Loc, Decls, Par_Prim, New_Spec);
+ -- Inherit dispatch table slot
- Insert_List_After_And_Analyze
- (Par_R, New_List (New_Decl, New_Body));
+ Set_DTC_Entity_Value (R, DTW_Id);
+ Set_DT_Position (DTW_Id, DT_Position (Alias_Id));
- -- Ensure correct decoration
+ -- Register the wrapper in the dispatch table
- pragma Assert (Present (Alias (Prim)));
- pragma Assert (Present (Overridden_Operation (New_Id)));
- pragma Assert (Overridden_Operation (New_Id) = Alias_Id);
+ if Late_Overriding
+ and then not Building_Static_DT (R)
+ then
+ Insert_List_After_And_Analyze (Freeze_Node (R),
+ Register_Primitive (Loc, DTW_Id));
end if;
- pragma Assert (Is_Dispatching_Operation (Prim));
- pragma Assert (Is_Dispatching_Operation (New_Id));
+ -- Build the helper and ICW for the DTW
+
+ if Present (Indirect_Call_Wrapper (Par_Prim)) then
+ declare
+ CW_Subp : Entity_Id;
+ Decl_N : Node_Id;
+ Body_N : Node_Id;
+
+ begin
+ Merge_Class_Conditions (DTW_Id);
+ Make_Class_Precondition_Subps (DTW_Id,
+ Late_Overriding => Late_Overriding);
+
+ CW_Subp := Static_Call_Helper (DTW_Id);
+ Decl_N := Unit_Declaration_Node (CW_Subp);
+ Analyze (Decl_N);
+
+ -- If the DTW was built for a late-overriding primitive
+ -- its body must be analyzed now (since the tagged type
+ -- is already frozen).
+
+ if Late_Overriding then
+ Body_N :=
+ Unit_Declaration_Node
+ (Corresponding_Body (Decl_N));
+ Analyze (Body_N);
+ end if;
+ end;
+ end if;
Pop_Scope;
end;
@@ -7398,7 +7728,7 @@ package body Freeze is
if Is_Type (E) then
Freeze_And_Append (First_Subtype (E), N, Result);
- -- If we just froze a tagged non-class wide record, then freeze the
+ -- If we just froze a tagged non-class-wide record, then freeze the
-- corresponding class-wide type. This must be done after the tagged
-- type itself is frozen, because the class-wide type refers to the
-- tagged type which generates the class.
@@ -10062,7 +10392,7 @@ package body Freeze is
-- Warn_Overlay --
------------------
- procedure Warn_Overlay (Expr : Node_Id; Typ : Entity_Id; Nam : Entity_Id) is
+ procedure Warn_Overlay (Expr : Node_Id; Typ : Entity_Id; Nam : Node_Id) is
Ent : constant Entity_Id := Entity (Nam);
-- The object to which the address clause applies
diff --git a/gcc/ada/freeze.ads b/gcc/ada/freeze.ads
index 6f4feca..0174756 100644
--- a/gcc/ada/freeze.ads
+++ b/gcc/ada/freeze.ads
@@ -174,6 +174,15 @@ package Freeze is
-- do not allow a size clause if the size would not otherwise be known at
-- compile time in any case.
+ procedure Check_Inherited_Conditions
+ (R : Entity_Id;
+ Late_Overriding : Boolean := False);
+ -- For a tagged derived type R, create wrappers for inherited operations
+ -- that have class-wide conditions, so it can be properly rewritten if
+ -- it involves calls to other overriding primitives. Late_Overriding is
+ -- True when we are processing the body of a primitive with no previous
+ -- spec defined after R is frozen (see Check_Dispatching_Operation).
+
function Is_Full_Access_Aggregate (N : Node_Id) return Boolean;
-- If a full access object is initialized with an aggregate or is assigned
-- an aggregate, we have to prevent a piecemeal access or assignment to the
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index c341e2d..61a627f 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -517,7 +517,6 @@ GNAT_ADA_OBJS+= \
ada/libgnat/s-excmac.o \
ada/libgnat/s-exctab.o \
ada/libgnat/s-htable.o \
- ada/libgnat/s-imenne.o \
ada/libgnat/s-imgint.o \
ada/libgnat/s-mastop.o \
ada/libgnat/s-memory.o \
@@ -684,7 +683,6 @@ GNATBIND_OBJS += \
ada/libgnat/s-excmac.o \
ada/libgnat/s-exctab.o \
ada/libgnat/s-htable.o \
- ada/libgnat/s-imenne.o \
ada/libgnat/s-imgint.o \
ada/libgnat/s-mastop.o \
ada/libgnat/s-memory.o \
diff --git a/gcc/ada/gcc-interface/cuintp.c b/gcc/ada/gcc-interface/cuintp.c
index 6ac82d7..abf8d46 100644
--- a/gcc/ada/gcc-interface/cuintp.c
+++ b/gcc/ada/gcc-interface/cuintp.c
@@ -39,6 +39,7 @@
#include "ada.h"
#include "types.h"
#include "uintp.h"
+#include "sinfo.h"
#include "ada-tree.h"
#include "gigi.h"
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 884d1d8..13e9004 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -557,7 +557,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* If the entity is an inherited component (in the case of extended
tagged record types), just return the original entity, which must
be a FIELD_DECL. Likewise for discriminants. If the entity is a
- non-girder discriminant (in the case of derived untagged record
+ non-stored discriminant (in the case of derived untagged record
types), return the stored discriminant it renames. */
if (Present (Original_Record_Component (gnat_entity))
&& Original_Record_Component (gnat_entity) != gnat_entity)
@@ -6503,7 +6503,8 @@ range_cannot_be_superflat (Node_Id gnat_range)
Node_Id gnat_scalar_range;
tree gnu_lb, gnu_hb, gnu_lb_minus_one;
- /* If the low bound is not constant, try to find an upper bound. */
+ /* If the low bound is not constant, take the worst case by finding an upper
+ bound for its type, repeatedly if need be. */
while (Nkind (gnat_lb) != N_Integer_Literal
&& (Ekind (Etype (gnat_lb)) == E_Signed_Integer_Subtype
|| Ekind (Etype (gnat_lb)) == E_Modular_Integer_Subtype)
@@ -6512,7 +6513,8 @@ range_cannot_be_superflat (Node_Id gnat_range)
|| Nkind (gnat_scalar_range) == N_Range))
gnat_lb = High_Bound (gnat_scalar_range);
- /* If the high bound is not constant, try to find a lower bound. */
+ /* If the high bound is not constant, take the worst case by finding a lower
+ bound for its type, repeatedly if need be. */
while (Nkind (gnat_hb) != N_Integer_Literal
&& (Ekind (Etype (gnat_hb)) == E_Signed_Integer_Subtype
|| Ekind (Etype (gnat_hb)) == E_Modular_Integer_Subtype)
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index 49b85a4..692ef44 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -234,7 +234,7 @@ extern "C" {
extern void gigi (Node_Id gnat_root,
int max_gnat_node,
int number_name,
- Field_Offset *node_offsets_ptr,
+ Node_Header *node_offsets_ptr,
any_slot *slots_ptr,
Node_Id *next_node_ptr,
Node_Id *prev_node_ptr,
diff --git a/gcc/ada/gcc-interface/targtyps.c b/gcc/ada/gcc-interface/targtyps.c
index 704172d..fb103a1 100644
--- a/gcc/ada/gcc-interface/targtyps.c
+++ b/gcc/ada/gcc-interface/targtyps.c
@@ -34,6 +34,7 @@
#include "ada.h"
#include "types.h"
+#include "sinfo.h"
#include "ada-tree.h"
#include "gigi.h"
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index d3c421d..3fec060 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -75,7 +75,7 @@
#define ALLOCA_THRESHOLD 1000
/* Pointers to front-end tables accessed through macros. */
-Field_Offset *Node_Offsets_Ptr;
+Node_Header *Node_Offsets_Ptr;
any_slot *Slots_Ptr;
Node_Id *Next_Node_Ptr;
Node_Id *Prev_Node_Ptr;
@@ -279,7 +279,7 @@ void
gigi (Node_Id gnat_root,
int max_gnat_node,
int number_name ATTRIBUTE_UNUSED,
- Field_Offset *node_offsets_ptr,
+ Node_Header *node_offsets_ptr,
any_slot *slots_ptr,
Node_Id *next_node_ptr,
Node_Id *prev_node_ptr,
@@ -3893,7 +3893,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
/* If the body comes from an expression function, arrange it to be inlined
in almost all cases. */
- if (Was_Expression_Function (gnat_node))
+ if (Was_Expression_Function (gnat_node) && !Debug_Flag_Dot_8)
DECL_DISREGARD_INLINE_LIMITS (gnu_subprog_decl) = 1;
/* Try to create a bona-fide thunk and hand it over to the middle-end. */
@@ -8261,6 +8261,7 @@ gnat_to_gnu (Node_Id gnat_node)
|| kind == N_Selected_Component)
&& TREE_CODE (get_base_type (gnu_result_type)) == BOOLEAN_TYPE
&& Nkind (Parent (gnat_node)) != N_Attribute_Reference
+ && Nkind (Parent (gnat_node)) != N_Pragma_Argument_Association
&& Nkind (Parent (gnat_node)) != N_Variant_Part
&& !lvalue_required_p (gnat_node, gnu_result_type, false, false))
{
@@ -10507,10 +10508,15 @@ set_end_locus_from_node (tree gnu_node, Node_Id gnat_node)
case N_Package_Body:
case N_Subprogram_Body:
case N_Block_Statement:
- gnat_end_label = End_Label (Handled_Statement_Sequence (gnat_node));
+ if (Present (Handled_Statement_Sequence (gnat_node)))
+ gnat_end_label = End_Label (Handled_Statement_Sequence (gnat_node));
+ else
+ gnat_end_label = Empty;
+
break;
case N_Package_Declaration:
+ gcc_checking_assert (Present (Specification (gnat_node)));
gnat_end_label = End_Label (Specification (gnat_node));
break;
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index be3f107..ab5ca5b 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -94,6 +94,7 @@ static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_stack_protector_attribute (tree *, tree, tree, int, bool *);
+static tree handle_strub_attribute (tree *, tree, tree, int, bool *);
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
static tree handle_noicf_attribute (tree *, tree, tree, int, bool *);
@@ -157,6 +158,8 @@ const struct attribute_spec gnat_internal_attribute_table[] =
{ "no_stack_protector",0, 0, true, false, false, false,
handle_no_stack_protector_attribute,
attr_stack_protect_exclusions },
+ { "strub", 0, 1, false, true, false, true,
+ handle_strub_attribute, NULL },
{ "noinline", 0, 0, true, false, false, false,
handle_noinline_attribute, NULL },
{ "noclone", 0, 0, true, false, false, false,
@@ -6602,6 +6605,15 @@ handle_no_stack_protector_attribute (tree *node, tree name, tree, int,
return NULL_TREE;
}
+/* Handle a "strub" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_strub_attribute (tree *, tree, tree, int, bool *no_add_attrs)
+{
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
/* Handle a "noinline" attribute; arguments as in
struct attribute_spec.handler. */
diff --git a/gcc/ada/gen_il-fields.ads b/gcc/ada/gen_il-fields.ads
index 360e2e1..f3f3ca4 100644
--- a/gcc/ada/gen_il-fields.ads
+++ b/gcc/ada/gen_il-fields.ads
@@ -23,8 +23,6 @@
-- --
------------------------------------------------------------------------------
-with Gen_IL.Types;
-
package Gen_IL.Fields is
-- The following is "optional field enumeration" -- i.e. it is Field_Enum
@@ -36,8 +34,7 @@ package Gen_IL.Fields is
-- which might need to be kept in sync when modifying this.
-- Be sure to put new fields in the appropriate subrange (Field_Enum,
- -- Node_Header_Field, Node_Field, Entity_Field -- search for comments
- -- below).
+ -- Node_Field, Entity_Field -- search for comments below).
type Opt_Field_Enum is
(No_Field,
@@ -461,7 +458,9 @@ package Gen_IL.Fields is
Can_Never_Be_Null,
Can_Use_Internal_Rep,
Checks_May_Be_Suppressed,
- Class_Wide_Clone,
+ Class_Postconditions,
+ Class_Preconditions,
+ Class_Preconditions_Subprogram,
Class_Wide_Type,
Cloned_Subtype,
Component_Alignment,
@@ -509,6 +508,7 @@ package Gen_IL.Fields is
Discriminant_Default_Value,
Discriminant_Number,
Dispatch_Table_Wrappers,
+ Dynamic_Call_Helper,
DT_Entry_Count,
DT_Offset_To_Top_Func,
DT_Position,
@@ -649,9 +649,12 @@ package Gen_IL.Fields is
Hiding_Loop_Variable,
Hidden_In_Formal_Instance,
Homonym,
+ Ignored_Class_Postconditions,
+ Ignored_Class_Preconditions,
Ignore_SPARK_Mode_Pragmas,
Import_Pragma,
Incomplete_Actuals,
+ Indirect_Call_Wrapper,
In_Package_Body,
In_Private_Part,
In_Use,
@@ -677,6 +680,7 @@ package Gen_IL.Fields is
Is_Checked_Ghost_Entity,
Is_Child_Unit,
Is_Class_Wide_Equivalent_Type,
+ Is_Class_Wide_Wrapper,
Is_Compilation_Unit,
Is_Completely_Hidden,
Is_Concurrent_Record_Type,
@@ -693,6 +697,7 @@ package Gen_IL.Fields is
Is_Discrim_SO_Function,
Is_Discriminant_Check_Function,
Is_Dispatch_Table_Entity,
+ Is_Dispatch_Table_Wrapper,
Is_Dispatching_Operation,
Is_Elaboration_Checks_OK_Id,
Is_Elaboration_Warnings_OK_Id,
@@ -892,6 +897,7 @@ package Gen_IL.Fields is
Spec_Entity,
SSO_Set_High_By_Default,
SSO_Set_Low_By_Default,
+ Static_Call_Helper,
Static_Discrete_Predicate,
Static_Elaboration_Desired,
Static_Initialization,
@@ -935,13 +941,4 @@ package Gen_IL.Fields is
-- Enumeration of fields -- Opt_Field_Enum without the special null value
-- No_Field.
- subtype Node_Header_Field is Field_Enum with Predicate =>
- Node_Header_Field in Nkind .. Link | Ekind;
-
- use Gen_IL.Types;
-
- subtype Node_Header_Type is Type_Enum range
- Node_Kind_Type .. Union_Id;
- -- Types of node header fields
-
end Gen_IL.Fields;
diff --git a/gcc/ada/gen_il-gen-gen_entities.adb b/gcc/ada/gen_il-gen-gen_entities.adb
index bca0549..1fa7f0b 100644
--- a/gcc/ada/gen_il-gen-gen_entities.adb
+++ b/gcc/ada/gen_il-gen-gen_entities.adb
@@ -126,6 +126,7 @@ begin -- Gen_IL.Gen.Gen_Entities
Sm (Is_Character_Type, Flag),
Sm (Is_Checked_Ghost_Entity, Flag),
Sm (Is_Child_Unit, Flag),
+ Sm (Is_Class_Wide_Wrapper, Flag),
Sm (Is_Class_Wide_Equivalent_Type, Flag),
Sm (Is_Compilation_Unit, Flag),
Sm (Is_Concurrent_Record_Type, Flag),
@@ -139,6 +140,7 @@ begin -- Gen_IL.Gen.Gen_Entities
Sm (Is_Discrim_SO_Function, Flag),
Sm (Is_Discriminant_Check_Function, Flag),
Sm (Is_Dispatch_Table_Entity, Flag),
+ Sm (Is_Dispatch_Table_Wrapper, Flag),
Sm (Is_Dispatching_Operation, Flag),
Sm (Is_Eliminated, Flag),
Sm (Is_Entry_Formal, Flag),
@@ -977,8 +979,11 @@ begin -- Gen_IL.Gen.Gen_Entities
Ab (Subprogram_Kind, Overloadable_Kind,
(Sm (Body_Needed_For_SAL, Flag),
- Sm (Class_Wide_Clone, Node_Id),
+ Sm (Class_Postconditions, Node_Id),
+ Sm (Class_Preconditions, Node_Id),
+ Sm (Class_Preconditions_Subprogram, Node_Id),
Sm (Contract, Node_Id),
+ Sm (Dynamic_Call_Helper, Node_Id),
Sm (Elaboration_Entity, Node_Id),
Sm (Elaboration_Entity_Required, Flag),
Sm (First_Entity, Node_Id),
@@ -986,8 +991,11 @@ begin -- Gen_IL.Gen.Gen_Entities
Sm (Has_Nested_Subprogram, Flag),
Sm (Has_Out_Or_In_Out_Parameter, Flag),
Sm (Has_Recursive_Call, Flag),
+ Sm (Ignored_Class_Postconditions, Node_Id),
+ Sm (Ignored_Class_Preconditions, Node_Id),
Sm (Ignore_SPARK_Mode_Pragmas, Flag),
Sm (Import_Pragma, Node_Id),
+ Sm (Indirect_Call_Wrapper, Node_Id),
Sm (Interface_Alias, Node_Id),
Sm (Interface_Name, Node_Id),
Sm (Is_Elaboration_Checks_OK_Id, Flag),
@@ -998,6 +1006,7 @@ begin -- Gen_IL.Gen.Gen_Entities
Sm (Overridden_Operation, Node_Id),
Sm (Protected_Body_Subprogram, Node_Id),
Sm (Scope_Depth_Value, Uint),
+ Sm (Static_Call_Helper, Node_Id),
Sm (SPARK_Pragma, Node_Id),
Sm (SPARK_Pragma_Inherited, Flag),
Sm (Subps_Index, Uint)));
@@ -1383,6 +1392,23 @@ begin -- Gen_IL.Gen.Gen_Entities
(E_Entry,
E_Entry_Family));
+ Union (Evaluable_Kind,
+ Children =>
+ (Exception_Or_Object_Kind,
+ E_Enumeration_Literal,
+ E_Label,
+ Subprogram_Kind));
+ -- Kinds that represent values that can be evaluated
+
+ Union (Global_Name_Kind,
+ Children =>
+ (Constant_Or_Variable_Kind,
+ E_Exception,
+ E_Package,
+ Subprogram_Kind));
+ -- Kinds that can have an Interface_Name that corresponds to a global
+ -- (linker) name.
+
Union (Named_Access_Kind,
Children =>
(E_Access_Type,
@@ -1408,4 +1434,10 @@ begin -- Gen_IL.Gen.Gen_Entities
E_Record_Type_With_Private,
E_Record_Subtype_With_Private));
+ Union (Subprogram_Type_Or_Kind,
+ Children =>
+ (Subprogram_Kind,
+ E_Subprogram_Body,
+ E_Subprogram_Type));
+
end Gen_IL.Gen.Gen_Entities;
diff --git a/gcc/ada/gen_il-gen-gen_nodes.adb b/gcc/ada/gen_il-gen-gen_nodes.adb
index 55ba71d..20d25ea 100644
--- a/gcc/ada/gen_il-gen-gen_nodes.adb
+++ b/gcc/ada/gen_il-gen-gen_nodes.adb
@@ -577,7 +577,8 @@ begin -- Gen_IL.Gen.Gen_Nodes
Ab (N_Declaration, Node_Kind);
-- Note: this includes all constructs normally thought of as declarations
- -- except those that are separately grouped in N_Later_Decl_Item.
+ -- except those that are separately grouped in N_Later_Decl_Item. But
+ -- Declaration_Node may return yet more node types; see N_Is_Decl below.
Cc (N_Component_Declaration, N_Declaration,
(Sy (Defining_Identifier, Node_Id),
@@ -1649,4 +1650,67 @@ begin -- Gen_IL.Gen.Gen_Nodes
N_Terminate_Alternative));
-- Nodes with condition fields (does not include N_Raise_xxx_Error)
+ Union (N_Has_Bounds,
+ Children =>
+ (N_Range,
+ N_Real_Range_Specification,
+ N_Signed_Integer_Type_Definition));
+ -- Nodes that have Low_Bound and High_Bound defined
+
+ Union (N_Is_Index,
+ Children =>
+ (N_Has_Bounds,
+ N_Has_Entity,
+ N_Subtype_Indication));
+ -- Nodes that can be an index of an array
+
+ Union (N_Entity_Name,
+ Children =>
+ (N_Expanded_Name,
+ N_Identifier,
+ N_Operator_Symbol));
+ -- Nodes that are definitely representing an entity.
+ -- Some N_Attribute_Reference nodes may also represent an entity. See
+ -- Is_Entity_Name.
+
+ Union (N_Is_Decl,
+ Children =>
+ (N_Declaration,
+ N_Discriminant_Specification,
+ N_Enumeration_Type_Definition,
+ N_Exception_Handler,
+ N_Later_Decl_Item,
+ N_Package_Specification,
+ N_Parameter_Specification,
+ N_Renaming_Declaration,
+ N_Subprogram_Specification));
+ -- Nodes that can be returned by Declaration_Node
+
+ Union (N_Is_Range,
+ Children =>
+ (N_Character_Literal,
+ N_Entity_Name,
+ N_Has_Bounds,
+ N_Integer_Literal,
+ N_Subtype_Indication));
+ -- Nodes that can be used to specify a range
+
+ Union (N_Is_Case_Choice,
+ Children =>
+ (N_Is_Range,
+ N_Others_Choice));
+ -- Nodes that can be in the choices of a case statement
+
+ Union (N_Is_Exception_Choice,
+ Children =>
+ (N_Entity_Name,
+ N_Others_Choice));
+ -- Nodes that can be in the choices of an exception handler
+
+ Union (N_Alternative,
+ Children =>
+ (N_Case_Statement_Alternative,
+ N_Variant));
+ -- Nodes that can be alternatives in case contructs
+
end Gen_IL.Gen.Gen_Nodes;
diff --git a/gcc/ada/gen_il-gen.adb b/gcc/ada/gen_il-gen.adb
index 3bb9807..e786251 100644
--- a/gcc/ada/gen_il-gen.adb
+++ b/gcc/ada/gen_il-gen.adb
@@ -28,6 +28,27 @@ with Ada.Text_IO;
package body Gen_IL.Gen is
+ Statistics_Enabled : constant Boolean := False;
+ -- Change to True or False to enable/disable statistics printed by
+ -- Atree. Should normally be False, for efficiency. Also compile with
+ -- -gnatd.A to get the statistics printed. Enabling these statistics
+ -- makes the compiler about 20% slower.
+
+ Num_Header_Slots : constant := 3;
+ -- Number of header slots; the first Num_Header_Slots slots are stored in
+ -- the header; the rest are dynamically allocated in the Slots table. We
+ -- need to subtract this off when accessing dynamic slots. The constant
+ -- Seinfo.N_Head will contain this value. Fields that are allocated in the
+ -- header slots are quicker to access.
+ --
+ -- This number can be adjusted for efficiency. We choose 3 because the
+ -- minimum node size is 3 slots, and because that causes the size of type
+ -- Node_Header to be a power of 2. We can't make it zero, however, because
+ -- C doesn't allow zero-length arrays.
+
+ N_Head : constant String := Image (Field_Offset'(Num_Header_Slots));
+ -- String form of the above
+
Enable_Assertions : constant Boolean := True;
-- True to enable predicates on the _Id types, and preconditions on getters
-- and setters.
@@ -37,6 +58,9 @@ package body Gen_IL.Gen is
-- which results in enormous nodes. For experimenting and debugging.
-- Should be True in normal operation, for efficiency.
+ SS : constant := 32; -- slot size in bits
+ SSS : constant String := Image (Bit_Offset'(SS));
+
Inline : constant String := "Inline";
-- For experimenting with Inline_Always
@@ -309,7 +333,7 @@ package body Gen_IL.Gen is
Pre => new String'(Pre),
Pre_Get => new String'(Pre_Get),
Pre_Set => new String'(Pre_Set),
- Offset => <>); -- filled in later
+ Offset => Unknown_Offset);
-- The Field_Table entry has already been created by the 'then' part
-- above. Now we're seeing the same field being "created" again in a
@@ -479,8 +503,6 @@ package body Gen_IL.Gen is
Min_Entity_Size : Field_Offset := Field_Offset'Last;
Max_Entity_Size : Field_Offset := 0;
- Average_Node_Size_In_Slots : Long_Float;
-
Node_Field_Types_Used, Entity_Field_Types_Used : Type_Set;
Setter_Needs_Parent : Field_Set :=
@@ -563,6 +585,8 @@ package body Gen_IL.Gen is
procedure Put_Setter_Spec (S : in out Sink; F : Field_Enum);
procedure Put_Getter_Decl (S : in out Sink; F : Field_Enum);
procedure Put_Setter_Decl (S : in out Sink; F : Field_Enum);
+ procedure Put_Getter_Setter_Locals
+ (S : in out Sink; F : Field_Enum; Get : Boolean);
procedure Put_Getter_Body (S : in out Sink; F : Field_Enum);
procedure Put_Setter_Body (S : in out Sink; F : Field_Enum);
-- Print out the specification, declaration, or body of a getter or
@@ -573,9 +597,9 @@ package body Gen_IL.Gen is
-- Print out the precondition, if any, for a getter or setter for the
-- given field.
- procedure Put_Low_Level_Accessor_Instantiations
+ procedure Put_Casts
(S : in out Sink; T : Type_Enum);
- -- Print out the low-level getter and setter for a given type
+ -- Print out the Cast functions for a given type
procedure Put_Traversed_Fields (S : in out Sink);
-- Called by Put_Nodes to print out the Traversed_Fields table in
@@ -616,22 +640,17 @@ package body Gen_IL.Gen is
-- corresponding to the Ada Node_Kind, Entity_Kind, and subtypes
-- thereof.
- procedure Put_Low_Level_C_Getter
- (S : in out Sink; T : Type_Enum);
- -- Used by Put_Sinfo_Dot_H and Put_Einfo_Dot_H to print out low-level
- -- getters.
-
- procedure Put_High_Level_C_Getters
+ procedure Put_C_Getters
(S : in out Sink; Root : Root_Type);
-- Used by Put_Sinfo_Dot_H and Put_Einfo_Dot_H to print out high-level
-- getters.
- procedure Put_High_Level_C_Getter
+ procedure Put_C_Getter
(S : in out Sink; F : Field_Enum);
- -- Used by Put_High_Level_C_Getters to print out one high-level getter.
+ -- Used by Put_C_Getters to print out one high-level getter.
procedure Put_Union_Membership
- (S : in out Sink; Root : Root_Type);
+ (S : in out Sink; Root : Root_Type; Only_Prototypes : Boolean);
-- Used by Put_Sinfo_Dot_H and Put_Einfo_Dot_H to print out functions to
-- test membership in a union type.
@@ -691,6 +710,8 @@ package body Gen_IL.Gen is
Type_Table (T).Last := T;
Add_Concrete_Descendant_To_Ancestors
(Type_Table (T).Parent, T);
+ -- Parent cannot be No_Type here, because T is a concrete
+ -- type, and therefore not a root type.
when Abstract_Type =>
declare
@@ -884,13 +905,13 @@ package body Gen_IL.Gen is
function To_Size_In_Slots (Size_In_Bits : Bit_Offset)
return Field_Offset is
- ((Field_Offset (Size_In_Bits) + 31) / 32);
+ ((Field_Offset (Size_In_Bits) + (SS - 1)) / SS);
function Type_Size_In_Slots (T : Concrete_Type) return Field_Offset is
(To_Size_In_Slots (Type_Bit_Size (T))); -- rounded up to slot boundary
function Type_Bit_Size_Aligned (T : Concrete_Type) return Bit_Offset is
- (Bit_Offset (Type_Size_In_Slots (T)) * 32); -- multiple of slot size
+ (Bit_Offset (Type_Size_In_Slots (T)) * SS); -- multiple of slot size
---------------------------
-- Compute_Field_Offsets --
@@ -924,8 +945,7 @@ package body Gen_IL.Gen is
(F : Field_Enum; Offset : Field_Offset);
-- Mark the offset as "in use"
- function Choose_Offset
- (F : Field_Enum) return Field_Offset;
+ procedure Choose_Offset (F : Field_Enum);
-- Choose an offset for this field
function Offset_OK
@@ -965,14 +985,14 @@ package body Gen_IL.Gen is
end loop;
end Set_Offset_In_Use;
- function Choose_Offset
- (F : Field_Enum) return Field_Offset is
+ procedure Choose_Offset (F : Field_Enum) is
begin
for Offset in Field_Offset loop
if Offset_OK (F, Offset) then
Set_Offset_In_Use (F, Offset);
- return Offset;
+ Field_Table (F).Offset := Offset;
+ return;
end if;
end loop;
@@ -981,16 +1001,16 @@ package body Gen_IL.Gen is
Image (Gen_IL.Internals.Bit_Offset'Last) & " is too small)";
end Choose_Offset;
- Num_Concrete_Have_Field : array (Field_Enum) of Type_Count :=
+ Weighted_Node_Frequency : array (Field_Enum) of Type_Count :=
(others => 0);
-- Number of concrete types that have each field
function More_Types_Have_Field (F1, F2 : Field_Enum) return Boolean is
- (Num_Concrete_Have_Field (F1) > Num_Concrete_Have_Field (F2));
+ (Weighted_Node_Frequency (F1) > Weighted_Node_Frequency (F2));
-- True if F1 appears in more concrete types than F2
function Sort_Less (F1, F2 : Field_Enum) return Boolean is
- (if Num_Concrete_Have_Field (F1) = Num_Concrete_Have_Field (F2) then
+ (if Weighted_Node_Frequency (F1) = Weighted_Node_Frequency (F2) then
F1 < F2
else More_Types_Have_Field (F1, F2));
@@ -999,15 +1019,18 @@ package body Gen_IL.Gen is
All_Fields : Field_Vector;
+ -- Start of processing for Compute_Field_Offsets
+
begin
- -- Compute the number of types that have each field
+ -- Compute the number of types that have each field, weighted by the
+ -- frequency of such nodes.
for T in Concrete_Type loop
for F in Field_Enum loop
if Fields_Per_Node (T) (F) then
- Num_Concrete_Have_Field (F) :=
- Num_Concrete_Have_Field (F) + 1;
+ Weighted_Node_Frequency (F) :=
+ Weighted_Node_Frequency (F) + Type_Frequency (T);
end if;
end loop;
end loop;
@@ -1038,8 +1061,33 @@ package body Gen_IL.Gen is
-- complication compared to standard graph coloring is that fields
-- are different sizes.
+ -- First choose offsets for some heavily-used fields, so they will
+ -- get low offsets, so they will wind up in the node header for
+ -- faster access.
+
+ Choose_Offset (Nkind);
+ pragma Assert (Field_Table (Nkind).Offset = 0);
+ Choose_Offset (Ekind);
+ pragma Assert (Field_Table (Ekind).Offset = 1);
+ Choose_Offset (Homonym);
+ pragma Assert (Field_Table (Homonym).Offset = 1);
+ Choose_Offset (Is_Immediately_Visible);
+ pragma Assert (Field_Table (Is_Immediately_Visible).Offset = 16);
+ Choose_Offset (From_Limited_With);
+ pragma Assert (Field_Table (From_Limited_With).Offset = 17);
+ Choose_Offset (Is_Potentially_Use_Visible);
+ pragma Assert (Field_Table (Is_Potentially_Use_Visible).Offset = 18);
+ Choose_Offset (Is_Generic_Instance);
+ pragma Assert (Field_Table (Is_Generic_Instance).Offset = 19);
+ Choose_Offset (Scope);
+ pragma Assert (Field_Table (Scope).Offset = 2);
+
+ -- Then loop through them all, skipping the ones we did above
+
for F of All_Fields loop
- Field_Table (F).Offset := Choose_Offset (F);
+ if Field_Table (F).Offset = Unknown_Offset then
+ Choose_Offset (F);
+ end if;
end loop;
end Compute_Field_Offsets;
@@ -1049,231 +1097,6 @@ package body Gen_IL.Gen is
------------------------
procedure Compute_Type_Sizes is
- -- Node_Counts is the number of nodes of each kind created during
- -- compilation of a large example. This is used purely to compute an
- -- estimate of the average node size. New node types can default to
- -- "others => 0". At some point we can instrument Atree to print out
- -- accurate size statistics, and remove this code.
-
- Node_Counts : constant array (Concrete_Node) of Natural :=
- (N_Identifier => 429298,
- N_Defining_Identifier => 231636,
- N_Integer_Literal => 90892,
- N_Parameter_Specification => 62811,
- N_Attribute_Reference => 47150,
- N_Expanded_Name => 37375,
- N_Selected_Component => 30699,
- N_Subprogram_Declaration => 20744,
- N_Freeze_Entity => 20314,
- N_Procedure_Specification => 18901,
- N_Object_Declaration => 18023,
- N_Function_Specification => 16570,
- N_Range => 16216,
- N_Explicit_Dereference => 12198,
- N_Component_Association => 11188,
- N_Unchecked_Type_Conversion => 11165,
- N_Subtype_Indication => 10727,
- N_Procedure_Call_Statement => 10056,
- N_Subtype_Declaration => 8141,
- N_Handled_Sequence_Of_Statements => 8078,
- N_Null => 7288,
- N_Aggregate => 7222,
- N_String_Literal => 7152,
- N_Function_Call => 6958,
- N_Simple_Return_Statement => 6911,
- N_And_Then => 6867,
- N_Op_Eq => 6845,
- N_Call_Marker => 6683,
- N_Pragma_Argument_Association => 6525,
- N_Component_Definition => 6487,
- N_Assignment_Statement => 6483,
- N_With_Clause => 6480,
- N_Null_Statement => 5917,
- N_Index_Or_Discriminant_Constraint => 5877,
- N_Generic_Association => 5667,
- N_Full_Type_Declaration => 5573,
- N_If_Statement => 5553,
- N_Subprogram_Body => 5455,
- N_Op_Add => 5443,
- N_Type_Conversion => 5260,
- N_Component_Declaration => 5059,
- N_Raise_Constraint_Error => 4840,
- N_Formal_Concrete_Subprogram_Declaration => 4602,
- N_Expression_With_Actions => 4598,
- N_Op_Ne => 3854,
- N_Indexed_Component => 3834,
- N_Op_Subtract => 3777,
- N_Package_Specification => 3490,
- N_Subprogram_Renaming_Declaration => 3445,
- N_Pragma => 3427,
- N_Case_Statement_Alternative => 3272,
- N_Block_Statement => 3239,
- N_Parameter_Association => 3213,
- N_Op_Lt => 3020,
- N_Op_Not => 2926,
- N_Character_Literal => 2914,
- N_Others_Choice => 2769,
- N_Or_Else => 2576,
- N_Itype_Reference => 2511,
- N_Defining_Operator_Symbol => 2487,
- N_Component_List => 2470,
- N_Formal_Object_Declaration => 2262,
- N_Generic_Subprogram_Declaration => 2227,
- N_Real_Literal => 2156,
- N_Op_Gt => 2156,
- N_Access_To_Object_Definition => 1984,
- N_Op_Le => 1975,
- N_Op_Ge => 1942,
- N_Package_Renaming_Declaration => 1811,
- N_Formal_Type_Declaration => 1756,
- N_Qualified_Expression => 1746,
- N_Package_Declaration => 1729,
- N_Record_Definition => 1651,
- N_Allocator => 1521,
- N_Op_Concat => 1377,
- N_Access_Definition => 1358,
- N_Case_Statement => 1322,
- N_Number_Declaration => 1316,
- N_Generic_Package_Declaration => 1311,
- N_Slice => 1078,
- N_Constrained_Array_Definition => 1068,
- N_Exception_Renaming_Declaration => 1011,
- N_Implicit_Label_Declaration => 978,
- N_Exception_Handler => 966,
- N_Private_Type_Declaration => 898,
- N_Operator_Symbol => 872,
- N_Formal_Private_Type_Definition => 867,
- N_Range_Constraint => 849,
- N_Aspect_Specification => 837,
- N_Variant => 834,
- N_Discriminant_Specification => 746,
- N_Loop_Statement => 744,
- N_Derived_Type_Definition => 731,
- N_Freeze_Generic_Entity => 702,
- N_Iteration_Scheme => 686,
- N_Package_Instantiation => 658,
- N_Loop_Parameter_Specification => 632,
- N_Attribute_Definition_Clause => 608,
- N_Compilation_Unit_Aux => 599,
- N_Compilation_Unit => 599,
- N_Label => 572,
- N_Goto_Statement => 572,
- N_In => 564,
- N_Enumeration_Type_Definition => 523,
- N_Object_Renaming_Declaration => 482,
- N_If_Expression => 476,
- N_Exception_Declaration => 472,
- N_Reference => 455,
- N_Incomplete_Type_Declaration => 438,
- N_Use_Package_Clause => 401,
- N_Unconstrained_Array_Definition => 360,
- N_Variant_Part => 340,
- N_Defining_Program_Unit_Name => 336,
- N_Op_And => 334,
- N_Raise_Program_Error => 329,
- N_Formal_Discrete_Type_Definition => 319,
- N_Contract => 311,
- N_Not_In => 305,
- N_Designator => 285,
- N_Component_Clause => 247,
- N_Formal_Signed_Integer_Type_Definition => 244,
- N_Raise_Statement => 214,
- N_Op_Expon => 205,
- N_Op_Minus => 202,
- N_Op_Multiply => 158,
- N_Exit_Statement => 130,
- N_Function_Instantiation => 129,
- N_Discriminant_Association => 123,
- N_Private_Extension_Declaration => 119,
- N_Extended_Return_Statement => 117,
- N_Op_Divide => 107,
- N_Op_Or => 103,
- N_Signed_Integer_Type_Definition => 101,
- N_Record_Representation_Clause => 76,
- N_Unchecked_Expression => 70,
- N_Op_Abs => 63,
- N_Elsif_Part => 62,
- N_Formal_Floating_Point_Definition => 59,
- N_Formal_Package_Declaration => 58,
- N_Modular_Type_Definition => 55,
- N_Abstract_Subprogram_Declaration => 52,
- N_Validate_Unchecked_Conversion => 49,
- N_Defining_Character_Literal => 36,
- N_Raise_Storage_Error => 33,
- N_Compound_Statement => 29,
- N_Procedure_Instantiation => 28,
- N_Access_Procedure_Definition => 25,
- N_Floating_Point_Definition => 20,
- N_Use_Type_Clause => 19,
- N_Op_Plus => 14,
- N_Package_Body => 13,
- N_Op_Rem => 13,
- N_Enumeration_Representation_Clause => 13,
- N_Access_Function_Definition => 11,
- N_Extension_Aggregate => 11,
- N_Formal_Ordinary_Fixed_Point_Definition => 10,
- N_Op_Mod => 10,
- N_Expression_Function => 9,
- N_Delay_Relative_Statement => 9,
- N_Quantified_Expression => 7,
- N_Formal_Derived_Type_Definition => 7,
- N_Free_Statement => 7,
- N_Iterator_Specification => 5,
- N_Op_Shift_Left => 5,
- N_Formal_Modular_Type_Definition => 4,
- N_Generic_Package_Renaming_Declaration => 1,
- N_Empty => 1,
- N_Real_Range_Specification => 1,
- N_Ordinary_Fixed_Point_Definition => 1,
- N_Op_Shift_Right => 1,
- N_Error => 1,
- N_Mod_Clause => 1,
- others => 0);
-
- Total_Node_Count : constant Long_Float := 1370676.0;
-
- type Node_Frequency_Table is array (Concrete_Node) of Long_Float;
-
- function Init_Node_Frequency return Node_Frequency_Table;
- -- Compute the value of the Node_Frequency table
-
- function Average_Type_Size_In_Slots return Long_Float;
- -- Compute the average over all concrete node types of the size,
- -- weighted by the frequency of that node type.
-
- function Init_Node_Frequency return Node_Frequency_Table is
- Result : Node_Frequency_Table := (others => 0.0);
-
- begin
- for T in Concrete_Node loop
- Result (T) := Long_Float (Node_Counts (T)) / Total_Node_Count;
- end loop;
-
- return Result;
- end Init_Node_Frequency;
-
- Node_Frequency : constant Node_Frequency_Table := Init_Node_Frequency;
- -- Table mapping concrete node types to the relative frequency of
- -- that node, in our large example. The sum of these values should
- -- add up to approximately 1.0. For example, if Node_Frequency(K) =
- -- 0.02, then that means that approximately 2% of all nodes are K
- -- nodes.
-
- function Average_Type_Size_In_Slots return Long_Float is
- -- We don't have data on entities, so we leave those out
-
- Result : Long_Float := 0.0;
- begin
- for T in Concrete_Node loop
- Result := Result +
- Node_Frequency (T) * Long_Float (Type_Size_In_Slots (T));
- end loop;
-
- return Result;
- end Average_Type_Size_In_Slots;
-
- -- Start of processing for Compute_Type_Sizes
-
begin
for T in Concrete_Type loop
declare
@@ -1289,7 +1112,10 @@ package body Gen_IL.Gen is
end if;
end loop;
- Type_Bit_Size (T) := Max_Offset + 1;
+ -- No type can be smaller than the header slots
+
+ Type_Bit_Size (T) :=
+ Bit_Offset'Max (Max_Offset + 1, SS * Num_Header_Slots);
end;
end loop;
@@ -1311,8 +1137,6 @@ package body Gen_IL.Gen is
Max_Node_Size := To_Size_In_Slots (Max_Node_Bit_Size);
Min_Entity_Size := To_Size_In_Slots (Min_Entity_Bit_Size);
Max_Entity_Size := To_Size_In_Slots (Max_Entity_Bit_Size);
-
- Average_Node_Size_In_Slots := Average_Type_Size_In_Slots;
end Compute_Type_Sizes;
----------------------------------------
@@ -1533,7 +1357,7 @@ package body Gen_IL.Gen is
case Root is
when Node_Kind =>
Put_Getter_Decl (S, Nkind);
- Put (S, "function K (N : Node_Id) return Node_Kind renames Nkind;" & LF);
+ Put (S, "function K (N : Node_Id) return Node_Kind renames " & Image (Nkind) & ";" & LF);
Put (S, "-- Shorthand for use in predicates and preconditions below" & LF);
Put (S, "-- There is no procedure Set_Nkind." & LF);
Put (S, "-- See Init_Nkind and Mutate_Nkind in Atree." & LF & LF);
@@ -1587,66 +1411,26 @@ package body Gen_IL.Gen is
Put (S, LF & "subtype Flag is Boolean;" & LF & LF);
end Put_Type_And_Subtypes;
- function Low_Level_Getter_Name (T : Type_Enum) return String is
- ("Get_" & Image (T));
- function Low_Level_Setter_Name (T : Type_Enum) return String is
- ("Set_" & Image (T));
- function Low_Level_Setter_Name (F : Field_Enum) return String is
- (Low_Level_Setter_Name (Field_Table (F).Field_Type) &
- (if Setter_Needs_Parent (F) then "_With_Parent" else ""));
-
-------------------------------------------
- -- Put_Low_Level_Accessor_Instantiations --
+ -- Put_Casts --
-------------------------------------------
- procedure Put_Low_Level_Accessor_Instantiations
+ procedure Put_Casts
(S : in out Sink; T : Type_Enum)
is
+ Pre : constant String :=
+ "function Cast is new Unchecked_Conversion (";
+ Lo_Type : constant String := "Field_Size_" & Image (Field_Size (T)) & "_Bit";
+ Hi_Type : constant String := Get_Set_Id_Image (T);
begin
- -- Special case for subtypes of Uint that have predicates. Use
- -- Get_Valid_32_Bit_Field in that case.
-
- if T in Uint_Subtype then
- pragma Assert (Field_Size (T) = 32);
- Put (S, LF & "function " & Low_Level_Getter_Name (T) &
- " is new Get_Valid_32_Bit_Field (" &
- Get_Set_Id_Image (T) &
- ") with " & Inline & ";" & LF);
-
- -- Special case for types that have special defaults; instantiate
- -- Get_32_Bit_Field_With_Default and pass in the Default_Val.
-
- elsif Field_Has_Special_Default (T) then
- pragma Assert (Field_Size (T) = 32);
- Put (S, LF & "function " & Low_Level_Getter_Name (T) &
- " is new Get_32_Bit_Field_With_Default (" &
- Get_Set_Id_Image (T) & ", " & Special_Default (T) &
- ") with " & Inline & ";" & LF);
-
- -- Otherwise, instantiate the normal getter for the right size in
- -- bits.
-
- else
- Put (S, LF & "function " & Low_Level_Getter_Name (T) &
- " is new Get_" & Image (Field_Size (T)) & "_Bit_Field (" &
- Get_Set_Id_Image (T) & ") with " & Inline & ";" & LF);
- end if;
-
- if T in Node_Kind_Type | Entity_Kind_Type then
- Put (S, "pragma Warnings (Off);" & LF);
- -- Set_Node_Kind_Type and Set_Entity_Kind_Type might not be called
- end if;
-
- -- No special cases for the setter
-
- Put (S, "procedure " & Low_Level_Setter_Name (T) & " is new Set_" &
- Image (Field_Size (T)) & "_Bit_Field (" & Get_Set_Id_Image (T) &
- ") with " & Inline & ";" & LF);
+ if T not in Uint_Subtype then
+ if T not in Node_Kind_Type | Entity_Kind_Type then
+ Put (S, Pre & Hi_Type & ", " & Lo_Type & ");" & LF);
+ end if;
- if T in Node_Kind_Type | Entity_Kind_Type then
- Put (S, "pragma Warnings (On);" & LF);
+ Put (S, Pre & Lo_Type & ", " & Hi_Type & ");" & LF);
end if;
- end Put_Low_Level_Accessor_Instantiations;
+ end Put_Casts;
----------------------
-- Put_Precondition --
@@ -1713,6 +1497,25 @@ package body Gen_IL.Gen is
-- Node_Id or Entity_Id, and the getter and setter will have
-- preconditions.
+ procedure Put_Get_Set_Incr
+ (S : in out Sink; F : Field_Enum; Get_Or_Set : String)
+ with Pre => Get_Or_Set in "Get" | "Set";
+ -- If statistics are enabled, put the appropriate increment statement
+
+ ----------------------
+ -- Put_Get_Set_Incr --
+ ----------------------
+
+ procedure Put_Get_Set_Incr
+ (S : in out Sink; F : Field_Enum; Get_Or_Set : String) is
+ begin
+ if Statistics_Enabled then
+ Put (S, "Atree." & Get_Or_Set & "_Count (" & F_Image (F) &
+ ") := Atree." & Get_Or_Set & "_Count (" &
+ F_Image (F) & ") + 1;" & LF);
+ end if;
+ end Put_Get_Set_Incr;
+
------------------------
-- Node_To_Fetch_From --
------------------------
@@ -1748,17 +1551,68 @@ package body Gen_IL.Gen is
Put (S, " with " & Inline);
Increase_Indent (S, 2);
Put_Precondition (S, F);
-
Decrease_Indent (S, 2);
Put (S, ";" & LF);
end Put_Getter_Decl;
+ ------------------------------
+ -- Put_Getter_Setter_Locals --
+ ------------------------------
+
+ procedure Put_Getter_Setter_Locals
+ (S : in out Sink; F : Field_Enum; Get : Boolean)
+ is
+ Rec : Field_Info renames Field_Table (F).all;
+
+ F_Size : constant Bit_Offset := Field_Size (Rec.Field_Type);
+ Off : constant Field_Offset := Rec.Offset;
+ F_Per_Slot : constant Field_Offset :=
+ SS / Field_Offset (Field_Size (Rec.Field_Type));
+ Slot_Off : constant Field_Offset := Off / F_Per_Slot;
+ In_NH : constant Boolean := Slot_Off < Num_Header_Slots;
+
+ N : constant String :=
+ (if Get then Node_To_Fetch_From (F) else "N");
+
+ begin
+ Put (S, " is" & LF);
+ Increase_Indent (S, 3);
+ Put (S, "-- " & Image (F_Per_Slot) & " " & Image (F_Size) &
+ "-bit fields per " & SSS & "-bit slot." & LF);
+ Put (S, "-- Offset " & Image (Off) & " = " &
+ Image (Slot_Off) & " slots + " & Image (Off mod F_Per_Slot) &
+ " fields in slot." & LF & LF);
+
+ Put (S, "Off : constant := " & Image (Off) & ";" & LF);
+ Put (S, "F_Size : constant := " & Image (F_Size) & ";" & LF);
+
+ if Field_Size (Rec.Field_Type) /= SS then
+ Put (S, "Mask : constant := 2**F_Size - 1;" & LF);
+ end if;
+
+ Put (S, "F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;" & LF);
+ Put (S, "Slot_Off : constant Field_Offset := Off / F_Per_Slot;" & LF);
+
+ if In_NH then
+ Put (S, "S : Slot renames Node_Offsets.Table (" & N & ").Slots (Slot_Off);" & LF);
+ else
+ Put (S, "S : Slot renames Slots.Table (Node_Offsets.Table (" & N & ").Offset + Slot_Off);" & LF);
+ end if;
+
+ if Field_Size (Rec.Field_Type) /= SS then
+ Put (S, "V : constant Natural := Natural ((Off mod F_Per_Slot) * F_Size);" & LF);
+ Put (S, LF);
+ end if;
+ end Put_Getter_Setter_Locals;
+
---------------------
-- Put_Getter_Body --
---------------------
procedure Put_Getter_Body (S : in out Sink; F : Field_Enum) is
Rec : Field_Info renames Field_Table (F).all;
+ F_Size : constant Bit_Offset := Field_Size (Rec.Field_Type);
+ T : constant String := Get_Set_Id_Image (Rec.Field_Type);
begin
-- Note that we store the result in a local constant below, so that
-- the "Pre => ..." can refer to it. The constant is called Val so
@@ -1767,16 +1621,44 @@ package body Gen_IL.Gen is
-- and setter.
Put_Getter_Spec (S, F);
- Put (S, " is" & LF);
- Increase_Indent (S, 3);
- Put (S, "Val : constant " & Get_Set_Id_Image (Rec.Field_Type) &
- " := " & Low_Level_Getter_Name (Rec.Field_Type) &
- " (" & Node_To_Fetch_From (F) & ", " &
- Image (Rec.Offset) & ");" & LF);
+ Put_Getter_Setter_Locals (S, F, Get => True);
+
+ Put (S, "Raw : constant Field_Size_" & Image (F_Size) & "_Bit :=" & LF);
+ Increase_Indent (S, 2);
+ Put (S, "Field_Size_" & Image (F_Size) & "_Bit (");
+
+ if Field_Size (Rec.Field_Type) /= SS then
+ Put (S, "Shift_Right (S, V) and Mask);" & LF);
+ else
+ Put (S, "S);" & LF);
+ end if;
+
+ Decrease_Indent (S, 2);
+
+ Put (S, "Val : constant " & T & " :=");
+
+ if Field_Has_Special_Default (Rec.Field_Type) then
+ pragma Assert (Field_Size (Rec.Field_Type) = 32);
+ Put (S, LF);
+ Increase_Indent (S, 2);
+ Put (S, "(if Raw = 0 then " & Special_Default (Rec.Field_Type) &
+ " else " & "Cast (Raw));");
+ Decrease_Indent (S, 2);
+
+ else
+ Put (S, " Cast (Raw);");
+ end if;
+
+ Put (S, LF);
+
Decrease_Indent (S, 3);
Put (S, "begin" & LF);
Increase_Indent (S, 3);
+ Put (S, "-- pragma Debug (Validate_Node_And_Offset (NN, Slot_Off));" & LF);
+ -- Comment out the validation, because it's too slow, and because the
+ -- relevant routines in Atree are not visible.
+
if Rec.Pre.all /= "" then
Put (S, "pragma Assert (" & Rec.Pre.all & ");" & LF);
end if;
@@ -1785,6 +1667,7 @@ package body Gen_IL.Gen is
Put (S, "pragma Assert (" & Rec.Pre_Get.all & ");" & LF);
end if;
+ Put_Get_Set_Incr (S, F, "Get");
Put (S, "return Val;" & LF);
Decrease_Indent (S, 3);
Put (S, "end " & Image (F) & ";" & LF & LF);
@@ -1824,6 +1707,7 @@ package body Gen_IL.Gen is
procedure Put_Setter_Body (S : in out Sink; F : Field_Enum) is
Rec : Field_Info renames Field_Table (F).all;
+ F_Size : constant Bit_Offset := Field_Size (Rec.Field_Type);
-- If Type_Only was specified in the call to Create_Semantic_Field,
-- then we assert that the node is a base type. We cannot assert that
@@ -1836,10 +1720,18 @@ package body Gen_IL.Gen is
"Is_Base_Type (N)");
begin
Put_Setter_Spec (S, F);
- Put (S, " is" & LF);
+ Put_Getter_Setter_Locals (S, F, Get => False);
+
+ Put (S, "Raw : constant Field_Size_" & Image (F_Size) & "_Bit := Cast (Val);" & LF);
+
+ Decrease_Indent (S, 3);
Put (S, "begin" & LF);
Increase_Indent (S, 3);
+ Put (S, "-- pragma Debug (Validate_Node_And_Offset_Write (N, Slot_Off));" & LF);
+ -- Comment out the validation, because it's too slow, and because the
+ -- relevant routines in Atree are not visible.
+
if Rec.Pre.all /= "" then
Put (S, "pragma Assert (" & Rec.Pre.all & ");" & LF);
end if;
@@ -1852,8 +1744,29 @@ package body Gen_IL.Gen is
Put (S, "pragma Assert (" & Type_Only_Assertion & ");" & LF);
end if;
- Put (S, Low_Level_Setter_Name (F) & " (N, " & Image (Rec.Offset)
- & ", Val);" & LF);
+ if Setter_Needs_Parent (F) then
+ declare
+ Err : constant String :=
+ (if Rec.Field_Type = List_Id then "Error_List" else "Error");
+ begin
+ Put (S, "if Present (Val) and then Val /= " & Err & " then" & LF);
+ Increase_Indent (S, 3);
+ Put (S, "pragma Warnings (Off, ""actuals for this call may be in wrong order"");" & LF);
+ Put (S, "Set_Parent (Val, N);" & LF);
+ Put (S, "pragma Warnings (On, ""actuals for this call may be in wrong order"");" & LF);
+ Decrease_Indent (S, 3);
+ Put (S, "end if;" & LF & LF);
+ end;
+ end if;
+
+ if Field_Size (Rec.Field_Type) /= SS then
+ Put (S, "S := (S and not Shift_Left (Mask, V)) or Shift_Left (Slot (Raw), V);" & LF);
+
+ else
+ Put (S, "S := Slot (Raw);" & LF);
+ end if;
+
+ Put_Get_Set_Incr (S, F, "Set");
Decrease_Indent (S, 3);
Put (S, "end Set_" & Image (F) & ";" & LF & LF);
end Put_Setter_Body;
@@ -2076,7 +1989,7 @@ package body Gen_IL.Gen is
when others => "Entity_Field"); -- Entity_Kind
begin
- Put (S, "-- Table of sizes in 32-bit slots for given " &
+ Put (S, "-- Table of sizes in " & SSS & "-bit slots for given " &
Image (Root) & ", for use by Atree:" & LF);
case Root is
@@ -2085,8 +1998,7 @@ package body Gen_IL.Gen is
Image (Min_Node_Size) & ";" & LF);
Put (S, "Max_Node_Size : constant Field_Offset := " &
Image (Max_Node_Size) & ";" & LF & LF);
- Put (S, "Average_Node_Size_In_Slots : constant := " &
- Average_Node_Size_In_Slots'Img & ";" & LF & LF);
+
when Entity_Kind =>
Put (S, LF & "Min_Entity_Size : constant Field_Offset := " &
Image (Min_Entity_Size) & ";" & LF);
@@ -2107,34 +2019,48 @@ package body Gen_IL.Gen is
Put (S, "); -- Size" & LF);
Decrease_Indent (S, 2);
- declare
- type Dummy is array
- (First_Field (Root) .. Last_Field (Root)) of Boolean;
- Num_Fields : constant Root_Int := Dummy'Length;
- First_Time : Boolean := True;
- begin
- Put (S, LF & "-- Enumeration of all " & Image (Num_Fields)
- & " fields:" & LF & LF);
+ if Root = Node_Kind then
+ declare
+ type Node_Dummy is array (Node_Field) of Boolean;
+ type Entity_Dummy is array (Entity_Field) of Boolean;
+ Num_Fields : constant Root_Int :=
+ Node_Dummy'Length + Entity_Dummy'Length;
+ First_Time : Boolean := True;
+ begin
+ Put (S, LF & "-- Enumeration of all " & Image (Num_Fields)
+ & " fields:" & LF & LF);
- Put (S, "type " & Field_Enum_Type_Name & " is" & LF);
- Increase_Indent (S, 2);
- Put (S, "(");
- Increase_Indent (S, 1);
+ Put (S, "type Node_Or_Entity_Field is" & LF);
+ Increase_Indent (S, 2);
+ Put (S, "(");
+ Increase_Indent (S, 1);
- for F in First_Field (Root) .. Last_Field (Root) loop
- if First_Time then
- First_Time := False;
- else
+ for F in Node_Field loop
+ if First_Time then
+ First_Time := False;
+ else
+ Put (S, "," & LF);
+ end if;
+
+ Put (S, F_Image (F));
+ end loop;
+
+ for F in Entity_Field loop
Put (S, "," & LF);
- end if;
+ Put (S, F_Image (F));
+ end loop;
- Put (S, F_Image (F));
- end loop;
+ Decrease_Indent (S, 1);
+ Put (S, "); -- Node_Or_Entity_Field" & LF);
+ Decrease_Indent (S, 2);
+ end;
+ end if;
- Decrease_Indent (S, 1);
- Put (S, "); -- " & Field_Enum_Type_Name & LF);
- Decrease_Indent (S, 2);
- end;
+ Put (S, LF & "subtype " & Field_Enum_Type_Name & " is" & LF);
+ Increase_Indent (S, 2);
+ Put (S, "Node_Or_Entity_Field range " & F_Image (First_Field (Root)) &
+ " .. " & F_Image (Last_Field (Root)) & ";" & LF);
+ Decrease_Indent (S, 2);
Put (S, LF & "type " & Field_Enum_Type_Name & "_Index is new Pos;" & LF);
Put (S, "type " & Field_Enum_Type_Name & "_Array is array (" &
@@ -2193,34 +2119,67 @@ package body Gen_IL.Gen is
Decrease_Indent (S, 2);
end;
- declare
- First_Time : Boolean := True;
- begin
- Put (S, LF & "-- Table mapping fields to kind and offset:" & LF & LF);
+ if Root = Node_Kind then
+ declare
+ First_Time : Boolean := True;
+ FS, FB, LB : Bit_Offset;
+ -- Field size in bits, first bit, and last bit for the previous
+ -- time around the loop. Used to print a comment after ",".
- Put (S, Field_Enum_Type_Name & "_Descriptors : constant array (" &
- Field_Enum_Type_Name & ") of Field_Descriptor :=" & LF);
+ procedure One_Comp (F : Field_Enum);
- Increase_Indent (S, 2);
- Put (S, "(");
- Increase_Indent (S, 1);
+ procedure One_Comp (F : Field_Enum) is
+ pragma Annotate (Codepeer, Modified, Field_Table);
+ Offset : constant Field_Offset := Field_Table (F).Offset;
+ begin
+ if First_Time then
+ First_Time := False;
+ else
+ Put (S, ",");
- for F in First_Field (Root) .. Last_Field (Root) loop
- if First_Time then
- First_Time := False;
- else
- Put (S, "," & LF);
- end if;
+ -- Print comment showing field's bits, except for 1-bit
+ -- fields.
- Put (S, F_Image (F) & " => (" &
- Image (Field_Table (F).Field_Type) & "_Field, " &
- Image (Field_Table (F).Offset) & ")");
- end loop;
+ if FS /= 1 then
+ Put (S, " -- *" & Image (FS) & " = bits " &
+ Image (FB) & ".." & Image (LB));
+ end if;
- Decrease_Indent (S, 1);
- Put (S, "); -- Field_Descriptors" & LF);
- Decrease_Indent (S, 2);
- end;
+ Put (S, LF);
+ end if;
+
+ Put (S, F_Image (F) & " => (" &
+ Image (Field_Table (F).Field_Type) & "_Field, " &
+ Image (Offset) & ")");
+
+ FS := Field_Size (F);
+ FB := First_Bit (F, Offset);
+ LB := Last_Bit (F, Offset);
+ end One_Comp;
+
+ begin
+ Put (S, LF & "-- Table mapping fields to kind and offset:" & LF & LF);
+
+ Put (S, "Field_Descriptors : constant array (" &
+ "Node_Or_Entity_Field) of Field_Descriptor :=" & LF);
+
+ Increase_Indent (S, 2);
+ Put (S, "(");
+ Increase_Indent (S, 1);
+
+ for F in Node_Field loop
+ One_Comp (F);
+ end loop;
+
+ for F in Entity_Field loop
+ One_Comp (F);
+ end loop;
+
+ Decrease_Indent (S, 1);
+ Put (S, "); -- Field_Descriptors" & LF);
+ Decrease_Indent (S, 2);
+ end;
+ end if;
end Put_Tables;
@@ -2291,7 +2250,16 @@ package body Gen_IL.Gen is
Put (S, "Kind : Field_Kind;" & LF);
Put (S, "Offset : Field_Offset;" & LF);
Decrease_Indent (S, 3);
- Put (S, "end record;" & LF);
+ Put (S, "end record;" & LF & LF);
+
+ -- Print out the node header types. Note that the Offset field is of
+ -- the base type, because we are using zero-origin addressing in
+ -- Atree.
+
+ Put (S, "N_Head : constant Field_Offset := " & N_Head & ";" & LF & LF);
+
+ Put (S, "Atree_Statistics_Enabled : constant Boolean := " &
+ Capitalize (Boolean'Image (Statistics_Enabled)) & ";" & LF);
Decrease_Indent (S, 3);
Put (S, LF & "end Seinfo;" & LF);
@@ -2305,39 +2273,6 @@ package body Gen_IL.Gen is
S : Sink;
B : Sink;
- procedure Put_Setter_With_Parent (Kind : String);
- -- Put the low-level ..._With_Parent setter. Kind is either "Node" or
- -- "List".
-
- procedure Put_Setter_With_Parent (Kind : String) is
- Error : constant String := (if Kind = "Node" then "" else "_" & Kind);
- begin
- Put (B, LF & "procedure Set_" & Kind & "_Id_With_Parent" & LF);
- Increase_Indent (B, 2);
- Put (B, "(N : Node_Id; Offset : Field_Offset; Val : " & Kind & "_Id);" & LF & LF);
- Decrease_Indent (B, 2);
-
- Put (B, "procedure Set_" & Kind & "_Id_With_Parent" & LF);
- Increase_Indent (B, 2);
- Put (B, "(N : Node_Id; Offset : Field_Offset; Val : " & Kind & "_Id) is" & LF);
- Decrease_Indent (B, 2);
- Put (B, "begin" & LF);
- Increase_Indent (B, 3);
- Put (B, "if Present (Val) and then Val /= Error" & Error & " then" & LF);
- Increase_Indent (B, 3);
- Put (B, "pragma Warnings (Off, ""actuals for this call may be in wrong order"");" & LF);
- Put (B, "Set_Parent (Val, N);" & LF);
- Put (B, "pragma Warnings (On, ""actuals for this call may be in wrong order"");" & LF);
- Decrease_Indent (B, 3);
- Put (B, "end if;" & LF & LF);
-
- Put (B, "Set_" & Kind & "_Id (N, Offset, Val);" & LF);
- Decrease_Indent (B, 3);
- Put (B, "end Set_" & Kind & "_Id_With_Parent;" & LF);
- end Put_Setter_With_Parent;
-
- -- Start of processing for Put_Nodes
-
begin
Create_File (S, "sinfo-nodes.ads");
Create_File (B, "sinfo-nodes.adb");
@@ -2369,6 +2304,7 @@ package body Gen_IL.Gen is
Decrease_Indent (S, 3);
Put (S, LF & "end Sinfo.Nodes;" & LF);
+ Put (B, "with Unchecked_Conversion;" & LF);
Put (B, "with Atree; use Atree; use Atree.Atree_Private_Part;" & LF);
Put (B, "with Nlists; use Nlists;" & LF);
Put (B, "pragma Warnings (Off);" & LF);
@@ -2381,19 +2317,14 @@ package body Gen_IL.Gen is
Put (B, "-- This package is automatically generated." & LF & LF);
- Put (B, "-- Instantiations of low-level getters and setters that take offsets" & LF);
- Put (B, "-- in units of the size of the field." & LF);
-
Put (B, "pragma Style_Checks (""M200"");" & LF);
+
for T in Special_Type loop
if Node_Field_Types_Used (T) then
- Put_Low_Level_Accessor_Instantiations (B, T);
+ Put_Casts (B, T);
end if;
end loop;
- Put_Setter_With_Parent ("Node");
- Put_Setter_With_Parent ("List");
-
Put_Subp_Bodies (B, Node_Kind);
Decrease_Indent (B, 3);
@@ -2411,7 +2342,6 @@ package body Gen_IL.Gen is
begin
Create_File (S, "einfo-entities.ads");
Create_File (B, "einfo-entities.adb");
- Put (S, "with Seinfo; use Seinfo;" & LF);
Put (S, "with Sinfo.Nodes; use Sinfo.Nodes;" & LF);
Put (S, LF & "package Einfo.Entities is" & LF & LF);
@@ -2430,6 +2360,7 @@ package body Gen_IL.Gen is
Decrease_Indent (S, 3);
Put (S, LF & "end Einfo.Entities;" & LF);
+ Put (B, "with Unchecked_Conversion;" & LF);
Put (B, "with Atree; use Atree; use Atree.Atree_Private_Part;" & LF);
Put (B, "with Einfo.Utils; use Einfo.Utils;" & LF);
-- This forms a cycle between packages (via bodies, which is OK)
@@ -2439,13 +2370,11 @@ package body Gen_IL.Gen is
Put (B, "-- This package is automatically generated." & LF & LF);
- Put (B, "-- Instantiations of low-level getters and setters that take offsets" & LF);
- Put (B, "-- in units of the size of the field." & LF);
-
Put (B, "pragma Style_Checks (""M200"");" & LF);
+
for T in Special_Type loop
if Entity_Field_Types_Used (T) then
- Put_Low_Level_Accessor_Instantiations (B, T);
+ Put_Casts (B, T);
end if;
end loop;
@@ -2494,7 +2423,8 @@ package body Gen_IL.Gen is
end if;
end loop;
- Put (S, ")" & LF & "return " & Node_Or_Entity (Root) & "_Id");
+ Put (S, ")" & LF);
+ Put (S, "return " & Node_Or_Entity (Root) & "_Id");
Decrease_Indent (S, 2);
Decrease_Indent (S, 1);
end Put_Make_Spec;
@@ -2714,11 +2644,11 @@ package body Gen_IL.Gen is
return Result : Bit_Offset do
if F = No_Field then
-- We don't have a field size for No_Field, so just look at
- -- the bits up to the next word boundary.
+ -- the bits up to the next slot boundary.
Result := First_Bit;
- while (Result + 1) mod 32 /= 0
+ while (Result + 1) mod SS /= 0
and then Type_Layout (T) (Result + 1) = No_Field
loop
Result := Result + 1;
@@ -2731,19 +2661,19 @@ package body Gen_IL.Gen is
end Get_Last_Bit;
function First_Bit_Image (First_Bit : Bit_Offset) return String is
- W : constant Bit_Offset := First_Bit / 32;
- B : constant Bit_Offset := First_Bit mod 32;
- pragma Assert (W * 32 + B = First_Bit);
+ W : constant Bit_Offset := First_Bit / SS;
+ B : constant Bit_Offset := First_Bit mod SS;
+ pragma Assert (W * SS + B = First_Bit);
begin
return
- Image (W) & "*32" & (if B = 0 then "" else " + " & Image (B));
+ Image (W) & "*" & SSS & (if B = 0 then "" else " + " & Image (B));
end First_Bit_Image;
function Last_Bit_Image (Last_Bit : Bit_Offset) return String is
- W : constant Bit_Offset := (Last_Bit + 1) / 32;
+ W : constant Bit_Offset := (Last_Bit + 1) / SS;
begin
- if W * 32 - 1 = Last_Bit then
- return Image (W) & "*32 - 1";
+ if W * SS - 1 = Last_Bit then
+ return Image (W) & "*" & SSS & " - 1";
else
return First_Bit_Image (Last_Bit);
end if;
@@ -2857,6 +2787,7 @@ package body Gen_IL.Gen is
declare
First_Time : Boolean := True;
+
begin
for T in Concrete_Type loop
if First_Time then
@@ -2878,40 +2809,45 @@ package body Gen_IL.Gen is
declare
First_Time : Boolean := True;
First_Bit : Bit_Offset := 0;
+ F : Opt_Field_Enum;
+
+ function Node_Field_Of_Entity return String is
+ (if T in Entity_Type and then F in Node_Field then
+ " -- N" else "");
+ -- A comment to put out for fields of entities that are
+ -- shared with nodes, such as Chars.
+
begin
while First_Bit < Type_Bit_Size_Aligned (T) loop
if First_Time then
First_Time := False;
else
- Put (B, "," & LF);
+ Put (B, "," & Node_Field_Of_Entity & LF);
end if;
+ F := Type_Layout (T) (First_Bit);
+
declare
- F : constant Opt_Field_Enum :=
- Type_Layout (T) (First_Bit);
+ Last_Bit : constant Bit_Offset :=
+ Get_Last_Bit (T, F, First_Bit);
begin
- declare
- Last_Bit : constant Bit_Offset :=
- Get_Last_Bit (T, F, First_Bit);
- begin
+ pragma Assert
+ (Type_Layout (T) (First_Bit .. Last_Bit) =
+ (First_Bit .. Last_Bit => F));
+
+ if Last_Bit = First_Bit then
+ Put (B, First_Bit_Image (First_Bit) & " => " &
+ Image_Or_Waste (F));
+ else
pragma Assert
- (Type_Layout (T) (First_Bit .. Last_Bit) =
- (First_Bit .. Last_Bit => F));
-
- if Last_Bit = First_Bit then
- Put (B, First_Bit_Image (First_Bit) & " => " &
- Image_Or_Waste (F));
- else
- pragma Assert
- (if F /= No_Field then
- First_Bit mod Field_Size (F) = 0);
- Put (B, First_Bit_Image (First_Bit) & " .. " &
- Last_Bit_Image (Last_Bit) & " => " &
- Image_Or_Waste (F));
- end if;
-
- First_Bit := Last_Bit + 1;
- end;
+ (if F /= No_Field then
+ First_Bit mod Field_Size (F) = 0);
+ Put (B, First_Bit_Image (First_Bit) & " .. " &
+ Last_Bit_Image (Last_Bit) & " => " &
+ Image_Or_Waste (F));
+ end if;
+
+ First_Bit := Last_Bit + 1;
end;
end loop;
end;
@@ -3017,6 +2953,8 @@ package body Gen_IL.Gen is
end Put_Kind_Subtype;
begin
+ Put_Union_Membership (S, Root, Only_Prototypes => True);
+
Iterate_Types (Root, Pre => Put_Enum_Lit'Access);
Put (S, "#define Number_" & Node_Or_Entity (Root) & "_Kinds " &
@@ -3024,86 +2962,94 @@ package body Gen_IL.Gen is
Iterate_Types (Root, Pre => Put_Kind_Subtype'Access);
- Put_Union_Membership (S, Root);
+ Put_Union_Membership (S, Root, Only_Prototypes => False);
end Put_C_Type_And_Subtypes;
- ----------------------------
- -- Put_Low_Level_C_Getter --
- ----------------------------
+ ------------------
+ -- Put_C_Getter --
+ ------------------
- procedure Put_Low_Level_C_Getter
- (S : in out Sink; T : Type_Enum)
+ procedure Put_C_Getter
+ (S : in out Sink; F : Field_Enum)
is
- T_Image : constant String := Get_Set_Id_Image (T);
+ Rec : Field_Info renames Field_Table (F).all;
+ Off : constant Field_Offset := Rec.Offset;
+ F_Size : constant Bit_Offset := Field_Size (Rec.Field_Type);
+ F_Per_Slot : constant Field_Offset :=
+ SS / Field_Offset (Field_Size (Rec.Field_Type));
+ Slot_Off : constant Field_Offset := Off / F_Per_Slot;
+ In_NH : constant Boolean := Slot_Off < Num_Header_Slots;
+
+ N : constant String := Node_To_Fetch_From (F);
begin
- Put (S, "INLINE " & T_Image & "" & LF);
- Put (S, "Get_" & Image (T) & " (Node_Id N, Field_Offset Offset)" & LF);
+ Put (S, "INLINE " & Get_Set_Id_Image (Rec.Field_Type) &
+ " " & Image (F) & " (Node_Id N)" & LF);
+ Put (S, "{" & LF);
Increase_Indent (S, 3);
+ Put (S, "const Field_Offset Off = " & Image (Rec.Offset) & ";" & LF);
+ Put (S, "const Field_Offset F_Size = " & Image (F_Size) & ";" & LF);
- -- Same special cases for getters as in
- -- Put_Low_Level_Accessor_Instantiations.
-
- if T in Uint_Subtype then
- pragma Assert (Field_Size (T) = 32);
- Put (S, "{ return (" & T_Image &
- ") Get_Valid_32_Bit_Field(N, Offset); }" & LF & LF);
+ if Field_Size (Rec.Field_Type) /= SS then
+ Put (S, "const any_slot Mask = (1 << F_Size) - 1;" & LF);
+ end if;
- elsif Field_Has_Special_Default (T) then
- pragma Assert (Field_Size (T) = 32);
- Put (S, "{ return (" & T_Image &
- ") Get_32_Bit_Field_With_Default(N, Offset, " &
- Special_Default (T) & "); }" & LF & LF);
+ Put (S, "const Field_Offset F_Per_Slot = Slot_Size / F_Size;" & LF);
+ Put (S, "const Field_Offset Slot_Off = Off / F_Per_Slot;" & LF);
+ Put (S, LF);
+ if In_NH then
+ Put (S, "any_slot slot = Node_Offsets_Ptr[" & N & "].Slots[Slot_Off];" & LF);
+ else
+ Put (S, "any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[" & N &
+ "].Offset + Slot_Off);" & LF);
+ end if;
+ if Field_Size (Rec.Field_Type) /= SS then
+ Put (S, "unsigned int Raw = (slot >> (Off % F_Per_Slot) * F_Size) & Mask;" & LF);
else
- Put (S, "{ return (" & T_Image & ") Get_" &
- Image (Field_Size (T)) & "_Bit_Field(N, Offset); }" & LF & LF);
+ Put (S, "unsigned int Raw = slot;" & LF);
end if;
- Decrease_Indent (S, 3);
- end Put_Low_Level_C_Getter;
+ Put (S, Get_Set_Id_Image (Rec.Field_Type) & " val = ");
- -----------------------------
- -- Put_High_Level_C_Getter --
- -----------------------------
+ if Field_Has_Special_Default (Rec.Field_Type) then
+ Increase_Indent (S, 2);
+ Put (S, "(Raw? Raw : " & Special_Default (Rec.Field_Type) & ")");
+ Decrease_Indent (S, 2);
- procedure Put_High_Level_C_Getter
- (S : in out Sink; F : Field_Enum)
- is
- begin
- Put (S, "INLINE " & Get_Set_Id_Image (Field_Table (F).Field_Type) &
- " " & Image (F) & " (Node_Id N)" & LF);
+ else
+ Put (S, "Raw");
+ end if;
- Increase_Indent (S, 3);
- Put (S, "{ return " &
- Low_Level_Getter_Name (Field_Table (F).Field_Type) &
- "(" & Node_To_Fetch_From (F) & ", " &
- Image (Field_Table (F).Offset) & "); }" & LF & LF);
+ Put (S, ";" & LF);
+
+ Put (S, "return val;" & LF);
Decrease_Indent (S, 3);
- end Put_High_Level_C_Getter;
+ Put (S, "}" & LF & LF);
+ end Put_C_Getter;
- ------------------------------
- -- Put_High_Level_C_Getters --
- ------------------------------
+ -------------------
+ -- Put_C_Getters --
+ -------------------
- procedure Put_High_Level_C_Getters
+ procedure Put_C_Getters
(S : in out Sink; Root : Root_Type)
is
begin
Put (S, "// Getters for fields" & LF & LF);
for F in First_Field (Root) .. Last_Field (Root) loop
- Put_High_Level_C_Getter (S, F);
+ Put_C_Getter (S, F);
end loop;
- end Put_High_Level_C_Getters;
+ end Put_C_Getters;
--------------------------
-- Put_Union_Membership --
--------------------------
procedure Put_Union_Membership
- (S : in out Sink; Root : Root_Type) is
+ (S : in out Sink; Root : Root_Type; Only_Prototypes : Boolean) is
procedure Put_Ors (T : Abstract_Type);
-- Print the "or" (i.e. "||") of tests whether kind is in each child
@@ -3137,22 +3083,27 @@ package body Gen_IL.Gen is
end Put_Ors;
begin
- Put (S, LF & "// Membership tests for union types" & LF & LF);
+ if not Only_Prototypes then
+ Put (S, LF & "// Membership tests for union types" & LF & LF);
+ end if;
for T in First_Abstract (Root) .. Last_Abstract (Root) loop
if Type_Table (T) /= null and then Type_Table (T).Is_Union then
Put (S, "INLINE Boolean" & LF);
Put (S, "Is_In_" & Image (T) & " (" &
- Node_Or_Entity (Root) & "_Kind kind)" & LF);
+ Node_Or_Entity (Root) & "_Kind kind)" &
+ (if Only_Prototypes then ";" else "") & LF);
- Put (S, "{" & LF);
- Increase_Indent (S, 3);
- Put (S, "return" & LF);
- Increase_Indent (S, 3);
- Put_Ors (T);
- Decrease_Indent (S, 3);
- Decrease_Indent (S, 3);
- Put (S, ";" & LF & "}" & LF);
+ if not Only_Prototypes then
+ Put (S, "{" & LF);
+ Increase_Indent (S, 3);
+ Put (S, "return" & LF);
+ Increase_Indent (S, 3);
+ Put_Ors (T);
+ Decrease_Indent (S, 3);
+ Decrease_Indent (S, 3);
+ Put (S, ";" & LF & "}" & LF);
+ end if;
Put (S, "" & LF);
end if;
@@ -3174,16 +3125,24 @@ package body Gen_IL.Gen is
Put (S, "typedef Boolean Flag;" & LF & LF);
+ Put (S, "#define N_Head " & N_Head & LF);
+ Put (S, "" & LF);
+ Put (S, "typedef struct Node_Header {" & LF);
+ Increase_Indent (S, 2);
+ Put (S, "any_slot Slots[N_Head];" & LF);
+ Put (S, "Field_Offset Offset;" & LF);
+ Decrease_Indent (S, 2);
+ Put (S, "} Node_Header;" & LF & LF);
+
+ Put (S, "extern Node_Header *Node_Offsets_Ptr;" & LF);
+ Put (S, "extern any_slot *Slots_Ptr;" & LF & LF);
+
Put_C_Type_And_Subtypes (S, Node_Kind);
Put (S, "// Getters corresponding to instantiations of Atree.Get_n_Bit_Field"
& LF & LF);
- for T in Special_Type loop
- Put_Low_Level_C_Getter (S, T);
- end loop;
-
- Put_High_Level_C_Getters (S, Node_Kind);
+ Put_C_Getters (S, Node_Kind);
Put (S, "#ifdef __cplusplus" & LF);
Put (S, "}" & LF);
@@ -3238,11 +3197,7 @@ package body Gen_IL.Gen is
Put_C_Type_And_Subtypes (S, Entity_Kind);
- -- Note that we do not call Put_Low_Level_C_Getter here. Those are in
- -- sinfo.h, so every file that #includes einfo.h must #include
- -- sinfo.h first.
-
- Put_High_Level_C_Getters (S, Entity_Kind);
+ Put_C_Getters (S, Entity_Kind);
Put (S, "// Abstract type queries" & LF & LF);
diff --git a/gcc/ada/gen_il-internals.adb b/gcc/ada/gen_il-internals.adb
index d77fe7a..fe1af78 100644
--- a/gcc/ada/gen_il-internals.adb
+++ b/gcc/ada/gen_il-internals.adb
@@ -255,7 +255,7 @@ package body Gen_IL.Internals is
begin
case F is
-- Special cases for the same reason as in the above Image
- -- function.
+ -- function for Opt_Type_Enum.
when Alloc_For_BIP_Return =>
return "Alloc_For_BIP_Return";
diff --git a/gcc/ada/gen_il-internals.ads b/gcc/ada/gen_il-internals.ads
index 53c23a2..a811e0b4 100644
--- a/gcc/ada/gen_il-internals.ads
+++ b/gcc/ada/gen_il-internals.ads
@@ -147,6 +147,9 @@ package Gen_IL.Internals is
-- The default is No_Type_Only, indicating the field is not one of
-- these special "[... only]" ones.
+ Unknown_Offset : constant := -1;
+ -- Initial value of Offset, so we can tell whether it has been set
+
type Field_Info is record
Have_This_Field : Type_Vector;
-- Types that have this field
@@ -162,7 +165,7 @@ package Gen_IL.Internals is
-- Above record the information in the calls to Create_...Field.
-- See Gen_IL.Gen for details.
- Offset : Field_Offset;
+ Offset : Field_Offset'Base range Unknown_Offset .. Field_Offset'Last;
-- Offset of the field from the start of the node, in units of the field
-- size. So if a field is 4 bits in size, it starts at bit number
-- Offset*4 from the start of the node.
@@ -274,4 +277,344 @@ package Gen_IL.Internals is
-- Return "Node" or "Entity" depending on whether Root = Node_Kind or
-- Entity_Kind.
+ pragma Style_Checks (Off);
+ -- We don't want warnings about wrong casing in the Type_Frequency table;
+ -- this table is not intended to be particularly readable.
+
+ -- The Type_Frequency table shows the frequency of nodes and entity kinds
+ -- printed by -gnatd.A for a large example. It is used in the field offset
+ -- computations for efficiency. Note that N_Defining_Identifier,
+ -- N_Defining_Operator_Symbol, and N_Defining_Character_Literal are set to
+ -- zero, because the Ekind is what matters for those.
+
+ Type_Frequency : constant array (Concrete_Type) of Type_Count :=
+ (N_Identifier => 3496964, -- (0.354) 7 slots
+ N_Defining_Identifier => 0, -- 1468484, -- (0.149) 8 slots
+ N_Integer_Literal => 455415, -- (0.046) 6 slots
+ E_In_Parameter => 391008, -- (0.040) 42 slots
+ N_Attribute_Reference => 330825, -- (0.033) 9 slots
+ N_Expanded_Name => 329509, -- (0.033) 8 slots
+ N_Selected_Component => 328862, -- (0.033) 8 slots
+ N_Parameter_Specification => 321313, -- (0.033) 7 slots
+ E_Void => 173019, -- (0.018) 59 slots
+ N_Explicit_Dereference => 155113, -- (0.016) 8 slots
+ N_Procedure_Call_Statement => 125403, -- (0.013) 8 slots
+ N_Object_Declaration => 115610, -- (0.012) 8 slots
+ E_Component => 108208, -- (0.011) 49 slots
+ N_Procedure_Specification => 106277, -- (0.011) 7 slots
+ E_Procedure => 104063, -- (0.011) 62 slots
+ N_Unchecked_Type_Conversion => 94477, -- (0.010) 7 slots
+ N_Range => 91413, -- (0.009) 6 slots
+ E_Function => 90035, -- (0.009) 62 slots
+ N_Handled_Sequence_Of_Statements => 87930, -- (0.009) 8 slots
+ N_Subprogram_Declaration => 85248, -- (0.009) 7 slots
+ N_Parameter_Association => 81464, -- (0.008) 8 slots
+ N_Indexed_Component => 80049, -- (0.008) 7 slots
+ N_Freeze_Entity => 79904, -- (0.008) 8 slots
+ N_Call_Marker => 79521, -- (0.008) 4 slots
+ N_Assignment_Statement => 76554, -- (0.008) 8 slots
+ N_Function_Specification => 76052, -- (0.008) 7 slots
+ N_Function_Call => 75028, -- (0.008) 9 slots
+ N_Op_Eq => 74874, -- (0.008) 8 slots
+ E_Constant => 66667, -- (0.007) 47 slots
+ N_If_Statement => 60066, -- (0.006) 8 slots
+ N_Component_Association => 54642, -- (0.006) 7 slots
+ N_Subprogram_Body => 53805, -- (0.005) 10 slots
+ N_Type_Conversion => 53383, -- (0.005) 7 slots
+ E_In_Out_Parameter => 52936, -- (0.005) 38 slots
+ N_Simple_Return_Statement => 52436, -- (0.005) 7 slots
+ N_Subtype_Indication => 49535, -- (0.005) 6 slots
+ N_Raise_Constraint_Error => 49069, -- (0.005) 6 slots
+ N_Null => 46850, -- (0.005) 5 slots
+ N_Itype_Reference => 45422, -- (0.005) 4 slots
+ E_Anonymous_Access_Type => 45149, -- (0.005) 44 slots
+ N_And_Then => 44721, -- (0.005) 8 slots
+ N_Block_Statement => 44328, -- (0.004) 10 slots
+ N_Subtype_Declaration => 43149, -- (0.004) 6 slots
+ N_Op_Not => 40531, -- (0.004) 7 slots
+ E_Array_Subtype => 40051, -- (0.004) 50 slots
+ N_Expression_With_Actions => 36726, -- (0.004) 7 slots
+ E_Access_Subprogram_Type => 36700, -- (0.004) 45 slots
+ E_Signed_Integer_Subtype => 36659, -- (0.004) 43 slots
+ N_String_Literal => 34815, -- (0.004) 7 slots
+ N_Aggregate => 33899, -- (0.003) 8 slots
+ N_Index_Or_Discriminant_Constraint => 33546, -- (0.003) 4 slots
+ E_Variable => 33102, -- (0.003) 55 slots
+ E_Block => 32829, -- (0.003) 58 slots
+ N_Op_Ne => 32127, -- (0.003) 8 slots
+ N_Pragma_Argument_Association => 31504, -- (0.003) 7 slots
+ N_Null_Statement => 30816, -- (0.003) 5 slots
+ N_Aspect_Specification => 29667, -- (0.003) 9 slots
+ N_Pragma => 28317, -- (0.003) 9 slots
+ N_Generic_Association => 26297, -- (0.003) 8 slots
+ N_Formal_Concrete_Subprogram_Declaration => 25843, -- (0.003) 6 slots
+ N_Op_Lt => 25328, -- (0.003) 8 slots
+ E_String_Literal_Subtype => 25272, -- (0.003) 48 slots
+ N_Full_Type_Declaration => 25258, -- (0.003) 7 slots
+ N_With_Clause => 24370, -- (0.002) 9 slots
+ N_Op_Add => 23839, -- (0.002) 8 slots
+ E_Subprogram_Body => 23790, -- (0.002) 42 slots
+ E_Return_Statement => 23098, -- (0.002) 51 slots
+ N_Or_Else => 22858, -- (0.002) 8 slots
+ N_Implicit_Label_Declaration => 21687, -- (0.002) 5 slots
+ N_Others_Choice => 21579, -- (0.002) 4 slots
+ E_Out_Parameter => 21513, -- (0.002) 38 slots
+ N_Op_Subtract => 21441, -- (0.002) 8 slots
+ N_Op_Ge => 21116, -- (0.002) 8 slots
+ N_Component_Definition => 21075, -- (0.002) 7 slots
+ N_Case_Statement_Alternative => 19664, -- (0.002) 8 slots
+ N_Loop_Statement => 19507, -- (0.002) 9 slots
+ E_Package => 19029, -- (0.002) 53 slots
+ N_Op_Gt => 18619, -- (0.002) 8 slots
+ N_Op_Le => 16564, -- (0.002) 8 slots
+ N_Formal_Object_Declaration => 16219, -- (0.002) 7 slots
+ E_Discriminant => 16091, -- (0.002) 56 slots
+ N_Component_Declaration => 15858, -- (0.002) 7 slots
+ N_Iteration_Scheme => 15719, -- (0.002) 8 slots
+ N_Access_To_Object_Definition => 14875, -- (0.002) 5 slots
+ E_Record_Subtype => 14569, -- (0.001) 52 slots
+ N_Generic_Subprogram_Declaration => 14320, -- (0.001) 7 slots
+ N_Package_Specification => 13323, -- (0.001) 8 slots
+ N_Exception_Handler => 12841, -- (0.001) 8 slots
+ E_Enumeration_Literal => 11608, -- (0.001) 42 slots
+ N_Subprogram_Renaming_Declaration => 10991, -- (0.001) 9 slots
+ N_In => 10794, -- (0.001) 8 slots
+ E_Allocator_Type => 10751, -- (0.001) 44 slots
+ E_General_Access_Type => 10451, -- (0.001) 44 slots
+ E_Generic_Procedure => 9837, -- (0.001) 41 slots
+ N_Package_Renaming_Declaration => 9395, -- (0.001) 8 slots
+ N_Access_Definition => 9388, -- (0.001) 6 slots
+ N_Qualified_Expression => 9012, -- (0.001) 7 slots
+ E_Enumeration_Subtype => 8560, -- (0.001) 46 slots
+ N_Allocator => 8474, -- (0.001) 8 slots
+ N_Package_Declaration => 8099, -- (0.001) 10 slots
+ N_Formal_Type_Declaration => 7964, -- (0.001) 7 slots
+ N_Exit_Statement => 7960, -- (0.001) 8 slots
+ N_Component_List => 7829, -- (0.001) 5 slots
+ N_Defining_Operator_Symbol => 0, -- 7525, -- (0.001) 8 slots
+ N_Case_Statement => 7271, -- (0.001) 7 slots
+ N_Expression_Function => 7242, -- (0.001) 9 slots
+ N_Loop_Parameter_Specification => 7042, -- (0.001) 7 slots
+ N_Character_Literal => 6842, -- (0.001) 7 slots
+ N_Op_Concat => 6565, -- (0.001) 8 slots
+ N_Not_In => 6341, -- (0.001) 8 slots
+ N_Label => 6133, -- (0.001) 9 slots
+ N_Goto_Statement => 6133, -- (0.001) 8 slots
+ E_Label => 6133, -- (0.001) 57 slots
+ E_Loop => 6008, -- (0.001) 41 slots
+ N_Generic_Package_Declaration => 5808, -- (0.001) 10 slots
+ N_If_Expression => 5800, -- (0.001) 7 slots
+ N_Record_Definition => 5628, -- (0.001) 7 slots
+ N_Slice => 5461, -- (0.001) 7 slots
+ N_Reference => 5332, -- (0.001) 7 slots
+ E_Generic_Package => 5268, -- (0.001) 59 slots
+ E_Record_Type => 4838, -- (0.000) 51 slots
+ N_Raise_Program_Error => 4675, -- (0.000) 6 slots
+ N_Raise_Statement => 4628, -- (0.000) 8 slots
+ N_Use_Type_Clause => 4487, -- (0.000) 9 slots
+ E_Array_Type => 4325, -- (0.000) 48 slots
+ E_Operator => 4308, -- (0.000) 55 slots
+ N_Freeze_Generic_Entity => 4249, -- (0.000) 4 slots
+ N_Constrained_Array_Definition => 4244, -- (0.000) 5 slots
+ N_Object_Renaming_Declaration => 4067, -- (0.000) 8 slots
+ N_Formal_Private_Type_Definition => 4018, -- (0.000) 8 slots
+ E_Loop_Parameter => 3870, -- (0.000) 38 slots
+ N_Real_Literal => 3759, -- (0.000) 7 slots
+ N_Attribute_Definition_Clause => 3724, -- (0.000) 8 slots
+ N_Exception_Renaming_Declaration => 3697, -- (0.000) 8 slots
+ E_Class_Wide_Type => 3674, -- (0.000) 48 slots
+ E_Exception => 3632, -- (0.000) 24 slots
+ N_Range_Constraint => 3506, -- (0.000) 4 slots
+ E_Access_Type => 3487, -- (0.000) 44 slots
+ E_Subprogram_Type => 3248, -- (0.000) 47 slots
+ N_Package_Instantiation => 3005, -- (0.000) 8 slots
+ E_Access_Attribute_Type => 2959, -- (0.000) 44 slots
+ N_Op_And => 2957, -- (0.000) 8 slots
+ E_Generic_In_Parameter => 2704, -- (0.000) 31 slots
+ N_Derived_Type_Definition => 2688, -- (0.000) 7 slots
+ N_Variant => 2535, -- (0.000) 8 slots
+ E_Record_Subtype_With_Private => 2327, -- (0.000) 50 slots
+ N_Private_Type_Declaration => 2287, -- (0.000) 6 slots
+ E_Private_Type => 1890, -- (0.000) 48 slots
+ N_Discriminant_Specification => 1864, -- (0.000) 7 slots
+ N_Procedure_Instantiation => 1659, -- (0.000) 8 slots
+ N_Op_Multiply => 1634, -- (0.000) 8 slots
+ E_Access_Subtype => 1606, -- (0.000) 44 slots
+ N_Defining_Program_Unit_Name => 1463, -- (0.000) 8 slots
+ N_Number_Declaration => 1461, -- (0.000) 7 slots
+ E_Named_Integer => 1430, -- (0.000) 19 slots
+ N_Use_Package_Clause => 1369, -- (0.000) 9 slots
+ N_Compilation_Unit_Aux => 1341, -- (0.000) 8 slots
+ N_Compilation_Unit => 1341, -- (0.000) 8 slots
+ N_Elsif_Part => 1331, -- (0.000) 7 slots
+ N_Operator_Symbol => 1305, -- (0.000) 7 slots
+ E_Limited_Private_Type => 1299, -- (0.000) 48 slots
+ E_Generic_Function => 1292, -- (0.000) 41 slots
+ E_Enumeration_Type => 1186, -- (0.000) 47 slots
+ N_Enumeration_Type_Definition => 1169, -- (0.000) 6 slots
+ N_Unchecked_Expression => 1112, -- (0.000) 7 slots
+ N_Op_Or => 1107, -- (0.000) 8 slots
+ N_Designator => 1100, -- (0.000) 9 slots
+ N_Formal_Discrete_Type_Definition => 1086, -- (0.000) 4 slots
+ N_Variant_Part => 1072, -- (0.000) 8 slots
+ N_Formal_Package_Declaration => 1047, -- (0.000) 8 slots
+ N_Quantified_Expression => 1033, -- (0.000) 8 slots
+ E_Record_Type_With_Private => 1017, -- (0.000) 51 slots
+ N_Package_Body => 999, -- (0.000) 9 slots
+ N_Unconstrained_Array_Definition => 973, -- (0.000) 5 slots
+ E_Private_Subtype => 971, -- (0.000) 48 slots
+ N_Incomplete_Type_Declaration => 863, -- (0.000) 6 slots
+ E_Incomplete_Type => 863, -- (0.000) 48 slots
+ N_Contract => 859, -- (0.000) 6 slots
+ E_Package_Body => 852, -- (0.000) 46 slots
+ N_Extended_Return_Statement => 801, -- (0.000) 8 slots
+ N_Op_Divide => 724, -- (0.000) 8 slots
+ N_Extension_Aggregate => 718, -- (0.000) 8 slots
+ N_Function_Instantiation => 642, -- (0.000) 8 slots
+ N_Exception_Declaration => 594, -- (0.000) 7 slots
+ N_Discriminant_Association => 552, -- (0.000) 7 slots
+ N_Iterator_Specification => 543, -- (0.000) 8 slots
+ N_Private_Extension_Declaration => 540, -- (0.000) 8 slots
+ N_Formal_Signed_Integer_Type_Definition => 512, -- (0.000) 4 slots
+ E_Modular_Integer_Subtype => 490, -- (0.000) 44 slots
+ N_Component_Clause => 468, -- (0.000) 7 slots
+ E_Signed_Integer_Type => 399, -- (0.000) 43 slots
+ N_Op_Minus => 356, -- (0.000) 7 slots
+ N_Raise_Expression => 337, -- (0.000) 8 slots
+ N_Case_Expression_Alternative => 336, -- (0.000) 8 slots
+ N_Op_Expon => 280, -- (0.000) 8 slots
+ N_Abstract_Subprogram_Declaration => 250, -- (0.000) 6 slots
+ E_Modular_Integer_Type => 232, -- (0.000) 44 slots
+ N_Modular_Type_Definition => 214, -- (0.000) 7 slots
+ N_Compound_Statement => 212, -- (0.000) 6 slots
+ N_Free_Statement => 209, -- (0.000) 8 slots
+ N_Record_Representation_Clause => 197, -- (0.000) 9 slots
+ N_Access_Procedure_Definition => 195, -- (0.000) 6 slots
+ E_Limited_Private_Subtype => 178, -- (0.000) 48 slots
+ N_Access_Function_Definition => 172, -- (0.000) 7 slots
+ N_Op_Mod => 163, -- (0.000) 8 slots
+ N_Validate_Unchecked_Conversion => 156, -- (0.000) 5 slots
+ E_Anonymous_Access_Subprogram_Type => 155, -- (0.000) 44 slots
+ N_Op_Rem => 147, -- (0.000) 8 slots
+ N_Formal_Incomplete_Type_Definition => 140, -- (0.000) 4 slots
+ N_Signed_Integer_Type_Definition => 137, -- (0.000) 6 slots
+ N_Case_Expression => 132, -- (0.000) 7 slots
+ N_Op_Plus => 129, -- (0.000) 7 slots
+ E_Incomplete_Subtype => 129, -- (0.000) 48 slots
+ N_Op_Abs => 119, -- (0.000) 7 slots
+ N_Op_Shift_Right => 109, -- (0.000) 8 slots
+ E_Floating_Point_Subtype => 94, -- (0.000) 43 slots
+ N_Op_Shift_Left => 72, -- (0.000) 8 slots
+ E_Floating_Point_Type => 59, -- (0.000) 43 slots
+ N_Formal_Derived_Type_Definition => 53, -- (0.000) 7 slots
+ N_Formal_Floating_Point_Definition => 40, -- (0.000) 4 slots
+ N_Defining_Character_Literal => 0, -- 36, -- (0.000) 8 slots
+ N_Formal_Modular_Type_Definition => 27, -- (0.000) 4 slots
+ E_Ordinary_Fixed_Point_Subtype => 23, -- (0.000) 44 slots
+ E_Abstract_State => 22, -- (0.000) 48 slots
+ E_Named_Real => 20, -- (0.000) 19 slots
+ N_Floating_Point_Definition => 19, -- (0.000) 6 slots
+ N_Subunit => 17, -- (0.000) 8 slots
+ N_Enumeration_Representation_Clause => 17, -- (0.000) 9 slots
+ N_Entry_Declaration => 17, -- (0.000) 7 slots
+ N_Subprogram_Body_Stub => 16, -- (0.000) 8 slots
+ N_Unused_At_Start => 15, -- (0.000) 4 slots
+ E_Entry => 14, -- (0.000) 42 slots
+ N_Formal_Ordinary_Fixed_Point_Definition => 12, -- (0.000) 4 slots
+ E_Class_Wide_Subtype => 9, -- (0.000) 52 slots
+ E_Protected_Subtype => 8, -- (0.000) 48 slots
+ E_Ordinary_Fixed_Point_Type => 8, -- (0.000) 44 slots
+ N_Op_Xor => 7, -- (0.000) 8 slots
+ E_Generic_In_Out_Parameter => 7, -- (0.000) 31 slots
+ N_Protected_Type_Declaration => 6, -- (0.000) 8 slots
+ N_Protected_Definition => 6, -- (0.000) 8 slots
+ N_Task_Type_Declaration => 4, -- (0.000) 8 slots
+ N_Task_Definition => 4, -- (0.000) 8 slots
+ N_Protected_Body => 4, -- (0.000) 9 slots
+ E_Task_Subtype => 4, -- (0.000) 50 slots
+ E_Protected_Type => 4, -- (0.000) 49 slots
+ E_Access_Protected_Subprogram_Type => 4, -- (0.000) 45 slots
+ N_Entry_Call_Statement => 3, -- (0.000) 8 slots
+ E_Task_Type => 3, -- (0.000) 50 slots
+ N_Raise_Storage_Error => 2, -- (0.000) 6 slots
+ N_Package_Body_Stub => 2, -- (0.000) 8 slots
+ N_Generic_Procedure_Renaming_Declaration => 2, -- (0.000) 8 slots
+ N_Task_Body => 1, -- (0.000) 10 slots
+ N_Single_Protected_Declaration => 1, -- (0.000) 8 slots
+ N_Real_Range_Specification => 1, -- (0.000) 6 slots
+ N_Ordinary_Fixed_Point_Definition => 1, -- (0.000) 6 slots
+ N_Error => 1, -- (0.000) 6 slots
+ N_Entry_Body_Formal_Part => 1, -- (0.000) 6 slots
+ N_Entry_Body => 1, -- (0.000) 10 slots
+ N_Empty => 1, -- (0.000) 6 slots
+ N_Delay_Relative_Statement => 1, -- (0.000) 7 slots
+ E_Protected_Body => 1, -- (0.000) 35 slots
+
+ Between_Concrete_Node_And_Concrete_Entity_Types => 0,
+
+ -- The rest had frequency 0 (i.e. no such nodes were created in the
+ -- example), but we set them to 1, so we won't lose information when
+ -- multiplying. We use "others", so that if new node types are added,
+ -- we don't have to modify the table; new node types are unlikely to
+ -- be very common.
+
+ others => 1
+ -- N_Variable_Reference_Marker => 0, (0.000) 4 slots
+ -- N_Unused_At_End => 0, (0.000) 4 slots
+ -- N_Triggering_Alternative => 0, (0.000) 6 slots
+ -- N_Timed_Entry_Call => 0, (0.000) 5 slots
+ -- N_Terminate_Alternative => 0, (0.000) 6 slots
+ -- N_Task_Body_Stub => 0, (0.000) 8 slots
+ -- N_Target_Name => 0, (0.000) 5 slots
+ -- N_Single_Task_Declaration => 0, (0.000) 8 slots
+ -- N_Selective_Accept => 0, (0.000) 5 slots
+ -- N_Scil_Membership_Test => 0, (0.000) 5 slots
+ -- N_Scil_Dispatch_Table_Tag_Init => 0, (0.000) 4 slots
+ -- N_Scil_Dispatching_Call => 0, (0.000) 6 slots
+ -- N_Return_When_Statement => 0, (0.000) 7 slots
+ -- N_Requeue_Statement => 0, (0.000) 8 slots
+ -- N_Raise_When_Statement => 0, (0.000) 8 slots
+ -- N_Push_Storage_Error_Label => 0, (0.000) 4 slots
+ -- N_Push_Program_Error_Label => 0, (0.000) 4 slots
+ -- N_Push_Constraint_Error_Label => 0, (0.000) 4 slots
+ -- N_Protected_Body_Stub => 0, (0.000) 8 slots
+ -- N_Pop_Storage_Error_Label => 0, (0.000) 4 slots
+ -- N_Pop_Program_Error_Label => 0, (0.000) 4 slots
+ -- N_Pop_Constraint_Error_Label => 0, (0.000) 4 slots
+ -- N_Op_Shift_Right_Arithmetic => 0, (0.000) 8 slots
+ -- N_Op_Rotate_Right => 0, (0.000) 8 slots
+ -- N_Op_Rotate_Left => 0, (0.000) 8 slots
+ -- N_Mod_Clause => 0, (0.000) 7 slots
+ -- N_Iterated_Element_Association => 0, (0.000) 8 slots
+ -- N_Iterated_Component_Association => 0, (0.000) 8 slots
+ -- N_Goto_When_Statement => 0, (0.000) 8 slots
+ -- N_Generic_Package_Renaming_Declaration => 0, (0.000) 8 slots
+ -- N_Generic_Function_Renaming_Declaration => 0, (0.000) 8 slots
+ -- N_Formal_Decimal_Fixed_Point_Definition => 0, (0.000) 4 slots
+ -- N_Formal_Abstract_Subprogram_Declaration => 0, (0.000) 6 slots
+ -- N_Entry_Index_Specification => 0, (0.000) 7 slots
+ -- N_Entry_Call_Alternative => 0, (0.000) 6 slots
+ -- N_Digits_Constraint => 0, (0.000) 6 slots
+ -- N_Delta_Constraint => 0, (0.000) 6 slots
+ -- N_Delta_Aggregate => 0, (0.000) 8 slots
+ -- N_Delay_Until_Statement => 0, (0.000) 7 slots
+ -- N_Delay_Alternative => 0, (0.000) 7 slots
+ -- N_Decimal_Fixed_Point_Definition => 0, (0.000) 6 slots
+ -- N_Conditional_Entry_Call => 0, (0.000) 5 slots
+ -- N_Code_Statement => 0, (0.000) 7 slots
+ -- N_At_Clause => 0, (0.000) 9 slots
+ -- N_Asynchronous_Select => 0, (0.000) 5 slots
+ -- N_Accept_Statement => 0, (0.000) 8 slots
+ -- N_Accept_Alternative => 0, (0.000) 8 slots
+ -- N_Abort_Statement => 0, (0.000) 4 slots
+ -- N_Abortable_Part => 0, (0.000) 5 slots
+ -- E_Task_Body => 0, (0.000) 39 slots
+ -- E_Exception_Type => 0, (0.000) 45 slots
+ -- E_Entry_Index_Parameter => 0, (0.000) 19 slots
+ -- E_Entry_Family => 0, (0.000) 42 slots
+ -- E_Decimal_Fixed_Point_Type => 0, (0.000) 52 slots
+ -- E_Decimal_Fixed_Point_Subtype => 0, (0.000) 52 slots
+ -- E_Anonymous_Access_Protected_Subprogram_Type => 0, (0.000) 45 slots
+ ); -- Type_Frequency
+
end Gen_IL.Internals;
diff --git a/gcc/ada/gen_il-types.ads b/gcc/ada/gen_il-types.ads
index 321eec6..97b9dd2 100644
--- a/gcc/ada/gen_il-types.ads
+++ b/gcc/ada/gen_il-types.ads
@@ -77,6 +77,7 @@ package Gen_IL.Types is
Node_Kind, -- root of node type hierarchy
N_Access_To_Subprogram_Definition,
+ N_Alternative,
N_Array_Type_Definition,
N_Binary_Op,
N_Body_Stub,
@@ -84,13 +85,21 @@ package Gen_IL.Types is
N_Delay_Statement,
N_Direct_Name,
N_Entity,
+ N_Entity_Name,
N_Formal_Subprogram_Declaration,
N_Generic_Declaration,
N_Generic_Instantiation,
N_Generic_Renaming_Declaration,
+ N_Has_Bounds,
N_Has_Chars,
+ N_Has_Condition,
N_Has_Entity,
N_Has_Etype,
+ N_Is_Case_Choice,
+ N_Is_Decl,
+ N_Is_Exception_Choice,
+ N_Is_Index,
+ N_Is_Range,
N_Multiplying_Operator,
N_Later_Decl_Item,
N_Membership_Test,
@@ -111,7 +120,6 @@ package Gen_IL.Types is
N_Statement_Other_Than_Procedure_Call,
N_Subprogram_Call,
N_Subprogram_Instantiation,
- N_Has_Condition,
N_Subexpr,
N_Subprogram_Specification,
N_Unary_Op,
@@ -144,6 +152,7 @@ package Gen_IL.Types is
Elementary_Kind,
Enumeration_Kind,
Entry_Kind,
+ Evaluable_Kind,
Exception_Or_Object_Kind,
Fixed_Point_Kind,
Float_Kind,
@@ -151,6 +160,7 @@ package Gen_IL.Types is
Formal_Object_Kind,
Generic_Subprogram_Kind,
Generic_Unit_Kind,
+ Global_Name_Kind,
Incomplete_Kind,
Incomplete_Or_Private_Kind,
Integer_Kind,
@@ -167,8 +177,9 @@ package Gen_IL.Types is
Record_Kind,
Record_Field_Kind,
Scalar_Kind,
- Subprogram_Kind,
Signed_Integer_Kind,
+ Subprogram_Type_Or_Kind,
+ Subprogram_Kind,
Task_Kind,
Type_Kind,
Void_Or_Type_Kind,
diff --git a/gcc/ada/ghost.adb b/gcc/ada/ghost.adb
index 42ea0f5..1720fe0 100644
--- a/gcc/ada/ghost.adb
+++ b/gcc/ada/ghost.adb
@@ -584,6 +584,15 @@ package body Ghost is
-- Start of processing for Check_Ghost_Context
begin
+ -- Class-wide pre/postconditions of ignored pragmas are preanalyzed
+ -- to report errors on wrong conditions; however, ignored pragmas may
+ -- also have references to ghost entities and we must disable checking
+ -- their context to avoid reporting spurious errors.
+
+ if Inside_Class_Condition_Preanalysis then
+ return;
+ end if;
+
-- Once it has been established that the reference to the Ghost entity
-- is within a suitable context, ensure that the policy at the point of
-- declaration and at the point of use match.
diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb
index 95c1537..55f9efa 100644
--- a/gcc/ada/gnat1drv.adb
+++ b/gcc/ada/gnat1drv.adb
@@ -1695,6 +1695,10 @@ begin
<<End_Of_Program>>
+ if Debug_Flag_Dot_AA then
+ Atree.Print_Statistics;
+ end if;
+
-- The outer exception handler handles an unrecoverable error
exception
diff --git a/gcc/ada/gnat_cuda.adb b/gcc/ada/gnat_cuda.adb
index 6273a5d..a1739be 100644
--- a/gcc/ada/gnat_cuda.adb
+++ b/gcc/ada/gnat_cuda.adb
@@ -25,20 +25,25 @@
-- This package defines CUDA-specific datastructures and functions.
+with Atree; use Atree;
with Debug; use Debug;
+with Einfo.Entities; use Einfo.Entities;
+with Einfo.Utils; use Einfo.Utils;
with Elists; use Elists;
+with Errout; use Errout;
with Namet; use Namet;
with Nlists; use Nlists;
with Nmake; use Nmake;
with Rtsfind; use Rtsfind;
-with Sinfo; use Sinfo;
+with Sem; use Sem;
+with Sem_Aux; use Sem_Aux;
+with Sem_Util; use Sem_Util;
with Sinfo.Nodes; use Sinfo.Nodes;
+with Sinfo; use Sinfo;
+with Snames; use Snames;
with Stringt; use Stringt;
with Tbuild; use Tbuild;
with Uintp; use Uintp;
-with Sem; use Sem;
-with Sem_Util; use Sem_Util;
-with Snames; use Snames;
with GNAT.HTable;
@@ -54,6 +59,18 @@ package body GNAT_CUDA is
function Hash (F : Entity_Id) return Hash_Range;
-- Hash function for hash table
+ package CUDA_Device_Entities_Table is new
+ GNAT.HTable.Simple_HTable
+ (Header_Num => Hash_Range,
+ Element => Elist_Id,
+ No_Element => No_Elist,
+ Key => Entity_Id,
+ Hash => Hash,
+ Equal => "=");
+ -- The keys of this table are package entities whose bodies contain at
+ -- least one procedure marked with aspect CUDA_Device. The values are
+ -- Elists of the marked entities.
+
package CUDA_Kernels_Table is new
GNAT.HTable.Simple_HTable
(Header_Num => Hash_Range,
@@ -85,17 +102,60 @@ package body GNAT_CUDA is
-- * A procedure that takes care of calling CUDA functions that register
-- CUDA_Global procedures with the runtime.
+ procedure Empty_CUDA_Global_Subprograms (Pack_Id : Entity_Id);
+ -- For all subprograms marked CUDA_Global in Pack_Id, remove declarations
+ -- and replace statements with a single null statement.
+ -- This is required because CUDA_Global subprograms could be referring to
+ -- device-only symbols, which would result in unknown symbols at link time
+ -- if kept around.
+ -- We choose to empty CUDA_Global subprograms rather than completely
+ -- removing them from the package because registering CUDA_Global
+ -- subprograms with the CUDA runtime on the host requires knowing the
+ -- subprogram's host-side address.
+
+ function Get_CUDA_Device_Entities (Pack_Id : Entity_Id) return Elist_Id;
+ -- Returns an Elist of all entities marked with pragma CUDA_Device that
+ -- are declared within package body Pack_Body. Returns No_Elist if Pack_Id
+ -- does not contain such entities.
+
function Get_CUDA_Kernels (Pack_Id : Entity_Id) return Elist_Id;
-- Returns an Elist of all procedures marked with pragma CUDA_Global that
-- are declared within package body Pack_Body. Returns No_Elist if Pack_Id
-- does not contain such procedures.
+ procedure Remove_CUDA_Device_Entities (Pack_Id : Entity_Id);
+ -- Removes all entities marked with the CUDA_Device pragma from package
+ -- Pack_Id. Must only be called when compiling for the host.
+
+ procedure Set_CUDA_Device_Entities
+ (Pack_Id : Entity_Id;
+ E : Elist_Id);
+ -- Stores E as the list of CUDA_Device entities belonging to the package
+ -- entity Pack_Id. Pack_Id must not have a list of device entities.
+
procedure Set_CUDA_Kernels
(Pack_Id : Entity_Id;
Kernels : Elist_Id);
-- Stores Kernels as the list of kernels belonging to the package entity
-- Pack_Id. Pack_Id must not have a list of kernels.
+ ----------------------------
+ -- Add_CUDA_Device_Entity --
+ ----------------------------
+
+ procedure Add_CUDA_Device_Entity
+ (Pack_Id : Entity_Id;
+ E : Entity_Id)
+ is
+ Device_Entities : Elist_Id := Get_CUDA_Device_Entities (Pack_Id);
+ begin
+ if Device_Entities = No_Elist then
+ Device_Entities := New_Elmt_List;
+ Set_CUDA_Device_Entities (Pack_Id, Device_Entities);
+ end if;
+ Append_Elmt (E, Device_Entities);
+ end Add_CUDA_Device_Entity;
+
---------------------
-- Add_CUDA_Kernel --
---------------------
@@ -113,6 +173,50 @@ package body GNAT_CUDA is
Append_Elmt (Kernel, Kernels);
end Add_CUDA_Kernel;
+ -----------------------------------
+ -- Empty_CUDA_Global_Subprograms --
+ -----------------------------------
+
+ procedure Empty_CUDA_Global_Subprograms (Pack_Id : Entity_Id) is
+ Spec_Id : constant Node_Id := Corresponding_Spec (Pack_Id);
+ Kernels : constant Elist_Id := Get_CUDA_Kernels (Spec_Id);
+ Kernel_Elm : Elmt_Id;
+ Kernel : Entity_Id;
+ Kernel_Body : Node_Id;
+ Null_Body : Entity_Id;
+ Loc : Source_Ptr;
+ begin
+ -- It is an error to empty CUDA_Global subprograms when not compiling
+ -- for the host.
+ pragma Assert (Debug_Flag_Underscore_C);
+
+ if No (Kernels) then
+ return;
+ end if;
+
+ Kernel_Elm := First_Elmt (Kernels);
+ while Present (Kernel_Elm) loop
+ Kernel := Node (Kernel_Elm);
+ Kernel_Body := Subprogram_Body (Kernel);
+ Loc := Sloc (Kernel_Body);
+
+ Null_Body := Make_Subprogram_Body (Loc,
+ Specification => Subprogram_Specification (Kernel),
+ Declarations => New_List,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Make_Null_Statement (Loc))));
+
+ Rewrite (Kernel_Body, Null_Body);
+
+ Next_Elmt (Kernel_Elm);
+ end loop;
+ end Empty_CUDA_Global_Subprograms;
+
+ -------------------------
+ -- Expand_CUDA_Package --
+ -------------------------
+
procedure Expand_CUDA_Package (N : Node_Id) is
begin
@@ -122,6 +226,20 @@ package body GNAT_CUDA is
return;
end if;
+ -- Remove the content (both declarations and statements) of CUDA_Global
+ -- procedures. This is required because CUDA_Global functions could be
+ -- referencing entities available only on the device, which would result
+ -- in unknown symbol errors at link time.
+
+ Empty_CUDA_Global_Subprograms (N);
+
+ -- Remove CUDA_Device entities (except if they are also CUDA_Host), as
+ -- they can only be referenced from the device and might reference
+ -- device-only symbols.
+
+ Remove_CUDA_Device_Entities
+ (Package_Specification (Corresponding_Spec (N)));
+
-- If procedures marked with CUDA_Global have been defined within N,
-- we need to register them with the CUDA runtime at program startup.
-- This requires multiple declarations and function calls which need
@@ -139,6 +257,15 @@ package body GNAT_CUDA is
return Hash_Range (F mod 511);
end Hash;
+ ------------------------------
+ -- Get_CUDA_Device_Entities --
+ ------------------------------
+
+ function Get_CUDA_Device_Entities (Pack_Id : Entity_Id) return Elist_Id is
+ begin
+ return CUDA_Device_Entities_Table.Get (Pack_Id);
+ end Get_CUDA_Device_Entities;
+
----------------------
-- Get_CUDA_Kernels --
----------------------
@@ -605,9 +732,70 @@ package body GNAT_CUDA is
Analyze (New_Stmt);
end Build_And_Insert_CUDA_Initialization;
- --------------------
- -- Set_CUDA_Nodes --
- --------------------
+ ---------------------------------
+ -- Remove_CUDA_Device_Entities --
+ ---------------------------------
+
+ procedure Remove_CUDA_Device_Entities (Pack_Id : Entity_Id) is
+ Device_Entities : constant Elist_Id :=
+ Get_CUDA_Device_Entities (Pack_Id);
+ Device_Elmt : Elmt_Id;
+ Device_Entity : Entity_Id;
+ Bod : Node_Id;
+ begin
+ pragma Assert (Debug_Flag_Underscore_C);
+
+ if Device_Entities = No_Elist then
+ return;
+ end if;
+
+ Device_Elmt := First_Elmt (Device_Entities);
+ while Present (Device_Elmt) loop
+ Device_Entity := Node (Device_Elmt);
+ Next_Elmt (Device_Elmt);
+
+ case Ekind (Device_Entity) is
+ when E_Function | E_Procedure =>
+ Bod := Subprogram_Body (Device_Entity);
+
+ if Nkind (Parent (Bod)) = N_Subunit
+ and then Present (Corresponding_Stub (Parent (Bod)))
+ then
+ Error_Msg_N
+ ("Cuda_Device not suported on separate subprograms",
+ Corresponding_Stub (Parent (Bod)));
+ else
+ Remove (Bod);
+ Remove (Subprogram_Spec (Device_Entity));
+ end if;
+
+ when E_Variable | E_Constant =>
+ Remove (Declaration_Node (Device_Entity));
+
+ when others =>
+ pragma Assert (False);
+ end case;
+
+ Remove_Entity_And_Homonym (Device_Entity);
+ end loop;
+ end Remove_CUDA_Device_Entities;
+
+ ------------------------------
+ -- Set_CUDA_Device_Entities --
+ ------------------------------
+
+ procedure Set_CUDA_Device_Entities
+ (Pack_Id : Entity_Id;
+ E : Elist_Id)
+ is
+ begin
+ pragma Assert (Get_CUDA_Device_Entities (Pack_Id) = No_Elist);
+ CUDA_Device_Entities_Table.Set (Pack_Id, E);
+ end Set_CUDA_Device_Entities;
+
+ ----------------------
+ -- Set_CUDA_Kernels --
+ ----------------------
procedure Set_CUDA_Kernels
(Pack_Id : Entity_Id;
diff --git a/gcc/ada/gnat_cuda.ads b/gcc/ada/gnat_cuda.ads
index d35bc8a..390f5de 100644
--- a/gcc/ada/gnat_cuda.ads
+++ b/gcc/ada/gnat_cuda.ads
@@ -77,13 +77,19 @@ with Types; use Types;
package GNAT_CUDA is
+ procedure Add_CUDA_Device_Entity (Pack_Id : Entity_Id; E : Entity_Id);
+ -- And E to the list of CUDA_Device entities that belong to Pack_Id
+
procedure Add_CUDA_Kernel (Pack_Id : Entity_Id; Kernel : Entity_Id);
-- Add Kernel to the list of CUDA_Global nodes that belong to Pack_Id.
-- Kernel is a procedure entity marked with CUDA_Global, Pack_Id is the
-- entity of its parent package body.
procedure Expand_CUDA_Package (N : Node_Id);
- -- When compiling for the host, generate code to register kernels with the
- -- CUDA runtime and post-process kernels.
+ -- When compiling for the host:
+ -- - Generate code to register kernels with the CUDA runtime and
+ -- post-process kernels.
+ -- - Empty content of CUDA_Global procedures.
+ -- - Remove declarations of CUDA_Device entities.
end GNAT_CUDA;
diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi
index 349586e..0a962ee 100644
--- a/gcc/ada/gnat_rm.texi
+++ b/gcc/ada/gnat_rm.texi
@@ -21,7 +21,7 @@
@copying
@quotation
-GNAT Reference Manual , Jun 23, 2021
+GNAT Reference Manual , Sep 28, 2021
AdaCore
@@ -79,6 +79,7 @@ included in the section entitled @ref{1,,GNU Free Documentation License}.
* Specialized Needs Annexes::
* Implementation of Specific Ada Features::
* Implementation of Ada 2012 Features::
+* Security Hardening Features::
* Obsolescent Features::
* Compatibility and Porting Guide::
* GNU Free Documentation License::
@@ -224,7 +225,6 @@ Implementation Defined Pragmas
* Pragma Post::
* Pragma Postcondition::
* Pragma Post_Class::
-* Pragma Rename_Pragma::
* Pragma Pre::
* Pragma Precondition::
* Pragma Predicate::
@@ -247,6 +247,7 @@ Implementation Defined Pragmas
* Pragma Refined_State::
* Pragma Relative_Deadline::
* Pragma Remote_Access_Type::
+* Pragma Rename_Pragma::
* Pragma Restricted_Run_Time::
* Pragma Restriction_Warnings::
* Pragma Reviewable::
@@ -529,6 +530,7 @@ Partition-Wide Restrictions
Program Unit Level Restrictions
* No_Elaboration_Code::
+* No_Dynamic_Accessibility_Checks::
* No_Dynamic_Sized_Objects::
* No_Entry_Queue::
* No_Implementation_Aspect_Specifications::
@@ -877,6 +879,11 @@ Code Generation for Array Aggregates
* Aggregates with nonstatic bounds::
* Aggregates in assignment statements::
+Security Hardening Features
+
+* Register Scrubbing::
+* Stack Scrubbing::
+
Obsolescent Features
* pragma No_Run_Time::
@@ -1033,13 +1040,17 @@ other features.
GNAT implementation of the Ada 2012 language standard.
@item
-@ref{15,,Obsolescent Features} documents implementation dependent features,
+@ref{15,,Security Hardening Features} documents GNAT extensions aimed
+at security hardening.
+
+@item
+@ref{16,,Obsolescent Features} documents implementation dependent features,
including pragmas and attributes, which are considered obsolescent, since
there are other preferred ways of achieving the same results. These
obsolescent forms are retained for backwards compatibility.
@item
-@ref{16,,Compatibility and Porting Guide} presents some guidelines for
+@ref{17,,Compatibility and Porting Guide} presents some guidelines for
developing portable Ada code, describes the compatibility issues that
may arise between GNAT and other Ada compilation systems (including those
for Ada 83), and shows how GNAT can expedite porting applications
@@ -1062,7 +1073,7 @@ All three reference manuals are included in the GNAT documentation
package.
@node Conventions,Related Information,What This Reference Manual Contains,About This Guide
-@anchor{gnat_rm/about_this_guide conventions}@anchor{17}
+@anchor{gnat_rm/about_this_guide conventions}@anchor{18}
@section Conventions
@@ -1109,7 +1120,7 @@ comprising the @code{$} character followed by a space.
@end itemize
@node Related Information,,Conventions,About This Guide
-@anchor{gnat_rm/about_this_guide related-information}@anchor{18}
+@anchor{gnat_rm/about_this_guide related-information}@anchor{19}
@section Related Information
@@ -1155,7 +1166,7 @@ compiler system.
@end itemize
@node Implementation Defined Pragmas,Implementation Defined Aspects,About This Guide,Top
-@anchor{gnat_rm/implementation_defined_pragmas doc}@anchor{19}@anchor{gnat_rm/implementation_defined_pragmas id1}@anchor{1a}@anchor{gnat_rm/implementation_defined_pragmas implementation-defined-pragmas}@anchor{7}
+@anchor{gnat_rm/implementation_defined_pragmas doc}@anchor{1a}@anchor{gnat_rm/implementation_defined_pragmas id1}@anchor{1b}@anchor{gnat_rm/implementation_defined_pragmas implementation-defined-pragmas}@anchor{7}
@chapter Implementation Defined Pragmas
@@ -1304,7 +1315,6 @@ consideration, the use of these pragmas should be minimized.
* Pragma Post::
* Pragma Postcondition::
* Pragma Post_Class::
-* Pragma Rename_Pragma::
* Pragma Pre::
* Pragma Precondition::
* Pragma Predicate::
@@ -1327,6 +1337,7 @@ consideration, the use of these pragmas should be minimized.
* Pragma Refined_State::
* Pragma Relative_Deadline::
* Pragma Remote_Access_Type::
+* Pragma Rename_Pragma::
* Pragma Restricted_Run_Time::
* Pragma Restriction_Warnings::
* Pragma Reviewable::
@@ -1380,7 +1391,7 @@ consideration, the use of these pragmas should be minimized.
@end menu
@node Pragma Abort_Defer,Pragma Abstract_State,,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-abort-defer}@anchor{1b}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-abort-defer}@anchor{1c}
@section Pragma Abort_Defer
@@ -1413,7 +1424,7 @@ end;
@end example
@node Pragma Abstract_State,Pragma Ada_83,Pragma Abort_Defer,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id2}@anchor{1c}@anchor{gnat_rm/implementation_defined_pragmas pragma-abstract-state}@anchor{1d}
+@anchor{gnat_rm/implementation_defined_pragmas id2}@anchor{1d}@anchor{gnat_rm/implementation_defined_pragmas pragma-abstract-state}@anchor{1e}
@section Pragma Abstract_State
@@ -1463,7 +1474,7 @@ For the semantics of this pragma, see the entry for aspect @code{Abstract_State}
the SPARK 2014 Reference Manual, section 7.1.4.
@node Pragma Ada_83,Pragma Ada_95,Pragma Abstract_State,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-83}@anchor{1e}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-83}@anchor{1f}
@section Pragma Ada_83
@@ -1492,7 +1503,7 @@ by GNAT in Ada 83 mode will in fact compile and execute with an Ada
required by Ada 83.
@node Pragma Ada_95,Pragma Ada_05,Pragma Ada_83,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-95}@anchor{1f}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-95}@anchor{20}
@section Pragma Ada_95
@@ -1511,7 +1522,7 @@ itself uses Ada 95 features, but which is intended to be usable from
either Ada 83 or Ada 95 programs.
@node Pragma Ada_05,Pragma Ada_2005,Pragma Ada_95,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-05}@anchor{20}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-05}@anchor{21}
@section Pragma Ada_05
@@ -1540,7 +1551,7 @@ otherwise legal pre-Ada_2005 programs. The one argument form is
intended for exclusive use in the GNAT run-time library.
@node Pragma Ada_2005,Pragma Ada_12,Pragma Ada_05,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-2005}@anchor{21}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-2005}@anchor{22}
@section Pragma Ada_2005
@@ -1554,7 +1565,7 @@ This configuration pragma is a synonym for pragma Ada_05 and has the
same syntax and effect.
@node Pragma Ada_12,Pragma Ada_2012,Pragma Ada_2005,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-12}@anchor{22}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-12}@anchor{23}
@section Pragma Ada_12
@@ -1585,7 +1596,7 @@ otherwise legal pre-Ada_2012 programs. The one argument form is
intended for exclusive use in the GNAT run-time library.
@node Pragma Ada_2012,Pragma Aggregate_Individually_Assign,Pragma Ada_12,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-2012}@anchor{23}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-2012}@anchor{24}
@section Pragma Ada_2012
@@ -1599,7 +1610,7 @@ This configuration pragma is a synonym for pragma Ada_12 and has the
same syntax and effect.
@node Pragma Aggregate_Individually_Assign,Pragma Allow_Integer_Address,Pragma Ada_2012,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-aggregate-individually-assign}@anchor{24}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-aggregate-individually-assign}@anchor{25}
@section Pragma Aggregate_Individually_Assign
@@ -1615,7 +1626,7 @@ this behavior so that record aggregates are instead always converted into
individual assignment statements.
@node Pragma Allow_Integer_Address,Pragma Annotate,Pragma Aggregate_Individually_Assign,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-allow-integer-address}@anchor{25}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-allow-integer-address}@anchor{26}
@section Pragma Allow_Integer_Address
@@ -1665,7 +1676,7 @@ rather than rejected to allow common sets of sources to be used
in the two situations.
@node Pragma Annotate,Pragma Assert,Pragma Allow_Integer_Address,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id3}@anchor{26}@anchor{gnat_rm/implementation_defined_pragmas pragma-annotate}@anchor{27}
+@anchor{gnat_rm/implementation_defined_pragmas id3}@anchor{27}@anchor{gnat_rm/implementation_defined_pragmas pragma-annotate}@anchor{28}
@section Pragma Annotate
@@ -1700,7 +1711,7 @@ affect the compilation process in any way. This pragma may be used as
a configuration pragma.
@node Pragma Assert,Pragma Assert_And_Cut,Pragma Annotate,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-assert}@anchor{28}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-assert}@anchor{29}
@section Pragma Assert
@@ -1766,7 +1777,7 @@ of Ada, and the DISABLE policy is an implementation-defined
addition.
@node Pragma Assert_And_Cut,Pragma Assertion_Policy,Pragma Assert,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-assert-and-cut}@anchor{29}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-assert-and-cut}@anchor{2a}
@section Pragma Assert_And_Cut
@@ -1793,7 +1804,7 @@ formal verification. The pragma also serves as useful
documentation.
@node Pragma Assertion_Policy,Pragma Assume,Pragma Assert_And_Cut,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-assertion-policy}@anchor{2a}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-assertion-policy}@anchor{2b}
@section Pragma Assertion_Policy
@@ -1880,7 +1891,7 @@ applies to @code{Assert}, @code{Assert_And_Cut},
@code{Assume}, @code{Loop_Invariant}, and @code{Loop_Variant}.
@node Pragma Assume,Pragma Assume_No_Invalid_Values,Pragma Assertion_Policy,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-assume}@anchor{2b}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-assume}@anchor{2c}
@section Pragma Assume
@@ -1914,7 +1925,7 @@ is met, and documents the need to ensure that it is met by
reference to information outside the program.
@node Pragma Assume_No_Invalid_Values,Pragma Async_Readers,Pragma Assume,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-assume-no-invalid-values}@anchor{2c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-assume-no-invalid-values}@anchor{2d}
@section Pragma Assume_No_Invalid_Values
@@ -1967,7 +1978,7 @@ is erroneous so there are no guarantees that this will always be the
case, and it is recommended that these two options not be used together.
@node Pragma Async_Readers,Pragma Async_Writers,Pragma Assume_No_Invalid_Values,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id4}@anchor{2d}@anchor{gnat_rm/implementation_defined_pragmas pragma-async-readers}@anchor{2e}
+@anchor{gnat_rm/implementation_defined_pragmas id4}@anchor{2e}@anchor{gnat_rm/implementation_defined_pragmas pragma-async-readers}@anchor{2f}
@section Pragma Async_Readers
@@ -1981,7 +1992,7 @@ For the semantics of this pragma, see the entry for aspect @code{Async_Readers}
the SPARK 2014 Reference Manual, section 7.1.2.
@node Pragma Async_Writers,Pragma Attribute_Definition,Pragma Async_Readers,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id5}@anchor{2f}@anchor{gnat_rm/implementation_defined_pragmas pragma-async-writers}@anchor{30}
+@anchor{gnat_rm/implementation_defined_pragmas id5}@anchor{30}@anchor{gnat_rm/implementation_defined_pragmas pragma-async-writers}@anchor{31}
@section Pragma Async_Writers
@@ -1995,7 +2006,7 @@ For the semantics of this pragma, see the entry for aspect @code{Async_Writers}
the SPARK 2014 Reference Manual, section 7.1.2.
@node Pragma Attribute_Definition,Pragma C_Pass_By_Copy,Pragma Async_Writers,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-attribute-definition}@anchor{31}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-attribute-definition}@anchor{32}
@section Pragma Attribute_Definition
@@ -2021,7 +2032,7 @@ code to be written that takes advantage of some new attribute, while remaining
compilable with earlier compilers.
@node Pragma C_Pass_By_Copy,Pragma Check,Pragma Attribute_Definition,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-c-pass-by-copy}@anchor{32}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-c-pass-by-copy}@anchor{33}
@section Pragma C_Pass_By_Copy
@@ -2065,7 +2076,7 @@ You can also pass records by copy by specifying the convention
passing mechanisms on a parameter by parameter basis.
@node Pragma Check,Pragma Check_Float_Overflow,Pragma C_Pass_By_Copy,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-check}@anchor{33}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-check}@anchor{34}
@section Pragma Check
@@ -2104,7 +2115,7 @@ of these identifiers in @code{Assertion_Policy} and @code{Check_Policy}
pragmas, where they are used to refer to sets of assertions.
@node Pragma Check_Float_Overflow,Pragma Check_Name,Pragma Check,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-check-float-overflow}@anchor{34}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-check-float-overflow}@anchor{35}
@section Pragma Check_Float_Overflow
@@ -2160,7 +2171,7 @@ This mode can also be set by use of the compiler
switch @emph{-gnateF}.
@node Pragma Check_Name,Pragma Check_Policy,Pragma Check_Float_Overflow,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-check-name}@anchor{35}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-check-name}@anchor{36}
@section Pragma Check_Name
@@ -2196,7 +2207,7 @@ Check names introduced by this pragma are subject to control by compiler
switches (in particular -gnatp) in the usual manner.
@node Pragma Check_Policy,Pragma Comment,Pragma Check_Name,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-check-policy}@anchor{36}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-check-policy}@anchor{37}
@section Pragma Check_Policy
@@ -2276,7 +2287,7 @@ policy setting @code{DISABLE} causes the second argument of a corresponding
@code{Check} pragma to be completely ignored and not analyzed.
@node Pragma Comment,Pragma Common_Object,Pragma Check_Policy,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-comment}@anchor{37}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-comment}@anchor{38}
@section Pragma Comment
@@ -2295,7 +2306,7 @@ anywhere in the main source unit), and if more than one pragma
is used, all comments are retained.
@node Pragma Common_Object,Pragma Compile_Time_Error,Pragma Comment,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-common-object}@anchor{38}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-common-object}@anchor{39}
@section Pragma Common_Object
@@ -2327,7 +2338,7 @@ indicating that the necessary attribute for implementation of this
pragma is not available.
@node Pragma Compile_Time_Error,Pragma Compile_Time_Warning,Pragma Common_Object,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas compile-time-error}@anchor{39}@anchor{gnat_rm/implementation_defined_pragmas pragma-compile-time-error}@anchor{3a}
+@anchor{gnat_rm/implementation_defined_pragmas compile-time-error}@anchor{3a}@anchor{gnat_rm/implementation_defined_pragmas pragma-compile-time-error}@anchor{3b}
@section Pragma Compile_Time_Error
@@ -2354,7 +2365,7 @@ the value given as the second argument. This string value may contain
embedded ASCII.LF characters to break the message into multiple lines.
@node Pragma Compile_Time_Warning,Pragma Compiler_Unit,Pragma Compile_Time_Error,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-compile-time-warning}@anchor{3b}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-compile-time-warning}@anchor{3c}
@section Pragma Compile_Time_Warning
@@ -2381,11 +2392,11 @@ for example that it is not fully implemented.
In previous versions of the compiler, combining @emph{-gnatwe} with
Compile_Time_Warning resulted in a fatal error. Now the compiler always emits
-a warning. You can use @ref{39,,Pragma Compile_Time_Error} to force the generation of
+a warning. You can use @ref{3a,,Pragma Compile_Time_Error} to force the generation of
an error.
@node Pragma Compiler_Unit,Pragma Compiler_Unit_Warning,Pragma Compile_Time_Warning,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-compiler-unit}@anchor{3c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-compiler-unit}@anchor{3d}
@section Pragma Compiler_Unit
@@ -2400,7 +2411,7 @@ retained so that old versions of the GNAT run-time that use this pragma can
be compiled with newer versions of the compiler.
@node Pragma Compiler_Unit_Warning,Pragma Complete_Representation,Pragma Compiler_Unit,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-compiler-unit-warning}@anchor{3d}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-compiler-unit-warning}@anchor{3e}
@section Pragma Compiler_Unit_Warning
@@ -2418,7 +2429,7 @@ version of GNAT. For the exact list of restrictions, see the compiler sources
and references to Check_Compiler_Unit.
@node Pragma Complete_Representation,Pragma Complex_Representation,Pragma Compiler_Unit_Warning,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-complete-representation}@anchor{3e}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-complete-representation}@anchor{3f}
@section Pragma Complete_Representation
@@ -2437,7 +2448,7 @@ complete, and that this invariant is maintained if fields are
added to the record in the future.
@node Pragma Complex_Representation,Pragma Component_Alignment,Pragma Complete_Representation,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-complex-representation}@anchor{3f}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-complex-representation}@anchor{40}
@section Pragma Complex_Representation
@@ -2459,7 +2470,7 @@ records by pointer, and the use of this pragma may result in passing
this type in floating-point registers.
@node Pragma Component_Alignment,Pragma Constant_After_Elaboration,Pragma Complex_Representation,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-component-alignment}@anchor{40}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-component-alignment}@anchor{41}
@section Pragma Component_Alignment
@@ -2550,7 +2561,7 @@ pragma @code{Pack}, pragma @code{Component_Alignment}, or a record rep
clause), the GNAT uses the default alignment as described previously.
@node Pragma Constant_After_Elaboration,Pragma Contract_Cases,Pragma Component_Alignment,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id6}@anchor{41}@anchor{gnat_rm/implementation_defined_pragmas pragma-constant-after-elaboration}@anchor{42}
+@anchor{gnat_rm/implementation_defined_pragmas id6}@anchor{42}@anchor{gnat_rm/implementation_defined_pragmas pragma-constant-after-elaboration}@anchor{43}
@section Pragma Constant_After_Elaboration
@@ -2564,7 +2575,7 @@ For the semantics of this pragma, see the entry for aspect
@code{Constant_After_Elaboration} in the SPARK 2014 Reference Manual, section 3.3.1.
@node Pragma Contract_Cases,Pragma Convention_Identifier,Pragma Constant_After_Elaboration,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id7}@anchor{43}@anchor{gnat_rm/implementation_defined_pragmas pragma-contract-cases}@anchor{44}
+@anchor{gnat_rm/implementation_defined_pragmas id7}@anchor{44}@anchor{gnat_rm/implementation_defined_pragmas pragma-contract-cases}@anchor{45}
@section Pragma Contract_Cases
@@ -2649,7 +2660,7 @@ and that the consequence for this case should hold when the subprogram
returns.
@node Pragma Convention_Identifier,Pragma CPP_Class,Pragma Contract_Cases,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-convention-identifier}@anchor{45}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-convention-identifier}@anchor{46}
@section Pragma Convention_Identifier
@@ -2685,7 +2696,7 @@ define a convention identifier @code{Library} and use a single
would be used system-wide.
@node Pragma CPP_Class,Pragma CPP_Constructor,Pragma Convention_Identifier,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-class}@anchor{46}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-class}@anchor{47}
@section Pragma CPP_Class
@@ -2710,14 +2721,14 @@ functions (see pragma @code{CPP_Constructor}). Such types are implicitly
limited if not explicitly declared as limited or derived from a limited
type, and an error is issued in that case.
-See @ref{47,,Interfacing to C++} for related information.
+See @ref{48,,Interfacing to C++} for related information.
Note: Pragma @code{CPP_Class} is currently obsolete. It is supported
for backward compatibility but its functionality is available
using pragma @code{Import} with @code{Convention} = @code{CPP}.
@node Pragma CPP_Constructor,Pragma CPP_Virtual,Pragma CPP_Class,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-constructor}@anchor{48}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-constructor}@anchor{49}
@section Pragma CPP_Constructor
@@ -2768,7 +2779,7 @@ on the Ada side and the type is implicitly declared abstract.
Pragma @code{CPP_Constructor} is intended primarily for automatic generation
using an automatic binding generator tool (such as the @code{-fdump-ada-spec}
GCC switch).
-See @ref{47,,Interfacing to C++} for more related information.
+See @ref{48,,Interfacing to C++} for more related information.
Note: The use of functions returning class-wide types for constructors is
currently obsolete. They are supported for backward compatibility. The
@@ -2777,7 +2788,7 @@ because the imported C++ constructors always return an object of type T;
that is, they never return an object whose type is a descendant of type T.
@node Pragma CPP_Virtual,Pragma CPP_Vtable,Pragma CPP_Constructor,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-virtual}@anchor{49}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-virtual}@anchor{4a}
@section Pragma CPP_Virtual
@@ -2790,10 +2801,10 @@ purposes. It used to be required to ensure compoatibility with C++, but
is no longer required for that purpose because GNAT generates
the same object layout as the G++ compiler by default.
-See @ref{47,,Interfacing to C++} for related information.
+See @ref{48,,Interfacing to C++} for related information.
@node Pragma CPP_Vtable,Pragma CPU,Pragma CPP_Virtual,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-vtable}@anchor{4a}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-vtable}@anchor{4b}
@section Pragma CPP_Vtable
@@ -2805,10 +2816,10 @@ It used to be required to ensure compatibility with C++, but
is no longer required for that purpose because GNAT generates
the same object layout as the G++ compiler by default.
-See @ref{47,,Interfacing to C++} for related information.
+See @ref{48,,Interfacing to C++} for related information.
@node Pragma CPU,Pragma Deadline_Floor,Pragma CPP_Vtable,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-cpu}@anchor{4b}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-cpu}@anchor{4c}
@section Pragma CPU
@@ -2823,7 +2834,7 @@ versions of Ada as an implementation-defined pragma.
See Ada 2012 Reference Manual for details.
@node Pragma Deadline_Floor,Pragma Default_Initial_Condition,Pragma CPU,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-deadline-floor}@anchor{4c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-deadline-floor}@anchor{4d}
@section Pragma Deadline_Floor
@@ -2838,7 +2849,7 @@ deadline inherited by a task when the task enters a protected object.
It is effective only when the EDF scheduling policy is used.
@node Pragma Default_Initial_Condition,Pragma Debug,Pragma Deadline_Floor,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id8}@anchor{4d}@anchor{gnat_rm/implementation_defined_pragmas pragma-default-initial-condition}@anchor{4e}
+@anchor{gnat_rm/implementation_defined_pragmas id8}@anchor{4e}@anchor{gnat_rm/implementation_defined_pragmas pragma-default-initial-condition}@anchor{4f}
@section Pragma Default_Initial_Condition
@@ -2852,7 +2863,7 @@ For the semantics of this pragma, see the entry for aspect
@code{Default_Initial_Condition} in the SPARK 2014 Reference Manual, section 7.3.3.
@node Pragma Debug,Pragma Debug_Policy,Pragma Default_Initial_Condition,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-debug}@anchor{4f}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-debug}@anchor{50}
@section Pragma Debug
@@ -2880,7 +2891,7 @@ or by use of the pragma @code{Check_Policy} with a first argument of
@code{Debug}.
@node Pragma Debug_Policy,Pragma Default_Scalar_Storage_Order,Pragma Debug,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-debug-policy}@anchor{50}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-debug-policy}@anchor{51}
@section Pragma Debug_Policy
@@ -2895,7 +2906,7 @@ with a first argument of @code{Debug}. It is retained for historical
compatibility reasons.
@node Pragma Default_Scalar_Storage_Order,Pragma Default_Storage_Pool,Pragma Debug_Policy,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-default-scalar-storage-order}@anchor{51}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-default-scalar-storage-order}@anchor{52}
@section Pragma Default_Scalar_Storage_Order
@@ -2968,7 +2979,7 @@ it may significantly degrade the run-time performance of the software, instead
the default scalar storage order ought to be changed only on a local basis.
@node Pragma Default_Storage_Pool,Pragma Depends,Pragma Default_Scalar_Storage_Order,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-default-storage-pool}@anchor{52}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-default-storage-pool}@anchor{53}
@section Pragma Default_Storage_Pool
@@ -2985,7 +2996,7 @@ versions of Ada as an implementation-defined pragma.
See Ada 2012 Reference Manual for details.
@node Pragma Depends,Pragma Detect_Blocking,Pragma Default_Storage_Pool,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id9}@anchor{53}@anchor{gnat_rm/implementation_defined_pragmas pragma-depends}@anchor{54}
+@anchor{gnat_rm/implementation_defined_pragmas id9}@anchor{54}@anchor{gnat_rm/implementation_defined_pragmas pragma-depends}@anchor{55}
@section Pragma Depends
@@ -3018,7 +3029,7 @@ For the semantics of this pragma, see the entry for aspect @code{Depends} in the
SPARK 2014 Reference Manual, section 6.1.5.
@node Pragma Detect_Blocking,Pragma Disable_Atomic_Synchronization,Pragma Depends,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-detect-blocking}@anchor{55}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-detect-blocking}@anchor{56}
@section Pragma Detect_Blocking
@@ -3036,7 +3047,7 @@ blocking operations within a protected operation, and to raise Program_Error
if that happens.
@node Pragma Disable_Atomic_Synchronization,Pragma Dispatching_Domain,Pragma Detect_Blocking,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-disable-atomic-synchronization}@anchor{56}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-disable-atomic-synchronization}@anchor{57}
@section Pragma Disable_Atomic_Synchronization
@@ -3062,7 +3073,7 @@ till the end of the scope. If an @code{Entity} argument is present,
the action applies only to that entity.
@node Pragma Dispatching_Domain,Pragma Effective_Reads,Pragma Disable_Atomic_Synchronization,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-dispatching-domain}@anchor{57}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-dispatching-domain}@anchor{58}
@section Pragma Dispatching_Domain
@@ -3077,7 +3088,7 @@ versions of Ada as an implementation-defined pragma.
See Ada 2012 Reference Manual for details.
@node Pragma Effective_Reads,Pragma Effective_Writes,Pragma Dispatching_Domain,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id10}@anchor{58}@anchor{gnat_rm/implementation_defined_pragmas pragma-effective-reads}@anchor{59}
+@anchor{gnat_rm/implementation_defined_pragmas id10}@anchor{59}@anchor{gnat_rm/implementation_defined_pragmas pragma-effective-reads}@anchor{5a}
@section Pragma Effective_Reads
@@ -3091,7 +3102,7 @@ For the semantics of this pragma, see the entry for aspect @code{Effective_Reads
the SPARK 2014 Reference Manual, section 7.1.2.
@node Pragma Effective_Writes,Pragma Elaboration_Checks,Pragma Effective_Reads,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id11}@anchor{5a}@anchor{gnat_rm/implementation_defined_pragmas pragma-effective-writes}@anchor{5b}
+@anchor{gnat_rm/implementation_defined_pragmas id11}@anchor{5b}@anchor{gnat_rm/implementation_defined_pragmas pragma-effective-writes}@anchor{5c}
@section Pragma Effective_Writes
@@ -3105,7 +3116,7 @@ For the semantics of this pragma, see the entry for aspect @code{Effective_Write
in the SPARK 2014 Reference Manual, section 7.1.2.
@node Pragma Elaboration_Checks,Pragma Eliminate,Pragma Effective_Writes,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-elaboration-checks}@anchor{5c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-elaboration-checks}@anchor{5d}
@section Pragma Elaboration_Checks
@@ -3142,7 +3153,7 @@ effect. If the pragma argument is @code{Static}, then the static elaboration mod
is in effect.
@node Pragma Eliminate,Pragma Enable_Atomic_Synchronization,Pragma Elaboration_Checks,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-eliminate}@anchor{5d}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-eliminate}@anchor{5e}
@section Pragma Eliminate
@@ -3302,7 +3313,7 @@ pragma Eliminate (Q, Proc,
@end quotation
@node Pragma Enable_Atomic_Synchronization,Pragma Export_Function,Pragma Eliminate,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-enable-atomic-synchronization}@anchor{5e}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-enable-atomic-synchronization}@anchor{5f}
@section Pragma Enable_Atomic_Synchronization
@@ -3330,7 +3341,7 @@ till the end of the scope. If an @code{Entity} argument is present,
the action applies only to that entity.
@node Pragma Export_Function,Pragma Export_Object,Pragma Enable_Atomic_Synchronization,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-export-function}@anchor{5f}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-export-function}@anchor{60}
@section Pragma Export_Function
@@ -3402,7 +3413,7 @@ string. In this case, no external name is generated. This form
still allows the specification of parameter mechanisms.
@node Pragma Export_Object,Pragma Export_Procedure,Pragma Export_Function,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-export-object}@anchor{60}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-export-object}@anchor{61}
@section Pragma Export_Object
@@ -3427,7 +3438,7 @@ of portability), but it is not required. @code{Size} is syntax checked,
but otherwise ignored by GNAT.
@node Pragma Export_Procedure,Pragma Export_Valued_Procedure,Pragma Export_Object,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-export-procedure}@anchor{61}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-export-procedure}@anchor{62}
@section Pragma Export_Procedure
@@ -3480,7 +3491,7 @@ string. In this case, no external name is generated. This form
still allows the specification of parameter mechanisms.
@node Pragma Export_Valued_Procedure,Pragma Extend_System,Pragma Export_Procedure,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-export-valued-procedure}@anchor{62}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-export-valued-procedure}@anchor{63}
@section Pragma Export_Valued_Procedure
@@ -3538,7 +3549,7 @@ string. In this case, no external name is generated. This form
still allows the specification of parameter mechanisms.
@node Pragma Extend_System,Pragma Extensions_Allowed,Pragma Export_Valued_Procedure,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-extend-system}@anchor{63}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-extend-system}@anchor{64}
@section Pragma Extend_System
@@ -3589,7 +3600,7 @@ for compiling System units, as explained in the
GNAT User’s Guide.
@node Pragma Extensions_Allowed,Pragma Extensions_Visible,Pragma Extend_System,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-extensions-allowed}@anchor{64}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-extensions-allowed}@anchor{65}
@section Pragma Extensions_Allowed
@@ -3698,8 +3709,15 @@ will not be executed if the earlier alternative “matches”). All possible
values of the composite type shall be covered. The composite type of the
selector shall be a nonlimited untagged (but possibly discriminated)
record type, all of whose subcomponent subtypes are either static discrete
-subtypes or record types that meet the same restrictions. Support for arrays
-is planned, but not yet implemented.
+subtypes or record types that meet the same restrictions.
+
+Support for casing on arrays (and on records that contain arrays) is
+currently subject to some restrictions. Non-positional
+array aggregates are not supported as (or within) case choices. Likewise
+for array type and subtype names. The current implementation exceeds
+compile-time capacity limits in some annoyingly common scenarios; the
+message generated in such cases is usually “Capacity exceeded in compiling
+case statement with composite selector type”.
In addition, pattern bindings are supported. This is a mechanism
for binding a name to a component of a matching value for use within
@@ -3708,7 +3726,8 @@ that occurs within a case choice, the expression may be followed by
“is <identifier>”. In the special case of a “box” component association,
the identifier may instead be provided within the box. Either of these
indicates that the given identifer denotes (a constant view of) the matching
-subcomponent of the case selector.
+subcomponent of the case selector. Binding is not yet supported for arrays
+or subcomponents thereof.
Consider this example (which uses type Rec from the previous example):
@@ -3813,7 +3832,7 @@ name, preference is given to the component in a selected_component
@end itemize
@node Pragma Extensions_Visible,Pragma External,Pragma Extensions_Allowed,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id12}@anchor{65}@anchor{gnat_rm/implementation_defined_pragmas pragma-extensions-visible}@anchor{66}
+@anchor{gnat_rm/implementation_defined_pragmas id12}@anchor{66}@anchor{gnat_rm/implementation_defined_pragmas pragma-extensions-visible}@anchor{67}
@section Pragma Extensions_Visible
@@ -3827,7 +3846,7 @@ For the semantics of this pragma, see the entry for aspect @code{Extensions_Visi
in the SPARK 2014 Reference Manual, section 6.1.7.
@node Pragma External,Pragma External_Name_Casing,Pragma Extensions_Visible,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-external}@anchor{67}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-external}@anchor{68}
@section Pragma External
@@ -3848,7 +3867,7 @@ used this pragma for exactly the same purposes as pragma
@code{Export} before the latter was standardized.
@node Pragma External_Name_Casing,Pragma Fast_Math,Pragma External,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-external-name-casing}@anchor{68}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-external-name-casing}@anchor{69}
@section Pragma External_Name_Casing
@@ -3937,7 +3956,7 @@ pragma External_Name_Casing (Uppercase, Uppercase);
to enforce the upper casing of all external symbols.
@node Pragma Fast_Math,Pragma Favor_Top_Level,Pragma External_Name_Casing,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-fast-math}@anchor{69}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-fast-math}@anchor{6a}
@section Pragma Fast_Math
@@ -3966,7 +3985,7 @@ under control of the pragma, rather than use the preinstantiated versions.
@end table
@node Pragma Favor_Top_Level,Pragma Finalize_Storage_Only,Pragma Fast_Math,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id13}@anchor{6a}@anchor{gnat_rm/implementation_defined_pragmas pragma-favor-top-level}@anchor{6b}
+@anchor{gnat_rm/implementation_defined_pragmas id13}@anchor{6b}@anchor{gnat_rm/implementation_defined_pragmas pragma-favor-top-level}@anchor{6c}
@section Pragma Favor_Top_Level
@@ -3985,7 +4004,7 @@ When this pragma is used, dynamically generated trampolines may be used on some
targets for nested subprograms. See restriction @code{No_Implicit_Dynamic_Code}.
@node Pragma Finalize_Storage_Only,Pragma Float_Representation,Pragma Favor_Top_Level,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-finalize-storage-only}@anchor{6c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-finalize-storage-only}@anchor{6d}
@section Pragma Finalize_Storage_Only
@@ -4005,7 +4024,7 @@ name. Note that this pragma does not suppress Finalize calls for library-level
heap-allocated objects (see pragma @code{No_Heap_Finalization}).
@node Pragma Float_Representation,Pragma Ghost,Pragma Finalize_Storage_Only,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-float-representation}@anchor{6d}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-float-representation}@anchor{6e}
@section Pragma Float_Representation
@@ -4040,7 +4059,7 @@ No other value of digits is permitted.
@end itemize
@node Pragma Ghost,Pragma Global,Pragma Float_Representation,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id14}@anchor{6e}@anchor{gnat_rm/implementation_defined_pragmas pragma-ghost}@anchor{6f}
+@anchor{gnat_rm/implementation_defined_pragmas id14}@anchor{6f}@anchor{gnat_rm/implementation_defined_pragmas pragma-ghost}@anchor{70}
@section Pragma Ghost
@@ -4054,7 +4073,7 @@ For the semantics of this pragma, see the entry for aspect @code{Ghost} in the S
2014 Reference Manual, section 6.9.
@node Pragma Global,Pragma Ident,Pragma Ghost,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id15}@anchor{70}@anchor{gnat_rm/implementation_defined_pragmas pragma-global}@anchor{71}
+@anchor{gnat_rm/implementation_defined_pragmas id15}@anchor{71}@anchor{gnat_rm/implementation_defined_pragmas pragma-global}@anchor{72}
@section Pragma Global
@@ -4079,7 +4098,7 @@ For the semantics of this pragma, see the entry for aspect @code{Global} in the
SPARK 2014 Reference Manual, section 6.1.4.
@node Pragma Ident,Pragma Ignore_Pragma,Pragma Global,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ident}@anchor{72}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ident}@anchor{73}
@section Pragma Ident
@@ -4093,7 +4112,7 @@ This pragma is identical in effect to pragma @code{Comment}. It is provided
for compatibility with other Ada compilers providing this pragma.
@node Pragma Ignore_Pragma,Pragma Implementation_Defined,Pragma Ident,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ignore-pragma}@anchor{73}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ignore-pragma}@anchor{74}
@section Pragma Ignore_Pragma
@@ -4113,7 +4132,7 @@ pragma allows such pragmas to be ignored, which may be useful in CodePeer
mode, or during porting of legacy code.
@node Pragma Implementation_Defined,Pragma Implemented,Pragma Ignore_Pragma,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-implementation-defined}@anchor{74}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-implementation-defined}@anchor{75}
@section Pragma Implementation_Defined
@@ -4140,7 +4159,7 @@ for the purpose of implementing the No_Implementation_Identifiers
restriction.
@node Pragma Implemented,Pragma Implicit_Packing,Pragma Implementation_Defined,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-implemented}@anchor{75}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-implemented}@anchor{76}
@section Pragma Implemented
@@ -4186,7 +4205,7 @@ By_Any shares the behavior of By_Entry and By_Protected_Procedure depending on
the target’s overriding subprogram kind.
@node Pragma Implicit_Packing,Pragma Import_Function,Pragma Implemented,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-implicit-packing}@anchor{76}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-implicit-packing}@anchor{77}
@section Pragma Implicit_Packing
@@ -4240,7 +4259,7 @@ sufficient. The use of pragma Implicit_Packing allows this record
declaration to compile without an explicit pragma Pack.
@node Pragma Import_Function,Pragma Import_Object,Pragma Implicit_Packing,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-import-function}@anchor{77}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-import-function}@anchor{78}
@section Pragma Import_Function
@@ -4305,7 +4324,7 @@ notation. If the mechanism is not specified, the default mechanism
is used.
@node Pragma Import_Object,Pragma Import_Procedure,Pragma Import_Function,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-import-object}@anchor{78}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-import-object}@anchor{79}
@section Pragma Import_Object
@@ -4331,7 +4350,7 @@ point of view). @code{size} is syntax checked, but otherwise ignored by
GNAT.
@node Pragma Import_Procedure,Pragma Import_Valued_Procedure,Pragma Import_Object,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-import-procedure}@anchor{79}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-import-procedure}@anchor{7a}
@section Pragma Import_Procedure
@@ -4371,7 +4390,7 @@ applies to a procedure rather than a function and the parameters
@code{Result_Type} and @code{Result_Mechanism} are not permitted.
@node Pragma Import_Valued_Procedure,Pragma Independent,Pragma Import_Procedure,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-import-valued-procedure}@anchor{7a}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-import-valued-procedure}@anchor{7b}
@section Pragma Import_Valued_Procedure
@@ -4424,7 +4443,7 @@ pragma Import that specifies the desired convention, since otherwise the
default convention is Ada, which is almost certainly not what is required.
@node Pragma Independent,Pragma Independent_Components,Pragma Import_Valued_Procedure,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-independent}@anchor{7b}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-independent}@anchor{7c}
@section Pragma Independent
@@ -4446,7 +4465,7 @@ constraints on the representation of the object (for instance prohibiting
tight packing).
@node Pragma Independent_Components,Pragma Initial_Condition,Pragma Independent,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-independent-components}@anchor{7c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-independent-components}@anchor{7d}
@section Pragma Independent_Components
@@ -4467,7 +4486,7 @@ constraints on the representation of the object (for instance prohibiting
tight packing).
@node Pragma Initial_Condition,Pragma Initialize_Scalars,Pragma Independent_Components,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id16}@anchor{7d}@anchor{gnat_rm/implementation_defined_pragmas pragma-initial-condition}@anchor{7e}
+@anchor{gnat_rm/implementation_defined_pragmas id16}@anchor{7e}@anchor{gnat_rm/implementation_defined_pragmas pragma-initial-condition}@anchor{7f}
@section Pragma Initial_Condition
@@ -4481,7 +4500,7 @@ For the semantics of this pragma, see the entry for aspect @code{Initial_Conditi
in the SPARK 2014 Reference Manual, section 7.1.6.
@node Pragma Initialize_Scalars,Pragma Initializes,Pragma Initial_Condition,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-initialize-scalars}@anchor{7f}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-initialize-scalars}@anchor{80}
@section Pragma Initialize_Scalars
@@ -4590,7 +4609,7 @@ good idea to turn on stack checking (see description of stack checking in the
GNAT User’s Guide) when using this pragma.
@node Pragma Initializes,Pragma Inline_Always,Pragma Initialize_Scalars,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id17}@anchor{80}@anchor{gnat_rm/implementation_defined_pragmas pragma-initializes}@anchor{81}
+@anchor{gnat_rm/implementation_defined_pragmas id17}@anchor{81}@anchor{gnat_rm/implementation_defined_pragmas pragma-initializes}@anchor{82}
@section Pragma Initializes
@@ -4617,7 +4636,7 @@ For the semantics of this pragma, see the entry for aspect @code{Initializes} in
SPARK 2014 Reference Manual, section 7.1.5.
@node Pragma Inline_Always,Pragma Inline_Generic,Pragma Initializes,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id18}@anchor{82}@anchor{gnat_rm/implementation_defined_pragmas pragma-inline-always}@anchor{83}
+@anchor{gnat_rm/implementation_defined_pragmas id18}@anchor{83}@anchor{gnat_rm/implementation_defined_pragmas pragma-inline-always}@anchor{84}
@section Pragma Inline_Always
@@ -4636,7 +4655,7 @@ apply this pragma to a primitive operation of a tagged type. Thanks to such
restrictions, the compiler is allowed to remove the out-of-line body of @code{NAME}.
@node Pragma Inline_Generic,Pragma Interface,Pragma Inline_Always,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-inline-generic}@anchor{84}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-inline-generic}@anchor{85}
@section Pragma Inline_Generic
@@ -4654,7 +4673,7 @@ than to check that the given names are all names of generic units or
generic instances.
@node Pragma Interface,Pragma Interface_Name,Pragma Inline_Generic,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-interface}@anchor{85}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-interface}@anchor{86}
@section Pragma Interface
@@ -4681,7 +4700,7 @@ maintaining Ada 83/Ada 95 compatibility and is compatible with other
Ada 83 compilers.
@node Pragma Interface_Name,Pragma Interrupt_Handler,Pragma Interface,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-interface-name}@anchor{86}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-interface-name}@anchor{87}
@section Pragma Interface_Name
@@ -4700,7 +4719,7 @@ for an interfaced subprogram, and is provided for compatibility with Ada
least one of @code{External_Name} or @code{Link_Name}.
@node Pragma Interrupt_Handler,Pragma Interrupt_State,Pragma Interface_Name,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-interrupt-handler}@anchor{87}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-interrupt-handler}@anchor{88}
@section Pragma Interrupt_Handler
@@ -4714,7 +4733,7 @@ This program unit pragma is supported for parameterless protected procedures
as described in Annex C of the Ada Reference Manual.
@node Pragma Interrupt_State,Pragma Invariant,Pragma Interrupt_Handler,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-interrupt-state}@anchor{88}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-interrupt-state}@anchor{89}
@section Pragma Interrupt_State
@@ -4800,7 +4819,7 @@ with an application’s runtime behavior in the cases of the synchronous signals
and in the case of the signal used to implement the @code{abort} statement.
@node Pragma Invariant,Pragma Keep_Names,Pragma Interrupt_State,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id19}@anchor{89}@anchor{gnat_rm/implementation_defined_pragmas pragma-invariant}@anchor{8a}
+@anchor{gnat_rm/implementation_defined_pragmas id19}@anchor{8a}@anchor{gnat_rm/implementation_defined_pragmas pragma-invariant}@anchor{8b}
@section Pragma Invariant
@@ -4839,7 +4858,7 @@ For further details on the use of this pragma, see the Ada 2012 documentation
of the Type_Invariant aspect.
@node Pragma Keep_Names,Pragma License,Pragma Invariant,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-keep-names}@anchor{8b}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-keep-names}@anchor{8c}
@section Pragma Keep_Names
@@ -4859,7 +4878,7 @@ use a @code{Discard_Names} pragma in the @code{gnat.adc} file, but you
want to retain the names for specific enumeration types.
@node Pragma License,Pragma Link_With,Pragma Keep_Names,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-license}@anchor{8c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-license}@anchor{8d}
@section Pragma License
@@ -4954,7 +4973,7 @@ GPL, but no warning for @code{GNAT.Sockets} which is part of the GNAT
run time, and is therefore licensed under the modified GPL.
@node Pragma Link_With,Pragma Linker_Alias,Pragma License,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-link-with}@anchor{8d}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-link-with}@anchor{8e}
@section Pragma Link_With
@@ -4978,7 +4997,7 @@ separate arguments to the linker. In addition pragma Link_With allows
multiple arguments, with the same effect as successive pragmas.
@node Pragma Linker_Alias,Pragma Linker_Constructor,Pragma Link_With,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-alias}@anchor{8e}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-alias}@anchor{8f}
@section Pragma Linker_Alias
@@ -5019,7 +5038,7 @@ end p;
@end example
@node Pragma Linker_Constructor,Pragma Linker_Destructor,Pragma Linker_Alias,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-constructor}@anchor{8f}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-constructor}@anchor{90}
@section Pragma Linker_Constructor
@@ -5049,7 +5068,7 @@ listed above. Where possible, the use of Stand Alone Libraries is preferable
to the use of this pragma.
@node Pragma Linker_Destructor,Pragma Linker_Section,Pragma Linker_Constructor,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-destructor}@anchor{90}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-destructor}@anchor{91}
@section Pragma Linker_Destructor
@@ -5072,7 +5091,7 @@ See @code{pragma Linker_Constructor} for the set of restrictions that apply
because of these specific contexts.
@node Pragma Linker_Section,Pragma Lock_Free,Pragma Linker_Destructor,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id20}@anchor{91}@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-section}@anchor{92}
+@anchor{gnat_rm/implementation_defined_pragmas id20}@anchor{92}@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-section}@anchor{93}
@section Pragma Linker_Section
@@ -5146,7 +5165,7 @@ end IO_Card;
@end example
@node Pragma Lock_Free,Pragma Loop_Invariant,Pragma Linker_Section,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id21}@anchor{93}@anchor{gnat_rm/implementation_defined_pragmas pragma-lock-free}@anchor{94}
+@anchor{gnat_rm/implementation_defined_pragmas id21}@anchor{94}@anchor{gnat_rm/implementation_defined_pragmas pragma-lock-free}@anchor{95}
@section Pragma Lock_Free
@@ -5198,7 +5217,7 @@ Function calls and attribute references must be static
@end itemize
@node Pragma Loop_Invariant,Pragma Loop_Optimize,Pragma Lock_Free,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-loop-invariant}@anchor{95}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-loop-invariant}@anchor{96}
@section Pragma Loop_Invariant
@@ -5231,7 +5250,7 @@ attribute can only be used within the expression of a @code{Loop_Invariant}
pragma. For full details, see documentation of attribute @code{Loop_Entry}.
@node Pragma Loop_Optimize,Pragma Loop_Variant,Pragma Loop_Invariant,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-loop-optimize}@anchor{96}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-loop-optimize}@anchor{97}
@section Pragma Loop_Optimize
@@ -5293,7 +5312,7 @@ compiler in order to enable the relevant optimizations, that is to say
vectorization.
@node Pragma Loop_Variant,Pragma Machine_Attribute,Pragma Loop_Optimize,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-loop-variant}@anchor{97}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-loop-variant}@anchor{98}
@section Pragma Loop_Variant
@@ -5340,7 +5359,7 @@ The @code{Loop_Entry} attribute may be used within the expressions of the
@code{Loop_Variant} pragma to refer to values on entry to the loop.
@node Pragma Machine_Attribute,Pragma Main,Pragma Loop_Variant,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-machine-attribute}@anchor{98}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-machine-attribute}@anchor{99}
@section Pragma Machine_Attribute
@@ -5366,7 +5385,7 @@ which may make this pragma unusable for some attributes.
For further information see @cite{GNU Compiler Collection (GCC) Internals}.
@node Pragma Main,Pragma Main_Storage,Pragma Machine_Attribute,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-main}@anchor{99}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-main}@anchor{9a}
@section Pragma Main
@@ -5386,7 +5405,7 @@ This pragma is provided for compatibility with OpenVMS VAX Systems. It has
no effect in GNAT, other than being syntax checked.
@node Pragma Main_Storage,Pragma Max_Queue_Length,Pragma Main,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-main-storage}@anchor{9a}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-main-storage}@anchor{9b}
@section Pragma Main_Storage
@@ -5405,7 +5424,7 @@ This pragma is provided for compatibility with OpenVMS VAX Systems. It has
no effect in GNAT, other than being syntax checked.
@node Pragma Max_Queue_Length,Pragma No_Body,Pragma Main_Storage,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id22}@anchor{9b}@anchor{gnat_rm/implementation_defined_pragmas pragma-max-queue-length}@anchor{9c}
+@anchor{gnat_rm/implementation_defined_pragmas id22}@anchor{9c}@anchor{gnat_rm/implementation_defined_pragmas pragma-max-queue-length}@anchor{9d}
@section Pragma Max_Queue_Length
@@ -5423,7 +5442,7 @@ entry.
A value of -1 represents no additional restriction on queue length.
@node Pragma No_Body,Pragma No_Caching,Pragma Max_Queue_Length,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-no-body}@anchor{9d}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-no-body}@anchor{9e}
@section Pragma No_Body
@@ -5446,7 +5465,7 @@ dummy body with a No_Body pragma ensures that there is no interference from
earlier versions of the package body.
@node Pragma No_Caching,Pragma No_Component_Reordering,Pragma No_Body,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id23}@anchor{9e}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-caching}@anchor{9f}
+@anchor{gnat_rm/implementation_defined_pragmas id23}@anchor{9f}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-caching}@anchor{a0}
@section Pragma No_Caching
@@ -5460,7 +5479,7 @@ For the semantics of this pragma, see the entry for aspect @code{No_Caching} in
the SPARK 2014 Reference Manual, section 7.1.2.
@node Pragma No_Component_Reordering,Pragma No_Elaboration_Code_All,Pragma No_Caching,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-no-component-reordering}@anchor{a0}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-no-component-reordering}@anchor{a1}
@section Pragma No_Component_Reordering
@@ -5479,7 +5498,7 @@ declared in units to which the pragma applies and there is a requirement
that this pragma be used consistently within a partition.
@node Pragma No_Elaboration_Code_All,Pragma No_Heap_Finalization,Pragma No_Component_Reordering,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id24}@anchor{a1}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-elaboration-code-all}@anchor{a2}
+@anchor{gnat_rm/implementation_defined_pragmas id24}@anchor{a2}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-elaboration-code-all}@anchor{a3}
@section Pragma No_Elaboration_Code_All
@@ -5498,7 +5517,7 @@ current unit, it must also have the No_Elaboration_Code_All aspect set.
It may be applied to package or subprogram specs or their generic versions.
@node Pragma No_Heap_Finalization,Pragma No_Inline,Pragma No_Elaboration_Code_All,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-no-heap-finalization}@anchor{a3}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-no-heap-finalization}@anchor{a4}
@section Pragma No_Heap_Finalization
@@ -5530,7 +5549,7 @@ lose its @code{No_Heap_Finalization} pragma when the corresponding instance does
appear at the library level.
@node Pragma No_Inline,Pragma No_Return,Pragma No_Heap_Finalization,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id25}@anchor{a4}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-inline}@anchor{a5}
+@anchor{gnat_rm/implementation_defined_pragmas id25}@anchor{a5}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-inline}@anchor{a6}
@section Pragma No_Inline
@@ -5548,7 +5567,7 @@ in particular it is not subject to the use of option @emph{-gnatn} or
pragma @code{Inline_Always} for the same @code{NAME}.
@node Pragma No_Return,Pragma No_Strict_Aliasing,Pragma No_Inline,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-no-return}@anchor{a6}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-no-return}@anchor{a7}
@section Pragma No_Return
@@ -5575,7 +5594,7 @@ available in all earlier versions of Ada as an implementation-defined
pragma.
@node Pragma No_Strict_Aliasing,Pragma No_Tagged_Streams,Pragma No_Return,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-no-strict-aliasing}@anchor{a7}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-no-strict-aliasing}@anchor{a8}
@section Pragma No_Strict_Aliasing
@@ -5597,7 +5616,7 @@ in the @cite{GNAT User’s Guide}.
This pragma currently has no effects on access to unconstrained array types.
@node Pragma No_Tagged_Streams,Pragma Normalize_Scalars,Pragma No_Strict_Aliasing,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id26}@anchor{a8}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-tagged-streams}@anchor{a9}
+@anchor{gnat_rm/implementation_defined_pragmas id26}@anchor{a9}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-tagged-streams}@anchor{aa}
@section Pragma No_Tagged_Streams
@@ -5636,7 +5655,7 @@ with empty strings. This is useful to avoid exposing entity names at binary
level but has a negative impact on the debuggability of tagged types.
@node Pragma Normalize_Scalars,Pragma Obsolescent,Pragma No_Tagged_Streams,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-normalize-scalars}@anchor{aa}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-normalize-scalars}@anchor{ab}
@section Pragma Normalize_Scalars
@@ -5718,7 +5737,7 @@ will always generate an invalid value if one exists.
@end table
@node Pragma Obsolescent,Pragma Optimize_Alignment,Pragma Normalize_Scalars,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id27}@anchor{ab}@anchor{gnat_rm/implementation_defined_pragmas pragma-obsolescent}@anchor{ac}
+@anchor{gnat_rm/implementation_defined_pragmas id27}@anchor{ac}@anchor{gnat_rm/implementation_defined_pragmas pragma-obsolescent}@anchor{ad}
@section Pragma Obsolescent
@@ -5814,7 +5833,7 @@ So if you specify @code{Entity =>} for the @code{Entity} argument, and a @code{M
argument is present, it must be preceded by @code{Message =>}.
@node Pragma Optimize_Alignment,Pragma Ordered,Pragma Obsolescent,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-optimize-alignment}@anchor{ad}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-optimize-alignment}@anchor{ae}
@section Pragma Optimize_Alignment
@@ -5900,7 +5919,7 @@ latter are compiled by default in pragma Optimize_Alignment (Off) mode if no
pragma appears at the start of the file.
@node Pragma Ordered,Pragma Overflow_Mode,Pragma Optimize_Alignment,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ordered}@anchor{ae}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ordered}@anchor{af}
@section Pragma Ordered
@@ -5992,7 +6011,7 @@ For additional information please refer to the description of the
@emph{-gnatw.u} switch in the GNAT User’s Guide.
@node Pragma Overflow_Mode,Pragma Overriding_Renamings,Pragma Ordered,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-overflow-mode}@anchor{af}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-overflow-mode}@anchor{b0}
@section Pragma Overflow_Mode
@@ -6031,7 +6050,7 @@ The pragma @code{Unsuppress (Overflow_Check)} unsuppresses (enables)
overflow checking, but does not affect the overflow mode.
@node Pragma Overriding_Renamings,Pragma Partition_Elaboration_Policy,Pragma Overflow_Mode,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-overriding-renamings}@anchor{b0}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-overriding-renamings}@anchor{b1}
@section Pragma Overriding_Renamings
@@ -6066,7 +6085,7 @@ RM 8.3 (15) stipulates that an overridden operation is not visible within the
declaration of the overriding operation.
@node Pragma Partition_Elaboration_Policy,Pragma Part_Of,Pragma Overriding_Renamings,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-partition-elaboration-policy}@anchor{b1}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-partition-elaboration-policy}@anchor{b2}
@section Pragma Partition_Elaboration_Policy
@@ -6083,7 +6102,7 @@ versions of Ada as an implementation-defined pragma.
See Ada 2012 Reference Manual for details.
@node Pragma Part_Of,Pragma Passive,Pragma Partition_Elaboration_Policy,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id28}@anchor{b2}@anchor{gnat_rm/implementation_defined_pragmas pragma-part-of}@anchor{b3}
+@anchor{gnat_rm/implementation_defined_pragmas id28}@anchor{b3}@anchor{gnat_rm/implementation_defined_pragmas pragma-part-of}@anchor{b4}
@section Pragma Part_Of
@@ -6099,7 +6118,7 @@ For the semantics of this pragma, see the entry for aspect @code{Part_Of} in the
SPARK 2014 Reference Manual, section 7.2.6.
@node Pragma Passive,Pragma Persistent_BSS,Pragma Part_Of,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-passive}@anchor{b4}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-passive}@anchor{b5}
@section Pragma Passive
@@ -6123,7 +6142,7 @@ For more information on the subject of passive tasks, see the section
‘Passive Task Optimization’ in the GNAT Users Guide.
@node Pragma Persistent_BSS,Pragma Post,Pragma Passive,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id29}@anchor{b5}@anchor{gnat_rm/implementation_defined_pragmas pragma-persistent-bss}@anchor{b6}
+@anchor{gnat_rm/implementation_defined_pragmas id29}@anchor{b6}@anchor{gnat_rm/implementation_defined_pragmas pragma-persistent-bss}@anchor{b7}
@section Pragma Persistent_BSS
@@ -6154,7 +6173,7 @@ If this pragma is used on a target where this feature is not supported,
then the pragma will be ignored. See also @code{pragma Linker_Section}.
@node Pragma Post,Pragma Postcondition,Pragma Persistent_BSS,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-post}@anchor{b7}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-post}@anchor{b8}
@section Pragma Post
@@ -6179,7 +6198,7 @@ appear at the start of the declarations in a subprogram body
(preceded only by other pragmas).
@node Pragma Postcondition,Pragma Post_Class,Pragma Post,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-postcondition}@anchor{b8}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-postcondition}@anchor{b9}
@section Pragma Postcondition
@@ -6343,8 +6362,8 @@ use of the pragma identifier @code{Check}. Historically, pragma
Ada 2012, and has been retained in its original form for
compatibility purposes.
-@node Pragma Post_Class,Pragma Rename_Pragma,Pragma Postcondition,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-post-class}@anchor{b9}
+@node Pragma Post_Class,Pragma Pre,Pragma Postcondition,Implementation Defined Pragmas
+@anchor{gnat_rm/implementation_defined_pragmas pragma-post-class}@anchor{ba}
@section Pragma Post_Class
@@ -6378,46 +6397,7 @@ aspects, but is prepared to ignore the pragmas. The assertion
policy that controls this pragma is @code{Post'Class}, not
@code{Post_Class}.
-@node Pragma Rename_Pragma,Pragma Pre,Pragma Post_Class,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-rename-pragma}@anchor{ba}
-@section Pragma Rename_Pragma
-
-
-@geindex Pragmas
-@geindex synonyms
-
-Syntax:
-
-@example
-pragma Rename_Pragma (
- [New_Name =>] IDENTIFIER,
- [Renamed =>] pragma_IDENTIFIER);
-@end example
-
-This pragma provides a mechanism for supplying new names for existing
-pragmas. The @code{New_Name} identifier can subsequently be used as a synonym for
-the Renamed pragma. For example, suppose you have code that was originally
-developed on a compiler that supports Inline_Only as an implementation defined
-pragma. And suppose the semantics of pragma Inline_Only are identical to (or at
-least very similar to) the GNAT implementation defined pragma
-Inline_Always. You could globally replace Inline_Only with Inline_Always.
-
-However, to avoid that source modification, you could instead add a
-configuration pragma:
-
-@example
-pragma Rename_Pragma (
- New_Name => Inline_Only,
- Renamed => Inline_Always);
-@end example
-
-Then GNAT will treat “pragma Inline_Only …” as if you had written
-“pragma Inline_Always …”.
-
-Pragma Inline_Only will not necessarily mean the same thing as the other Ada
-compiler; it’s up to you to make sure the semantics are close enough.
-
-@node Pragma Pre,Pragma Precondition,Pragma Rename_Pragma,Implementation Defined Pragmas
+@node Pragma Pre,Pragma Precondition,Pragma Post_Class,Implementation Defined Pragmas
@anchor{gnat_rm/implementation_defined_pragmas pragma-pre}@anchor{bb}
@section Pragma Pre
@@ -7246,7 +7226,7 @@ This pragma is standard in Ada 2005, but is available in all earlier
versions of Ada as an implementation-defined pragma.
See Ada 2012 Reference Manual for details.
-@node Pragma Remote_Access_Type,Pragma Restricted_Run_Time,Pragma Relative_Deadline,Implementation Defined Pragmas
+@node Pragma Remote_Access_Type,Pragma Rename_Pragma,Pragma Relative_Deadline,Implementation Defined Pragmas
@anchor{gnat_rm/implementation_defined_pragmas id36}@anchor{d6}@anchor{gnat_rm/implementation_defined_pragmas pragma-remote-access-type}@anchor{d7}
@section Pragma Remote_Access_Type
@@ -7272,8 +7252,47 @@ In the generic unit, the formal type is subject to all restrictions
pertaining to remote access to class-wide types. At instantiation, the
actual type must be a remote access to class-wide type.
-@node Pragma Restricted_Run_Time,Pragma Restriction_Warnings,Pragma Remote_Access_Type,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-restricted-run-time}@anchor{d8}
+@node Pragma Rename_Pragma,Pragma Restricted_Run_Time,Pragma Remote_Access_Type,Implementation Defined Pragmas
+@anchor{gnat_rm/implementation_defined_pragmas pragma-rename-pragma}@anchor{d8}
+@section Pragma Rename_Pragma
+
+
+@geindex Pragmas
+@geindex synonyms
+
+Syntax:
+
+@example
+pragma Rename_Pragma (
+ [New_Name =>] IDENTIFIER,
+ [Renamed =>] pragma_IDENTIFIER);
+@end example
+
+This pragma provides a mechanism for supplying new names for existing
+pragmas. The @code{New_Name} identifier can subsequently be used as a synonym for
+the Renamed pragma. For example, suppose you have code that was originally
+developed on a compiler that supports Inline_Only as an implementation defined
+pragma. And suppose the semantics of pragma Inline_Only are identical to (or at
+least very similar to) the GNAT implementation defined pragma
+Inline_Always. You could globally replace Inline_Only with Inline_Always.
+
+However, to avoid that source modification, you could instead add a
+configuration pragma:
+
+@example
+pragma Rename_Pragma (
+ New_Name => Inline_Only,
+ Renamed => Inline_Always);
+@end example
+
+Then GNAT will treat “pragma Inline_Only …” as if you had written
+“pragma Inline_Always …”.
+
+Pragma Inline_Only will not necessarily mean the same thing as the other Ada
+compiler; it’s up to you to make sure the semantics are close enough.
+
+@node Pragma Restricted_Run_Time,Pragma Restriction_Warnings,Pragma Rename_Pragma,Implementation Defined Pragmas
+@anchor{gnat_rm/implementation_defined_pragmas pragma-restricted-run-time}@anchor{d9}
@section Pragma Restricted_Run_Time
@@ -7294,7 +7313,7 @@ which is the preferred method of setting the restricted run time
profile.
@node Pragma Restriction_Warnings,Pragma Reviewable,Pragma Restricted_Run_Time,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-restriction-warnings}@anchor{d9}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-restriction-warnings}@anchor{da}
@section Pragma Restriction_Warnings
@@ -7332,7 +7351,7 @@ generating a warning, but any other use of implementation
defined pragmas will cause a warning to be generated.
@node Pragma Reviewable,Pragma Secondary_Stack_Size,Pragma Restriction_Warnings,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-reviewable}@anchor{da}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-reviewable}@anchor{db}
@section Pragma Reviewable
@@ -7436,7 +7455,7 @@ comprehensive messages identifying possible problems based on this
information.
@node Pragma Secondary_Stack_Size,Pragma Share_Generic,Pragma Reviewable,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id37}@anchor{db}@anchor{gnat_rm/implementation_defined_pragmas pragma-secondary-stack-size}@anchor{dc}
+@anchor{gnat_rm/implementation_defined_pragmas id37}@anchor{dc}@anchor{gnat_rm/implementation_defined_pragmas pragma-secondary-stack-size}@anchor{dd}
@section Pragma Secondary_Stack_Size
@@ -7472,7 +7491,7 @@ Note the pragma cannot appear when the restriction @code{No_Secondary_Stack}
is in effect.
@node Pragma Share_Generic,Pragma Shared,Pragma Secondary_Stack_Size,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-share-generic}@anchor{dd}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-share-generic}@anchor{de}
@section Pragma Share_Generic
@@ -7490,7 +7509,7 @@ than to check that the given names are all names of generic units or
generic instances.
@node Pragma Shared,Pragma Short_Circuit_And_Or,Pragma Share_Generic,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id38}@anchor{de}@anchor{gnat_rm/implementation_defined_pragmas pragma-shared}@anchor{df}
+@anchor{gnat_rm/implementation_defined_pragmas id38}@anchor{df}@anchor{gnat_rm/implementation_defined_pragmas pragma-shared}@anchor{e0}
@section Pragma Shared
@@ -7498,7 +7517,7 @@ This pragma is provided for compatibility with Ada 83. The syntax and
semantics are identical to pragma Atomic.
@node Pragma Short_Circuit_And_Or,Pragma Short_Descriptors,Pragma Shared,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-short-circuit-and-or}@anchor{e0}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-short-circuit-and-or}@anchor{e1}
@section Pragma Short_Circuit_And_Or
@@ -7517,7 +7536,7 @@ within the file being compiled, it applies only to the file being compiled.
There is no requirement that all units in a partition use this option.
@node Pragma Short_Descriptors,Pragma Simple_Storage_Pool_Type,Pragma Short_Circuit_And_Or,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-short-descriptors}@anchor{e1}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-short-descriptors}@anchor{e2}
@section Pragma Short_Descriptors
@@ -7531,7 +7550,7 @@ This pragma is provided for compatibility with other Ada implementations. It
is recognized but ignored by all current versions of GNAT.
@node Pragma Simple_Storage_Pool_Type,Pragma Source_File_Name,Pragma Short_Descriptors,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id39}@anchor{e2}@anchor{gnat_rm/implementation_defined_pragmas pragma-simple-storage-pool-type}@anchor{e3}
+@anchor{gnat_rm/implementation_defined_pragmas id39}@anchor{e3}@anchor{gnat_rm/implementation_defined_pragmas pragma-simple-storage-pool-type}@anchor{e4}
@section Pragma Simple_Storage_Pool_Type
@@ -7585,7 +7604,7 @@ storage-management discipline).
An object of a simple storage pool type can be associated with an access
type by specifying the attribute
-@ref{e4,,Simple_Storage_Pool}. For example:
+@ref{e5,,Simple_Storage_Pool}. For example:
@example
My_Pool : My_Simple_Storage_Pool_Type;
@@ -7595,11 +7614,11 @@ type Acc is access My_Data_Type;
for Acc'Simple_Storage_Pool use My_Pool;
@end example
-See attribute @ref{e4,,Simple_Storage_Pool}
+See attribute @ref{e5,,Simple_Storage_Pool}
for further details.
@node Pragma Source_File_Name,Pragma Source_File_Name_Project,Pragma Simple_Storage_Pool_Type,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id40}@anchor{e5}@anchor{gnat_rm/implementation_defined_pragmas pragma-source-file-name}@anchor{e6}
+@anchor{gnat_rm/implementation_defined_pragmas id40}@anchor{e6}@anchor{gnat_rm/implementation_defined_pragmas pragma-source-file-name}@anchor{e7}
@section Pragma Source_File_Name
@@ -7691,20 +7710,20 @@ aware of these pragmas, and so other tools that use the projet file would not
be aware of the intended naming conventions. If you are using project files,
file naming is controlled by Source_File_Name_Project pragmas, which are
usually supplied automatically by the project manager. A pragma
-Source_File_Name cannot appear after a @ref{e7,,Pragma Source_File_Name_Project}.
+Source_File_Name cannot appear after a @ref{e8,,Pragma Source_File_Name_Project}.
For more details on the use of the @code{Source_File_Name} pragma, see the
sections on @cite{Using Other File Names} and @cite{Alternative File Naming Schemes}
in the @cite{GNAT User’s Guide}.
@node Pragma Source_File_Name_Project,Pragma Source_Reference,Pragma Source_File_Name,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id41}@anchor{e8}@anchor{gnat_rm/implementation_defined_pragmas pragma-source-file-name-project}@anchor{e7}
+@anchor{gnat_rm/implementation_defined_pragmas id41}@anchor{e9}@anchor{gnat_rm/implementation_defined_pragmas pragma-source-file-name-project}@anchor{e8}
@section Pragma Source_File_Name_Project
This pragma has the same syntax and semantics as pragma Source_File_Name.
It is only allowed as a stand-alone configuration pragma.
-It cannot appear after a @ref{e6,,Pragma Source_File_Name}, and
+It cannot appear after a @ref{e7,,Pragma Source_File_Name}, and
most importantly, once pragma Source_File_Name_Project appears,
no further Source_File_Name pragmas are allowed.
@@ -7716,7 +7735,7 @@ Source_File_Name or Source_File_Name_Project pragmas (which would not be
known to the project manager).
@node Pragma Source_Reference,Pragma SPARK_Mode,Pragma Source_File_Name_Project,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-source-reference}@anchor{e9}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-source-reference}@anchor{ea}
@section Pragma Source_Reference
@@ -7740,7 +7759,7 @@ string expression other than a string literal. This is because its value
is needed for error messages issued by all phases of the compiler.
@node Pragma SPARK_Mode,Pragma Static_Elaboration_Desired,Pragma Source_Reference,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id42}@anchor{ea}@anchor{gnat_rm/implementation_defined_pragmas pragma-spark-mode}@anchor{eb}
+@anchor{gnat_rm/implementation_defined_pragmas id42}@anchor{eb}@anchor{gnat_rm/implementation_defined_pragmas pragma-spark-mode}@anchor{ec}
@section Pragma SPARK_Mode
@@ -7822,7 +7841,7 @@ SPARK_Mode (@code{Off}), then that pragma will need to be repeated in
the package body.
@node Pragma Static_Elaboration_Desired,Pragma Stream_Convert,Pragma SPARK_Mode,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-static-elaboration-desired}@anchor{ec}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-static-elaboration-desired}@anchor{ed}
@section Pragma Static_Elaboration_Desired
@@ -7846,7 +7865,7 @@ construction of larger aggregates with static components that include an others
choice.)
@node Pragma Stream_Convert,Pragma Style_Checks,Pragma Static_Elaboration_Desired,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-stream-convert}@anchor{ed}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-stream-convert}@anchor{ee}
@section Pragma Stream_Convert
@@ -7923,7 +7942,7 @@ the pragma is silently ignored, and the default implementation of the stream
attributes is used instead.
@node Pragma Style_Checks,Pragma Subtitle,Pragma Stream_Convert,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-style-checks}@anchor{ee}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-style-checks}@anchor{ef}
@section Pragma Style_Checks
@@ -7996,7 +8015,7 @@ Rf2 : Integer := ARG; -- OK, no error
@end example
@node Pragma Subtitle,Pragma Suppress,Pragma Style_Checks,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-subtitle}@anchor{ef}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-subtitle}@anchor{f0}
@section Pragma Subtitle
@@ -8010,7 +8029,7 @@ This pragma is recognized for compatibility with other Ada compilers
but is ignored by GNAT.
@node Pragma Suppress,Pragma Suppress_All,Pragma Subtitle,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress}@anchor{f0}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress}@anchor{f1}
@section Pragma Suppress
@@ -8083,7 +8102,7 @@ Of course, run-time checks are omitted whenever the compiler can prove
that they will not fail, whether or not checks are suppressed.
@node Pragma Suppress_All,Pragma Suppress_Debug_Info,Pragma Suppress,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-all}@anchor{f1}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-all}@anchor{f2}
@section Pragma Suppress_All
@@ -8102,7 +8121,7 @@ The use of the standard Ada pragma @code{Suppress (All_Checks)}
as a normal configuration pragma is the preferred usage in GNAT.
@node Pragma Suppress_Debug_Info,Pragma Suppress_Exception_Locations,Pragma Suppress_All,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id43}@anchor{f2}@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-debug-info}@anchor{f3}
+@anchor{gnat_rm/implementation_defined_pragmas id43}@anchor{f3}@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-debug-info}@anchor{f4}
@section Pragma Suppress_Debug_Info
@@ -8117,7 +8136,7 @@ for the specified entity. It is intended primarily for use in debugging
the debugger, and navigating around debugger problems.
@node Pragma Suppress_Exception_Locations,Pragma Suppress_Initialization,Pragma Suppress_Debug_Info,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-exception-locations}@anchor{f4}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-exception-locations}@anchor{f5}
@section Pragma Suppress_Exception_Locations
@@ -8140,7 +8159,7 @@ a partition, so it is fine to have some units within a partition compiled
with this pragma and others compiled in normal mode without it.
@node Pragma Suppress_Initialization,Pragma Task_Name,Pragma Suppress_Exception_Locations,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id44}@anchor{f5}@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-initialization}@anchor{f6}
+@anchor{gnat_rm/implementation_defined_pragmas id44}@anchor{f6}@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-initialization}@anchor{f7}
@section Pragma Suppress_Initialization
@@ -8185,7 +8204,7 @@ is suppressed, just as though its subtype had been given in a pragma
Suppress_Initialization, as described above.
@node Pragma Task_Name,Pragma Task_Storage,Pragma Suppress_Initialization,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-task-name}@anchor{f7}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-task-name}@anchor{f8}
@section Pragma Task_Name
@@ -8241,7 +8260,7 @@ end;
@end example
@node Pragma Task_Storage,Pragma Test_Case,Pragma Task_Name,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-task-storage}@anchor{f8}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-task-storage}@anchor{f9}
@section Pragma Task_Storage
@@ -8261,7 +8280,7 @@ created, depending on the target. This pragma can appear anywhere a
type.
@node Pragma Test_Case,Pragma Thread_Local_Storage,Pragma Task_Storage,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id45}@anchor{f9}@anchor{gnat_rm/implementation_defined_pragmas pragma-test-case}@anchor{fa}
+@anchor{gnat_rm/implementation_defined_pragmas id45}@anchor{fa}@anchor{gnat_rm/implementation_defined_pragmas pragma-test-case}@anchor{fb}
@section Pragma Test_Case
@@ -8317,7 +8336,7 @@ postcondition. Mode @code{Robustness} indicates that the precondition and
postcondition of the subprogram should be ignored for this test case.
@node Pragma Thread_Local_Storage,Pragma Time_Slice,Pragma Test_Case,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id46}@anchor{fb}@anchor{gnat_rm/implementation_defined_pragmas pragma-thread-local-storage}@anchor{fc}
+@anchor{gnat_rm/implementation_defined_pragmas id46}@anchor{fc}@anchor{gnat_rm/implementation_defined_pragmas pragma-thread-local-storage}@anchor{fd}
@section Pragma Thread_Local_Storage
@@ -8355,7 +8374,7 @@ If this pragma is used on a system where @code{TLS} is not supported,
then an error message will be generated and the program will be rejected.
@node Pragma Time_Slice,Pragma Title,Pragma Thread_Local_Storage,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-time-slice}@anchor{fd}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-time-slice}@anchor{fe}
@section Pragma Time_Slice
@@ -8371,7 +8390,7 @@ It is ignored if it is used in a system that does not allow this control,
or if it appears in other than the main program unit.
@node Pragma Title,Pragma Type_Invariant,Pragma Time_Slice,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-title}@anchor{fe}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-title}@anchor{ff}
@section Pragma Title
@@ -8396,7 +8415,7 @@ notation is used, and named and positional notation can be mixed
following the normal rules for procedure calls in Ada.
@node Pragma Type_Invariant,Pragma Type_Invariant_Class,Pragma Title,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-type-invariant}@anchor{ff}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-type-invariant}@anchor{100}
@section Pragma Type_Invariant
@@ -8417,7 +8436,7 @@ controlled by the assertion identifier @code{Type_Invariant}
rather than @code{Invariant}.
@node Pragma Type_Invariant_Class,Pragma Unchecked_Union,Pragma Type_Invariant,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id47}@anchor{100}@anchor{gnat_rm/implementation_defined_pragmas pragma-type-invariant-class}@anchor{101}
+@anchor{gnat_rm/implementation_defined_pragmas id47}@anchor{101}@anchor{gnat_rm/implementation_defined_pragmas pragma-type-invariant-class}@anchor{102}
@section Pragma Type_Invariant_Class
@@ -8444,7 +8463,7 @@ policy that controls this pragma is @code{Type_Invariant'Class},
not @code{Type_Invariant_Class}.
@node Pragma Unchecked_Union,Pragma Unevaluated_Use_Of_Old,Pragma Type_Invariant_Class,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-unchecked-union}@anchor{102}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-unchecked-union}@anchor{103}
@section Pragma Unchecked_Union
@@ -8464,7 +8483,7 @@ version in all language modes (Ada 83, Ada 95, and Ada 2005). For full
details, consult the Ada 2012 Reference Manual, section B.3.3.
@node Pragma Unevaluated_Use_Of_Old,Pragma Unimplemented_Unit,Pragma Unchecked_Union,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-unevaluated-use-of-old}@anchor{103}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-unevaluated-use-of-old}@anchor{104}
@section Pragma Unevaluated_Use_Of_Old
@@ -8519,7 +8538,7 @@ uses up to the end of the corresponding statement sequence or
sequence of package declarations.
@node Pragma Unimplemented_Unit,Pragma Universal_Aliasing,Pragma Unevaluated_Use_Of_Old,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-unimplemented-unit}@anchor{104}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-unimplemented-unit}@anchor{105}
@section Pragma Unimplemented_Unit
@@ -8539,7 +8558,7 @@ The abort only happens if code is being generated. Thus you can use
specs of unimplemented packages in syntax or semantic checking mode.
@node Pragma Universal_Aliasing,Pragma Unmodified,Pragma Unimplemented_Unit,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id48}@anchor{105}@anchor{gnat_rm/implementation_defined_pragmas pragma-universal-aliasing}@anchor{106}
+@anchor{gnat_rm/implementation_defined_pragmas id48}@anchor{106}@anchor{gnat_rm/implementation_defined_pragmas pragma-universal-aliasing}@anchor{107}
@section Pragma Universal_Aliasing
@@ -8558,7 +8577,7 @@ situations in which it must be suppressed, see the section on
@code{Optimization and Strict Aliasing} in the @cite{GNAT User’s Guide}.
@node Pragma Unmodified,Pragma Unreferenced,Pragma Universal_Aliasing,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id49}@anchor{107}@anchor{gnat_rm/implementation_defined_pragmas pragma-unmodified}@anchor{108}
+@anchor{gnat_rm/implementation_defined_pragmas id49}@anchor{108}@anchor{gnat_rm/implementation_defined_pragmas pragma-unmodified}@anchor{109}
@section Pragma Unmodified
@@ -8592,7 +8611,7 @@ Thus it is never necessary to use @code{pragma Unmodified} for such
variables, though it is harmless to do so.
@node Pragma Unreferenced,Pragma Unreferenced_Objects,Pragma Unmodified,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id50}@anchor{109}@anchor{gnat_rm/implementation_defined_pragmas pragma-unreferenced}@anchor{10a}
+@anchor{gnat_rm/implementation_defined_pragmas id50}@anchor{10a}@anchor{gnat_rm/implementation_defined_pragmas pragma-unreferenced}@anchor{10b}
@section Pragma Unreferenced
@@ -8636,7 +8655,7 @@ Note that if a warning is desired for all calls to a given subprogram,
regardless of whether they occur in the same unit as the subprogram
declaration, then this pragma should not be used (calls from another
unit would not be flagged); pragma Obsolescent can be used instead
-for this purpose, see @ref{ac,,Pragma Obsolescent}.
+for this purpose, see @ref{ad,,Pragma Obsolescent}.
The second form of pragma @code{Unreferenced} is used within a context
clause. In this case the arguments must be unit names of units previously
@@ -8652,7 +8671,7 @@ Thus it is never necessary to use @code{pragma Unreferenced} for such
variables, though it is harmless to do so.
@node Pragma Unreferenced_Objects,Pragma Unreserve_All_Interrupts,Pragma Unreferenced,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id51}@anchor{10b}@anchor{gnat_rm/implementation_defined_pragmas pragma-unreferenced-objects}@anchor{10c}
+@anchor{gnat_rm/implementation_defined_pragmas id51}@anchor{10c}@anchor{gnat_rm/implementation_defined_pragmas pragma-unreferenced-objects}@anchor{10d}
@section Pragma Unreferenced_Objects
@@ -8677,7 +8696,7 @@ compiler will automatically suppress unwanted warnings about these variables
not being referenced.
@node Pragma Unreserve_All_Interrupts,Pragma Unsuppress,Pragma Unreferenced_Objects,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-unreserve-all-interrupts}@anchor{10d}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-unreserve-all-interrupts}@anchor{10e}
@section Pragma Unreserve_All_Interrupts
@@ -8713,7 +8732,7 @@ handled, see pragma @code{Interrupt_State}, which subsumes the functionality
of the @code{Unreserve_All_Interrupts} pragma.
@node Pragma Unsuppress,Pragma Use_VADS_Size,Pragma Unreserve_All_Interrupts,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-unsuppress}@anchor{10e}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-unsuppress}@anchor{10f}
@section Pragma Unsuppress
@@ -8749,7 +8768,7 @@ number of implementation-defined check names. See the description of pragma
@code{Suppress} for full details.
@node Pragma Use_VADS_Size,Pragma Unused,Pragma Unsuppress,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-use-vads-size}@anchor{10f}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-use-vads-size}@anchor{110}
@section Pragma Use_VADS_Size
@@ -8773,7 +8792,7 @@ as implemented in the VADS compiler. See description of the VADS_Size
attribute for further details.
@node Pragma Unused,Pragma Validity_Checks,Pragma Use_VADS_Size,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id52}@anchor{110}@anchor{gnat_rm/implementation_defined_pragmas pragma-unused}@anchor{111}
+@anchor{gnat_rm/implementation_defined_pragmas id52}@anchor{111}@anchor{gnat_rm/implementation_defined_pragmas pragma-unused}@anchor{112}
@section Pragma Unused
@@ -8807,7 +8826,7 @@ Thus it is never necessary to use @code{pragma Unmodified} for such
variables, though it is harmless to do so.
@node Pragma Validity_Checks,Pragma Volatile,Pragma Unused,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-validity-checks}@anchor{112}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-validity-checks}@anchor{113}
@section Pragma Validity_Checks
@@ -8863,7 +8882,7 @@ A := C; -- C will be validity checked
@end example
@node Pragma Volatile,Pragma Volatile_Full_Access,Pragma Validity_Checks,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id53}@anchor{113}@anchor{gnat_rm/implementation_defined_pragmas pragma-volatile}@anchor{114}
+@anchor{gnat_rm/implementation_defined_pragmas id53}@anchor{114}@anchor{gnat_rm/implementation_defined_pragmas pragma-volatile}@anchor{115}
@section Pragma Volatile
@@ -8881,7 +8900,7 @@ implementation of pragma Volatile is upwards compatible with the
implementation in DEC Ada 83.
@node Pragma Volatile_Full_Access,Pragma Volatile_Function,Pragma Volatile,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id54}@anchor{115}@anchor{gnat_rm/implementation_defined_pragmas pragma-volatile-full-access}@anchor{116}
+@anchor{gnat_rm/implementation_defined_pragmas id54}@anchor{116}@anchor{gnat_rm/implementation_defined_pragmas pragma-volatile-full-access}@anchor{117}
@section Pragma Volatile_Full_Access
@@ -8907,7 +8926,7 @@ is not to the whole object; the compiler is allowed (and generally will)
access only part of the object in this case.
@node Pragma Volatile_Function,Pragma Warning_As_Error,Pragma Volatile_Full_Access,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id55}@anchor{117}@anchor{gnat_rm/implementation_defined_pragmas pragma-volatile-function}@anchor{118}
+@anchor{gnat_rm/implementation_defined_pragmas id55}@anchor{118}@anchor{gnat_rm/implementation_defined_pragmas pragma-volatile-function}@anchor{119}
@section Pragma Volatile_Function
@@ -8921,7 +8940,7 @@ For the semantics of this pragma, see the entry for aspect @code{Volatile_Functi
in the SPARK 2014 Reference Manual, section 7.1.2.
@node Pragma Warning_As_Error,Pragma Warnings,Pragma Volatile_Function,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-warning-as-error}@anchor{119}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-warning-as-error}@anchor{11a}
@section Pragma Warning_As_Error
@@ -8961,7 +8980,7 @@ you can use multiple pragma Warning_As_Error.
The above use of patterns to match the message applies only to warning
messages generated by the front end. This pragma can also be applied to
-warnings provided by the back end and mentioned in @ref{11a,,Pragma Warnings}.
+warnings provided by the back end and mentioned in @ref{11b,,Pragma Warnings}.
By using a single full @emph{-Wxxx} switch in the pragma, such warnings
can also be treated as errors.
@@ -9011,7 +9030,7 @@ the tag is changed from “warning:” to “error:” and the string
“[warning-as-error]” is appended to the end of the message.
@node Pragma Warnings,Pragma Weak_External,Pragma Warning_As_Error,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id56}@anchor{11b}@anchor{gnat_rm/implementation_defined_pragmas pragma-warnings}@anchor{11a}
+@anchor{gnat_rm/implementation_defined_pragmas id56}@anchor{11c}@anchor{gnat_rm/implementation_defined_pragmas pragma-warnings}@anchor{11b}
@section Pragma Warnings
@@ -9167,7 +9186,7 @@ selectively for each tool, and as a consequence to detect useless pragma
Warnings with switch @code{-gnatw.w}.
@node Pragma Weak_External,Pragma Wide_Character_Encoding,Pragma Warnings,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-weak-external}@anchor{11c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-weak-external}@anchor{11d}
@section Pragma Weak_External
@@ -9218,7 +9237,7 @@ end External_Module;
@end example
@node Pragma Wide_Character_Encoding,,Pragma Weak_External,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-wide-character-encoding}@anchor{11d}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-wide-character-encoding}@anchor{11e}
@section Pragma Wide_Character_Encoding
@@ -9249,7 +9268,7 @@ encoding within that file, and does not affect withed units, specs,
or subunits.
@node Implementation Defined Aspects,Implementation Defined Attributes,Implementation Defined Pragmas,Top
-@anchor{gnat_rm/implementation_defined_aspects doc}@anchor{11e}@anchor{gnat_rm/implementation_defined_aspects id1}@anchor{11f}@anchor{gnat_rm/implementation_defined_aspects implementation-defined-aspects}@anchor{120}
+@anchor{gnat_rm/implementation_defined_aspects doc}@anchor{11f}@anchor{gnat_rm/implementation_defined_aspects id1}@anchor{120}@anchor{gnat_rm/implementation_defined_aspects implementation-defined-aspects}@anchor{121}
@chapter Implementation Defined Aspects
@@ -9369,16 +9388,16 @@ or attribute definition clause.
@end menu
@node Aspect Abstract_State,Aspect Annotate,,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-abstract-state}@anchor{121}
+@anchor{gnat_rm/implementation_defined_aspects aspect-abstract-state}@anchor{122}
@section Aspect Abstract_State
@geindex Abstract_State
-This aspect is equivalent to @ref{1d,,pragma Abstract_State}.
+This aspect is equivalent to @ref{1e,,pragma Abstract_State}.
@node Aspect Annotate,Aspect Async_Readers,Aspect Abstract_State,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-annotate}@anchor{122}
+@anchor{gnat_rm/implementation_defined_aspects aspect-annotate}@anchor{123}
@section Aspect Annotate
@@ -9386,7 +9405,7 @@ This aspect is equivalent to @ref{1d,,pragma Abstract_State}.
There are three forms of this aspect (where ID is an identifier,
and ARG is a general expression),
-corresponding to @ref{27,,pragma Annotate}.
+corresponding to @ref{28,,pragma Annotate}.
@table @asis
@@ -9405,63 +9424,63 @@ Equivalent to @code{pragma Annotate (ID, ID @{, ARG@}, Entity => Name);}
@end table
@node Aspect Async_Readers,Aspect Async_Writers,Aspect Annotate,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-async-readers}@anchor{123}
+@anchor{gnat_rm/implementation_defined_aspects aspect-async-readers}@anchor{124}
@section Aspect Async_Readers
@geindex Async_Readers
-This boolean aspect is equivalent to @ref{2e,,pragma Async_Readers}.
+This boolean aspect is equivalent to @ref{2f,,pragma Async_Readers}.
@node Aspect Async_Writers,Aspect Constant_After_Elaboration,Aspect Async_Readers,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-async-writers}@anchor{124}
+@anchor{gnat_rm/implementation_defined_aspects aspect-async-writers}@anchor{125}
@section Aspect Async_Writers
@geindex Async_Writers
-This boolean aspect is equivalent to @ref{30,,pragma Async_Writers}.
+This boolean aspect is equivalent to @ref{31,,pragma Async_Writers}.
@node Aspect Constant_After_Elaboration,Aspect Contract_Cases,Aspect Async_Writers,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-constant-after-elaboration}@anchor{125}
+@anchor{gnat_rm/implementation_defined_aspects aspect-constant-after-elaboration}@anchor{126}
@section Aspect Constant_After_Elaboration
@geindex Constant_After_Elaboration
-This aspect is equivalent to @ref{42,,pragma Constant_After_Elaboration}.
+This aspect is equivalent to @ref{43,,pragma Constant_After_Elaboration}.
@node Aspect Contract_Cases,Aspect Depends,Aspect Constant_After_Elaboration,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-contract-cases}@anchor{126}
+@anchor{gnat_rm/implementation_defined_aspects aspect-contract-cases}@anchor{127}
@section Aspect Contract_Cases
@geindex Contract_Cases
-This aspect is equivalent to @ref{44,,pragma Contract_Cases}, the sequence
+This aspect is equivalent to @ref{45,,pragma Contract_Cases}, the sequence
of clauses being enclosed in parentheses so that syntactically it is an
aggregate.
@node Aspect Depends,Aspect Default_Initial_Condition,Aspect Contract_Cases,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-depends}@anchor{127}
+@anchor{gnat_rm/implementation_defined_aspects aspect-depends}@anchor{128}
@section Aspect Depends
@geindex Depends
-This aspect is equivalent to @ref{54,,pragma Depends}.
+This aspect is equivalent to @ref{55,,pragma Depends}.
@node Aspect Default_Initial_Condition,Aspect Dimension,Aspect Depends,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-default-initial-condition}@anchor{128}
+@anchor{gnat_rm/implementation_defined_aspects aspect-default-initial-condition}@anchor{129}
@section Aspect Default_Initial_Condition
@geindex Default_Initial_Condition
-This aspect is equivalent to @ref{4e,,pragma Default_Initial_Condition}.
+This aspect is equivalent to @ref{4f,,pragma Default_Initial_Condition}.
@node Aspect Dimension,Aspect Dimension_System,Aspect Default_Initial_Condition,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-dimension}@anchor{129}
+@anchor{gnat_rm/implementation_defined_aspects aspect-dimension}@anchor{12a}
@section Aspect Dimension
@@ -9497,7 +9516,7 @@ Note that when the dimensioned type is an integer type, then any
dimension value must be an integer literal.
@node Aspect Dimension_System,Aspect Disable_Controlled,Aspect Dimension,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-dimension-system}@anchor{12a}
+@anchor{gnat_rm/implementation_defined_aspects aspect-dimension-system}@anchor{12b}
@section Aspect Dimension_System
@@ -9557,7 +9576,7 @@ See section ‘Performing Dimensionality Analysis in GNAT’ in the GNAT Users
Guide for detailed examples of use of the dimension system.
@node Aspect Disable_Controlled,Aspect Effective_Reads,Aspect Dimension_System,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-disable-controlled}@anchor{12b}
+@anchor{gnat_rm/implementation_defined_aspects aspect-disable-controlled}@anchor{12c}
@section Aspect Disable_Controlled
@@ -9570,110 +9589,110 @@ where for example you might want a record to be controlled or not depending on
whether some run-time check is enabled or suppressed.
@node Aspect Effective_Reads,Aspect Effective_Writes,Aspect Disable_Controlled,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-effective-reads}@anchor{12c}
+@anchor{gnat_rm/implementation_defined_aspects aspect-effective-reads}@anchor{12d}
@section Aspect Effective_Reads
@geindex Effective_Reads
-This aspect is equivalent to @ref{59,,pragma Effective_Reads}.
+This aspect is equivalent to @ref{5a,,pragma Effective_Reads}.
@node Aspect Effective_Writes,Aspect Extensions_Visible,Aspect Effective_Reads,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-effective-writes}@anchor{12d}
+@anchor{gnat_rm/implementation_defined_aspects aspect-effective-writes}@anchor{12e}
@section Aspect Effective_Writes
@geindex Effective_Writes
-This aspect is equivalent to @ref{5b,,pragma Effective_Writes}.
+This aspect is equivalent to @ref{5c,,pragma Effective_Writes}.
@node Aspect Extensions_Visible,Aspect Favor_Top_Level,Aspect Effective_Writes,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-extensions-visible}@anchor{12e}
+@anchor{gnat_rm/implementation_defined_aspects aspect-extensions-visible}@anchor{12f}
@section Aspect Extensions_Visible
@geindex Extensions_Visible
-This aspect is equivalent to @ref{66,,pragma Extensions_Visible}.
+This aspect is equivalent to @ref{67,,pragma Extensions_Visible}.
@node Aspect Favor_Top_Level,Aspect Ghost,Aspect Extensions_Visible,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-favor-top-level}@anchor{12f}
+@anchor{gnat_rm/implementation_defined_aspects aspect-favor-top-level}@anchor{130}
@section Aspect Favor_Top_Level
@geindex Favor_Top_Level
-This boolean aspect is equivalent to @ref{6b,,pragma Favor_Top_Level}.
+This boolean aspect is equivalent to @ref{6c,,pragma Favor_Top_Level}.
@node Aspect Ghost,Aspect Global,Aspect Favor_Top_Level,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-ghost}@anchor{130}
+@anchor{gnat_rm/implementation_defined_aspects aspect-ghost}@anchor{131}
@section Aspect Ghost
@geindex Ghost
-This aspect is equivalent to @ref{6f,,pragma Ghost}.
+This aspect is equivalent to @ref{70,,pragma Ghost}.
@node Aspect Global,Aspect Initial_Condition,Aspect Ghost,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-global}@anchor{131}
+@anchor{gnat_rm/implementation_defined_aspects aspect-global}@anchor{132}
@section Aspect Global
@geindex Global
-This aspect is equivalent to @ref{71,,pragma Global}.
+This aspect is equivalent to @ref{72,,pragma Global}.
@node Aspect Initial_Condition,Aspect Initializes,Aspect Global,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-initial-condition}@anchor{132}
+@anchor{gnat_rm/implementation_defined_aspects aspect-initial-condition}@anchor{133}
@section Aspect Initial_Condition
@geindex Initial_Condition
-This aspect is equivalent to @ref{7e,,pragma Initial_Condition}.
+This aspect is equivalent to @ref{7f,,pragma Initial_Condition}.
@node Aspect Initializes,Aspect Inline_Always,Aspect Initial_Condition,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-initializes}@anchor{133}
+@anchor{gnat_rm/implementation_defined_aspects aspect-initializes}@anchor{134}
@section Aspect Initializes
@geindex Initializes
-This aspect is equivalent to @ref{81,,pragma Initializes}.
+This aspect is equivalent to @ref{82,,pragma Initializes}.
@node Aspect Inline_Always,Aspect Invariant,Aspect Initializes,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-inline-always}@anchor{134}
+@anchor{gnat_rm/implementation_defined_aspects aspect-inline-always}@anchor{135}
@section Aspect Inline_Always
@geindex Inline_Always
-This boolean aspect is equivalent to @ref{83,,pragma Inline_Always}.
+This boolean aspect is equivalent to @ref{84,,pragma Inline_Always}.
@node Aspect Invariant,Aspect Invariant’Class,Aspect Inline_Always,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-invariant}@anchor{135}
+@anchor{gnat_rm/implementation_defined_aspects aspect-invariant}@anchor{136}
@section Aspect Invariant
@geindex Invariant
-This aspect is equivalent to @ref{8a,,pragma Invariant}. It is a
+This aspect is equivalent to @ref{8b,,pragma Invariant}. It is a
synonym for the language defined aspect @code{Type_Invariant} except
that it is separately controllable using pragma @code{Assertion_Policy}.
@node Aspect Invariant’Class,Aspect Iterable,Aspect Invariant,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-invariant-class}@anchor{136}
+@anchor{gnat_rm/implementation_defined_aspects aspect-invariant-class}@anchor{137}
@section Aspect Invariant’Class
@geindex Invariant'Class
-This aspect is equivalent to @ref{101,,pragma Type_Invariant_Class}. It is a
+This aspect is equivalent to @ref{102,,pragma Type_Invariant_Class}. It is a
synonym for the language defined aspect @code{Type_Invariant'Class} except
that it is separately controllable using pragma @code{Assertion_Policy}.
@node Aspect Iterable,Aspect Linker_Section,Aspect Invariant’Class,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-iterable}@anchor{137}
+@anchor{gnat_rm/implementation_defined_aspects aspect-iterable}@anchor{138}
@section Aspect Iterable
@@ -9753,73 +9772,73 @@ function Get_Element (Cont : Container; Position : Cursor) return Element_Type;
This aspect is used in the GNAT-defined formal container packages.
@node Aspect Linker_Section,Aspect Lock_Free,Aspect Iterable,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-linker-section}@anchor{138}
+@anchor{gnat_rm/implementation_defined_aspects aspect-linker-section}@anchor{139}
@section Aspect Linker_Section
@geindex Linker_Section
-This aspect is equivalent to @ref{92,,pragma Linker_Section}.
+This aspect is equivalent to @ref{93,,pragma Linker_Section}.
@node Aspect Lock_Free,Aspect Max_Queue_Length,Aspect Linker_Section,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-lock-free}@anchor{139}
+@anchor{gnat_rm/implementation_defined_aspects aspect-lock-free}@anchor{13a}
@section Aspect Lock_Free
@geindex Lock_Free
-This boolean aspect is equivalent to @ref{94,,pragma Lock_Free}.
+This boolean aspect is equivalent to @ref{95,,pragma Lock_Free}.
@node Aspect Max_Queue_Length,Aspect No_Caching,Aspect Lock_Free,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-max-queue-length}@anchor{13a}
+@anchor{gnat_rm/implementation_defined_aspects aspect-max-queue-length}@anchor{13b}
@section Aspect Max_Queue_Length
@geindex Max_Queue_Length
-This aspect is equivalent to @ref{9c,,pragma Max_Queue_Length}.
+This aspect is equivalent to @ref{9d,,pragma Max_Queue_Length}.
@node Aspect No_Caching,Aspect No_Elaboration_Code_All,Aspect Max_Queue_Length,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-no-caching}@anchor{13b}
+@anchor{gnat_rm/implementation_defined_aspects aspect-no-caching}@anchor{13c}
@section Aspect No_Caching
@geindex No_Caching
-This boolean aspect is equivalent to @ref{9f,,pragma No_Caching}.
+This boolean aspect is equivalent to @ref{a0,,pragma No_Caching}.
@node Aspect No_Elaboration_Code_All,Aspect No_Inline,Aspect No_Caching,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-no-elaboration-code-all}@anchor{13c}
+@anchor{gnat_rm/implementation_defined_aspects aspect-no-elaboration-code-all}@anchor{13d}
@section Aspect No_Elaboration_Code_All
@geindex No_Elaboration_Code_All
-This aspect is equivalent to @ref{a2,,pragma No_Elaboration_Code_All}
+This aspect is equivalent to @ref{a3,,pragma No_Elaboration_Code_All}
for a program unit.
@node Aspect No_Inline,Aspect No_Tagged_Streams,Aspect No_Elaboration_Code_All,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-no-inline}@anchor{13d}
+@anchor{gnat_rm/implementation_defined_aspects aspect-no-inline}@anchor{13e}
@section Aspect No_Inline
@geindex No_Inline
-This boolean aspect is equivalent to @ref{a5,,pragma No_Inline}.
+This boolean aspect is equivalent to @ref{a6,,pragma No_Inline}.
@node Aspect No_Tagged_Streams,Aspect No_Task_Parts,Aspect No_Inline,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-no-tagged-streams}@anchor{13e}
+@anchor{gnat_rm/implementation_defined_aspects aspect-no-tagged-streams}@anchor{13f}
@section Aspect No_Tagged_Streams
@geindex No_Tagged_Streams
-This aspect is equivalent to @ref{a9,,pragma No_Tagged_Streams} with an
+This aspect is equivalent to @ref{aa,,pragma No_Tagged_Streams} with an
argument specifying a root tagged type (thus this aspect can only be
applied to such a type).
@node Aspect No_Task_Parts,Aspect Object_Size,Aspect No_Tagged_Streams,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-no-task-parts}@anchor{13f}
+@anchor{gnat_rm/implementation_defined_aspects aspect-no-task-parts}@anchor{140}
@section Aspect No_Task_Parts
@@ -9835,45 +9854,45 @@ away certain tasking-related code that would otherwise be needed
for T’Class, because descendants of T might contain tasks.
@node Aspect Object_Size,Aspect Obsolescent,Aspect No_Task_Parts,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-object-size}@anchor{140}
+@anchor{gnat_rm/implementation_defined_aspects aspect-object-size}@anchor{141}
@section Aspect Object_Size
@geindex Object_Size
-This aspect is equivalent to @ref{141,,attribute Object_Size}.
+This aspect is equivalent to @ref{142,,attribute Object_Size}.
@node Aspect Obsolescent,Aspect Part_Of,Aspect Object_Size,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-obsolescent}@anchor{142}
+@anchor{gnat_rm/implementation_defined_aspects aspect-obsolescent}@anchor{143}
@section Aspect Obsolescent
@geindex Obsolsecent
-This aspect is equivalent to @ref{ac,,pragma Obsolescent}. Note that the
+This aspect is equivalent to @ref{ad,,pragma Obsolescent}. Note that the
evaluation of this aspect happens at the point of occurrence, it is not
delayed until the freeze point.
@node Aspect Part_Of,Aspect Persistent_BSS,Aspect Obsolescent,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-part-of}@anchor{143}
+@anchor{gnat_rm/implementation_defined_aspects aspect-part-of}@anchor{144}
@section Aspect Part_Of
@geindex Part_Of
-This aspect is equivalent to @ref{b3,,pragma Part_Of}.
+This aspect is equivalent to @ref{b4,,pragma Part_Of}.
@node Aspect Persistent_BSS,Aspect Predicate,Aspect Part_Of,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-persistent-bss}@anchor{144}
+@anchor{gnat_rm/implementation_defined_aspects aspect-persistent-bss}@anchor{145}
@section Aspect Persistent_BSS
@geindex Persistent_BSS
-This boolean aspect is equivalent to @ref{b6,,pragma Persistent_BSS}.
+This boolean aspect is equivalent to @ref{b7,,pragma Persistent_BSS}.
@node Aspect Predicate,Aspect Pure_Function,Aspect Persistent_BSS,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-predicate}@anchor{145}
+@anchor{gnat_rm/implementation_defined_aspects aspect-predicate}@anchor{146}
@section Aspect Predicate
@@ -9887,7 +9906,7 @@ expression. It is also separately controllable using pragma
@code{Assertion_Policy}.
@node Aspect Pure_Function,Aspect Refined_Depends,Aspect Predicate,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-pure-function}@anchor{146}
+@anchor{gnat_rm/implementation_defined_aspects aspect-pure-function}@anchor{147}
@section Aspect Pure_Function
@@ -9896,7 +9915,7 @@ expression. It is also separately controllable using pragma
This boolean aspect is equivalent to @ref{ca,,pragma Pure_Function}.
@node Aspect Refined_Depends,Aspect Refined_Global,Aspect Pure_Function,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-refined-depends}@anchor{147}
+@anchor{gnat_rm/implementation_defined_aspects aspect-refined-depends}@anchor{148}
@section Aspect Refined_Depends
@@ -9905,7 +9924,7 @@ This boolean aspect is equivalent to @ref{ca,,pragma Pure_Function}.
This aspect is equivalent to @ref{ce,,pragma Refined_Depends}.
@node Aspect Refined_Global,Aspect Refined_Post,Aspect Refined_Depends,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-refined-global}@anchor{148}
+@anchor{gnat_rm/implementation_defined_aspects aspect-refined-global}@anchor{149}
@section Aspect Refined_Global
@@ -9914,7 +9933,7 @@ This aspect is equivalent to @ref{ce,,pragma Refined_Depends}.
This aspect is equivalent to @ref{d0,,pragma Refined_Global}.
@node Aspect Refined_Post,Aspect Refined_State,Aspect Refined_Global,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-refined-post}@anchor{149}
+@anchor{gnat_rm/implementation_defined_aspects aspect-refined-post}@anchor{14a}
@section Aspect Refined_Post
@@ -9923,7 +9942,7 @@ This aspect is equivalent to @ref{d0,,pragma Refined_Global}.
This aspect is equivalent to @ref{d2,,pragma Refined_Post}.
@node Aspect Refined_State,Aspect Relaxed_Initialization,Aspect Refined_Post,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-refined-state}@anchor{14a}
+@anchor{gnat_rm/implementation_defined_aspects aspect-refined-state}@anchor{14b}
@section Aspect Refined_State
@@ -9932,7 +9951,7 @@ This aspect is equivalent to @ref{d2,,pragma Refined_Post}.
This aspect is equivalent to @ref{d4,,pragma Refined_State}.
@node Aspect Relaxed_Initialization,Aspect Remote_Access_Type,Aspect Refined_State,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-relaxed-initialization}@anchor{14b}
+@anchor{gnat_rm/implementation_defined_aspects aspect-relaxed-initialization}@anchor{14c}
@section Aspect Relaxed_Initialization
@@ -9942,7 +9961,7 @@ For the syntax and semantics of this aspect, see the SPARK 2014 Reference
Manual, section 6.10.
@node Aspect Remote_Access_Type,Aspect Secondary_Stack_Size,Aspect Relaxed_Initialization,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-remote-access-type}@anchor{14c}
+@anchor{gnat_rm/implementation_defined_aspects aspect-remote-access-type}@anchor{14d}
@section Aspect Remote_Access_Type
@@ -9951,178 +9970,178 @@ Manual, section 6.10.
This aspect is equivalent to @ref{d7,,pragma Remote_Access_Type}.
@node Aspect Secondary_Stack_Size,Aspect Scalar_Storage_Order,Aspect Remote_Access_Type,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-secondary-stack-size}@anchor{14d}
+@anchor{gnat_rm/implementation_defined_aspects aspect-secondary-stack-size}@anchor{14e}
@section Aspect Secondary_Stack_Size
@geindex Secondary_Stack_Size
-This aspect is equivalent to @ref{dc,,pragma Secondary_Stack_Size}.
+This aspect is equivalent to @ref{dd,,pragma Secondary_Stack_Size}.
@node Aspect Scalar_Storage_Order,Aspect Shared,Aspect Secondary_Stack_Size,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-scalar-storage-order}@anchor{14e}
+@anchor{gnat_rm/implementation_defined_aspects aspect-scalar-storage-order}@anchor{14f}
@section Aspect Scalar_Storage_Order
@geindex Scalar_Storage_Order
-This aspect is equivalent to a @ref{14f,,attribute Scalar_Storage_Order}.
+This aspect is equivalent to a @ref{150,,attribute Scalar_Storage_Order}.
@node Aspect Shared,Aspect Simple_Storage_Pool,Aspect Scalar_Storage_Order,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-shared}@anchor{150}
+@anchor{gnat_rm/implementation_defined_aspects aspect-shared}@anchor{151}
@section Aspect Shared
@geindex Shared
-This boolean aspect is equivalent to @ref{df,,pragma Shared}
+This boolean aspect is equivalent to @ref{e0,,pragma Shared}
and is thus a synonym for aspect @code{Atomic}.
@node Aspect Simple_Storage_Pool,Aspect Simple_Storage_Pool_Type,Aspect Shared,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-simple-storage-pool}@anchor{151}
+@anchor{gnat_rm/implementation_defined_aspects aspect-simple-storage-pool}@anchor{152}
@section Aspect Simple_Storage_Pool
@geindex Simple_Storage_Pool
-This aspect is equivalent to @ref{e4,,attribute Simple_Storage_Pool}.
+This aspect is equivalent to @ref{e5,,attribute Simple_Storage_Pool}.
@node Aspect Simple_Storage_Pool_Type,Aspect SPARK_Mode,Aspect Simple_Storage_Pool,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-simple-storage-pool-type}@anchor{152}
+@anchor{gnat_rm/implementation_defined_aspects aspect-simple-storage-pool-type}@anchor{153}
@section Aspect Simple_Storage_Pool_Type
@geindex Simple_Storage_Pool_Type
-This boolean aspect is equivalent to @ref{e3,,pragma Simple_Storage_Pool_Type}.
+This boolean aspect is equivalent to @ref{e4,,pragma Simple_Storage_Pool_Type}.
@node Aspect SPARK_Mode,Aspect Suppress_Debug_Info,Aspect Simple_Storage_Pool_Type,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-spark-mode}@anchor{153}
+@anchor{gnat_rm/implementation_defined_aspects aspect-spark-mode}@anchor{154}
@section Aspect SPARK_Mode
@geindex SPARK_Mode
-This aspect is equivalent to @ref{eb,,pragma SPARK_Mode} and
+This aspect is equivalent to @ref{ec,,pragma SPARK_Mode} and
may be specified for either or both of the specification and body
of a subprogram or package.
@node Aspect Suppress_Debug_Info,Aspect Suppress_Initialization,Aspect SPARK_Mode,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-suppress-debug-info}@anchor{154}
+@anchor{gnat_rm/implementation_defined_aspects aspect-suppress-debug-info}@anchor{155}
@section Aspect Suppress_Debug_Info
@geindex Suppress_Debug_Info
-This boolean aspect is equivalent to @ref{f3,,pragma Suppress_Debug_Info}.
+This boolean aspect is equivalent to @ref{f4,,pragma Suppress_Debug_Info}.
@node Aspect Suppress_Initialization,Aspect Test_Case,Aspect Suppress_Debug_Info,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-suppress-initialization}@anchor{155}
+@anchor{gnat_rm/implementation_defined_aspects aspect-suppress-initialization}@anchor{156}
@section Aspect Suppress_Initialization
@geindex Suppress_Initialization
-This boolean aspect is equivalent to @ref{f6,,pragma Suppress_Initialization}.
+This boolean aspect is equivalent to @ref{f7,,pragma Suppress_Initialization}.
@node Aspect Test_Case,Aspect Thread_Local_Storage,Aspect Suppress_Initialization,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-test-case}@anchor{156}
+@anchor{gnat_rm/implementation_defined_aspects aspect-test-case}@anchor{157}
@section Aspect Test_Case
@geindex Test_Case
-This aspect is equivalent to @ref{fa,,pragma Test_Case}.
+This aspect is equivalent to @ref{fb,,pragma Test_Case}.
@node Aspect Thread_Local_Storage,Aspect Universal_Aliasing,Aspect Test_Case,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-thread-local-storage}@anchor{157}
+@anchor{gnat_rm/implementation_defined_aspects aspect-thread-local-storage}@anchor{158}
@section Aspect Thread_Local_Storage
@geindex Thread_Local_Storage
-This boolean aspect is equivalent to @ref{fc,,pragma Thread_Local_Storage}.
+This boolean aspect is equivalent to @ref{fd,,pragma Thread_Local_Storage}.
@node Aspect Universal_Aliasing,Aspect Unmodified,Aspect Thread_Local_Storage,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-universal-aliasing}@anchor{158}
+@anchor{gnat_rm/implementation_defined_aspects aspect-universal-aliasing}@anchor{159}
@section Aspect Universal_Aliasing
@geindex Universal_Aliasing
-This boolean aspect is equivalent to @ref{106,,pragma Universal_Aliasing}.
+This boolean aspect is equivalent to @ref{107,,pragma Universal_Aliasing}.
@node Aspect Unmodified,Aspect Unreferenced,Aspect Universal_Aliasing,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-unmodified}@anchor{159}
+@anchor{gnat_rm/implementation_defined_aspects aspect-unmodified}@anchor{15a}
@section Aspect Unmodified
@geindex Unmodified
-This boolean aspect is equivalent to @ref{108,,pragma Unmodified}.
+This boolean aspect is equivalent to @ref{109,,pragma Unmodified}.
@node Aspect Unreferenced,Aspect Unreferenced_Objects,Aspect Unmodified,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-unreferenced}@anchor{15a}
+@anchor{gnat_rm/implementation_defined_aspects aspect-unreferenced}@anchor{15b}
@section Aspect Unreferenced
@geindex Unreferenced
-This boolean aspect is equivalent to @ref{10a,,pragma Unreferenced}.
+This boolean aspect is equivalent to @ref{10b,,pragma Unreferenced}.
When using the @code{-gnat2022} switch, this aspect is also supported on formal
parameters, which is in particular the only form possible for expression
functions.
@node Aspect Unreferenced_Objects,Aspect Value_Size,Aspect Unreferenced,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-unreferenced-objects}@anchor{15b}
+@anchor{gnat_rm/implementation_defined_aspects aspect-unreferenced-objects}@anchor{15c}
@section Aspect Unreferenced_Objects
@geindex Unreferenced_Objects
-This boolean aspect is equivalent to @ref{10c,,pragma Unreferenced_Objects}.
+This boolean aspect is equivalent to @ref{10d,,pragma Unreferenced_Objects}.
@node Aspect Value_Size,Aspect Volatile_Full_Access,Aspect Unreferenced_Objects,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-value-size}@anchor{15c}
+@anchor{gnat_rm/implementation_defined_aspects aspect-value-size}@anchor{15d}
@section Aspect Value_Size
@geindex Value_Size
-This aspect is equivalent to @ref{15d,,attribute Value_Size}.
+This aspect is equivalent to @ref{15e,,attribute Value_Size}.
@node Aspect Volatile_Full_Access,Aspect Volatile_Function,Aspect Value_Size,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-volatile-full-access}@anchor{15e}
+@anchor{gnat_rm/implementation_defined_aspects aspect-volatile-full-access}@anchor{15f}
@section Aspect Volatile_Full_Access
@geindex Volatile_Full_Access
-This boolean aspect is equivalent to @ref{116,,pragma Volatile_Full_Access}.
+This boolean aspect is equivalent to @ref{117,,pragma Volatile_Full_Access}.
@node Aspect Volatile_Function,Aspect Warnings,Aspect Volatile_Full_Access,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-volatile-function}@anchor{15f}
+@anchor{gnat_rm/implementation_defined_aspects aspect-volatile-function}@anchor{160}
@section Aspect Volatile_Function
@geindex Volatile_Function
-This boolean aspect is equivalent to @ref{118,,pragma Volatile_Function}.
+This boolean aspect is equivalent to @ref{119,,pragma Volatile_Function}.
@node Aspect Warnings,,Aspect Volatile_Function,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-warnings}@anchor{160}
+@anchor{gnat_rm/implementation_defined_aspects aspect-warnings}@anchor{161}
@section Aspect Warnings
@geindex Warnings
-This aspect is equivalent to the two argument form of @ref{11a,,pragma Warnings},
+This aspect is equivalent to the two argument form of @ref{11b,,pragma Warnings},
where the first argument is @code{ON} or @code{OFF} and the second argument
is the entity.
@node Implementation Defined Attributes,Standard and Implementation Defined Restrictions,Implementation Defined Aspects,Top
-@anchor{gnat_rm/implementation_defined_attributes doc}@anchor{161}@anchor{gnat_rm/implementation_defined_attributes id1}@anchor{162}@anchor{gnat_rm/implementation_defined_attributes implementation-defined-attributes}@anchor{8}
+@anchor{gnat_rm/implementation_defined_attributes doc}@anchor{162}@anchor{gnat_rm/implementation_defined_attributes id1}@anchor{163}@anchor{gnat_rm/implementation_defined_attributes implementation-defined-attributes}@anchor{8}
@chapter Implementation Defined Attributes
@@ -10229,7 +10248,7 @@ consideration, you should minimize the use of these attributes.
@end menu
@node Attribute Abort_Signal,Attribute Address_Size,,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-abort-signal}@anchor{163}
+@anchor{gnat_rm/implementation_defined_attributes attribute-abort-signal}@anchor{164}
@section Attribute Abort_Signal
@@ -10243,7 +10262,7 @@ completely outside the normal semantics of Ada, for a user program to
intercept the abort exception).
@node Attribute Address_Size,Attribute Asm_Input,Attribute Abort_Signal,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-address-size}@anchor{164}
+@anchor{gnat_rm/implementation_defined_attributes attribute-address-size}@anchor{165}
@section Attribute Address_Size
@@ -10259,7 +10278,7 @@ reference to System.Address’Size is nonstatic because Address
is a private type.
@node Attribute Asm_Input,Attribute Asm_Output,Attribute Address_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-asm-input}@anchor{165}
+@anchor{gnat_rm/implementation_defined_attributes attribute-asm-input}@anchor{166}
@section Attribute Asm_Input
@@ -10273,10 +10292,10 @@ to be a static expression, and is the constraint for the parameter,
value to be used as the input argument. The possible values for the
constant are the same as those used in the RTL, and are dependent on
the configuration file used to built the GCC back end.
-@ref{166,,Machine Code Insertions}
+@ref{167,,Machine Code Insertions}
@node Attribute Asm_Output,Attribute Atomic_Always_Lock_Free,Attribute Asm_Input,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-asm-output}@anchor{167}
+@anchor{gnat_rm/implementation_defined_attributes attribute-asm-output}@anchor{168}
@section Attribute Asm_Output
@@ -10292,10 +10311,10 @@ result. The possible values for constraint are the same as those used in
the RTL, and are dependent on the configuration file used to build the
GCC back end. If there are no output operands, then this argument may
either be omitted, or explicitly given as @code{No_Output_Operands}.
-@ref{166,,Machine Code Insertions}
+@ref{167,,Machine Code Insertions}
@node Attribute Atomic_Always_Lock_Free,Attribute Bit,Attribute Asm_Output,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-atomic-always-lock-free}@anchor{168}
+@anchor{gnat_rm/implementation_defined_attributes attribute-atomic-always-lock-free}@anchor{169}
@section Attribute Atomic_Always_Lock_Free
@@ -10307,7 +10326,7 @@ and False otherwise. The result indicate whether atomic operations are
supported by the target for the given type.
@node Attribute Bit,Attribute Bit_Position,Attribute Atomic_Always_Lock_Free,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-bit}@anchor{169}
+@anchor{gnat_rm/implementation_defined_attributes attribute-bit}@anchor{16a}
@section Attribute Bit
@@ -10338,7 +10357,7 @@ This attribute is designed to be compatible with the DEC Ada 83 definition
and implementation of the @code{Bit} attribute.
@node Attribute Bit_Position,Attribute Code_Address,Attribute Bit,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-bit-position}@anchor{16a}
+@anchor{gnat_rm/implementation_defined_attributes attribute-bit-position}@anchor{16b}
@section Attribute Bit_Position
@@ -10353,7 +10372,7 @@ type @emph{universal_integer}. The value depends only on the field
the containing record @code{R}.
@node Attribute Code_Address,Attribute Compiler_Version,Attribute Bit_Position,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-code-address}@anchor{16b}
+@anchor{gnat_rm/implementation_defined_attributes attribute-code-address}@anchor{16c}
@section Attribute Code_Address
@@ -10396,7 +10415,7 @@ the same value as is returned by the corresponding @code{'Address}
attribute.
@node Attribute Compiler_Version,Attribute Constrained,Attribute Code_Address,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-compiler-version}@anchor{16c}
+@anchor{gnat_rm/implementation_defined_attributes attribute-compiler-version}@anchor{16d}
@section Attribute Compiler_Version
@@ -10407,7 +10426,7 @@ prefix) yields a static string identifying the version of the compiler
being used to compile the unit containing the attribute reference.
@node Attribute Constrained,Attribute Default_Bit_Order,Attribute Compiler_Version,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-constrained}@anchor{16d}
+@anchor{gnat_rm/implementation_defined_attributes attribute-constrained}@anchor{16e}
@section Attribute Constrained
@@ -10422,7 +10441,7 @@ record type without discriminants is always @code{True}. This usage is
compatible with older Ada compilers, including notably DEC Ada.
@node Attribute Default_Bit_Order,Attribute Default_Scalar_Storage_Order,Attribute Constrained,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-default-bit-order}@anchor{16e}
+@anchor{gnat_rm/implementation_defined_attributes attribute-default-bit-order}@anchor{16f}
@section Attribute Default_Bit_Order
@@ -10439,7 +10458,7 @@ as a @code{Pos} value (0 for @code{High_Order_First}, 1 for
@code{Default_Bit_Order} in package @code{System}.
@node Attribute Default_Scalar_Storage_Order,Attribute Deref,Attribute Default_Bit_Order,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-default-scalar-storage-order}@anchor{16f}
+@anchor{gnat_rm/implementation_defined_attributes attribute-default-scalar-storage-order}@anchor{170}
@section Attribute Default_Scalar_Storage_Order
@@ -10456,7 +10475,7 @@ equal to @code{Default_Bit_Order} if unspecified) as a
@code{System.Bit_Order} value. This is a static attribute.
@node Attribute Deref,Attribute Descriptor_Size,Attribute Default_Scalar_Storage_Order,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-deref}@anchor{170}
+@anchor{gnat_rm/implementation_defined_attributes attribute-deref}@anchor{171}
@section Attribute Deref
@@ -10469,7 +10488,7 @@ a named access-to-@cite{typ} type, except that it yields a variable, so it can b
used on the left side of an assignment.
@node Attribute Descriptor_Size,Attribute Elaborated,Attribute Deref,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-descriptor-size}@anchor{171}
+@anchor{gnat_rm/implementation_defined_attributes attribute-descriptor-size}@anchor{172}
@section Attribute Descriptor_Size
@@ -10498,7 +10517,7 @@ since @code{Positive} has an alignment of 4, the size of the descriptor is
which yields a size of 32 bits, i.e. including 16 bits of padding.
@node Attribute Elaborated,Attribute Elab_Body,Attribute Descriptor_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-elaborated}@anchor{172}
+@anchor{gnat_rm/implementation_defined_attributes attribute-elaborated}@anchor{173}
@section Attribute Elaborated
@@ -10513,7 +10532,7 @@ units has been completed. An exception is for units which need no
elaboration, the value is always False for such units.
@node Attribute Elab_Body,Attribute Elab_Spec,Attribute Elaborated,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-elab-body}@anchor{173}
+@anchor{gnat_rm/implementation_defined_attributes attribute-elab-body}@anchor{174}
@section Attribute Elab_Body
@@ -10529,7 +10548,7 @@ e.g., if it is necessary to do selective re-elaboration to fix some
error.
@node Attribute Elab_Spec,Attribute Elab_Subp_Body,Attribute Elab_Body,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-elab-spec}@anchor{174}
+@anchor{gnat_rm/implementation_defined_attributes attribute-elab-spec}@anchor{175}
@section Attribute Elab_Spec
@@ -10545,7 +10564,7 @@ Ada code, e.g., if it is necessary to do selective re-elaboration to fix
some error.
@node Attribute Elab_Subp_Body,Attribute Emax,Attribute Elab_Spec,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-elab-subp-body}@anchor{175}
+@anchor{gnat_rm/implementation_defined_attributes attribute-elab-subp-body}@anchor{176}
@section Attribute Elab_Subp_Body
@@ -10559,7 +10578,7 @@ elaboration procedure by the binder in CodePeer mode only and is unrecognized
otherwise.
@node Attribute Emax,Attribute Enabled,Attribute Elab_Subp_Body,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-emax}@anchor{176}
+@anchor{gnat_rm/implementation_defined_attributes attribute-emax}@anchor{177}
@section Attribute Emax
@@ -10572,7 +10591,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute.
@node Attribute Enabled,Attribute Enum_Rep,Attribute Emax,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-enabled}@anchor{177}
+@anchor{gnat_rm/implementation_defined_attributes attribute-enabled}@anchor{178}
@section Attribute Enabled
@@ -10596,7 +10615,7 @@ a @code{pragma Suppress} or @code{pragma Unsuppress} before instantiating
the package or subprogram, controlling whether the check will be present.
@node Attribute Enum_Rep,Attribute Enum_Val,Attribute Enabled,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-enum-rep}@anchor{178}
+@anchor{gnat_rm/implementation_defined_attributes attribute-enum-rep}@anchor{179}
@section Attribute Enum_Rep
@@ -10636,7 +10655,7 @@ integer calculation is done at run time, then the call to @code{Enum_Rep}
may raise @code{Constraint_Error}.
@node Attribute Enum_Val,Attribute Epsilon,Attribute Enum_Rep,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-enum-val}@anchor{179}
+@anchor{gnat_rm/implementation_defined_attributes attribute-enum-val}@anchor{17a}
@section Attribute Enum_Val
@@ -10662,7 +10681,7 @@ absence of an enumeration representation clause. This is a static
attribute (i.e., the result is static if the argument is static).
@node Attribute Epsilon,Attribute Fast_Math,Attribute Enum_Val,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-epsilon}@anchor{17a}
+@anchor{gnat_rm/implementation_defined_attributes attribute-epsilon}@anchor{17b}
@section Attribute Epsilon
@@ -10675,7 +10694,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute.
@node Attribute Fast_Math,Attribute Finalization_Size,Attribute Epsilon,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-fast-math}@anchor{17b}
+@anchor{gnat_rm/implementation_defined_attributes attribute-fast-math}@anchor{17c}
@section Attribute Fast_Math
@@ -10686,7 +10705,7 @@ prefix) yields a static Boolean value that is True if pragma
@code{Fast_Math} is active, and False otherwise.
@node Attribute Finalization_Size,Attribute Fixed_Value,Attribute Fast_Math,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-finalization-size}@anchor{17c}
+@anchor{gnat_rm/implementation_defined_attributes attribute-finalization-size}@anchor{17d}
@section Attribute Finalization_Size
@@ -10704,7 +10723,7 @@ class-wide type whose tag denotes a type with no controlled parts.
Note that only heap-allocated objects contain finalization data.
@node Attribute Fixed_Value,Attribute From_Any,Attribute Finalization_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-fixed-value}@anchor{17d}
+@anchor{gnat_rm/implementation_defined_attributes attribute-fixed-value}@anchor{17e}
@section Attribute Fixed_Value
@@ -10731,7 +10750,7 @@ This attribute is primarily intended for use in implementation of the
input-output functions for fixed-point values.
@node Attribute From_Any,Attribute Has_Access_Values,Attribute Fixed_Value,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-from-any}@anchor{17e}
+@anchor{gnat_rm/implementation_defined_attributes attribute-from-any}@anchor{17f}
@section Attribute From_Any
@@ -10741,7 +10760,7 @@ This internal attribute is used for the generation of remote subprogram
stubs in the context of the Distributed Systems Annex.
@node Attribute Has_Access_Values,Attribute Has_Discriminants,Attribute From_Any,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-has-access-values}@anchor{17f}
+@anchor{gnat_rm/implementation_defined_attributes attribute-has-access-values}@anchor{180}
@section Attribute Has_Access_Values
@@ -10759,7 +10778,7 @@ definitions. If the attribute is applied to a generic private type, it
indicates whether or not the corresponding actual type has access values.
@node Attribute Has_Discriminants,Attribute Has_Tagged_Values,Attribute Has_Access_Values,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-has-discriminants}@anchor{180}
+@anchor{gnat_rm/implementation_defined_attributes attribute-has-discriminants}@anchor{181}
@section Attribute Has_Discriminants
@@ -10775,7 +10794,7 @@ definitions. If the attribute is applied to a generic private type, it
indicates whether or not the corresponding actual type has discriminants.
@node Attribute Has_Tagged_Values,Attribute Img,Attribute Has_Discriminants,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-has-tagged-values}@anchor{181}
+@anchor{gnat_rm/implementation_defined_attributes attribute-has-tagged-values}@anchor{182}
@section Attribute Has_Tagged_Values
@@ -10792,7 +10811,7 @@ definitions. If the attribute is applied to a generic private type, it
indicates whether or not the corresponding actual type has access values.
@node Attribute Img,Attribute Initialized,Attribute Has_Tagged_Values,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-img}@anchor{182}
+@anchor{gnat_rm/implementation_defined_attributes attribute-img}@anchor{183}
@section Attribute Img
@@ -10822,7 +10841,7 @@ that returns the appropriate string when called. This means that
in an instantiation as a function parameter.
@node Attribute Initialized,Attribute Integer_Value,Attribute Img,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-initialized}@anchor{183}
+@anchor{gnat_rm/implementation_defined_attributes attribute-initialized}@anchor{184}
@section Attribute Initialized
@@ -10832,7 +10851,7 @@ For the syntax and semantics of this attribute, see the SPARK 2014 Reference
Manual, section 6.10.
@node Attribute Integer_Value,Attribute Invalid_Value,Attribute Initialized,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-integer-value}@anchor{184}
+@anchor{gnat_rm/implementation_defined_attributes attribute-integer-value}@anchor{185}
@section Attribute Integer_Value
@@ -10860,7 +10879,7 @@ This attribute is primarily intended for use in implementation of the
standard input-output functions for fixed-point values.
@node Attribute Invalid_Value,Attribute Iterable,Attribute Integer_Value,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-invalid-value}@anchor{185}
+@anchor{gnat_rm/implementation_defined_attributes attribute-invalid-value}@anchor{186}
@section Attribute Invalid_Value
@@ -10874,7 +10893,7 @@ including the ability to modify the value with the binder -Sxx flag and
relevant environment variables at run time.
@node Attribute Iterable,Attribute Large,Attribute Invalid_Value,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-iterable}@anchor{186}
+@anchor{gnat_rm/implementation_defined_attributes attribute-iterable}@anchor{187}
@section Attribute Iterable
@@ -10883,7 +10902,7 @@ relevant environment variables at run time.
Equivalent to Aspect Iterable.
@node Attribute Large,Attribute Library_Level,Attribute Iterable,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-large}@anchor{187}
+@anchor{gnat_rm/implementation_defined_attributes attribute-large}@anchor{188}
@section Attribute Large
@@ -10896,7 +10915,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute.
@node Attribute Library_Level,Attribute Lock_Free,Attribute Large,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-library-level}@anchor{188}
+@anchor{gnat_rm/implementation_defined_attributes attribute-library-level}@anchor{189}
@section Attribute Library_Level
@@ -10922,7 +10941,7 @@ end Gen;
@end example
@node Attribute Lock_Free,Attribute Loop_Entry,Attribute Library_Level,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-lock-free}@anchor{189}
+@anchor{gnat_rm/implementation_defined_attributes attribute-lock-free}@anchor{18a}
@section Attribute Lock_Free
@@ -10932,7 +10951,7 @@ end Gen;
pragma @code{Lock_Free} applies to P.
@node Attribute Loop_Entry,Attribute Machine_Size,Attribute Lock_Free,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-loop-entry}@anchor{18a}
+@anchor{gnat_rm/implementation_defined_attributes attribute-loop-entry}@anchor{18b}
@section Attribute Loop_Entry
@@ -10962,7 +10981,7 @@ entry. This copy is not performed if the loop is not entered, or if the
corresponding pragmas are ignored or disabled.
@node Attribute Machine_Size,Attribute Mantissa,Attribute Loop_Entry,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-machine-size}@anchor{18b}
+@anchor{gnat_rm/implementation_defined_attributes attribute-machine-size}@anchor{18c}
@section Attribute Machine_Size
@@ -10972,7 +10991,7 @@ This attribute is identical to the @code{Object_Size} attribute. It is
provided for compatibility with the DEC Ada 83 attribute of this name.
@node Attribute Mantissa,Attribute Maximum_Alignment,Attribute Machine_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-mantissa}@anchor{18c}
+@anchor{gnat_rm/implementation_defined_attributes attribute-mantissa}@anchor{18d}
@section Attribute Mantissa
@@ -10985,7 +11004,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute.
@node Attribute Maximum_Alignment,Attribute Max_Integer_Size,Attribute Mantissa,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-maximum-alignment}@anchor{18d}@anchor{gnat_rm/implementation_defined_attributes id2}@anchor{18e}
+@anchor{gnat_rm/implementation_defined_attributes attribute-maximum-alignment}@anchor{18e}@anchor{gnat_rm/implementation_defined_attributes id2}@anchor{18f}
@section Attribute Maximum_Alignment
@@ -11001,7 +11020,7 @@ for an object, guaranteeing that it is properly aligned in all
cases.
@node Attribute Max_Integer_Size,Attribute Mechanism_Code,Attribute Maximum_Alignment,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-max-integer-size}@anchor{18f}
+@anchor{gnat_rm/implementation_defined_attributes attribute-max-integer-size}@anchor{190}
@section Attribute Max_Integer_Size
@@ -11012,7 +11031,7 @@ prefix) provides the size of the largest supported integer type for
the target. The result is a static constant.
@node Attribute Mechanism_Code,Attribute Null_Parameter,Attribute Max_Integer_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-mechanism-code}@anchor{190}
+@anchor{gnat_rm/implementation_defined_attributes attribute-mechanism-code}@anchor{191}
@section Attribute Mechanism_Code
@@ -11043,7 +11062,7 @@ by reference
@end table
@node Attribute Null_Parameter,Attribute Object_Size,Attribute Mechanism_Code,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-null-parameter}@anchor{191}
+@anchor{gnat_rm/implementation_defined_attributes attribute-null-parameter}@anchor{192}
@section Attribute Null_Parameter
@@ -11068,7 +11087,7 @@ There is no way of indicating this without the @code{Null_Parameter}
attribute.
@node Attribute Object_Size,Attribute Old,Attribute Null_Parameter,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-object-size}@anchor{141}@anchor{gnat_rm/implementation_defined_attributes id3}@anchor{192}
+@anchor{gnat_rm/implementation_defined_attributes attribute-object-size}@anchor{142}@anchor{gnat_rm/implementation_defined_attributes id3}@anchor{193}
@section Attribute Object_Size
@@ -11138,7 +11157,7 @@ Similar additional checks are performed in other contexts requiring
statically matching subtypes.
@node Attribute Old,Attribute Passed_By_Reference,Attribute Object_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-old}@anchor{193}
+@anchor{gnat_rm/implementation_defined_attributes attribute-old}@anchor{194}
@section Attribute Old
@@ -11153,7 +11172,7 @@ definition are allowed under control of
implementation defined pragma @code{Unevaluated_Use_Of_Old}.
@node Attribute Passed_By_Reference,Attribute Pool_Address,Attribute Old,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-passed-by-reference}@anchor{194}
+@anchor{gnat_rm/implementation_defined_attributes attribute-passed-by-reference}@anchor{195}
@section Attribute Passed_By_Reference
@@ -11169,7 +11188,7 @@ passed by copy in calls. For scalar types, the result is always @code{False}
and is static. For non-scalar types, the result is nonstatic.
@node Attribute Pool_Address,Attribute Range_Length,Attribute Passed_By_Reference,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-pool-address}@anchor{195}
+@anchor{gnat_rm/implementation_defined_attributes attribute-pool-address}@anchor{196}
@section Attribute Pool_Address
@@ -11191,7 +11210,7 @@ For an object created by @code{new}, @code{Ptr.all'Pool_Address} is
what is passed to @code{Allocate} and returned from @code{Deallocate}.
@node Attribute Range_Length,Attribute Restriction_Set,Attribute Pool_Address,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-range-length}@anchor{196}
+@anchor{gnat_rm/implementation_defined_attributes attribute-range-length}@anchor{197}
@section Attribute Range_Length
@@ -11204,7 +11223,7 @@ applied to the index subtype of a one dimensional array always gives the
same result as @code{Length} applied to the array itself.
@node Attribute Restriction_Set,Attribute Result,Attribute Range_Length,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-restriction-set}@anchor{197}
+@anchor{gnat_rm/implementation_defined_attributes attribute-restriction-set}@anchor{198}
@section Attribute Restriction_Set
@@ -11274,7 +11293,7 @@ Restrictions pragma, they are not analyzed semantically,
so they do not have a type.
@node Attribute Result,Attribute Safe_Emax,Attribute Restriction_Set,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-result}@anchor{198}
+@anchor{gnat_rm/implementation_defined_attributes attribute-result}@anchor{199}
@section Attribute Result
@@ -11287,7 +11306,7 @@ For a further discussion of the use of this attribute and examples of its use,
see the description of pragma Postcondition.
@node Attribute Safe_Emax,Attribute Safe_Large,Attribute Result,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-safe-emax}@anchor{199}
+@anchor{gnat_rm/implementation_defined_attributes attribute-safe-emax}@anchor{19a}
@section Attribute Safe_Emax
@@ -11300,7 +11319,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute.
@node Attribute Safe_Large,Attribute Safe_Small,Attribute Safe_Emax,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-safe-large}@anchor{19a}
+@anchor{gnat_rm/implementation_defined_attributes attribute-safe-large}@anchor{19b}
@section Attribute Safe_Large
@@ -11313,7 +11332,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute.
@node Attribute Safe_Small,Attribute Scalar_Storage_Order,Attribute Safe_Large,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-safe-small}@anchor{19b}
+@anchor{gnat_rm/implementation_defined_attributes attribute-safe-small}@anchor{19c}
@section Attribute Safe_Small
@@ -11326,7 +11345,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute.
@node Attribute Scalar_Storage_Order,Attribute Simple_Storage_Pool,Attribute Safe_Small,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-scalar-storage-order}@anchor{14f}@anchor{gnat_rm/implementation_defined_attributes id4}@anchor{19c}
+@anchor{gnat_rm/implementation_defined_attributes attribute-scalar-storage-order}@anchor{150}@anchor{gnat_rm/implementation_defined_attributes id4}@anchor{19d}
@section Attribute Scalar_Storage_Order
@@ -11489,7 +11508,7 @@ Note that debuggers may be unable to display the correct value of scalar
components of a type for which the opposite storage order is specified.
@node Attribute Simple_Storage_Pool,Attribute Small,Attribute Scalar_Storage_Order,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-simple-storage-pool}@anchor{e4}@anchor{gnat_rm/implementation_defined_attributes id5}@anchor{19d}
+@anchor{gnat_rm/implementation_defined_attributes attribute-simple-storage-pool}@anchor{e5}@anchor{gnat_rm/implementation_defined_attributes id5}@anchor{19e}
@section Attribute Simple_Storage_Pool
@@ -11552,7 +11571,7 @@ as defined in section 13.11.2 of the Ada Reference Manual, except that the
term @emph{simple storage pool} is substituted for @emph{storage pool}.
@node Attribute Small,Attribute Small_Denominator,Attribute Simple_Storage_Pool,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-small}@anchor{19e}
+@anchor{gnat_rm/implementation_defined_attributes attribute-small}@anchor{19f}
@section Attribute Small
@@ -11568,7 +11587,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute when applied to floating-point types.
@node Attribute Small_Denominator,Attribute Small_Numerator,Attribute Small,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-small-denominator}@anchor{19f}
+@anchor{gnat_rm/implementation_defined_attributes attribute-small-denominator}@anchor{1a0}
@section Attribute Small_Denominator
@@ -11581,7 +11600,7 @@ denominator in the representation of @code{typ'Small} as a rational number
with coprime factors (i.e. as an irreducible fraction).
@node Attribute Small_Numerator,Attribute Storage_Unit,Attribute Small_Denominator,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-small-numerator}@anchor{1a0}
+@anchor{gnat_rm/implementation_defined_attributes attribute-small-numerator}@anchor{1a1}
@section Attribute Small_Numerator
@@ -11594,7 +11613,7 @@ numerator in the representation of @code{typ'Small} as a rational number
with coprime factors (i.e. as an irreducible fraction).
@node Attribute Storage_Unit,Attribute Stub_Type,Attribute Small_Numerator,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-storage-unit}@anchor{1a1}
+@anchor{gnat_rm/implementation_defined_attributes attribute-storage-unit}@anchor{1a2}
@section Attribute Storage_Unit
@@ -11604,7 +11623,7 @@ with coprime factors (i.e. as an irreducible fraction).
prefix) provides the same value as @code{System.Storage_Unit}.
@node Attribute Stub_Type,Attribute System_Allocator_Alignment,Attribute Storage_Unit,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-stub-type}@anchor{1a2}
+@anchor{gnat_rm/implementation_defined_attributes attribute-stub-type}@anchor{1a3}
@section Attribute Stub_Type
@@ -11628,7 +11647,7 @@ unit @code{System.Partition_Interface}. Use of this attribute will create
an implicit dependency on this unit.
@node Attribute System_Allocator_Alignment,Attribute Target_Name,Attribute Stub_Type,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-system-allocator-alignment}@anchor{1a3}
+@anchor{gnat_rm/implementation_defined_attributes attribute-system-allocator-alignment}@anchor{1a4}
@section Attribute System_Allocator_Alignment
@@ -11645,7 +11664,7 @@ with alignment too large or to enable a realignment circuitry if the
alignment request is larger than this value.
@node Attribute Target_Name,Attribute To_Address,Attribute System_Allocator_Alignment,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-target-name}@anchor{1a4}
+@anchor{gnat_rm/implementation_defined_attributes attribute-target-name}@anchor{1a5}
@section Attribute Target_Name
@@ -11658,7 +11677,7 @@ standard gcc target name without the terminating slash (for
example, GNAT 5.0 on windows yields “i586-pc-mingw32msv”).
@node Attribute To_Address,Attribute To_Any,Attribute Target_Name,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-to-address}@anchor{1a5}
+@anchor{gnat_rm/implementation_defined_attributes attribute-to-address}@anchor{1a6}
@section Attribute To_Address
@@ -11681,7 +11700,7 @@ modular manner (e.g., -1 means the same as 16#FFFF_FFFF# on
a 32 bits machine).
@node Attribute To_Any,Attribute Type_Class,Attribute To_Address,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-to-any}@anchor{1a6}
+@anchor{gnat_rm/implementation_defined_attributes attribute-to-any}@anchor{1a7}
@section Attribute To_Any
@@ -11691,7 +11710,7 @@ This internal attribute is used for the generation of remote subprogram
stubs in the context of the Distributed Systems Annex.
@node Attribute Type_Class,Attribute Type_Key,Attribute To_Any,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-type-class}@anchor{1a7}
+@anchor{gnat_rm/implementation_defined_attributes attribute-type-class}@anchor{1a8}
@section Attribute Type_Class
@@ -11721,7 +11740,7 @@ applies to all concurrent types. This attribute is designed to
be compatible with the DEC Ada 83 attribute of the same name.
@node Attribute Type_Key,Attribute TypeCode,Attribute Type_Class,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-type-key}@anchor{1a8}
+@anchor{gnat_rm/implementation_defined_attributes attribute-type-key}@anchor{1a9}
@section Attribute Type_Key
@@ -11733,7 +11752,7 @@ about the type or subtype. This provides improved compatibility with
other implementations that support this attribute.
@node Attribute TypeCode,Attribute Unconstrained_Array,Attribute Type_Key,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-typecode}@anchor{1a9}
+@anchor{gnat_rm/implementation_defined_attributes attribute-typecode}@anchor{1aa}
@section Attribute TypeCode
@@ -11743,7 +11762,7 @@ This internal attribute is used for the generation of remote subprogram
stubs in the context of the Distributed Systems Annex.
@node Attribute Unconstrained_Array,Attribute Universal_Literal_String,Attribute TypeCode,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-unconstrained-array}@anchor{1aa}
+@anchor{gnat_rm/implementation_defined_attributes attribute-unconstrained-array}@anchor{1ab}
@section Attribute Unconstrained_Array
@@ -11757,7 +11776,7 @@ still static, and yields the result of applying this test to the
generic actual.
@node Attribute Universal_Literal_String,Attribute Unrestricted_Access,Attribute Unconstrained_Array,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-universal-literal-string}@anchor{1ab}
+@anchor{gnat_rm/implementation_defined_attributes attribute-universal-literal-string}@anchor{1ac}
@section Attribute Universal_Literal_String
@@ -11785,7 +11804,7 @@ end;
@end example
@node Attribute Unrestricted_Access,Attribute Update,Attribute Universal_Literal_String,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-unrestricted-access}@anchor{1ac}
+@anchor{gnat_rm/implementation_defined_attributes attribute-unrestricted-access}@anchor{1ad}
@section Attribute Unrestricted_Access
@@ -11972,7 +11991,7 @@ In general this is a risky approach. It may appear to “work” but such uses o
of GNAT to another, so are best avoided if possible.
@node Attribute Update,Attribute Valid_Image,Attribute Unrestricted_Access,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-update}@anchor{1ad}
+@anchor{gnat_rm/implementation_defined_attributes attribute-update}@anchor{1ae}
@section Attribute Update
@@ -12053,7 +12072,7 @@ A := A'Update ((1, 2) => 20, (3, 4) => 30);
which changes element (1,2) to 20 and (3,4) to 30.
@node Attribute Valid_Image,Attribute Valid_Scalars,Attribute Update,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-valid-image}@anchor{1ae}
+@anchor{gnat_rm/implementation_defined_attributes attribute-valid-image}@anchor{1af}
@section Attribute Valid_Image
@@ -12065,7 +12084,7 @@ a String, and returns Boolean. @code{T'Valid_Image (S)} returns True
if and only if @code{T'Value (S)} would not raise Constraint_Error.
@node Attribute Valid_Scalars,Attribute VADS_Size,Attribute Valid_Image,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-valid-scalars}@anchor{1af}
+@anchor{gnat_rm/implementation_defined_attributes attribute-valid-scalars}@anchor{1b0}
@section Attribute Valid_Scalars
@@ -12099,7 +12118,7 @@ write a function with a single use of the attribute, and then call that
function from multiple places.
@node Attribute VADS_Size,Attribute Value_Size,Attribute Valid_Scalars,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-vads-size}@anchor{1b0}
+@anchor{gnat_rm/implementation_defined_attributes attribute-vads-size}@anchor{1b1}
@section Attribute VADS_Size
@@ -12119,7 +12138,7 @@ gives the result that would be obtained by applying the attribute to
the corresponding type.
@node Attribute Value_Size,Attribute Wchar_T_Size,Attribute VADS_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-value-size}@anchor{15d}@anchor{gnat_rm/implementation_defined_attributes id6}@anchor{1b1}
+@anchor{gnat_rm/implementation_defined_attributes attribute-value-size}@anchor{15e}@anchor{gnat_rm/implementation_defined_attributes id6}@anchor{1b2}
@section Attribute Value_Size
@@ -12133,7 +12152,7 @@ a value of the given subtype. It is the same as @code{type'Size},
but, unlike @code{Size}, may be set for non-first subtypes.
@node Attribute Wchar_T_Size,Attribute Word_Size,Attribute Value_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-wchar-t-size}@anchor{1b2}
+@anchor{gnat_rm/implementation_defined_attributes attribute-wchar-t-size}@anchor{1b3}
@section Attribute Wchar_T_Size
@@ -12145,7 +12164,7 @@ primarily for constructing the definition of this type in
package @code{Interfaces.C}. The result is a static constant.
@node Attribute Word_Size,,Attribute Wchar_T_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-word-size}@anchor{1b3}
+@anchor{gnat_rm/implementation_defined_attributes attribute-word-size}@anchor{1b4}
@section Attribute Word_Size
@@ -12156,7 +12175,7 @@ prefix) provides the value @code{System.Word_Size}. The result is
a static constant.
@node Standard and Implementation Defined Restrictions,Implementation Advice,Implementation Defined Attributes,Top
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions doc}@anchor{1b4}@anchor{gnat_rm/standard_and_implementation_defined_restrictions id1}@anchor{1b5}@anchor{gnat_rm/standard_and_implementation_defined_restrictions standard-and-implementation-defined-restrictions}@anchor{9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions doc}@anchor{1b5}@anchor{gnat_rm/standard_and_implementation_defined_restrictions id1}@anchor{1b6}@anchor{gnat_rm/standard_and_implementation_defined_restrictions standard-and-implementation-defined-restrictions}@anchor{9}
@chapter Standard and Implementation Defined Restrictions
@@ -12185,7 +12204,7 @@ language defined or GNAT-specific, are listed in the following.
@end menu
@node Partition-Wide Restrictions,Program Unit Level Restrictions,,Standard and Implementation Defined Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions id2}@anchor{1b6}@anchor{gnat_rm/standard_and_implementation_defined_restrictions partition-wide-restrictions}@anchor{1b7}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions id2}@anchor{1b7}@anchor{gnat_rm/standard_and_implementation_defined_restrictions partition-wide-restrictions}@anchor{1b8}
@section Partition-Wide Restrictions
@@ -12274,7 +12293,7 @@ then all compilation units in the partition must obey the restriction).
@end menu
@node Immediate_Reclamation,Max_Asynchronous_Select_Nesting,,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions immediate-reclamation}@anchor{1b8}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions immediate-reclamation}@anchor{1b9}
@subsection Immediate_Reclamation
@@ -12286,7 +12305,7 @@ deallocation, any storage reserved at run time for an object is
immediately reclaimed when the object no longer exists.
@node Max_Asynchronous_Select_Nesting,Max_Entry_Queue_Length,Immediate_Reclamation,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-asynchronous-select-nesting}@anchor{1b9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-asynchronous-select-nesting}@anchor{1ba}
@subsection Max_Asynchronous_Select_Nesting
@@ -12298,7 +12317,7 @@ detected at compile time. Violations of this restriction with values
other than zero cause Storage_Error to be raised.
@node Max_Entry_Queue_Length,Max_Protected_Entries,Max_Asynchronous_Select_Nesting,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-entry-queue-length}@anchor{1ba}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-entry-queue-length}@anchor{1bb}
@subsection Max_Entry_Queue_Length
@@ -12319,7 +12338,7 @@ compatibility purposes (and a warning will be generated for its use if
warnings on obsolescent features are activated).
@node Max_Protected_Entries,Max_Select_Alternatives,Max_Entry_Queue_Length,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-protected-entries}@anchor{1bb}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-protected-entries}@anchor{1bc}
@subsection Max_Protected_Entries
@@ -12330,7 +12349,7 @@ bounds of every entry family of a protected unit shall be static, or shall be
defined by a discriminant of a subtype whose corresponding bound is static.
@node Max_Select_Alternatives,Max_Storage_At_Blocking,Max_Protected_Entries,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-select-alternatives}@anchor{1bc}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-select-alternatives}@anchor{1bd}
@subsection Max_Select_Alternatives
@@ -12339,7 +12358,7 @@ defined by a discriminant of a subtype whose corresponding bound is static.
[RM D.7] Specifies the maximum number of alternatives in a selective accept.
@node Max_Storage_At_Blocking,Max_Task_Entries,Max_Select_Alternatives,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-storage-at-blocking}@anchor{1bd}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-storage-at-blocking}@anchor{1be}
@subsection Max_Storage_At_Blocking
@@ -12350,7 +12369,7 @@ Storage_Size that can be retained by a blocked task. A violation of this
restriction causes Storage_Error to be raised.
@node Max_Task_Entries,Max_Tasks,Max_Storage_At_Blocking,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-task-entries}@anchor{1be}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-task-entries}@anchor{1bf}
@subsection Max_Task_Entries
@@ -12363,7 +12382,7 @@ defined by a discriminant of a subtype whose
corresponding bound is static.
@node Max_Tasks,No_Abort_Statements,Max_Task_Entries,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-tasks}@anchor{1bf}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-tasks}@anchor{1c0}
@subsection Max_Tasks
@@ -12376,7 +12395,7 @@ time. Violations of this restriction with values other than zero cause
Storage_Error to be raised.
@node No_Abort_Statements,No_Access_Parameter_Allocators,Max_Tasks,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-abort-statements}@anchor{1c0}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-abort-statements}@anchor{1c1}
@subsection No_Abort_Statements
@@ -12386,7 +12405,7 @@ Storage_Error to be raised.
no calls to Task_Identification.Abort_Task.
@node No_Access_Parameter_Allocators,No_Access_Subprograms,No_Abort_Statements,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-access-parameter-allocators}@anchor{1c1}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-access-parameter-allocators}@anchor{1c2}
@subsection No_Access_Parameter_Allocators
@@ -12397,7 +12416,7 @@ occurrences of an allocator as the actual parameter to an access
parameter.
@node No_Access_Subprograms,No_Allocators,No_Access_Parameter_Allocators,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-access-subprograms}@anchor{1c2}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-access-subprograms}@anchor{1c3}
@subsection No_Access_Subprograms
@@ -12407,7 +12426,7 @@ parameter.
declarations of access-to-subprogram types.
@node No_Allocators,No_Anonymous_Allocators,No_Access_Subprograms,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-allocators}@anchor{1c3}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-allocators}@anchor{1c4}
@subsection No_Allocators
@@ -12417,7 +12436,7 @@ declarations of access-to-subprogram types.
occurrences of an allocator.
@node No_Anonymous_Allocators,No_Asynchronous_Control,No_Allocators,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-anonymous-allocators}@anchor{1c4}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-anonymous-allocators}@anchor{1c5}
@subsection No_Anonymous_Allocators
@@ -12427,7 +12446,7 @@ occurrences of an allocator.
occurrences of an allocator of anonymous access type.
@node No_Asynchronous_Control,No_Calendar,No_Anonymous_Allocators,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-asynchronous-control}@anchor{1c5}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-asynchronous-control}@anchor{1c6}
@subsection No_Asynchronous_Control
@@ -12437,7 +12456,7 @@ occurrences of an allocator of anonymous access type.
dependences on the predefined package Asynchronous_Task_Control.
@node No_Calendar,No_Coextensions,No_Asynchronous_Control,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-calendar}@anchor{1c6}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-calendar}@anchor{1c7}
@subsection No_Calendar
@@ -12447,7 +12466,7 @@ dependences on the predefined package Asynchronous_Task_Control.
dependences on package Calendar.
@node No_Coextensions,No_Default_Initialization,No_Calendar,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-coextensions}@anchor{1c7}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-coextensions}@anchor{1c8}
@subsection No_Coextensions
@@ -12457,7 +12476,7 @@ dependences on package Calendar.
coextensions. See 3.10.2.
@node No_Default_Initialization,No_Delay,No_Coextensions,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-default-initialization}@anchor{1c8}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-default-initialization}@anchor{1c9}
@subsection No_Default_Initialization
@@ -12474,7 +12493,7 @@ is to prohibit all cases of variables declared without a specific
initializer (including the case of OUT scalar parameters).
@node No_Delay,No_Dependence,No_Default_Initialization,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-delay}@anchor{1c9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-delay}@anchor{1ca}
@subsection No_Delay
@@ -12484,7 +12503,7 @@ initializer (including the case of OUT scalar parameters).
delay statements and no semantic dependences on package Calendar.
@node No_Dependence,No_Direct_Boolean_Operators,No_Delay,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dependence}@anchor{1ca}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dependence}@anchor{1cb}
@subsection No_Dependence
@@ -12494,7 +12513,7 @@ delay statements and no semantic dependences on package Calendar.
dependences on a library unit.
@node No_Direct_Boolean_Operators,No_Dispatch,No_Dependence,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-direct-boolean-operators}@anchor{1cb}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-direct-boolean-operators}@anchor{1cc}
@subsection No_Direct_Boolean_Operators
@@ -12507,7 +12526,7 @@ protocol requires the use of short-circuit (and then, or else) forms for all
composite boolean operations.
@node No_Dispatch,No_Dispatching_Calls,No_Direct_Boolean_Operators,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dispatch}@anchor{1cc}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dispatch}@anchor{1cd}
@subsection No_Dispatch
@@ -12517,7 +12536,7 @@ composite boolean operations.
occurrences of @code{T'Class}, for any (tagged) subtype @code{T}.
@node No_Dispatching_Calls,No_Dynamic_Attachment,No_Dispatch,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dispatching-calls}@anchor{1cd}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dispatching-calls}@anchor{1ce}
@subsection No_Dispatching_Calls
@@ -12578,7 +12597,7 @@ end Example;
@end example
@node No_Dynamic_Attachment,No_Dynamic_Priorities,No_Dispatching_Calls,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-attachment}@anchor{1ce}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-attachment}@anchor{1cf}
@subsection No_Dynamic_Attachment
@@ -12597,7 +12616,7 @@ compatibility purposes (and a warning will be generated for its use if
warnings on obsolescent features are activated).
@node No_Dynamic_Priorities,No_Entry_Calls_In_Elaboration_Code,No_Dynamic_Attachment,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-priorities}@anchor{1cf}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-priorities}@anchor{1d0}
@subsection No_Dynamic_Priorities
@@ -12606,7 +12625,7 @@ warnings on obsolescent features are activated).
[RM D.7] There are no semantic dependencies on the package Dynamic_Priorities.
@node No_Entry_Calls_In_Elaboration_Code,No_Enumeration_Maps,No_Dynamic_Priorities,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-entry-calls-in-elaboration-code}@anchor{1d0}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-entry-calls-in-elaboration-code}@anchor{1d1}
@subsection No_Entry_Calls_In_Elaboration_Code
@@ -12618,7 +12637,7 @@ restriction, the compiler can assume that no code past an accept statement
in a task can be executed at elaboration time.
@node No_Enumeration_Maps,No_Exception_Handlers,No_Entry_Calls_In_Elaboration_Code,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-enumeration-maps}@anchor{1d1}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-enumeration-maps}@anchor{1d2}
@subsection No_Enumeration_Maps
@@ -12629,7 +12648,7 @@ enumeration maps are used (that is Image and Value attributes applied
to enumeration types).
@node No_Exception_Handlers,No_Exception_Propagation,No_Enumeration_Maps,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exception-handlers}@anchor{1d2}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exception-handlers}@anchor{1d3}
@subsection No_Exception_Handlers
@@ -12654,7 +12673,7 @@ statement generated by the compiler). The Line parameter when nonzero
represents the line number in the source program where the raise occurs.
@node No_Exception_Propagation,No_Exception_Registration,No_Exception_Handlers,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exception-propagation}@anchor{1d3}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exception-propagation}@anchor{1d4}
@subsection No_Exception_Propagation
@@ -12671,7 +12690,7 @@ the package GNAT.Current_Exception is not permitted, and reraise
statements (raise with no operand) are not permitted.
@node No_Exception_Registration,No_Exceptions,No_Exception_Propagation,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exception-registration}@anchor{1d4}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exception-registration}@anchor{1d5}
@subsection No_Exception_Registration
@@ -12685,7 +12704,7 @@ code is simplified by omitting the otherwise-required global registration
of exceptions when they are declared.
@node No_Exceptions,No_Finalization,No_Exception_Registration,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exceptions}@anchor{1d5}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exceptions}@anchor{1d6}
@subsection No_Exceptions
@@ -12696,7 +12715,7 @@ raise statements and no exception handlers and also suppresses the
generation of language-defined run-time checks.
@node No_Finalization,No_Fixed_Point,No_Exceptions,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-finalization}@anchor{1d6}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-finalization}@anchor{1d7}
@subsection No_Finalization
@@ -12737,7 +12756,7 @@ object or a nested component, either declared on the stack or on the heap. The
deallocation of a controlled object no longer finalizes its contents.
@node No_Fixed_Point,No_Floating_Point,No_Finalization,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-fixed-point}@anchor{1d7}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-fixed-point}@anchor{1d8}
@subsection No_Fixed_Point
@@ -12747,7 +12766,7 @@ deallocation of a controlled object no longer finalizes its contents.
occurrences of fixed point types and operations.
@node No_Floating_Point,No_Implicit_Conditionals,No_Fixed_Point,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-floating-point}@anchor{1d8}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-floating-point}@anchor{1d9}
@subsection No_Floating_Point
@@ -12757,7 +12776,7 @@ occurrences of fixed point types and operations.
occurrences of floating point types and operations.
@node No_Implicit_Conditionals,No_Implicit_Dynamic_Code,No_Floating_Point,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-conditionals}@anchor{1d9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-conditionals}@anchor{1da}
@subsection No_Implicit_Conditionals
@@ -12773,7 +12792,7 @@ normal manner. Constructs generating implicit conditionals include comparisons
of composite objects and the Max/Min attributes.
@node No_Implicit_Dynamic_Code,No_Implicit_Heap_Allocations,No_Implicit_Conditionals,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-dynamic-code}@anchor{1da}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-dynamic-code}@anchor{1db}
@subsection No_Implicit_Dynamic_Code
@@ -12803,7 +12822,7 @@ foreign-language convention; primitive operations of nested tagged
types.
@node No_Implicit_Heap_Allocations,No_Implicit_Protected_Object_Allocations,No_Implicit_Dynamic_Code,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-heap-allocations}@anchor{1db}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-heap-allocations}@anchor{1dc}
@subsection No_Implicit_Heap_Allocations
@@ -12812,7 +12831,7 @@ types.
[RM D.7] No constructs are allowed to cause implicit heap allocation.
@node No_Implicit_Protected_Object_Allocations,No_Implicit_Task_Allocations,No_Implicit_Heap_Allocations,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-protected-object-allocations}@anchor{1dc}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-protected-object-allocations}@anchor{1dd}
@subsection No_Implicit_Protected_Object_Allocations
@@ -12822,7 +12841,7 @@ types.
protected object.
@node No_Implicit_Task_Allocations,No_Initialize_Scalars,No_Implicit_Protected_Object_Allocations,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-task-allocations}@anchor{1dd}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-task-allocations}@anchor{1de}
@subsection No_Implicit_Task_Allocations
@@ -12831,7 +12850,7 @@ protected object.
[GNAT] No constructs are allowed to cause implicit heap allocation of a task.
@node No_Initialize_Scalars,No_IO,No_Implicit_Task_Allocations,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-initialize-scalars}@anchor{1de}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-initialize-scalars}@anchor{1df}
@subsection No_Initialize_Scalars
@@ -12843,7 +12862,7 @@ code, and in particular eliminates dummy null initialization routines that
are otherwise generated for some record and array types.
@node No_IO,No_Local_Allocators,No_Initialize_Scalars,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-io}@anchor{1df}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-io}@anchor{1e0}
@subsection No_IO
@@ -12854,7 +12873,7 @@ dependences on any of the library units Sequential_IO, Direct_IO,
Text_IO, Wide_Text_IO, Wide_Wide_Text_IO, or Stream_IO.
@node No_Local_Allocators,No_Local_Protected_Objects,No_IO,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-local-allocators}@anchor{1e0}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-local-allocators}@anchor{1e1}
@subsection No_Local_Allocators
@@ -12865,7 +12884,7 @@ occurrences of an allocator in subprograms, generic subprograms, tasks,
and entry bodies.
@node No_Local_Protected_Objects,No_Local_Timing_Events,No_Local_Allocators,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-local-protected-objects}@anchor{1e1}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-local-protected-objects}@anchor{1e2}
@subsection No_Local_Protected_Objects
@@ -12875,7 +12894,7 @@ and entry bodies.
only declared at the library level.
@node No_Local_Timing_Events,No_Long_Long_Integers,No_Local_Protected_Objects,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-local-timing-events}@anchor{1e2}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-local-timing-events}@anchor{1e3}
@subsection No_Local_Timing_Events
@@ -12885,7 +12904,7 @@ only declared at the library level.
declared at the library level.
@node No_Long_Long_Integers,No_Multiple_Elaboration,No_Local_Timing_Events,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-long-long-integers}@anchor{1e3}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-long-long-integers}@anchor{1e4}
@subsection No_Long_Long_Integers
@@ -12897,7 +12916,7 @@ implicit base type is Long_Long_Integer, and modular types whose size exceeds
Long_Integer’Size.
@node No_Multiple_Elaboration,No_Nested_Finalization,No_Long_Long_Integers,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-multiple-elaboration}@anchor{1e4}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-multiple-elaboration}@anchor{1e5}
@subsection No_Multiple_Elaboration
@@ -12913,7 +12932,7 @@ possible, including non-Ada main programs and Stand Alone libraries, are not
permitted and will be diagnosed by the binder.
@node No_Nested_Finalization,No_Protected_Type_Allocators,No_Multiple_Elaboration,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-nested-finalization}@anchor{1e5}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-nested-finalization}@anchor{1e6}
@subsection No_Nested_Finalization
@@ -12922,7 +12941,7 @@ permitted and will be diagnosed by the binder.
[RM D.7] All objects requiring finalization are declared at the library level.
@node No_Protected_Type_Allocators,No_Protected_Types,No_Nested_Finalization,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-protected-type-allocators}@anchor{1e6}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-protected-type-allocators}@anchor{1e7}
@subsection No_Protected_Type_Allocators
@@ -12932,7 +12951,7 @@ permitted and will be diagnosed by the binder.
expressions that attempt to allocate protected objects.
@node No_Protected_Types,No_Recursion,No_Protected_Type_Allocators,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-protected-types}@anchor{1e7}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-protected-types}@anchor{1e8}
@subsection No_Protected_Types
@@ -12942,7 +12961,7 @@ expressions that attempt to allocate protected objects.
declarations of protected types or protected objects.
@node No_Recursion,No_Reentrancy,No_Protected_Types,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-recursion}@anchor{1e8}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-recursion}@anchor{1e9}
@subsection No_Recursion
@@ -12952,7 +12971,7 @@ declarations of protected types or protected objects.
part of its execution.
@node No_Reentrancy,No_Relative_Delay,No_Recursion,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-reentrancy}@anchor{1e9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-reentrancy}@anchor{1ea}
@subsection No_Reentrancy
@@ -12962,7 +12981,7 @@ part of its execution.
two tasks at the same time.
@node No_Relative_Delay,No_Requeue_Statements,No_Reentrancy,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-relative-delay}@anchor{1ea}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-relative-delay}@anchor{1eb}
@subsection No_Relative_Delay
@@ -12973,7 +12992,7 @@ relative statements and prevents expressions such as @code{delay 1.23;} from
appearing in source code.
@node No_Requeue_Statements,No_Secondary_Stack,No_Relative_Delay,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-requeue-statements}@anchor{1eb}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-requeue-statements}@anchor{1ec}
@subsection No_Requeue_Statements
@@ -12991,7 +13010,7 @@ compatibility purposes (and a warning will be generated for its use if
warnings on oNobsolescent features are activated).
@node No_Secondary_Stack,No_Select_Statements,No_Requeue_Statements,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-secondary-stack}@anchor{1ec}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-secondary-stack}@anchor{1ed}
@subsection No_Secondary_Stack
@@ -13004,7 +13023,7 @@ stack is used to implement functions returning unconstrained objects
secondary stacks for tasks (excluding the environment task) at run time.
@node No_Select_Statements,No_Specific_Termination_Handlers,No_Secondary_Stack,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-select-statements}@anchor{1ed}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-select-statements}@anchor{1ee}
@subsection No_Select_Statements
@@ -13014,7 +13033,7 @@ secondary stacks for tasks (excluding the environment task) at run time.
kind are permitted, that is the keyword @code{select} may not appear.
@node No_Specific_Termination_Handlers,No_Specification_of_Aspect,No_Select_Statements,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-specific-termination-handlers}@anchor{1ee}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-specific-termination-handlers}@anchor{1ef}
@subsection No_Specific_Termination_Handlers
@@ -13024,7 +13043,7 @@ kind are permitted, that is the keyword @code{select} may not appear.
or to Ada.Task_Termination.Specific_Handler.
@node No_Specification_of_Aspect,No_Standard_Allocators_After_Elaboration,No_Specific_Termination_Handlers,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-specification-of-aspect}@anchor{1ef}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-specification-of-aspect}@anchor{1f0}
@subsection No_Specification_of_Aspect
@@ -13035,7 +13054,7 @@ specification, attribute definition clause, or pragma is given for a
given aspect.
@node No_Standard_Allocators_After_Elaboration,No_Standard_Storage_Pools,No_Specification_of_Aspect,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-standard-allocators-after-elaboration}@anchor{1f0}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-standard-allocators-after-elaboration}@anchor{1f1}
@subsection No_Standard_Allocators_After_Elaboration
@@ -13047,7 +13066,7 @@ library items of the partition has completed. Otherwise, Storage_Error
is raised.
@node No_Standard_Storage_Pools,No_Stream_Optimizations,No_Standard_Allocators_After_Elaboration,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-standard-storage-pools}@anchor{1f1}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-standard-storage-pools}@anchor{1f2}
@subsection No_Standard_Storage_Pools
@@ -13059,7 +13078,7 @@ have an explicit Storage_Pool attribute defined specifying a
user-defined storage pool.
@node No_Stream_Optimizations,No_Streams,No_Standard_Storage_Pools,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-stream-optimizations}@anchor{1f2}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-stream-optimizations}@anchor{1f3}
@subsection No_Stream_Optimizations
@@ -13072,7 +13091,7 @@ due to their superior performance. When this restriction is in effect, the
compiler performs all IO operations on a per-character basis.
@node No_Streams,No_Task_Allocators,No_Stream_Optimizations,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-streams}@anchor{1f3}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-streams}@anchor{1f4}
@subsection No_Streams
@@ -13093,7 +13112,7 @@ unit declaring a tagged type should be compiled with the restriction,
though this is not required.
@node No_Task_Allocators,No_Task_At_Interrupt_Priority,No_Streams,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-allocators}@anchor{1f4}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-allocators}@anchor{1f5}
@subsection No_Task_Allocators
@@ -13103,7 +13122,7 @@ though this is not required.
or types containing task subcomponents.
@node No_Task_At_Interrupt_Priority,No_Task_Attributes_Package,No_Task_Allocators,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-at-interrupt-priority}@anchor{1f5}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-at-interrupt-priority}@anchor{1f6}
@subsection No_Task_At_Interrupt_Priority
@@ -13115,7 +13134,7 @@ a consequence, the tasks are always created with a priority below
that an interrupt priority.
@node No_Task_Attributes_Package,No_Task_Hierarchy,No_Task_At_Interrupt_Priority,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-attributes-package}@anchor{1f6}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-attributes-package}@anchor{1f7}
@subsection No_Task_Attributes_Package
@@ -13132,7 +13151,7 @@ compatibility purposes (and a warning will be generated for its use if
warnings on obsolescent features are activated).
@node No_Task_Hierarchy,No_Task_Termination,No_Task_Attributes_Package,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-hierarchy}@anchor{1f7}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-hierarchy}@anchor{1f8}
@subsection No_Task_Hierarchy
@@ -13142,7 +13161,7 @@ warnings on obsolescent features are activated).
directly on the environment task of the partition.
@node No_Task_Termination,No_Tasking,No_Task_Hierarchy,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-termination}@anchor{1f8}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-termination}@anchor{1f9}
@subsection No_Task_Termination
@@ -13151,7 +13170,7 @@ directly on the environment task of the partition.
[RM D.7] Tasks that terminate are erroneous.
@node No_Tasking,No_Terminate_Alternatives,No_Task_Termination,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-tasking}@anchor{1f9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-tasking}@anchor{1fa}
@subsection No_Tasking
@@ -13164,7 +13183,7 @@ and cause an error message to be output either by the compiler or
binder.
@node No_Terminate_Alternatives,No_Unchecked_Access,No_Tasking,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-terminate-alternatives}@anchor{1fa}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-terminate-alternatives}@anchor{1fb}
@subsection No_Terminate_Alternatives
@@ -13173,7 +13192,7 @@ binder.
[RM D.7] There are no selective accepts with terminate alternatives.
@node No_Unchecked_Access,No_Unchecked_Conversion,No_Terminate_Alternatives,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-unchecked-access}@anchor{1fb}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-unchecked-access}@anchor{1fc}
@subsection No_Unchecked_Access
@@ -13183,7 +13202,7 @@ binder.
occurrences of the Unchecked_Access attribute.
@node No_Unchecked_Conversion,No_Unchecked_Deallocation,No_Unchecked_Access,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-unchecked-conversion}@anchor{1fc}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-unchecked-conversion}@anchor{1fd}
@subsection No_Unchecked_Conversion
@@ -13193,7 +13212,7 @@ occurrences of the Unchecked_Access attribute.
dependences on the predefined generic function Unchecked_Conversion.
@node No_Unchecked_Deallocation,No_Use_Of_Entity,No_Unchecked_Conversion,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-unchecked-deallocation}@anchor{1fd}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-unchecked-deallocation}@anchor{1fe}
@subsection No_Unchecked_Deallocation
@@ -13203,7 +13222,7 @@ dependences on the predefined generic function Unchecked_Conversion.
dependences on the predefined generic procedure Unchecked_Deallocation.
@node No_Use_Of_Entity,Pure_Barriers,No_Unchecked_Deallocation,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-use-of-entity}@anchor{1fe}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-use-of-entity}@anchor{1ff}
@subsection No_Use_Of_Entity
@@ -13223,7 +13242,7 @@ No_Use_Of_Entity => Ada.Text_IO.Put_Line
@end example
@node Pure_Barriers,Simple_Barriers,No_Use_Of_Entity,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions pure-barriers}@anchor{1ff}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions pure-barriers}@anchor{200}
@subsection Pure_Barriers
@@ -13274,7 +13293,7 @@ but still ensures absence of side effects, exceptions, and recursion
during the evaluation of the barriers.
@node Simple_Barriers,Static_Priorities,Pure_Barriers,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions simple-barriers}@anchor{200}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions simple-barriers}@anchor{201}
@subsection Simple_Barriers
@@ -13293,7 +13312,7 @@ compatibility purposes (and a warning will be generated for its use if
warnings on obsolescent features are activated).
@node Static_Priorities,Static_Storage_Size,Simple_Barriers,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions static-priorities}@anchor{201}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions static-priorities}@anchor{202}
@subsection Static_Priorities
@@ -13304,7 +13323,7 @@ are static, and that there are no dependences on the package
@code{Ada.Dynamic_Priorities}.
@node Static_Storage_Size,,Static_Priorities,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions static-storage-size}@anchor{202}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions static-storage-size}@anchor{203}
@subsection Static_Storage_Size
@@ -13314,7 +13333,7 @@ are static, and that there are no dependences on the package
in a Storage_Size pragma or attribute definition clause is static.
@node Program Unit Level Restrictions,,Partition-Wide Restrictions,Standard and Implementation Defined Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions id3}@anchor{203}@anchor{gnat_rm/standard_and_implementation_defined_restrictions program-unit-level-restrictions}@anchor{204}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions id3}@anchor{204}@anchor{gnat_rm/standard_and_implementation_defined_restrictions program-unit-level-restrictions}@anchor{205}
@section Program Unit Level Restrictions
@@ -13326,6 +13345,7 @@ other compilation units in the partition.
@menu
* No_Elaboration_Code::
+* No_Dynamic_Accessibility_Checks::
* No_Dynamic_Sized_Objects::
* No_Entry_Queue::
* No_Implementation_Aspect_Specifications::
@@ -13343,8 +13363,8 @@ other compilation units in the partition.
@end menu
-@node No_Elaboration_Code,No_Dynamic_Sized_Objects,,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-elaboration-code}@anchor{205}
+@node No_Elaboration_Code,No_Dynamic_Accessibility_Checks,,Program Unit Level Restrictions
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-elaboration-code}@anchor{206}
@subsection No_Elaboration_Code
@@ -13399,8 +13419,57 @@ used, the compiler is allowed to suppress the elaboration counter normally
associated with the unit. This counter is typically used to check for access
before elaboration and to control multiple elaboration attempts.
-@node No_Dynamic_Sized_Objects,No_Entry_Queue,No_Elaboration_Code,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-sized-objects}@anchor{206}
+@node No_Dynamic_Accessibility_Checks,No_Dynamic_Sized_Objects,No_Elaboration_Code,Program Unit Level Restrictions
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-accessibility-checks}@anchor{207}
+@subsection No_Dynamic_Accessibility_Checks
+
+
+@geindex No_Dynamic_Accessibility_Checks
+
+[GNAT] No dynamic accessibility checks are generated when this restriction is
+in effect. Instead, dangling references are prevented via more conservative
+compile-time checking. More specifically, existing compile-time checks are
+enforced but with more conservative assumptions about the accessibility levels
+of the relevant entities. These conservative assumptions eliminate the need for
+dynamic accessibility checks.
+
+These new rules for computing (at compile-time) the accessibility level of an
+anonymous access type T are as follows:
+
+
+@itemize *
+
+@item
+If T is a function result type then, from the caller’s perspective, its level
+is that of the innermost master enclosing the function call. From the callee’s
+perspective, the level of parameters and local variables of the callee is
+statically deeper than the level of T.
+
+For any other accessibility level L such that the level of parameters and local
+variables of the callee is statically deeper than L, the level of T (from the
+callee’s perspective) is also statically deeper than L.
+
+@item
+If T is the type of a formal parameter then, from the caller’s perspective,
+its level is at least as deep as that of the type of the corresponding actual
+parameter (whatever that actual parameter might be). From the callee’s
+perspective, the level of parameters and local variables of the callee is
+statically deeper than the level of T.
+
+@item
+If T is the type of a discriminant then its level is that of the discriminated
+type.
+
+@item
+If T is the type of a stand-alone object then its level is the level of the
+object.
+
+@item
+In all other cases, the level of T is as defined by the existing rules of Ada.
+@end itemize
+
+@node No_Dynamic_Sized_Objects,No_Entry_Queue,No_Dynamic_Accessibility_Checks,Program Unit Level Restrictions
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-sized-objects}@anchor{208}
@subsection No_Dynamic_Sized_Objects
@@ -13418,7 +13487,7 @@ access discriminants. It is often a good idea to combine this restriction
with No_Secondary_Stack.
@node No_Entry_Queue,No_Implementation_Aspect_Specifications,No_Dynamic_Sized_Objects,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-entry-queue}@anchor{207}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-entry-queue}@anchor{209}
@subsection No_Entry_Queue
@@ -13431,7 +13500,7 @@ checked at compile time. A program execution is erroneous if an attempt
is made to queue a second task on such an entry.
@node No_Implementation_Aspect_Specifications,No_Implementation_Attributes,No_Entry_Queue,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-aspect-specifications}@anchor{208}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-aspect-specifications}@anchor{20a}
@subsection No_Implementation_Aspect_Specifications
@@ -13442,7 +13511,7 @@ GNAT-defined aspects are present. With this restriction, the only
aspects that can be used are those defined in the Ada Reference Manual.
@node No_Implementation_Attributes,No_Implementation_Identifiers,No_Implementation_Aspect_Specifications,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-attributes}@anchor{209}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-attributes}@anchor{20b}
@subsection No_Implementation_Attributes
@@ -13454,7 +13523,7 @@ attributes that can be used are those defined in the Ada Reference
Manual.
@node No_Implementation_Identifiers,No_Implementation_Pragmas,No_Implementation_Attributes,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-identifiers}@anchor{20a}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-identifiers}@anchor{20c}
@subsection No_Implementation_Identifiers
@@ -13465,7 +13534,7 @@ implementation-defined identifiers (marked with pragma Implementation_Defined)
occur within language-defined packages.
@node No_Implementation_Pragmas,No_Implementation_Restrictions,No_Implementation_Identifiers,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-pragmas}@anchor{20b}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-pragmas}@anchor{20d}
@subsection No_Implementation_Pragmas
@@ -13476,7 +13545,7 @@ GNAT-defined pragmas are present. With this restriction, the only
pragmas that can be used are those defined in the Ada Reference Manual.
@node No_Implementation_Restrictions,No_Implementation_Units,No_Implementation_Pragmas,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-restrictions}@anchor{20c}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-restrictions}@anchor{20e}
@subsection No_Implementation_Restrictions
@@ -13488,7 +13557,7 @@ are present. With this restriction, the only other restriction identifiers
that can be used are those defined in the Ada Reference Manual.
@node No_Implementation_Units,No_Implicit_Aliasing,No_Implementation_Restrictions,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-units}@anchor{20d}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-units}@anchor{20f}
@subsection No_Implementation_Units
@@ -13499,7 +13568,7 @@ mention in the context clause of any implementation-defined descendants
of packages Ada, Interfaces, or System.
@node No_Implicit_Aliasing,No_Implicit_Loops,No_Implementation_Units,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-aliasing}@anchor{20e}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-aliasing}@anchor{210}
@subsection No_Implicit_Aliasing
@@ -13514,7 +13583,7 @@ to be aliased, and in such cases, it can always be replaced by
the standard attribute Unchecked_Access which is preferable.
@node No_Implicit_Loops,No_Obsolescent_Features,No_Implicit_Aliasing,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-loops}@anchor{20f}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-loops}@anchor{211}
@subsection No_Implicit_Loops
@@ -13531,7 +13600,7 @@ arrays larger than about 5000 scalar components. Note that if this restriction
is set in the spec of a package, it will not apply to its body.
@node No_Obsolescent_Features,No_Wide_Characters,No_Implicit_Loops,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-obsolescent-features}@anchor{210}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-obsolescent-features}@anchor{212}
@subsection No_Obsolescent_Features
@@ -13541,7 +13610,7 @@ is set in the spec of a package, it will not apply to its body.
features are used, as defined in Annex J of the Ada Reference Manual.
@node No_Wide_Characters,Static_Dispatch_Tables,No_Obsolescent_Features,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-wide-characters}@anchor{211}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-wide-characters}@anchor{213}
@subsection No_Wide_Characters
@@ -13555,7 +13624,7 @@ appear in the program (that is literals representing characters not in
type @code{Character}).
@node Static_Dispatch_Tables,SPARK_05,No_Wide_Characters,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions static-dispatch-tables}@anchor{212}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions static-dispatch-tables}@anchor{214}
@subsection Static_Dispatch_Tables
@@ -13565,7 +13634,7 @@ type @code{Character}).
associated with dispatch tables can be placed in read-only memory.
@node SPARK_05,,Static_Dispatch_Tables,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions spark-05}@anchor{213}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions spark-05}@anchor{215}
@subsection SPARK_05
@@ -13588,7 +13657,7 @@ gnatprove -P project.gpr --mode=check_all
@end example
@node Implementation Advice,Implementation Defined Characteristics,Standard and Implementation Defined Restrictions,Top
-@anchor{gnat_rm/implementation_advice doc}@anchor{214}@anchor{gnat_rm/implementation_advice id1}@anchor{215}@anchor{gnat_rm/implementation_advice implementation-advice}@anchor{a}
+@anchor{gnat_rm/implementation_advice doc}@anchor{216}@anchor{gnat_rm/implementation_advice id1}@anchor{217}@anchor{gnat_rm/implementation_advice implementation-advice}@anchor{a}
@chapter Implementation Advice
@@ -13686,7 +13755,7 @@ case the text describes what GNAT does and why.
@end menu
@node RM 1 1 3 20 Error Detection,RM 1 1 3 31 Child Units,,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-1-1-3-20-error-detection}@anchor{216}
+@anchor{gnat_rm/implementation_advice rm-1-1-3-20-error-detection}@anchor{218}
@section RM 1.1.3(20): Error Detection
@@ -13703,7 +13772,7 @@ or diagnosed at compile time.
@geindex Child Units
@node RM 1 1 3 31 Child Units,RM 1 1 5 12 Bounded Errors,RM 1 1 3 20 Error Detection,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-1-1-3-31-child-units}@anchor{217}
+@anchor{gnat_rm/implementation_advice rm-1-1-3-31-child-units}@anchor{219}
@section RM 1.1.3(31): Child Units
@@ -13719,7 +13788,7 @@ Followed.
@geindex Bounded errors
@node RM 1 1 5 12 Bounded Errors,RM 2 8 16 Pragmas,RM 1 1 3 31 Child Units,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-1-1-5-12-bounded-errors}@anchor{218}
+@anchor{gnat_rm/implementation_advice rm-1-1-5-12-bounded-errors}@anchor{21a}
@section RM 1.1.5(12): Bounded Errors
@@ -13736,7 +13805,7 @@ runtime.
@geindex Pragmas
@node RM 2 8 16 Pragmas,RM 2 8 17-19 Pragmas,RM 1 1 5 12 Bounded Errors,Implementation Advice
-@anchor{gnat_rm/implementation_advice id2}@anchor{219}@anchor{gnat_rm/implementation_advice rm-2-8-16-pragmas}@anchor{21a}
+@anchor{gnat_rm/implementation_advice id2}@anchor{21b}@anchor{gnat_rm/implementation_advice rm-2-8-16-pragmas}@anchor{21c}
@section RM 2.8(16): Pragmas
@@ -13849,7 +13918,7 @@ that this advice not be followed. For details see
@ref{7,,Implementation Defined Pragmas}.
@node RM 2 8 17-19 Pragmas,RM 3 5 2 5 Alternative Character Sets,RM 2 8 16 Pragmas,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-2-8-17-19-pragmas}@anchor{21b}
+@anchor{gnat_rm/implementation_advice rm-2-8-17-19-pragmas}@anchor{21d}
@section RM 2.8(17-19): Pragmas
@@ -13870,14 +13939,14 @@ replacing @code{library_items}.”
@end itemize
@end quotation
-See @ref{21a,,RM 2.8(16); Pragmas}.
+See @ref{21c,,RM 2.8(16); Pragmas}.
@geindex Character Sets
@geindex Alternative Character Sets
@node RM 3 5 2 5 Alternative Character Sets,RM 3 5 4 28 Integer Types,RM 2 8 17-19 Pragmas,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-3-5-2-5-alternative-character-sets}@anchor{21c}
+@anchor{gnat_rm/implementation_advice rm-3-5-2-5-alternative-character-sets}@anchor{21e}
@section RM 3.5.2(5): Alternative Character Sets
@@ -13905,7 +13974,7 @@ there is no such restriction.
@geindex Integer types
@node RM 3 5 4 28 Integer Types,RM 3 5 4 29 Integer Types,RM 3 5 2 5 Alternative Character Sets,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-3-5-4-28-integer-types}@anchor{21d}
+@anchor{gnat_rm/implementation_advice rm-3-5-4-28-integer-types}@anchor{21f}
@section RM 3.5.4(28): Integer Types
@@ -13924,7 +13993,7 @@ are supported for convenient interface to C, and so that all hardware
types of the machine are easily available.
@node RM 3 5 4 29 Integer Types,RM 3 5 5 8 Enumeration Values,RM 3 5 4 28 Integer Types,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-3-5-4-29-integer-types}@anchor{21e}
+@anchor{gnat_rm/implementation_advice rm-3-5-4-29-integer-types}@anchor{220}
@section RM 3.5.4(29): Integer Types
@@ -13940,7 +14009,7 @@ Followed.
@geindex Enumeration values
@node RM 3 5 5 8 Enumeration Values,RM 3 5 7 17 Float Types,RM 3 5 4 29 Integer Types,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-3-5-5-8-enumeration-values}@anchor{21f}
+@anchor{gnat_rm/implementation_advice rm-3-5-5-8-enumeration-values}@anchor{221}
@section RM 3.5.5(8): Enumeration Values
@@ -13960,7 +14029,7 @@ Followed.
@geindex Float types
@node RM 3 5 7 17 Float Types,RM 3 6 2 11 Multidimensional Arrays,RM 3 5 5 8 Enumeration Values,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-3-5-7-17-float-types}@anchor{220}
+@anchor{gnat_rm/implementation_advice rm-3-5-7-17-float-types}@anchor{222}
@section RM 3.5.7(17): Float Types
@@ -13990,7 +14059,7 @@ is a software rather than a hardware format.
@geindex multidimensional
@node RM 3 6 2 11 Multidimensional Arrays,RM 9 6 30-31 Duration’Small,RM 3 5 7 17 Float Types,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-3-6-2-11-multidimensional-arrays}@anchor{221}
+@anchor{gnat_rm/implementation_advice rm-3-6-2-11-multidimensional-arrays}@anchor{223}
@section RM 3.6.2(11): Multidimensional Arrays
@@ -14008,7 +14077,7 @@ Followed.
@geindex Duration'Small
@node RM 9 6 30-31 Duration’Small,RM 10 2 1 12 Consistent Representation,RM 3 6 2 11 Multidimensional Arrays,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-9-6-30-31-duration-small}@anchor{222}
+@anchor{gnat_rm/implementation_advice rm-9-6-30-31-duration-small}@anchor{224}
@section RM 9.6(30-31): Duration’Small
@@ -14029,7 +14098,7 @@ it need not be the same time base as used for @code{Calendar.Clock}.”
Followed.
@node RM 10 2 1 12 Consistent Representation,RM 11 4 1 19 Exception Information,RM 9 6 30-31 Duration’Small,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-10-2-1-12-consistent-representation}@anchor{223}
+@anchor{gnat_rm/implementation_advice rm-10-2-1-12-consistent-representation}@anchor{225}
@section RM 10.2.1(12): Consistent Representation
@@ -14051,7 +14120,7 @@ advice without severely impacting efficiency of execution.
@geindex Exception information
@node RM 11 4 1 19 Exception Information,RM 11 5 28 Suppression of Checks,RM 10 2 1 12 Consistent Representation,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-11-4-1-19-exception-information}@anchor{224}
+@anchor{gnat_rm/implementation_advice rm-11-4-1-19-exception-information}@anchor{226}
@section RM 11.4.1(19): Exception Information
@@ -14082,7 +14151,7 @@ Pragma @code{Discard_Names}.
@geindex suppression of
@node RM 11 5 28 Suppression of Checks,RM 13 1 21-24 Representation Clauses,RM 11 4 1 19 Exception Information,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-11-5-28-suppression-of-checks}@anchor{225}
+@anchor{gnat_rm/implementation_advice rm-11-5-28-suppression-of-checks}@anchor{227}
@section RM 11.5(28): Suppression of Checks
@@ -14097,7 +14166,7 @@ Followed.
@geindex Representation clauses
@node RM 13 1 21-24 Representation Clauses,RM 13 2 6-8 Packed Types,RM 11 5 28 Suppression of Checks,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-1-21-24-representation-clauses}@anchor{226}
+@anchor{gnat_rm/implementation_advice rm-13-1-21-24-representation-clauses}@anchor{228}
@section RM 13.1 (21-24): Representation Clauses
@@ -14146,7 +14215,7 @@ Followed.
@geindex Packed types
@node RM 13 2 6-8 Packed Types,RM 13 3 14-19 Address Clauses,RM 13 1 21-24 Representation Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-2-6-8-packed-types}@anchor{227}
+@anchor{gnat_rm/implementation_advice rm-13-2-6-8-packed-types}@anchor{229}
@section RM 13.2(6-8): Packed Types
@@ -14185,7 +14254,7 @@ Followed.
@geindex Address clauses
@node RM 13 3 14-19 Address Clauses,RM 13 3 29-35 Alignment Clauses,RM 13 2 6-8 Packed Types,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-3-14-19-address-clauses}@anchor{228}
+@anchor{gnat_rm/implementation_advice rm-13-3-14-19-address-clauses}@anchor{22a}
@section RM 13.3(14-19): Address Clauses
@@ -14238,7 +14307,7 @@ Followed.
@geindex Alignment clauses
@node RM 13 3 29-35 Alignment Clauses,RM 13 3 42-43 Size Clauses,RM 13 3 14-19 Address Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-3-29-35-alignment-clauses}@anchor{229}
+@anchor{gnat_rm/implementation_advice rm-13-3-29-35-alignment-clauses}@anchor{22b}
@section RM 13.3(29-35): Alignment Clauses
@@ -14295,7 +14364,7 @@ Followed.
@geindex Size clauses
@node RM 13 3 42-43 Size Clauses,RM 13 3 50-56 Size Clauses,RM 13 3 29-35 Alignment Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-3-42-43-size-clauses}@anchor{22a}
+@anchor{gnat_rm/implementation_advice rm-13-3-42-43-size-clauses}@anchor{22c}
@section RM 13.3(42-43): Size Clauses
@@ -14313,7 +14382,7 @@ object’s @code{Alignment} (if the @code{Alignment} is nonzero).”
Followed.
@node RM 13 3 50-56 Size Clauses,RM 13 3 71-73 Component Size Clauses,RM 13 3 42-43 Size Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-3-50-56-size-clauses}@anchor{22b}
+@anchor{gnat_rm/implementation_advice rm-13-3-50-56-size-clauses}@anchor{22d}
@section RM 13.3(50-56): Size Clauses
@@ -14364,7 +14433,7 @@ Followed.
@geindex Component_Size clauses
@node RM 13 3 71-73 Component Size Clauses,RM 13 4 9-10 Enumeration Representation Clauses,RM 13 3 50-56 Size Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-3-71-73-component-size-clauses}@anchor{22c}
+@anchor{gnat_rm/implementation_advice rm-13-3-71-73-component-size-clauses}@anchor{22e}
@section RM 13.3(71-73): Component Size Clauses
@@ -14398,7 +14467,7 @@ Followed.
@geindex enumeration
@node RM 13 4 9-10 Enumeration Representation Clauses,RM 13 5 1 17-22 Record Representation Clauses,RM 13 3 71-73 Component Size Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-4-9-10-enumeration-representation-clauses}@anchor{22d}
+@anchor{gnat_rm/implementation_advice rm-13-4-9-10-enumeration-representation-clauses}@anchor{22f}
@section RM 13.4(9-10): Enumeration Representation Clauses
@@ -14420,7 +14489,7 @@ Followed.
@geindex records
@node RM 13 5 1 17-22 Record Representation Clauses,RM 13 5 2 5 Storage Place Attributes,RM 13 4 9-10 Enumeration Representation Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-5-1-17-22-record-representation-clauses}@anchor{22e}
+@anchor{gnat_rm/implementation_advice rm-13-5-1-17-22-record-representation-clauses}@anchor{230}
@section RM 13.5.1(17-22): Record Representation Clauses
@@ -14480,7 +14549,7 @@ and all mentioned features are implemented.
@geindex Storage place attributes
@node RM 13 5 2 5 Storage Place Attributes,RM 13 5 3 7-8 Bit Ordering,RM 13 5 1 17-22 Record Representation Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-5-2-5-storage-place-attributes}@anchor{22f}
+@anchor{gnat_rm/implementation_advice rm-13-5-2-5-storage-place-attributes}@anchor{231}
@section RM 13.5.2(5): Storage Place Attributes
@@ -14500,7 +14569,7 @@ Followed. There are no such components in GNAT.
@geindex Bit ordering
@node RM 13 5 3 7-8 Bit Ordering,RM 13 7 37 Address as Private,RM 13 5 2 5 Storage Place Attributes,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-5-3-7-8-bit-ordering}@anchor{230}
+@anchor{gnat_rm/implementation_advice rm-13-5-3-7-8-bit-ordering}@anchor{232}
@section RM 13.5.3(7-8): Bit Ordering
@@ -14520,7 +14589,7 @@ Thus non-default bit ordering is not supported.
@geindex as private type
@node RM 13 7 37 Address as Private,RM 13 7 1 16 Address Operations,RM 13 5 3 7-8 Bit Ordering,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-7-37-address-as-private}@anchor{231}
+@anchor{gnat_rm/implementation_advice rm-13-7-37-address-as-private}@anchor{233}
@section RM 13.7(37): Address as Private
@@ -14538,7 +14607,7 @@ Followed.
@geindex operations of
@node RM 13 7 1 16 Address Operations,RM 13 9 14-17 Unchecked Conversion,RM 13 7 37 Address as Private,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-7-1-16-address-operations}@anchor{232}
+@anchor{gnat_rm/implementation_advice rm-13-7-1-16-address-operations}@anchor{234}
@section RM 13.7.1(16): Address Operations
@@ -14556,7 +14625,7 @@ operation raises @code{Program_Error}, since all operations make sense.
@geindex Unchecked conversion
@node RM 13 9 14-17 Unchecked Conversion,RM 13 11 23-25 Implicit Heap Usage,RM 13 7 1 16 Address Operations,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-9-14-17-unchecked-conversion}@anchor{233}
+@anchor{gnat_rm/implementation_advice rm-13-9-14-17-unchecked-conversion}@anchor{235}
@section RM 13.9(14-17): Unchecked Conversion
@@ -14600,7 +14669,7 @@ Followed.
@geindex implicit
@node RM 13 11 23-25 Implicit Heap Usage,RM 13 11 2 17 Unchecked Deallocation,RM 13 9 14-17 Unchecked Conversion,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-11-23-25-implicit-heap-usage}@anchor{234}
+@anchor{gnat_rm/implementation_advice rm-13-11-23-25-implicit-heap-usage}@anchor{236}
@section RM 13.11(23-25): Implicit Heap Usage
@@ -14651,7 +14720,7 @@ Followed.
@geindex Unchecked deallocation
@node RM 13 11 2 17 Unchecked Deallocation,RM 13 13 2 1 6 Stream Oriented Attributes,RM 13 11 23-25 Implicit Heap Usage,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-11-2-17-unchecked-deallocation}@anchor{235}
+@anchor{gnat_rm/implementation_advice rm-13-11-2-17-unchecked-deallocation}@anchor{237}
@section RM 13.11.2(17): Unchecked Deallocation
@@ -14666,7 +14735,7 @@ Followed.
@geindex Stream oriented attributes
@node RM 13 13 2 1 6 Stream Oriented Attributes,RM A 1 52 Names of Predefined Numeric Types,RM 13 11 2 17 Unchecked Deallocation,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-13-2-1-6-stream-oriented-attributes}@anchor{236}
+@anchor{gnat_rm/implementation_advice rm-13-13-2-1-6-stream-oriented-attributes}@anchor{238}
@section RM 13.13.2(1.6): Stream Oriented Attributes
@@ -14697,7 +14766,7 @@ scalar types. This XDR alternative can be enabled via the binder switch -xdr.
@geindex Stream oriented attributes
@node RM A 1 52 Names of Predefined Numeric Types,RM A 3 2 49 Ada Characters Handling,RM 13 13 2 1 6 Stream Oriented Attributes,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-a-1-52-names-of-predefined-numeric-types}@anchor{237}
+@anchor{gnat_rm/implementation_advice rm-a-1-52-names-of-predefined-numeric-types}@anchor{239}
@section RM A.1(52): Names of Predefined Numeric Types
@@ -14715,7 +14784,7 @@ Followed.
@geindex Ada.Characters.Handling
@node RM A 3 2 49 Ada Characters Handling,RM A 4 4 106 Bounded-Length String Handling,RM A 1 52 Names of Predefined Numeric Types,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-a-3-2-49-ada-characters-handling}@anchor{238}
+@anchor{gnat_rm/implementation_advice rm-a-3-2-49-ada-characters-handling}@anchor{23a}
@section RM A.3.2(49): @code{Ada.Characters.Handling}
@@ -14732,7 +14801,7 @@ Followed. GNAT provides no such localized definitions.
@geindex Bounded-length strings
@node RM A 4 4 106 Bounded-Length String Handling,RM A 5 2 46-47 Random Number Generation,RM A 3 2 49 Ada Characters Handling,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-a-4-4-106-bounded-length-string-handling}@anchor{239}
+@anchor{gnat_rm/implementation_advice rm-a-4-4-106-bounded-length-string-handling}@anchor{23b}
@section RM A.4.4(106): Bounded-Length String Handling
@@ -14747,7 +14816,7 @@ Followed. No implicit pointers or dynamic allocation are used.
@geindex Random number generation
@node RM A 5 2 46-47 Random Number Generation,RM A 10 7 23 Get_Immediate,RM A 4 4 106 Bounded-Length String Handling,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-a-5-2-46-47-random-number-generation}@anchor{23a}
+@anchor{gnat_rm/implementation_advice rm-a-5-2-46-47-random-number-generation}@anchor{23c}
@section RM A.5.2(46-47): Random Number Generation
@@ -14776,7 +14845,7 @@ condition here to hold true.
@geindex Get_Immediate
@node RM A 10 7 23 Get_Immediate,RM A 18 Containers,RM A 5 2 46-47 Random Number Generation,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-a-10-7-23-get-immediate}@anchor{23b}
+@anchor{gnat_rm/implementation_advice rm-a-10-7-23-get-immediate}@anchor{23d}
@section RM A.10.7(23): @code{Get_Immediate}
@@ -14800,7 +14869,7 @@ this functionality.
@geindex Containers
@node RM A 18 Containers,RM B 1 39-41 Pragma Export,RM A 10 7 23 Get_Immediate,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-a-18-containers}@anchor{23c}
+@anchor{gnat_rm/implementation_advice rm-a-18-containers}@anchor{23e}
@section RM A.18: @code{Containers}
@@ -14821,7 +14890,7 @@ follow the implementation advice.
@geindex Export
@node RM B 1 39-41 Pragma Export,RM B 2 12-13 Package Interfaces,RM A 18 Containers,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-b-1-39-41-pragma-export}@anchor{23d}
+@anchor{gnat_rm/implementation_advice rm-b-1-39-41-pragma-export}@anchor{23f}
@section RM B.1(39-41): Pragma @code{Export}
@@ -14869,7 +14938,7 @@ Followed.
@geindex Interfaces
@node RM B 2 12-13 Package Interfaces,RM B 3 63-71 Interfacing with C,RM B 1 39-41 Pragma Export,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-b-2-12-13-package-interfaces}@anchor{23e}
+@anchor{gnat_rm/implementation_advice rm-b-2-12-13-package-interfaces}@anchor{240}
@section RM B.2(12-13): Package @code{Interfaces}
@@ -14899,7 +14968,7 @@ Followed. GNAT provides all the packages described in this section.
@geindex interfacing with
@node RM B 3 63-71 Interfacing with C,RM B 4 95-98 Interfacing with COBOL,RM B 2 12-13 Package Interfaces,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-b-3-63-71-interfacing-with-c}@anchor{23f}
+@anchor{gnat_rm/implementation_advice rm-b-3-63-71-interfacing-with-c}@anchor{241}
@section RM B.3(63-71): Interfacing with C
@@ -14987,7 +15056,7 @@ Followed.
@geindex interfacing with
@node RM B 4 95-98 Interfacing with COBOL,RM B 5 22-26 Interfacing with Fortran,RM B 3 63-71 Interfacing with C,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-b-4-95-98-interfacing-with-cobol}@anchor{240}
+@anchor{gnat_rm/implementation_advice rm-b-4-95-98-interfacing-with-cobol}@anchor{242}
@section RM B.4(95-98): Interfacing with COBOL
@@ -15028,7 +15097,7 @@ Followed.
@geindex interfacing with
@node RM B 5 22-26 Interfacing with Fortran,RM C 1 3-5 Access to Machine Operations,RM B 4 95-98 Interfacing with COBOL,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-b-5-22-26-interfacing-with-fortran}@anchor{241}
+@anchor{gnat_rm/implementation_advice rm-b-5-22-26-interfacing-with-fortran}@anchor{243}
@section RM B.5(22-26): Interfacing with Fortran
@@ -15079,7 +15148,7 @@ Followed.
@geindex Machine operations
@node RM C 1 3-5 Access to Machine Operations,RM C 1 10-16 Access to Machine Operations,RM B 5 22-26 Interfacing with Fortran,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-1-3-5-access-to-machine-operations}@anchor{242}
+@anchor{gnat_rm/implementation_advice rm-c-1-3-5-access-to-machine-operations}@anchor{244}
@section RM C.1(3-5): Access to Machine Operations
@@ -15114,7 +15183,7 @@ object that is specified as exported.”
Followed.
@node RM C 1 10-16 Access to Machine Operations,RM C 3 28 Interrupt Support,RM C 1 3-5 Access to Machine Operations,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-1-10-16-access-to-machine-operations}@anchor{243}
+@anchor{gnat_rm/implementation_advice rm-c-1-10-16-access-to-machine-operations}@anchor{245}
@section RM C.1(10-16): Access to Machine Operations
@@ -15175,7 +15244,7 @@ Followed on any target supporting such operations.
@geindex Interrupt support
@node RM C 3 28 Interrupt Support,RM C 3 1 20-21 Protected Procedure Handlers,RM C 1 10-16 Access to Machine Operations,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-3-28-interrupt-support}@anchor{244}
+@anchor{gnat_rm/implementation_advice rm-c-3-28-interrupt-support}@anchor{246}
@section RM C.3(28): Interrupt Support
@@ -15193,7 +15262,7 @@ of interrupt blocking.
@geindex Protected procedure handlers
@node RM C 3 1 20-21 Protected Procedure Handlers,RM C 3 2 25 Package Interrupts,RM C 3 28 Interrupt Support,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-3-1-20-21-protected-procedure-handlers}@anchor{245}
+@anchor{gnat_rm/implementation_advice rm-c-3-1-20-21-protected-procedure-handlers}@anchor{247}
@section RM C.3.1(20-21): Protected Procedure Handlers
@@ -15219,7 +15288,7 @@ Followed. Compile time warnings are given when possible.
@geindex Interrupts
@node RM C 3 2 25 Package Interrupts,RM C 4 14 Pre-elaboration Requirements,RM C 3 1 20-21 Protected Procedure Handlers,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-3-2-25-package-interrupts}@anchor{246}
+@anchor{gnat_rm/implementation_advice rm-c-3-2-25-package-interrupts}@anchor{248}
@section RM C.3.2(25): Package @code{Interrupts}
@@ -15237,7 +15306,7 @@ Followed.
@geindex Pre-elaboration requirements
@node RM C 4 14 Pre-elaboration Requirements,RM C 5 8 Pragma Discard_Names,RM C 3 2 25 Package Interrupts,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-4-14-pre-elaboration-requirements}@anchor{247}
+@anchor{gnat_rm/implementation_advice rm-c-4-14-pre-elaboration-requirements}@anchor{249}
@section RM C.4(14): Pre-elaboration Requirements
@@ -15253,7 +15322,7 @@ Followed. Executable code is generated in some cases, e.g., loops
to initialize large arrays.
@node RM C 5 8 Pragma Discard_Names,RM C 7 2 30 The Package Task_Attributes,RM C 4 14 Pre-elaboration Requirements,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-5-8-pragma-discard-names}@anchor{248}
+@anchor{gnat_rm/implementation_advice rm-c-5-8-pragma-discard-names}@anchor{24a}
@section RM C.5(8): Pragma @code{Discard_Names}
@@ -15271,7 +15340,7 @@ Followed.
@geindex Task_Attributes
@node RM C 7 2 30 The Package Task_Attributes,RM D 3 17 Locking Policies,RM C 5 8 Pragma Discard_Names,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-7-2-30-the-package-task-attributes}@anchor{249}
+@anchor{gnat_rm/implementation_advice rm-c-7-2-30-the-package-task-attributes}@anchor{24b}
@section RM C.7.2(30): The Package Task_Attributes
@@ -15292,7 +15361,7 @@ Not followed. This implementation is not targeted to such a domain.
@geindex Locking Policies
@node RM D 3 17 Locking Policies,RM D 4 16 Entry Queuing Policies,RM C 7 2 30 The Package Task_Attributes,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-d-3-17-locking-policies}@anchor{24a}
+@anchor{gnat_rm/implementation_advice rm-d-3-17-locking-policies}@anchor{24c}
@section RM D.3(17): Locking Policies
@@ -15309,7 +15378,7 @@ whose names (@code{Inheritance_Locking} and
@geindex Entry queuing policies
@node RM D 4 16 Entry Queuing Policies,RM D 6 9-10 Preemptive Abort,RM D 3 17 Locking Policies,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-d-4-16-entry-queuing-policies}@anchor{24b}
+@anchor{gnat_rm/implementation_advice rm-d-4-16-entry-queuing-policies}@anchor{24d}
@section RM D.4(16): Entry Queuing Policies
@@ -15324,7 +15393,7 @@ Followed. No such implementation-defined queuing policies exist.
@geindex Preemptive abort
@node RM D 6 9-10 Preemptive Abort,RM D 7 21 Tasking Restrictions,RM D 4 16 Entry Queuing Policies,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-d-6-9-10-preemptive-abort}@anchor{24c}
+@anchor{gnat_rm/implementation_advice rm-d-6-9-10-preemptive-abort}@anchor{24e}
@section RM D.6(9-10): Preemptive Abort
@@ -15350,7 +15419,7 @@ Followed.
@geindex Tasking restrictions
@node RM D 7 21 Tasking Restrictions,RM D 8 47-49 Monotonic Time,RM D 6 9-10 Preemptive Abort,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-d-7-21-tasking-restrictions}@anchor{24d}
+@anchor{gnat_rm/implementation_advice rm-d-7-21-tasking-restrictions}@anchor{24f}
@section RM D.7(21): Tasking Restrictions
@@ -15369,7 +15438,7 @@ pragma @code{Profile (Restricted)} for more details.
@geindex monotonic
@node RM D 8 47-49 Monotonic Time,RM E 5 28-29 Partition Communication Subsystem,RM D 7 21 Tasking Restrictions,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-d-8-47-49-monotonic-time}@anchor{24e}
+@anchor{gnat_rm/implementation_advice rm-d-8-47-49-monotonic-time}@anchor{250}
@section RM D.8(47-49): Monotonic Time
@@ -15404,7 +15473,7 @@ Followed.
@geindex PCS
@node RM E 5 28-29 Partition Communication Subsystem,RM F 7 COBOL Support,RM D 8 47-49 Monotonic Time,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-e-5-28-29-partition-communication-subsystem}@anchor{24f}
+@anchor{gnat_rm/implementation_advice rm-e-5-28-29-partition-communication-subsystem}@anchor{251}
@section RM E.5(28-29): Partition Communication Subsystem
@@ -15432,7 +15501,7 @@ GNAT.
@geindex COBOL support
@node RM F 7 COBOL Support,RM F 1 2 Decimal Radix Support,RM E 5 28-29 Partition Communication Subsystem,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-f-7-cobol-support}@anchor{250}
+@anchor{gnat_rm/implementation_advice rm-f-7-cobol-support}@anchor{252}
@section RM F(7): COBOL Support
@@ -15452,7 +15521,7 @@ Followed.
@geindex Decimal radix support
@node RM F 1 2 Decimal Radix Support,RM G Numerics,RM F 7 COBOL Support,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-f-1-2-decimal-radix-support}@anchor{251}
+@anchor{gnat_rm/implementation_advice rm-f-1-2-decimal-radix-support}@anchor{253}
@section RM F.1(2): Decimal Radix Support
@@ -15468,7 +15537,7 @@ representations.
@geindex Numerics
@node RM G Numerics,RM G 1 1 56-58 Complex Types,RM F 1 2 Decimal Radix Support,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-g-numerics}@anchor{252}
+@anchor{gnat_rm/implementation_advice rm-g-numerics}@anchor{254}
@section RM G: Numerics
@@ -15488,7 +15557,7 @@ Followed.
@geindex Complex types
@node RM G 1 1 56-58 Complex Types,RM G 1 2 49 Complex Elementary Functions,RM G Numerics,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-g-1-1-56-58-complex-types}@anchor{253}
+@anchor{gnat_rm/implementation_advice rm-g-1-1-56-58-complex-types}@anchor{255}
@section RM G.1.1(56-58): Complex Types
@@ -15550,7 +15619,7 @@ Followed.
@geindex Complex elementary functions
@node RM G 1 2 49 Complex Elementary Functions,RM G 2 4 19 Accuracy Requirements,RM G 1 1 56-58 Complex Types,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-g-1-2-49-complex-elementary-functions}@anchor{254}
+@anchor{gnat_rm/implementation_advice rm-g-1-2-49-complex-elementary-functions}@anchor{256}
@section RM G.1.2(49): Complex Elementary Functions
@@ -15572,7 +15641,7 @@ Followed.
@geindex Accuracy requirements
@node RM G 2 4 19 Accuracy Requirements,RM G 2 6 15 Complex Arithmetic Accuracy,RM G 1 2 49 Complex Elementary Functions,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-g-2-4-19-accuracy-requirements}@anchor{255}
+@anchor{gnat_rm/implementation_advice rm-g-2-4-19-accuracy-requirements}@anchor{257}
@section RM G.2.4(19): Accuracy Requirements
@@ -15596,7 +15665,7 @@ Followed.
@geindex complex arithmetic
@node RM G 2 6 15 Complex Arithmetic Accuracy,RM H 6 15/2 Pragma Partition_Elaboration_Policy,RM G 2 4 19 Accuracy Requirements,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-g-2-6-15-complex-arithmetic-accuracy}@anchor{256}
+@anchor{gnat_rm/implementation_advice rm-g-2-6-15-complex-arithmetic-accuracy}@anchor{258}
@section RM G.2.6(15): Complex Arithmetic Accuracy
@@ -15614,7 +15683,7 @@ Followed.
@geindex Sequential elaboration policy
@node RM H 6 15/2 Pragma Partition_Elaboration_Policy,,RM G 2 6 15 Complex Arithmetic Accuracy,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-h-6-15-2-pragma-partition-elaboration-policy}@anchor{257}
+@anchor{gnat_rm/implementation_advice rm-h-6-15-2-pragma-partition-elaboration-policy}@anchor{259}
@section RM H.6(15/2): Pragma Partition_Elaboration_Policy
@@ -15629,7 +15698,7 @@ immediately terminated.”
Not followed.
@node Implementation Defined Characteristics,Intrinsic Subprograms,Implementation Advice,Top
-@anchor{gnat_rm/implementation_defined_characteristics doc}@anchor{258}@anchor{gnat_rm/implementation_defined_characteristics id1}@anchor{259}@anchor{gnat_rm/implementation_defined_characteristics implementation-defined-characteristics}@anchor{b}
+@anchor{gnat_rm/implementation_defined_characteristics doc}@anchor{25a}@anchor{gnat_rm/implementation_defined_characteristics id1}@anchor{25b}@anchor{gnat_rm/implementation_defined_characteristics implementation-defined-characteristics}@anchor{b}
@chapter Implementation Defined Characteristics
@@ -15705,7 +15774,13 @@ See separate section on source representation.
@itemize *
@item
-“The control functions allowed in comments. See 2.1(14).”
+
+@table @asis
+
+@item “The semantics of an Ada program whose text is not in
+
+Normalization Form C. See 2.1(4).”
+@end table
@end itemize
See separate section on source representation.
@@ -15758,15 +15833,15 @@ not.
@itemize *
@item
-“The sequence of characters of the value returned by
-@code{S'Image} when some of the graphic characters of
-@code{S'Wide_Image} are not defined in @code{Character}. See
-3.5(37).”
+“The message string associated with the Assertion_Error exception raised
+by the failure of a predicate check if there is no applicable
+Predicate_Failure aspect. See 3.2.4(31).”
@end itemize
-The sequence of characters is as defined by the wide character encoding
-method used for the source. See section on source representation for
-further details.
+In the case of a Dynamic_Predicate aspect, the string is
+“Dynamic_Predicate failed at <source position>”, where
+“<source position>” might be something like “foo.adb:123”.
+The Static_Predicate case is handled analogously.
@itemize *
@@ -15925,12 +16000,12 @@ IEEE 80-bit Extended on x86 architecture
@end multitable
-The default rounding mode specified by the IEEE 754 Standard is assumed for
-static computations, i.e. round to nearest, ties to even. The input routines
-yield correctly rounded values for Short_Float, Float and Long_Float at least.
-The output routines can compute up to twice as many exact digits as the value
-of @code{T'Digits} for any type, for example 30 digits for Long_Float; if more
-digits are requested, zeros are printed.
+The default rounding mode specified by the IEEE 754 Standard is assumed both
+for static and dynamic computations (that is, round to nearest, ties to even).
+The input routines yield correctly rounded values for Short_Float, Float, and
+Long_Float at least. The output routines can compute up to twice as many exact
+digits as the value of @code{T'Digits} for any type, for example 30 digits for
+Long_Float; if more digits are requested, zeros are printed.
@itemize *
@@ -15986,6 +16061,19 @@ decimal integer are allocated.
@itemize *
@item
+“The sequence of characters of the value returned by Tags.Expanded_Name
+(respectively, Tags.Wide_Expanded_Name) when some of the graphic
+characters of Tags.Wide_Wide_Expanded_Name are not defined in Character
+(respectively, Wide_Character). See 3.9(10.1).”
+@end itemize
+
+This is handled in the same way as the implementation-defined behavior
+referenced in A.4.12(34).
+
+
+@itemize *
+
+@item
“Implementation-defined attributes. See 4.1.4(12).”
@end itemize
@@ -15995,6 +16083,90 @@ See @ref{8,,Implementation Defined Attributes}.
@itemize *
@item
+“The value of the parameter to Empty for some container aggregates.
+See 4.3.5(40).”
+@end itemize
+
+As per the suggestion given in the Annotated Ada RM, the default value
+of the formal parameter is used if one exists and zero is used otherwise.
+
+
+@itemize *
+
+@item
+“The maximum number of chunks for a parallel reduction expression without
+a chunk_specification. See 4.5.10(21).”
+@end itemize
+
+Feature unimplemented.
+
+
+@itemize *
+
+@item
+“Rounding of real static expressions which are exactly half-way between
+two machine numbers. See 4.9(38).”
+@end itemize
+
+Round to even is used in all such cases.
+
+
+@itemize *
+
+@item
+
+@table @asis
+
+@item “The maximum number of chunks for a parallel generalized iterator without
+
+a chunk_specification. See 5.5.2(10).”
+@end table
+@end itemize
+
+Feature unimplemented.
+
+
+@itemize *
+
+@item
+“The number of chunks for an array component iterator. See 5.5.2(11).”
+@end itemize
+
+Feature unimplemented.
+
+
+@itemize *
+
+@item
+“Any extensions of the Global aspect. See 6.1.2(43).”
+@end itemize
+
+Feature unimplemented.
+
+
+@itemize *
+
+@item
+“The circumstances the implementation passes in the null value for a view
+conversion of an access type used as an out parameter. See 6.4.1(19).”
+@end itemize
+
+Difficult to characterize.
+
+
+@itemize *
+
+@item
+“Any extensions of the Default_Initial_Condition aspect. See 7.3.3(11).”
+@end itemize
+
+SPARK allows specifying @emph{null} as the Default_Initial_Condition
+aspect of a type. See the SPARK reference manual for further details.
+
+
+@itemize *
+
+@item
“Any implementation-defined time types. See 9.6(6).”
@end itemize
@@ -16004,7 +16176,7 @@ There are no implementation-defined time types.
@itemize *
@item
-“The time base associated with relative delays.”
+“The time base associated with relative delays. See 9.6(20).”
@end itemize
See 9.6(20). The time base used is that provided by the C library
@@ -16014,8 +16186,7 @@ function @code{gettimeofday}.
@itemize *
@item
-“The time base of the type @code{Calendar.Time}. See
-9.6(23).”
+“The time base of the type @code{Calendar.Time}. See 9.6(23).”
@end itemize
The time base used is that provided by the C library function
@@ -16047,14 +16218,25 @@ There are no such limits.
@itemize *
@item
-“Whether or not two non-overlapping parts of a composite
-object are independently addressable, in the case where packing, record
-layout, or @code{Component_Size} is specified for the object. See
-9.10(1).”
+
+@table @asis
+
+@item “The result of Calendar.Formatting.Image if its argument represents more
+
+than 100 hours. See 9.6.1(86).”
+@end table
+@end itemize
+
+Calendar.Time_Error is raised.
+
+
+@itemize *
+
+@item
+“Implementation-defined conflict check policies. See 9.10.1(5).”
@end itemize
-Separate components are independently addressable if they do not share
-overlapping storage units.
+There are no implementation-defined conflict check policies.
@itemize *
@@ -16119,9 +16301,8 @@ options, refer to @emph{GNAT Make Program gnatmake} in the
@itemize *
@item
-“The implementation-defined means, if any, of specifying
-which compilation units are needed by a given compilation unit. See
-10.2(2).”
+“The implementation-defined means, if any, of specifying which compilation
+units are needed by a given compilation unit. See 10.2(2).”
@end itemize
The units needed by a given compilation unit are as defined in
@@ -16144,18 +16325,14 @@ corresponding @code{ALI} file as the input parameter to the binder.
@itemize *
@item
-“The order of elaboration of @emph{library_items}. See
-10.2(18).”
+“The order of elaboration of @emph{library_items}. See 10.2(18).”
@end itemize
The first constraint on ordering is that it meets the requirements of
Chapter 10 of the Ada Reference Manual. This still leaves some
-implementation dependent choices, which are resolved by first
-elaborating bodies as early as possible (i.e., in preference to specs
-where there is a choice), and second by evaluating the immediate with
-clauses of a unit to determine the probably best choice, and
-third by elaborating in alphabetical order of unit names
-where a choice still remains.
+implementation-dependent choices, which are resolved by analyzing
+the elaboration code of each unit and identifying implicit
+elaboration-order dependencies.
@itemize *
@@ -16174,14 +16351,13 @@ may have been set by a call to @code{Ada.Command_Line.Set_Exit_Status}).
@itemize *
@item
-“The mechanisms for building and running partitions. See
-10.2(24).”
+“The mechanisms for building and running partitions. See 10.2(24).”
@end itemize
-GNAT itself supports programs with only a single partition. The GNATDIST
+GNAT itself supports programs with only a single partition. The GNATDIST
tool provided with the GLADE package (which also includes an implementation
of the PCS) provides a completely flexible method for building and running
-programs consisting of multiple partitions. See the separate GLADE manual
+programs consisting of multiple partitions. See the separate GLADE manual
for details.
@@ -16203,15 +16379,14 @@ implementation. See 10.2(28).”
@end itemize
Passive partitions are supported on targets where shared memory is
-provided by the operating system. See the GLADE reference manual for
+provided by the operating system. See the GLADE reference manual for
further details.
@itemize *
@item
-“The information returned by @code{Exception_Message}. See
-11.4.1(10).”
+“The information returned by @code{Exception_Message}. See 11.4.1(10).”
@end itemize
Exception message returns the null string unless a specific message has
@@ -16282,6 +16457,54 @@ the last line is a single @code{LF} character (@code{16#0A#}).
@itemize *
@item
+“The sequence of characters of the value returned by
+Exceptions.Exception_Name (respectively, Exceptions.Wide_Exception_Name)
+when some of the graphic characters of Exceptions.Wide_Wide_Exception_Name
+are not defined in Character (respectively, Wide_Character).
+See 11.4.1(12.1).”
+@end itemize
+
+This is handled in the same way as the implementation-defined behavior
+referenced in A.4.12(34).
+
+
+@itemize *
+
+@item
+“The information returned by Exception_Information. See 11.4.1(13).”
+@end itemize
+
+The exception name and the source location at which the exception was
+raised are included.
+
+
+@itemize *
+
+@item
+“Implementation-defined policy_identifiers and assertion_aspect_marks
+allowed in a pragma Assertion_Policy. See 11.4.2(9).”
+@end itemize
+
+Implementation-defined assertion_aspect_marks include Assert_And_Cut,
+Assume, Contract_Cases, Debug, Ghost, Initial_Condition, Loop_Invariant,
+Loop_Variant, Postcondition, Precondition, Predicate, Refined_Post,
+Statement_Assertions, and Subprogram_Variant. Implementation-defined
+policy_identifiers include Ignore and Suppressible.
+
+
+@itemize *
+
+@item
+“The default assertion policy. See 11.4.2(10).”
+@end itemize
+
+The default assertion policy is Ignore, although this can be overridden
+via compiler switches such as “-gnata”.
+
+
+@itemize *
+
+@item
“Implementation-defined check names. See 11.5(27).”
@end itemize
@@ -16295,8 +16518,33 @@ Check_Name. See the description of pragma @code{Suppress} for full details.
@itemize *
@item
-“The interpretation of each aspect of representation. See
-13.1(20).”
+“Existence and meaning of second parameter of pragma Unsuppress.
+See 11.5(27.1).”
+@end itemize
+
+The legality rules for and semantics of the second parameter of pragma
+Unsuppress match those for the second argument of pragma Suppress.
+
+
+@itemize *
+
+@item
+
+@table @asis
+
+@item “The cases that cause conflicts between the representation of the
+
+ancestors of a type_declaration. See 13.1(13.1).”
+@end table
+@end itemize
+
+No such cases exist.
+
+
+@itemize *
+
+@item
+“The interpretation of each representation aspect. See 13.1(20).”
@end itemize
See separate section on data representations.
@@ -16305,8 +16553,8 @@ See separate section on data representations.
@itemize *
@item
-“Any restrictions placed upon representation items. See
-13.1(20).”
+“Any restrictions placed upon the specification of representation aspects.
+See 13.1(20).”
@end itemize
See separate section on data representations.
@@ -16315,20 +16563,46 @@ See separate section on data representations.
@itemize *
@item
-“The meaning of @code{Size} for indefinite subtypes. See
-13.3(48).”
+“Implementation-defined aspects, including the syntax for specifying
+such aspects and the legality rules for such aspects. See 13.1.1(38).”
+@end itemize
+
+See @ref{121,,Implementation Defined Aspects}.
+
+
+@itemize *
+
+@item
+“The set of machine scalars. See 13.3(8.1).”
@end itemize
-Size for an indefinite subtype is the maximum possible size, except that
-for the case of a subprogram parameter, the size of the parameter object
-is the actual size.
+See separate section on data representations.
@itemize *
@item
-“The default external representation for a type tag. See
-13.3(75).”
+“The meaning of @code{Size} for indefinite subtypes. See 13.3(48).”
+@end itemize
+
+The Size attribute of an indefinite subtype is not less than the Size
+attribute of any object of that type.
+
+
+@itemize *
+
+@item
+“The meaning of Object_Size for indefinite subtypes. See 13.3(58).”
+@end itemize
+
+The Object_Size attribute of an indefinite subtype is not less than the
+Object_Size attribute of any object of that type.
+
+
+@itemize *
+
+@item
+“The default external representation for a type tag. See 13.3(75).”
@end itemize
The default external representation for a type tag is the fully expanded
@@ -16371,13 +16645,11 @@ bit ordering corresponds to the natural endianness of the target architecture.
@itemize *
@item
-“The contents of the visible part of package @code{System}
-and its language-defined children. See 13.7(2).”
+“The contents of the visible part of package @code{System}. See 13.7(2).”
@end itemize
-See the definition of these packages in files @code{system.ads} and
-@code{s-stoele.ads}. Note that two declarations are added to package
-System.
+See the definition of package System in @code{system.ads}.
+Note that two declarations are added to package System.
@example
Max_Priority : constant Positive := Priority'Last;
@@ -16388,9 +16660,19 @@ Max_Interrupt_Priority : constant Positive := Interrupt_Priority'Last;
@itemize *
@item
-“The contents of the visible part of package
-@code{System.Machine_Code}, and the meaning of
-@emph{code_statements}. See 13.8(7).”
+“The range of Storage_Elements.Storage_Offset, the modulus of
+Storage_Elements.Storage_Element, and the declaration of
+Storage_Elements.Integer_Address. See 13.7.1(11).”
+@end itemize
+
+See the definition of package System.Storage_Elements in @code{s-stoele.ads}.
+
+
+@itemize *
+
+@item
+“The contents of the visible part of package @code{System.Machine_Code},
+and the meaning of @emph{code_statements}. See 13.8(7).”
@end itemize
See the definition and documentation in file @code{s-maccod.ads}.
@@ -16399,7 +16681,8 @@ See the definition and documentation in file @code{s-maccod.ads}.
@itemize *
@item
-“The effect of unchecked conversion. See 13.9(11).”
+“The result of unchecked conversion for instances with scalar result
+types whose result is not defined by the language. See 13.9(11).”
@end itemize
Unchecked conversion between types of the same size
@@ -16420,65 +16703,36 @@ made with appropriate alignment
@itemize *
@item
-“The semantics of operations on invalid representations.
-See 13.9.2(10-11).”
+“The result of unchecked conversion for instances with nonscalar result
+types whose result is not defined by the language. See 13.9(11).”
@end itemize
-For assignments and other operations where the use of invalid values cannot
-result in erroneous behavior, the compiler ignores the possibility of invalid
-values. An exception is raised at the point where an invalid value would
-result in erroneous behavior. For example executing:
-
-@example
-procedure invalidvals is
- X : Integer := -1;
- Y : Natural range 1 .. 10;
- for Y'Address use X'Address;
- Z : Natural range 1 .. 10;
- A : array (Natural range 1 .. 10) of Integer;
-begin
- Z := Y; -- no exception
- A (Z) := 3; -- exception raised;
-end;
-@end example
-
-As indicated, an exception is raised on the array assignment, but not
-on the simple assignment of the invalid negative value from Y to Z.
+See preceding definition for the scalar result case.
@itemize *
@item
-“The manner of choosing a storage pool for an access type
-when @code{Storage_Pool} is not specified for the type. See 13.11(17).”
+“Whether or not the implementation provides user-accessible
+names for the standard pool type(s). See 13.11(17).”
@end itemize
There are 3 different standard pools used by the compiler when
@code{Storage_Pool} is not specified depending whether the type is local
to a subprogram or defined at the library level and whether
-@code{Storage_Size`@w{`}is specified or not. See documentation in the runtime
+@code{Storage_Size`@w{`}is specified or not. See documentation in the runtime
library units `@w{`}System.Pool_Global}, @code{System.Pool_Size} and
@code{System.Pool_Local} in files @code{s-poosiz.ads},
@code{s-pooglo.ads} and @code{s-pooloc.ads} for full details on the
-default pools used.
-
-
-@itemize *
-
-@item
-“Whether or not the implementation provides user-accessible
-names for the standard pool type(s). See 13.11(17).”
-@end itemize
-
-See documentation in the sources of the run time mentioned in the previous
-paragraph. All these pools are accessible by means of @cite{with}ing
+default pools used. All these pools are accessible by means of @cite{with}ing
these units.
@itemize *
@item
-“The meaning of @code{Storage_Size}. See 13.11(18).”
+“The meaning of @code{Storage_Size} when neither the Storage_Size nor the
+Storage_Pool is specified for an access type. See 13.11(18).”
@end itemize
@code{Storage_Size} is measured in storage units, and refers to the
@@ -16489,20 +16743,19 @@ stack space for a task.
@itemize *
@item
-“Implementation-defined aspects of storage pools. See
-13.11(22).”
+“The effect of specifying aspect Default_Storage_Pool on an instance
+of a language-defined generic unit. See 13.11.3(5).”
@end itemize
-See documentation in the sources of the run time mentioned in the
-paragraph about standard storage pools above
-for details on GNAT-defined aspects of storage pools.
+Instances of language-defined generic units are treated the same as other
+instances with respect to the Default_Storage_Pool aspect.
@itemize *
@item
-“The set of restrictions allowed in a pragma
-@code{Restrictions}. See 13.12(7).”
+“Implementation-defined restrictions allowed in a pragma
+@code{Restrictions}. See 13.12(8.7).”
@end itemize
See @ref{9,,Standard and Implementation Defined Restrictions}.
@@ -16515,17 +16768,26 @@ See @ref{9,,Standard and Implementation Defined Restrictions}.
@code{Restrictions} pragmas. See 13.12(9).”
@end itemize
-Restrictions that can be checked at compile time result in illegalities
-if violated. Currently there are no other consequences of violating
-restrictions.
+Restrictions that can be checked at compile time are enforced at
+compile time; violations are illegal. For other restrictions, any
+violation during program execution results in erroneous execution.
+
+
+@itemize *
+
+@item
+“Implementation-defined usage profiles allowed in a pragma Profile.
+See 13.12(15).”
+@end itemize
+
+See @ref{7,,Implementation Defined Pragmas}.
@itemize *
@item
-“The representation used by the @code{Read} and
-@code{Write} attributes of elementary types in terms of stream
-elements. See 13.13.2(9).”
+“The contents of the stream elements read and written by the Read and
+Write attributes of elementary types. See 13.13.2(9).”
@end itemize
The representation is the in-memory representation of the base type of
@@ -16546,13 +16808,38 @@ See items describing the integer and floating-point types supported.
@itemize *
@item
-“The string returned by @code{Character_Set_Version}.
-See A.3.5(3).”
+“The values returned by Strings.Hash. See A.4.9(3).”
+@end itemize
+
+This hash function has predictable collisions and is subject to
+equivalent substring attacks. It is not suitable for construction of a
+hash table keyed on possibly malicious user input.
+
+
+@itemize *
+
+@item
+“The value returned by a call to a Text_Buffer Get procedure if any
+character in the returned sequence is not defined in Character.
+See A.4.12(34).”
+@end itemize
+
+The contents of a buffer is represented internally as a UTF_8 string.
+The value return by Text_Buffer.Get is the result of passing that
+UTF_8 string to UTF_Encoding.Strings.Decode.
+
+
+@itemize *
+
+@item
+“The value returned by a call to a Text_Buffer Wide_Get procedure if
+any character in the returned sequence is not defined in Wide_Character.
+See A.4.12(34).”
@end itemize
-@code{Ada.Wide_Characters.Handling.Character_Set_Version} returns
-the string “Unicode 4.0”, referring to version 4.0 of the
-Unicode specification.
+The contents of a buffer is represented internally as a UTF_8 string.
+The value return by Text_Buffer.Wide_Get is the result of passing that
+UTF_8 string to UTF_Encoding.Wide_Strings.Decode.
@itemize *
@@ -16601,18 +16888,6 @@ Maximum image width is 6864, see library file @code{s-rannum.ads}.
@itemize *
@item
-“The algorithms for random number generation. See
-A.5.2(32).”
-@end itemize
-
-The algorithm is the Mersenne Twister, as documented in the source file
-@code{s-rannum.adb}. This version of the algorithm has a period of
-2**19937-1.
-
-
-@itemize *
-
-@item
“The string representation of a random number generator’s
state. See A.5.2(38).”
@end itemize
@@ -16625,44 +16900,20 @@ of the state vector.
@itemize *
@item
-“The minimum time interval between calls to the
-time-dependent Reset procedure that are guaranteed to initiate different
-random number sequences. See A.5.2(45).”
-@end itemize
-
-The minimum period between reset calls to guarantee distinct series of
-random numbers is one microsecond.
-
-
-@itemize *
-
-@item
“The values of the @code{Model_Mantissa},
@code{Model_Emin}, @code{Model_Epsilon}, @code{Model},
@code{Safe_First}, and @code{Safe_Last} attributes, if the Numerics
Annex is not supported. See A.5.3(72).”
@end itemize
-Run the compiler with @emph{-gnatS} to produce a listing of package
-@code{Standard}, has the values of all numeric attributes.
-
-
-@itemize *
-
-@item
-“Any implementation-defined characteristics of the
-input-output packages. See A.7(14).”
-@end itemize
-
-There are no special implementation defined characteristics for these
-packages.
+Running the compiler with @emph{-gnatS} to produce a listing of package
+@code{Standard} displays the values of these attributes.
@itemize *
@item
-“The value of @code{Buffer_Size} in @code{Storage_IO}. See
-A.9(10).”
+“The value of @code{Buffer_Size} in @code{Storage_IO}. See A.9(10).”
@end itemize
All type representations are contiguous, and the @code{Buffer_Size} is
@@ -16678,14 +16929,13 @@ standard error See A.10(5).”
@end itemize
These files are mapped onto the files provided by the C streams
-libraries. See source file @code{i-cstrea.ads} for further details.
+libraries. See source file @code{i-cstrea.ads} for further details.
@itemize *
@item
-“The accuracy of the value produced by @code{Put}. See
-A.10.9(36).”
+“The accuracy of the value produced by @code{Put}. See A.10.9(36).”
@end itemize
If more digits are requested in the output than are represented by the
@@ -16696,168 +16946,140 @@ significant digit positions.
@itemize *
@item
-“The meaning of @code{Argument_Count}, @code{Argument}, and
-@code{Command_Name}. See A.15(1).”
+“Current size for a stream file for which positioning is not supported.
+See A.12.1(1.1).”
@end itemize
-These are mapped onto the @code{argv} and @code{argc} parameters of the
-main program in the natural manner.
+Positioning is supported.
@itemize *
@item
-“The interpretation of the @code{Form} parameter in procedure
-@code{Create_Directory}. See A.16(56).”
+“The meaning of @code{Argument_Count}, @code{Argument}, and
+@code{Command_Name}. See A.15(1).”
@end itemize
-The @code{Form} parameter is not used.
+These are mapped onto the @code{argv} and @code{argc} parameters of the
+main program in the natural manner.
@itemize *
@item
-“The interpretation of the @code{Form} parameter in procedure
-@code{Create_Path}. See A.16(60).”
+“The interpretation of file names and directory names. See A.16(46).”
@end itemize
-The @code{Form} parameter is not used.
+These names are interpreted consistently with the underlying file system.
@itemize *
@item
-“The interpretation of the @code{Form} parameter in procedure
-@code{Copy_File}. See A.16(68).”
+“The maxium value for a file size in Directories. See A.16(87).”
@end itemize
-The @code{Form} parameter is case-insensitive.
-Two fields are recognized in the @code{Form} parameter:
-
-@example
-*preserve=<value>*
-*mode=<value>*
-@end example
-
-<value> starts immediately after the character ‘=’ and ends with the
-character immediately preceding the next comma (‘,’) or with the last
-character of the parameter.
-
-The only possible values for preserve= are:
-
-
-@multitable {xxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
-@headitem
-
-Value
+Directories.File_Size’Last is equal to Long_Long_Integer’Last .
-@tab
-
-Meaning
-@item
-
-@emph{no_attributes}
+@itemize *
-@tab
+@item
-Do not try to preserve any file attributes. This is the
-default if no preserve= is found in Form.
+@table @asis
-@item
+@item “The result for Directories.Size for a directory or special file.
-@emph{all_attributes}
+See A.16(93).”
+@end table
+@end itemize
-@tab
+Name_Error is raised.
-Try to preserve all file attributes (timestamps, access rights).
-@item
+@itemize *
-@emph{timestamps}
+@item
-@tab
+@table @asis
-Preserve the timestamp of the copied file, but not the other
-file attributes.
+@item “The result for Directories.Modification_Time for a directory or special file.
-@end multitable
+See A.16(93).”
+@end table
+@end itemize
+Name_Error is raised.
-The only possible values for mode= are:
+@itemize *
-@multitable {xxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
-@headitem
+@item
-Value
+@table @asis
-@tab
+@item “The interpretation of a nonnull search pattern in Directories.
-Meaning
+See A.16(104).”
+@end table
+@end itemize
-@item
+When the @code{Pattern} parameter is not the null string, it is interpreted
+according to the syntax of regular expressions as defined in the
+@code{GNAT.Regexp} package.
-@emph{copy}
+See @ref{25c,,GNAT.Regexp (g-regexp.ads)}.
-@tab
-Only do the copy if the destination file does not already exist.
-If it already exists, Copy_File fails.
+@itemize *
-@item
+@item
-@emph{overwrite}
+@table @asis
-@tab
+@item “The results of a Directories search if the contents of the directory are
-Copy the file in all cases. Overwrite an already existing destination file.
+altered while a search is in progress. See A.16(110).”
+@end table
+@end itemize
-@item
+The effect of a call to Get_Next_Entry is determined by the current
+state of the directory.
-@emph{append}
-@tab
+@itemize *
-Append the original file to the destination file. If the destination file
-does not exist, the destination file is a copy of the source file.
-When mode=append, the field preserve=, if it exists, is not taken into account.
+@item
+“The definition and meaning of an environment variable. See A.17(1).”
+@end itemize
-@end multitable
+This definition is determined by the underlying operating system.
-If the Form parameter includes one or both of the fields and the value or
-values are incorrect, Copy_file fails with Use_Error.
+@itemize *
-Examples of correct Forms:
+@item
+“The circumstances where an environment variable cannot be defined.
+See A.17(16).”
-@example
-Form => "preserve=no_attributes,mode=overwrite" (the default)
-Form => "mode=append"
-Form => "mode=copy, preserve=all_attributes"
-@end example
+There are no such implementation-defined circumstances.
-Examples of incorrect Forms:
+@item
+“Environment names for which Set has the effect of Clear. See A.17(17).”
+@end itemize
-@example
-Form => "preserve=junk"
-Form => "mode=internal, preserve=timestamps"
-@end example
+There are no such names.
@itemize *
@item
-“The interpretation of the @code{Pattern} parameter, when not the null string,
-in the @code{Start_Search} and @code{Search} procedures.
-See A.16(104) and A.16(112).”
+“The value of Containers.Hash_Type’Modulus. The value of
+Containers.Count_Type’Last. See A.18.1(7).”
@end itemize
-When the @code{Pattern} parameter is not the null string, it is interpreted
-according to the syntax of regular expressions as defined in the
-@code{GNAT.Regexp} package.
-
-See @ref{25a,,GNAT.Regexp (g-regexp.ads)}.
+Containers.Hash_Type’Modulus is 2**32.
+Containers.Count_Type’Last is 2**31 - 1.
@itemize *
@@ -17055,9 +17277,8 @@ Link names are the actual names used by the linker.
@itemize *
@item
-“The manner of choosing link names when neither the link
-name nor the address of an imported or exported entity is specified. See
-B.1(36).”
+“The manner of choosing link names when neither the link name nor the
+address of an imported or exported entity is specified. See B.1(36).”
@end itemize
The default linker name is that which would be assigned by the relevant
@@ -17110,6 +17331,16 @@ See files with prefix @code{i-} in the distributed library.
@itemize *
@item
+“The definitions of certain types and constants in Interfaces.C.
+See B.3(41).”
+@end itemize
+
+See source file @code{i-c.ads}.
+
+
+@itemize *
+
+@item
“The types @code{Floating}, @code{Long_Floating},
@code{Binary}, @code{Long_Binary}, @code{Decimal_ Element}, and
@code{COBOL_Character}; and the initialization of the variables
@@ -17184,65 +17415,87 @@ For initialization, see the file @code{i-cobol.ads} in the distributed library.
@itemize *
@item
-“Support for access to machine instructions. See C.1(1).”
+“The types Fortran_Integer, Real, Double_Precision, and Character_Set
+in Interfaces.Fortran. See B.5(17).”
@end itemize
-See documentation in file @code{s-maccod.ads} in the distributed library.
+See source file @code{i-fortra.ads}. These types are derived, respectively,
+from Integer, Float, Long_Float, and Character.
@itemize *
@item
-“Implementation-defined aspects of access to machine
-operations. See C.1(9).”
+“Implementation-defined intrinsic subprograms. See C.1(1).”
@end itemize
-See documentation in file @code{s-maccod.ads} in the distributed library.
+See separate section on Intrinsic Subprograms.
@itemize *
@item
-“Implementation-defined aspects of interrupts. See C.3(2).”
+“Any restrictions on a protected procedure or its containing type when an
+aspect Attach_handler or Interrupt_Handler is specified. See C.3.1(17).”
@end itemize
-Interrupts are mapped to signals or conditions as appropriate. See
-definition of unit
-@code{Ada.Interrupt_Names} in source file @code{a-intnam.ads} for details
-on the interrupts supported on a particular target.
+There are no such restrictions.
@itemize *
@item
-“Implementation-defined aspects of pre-elaboration. See
-C.4(13).”
+“Any other forms of interrupt handler supported by the Attach_Handler and
+Interrupt_Handler aspects. See C.3.1(19).”
@end itemize
-GNAT does not permit a partition to be restarted without reloading,
-except under control of the debugger.
+There are no such forms.
@itemize *
@item
-“The semantics of pragma @code{Discard_Names}. See C.5(7).”
+
+@table @asis
+
+@item “The semantics of some attributes and functions of an entity for which
+
+aspect Discard_Names is True. See C.5(7).”
+@end table
@end itemize
-Pragma @code{Discard_Names} causes names of enumeration literals to
-be suppressed. In the presence of this pragma, the Image attribute
+If Discard_Names is True for an enumeration type, the Image attribute
provides the image of the Pos of the literal, and Value accepts
Pos values.
-For tagged types, when pragmas @code{Discard_Names} and @code{No_Tagged_Streams}
-simultaneously apply, their Expanded_Name and External_Tag are initialized
-with empty strings. This is useful to avoid exposing entity names at binary
+If both of the aspects`@w{`}Discard_Names`@w{`} and @code{No_Tagged_Streams} are true
+for a tagged type, its Expanded_Name and External_Tag values are
+empty strings. This is useful to avoid exposing entity names at binary
level.
@itemize *
@item
+“The modulus and size of Test_and_Set_Flag. See C.6.3(8).”
+@end itemize
+
+The modulus is 2**8. The size is 8.
+
+
+@itemize *
+
+@item
+“The value used to represent the set value for Atomic_Test_and_Set.
+See C.6.3(10).”
+@end itemize
+
+The value is 1.
+
+
+@itemize *
+
+@item
“The result of the @code{Task_Identification.Image}
attribute. See C.7.1(7).”
@end itemize
@@ -17286,41 +17539,12 @@ convenient thread, so the value of @code{Current_Task} is undefined.
@itemize *
@item
-“The effect of calling @code{Current_Task} from an entry
-body or interrupt handler. See C.7.1(19).”
-@end itemize
-
-When GNAT can determine statically that @code{Current_Task} is called directly in
-the body of an entry (or barrier) then a warning is emitted and @code{Program_Error}
-is raised at run time. Otherwise, the effect of calling @code{Current_Task} from an
-entry body or interrupt handler is to return the identification of the task
-currently executing the code.
-
-
-@itemize *
-
-@item
-“Implementation-defined aspects of
-@code{Task_Attributes}. See C.7.2(19).”
-@end itemize
-
-There are no implementation-defined aspects of @code{Task_Attributes}.
-
-
-@itemize *
-
-@item
-“Values of all @code{Metrics}. See D(2).”
+“Granularity of locking for Task_Attributes. See C.7.2(16).”
@end itemize
-The metrics information for GNAT depends on the performance of the
-underlying operating system. The sources of the run-time for tasking
-implementation, together with the output from @emph{-gnatG} can be
-used to determine the exact sequence of operating systems calls made
-to implement various tasking constructs. Together with appropriate
-information on the performance of the underlying operating system,
-on the exact target in use, this information can be used to determine
-the required metrics.
+No locking is needed if the formal type Attribute has the size and
+alignment of either Integer or System.Address and the bit representation
+of Initial_Value is all zeroes. Otherwise, locking is performed.
@itemize *
@@ -17368,32 +17592,19 @@ underlying operating system.
@itemize *
@item
-“Implementation-defined @emph{policy_identifiers} allowed
-in a pragma @code{Task_Dispatching_Policy}. See D.2.2(3).”
-@end itemize
-
-There are no implementation-defined policy-identifiers allowed in this
-pragma.
-
-
-@itemize *
-
-@item
-“Implementation-defined aspects of priority inversion. See
-D.2.2(16).”
+“Implementation-defined task dispatching policies. See D.2.2(3).”
@end itemize
-Execution of a task cannot be preempted by the implementation processing
-of delay expirations for lower priority tasks.
+There are no implementation-defined task dispatching policies.
@itemize *
@item
-“Implementation-defined task dispatching. See D.2.2(18).”
+“The value of Default_Quantum in Dispatching.Round_Robin. See D.2.5(4).”
@end itemize
-The policy is the same as that of the underlying threads implementation.
+The value is 10 milliseconds.
@itemize *
@@ -17448,13 +17659,10 @@ There are no implementation-defined queuing policies.
@itemize *
@item
-“On a multiprocessor, any conditions that cause the
-completion of an aborted construct to be delayed later than what is
-specified for a single processor. See D.6(3).”
+“Implementation-defined admission policies. See D.4.1(1).”
@end itemize
-The semantics for abort on a multi-processor is the same as on a single
-processor, there are no further delays.
+There are no implementation-defined admission policies.
@itemize *
@@ -17471,8 +17679,39 @@ task creation.
@itemize *
@item
-“What happens when a task terminates in the presence of
-pragma @code{No_Task_Termination}. See D.7(15).”
+“When restriction No_Dynamic_CPU_Assignment applies to a partition, the
+processor on which a task with a CPU value of a Not_A_Specific_CPU will
+execute. See D.7(10).”
+@end itemize
+
+Unknown.
+
+
+@itemize *
+
+@item
+
+@table @asis
+
+@item “When restriction No_Task_Termination applies to a partition, what happens
+
+when a task terminates. See D.7(15.1).”
+@end table
+@end itemize
+
+Execution is erroneous in that case.
+
+
+@itemize *
+
+@item
+
+@table @asis
+
+@item “The behavior when restriction Max_Storage_At_Blocking is violated.
+
+See D.7(17).”
+@end table
@end itemize
Execution is erroneous in that case.
@@ -17481,43 +17720,85 @@ Execution is erroneous in that case.
@itemize *
@item
-“Implementation-defined aspects of pragma
-@code{Restrictions}. See D.7(20).”
+“The behavior when restriction Max_Asynchronous_Select_Nesting is violated.
+See D.7(18).”
+@end itemize
+
+Execution is erroneous in that case.
+
+
+@itemize *
+
+@item
+“The behavior when restriction Max_Tasks is violated. See D.7(19).”
+@end itemize
+
+Execution is erroneous in that case.
+
+
+@itemize *
+
+@item
+
+@table @asis
+
+@item “Whether the use of pragma Restrictions results in a reduction in program
+
+code or data size or execution time. See D.7(20).”
+
+Yes it can, but the precise circumstances and properties of such reductions
+are difficult to characterize.
+@end table
+
+@item
+“The value of Barrier_Limit’Last in Synchronous_Barriers. See D.10.1(4).”
+@end itemize
+
+Synchronous_Barriers.Barrier_Limit’Last is Integer’Last .
+
+
+@itemize *
+
+@item
+“When an aborted task that is waiting on a Synchronous_Barrier is aborted.
+See D.10.1(13).”
@end itemize
-There are no such implementation-defined aspects.
+Difficult to characterize.
@itemize *
@item
-“Implementation-defined aspects of package
-@code{Real_Time}. See D.8(17).”
+
+@table @asis
+
+@item “The value of Min_Handler_Ceiling in Execution_Time.Group_Budgets.
+
+See D.14.2(7).”
+@end table
@end itemize
-There are no implementation defined aspects of package @code{Real_Time}.
+See source file @code{a-etgrbu.ads}.
@itemize *
@item
-“Implementation-defined aspects of
-@emph{delay_statements}. See D.9(8).”
+“The value of CPU_Range’Last in System.Multiprocessors. See D.16(4).”
@end itemize
-Any difference greater than one microsecond will cause the task to be
-delayed (see D.9(7)).
+See source file @code{s-multip.ads}.
@itemize *
@item
-“The upper bound on the duration of interrupt blocking
-caused by the implementation. See D.12(5).”
+“The processor on which the environment task executes in the absence
+of a value for the aspect CPU. See D.16(13).”
@end itemize
-The upper bound is determined by the underlying operating system. In
-no cases is it more than 10 milliseconds.
+Unknown.
@itemize *
@@ -17528,7 +17809,7 @@ programs. See E(5).”
@end itemize
The GLADE package provides a utility GNATDIST for creating and executing
-distributed programs. See the GLADE reference manual for further details.
+distributed programs. See the GLADE reference manual for further details.
@itemize *
@@ -17544,9 +17825,8 @@ See the GLADE reference manual for full details on such events.
@itemize *
@item
-“The scheduling policies, treatment of priorities, and
-management of shared resources between partitions in certain cases. See
-E.1(11).”
+“The scheduling policies, treatment of priorities, and management of
+shared resources between partitions in certain cases. See E.1(11).”
@end itemize
See the GLADE reference manual for full details on these aspects of
@@ -17556,20 +17836,6 @@ multi-partition execution.
@itemize *
@item
-“Events that cause the version of a compilation unit to
-change. See E.3(5).”
-@end itemize
-
-Editing the source file of a compilation unit, or the source files of
-any units on which it is dependent in a significant way cause the version
-to change. No other actions cause the version number to change. All changes
-are significant except those which affect only layout, capitalization or
-comments.
-
-
-@itemize *
-
-@item
“Whether the execution of the remote subprogram is
immediately aborted as a result of cancellation. See E.4(13).”
@end itemize
@@ -17581,18 +17847,16 @@ a distributed application.
@itemize *
@item
-“Implementation-defined aspects of the PCS. See E.5(25).”
+“The range of type System.RPC.Partition_Id. See E.5(14).”
@end itemize
-See the GLADE reference manual for a full description of all implementation
-defined aspects of the PCS.
+System.RPC.Partion_ID’Last is Integer’Last. See source file @code{s-rpc.ads}.
@itemize *
@item
-“Implementation-defined interfaces in the PCS. See
-E.5(26).”
+“Implementation-defined interfaces in the PCS. See E.5(26).”
@end itemize
See the GLADE reference manual for a full description of all
@@ -17770,9 +18034,8 @@ Not relevant, division is IEEE exact.
@itemize *
@item
-“The definition of close result set, which determines the
-accuracy of certain fixed point multiplications and divisions. See
-G.2.3(5).”
+“The definition of close result set, which determines the accuracy of
+certain fixed point multiplications and divisions. See G.2.3(5).”
@end itemize
Operations in the close result set are performed using IEEE long format
@@ -17865,47 +18128,45 @@ Information on those subjects is not yet available.
@itemize *
@item
-“Information regarding bounded errors and erroneous
-execution. See H.2(1).”
-@end itemize
-
-Information on this subject is not yet available.
+@table @asis
-@itemize *
+@item “The accuracy requirements for the subprograms Solve, Inverse,
-@item
-“Implementation-defined aspects of pragma
-@code{Inspection_Point}. See H.3.2(8).”
+Determinant, Eigenvalues and Eigensystem for type Real_Matrix.
+See G.3.1(81).”
+@end table
@end itemize
-Pragma @code{Inspection_Point} ensures that the variable is live and can
-be examined by the debugger at the inspection point.
+Information on those subjects is not yet available.
@itemize *
@item
-“Implementation-defined aspects of pragma
-@code{Restrictions}. See H.4(25).”
+
+@table @asis
+
+@item “The accuracy requirements for the subprograms Solve, Inverse,
+
+Determinant, Eigenvalues and Eigensystem for type Complex_Matrix.
+See G.3.2(149).”
+@end table
@end itemize
-There are no implementation-defined aspects of pragma @code{Restrictions}. The
-use of pragma @code{Restrictions [No_Exceptions]} has no effect on the
-generated code. Checks must suppressed by use of pragma @code{Suppress}.
+Information on those subjects is not yet available.
@itemize *
@item
-“Any restrictions on pragma @code{Restrictions}. See
-H.4(27).”
+“The consequences of violating No_Hidden_Indirect_Globals. See H.4(23.9).”
@end itemize
-There are no restrictions on pragma @code{Restrictions}.
+Execution is erroneous in that case.
@node Intrinsic Subprograms,Representation Clauses and Pragmas,Implementation Defined Characteristics,Top
-@anchor{gnat_rm/intrinsic_subprograms doc}@anchor{25b}@anchor{gnat_rm/intrinsic_subprograms id1}@anchor{25c}@anchor{gnat_rm/intrinsic_subprograms intrinsic-subprograms}@anchor{c}
+@anchor{gnat_rm/intrinsic_subprograms doc}@anchor{25d}@anchor{gnat_rm/intrinsic_subprograms id1}@anchor{25e}@anchor{gnat_rm/intrinsic_subprograms intrinsic-subprograms}@anchor{c}
@chapter Intrinsic Subprograms
@@ -17943,7 +18204,7 @@ Ada standard does not require Ada compilers to implement this feature.
@end menu
@node Intrinsic Operators,Compilation_ISO_Date,,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms id2}@anchor{25d}@anchor{gnat_rm/intrinsic_subprograms intrinsic-operators}@anchor{25e}
+@anchor{gnat_rm/intrinsic_subprograms id2}@anchor{25f}@anchor{gnat_rm/intrinsic_subprograms intrinsic-operators}@anchor{260}
@section Intrinsic Operators
@@ -17974,7 +18235,7 @@ It is also possible to specify such operators for private types, if the
full views are appropriate arithmetic types.
@node Compilation_ISO_Date,Compilation_Date,Intrinsic Operators,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms compilation-iso-date}@anchor{25f}@anchor{gnat_rm/intrinsic_subprograms id3}@anchor{260}
+@anchor{gnat_rm/intrinsic_subprograms compilation-iso-date}@anchor{261}@anchor{gnat_rm/intrinsic_subprograms id3}@anchor{262}
@section Compilation_ISO_Date
@@ -17988,7 +18249,7 @@ application program should simply call the function
the current compilation (in local time format YYYY-MM-DD).
@node Compilation_Date,Compilation_Time,Compilation_ISO_Date,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms compilation-date}@anchor{261}@anchor{gnat_rm/intrinsic_subprograms id4}@anchor{262}
+@anchor{gnat_rm/intrinsic_subprograms compilation-date}@anchor{263}@anchor{gnat_rm/intrinsic_subprograms id4}@anchor{264}
@section Compilation_Date
@@ -17998,7 +18259,7 @@ Same as Compilation_ISO_Date, except the string is in the form
MMM DD YYYY.
@node Compilation_Time,Enclosing_Entity,Compilation_Date,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms compilation-time}@anchor{263}@anchor{gnat_rm/intrinsic_subprograms id5}@anchor{264}
+@anchor{gnat_rm/intrinsic_subprograms compilation-time}@anchor{265}@anchor{gnat_rm/intrinsic_subprograms id5}@anchor{266}
@section Compilation_Time
@@ -18012,7 +18273,7 @@ application program should simply call the function
the current compilation (in local time format HH:MM:SS).
@node Enclosing_Entity,Exception_Information,Compilation_Time,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms enclosing-entity}@anchor{265}@anchor{gnat_rm/intrinsic_subprograms id6}@anchor{266}
+@anchor{gnat_rm/intrinsic_subprograms enclosing-entity}@anchor{267}@anchor{gnat_rm/intrinsic_subprograms id6}@anchor{268}
@section Enclosing_Entity
@@ -18026,7 +18287,7 @@ application program should simply call the function
the current subprogram, package, task, entry, or protected subprogram.
@node Exception_Information,Exception_Message,Enclosing_Entity,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms exception-information}@anchor{267}@anchor{gnat_rm/intrinsic_subprograms id7}@anchor{268}
+@anchor{gnat_rm/intrinsic_subprograms exception-information}@anchor{269}@anchor{gnat_rm/intrinsic_subprograms id7}@anchor{26a}
@section Exception_Information
@@ -18040,7 +18301,7 @@ so an application program should simply call the function
the exception information associated with the current exception.
@node Exception_Message,Exception_Name,Exception_Information,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms exception-message}@anchor{269}@anchor{gnat_rm/intrinsic_subprograms id8}@anchor{26a}
+@anchor{gnat_rm/intrinsic_subprograms exception-message}@anchor{26b}@anchor{gnat_rm/intrinsic_subprograms id8}@anchor{26c}
@section Exception_Message
@@ -18054,7 +18315,7 @@ so an application program should simply call the function
the message associated with the current exception.
@node Exception_Name,File,Exception_Message,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms exception-name}@anchor{26b}@anchor{gnat_rm/intrinsic_subprograms id9}@anchor{26c}
+@anchor{gnat_rm/intrinsic_subprograms exception-name}@anchor{26d}@anchor{gnat_rm/intrinsic_subprograms id9}@anchor{26e}
@section Exception_Name
@@ -18068,7 +18329,7 @@ so an application program should simply call the function
the name of the current exception.
@node File,Line,Exception_Name,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms file}@anchor{26d}@anchor{gnat_rm/intrinsic_subprograms id10}@anchor{26e}
+@anchor{gnat_rm/intrinsic_subprograms file}@anchor{26f}@anchor{gnat_rm/intrinsic_subprograms id10}@anchor{270}
@section File
@@ -18082,7 +18343,7 @@ application program should simply call the function
file.
@node Line,Shifts and Rotates,File,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms id11}@anchor{26f}@anchor{gnat_rm/intrinsic_subprograms line}@anchor{270}
+@anchor{gnat_rm/intrinsic_subprograms id11}@anchor{271}@anchor{gnat_rm/intrinsic_subprograms line}@anchor{272}
@section Line
@@ -18096,7 +18357,7 @@ application program should simply call the function
source line.
@node Shifts and Rotates,Source_Location,Line,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms id12}@anchor{271}@anchor{gnat_rm/intrinsic_subprograms shifts-and-rotates}@anchor{272}
+@anchor{gnat_rm/intrinsic_subprograms id12}@anchor{273}@anchor{gnat_rm/intrinsic_subprograms shifts-and-rotates}@anchor{274}
@section Shifts and Rotates
@@ -18139,7 +18400,7 @@ corresponding operator for modular type. In particular, shifting a negative
number may change its sign bit to positive.
@node Source_Location,,Shifts and Rotates,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms id13}@anchor{273}@anchor{gnat_rm/intrinsic_subprograms source-location}@anchor{274}
+@anchor{gnat_rm/intrinsic_subprograms id13}@anchor{275}@anchor{gnat_rm/intrinsic_subprograms source-location}@anchor{276}
@section Source_Location
@@ -18153,7 +18414,7 @@ application program should simply call the function
source file location.
@node Representation Clauses and Pragmas,Standard Library Routines,Intrinsic Subprograms,Top
-@anchor{gnat_rm/representation_clauses_and_pragmas doc}@anchor{275}@anchor{gnat_rm/representation_clauses_and_pragmas id1}@anchor{276}@anchor{gnat_rm/representation_clauses_and_pragmas representation-clauses-and-pragmas}@anchor{d}
+@anchor{gnat_rm/representation_clauses_and_pragmas doc}@anchor{277}@anchor{gnat_rm/representation_clauses_and_pragmas id1}@anchor{278}@anchor{gnat_rm/representation_clauses_and_pragmas representation-clauses-and-pragmas}@anchor{d}
@chapter Representation Clauses and Pragmas
@@ -18199,7 +18460,7 @@ and this section describes the additional capabilities provided.
@end menu
@node Alignment Clauses,Size Clauses,,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas alignment-clauses}@anchor{277}@anchor{gnat_rm/representation_clauses_and_pragmas id2}@anchor{278}
+@anchor{gnat_rm/representation_clauses_and_pragmas alignment-clauses}@anchor{279}@anchor{gnat_rm/representation_clauses_and_pragmas id2}@anchor{27a}
@section Alignment Clauses
@@ -18221,7 +18482,7 @@ For elementary types, the alignment is the minimum of the actual size of
objects of the type divided by @code{Storage_Unit},
and the maximum alignment supported by the target.
(This maximum alignment is given by the GNAT-specific attribute
-@code{Standard'Maximum_Alignment}; see @ref{18d,,Attribute Maximum_Alignment}.)
+@code{Standard'Maximum_Alignment}; see @ref{18e,,Attribute Maximum_Alignment}.)
@geindex Maximum_Alignment attribute
@@ -18330,7 +18591,7 @@ assumption is non-portable, and other compilers may choose different
alignments for the subtype @code{RS}.
@node Size Clauses,Storage_Size Clauses,Alignment Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id3}@anchor{279}@anchor{gnat_rm/representation_clauses_and_pragmas size-clauses}@anchor{27a}
+@anchor{gnat_rm/representation_clauses_and_pragmas id3}@anchor{27b}@anchor{gnat_rm/representation_clauses_and_pragmas size-clauses}@anchor{27c}
@section Size Clauses
@@ -18407,7 +18668,7 @@ if it is known that a Size value can be accommodated in an object of
type Integer.
@node Storage_Size Clauses,Size of Variant Record Objects,Size Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id4}@anchor{27b}@anchor{gnat_rm/representation_clauses_and_pragmas storage-size-clauses}@anchor{27c}
+@anchor{gnat_rm/representation_clauses_and_pragmas id4}@anchor{27d}@anchor{gnat_rm/representation_clauses_and_pragmas storage-size-clauses}@anchor{27e}
@section Storage_Size Clauses
@@ -18480,7 +18741,7 @@ Of course in practice, there will not be any explicit allocators in the
case of such an access declaration.
@node Size of Variant Record Objects,Biased Representation,Storage_Size Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id5}@anchor{27d}@anchor{gnat_rm/representation_clauses_and_pragmas size-of-variant-record-objects}@anchor{27e}
+@anchor{gnat_rm/representation_clauses_and_pragmas id5}@anchor{27f}@anchor{gnat_rm/representation_clauses_and_pragmas size-of-variant-record-objects}@anchor{280}
@section Size of Variant Record Objects
@@ -18590,7 +18851,7 @@ the maximum size, regardless of the current variant value, the
variant value.
@node Biased Representation,Value_Size and Object_Size Clauses,Size of Variant Record Objects,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas biased-representation}@anchor{27f}@anchor{gnat_rm/representation_clauses_and_pragmas id6}@anchor{280}
+@anchor{gnat_rm/representation_clauses_and_pragmas biased-representation}@anchor{281}@anchor{gnat_rm/representation_clauses_and_pragmas id6}@anchor{282}
@section Biased Representation
@@ -18628,7 +18889,7 @@ biased representation can be used for all discrete types except for
enumeration types for which a representation clause is given.
@node Value_Size and Object_Size Clauses,Component_Size Clauses,Biased Representation,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id7}@anchor{281}@anchor{gnat_rm/representation_clauses_and_pragmas value-size-and-object-size-clauses}@anchor{282}
+@anchor{gnat_rm/representation_clauses_and_pragmas id7}@anchor{283}@anchor{gnat_rm/representation_clauses_and_pragmas value-size-and-object-size-clauses}@anchor{284}
@section Value_Size and Object_Size Clauses
@@ -18944,7 +19205,7 @@ definition clause forces biased representation. This
warning can be turned off using @code{-gnatw.B}.
@node Component_Size Clauses,Bit_Order Clauses,Value_Size and Object_Size Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas component-size-clauses}@anchor{283}@anchor{gnat_rm/representation_clauses_and_pragmas id8}@anchor{284}
+@anchor{gnat_rm/representation_clauses_and_pragmas component-size-clauses}@anchor{285}@anchor{gnat_rm/representation_clauses_and_pragmas id8}@anchor{286}
@section Component_Size Clauses
@@ -18992,7 +19253,7 @@ and a pragma Pack for the same array type. if such duplicate
clauses are given, the pragma Pack will be ignored.
@node Bit_Order Clauses,Effect of Bit_Order on Byte Ordering,Component_Size Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas bit-order-clauses}@anchor{285}@anchor{gnat_rm/representation_clauses_and_pragmas id9}@anchor{286}
+@anchor{gnat_rm/representation_clauses_and_pragmas bit-order-clauses}@anchor{287}@anchor{gnat_rm/representation_clauses_and_pragmas id9}@anchor{288}
@section Bit_Order Clauses
@@ -19098,7 +19359,7 @@ if desired. The following section contains additional
details regarding the issue of byte ordering.
@node Effect of Bit_Order on Byte Ordering,Pragma Pack for Arrays,Bit_Order Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas effect-of-bit-order-on-byte-ordering}@anchor{287}@anchor{gnat_rm/representation_clauses_and_pragmas id10}@anchor{288}
+@anchor{gnat_rm/representation_clauses_and_pragmas effect-of-bit-order-on-byte-ordering}@anchor{289}@anchor{gnat_rm/representation_clauses_and_pragmas id10}@anchor{28a}
@section Effect of Bit_Order on Byte Ordering
@@ -19355,7 +19616,7 @@ to set the boolean constant @code{Master_Byte_First} in
an appropriate manner.
@node Pragma Pack for Arrays,Pragma Pack for Records,Effect of Bit_Order on Byte Ordering,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id11}@anchor{289}@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-arrays}@anchor{28a}
+@anchor{gnat_rm/representation_clauses_and_pragmas id11}@anchor{28b}@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-arrays}@anchor{28c}
@section Pragma Pack for Arrays
@@ -19475,7 +19736,7 @@ Here 31-bit packing is achieved as required, and no warning is generated,
since in this case the programmer intention is clear.
@node Pragma Pack for Records,Record Representation Clauses,Pragma Pack for Arrays,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id12}@anchor{28b}@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-records}@anchor{28c}
+@anchor{gnat_rm/representation_clauses_and_pragmas id12}@anchor{28d}@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-records}@anchor{28e}
@section Pragma Pack for Records
@@ -19559,7 +19820,7 @@ array that is longer than 64 bits, so it is itself non-packable on
boundary, and takes an integral number of bytes, i.e., 72 bits.
@node Record Representation Clauses,Handling of Records with Holes,Pragma Pack for Records,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id13}@anchor{28d}@anchor{gnat_rm/representation_clauses_and_pragmas record-representation-clauses}@anchor{28e}
+@anchor{gnat_rm/representation_clauses_and_pragmas id13}@anchor{28f}@anchor{gnat_rm/representation_clauses_and_pragmas record-representation-clauses}@anchor{290}
@section Record Representation Clauses
@@ -19638,7 +19899,7 @@ end record;
@end example
@node Handling of Records with Holes,Enumeration Clauses,Record Representation Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas handling-of-records-with-holes}@anchor{28f}@anchor{gnat_rm/representation_clauses_and_pragmas id14}@anchor{290}
+@anchor{gnat_rm/representation_clauses_and_pragmas handling-of-records-with-holes}@anchor{291}@anchor{gnat_rm/representation_clauses_and_pragmas id14}@anchor{292}
@section Handling of Records with Holes
@@ -19714,7 +19975,7 @@ for Hrec'Size use 64;
@end example
@node Enumeration Clauses,Address Clauses,Handling of Records with Holes,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas enumeration-clauses}@anchor{291}@anchor{gnat_rm/representation_clauses_and_pragmas id15}@anchor{292}
+@anchor{gnat_rm/representation_clauses_and_pragmas enumeration-clauses}@anchor{293}@anchor{gnat_rm/representation_clauses_and_pragmas id15}@anchor{294}
@section Enumeration Clauses
@@ -19757,7 +20018,7 @@ the overhead of converting representation values to the corresponding
positional values, (i.e., the value delivered by the @code{Pos} attribute).
@node Address Clauses,Use of Address Clauses for Memory-Mapped I/O,Enumeration Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas address-clauses}@anchor{293}@anchor{gnat_rm/representation_clauses_and_pragmas id16}@anchor{294}
+@anchor{gnat_rm/representation_clauses_and_pragmas address-clauses}@anchor{295}@anchor{gnat_rm/representation_clauses_and_pragmas id16}@anchor{296}
@section Address Clauses
@@ -20086,7 +20347,7 @@ then the program compiles without the warning and when run will generate
the output @code{X was not clobbered}.
@node Use of Address Clauses for Memory-Mapped I/O,Effect of Convention on Representation,Address Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id17}@anchor{295}@anchor{gnat_rm/representation_clauses_and_pragmas use-of-address-clauses-for-memory-mapped-i-o}@anchor{296}
+@anchor{gnat_rm/representation_clauses_and_pragmas id17}@anchor{297}@anchor{gnat_rm/representation_clauses_and_pragmas use-of-address-clauses-for-memory-mapped-i-o}@anchor{298}
@section Use of Address Clauses for Memory-Mapped I/O
@@ -20144,7 +20405,7 @@ provides the pragma @code{Volatile_Full_Access} which can be used in lieu of
pragma @code{Atomic} and will give the additional guarantee.
@node Effect of Convention on Representation,Conventions and Anonymous Access Types,Use of Address Clauses for Memory-Mapped I/O,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas effect-of-convention-on-representation}@anchor{297}@anchor{gnat_rm/representation_clauses_and_pragmas id18}@anchor{298}
+@anchor{gnat_rm/representation_clauses_and_pragmas effect-of-convention-on-representation}@anchor{299}@anchor{gnat_rm/representation_clauses_and_pragmas id18}@anchor{29a}
@section Effect of Convention on Representation
@@ -20222,7 +20483,7 @@ when one of these values is read, any nonzero value is treated as True.
@end itemize
@node Conventions and Anonymous Access Types,Determining the Representations chosen by GNAT,Effect of Convention on Representation,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas conventions-and-anonymous-access-types}@anchor{299}@anchor{gnat_rm/representation_clauses_and_pragmas id19}@anchor{29a}
+@anchor{gnat_rm/representation_clauses_and_pragmas conventions-and-anonymous-access-types}@anchor{29b}@anchor{gnat_rm/representation_clauses_and_pragmas id19}@anchor{29c}
@section Conventions and Anonymous Access Types
@@ -20298,7 +20559,7 @@ package ConvComp is
@end example
@node Determining the Representations chosen by GNAT,,Conventions and Anonymous Access Types,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas determining-the-representations-chosen-by-gnat}@anchor{29b}@anchor{gnat_rm/representation_clauses_and_pragmas id20}@anchor{29c}
+@anchor{gnat_rm/representation_clauses_and_pragmas determining-the-representations-chosen-by-gnat}@anchor{29d}@anchor{gnat_rm/representation_clauses_and_pragmas id20}@anchor{29e}
@section Determining the Representations chosen by GNAT
@@ -20450,7 +20711,7 @@ generated by the compiler into the original source to fix and guarantee
the actual representation to be used.
@node Standard Library Routines,The Implementation of Standard I/O,Representation Clauses and Pragmas,Top
-@anchor{gnat_rm/standard_library_routines doc}@anchor{29d}@anchor{gnat_rm/standard_library_routines id1}@anchor{29e}@anchor{gnat_rm/standard_library_routines standard-library-routines}@anchor{e}
+@anchor{gnat_rm/standard_library_routines doc}@anchor{29f}@anchor{gnat_rm/standard_library_routines id1}@anchor{2a0}@anchor{gnat_rm/standard_library_routines standard-library-routines}@anchor{e}
@chapter Standard Library Routines
@@ -21274,7 +21535,7 @@ For packages in Interfaces and System, all the RM defined packages are
available in GNAT, see the Ada 2012 RM for full details.
@node The Implementation of Standard I/O,The GNAT Library,Standard Library Routines,Top
-@anchor{gnat_rm/the_implementation_of_standard_i_o doc}@anchor{29f}@anchor{gnat_rm/the_implementation_of_standard_i_o id1}@anchor{2a0}@anchor{gnat_rm/the_implementation_of_standard_i_o the-implementation-of-standard-i-o}@anchor{f}
+@anchor{gnat_rm/the_implementation_of_standard_i_o doc}@anchor{2a1}@anchor{gnat_rm/the_implementation_of_standard_i_o id1}@anchor{2a2}@anchor{gnat_rm/the_implementation_of_standard_i_o the-implementation-of-standard-i-o}@anchor{f}
@chapter The Implementation of Standard I/O
@@ -21326,7 +21587,7 @@ these additional facilities are also described in this chapter.
@end menu
@node Standard I/O Packages,FORM Strings,,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id2}@anchor{2a1}@anchor{gnat_rm/the_implementation_of_standard_i_o standard-i-o-packages}@anchor{2a2}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id2}@anchor{2a3}@anchor{gnat_rm/the_implementation_of_standard_i_o standard-i-o-packages}@anchor{2a4}
@section Standard I/O Packages
@@ -21397,7 +21658,7 @@ flush the common I/O streams and in particular Standard_Output before
elaborating the Ada code.
@node FORM Strings,Direct_IO,Standard I/O Packages,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o form-strings}@anchor{2a3}@anchor{gnat_rm/the_implementation_of_standard_i_o id3}@anchor{2a4}
+@anchor{gnat_rm/the_implementation_of_standard_i_o form-strings}@anchor{2a5}@anchor{gnat_rm/the_implementation_of_standard_i_o id3}@anchor{2a6}
@section FORM Strings
@@ -21423,7 +21684,7 @@ unrecognized keyword appears in a form string, it is silently ignored
and not considered invalid.
@node Direct_IO,Sequential_IO,FORM Strings,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o direct-io}@anchor{2a5}@anchor{gnat_rm/the_implementation_of_standard_i_o id4}@anchor{2a6}
+@anchor{gnat_rm/the_implementation_of_standard_i_o direct-io}@anchor{2a7}@anchor{gnat_rm/the_implementation_of_standard_i_o id4}@anchor{2a8}
@section Direct_IO
@@ -21443,7 +21704,7 @@ There is no limit on the size of Direct_IO files, they are expanded as
necessary to accommodate whatever records are written to the file.
@node Sequential_IO,Text_IO,Direct_IO,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id5}@anchor{2a7}@anchor{gnat_rm/the_implementation_of_standard_i_o sequential-io}@anchor{2a8}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id5}@anchor{2a9}@anchor{gnat_rm/the_implementation_of_standard_i_o sequential-io}@anchor{2aa}
@section Sequential_IO
@@ -21490,7 +21751,7 @@ using Stream_IO, and this is the preferred mechanism. In particular, the
above program fragment rewritten to use Stream_IO will work correctly.
@node Text_IO,Wide_Text_IO,Sequential_IO,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id6}@anchor{2a9}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io}@anchor{2aa}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id6}@anchor{2ab}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io}@anchor{2ac}
@section Text_IO
@@ -21573,7 +21834,7 @@ the file.
@end menu
@node Stream Pointer Positioning,Reading and Writing Non-Regular Files,,Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o id7}@anchor{2ab}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning}@anchor{2ac}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id7}@anchor{2ad}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning}@anchor{2ae}
@subsection Stream Pointer Positioning
@@ -21609,7 +21870,7 @@ between two Ada files, then the difference may be observable in some
situations.
@node Reading and Writing Non-Regular Files,Get_Immediate,Stream Pointer Positioning,Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o id8}@anchor{2ad}@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files}@anchor{2ae}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id8}@anchor{2af}@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files}@anchor{2b0}
@subsection Reading and Writing Non-Regular Files
@@ -21660,7 +21921,7 @@ to read data past that end of
file indication, until another end of file indication is entered.
@node Get_Immediate,Treating Text_IO Files as Streams,Reading and Writing Non-Regular Files,Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o get-immediate}@anchor{2af}@anchor{gnat_rm/the_implementation_of_standard_i_o id9}@anchor{2b0}
+@anchor{gnat_rm/the_implementation_of_standard_i_o get-immediate}@anchor{2b1}@anchor{gnat_rm/the_implementation_of_standard_i_o id9}@anchor{2b2}
@subsection Get_Immediate
@@ -21678,7 +21939,7 @@ possible), it is undefined whether the FF character will be treated as a
page mark.
@node Treating Text_IO Files as Streams,Text_IO Extensions,Get_Immediate,Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o id10}@anchor{2b1}@anchor{gnat_rm/the_implementation_of_standard_i_o treating-text-io-files-as-streams}@anchor{2b2}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id10}@anchor{2b3}@anchor{gnat_rm/the_implementation_of_standard_i_o treating-text-io-files-as-streams}@anchor{2b4}
@subsection Treating Text_IO Files as Streams
@@ -21694,7 +21955,7 @@ skipped and the effect is similar to that described above for
@code{Get_Immediate}.
@node Text_IO Extensions,Text_IO Facilities for Unbounded Strings,Treating Text_IO Files as Streams,Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o id11}@anchor{2b3}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io-extensions}@anchor{2b4}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id11}@anchor{2b5}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io-extensions}@anchor{2b6}
@subsection Text_IO Extensions
@@ -21722,7 +21983,7 @@ the string is to be read.
@end itemize
@node Text_IO Facilities for Unbounded Strings,,Text_IO Extensions,Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o id12}@anchor{2b5}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io-facilities-for-unbounded-strings}@anchor{2b6}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id12}@anchor{2b7}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io-facilities-for-unbounded-strings}@anchor{2b8}
@subsection Text_IO Facilities for Unbounded Strings
@@ -21770,7 +22031,7 @@ files @code{a-szuzti.ads} and @code{a-szuzti.adb} provides similar extended
@code{Wide_Wide_Text_IO} functionality for unbounded wide wide strings.
@node Wide_Text_IO,Wide_Wide_Text_IO,Text_IO,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id13}@anchor{2b7}@anchor{gnat_rm/the_implementation_of_standard_i_o wide-text-io}@anchor{2b8}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id13}@anchor{2b9}@anchor{gnat_rm/the_implementation_of_standard_i_o wide-text-io}@anchor{2ba}
@section Wide_Text_IO
@@ -22017,12 +22278,12 @@ input also causes Constraint_Error to be raised.
@end menu
@node Stream Pointer Positioning<2>,Reading and Writing Non-Regular Files<2>,,Wide_Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o id14}@anchor{2b9}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning-1}@anchor{2ba}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id14}@anchor{2bb}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning-1}@anchor{2bc}
@subsection Stream Pointer Positioning
@code{Ada.Wide_Text_IO} is similar to @code{Ada.Text_IO} in its handling
-of stream pointer positioning (@ref{2aa,,Text_IO}). There is one additional
+of stream pointer positioning (@ref{2ac,,Text_IO}). There is one additional
case:
If @code{Ada.Wide_Text_IO.Look_Ahead} reads a character outside the
@@ -22041,7 +22302,7 @@ to a normal program using @code{Wide_Text_IO}. However, this discrepancy
can be observed if the wide text file shares a stream with another file.
@node Reading and Writing Non-Regular Files<2>,,Stream Pointer Positioning<2>,Wide_Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o id15}@anchor{2bb}@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files-1}@anchor{2bc}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id15}@anchor{2bd}@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files-1}@anchor{2be}
@subsection Reading and Writing Non-Regular Files
@@ -22052,7 +22313,7 @@ treated as data characters), and @code{End_Of_Page} always returns
it is possible to read beyond an end of file.
@node Wide_Wide_Text_IO,Stream_IO,Wide_Text_IO,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id16}@anchor{2bd}@anchor{gnat_rm/the_implementation_of_standard_i_o wide-wide-text-io}@anchor{2be}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id16}@anchor{2bf}@anchor{gnat_rm/the_implementation_of_standard_i_o wide-wide-text-io}@anchor{2c0}
@section Wide_Wide_Text_IO
@@ -22221,12 +22482,12 @@ input also causes Constraint_Error to be raised.
@end menu
@node Stream Pointer Positioning<3>,Reading and Writing Non-Regular Files<3>,,Wide_Wide_Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o id17}@anchor{2bf}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning-2}@anchor{2c0}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id17}@anchor{2c1}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning-2}@anchor{2c2}
@subsection Stream Pointer Positioning
@code{Ada.Wide_Wide_Text_IO} is similar to @code{Ada.Text_IO} in its handling
-of stream pointer positioning (@ref{2aa,,Text_IO}). There is one additional
+of stream pointer positioning (@ref{2ac,,Text_IO}). There is one additional
case:
If @code{Ada.Wide_Wide_Text_IO.Look_Ahead} reads a character outside the
@@ -22245,7 +22506,7 @@ to a normal program using @code{Wide_Wide_Text_IO}. However, this discrepancy
can be observed if the wide text file shares a stream with another file.
@node Reading and Writing Non-Regular Files<3>,,Stream Pointer Positioning<3>,Wide_Wide_Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o id18}@anchor{2c1}@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files-2}@anchor{2c2}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id18}@anchor{2c3}@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files-2}@anchor{2c4}
@subsection Reading and Writing Non-Regular Files
@@ -22256,7 +22517,7 @@ treated as data characters), and @code{End_Of_Page} always returns
it is possible to read beyond an end of file.
@node Stream_IO,Text Translation,Wide_Wide_Text_IO,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id19}@anchor{2c3}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-io}@anchor{2c4}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id19}@anchor{2c5}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-io}@anchor{2c6}
@section Stream_IO
@@ -22278,7 +22539,7 @@ manner described for stream attributes.
@end itemize
@node Text Translation,Shared Files,Stream_IO,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id20}@anchor{2c5}@anchor{gnat_rm/the_implementation_of_standard_i_o text-translation}@anchor{2c6}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id20}@anchor{2c7}@anchor{gnat_rm/the_implementation_of_standard_i_o text-translation}@anchor{2c8}
@section Text Translation
@@ -22312,7 +22573,7 @@ mode. (corresponds to_O_U16TEXT).
@end itemize
@node Shared Files,Filenames encoding,Text Translation,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id21}@anchor{2c7}@anchor{gnat_rm/the_implementation_of_standard_i_o shared-files}@anchor{2c8}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id21}@anchor{2c9}@anchor{gnat_rm/the_implementation_of_standard_i_o shared-files}@anchor{2ca}
@section Shared Files
@@ -22375,7 +22636,7 @@ heterogeneous input-output. Although this approach will work in GNAT if
for this purpose (using the stream attributes)
@node Filenames encoding,File content encoding,Shared Files,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o filenames-encoding}@anchor{2c9}@anchor{gnat_rm/the_implementation_of_standard_i_o id22}@anchor{2ca}
+@anchor{gnat_rm/the_implementation_of_standard_i_o filenames-encoding}@anchor{2cb}@anchor{gnat_rm/the_implementation_of_standard_i_o id22}@anchor{2cc}
@section Filenames encoding
@@ -22415,7 +22676,7 @@ platform. On the other Operating Systems the run-time is supporting
UTF-8 natively.
@node File content encoding,Open Modes,Filenames encoding,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o file-content-encoding}@anchor{2cb}@anchor{gnat_rm/the_implementation_of_standard_i_o id23}@anchor{2cc}
+@anchor{gnat_rm/the_implementation_of_standard_i_o file-content-encoding}@anchor{2cd}@anchor{gnat_rm/the_implementation_of_standard_i_o id23}@anchor{2ce}
@section File content encoding
@@ -22448,7 +22709,7 @@ Unicode 8-bit encoding
This encoding is only supported on the Windows platform.
@node Open Modes,Operations on C Streams,File content encoding,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id24}@anchor{2cd}@anchor{gnat_rm/the_implementation_of_standard_i_o open-modes}@anchor{2ce}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id24}@anchor{2cf}@anchor{gnat_rm/the_implementation_of_standard_i_o open-modes}@anchor{2d0}
@section Open Modes
@@ -22551,7 +22812,7 @@ subsequently requires switching from reading to writing or vice-versa,
then the file is reopened in @code{r+} mode to permit the required operation.
@node Operations on C Streams,Interfacing to C Streams,Open Modes,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id25}@anchor{2cf}@anchor{gnat_rm/the_implementation_of_standard_i_o operations-on-c-streams}@anchor{2d0}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id25}@anchor{2d1}@anchor{gnat_rm/the_implementation_of_standard_i_o operations-on-c-streams}@anchor{2d2}
@section Operations on C Streams
@@ -22711,7 +22972,7 @@ end Interfaces.C_Streams;
@end example
@node Interfacing to C Streams,,Operations on C Streams,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id26}@anchor{2d1}@anchor{gnat_rm/the_implementation_of_standard_i_o interfacing-to-c-streams}@anchor{2d2}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id26}@anchor{2d3}@anchor{gnat_rm/the_implementation_of_standard_i_o interfacing-to-c-streams}@anchor{2d4}
@section Interfacing to C Streams
@@ -22804,7 +23065,7 @@ imported from a C program, allowing an Ada file to operate on an
existing C file.
@node The GNAT Library,Interfacing to Other Languages,The Implementation of Standard I/O,Top
-@anchor{gnat_rm/the_gnat_library doc}@anchor{2d3}@anchor{gnat_rm/the_gnat_library id1}@anchor{2d4}@anchor{gnat_rm/the_gnat_library the-gnat-library}@anchor{10}
+@anchor{gnat_rm/the_gnat_library doc}@anchor{2d5}@anchor{gnat_rm/the_gnat_library id1}@anchor{2d6}@anchor{gnat_rm/the_gnat_library the-gnat-library}@anchor{10}
@chapter The GNAT Library
@@ -22998,7 +23259,7 @@ of GNAT, and will generate a warning message.
@end menu
@node Ada Characters Latin_9 a-chlat9 ads,Ada Characters Wide_Latin_1 a-cwila1 ads,,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-characters-latin-9-a-chlat9-ads}@anchor{2d5}@anchor{gnat_rm/the_gnat_library id2}@anchor{2d6}
+@anchor{gnat_rm/the_gnat_library ada-characters-latin-9-a-chlat9-ads}@anchor{2d7}@anchor{gnat_rm/the_gnat_library id2}@anchor{2d8}
@section @code{Ada.Characters.Latin_9} (@code{a-chlat9.ads})
@@ -23015,7 +23276,7 @@ is specifically authorized by the Ada Reference Manual
(RM A.3.3(27)).
@node Ada Characters Wide_Latin_1 a-cwila1 ads,Ada Characters Wide_Latin_9 a-cwila1 ads,Ada Characters Latin_9 a-chlat9 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-characters-wide-latin-1-a-cwila1-ads}@anchor{2d7}@anchor{gnat_rm/the_gnat_library id3}@anchor{2d8}
+@anchor{gnat_rm/the_gnat_library ada-characters-wide-latin-1-a-cwila1-ads}@anchor{2d9}@anchor{gnat_rm/the_gnat_library id3}@anchor{2da}
@section @code{Ada.Characters.Wide_Latin_1} (@code{a-cwila1.ads})
@@ -23032,7 +23293,7 @@ is specifically authorized by the Ada Reference Manual
(RM A.3.3(27)).
@node Ada Characters Wide_Latin_9 a-cwila1 ads,Ada Characters Wide_Wide_Latin_1 a-chzla1 ads,Ada Characters Wide_Latin_1 a-cwila1 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-characters-wide-latin-9-a-cwila1-ads}@anchor{2d9}@anchor{gnat_rm/the_gnat_library id4}@anchor{2da}
+@anchor{gnat_rm/the_gnat_library ada-characters-wide-latin-9-a-cwila1-ads}@anchor{2db}@anchor{gnat_rm/the_gnat_library id4}@anchor{2dc}
@section @code{Ada.Characters.Wide_Latin_9} (@code{a-cwila1.ads})
@@ -23049,7 +23310,7 @@ is specifically authorized by the Ada Reference Manual
(RM A.3.3(27)).
@node Ada Characters Wide_Wide_Latin_1 a-chzla1 ads,Ada Characters Wide_Wide_Latin_9 a-chzla9 ads,Ada Characters Wide_Latin_9 a-cwila1 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-characters-wide-wide-latin-1-a-chzla1-ads}@anchor{2db}@anchor{gnat_rm/the_gnat_library id5}@anchor{2dc}
+@anchor{gnat_rm/the_gnat_library ada-characters-wide-wide-latin-1-a-chzla1-ads}@anchor{2dd}@anchor{gnat_rm/the_gnat_library id5}@anchor{2de}
@section @code{Ada.Characters.Wide_Wide_Latin_1} (@code{a-chzla1.ads})
@@ -23066,7 +23327,7 @@ is specifically authorized by the Ada Reference Manual
(RM A.3.3(27)).
@node Ada Characters Wide_Wide_Latin_9 a-chzla9 ads,Ada Containers Formal_Doubly_Linked_Lists a-cfdlli ads,Ada Characters Wide_Wide_Latin_1 a-chzla1 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-characters-wide-wide-latin-9-a-chzla9-ads}@anchor{2dd}@anchor{gnat_rm/the_gnat_library id6}@anchor{2de}
+@anchor{gnat_rm/the_gnat_library ada-characters-wide-wide-latin-9-a-chzla9-ads}@anchor{2df}@anchor{gnat_rm/the_gnat_library id6}@anchor{2e0}
@section @code{Ada.Characters.Wide_Wide_Latin_9} (@code{a-chzla9.ads})
@@ -23083,7 +23344,7 @@ is specifically authorized by the Ada Reference Manual
(RM A.3.3(27)).
@node Ada Containers Formal_Doubly_Linked_Lists a-cfdlli ads,Ada Containers Formal_Hashed_Maps a-cfhama ads,Ada Characters Wide_Wide_Latin_9 a-chzla9 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-containers-formal-doubly-linked-lists-a-cfdlli-ads}@anchor{2df}@anchor{gnat_rm/the_gnat_library id7}@anchor{2e0}
+@anchor{gnat_rm/the_gnat_library ada-containers-formal-doubly-linked-lists-a-cfdlli-ads}@anchor{2e1}@anchor{gnat_rm/the_gnat_library id7}@anchor{2e2}
@section @code{Ada.Containers.Formal_Doubly_Linked_Lists} (@code{a-cfdlli.ads})
@@ -23102,7 +23363,7 @@ efficient version than the one defined in the standard. In particular it
does not have the complex overhead required to detect cursor tampering.
@node Ada Containers Formal_Hashed_Maps a-cfhama ads,Ada Containers Formal_Hashed_Sets a-cfhase ads,Ada Containers Formal_Doubly_Linked_Lists a-cfdlli ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-containers-formal-hashed-maps-a-cfhama-ads}@anchor{2e1}@anchor{gnat_rm/the_gnat_library id8}@anchor{2e2}
+@anchor{gnat_rm/the_gnat_library ada-containers-formal-hashed-maps-a-cfhama-ads}@anchor{2e3}@anchor{gnat_rm/the_gnat_library id8}@anchor{2e4}
@section @code{Ada.Containers.Formal_Hashed_Maps} (@code{a-cfhama.ads})
@@ -23121,7 +23382,7 @@ efficient version than the one defined in the standard. In particular it
does not have the complex overhead required to detect cursor tampering.
@node Ada Containers Formal_Hashed_Sets a-cfhase ads,Ada Containers Formal_Ordered_Maps a-cforma ads,Ada Containers Formal_Hashed_Maps a-cfhama ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-containers-formal-hashed-sets-a-cfhase-ads}@anchor{2e3}@anchor{gnat_rm/the_gnat_library id9}@anchor{2e4}
+@anchor{gnat_rm/the_gnat_library ada-containers-formal-hashed-sets-a-cfhase-ads}@anchor{2e5}@anchor{gnat_rm/the_gnat_library id9}@anchor{2e6}
@section @code{Ada.Containers.Formal_Hashed_Sets} (@code{a-cfhase.ads})
@@ -23140,7 +23401,7 @@ efficient version than the one defined in the standard. In particular it
does not have the complex overhead required to detect cursor tampering.
@node Ada Containers Formal_Ordered_Maps a-cforma ads,Ada Containers Formal_Ordered_Sets a-cforse ads,Ada Containers Formal_Hashed_Sets a-cfhase ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-containers-formal-ordered-maps-a-cforma-ads}@anchor{2e5}@anchor{gnat_rm/the_gnat_library id10}@anchor{2e6}
+@anchor{gnat_rm/the_gnat_library ada-containers-formal-ordered-maps-a-cforma-ads}@anchor{2e7}@anchor{gnat_rm/the_gnat_library id10}@anchor{2e8}
@section @code{Ada.Containers.Formal_Ordered_Maps} (@code{a-cforma.ads})
@@ -23159,7 +23420,7 @@ efficient version than the one defined in the standard. In particular it
does not have the complex overhead required to detect cursor tampering.
@node Ada Containers Formal_Ordered_Sets a-cforse ads,Ada Containers Formal_Vectors a-cofove ads,Ada Containers Formal_Ordered_Maps a-cforma ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-containers-formal-ordered-sets-a-cforse-ads}@anchor{2e7}@anchor{gnat_rm/the_gnat_library id11}@anchor{2e8}
+@anchor{gnat_rm/the_gnat_library ada-containers-formal-ordered-sets-a-cforse-ads}@anchor{2e9}@anchor{gnat_rm/the_gnat_library id11}@anchor{2ea}
@section @code{Ada.Containers.Formal_Ordered_Sets} (@code{a-cforse.ads})
@@ -23178,7 +23439,7 @@ efficient version than the one defined in the standard. In particular it
does not have the complex overhead required to detect cursor tampering.
@node Ada Containers Formal_Vectors a-cofove ads,Ada Containers Formal_Indefinite_Vectors a-cfinve ads,Ada Containers Formal_Ordered_Sets a-cforse ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-containers-formal-vectors-a-cofove-ads}@anchor{2e9}@anchor{gnat_rm/the_gnat_library id12}@anchor{2ea}
+@anchor{gnat_rm/the_gnat_library ada-containers-formal-vectors-a-cofove-ads}@anchor{2eb}@anchor{gnat_rm/the_gnat_library id12}@anchor{2ec}
@section @code{Ada.Containers.Formal_Vectors} (@code{a-cofove.ads})
@@ -23197,7 +23458,7 @@ efficient version than the one defined in the standard. In particular it
does not have the complex overhead required to detect cursor tampering.
@node Ada Containers Formal_Indefinite_Vectors a-cfinve ads,Ada Containers Functional_Vectors a-cofuve ads,Ada Containers Formal_Vectors a-cofove ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-containers-formal-indefinite-vectors-a-cfinve-ads}@anchor{2eb}@anchor{gnat_rm/the_gnat_library id13}@anchor{2ec}
+@anchor{gnat_rm/the_gnat_library ada-containers-formal-indefinite-vectors-a-cfinve-ads}@anchor{2ed}@anchor{gnat_rm/the_gnat_library id13}@anchor{2ee}
@section @code{Ada.Containers.Formal_Indefinite_Vectors} (@code{a-cfinve.ads})
@@ -23216,7 +23477,7 @@ efficient version than the one defined in the standard. In particular it
does not have the complex overhead required to detect cursor tampering.
@node Ada Containers Functional_Vectors a-cofuve ads,Ada Containers Functional_Sets a-cofuse ads,Ada Containers Formal_Indefinite_Vectors a-cfinve ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-containers-functional-vectors-a-cofuve-ads}@anchor{2ed}@anchor{gnat_rm/the_gnat_library id14}@anchor{2ee}
+@anchor{gnat_rm/the_gnat_library ada-containers-functional-vectors-a-cofuve-ads}@anchor{2ef}@anchor{gnat_rm/the_gnat_library id14}@anchor{2f0}
@section @code{Ada.Containers.Functional_Vectors} (@code{a-cofuve.ads})
@@ -23238,7 +23499,7 @@ and annotations, so that they can be removed from the final executable. The
specification of this unit is compatible with SPARK 2014.
@node Ada Containers Functional_Sets a-cofuse ads,Ada Containers Functional_Maps a-cofuma ads,Ada Containers Functional_Vectors a-cofuve ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-containers-functional-sets-a-cofuse-ads}@anchor{2ef}@anchor{gnat_rm/the_gnat_library id15}@anchor{2f0}
+@anchor{gnat_rm/the_gnat_library ada-containers-functional-sets-a-cofuse-ads}@anchor{2f1}@anchor{gnat_rm/the_gnat_library id15}@anchor{2f2}
@section @code{Ada.Containers.Functional_Sets} (@code{a-cofuse.ads})
@@ -23260,7 +23521,7 @@ and annotations, so that they can be removed from the final executable. The
specification of this unit is compatible with SPARK 2014.
@node Ada Containers Functional_Maps a-cofuma ads,Ada Containers Bounded_Holders a-coboho ads,Ada Containers Functional_Sets a-cofuse ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-containers-functional-maps-a-cofuma-ads}@anchor{2f1}@anchor{gnat_rm/the_gnat_library id16}@anchor{2f2}
+@anchor{gnat_rm/the_gnat_library ada-containers-functional-maps-a-cofuma-ads}@anchor{2f3}@anchor{gnat_rm/the_gnat_library id16}@anchor{2f4}
@section @code{Ada.Containers.Functional_Maps} (@code{a-cofuma.ads})
@@ -23282,7 +23543,7 @@ and annotations, so that they can be removed from the final executable. The
specification of this unit is compatible with SPARK 2014.
@node Ada Containers Bounded_Holders a-coboho ads,Ada Command_Line Environment a-colien ads,Ada Containers Functional_Maps a-cofuma ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-containers-bounded-holders-a-coboho-ads}@anchor{2f3}@anchor{gnat_rm/the_gnat_library id17}@anchor{2f4}
+@anchor{gnat_rm/the_gnat_library ada-containers-bounded-holders-a-coboho-ads}@anchor{2f5}@anchor{gnat_rm/the_gnat_library id17}@anchor{2f6}
@section @code{Ada.Containers.Bounded_Holders} (@code{a-coboho.ads})
@@ -23294,7 +23555,7 @@ This child of @code{Ada.Containers} defines a modified version of
Indefinite_Holders that avoids heap allocation.
@node Ada Command_Line Environment a-colien ads,Ada Command_Line Remove a-colire ads,Ada Containers Bounded_Holders a-coboho ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-command-line-environment-a-colien-ads}@anchor{2f5}@anchor{gnat_rm/the_gnat_library id18}@anchor{2f6}
+@anchor{gnat_rm/the_gnat_library ada-command-line-environment-a-colien-ads}@anchor{2f7}@anchor{gnat_rm/the_gnat_library id18}@anchor{2f8}
@section @code{Ada.Command_Line.Environment} (@code{a-colien.ads})
@@ -23307,7 +23568,7 @@ provides a mechanism for obtaining environment values on systems
where this concept makes sense.
@node Ada Command_Line Remove a-colire ads,Ada Command_Line Response_File a-clrefi ads,Ada Command_Line Environment a-colien ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-command-line-remove-a-colire-ads}@anchor{2f7}@anchor{gnat_rm/the_gnat_library id19}@anchor{2f8}
+@anchor{gnat_rm/the_gnat_library ada-command-line-remove-a-colire-ads}@anchor{2f9}@anchor{gnat_rm/the_gnat_library id19}@anchor{2fa}
@section @code{Ada.Command_Line.Remove} (@code{a-colire.ads})
@@ -23325,7 +23586,7 @@ to further calls on the subprograms in @code{Ada.Command_Line} will not
see the removed argument.
@node Ada Command_Line Response_File a-clrefi ads,Ada Direct_IO C_Streams a-diocst ads,Ada Command_Line Remove a-colire ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-command-line-response-file-a-clrefi-ads}@anchor{2f9}@anchor{gnat_rm/the_gnat_library id20}@anchor{2fa}
+@anchor{gnat_rm/the_gnat_library ada-command-line-response-file-a-clrefi-ads}@anchor{2fb}@anchor{gnat_rm/the_gnat_library id20}@anchor{2fc}
@section @code{Ada.Command_Line.Response_File} (@code{a-clrefi.ads})
@@ -23345,7 +23606,7 @@ Using a response file allow passing a set of arguments to an executable longer
than the maximum allowed by the system on the command line.
@node Ada Direct_IO C_Streams a-diocst ads,Ada Exceptions Is_Null_Occurrence a-einuoc ads,Ada Command_Line Response_File a-clrefi ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-direct-io-c-streams-a-diocst-ads}@anchor{2fb}@anchor{gnat_rm/the_gnat_library id21}@anchor{2fc}
+@anchor{gnat_rm/the_gnat_library ada-direct-io-c-streams-a-diocst-ads}@anchor{2fd}@anchor{gnat_rm/the_gnat_library id21}@anchor{2fe}
@section @code{Ada.Direct_IO.C_Streams} (@code{a-diocst.ads})
@@ -23360,7 +23621,7 @@ extracted from a file opened on the Ada side, and an Ada file
can be constructed from a stream opened on the C side.
@node Ada Exceptions Is_Null_Occurrence a-einuoc ads,Ada Exceptions Last_Chance_Handler a-elchha ads,Ada Direct_IO C_Streams a-diocst ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-exceptions-is-null-occurrence-a-einuoc-ads}@anchor{2fd}@anchor{gnat_rm/the_gnat_library id22}@anchor{2fe}
+@anchor{gnat_rm/the_gnat_library ada-exceptions-is-null-occurrence-a-einuoc-ads}@anchor{2ff}@anchor{gnat_rm/the_gnat_library id22}@anchor{300}
@section @code{Ada.Exceptions.Is_Null_Occurrence} (@code{a-einuoc.ads})
@@ -23374,7 +23635,7 @@ exception occurrence (@code{Null_Occurrence}) without raising
an exception.
@node Ada Exceptions Last_Chance_Handler a-elchha ads,Ada Exceptions Traceback a-exctra ads,Ada Exceptions Is_Null_Occurrence a-einuoc ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-exceptions-last-chance-handler-a-elchha-ads}@anchor{2ff}@anchor{gnat_rm/the_gnat_library id23}@anchor{300}
+@anchor{gnat_rm/the_gnat_library ada-exceptions-last-chance-handler-a-elchha-ads}@anchor{301}@anchor{gnat_rm/the_gnat_library id23}@anchor{302}
@section @code{Ada.Exceptions.Last_Chance_Handler} (@code{a-elchha.ads})
@@ -23388,7 +23649,7 @@ exceptions (hence the name last chance), and perform clean ups before
terminating the program. Note that this subprogram never returns.
@node Ada Exceptions Traceback a-exctra ads,Ada Sequential_IO C_Streams a-siocst ads,Ada Exceptions Last_Chance_Handler a-elchha ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-exceptions-traceback-a-exctra-ads}@anchor{301}@anchor{gnat_rm/the_gnat_library id24}@anchor{302}
+@anchor{gnat_rm/the_gnat_library ada-exceptions-traceback-a-exctra-ads}@anchor{303}@anchor{gnat_rm/the_gnat_library id24}@anchor{304}
@section @code{Ada.Exceptions.Traceback} (@code{a-exctra.ads})
@@ -23401,7 +23662,7 @@ give a traceback array of addresses based on an exception
occurrence.
@node Ada Sequential_IO C_Streams a-siocst ads,Ada Streams Stream_IO C_Streams a-ssicst ads,Ada Exceptions Traceback a-exctra ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-sequential-io-c-streams-a-siocst-ads}@anchor{303}@anchor{gnat_rm/the_gnat_library id25}@anchor{304}
+@anchor{gnat_rm/the_gnat_library ada-sequential-io-c-streams-a-siocst-ads}@anchor{305}@anchor{gnat_rm/the_gnat_library id25}@anchor{306}
@section @code{Ada.Sequential_IO.C_Streams} (@code{a-siocst.ads})
@@ -23416,7 +23677,7 @@ extracted from a file opened on the Ada side, and an Ada file
can be constructed from a stream opened on the C side.
@node Ada Streams Stream_IO C_Streams a-ssicst ads,Ada Strings Unbounded Text_IO a-suteio ads,Ada Sequential_IO C_Streams a-siocst ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-streams-stream-io-c-streams-a-ssicst-ads}@anchor{305}@anchor{gnat_rm/the_gnat_library id26}@anchor{306}
+@anchor{gnat_rm/the_gnat_library ada-streams-stream-io-c-streams-a-ssicst-ads}@anchor{307}@anchor{gnat_rm/the_gnat_library id26}@anchor{308}
@section @code{Ada.Streams.Stream_IO.C_Streams} (@code{a-ssicst.ads})
@@ -23431,7 +23692,7 @@ extracted from a file opened on the Ada side, and an Ada file
can be constructed from a stream opened on the C side.
@node Ada Strings Unbounded Text_IO a-suteio ads,Ada Strings Wide_Unbounded Wide_Text_IO a-swuwti ads,Ada Streams Stream_IO C_Streams a-ssicst ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-strings-unbounded-text-io-a-suteio-ads}@anchor{307}@anchor{gnat_rm/the_gnat_library id27}@anchor{308}
+@anchor{gnat_rm/the_gnat_library ada-strings-unbounded-text-io-a-suteio-ads}@anchor{309}@anchor{gnat_rm/the_gnat_library id27}@anchor{30a}
@section @code{Ada.Strings.Unbounded.Text_IO} (@code{a-suteio.ads})
@@ -23448,7 +23709,7 @@ strings, avoiding the necessity for an intermediate operation
with ordinary strings.
@node Ada Strings Wide_Unbounded Wide_Text_IO a-swuwti ads,Ada Strings Wide_Wide_Unbounded Wide_Wide_Text_IO a-szuzti ads,Ada Strings Unbounded Text_IO a-suteio ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-strings-wide-unbounded-wide-text-io-a-swuwti-ads}@anchor{309}@anchor{gnat_rm/the_gnat_library id28}@anchor{30a}
+@anchor{gnat_rm/the_gnat_library ada-strings-wide-unbounded-wide-text-io-a-swuwti-ads}@anchor{30b}@anchor{gnat_rm/the_gnat_library id28}@anchor{30c}
@section @code{Ada.Strings.Wide_Unbounded.Wide_Text_IO} (@code{a-swuwti.ads})
@@ -23465,7 +23726,7 @@ wide strings, avoiding the necessity for an intermediate operation
with ordinary wide strings.
@node Ada Strings Wide_Wide_Unbounded Wide_Wide_Text_IO a-szuzti ads,Ada Task_Initialization a-tasini ads,Ada Strings Wide_Unbounded Wide_Text_IO a-swuwti ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-strings-wide-wide-unbounded-wide-wide-text-io-a-szuzti-ads}@anchor{30b}@anchor{gnat_rm/the_gnat_library id29}@anchor{30c}
+@anchor{gnat_rm/the_gnat_library ada-strings-wide-wide-unbounded-wide-wide-text-io-a-szuzti-ads}@anchor{30d}@anchor{gnat_rm/the_gnat_library id29}@anchor{30e}
@section @code{Ada.Strings.Wide_Wide_Unbounded.Wide_Wide_Text_IO} (@code{a-szuzti.ads})
@@ -23482,7 +23743,7 @@ wide wide strings, avoiding the necessity for an intermediate operation
with ordinary wide wide strings.
@node Ada Task_Initialization a-tasini ads,Ada Text_IO C_Streams a-tiocst ads,Ada Strings Wide_Wide_Unbounded Wide_Wide_Text_IO a-szuzti ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-task-initialization-a-tasini-ads}@anchor{30d}@anchor{gnat_rm/the_gnat_library id30}@anchor{30e}
+@anchor{gnat_rm/the_gnat_library ada-task-initialization-a-tasini-ads}@anchor{30f}@anchor{gnat_rm/the_gnat_library id30}@anchor{310}
@section @code{Ada.Task_Initialization} (@code{a-tasini.ads})
@@ -23494,7 +23755,7 @@ parameterless procedures. Note that such a handler is only invoked for
those tasks activated after the handler is set.
@node Ada Text_IO C_Streams a-tiocst ads,Ada Text_IO Reset_Standard_Files a-tirsfi ads,Ada Task_Initialization a-tasini ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-text-io-c-streams-a-tiocst-ads}@anchor{30f}@anchor{gnat_rm/the_gnat_library id31}@anchor{310}
+@anchor{gnat_rm/the_gnat_library ada-text-io-c-streams-a-tiocst-ads}@anchor{311}@anchor{gnat_rm/the_gnat_library id31}@anchor{312}
@section @code{Ada.Text_IO.C_Streams} (@code{a-tiocst.ads})
@@ -23509,7 +23770,7 @@ extracted from a file opened on the Ada side, and an Ada file
can be constructed from a stream opened on the C side.
@node Ada Text_IO Reset_Standard_Files a-tirsfi ads,Ada Wide_Characters Unicode a-wichun ads,Ada Text_IO C_Streams a-tiocst ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-text-io-reset-standard-files-a-tirsfi-ads}@anchor{311}@anchor{gnat_rm/the_gnat_library id32}@anchor{312}
+@anchor{gnat_rm/the_gnat_library ada-text-io-reset-standard-files-a-tirsfi-ads}@anchor{313}@anchor{gnat_rm/the_gnat_library id32}@anchor{314}
@section @code{Ada.Text_IO.Reset_Standard_Files} (@code{a-tirsfi.ads})
@@ -23524,7 +23785,7 @@ execution (for example a standard input file may be redefined to be
interactive).
@node Ada Wide_Characters Unicode a-wichun ads,Ada Wide_Text_IO C_Streams a-wtcstr ads,Ada Text_IO Reset_Standard_Files a-tirsfi ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-wide-characters-unicode-a-wichun-ads}@anchor{313}@anchor{gnat_rm/the_gnat_library id33}@anchor{314}
+@anchor{gnat_rm/the_gnat_library ada-wide-characters-unicode-a-wichun-ads}@anchor{315}@anchor{gnat_rm/the_gnat_library id33}@anchor{316}
@section @code{Ada.Wide_Characters.Unicode} (@code{a-wichun.ads})
@@ -23537,7 +23798,7 @@ This package provides subprograms that allow categorization of
Wide_Character values according to Unicode categories.
@node Ada Wide_Text_IO C_Streams a-wtcstr ads,Ada Wide_Text_IO Reset_Standard_Files a-wrstfi ads,Ada Wide_Characters Unicode a-wichun ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-wide-text-io-c-streams-a-wtcstr-ads}@anchor{315}@anchor{gnat_rm/the_gnat_library id34}@anchor{316}
+@anchor{gnat_rm/the_gnat_library ada-wide-text-io-c-streams-a-wtcstr-ads}@anchor{317}@anchor{gnat_rm/the_gnat_library id34}@anchor{318}
@section @code{Ada.Wide_Text_IO.C_Streams} (@code{a-wtcstr.ads})
@@ -23552,7 +23813,7 @@ extracted from a file opened on the Ada side, and an Ada file
can be constructed from a stream opened on the C side.
@node Ada Wide_Text_IO Reset_Standard_Files a-wrstfi ads,Ada Wide_Wide_Characters Unicode a-zchuni ads,Ada Wide_Text_IO C_Streams a-wtcstr ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-wide-text-io-reset-standard-files-a-wrstfi-ads}@anchor{317}@anchor{gnat_rm/the_gnat_library id35}@anchor{318}
+@anchor{gnat_rm/the_gnat_library ada-wide-text-io-reset-standard-files-a-wrstfi-ads}@anchor{319}@anchor{gnat_rm/the_gnat_library id35}@anchor{31a}
@section @code{Ada.Wide_Text_IO.Reset_Standard_Files} (@code{a-wrstfi.ads})
@@ -23567,7 +23828,7 @@ execution (for example a standard input file may be redefined to be
interactive).
@node Ada Wide_Wide_Characters Unicode a-zchuni ads,Ada Wide_Wide_Text_IO C_Streams a-ztcstr ads,Ada Wide_Text_IO Reset_Standard_Files a-wrstfi ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-wide-wide-characters-unicode-a-zchuni-ads}@anchor{319}@anchor{gnat_rm/the_gnat_library id36}@anchor{31a}
+@anchor{gnat_rm/the_gnat_library ada-wide-wide-characters-unicode-a-zchuni-ads}@anchor{31b}@anchor{gnat_rm/the_gnat_library id36}@anchor{31c}
@section @code{Ada.Wide_Wide_Characters.Unicode} (@code{a-zchuni.ads})
@@ -23580,7 +23841,7 @@ This package provides subprograms that allow categorization of
Wide_Wide_Character values according to Unicode categories.
@node Ada Wide_Wide_Text_IO C_Streams a-ztcstr ads,Ada Wide_Wide_Text_IO Reset_Standard_Files a-zrstfi ads,Ada Wide_Wide_Characters Unicode a-zchuni ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-wide-wide-text-io-c-streams-a-ztcstr-ads}@anchor{31b}@anchor{gnat_rm/the_gnat_library id37}@anchor{31c}
+@anchor{gnat_rm/the_gnat_library ada-wide-wide-text-io-c-streams-a-ztcstr-ads}@anchor{31d}@anchor{gnat_rm/the_gnat_library id37}@anchor{31e}
@section @code{Ada.Wide_Wide_Text_IO.C_Streams} (@code{a-ztcstr.ads})
@@ -23595,7 +23856,7 @@ extracted from a file opened on the Ada side, and an Ada file
can be constructed from a stream opened on the C side.
@node Ada Wide_Wide_Text_IO Reset_Standard_Files a-zrstfi ads,GNAT Altivec g-altive ads,Ada Wide_Wide_Text_IO C_Streams a-ztcstr ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-wide-wide-text-io-reset-standard-files-a-zrstfi-ads}@anchor{31d}@anchor{gnat_rm/the_gnat_library id38}@anchor{31e}
+@anchor{gnat_rm/the_gnat_library ada-wide-wide-text-io-reset-standard-files-a-zrstfi-ads}@anchor{31f}@anchor{gnat_rm/the_gnat_library id38}@anchor{320}
@section @code{Ada.Wide_Wide_Text_IO.Reset_Standard_Files} (@code{a-zrstfi.ads})
@@ -23610,7 +23871,7 @@ change during execution (for example a standard input file may be
redefined to be interactive).
@node GNAT Altivec g-altive ads,GNAT Altivec Conversions g-altcon ads,Ada Wide_Wide_Text_IO Reset_Standard_Files a-zrstfi ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-altivec-g-altive-ads}@anchor{31f}@anchor{gnat_rm/the_gnat_library id39}@anchor{320}
+@anchor{gnat_rm/the_gnat_library gnat-altivec-g-altive-ads}@anchor{321}@anchor{gnat_rm/the_gnat_library id39}@anchor{322}
@section @code{GNAT.Altivec} (@code{g-altive.ads})
@@ -23623,7 +23884,7 @@ definitions of constants and types common to all the versions of the
binding.
@node GNAT Altivec Conversions g-altcon ads,GNAT Altivec Vector_Operations g-alveop ads,GNAT Altivec g-altive ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-altivec-conversions-g-altcon-ads}@anchor{321}@anchor{gnat_rm/the_gnat_library id40}@anchor{322}
+@anchor{gnat_rm/the_gnat_library gnat-altivec-conversions-g-altcon-ads}@anchor{323}@anchor{gnat_rm/the_gnat_library id40}@anchor{324}
@section @code{GNAT.Altivec.Conversions} (@code{g-altcon.ads})
@@ -23634,7 +23895,7 @@ binding.
This package provides the Vector/View conversion routines.
@node GNAT Altivec Vector_Operations g-alveop ads,GNAT Altivec Vector_Types g-alvety ads,GNAT Altivec Conversions g-altcon ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-operations-g-alveop-ads}@anchor{323}@anchor{gnat_rm/the_gnat_library id41}@anchor{324}
+@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-operations-g-alveop-ads}@anchor{325}@anchor{gnat_rm/the_gnat_library id41}@anchor{326}
@section @code{GNAT.Altivec.Vector_Operations} (@code{g-alveop.ads})
@@ -23648,7 +23909,7 @@ library. The hard binding is provided as a separate package. This unit
is common to both bindings.
@node GNAT Altivec Vector_Types g-alvety ads,GNAT Altivec Vector_Views g-alvevi ads,GNAT Altivec Vector_Operations g-alveop ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-types-g-alvety-ads}@anchor{325}@anchor{gnat_rm/the_gnat_library id42}@anchor{326}
+@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-types-g-alvety-ads}@anchor{327}@anchor{gnat_rm/the_gnat_library id42}@anchor{328}
@section @code{GNAT.Altivec.Vector_Types} (@code{g-alvety.ads})
@@ -23660,7 +23921,7 @@ This package exposes the various vector types part of the Ada binding
to AltiVec facilities.
@node GNAT Altivec Vector_Views g-alvevi ads,GNAT Array_Split g-arrspl ads,GNAT Altivec Vector_Types g-alvety ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-views-g-alvevi-ads}@anchor{327}@anchor{gnat_rm/the_gnat_library id43}@anchor{328}
+@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-views-g-alvevi-ads}@anchor{329}@anchor{gnat_rm/the_gnat_library id43}@anchor{32a}
@section @code{GNAT.Altivec.Vector_Views} (@code{g-alvevi.ads})
@@ -23675,7 +23936,7 @@ vector elements and provides a simple way to initialize vector
objects.
@node GNAT Array_Split g-arrspl ads,GNAT AWK g-awk ads,GNAT Altivec Vector_Views g-alvevi ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-array-split-g-arrspl-ads}@anchor{329}@anchor{gnat_rm/the_gnat_library id44}@anchor{32a}
+@anchor{gnat_rm/the_gnat_library gnat-array-split-g-arrspl-ads}@anchor{32b}@anchor{gnat_rm/the_gnat_library id44}@anchor{32c}
@section @code{GNAT.Array_Split} (@code{g-arrspl.ads})
@@ -23688,7 +23949,7 @@ an array wherever the separators appear, and provide direct access
to the resulting slices.
@node GNAT AWK g-awk ads,GNAT Bind_Environment g-binenv ads,GNAT Array_Split g-arrspl ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-awk-g-awk-ads}@anchor{32b}@anchor{gnat_rm/the_gnat_library id45}@anchor{32c}
+@anchor{gnat_rm/the_gnat_library gnat-awk-g-awk-ads}@anchor{32d}@anchor{gnat_rm/the_gnat_library id45}@anchor{32e}
@section @code{GNAT.AWK} (@code{g-awk.ads})
@@ -23703,7 +23964,7 @@ or more files containing formatted data. The file is viewed as a database
where each record is a line and a field is a data element in this line.
@node GNAT Bind_Environment g-binenv ads,GNAT Branch_Prediction g-brapre ads,GNAT AWK g-awk ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-bind-environment-g-binenv-ads}@anchor{32d}@anchor{gnat_rm/the_gnat_library id46}@anchor{32e}
+@anchor{gnat_rm/the_gnat_library gnat-bind-environment-g-binenv-ads}@anchor{32f}@anchor{gnat_rm/the_gnat_library id46}@anchor{330}
@section @code{GNAT.Bind_Environment} (@code{g-binenv.ads})
@@ -23716,7 +23977,7 @@ These associations can be specified using the @code{-V} binder command
line switch.
@node GNAT Branch_Prediction g-brapre ads,GNAT Bounded_Buffers g-boubuf ads,GNAT Bind_Environment g-binenv ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-branch-prediction-g-brapre-ads}@anchor{32f}@anchor{gnat_rm/the_gnat_library id47}@anchor{330}
+@anchor{gnat_rm/the_gnat_library gnat-branch-prediction-g-brapre-ads}@anchor{331}@anchor{gnat_rm/the_gnat_library id47}@anchor{332}
@section @code{GNAT.Branch_Prediction} (@code{g-brapre.ads})
@@ -23727,7 +23988,7 @@ line switch.
Provides routines giving hints to the branch predictor of the code generator.
@node GNAT Bounded_Buffers g-boubuf ads,GNAT Bounded_Mailboxes g-boumai ads,GNAT Branch_Prediction g-brapre ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-bounded-buffers-g-boubuf-ads}@anchor{331}@anchor{gnat_rm/the_gnat_library id48}@anchor{332}
+@anchor{gnat_rm/the_gnat_library gnat-bounded-buffers-g-boubuf-ads}@anchor{333}@anchor{gnat_rm/the_gnat_library id48}@anchor{334}
@section @code{GNAT.Bounded_Buffers} (@code{g-boubuf.ads})
@@ -23742,7 +24003,7 @@ useful directly or as parts of the implementations of other abstractions,
such as mailboxes.
@node GNAT Bounded_Mailboxes g-boumai ads,GNAT Bubble_Sort g-bubsor ads,GNAT Bounded_Buffers g-boubuf ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-bounded-mailboxes-g-boumai-ads}@anchor{333}@anchor{gnat_rm/the_gnat_library id49}@anchor{334}
+@anchor{gnat_rm/the_gnat_library gnat-bounded-mailboxes-g-boumai-ads}@anchor{335}@anchor{gnat_rm/the_gnat_library id49}@anchor{336}
@section @code{GNAT.Bounded_Mailboxes} (@code{g-boumai.ads})
@@ -23755,7 +24016,7 @@ such as mailboxes.
Provides a thread-safe asynchronous intertask mailbox communication facility.
@node GNAT Bubble_Sort g-bubsor ads,GNAT Bubble_Sort_A g-busora ads,GNAT Bounded_Mailboxes g-boumai ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-g-bubsor-ads}@anchor{335}@anchor{gnat_rm/the_gnat_library id50}@anchor{336}
+@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-g-bubsor-ads}@anchor{337}@anchor{gnat_rm/the_gnat_library id50}@anchor{338}
@section @code{GNAT.Bubble_Sort} (@code{g-bubsor.ads})
@@ -23770,7 +24031,7 @@ data items. Exchange and comparison procedures are provided by passing
access-to-procedure values.
@node GNAT Bubble_Sort_A g-busora ads,GNAT Bubble_Sort_G g-busorg ads,GNAT Bubble_Sort g-bubsor ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-a-g-busora-ads}@anchor{337}@anchor{gnat_rm/the_gnat_library id51}@anchor{338}
+@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-a-g-busora-ads}@anchor{339}@anchor{gnat_rm/the_gnat_library id51}@anchor{33a}
@section @code{GNAT.Bubble_Sort_A} (@code{g-busora.ads})
@@ -23786,7 +24047,7 @@ access-to-procedure values. This is an older version, retained for
compatibility. Usually @code{GNAT.Bubble_Sort} will be preferable.
@node GNAT Bubble_Sort_G g-busorg ads,GNAT Byte_Order_Mark g-byorma ads,GNAT Bubble_Sort_A g-busora ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-g-g-busorg-ads}@anchor{339}@anchor{gnat_rm/the_gnat_library id52}@anchor{33a}
+@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-g-g-busorg-ads}@anchor{33b}@anchor{gnat_rm/the_gnat_library id52}@anchor{33c}
@section @code{GNAT.Bubble_Sort_G} (@code{g-busorg.ads})
@@ -23802,7 +24063,7 @@ if the procedures can be inlined, at the expense of duplicating code for
multiple instantiations.
@node GNAT Byte_Order_Mark g-byorma ads,GNAT Byte_Swapping g-bytswa ads,GNAT Bubble_Sort_G g-busorg ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-byte-order-mark-g-byorma-ads}@anchor{33b}@anchor{gnat_rm/the_gnat_library id53}@anchor{33c}
+@anchor{gnat_rm/the_gnat_library gnat-byte-order-mark-g-byorma-ads}@anchor{33d}@anchor{gnat_rm/the_gnat_library id53}@anchor{33e}
@section @code{GNAT.Byte_Order_Mark} (@code{g-byorma.ads})
@@ -23818,7 +24079,7 @@ the encoding of the string. The routine includes detection of special XML
sequences for various UCS input formats.
@node GNAT Byte_Swapping g-bytswa ads,GNAT Calendar g-calend ads,GNAT Byte_Order_Mark g-byorma ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-byte-swapping-g-bytswa-ads}@anchor{33d}@anchor{gnat_rm/the_gnat_library id54}@anchor{33e}
+@anchor{gnat_rm/the_gnat_library gnat-byte-swapping-g-bytswa-ads}@anchor{33f}@anchor{gnat_rm/the_gnat_library id54}@anchor{340}
@section @code{GNAT.Byte_Swapping} (@code{g-bytswa.ads})
@@ -23832,7 +24093,7 @@ General routines for swapping the bytes in 2-, 4-, and 8-byte quantities.
Machine-specific implementations are available in some cases.
@node GNAT Calendar g-calend ads,GNAT Calendar Time_IO g-catiio ads,GNAT Byte_Swapping g-bytswa ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-calendar-g-calend-ads}@anchor{33f}@anchor{gnat_rm/the_gnat_library id55}@anchor{340}
+@anchor{gnat_rm/the_gnat_library gnat-calendar-g-calend-ads}@anchor{341}@anchor{gnat_rm/the_gnat_library id55}@anchor{342}
@section @code{GNAT.Calendar} (@code{g-calend.ads})
@@ -23846,7 +24107,7 @@ Also provides conversion of @code{Ada.Calendar.Time} values to and from the
C @code{timeval} format.
@node GNAT Calendar Time_IO g-catiio ads,GNAT CRC32 g-crc32 ads,GNAT Calendar g-calend ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-calendar-time-io-g-catiio-ads}@anchor{341}@anchor{gnat_rm/the_gnat_library id56}@anchor{342}
+@anchor{gnat_rm/the_gnat_library gnat-calendar-time-io-g-catiio-ads}@anchor{343}@anchor{gnat_rm/the_gnat_library id56}@anchor{344}
@section @code{GNAT.Calendar.Time_IO} (@code{g-catiio.ads})
@@ -23857,7 +24118,7 @@ C @code{timeval} format.
@geindex GNAT.Calendar.Time_IO (g-catiio.ads)
@node GNAT CRC32 g-crc32 ads,GNAT Case_Util g-casuti ads,GNAT Calendar Time_IO g-catiio ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-crc32-g-crc32-ads}@anchor{343}@anchor{gnat_rm/the_gnat_library id57}@anchor{344}
+@anchor{gnat_rm/the_gnat_library gnat-crc32-g-crc32-ads}@anchor{345}@anchor{gnat_rm/the_gnat_library id57}@anchor{346}
@section @code{GNAT.CRC32} (@code{g-crc32.ads})
@@ -23874,7 +24135,7 @@ of this algorithm see
Aug. 1988. Sarwate, D.V.
@node GNAT Case_Util g-casuti ads,GNAT CGI g-cgi ads,GNAT CRC32 g-crc32 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-case-util-g-casuti-ads}@anchor{345}@anchor{gnat_rm/the_gnat_library id58}@anchor{346}
+@anchor{gnat_rm/the_gnat_library gnat-case-util-g-casuti-ads}@anchor{347}@anchor{gnat_rm/the_gnat_library id58}@anchor{348}
@section @code{GNAT.Case_Util} (@code{g-casuti.ads})
@@ -23889,7 +24150,7 @@ without the overhead of the full casing tables
in @code{Ada.Characters.Handling}.
@node GNAT CGI g-cgi ads,GNAT CGI Cookie g-cgicoo ads,GNAT Case_Util g-casuti ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-cgi-g-cgi-ads}@anchor{347}@anchor{gnat_rm/the_gnat_library id59}@anchor{348}
+@anchor{gnat_rm/the_gnat_library gnat-cgi-g-cgi-ads}@anchor{349}@anchor{gnat_rm/the_gnat_library id59}@anchor{34a}
@section @code{GNAT.CGI} (@code{g-cgi.ads})
@@ -23904,7 +24165,7 @@ builds a table whose index is the key and provides some services to deal
with this table.
@node GNAT CGI Cookie g-cgicoo ads,GNAT CGI Debug g-cgideb ads,GNAT CGI g-cgi ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-cgi-cookie-g-cgicoo-ads}@anchor{349}@anchor{gnat_rm/the_gnat_library id60}@anchor{34a}
+@anchor{gnat_rm/the_gnat_library gnat-cgi-cookie-g-cgicoo-ads}@anchor{34b}@anchor{gnat_rm/the_gnat_library id60}@anchor{34c}
@section @code{GNAT.CGI.Cookie} (@code{g-cgicoo.ads})
@@ -23919,7 +24180,7 @@ Common Gateway Interface (CGI). It exports services to deal with Web
cookies (piece of information kept in the Web client software).
@node GNAT CGI Debug g-cgideb ads,GNAT Command_Line g-comlin ads,GNAT CGI Cookie g-cgicoo ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-cgi-debug-g-cgideb-ads}@anchor{34b}@anchor{gnat_rm/the_gnat_library id61}@anchor{34c}
+@anchor{gnat_rm/the_gnat_library gnat-cgi-debug-g-cgideb-ads}@anchor{34d}@anchor{gnat_rm/the_gnat_library id61}@anchor{34e}
@section @code{GNAT.CGI.Debug} (@code{g-cgideb.ads})
@@ -23931,7 +24192,7 @@ This is a package to help debugging CGI (Common Gateway Interface)
programs written in Ada.
@node GNAT Command_Line g-comlin ads,GNAT Compiler_Version g-comver ads,GNAT CGI Debug g-cgideb ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-command-line-g-comlin-ads}@anchor{34d}@anchor{gnat_rm/the_gnat_library id62}@anchor{34e}
+@anchor{gnat_rm/the_gnat_library gnat-command-line-g-comlin-ads}@anchor{34f}@anchor{gnat_rm/the_gnat_library id62}@anchor{350}
@section @code{GNAT.Command_Line} (@code{g-comlin.ads})
@@ -23944,7 +24205,7 @@ including the ability to scan for named switches with optional parameters
and expand file names using wildcard notations.
@node GNAT Compiler_Version g-comver ads,GNAT Ctrl_C g-ctrl_c ads,GNAT Command_Line g-comlin ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-compiler-version-g-comver-ads}@anchor{34f}@anchor{gnat_rm/the_gnat_library id63}@anchor{350}
+@anchor{gnat_rm/the_gnat_library gnat-compiler-version-g-comver-ads}@anchor{351}@anchor{gnat_rm/the_gnat_library id63}@anchor{352}
@section @code{GNAT.Compiler_Version} (@code{g-comver.ads})
@@ -23962,7 +24223,7 @@ of the compiler if a consistent tool set is used to compile all units
of a partition).
@node GNAT Ctrl_C g-ctrl_c ads,GNAT Current_Exception g-curexc ads,GNAT Compiler_Version g-comver ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-ctrl-c-g-ctrl-c-ads}@anchor{351}@anchor{gnat_rm/the_gnat_library id64}@anchor{352}
+@anchor{gnat_rm/the_gnat_library gnat-ctrl-c-g-ctrl-c-ads}@anchor{353}@anchor{gnat_rm/the_gnat_library id64}@anchor{354}
@section @code{GNAT.Ctrl_C} (@code{g-ctrl_c.ads})
@@ -23973,7 +24234,7 @@ of a partition).
Provides a simple interface to handle Ctrl-C keyboard events.
@node GNAT Current_Exception g-curexc ads,GNAT Debug_Pools g-debpoo ads,GNAT Ctrl_C g-ctrl_c ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-current-exception-g-curexc-ads}@anchor{353}@anchor{gnat_rm/the_gnat_library id65}@anchor{354}
+@anchor{gnat_rm/the_gnat_library gnat-current-exception-g-curexc-ads}@anchor{355}@anchor{gnat_rm/the_gnat_library id65}@anchor{356}
@section @code{GNAT.Current_Exception} (@code{g-curexc.ads})
@@ -23990,7 +24251,7 @@ This is particularly useful in simulating typical facilities for
obtaining information about exceptions provided by Ada 83 compilers.
@node GNAT Debug_Pools g-debpoo ads,GNAT Debug_Utilities g-debuti ads,GNAT Current_Exception g-curexc ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-debug-pools-g-debpoo-ads}@anchor{355}@anchor{gnat_rm/the_gnat_library id66}@anchor{356}
+@anchor{gnat_rm/the_gnat_library gnat-debug-pools-g-debpoo-ads}@anchor{357}@anchor{gnat_rm/the_gnat_library id66}@anchor{358}
@section @code{GNAT.Debug_Pools} (@code{g-debpoo.ads})
@@ -24007,7 +24268,7 @@ problems.
See @code{The GNAT Debug_Pool Facility} section in the @cite{GNAT User’s Guide}.
@node GNAT Debug_Utilities g-debuti ads,GNAT Decode_String g-decstr ads,GNAT Debug_Pools g-debpoo ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-debug-utilities-g-debuti-ads}@anchor{357}@anchor{gnat_rm/the_gnat_library id67}@anchor{358}
+@anchor{gnat_rm/the_gnat_library gnat-debug-utilities-g-debuti-ads}@anchor{359}@anchor{gnat_rm/the_gnat_library id67}@anchor{35a}
@section @code{GNAT.Debug_Utilities} (@code{g-debuti.ads})
@@ -24020,7 +24281,7 @@ to and from string images of address values. Supports both C and Ada formats
for hexadecimal literals.
@node GNAT Decode_String g-decstr ads,GNAT Decode_UTF8_String g-deutst ads,GNAT Debug_Utilities g-debuti ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-decode-string-g-decstr-ads}@anchor{359}@anchor{gnat_rm/the_gnat_library id68}@anchor{35a}
+@anchor{gnat_rm/the_gnat_library gnat-decode-string-g-decstr-ads}@anchor{35b}@anchor{gnat_rm/the_gnat_library id68}@anchor{35c}
@section @code{GNAT.Decode_String} (@code{g-decstr.ads})
@@ -24044,7 +24305,7 @@ Useful in conjunction with Unicode character coding. Note there is a
preinstantiation for UTF-8. See next entry.
@node GNAT Decode_UTF8_String g-deutst ads,GNAT Directory_Operations g-dirope ads,GNAT Decode_String g-decstr ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-decode-utf8-string-g-deutst-ads}@anchor{35b}@anchor{gnat_rm/the_gnat_library id69}@anchor{35c}
+@anchor{gnat_rm/the_gnat_library gnat-decode-utf8-string-g-deutst-ads}@anchor{35d}@anchor{gnat_rm/the_gnat_library id69}@anchor{35e}
@section @code{GNAT.Decode_UTF8_String} (@code{g-deutst.ads})
@@ -24065,7 +24326,7 @@ preinstantiation for UTF-8. See next entry.
A preinstantiation of GNAT.Decode_Strings for UTF-8 encoding.
@node GNAT Directory_Operations g-dirope ads,GNAT Directory_Operations Iteration g-diopit ads,GNAT Decode_UTF8_String g-deutst ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-directory-operations-g-dirope-ads}@anchor{35d}@anchor{gnat_rm/the_gnat_library id70}@anchor{35e}
+@anchor{gnat_rm/the_gnat_library gnat-directory-operations-g-dirope-ads}@anchor{35f}@anchor{gnat_rm/the_gnat_library id70}@anchor{360}
@section @code{GNAT.Directory_Operations} (@code{g-dirope.ads})
@@ -24078,7 +24339,7 @@ the current directory, making new directories, and scanning the files in a
directory.
@node GNAT Directory_Operations Iteration g-diopit ads,GNAT Dynamic_HTables g-dynhta ads,GNAT Directory_Operations g-dirope ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-directory-operations-iteration-g-diopit-ads}@anchor{35f}@anchor{gnat_rm/the_gnat_library id71}@anchor{360}
+@anchor{gnat_rm/the_gnat_library gnat-directory-operations-iteration-g-diopit-ads}@anchor{361}@anchor{gnat_rm/the_gnat_library id71}@anchor{362}
@section @code{GNAT.Directory_Operations.Iteration} (@code{g-diopit.ads})
@@ -24090,7 +24351,7 @@ A child unit of GNAT.Directory_Operations providing additional operations
for iterating through directories.
@node GNAT Dynamic_HTables g-dynhta ads,GNAT Dynamic_Tables g-dyntab ads,GNAT Directory_Operations Iteration g-diopit ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-dynamic-htables-g-dynhta-ads}@anchor{361}@anchor{gnat_rm/the_gnat_library id72}@anchor{362}
+@anchor{gnat_rm/the_gnat_library gnat-dynamic-htables-g-dynhta-ads}@anchor{363}@anchor{gnat_rm/the_gnat_library id72}@anchor{364}
@section @code{GNAT.Dynamic_HTables} (@code{g-dynhta.ads})
@@ -24108,7 +24369,7 @@ dynamic instances of the hash table, while an instantiation of
@code{GNAT.HTable} creates a single instance of the hash table.
@node GNAT Dynamic_Tables g-dyntab ads,GNAT Encode_String g-encstr ads,GNAT Dynamic_HTables g-dynhta ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-dynamic-tables-g-dyntab-ads}@anchor{363}@anchor{gnat_rm/the_gnat_library id73}@anchor{364}
+@anchor{gnat_rm/the_gnat_library gnat-dynamic-tables-g-dyntab-ads}@anchor{365}@anchor{gnat_rm/the_gnat_library id73}@anchor{366}
@section @code{GNAT.Dynamic_Tables} (@code{g-dyntab.ads})
@@ -24128,7 +24389,7 @@ dynamic instances of the table, while an instantiation of
@code{GNAT.Table} creates a single instance of the table type.
@node GNAT Encode_String g-encstr ads,GNAT Encode_UTF8_String g-enutst ads,GNAT Dynamic_Tables g-dyntab ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-encode-string-g-encstr-ads}@anchor{365}@anchor{gnat_rm/the_gnat_library id74}@anchor{366}
+@anchor{gnat_rm/the_gnat_library gnat-encode-string-g-encstr-ads}@anchor{367}@anchor{gnat_rm/the_gnat_library id74}@anchor{368}
@section @code{GNAT.Encode_String} (@code{g-encstr.ads})
@@ -24150,7 +24411,7 @@ encoding method. Useful in conjunction with Unicode character coding.
Note there is a preinstantiation for UTF-8. See next entry.
@node GNAT Encode_UTF8_String g-enutst ads,GNAT Exception_Actions g-excact ads,GNAT Encode_String g-encstr ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-encode-utf8-string-g-enutst-ads}@anchor{367}@anchor{gnat_rm/the_gnat_library id75}@anchor{368}
+@anchor{gnat_rm/the_gnat_library gnat-encode-utf8-string-g-enutst-ads}@anchor{369}@anchor{gnat_rm/the_gnat_library id75}@anchor{36a}
@section @code{GNAT.Encode_UTF8_String} (@code{g-enutst.ads})
@@ -24171,7 +24432,7 @@ Note there is a preinstantiation for UTF-8. See next entry.
A preinstantiation of GNAT.Encode_Strings for UTF-8 encoding.
@node GNAT Exception_Actions g-excact ads,GNAT Exception_Traces g-exctra ads,GNAT Encode_UTF8_String g-enutst ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-exception-actions-g-excact-ads}@anchor{369}@anchor{gnat_rm/the_gnat_library id76}@anchor{36a}
+@anchor{gnat_rm/the_gnat_library gnat-exception-actions-g-excact-ads}@anchor{36b}@anchor{gnat_rm/the_gnat_library id76}@anchor{36c}
@section @code{GNAT.Exception_Actions} (@code{g-excact.ads})
@@ -24184,7 +24445,7 @@ for specific exceptions, or when any exception is raised. This
can be used for instance to force a core dump to ease debugging.
@node GNAT Exception_Traces g-exctra ads,GNAT Exceptions g-except ads,GNAT Exception_Actions g-excact ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-exception-traces-g-exctra-ads}@anchor{36b}@anchor{gnat_rm/the_gnat_library id77}@anchor{36c}
+@anchor{gnat_rm/the_gnat_library gnat-exception-traces-g-exctra-ads}@anchor{36d}@anchor{gnat_rm/the_gnat_library id77}@anchor{36e}
@section @code{GNAT.Exception_Traces} (@code{g-exctra.ads})
@@ -24198,7 +24459,7 @@ Provides an interface allowing to control automatic output upon exception
occurrences.
@node GNAT Exceptions g-except ads,GNAT Expect g-expect ads,GNAT Exception_Traces g-exctra ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-exceptions-g-except-ads}@anchor{36d}@anchor{gnat_rm/the_gnat_library id78}@anchor{36e}
+@anchor{gnat_rm/the_gnat_library gnat-exceptions-g-except-ads}@anchor{36f}@anchor{gnat_rm/the_gnat_library id78}@anchor{370}
@section @code{GNAT.Exceptions} (@code{g-except.ads})
@@ -24219,7 +24480,7 @@ predefined exceptions, and for example allow raising
@code{Constraint_Error} with a message from a pure subprogram.
@node GNAT Expect g-expect ads,GNAT Expect TTY g-exptty ads,GNAT Exceptions g-except ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-expect-g-expect-ads}@anchor{36f}@anchor{gnat_rm/the_gnat_library id79}@anchor{370}
+@anchor{gnat_rm/the_gnat_library gnat-expect-g-expect-ads}@anchor{371}@anchor{gnat_rm/the_gnat_library id79}@anchor{372}
@section @code{GNAT.Expect} (@code{g-expect.ads})
@@ -24235,7 +24496,7 @@ It is not implemented for cross ports, and in particular is not
implemented for VxWorks or LynxOS.
@node GNAT Expect TTY g-exptty ads,GNAT Float_Control g-flocon ads,GNAT Expect g-expect ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-expect-tty-g-exptty-ads}@anchor{371}@anchor{gnat_rm/the_gnat_library id80}@anchor{372}
+@anchor{gnat_rm/the_gnat_library gnat-expect-tty-g-exptty-ads}@anchor{373}@anchor{gnat_rm/the_gnat_library id80}@anchor{374}
@section @code{GNAT.Expect.TTY} (@code{g-exptty.ads})
@@ -24247,7 +24508,7 @@ ports. It is not implemented for cross ports, and
in particular is not implemented for VxWorks or LynxOS.
@node GNAT Float_Control g-flocon ads,GNAT Formatted_String g-forstr ads,GNAT Expect TTY g-exptty ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-float-control-g-flocon-ads}@anchor{373}@anchor{gnat_rm/the_gnat_library id81}@anchor{374}
+@anchor{gnat_rm/the_gnat_library gnat-float-control-g-flocon-ads}@anchor{375}@anchor{gnat_rm/the_gnat_library id81}@anchor{376}
@section @code{GNAT.Float_Control} (@code{g-flocon.ads})
@@ -24261,7 +24522,7 @@ library calls may cause this mode to be modified, and the Reset procedure
in this package can be used to reestablish the required mode.
@node GNAT Formatted_String g-forstr ads,GNAT Heap_Sort g-heasor ads,GNAT Float_Control g-flocon ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-formatted-string-g-forstr-ads}@anchor{375}@anchor{gnat_rm/the_gnat_library id82}@anchor{376}
+@anchor{gnat_rm/the_gnat_library gnat-formatted-string-g-forstr-ads}@anchor{377}@anchor{gnat_rm/the_gnat_library id82}@anchor{378}
@section @code{GNAT.Formatted_String} (@code{g-forstr.ads})
@@ -24276,7 +24537,7 @@ derived from Integer, Float or enumerations as values for the
formatted string.
@node GNAT Heap_Sort g-heasor ads,GNAT Heap_Sort_A g-hesora ads,GNAT Formatted_String g-forstr ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-heasor-ads}@anchor{377}@anchor{gnat_rm/the_gnat_library id83}@anchor{378}
+@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-heasor-ads}@anchor{379}@anchor{gnat_rm/the_gnat_library id83}@anchor{37a}
@section @code{GNAT.Heap_Sort} (@code{g-heasor.ads})
@@ -24290,7 +24551,7 @@ access-to-procedure values. The algorithm used is a modified heap sort
that performs approximately N*log(N) comparisons in the worst case.
@node GNAT Heap_Sort_A g-hesora ads,GNAT Heap_Sort_G g-hesorg ads,GNAT Heap_Sort g-heasor ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-heap-sort-a-g-hesora-ads}@anchor{379}@anchor{gnat_rm/the_gnat_library id84}@anchor{37a}
+@anchor{gnat_rm/the_gnat_library gnat-heap-sort-a-g-hesora-ads}@anchor{37b}@anchor{gnat_rm/the_gnat_library id84}@anchor{37c}
@section @code{GNAT.Heap_Sort_A} (@code{g-hesora.ads})
@@ -24306,7 +24567,7 @@ This differs from @code{GNAT.Heap_Sort} in having a less convenient
interface, but may be slightly more efficient.
@node GNAT Heap_Sort_G g-hesorg ads,GNAT HTable g-htable ads,GNAT Heap_Sort_A g-hesora ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-g-hesorg-ads}@anchor{37b}@anchor{gnat_rm/the_gnat_library id85}@anchor{37c}
+@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-g-hesorg-ads}@anchor{37d}@anchor{gnat_rm/the_gnat_library id85}@anchor{37e}
@section @code{GNAT.Heap_Sort_G} (@code{g-hesorg.ads})
@@ -24320,7 +24581,7 @@ if the procedures can be inlined, at the expense of duplicating code for
multiple instantiations.
@node GNAT HTable g-htable ads,GNAT IO g-io ads,GNAT Heap_Sort_G g-hesorg ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-htable-g-htable-ads}@anchor{37d}@anchor{gnat_rm/the_gnat_library id86}@anchor{37e}
+@anchor{gnat_rm/the_gnat_library gnat-htable-g-htable-ads}@anchor{37f}@anchor{gnat_rm/the_gnat_library id86}@anchor{380}
@section @code{GNAT.HTable} (@code{g-htable.ads})
@@ -24333,7 +24594,7 @@ data. Provides two approaches, one a simple static approach, and the other
allowing arbitrary dynamic hash tables.
@node GNAT IO g-io ads,GNAT IO_Aux g-io_aux ads,GNAT HTable g-htable ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-io-g-io-ads}@anchor{37f}@anchor{gnat_rm/the_gnat_library id87}@anchor{380}
+@anchor{gnat_rm/the_gnat_library gnat-io-g-io-ads}@anchor{381}@anchor{gnat_rm/the_gnat_library id87}@anchor{382}
@section @code{GNAT.IO} (@code{g-io.ads})
@@ -24349,7 +24610,7 @@ Standard_Input, and writing characters, strings and integers to either
Standard_Output or Standard_Error.
@node GNAT IO_Aux g-io_aux ads,GNAT Lock_Files g-locfil ads,GNAT IO g-io ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-io-aux-g-io-aux-ads}@anchor{381}@anchor{gnat_rm/the_gnat_library id88}@anchor{382}
+@anchor{gnat_rm/the_gnat_library gnat-io-aux-g-io-aux-ads}@anchor{383}@anchor{gnat_rm/the_gnat_library id88}@anchor{384}
@section @code{GNAT.IO_Aux} (@code{g-io_aux.ads})
@@ -24363,7 +24624,7 @@ Provides some auxiliary functions for use with Text_IO, including a test
for whether a file exists, and functions for reading a line of text.
@node GNAT Lock_Files g-locfil ads,GNAT MBBS_Discrete_Random g-mbdira ads,GNAT IO_Aux g-io_aux ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-lock-files-g-locfil-ads}@anchor{383}@anchor{gnat_rm/the_gnat_library id89}@anchor{384}
+@anchor{gnat_rm/the_gnat_library gnat-lock-files-g-locfil-ads}@anchor{385}@anchor{gnat_rm/the_gnat_library id89}@anchor{386}
@section @code{GNAT.Lock_Files} (@code{g-locfil.ads})
@@ -24377,7 +24638,7 @@ Provides a general interface for using files as locks. Can be used for
providing program level synchronization.
@node GNAT MBBS_Discrete_Random g-mbdira ads,GNAT MBBS_Float_Random g-mbflra ads,GNAT Lock_Files g-locfil ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-mbbs-discrete-random-g-mbdira-ads}@anchor{385}@anchor{gnat_rm/the_gnat_library id90}@anchor{386}
+@anchor{gnat_rm/the_gnat_library gnat-mbbs-discrete-random-g-mbdira-ads}@anchor{387}@anchor{gnat_rm/the_gnat_library id90}@anchor{388}
@section @code{GNAT.MBBS_Discrete_Random} (@code{g-mbdira.ads})
@@ -24389,7 +24650,7 @@ The original implementation of @code{Ada.Numerics.Discrete_Random}. Uses
a modified version of the Blum-Blum-Shub generator.
@node GNAT MBBS_Float_Random g-mbflra ads,GNAT MD5 g-md5 ads,GNAT MBBS_Discrete_Random g-mbdira ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-mbbs-float-random-g-mbflra-ads}@anchor{387}@anchor{gnat_rm/the_gnat_library id91}@anchor{388}
+@anchor{gnat_rm/the_gnat_library gnat-mbbs-float-random-g-mbflra-ads}@anchor{389}@anchor{gnat_rm/the_gnat_library id91}@anchor{38a}
@section @code{GNAT.MBBS_Float_Random} (@code{g-mbflra.ads})
@@ -24401,7 +24662,7 @@ The original implementation of @code{Ada.Numerics.Float_Random}. Uses
a modified version of the Blum-Blum-Shub generator.
@node GNAT MD5 g-md5 ads,GNAT Memory_Dump g-memdum ads,GNAT MBBS_Float_Random g-mbflra ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-md5-g-md5-ads}@anchor{389}@anchor{gnat_rm/the_gnat_library id92}@anchor{38a}
+@anchor{gnat_rm/the_gnat_library gnat-md5-g-md5-ads}@anchor{38b}@anchor{gnat_rm/the_gnat_library id92}@anchor{38c}
@section @code{GNAT.MD5} (@code{g-md5.ads})
@@ -24414,7 +24675,7 @@ the HMAC-MD5 message authentication function as described in RFC 2104 and
FIPS PUB 198.
@node GNAT Memory_Dump g-memdum ads,GNAT Most_Recent_Exception g-moreex ads,GNAT MD5 g-md5 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-memory-dump-g-memdum-ads}@anchor{38b}@anchor{gnat_rm/the_gnat_library id93}@anchor{38c}
+@anchor{gnat_rm/the_gnat_library gnat-memory-dump-g-memdum-ads}@anchor{38d}@anchor{gnat_rm/the_gnat_library id93}@anchor{38e}
@section @code{GNAT.Memory_Dump} (@code{g-memdum.ads})
@@ -24427,7 +24688,7 @@ standard output or standard error files. Uses GNAT.IO for actual
output.
@node GNAT Most_Recent_Exception g-moreex ads,GNAT OS_Lib g-os_lib ads,GNAT Memory_Dump g-memdum ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-most-recent-exception-g-moreex-ads}@anchor{38d}@anchor{gnat_rm/the_gnat_library id94}@anchor{38e}
+@anchor{gnat_rm/the_gnat_library gnat-most-recent-exception-g-moreex-ads}@anchor{38f}@anchor{gnat_rm/the_gnat_library id94}@anchor{390}
@section @code{GNAT.Most_Recent_Exception} (@code{g-moreex.ads})
@@ -24441,7 +24702,7 @@ various logging purposes, including duplicating functionality of some
Ada 83 implementation dependent extensions.
@node GNAT OS_Lib g-os_lib ads,GNAT Perfect_Hash_Generators g-pehage ads,GNAT Most_Recent_Exception g-moreex ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-os-lib-g-os-lib-ads}@anchor{38f}@anchor{gnat_rm/the_gnat_library id95}@anchor{390}
+@anchor{gnat_rm/the_gnat_library gnat-os-lib-g-os-lib-ads}@anchor{391}@anchor{gnat_rm/the_gnat_library id95}@anchor{392}
@section @code{GNAT.OS_Lib} (@code{g-os_lib.ads})
@@ -24457,7 +24718,7 @@ including a portable spawn procedure, and access to environment variables
and error return codes.
@node GNAT Perfect_Hash_Generators g-pehage ads,GNAT Random_Numbers g-rannum ads,GNAT OS_Lib g-os_lib ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-perfect-hash-generators-g-pehage-ads}@anchor{391}@anchor{gnat_rm/the_gnat_library id96}@anchor{392}
+@anchor{gnat_rm/the_gnat_library gnat-perfect-hash-generators-g-pehage-ads}@anchor{393}@anchor{gnat_rm/the_gnat_library id96}@anchor{394}
@section @code{GNAT.Perfect_Hash_Generators} (@code{g-pehage.ads})
@@ -24475,7 +24736,7 @@ hashcode are in the same order. These hashing functions are very
convenient for use with realtime applications.
@node GNAT Random_Numbers g-rannum ads,GNAT Regexp g-regexp ads,GNAT Perfect_Hash_Generators g-pehage ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-random-numbers-g-rannum-ads}@anchor{393}@anchor{gnat_rm/the_gnat_library id97}@anchor{394}
+@anchor{gnat_rm/the_gnat_library gnat-random-numbers-g-rannum-ads}@anchor{395}@anchor{gnat_rm/the_gnat_library id97}@anchor{396}
@section @code{GNAT.Random_Numbers} (@code{g-rannum.ads})
@@ -24487,7 +24748,7 @@ Provides random number capabilities which extend those available in the
standard Ada library and are more convenient to use.
@node GNAT Regexp g-regexp ads,GNAT Registry g-regist ads,GNAT Random_Numbers g-rannum ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-regexp-g-regexp-ads}@anchor{25a}@anchor{gnat_rm/the_gnat_library id98}@anchor{395}
+@anchor{gnat_rm/the_gnat_library gnat-regexp-g-regexp-ads}@anchor{25c}@anchor{gnat_rm/the_gnat_library id98}@anchor{397}
@section @code{GNAT.Regexp} (@code{g-regexp.ads})
@@ -24503,7 +24764,7 @@ simplest of the three pattern matching packages provided, and is particularly
suitable for ‘file globbing’ applications.
@node GNAT Registry g-regist ads,GNAT Regpat g-regpat ads,GNAT Regexp g-regexp ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-registry-g-regist-ads}@anchor{396}@anchor{gnat_rm/the_gnat_library id99}@anchor{397}
+@anchor{gnat_rm/the_gnat_library gnat-registry-g-regist-ads}@anchor{398}@anchor{gnat_rm/the_gnat_library id99}@anchor{399}
@section @code{GNAT.Registry} (@code{g-regist.ads})
@@ -24517,7 +24778,7 @@ registry API, but at a lower level of abstraction, refer to the Win32.Winreg
package provided with the Win32Ada binding
@node GNAT Regpat g-regpat ads,GNAT Rewrite_Data g-rewdat ads,GNAT Registry g-regist ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-regpat-g-regpat-ads}@anchor{398}@anchor{gnat_rm/the_gnat_library id100}@anchor{399}
+@anchor{gnat_rm/the_gnat_library gnat-regpat-g-regpat-ads}@anchor{39a}@anchor{gnat_rm/the_gnat_library id100}@anchor{39b}
@section @code{GNAT.Regpat} (@code{g-regpat.ads})
@@ -24532,7 +24793,7 @@ from the original V7 style regular expression library written in C by
Henry Spencer (and binary compatible with this C library).
@node GNAT Rewrite_Data g-rewdat ads,GNAT Secondary_Stack_Info g-sestin ads,GNAT Regpat g-regpat ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-rewrite-data-g-rewdat-ads}@anchor{39a}@anchor{gnat_rm/the_gnat_library id101}@anchor{39b}
+@anchor{gnat_rm/the_gnat_library gnat-rewrite-data-g-rewdat-ads}@anchor{39c}@anchor{gnat_rm/the_gnat_library id101}@anchor{39d}
@section @code{GNAT.Rewrite_Data} (@code{g-rewdat.ads})
@@ -24546,7 +24807,7 @@ full content to be processed is not loaded into memory all at once. This makes
this interface usable for large files or socket streams.
@node GNAT Secondary_Stack_Info g-sestin ads,GNAT Semaphores g-semaph ads,GNAT Rewrite_Data g-rewdat ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-secondary-stack-info-g-sestin-ads}@anchor{39c}@anchor{gnat_rm/the_gnat_library id102}@anchor{39d}
+@anchor{gnat_rm/the_gnat_library gnat-secondary-stack-info-g-sestin-ads}@anchor{39e}@anchor{gnat_rm/the_gnat_library id102}@anchor{39f}
@section @code{GNAT.Secondary_Stack_Info} (@code{g-sestin.ads})
@@ -24558,7 +24819,7 @@ Provide the capability to query the high water mark of the current task’s
secondary stack.
@node GNAT Semaphores g-semaph ads,GNAT Serial_Communications g-sercom ads,GNAT Secondary_Stack_Info g-sestin ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-semaphores-g-semaph-ads}@anchor{39e}@anchor{gnat_rm/the_gnat_library id103}@anchor{39f}
+@anchor{gnat_rm/the_gnat_library gnat-semaphores-g-semaph-ads}@anchor{3a0}@anchor{gnat_rm/the_gnat_library id103}@anchor{3a1}
@section @code{GNAT.Semaphores} (@code{g-semaph.ads})
@@ -24569,7 +24830,7 @@ secondary stack.
Provides classic counting and binary semaphores using protected types.
@node GNAT Serial_Communications g-sercom ads,GNAT SHA1 g-sha1 ads,GNAT Semaphores g-semaph ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-serial-communications-g-sercom-ads}@anchor{3a0}@anchor{gnat_rm/the_gnat_library id104}@anchor{3a1}
+@anchor{gnat_rm/the_gnat_library gnat-serial-communications-g-sercom-ads}@anchor{3a2}@anchor{gnat_rm/the_gnat_library id104}@anchor{3a3}
@section @code{GNAT.Serial_Communications} (@code{g-sercom.ads})
@@ -24581,7 +24842,7 @@ Provides a simple interface to send and receive data over a serial
port. This is only supported on GNU/Linux and Windows.
@node GNAT SHA1 g-sha1 ads,GNAT SHA224 g-sha224 ads,GNAT Serial_Communications g-sercom ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-sha1-g-sha1-ads}@anchor{3a2}@anchor{gnat_rm/the_gnat_library id105}@anchor{3a3}
+@anchor{gnat_rm/the_gnat_library gnat-sha1-g-sha1-ads}@anchor{3a4}@anchor{gnat_rm/the_gnat_library id105}@anchor{3a5}
@section @code{GNAT.SHA1} (@code{g-sha1.ads})
@@ -24594,7 +24855,7 @@ and RFC 3174, and the HMAC-SHA1 message authentication function as described
in RFC 2104 and FIPS PUB 198.
@node GNAT SHA224 g-sha224 ads,GNAT SHA256 g-sha256 ads,GNAT SHA1 g-sha1 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-sha224-g-sha224-ads}@anchor{3a4}@anchor{gnat_rm/the_gnat_library id106}@anchor{3a5}
+@anchor{gnat_rm/the_gnat_library gnat-sha224-g-sha224-ads}@anchor{3a6}@anchor{gnat_rm/the_gnat_library id106}@anchor{3a7}
@section @code{GNAT.SHA224} (@code{g-sha224.ads})
@@ -24607,7 +24868,7 @@ and the HMAC-SHA224 message authentication function as described
in RFC 2104 and FIPS PUB 198.
@node GNAT SHA256 g-sha256 ads,GNAT SHA384 g-sha384 ads,GNAT SHA224 g-sha224 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-sha256-g-sha256-ads}@anchor{3a6}@anchor{gnat_rm/the_gnat_library id107}@anchor{3a7}
+@anchor{gnat_rm/the_gnat_library gnat-sha256-g-sha256-ads}@anchor{3a8}@anchor{gnat_rm/the_gnat_library id107}@anchor{3a9}
@section @code{GNAT.SHA256} (@code{g-sha256.ads})
@@ -24620,7 +24881,7 @@ and the HMAC-SHA256 message authentication function as described
in RFC 2104 and FIPS PUB 198.
@node GNAT SHA384 g-sha384 ads,GNAT SHA512 g-sha512 ads,GNAT SHA256 g-sha256 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-sha384-g-sha384-ads}@anchor{3a8}@anchor{gnat_rm/the_gnat_library id108}@anchor{3a9}
+@anchor{gnat_rm/the_gnat_library gnat-sha384-g-sha384-ads}@anchor{3aa}@anchor{gnat_rm/the_gnat_library id108}@anchor{3ab}
@section @code{GNAT.SHA384} (@code{g-sha384.ads})
@@ -24633,7 +24894,7 @@ and the HMAC-SHA384 message authentication function as described
in RFC 2104 and FIPS PUB 198.
@node GNAT SHA512 g-sha512 ads,GNAT Signals g-signal ads,GNAT SHA384 g-sha384 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-sha512-g-sha512-ads}@anchor{3aa}@anchor{gnat_rm/the_gnat_library id109}@anchor{3ab}
+@anchor{gnat_rm/the_gnat_library gnat-sha512-g-sha512-ads}@anchor{3ac}@anchor{gnat_rm/the_gnat_library id109}@anchor{3ad}
@section @code{GNAT.SHA512} (@code{g-sha512.ads})
@@ -24646,7 +24907,7 @@ and the HMAC-SHA512 message authentication function as described
in RFC 2104 and FIPS PUB 198.
@node GNAT Signals g-signal ads,GNAT Sockets g-socket ads,GNAT SHA512 g-sha512 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-signals-g-signal-ads}@anchor{3ac}@anchor{gnat_rm/the_gnat_library id110}@anchor{3ad}
+@anchor{gnat_rm/the_gnat_library gnat-signals-g-signal-ads}@anchor{3ae}@anchor{gnat_rm/the_gnat_library id110}@anchor{3af}
@section @code{GNAT.Signals} (@code{g-signal.ads})
@@ -24658,7 +24919,7 @@ Provides the ability to manipulate the blocked status of signals on supported
targets.
@node GNAT Sockets g-socket ads,GNAT Source_Info g-souinf ads,GNAT Signals g-signal ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-sockets-g-socket-ads}@anchor{3ae}@anchor{gnat_rm/the_gnat_library id111}@anchor{3af}
+@anchor{gnat_rm/the_gnat_library gnat-sockets-g-socket-ads}@anchor{3b0}@anchor{gnat_rm/the_gnat_library id111}@anchor{3b1}
@section @code{GNAT.Sockets} (@code{g-socket.ads})
@@ -24673,7 +24934,7 @@ on all native GNAT ports and on VxWorks cross prots. It is not implemented for
the LynxOS cross port.
@node GNAT Source_Info g-souinf ads,GNAT Spelling_Checker g-speche ads,GNAT Sockets g-socket ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-source-info-g-souinf-ads}@anchor{3b0}@anchor{gnat_rm/the_gnat_library id112}@anchor{3b1}
+@anchor{gnat_rm/the_gnat_library gnat-source-info-g-souinf-ads}@anchor{3b2}@anchor{gnat_rm/the_gnat_library id112}@anchor{3b3}
@section @code{GNAT.Source_Info} (@code{g-souinf.ads})
@@ -24687,7 +24948,7 @@ subprograms yielding the date and time of the current compilation (like the
C macros @code{__DATE__} and @code{__TIME__})
@node GNAT Spelling_Checker g-speche ads,GNAT Spelling_Checker_Generic g-spchge ads,GNAT Source_Info g-souinf ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-spelling-checker-g-speche-ads}@anchor{3b2}@anchor{gnat_rm/the_gnat_library id113}@anchor{3b3}
+@anchor{gnat_rm/the_gnat_library gnat-spelling-checker-g-speche-ads}@anchor{3b4}@anchor{gnat_rm/the_gnat_library id113}@anchor{3b5}
@section @code{GNAT.Spelling_Checker} (@code{g-speche.ads})
@@ -24699,7 +24960,7 @@ Provides a function for determining whether one string is a plausible
near misspelling of another string.
@node GNAT Spelling_Checker_Generic g-spchge ads,GNAT Spitbol Patterns g-spipat ads,GNAT Spelling_Checker g-speche ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-spelling-checker-generic-g-spchge-ads}@anchor{3b4}@anchor{gnat_rm/the_gnat_library id114}@anchor{3b5}
+@anchor{gnat_rm/the_gnat_library gnat-spelling-checker-generic-g-spchge-ads}@anchor{3b6}@anchor{gnat_rm/the_gnat_library id114}@anchor{3b7}
@section @code{GNAT.Spelling_Checker_Generic} (@code{g-spchge.ads})
@@ -24712,7 +24973,7 @@ determining whether one string is a plausible near misspelling of another
string.
@node GNAT Spitbol Patterns g-spipat ads,GNAT Spitbol g-spitbo ads,GNAT Spelling_Checker_Generic g-spchge ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-spitbol-patterns-g-spipat-ads}@anchor{3b6}@anchor{gnat_rm/the_gnat_library id115}@anchor{3b7}
+@anchor{gnat_rm/the_gnat_library gnat-spitbol-patterns-g-spipat-ads}@anchor{3b8}@anchor{gnat_rm/the_gnat_library id115}@anchor{3b9}
@section @code{GNAT.Spitbol.Patterns} (@code{g-spipat.ads})
@@ -24728,7 +24989,7 @@ the SNOBOL4 dynamic pattern construction and matching capabilities, using the
efficient algorithm developed by Robert Dewar for the SPITBOL system.
@node GNAT Spitbol g-spitbo ads,GNAT Spitbol Table_Boolean g-sptabo ads,GNAT Spitbol Patterns g-spipat ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-spitbol-g-spitbo-ads}@anchor{3b8}@anchor{gnat_rm/the_gnat_library id116}@anchor{3b9}
+@anchor{gnat_rm/the_gnat_library gnat-spitbol-g-spitbo-ads}@anchor{3ba}@anchor{gnat_rm/the_gnat_library id116}@anchor{3bb}
@section @code{GNAT.Spitbol} (@code{g-spitbo.ads})
@@ -24743,7 +25004,7 @@ useful for constructing arbitrary mappings from strings in the style of
the SNOBOL4 TABLE function.
@node GNAT Spitbol Table_Boolean g-sptabo ads,GNAT Spitbol Table_Integer g-sptain ads,GNAT Spitbol g-spitbo ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-boolean-g-sptabo-ads}@anchor{3ba}@anchor{gnat_rm/the_gnat_library id117}@anchor{3bb}
+@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-boolean-g-sptabo-ads}@anchor{3bc}@anchor{gnat_rm/the_gnat_library id117}@anchor{3bd}
@section @code{GNAT.Spitbol.Table_Boolean} (@code{g-sptabo.ads})
@@ -24758,7 +25019,7 @@ for type @code{Standard.Boolean}, giving an implementation of sets of
string values.
@node GNAT Spitbol Table_Integer g-sptain ads,GNAT Spitbol Table_VString g-sptavs ads,GNAT Spitbol Table_Boolean g-sptabo ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-integer-g-sptain-ads}@anchor{3bc}@anchor{gnat_rm/the_gnat_library id118}@anchor{3bd}
+@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-integer-g-sptain-ads}@anchor{3be}@anchor{gnat_rm/the_gnat_library id118}@anchor{3bf}
@section @code{GNAT.Spitbol.Table_Integer} (@code{g-sptain.ads})
@@ -24775,7 +25036,7 @@ for type @code{Standard.Integer}, giving an implementation of maps
from string to integer values.
@node GNAT Spitbol Table_VString g-sptavs ads,GNAT SSE g-sse ads,GNAT Spitbol Table_Integer g-sptain ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-vstring-g-sptavs-ads}@anchor{3be}@anchor{gnat_rm/the_gnat_library id119}@anchor{3bf}
+@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-vstring-g-sptavs-ads}@anchor{3c0}@anchor{gnat_rm/the_gnat_library id119}@anchor{3c1}
@section @code{GNAT.Spitbol.Table_VString} (@code{g-sptavs.ads})
@@ -24792,7 +25053,7 @@ a variable length string type, giving an implementation of general
maps from strings to strings.
@node GNAT SSE g-sse ads,GNAT SSE Vector_Types g-ssvety ads,GNAT Spitbol Table_VString g-sptavs ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-sse-g-sse-ads}@anchor{3c0}@anchor{gnat_rm/the_gnat_library id120}@anchor{3c1}
+@anchor{gnat_rm/the_gnat_library gnat-sse-g-sse-ads}@anchor{3c2}@anchor{gnat_rm/the_gnat_library id120}@anchor{3c3}
@section @code{GNAT.SSE} (@code{g-sse.ads})
@@ -24804,7 +25065,7 @@ targets. It exposes vector component types together with a general
introduction to the binding contents and use.
@node GNAT SSE Vector_Types g-ssvety ads,GNAT String_Hash g-strhas ads,GNAT SSE g-sse ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-sse-vector-types-g-ssvety-ads}@anchor{3c2}@anchor{gnat_rm/the_gnat_library id121}@anchor{3c3}
+@anchor{gnat_rm/the_gnat_library gnat-sse-vector-types-g-ssvety-ads}@anchor{3c4}@anchor{gnat_rm/the_gnat_library id121}@anchor{3c5}
@section @code{GNAT.SSE.Vector_Types} (@code{g-ssvety.ads})
@@ -24813,7 +25074,7 @@ introduction to the binding contents and use.
SSE vector types for use with SSE related intrinsics.
@node GNAT String_Hash g-strhas ads,GNAT Strings g-string ads,GNAT SSE Vector_Types g-ssvety ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-string-hash-g-strhas-ads}@anchor{3c4}@anchor{gnat_rm/the_gnat_library id122}@anchor{3c5}
+@anchor{gnat_rm/the_gnat_library gnat-string-hash-g-strhas-ads}@anchor{3c6}@anchor{gnat_rm/the_gnat_library id122}@anchor{3c7}
@section @code{GNAT.String_Hash} (@code{g-strhas.ads})
@@ -24825,7 +25086,7 @@ Provides a generic hash function working on arrays of scalars. Both the scalar
type and the hash result type are parameters.
@node GNAT Strings g-string ads,GNAT String_Split g-strspl ads,GNAT String_Hash g-strhas ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-strings-g-string-ads}@anchor{3c6}@anchor{gnat_rm/the_gnat_library id123}@anchor{3c7}
+@anchor{gnat_rm/the_gnat_library gnat-strings-g-string-ads}@anchor{3c8}@anchor{gnat_rm/the_gnat_library id123}@anchor{3c9}
@section @code{GNAT.Strings} (@code{g-string.ads})
@@ -24835,7 +25096,7 @@ Common String access types and related subprograms. Basically it
defines a string access and an array of string access types.
@node GNAT String_Split g-strspl ads,GNAT Table g-table ads,GNAT Strings g-string ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-string-split-g-strspl-ads}@anchor{3c8}@anchor{gnat_rm/the_gnat_library id124}@anchor{3c9}
+@anchor{gnat_rm/the_gnat_library gnat-string-split-g-strspl-ads}@anchor{3ca}@anchor{gnat_rm/the_gnat_library id124}@anchor{3cb}
@section @code{GNAT.String_Split} (@code{g-strspl.ads})
@@ -24849,7 +25110,7 @@ to the resulting slices. This package is instantiated from
@code{GNAT.Array_Split}.
@node GNAT Table g-table ads,GNAT Task_Lock g-tasloc ads,GNAT String_Split g-strspl ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-table-g-table-ads}@anchor{3ca}@anchor{gnat_rm/the_gnat_library id125}@anchor{3cb}
+@anchor{gnat_rm/the_gnat_library gnat-table-g-table-ads}@anchor{3cc}@anchor{gnat_rm/the_gnat_library id125}@anchor{3cd}
@section @code{GNAT.Table} (@code{g-table.ads})
@@ -24869,7 +25130,7 @@ while an instantiation of @code{GNAT.Dynamic_Tables} creates a type that can be
used to define dynamic instances of the table.
@node GNAT Task_Lock g-tasloc ads,GNAT Time_Stamp g-timsta ads,GNAT Table g-table ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-task-lock-g-tasloc-ads}@anchor{3cc}@anchor{gnat_rm/the_gnat_library id126}@anchor{3cd}
+@anchor{gnat_rm/the_gnat_library gnat-task-lock-g-tasloc-ads}@anchor{3ce}@anchor{gnat_rm/the_gnat_library id126}@anchor{3cf}
@section @code{GNAT.Task_Lock} (@code{g-tasloc.ads})
@@ -24886,7 +25147,7 @@ single global task lock. Appropriate for use in situations where contention
between tasks is very rarely expected.
@node GNAT Time_Stamp g-timsta ads,GNAT Threads g-thread ads,GNAT Task_Lock g-tasloc ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-time-stamp-g-timsta-ads}@anchor{3ce}@anchor{gnat_rm/the_gnat_library id127}@anchor{3cf}
+@anchor{gnat_rm/the_gnat_library gnat-time-stamp-g-timsta-ads}@anchor{3d0}@anchor{gnat_rm/the_gnat_library id127}@anchor{3d1}
@section @code{GNAT.Time_Stamp} (@code{g-timsta.ads})
@@ -24901,7 +25162,7 @@ represents the current date and time in ISO 8601 format. This is a very simple
routine with minimal code and there are no dependencies on any other unit.
@node GNAT Threads g-thread ads,GNAT Traceback g-traceb ads,GNAT Time_Stamp g-timsta ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-threads-g-thread-ads}@anchor{3d0}@anchor{gnat_rm/the_gnat_library id128}@anchor{3d1}
+@anchor{gnat_rm/the_gnat_library gnat-threads-g-thread-ads}@anchor{3d2}@anchor{gnat_rm/the_gnat_library id128}@anchor{3d3}
@section @code{GNAT.Threads} (@code{g-thread.ads})
@@ -24918,7 +25179,7 @@ further details if your program has threads that are created by a non-Ada
environment which then accesses Ada code.
@node GNAT Traceback g-traceb ads,GNAT Traceback Symbolic g-trasym ads,GNAT Threads g-thread ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-traceback-g-traceb-ads}@anchor{3d2}@anchor{gnat_rm/the_gnat_library id129}@anchor{3d3}
+@anchor{gnat_rm/the_gnat_library gnat-traceback-g-traceb-ads}@anchor{3d4}@anchor{gnat_rm/the_gnat_library id129}@anchor{3d5}
@section @code{GNAT.Traceback} (@code{g-traceb.ads})
@@ -24930,7 +25191,7 @@ Provides a facility for obtaining non-symbolic traceback information, useful
in various debugging situations.
@node GNAT Traceback Symbolic g-trasym ads,GNAT UTF_32 g-table ads,GNAT Traceback g-traceb ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-traceback-symbolic-g-trasym-ads}@anchor{3d4}@anchor{gnat_rm/the_gnat_library id130}@anchor{3d5}
+@anchor{gnat_rm/the_gnat_library gnat-traceback-symbolic-g-trasym-ads}@anchor{3d6}@anchor{gnat_rm/the_gnat_library id130}@anchor{3d7}
@section @code{GNAT.Traceback.Symbolic} (@code{g-trasym.ads})
@@ -24939,7 +25200,7 @@ in various debugging situations.
@geindex Trace back facilities
@node GNAT UTF_32 g-table ads,GNAT Wide_Spelling_Checker g-u3spch ads,GNAT Traceback Symbolic g-trasym ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-utf-32-g-table-ads}@anchor{3d6}@anchor{gnat_rm/the_gnat_library id131}@anchor{3d7}
+@anchor{gnat_rm/the_gnat_library gnat-utf-32-g-table-ads}@anchor{3d8}@anchor{gnat_rm/the_gnat_library id131}@anchor{3d9}
@section @code{GNAT.UTF_32} (@code{g-table.ads})
@@ -24958,7 +25219,7 @@ lower case to upper case fold routine corresponding to
the Ada 2005 rules for identifier equivalence.
@node GNAT Wide_Spelling_Checker g-u3spch ads,GNAT Wide_Spelling_Checker g-wispch ads,GNAT UTF_32 g-table ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-wide-spelling-checker-g-u3spch-ads}@anchor{3d8}@anchor{gnat_rm/the_gnat_library id132}@anchor{3d9}
+@anchor{gnat_rm/the_gnat_library gnat-wide-spelling-checker-g-u3spch-ads}@anchor{3da}@anchor{gnat_rm/the_gnat_library id132}@anchor{3db}
@section @code{GNAT.Wide_Spelling_Checker} (@code{g-u3spch.ads})
@@ -24971,7 +25232,7 @@ near misspelling of another wide wide string, where the strings are represented
using the UTF_32_String type defined in System.Wch_Cnv.
@node GNAT Wide_Spelling_Checker g-wispch ads,GNAT Wide_String_Split g-wistsp ads,GNAT Wide_Spelling_Checker g-u3spch ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-wide-spelling-checker-g-wispch-ads}@anchor{3da}@anchor{gnat_rm/the_gnat_library id133}@anchor{3db}
+@anchor{gnat_rm/the_gnat_library gnat-wide-spelling-checker-g-wispch-ads}@anchor{3dc}@anchor{gnat_rm/the_gnat_library id133}@anchor{3dd}
@section @code{GNAT.Wide_Spelling_Checker} (@code{g-wispch.ads})
@@ -24983,7 +25244,7 @@ Provides a function for determining whether one wide string is a plausible
near misspelling of another wide string.
@node GNAT Wide_String_Split g-wistsp ads,GNAT Wide_Wide_Spelling_Checker g-zspche ads,GNAT Wide_Spelling_Checker g-wispch ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-wide-string-split-g-wistsp-ads}@anchor{3dc}@anchor{gnat_rm/the_gnat_library id134}@anchor{3dd}
+@anchor{gnat_rm/the_gnat_library gnat-wide-string-split-g-wistsp-ads}@anchor{3de}@anchor{gnat_rm/the_gnat_library id134}@anchor{3df}
@section @code{GNAT.Wide_String_Split} (@code{g-wistsp.ads})
@@ -24997,7 +25258,7 @@ to the resulting slices. This package is instantiated from
@code{GNAT.Array_Split}.
@node GNAT Wide_Wide_Spelling_Checker g-zspche ads,GNAT Wide_Wide_String_Split g-zistsp ads,GNAT Wide_String_Split g-wistsp ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-wide-wide-spelling-checker-g-zspche-ads}@anchor{3de}@anchor{gnat_rm/the_gnat_library id135}@anchor{3df}
+@anchor{gnat_rm/the_gnat_library gnat-wide-wide-spelling-checker-g-zspche-ads}@anchor{3e0}@anchor{gnat_rm/the_gnat_library id135}@anchor{3e1}
@section @code{GNAT.Wide_Wide_Spelling_Checker} (@code{g-zspche.ads})
@@ -25009,7 +25270,7 @@ Provides a function for determining whether one wide wide string is a plausible
near misspelling of another wide wide string.
@node GNAT Wide_Wide_String_Split g-zistsp ads,Interfaces C Extensions i-cexten ads,GNAT Wide_Wide_Spelling_Checker g-zspche ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-wide-wide-string-split-g-zistsp-ads}@anchor{3e0}@anchor{gnat_rm/the_gnat_library id136}@anchor{3e1}
+@anchor{gnat_rm/the_gnat_library gnat-wide-wide-string-split-g-zistsp-ads}@anchor{3e2}@anchor{gnat_rm/the_gnat_library id136}@anchor{3e3}
@section @code{GNAT.Wide_Wide_String_Split} (@code{g-zistsp.ads})
@@ -25023,7 +25284,7 @@ to the resulting slices. This package is instantiated from
@code{GNAT.Array_Split}.
@node Interfaces C Extensions i-cexten ads,Interfaces C Streams i-cstrea ads,GNAT Wide_Wide_String_Split g-zistsp ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id137}@anchor{3e2}@anchor{gnat_rm/the_gnat_library interfaces-c-extensions-i-cexten-ads}@anchor{3e3}
+@anchor{gnat_rm/the_gnat_library id137}@anchor{3e4}@anchor{gnat_rm/the_gnat_library interfaces-c-extensions-i-cexten-ads}@anchor{3e5}
@section @code{Interfaces.C.Extensions} (@code{i-cexten.ads})
@@ -25034,7 +25295,7 @@ for use with either manually or automatically generated bindings
to C libraries.
@node Interfaces C Streams i-cstrea ads,Interfaces Packed_Decimal i-pacdec ads,Interfaces C Extensions i-cexten ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id138}@anchor{3e4}@anchor{gnat_rm/the_gnat_library interfaces-c-streams-i-cstrea-ads}@anchor{3e5}
+@anchor{gnat_rm/the_gnat_library id138}@anchor{3e6}@anchor{gnat_rm/the_gnat_library interfaces-c-streams-i-cstrea-ads}@anchor{3e7}
@section @code{Interfaces.C.Streams} (@code{i-cstrea.ads})
@@ -25047,7 +25308,7 @@ This package is a binding for the most commonly used operations
on C streams.
@node Interfaces Packed_Decimal i-pacdec ads,Interfaces VxWorks i-vxwork ads,Interfaces C Streams i-cstrea ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id139}@anchor{3e6}@anchor{gnat_rm/the_gnat_library interfaces-packed-decimal-i-pacdec-ads}@anchor{3e7}
+@anchor{gnat_rm/the_gnat_library id139}@anchor{3e8}@anchor{gnat_rm/the_gnat_library interfaces-packed-decimal-i-pacdec-ads}@anchor{3e9}
@section @code{Interfaces.Packed_Decimal} (@code{i-pacdec.ads})
@@ -25062,7 +25323,7 @@ from a packed decimal format compatible with that used on IBM
mainframes.
@node Interfaces VxWorks i-vxwork ads,Interfaces VxWorks Int_Connection i-vxinco ads,Interfaces Packed_Decimal i-pacdec ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id140}@anchor{3e8}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-i-vxwork-ads}@anchor{3e9}
+@anchor{gnat_rm/the_gnat_library id140}@anchor{3ea}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-i-vxwork-ads}@anchor{3eb}
@section @code{Interfaces.VxWorks} (@code{i-vxwork.ads})
@@ -25078,7 +25339,7 @@ In particular, it interfaces with the
VxWorks hardware interrupt facilities.
@node Interfaces VxWorks Int_Connection i-vxinco ads,Interfaces VxWorks IO i-vxwoio ads,Interfaces VxWorks i-vxwork ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id141}@anchor{3ea}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-int-connection-i-vxinco-ads}@anchor{3eb}
+@anchor{gnat_rm/the_gnat_library id141}@anchor{3ec}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-int-connection-i-vxinco-ads}@anchor{3ed}
@section @code{Interfaces.VxWorks.Int_Connection} (@code{i-vxinco.ads})
@@ -25094,7 +25355,7 @@ intConnect() with a custom routine for installing interrupt
handlers.
@node Interfaces VxWorks IO i-vxwoio ads,System Address_Image s-addima ads,Interfaces VxWorks Int_Connection i-vxinco ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id142}@anchor{3ec}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-io-i-vxwoio-ads}@anchor{3ed}
+@anchor{gnat_rm/the_gnat_library id142}@anchor{3ee}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-io-i-vxwoio-ads}@anchor{3ef}
@section @code{Interfaces.VxWorks.IO} (@code{i-vxwoio.ads})
@@ -25117,7 +25378,7 @@ function codes. A particular use of this package is
to enable the use of Get_Immediate under VxWorks.
@node System Address_Image s-addima ads,System Assertions s-assert ads,Interfaces VxWorks IO i-vxwoio ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id143}@anchor{3ee}@anchor{gnat_rm/the_gnat_library system-address-image-s-addima-ads}@anchor{3ef}
+@anchor{gnat_rm/the_gnat_library id143}@anchor{3f0}@anchor{gnat_rm/the_gnat_library system-address-image-s-addima-ads}@anchor{3f1}
@section @code{System.Address_Image} (@code{s-addima.ads})
@@ -25133,7 +25394,7 @@ function that gives an (implementation dependent)
string which identifies an address.
@node System Assertions s-assert ads,System Atomic_Counters s-atocou ads,System Address_Image s-addima ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id144}@anchor{3f0}@anchor{gnat_rm/the_gnat_library system-assertions-s-assert-ads}@anchor{3f1}
+@anchor{gnat_rm/the_gnat_library id144}@anchor{3f2}@anchor{gnat_rm/the_gnat_library system-assertions-s-assert-ads}@anchor{3f3}
@section @code{System.Assertions} (@code{s-assert.ads})
@@ -25149,7 +25410,7 @@ by an run-time assertion failure, as well as the routine that
is used internally to raise this assertion.
@node System Atomic_Counters s-atocou ads,System Memory s-memory ads,System Assertions s-assert ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id145}@anchor{3f2}@anchor{gnat_rm/the_gnat_library system-atomic-counters-s-atocou-ads}@anchor{3f3}
+@anchor{gnat_rm/the_gnat_library id145}@anchor{3f4}@anchor{gnat_rm/the_gnat_library system-atomic-counters-s-atocou-ads}@anchor{3f5}
@section @code{System.Atomic_Counters} (@code{s-atocou.ads})
@@ -25163,7 +25424,7 @@ on most targets, including all Alpha, ia64, PowerPC, SPARC V9,
x86, and x86_64 platforms.
@node System Memory s-memory ads,System Multiprocessors s-multip ads,System Atomic_Counters s-atocou ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id146}@anchor{3f4}@anchor{gnat_rm/the_gnat_library system-memory-s-memory-ads}@anchor{3f5}
+@anchor{gnat_rm/the_gnat_library id146}@anchor{3f6}@anchor{gnat_rm/the_gnat_library system-memory-s-memory-ads}@anchor{3f7}
@section @code{System.Memory} (@code{s-memory.ads})
@@ -25181,7 +25442,7 @@ calls to this unit may be made for low level allocation uses (for
example see the body of @code{GNAT.Tables}).
@node System Multiprocessors s-multip ads,System Multiprocessors Dispatching_Domains s-mudido ads,System Memory s-memory ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id147}@anchor{3f6}@anchor{gnat_rm/the_gnat_library system-multiprocessors-s-multip-ads}@anchor{3f7}
+@anchor{gnat_rm/the_gnat_library id147}@anchor{3f8}@anchor{gnat_rm/the_gnat_library system-multiprocessors-s-multip-ads}@anchor{3f9}
@section @code{System.Multiprocessors} (@code{s-multip.ads})
@@ -25194,7 +25455,7 @@ in GNAT we also make it available in Ada 95 and Ada 2005 (where it is
technically an implementation-defined addition).
@node System Multiprocessors Dispatching_Domains s-mudido ads,System Partition_Interface s-parint ads,System Multiprocessors s-multip ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id148}@anchor{3f8}@anchor{gnat_rm/the_gnat_library system-multiprocessors-dispatching-domains-s-mudido-ads}@anchor{3f9}
+@anchor{gnat_rm/the_gnat_library id148}@anchor{3fa}@anchor{gnat_rm/the_gnat_library system-multiprocessors-dispatching-domains-s-mudido-ads}@anchor{3fb}
@section @code{System.Multiprocessors.Dispatching_Domains} (@code{s-mudido.ads})
@@ -25207,7 +25468,7 @@ in GNAT we also make it available in Ada 95 and Ada 2005 (where it is
technically an implementation-defined addition).
@node System Partition_Interface s-parint ads,System Pool_Global s-pooglo ads,System Multiprocessors Dispatching_Domains s-mudido ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id149}@anchor{3fa}@anchor{gnat_rm/the_gnat_library system-partition-interface-s-parint-ads}@anchor{3fb}
+@anchor{gnat_rm/the_gnat_library id149}@anchor{3fc}@anchor{gnat_rm/the_gnat_library system-partition-interface-s-parint-ads}@anchor{3fd}
@section @code{System.Partition_Interface} (@code{s-parint.ads})
@@ -25220,7 +25481,7 @@ is used primarily in a distribution context when using Annex E
with @code{GLADE}.
@node System Pool_Global s-pooglo ads,System Pool_Local s-pooloc ads,System Partition_Interface s-parint ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id150}@anchor{3fc}@anchor{gnat_rm/the_gnat_library system-pool-global-s-pooglo-ads}@anchor{3fd}
+@anchor{gnat_rm/the_gnat_library id150}@anchor{3fe}@anchor{gnat_rm/the_gnat_library system-pool-global-s-pooglo-ads}@anchor{3ff}
@section @code{System.Pool_Global} (@code{s-pooglo.ads})
@@ -25237,7 +25498,7 @@ declared. It uses malloc/free to allocate/free and does not attempt to
do any automatic reclamation.
@node System Pool_Local s-pooloc ads,System Restrictions s-restri ads,System Pool_Global s-pooglo ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id151}@anchor{3fe}@anchor{gnat_rm/the_gnat_library system-pool-local-s-pooloc-ads}@anchor{3ff}
+@anchor{gnat_rm/the_gnat_library id151}@anchor{400}@anchor{gnat_rm/the_gnat_library system-pool-local-s-pooloc-ads}@anchor{401}
@section @code{System.Pool_Local} (@code{s-pooloc.ads})
@@ -25254,7 +25515,7 @@ a list of allocated blocks, so that all storage allocated for the pool can
be freed automatically when the pool is finalized.
@node System Restrictions s-restri ads,System Rident s-rident ads,System Pool_Local s-pooloc ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id152}@anchor{400}@anchor{gnat_rm/the_gnat_library system-restrictions-s-restri-ads}@anchor{401}
+@anchor{gnat_rm/the_gnat_library id152}@anchor{402}@anchor{gnat_rm/the_gnat_library system-restrictions-s-restri-ads}@anchor{403}
@section @code{System.Restrictions} (@code{s-restri.ads})
@@ -25270,7 +25531,7 @@ compiler determined information on which restrictions
are violated by one or more packages in the partition.
@node System Rident s-rident ads,System Strings Stream_Ops s-ststop ads,System Restrictions s-restri ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id153}@anchor{402}@anchor{gnat_rm/the_gnat_library system-rident-s-rident-ads}@anchor{403}
+@anchor{gnat_rm/the_gnat_library id153}@anchor{404}@anchor{gnat_rm/the_gnat_library system-rident-s-rident-ads}@anchor{405}
@section @code{System.Rident} (@code{s-rident.ads})
@@ -25286,7 +25547,7 @@ since the necessary instantiation is included in
package System.Restrictions.
@node System Strings Stream_Ops s-ststop ads,System Unsigned_Types s-unstyp ads,System Rident s-rident ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id154}@anchor{404}@anchor{gnat_rm/the_gnat_library system-strings-stream-ops-s-ststop-ads}@anchor{405}
+@anchor{gnat_rm/the_gnat_library id154}@anchor{406}@anchor{gnat_rm/the_gnat_library system-strings-stream-ops-s-ststop-ads}@anchor{407}
@section @code{System.Strings.Stream_Ops} (@code{s-ststop.ads})
@@ -25302,7 +25563,7 @@ stream attributes are applied to string types, but the subprograms in this
package can be used directly by application programs.
@node System Unsigned_Types s-unstyp ads,System Wch_Cnv s-wchcnv ads,System Strings Stream_Ops s-ststop ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id155}@anchor{406}@anchor{gnat_rm/the_gnat_library system-unsigned-types-s-unstyp-ads}@anchor{407}
+@anchor{gnat_rm/the_gnat_library id155}@anchor{408}@anchor{gnat_rm/the_gnat_library system-unsigned-types-s-unstyp-ads}@anchor{409}
@section @code{System.Unsigned_Types} (@code{s-unstyp.ads})
@@ -25315,7 +25576,7 @@ also contains some related definitions for other specialized types
used by the compiler in connection with packed array types.
@node System Wch_Cnv s-wchcnv ads,System Wch_Con s-wchcon ads,System Unsigned_Types s-unstyp ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id156}@anchor{408}@anchor{gnat_rm/the_gnat_library system-wch-cnv-s-wchcnv-ads}@anchor{409}
+@anchor{gnat_rm/the_gnat_library id156}@anchor{40a}@anchor{gnat_rm/the_gnat_library system-wch-cnv-s-wchcnv-ads}@anchor{40b}
@section @code{System.Wch_Cnv} (@code{s-wchcnv.ads})
@@ -25336,7 +25597,7 @@ encoding method. It uses definitions in
package @code{System.Wch_Con}.
@node System Wch_Con s-wchcon ads,,System Wch_Cnv s-wchcnv ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id157}@anchor{40a}@anchor{gnat_rm/the_gnat_library system-wch-con-s-wchcon-ads}@anchor{40b}
+@anchor{gnat_rm/the_gnat_library id157}@anchor{40c}@anchor{gnat_rm/the_gnat_library system-wch-con-s-wchcon-ads}@anchor{40d}
@section @code{System.Wch_Con} (@code{s-wchcon.ads})
@@ -25348,7 +25609,7 @@ in ordinary strings. These definitions are used by
the package @code{System.Wch_Cnv}.
@node Interfacing to Other Languages,Specialized Needs Annexes,The GNAT Library,Top
-@anchor{gnat_rm/interfacing_to_other_languages doc}@anchor{40c}@anchor{gnat_rm/interfacing_to_other_languages id1}@anchor{40d}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-other-languages}@anchor{11}
+@anchor{gnat_rm/interfacing_to_other_languages doc}@anchor{40e}@anchor{gnat_rm/interfacing_to_other_languages id1}@anchor{40f}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-other-languages}@anchor{11}
@chapter Interfacing to Other Languages
@@ -25366,7 +25627,7 @@ provided.
@end menu
@node Interfacing to C,Interfacing to C++,,Interfacing to Other Languages
-@anchor{gnat_rm/interfacing_to_other_languages id2}@anchor{40e}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-c}@anchor{40f}
+@anchor{gnat_rm/interfacing_to_other_languages id2}@anchor{410}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-c}@anchor{411}
@section Interfacing to C
@@ -25506,7 +25767,7 @@ of the length corresponding to the @code{type'Size} value in Ada.
@end itemize
@node Interfacing to C++,Interfacing to COBOL,Interfacing to C,Interfacing to Other Languages
-@anchor{gnat_rm/interfacing_to_other_languages id3}@anchor{47}@anchor{gnat_rm/interfacing_to_other_languages id4}@anchor{410}
+@anchor{gnat_rm/interfacing_to_other_languages id3}@anchor{48}@anchor{gnat_rm/interfacing_to_other_languages id4}@anchor{412}
@section Interfacing to C++
@@ -25563,7 +25824,7 @@ The @code{External_Name} is the name of the C++ RTTI symbol. You can then
cover a specific C++ exception in an exception handler.
@node Interfacing to COBOL,Interfacing to Fortran,Interfacing to C++,Interfacing to Other Languages
-@anchor{gnat_rm/interfacing_to_other_languages id5}@anchor{411}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-cobol}@anchor{412}
+@anchor{gnat_rm/interfacing_to_other_languages id5}@anchor{413}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-cobol}@anchor{414}
@section Interfacing to COBOL
@@ -25571,7 +25832,7 @@ Interfacing to COBOL is achieved as described in section B.4 of
the Ada Reference Manual.
@node Interfacing to Fortran,Interfacing to non-GNAT Ada code,Interfacing to COBOL,Interfacing to Other Languages
-@anchor{gnat_rm/interfacing_to_other_languages id6}@anchor{413}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-fortran}@anchor{414}
+@anchor{gnat_rm/interfacing_to_other_languages id6}@anchor{415}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-fortran}@anchor{416}
@section Interfacing to Fortran
@@ -25581,7 +25842,7 @@ multi-dimensional array causes the array to be stored in column-major
order as required for convenient interface to Fortran.
@node Interfacing to non-GNAT Ada code,,Interfacing to Fortran,Interfacing to Other Languages
-@anchor{gnat_rm/interfacing_to_other_languages id7}@anchor{415}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-non-gnat-ada-code}@anchor{416}
+@anchor{gnat_rm/interfacing_to_other_languages id7}@anchor{417}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-non-gnat-ada-code}@anchor{418}
@section Interfacing to non-GNAT Ada code
@@ -25605,7 +25866,7 @@ values or simple record types without variants, or simple array
types with fixed bounds.
@node Specialized Needs Annexes,Implementation of Specific Ada Features,Interfacing to Other Languages,Top
-@anchor{gnat_rm/specialized_needs_annexes doc}@anchor{417}@anchor{gnat_rm/specialized_needs_annexes id1}@anchor{418}@anchor{gnat_rm/specialized_needs_annexes specialized-needs-annexes}@anchor{12}
+@anchor{gnat_rm/specialized_needs_annexes doc}@anchor{419}@anchor{gnat_rm/specialized_needs_annexes id1}@anchor{41a}@anchor{gnat_rm/specialized_needs_annexes specialized-needs-annexes}@anchor{12}
@chapter Specialized Needs Annexes
@@ -25646,7 +25907,7 @@ in Ada 2005) is fully implemented.
@end table
@node Implementation of Specific Ada Features,Implementation of Ada 2012 Features,Specialized Needs Annexes,Top
-@anchor{gnat_rm/implementation_of_specific_ada_features doc}@anchor{419}@anchor{gnat_rm/implementation_of_specific_ada_features id1}@anchor{41a}@anchor{gnat_rm/implementation_of_specific_ada_features implementation-of-specific-ada-features}@anchor{13}
+@anchor{gnat_rm/implementation_of_specific_ada_features doc}@anchor{41b}@anchor{gnat_rm/implementation_of_specific_ada_features id1}@anchor{41c}@anchor{gnat_rm/implementation_of_specific_ada_features implementation-of-specific-ada-features}@anchor{13}
@chapter Implementation of Specific Ada Features
@@ -25665,7 +25926,7 @@ facilities.
@end menu
@node Machine Code Insertions,GNAT Implementation of Tasking,,Implementation of Specific Ada Features
-@anchor{gnat_rm/implementation_of_specific_ada_features id2}@anchor{41b}@anchor{gnat_rm/implementation_of_specific_ada_features machine-code-insertions}@anchor{166}
+@anchor{gnat_rm/implementation_of_specific_ada_features id2}@anchor{41d}@anchor{gnat_rm/implementation_of_specific_ada_features machine-code-insertions}@anchor{167}
@section Machine Code Insertions
@@ -25833,7 +26094,7 @@ according to normal visibility rules. In particular if there is no
qualification is required.
@node GNAT Implementation of Tasking,GNAT Implementation of Shared Passive Packages,Machine Code Insertions,Implementation of Specific Ada Features
-@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-tasking}@anchor{41c}@anchor{gnat_rm/implementation_of_specific_ada_features id3}@anchor{41d}
+@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-tasking}@anchor{41e}@anchor{gnat_rm/implementation_of_specific_ada_features id3}@anchor{41f}
@section GNAT Implementation of Tasking
@@ -25849,7 +26110,7 @@ to compliance with the Real-Time Systems Annex.
@end menu
@node Mapping Ada Tasks onto the Underlying Kernel Threads,Ensuring Compliance with the Real-Time Annex,,GNAT Implementation of Tasking
-@anchor{gnat_rm/implementation_of_specific_ada_features id4}@anchor{41e}@anchor{gnat_rm/implementation_of_specific_ada_features mapping-ada-tasks-onto-the-underlying-kernel-threads}@anchor{41f}
+@anchor{gnat_rm/implementation_of_specific_ada_features id4}@anchor{420}@anchor{gnat_rm/implementation_of_specific_ada_features mapping-ada-tasks-onto-the-underlying-kernel-threads}@anchor{421}
@subsection Mapping Ada Tasks onto the Underlying Kernel Threads
@@ -25918,7 +26179,7 @@ support this functionality when the parent contains more than one task.
@geindex Forking a new process
@node Ensuring Compliance with the Real-Time Annex,Support for Locking Policies,Mapping Ada Tasks onto the Underlying Kernel Threads,GNAT Implementation of Tasking
-@anchor{gnat_rm/implementation_of_specific_ada_features ensuring-compliance-with-the-real-time-annex}@anchor{420}@anchor{gnat_rm/implementation_of_specific_ada_features id5}@anchor{421}
+@anchor{gnat_rm/implementation_of_specific_ada_features ensuring-compliance-with-the-real-time-annex}@anchor{422}@anchor{gnat_rm/implementation_of_specific_ada_features id5}@anchor{423}
@subsection Ensuring Compliance with the Real-Time Annex
@@ -25969,7 +26230,7 @@ placed at the end.
@c Support_for_Locking_Policies
@node Support for Locking Policies,,Ensuring Compliance with the Real-Time Annex,GNAT Implementation of Tasking
-@anchor{gnat_rm/implementation_of_specific_ada_features support-for-locking-policies}@anchor{422}
+@anchor{gnat_rm/implementation_of_specific_ada_features support-for-locking-policies}@anchor{424}
@subsection Support for Locking Policies
@@ -26003,7 +26264,7 @@ then ceiling locking is used.
Otherwise, the @code{Ceiling_Locking} policy is ignored.
@node GNAT Implementation of Shared Passive Packages,Code Generation for Array Aggregates,GNAT Implementation of Tasking,Implementation of Specific Ada Features
-@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-shared-passive-packages}@anchor{423}@anchor{gnat_rm/implementation_of_specific_ada_features id6}@anchor{424}
+@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-shared-passive-packages}@anchor{425}@anchor{gnat_rm/implementation_of_specific_ada_features id6}@anchor{426}
@section GNAT Implementation of Shared Passive Packages
@@ -26101,7 +26362,7 @@ This is used to provide the required locking
semantics for proper protected object synchronization.
@node Code Generation for Array Aggregates,The Size of Discriminated Records with Default Discriminants,GNAT Implementation of Shared Passive Packages,Implementation of Specific Ada Features
-@anchor{gnat_rm/implementation_of_specific_ada_features code-generation-for-array-aggregates}@anchor{425}@anchor{gnat_rm/implementation_of_specific_ada_features id7}@anchor{426}
+@anchor{gnat_rm/implementation_of_specific_ada_features code-generation-for-array-aggregates}@anchor{427}@anchor{gnat_rm/implementation_of_specific_ada_features id7}@anchor{428}
@section Code Generation for Array Aggregates
@@ -26132,7 +26393,7 @@ component values and static subtypes also lead to simpler code.
@end menu
@node Static constant aggregates with static bounds,Constant aggregates with unconstrained nominal types,,Code Generation for Array Aggregates
-@anchor{gnat_rm/implementation_of_specific_ada_features id8}@anchor{427}@anchor{gnat_rm/implementation_of_specific_ada_features static-constant-aggregates-with-static-bounds}@anchor{428}
+@anchor{gnat_rm/implementation_of_specific_ada_features id8}@anchor{429}@anchor{gnat_rm/implementation_of_specific_ada_features static-constant-aggregates-with-static-bounds}@anchor{42a}
@subsection Static constant aggregates with static bounds
@@ -26179,7 +26440,7 @@ Zero2: constant two_dim := (others => (others => 0));
@end example
@node Constant aggregates with unconstrained nominal types,Aggregates with static bounds,Static constant aggregates with static bounds,Code Generation for Array Aggregates
-@anchor{gnat_rm/implementation_of_specific_ada_features constant-aggregates-with-unconstrained-nominal-types}@anchor{429}@anchor{gnat_rm/implementation_of_specific_ada_features id9}@anchor{42a}
+@anchor{gnat_rm/implementation_of_specific_ada_features constant-aggregates-with-unconstrained-nominal-types}@anchor{42b}@anchor{gnat_rm/implementation_of_specific_ada_features id9}@anchor{42c}
@subsection Constant aggregates with unconstrained nominal types
@@ -26194,7 +26455,7 @@ Cr_Unc : constant One_Unc := (12,24,36);
@end example
@node Aggregates with static bounds,Aggregates with nonstatic bounds,Constant aggregates with unconstrained nominal types,Code Generation for Array Aggregates
-@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-static-bounds}@anchor{42b}@anchor{gnat_rm/implementation_of_specific_ada_features id10}@anchor{42c}
+@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-static-bounds}@anchor{42d}@anchor{gnat_rm/implementation_of_specific_ada_features id10}@anchor{42e}
@subsection Aggregates with static bounds
@@ -26222,7 +26483,7 @@ end loop;
@end example
@node Aggregates with nonstatic bounds,Aggregates in assignment statements,Aggregates with static bounds,Code Generation for Array Aggregates
-@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-nonstatic-bounds}@anchor{42d}@anchor{gnat_rm/implementation_of_specific_ada_features id11}@anchor{42e}
+@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-nonstatic-bounds}@anchor{42f}@anchor{gnat_rm/implementation_of_specific_ada_features id11}@anchor{430}
@subsection Aggregates with nonstatic bounds
@@ -26233,7 +26494,7 @@ have to be applied to sub-arrays individually, if they do not have statically
compatible subtypes.
@node Aggregates in assignment statements,,Aggregates with nonstatic bounds,Code Generation for Array Aggregates
-@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-in-assignment-statements}@anchor{42f}@anchor{gnat_rm/implementation_of_specific_ada_features id12}@anchor{430}
+@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-in-assignment-statements}@anchor{431}@anchor{gnat_rm/implementation_of_specific_ada_features id12}@anchor{432}
@subsection Aggregates in assignment statements
@@ -26275,7 +26536,7 @@ a temporary (created either by the front-end or the code generator) and then
that temporary will be copied onto the target.
@node The Size of Discriminated Records with Default Discriminants,Image Values For Nonscalar Types,Code Generation for Array Aggregates,Implementation of Specific Ada Features
-@anchor{gnat_rm/implementation_of_specific_ada_features id13}@anchor{431}@anchor{gnat_rm/implementation_of_specific_ada_features the-size-of-discriminated-records-with-default-discriminants}@anchor{432}
+@anchor{gnat_rm/implementation_of_specific_ada_features id13}@anchor{433}@anchor{gnat_rm/implementation_of_specific_ada_features the-size-of-discriminated-records-with-default-discriminants}@anchor{434}
@section The Size of Discriminated Records with Default Discriminants
@@ -26355,7 +26616,7 @@ say) must be consistent, so it is imperative that the object, once created,
remain invariant.
@node Image Values For Nonscalar Types,Strict Conformance to the Ada Reference Manual,The Size of Discriminated Records with Default Discriminants,Implementation of Specific Ada Features
-@anchor{gnat_rm/implementation_of_specific_ada_features id14}@anchor{433}@anchor{gnat_rm/implementation_of_specific_ada_features image-values-for-nonscalar-types}@anchor{434}
+@anchor{gnat_rm/implementation_of_specific_ada_features id14}@anchor{435}@anchor{gnat_rm/implementation_of_specific_ada_features image-values-for-nonscalar-types}@anchor{436}
@section Image Values For Nonscalar Types
@@ -26375,7 +26636,7 @@ control of image text is required for some type T, then T’Put_Image should be
explicitly specified.
@node Strict Conformance to the Ada Reference Manual,,Image Values For Nonscalar Types,Implementation of Specific Ada Features
-@anchor{gnat_rm/implementation_of_specific_ada_features id15}@anchor{435}@anchor{gnat_rm/implementation_of_specific_ada_features strict-conformance-to-the-ada-reference-manual}@anchor{436}
+@anchor{gnat_rm/implementation_of_specific_ada_features id15}@anchor{437}@anchor{gnat_rm/implementation_of_specific_ada_features strict-conformance-to-the-ada-reference-manual}@anchor{438}
@section Strict Conformance to the Ada Reference Manual
@@ -26401,8 +26662,8 @@ machines that are not fully compliant with this standard, such as Alpha, the
behavior (although at the cost of a significant performance penalty), so
infinite and NaN values are properly generated.
-@node Implementation of Ada 2012 Features,Obsolescent Features,Implementation of Specific Ada Features,Top
-@anchor{gnat_rm/implementation_of_ada_2012_features doc}@anchor{437}@anchor{gnat_rm/implementation_of_ada_2012_features id1}@anchor{438}@anchor{gnat_rm/implementation_of_ada_2012_features implementation-of-ada-2012-features}@anchor{14}
+@node Implementation of Ada 2012 Features,Security Hardening Features,Implementation of Specific Ada Features,Top
+@anchor{gnat_rm/implementation_of_ada_2012_features doc}@anchor{439}@anchor{gnat_rm/implementation_of_ada_2012_features id1}@anchor{43a}@anchor{gnat_rm/implementation_of_ada_2012_features implementation-of-ada-2012-features}@anchor{14}
@chapter Implementation of Ada 2012 Features
@@ -28567,8 +28828,102 @@ where the type of the returned value is an anonymous access type.
RM References: H.04 (8/1)
@end itemize
-@node Obsolescent Features,Compatibility and Porting Guide,Implementation of Ada 2012 Features,Top
-@anchor{gnat_rm/obsolescent_features doc}@anchor{439}@anchor{gnat_rm/obsolescent_features id1}@anchor{43a}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{15}
+@node Security Hardening Features,Obsolescent Features,Implementation of Ada 2012 Features,Top
+@anchor{gnat_rm/security_hardening_features doc}@anchor{43b}@anchor{gnat_rm/security_hardening_features id1}@anchor{43c}@anchor{gnat_rm/security_hardening_features security-hardening-features}@anchor{15}
+@chapter Security Hardening Features
+
+
+This chapter describes Ada extensions aimed at security hardening that
+are provided by GNAT.
+
+@c Register Scrubbing:
+
+@menu
+* Register Scrubbing::
+* Stack Scrubbing::
+
+@end menu
+
+@node Register Scrubbing,Stack Scrubbing,,Security Hardening Features
+@anchor{gnat_rm/security_hardening_features register-scrubbing}@anchor{43d}
+@section Register Scrubbing
+
+
+GNAT can generate code to zero-out hardware registers before returning
+from a subprogram.
+
+It can be enabled with the @emph{-fzero-call-used-regs} command line
+option, to affect all subprograms in a compilation, and with a
+@code{Machine_Attribute} pragma, to affect only specific subprograms.
+
+@example
+procedure Foo;
+pragma Machine_Attribute (Foo, "zero_call_used_regs", "used");
+-- Before returning, Foo scrubs only call-clobbered registers
+-- that it uses itself.
+
+function Bar return Integer;
+pragma Machine_Attribute (Bar, "zero_call_used_regs", "all");
+-- Before returning, Bar scrubs all call-clobbered registers.
+@end example
+
+For usage and more details on the command line option, and on the
+@code{zero_call_used_regs} attribute, see @cite{Using the GNU Compiler Collection (GCC)}.
+
+@c Stack Scrubbing:
+
+@node Stack Scrubbing,,Register Scrubbing,Security Hardening Features
+@anchor{gnat_rm/security_hardening_features stack-scrubbing}@anchor{43e}
+@section Stack Scrubbing
+
+
+GNAT can generate code to zero-out stack frames used by subprograms.
+
+It can be activated with the @code{Machine_Attribute} pragma, on
+specific subprograms and variables.
+
+@example
+function Foo returns Integer;
+pragma Machine_Attribute (Foo, "strub");
+-- Foo and its callers are modified so as to scrub the stack
+-- space used by Foo after it returns.
+
+procedure Bar;
+pragma Machine_Attribute (Bar, "strub", "internal");
+-- Bar is turned into a wrapper for its original body,
+-- and they scrub the stack used by the original body.
+
+Var : Integer;
+pragma Machine_Attribute (Var, "strub");
+-- Reading from Var in a subprogram enables stack scrubbing
+-- of the stack space used by the subprogram.
+@end example
+
+There are also @emph{-fstrub} command line options to control default
+settings. For usage and more details on the command line option, and
+on the @code{strub} attribute, see @cite{Using the GNU Compiler Collection (GCC)}.
+
+Note that Ada secondary stacks are not scrubbed. The restriction
+@code{No_Secondary_Stack} avoids their use, and thus their accidental
+preservation of data that should be scrubbed.
+
+Also note that the machine attribute is not integrated in the Ada type
+system. Though it may modify subprogram and variable interfaces, it
+is not fully reflected in Ada types, @code{Access} attributes, renaming
+and overriding. Every access type, renaming, and overriding and
+overridden dispatching operations that may refer to an entity with an
+attribute-modified interface must be annotated with the same
+interface-modifying attribute, or with an interface-compatible one.
+
+Even then, the pragma is currently only functional when applied to
+subprograms and scalar variables; other uses, such as directly on
+types and subtypes, may be silently ignored. Specifically, it is not
+currently recommended to rely on any effects this pragma might be
+expected to have when calling subprograms through access-to-subprogram
+variables.
+
+@node Obsolescent Features,Compatibility and Porting Guide,Security Hardening Features,Top
+@anchor{gnat_rm/obsolescent_features doc}@anchor{43f}@anchor{gnat_rm/obsolescent_features id1}@anchor{440}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{16}
@chapter Obsolescent Features
@@ -28587,7 +28942,7 @@ compatibility purposes.
@end menu
@node pragma No_Run_Time,pragma Ravenscar,,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features id2}@anchor{43b}@anchor{gnat_rm/obsolescent_features pragma-no-run-time}@anchor{43c}
+@anchor{gnat_rm/obsolescent_features id2}@anchor{441}@anchor{gnat_rm/obsolescent_features pragma-no-run-time}@anchor{442}
@section pragma No_Run_Time
@@ -28600,7 +28955,7 @@ preferred usage is to use an appropriately configured run-time that
includes just those features that are to be made accessible.
@node pragma Ravenscar,pragma Restricted_Run_Time,pragma No_Run_Time,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features id3}@anchor{43d}@anchor{gnat_rm/obsolescent_features pragma-ravenscar}@anchor{43e}
+@anchor{gnat_rm/obsolescent_features id3}@anchor{443}@anchor{gnat_rm/obsolescent_features pragma-ravenscar}@anchor{444}
@section pragma Ravenscar
@@ -28609,7 +28964,7 @@ The pragma @code{Ravenscar} has exactly the same effect as pragma
is part of the new Ada 2005 standard.
@node pragma Restricted_Run_Time,pragma Task_Info,pragma Ravenscar,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features id4}@anchor{43f}@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{440}
+@anchor{gnat_rm/obsolescent_features id4}@anchor{445}@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{446}
@section pragma Restricted_Run_Time
@@ -28619,7 +28974,7 @@ preferred since the Ada 2005 pragma @code{Profile} is intended for
this kind of implementation dependent addition.
@node pragma Task_Info,package System Task_Info s-tasinf ads,pragma Restricted_Run_Time,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features id5}@anchor{441}@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{442}
+@anchor{gnat_rm/obsolescent_features id5}@anchor{447}@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{448}
@section pragma Task_Info
@@ -28645,7 +29000,7 @@ in the spec of package System.Task_Info in the runtime
library.
@node package System Task_Info s-tasinf ads,,pragma Task_Info,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features package-system-task-info}@anchor{443}@anchor{gnat_rm/obsolescent_features package-system-task-info-s-tasinf-ads}@anchor{444}
+@anchor{gnat_rm/obsolescent_features package-system-task-info}@anchor{449}@anchor{gnat_rm/obsolescent_features package-system-task-info-s-tasinf-ads}@anchor{44a}
@section package System.Task_Info (@code{s-tasinf.ads})
@@ -28655,7 +29010,7 @@ to support the @code{Task_Info} pragma. The predefined Ada package
standard replacement for GNAT’s @code{Task_Info} functionality.
@node Compatibility and Porting Guide,GNU Free Documentation License,Obsolescent Features,Top
-@anchor{gnat_rm/compatibility_and_porting_guide doc}@anchor{445}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{16}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{446}
+@anchor{gnat_rm/compatibility_and_porting_guide doc}@anchor{44b}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{17}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{44c}
@chapter Compatibility and Porting Guide
@@ -28677,7 +29032,7 @@ applications developed in other Ada environments.
@end menu
@node Writing Portable Fixed-Point Declarations,Compatibility with Ada 83,,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide id2}@anchor{447}@anchor{gnat_rm/compatibility_and_porting_guide writing-portable-fixed-point-declarations}@anchor{448}
+@anchor{gnat_rm/compatibility_and_porting_guide id2}@anchor{44d}@anchor{gnat_rm/compatibility_and_porting_guide writing-portable-fixed-point-declarations}@anchor{44e}
@section Writing Portable Fixed-Point Declarations
@@ -28799,7 +29154,7 @@ If you follow this scheme you will be guaranteed that your fixed-point
types will be portable.
@node Compatibility with Ada 83,Compatibility between Ada 95 and Ada 2005,Writing Portable Fixed-Point Declarations,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-ada-83}@anchor{449}@anchor{gnat_rm/compatibility_and_porting_guide id3}@anchor{44a}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-ada-83}@anchor{44f}@anchor{gnat_rm/compatibility_and_porting_guide id3}@anchor{450}
@section Compatibility with Ada 83
@@ -28827,7 +29182,7 @@ following subsections treat the most likely issues to be encountered.
@end menu
@node Legal Ada 83 programs that are illegal in Ada 95,More deterministic semantics,,Compatibility with Ada 83
-@anchor{gnat_rm/compatibility_and_porting_guide id4}@anchor{44b}@anchor{gnat_rm/compatibility_and_porting_guide legal-ada-83-programs-that-are-illegal-in-ada-95}@anchor{44c}
+@anchor{gnat_rm/compatibility_and_porting_guide id4}@anchor{451}@anchor{gnat_rm/compatibility_and_porting_guide legal-ada-83-programs-that-are-illegal-in-ada-95}@anchor{452}
@subsection Legal Ada 83 programs that are illegal in Ada 95
@@ -28927,7 +29282,7 @@ the fix is usually simply to add the @code{(<>)} to the generic declaration.
@end itemize
@node More deterministic semantics,Changed semantics,Legal Ada 83 programs that are illegal in Ada 95,Compatibility with Ada 83
-@anchor{gnat_rm/compatibility_and_porting_guide id5}@anchor{44d}@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{44e}
+@anchor{gnat_rm/compatibility_and_porting_guide id5}@anchor{453}@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{454}
@subsection More deterministic semantics
@@ -28955,7 +29310,7 @@ which open select branches are executed.
@end itemize
@node Changed semantics,Other language compatibility issues,More deterministic semantics,Compatibility with Ada 83
-@anchor{gnat_rm/compatibility_and_porting_guide changed-semantics}@anchor{44f}@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{450}
+@anchor{gnat_rm/compatibility_and_porting_guide changed-semantics}@anchor{455}@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{456}
@subsection Changed semantics
@@ -28997,7 +29352,7 @@ covers only the restricted range.
@end itemize
@node Other language compatibility issues,,Changed semantics,Compatibility with Ada 83
-@anchor{gnat_rm/compatibility_and_porting_guide id7}@anchor{451}@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{452}
+@anchor{gnat_rm/compatibility_and_porting_guide id7}@anchor{457}@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{458}
@subsection Other language compatibility issues
@@ -29030,7 +29385,7 @@ include @code{pragma Interface} and the floating point type attributes
@end itemize
@node Compatibility between Ada 95 and Ada 2005,Implementation-dependent characteristics,Compatibility with Ada 83,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide compatibility-between-ada-95-and-ada-2005}@anchor{453}@anchor{gnat_rm/compatibility_and_porting_guide id8}@anchor{454}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-between-ada-95-and-ada-2005}@anchor{459}@anchor{gnat_rm/compatibility_and_porting_guide id8}@anchor{45a}
@section Compatibility between Ada 95 and Ada 2005
@@ -29102,7 +29457,7 @@ can declare a function returning a value from an anonymous access type.
@end itemize
@node Implementation-dependent characteristics,Compatibility with Other Ada Systems,Compatibility between Ada 95 and Ada 2005,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide id9}@anchor{455}@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{456}
+@anchor{gnat_rm/compatibility_and_porting_guide id9}@anchor{45b}@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{45c}
@section Implementation-dependent characteristics
@@ -29125,7 +29480,7 @@ transition from certain Ada 83 compilers.
@end menu
@node Implementation-defined pragmas,Implementation-defined attributes,,Implementation-dependent characteristics
-@anchor{gnat_rm/compatibility_and_porting_guide id10}@anchor{457}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{458}
+@anchor{gnat_rm/compatibility_and_porting_guide id10}@anchor{45d}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{45e}
@subsection Implementation-defined pragmas
@@ -29147,7 +29502,7 @@ avoiding compiler rejection of units that contain such pragmas; they are not
relevant in a GNAT context and hence are not otherwise implemented.
@node Implementation-defined attributes,Libraries,Implementation-defined pragmas,Implementation-dependent characteristics
-@anchor{gnat_rm/compatibility_and_porting_guide id11}@anchor{459}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-attributes}@anchor{45a}
+@anchor{gnat_rm/compatibility_and_porting_guide id11}@anchor{45f}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-attributes}@anchor{460}
@subsection Implementation-defined attributes
@@ -29161,7 +29516,7 @@ Ada 83, GNAT supplies the attributes @code{Bit}, @code{Machine_Size} and
@code{Type_Class}.
@node Libraries,Elaboration order,Implementation-defined attributes,Implementation-dependent characteristics
-@anchor{gnat_rm/compatibility_and_porting_guide id12}@anchor{45b}@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{45c}
+@anchor{gnat_rm/compatibility_and_porting_guide id12}@anchor{461}@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{462}
@subsection Libraries
@@ -29190,7 +29545,7 @@ be preferable to retrofit the application using modular types.
@end itemize
@node Elaboration order,Target-specific aspects,Libraries,Implementation-dependent characteristics
-@anchor{gnat_rm/compatibility_and_porting_guide elaboration-order}@anchor{45d}@anchor{gnat_rm/compatibility_and_porting_guide id13}@anchor{45e}
+@anchor{gnat_rm/compatibility_and_porting_guide elaboration-order}@anchor{463}@anchor{gnat_rm/compatibility_and_porting_guide id13}@anchor{464}
@subsection Elaboration order
@@ -29226,7 +29581,7 @@ pragmas either globally (as an effect of the @emph{-gnatE} switch) or locally
@end itemize
@node Target-specific aspects,,Elaboration order,Implementation-dependent characteristics
-@anchor{gnat_rm/compatibility_and_porting_guide id14}@anchor{45f}@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{460}
+@anchor{gnat_rm/compatibility_and_porting_guide id14}@anchor{465}@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{466}
@subsection Target-specific aspects
@@ -29239,10 +29594,10 @@ on the robustness of the original design. Moreover, Ada 95 (and thus
Ada 2005 and Ada 2012) are sometimes
incompatible with typical Ada 83 compiler practices regarding implicit
packing, the meaning of the Size attribute, and the size of access values.
-GNAT’s approach to these issues is described in @ref{461,,Representation Clauses}.
+GNAT’s approach to these issues is described in @ref{467,,Representation Clauses}.
@node Compatibility with Other Ada Systems,Representation Clauses,Implementation-dependent characteristics,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{462}@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{463}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{468}@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{469}
@section Compatibility with Other Ada Systems
@@ -29285,7 +29640,7 @@ far beyond this minimal set, as described in the next section.
@end itemize
@node Representation Clauses,Compatibility with HP Ada 83,Compatibility with Other Ada Systems,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide id16}@anchor{464}@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{461}
+@anchor{gnat_rm/compatibility_and_porting_guide id16}@anchor{46a}@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{467}
@section Representation Clauses
@@ -29378,7 +29733,7 @@ with thin pointers.
@end itemize
@node Compatibility with HP Ada 83,,Representation Clauses,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-hp-ada-83}@anchor{465}@anchor{gnat_rm/compatibility_and_porting_guide id17}@anchor{466}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-hp-ada-83}@anchor{46b}@anchor{gnat_rm/compatibility_and_porting_guide id17}@anchor{46c}
@section Compatibility with HP Ada 83
@@ -29408,7 +29763,7 @@ extension of package System.
@end itemize
@node GNU Free Documentation License,Index,Compatibility and Porting Guide,Top
-@anchor{share/gnu_free_documentation_license doc}@anchor{467}@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{468}
+@anchor{share/gnu_free_documentation_license doc}@anchor{46d}@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{46e}
@chapter GNU Free Documentation License
diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi
index 9919cad..28f2f19 100644
--- a/gcc/ada/gnat_ugn.texi
+++ b/gcc/ada/gnat_ugn.texi
@@ -21,7 +21,7 @@
@copying
@quotation
-GNAT User's Guide for Native Platforms , Aug 03, 2021
+GNAT User's Guide for Native Platforms , Sep 28, 2021
AdaCore
@@ -2814,16 +2814,12 @@ C_Pass_By_Copy
Check_Float_Overflow
Check_Name
Check_Policy
-Compile_Time_Error
-Compile_Time_Warning
-Compiler_Unit
-Compiler_Unit_Warning
Component_Alignment
Convention_Identifier
Debug_Policy
-Detect_Blocking
Default_Scalar_Storage_Order
Default_Storage_Pool
+Detect_Blocking
Disable_Atomic_Synchronization
Discard_Names
Elaboration_Checks
@@ -2842,7 +2838,6 @@ License
Locking_Policy
No_Component_Reordering
No_Heap_Finalization
-No_Run_Time
No_Strict_Aliasing
Normalize_Scalars
Optimize_Alignment
@@ -2854,17 +2849,12 @@ Prefix_Exception_Messages
Priority_Specific_Dispatching
Profile
Profile_Warnings
-Propagate_Exceptions
Queuing_Policy
-Rational
-Ravenscar
Rename_Pragma
-Restricted_Run_Time
Restrictions
-Restrictions_Warnings
+Restriction_Warnings
Reviewable
Short_Circuit_And_Or
-Short_Descriptors
Source_File_Name
Source_File_Name_Project
SPARK_Mode
@@ -2873,7 +2863,6 @@ Suppress
Suppress_Exception_Locations
Task_Dispatching_Policy
Unevaluated_Use_Of_Old
-Universal_Data
Unsuppress
Use_VADS_Size
Validity_Checks
@@ -2925,7 +2914,7 @@ only to the unit in which the pragma appears, and not to any other units.
The exception is No_Elaboration_Code which always applies to the entire
object file from a compilation, i.e. to the body, spec, and all subunits.
This restriction can be specified in a configuration pragma file, or it
-can be on the body and/or the spec (in eithe case it applies to all the
+can be on the body and/or the spec (in either case it applies to all the
relevant units). It can appear on a subunit only if it has previously
appeared in the body of spec.
@@ -6421,10 +6410,10 @@ as comments, to be completed manually if needed.
some extensions (e.g. vector types) are not supported
@item
-pointers to pointers or complex structures are mapped to System.Address
+pointers to pointers are mapped to System.Address
@item
-identifiers with identical name (except casing) will generate compilation
+identifiers with identical name (except casing) may generate compilation
errors (e.g. @code{shm_get} vs @code{SHM_GET}).
@end itemize
@@ -6450,15 +6439,18 @@ spec files for the header files specified on the command line, and all
header files needed by these files transitively. For example:
@example
-$ g++ -c -fdump-ada-spec -C /usr/include/time.h
+$ gcc -c -fdump-ada-spec -C /usr/include/time.h
$ gcc -c *.ads
@end example
will generate, under GNU/Linux, the following files: @code{time_h.ads},
@code{bits_time_h.ads}, @code{stddef_h.ads}, @code{bits_types_h.ads} which
correspond to the files @code{/usr/include/time.h},
-@code{/usr/include/bits/time.h}, etc…, and will then compile these Ada specs
-in Ada 2005 mode.
+@code{/usr/include/bits/time.h}, etc…, and then compile these Ada specs.
+That is to say, the name of the Ada specs is in keeping with the relative path
+under @code{/usr/include/} of the header files. This behavior is specific to
+paths ending with @code{/include/}; in all the other cases, the name of the
+Ada specs is derived from the simple name of the header files instead.
The @code{-C} switch tells @code{gcc} to extract comments from headers,
and will attempt to generate corresponding Ada comments.
@@ -6469,46 +6461,15 @@ can use instead the @code{-fdump-ada-spec-slim} switch.
You can optionally specify a parent unit, of which all generated units will
be children, using @code{-fada-spec-parent=@emph{unit}}.
-Note that we recommend when possible to use the @emph{g++} driver to
-generate bindings, even for most C headers, since this will in general
-generate better Ada specs. For generating bindings for C++ headers, it is
-mandatory to use the @emph{g++} command, or @emph{gcc -x c++} which
-is equivalent in this case. If @emph{g++} cannot work on your C headers
-because of incompatibilities between C and C++, then you can fallback to
-@code{gcc} instead.
-
-For an example of better bindings generated from the C++ front-end,
-the name of the parameters (when available) are actually ignored by the C
-front-end. Consider the following C header:
-
-@example
-extern void foo (int variable);
-@end example
-
-with the C front-end, @code{variable} is ignored, and the above is handled as:
-
-@example
-extern void foo (int);
-@end example
-
-generating a generic:
-
-@example
-procedure foo (param1 : int);
-@end example
-
-with the C++ front-end, the name is available, and we generate:
-
-@example
-procedure foo (variable : int);
-@end example
+The simple @code{gcc`}-based command works only for C headers. For C++ headers
+you need to use either the @code{g++} command or the combination @code{gcc -x c++`}.
In some cases, the generated bindings will be more complete or more meaningful
when defining some macros, which you can do via the @code{-D} switch. This
is for example the case with @code{Xlib.h} under GNU/Linux:
@example
-$ g++ -c -fdump-ada-spec -DXLIB_ILLEGAL_ACCESS -C /usr/include/X11/Xlib.h
+$ gcc -c -fdump-ada-spec -DXLIB_ILLEGAL_ACCESS -C /usr/include/X11/Xlib.h
@end example
The above will generate more complete bindings than a straight call without
@@ -6530,7 +6491,7 @@ lines in e.g. @code{readline1.h}:
and then generate Ada bindings from this file:
@example
-$ g++ -c -fdump-ada-spec readline1.h
+$ gcc -c -fdump-ada-spec readline1.h
@end example
@node Generating Bindings for C++ Headers,Switches,Running the Binding Generator,Generating Ada Bindings for C and C++ headers
@@ -6799,7 +6760,7 @@ call subprograms, reference objects, and constants.
This section compares the GNAT model with the approaches taken in
-other environents, first the C/C++ model and then the mechanism that
+other environments, first the C/C++ model and then the mechanism that
has been used in other Ada systems, in particular those traditionally
used for Ada 83.
@@ -8961,9 +8922,10 @@ also suppresses generation of cross-reference information
@item @code{-gnateA}
Check that the actual parameters of a subprogram call are not aliases of one
-another. To qualify as aliasing, the actuals must denote objects of a composite
-type, their memory locations must be identical or overlapping, and at least one
-of the corresponding formal parameters must be of mode OUT or IN OUT.
+another. To qualify as aliasing, their memory locations must be identical or
+overlapping, at least one of the corresponding formal parameters must be of
+mode OUT or IN OUT, and at least one of the corresponding formal parameters
+must have its parameter passing mechanism not specified.
@example
type Rec_Typ is record
@@ -22645,7 +22607,10 @@ Ignore : constant Boolean :=
@end quotation
It gets the effective user id, and if it’s not 0 (i.e. root), it raises
-Program_Error.
+Program_Error. Note that if you re running the code in a container, this may
+not be sufficient, as you may have sufficient priviledge on the container,
+but not on the host machine running the container, so check that you also
+have sufficient priviledge for running the container image.
@geindex Linux
diff --git a/gcc/ada/gnatbind.adb b/gcc/ada/gnatbind.adb
index 5cb2df0..90d8af4 100644
--- a/gcc/ada/gnatbind.adb
+++ b/gcc/ada/gnatbind.adb
@@ -125,7 +125,6 @@ procedure Gnatbind is
Scan_ALI
(F => Std_Lib_File,
T => Text,
- Ignore_ED => False,
Err => False,
Ignore_Errors => Debug_Flag_I);
@@ -770,7 +769,6 @@ begin
Id := Scan_ALI
(F => Main_Lib_File,
T => Text,
- Ignore_ED => False,
Err => False,
Ignore_Errors => Debug_Flag_I,
Directly_Scanned => True);
diff --git a/gcc/ada/gnatfind.adb b/gcc/ada/gnatfind.adb
index c3fc25e..83bafff 100644
--- a/gcc/ada/gnatfind.adb
+++ b/gcc/ada/gnatfind.adb
@@ -347,6 +347,11 @@ procedure Gnatfind is
-- Start of processing for Gnatfind
begin
+ Put_Line
+ ("WARNING: gnatfind is obsolete and will be removed in the next release");
+ Put_Line
+ ("Consider using Libadalang or GNAT Studio python scripting instead");
+
Parse_Cmd_Line;
if not Have_Entity then
diff --git a/gcc/ada/gnatlink.adb b/gcc/ada/gnatlink.adb
index 52e714a..a321bf3 100644
--- a/gcc/ada/gnatlink.adb
+++ b/gcc/ada/gnatlink.adb
@@ -1531,7 +1531,6 @@ begin
A := Scan_ALI
(F,
T,
- Ignore_ED => False,
Err => False,
Ignore_Errors => True);
diff --git a/gcc/ada/gnatls.adb b/gcc/ada/gnatls.adb
index 353e36d..c676996 100644
--- a/gcc/ada/gnatls.adb
+++ b/gcc/ada/gnatls.adb
@@ -2278,7 +2278,6 @@ begin
Scan_ALI
(Ali_File,
Text,
- Ignore_ED => False,
Err => False,
Ignore_Errors => True);
end;
diff --git a/gcc/ada/gnatxref.adb b/gcc/ada/gnatxref.adb
index 9a3935c..3737f66 100644
--- a/gcc/ada/gnatxref.adb
+++ b/gcc/ada/gnatxref.adb
@@ -299,6 +299,11 @@ procedure Gnatxref is
end Write_Usage;
begin
+ Put_Line
+ ("WARNING: gnatxref is obsolete and will be removed in the next release");
+ Put_Line
+ ("Consider using Libadalang or GNAT Studio python scripting instead");
+
Parse_Cmd_Line;
if not Have_File then
diff --git a/gcc/ada/impunit.adb b/gcc/ada/impunit.adb
index b99f3fd..5fe1353 100644
--- a/gcc/ada/impunit.adb
+++ b/gcc/ada/impunit.adb
@@ -23,14 +23,14 @@
-- --
------------------------------------------------------------------------------
-with Errout; use Errout;
-with Sinfo; use Sinfo;
-with Sinfo.Nodes; use Sinfo.Nodes;
-with Fname.UF; use Fname.UF;
-with Lib; use Lib;
-with Namet; use Namet;
-with Opt; use Opt;
-with Uname; use Uname;
+with Errout; use Errout;
+with Sinfo; use Sinfo;
+with Sinfo.Nodes; use Sinfo.Nodes;
+with Fname.UF; use Fname.UF;
+with Lib; use Lib;
+with Namet; use Namet;
+with Opt; use Opt;
+with Uname; use Uname;
-- Note: this package body is used by GNAT Studio and GNATBench to supply a
-- list of entries for help on available library routines.
diff --git a/gcc/ada/init.c b/gcc/ada/init.c
index 2bbb601..dbd8516 100644
--- a/gcc/ada/init.c
+++ b/gcc/ada/init.c
@@ -2551,6 +2551,7 @@ __gnat_install_handler (void)
#include <signal.h>
#include <unistd.h>
#include <string.h>
+#include <errno.h>
#include "sigtramp.h"
void
diff --git a/gcc/ada/libgnarl/a-tasini.adb b/gcc/ada/libgnarl/a-tasini.adb
index c0dfe70..a8981d6 100644
--- a/gcc/ada/libgnarl/a-tasini.adb
+++ b/gcc/ada/libgnarl/a-tasini.adb
@@ -26,13 +26,13 @@
-- --
------------------------------------------------------------------------------
-with Ada.Unchecked_Conversion;
-with System.Tasking;
-
package body Ada.Task_Initialization is
- function To_STIH is new Ada.Unchecked_Conversion
- (Initialization_Handler, System.Tasking.Initialization_Handler);
+ Global_Initialization_Handler : Initialization_Handler := null;
+ pragma Atomic (Global_Initialization_Handler);
+ pragma Export (Ada, Global_Initialization_Handler,
+ "__gnat_global_initialization_handler");
+ -- Global handler called when each task initializes.
--------------------------------
-- Set_Initialization_Handler --
@@ -40,7 +40,7 @@ package body Ada.Task_Initialization is
procedure Set_Initialization_Handler (Handler : Initialization_Handler) is
begin
- System.Tasking.Global_Initialization_Handler := To_STIH (Handler);
+ Global_Initialization_Handler := Handler;
end Set_Initialization_Handler;
end Ada.Task_Initialization;
diff --git a/gcc/ada/libgnarl/a-tasini.ads b/gcc/ada/libgnarl/a-tasini.ads
index dd2a17c..a754c06 100644
--- a/gcc/ada/libgnarl/a-tasini.ads
+++ b/gcc/ada/libgnarl/a-tasini.ads
@@ -30,12 +30,17 @@
-- when tasks start.
package Ada.Task_Initialization is
- pragma Preelaborate (Task_Initialization);
+ pragma Preelaborate;
+ pragma No_Elaboration_Code_All;
type Initialization_Handler is access procedure;
procedure Set_Initialization_Handler (Handler : Initialization_Handler);
- -- Set the global task initialization handler to Handler
+ -- Set the global task initialization handler to Handler.
+ -- Note that only tasks created after this procedure is called will trigger
+ -- a call to Handler. You can use Ada's elaboration rules and pragma
+ -- Elaborate_All, or the pragma Linker_Constructor to ensure this
+ -- procedure is called early.
private
pragma Favor_Top_Level (Initialization_Handler);
diff --git a/gcc/ada/libgnarl/s-interr__vxworks.adb b/gcc/ada/libgnarl/s-interr__vxworks.adb
index d496b74..db2ca95 100644
--- a/gcc/ada/libgnarl/s-interr__vxworks.adb
+++ b/gcc/ada/libgnarl/s-interr__vxworks.adb
@@ -66,7 +66,6 @@
with Ada.Unchecked_Conversion;
with Ada.Task_Identification;
-with Interfaces.C; use Interfaces.C;
with System.OS_Interface; use System.OS_Interface;
with System.Interrupt_Management;
with System.Task_Primitives.Operations;
@@ -76,12 +75,18 @@ with System.Tasking.Utilities;
with System.Tasking.Rendezvous;
pragma Elaborate_All (System.Tasking.Rendezvous);
+with System.VxWorks.Ext;
+
package body System.Interrupts is
use Tasking;
package POP renames System.Task_Primitives.Operations;
+ use type System.VxWorks.Ext.STATUS;
+ subtype STATUS is System.VxWorks.Ext.STATUS;
+ OK : constant STATUS := System.VxWorks.Ext.OK;
+
function To_Ada is new Ada.Unchecked_Conversion
(System.Tasking.Task_Id, Ada.Task_Identification.Task_Id);
@@ -199,7 +204,7 @@ package body System.Interrupts is
type Interrupt_Connector is access function
(Vector : Interrupt_Vector;
Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int;
+ Parameter : System.Address := System.Null_Address) return STATUS;
-- Profile must match VxWorks intConnect()
Interrupt_Connect : Interrupt_Connector :=
@@ -515,7 +520,7 @@ package body System.Interrupts is
Vec : constant Interrupt_Vector :=
Interrupt_Number_To_Vector (int (Interrupt));
- Status : int;
+ Result : STATUS;
begin
-- Only install umbrella handler when no Ada handler has already been
@@ -525,9 +530,9 @@ package body System.Interrupts is
-- number.
if not Handler_Installed (Interrupt) then
- Status :=
+ Result :=
Interrupt_Connect.all (Vec, Handler, System.Address (Interrupt));
- pragma Assert (Status = 0);
+ pragma Assert (Result = OK);
Handler_Installed (Interrupt) := True;
end if;
@@ -646,11 +651,11 @@ package body System.Interrupts is
procedure Notify_Interrupt (Param : System.Address) is
Interrupt : constant Interrupt_ID := Interrupt_ID (Param);
Id : constant Binary_Semaphore_Id := Semaphore_ID_Map (Interrupt);
- Status : int;
+ Result : STATUS;
begin
if Id /= 0 then
- Status := Binary_Semaphore_Release (Id);
- pragma Assert (Status = 0);
+ Result := Binary_Semaphore_Release (Id);
+ pragma Assert (Result = OK);
end if;
end Notify_Interrupt;
@@ -787,13 +792,13 @@ package body System.Interrupts is
--------------------
procedure Unbind_Handler (Interrupt : Interrupt_ID) is
- Status : int;
+ Result : STATUS;
begin
-- Flush server task off semaphore, allowing it to terminate
- Status := Binary_Semaphore_Flush (Semaphore_ID_Map (Interrupt));
- pragma Assert (Status = 0);
+ Result := Binary_Semaphore_Flush (Semaphore_ID_Map (Interrupt));
+ pragma Assert (Result = OK);
end Unbind_Handler;
--------------------------------
@@ -1067,7 +1072,7 @@ package body System.Interrupts is
Tmp_Handler : Parameterless_Handler;
Tmp_ID : Task_Id;
Tmp_Entry_Index : Task_Entry_Index;
- Status : int;
+ Result : STATUS;
begin
Semaphore_ID_Map (Interrupt) := Int_Sema;
@@ -1076,8 +1081,8 @@ package body System.Interrupts is
-- Pend on semaphore that will be triggered by the umbrella handler
-- when the associated interrupt comes in.
- Status := Binary_Semaphore_Obtain (Int_Sema);
- pragma Assert (Status = 0);
+ Result := Binary_Semaphore_Obtain (Int_Sema);
+ pragma Assert (Result = OK);
if User_Handler (Interrupt).H /= null then
@@ -1109,9 +1114,9 @@ package body System.Interrupts is
-- Delete the associated semaphore
- Status := Binary_Semaphore_Delete (Int_Sema);
+ Result := Binary_Semaphore_Delete (Int_Sema);
- pragma Assert (Status = 0);
+ pragma Assert (Result = OK);
-- Set status for the Interrupt_Manager
diff --git a/gcc/ada/libgnarl/s-osinte__vxworks.adb b/gcc/ada/libgnarl/s-osinte__vxworks.adb
index cf3ece3..fbc8367 100644
--- a/gcc/ada/libgnarl/s-osinte__vxworks.adb
+++ b/gcc/ada/libgnarl/s-osinte__vxworks.adb
@@ -100,10 +100,11 @@ package body System.OS_Interface is
Ticks : Long_Long_Integer;
Rate_Duration : Duration;
Ticks_Duration : Duration;
+ IERR : constant int := -1;
begin
if D < 0.0 then
- return ERROR;
+ return IERR;
end if;
-- Ensure that the duration can be converted to ticks
@@ -142,7 +143,8 @@ package body System.OS_Interface is
-- Binary_Semaphore_Delete --
-----------------------------
- function Binary_Semaphore_Delete (ID : Binary_Semaphore_Id) return int is
+ function Binary_Semaphore_Delete (ID : Binary_Semaphore_Id)
+ return STATUS is
begin
return semDelete (SEM_ID (ID));
end Binary_Semaphore_Delete;
@@ -151,7 +153,8 @@ package body System.OS_Interface is
-- Binary_Semaphore_Obtain --
-----------------------------
- function Binary_Semaphore_Obtain (ID : Binary_Semaphore_Id) return int is
+ function Binary_Semaphore_Obtain (ID : Binary_Semaphore_Id)
+ return STATUS is
begin
return semTake (SEM_ID (ID), WAIT_FOREVER);
end Binary_Semaphore_Obtain;
@@ -160,7 +163,8 @@ package body System.OS_Interface is
-- Binary_Semaphore_Release --
------------------------------
- function Binary_Semaphore_Release (ID : Binary_Semaphore_Id) return int is
+ function Binary_Semaphore_Release (ID : Binary_Semaphore_Id)
+ return STATUS is
begin
return semGive (SEM_ID (ID));
end Binary_Semaphore_Release;
@@ -169,7 +173,7 @@ package body System.OS_Interface is
-- Binary_Semaphore_Flush --
----------------------------
- function Binary_Semaphore_Flush (ID : Binary_Semaphore_Id) return int is
+ function Binary_Semaphore_Flush (ID : Binary_Semaphore_Id) return STATUS is
begin
return semFlush (SEM_ID (ID));
end Binary_Semaphore_Flush;
@@ -190,7 +194,7 @@ package body System.OS_Interface is
function Interrupt_Connect
(Vector : Interrupt_Vector;
Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int is
+ Parameter : System.Address := System.Null_Address) return STATUS is
begin
return
System.VxWorks.Ext.Interrupt_Connect
@@ -203,7 +207,7 @@ package body System.OS_Interface is
-- Interrupt_Context --
-----------------------
- function Interrupt_Context return int is
+ function Interrupt_Context return BOOL is
begin
return System.VxWorks.Ext.Interrupt_Context;
end Interrupt_Context;
diff --git a/gcc/ada/libgnarl/s-osinte__vxworks.ads b/gcc/ada/libgnarl/s-osinte__vxworks.ads
index a2d5620..e851645 100644
--- a/gcc/ada/libgnarl/s-osinte__vxworks.ads
+++ b/gcc/ada/libgnarl/s-osinte__vxworks.ads
@@ -47,6 +47,8 @@ with System.Parameters;
package System.OS_Interface is
pragma Preelaborate;
+ package SVE renames System.VxWorks.Ext;
+
subtype int is Interfaces.C.int;
subtype unsigned is Interfaces.C.unsigned;
subtype short is Short_Integer;
@@ -57,6 +59,10 @@ package System.OS_Interface is
type unsigned_long_long is mod 2 ** long_long'Size;
type size_t is mod 2 ** Standard'Address_Size;
+ subtype STATUS is SVE.STATUS;
+ subtype BOOL is SVE.BOOL;
+ subtype vx_freq_t is SVE.vx_freq_t;
+
-----------
-- Errno --
-----------
@@ -201,7 +207,7 @@ package System.OS_Interface is
oset : access sigset_t) return int;
pragma Import (C, pthread_sigmask, "sigprocmask");
- subtype t_id is System.VxWorks.Ext.t_id;
+ subtype t_id is SVE.t_id;
subtype Thread_Id is t_id;
-- Thread_Id and t_id are VxWorks identifiers for tasks. This value,
-- although represented as a Long_Integer, is in fact an address. With
@@ -211,27 +217,24 @@ package System.OS_Interface is
function kill (pid : t_id; sig : Signal) return int;
pragma Inline (kill);
- function getpid return t_id renames System.VxWorks.Ext.getpid;
+ function getpid return t_id renames SVE.getpid;
- function Task_Stop (tid : t_id) return int
- renames System.VxWorks.Ext.Task_Stop;
+ function Task_Stop (tid : t_id) return STATUS renames SVE.Task_Stop;
-- If we are in the kernel space, stop the task whose t_id is given in
-- parameter in such a way that it can be examined by the debugger. This
-- typically maps to taskSuspend on VxWorks 5 and to taskStop on VxWorks 6.
- function Task_Cont (tid : t_id) return int
- renames System.VxWorks.Ext.Task_Cont;
+ function Task_Cont (tid : t_id) return STATUS renames SVE.Task_Cont;
-- If we are in the kernel space, continue the task whose t_id is given
-- in parameter if it has been stopped previously to be examined by the
-- debugger (e.g. by taskStop). It typically maps to taskResume on VxWorks
-- 5 and to taskCont on VxWorks 6.
- function Int_Lock return int renames System.VxWorks.Ext.Int_Lock;
+ function Int_Lock return int renames SVE.Int_Lock;
-- If we are in the kernel space, lock interrupts. It typically maps to
-- intLock.
- function Int_Unlock (Old : int) return int
- renames System.VxWorks.Ext.Int_Unlock;
+ procedure Int_Unlock (Old : int) renames SVE.Int_Unlock;
-- If we are in the kernel space, unlock interrupts. It typically maps to
-- intUnlock. The parameter Old is only used on PowerPC where it contains
-- the returned value from Int_Lock (the old MPSR).
@@ -285,34 +288,28 @@ package System.OS_Interface is
-- VxWorks specific API --
--------------------------
- subtype STATUS is int;
- -- Equivalent of the C type STATUS
-
- OK : constant STATUS := 0;
- ERROR : constant STATUS := Interfaces.C.int (-1);
-
function taskIdVerify (tid : t_id) return STATUS;
pragma Import (C, taskIdVerify, "taskIdVerify");
function taskIdSelf return t_id;
pragma Import (C, taskIdSelf, "taskIdSelf");
- function taskOptionsGet (tid : t_id; pOptions : access int) return int;
+ function taskOptionsGet (tid : t_id; pOptions : access int) return STATUS;
pragma Import (C, taskOptionsGet, "taskOptionsGet");
- function taskSuspend (tid : t_id) return int;
+ function taskSuspend (tid : t_id) return STATUS;
pragma Import (C, taskSuspend, "taskSuspend");
- function taskResume (tid : t_id) return int;
+ function taskResume (tid : t_id) return STATUS;
pragma Import (C, taskResume, "taskResume");
- function taskIsSuspended (tid : t_id) return int;
+ function taskIsSuspended (tid : t_id) return BOOL;
pragma Import (C, taskIsSuspended, "taskIsSuspended");
- function taskDelay (ticks : int) return int;
+ function taskDelay (ticks : int) return STATUS;
pragma Import (C, taskDelay, "taskDelay");
- function sysClkRateGet return int;
+ function sysClkRateGet return vx_freq_t;
pragma Import (C, sysClkRateGet, "sysClkRateGet");
-- VxWorks 5.x specific functions
@@ -320,17 +317,17 @@ package System.OS_Interface is
-- taskVarLib: eg VxWorks 6 RTPs
function taskVarAdd
- (tid : t_id; pVar : access System.Address) return int;
+ (tid : t_id; pVar : access System.Address) return STATUS;
pragma Import (C, taskVarAdd, "taskVarAdd");
function taskVarDelete
- (tid : t_id; pVar : access System.Address) return int;
+ (tid : t_id; pVar : access System.Address) return STATUS;
pragma Import (C, taskVarDelete, "taskVarDelete");
function taskVarSet
(tid : t_id;
pVar : access System.Address;
- value : System.Address) return int;
+ value : System.Address) return STATUS;
pragma Import (C, taskVarSet, "taskVarSet");
function taskVarGet
@@ -379,15 +376,15 @@ package System.OS_Interface is
procedure taskDelete (tid : t_id);
pragma Import (C, taskDelete, "taskDelete");
- function Set_Time_Slice (ticks : int) return int
- renames System.VxWorks.Ext.Set_Time_Slice;
+ function Set_Time_Slice (ticks : int) return STATUS renames
+ SVE.Set_Time_Slice;
-- Calls kernelTimeSlice under VxWorks 5.x, VxWorks 653, or in VxWorks 6
-- kernel apps. Returns ERROR for RTPs, VxWorks 5 /CERT
- function taskPriorityGet (tid : t_id; pPriority : access int) return int;
+ function taskPriorityGet (tid : t_id; pPriority : access int) return STATUS;
pragma Import (C, taskPriorityGet, "taskPriorityGet");
- function taskPrioritySet (tid : t_id; newPriority : int) return int;
+ function taskPrioritySet (tid : t_id; newPriority : int) return STATUS;
pragma Import (C, taskPrioritySet, "taskPrioritySet");
-- Semaphore creation flags
@@ -419,7 +416,7 @@ package System.OS_Interface is
-- semTake() timeout with ticks > NO_WAIT
S_objLib_OBJ_TIMEOUT : constant := M_objLib + 4;
- subtype SEM_ID is System.VxWorks.Ext.SEM_ID;
+ subtype SEM_ID is SVE.SEM_ID;
-- typedef struct semaphore *SEM_ID;
-- We use two different kinds of VxWorks semaphores: mutex and binary
@@ -433,14 +430,13 @@ package System.OS_Interface is
function semMCreate (options : int) return SEM_ID;
pragma Import (C, semMCreate, "semMCreate");
- function semDelete (Sem : SEM_ID) return int
- renames System.VxWorks.Ext.semDelete;
+ function semDelete (Sem : SEM_ID) return STATUS renames SVE.semDelete;
-- Delete a semaphore
- function semGive (Sem : SEM_ID) return int;
+ function semGive (Sem : SEM_ID) return STATUS;
pragma Import (C, semGive, "semGive");
- function semTake (Sem : SEM_ID; timeout : int) return int;
+ function semTake (Sem : SEM_ID; timeout : int) return STATUS;
pragma Import (C, semTake, "semTake");
-- Attempt to take binary semaphore. Error is returned if operation
-- times out
@@ -458,16 +454,16 @@ package System.OS_Interface is
function Binary_Semaphore_Create return Binary_Semaphore_Id;
pragma Inline (Binary_Semaphore_Create);
- function Binary_Semaphore_Delete (ID : Binary_Semaphore_Id) return int;
+ function Binary_Semaphore_Delete (ID : Binary_Semaphore_Id) return STATUS;
pragma Inline (Binary_Semaphore_Delete);
- function Binary_Semaphore_Obtain (ID : Binary_Semaphore_Id) return int;
+ function Binary_Semaphore_Obtain (ID : Binary_Semaphore_Id) return STATUS;
pragma Inline (Binary_Semaphore_Obtain);
- function Binary_Semaphore_Release (ID : Binary_Semaphore_Id) return int;
+ function Binary_Semaphore_Release (ID : Binary_Semaphore_Id) return STATUS;
pragma Inline (Binary_Semaphore_Release);
- function Binary_Semaphore_Flush (ID : Binary_Semaphore_Id) return int;
+ function Binary_Semaphore_Flush (ID : Binary_Semaphore_Id) return STATUS;
pragma Inline (Binary_Semaphore_Flush);
------------------------------------------------------------
@@ -482,16 +478,16 @@ package System.OS_Interface is
function Interrupt_Connect
(Vector : Interrupt_Vector;
Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int;
+ Parameter : System.Address := System.Null_Address) return STATUS;
pragma Inline (Interrupt_Connect);
-- Use this to set up an user handler. The routine installs a user handler
-- which is invoked after the OS has saved enough context for a high-level
-- language routine to be safely invoked.
- function Interrupt_Context return int;
+ function Interrupt_Context return BOOL;
pragma Inline (Interrupt_Context);
- -- Return 1 if executing in an interrupt context; return 0 if executing in
- -- a task context.
+ -- Return 1 (TRUE) if executing in an interrupt context;
+ -- return 0 (FALSE) if executing in a task context.
function Interrupt_Number_To_Vector (intNum : int) return Interrupt_Vector;
pragma Inline (Interrupt_Number_To_Vector);
@@ -503,12 +499,12 @@ package System.OS_Interface is
--------------------------------
function taskCpuAffinitySet (tid : t_id; CPU : int) return int
- renames System.VxWorks.Ext.taskCpuAffinitySet;
+ renames SVE.taskCpuAffinitySet;
-- For SMP run-times the affinity to CPU.
-- For uniprocessor systems return ERROR status.
function taskMaskAffinitySet (tid : t_id; CPU_Set : unsigned) return int
- renames System.VxWorks.Ext.taskMaskAffinitySet;
+ renames SVE.taskMaskAffinitySet;
-- For SMP run-times the affinity to CPU_Set.
-- For uniprocessor systems return ERROR status.
@@ -524,5 +520,5 @@ private
ERROR_PID : constant pid_t := -1;
- type sigset_t is new System.VxWorks.Ext.sigset_t;
+ type sigset_t is new SVE.sigset_t;
end System.OS_Interface;
diff --git a/gcc/ada/libgnarl/s-taprop__vxworks.adb b/gcc/ada/libgnarl/s-taprop__vxworks.adb
index a87d1a0..273aca8 100644
--- a/gcc/ada/libgnarl/s-taprop__vxworks.adb
+++ b/gcc/ada/libgnarl/s-taprop__vxworks.adb
@@ -62,12 +62,17 @@ package body System.Task_Primitives.Operations is
use System.Tasking;
use System.OS_Interface;
use System.Parameters;
- use type System.VxWorks.Ext.t_id;
use type Interfaces.C.int;
use type System.OS_Interface.unsigned;
+ use type System.VxWorks.Ext.t_id;
+ use type System.VxWorks.Ext.STATUS;
+ use type System.VxWorks.Ext.BOOL;
- subtype int is System.OS_Interface.int;
+ subtype int is System.OS_Interface.int;
subtype unsigned is System.OS_Interface.unsigned;
+ subtype STATUS is System.VxWorks.Ext.STATUS;
+
+ OK : constant STATUS := System.VxWorks.Ext.OK;
Relative : constant := 0;
@@ -333,17 +338,17 @@ package body System.Task_Primitives.Operations is
-------------------
procedure Finalize_Lock (L : not null access Lock) is
- Result : int;
+ Result : STATUS;
begin
Result := semDelete (L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Finalize_Lock;
procedure Finalize_Lock (L : not null access RTS_Lock) is
- Result : int;
+ Result : STATUS;
begin
Result := semDelete (L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Finalize_Lock;
----------------
@@ -354,7 +359,7 @@ package body System.Task_Primitives.Operations is
(L : not null access Lock;
Ceiling_Violation : out Boolean)
is
- Result : int;
+ Result : STATUS;
begin
if L.Protocol = Prio_Protect
@@ -367,21 +372,21 @@ package body System.Task_Primitives.Operations is
end if;
Result := semTake (L.Mutex, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Write_Lock;
procedure Write_Lock (L : not null access RTS_Lock) is
- Result : int;
+ Result : STATUS;
begin
Result := semTake (L.Mutex, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Write_Lock;
procedure Write_Lock (T : Task_Id) is
- Result : int;
+ Result : STATUS;
begin
Result := semTake (T.Common.LL.L.Mutex, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Write_Lock;
---------------
@@ -400,24 +405,24 @@ package body System.Task_Primitives.Operations is
------------
procedure Unlock (L : not null access Lock) is
- Result : int;
+ Result : STATUS;
begin
Result := semGive (L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Unlock;
procedure Unlock (L : not null access RTS_Lock) is
- Result : int;
+ Result : STATUS;
begin
Result := semGive (L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Unlock;
procedure Unlock (T : Task_Id) is
- Result : int;
+ Result : STATUS;
begin
Result := semGive (T.Common.LL.L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Unlock;
-----------------
@@ -442,7 +447,7 @@ package body System.Task_Primitives.Operations is
procedure Sleep (Self_ID : Task_Id; Reason : System.Tasking.Task_States) is
pragma Unreferenced (Reason);
- Result : int;
+ Result : STATUS;
begin
pragma Assert (Self_ID = Self);
@@ -450,7 +455,7 @@ package body System.Task_Primitives.Operations is
-- Release the mutex before sleeping
Result := semGive (Self_ID.Common.LL.L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
-- Perform a blocking operation to take the CV semaphore. Note that a
-- blocking operation in VxWorks will reenable task scheduling. When we
@@ -458,12 +463,12 @@ package body System.Task_Primitives.Operations is
-- again be disabled.
Result := semTake (Self_ID.Common.LL.CV, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
-- Take the mutex back
Result := semTake (Self_ID.Common.LL.L.Mutex, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Sleep;
-----------------
@@ -486,7 +491,7 @@ package body System.Task_Primitives.Operations is
Orig : constant Duration := Monotonic_Clock;
Absolute : Duration;
Ticks : int;
- Result : int;
+ Result : STATUS;
Wakeup : Boolean := False;
begin
@@ -516,7 +521,7 @@ package body System.Task_Primitives.Operations is
-- Release the mutex before sleeping
Result := semGive (Self_ID.Common.LL.L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
-- Perform a blocking operation to take the CV semaphore. Note
-- that a blocking operation in VxWorks will reenable task
@@ -525,7 +530,7 @@ package body System.Task_Primitives.Operations is
Result := semTake (Self_ID.Common.LL.CV, Ticks);
- if Result = 0 then
+ if Result = OK then
-- Somebody may have called Wakeup for us
@@ -556,7 +561,7 @@ package body System.Task_Primitives.Operations is
-- Take the mutex back
Result := semTake (Self_ID.Common.LL.L.Mutex, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
exit when Timedout or Wakeup;
end loop;
@@ -590,7 +595,7 @@ package body System.Task_Primitives.Operations is
Timedout : Boolean;
Aborted : Boolean := False;
- Result : int;
+ Result : STATUS;
pragma Warnings (Off, Result);
begin
@@ -617,7 +622,7 @@ package body System.Task_Primitives.Operations is
Result := semTake (Self_ID.Common.LL.L.Mutex, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
Self_ID.Common.State := Delay_Sleep;
Timedout := False;
@@ -628,13 +633,13 @@ package body System.Task_Primitives.Operations is
-- Release the TCB before sleeping
Result := semGive (Self_ID.Common.LL.L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
exit when Aborted;
Result := semTake (Self_ID.Common.LL.CV, Ticks);
- if Result /= 0 then
+ if Result /= OK then
-- If Ticks = int'last, it was most probably truncated, so make
-- another round after recomputing Ticks from absolute time.
@@ -655,7 +660,7 @@ package body System.Task_Primitives.Operations is
Result := semTake (Self_ID.Common.LL.L.Mutex, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
exit when Timedout;
end loop;
@@ -697,10 +702,10 @@ package body System.Task_Primitives.Operations is
procedure Wakeup (T : Task_Id; Reason : System.Tasking.Task_States) is
pragma Unreferenced (Reason);
- Result : int;
+ Result : STATUS;
begin
Result := semGive (T.Common.LL.CV);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Wakeup;
-----------
@@ -709,7 +714,7 @@ package body System.Task_Primitives.Operations is
procedure Yield (Do_Yield : Boolean := True) is
pragma Unreferenced (Do_Yield);
- Result : int;
+ Result : STATUS;
pragma Unreferenced (Result);
begin
Result := taskDelay (0);
@@ -726,13 +731,13 @@ package body System.Task_Primitives.Operations is
is
pragma Unreferenced (Loss_Of_Inheritance);
- Result : int;
+ Result : STATUS;
begin
Result :=
taskPrioritySet
(T.Common.LL.Thread, To_VxWorks_Priority (int (Prio)));
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
-- Note: in VxWorks 6.6 (or earlier), the task is placed at the end of
-- the priority queue instead of the head. This is not the behavior
@@ -938,16 +943,16 @@ package body System.Task_Primitives.Operations is
------------------
procedure Finalize_TCB (T : Task_Id) is
- Result : int;
+ Result : STATUS;
begin
Result := semDelete (T.Common.LL.L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
T.Common.LL.Thread := Null_Thread_Id;
Result := semDelete (T.Common.LL.CV);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
if T.Known_Tasks_Index /= -1 then
Known_Tasks (T.Known_Tasks_Index) := null;
@@ -1137,7 +1142,7 @@ package body System.Task_Primitives.Operations is
S.State := False;
Result := semGive (S.L);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
SSL.Abort_Undefer.all;
@@ -1218,7 +1223,7 @@ package body System.Task_Primitives.Operations is
if T.Common.LL.Thread /= Null_Thread_Id
and then T.Common.LL.Thread /= Thread_Self
then
- return taskSuspend (T.Common.LL.Thread) = 0;
+ return taskSuspend (T.Common.LL.Thread) = OK;
else
return True;
end if;
@@ -1236,7 +1241,7 @@ package body System.Task_Primitives.Operations is
if T.Common.LL.Thread /= Null_Thread_Id
and then T.Common.LL.Thread /= Thread_Self
then
- return taskResume (T.Common.LL.Thread) = 0;
+ return taskResume (T.Common.LL.Thread) = OK;
else
return True;
end if;
@@ -1251,7 +1256,7 @@ package body System.Task_Primitives.Operations is
Thread_Self : constant Thread_Id := taskIdSelf;
C : Task_Id;
- Dummy : int;
+ Dummy : STATUS;
Old : int;
begin
@@ -1268,7 +1273,7 @@ package body System.Task_Primitives.Operations is
C := C.Common.All_Tasks_Link;
end loop;
- Dummy := Int_Unlock (Old);
+ Int_Unlock (Old);
end Stop_All_Tasks;
---------------
@@ -1278,7 +1283,7 @@ package body System.Task_Primitives.Operations is
function Stop_Task (T : ST.Task_Id) return Boolean is
begin
if T.Common.LL.Thread /= Null_Thread_Id then
- return Task_Stop (T.Common.LL.Thread) = 0;
+ return Task_Stop (T.Common.LL.Thread) = OK;
else
return True;
end if;
@@ -1292,7 +1297,7 @@ package body System.Task_Primitives.Operations is
is
begin
if T.Common.LL.Thread /= Null_Thread_Id then
- return Task_Cont (T.Common.LL.Thread) = 0;
+ return Task_Cont (T.Common.LL.Thread) = OK;
else
return True;
end if;
@@ -1304,7 +1309,7 @@ package body System.Task_Primitives.Operations is
function Is_Task_Context return Boolean is
begin
- return System.OS_Interface.Interrupt_Context /= 1;
+ return OSI.Interrupt_Context = 0;
end Is_Task_Context;
----------------
@@ -1312,7 +1317,7 @@ package body System.Task_Primitives.Operations is
----------------
procedure Initialize (Environment_Task : Task_Id) is
- Result : int;
+ Result : STATUS;
pragma Unreferenced (Result);
begin
diff --git a/gcc/ada/libgnarl/s-taskin.ads b/gcc/ada/libgnarl/s-taskin.ads
index 5c03829..cf560b5 100644
--- a/gcc/ada/libgnarl/s-taskin.ads
+++ b/gcc/ada/libgnarl/s-taskin.ads
@@ -368,14 +368,6 @@ package System.Tasking is
-- Used to represent protected procedures to be executed when task
-- terminates.
- type Initialization_Handler is access procedure;
- pragma Favor_Top_Level (Initialization_Handler);
- -- Use to represent procedures to be executed at task initialization.
-
- Global_Initialization_Handler : Initialization_Handler := null;
- pragma Atomic (Global_Initialization_Handler);
- -- Global handler called when each task initializes.
-
------------------------------------
-- Dispatching domain definitions --
------------------------------------
diff --git a/gcc/ada/libgnarl/s-tassta.adb b/gcc/ada/libgnarl/s-tassta.adb
index 88850c2..bbc7d14 100644
--- a/gcc/ada/libgnarl/s-tassta.adb
+++ b/gcc/ada/libgnarl/s-tassta.adb
@@ -35,6 +35,7 @@ pragma Partition_Elaboration_Policy (Concurrent);
with Ada.Exceptions;
with Ada.Unchecked_Deallocation;
+with Ada.Task_Initialization;
with System.Interrupt_Management;
with System.Tasking.Debug;
@@ -1177,6 +1178,14 @@ package body System.Tasking.Stages is
Debug.Signal_Debug_Event (Debug.Debug_Event_Run, Self_ID);
end if;
+ declare
+ use Ada.Task_Initialization;
+
+ Global_Initialization_Handler : Initialization_Handler;
+ pragma Atomic (Global_Initialization_Handler);
+ pragma Import (Ada, Global_Initialization_Handler,
+ "__gnat_global_initialization_handler");
+
begin
-- We are separating the following portion of the code in order to
-- place the exception handlers in a different block. In this way,
diff --git a/gcc/ada/libgnarl/s-tpopsp__vxworks-rtp.adb b/gcc/ada/libgnarl/s-tpopsp__vxworks-rtp.adb
index e5d4089..1343f6b 100644
--- a/gcc/ada/libgnarl/s-tpopsp__vxworks-rtp.adb
+++ b/gcc/ada/libgnarl/s-tpopsp__vxworks-rtp.adb
@@ -35,6 +35,8 @@
separate (System.Task_Primitives.Operations)
package body Specific is
+ ERROR : constant STATUS := System.VxWorks.Ext.ERROR;
+
ATCB_Key : int := 0;
-- Key used to find the Ada Task_Id associated with a thread
@@ -43,9 +45,10 @@ package body Specific is
----------------
procedure Initialize is
+ IERR : constant := -1;
begin
ATCB_Key := tlsKeyCreate;
- pragma Assert (ATCB_Key /= ERROR);
+ pragma Assert (ATCB_Key /= IERR);
end Initialize;
-------------------
diff --git a/gcc/ada/libgnarl/s-tpopsp__vxworks.adb b/gcc/ada/libgnarl/s-tpopsp__vxworks.adb
index 2d7cf00..9dc5d8b 100644
--- a/gcc/ada/libgnarl/s-tpopsp__vxworks.adb
+++ b/gcc/ada/libgnarl/s-tpopsp__vxworks.adb
@@ -35,6 +35,8 @@
separate (System.Task_Primitives.Operations)
package body Specific is
+ ERROR : constant STATUS := System.VxWorks.Ext.ERROR;
+
ATCB_Key : aliased System.Address := System.Null_Address;
-- Key used to find the Ada Task_Id associated with a thread
@@ -70,8 +72,9 @@ package body Specific is
-------------------
function Is_Valid_Task return Boolean is
+ IERR : constant := -1;
begin
- return taskVarGet (taskIdSelf, ATCB_Key'Access) /= ERROR;
+ return taskVarGet (taskIdSelf, ATCB_Key'Access) /= IERR;
end Is_Valid_Task;
---------
diff --git a/gcc/ada/libgnarl/s-vxwext.adb b/gcc/ada/libgnarl/s-vxwext.adb
index 0e1a792..d50d93d 100644
--- a/gcc/ada/libgnarl/s-vxwext.adb
+++ b/gcc/ada/libgnarl/s-vxwext.adb
@@ -30,7 +30,7 @@
package body System.VxWorks.Ext is
- ERROR : constant := -1;
+ IERR : constant := -1;
------------------------
-- taskCpuAffinitySet --
@@ -39,7 +39,7 @@ package body System.VxWorks.Ext is
function taskCpuAffinitySet (tid : t_id; CPU : int) return int is
pragma Unreferenced (tid, CPU);
begin
- return ERROR;
+ return IERR;
end taskCpuAffinitySet;
-------------------------
@@ -49,7 +49,7 @@ package body System.VxWorks.Ext is
function taskMaskAffinitySet (tid : t_id; CPU_Set : unsigned) return int is
pragma Unreferenced (tid, CPU_Set);
begin
- return ERROR;
+ return IERR;
end taskMaskAffinitySet;
end System.VxWorks.Ext;
diff --git a/gcc/ada/libgnarl/s-vxwext.ads b/gcc/ada/libgnarl/s-vxwext.ads
index 915db33..ab73415 100644
--- a/gcc/ada/libgnarl/s-vxwext.ads
+++ b/gcc/ada/libgnarl/s-vxwext.ads
@@ -46,6 +46,18 @@ package System.VxWorks.Ext is
subtype int is Interfaces.C.int;
subtype unsigned is Interfaces.C.unsigned;
+ type STATUS is new int;
+ -- Equivalent of the C type STATUS
+
+ OK : constant STATUS := 0;
+ ERROR : constant STATUS := -1;
+
+ type BOOL is new int;
+ -- Equivalent of the C type BOOL
+
+ type vx_freq_t is new unsigned;
+ -- Equivalent of the C type _Vx_freq_t
+
type Interrupt_Handler is access procedure (parameter : System.Address);
pragma Convention (C, Interrupt_Handler);
@@ -54,7 +66,7 @@ package System.VxWorks.Ext is
function Int_Lock return int;
pragma Import (C, Int_Lock, "intLock");
- function Int_Unlock (Old : int) return int;
+ procedure Int_Unlock (Old : int);
pragma Import (C, Int_Unlock, "intUnlock");
function Interrupt_Connect
@@ -63,7 +75,7 @@ package System.VxWorks.Ext is
Parameter : System.Address := System.Null_Address) return int;
pragma Import (C, Interrupt_Connect, "intConnect");
- function Interrupt_Context return int;
+ function Interrupt_Context return BOOL;
pragma Import (C, Interrupt_Context, "intContext");
function Interrupt_Number_To_Vector
diff --git a/gcc/ada/libgnarl/s-vxwext__kernel-smp.adb b/gcc/ada/libgnarl/s-vxwext__kernel-smp.adb
index ea1f71c..b78e078 100644
--- a/gcc/ada/libgnarl/s-vxwext__kernel-smp.adb
+++ b/gcc/ada/libgnarl/s-vxwext__kernel-smp.adb
@@ -33,7 +33,7 @@
package body System.VxWorks.Ext is
- ERROR : constant := -1;
+ IERR : constant := -1;
--------------
-- Int_Lock --
@@ -41,25 +41,25 @@ package body System.VxWorks.Ext is
function Int_Lock return int is
begin
- return ERROR;
+ return IERR;
end Int_Lock;
----------------
-- Int_Unlock --
----------------
- function Int_Unlock (Old : int) return int is
+ procedure Int_Unlock (Old : int) is
pragma Unreferenced (Old);
begin
- return ERROR;
+ null;
end Int_Unlock;
---------------
-- semDelete --
---------------
- function semDelete (Sem : SEM_ID) return int is
- function Os_Sem_Delete (Sem : SEM_ID) return int;
+ function semDelete (Sem : SEM_ID) return STATUS is
+ function Os_Sem_Delete (Sem : SEM_ID) return STATUS;
pragma Import (C, Os_Sem_Delete, "semDelete");
begin
return Os_Sem_Delete (Sem);
@@ -92,8 +92,8 @@ package body System.VxWorks.Ext is
-- Task_Cont --
---------------
- function Task_Cont (tid : t_id) return int is
- function taskCont (tid : t_id) return int;
+ function Task_Cont (tid : t_id) return STATUS is
+ function taskCont (tid : t_id) return STATUS;
pragma Import (C, taskCont, "taskCont");
begin
return taskCont (tid);
@@ -103,8 +103,8 @@ package body System.VxWorks.Ext is
-- Task_Stop --
---------------
- function Task_Stop (tid : t_id) return int is
- function taskStop (tid : t_id) return int;
+ function Task_Stop (tid : t_id) return STATUS is
+ function taskStop (tid : t_id) return STATUS;
pragma Import (C, taskStop, "taskStop");
begin
return taskStop (tid);
diff --git a/gcc/ada/libgnarl/s-vxwext__kernel.adb b/gcc/ada/libgnarl/s-vxwext__kernel.adb
index 4743540..2f00059 100644
--- a/gcc/ada/libgnarl/s-vxwext__kernel.adb
+++ b/gcc/ada/libgnarl/s-vxwext__kernel.adb
@@ -34,7 +34,7 @@
package body System.VxWorks.Ext is
- ERROR : constant := -1;
+ IERR : constant := -1;
--------------
-- Int_Lock --
@@ -49,17 +49,17 @@ package body System.VxWorks.Ext is
-- Int_Unlock --
----------------
- function intUnlock (Old : int) return int;
+ procedure intUnlock (Old : int);
pragma Import (C, intUnlock, "intUnlock");
- function Int_Unlock (Old : int) return int renames intUnlock;
+ procedure Int_Unlock (Old : int) renames intUnlock;
---------------
-- semDelete --
---------------
- function semDelete (Sem : SEM_ID) return int is
- function Os_Sem_Delete (Sem : SEM_ID) return int;
+ function semDelete (Sem : SEM_ID) return STATUS is
+ function Os_Sem_Delete (Sem : SEM_ID) return STATUS;
pragma Import (C, Os_Sem_Delete, "semDelete");
begin
return Os_Sem_Delete (Sem);
@@ -72,7 +72,7 @@ package body System.VxWorks.Ext is
function taskCpuAffinitySet (tid : t_id; CPU : int) return int is
pragma Unreferenced (tid, CPU);
begin
- return ERROR;
+ return IERR;
end taskCpuAffinitySet;
-------------------------
@@ -82,15 +82,15 @@ package body System.VxWorks.Ext is
function taskMaskAffinitySet (tid : t_id; CPU_Set : unsigned) return int is
pragma Unreferenced (tid, CPU_Set);
begin
- return ERROR;
+ return IERR;
end taskMaskAffinitySet;
---------------
-- Task_Cont --
---------------
- function Task_Cont (tid : t_id) return int is
- function taskCont (tid : t_id) return int;
+ function Task_Cont (tid : t_id) return STATUS is
+ function taskCont (tid : t_id) return STATUS;
pragma Import (C, taskCont, "taskCont");
begin
return taskCont (tid);
@@ -100,8 +100,8 @@ package body System.VxWorks.Ext is
-- Task_Stop --
---------------
- function Task_Stop (tid : t_id) return int is
- function taskStop (tid : t_id) return int;
+ function Task_Stop (tid : t_id) return STATUS is
+ function taskStop (tid : t_id) return STATUS;
pragma Import (C, taskStop, "taskStop");
begin
return taskStop (tid);
diff --git a/gcc/ada/libgnarl/s-vxwext__kernel.ads b/gcc/ada/libgnarl/s-vxwext__kernel.ads
index 3c200a1..7b299b9 100644
--- a/gcc/ada/libgnarl/s-vxwext__kernel.ads
+++ b/gcc/ada/libgnarl/s-vxwext__kernel.ads
@@ -45,6 +45,18 @@ package System.VxWorks.Ext is
subtype int is Interfaces.C.int;
subtype unsigned is Interfaces.C.unsigned;
+ type STATUS is new int;
+ -- Equivalent of the C type STATUS
+
+ OK : constant STATUS := 0;
+ ERROR : constant STATUS := -1;
+
+ type BOOL is new int;
+ -- Equivalent of the C type BOOL
+
+ type vx_freq_t is new unsigned;
+ -- Equivalent of the C type _Vx_freq_t
+
type Interrupt_Handler is access procedure (parameter : System.Address);
pragma Convention (C, Interrupt_Handler);
@@ -53,29 +65,29 @@ package System.VxWorks.Ext is
function Int_Lock return int;
pragma Convention (C, Int_Lock);
- function Int_Unlock (Old : int) return int;
+ procedure Int_Unlock (Old : int);
pragma Convention (C, Int_Unlock);
function Interrupt_Connect
(Vector : Interrupt_Vector;
Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int;
+ Parameter : System.Address := System.Null_Address) return STATUS;
pragma Import (C, Interrupt_Connect, "intConnect");
- function Interrupt_Context return int;
+ function Interrupt_Context return BOOL;
pragma Import (C, Interrupt_Context, "intContext");
function Interrupt_Number_To_Vector
(intNum : int) return Interrupt_Vector;
pragma Import (C, Interrupt_Number_To_Vector, "__gnat_inum_to_ivec");
- function semDelete (Sem : SEM_ID) return int;
+ function semDelete (Sem : SEM_ID) return STATUS;
pragma Convention (C, semDelete);
- function Task_Cont (tid : t_id) return int;
+ function Task_Cont (tid : t_id) return STATUS;
pragma Convention (C, Task_Cont);
- function Task_Stop (tid : t_id) return int;
+ function Task_Stop (tid : t_id) return STATUS;
pragma Convention (C, Task_Stop);
function kill (pid : t_id; sig : int) return int;
@@ -84,7 +96,7 @@ package System.VxWorks.Ext is
function getpid return t_id;
pragma Import (C, getpid, "taskIdSelf");
- function Set_Time_Slice (ticks : int) return int;
+ function Set_Time_Slice (ticks : int) return STATUS;
pragma Import (C, Set_Time_Slice, "kernelTimeSlice");
type UINT64 is mod 2 ** Long_Long_Integer'Size;
diff --git a/gcc/ada/libgnarl/s-vxwext__rtp-smp.adb b/gcc/ada/libgnarl/s-vxwext__rtp-smp.adb
index 241a8f5..5bf6ae5 100644
--- a/gcc/ada/libgnarl/s-vxwext__rtp-smp.adb
+++ b/gcc/ada/libgnarl/s-vxwext__rtp-smp.adb
@@ -33,7 +33,7 @@
package body System.VxWorks.Ext is
- ERROR : constant := -1;
+ IERR : constant := -1;
--------------
-- Int_Lock --
@@ -41,17 +41,17 @@ package body System.VxWorks.Ext is
function Int_Lock return int is
begin
- return ERROR;
+ return IERR;
end Int_Lock;
----------------
-- Int_Unlock --
----------------
- function Int_Unlock (Old : int) return int is
+ procedure Int_Unlock (Old : int) is
pragma Unreferenced (Old);
begin
- return ERROR;
+ null;
end Int_Unlock;
-----------------------
@@ -61,7 +61,7 @@ package body System.VxWorks.Ext is
function Interrupt_Connect
(Vector : Interrupt_Vector;
Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int
+ Parameter : System.Address := System.Null_Address) return STATUS
is
pragma Unreferenced (Vector, Handler, Parameter);
begin
@@ -72,7 +72,7 @@ package body System.VxWorks.Ext is
-- Interrupt_Context --
-----------------------
- function Interrupt_Context return int is
+ function Interrupt_Context return BOOL is
begin
-- For RTPs, never in an interrupt context
@@ -95,8 +95,8 @@ package body System.VxWorks.Ext is
-- semDelete --
---------------
- function semDelete (Sem : SEM_ID) return int is
- function OS_semDelete (Sem : SEM_ID) return int;
+ function semDelete (Sem : SEM_ID) return STATUS is
+ function OS_semDelete (Sem : SEM_ID) return STATUS;
pragma Import (C, OS_semDelete, "semDelete");
begin
return OS_semDelete (Sem);
@@ -106,7 +106,7 @@ package body System.VxWorks.Ext is
-- Set_Time_Slice --
--------------------
- function Set_Time_Slice (ticks : int) return int is
+ function Set_Time_Slice (ticks : int) return STATUS is
pragma Unreferenced (ticks);
begin
return ERROR;
diff --git a/gcc/ada/libgnarl/s-vxwext__rtp.adb b/gcc/ada/libgnarl/s-vxwext__rtp.adb
index f188ff8..543f152 100644
--- a/gcc/ada/libgnarl/s-vxwext__rtp.adb
+++ b/gcc/ada/libgnarl/s-vxwext__rtp.adb
@@ -33,7 +33,7 @@
package body System.VxWorks.Ext is
- ERROR : constant := -1;
+ IERR : constant := -1;
--------------
-- Int_Lock --
@@ -41,17 +41,17 @@ package body System.VxWorks.Ext is
function Int_Lock return int is
begin
- return ERROR;
+ return IERR;
end Int_Lock;
----------------
-- Int_Unlock --
----------------
- function Int_Unlock (Old : int) return int is
+ procedure Int_Unlock (Old : int) is
pragma Unreferenced (Old);
begin
- return ERROR;
+ null;
end Int_Unlock;
-----------------------
@@ -61,7 +61,7 @@ package body System.VxWorks.Ext is
function Interrupt_Connect
(Vector : Interrupt_Vector;
Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int
+ Parameter : System.Address := System.Null_Address) return STATUS
is
pragma Unreferenced (Vector, Handler, Parameter);
begin
@@ -72,7 +72,7 @@ package body System.VxWorks.Ext is
-- Interrupt_Context --
-----------------------
- function Interrupt_Context return int is
+ function Interrupt_Context return BOOL is
begin
-- For RTPs, never in an interrupt context
@@ -95,8 +95,8 @@ package body System.VxWorks.Ext is
-- semDelete --
---------------
- function semDelete (Sem : SEM_ID) return int is
- function OS_semDelete (Sem : SEM_ID) return int;
+ function semDelete (Sem : SEM_ID) return STATUS is
+ function OS_semDelete (Sem : SEM_ID) return STATUS;
pragma Import (C, OS_semDelete, "semDelete");
begin
return OS_semDelete (Sem);
@@ -106,7 +106,7 @@ package body System.VxWorks.Ext is
-- Set_Time_Slice --
--------------------
- function Set_Time_Slice (ticks : int) return int is
+ function Set_Time_Slice (ticks : int) return STATUS is
pragma Unreferenced (ticks);
begin
return ERROR;
@@ -119,7 +119,7 @@ package body System.VxWorks.Ext is
function taskCpuAffinitySet (tid : t_id; CPU : int) return int is
pragma Unreferenced (tid, CPU);
begin
- return ERROR;
+ return IERR;
end taskCpuAffinitySet;
-------------------------
@@ -129,7 +129,7 @@ package body System.VxWorks.Ext is
function taskMaskAffinitySet (tid : t_id; CPU_Set : unsigned) return int is
pragma Unreferenced (tid, CPU_Set);
begin
- return ERROR;
+ return IERR;
end taskMaskAffinitySet;
end System.VxWorks.Ext;
diff --git a/gcc/ada/libgnarl/s-vxwext__rtp.ads b/gcc/ada/libgnarl/s-vxwext__rtp.ads
index d13344e..995d098 100644
--- a/gcc/ada/libgnarl/s-vxwext__rtp.ads
+++ b/gcc/ada/libgnarl/s-vxwext__rtp.ads
@@ -45,6 +45,18 @@ package System.VxWorks.Ext is
subtype int is Interfaces.C.int;
subtype unsigned is Interfaces.C.unsigned;
+ type STATUS is new int;
+ -- Equivalent of the C type STATUS
+
+ OK : constant STATUS := 0;
+ ERROR : constant STATUS := -1;
+
+ type BOOL is new int;
+ -- Equivalent of the C type BOOL
+
+ type vx_freq_t is new unsigned;
+ -- Equivalent of the C type _Vx_freq_t
+
type Interrupt_Handler is access procedure (parameter : System.Address);
pragma Convention (C, Interrupt_Handler);
@@ -53,29 +65,29 @@ package System.VxWorks.Ext is
function Int_Lock return int;
pragma Inline (Int_Lock);
- function Int_Unlock (Old : int) return int;
+ procedure Int_Unlock (Old : int);
pragma Inline (Int_Unlock);
function Interrupt_Connect
(Vector : Interrupt_Vector;
Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int;
+ Parameter : System.Address := System.Null_Address) return STATUS;
pragma Convention (C, Interrupt_Connect);
- function Interrupt_Context return int;
+ function Interrupt_Context return BOOL;
pragma Convention (C, Interrupt_Context);
function Interrupt_Number_To_Vector
(intNum : int) return Interrupt_Vector;
pragma Convention (C, Interrupt_Number_To_Vector);
- function semDelete (Sem : SEM_ID) return int;
+ function semDelete (Sem : SEM_ID) return STATUS;
pragma Convention (C, semDelete);
- function Task_Cont (tid : t_id) return int;
+ function Task_Cont (tid : t_id) return STATUS;
pragma Import (C, Task_Cont, "taskResume");
- function Task_Stop (tid : t_id) return int;
+ function Task_Stop (tid : t_id) return STATUS;
pragma Import (C, Task_Stop, "taskSuspend");
function kill (pid : t_id; sig : int) return int;
@@ -84,7 +96,7 @@ package System.VxWorks.Ext is
function getpid return t_id;
pragma Import (C, getpid, "getpid");
- function Set_Time_Slice (ticks : int) return int;
+ function Set_Time_Slice (ticks : int) return STATUS;
pragma Inline (Set_Time_Slice);
--------------------------------
diff --git a/gcc/ada/libgnat/a-cbdlli.ads b/gcc/ada/libgnat/a-cbdlli.ads
index ab55086..f4086ea 100644
--- a/gcc/ada/libgnat/a-cbdlli.ads
+++ b/gcc/ada/libgnat/a-cbdlli.ads
@@ -57,11 +57,11 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Unnamed => Append);
- pragma Preelaborable_Initialization (List);
+ Add_Unnamed => Append),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_List : constant List;
diff --git a/gcc/ada/libgnat/a-cbhama.ads b/gcc/ada/libgnat/a-cbhama.ads
index 8be64c8..cdd4135 100644
--- a/gcc/ada/libgnat/a-cbhama.ads
+++ b/gcc/ada/libgnat/a-cbhama.ads
@@ -59,12 +59,13 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Named => Insert);
+ Add_Named => Insert),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization
+ and
+ Key_Type'Preelaborable_Initialization;
- pragma Preelaborable_Initialization (Map);
-
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Map : constant Map;
-- Map objects declared without an initialization expression are
diff --git a/gcc/ada/libgnat/a-cbhase.ads b/gcc/ada/libgnat/a-cbhase.ads
index 92926c1..78b31cf 100644
--- a/gcc/ada/libgnat/a-cbhase.ads
+++ b/gcc/ada/libgnat/a-cbhase.ads
@@ -61,12 +61,11 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Unnamed => Include);
+ Add_Unnamed => Include),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
- pragma Preelaborable_Initialization (Set);
-
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Set : constant Set;
-- Set objects declared without an initialization expression are
diff --git a/gcc/ada/libgnat/a-cbmutr.ads b/gcc/ada/libgnat/a-cbmutr.ads
index c7e221a..3712039 100644
--- a/gcc/ada/libgnat/a-cbmutr.ads
+++ b/gcc/ada/libgnat/a-cbmutr.ads
@@ -53,11 +53,11 @@ is
with Constant_Indexing => Constant_Reference,
Variable_Indexing => Reference,
Default_Iterator => Iterate,
- Iterator_Element => Element_Type;
- pragma Preelaborable_Initialization (Tree);
+ Iterator_Element => Element_Type,
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Tree : constant Tree;
diff --git a/gcc/ada/libgnat/a-cborma.ads b/gcc/ada/libgnat/a-cborma.ads
index f87522a..9d40a51 100644
--- a/gcc/ada/libgnat/a-cborma.ads
+++ b/gcc/ada/libgnat/a-cborma.ads
@@ -60,12 +60,13 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Named => Insert);
+ Add_Named => Insert),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization
+ and
+ Key_Type'Preelaborable_Initialization;
- pragma Preelaborable_Initialization (Map);
-
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Map : constant Map;
diff --git a/gcc/ada/libgnat/a-cborse.ads b/gcc/ada/libgnat/a-cborse.ads
index 06bd20f..31b8b91 100644
--- a/gcc/ada/libgnat/a-cborse.ads
+++ b/gcc/ada/libgnat/a-cborse.ads
@@ -59,12 +59,11 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Unnamed => Include);
+ Add_Unnamed => Include),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
- pragma Preelaborable_Initialization (Set);
-
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Set : constant Set;
diff --git a/gcc/ada/libgnat/a-cfdlli.ads b/gcc/ada/libgnat/a-cfdlli.ads
index 590643e..ded496b 100644
--- a/gcc/ada/libgnat/a-cfdlli.ads
+++ b/gcc/ada/libgnat/a-cfdlli.ads
@@ -44,6 +44,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
type List (Capacity : Count_Type) is private with
diff --git a/gcc/ada/libgnat/a-cfhama.ads b/gcc/ada/libgnat/a-cfhama.ads
index 2b49c13..59e295d 100644
--- a/gcc/ada/libgnat/a-cfhama.ads
+++ b/gcc/ada/libgnat/a-cfhama.ads
@@ -69,6 +69,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
type Map (Capacity : Count_Type; Modulus : Hash_Type) is private with
diff --git a/gcc/ada/libgnat/a-cfhase.ads b/gcc/ada/libgnat/a-cfhase.ads
index 9bcd8ce..23b3b6d 100644
--- a/gcc/ada/libgnat/a-cfhase.ads
+++ b/gcc/ada/libgnat/a-cfhase.ads
@@ -67,6 +67,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
type Set (Capacity : Count_Type; Modulus : Hash_Type) is private with
diff --git a/gcc/ada/libgnat/a-cfinve.ads b/gcc/ada/libgnat/a-cfinve.ads
index 9b95437..bd0c334 100644
--- a/gcc/ada/libgnat/a-cfinve.ads
+++ b/gcc/ada/libgnat/a-cfinve.ads
@@ -60,6 +60,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
subtype Extended_Index is Index_Type'Base
diff --git a/gcc/ada/libgnat/a-cforma.ads b/gcc/ada/libgnat/a-cforma.ads
index a1cad03..048e7cb 100644
--- a/gcc/ada/libgnat/a-cforma.ads
+++ b/gcc/ada/libgnat/a-cforma.ads
@@ -68,6 +68,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
function Equivalent_Keys (Left, Right : Key_Type) return Boolean with
diff --git a/gcc/ada/libgnat/a-cforse.ads b/gcc/ada/libgnat/a-cforse.ads
index e1d7c91..db7c586 100644
--- a/gcc/ada/libgnat/a-cforse.ads
+++ b/gcc/ada/libgnat/a-cforse.ads
@@ -64,6 +64,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
function Equivalent_Elements (Left, Right : Element_Type) return Boolean
diff --git a/gcc/ada/libgnat/a-chahan.adb b/gcc/ada/libgnat/a-chahan.adb
index 827794c..411d485 100644
--- a/gcc/ada/libgnat/a-chahan.adb
+++ b/gcc/ada/libgnat/a-chahan.adb
@@ -29,11 +29,19 @@
-- --
------------------------------------------------------------------------------
+-- Loop invariants in this unit are meant for analysis only, not for run-time
+-- checking, as it would be too costly otherwise. This is enforced by setting
+-- the assertion policy to Ignore.
+
+pragma Assertion_Policy (Loop_Invariant => Ignore);
+
with Ada.Characters.Latin_1; use Ada.Characters.Latin_1;
with Ada.Strings.Maps; use Ada.Strings.Maps;
with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
-package body Ada.Characters.Handling is
+package body Ada.Characters.Handling
+ with SPARK_Mode
+is
------------------------------------
-- Character Classification Table --
@@ -299,9 +307,7 @@ package body Ada.Characters.Handling is
------------------
function Is_Character (Item : Wide_Character) return Boolean is
- begin
- return Wide_Character'Pos (Item) < 256;
- end Is_Character;
+ (Wide_Character'Pos (Item) < 256);
----------------
-- Is_Control --
@@ -344,9 +350,7 @@ package body Ada.Characters.Handling is
----------------
function Is_ISO_646 (Item : Character) return Boolean is
- begin
- return Item in ISO_646;
- end Is_ISO_646;
+ (Item in ISO_646);
-- Note: much more efficient coding of the following function is possible
-- by testing several 16#80# bits in a complete word in a single operation
@@ -357,6 +361,8 @@ package body Ada.Characters.Handling is
if Item (J) not in ISO_646 then
return False;
end if;
+ pragma Loop_Invariant
+ (for all K in Item'First .. J => Is_ISO_646 (Item (K)));
end loop;
return True;
@@ -456,6 +462,8 @@ package body Ada.Characters.Handling is
if Wide_Character'Pos (Item (J)) >= 256 then
return False;
end if;
+ pragma Loop_Invariant
+ (for all K in Item'First .. J => Is_Character (Item (K)));
end loop;
return True;
@@ -475,15 +483,18 @@ package body Ada.Characters.Handling is
--------------
function To_Basic (Item : Character) return Character is
- begin
- return Value (Basic_Map, Item);
- end To_Basic;
+ (Value (Basic_Map, Item));
function To_Basic (Item : String) return String is
begin
- return Result : String (1 .. Item'Length) do
+ return Result : String (1 .. Item'Length) with Relaxed_Initialization do
for J in Item'Range loop
Result (J - (Item'First - 1)) := Value (Basic_Map, Item (J));
+ pragma Loop_Invariant
+ (Result (1 .. J - Item'First + 1)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) = To_Basic (Item (K)));
end loop;
end return;
end To_Basic;
@@ -511,24 +522,25 @@ package body Ada.Characters.Handling is
function To_ISO_646
(Item : Character;
Substitute : ISO_646 := ' ') return ISO_646
- is
- begin
- return (if Item in ISO_646 then Item else Substitute);
- end To_ISO_646;
+ is (if Item in ISO_646 then Item else Substitute);
function To_ISO_646
(Item : String;
Substitute : ISO_646 := ' ') return String
is
- Result : String (1 .. Item'Length);
-
begin
- for J in Item'Range loop
- Result (J - (Item'First - 1)) :=
- (if Item (J) in ISO_646 then Item (J) else Substitute);
- end loop;
-
- return Result;
+ return Result : String (1 .. Item'Length) with Relaxed_Initialization do
+ for J in Item'Range loop
+ Result (J - (Item'First - 1)) :=
+ (if Item (J) in ISO_646 then Item (J) else Substitute);
+ pragma Loop_Invariant
+ (Result (1 .. J - Item'First + 1)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) =
+ To_ISO_646 (Item (K), Substitute));
+ end loop;
+ end return;
end To_ISO_646;
--------------
@@ -536,15 +548,18 @@ package body Ada.Characters.Handling is
--------------
function To_Lower (Item : Character) return Character is
- begin
- return Value (Lower_Case_Map, Item);
- end To_Lower;
+ (Value (Lower_Case_Map, Item));
function To_Lower (Item : String) return String is
begin
- return Result : String (1 .. Item'Length) do
+ return Result : String (1 .. Item'Length) with Relaxed_Initialization do
for J in Item'Range loop
Result (J - (Item'First - 1)) := Value (Lower_Case_Map, Item (J));
+ pragma Loop_Invariant
+ (Result (1 .. J - Item'First + 1)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) = To_Lower (Item (K)));
end loop;
end return;
end To_Lower;
@@ -557,34 +572,40 @@ package body Ada.Characters.Handling is
(Item : Wide_String;
Substitute : Character := ' ') return String
is
- Result : String (1 .. Item'Length);
-
begin
- for J in Item'Range loop
- Result (J - (Item'First - 1)) := To_Character (Item (J), Substitute);
- end loop;
-
- return Result;
+ return Result : String (1 .. Item'Length) with Relaxed_Initialization do
+ for J in Item'Range loop
+ Result (J - (Item'First - 1)) :=
+ To_Character (Item (J), Substitute);
+ pragma Loop_Invariant
+ (Result (1 .. J - (Item'First - 1))'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) =
+ To_Character (Item (K), Substitute));
+ end loop;
+ end return;
end To_String;
--------------
-- To_Upper --
--------------
- function To_Upper
- (Item : Character) return Character
- is
- begin
- return Value (Upper_Case_Map, Item);
- end To_Upper;
+ function To_Upper (Item : Character) return Character is
+ (Value (Upper_Case_Map, Item));
function To_Upper
(Item : String) return String
is
begin
- return Result : String (1 .. Item'Length) do
+ return Result : String (1 .. Item'Length) with Relaxed_Initialization do
for J in Item'Range loop
Result (J - (Item'First - 1)) := Value (Upper_Case_Map, Item (J));
+ pragma Loop_Invariant
+ (Result (1 .. J - Item'First + 1)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) = To_Upper (Item (K)));
end loop;
end return;
end To_Upper;
@@ -607,14 +628,19 @@ package body Ada.Characters.Handling is
function To_Wide_String
(Item : String) return Wide_String
is
- Result : Wide_String (1 .. Item'Length);
-
begin
- for J in Item'Range loop
- Result (J - (Item'First - 1)) := To_Wide_Character (Item (J));
- end loop;
-
- return Result;
+ return Result : Wide_String (1 .. Item'Length)
+ with Relaxed_Initialization
+ do
+ for J in Item'Range loop
+ Result (J - (Item'First - 1)) := To_Wide_Character (Item (J));
+ pragma Loop_Invariant
+ (Result (1 .. J - (Item'First - 1))'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) = To_Wide_Character (Item (K)));
+ end loop;
+ end return;
end To_Wide_String;
end Ada.Characters.Handling;
diff --git a/gcc/ada/libgnat/a-chahan.ads b/gcc/ada/libgnat/a-chahan.ads
index 2f93e7c..093237d 100644
--- a/gcc/ada/libgnat/a-chahan.ads
+++ b/gcc/ada/libgnat/a-chahan.ads
@@ -33,7 +33,16 @@
-- --
------------------------------------------------------------------------------
-package Ada.Characters.Handling is
+-- Postconditions in this unit are meant for analysis only, not for run-time
+-- checking, in order not to slow down the execution of these functions.
+
+pragma Assertion_Policy (Post => Ignore);
+
+with Ada.Characters.Latin_1;
+
+package Ada.Characters.Handling
+ with SPARK_Mode
+is
pragma Pure;
-- In accordance with Ada 2005 AI-362
@@ -41,54 +50,296 @@ package Ada.Characters.Handling is
-- Character Classification Functions --
----------------------------------------
- function Is_Control (Item : Character) return Boolean;
- function Is_Graphic (Item : Character) return Boolean;
- function Is_Letter (Item : Character) return Boolean;
- function Is_Lower (Item : Character) return Boolean;
- function Is_Upper (Item : Character) return Boolean;
- function Is_Basic (Item : Character) return Boolean;
- function Is_Digit (Item : Character) return Boolean;
+ -- In the description below for each function that returns a Boolean
+ -- result, the effect is described in terms of the conditions under which
+ -- the value True is returned. If these conditions are not met, then the
+ -- function returns False.
+ --
+ -- Each of the following classification functions has a formal Character
+ -- parameter, Item, and returns a Boolean result.
+
+ function Is_Control (Item : Character) return Boolean
+ with
+ Post => Is_Control'Result =
+ (Character'Pos (Item) in 0 .. 31 | 127 .. 159);
+ -- True if Item is a control character. A control character is a character
+ -- whose position is in one of the ranges 0..31 or 127..159.
+
+ function Is_Graphic (Item : Character) return Boolean
+ with
+ Post => Is_Graphic'Result =
+ (Character'Pos (Item) in 32 .. 126 | 160 .. 255);
+ -- True if Item is a graphic character. A graphic character is a character
+ -- whose position is in one of the ranges 32..126 or 160..255.
+
+ function Is_Letter (Item : Character) return Boolean
+ with
+ Post => Is_Letter'Result =
+ (Item in 'A' .. 'Z' | 'a' .. 'z'
+ or else Character'Pos (Item) in 192 .. 214 | 216 .. 246 | 248 .. 255);
+ -- True if Item is a letter. A letter is a character that is in one of the
+ -- ranges 'A'..'Z' or 'a'..'z', or whose position is in one of the ranges
+ -- 192..214, 216..246, or 248..255.
+
+ function Is_Lower (Item : Character) return Boolean
+ with
+ Post => Is_Lower'Result =
+ (Item in 'a' .. 'z'
+ or else Character'Pos (Item) in 223 .. 246 | 248 .. 255);
+ -- True if Item is a lower-case letter. A lower-case letter is a character
+ -- that is in the range 'a'..'z', or whose position is in one of the ranges
+ -- 223..246 or 248..255.
+
+ function Is_Upper (Item : Character) return Boolean
+ with
+ Post => Is_Upper'Result =
+ (Item in 'A' .. 'Z'
+ or else Character'Pos (Item) in 192 .. 214 | 216 .. 222);
+ -- True if Item is an upper-case letter. An upper-case letter is a
+ -- character that is in the range 'A'..'Z' or whose position is in one
+ -- of the ranges 192..214 or 216..222.
+
+ function Is_Basic (Item : Character) return Boolean
+ with
+ Post => Is_Basic'Result =
+ (Item in 'A' .. 'Z'
+ | 'a' .. 'z'
+ | Latin_1.UC_AE_Diphthong
+ | Latin_1.LC_AE_Diphthong
+ | Latin_1.UC_Icelandic_Eth
+ | Latin_1.LC_Icelandic_Eth
+ | Latin_1.UC_Icelandic_Thorn
+ | Latin_1.LC_Icelandic_Thorn
+ | Latin_1.LC_German_Sharp_S);
+ -- True if Item is a basic letter. A basic letter is a character that
+ -- is in one of the ranges 'A'..'Z' and 'a'..'z', or that is one of
+ -- the following: UC_AE_Diphthong, LC_AE_Diphthong, UC_Icelandic_Eth,
+ -- LC_Icelandic_Eth, UC_Icelandic_Thorn, LC_Icelandic_Thorn, or
+ -- LC_German_Sharp_S.
+
+ function Is_Digit (Item : Character) return Boolean
+ with
+ Post => Is_Digit'Result = (Item in '0' .. '9');
+ -- True if Item is a decimal digit. A decimal digit is a character in the
+ -- range '0'..'9'.
+
function Is_Decimal_Digit (Item : Character) return Boolean
renames Is_Digit;
- function Is_Hexadecimal_Digit (Item : Character) return Boolean;
- function Is_Alphanumeric (Item : Character) return Boolean;
- function Is_Special (Item : Character) return Boolean;
- function Is_Line_Terminator (Item : Character) return Boolean;
- function Is_Mark (Item : Character) return Boolean;
- function Is_Other_Format (Item : Character) return Boolean;
- function Is_Punctuation_Connector (Item : Character) return Boolean;
- function Is_Space (Item : Character) return Boolean;
- function Is_NFKC (Item : Character) return Boolean;
+
+ function Is_Hexadecimal_Digit (Item : Character) return Boolean
+ with
+ Post => Is_Hexadecimal_Digit'Result =
+ (Is_Decimal_Digit (Item) or Item in 'A' .. 'F' | 'a' .. 'f');
+ -- True if Item is a hexadecimal digit. A hexadecimal digit is a character
+ -- that is either a decimal digit or that is in one of the ranges 'A'..'F'
+ -- or 'a'..'f'.
+
+ function Is_Alphanumeric (Item : Character) return Boolean
+ with
+ Post => Is_Alphanumeric'Result =
+ (Is_Letter (Item) or Is_Decimal_Digit (Item));
+ -- True if Item is an alphanumeric character. An alphanumeric character is
+ -- a character that is either a letter or a decimal digit.
+
+ function Is_Special (Item : Character) return Boolean
+ with
+ Post => Is_Special'Result =
+ (Is_Graphic (Item) and not Is_Alphanumeric (Item));
+ -- True if Item is a special graphic character. A special graphic character
+ -- is a graphic character that is not alphanumeric.
+
+ function Is_Line_Terminator (Item : Character) return Boolean
+ with
+ Post => Is_Line_Terminator'Result =
+ (Character'Pos (Item) in 10 .. 13 | 133);
+ -- True if Item is a character with position 10..13 (Line_Feed,
+ -- Line_Tabulation, Form_Feed, Carriage_Return) or 133 (Next_Line).
+
+ function Is_Mark (Item : Character) return Boolean
+ with
+ Post => Is_Mark'Result = False;
+ -- Never True (no value of type Character has categories Mark, Non-Spacing
+ -- or Mark, Spacing Combining).
+
+ function Is_Other_Format (Item : Character) return Boolean
+ with
+ Post => Is_Other_Format'Result = (Character'Pos (Item) = 173);
+ -- True if Item is a character with position 173 (Soft_Hyphen).
+
+ function Is_Punctuation_Connector (Item : Character) return Boolean
+ with
+ Post => Is_Punctuation_Connector'Result =
+ (Character'Pos (Item) = 95);
+ -- True if Item is a character with position 95 ('_', known as Low_Line or
+ -- Underscore).
+
+ function Is_Space (Item : Character) return Boolean
+ with
+ Post => Is_Space'Result = (Character'Pos (Item) in 32 | 160);
+ -- True if Item is a character with position 32 (' ') or 160
+ -- (No_Break_Space).
+
+ function Is_NFKC (Item : Character) return Boolean
+ with
+ Post => Is_NFKC'Result =
+ (Character'Pos (Item) not in
+ 160 | 168 | 170 | 175 | 178 | 179 | 180
+ | 181 | 184 | 185 | 186 | 188 | 189 | 190);
+ -- True if Item could be present in a string normalized to Normalization
+ -- Form KC (as defined by Clause 21 of ISO/IEC 10646:2017); this includes
+ -- all characters except those with positions 160, 168, 170, 175, 178, 179,
+ -- 180, 181, 184, 185, 186, 188, 189, and 190.
---------------------------------------------------
-- Conversion Functions for Character and String --
---------------------------------------------------
- function To_Lower (Item : Character) return Character;
- function To_Upper (Item : Character) return Character;
- function To_Basic (Item : Character) return Character;
+ -- Each of the names To_Lower, To_Upper, and To_Basic refers to two
+ -- functions: one that converts from Character to Character, and
+ -- the other that converts from String to String. The result of each
+ -- Character-to-Character function is described below, in terms of
+ -- the conversion applied to Item, its formal Character parameter. The
+ -- result of each String-to-String conversion is obtained by applying
+ -- to each element of the function's String parameter the corresponding
+ -- Character-to-Character conversion; the result is the null String if the
+ -- value of the formal parameter is the null String. The lower bound of the
+ -- result String is 1.
+
+ function To_Lower (Item : Character) return Character
+ with
+ Post => To_Lower'Result =
+ (if Is_Upper (Item) then
+ Character'Val (Character'Pos (Item) +
+ (if Item in 'A' .. 'Z' then
+ Character'Pos ('a') - Character'Pos ('A')
+ else
+ Character'Pos (Latin_1.LC_A_Grave)
+ - Character'Pos (Latin_1.UC_A_Grave)))
+ else
+ Item);
+ -- Returns the corresponding lower-case value for Item if Is_Upper(Item),
+ -- and returns Item otherwise.
- function To_Lower (Item : String) return String;
- function To_Upper (Item : String) return String;
- function To_Basic (Item : String) return String;
+ function To_Upper (Item : Character) return Character
+ with
+ Post => To_Upper'Result =
+ (if Is_Lower (Item)
+ and then Item not in Latin_1.LC_German_Sharp_S
+ | Latin_1.LC_Y_Diaeresis
+ then
+ Character'Val (Character'Pos (Item) +
+ (if Item in 'A' .. 'Z' then
+ Character'Pos ('A') - Character'Pos ('a')
+ else
+ Character'Pos (Latin_1.UC_A_Grave)
+ - Character'Pos (Latin_1.LC_A_Grave)))
+ else
+ Item);
+ -- Returns the corresponding upper-case value for Item if Is_Lower(Item)
+ -- and Item has an upper-case form, and returns Item otherwise. The lower
+ -- case letters LC_German_Sharp_S and LC_Y_Diaeresis do not have upper case
+ -- forms.
+
+ function To_Basic (Item : Character) return Character
+ with
+ Post => To_Basic'Result =
+ (if not Is_Letter (Item) or else Is_Basic (Item) then
+ Item
+ else
+ (case Item is
+ when Latin_1.UC_A_Grave .. Latin_1.UC_A_Ring => 'A',
+ when Latin_1.UC_C_Cedilla => 'C',
+ when Latin_1.UC_E_Grave .. Latin_1.UC_E_Diaeresis => 'E',
+ when Latin_1.UC_I_Grave .. Latin_1.UC_I_Diaeresis => 'I',
+ when Latin_1.UC_N_Tilde => 'N',
+ when Latin_1.UC_O_Grave .. Latin_1.UC_O_Diaeresis => 'O',
+ when Latin_1.UC_O_Oblique_Stroke => 'O',
+ when Latin_1.UC_U_Grave .. Latin_1.UC_U_Diaeresis => 'U',
+ when Latin_1.UC_Y_Acute => 'Y',
+ when Latin_1.LC_A_Grave .. Latin_1.LC_A_Ring => 'a',
+ when Latin_1.LC_C_Cedilla => 'c',
+ when Latin_1.LC_E_Grave .. Latin_1.LC_E_Diaeresis => 'e',
+ when Latin_1.LC_I_Grave .. Latin_1.LC_I_Diaeresis => 'i',
+ when Latin_1.LC_N_Tilde => 'n',
+ when Latin_1.LC_O_Grave .. Latin_1.LC_O_Diaeresis => 'o',
+ when Latin_1.LC_O_Oblique_Stroke => 'o',
+ when Latin_1.LC_U_Grave .. Latin_1.LC_U_Diaeresis => 'u',
+ when Latin_1.LC_Y_Acute => 'y',
+ when Latin_1.LC_Y_Diaeresis => 'y',
+ when others => raise Program_Error));
+ -- Returns the letter corresponding to Item but with no diacritical mark,
+ -- if Item is a letter but not a basic letter; returns Item otherwise.
+
+ function To_Lower (Item : String) return String
+ with
+ Post => To_Lower'Result'First = 1
+ and then To_Lower'Result'Length = Item'Length
+ and then
+ (for all J in To_Lower'Result'Range =>
+ To_Lower'Result (J) = To_Lower (Item (Item'First + (J - 1))));
+
+ function To_Upper (Item : String) return String
+ with
+ Post => To_Upper'Result'First = 1
+ and then To_Upper'Result'Length = Item'Length
+ and then
+ (for all J in To_Upper'Result'Range =>
+ To_Upper'Result (J) = To_Upper (Item (Item'First + (J - 1))));
+
+ function To_Basic (Item : String) return String
+ with
+ Post => To_Basic'Result'First = 1
+ and then To_Basic'Result'Length = Item'Length
+ and then
+ (for all J in To_Basic'Result'Range =>
+ To_Basic'Result (J) = To_Basic (Item (Item'First + (J - 1))));
----------------------------------------------------------------------
-- Classifications of and Conversions Between Character and ISO 646 --
----------------------------------------------------------------------
+ -- The following set of functions test for membership in the ISO 646
+ -- character range, or convert between ISO 646 and Character.
+
subtype ISO_646 is
Character range Character'Val (0) .. Character'Val (127);
- function Is_ISO_646 (Item : Character) return Boolean;
- function Is_ISO_646 (Item : String) return Boolean;
+ function Is_ISO_646 (Item : Character) return Boolean
+ with
+ Post => Is_ISO_646'Result = (Item in ISO_646);
+ -- The function whose formal parameter, Item, is of type Character returns
+ -- True if Item is in the subtype ISO_646.
+
+ function Is_ISO_646 (Item : String) return Boolean
+ with
+ Post => Is_ISO_646'Result =
+ (for all J in Item'Range => Is_ISO_646 (Item (J)));
+ -- The function whose formal parameter, Item, is of type String returns
+ -- True if Is_ISO_646(Item(I)) is True for each I in Item'Range.
function To_ISO_646
(Item : Character;
- Substitute : ISO_646 := ' ') return ISO_646;
+ Substitute : ISO_646 := ' ') return ISO_646
+ with
+ Post => To_ISO_646'Result =
+ (if Is_ISO_646 (Item) then Item else Substitute);
+ -- The function whose first formal parameter, Item, is of type Character
+ -- returns Item if Is_ISO_646(Item), and returns the Substitute ISO_646
+ -- character otherwise.
function To_ISO_646
(Item : String;
- Substitute : ISO_646 := ' ') return String;
+ Substitute : ISO_646 := ' ') return String
+ with
+ Post => To_ISO_646'Result'First = 1
+ and then To_ISO_646'Result'Length = Item'Length
+ and then
+ (for all J in To_ISO_646'Result'Range =>
+ To_ISO_646'Result (J) =
+ To_ISO_646 (Item (Item'First + (J - 1)), Substitute));
+ -- The function whose first formal parameter, Item, is of type String
+ -- returns the String whose Range is 1..Item'Length and each of whose
+ -- elements is given by To_ISO_646 of the corresponding element in Item.
------------------------------------------------------
-- Classifications of Wide_Character and Characters --
@@ -103,8 +354,18 @@ package Ada.Characters.Handling is
-- We do however have to flag these if the pragma No_Obsolescent_Features
-- restriction is active (see Restrict.Check_Obsolescent_2005_Entity).
- function Is_Character (Item : Wide_Character) return Boolean;
- function Is_String (Item : Wide_String) return Boolean;
+ function Is_Character (Item : Wide_Character) return Boolean
+ with
+ Post => Is_Character'Result =
+ (Wide_Character'Pos (Item) <= Character'Pos (Character'Last));
+ -- Returns True if Wide_Character'Pos(Item) <=
+ -- Character'Pos(Character'Last).
+
+ function Is_String (Item : Wide_String) return Boolean
+ with
+ Post => Is_String'Result =
+ (for all I in Item'Range => Is_Character (Item (I)));
+ -- Returns True if Is_Character(Item(I)) is True for each I in Item'Range.
------------------------------------------------------
-- Conversions between Wide_Character and Character --
@@ -121,17 +382,49 @@ package Ada.Characters.Handling is
function To_Character
(Item : Wide_Character;
- Substitute : Character := ' ') return Character;
+ Substitute : Character := ' ') return Character
+ with
+ Post => To_Character'Result =
+ (if Is_Character (Item) then
+ Character'Val (Wide_Character'Pos (Item))
+ else
+ Substitute);
+ -- Returns the Character corresponding to Item if Is_Character(Item), and
+ -- returns the Substitute Character otherwise.
function To_String
(Item : Wide_String;
- Substitute : Character := ' ') return String;
+ Substitute : Character := ' ') return String
+ with
+ Post => To_String'Result'First = 1
+ and then To_String'Result'Length = Item'Length
+ and then
+ (for all J in To_String'Result'Range =>
+ To_String'Result (J) =
+ To_Character (Item (Item'First + (J - 1)), Substitute));
+ -- Returns the String whose range is 1..Item'Length and each of whose
+ -- elements is given by To_Character of the corresponding element in Item.
function To_Wide_Character
- (Item : Character) return Wide_Character;
+ (Item : Character) return Wide_Character
+ with
+ Post => To_Wide_Character'Result =
+ Wide_Character'Val (Character'Pos (Item));
+ -- Returns the Wide_Character X such that Character'Pos(Item) =
+ -- Wide_Character'Pos (X).
function To_Wide_String
- (Item : String) return Wide_String;
+ (Item : String) return Wide_String
+ with
+ Post => To_Wide_String'Result'First = 1
+ and then To_Wide_String'Result'Length = Item'Length
+ and then
+ (for all J in To_Wide_String'Result'Range =>
+ To_Wide_String'Result (J) =
+ To_Wide_Character (Item (Item'First + (J - 1))));
+ -- Returns the Wide_String whose range is 1..Item'Length and each of whose
+ -- elements is given by To_Wide_Character of the corresponding element in
+ -- Item.
private
pragma Inline (Is_Alphanumeric);
diff --git a/gcc/ada/libgnat/a-coboho.ads b/gcc/ada/libgnat/a-coboho.ads
index 086f194..44269f0 100644
--- a/gcc/ada/libgnat/a-coboho.ads
+++ b/gcc/ada/libgnat/a-coboho.ads
@@ -70,7 +70,9 @@ package Ada.Containers.Bounded_Holders is
-- System.Storage_Unit; e.g. creating Holders from 5-bit objects won't
-- work.
- type Holder is private;
+ type Holder is private
+ with Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
function "=" (Left, Right : Holder) return Boolean;
diff --git a/gcc/ada/libgnat/a-cobove.ads b/gcc/ada/libgnat/a-cobove.ads
index 67c4419..5f3e1a7 100644
--- a/gcc/ada/libgnat/a-cobove.ads
+++ b/gcc/ada/libgnat/a-cobove.ads
@@ -63,12 +63,11 @@ package Ada.Containers.Bounded_Vectors is
Aggregate => (Empty => Empty,
Add_Unnamed => Append,
New_Indexed => New_Vector,
- Assign_Indexed => Replace_Element);
+ Assign_Indexed => Replace_Element),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
- pragma Preelaborable_Initialization (Vector);
-
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Vector : constant Vector;
diff --git a/gcc/ada/libgnat/a-cofove.ads b/gcc/ada/libgnat/a-cofove.ads
index a4ed7e5..6d3f486 100644
--- a/gcc/ada/libgnat/a-cofove.ads
+++ b/gcc/ada/libgnat/a-cofove.ads
@@ -50,6 +50,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
subtype Extended_Index is Index_Type'Base
diff --git a/gcc/ada/libgnat/a-except.adb b/gcc/ada/libgnat/a-except.adb
index c332afa..5933928 100644
--- a/gcc/ada/libgnat/a-except.adb
+++ b/gcc/ada/libgnat/a-except.adb
@@ -629,6 +629,96 @@ package body Ada.Exceptions is
pragma No_Return (Rcheck_CE_Invalid_Data_Ext);
pragma No_Return (Rcheck_CE_Range_Check_Ext);
+ -- Make all of these procedures callable from strub contexts.
+ -- These attributes are not visible to callers; they are made
+ -- visible in trans.c:build_raise_check.
+
+ pragma Machine_Attribute (Rcheck_CE_Access_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Null_Access_Parameter,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Discriminant_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Divide_By_Zero,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Explicit_Raise,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Index_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Invalid_Data,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Length_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Null_Exception_Id,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Null_Not_Allowed,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Overflow_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Partition_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Range_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Tag_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Access_Before_Elaboration,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Accessibility_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Address_Of_Intrinsic,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Aliased_Parameters,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_All_Guards_Closed,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Bad_Predicated_Generic_Type,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Build_In_Place_Mismatch,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Current_Task_In_Entry_Body,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Duplicated_Entry_Address,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Explicit_Raise,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Implicit_Return,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Misaligned_Address_Value,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Missing_Return,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Non_Transportable_Actual,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Overlaid_Controlled_Object,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Potentially_Blocking_Operation,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Stream_Operation_Not_Allowed,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Stubbed_Subprogram_Called,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Unchecked_Union_Restriction,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Finalize_Raised_Exception,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_SE_Empty_Storage_Pool,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_SE_Explicit_Raise,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_SE_Infinite_Recursion,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_SE_Object_Too_Large,
+ "strub", "callable");
+
+ pragma Machine_Attribute (Rcheck_CE_Access_Check_Ext,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Index_Check_Ext,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Invalid_Data_Ext,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Range_Check_Ext,
+ "strub", "callable");
+
---------------------------------------------
-- Reason Strings for Run-Time Check Calls --
---------------------------------------------
diff --git a/gcc/ada/libgnat/a-except.ads b/gcc/ada/libgnat/a-except.ads
index 2b27adb..1608e79 100644
--- a/gcc/ada/libgnat/a-except.ads
+++ b/gcc/ada/libgnat/a-except.ads
@@ -184,6 +184,15 @@ private
-- Raise_Exception_Always if it can determine this is the case. The Export
-- allows this routine to be accessed from Pure units.
+ -- Make these callable from strub contexts.
+ pragma Machine_Attribute (Raise_Exception_Always,
+ "strub", "callable");
+ pragma Machine_Attribute (Raise_Exception,
+ "strub", "callable");
+ -- This property should arguably be visible to callers, but let's
+ -- keep it private for now. In practice, it doesn't matter, since
+ -- it's only checked in the back end.
+
procedure Raise_From_Controlled_Operation (X : Exception_Occurrence);
pragma No_Return (Raise_From_Controlled_Operation);
pragma Export
diff --git a/gcc/ada/libgnat/a-strbou.adb b/gcc/ada/libgnat/a-strbou.adb
index 61b3d73..01a2002 100644
--- a/gcc/ada/libgnat/a-strbou.adb
+++ b/gcc/ada/libgnat/a-strbou.adb
@@ -29,7 +29,7 @@
-- --
------------------------------------------------------------------------------
-package body Ada.Strings.Bounded is
+package body Ada.Strings.Bounded with SPARK_Mode is
package body Generic_Bounded_Length is
diff --git a/gcc/ada/libgnat/a-strbou.ads b/gcc/ada/libgnat/a-strbou.ads
index f0cf7b2..e820184 100644
--- a/gcc/ada/libgnat/a-strbou.ads
+++ b/gcc/ada/libgnat/a-strbou.ads
@@ -33,25 +33,41 @@
-- --
------------------------------------------------------------------------------
--- Preconditions in this unit are meant for analysis only, not for run-time
--- checking, so that the expected exceptions are raised. This is enforced by
--- setting the corresponding assertion policy to Ignore.
-
-pragma Assertion_Policy (Pre => Ignore);
-
-with Ada.Strings.Maps;
+-- The language-defined package Strings.Bounded provides a generic package
+-- each of whose instances yields a private type Bounded_String and a set
+-- of operations. An object of a particular Bounded_String type represents
+-- a String whose low bound is 1 and whose length can vary conceptually
+-- between 0 and a maximum size established at the generic instantiation. The
+-- subprograms for fixed-length string handling are either overloaded directly
+-- for Bounded_String, or are modified as needed to reflect the variability in
+-- length. Additionally, since the Bounded_String type is private, appropriate
+-- constructor and selector operations are provided.
+
+with Ada.Strings.Maps; use type Ada.Strings.Maps.Character_Mapping_Function;
with Ada.Strings.Superbounded;
+with Ada.Strings.Search;
-package Ada.Strings.Bounded is
+package Ada.Strings.Bounded with SPARK_Mode is
pragma Preelaborate;
generic
Max : Positive;
-- Maximum length of a Bounded_String
- package Generic_Bounded_Length with
- Initial_Condition => Length (Null_Bounded_String) = 0
+ package Generic_Bounded_Length with SPARK_Mode,
+ Initial_Condition => Length (Null_Bounded_String) = 0,
+ Abstract_State => null
is
+ -- Preconditions in this unit are meant for analysis only, not for
+ -- run-time checking, so that the expected exceptions are raised. This
+ -- is enforced by setting the corresponding assertion policy to Ignore.
+ -- Postconditions and contract cases should not be executed at runtime
+ -- as well, in order not to slow down the execution of these functions.
+
+ pragma Assertion_Policy (Pre => Ignore,
+ Post => Ignore,
+ Contract_Cases => Ignore,
+ Ghost => Ignore);
Max_Length : constant Positive := Max;
@@ -59,11 +75,16 @@ package Ada.Strings.Bounded is
pragma Preelaborable_Initialization (Bounded_String);
Null_Bounded_String : constant Bounded_String;
+ -- Null_Bounded_String represents the null string. If an object of type
+ -- Bounded_String is not otherwise initialized, it will be initialized
+ -- to the same value as Null_Bounded_String.
subtype Length_Range is Natural range 0 .. Max_Length;
function Length (Source : Bounded_String) return Length_Range with
Global => null;
+ -- The Length function returns the length of the string represented by
+ -- Source.
--------------------------------------------------------
-- Conversion, Concatenation, and Selection Functions --
@@ -73,163 +94,466 @@ package Ada.Strings.Bounded is
(Source : String;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Source'Length > Max_Length then Drop /= Error),
- Post =>
- Length (To_Bounded_String'Result)
- = Natural'Min (Max_Length, Source'Length),
- Global => null;
+ Pre => (if Source'Length > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Source'Length <= Max_Length
+ =>
+ To_String (To_Bounded_String'Result) = Source,
+
+ Source'Length > Max_Length and then Drop = Left
+ =>
+ To_String (To_Bounded_String'Result) =
+ Source (Source'Last - Max_Length + 1 .. Source'Last),
+
+ others -- Drop = Right
+ =>
+ To_String (To_Bounded_String'Result) =
+ Source (Source'First .. Source'First - 1 + Max_Length));
+ -- If Source'Length <= Max_Length, then this function returns a
+ -- Bounded_String that represents Source. Otherwise, the effect
+ -- depends on the value of Drop:
+ --
+ -- * If Drop=Left, then the result is a Bounded_String that represents
+ -- the string comprising the rightmost Max_Length characters of
+ -- Source.
+ --
+ -- * If Drop=Right, then the result is a Bounded_String that represents
+ -- the string comprising the leftmost Max_Length characters of Source.
+ --
+ -- * If Drop=Error, then Strings.Length_Error is propagated.
function To_String (Source : Bounded_String) return String with
- Post => To_String'Result'Length = Length (Source),
Global => null;
+ -- To_String returns the String value with lower bound 1
+ -- represented by Source. If B is a Bounded_String, then
+ -- B = To_Bounded_String(To_String(B)).
procedure Set_Bounded_String
(Target : out Bounded_String;
Source : String;
Drop : Truncation := Error)
with
- Pre => (if Source'Length > Max_Length then Drop /= Error),
- Post => Length (Target) = Natural'Min (Max_Length, Source'Length),
- Global => null;
+ Pre => (if Source'Length > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Source'Length <= Max_Length
+ =>
+ To_String (Target) = Source,
+
+ Source'Length > Max_Length and then Drop = Left
+ =>
+ To_String (Target) =
+ Source (Source'Last - Max_Length + 1 .. Source'Last),
+
+ others -- Drop = Right
+ =>
+ To_String (Target) =
+ Source (Source'First .. Source'First - 1 + Max_Length));
pragma Ada_05 (Set_Bounded_String);
+ -- Equivalent to Target := To_Bounded_String (Source, Drop);
+
+ -- Each of the Append functions returns a Bounded_String obtained by
+ -- concatenating the string or character given or represented by one
+ -- of the parameters, with the string or character given or represented
+ -- by the other parameter, and applying To_Bounded_String to the
+ -- concatenation result string, with Drop as provided to the Append
+ -- function.
function Append
(Left : Bounded_String;
Right : Bounded_String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
+ Pre =>
(if Length (Left) > Max_Length - Length (Right)
then Drop /= Error),
- Post =>
- Length (Append'Result)
- = Natural'Min (Max_Length, Length (Left) + Length (Right)),
- Global => null;
+ Contract_Cases =>
+ (Length (Left) <= Max_Length - Length (Right)
+ =>
+ Length (Append'Result) = Length (Left) + Length (Right)
+ and then
+ Slice (Append'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Length (Right) > 0 then
+ Slice (Append'Result,
+ Length (Left) + 1, Length (Append'Result)) =
+ To_String (Right)),
+
+ Length (Left) > Max_Length - Length (Right)
+ and then Drop = Strings.Left
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ (if Length (Right) < Max_Length then
+ Slice (Append'Result, 1, Max_Length - Length (Right)) =
+ Slice (Left,
+ Length (Left) - Max_Length + Length (Right) + 1,
+ Length (Left)))
+ and then
+ Slice (Append'Result,
+ Max_Length - Length (Right) + 1, Max_Length) =
+ To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ Slice (Append'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Length (Left) < Max_Length then
+ Slice (Append'Result, Length (Left) + 1, Max_Length) =
+ Slice (Right, 1, Max_Length - Length (Left))));
function Append
(Left : Bounded_String;
Right : String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
+ Pre =>
(if Right'Length > Max_Length - Length (Left)
then Drop /= Error),
- Post =>
- Length (Append'Result)
- = Natural'Min (Max_Length, Length (Left) + Right'Length),
- Global => null;
-
+ Contract_Cases =>
+ (Length (Left) <= Max_Length - Right'Length
+ =>
+ Length (Append'Result) = Length (Left) + Right'Length
+ and then
+ Slice (Append'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Right'Length > 0 then
+ Slice (Append'Result,
+ Length (Left) + 1, Length (Append'Result)) =
+ Right),
+
+ Length (Left) > Max_Length - Right'Length
+ and then Drop = Strings.Left
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ (if Right'Length < Max_Length then
+
+ -- The result is the end of Left followed by Right
+
+ Slice (Append'Result, 1, Max_Length - Right'Length) =
+ Slice (Left,
+ Length (Left) - Max_Length + Right'Length + 1,
+ Length (Left))
+ and then
+ Slice (Append'Result,
+ Max_Length - Right'Length + 1, Max_Length) =
+ Right
+ else
+ -- The result is the last Max_Length characters of Right
+
+ To_String (Append'Result) =
+ Right (Right'Last - Max_Length + 1 .. Right'Last)),
+
+ others -- Drop = Right
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ Slice (Append'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Length (Left) < Max_Length then
+ Slice (Append'Result, Length (Left) + 1, Max_Length) =
+ Right (Right'First
+ .. Max_Length - Length (Left) - 1 + Right'First)));
function Append
(Left : String;
Right : Bounded_String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
+ Pre =>
(if Left'Length > Max_Length - Length (Right)
then Drop /= Error),
- Post =>
- Length (Append'Result)
- = Natural'Min (Max_Length, Left'Length + Length (Right)),
- Global => null;
+ Contract_Cases =>
+ (Left'Length <= Max_Length - Length (Right)
+ =>
+ Length (Append'Result) = Left'Length + Length (Right)
+ and then Slice (Append'Result, 1, Left'Length) = Left
+ and then
+ (if Length (Right) > 0 then
+ Slice (Append'Result,
+ Left'Length + 1, Length (Append'Result)) =
+ To_String (Right)),
+
+ Left'Length > Max_Length - Length (Right)
+ and then Drop = Strings.Left
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ (if Length (Right) < Max_Length then
+ Slice (Append'Result, 1, Max_Length - Length (Right)) =
+ Left (Left'Last - Max_Length + Length (Right) + 1
+ .. Left'Last))
+ and then
+ Slice (Append'Result,
+ Max_Length - Length (Right) + 1, Max_Length) =
+ To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ (if Left'Length < Max_Length then
+
+ -- The result is Left followed by the beginning of Right
+
+ Slice (Append'Result, 1, Left'Length) = Left
+ and then
+ Slice (Append'Result, Left'Length + 1, Max_Length) =
+ Slice (Right, 1, Max_Length - Left'Length)
+ else
+ -- The result is the first Max_Length characters of Left
+
+ To_String (Append'Result) =
+ Left (Left'First .. Max_Length - 1 + Left'First)));
function Append
(Left : Bounded_String;
Right : Character;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Length (Left) = Max_Length then Drop /= Error),
- Post =>
- Length (Append'Result)
- = Natural'Min (Max_Length, Length (Left) + 1),
- Global => null;
+ Pre => (if Length (Left) = Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Length (Left) < Max_Length
+ =>
+ Length (Append'Result) = Length (Left) + 1
+ and then
+ Slice (Append'Result, 1, Length (Left)) = To_String (Left)
+ and then Element (Append'Result, Length (Left) + 1) = Right,
+
+ Length (Left) = Max_Length and then Drop = Strings.Right
+ =>
+ Length (Append'Result) = Max_Length
+ and then To_String (Append'Result) = To_String (Left),
+
+ others -- Drop = Left
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ Slice (Append'Result, 1, Max_Length - 1) =
+ Slice (Left, 2, Max_Length)
+ and then Element (Append'Result, Max_Length) = Right);
function Append
(Left : Character;
Right : Bounded_String;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Length (Right) = Max_Length then Drop /= Error),
- Post =>
- Length (Append'Result)
- = Natural'Min (Max_Length, 1 + Length (Right)),
- Global => null;
+ Pre => (if Length (Right) = Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Length (Right) < Max_Length
+ =>
+ Length (Append'Result) = Length (Right) + 1
+ and then
+ Slice (Append'Result, 2, Length (Right) + 1) =
+ To_String (Right)
+ and then Element (Append'Result, 1) = Left,
+
+ Length (Right) = Max_Length and then Drop = Strings.Left
+ =>
+ Length (Append'Result) = Max_Length
+ and then To_String (Append'Result) = To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ Slice (Append'Result, 2, Max_Length) =
+ Slice (Right, 1, Max_Length - 1)
+ and then Element (Append'Result, 1) = Left);
+
+ -- Each of the procedures Append(Source, New_Item, Drop) has the same
+ -- effect as the corresponding assignment
+ -- Source := Append(Source, New_Item, Drop).
procedure Append
(Source : in out Bounded_String;
New_Item : Bounded_String;
Drop : Truncation := Error)
with
- Pre =>
+ Pre =>
(if Length (Source) > Max_Length - Length (New_Item)
then Drop /= Error),
- Post =>
- Length (Source)
- = Natural'Min (Max_Length, Length (Source)'Old + Length (New_Item)),
- Global => null;
+ Contract_Cases =>
+ (Length (Source) <= Max_Length - Length (New_Item)
+ =>
+ Length (Source) = Length (Source'Old) + Length (New_Item)
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ (if Length (New_Item) > 0 then
+ Slice (Source, Length (Source'Old) + 1, Length (Source)) =
+ To_String (New_Item)),
+
+ Length (Source) > Max_Length - Length (New_Item)
+ and then Drop = Left
+ =>
+ Length (Source) = Max_Length
+ and then
+ (if Length (New_Item) < Max_Length then
+ Slice (Source, 1, Max_Length - Length (New_Item)) =
+ Slice (Source'Old,
+ Length (Source'Old) - Max_Length + Length (New_Item)
+ + 1,
+ Length (Source'Old)))
+ and then
+ Slice (Source, Max_Length - Length (New_Item) + 1, Max_Length)
+ = To_String (New_Item),
+
+ others -- Drop = Right
+ =>
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ (if Length (Source'Old) < Max_Length then
+ Slice (Source, Length (Source'Old) + 1, Max_Length) =
+ Slice (New_Item, 1, Max_Length - Length (Source'Old))));
procedure Append
(Source : in out Bounded_String;
New_Item : String;
Drop : Truncation := Error)
with
- Pre =>
+ Pre =>
(if New_Item'Length > Max_Length - Length (Source)
then Drop /= Error),
- Post =>
- Length (Source)
- = Natural'Min (Max_Length, Length (Source)'Old + New_Item'Length),
- Global => null;
+ Contract_Cases =>
+ (Length (Source) <= Max_Length - New_Item'Length
+ =>
+ Length (Source) = Length (Source'Old) + New_Item'Length
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ (if New_Item'Length > 0 then
+ Slice (Source, Length (Source'Old) + 1, Length (Source)) =
+ New_Item),
+
+ Length (Source) > Max_Length - New_Item'Length
+ and then Drop = Left
+ =>
+ Length (Source) = Max_Length
+ and then
+ (if New_Item'Length < Max_Length then
+
+ -- The result is the end of Source followed by New_Item
+
+ Slice (Source, 1, Max_Length - New_Item'Length) =
+ Slice (Source'Old,
+ Length (Source'Old) - Max_Length + New_Item'Length + 1,
+ Length (Source'Old))
+ and then
+ Slice (Source,
+ Max_Length - New_Item'Length + 1, Max_Length) =
+ New_Item
+ else
+ -- The result is the last Max_Length characters of
+ -- New_Item.
+
+ To_String (Source) = New_Item
+ (New_Item'Last - Max_Length + 1 .. New_Item'Last)),
+
+ others -- Drop = Right
+ =>
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ (if Length (Source'Old) < Max_Length then
+ Slice (Source, Length (Source'Old) + 1, Max_Length) =
+ New_Item (New_Item'First
+ .. Max_Length - Length (Source'Old) - 1
+ + New_Item'First)));
procedure Append
(Source : in out Bounded_String;
New_Item : Character;
Drop : Truncation := Error)
with
- Pre => (if Length (Source) = Max_Length then Drop /= Error),
- Post =>
- Length (Source)
- = Natural'Min (Max_Length, Length (Source)'Old + 1),
- Global => null;
+ Pre => (if Length (Source) = Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Length (Source) < Max_Length
+ =>
+ Length (Source) = Length (Source'Old) + 1
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then Element (Source, Length (Source'Old) + 1) = New_Item,
+
+ Length (Source) = Max_Length and then Drop = Right
+ =>
+ Length (Source) = Max_Length
+ and then To_String (Source) = To_String (Source'Old),
+
+ others -- Drop = Left
+ =>
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Max_Length - 1) =
+ Slice (Source'Old, 2, Max_Length)
+ and then Element (Source, Max_Length) = New_Item);
+
+ -- Each of the "&" functions has the same effect as the corresponding
+ -- Append function, with Error as the Drop parameter.
function "&"
(Left : Bounded_String;
Right : Bounded_String) return Bounded_String
with
- Pre => Length (Left) <= Max_Length - Length (Right),
- Post => Length ("&"'Result) = Length (Left) + Length (Right),
- Global => null;
+ Pre => Length (Left) <= Max_Length - Length (Right),
+ Post => Length ("&"'Result) = Length (Left) + Length (Right)
+ and then Slice ("&"'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Length (Right) > 0 then
+ Slice ("&"'Result, Length (Left) + 1, Length ("&"'Result)) =
+ To_String (Right));
function "&"
(Left : Bounded_String;
Right : String) return Bounded_String
with
- Pre => Right'Length <= Max_Length - Length (Left),
- Post => Length ("&"'Result) = Length (Left) + Right'Length,
- Global => null;
+ Pre => Right'Length <= Max_Length - Length (Left),
+ Post => Length ("&"'Result) = Length (Left) + Right'Length
+ and then Slice ("&"'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Right'Length > 0 then
+ Slice ("&"'Result, Length (Left) + 1, Length ("&"'Result)) =
+ Right);
function "&"
(Left : String;
Right : Bounded_String) return Bounded_String
with
- Pre => Left'Length <= Max_Length - Length (Right),
- Post => Length ("&"'Result) = Left'Length + Length (Right),
- Global => null;
+ Pre => Left'Length <= Max_Length - Length (Right),
+ Post => Length ("&"'Result) = Left'Length + Length (Right)
+ and then Slice ("&"'Result, 1, Left'Length) = Left
+ and then
+ (if Length (Right) > 0 then
+ Slice ("&"'Result, Left'Length + 1, Length ("&"'Result)) =
+ To_String (Right));
function "&"
(Left : Bounded_String;
Right : Character) return Bounded_String
with
- Pre => Length (Left) < Max_Length,
- Post => Length ("&"'Result) = Length (Left) + 1,
- Global => null;
+ Pre => Length (Left) < Max_Length,
+ Post => Length ("&"'Result) = Length (Left) + 1
+ and then Slice ("&"'Result, 1, Length (Left)) = To_String (Left)
+ and then Element ("&"'Result, Length (Left) + 1) = Right;
function "&"
(Left : Character;
Right : Bounded_String) return Bounded_String
with
- Pre => Length (Right) < Max_Length,
- Post => Length ("&"'Result) = 1 + Length (Right),
- Global => null;
+ Pre => Length (Right) < Max_Length,
+ Post => Length ("&"'Result) = 1 + Length (Right)
+ and then Element ("&"'Result, 1) = Left
+ and then
+ Slice ("&"'Result, 2, Length ("&"'Result)) = To_String (Right);
function Element
(Source : Bounded_String;
@@ -237,6 +561,8 @@ package Ada.Strings.Bounded is
with
Pre => Index <= Length (Source),
Global => null;
+ -- Returns the character at position Index in the string represented by
+ -- Source; propagates Index_Error if Index > Length(Source).
procedure Replace_Element
(Source : in out Bounded_String;
@@ -244,8 +570,14 @@ package Ada.Strings.Bounded is
By : Character)
with
Pre => Index <= Length (Source),
- Post => Length (Source) = Length (Source)'Old,
+ Post => Length (Source) = Length (Source'Old)
+ and then (for all K in 1 .. Length (Source) =>
+ Element (Source, K) =
+ (if K = Index then By else Element (Source'Old, K))),
Global => null;
+ -- Updates Source such that the character at position Index in the
+ -- string represented by Source is By; propagates Index_Error if
+ -- Index > Length(Source).
function Slice
(Source : Bounded_String;
@@ -253,8 +585,11 @@ package Ada.Strings.Bounded is
High : Natural) return String
with
Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
- Post => Slice'Result'Length = Natural'Max (0, High - Low + 1),
Global => null;
+ -- Returns the slice at positions Low through High in the
+ -- string represented by Source; propagates Index_Error if
+ -- Low > Length(Source)+1 or High > Length(Source).
+ -- The bounds of the returned string are Low and High.
function Bounded_Slice
(Source : Bounded_String;
@@ -262,10 +597,12 @@ package Ada.Strings.Bounded is
High : Natural) return Bounded_String
with
Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
- Post =>
- Length (Bounded_Slice'Result) = Natural'Max (0, High - Low + 1),
+ Post => To_String (Bounded_Slice'Result) = Slice (Source, Low, High),
Global => null;
pragma Ada_05 (Bounded_Slice);
+ -- Returns the slice at positions Low through High in the string
+ -- represented by Source as a bounded string; propagates Index_Error
+ -- if Low > Length(Source)+1 or High > Length(Source).
procedure Bounded_Slice
(Source : Bounded_String;
@@ -274,112 +611,181 @@ package Ada.Strings.Bounded is
High : Natural)
with
Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
- Post => Length (Target) = Natural'Max (0, High - Low + 1),
+ Post => To_String (Target) = Slice (Source, Low, High),
Global => null;
pragma Ada_05 (Bounded_Slice);
+ -- Equivalent to Target := Bounded_Slice (Source, Low, High);
+
+ -- Each of the functions "=", "<", ">", "<=", and ">=" returns the same
+ -- result as the corresponding String operation applied to the String
+ -- values given or represented by the two parameters.
function "="
(Left : Bounded_String;
Right : Bounded_String) return Boolean
with
+ Post => "="'Result = (To_String (Left) = To_String (Right)),
Global => null;
function "="
(Left : Bounded_String;
Right : String) return Boolean
with
+ Post => "="'Result = (To_String (Left) = Right),
Global => null;
function "="
(Left : String;
Right : Bounded_String) return Boolean
with
+ Post => "="'Result = (Left = To_String (Right)),
Global => null;
function "<"
(Left : Bounded_String;
Right : Bounded_String) return Boolean
with
+ Post => "<"'Result = (To_String (Left) < To_String (Right)),
Global => null;
function "<"
(Left : Bounded_String;
Right : String) return Boolean
with
+ Post => "<"'Result = (To_String (Left) < Right),
Global => null;
function "<"
(Left : String;
Right : Bounded_String) return Boolean
with
+ Post => "<"'Result = (Left < To_String (Right)),
Global => null;
function "<="
(Left : Bounded_String;
Right : Bounded_String) return Boolean
with
+ Post => "<="'Result = (To_String (Left) <= To_String (Right)),
Global => null;
function "<="
(Left : Bounded_String;
Right : String) return Boolean
with
+ Post => "<="'Result = (To_String (Left) <= Right),
Global => null;
function "<="
(Left : String;
Right : Bounded_String) return Boolean
with
+ Post => "<="'Result = (Left <= To_String (Right)),
Global => null;
function ">"
(Left : Bounded_String;
Right : Bounded_String) return Boolean
with
+ Post => ">"'Result = (To_String (Left) > To_String (Right)),
Global => null;
function ">"
(Left : Bounded_String;
Right : String) return Boolean
with
+ Post => ">"'Result = (To_String (Left) > Right),
Global => null;
function ">"
(Left : String;
Right : Bounded_String) return Boolean
with
+ Post => ">"'Result = (Left > To_String (Right)),
Global => null;
function ">="
(Left : Bounded_String;
Right : Bounded_String) return Boolean
with
+ Post => ">="'Result = (To_String (Left) >= To_String (Right)),
Global => null;
function ">="
(Left : Bounded_String;
Right : String) return Boolean
with
+ Post => ">="'Result = (To_String (Left) >= Right),
Global => null;
function ">="
(Left : String;
Right : Bounded_String) return Boolean
with
+ Post => ">="'Result = (Left >= To_String (Right)),
Global => null;
----------------------
-- Search Functions --
----------------------
+ -- Each of the search subprograms (Index, Index_Non_Blank, Count,
+ -- Find_Token) has the same effect as the corresponding subprogram in
+ -- Strings.Fixed applied to the string represented by the Bounded_String
+ -- parameter.
+
function Index
(Source : Bounded_String;
Pattern : String;
Going : Direction := Forward;
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
with
- Pre => Pattern'Length /= 0,
- Global => null;
+ Pre => Pattern'Length > 0,
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Length (Source) = 0
+ =>
+ Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Length (Source) > 0
+ and then
+ (for some J in 1 .. Length (Source) - (Pattern'Length - 1) =>
+ Search.Match (To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Index'Result in 1 .. Length (Source) - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (To_String (Source), Pattern, Mapping, Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if (if Going = Forward
+ then J <= Index'Result - 1
+ else J - 1 in Index'Result
+ .. Length (Source) - Pattern'Length)
+ then not (Search.Match
+ (To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
+ Global => null;
function Index
(Source : Bounded_String;
@@ -387,8 +793,52 @@ package Ada.Strings.Bounded is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping_Function) return Natural
with
- Pre => Pattern'Length /= 0,
- Global => null;
+ Pre => Pattern'Length /= 0 and then Mapping /= null,
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Length (Source) = 0
+ =>
+ Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Length (Source) > 0
+ and then
+ (for some J in 1 .. Length (Source) - (Pattern'Length - 1) =>
+ Search.Match (To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Index'Result in 1 .. Length (Source) - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (To_String (Source), Pattern, Mapping, Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if (if Going = Forward
+ then J <= Index'Result - 1
+ else J - 1 in Index'Result
+ .. Length (Source) - Pattern'Length)
+ then not (Search.Match
+ (To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
+ Global => null;
function Index
(Source : Bounded_String;
@@ -396,7 +846,43 @@ package Ada.Strings.Bounded is
Test : Membership := Inside;
Going : Direction := Forward) return Natural
with
- Global => null;
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If no character of Source satisfies the property Test on Set,
+ -- then 0 is returned.
+
+ ((for all C of To_String (Source) =>
+ (Test = Inside) /= Maps.Is_In (C, Set))
+ =>
+ Index'Result = 0,
+
+ -- Otherwise, an index in the range of Source is returned
+
+ others
+ =>
+ -- The result is in the range of Source
+
+ Index'Result in 1 .. Length (Source)
+
+ -- The character at the returned index satisfies the property
+ -- Test on Set.
+
+ and then
+ (Test = Inside) =
+ Maps.Is_In (Element (Source, Index'Result), Set)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the property, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if J /= Index'Result
+ and then (J < Index'Result) = (Going = Forward)
+ then (Test = Inside)
+ /= Maps.Is_In (Element (Source, J), Set)))),
+ Global => null;
function Index
(Source : Bounded_String;
@@ -405,11 +891,60 @@ package Ada.Strings.Bounded is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
with
- Pre =>
- (if Length (Source) /= 0
- then From <= Length (Source))
- and then Pattern'Length /= 0,
- Global => null;
+ Pre =>
+ (if Length (Source) /= 0 then From <= Length (Source))
+ and then Pattern'Length /= 0,
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Length (Source) = 0
+ =>
+ Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Length (Source) > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Length (Source) else From)
+ - (Pattern'Length - 1) =>
+ Search.Match (To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Index'Result in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Length (Source) else From)
+ - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (To_String (Source), Pattern, Mapping, Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if (if Going = Forward
+ then J in From .. Index'Result - 1
+ else J - 1 in Index'Result
+ .. From - Pattern'Length)
+ then not (Search.Match
+ (To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
+ Global => null;
pragma Ada_05 (Index);
function Index
@@ -419,11 +954,61 @@ package Ada.Strings.Bounded is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping_Function) return Natural
with
- Pre =>
- (if Length (Source) /= 0
- then From <= Length (Source))
- and then Pattern'Length /= 0,
- Global => null;
+ Pre =>
+ (if Length (Source) /= 0 then From <= Length (Source))
+ and then Pattern'Length /= 0
+ and then Mapping /= null,
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Length (Source) = 0
+ =>
+ Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Length (Source) > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Length (Source) else From)
+ - (Pattern'Length - 1) =>
+ Search.Match (To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Index'Result in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Length (Source) else From)
+ - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (To_String (Source), Pattern, Mapping, Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if (if Going = Forward
+ then J in From .. Index'Result - 1
+ else J - 1 in Index'Result
+ .. From - Pattern'Length)
+ then not (Search.Match
+ (To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
+ Global => null;
pragma Ada_05 (Index);
function Index
@@ -433,23 +1018,147 @@ package Ada.Strings.Bounded is
Test : Membership := Inside;
Going : Direction := Forward) return Natural
with
- Pre => (if Length (Source) /= 0 then From <= Length (Source)),
- Global => null;
+ Pre =>
+ (if Length (Source) /= 0 then From <= Length (Source)),
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or no character of the considered
+ -- slice of Source satisfies the property Test on Set, then 0 is
+ -- returned.
+
+ (Length (Source) = 0
+ or else
+ (for all J in 1 .. Length (Source) =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ (Test = Inside) /= Maps.Is_In (Element (Source, J), Set)))
+ =>
+ Index'Result = 0,
+
+ -- Otherwise, an index in the considered range of Source is
+ -- returned.
+
+ others
+ =>
+ -- The result is in the considered range of Source
+
+ Index'Result in 1 .. Length (Source)
+ and then
+ (Index'Result = From
+ or else (Index'Result > From) = (Going = Forward))
+
+ -- The character at the returned index satisfies the property
+ -- Test on Set.
+
+ and then
+ (Test = Inside) =
+ Maps.Is_In (Element (Source, Index'Result), Set)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the property, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if J /= Index'Result
+ and then (J < Index'Result) = (Going = Forward)
+ and then (J = From
+ or else (J > From) = (Going = Forward))
+ then (Test = Inside)
+ /= Maps.Is_In (Element (Source, J), Set)))),
+ Global => null;
pragma Ada_05 (Index);
function Index_Non_Blank
(Source : Bounded_String;
Going : Direction := Forward) return Natural
with
- Global => null;
+ Post => Index_Non_Blank'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If all characters of Source are Space characters, then 0 is
+ -- returned.
+
+ ((for all C of To_String (Source) => C = ' ')
+ =>
+ Index_Non_Blank'Result = 0,
+
+ -- Otherwise, an index in the range of Source is returned
+
+ others
+ =>
+ -- The result is in the range of Source
+
+ Index_Non_Blank'Result in 1 .. Length (Source)
+
+ -- The character at the returned index is not a Space character
+
+ and then Element (Source, Index_Non_Blank'Result) /= ' '
+
+ -- The result is the smallest or largest index which is not a
+ -- Space character, respectively when Going = Forward and Going
+ -- = Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if J /= Index_Non_Blank'Result
+ and then
+ (J < Index_Non_Blank'Result) = (Going = Forward)
+ then Element (Source, J) = ' '))),
+ Global => null;
function Index_Non_Blank
(Source : Bounded_String;
From : Positive;
Going : Direction := Forward) return Natural
with
- Pre => (if Length (Source) /= 0 then From <= Length (Source)),
- Global => null;
+ Pre =>
+ (if Length (Source) /= 0 then From <= Length (Source)),
+ Post => Index_Non_Blank'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or all characters of the
+ -- considered slice of Source are Space characters, then 0
+ -- is returned.
+
+ (Length (Source) = 0
+ or else
+ (for all J in 1 .. Length (Source) =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ Element (Source, J) = ' '))
+ =>
+ Index_Non_Blank'Result = 0,
+
+ -- Otherwise, an index in the considered range of Source is
+ -- returned.
+
+ others
+ =>
+ -- The result is in the considered range of Source
+
+ Index_Non_Blank'Result in 1 .. Length (Source)
+ and then
+ (Index_Non_Blank'Result = From
+ or else
+ (Index_Non_Blank'Result > From) = (Going = Forward))
+
+ -- The character at the returned index is not a Space character
+
+ and then Element (Source, Index_Non_Blank'Result) /= ' '
+
+ -- The result is the smallest or largest index which isn't a
+ -- Space character, respectively when Going = Forward and Going
+ -- = Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if J /= Index_Non_Blank'Result
+ and then
+ (J < Index_Non_Blank'Result) = (Going = Forward)
+ and then (J = From
+ or else (J > From) = (Going = Forward))
+ then Element (Source, J) = ' '))),
+ Global => null;
pragma Ada_05 (Index_Non_Blank);
function Count
@@ -465,7 +1174,7 @@ package Ada.Strings.Bounded is
Pattern : String;
Mapping : Maps.Character_Mapping_Function) return Natural
with
- Pre => Pattern'Length /= 0,
+ Pre => Pattern'Length /= 0 and then Mapping /= null,
Global => null;
function Count
@@ -482,8 +1191,53 @@ package Ada.Strings.Bounded is
First : out Positive;
Last : out Natural)
with
- Pre => (if Length (Source) /= 0 then From <= Length (Source)),
- Global => null;
+ Pre =>
+ (if Length (Source) /= 0 then From <= Length (Source)),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or if no character of the
+ -- considered slice of Source satisfies the property Test on
+ -- Set, then First is set to From and Last is set to 0.
+
+ (Length (Source) = 0
+ or else
+ (for all J in From .. Length (Source) =>
+ (Test = Inside) /= Maps.Is_In (Element (Source, J), Set))
+ =>
+ First = From and then Last = 0,
+
+ -- Otherwise, First and Last are set to valid indexes
+
+ others
+ =>
+ -- First and Last are in the considered range of Source
+
+ First in From .. Length (Source)
+ and then Last in First .. Length (Source)
+
+ -- No character between From and First satisfies the property
+ -- Test on Set.
+
+ and then
+ (for all J in From .. First - 1 =>
+ (Test = Inside) /= Maps.Is_In (Element (Source, J), Set))
+
+ -- All characters between First and Last satisfy the property
+ -- Test on Set.
+
+ and then
+ (for all J in First .. Last =>
+ (Test = Inside) = Maps.Is_In (Element (Source, J), Set))
+
+ -- If Last is not Source'Last, then the character at position
+ -- Last + 1 does not satify the property Test on Set.
+
+ and then
+ (if Last < Length (Source)
+ then
+ (Test = Inside)
+ /= Maps.Is_In (Element (Source, Last + 1), Set))),
+ Global => null;
pragma Ada_2012 (Find_Token);
procedure Find_Token
@@ -493,44 +1247,127 @@ package Ada.Strings.Bounded is
First : out Positive;
Last : out Natural)
with
- Global => null;
+ Contract_Cases =>
+
+ -- If Source is the empty string, or if no character of the
+ -- considered slice of Source satisfies the property Test on
+ -- Set, then First is set to 1 and Last is set to 0.
+
+ (Length (Source) = 0
+ or else
+ (for all J in 1 .. Length (Source) =>
+ (Test = Inside) /= Maps.Is_In (Element (Source, J), Set))
+ =>
+ First = 1 and then Last = 0,
+
+ -- Otherwise, First and Last are set to valid indexes
+
+ others
+ =>
+ -- First and Last are in the considered range of Source
+
+ First in 1 .. Length (Source)
+ and then Last in First .. Length (Source)
+
+ -- No character between 1 and First satisfies the property Test
+ -- on Set.
+
+ and then
+ (for all J in 1 .. First - 1 =>
+ (Test = Inside) /= Maps.Is_In (Element (Source, J), Set))
+
+ -- All characters between First and Last satisfy the property
+ -- Test on Set.
+
+ and then
+ (for all J in First .. Last =>
+ (Test = Inside) = Maps.Is_In (Element (Source, J), Set))
+
+ -- If Last is not Source'Last, then the character at position
+ -- Last + 1 does not satify the property Test on Set.
+
+ and then
+ (if Last < Length (Source)
+ then
+ (Test = Inside)
+ /= Maps.Is_In (Element (Source, Last + 1), Set))),
+ Global => null;
------------------------------------
-- String Translation Subprograms --
------------------------------------
+ -- Each of the Translate subprograms, when applied to a Bounded_String,
+ -- has an analogous effect to the corresponding subprogram in
+ -- Strings.Fixed. For the Translate function, the translation is applied
+ -- to the string represented by the Bounded_String parameter, and the
+ -- result is converted (via To_Bounded_String) to a Bounded_String. For
+ -- the Translate procedure, the string represented by the Bounded_String
+ -- parameter after the translation is given by the Translate function
+ -- for fixed-length strings applied to the string represented by the
+ -- original value of the parameter.
+
function Translate
(Source : Bounded_String;
Mapping : Maps.Character_Mapping) return Bounded_String
with
- Post => Length (Translate'Result) = Length (Source),
+ Post => Length (Translate'Result) = Length (Source)
+ and then
+ (for all K in 1 .. Length (Source) =>
+ Element (Translate'Result, K) =
+ Ada.Strings.Maps.Value (Mapping, Element (Source, K))),
Global => null;
procedure Translate
(Source : in out Bounded_String;
Mapping : Maps.Character_Mapping)
with
- Post => Length (Source) = Length (Source)'Old,
+ Post => Length (Source) = Length (Source'Old)
+ and then
+ (for all K in 1 .. Length (Source) =>
+ Element (Source, K) =
+ Ada.Strings.Maps.Value (Mapping, Element (Source'Old, K))),
Global => null;
function Translate
(Source : Bounded_String;
Mapping : Maps.Character_Mapping_Function) return Bounded_String
with
- Post => Length (Translate'Result) = Length (Source),
+ Pre => Mapping /= null,
+ Post => Length (Translate'Result) = Length (Source)
+ and then
+ (for all K in 1 .. Length (Source) =>
+ Element (Translate'Result, K) = Mapping (Element (Source, K))),
Global => null;
procedure Translate
(Source : in out Bounded_String;
Mapping : Maps.Character_Mapping_Function)
with
- Post => Length (Source) = Length (Source)'Old,
+ Pre => Mapping /= null,
+ Post => Length (Source) = Length (Source'Old)
+ and then
+ (for all K in 1 .. Length (Source) =>
+ Element (Source, K) = Mapping (Element (Source'Old, K))),
Global => null;
---------------------------------------
-- String Transformation Subprograms --
---------------------------------------
+ -- Each of the transformation subprograms (Replace_Slice, Insert,
+ -- Overwrite, Delete), selector subprograms (Trim, Head, Tail), and
+ -- constructor functions ("*") has an effect based on its corresponding
+ -- subprogram in Strings.Fixed, and Replicate is based on Fixed."*".
+ -- In the case of a function, the corresponding fixed-length string
+ -- subprogram is applied to the string represented by the Bounded_String
+ -- parameter. To_Bounded_String is applied the result string, with Drop
+ -- (or Error in the case of Generic_Bounded_Length."*") determining
+ -- the effect when the string length exceeds Max_Length. In
+ -- the case of a procedure, the corresponding function in
+ -- Strings.Bounded.Generic_Bounded_Length is applied, with the
+ -- result assigned into the Source parameter.
+
function Replace_Slice
(Source : Bounded_String;
Low : Positive;
@@ -541,23 +1378,127 @@ package Ada.Strings.Bounded is
Pre =>
Low - 1 <= Length (Source)
and then
- (if Drop = Error
- then (if High >= Low
- then Low - 1
- <= Max_Length - By'Length
- - Natural'Max (Length (Source) - High, 0)
- else Length (Source) <= Max_Length - By'Length)),
+ (if Drop = Error
+ then (if High >= Low
+ then Low - 1
+ <= Max_Length - By'Length
+ - Integer'Max (Length (Source) - High, 0)
+ else Length (Source) <= Max_Length - By'Length)),
Contract_Cases =>
- (High >= Low =>
- Length (Replace_Slice'Result)
- = Natural'Min
- (Max_Length,
- Low - 1 + By'Length + Natural'Max (Length (Source) - High,
- 0)),
- others =>
- Length (Replace_Slice'Result)
- = Natural'Min (Max_Length, Length (Source) + By'Length)),
- Global => null;
+ (Low - 1 <= Max_Length - By'Length
+ - Integer'Max (Length (Source) - Integer'Max (High, Low - 1), 0)
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ -- Note that if High < Low, the insertion is done before Low,
+ -- so in all cases the starting position of the slice of Source
+ -- remaining after the replaced Slice is Integer'Max (High + 1,
+ -- Low).
+
+ Length (Replace_Slice'Result) = Low - 1 + By'Length
+ + Integer'Max (Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then
+ Slice (Replace_Slice'Result, 1, Low - 1) =
+ Slice (Source, 1, Low - 1)
+ and then
+ Slice (Replace_Slice'Result, Low, Low - 1 + By'Length) = By
+ and then
+ (if Integer'Max (High, Low - 1) < Length (Source) then
+ Slice (Replace_Slice'Result,
+ Low + By'Length, Length (Replace_Slice'Result)) =
+ Slice (Source,
+ Integer'Max (High + 1, Low), Length (Source))),
+
+ Low - 1 > Max_Length - By'Length
+ - Integer'Max (Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then Drop = Left
+ =>
+ -- Final_Slice is the length of the slice of Source remaining
+ -- after the replaced part.
+ (declare
+ Final_Slice : constant Natural :=
+ Integer'Max
+ (Length (Source) - Integer'Max (High, Low - 1), 0);
+ begin
+ -- The result is of maximal length and ends by the last
+ -- Final_Slice characters of Source.
+
+ Length (Replace_Slice'Result) = Max_Length
+ and then
+ (if Final_Slice > 0 then
+ Slice (Replace_Slice'Result,
+ Max_Length - Final_Slice + 1, Max_Length) =
+ Slice (Source,
+ Integer'Max (High + 1, Low), Length (Source)))
+
+ -- Depending on when we reach Max_Length, either the first
+ -- part of Source is fully dropped and By is partly dropped,
+ -- or By is fully added and the first part of Source is
+ -- partly dropped.
+
+ and then
+ (if Max_Length - Final_Slice - By'Length <= 0 then
+
+ -- The first (possibly zero) characters of By are
+ -- dropped.
+
+ (if Final_Slice < Max_Length then
+ Slice (Replace_Slice'Result,
+ 1, Max_Length - Final_Slice) =
+ By (By'Last - Max_Length + Final_Slice + 1
+ .. By'Last))
+
+ else -- By is added to the result
+
+ Slice (Replace_Slice'Result,
+ Max_Length - Final_Slice - By'Length + 1,
+ Max_Length - Final_Slice) =
+ By
+
+ -- The first characters of Source (1 .. Low - 1) are
+ -- dropped.
+
+ and then Slice (Replace_Slice'Result, 1,
+ Max_Length - Final_Slice - By'Length) =
+ Slice (Source,
+ Low - Max_Length + Final_Slice + By'Length,
+ Low - 1))),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first Low -
+ -- 1 characters of Source.
+
+ Length (Replace_Slice'Result) = Max_Length
+ and then
+ Slice (Replace_Slice'Result, 1, Low - 1) =
+ Slice (Source, 1, Low - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and By is partly dropped, or By
+ -- is fully added and the last part of Source is partly
+ -- dropped.
+
+ and then
+ (if Low - 1 >= Max_Length - By'Length then
+
+ -- The last characters of By are dropped
+
+ Slice (Replace_Slice'Result, Low, Max_Length) =
+ By (By'First .. Max_Length - Low + By'First)
+
+ else -- By is fully added
+
+ Slice (Replace_Slice'Result, Low, Low + By'Length - 1) = By
+
+ -- Then Source starting from Integer'Max (High + 1, Low)
+ -- is added but the last characters are dropped.
+
+ and then Slice (Replace_Slice'Result,
+ Low + By'Length, Max_Length) =
+ Slice (Source, Integer'Max (High + 1, Low),
+ Integer'Max (High + 1, Low) +
+ (Max_Length - Low - By'Length))));
procedure Replace_Slice
(Source : in out Bounded_String;
@@ -569,23 +1510,119 @@ package Ada.Strings.Bounded is
Pre =>
Low - 1 <= Length (Source)
and then
- (if Drop = Error
- then (if High >= Low
- then Low - 1
- <= Max_Length - By'Length
- - Natural'Max (Length (Source) - High, 0)
- else Length (Source) <= Max_Length - By'Length)),
+ (if Drop = Error
+ then (if High >= Low
+ then Low - 1
+ <= Max_Length - By'Length
+ - Natural'Max (Length (Source) - High, 0)
+ else Length (Source) <= Max_Length - By'Length)),
Contract_Cases =>
- (High >= Low =>
- Length (Source)
- = Natural'Min
- (Max_Length,
- Low - 1 + By'Length + Natural'Max (Length (Source)'Old - High,
- 0)),
- others =>
- Length (Source)
- = Natural'Min (Max_Length, Length (Source)'Old + By'Length)),
- Global => null;
+ (Low - 1 <= Max_Length - By'Length
+ - Integer'Max (Length (Source) - Integer'Max (High, Low - 1), 0)
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ -- Note that if High < Low, the insertion is done before Low,
+ -- so in all cases the starting position of the slice of Source
+ -- remaining after the replaced Slice is Integer'Max (High + 1,
+ -- Low).
+
+ Length (Source) = Low - 1 + By'Length + Integer'Max
+ (Length (Source'Old) - Integer'Max (High, Low - 1), 0)
+ and then
+ Slice (Source, 1, Low - 1) = Slice (Source'Old, 1, Low - 1)
+ and then Slice (Source, Low, Low - 1 + By'Length) = By
+ and then
+ (if Integer'Max (High, Low - 1) < Length (Source'Old) then
+ Slice (Source, Low + By'Length, Length (Source)) =
+ Slice (Source'Old,
+ Integer'Max (High + 1, Low), Length (Source'Old))),
+
+ Low - 1 > Max_Length - By'Length
+ - Integer'Max (Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then Drop = Left
+ =>
+ -- Final_Slice is the length of the slice of Source remaining
+ -- after the replaced part.
+ (declare
+ Final_Slice : constant Integer :=
+ Integer'Max (0,
+ Length (Source'Old) - Integer'Max (High, Low - 1));
+ begin
+ -- The result is of maximal length and ends by the last
+ -- Final_Slice characters of Source.
+
+ Length (Source) = Max_Length
+ and then
+ (if Final_Slice > 0 then
+ Slice (Source,
+ Max_Length - Final_Slice + 1, Max_Length) =
+ Slice (Source'Old,
+ Integer'Max (High + 1, Low), Length (Source'Old)))
+
+ -- Depending on when we reach Max_Length, either the first
+ -- part of Source is fully dropped and By is partly dropped,
+ -- or By is fully added and the first part of Source is
+ -- partly dropped.
+
+ and then
+ (if Max_Length - Final_Slice - By'Length <= 0 then
+
+ -- The first characters of By are dropped
+
+ (if Final_Slice < Max_Length then
+ Slice (Source, 1, Max_Length - Final_Slice) =
+ By (By'Last - Max_Length + Final_Slice + 1
+ .. By'Last))
+
+ else -- By is added to the result
+
+ Slice (Source,
+ Max_Length - Final_Slice - By'Length + 1,
+ Max_Length - Final_Slice) = By
+
+ -- The first characters of Source (1 .. Low - 1) are
+ -- dropped.
+
+ and then Slice (Source, 1,
+ Max_Length - Final_Slice - By'Length) =
+ Slice (Source'Old,
+ Low - Max_Length + Final_Slice + By'Length,
+ Low - 1))),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first Low -
+ -- 1 characters of Source.
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Low - 1) = Slice (Source'Old, 1, Low - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and By is partly dropped, or By
+ -- is fully added and the last part of Source is partly
+ -- dropped.
+
+ and then
+ (if Low - 1 >= Max_Length - By'Length then
+
+ -- The last characters of By are dropped
+
+ Slice (Source, Low, Max_Length) =
+ By (By'First .. Max_Length - Low + By'First)
+
+ else -- By is fully added
+
+ Slice (Source, Low, Low + By'Length - 1) = By
+
+ -- Then Source starting from Natural'Max (High + 1, Low)
+ -- is added but the last characters are dropped.
+
+ and then Slice (Source, Low + By'Length, Max_Length) =
+ Slice (Source'Old, Integer'Max (High + 1, Low),
+ Integer'Max (High + 1, Low) +
+ (Max_Length - Low - By'Length))));
function Insert
(Source : Bounded_String;
@@ -593,14 +1630,113 @@ package Ada.Strings.Bounded is
New_Item : String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
+ Pre =>
Before - 1 <= Length (Source)
and then (if New_Item'Length > Max_Length - Length (Source)
then Drop /= Error),
- Post =>
- Length (Insert'Result)
- = Natural'Min (Max_Length, Length (Source) + New_Item'Length),
- Global => null;
+ Contract_Cases =>
+ (Length (Source) <= Max_Length - New_Item'Length
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ Length (Insert'Result) = Length (Source) + New_Item'Length
+ and then
+ Slice (Insert'Result, 1, Before - 1) =
+ Slice (Source, 1, Before - 1)
+ and then
+ Slice (Insert'Result, Before, Before - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Before <= Length (Source) then
+ Slice (Insert'Result,
+ Before + New_Item'Length, Length (Insert'Result)) =
+ Slice (Source, Before, Length (Source))),
+
+ Length (Source) > Max_Length - New_Item'Length and then Drop = Left
+ =>
+ -- The result is of maximal length and ends by the last
+ -- characters of Source.
+
+ Length (Insert'Result) = Max_Length
+ and then
+ (if Before <= Length (Source) then
+ Slice (Insert'Result,
+ Max_Length - Length (Source) + Before, Max_Length) =
+ Slice (Source, Before, Length (Source)))
+
+ -- Depending on when we reach Max_Length, either the first part
+ -- of Source is fully dropped and New_Item is partly dropped,
+ -- or New_Item is fully added and the first part of Source is
+ -- partly dropped.
+
+ and then
+ (if Max_Length - Length (Source) - 1 + Before
+ < New_Item'Length
+ then
+ -- The first characters of New_Item are dropped
+
+ (if Length (Source) - Before + 1 < Max_Length then
+ Slice (Insert'Result,
+ 1, Max_Length - Length (Source) - 1 + Before) =
+ New_Item
+ (New_Item'Last - Max_Length + Length (Source)
+ - Before + 2
+ .. New_Item'Last))
+
+ else -- New_Item is added to the result
+
+ Slice (Insert'Result,
+ Max_Length - Length (Source) - New_Item'Length + Before,
+ Max_Length - Length (Source) - 1 + Before) = New_Item
+
+ -- The first characters of Source (1 .. Before - 1) are
+ -- dropped.
+
+ and then Slice (Insert'Result,
+ 1, Max_Length - Length (Source) - New_Item'Length
+ - 1 + Before) =
+ Slice (Source,
+ Length (Source) - Max_Length + New_Item'Length
+ + 1,
+ Before - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Length (Insert'Result) = Max_Length
+ and then
+ Slice (Insert'Result, 1, Before - 1) =
+ Slice (Source, 1, Before - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and New_Item is partly dropped,
+ -- or New_Item is fully added and the last part of Source is
+ -- partly dropped.
+
+ and then
+ (if Before - 1 >= Max_Length - New_Item'Length then
+
+ -- The last characters of New_Item are dropped
+
+ Slice (Insert'Result, Before, Max_Length) =
+ New_Item (New_Item'First
+ .. Max_Length - Before + New_Item'First)
+
+ else -- New_Item is fully added
+
+ Slice (Insert'Result,
+ Before, Before + New_Item'Length - 1) =
+ New_Item
+
+ -- Then Source starting from Before is added but the
+ -- last characters are dropped.
+
+ and then Slice (Insert'Result,
+ Before + New_Item'Length, Max_Length) =
+ Slice (Source,
+ Before, Max_Length - New_Item'Length)));
procedure Insert
(Source : in out Bounded_String;
@@ -608,14 +1744,112 @@ package Ada.Strings.Bounded is
New_Item : String;
Drop : Truncation := Error)
with
- Pre =>
+ Pre =>
Before - 1 <= Length (Source)
and then (if New_Item'Length > Max_Length - Length (Source)
then Drop /= Error),
- Post =>
- Length (Source)
- = Natural'Min (Max_Length, Length (Source)'Old + New_Item'Length),
- Global => null;
+ Contract_Cases =>
+ (Length (Source) <= Max_Length - New_Item'Length
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ Length (Source) = Length (Source'Old) + New_Item'Length
+ and then
+ Slice (Source, 1, Before - 1) =
+ Slice (Source'Old, 1, Before - 1)
+ and then
+ Slice (Source, Before, Before - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Before <= Length (Source'Old) then
+ Slice (Source, Before + New_Item'Length, Length (Source)) =
+ Slice (Source'Old, Before, Length (Source'Old))),
+
+ Length (Source) > Max_Length - New_Item'Length and then Drop = Left
+ =>
+ -- The result is of maximal length and ends by the last
+ -- characters of Source.
+
+ Length (Source) = Max_Length
+ and then
+ (if Before <= Length (Source'Old) then
+ Slice (Source,
+ Max_Length - Length (Source'Old) + Before, Max_Length) =
+ Slice (Source'Old, Before, Length (Source'Old)))
+
+ -- Depending on when we reach Max_Length, either the first part
+ -- of Source is fully dropped and New_Item is partly dropped,
+ -- or New_Item is fully added and the first part of Source is
+ -- partly dropped.
+
+ and then
+ (if Max_Length - Length (Source'Old) - 1 + Before
+ < New_Item'Length
+ then
+ -- The first characters of New_Item are dropped
+
+ (if Length (Source'Old) - Before + 1 < Max_Length then
+ Slice (Source,
+ 1, Max_Length - Length (Source'Old) - 1 + Before) =
+ New_Item
+ (New_Item'Last - Max_Length + Length (Source'Old)
+ - Before + 2
+ .. New_Item'Last))
+
+ else -- New_Item is added to the result
+
+ Slice (Source,
+ Max_Length - Length (Source'Old) - New_Item'Length
+ + Before,
+ Max_Length - Length (Source'Old) - 1 + Before) = New_Item
+
+ -- The first characters of Source (1 .. Before - 1) are
+ -- dropped.
+
+ and then Slice (Source, 1,
+ Max_Length - Length (Source'Old) - New_Item'Length
+ - 1 + Before) =
+ Slice (Source'Old,
+ Length (Source'Old)
+ - Max_Length + New_Item'Length + 1,
+ Before - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Before - 1) =
+ Slice (Source'Old, 1, Before - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and New_Item is partly dropped,
+ -- or New_Item is fully added and the last part of Source is
+ -- partly dropped.
+
+ and then
+ (if Before - 1 >= Max_Length - New_Item'Length then
+
+ -- The last characters of New_Item are dropped
+
+ Slice (Source, Before, Max_Length) =
+ New_Item (New_Item'First
+ .. Max_Length - Before + New_Item'First)
+
+ else -- New_Item is fully added
+
+ Slice (Source, Before, Before + New_Item'Length - 1) =
+ New_Item
+
+ -- Then Source starting from Before is added but the
+ -- last characters are dropped.
+
+ and then
+ Slice (Source, Before + New_Item'Length, Max_Length) =
+ Slice (Source'Old,
+ Before, Max_Length - New_Item'Length)));
function Overwrite
(Source : Bounded_String;
@@ -623,16 +1857,85 @@ package Ada.Strings.Bounded is
New_Item : String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
+ Pre =>
Position - 1 <= Length (Source)
and then (if New_Item'Length > Max_Length - (Position - 1)
then Drop /= Error),
- Post =>
- Length (Overwrite'Result)
- = Natural'Max
- (Length (Source),
- Natural'Min (Max_Length, Position - 1 + New_Item'Length)),
- Global => null;
+ Contract_Cases =>
+ (Position - 1 <= Max_Length - New_Item'Length
+ =>
+ -- The length is unchanged, unless New_Item overwrites further
+ -- than the end of Source. In this contract case, we suppose
+ -- New_Item doesn't overwrite further than Max_Length.
+
+ Length (Overwrite'Result) =
+ Integer'Max (Length (Source), Position - 1 + New_Item'Length)
+ and then
+ Slice (Overwrite'Result, 1, Position - 1) =
+ Slice (Source, 1, Position - 1)
+ and then Slice (Overwrite'Result,
+ Position, Position - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Position - 1 + New_Item'Length < Length (Source) then
+
+ -- There are some unchanged characters of Source remaining
+ -- after New_Item.
+
+ Slice (Overwrite'Result,
+ Position + New_Item'Length, Length (Source)) =
+ Slice (Source,
+ Position + New_Item'Length, Length (Source))),
+
+ Position - 1 > Max_Length - New_Item'Length and then Drop = Left
+ =>
+ Length (Overwrite'Result) = Max_Length
+
+ -- If a part of the result has to be dropped, it means New_Item
+ -- is overwriting further than the end of Source. Thus the
+ -- result is necessarily ending by New_Item. However, we don't
+ -- know whether New_Item covers all Max_Length characters or
+ -- some characters of Source are remaining at the left.
+
+ and then
+ (if New_Item'Length > Max_Length then
+
+ -- New_Item covers all Max_Length characters
+
+ To_String (Overwrite'Result) =
+ New_Item
+ (New_Item'Last - Max_Length + 1 .. New_Item'Last)
+ else
+ -- New_Item fully appears at the end
+
+ Slice (Overwrite'Result,
+ Max_Length - New_Item'Length + 1, Max_Length) =
+ New_Item
+
+ -- The left of Source is cut
+
+ and then
+ Slice (Overwrite'Result,
+ 1, Max_Length - New_Item'Length) =
+ Slice (Source,
+ Position - Max_Length + New_Item'Length,
+ Position - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Length (Overwrite'Result) = Max_Length
+ and then
+ Slice (Overwrite'Result, 1, Position - 1) =
+ Slice (Source, 1, Position - 1)
+
+ -- Then New_Item is written until Max_Length
+
+ and then Slice (Overwrite'Result, Position, Max_Length) =
+ New_Item
+ (New_Item'First .. Max_Length - Position + New_Item'First));
procedure Overwrite
(Source : in out Bounded_String;
@@ -640,16 +1943,84 @@ package Ada.Strings.Bounded is
New_Item : String;
Drop : Truncation := Error)
with
- Pre =>
+ Pre =>
Position - 1 <= Length (Source)
and then (if New_Item'Length > Max_Length - (Position - 1)
then Drop /= Error),
- Post =>
- Length (Source)
- = Natural'Max
- (Length (Source)'Old,
- Natural'Min (Max_Length, Position - 1 + New_Item'Length)),
- Global => null;
+ Contract_Cases =>
+ (Position - 1 <= Max_Length - New_Item'Length
+ =>
+ -- The length of Source is unchanged, unless New_Item overwrites
+ -- further than the end of Source. In this contract case, we
+ -- suppose New_Item doesn't overwrite further than Max_Length.
+
+ Length (Source) = Integer'Max
+ (Length (Source'Old), Position - 1 + New_Item'Length)
+ and then
+ Slice (Source, 1, Position - 1) =
+ Slice (Source'Old, 1, Position - 1)
+ and then Slice (Source,
+ Position, Position - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Position - 1 + New_Item'Length < Length (Source'Old) then
+
+ -- There are some unchanged characters of Source remaining
+ -- after New_Item.
+
+ Slice (Source,
+ Position + New_Item'Length, Length (Source'Old)) =
+ Slice (Source'Old,
+ Position + New_Item'Length, Length (Source'Old))),
+
+ Position - 1 > Max_Length - New_Item'Length and then Drop = Left
+ =>
+ Length (Source) = Max_Length
+
+ -- If a part of the result has to be dropped, it means New_Item
+ -- is overwriting further than the end of Source. Thus the
+ -- result is necessarily ending by New_Item. However, we don't
+ -- know whether New_Item covers all Max_Length characters or
+ -- some characters of Source are remaining at the left.
+
+ and then
+ (if New_Item'Length > Max_Length then
+
+ -- New_Item covers all Max_Length characters
+
+ To_String (Source) =
+ New_Item
+ (New_Item'Last - Max_Length + 1 .. New_Item'Last)
+ else
+ -- New_Item fully appears at the end
+
+ Slice (Source,
+ Max_Length - New_Item'Length + 1, Max_Length) =
+ New_Item
+
+ -- The left of Source is cut
+
+ and then
+ Slice (Source, 1, Max_Length - New_Item'Length) =
+ Slice (Source'Old,
+ Position - Max_Length + New_Item'Length,
+ Position - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Position - 1) =
+ Slice (Source'Old, 1, Position - 1)
+
+ -- New_Item is written until Max_Length
+
+ and then Slice (Source, Position, Max_Length) =
+ New_Item
+ (New_Item'First .. Max_Length - Position + New_Item'First));
function Delete
(Source : Bounded_String;
@@ -657,13 +2028,20 @@ package Ada.Strings.Bounded is
Through : Natural) return Bounded_String
with
Pre =>
- (if Through <= From then From - 1 <= Length (Source)),
+ (if Through >= From then From - 1 <= Length (Source)),
Contract_Cases =>
(Through >= From =>
- Length (Delete'Result) = Length (Source) - (Through - From + 1),
+ Length (Delete'Result) =
+ From - 1 + Natural'Max (Length (Source) - Through, 0)
+ and then
+ Slice (Delete'Result, 1, From - 1) =
+ Slice (Source, 1, From - 1)
+ and then
+ (if Through < Length (Source) then
+ Slice (Delete'Result, From, Length (Delete'Result)) =
+ Slice (Source, Through + 1, Length (Source))),
others =>
- Length (Delete'Result) = Length (Source)),
-
+ Delete'Result = Source),
Global => null;
procedure Delete
@@ -672,12 +2050,19 @@ package Ada.Strings.Bounded is
Through : Natural)
with
Pre =>
- (if Through <= From then From - 1 <= Length (Source)),
+ (if Through >= From then From - 1 <= Length (Source)),
Contract_Cases =>
(Through >= From =>
- Length (Source) = Length (Source)'Old - (Through - From + 1),
+ Length (Source) =
+ From - 1 + Natural'Max (Length (Source'Old) - Through, 0)
+ and then
+ Slice (Source, 1, From - 1) = Slice (Source'Old, 1, From - 1)
+ and then
+ (if Through < Length (Source) then
+ Slice (Source, From, Length (Source)) =
+ Slice (Source'Old, Through + 1, Length (Source'Old))),
others =>
- Length (Source) = Length (Source)'Old),
+ Source = Source'Old),
Global => null;
---------------------------------
@@ -688,31 +2073,111 @@ package Ada.Strings.Bounded is
(Source : Bounded_String;
Side : Trim_End) return Bounded_String
with
- Post => Length (Trim'Result) <= Length (Source),
- Global => null;
+ Contract_Cases =>
+ -- If all characters in Source are Space, the returned string is
+ -- empty.
+
+ ((for all C of To_String (Source) => C = ' ')
+ =>
+ Length (Trim'Result) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ (if Side = Right then 1
+ else Index_Non_Blank (Source, Forward));
+ High : constant Positive :=
+ (if Side = Left then Length (Source)
+ else Index_Non_Blank (Source, Backward));
+ begin
+ To_String (Trim'Result) = Slice (Source, Low, High))),
+ Global => null;
procedure Trim
(Source : in out Bounded_String;
Side : Trim_End)
with
- Post => Length (Source) <= Length (Source)'Old,
- Global => null;
+ Contract_Cases =>
+ -- If all characters in Source are Space, the returned string is
+ -- empty.
+
+ ((for all C of To_String (Source) => C = ' ')
+ =>
+ Length (Source) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ (if Side = Right then 1
+ else Index_Non_Blank (Source'Old, Forward));
+ High : constant Positive :=
+ (if Side = Left then Length (Source'Old)
+ else Index_Non_Blank (Source'Old, Backward));
+ begin
+ To_String (Source) = Slice (Source'Old, Low, High))),
+ Global => null;
function Trim
(Source : Bounded_String;
Left : Maps.Character_Set;
Right : Maps.Character_Set) return Bounded_String
with
- Post => Length (Trim'Result) <= Length (Source),
- Global => null;
+ Contract_Cases =>
+ -- If all characters in Source are contained in one of the sets Left
+ -- or Right, then the returned string is empty.
+
+ ((for all C of To_String (Source) => Maps.Is_In (C, Left))
+ or else
+ (for all C of To_String (Source) => Maps.Is_In (C, Right))
+ =>
+ Length (Trim'Result) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ Index (Source, Left, Outside, Forward);
+ High : constant Positive :=
+ Index (Source, Right, Outside, Backward);
+ begin
+ To_String (Trim'Result) = Slice (Source, Low, High))),
+ Global => null;
procedure Trim
(Source : in out Bounded_String;
Left : Maps.Character_Set;
Right : Maps.Character_Set)
with
- Post => Length (Source) <= Length (Source)'Old,
- Global => null;
+ Contract_Cases =>
+ -- If all characters in Source are contained in one of the sets Left
+ -- or Right, then the returned string is empty.
+
+ ((for all C of To_String (Source) => Maps.Is_In (C, Left))
+ or else
+ (for all C of To_String (Source) => Maps.Is_In (C, Right))
+ =>
+ Length (Source) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ Index (Source'Old, Left, Outside, Forward);
+ High : constant Positive :=
+ Index (Source'Old, Right, Outside, Backward);
+ begin
+ To_String (Source) = Slice (Source'Old, Low, High))),
+ Global => null;
function Head
(Source : Bounded_String;
@@ -720,9 +2185,54 @@ package Ada.Strings.Bounded is
Pad : Character := Space;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Count > Max_Length then Drop /= Error),
- Post => Length (Head'Result) = Natural'Min (Max_Length, Count),
- Global => null;
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count <= Length (Source)
+ =>
+ -- Source is cut
+
+ To_String (Head'Result) = Slice (Source, 1, Count),
+
+ Count > Length (Source) and then Count <= Max_Length
+ =>
+ -- Source is followed by Pad characters
+
+ Length (Head'Result) = Count
+ and then
+ Slice (Head'Result, 1, Length (Source)) = To_String (Source)
+ and then
+ Slice (Head'Result, Length (Source) + 1, Count) =
+ (1 .. Count - Length (Source) => Pad),
+
+ Count > Max_Length and then Drop = Right
+ =>
+ -- Source is followed by Pad characters
+
+ Length (Head'Result) = Max_Length
+ and then
+ Slice (Head'Result, 1, Length (Source)) = To_String (Source)
+ and then
+ Slice (Head'Result, Length (Source) + 1, Max_Length) =
+ (1 .. Max_Length - Length (Source) => Pad),
+
+ Count - Length (Source) > Max_Length and then Drop = Left
+ =>
+ -- Source is fully dropped at the left
+
+ To_String (Head'Result) = (1 .. Max_Length => Pad),
+
+ others
+ =>
+ -- Source is partly dropped at the left
+
+ Length (Head'Result) = Max_Length
+ and then
+ Slice (Head'Result, 1, Max_Length - Count + Length (Source)) =
+ Slice (Source, Count - Max_Length + 1, Length (Source))
+ and then
+ Slice (Head'Result,
+ Max_Length - Count + Length (Source) + 1, Max_Length) =
+ (1 .. Count - Length (Source) => Pad));
procedure Head
(Source : in out Bounded_String;
@@ -730,9 +2240,57 @@ package Ada.Strings.Bounded is
Pad : Character := Space;
Drop : Truncation := Error)
with
- Pre => (if Count > Max_Length then Drop /= Error),
- Post => Length (Source) = Natural'Min (Max_Length, Count),
- Global => null;
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count <= Length (Source)
+ =>
+ -- Source is cut
+
+ To_String (Source) = Slice (Source'Old, 1, Count),
+
+ Count > Length (Source) and then Count <= Max_Length
+ =>
+ -- Source is followed by Pad characters
+
+ Length (Source) = Count
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ Slice (Source, Length (Source'Old) + 1, Count) =
+ (1 .. Count - Length (Source'Old) => Pad),
+
+ Count > Max_Length and then Drop = Right
+ =>
+ -- Source is followed by Pad characters
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ Slice (Source, Length (Source'Old) + 1, Max_Length) =
+ (1 .. Max_Length - Length (Source'Old) => Pad),
+
+ Count - Length (Source) > Max_Length and then Drop = Left
+ =>
+ -- Source is fully dropped on the left
+
+ To_String (Source) = (1 .. Max_Length => Pad),
+
+ others
+ =>
+ -- Source is partly dropped on the left
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Max_Length - Count + Length (Source'Old)) =
+ Slice (Source'Old,
+ Count - Max_Length + 1, Length (Source'Old))
+ and then
+ Slice (Source,
+ Max_Length - Count + Length (Source'Old) + 1, Max_Length) =
+ (1 .. Count - Length (Source'Old) => Pad));
function Tail
(Source : Bounded_String;
@@ -740,9 +2298,60 @@ package Ada.Strings.Bounded is
Pad : Character := Space;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Count > Max_Length then Drop /= Error),
- Post => Length (Tail'Result) = Natural'Min (Max_Length, Count),
- Global => null;
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count < Length (Source)
+ =>
+ -- Source is cut
+
+ (if Count > 0 then
+ To_String (Tail'Result) =
+ Slice (Source, Length (Source) - Count + 1, Length (Source))
+ else Length (Tail'Result) = 0),
+
+ Count >= Length (Source) and then Count < Max_Length
+ =>
+ -- Source is preceded by Pad characters
+
+ Length (Tail'Result) = Count
+ and then
+ Slice (Tail'Result, 1, Count - Length (Source)) =
+ (1 .. Count - Length (Source) => Pad)
+ and then
+ Slice (Tail'Result, Count - Length (Source) + 1, Count) =
+ To_String (Source),
+
+ Count >= Max_Length and then Drop = Left
+ =>
+ -- Source is preceded by Pad characters
+
+ Length (Tail'Result) = Max_Length
+ and then
+ Slice (Tail'Result, 1, Max_Length - Length (Source)) =
+ (1 .. Max_Length - Length (Source) => Pad)
+ and then
+ (if Length (Source) > 0 then
+ Slice (Tail'Result,
+ Max_Length - Length (Source) + 1, Max_Length) =
+ To_String (Source)),
+
+ Count - Length (Source) >= Max_Length and then Drop /= Left
+ =>
+ -- Source is fully dropped on the right
+
+ To_String (Tail'Result) = (1 .. Max_Length => Pad),
+
+ others
+ =>
+ -- Source is partly dropped on the right
+
+ Length (Tail'Result) = Max_Length
+ and then
+ Slice (Tail'Result, 1, Count - Length (Source)) =
+ (1 .. Count - Length (Source) => Pad)
+ and then
+ Slice (Tail'Result, Count - Length (Source) + 1, Max_Length) =
+ Slice (Source, 1, Max_Length - Count + Length (Source)));
procedure Tail
(Source : in out Bounded_String;
@@ -750,9 +2359,62 @@ package Ada.Strings.Bounded is
Pad : Character := Space;
Drop : Truncation := Error)
with
- Pre => (if Count > Max_Length then Drop /= Error),
- Post => Length (Source) = Natural'Min (Max_Length, Count),
- Global => null;
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count < Length (Source)
+ =>
+ -- Source is cut
+
+ (if Count > 0 then
+ To_String (Source) =
+ Slice (Source'Old,
+ Length (Source'Old) - Count + 1, Length (Source'Old))
+ else Length (Source) = 0),
+
+ Count >= Length (Source) and then Count < Max_Length
+ =>
+ -- Source is preceded by Pad characters
+
+ Length (Source) = Count
+ and then
+ Slice (Source, 1, Count - Length (Source'Old)) =
+ (1 .. Count - Length (Source'Old) => Pad)
+ and then
+ Slice (Source, Count - Length (Source'Old) + 1, Count) =
+ To_String (Source'Old),
+
+ Count >= Max_Length and then Drop = Left
+ =>
+ -- Source is preceded by Pad characters
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Max_Length - Length (Source'Old)) =
+ (1 .. Max_Length - Length (Source'Old) => Pad)
+ and then
+ (if Length (Source'Old) > 0 then
+ Slice (Source,
+ Max_Length - Length (Source'Old) + 1, Max_Length) =
+ To_String (Source'Old)),
+
+ Count - Length (Source) >= Max_Length and then Drop /= Left
+ =>
+ -- Source is fully dropped at the right
+
+ To_String (Source) = (1 .. Max_Length => Pad),
+
+ others
+ =>
+ -- Source is partly dropped at the right
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Count - Length (Source'Old)) =
+ (1 .. Count - Length (Source'Old) => Pad)
+ and then
+ Slice (Source, Count - Length (Source'Old) + 1, Max_Length) =
+ Slice (Source'Old,
+ 1, Max_Length - Count + Length (Source'Old)));
------------------------------------
-- String Constructor Subprograms --
@@ -762,64 +2424,113 @@ package Ada.Strings.Bounded is
(Left : Natural;
Right : Character) return Bounded_String
with
- Pre => Left <= Max_Length,
- Post => Length ("*"'Result) = Left,
- Global => null;
+ Pre => Left <= Max_Length,
+ Post => To_String ("*"'Result) = (1 .. Left => Right);
function "*"
(Left : Natural;
Right : String) return Bounded_String
with
- Pre => (if Left /= 0 then Right'Length <= Max_Length / Left),
- Post => Length ("*"'Result) = Left * Right'Length,
- Global => null;
+ Pre => (if Left /= 0 then Right'Length <= Max_Length / Left),
+ Post =>
+ Length ("*"'Result) = Left * Right'Length
+ and then
+ (if Right'Length > 0 then
+ (for all K in 1 .. Left * Right'Length =>
+ Element ("*"'Result, K) =
+ Right (Right'First + (K - 1) mod Right'Length)));
function "*"
(Left : Natural;
Right : Bounded_String) return Bounded_String
with
- Pre => (if Left /= 0 then Length (Right) <= Max_Length / Left),
- Post => Length ("*"'Result) = Left * Length (Right),
- Global => null;
+ Pre => (if Left /= 0 then Length (Right) <= Max_Length / Left),
+ Post =>
+ Length ("*"'Result) = Left * Length (Right)
+ and then
+ (if Length (Right) > 0 then
+ (for all K in 1 .. Left * Length (Right) =>
+ Element ("*"'Result, K) =
+ Element (Right, 1 + (K - 1) mod Length (Right))));
function Replicate
(Count : Natural;
Item : Character;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Count > Max_Length then Drop /= Error),
- Post =>
- Length (Replicate'Result)
- = Natural'Min (Max_Length, Count),
- Global => null;
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Post =>
+ To_String (Replicate'Result) =
+ (1 .. Natural'Min (Max_Length, Count) => Item);
function Replicate
(Count : Natural;
Item : String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
- (if Item'Length /= 0
- and then Count > Max_Length / Item'Length
+ Pre =>
+ (if Count /= 0 and then Item'Length > Max_Length / Count
then Drop /= Error),
- Post =>
- Length (Replicate'Result)
- = Natural'Min (Max_Length, Count * Item'Length),
- Global => null;
+ Contract_Cases =>
+ (Count = 0 or else Item'Length <= Max_Length / Count
+ =>
+ Length (Replicate'Result) = Count * Item'Length
+ and then
+ (if Item'Length > 0 then
+ (for all K in 1 .. Count * Item'Length =>
+ Element (Replicate'Result, K) =
+ Item (Item'First + (K - 1) mod Item'Length))),
+ Count /= 0
+ and then Item'Length > Max_Length / Count
+ and then Drop = Right
+ =>
+ Length (Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Element (Replicate'Result, K) =
+ Item (Item'First + (K - 1) mod Item'Length)),
+ others -- Drop = Left
+ =>
+ Length (Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Element (Replicate'Result, K) =
+ Item (Item'Last - (Max_Length - K) mod Item'Length)));
function Replicate
(Count : Natural;
Item : Bounded_String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
- (if Length (Item) /= 0
- and then Count > Max_Length / Length (Item)
+ Pre =>
+ (if Count /= 0 and then Length (Item) > Max_Length / Count
then Drop /= Error),
- Post =>
- Length (Replicate'Result)
- = Natural'Min (Max_Length, Count * Length (Item)),
- Global => null;
+ Contract_Cases =>
+ ((if Count /= 0 then Length (Item) <= Max_Length / Count)
+ =>
+ Length (Replicate'Result) = Count * Length (Item)
+ and then
+ (if Length (Item) > 0 then
+ (for all K in 1 .. Count * Length (Item) =>
+ Element (Replicate'Result, K) =
+ Element (Item, 1 + (K - 1) mod Length (Item)))),
+ Count /= 0
+ and then Length (Item) > Max_Length / Count
+ and then Drop = Right
+ =>
+ Length (Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Element (Replicate'Result, K) =
+ Element (Item, 1 + (K - 1) mod Length (Item))),
+ others -- Drop = Left
+ =>
+ Length (Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Element (Replicate'Result, K) =
+ Element (Item,
+ Length (Item) - (Max_Length - K) mod Length (Item))));
private
-- Most of the implementation is in the separate non generic package
@@ -843,7 +2554,8 @@ package Ada.Strings.Bounded is
-- the generic instantiation is compatible with the Super_String
-- type declared in the Superbounded package.
- function From_String (Source : String) return Bounded_String;
+ function From_String (Source : String) return Bounded_String
+ with Pre => Source'Length <= Max_Length;
-- Private routine used only by Stream_Convert
pragma Stream_Convert (Bounded_String, From_String, To_String);
diff --git a/gcc/ada/libgnat/a-strfix.adb b/gcc/ada/libgnat/a-strfix.adb
index 00967c4..31dea6c 100644
--- a/gcc/ada/libgnat/a-strfix.adb
+++ b/gcc/ada/libgnat/a-strfix.adb
@@ -214,7 +214,8 @@ package body Ada.Strings.Fixed with SPARK_Mode is
-- Lemma_Split --
-----------------
- procedure Lemma_Split (Result : String) is
+ procedure Lemma_Split (Result : String)
+ is
begin
for K in Ptr + 1 .. Ptr + Right'Length loop
Lemma_Mod (K - 1);
@@ -307,7 +308,8 @@ package body Ada.Strings.Fixed with SPARK_Mode is
From : Positive;
Through : Natural;
Justify : Alignment := Left;
- Pad : Character := Space) with SPARK_Mode => Off is
+ Pad : Character := Space)
+ is
begin
Move (Source => Delete (Source, From, Through),
Target => Source,
@@ -403,7 +405,8 @@ package body Ada.Strings.Fixed with SPARK_Mode is
(Source : in out String;
Before : Positive;
New_Item : String;
- Drop : Truncation := Error) with SPARK_Mode => Off is
+ Drop : Truncation := Error)
+ is
begin
Move (Source => Insert (Source, Before, New_Item),
Target => Source,
@@ -419,7 +422,8 @@ package body Ada.Strings.Fixed with SPARK_Mode is
Target : out String;
Drop : Truncation := Error;
Justify : Alignment := Left;
- Pad : Character := Space) with SPARK_Mode => Off
+ Pad : Character := Space)
+ with SPARK_Mode => Off
is
Sfirst : constant Integer := Source'First;
Slast : constant Integer := Source'Last;
@@ -571,7 +575,8 @@ package body Ada.Strings.Fixed with SPARK_Mode is
(Source : in out String;
Position : Positive;
New_Item : String;
- Drop : Truncation := Right) with SPARK_Mode => Off is
+ Drop : Truncation := Right)
+ is
begin
Move (Source => Overwrite (Source, Position, New_Item),
Target => Source,
@@ -648,7 +653,8 @@ package body Ada.Strings.Fixed with SPARK_Mode is
By : String;
Drop : Truncation := Error;
Justify : Alignment := Left;
- Pad : Character := Space) with SPARK_Mode => Off is
+ Pad : Character := Space)
+ is
begin
Move (Replace_Slice (Source, Low, High, By), Source, Drop, Justify, Pad);
end Replace_Slice;
@@ -865,7 +871,7 @@ package body Ada.Strings.Fixed with SPARK_Mode is
High, Low : Integer;
begin
- Low := Index (Source, Set => Left, Test => Outside, Going => Forward);
+ Low := Index (Source, Set => Left, Test => Outside, Going => Forward);
-- Case where source comprises only characters in Left
diff --git a/gcc/ada/libgnat/a-strfix.ads b/gcc/ada/libgnat/a-strfix.ads
index 1a5ee94..1d9fd1b 100644
--- a/gcc/ada/libgnat/a-strfix.ads
+++ b/gcc/ada/libgnat/a-strfix.ads
@@ -382,7 +382,7 @@ package Ada.Strings.Fixed with SPARK_Mode is
=>
Index'Result = 0,
- -- Otherwise, a index in the range of Source is returned
+ -- Otherwise, an index in the range of Source is returned
others
=>
@@ -392,7 +392,7 @@ package Ada.Strings.Fixed with SPARK_Mode is
Index'Result in Source'Range
-- The character at the returned index satisfies the property
- -- Test on Set
+ -- Test on Set.
and then
(Test = Inside)
@@ -433,7 +433,7 @@ package Ada.Strings.Fixed with SPARK_Mode is
=>
Index'Result = 0,
- -- Otherwise, a index in the considered range of Source is returned
+ -- Otherwise, an index in the considered range of Source is returned
others
=>
@@ -904,7 +904,15 @@ package Ada.Strings.Fixed with SPARK_Mode is
Justify : Alignment := Left;
Pad : Character := Space)
with
- Pre => Low - 1 <= Source'Last,
+ Pre =>
+ Low - 1 <= Source'Last
+ and then High >= Source'First - 1
+ and then (if High >= Low
+ then Natural'Max (0, Low - Source'First)
+ <= Natural'Last
+ - By'Length
+ - Natural'Max (Source'Last - High, 0)
+ else Source'Length <= Natural'Last - By'Length),
-- Incomplete contract
@@ -966,7 +974,9 @@ package Ada.Strings.Fixed with SPARK_Mode is
New_Item : String;
Drop : Truncation := Error)
with
- Pre => Before - 1 in Source'First - 1 .. Source'Last,
+ Pre =>
+ Before - 1 in Source'First - 1 .. Source'Last
+ and then Source'Length <= Natural'Last - New_Item'Length,
-- Incomplete contract
@@ -1033,7 +1043,11 @@ package Ada.Strings.Fixed with SPARK_Mode is
New_Item : String;
Drop : Truncation := Right)
with
- Pre => Position - 1 in Source'First - 1 .. Source'Last,
+ Pre =>
+ Position - 1 in Source'First - 1 .. Source'Last
+ and then
+ (if Position - Source'First >= Source'Length - New_Item'Length
+ then Position - Source'First <= Natural'Last - New_Item'Length),
-- Incomplete contract
@@ -1133,31 +1147,15 @@ package Ada.Strings.Fixed with SPARK_Mode is
-- Otherwise, the returned string is a slice of Source
else
- (for some Low in Source'Range =>
- (for some High in Source'Range =>
-
- -- Trim returns the slice of Source between Low and High
-
- Trim'Result = Source (Low .. High)
-
- -- Values of Low and High and the characters at their
- -- position depend on Side.
-
- and then
- (if Side = Left then High = Source'Last
- else Source (High) /= ' ')
- and then
- (if Side = Right then Low = Source'First
- else Source (Low) /= ' ')
-
- -- All characters outside range Low .. High are
- -- Space characters.
-
- and then
- (for all J in Source'Range =>
- (if J < Low then Source (J) = ' ')
- and then
- (if J > High then Source (J) = ' '))))),
+ (declare
+ Low : constant Positive :=
+ (if Side = Right then Source'First
+ else Index_Non_Blank (Source, Forward));
+ High : constant Positive :=
+ (if Side = Left then Source'Last
+ else Index_Non_Blank (Source, Backward));
+ begin
+ Trim'Result = Source (Low .. High))),
Global => null;
-- Returns the string obtained by removing from Source all leading Space
-- characters (if Side = Left), all trailing Space characters (if
@@ -1203,30 +1201,13 @@ package Ada.Strings.Fixed with SPARK_Mode is
-- Otherwise, the returned string is a slice of Source
else
- (for some Low in Source'Range =>
- (for some High in Source'Range =>
-
- -- Trim returns the slice of Source between Low and High
-
- Trim'Result = Source (Low .. High)
-
- -- Characters at the bounds of the returned string are
- -- not contained in Left or Right.
-
- and then not Ada.Strings.Maps.Is_In (Source (Low), Left)
- and then not Ada.Strings.Maps.Is_In (Source (High), Right)
-
- -- All characters before Low are contained in Left.
- -- All characters after High are contained in Right.
-
- and then
- (for all K in Source'Range =>
- (if K < Low
- then
- Ada.Strings.Maps.Is_In (Source (K), Left))
- and then
- (if K > High then
- Ada.Strings.Maps.Is_In (Source (K), Right)))))),
+ (declare
+ Low : constant Positive :=
+ Index (Source, Left, Outside, Forward);
+ High : constant Positive :=
+ Index (Source, Right, Outside, Backward);
+ begin
+ Trim'Result = Source (Low .. High))),
Global => null;
-- Returns the string obtained by removing from Source all leading
-- characters in Left and all trailing characters in Right.
diff --git a/gcc/ada/libgnat/a-strmap.adb b/gcc/ada/libgnat/a-strmap.adb
index 8ad9f12..c87f4e5 100644
--- a/gcc/ada/libgnat/a-strmap.adb
+++ b/gcc/ada/libgnat/a-strmap.adb
@@ -35,7 +35,17 @@
-- is bit-by-bit or character-by-character and therefore rather slow.
-- Generally for character sets we favor the full 32-byte representation.
-package body Ada.Strings.Maps is
+-- Assertions, ghost code and loop invariants in this unit are meant for
+-- analysis only, not for run-time checking, as it would be too costly
+-- otherwise. This is enforced by setting the assertion policy to Ignore.
+
+pragma Assertion_Policy (Assert => Ignore,
+ Ghost => Ignore,
+ Loop_Invariant => Ignore);
+
+package body Ada.Strings.Maps
+ with SPARK_Mode
+is
---------
-- "-" --
@@ -102,9 +112,7 @@ package body Ada.Strings.Maps is
(Element : Character;
Set : Character_Set) return Boolean
is
- begin
- return Set (Element);
- end Is_In;
+ (Set (Element));
---------------
-- Is_Subset --
@@ -122,18 +130,37 @@ package body Ada.Strings.Maps is
-- To_Domain --
---------------
- function To_Domain (Map : Character_Mapping) return Character_Sequence
- is
- Result : String (1 .. Map'Length);
+ function To_Domain (Map : Character_Mapping) return Character_Sequence is
+ Result : String (1 .. Map'Length) with Relaxed_Initialization;
J : Natural;
+ type Character_Index is array (Character) of Natural with Ghost;
+ Indexes : Character_Index := (others => 0) with Ghost;
+
begin
J := 0;
for C in Map'Range loop
if Map (C) /= C then
J := J + 1;
Result (J) := C;
+ Indexes (C) := J;
end if;
+
+ pragma Loop_Invariant (if Map = Identity then J = 0);
+ pragma Loop_Invariant (J <= Character'Pos (C) + 1);
+ pragma Loop_Invariant (Result (1 .. J)'Initialized);
+ pragma Loop_Invariant (for all K in 1 .. J => Result (K) <= C);
+ pragma Loop_Invariant
+ (SPARK_Proof_Sorted_Character_Sequence (Result (1 .. J)));
+ pragma Loop_Invariant
+ (for all D in Map'First .. C =>
+ (if Map (D) = D then
+ Indexes (D) = 0
+ else
+ Indexes (D) in 1 .. J
+ and then Result (Indexes (D)) = D));
+ pragma Loop_Invariant
+ (for all Char of Result (1 .. J) => Map (Char) /= Char);
end loop;
return Result (1 .. J);
@@ -146,7 +173,7 @@ package body Ada.Strings.Maps is
function To_Mapping
(From, To : Character_Sequence) return Character_Mapping
is
- Result : Character_Mapping;
+ Result : Character_Mapping with Relaxed_Initialization;
Inserted : Character_Set := Null_Set;
From_Len : constant Natural := From'Length;
To_Len : constant Natural := To'Length;
@@ -158,6 +185,9 @@ package body Ada.Strings.Maps is
for Char in Character loop
Result (Char) := Char;
+ pragma Loop_Invariant (Result (Result'First .. Char)'Initialized);
+ pragma Loop_Invariant
+ (for all C in Result'First .. Char => Result (C) = C);
end loop;
for J in From'Range loop
@@ -167,6 +197,23 @@ package body Ada.Strings.Maps is
Result (From (J)) := To (J - From'First + To'First);
Inserted (From (J)) := True;
+
+ pragma Loop_Invariant (Result'Initialized);
+ pragma Loop_Invariant
+ (for all K in From'First .. J =>
+ Result (From (K)) = To (K - From'First + To'First)
+ and then Inserted (From (K)));
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ (Inserted (Char) =
+ (for some K in From'First .. J => Char = From (K))));
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ (if not Inserted (Char) then Result (Char) = Char));
+ pragma Loop_Invariant
+ (if (for all K in From'First .. J =>
+ From (K) = To (J - From'First + To'First))
+ then Result = Identity);
end loop;
return Result;
@@ -176,19 +223,195 @@ package body Ada.Strings.Maps is
-- To_Range --
--------------
- function To_Range (Map : Character_Mapping) return Character_Sequence
- is
- Result : String (1 .. Map'Length);
+ function To_Range (Map : Character_Mapping) return Character_Sequence is
+
+ -- Extract from the postcondition of To_Domain the essential properties
+ -- that define Seq as the domain of Map.
+ function Is_Domain
+ (Map : Character_Mapping;
+ Seq : Character_Sequence)
+ return Boolean
+ is
+ (Seq'First = 1
+ and then
+ SPARK_Proof_Sorted_Character_Sequence (Seq)
+ and then
+ (for all Char in Character =>
+ (if (for all X of Seq => X /= Char)
+ then Map (Char) = Char))
+ and then
+ (for all Char of Seq => Map (Char) /= Char))
+ with
+ Ghost;
+
+ -- Given Map, there is a unique sequence Seq for which
+ -- Is_Domain(Map,Seq) holds.
+ procedure Lemma_Domain_Unicity
+ (Map : Character_Mapping;
+ Seq1, Seq2 : Character_Sequence)
+ with
+ Ghost,
+ Pre => Is_Domain (Map, Seq1)
+ and then Is_Domain (Map, Seq2),
+ Post => Seq1 = Seq2;
+
+ -- Isolate the proof that To_Domain(Map) returns a sequence for which
+ -- Is_Domain holds.
+ procedure Lemma_Is_Domain (Map : Character_Mapping)
+ with
+ Ghost,
+ Post => Is_Domain (Map, To_Domain (Map));
+
+ -- Deduce the alternative expression of sortedness from the one in
+ -- SPARK_Proof_Sorted_Character_Sequence which compares consecutive
+ -- elements.
+ procedure Lemma_Is_Sorted (Seq : Character_Sequence)
+ with
+ Ghost,
+ Pre => SPARK_Proof_Sorted_Character_Sequence (Seq),
+ Post => (for all J in Seq'Range =>
+ (for all K in Seq'Range =>
+ (if J < K then Seq (J) < Seq (K))));
+
+ --------------------------
+ -- Lemma_Domain_Unicity --
+ --------------------------
+
+ procedure Lemma_Domain_Unicity
+ (Map : Character_Mapping;
+ Seq1, Seq2 : Character_Sequence)
+ is
+ J : Positive := 1;
+
+ begin
+ while J <= Seq1'Last
+ and then J <= Seq2'Last
+ and then Seq1 (J) = Seq2 (J)
+ loop
+ pragma Loop_Invariant
+ (Seq1 (Seq1'First .. J) = Seq2 (Seq2'First .. J));
+
+ if J = Positive'Last then
+ return;
+ end if;
+
+ J := J + 1;
+ end loop;
+
+ Lemma_Is_Sorted (Seq1);
+ Lemma_Is_Sorted (Seq2);
+
+ if J <= Seq1'Last
+ and then J <= Seq2'Last
+ then
+ if Seq1 (J) < Seq2 (J) then
+ pragma Assert (for all X of Seq2 => X /= Seq1 (J));
+ pragma Assert (Map (Seq1 (J)) = Seq1 (J));
+ pragma Assert (False);
+ else
+ pragma Assert (for all X of Seq1 => X /= Seq2 (J));
+ pragma Assert (Map (Seq2 (J)) = Seq2 (J));
+ pragma Assert (False);
+ end if;
+
+ elsif J <= Seq1'Last then
+ pragma Assert (for all X of Seq2 => X /= Seq1 (J));
+ pragma Assert (Map (Seq1 (J)) = Seq1 (J));
+ pragma Assert (False);
+
+ elsif J <= Seq2'Last then
+ pragma Assert (for all X of Seq1 => X /= Seq2 (J));
+ pragma Assert (Map (Seq2 (J)) = Seq2 (J));
+ pragma Assert (False);
+ end if;
+ end Lemma_Domain_Unicity;
+
+ ---------------------
+ -- Lemma_Is_Domain --
+ ---------------------
+
+ procedure Lemma_Is_Domain (Map : Character_Mapping) is
+ Ignore : constant Character_Sequence := To_Domain (Map);
+ begin
+ null;
+ end Lemma_Is_Domain;
+
+ ---------------------
+ -- Lemma_Is_Sorted --
+ ---------------------
+
+ procedure Lemma_Is_Sorted (Seq : Character_Sequence) is
+ begin
+ for A in Seq'Range loop
+ exit when A = Positive'Last;
+
+ for B in A + 1 .. Seq'Last loop
+ pragma Loop_Invariant
+ (for all K in A + 1 .. B => Seq (A) < Seq (K));
+ end loop;
+
+ pragma Loop_Invariant
+ (for all J in Seq'First .. A =>
+ (for all K in Seq'Range =>
+ (if J < K then Seq (J) < Seq (K))));
+ end loop;
+ end Lemma_Is_Sorted;
+
+ -- Local variables
+
+ Result : String (1 .. Map'Length) with Relaxed_Initialization;
J : Natural;
+
+ -- Repeat the computation from To_Domain in ghost code, in order to
+ -- prove the relationship between Result and To_Domain(Map).
+
+ Domain : String (1 .. Map'Length) with Ghost, Relaxed_Initialization;
+ type Character_Index is array (Character) of Natural with Ghost;
+ Indexes : Character_Index := (others => 0) with Ghost;
+
+ -- Start of processing for To_Range
+
begin
J := 0;
for C in Map'Range loop
if Map (C) /= C then
J := J + 1;
Result (J) := Map (C);
+ Domain (J) := C;
+ Indexes (C) := J;
end if;
+
+ -- Repeat the loop invariants from To_Domain regarding Domain and
+ -- Indexes. Add similar loop invariants for Result and Indexes.
+
+ pragma Loop_Invariant (J <= Character'Pos (C) + 1);
+ pragma Loop_Invariant (Result (1 .. J)'Initialized);
+ pragma Loop_Invariant (Domain (1 .. J)'Initialized);
+ pragma Loop_Invariant (for all K in 1 .. J => Domain (K) <= C);
+ pragma Loop_Invariant
+ (SPARK_Proof_Sorted_Character_Sequence (Domain (1 .. J)));
+ pragma Loop_Invariant
+ (for all D in Map'First .. C =>
+ (if Map (D) = D then
+ Indexes (D) = 0
+ else
+ Indexes (D) in 1 .. J
+ and then Domain (Indexes (D)) = D
+ and then Result (Indexes (D)) = Map (D)));
+ pragma Loop_Invariant
+ (for all Char of Domain (1 .. J) => Map (Char) /= Char);
+ pragma Loop_Invariant
+ (for all K in 1 .. J => Result (K) = Map (Domain (K)));
end loop;
+ -- Show the equality of Domain and To_Domain(Map)
+
+ Lemma_Is_Domain (Map);
+ Lemma_Domain_Unicity (Map, Domain (1 .. J), To_Domain (Map));
+ pragma Assert
+ (for all K in 1 .. J => Domain (K) = To_Domain (Map) (K));
+ pragma Assert (To_Domain (Map)'Length = J);
+
return Result (1 .. J);
end To_Range;
@@ -197,18 +420,26 @@ package body Ada.Strings.Maps is
---------------
function To_Ranges (Set : Character_Set) return Character_Ranges is
- Max_Ranges : Character_Ranges (1 .. Set'Length / 2 + 1);
+ Max_Ranges : Character_Ranges (1 .. Set'Length / 2 + 1)
+ with Relaxed_Initialization;
Range_Num : Natural;
C : Character;
+ C_Iter : Character with Ghost;
begin
C := Character'First;
Range_Num := 0;
loop
+ C_Iter := C;
+
-- Skip gap between subsets
while not Set (C) loop
+ pragma Loop_Invariant
+ (Character'Pos (C) >= Character'Pos (C'Loop_Entry));
+ pragma Loop_Invariant
+ (for all Char in C'Loop_Entry .. C => not Set (Char));
exit when C = Character'Last;
C := Character'Succ (C);
end loop;
@@ -221,16 +452,45 @@ package body Ada.Strings.Maps is
-- Span a subset
loop
+ pragma Loop_Invariant
+ (Character'Pos (C) >= Character'Pos (C'Loop_Entry));
+ pragma Loop_Invariant
+ (for all Char in C'Loop_Entry .. C =>
+ (if Char /= C then Set (Char)));
exit when not Set (C) or else C = Character'Last;
C := Character'Succ (C);
end loop;
if Set (C) then
- Max_Ranges (Range_Num). High := C;
+ Max_Ranges (Range_Num).High := C;
exit;
else
- Max_Ranges (Range_Num). High := Character'Pred (C);
+ Max_Ranges (Range_Num).High := Character'Pred (C);
end if;
+
+ pragma Assert
+ (for all Char in C_Iter .. C =>
+ (Set (Char) =
+ (Char in Max_Ranges (Range_Num).Low ..
+ Max_Ranges (Range_Num).High)));
+ pragma Assert
+ (for all Char in Character'First .. C_Iter =>
+ (if Char /= C_Iter then
+ (Set (Char) =
+ (for some Span of Max_Ranges (1 .. Range_Num - 1) =>
+ Char in Span.Low .. Span.High))));
+
+ pragma Loop_Invariant (2 * Range_Num <= Character'Pos (C) + 1);
+ pragma Loop_Invariant (Max_Ranges (1 .. Range_Num)'Initialized);
+ pragma Loop_Invariant (not Set (C));
+ pragma Loop_Invariant
+ (for all Char in Character'First .. C =>
+ (Set (Char) =
+ (for some Span of Max_Ranges (1 .. Range_Num) =>
+ Char in Span.Low .. Span.High)));
+ pragma Loop_Invariant
+ (for all Span of Max_Ranges (1 .. Range_Num) =>
+ (for all Char in Span.Low .. Span.High => Set (Char)));
end loop;
return Max_Ranges (1 .. Range_Num);
@@ -241,7 +501,8 @@ package body Ada.Strings.Maps is
-----------------
function To_Sequence (Set : Character_Set) return Character_Sequence is
- Result : String (1 .. Character'Pos (Character'Last) + 1);
+ Result : String (1 .. Character'Pos (Character'Last) + 1)
+ with Relaxed_Initialization;
Count : Natural := 0;
begin
for Char in Set'Range loop
@@ -249,6 +510,17 @@ package body Ada.Strings.Maps is
Count := Count + 1;
Result (Count) := Char;
end if;
+
+ pragma Loop_Invariant (Count <= Character'Pos (Char) + 1);
+ pragma Loop_Invariant (Result (1 .. Count)'Initialized);
+ pragma Loop_Invariant (for all K in 1 .. Count => Result (K) <= Char);
+ pragma Loop_Invariant
+ (SPARK_Proof_Sorted_Character_Sequence (Result (1 .. Count)));
+ pragma Loop_Invariant
+ (for all C in Set'First .. Char =>
+ (Set (C) = (for some X of Result (1 .. Count) => C = X)));
+ pragma Loop_Invariant
+ (for all Char of Result (1 .. Count) => Is_In (Char, Set));
end loop;
return Result (1 .. Count);
@@ -259,30 +531,37 @@ package body Ada.Strings.Maps is
------------
function To_Set (Ranges : Character_Ranges) return Character_Set is
- Result : Character_Set;
+ Result : Character_Set := Null_Set;
begin
- for C in Result'Range loop
- Result (C) := False;
- end loop;
-
for R in Ranges'Range loop
for C in Ranges (R).Low .. Ranges (R).High loop
Result (C) := True;
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ Result (Char) =
+ ((for some Prev in Ranges'First .. R - 1 =>
+ Char in Ranges (Prev).Low .. Ranges (Prev).High)
+ or else (Char in Ranges (R).Low .. C)));
end loop;
+
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ Result (Char) =
+ (for some Prev in Ranges'First .. R =>
+ Char in Ranges (Prev).Low .. Ranges (Prev).High));
end loop;
return Result;
end To_Set;
function To_Set (Span : Character_Range) return Character_Set is
- Result : Character_Set;
+ Result : Character_Set := Null_Set;
begin
- for C in Result'Range loop
- Result (C) := False;
- end loop;
-
for C in Span.Low .. Span.High loop
Result (C) := True;
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ Result (Char) = (Char in Span.Low .. C));
end loop;
return Result;
@@ -293,6 +572,10 @@ package body Ada.Strings.Maps is
begin
for J in Sequence'Range loop
Result (Sequence (J)) := True;
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ Result (Char) =
+ (for some K in Sequence'First .. J => Char = Sequence (K)));
end loop;
return Result;
@@ -313,8 +596,6 @@ package body Ada.Strings.Maps is
(Map : Character_Mapping;
Element : Character) return Character
is
- begin
- return Map (Element);
- end Value;
+ (Map (Element));
end Ada.Strings.Maps;
diff --git a/gcc/ada/libgnat/a-strmap.ads b/gcc/ada/libgnat/a-strmap.ads
index c35c392..1a15d5d 100644
--- a/gcc/ada/libgnat/a-strmap.ads
+++ b/gcc/ada/libgnat/a-strmap.ads
@@ -33,15 +33,24 @@
-- --
------------------------------------------------------------------------------
+-- The package Strings.Maps defines the types, operations, and other entities
+-- needed for character sets and character-to-character mappings.
+
-- Preconditions in this unit are meant for analysis only, not for run-time
-- checking, so that the expected exceptions are raised. This is enforced by
--- setting the corresponding assertion policy to Ignore.
+-- setting the corresponding assertion policy to Ignore. Postconditions and
+-- ghost code should not be executed at runtime as well, in order not to slow
+-- down the execution of these functions.
-pragma Assertion_Policy (Pre => Ignore);
+pragma Assertion_Policy (Pre => Ignore,
+ Post => Ignore,
+ Ghost => Ignore);
with Ada.Characters.Latin_1;
-package Ada.Strings.Maps is
+package Ada.Strings.Maps
+ with SPARK_Mode
+is
pragma Pure;
-- In accordance with Ada 2005 AI-362
@@ -51,9 +60,10 @@ package Ada.Strings.Maps is
type Character_Set is private;
pragma Preelaborable_Initialization (Character_Set);
- -- Representation for a set of character values:
+ -- An object of type Character_Set represents a set of characters.
Null_Set : constant Character_Set;
+ -- Null_Set represents the set containing no characters.
---------------------------
-- Constructors for Sets --
@@ -63,9 +73,12 @@ package Ada.Strings.Maps is
Low : Character;
High : Character;
end record;
- -- Represents Character range Low .. High
+ -- An object Obj of type Character_Range represents the set of characters
+ -- in the range Obj.Low .. Obj.High.
type Character_Ranges is array (Positive range <>) of Character_Range;
+ -- An object Obj of type Character_Ranges represents the union of the sets
+ -- corresponding to Obj(I) for I in Obj'Range.
function To_Set (Ranges : Character_Ranges) return Character_Set with
Post =>
@@ -78,6 +91,8 @@ package Ada.Strings.Maps is
(for all Span of Ranges =>
(for all Char in Span.Low .. Span.High =>
Is_In (Char, To_Set'Result)));
+ -- If Ranges'Length=0 then Null_Set is returned; otherwise, the returned
+ -- value represents the set corresponding to Ranges.
function To_Set (Span : Character_Range) return Character_Set with
Post =>
@@ -87,6 +102,7 @@ package Ada.Strings.Maps is
(if Is_In (Char, To_Set'Result) then Char in Span.Low .. Span.High))
and then
(for all Char in Span.Low .. Span.High => Is_In (Char, To_Set'Result));
+ -- The returned value represents the set containing each character in Span.
function To_Ranges (Set : Character_Set) return Character_Ranges with
Post =>
@@ -100,6 +116,12 @@ package Ada.Strings.Maps is
and then
(for all Span of To_Ranges'Result =>
(for all Char in Span.Low .. Span.High => Is_In (Char, Set)));
+ -- If Set = Null_Set, then an empty Character_Ranges array is returned;
+ -- otherwise, the shortest array of contiguous ranges of Character values
+ -- in Set, in increasing order of Low, is returned.
+ --
+ -- The postcondition above does not express that the result is the shortest
+ -- array and that it is sorted.
----------------------------------
-- Operations on Character Sets --
@@ -111,6 +133,13 @@ package Ada.Strings.Maps is
=
(for all Char in Character =>
(Is_In (Char, Left) = Is_In (Char, Right)));
+ -- The function "=" returns True if Left and Right represent identical
+ -- sets, and False otherwise.
+
+ -- Each of the logical operators "not", "and", "or", and "xor" returns a
+ -- Character_Set value that represents the set obtained by applying the
+ -- corresponding operation to the set(s) represented by the parameter(s)
+ -- of the operator.
function "not" (Right : Character_Set) return Character_Set with
Post =>
@@ -146,10 +175,12 @@ package Ada.Strings.Maps is
(Is_In (Char, "-"'Result)
=
(Is_In (Char, Left) and not Is_In (Char, Right))));
+ -- "-"(Left, Right) is equivalent to "and"(Left, "not"(Right)).
function Is_In
(Element : Character;
Set : Character_Set) return Boolean;
+ -- Is_In returns True if Element is in Set, and False otherwise.
function Is_Subset
(Elements : Character_Set;
@@ -160,6 +191,8 @@ package Ada.Strings.Maps is
=
(for all Char in Character =>
(if Is_In (Char, Elements) then Is_In (Char, Set)));
+ -- Is_Subset returns True if Elements is a subset of Set, and False
+ -- otherwise.
function "<="
(Left : Character_Set;
@@ -167,7 +200,23 @@ package Ada.Strings.Maps is
renames Is_Subset;
subtype Character_Sequence is String;
- -- Alternative representation for a set of character values
+ -- The Character_Sequence subtype is used to portray a set of character
+ -- values and also to identify the domain and range of a character mapping.
+
+ function SPARK_Proof_Sorted_Character_Sequence
+ (Seq : Character_Sequence) return Boolean
+ is
+ (for all J in Seq'Range =>
+ (if J /= Seq'Last then Seq (J) < Seq (J + 1)))
+ with
+ Ghost;
+ -- Check whether the Character_Sequence is sorted in stricly increasing
+ -- order, as expected from the result of To_Sequence and To_Domain.
+
+ -- Sequence portrays the set of character values that it explicitly
+ -- contains (ignoring duplicates). Singleton portrays the set comprising a
+ -- single Character. Each of the To_Set functions returns a Character_Set
+ -- value that represents the set portrayed by Sequence or Singleton.
function To_Set (Sequence : Character_Sequence) return Character_Set with
Post =>
@@ -197,10 +246,10 @@ package Ada.Strings.Maps is
and then
(for all Char of To_Sequence'Result => Is_In (Char, Set))
and then
- (for all J in To_Sequence'Result'Range =>
- (for all K in To_Sequence'Result'Range =>
- (if J /= K
- then To_Sequence'Result (J) /= To_Sequence'Result (K))));
+ SPARK_Proof_Sorted_Character_Sequence (To_Sequence'Result);
+ -- The function To_Sequence returns a Character_Sequence value containing
+ -- each of the characters in the set represented by Set, in ascending order
+ -- with no duplicates.
------------------------------------
-- Character Mapping Declarations --
@@ -208,13 +257,39 @@ package Ada.Strings.Maps is
type Character_Mapping is private;
pragma Preelaborable_Initialization (Character_Mapping);
- -- Representation for a character to character mapping:
+ -- An object of type Character_Mapping represents a Character-to-Character
+ -- mapping.
+
+ type SPARK_Proof_Character_Mapping_Model is
+ array (Character) of Character
+ with Ghost;
+ -- Publicly visible model of a Character_Mapping
+
+ function SPARK_Proof_Model
+ (Map : Character_Mapping)
+ return SPARK_Proof_Character_Mapping_Model
+ with Ghost;
+ -- Creation of a publicly visible model of a Character_Mapping
function Value
(Map : Character_Mapping;
- Element : Character) return Character;
+ Element : Character) return Character
+ with
+ Post => Value'Result = SPARK_Proof_Model (Map) (Element);
+ -- The function Value returns the Character value to which Element maps
+ -- with respect to the mapping represented by Map.
+
+ -- A character C matches a pattern character P with respect to a given
+ -- Character_Mapping value Map if Value(Map, C) = P. A string S matches
+ -- a pattern string P with respect to a given Character_Mapping if
+ -- their lengths are the same and if each character in S matches its
+ -- corresponding character in the pattern string P.
+
+ -- String handling subprograms that deal with character mappings have
+ -- parameters whose type is Character_Mapping.
Identity : constant Character_Mapping;
+ -- Identity maps each Character to itself.
----------------------------
-- Operations on Mappings --
@@ -240,6 +315,10 @@ package Ada.Strings.Maps is
and then
(if (for all X of From => Char /= X)
then Value (To_Mapping'Result, Char) = Char)));
+ -- To_Mapping produces a Character_Mapping such that each element of From
+ -- maps to the corresponding element of To, and each other character maps
+ -- to itself. If From'Length /= To'Length, or if some character is repeated
+ -- in From, then Translation_Error is propagated.
function To_Domain
(Map : Character_Mapping) return Character_Sequence with
@@ -248,24 +327,40 @@ package Ada.Strings.Maps is
and then
To_Domain'Result'First = 1
and then
+ SPARK_Proof_Sorted_Character_Sequence (To_Domain'Result)
+ and then
(for all Char in Character =>
(if (for all X of To_Domain'Result => X /= Char)
then Value (Map, Char) = Char))
and then
(for all Char of To_Domain'Result => Value (Map, Char) /= Char);
+ -- To_Domain returns the shortest Character_Sequence value D such that each
+ -- character not in D maps to itself, and such that the characters in D are
+ -- in ascending order. The lower bound of D is 1.
function To_Range
(Map : Character_Mapping) return Character_Sequence with
Post =>
To_Range'Result'First = 1
and then
- To_Range'Result'Last = To_Domain (Map)'Last
+ To_Range'Result'Length = To_Domain (Map)'Length
and then
(for all J in To_Range'Result'Range =>
To_Range'Result (J) = Value (Map, To_Domain (Map) (J)));
+ -- To_Range returns the Character_Sequence value R, such that if D =
+ -- To_Domain(Map), then R has the same bounds as D, and D(I) maps to
+ -- R(I) for each I in D'Range.
+ --
+ -- A direct encoding of the Ada RM would be the postcondition
+ -- To_Range'Result'Last = To_Domain (Map)'Last
+ -- which is not provable unless the postcondition of To_Domain is also
+ -- strengthened to state the value of the high bound for an empty result.
type Character_Mapping_Function is
access function (From : Character) return Character;
+ -- An object F of type Character_Mapping_Function maps a Character value C
+ -- to the Character value F.all(C), which is said to match C with respect
+ -- to mapping function F.
private
pragma Inline (Is_In);
@@ -285,6 +380,12 @@ private
type Character_Mapping is array (Character) of Character;
+ function SPARK_Proof_Model
+ (Map : Character_Mapping)
+ return SPARK_Proof_Character_Mapping_Model
+ is
+ (SPARK_Proof_Character_Mapping_Model (Map));
+
package L renames Ada.Characters.Latin_1;
Identity : constant Character_Mapping :=
diff --git a/gcc/ada/libgnat/a-strsea.ads b/gcc/ada/libgnat/a-strsea.ads
index 4396747..f4e7d36 100644
--- a/gcc/ada/libgnat/a-strsea.ads
+++ b/gcc/ada/libgnat/a-strsea.ads
@@ -213,7 +213,7 @@ package Ada.Strings.Search with SPARK_Mode is
=>
Index'Result = 0,
- -- Otherwise, a index in the range of Source is returned
+ -- Otherwise, an index in the range of Source is returned
others =>
@@ -222,7 +222,7 @@ package Ada.Strings.Search with SPARK_Mode is
Index'Result in Source'Range
-- The character at the returned index satisfies the property
- -- Test on Set
+ -- Test on Set.
and then (Test = Inside)
= Ada.Strings.Maps.Is_In (Source (Index'Result), Set)
@@ -377,7 +377,7 @@ package Ada.Strings.Search with SPARK_Mode is
=>
Index'Result = 0,
- -- Otherwise, a index in the considered range of Source is returned
+ -- Otherwise, an index in the considered range of Source is returned
others =>
diff --git a/gcc/ada/libgnat/a-strsup.adb b/gcc/ada/libgnat/a-strsup.adb
index 1e85cc2..a94d6ca 100644
--- a/gcc/ada/libgnat/a-strsup.adb
+++ b/gcc/ada/libgnat/a-strsup.adb
@@ -29,10 +29,17 @@
-- --
------------------------------------------------------------------------------
-with Ada.Strings.Maps; use Ada.Strings.Maps;
-with Ada.Strings.Search;
+-- Ghost code, loop invariants and assertions in this unit are meant for
+-- analysis only, not for run-time checking, as it would be too costly
+-- otherwise. This is enforced by setting the assertion policy to Ignore.
-package body Ada.Strings.Superbounded is
+pragma Assertion_Policy (Ghost => Ignore,
+ Loop_Invariant => Ignore,
+ Assert => Ignore);
+
+with Ada.Strings.Maps; use Ada.Strings.Maps;
+
+package body Ada.Strings.Superbounded with SPARK_Mode is
------------
-- Concat --
@@ -53,9 +60,13 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
end if;
- Result.Current_Length := Nlen;
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
+
+ if Rlen > 0 then
+ Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
+ end if;
+
+ Result.Current_Length := Nlen;
end;
end return;
end Concat;
@@ -74,9 +85,13 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
end if;
- Result.Current_Length := Nlen;
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Llen + 1 .. Nlen) := Right;
+
+ if Right'Length > 0 then
+ Result.Data (Llen + 1 .. Nlen) := Super_String_Data (Right);
+ end if;
+
+ Result.Current_Length := Nlen;
end;
end return;
end Concat;
@@ -97,9 +112,13 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
end if;
+ Result.Data (1 .. Llen) := Super_String_Data (Left);
+
+ if Rlen > 0 then
+ Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
+ end if;
+
Result.Current_Length := Nlen;
- Result.Data (1 .. Llen) := Left;
- Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
end;
end return;
end Concat;
@@ -117,9 +136,9 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
end if;
- Result.Current_Length := Llen + 1;
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Result.Current_Length) := Right;
+ Result.Data (Llen + 1) := Right;
+ Result.Current_Length := Llen + 1;
end;
end return;
end Concat;
@@ -137,10 +156,9 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
end if;
- Result.Current_Length := Rlen + 1;
Result.Data (1) := Left;
- Result.Data (2 .. Result.Current_Length) :=
- Right.Data (1 .. Rlen);
+ Result.Data (2 .. Rlen + 1) := Right.Data (1 .. Rlen);
+ Result.Current_Length := Rlen + 1;
end;
end return;
end Concat;
@@ -154,9 +172,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left.Current_Length = Right.Current_Length
- and then Left.Data (1 .. Left.Current_Length) =
- Right.Data (1 .. Right.Current_Length);
+ return Super_To_String (Left) = Super_To_String (Right);
end "=";
function Equal
@@ -164,8 +180,7 @@ package body Ada.Strings.Superbounded is
Right : String) return Boolean
is
begin
- return Left.Current_Length = Right'Length
- and then Left.Data (1 .. Left.Current_Length) = Right;
+ return Super_To_String (Left) = Right;
end Equal;
function Equal
@@ -173,8 +188,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left'Length = Right.Current_Length
- and then Left = Right.Data (1 .. Right.Current_Length);
+ return Left = Super_To_String (Right);
end Equal;
-------------
@@ -186,8 +200,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) >
- Right.Data (1 .. Right.Current_Length);
+ return Super_To_String (Left) > Super_To_String (Right);
end Greater;
function Greater
@@ -195,7 +208,7 @@ package body Ada.Strings.Superbounded is
Right : String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) > Right;
+ return Super_To_String (Left) > Right;
end Greater;
function Greater
@@ -203,7 +216,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left > Right.Data (1 .. Right.Current_Length);
+ return Left > Super_To_String (Right);
end Greater;
----------------------
@@ -215,8 +228,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) >=
- Right.Data (1 .. Right.Current_Length);
+ return Super_To_String (Left) >= Super_To_String (Right);
end Greater_Or_Equal;
function Greater_Or_Equal
@@ -224,7 +236,7 @@ package body Ada.Strings.Superbounded is
Right : String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) >= Right;
+ return Super_To_String (Left) >= Right;
end Greater_Or_Equal;
function Greater_Or_Equal
@@ -232,7 +244,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left >= Right.Data (1 .. Right.Current_Length);
+ return Left >= Super_To_String (Right);
end Greater_Or_Equal;
----------
@@ -244,8 +256,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) <
- Right.Data (1 .. Right.Current_Length);
+ return Super_To_String (Left) < Super_To_String (Right);
end Less;
function Less
@@ -253,7 +264,7 @@ package body Ada.Strings.Superbounded is
Right : String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) < Right;
+ return Super_To_String (Left) < Right;
end Less;
function Less
@@ -261,7 +272,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left < Right.Data (1 .. Right.Current_Length);
+ return Left < Super_To_String (Right);
end Less;
-------------------
@@ -273,8 +284,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) <=
- Right.Data (1 .. Right.Current_Length);
+ return Super_To_String (Left) <= Super_To_String (Right);
end Less_Or_Equal;
function Less_Or_Equal
@@ -282,7 +292,7 @@ package body Ada.Strings.Superbounded is
Right : String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) <= Right;
+ return Super_To_String (Left) <= Right;
end Less_Or_Equal;
function Less_Or_Equal
@@ -290,7 +300,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left <= Right.Data (1 .. Right.Current_Length);
+ return Left <= Super_To_String (Right);
end Less_Or_Equal;
----------------------
@@ -307,20 +317,20 @@ package body Ada.Strings.Superbounded is
begin
if Slen <= Max_Length then
+ Target.Data (1 .. Slen) := Super_String_Data (Source);
Target.Current_Length := Slen;
- Target.Data (1 .. Slen) := Source;
else
case Drop is
when Strings.Right =>
+ Target.Data (1 .. Max_Length) := Super_String_Data
+ (Source (Source'First .. Source'First - 1 + Max_Length));
Target.Current_Length := Max_Length;
- Target.Data (1 .. Max_Length) :=
- Source (Source'First .. Source'First - 1 + Max_Length);
when Strings.Left =>
+ Target.Data (1 .. Max_Length) := Super_String_Data
+ (Source (Source'Last - (Max_Length - 1) .. Source'Last));
Target.Current_Length := Max_Length;
- Target.Data (1 .. Max_Length) :=
- Source (Source'Last - (Max_Length - 1) .. Source'Last);
when Strings.Error =>
raise Ada.Strings.Length_Error;
@@ -343,17 +353,18 @@ package body Ada.Strings.Superbounded is
Result : Super_String (Max_Length);
Llen : constant Natural := Left.Current_Length;
Rlen : constant Natural := Right.Current_Length;
- Nlen : constant Natural := Llen + Rlen;
begin
- if Nlen <= Max_Length then
- Result.Current_Length := Nlen;
+ if Llen <= Max_Length - Rlen then
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
- else
- Result.Current_Length := Max_Length;
+ if Rlen > 0 then
+ Result.Data (Llen + 1 .. Llen + Rlen) := Right.Data (1 .. Rlen);
+ end if;
+
+ Result.Current_Length := Llen + Rlen;
+ else
case Drop is
when Strings.Right =>
if Llen >= Max_Length then -- only case is Llen = Max_Length
@@ -379,6 +390,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -392,16 +405,15 @@ package body Ada.Strings.Superbounded is
Max_Length : constant Positive := Source.Max_Length;
Llen : constant Natural := Source.Current_Length;
Rlen : constant Natural := New_Item.Current_Length;
- Nlen : constant Natural := Llen + Rlen;
begin
- if Nlen <= Max_Length then
- Source.Current_Length := Nlen;
- Source.Data (Llen + 1 .. Nlen) := New_Item.Data (1 .. Rlen);
+ if Llen <= Max_Length - Rlen then
+ if Rlen > 0 then
+ Source.Data (Llen + 1 .. Llen + Rlen) := New_Item.Data (1 .. Rlen);
+ Source.Current_Length := Llen + Rlen;
+ end if;
else
- Source.Current_Length := Max_Length;
-
case Drop is
when Strings.Right =>
if Llen < Max_Length then
@@ -423,6 +435,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Source.Current_Length := Max_Length;
end if;
end Super_Append;
@@ -438,17 +452,18 @@ package body Ada.Strings.Superbounded is
Result : Super_String (Max_Length);
Llen : constant Natural := Left.Current_Length;
Rlen : constant Natural := Right'Length;
- Nlen : constant Natural := Llen + Rlen;
begin
- if Nlen <= Max_Length then
- Result.Current_Length := Nlen;
+ if Llen <= Max_Length - Rlen then
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Llen + 1 .. Nlen) := Right;
- else
- Result.Current_Length := Max_Length;
+ if Rlen > 0 then
+ Result.Data (Llen + 1 .. Llen + Rlen) := Super_String_Data (Right);
+ end if;
+
+ Result.Current_Length := Llen + Rlen;
+ else
case Drop is
when Strings.Right =>
if Llen >= Max_Length then -- only case is Llen = Max_Length
@@ -456,27 +471,29 @@ package body Ada.Strings.Superbounded is
else
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Llen + 1 .. Max_Length) :=
- Right (Right'First .. Right'First - 1 +
- Max_Length - Llen);
+ Result.Data (Llen + 1 .. Max_Length) := Super_String_Data
+ (Right
+ (Right'First .. Right'First - 1 - Llen + Max_Length));
end if;
when Strings.Left =>
if Rlen >= Max_Length then
- Result.Data (1 .. Max_Length) :=
- Right (Right'Last - (Max_Length - 1) .. Right'Last);
+ Result.Data (1 .. Max_Length) := Super_String_Data
+ (Right (Right'Last - (Max_Length - 1) .. Right'Last));
else
Result.Data (1 .. Max_Length - Rlen) :=
Left.Data (Llen - (Max_Length - Rlen - 1) .. Llen);
Result.Data (Max_Length - Rlen + 1 .. Max_Length) :=
- Right;
+ Super_String_Data (Right);
end if;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -490,40 +507,42 @@ package body Ada.Strings.Superbounded is
Max_Length : constant Positive := Source.Max_Length;
Llen : constant Natural := Source.Current_Length;
Rlen : constant Natural := New_Item'Length;
- Nlen : constant Natural := Llen + Rlen;
begin
- if Nlen <= Max_Length then
- Source.Current_Length := Nlen;
- Source.Data (Llen + 1 .. Nlen) := New_Item;
+ if Llen <= Max_Length - Rlen then
+ if Rlen > 0 then
+ Source.Data (Llen + 1 .. Llen + Rlen) :=
+ Super_String_Data (New_Item);
+ Source.Current_Length := Llen + Rlen;
+ end if;
else
- Source.Current_Length := Max_Length;
-
case Drop is
when Strings.Right =>
if Llen < Max_Length then
- Source.Data (Llen + 1 .. Max_Length) :=
- New_Item (New_Item'First ..
- New_Item'First - 1 + Max_Length - Llen);
+ Source.Data (Llen + 1 .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'First ..
+ New_Item'First - 1 - Llen + Max_Length));
end if;
when Strings.Left =>
if Rlen >= Max_Length then
- Source.Data (1 .. Max_Length) :=
- New_Item (New_Item'Last - (Max_Length - 1) ..
- New_Item'Last);
+ Source.Data (1 .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'Last - (Max_Length - 1) ..
+ New_Item'Last));
else
Source.Data (1 .. Max_Length - Rlen) :=
Source.Data (Llen - (Max_Length - Rlen - 1) .. Llen);
Source.Data (Max_Length - Rlen + 1 .. Max_Length) :=
- New_Item;
+ Super_String_Data (New_Item);
end if;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Source.Current_Length := Max_Length;
end if;
end Super_Append;
@@ -539,25 +558,25 @@ package body Ada.Strings.Superbounded is
Result : Super_String (Max_Length);
Llen : constant Natural := Left'Length;
Rlen : constant Natural := Right.Current_Length;
- Nlen : constant Natural := Llen + Rlen;
begin
- if Nlen <= Max_Length then
- Result.Current_Length := Nlen;
- Result.Data (1 .. Llen) := Left;
- Result.Data (Llen + 1 .. Llen + Rlen) := Right.Data (1 .. Rlen);
+ if Llen <= Max_Length - Rlen then
+ Result.Data (1 .. Llen) := Super_String_Data (Left);
- else
- Result.Current_Length := Max_Length;
+ if Rlen > 0 then
+ Result.Data (Llen + 1 .. Llen + Rlen) := Right.Data (1 .. Rlen);
+ end if;
+ Result.Current_Length := Llen + Rlen;
+ else
case Drop is
when Strings.Right =>
if Llen >= Max_Length then
- Result.Data (1 .. Max_Length) :=
- Left (Left'First .. Left'First + (Max_Length - 1));
+ Result.Data (1 .. Max_Length) := Super_String_Data
+ (Left (Left'First .. Left'First + (Max_Length - 1)));
else
- Result.Data (1 .. Llen) := Left;
+ Result.Data (1 .. Llen) := Super_String_Data (Left);
Result.Data (Llen + 1 .. Max_Length) :=
Right.Data (1 .. Max_Length - Llen);
end if;
@@ -568,8 +587,8 @@ package body Ada.Strings.Superbounded is
Right.Data (Rlen - (Max_Length - 1) .. Rlen);
else
- Result.Data (1 .. Max_Length - Rlen) :=
- Left (Left'Last - (Max_Length - Rlen - 1) .. Left'Last);
+ Result.Data (1 .. Max_Length - Rlen) := Super_String_Data
+ (Left (Left'Last - (Max_Length - Rlen - 1) .. Left'Last));
Result.Data (Max_Length - Rlen + 1 .. Max_Length) :=
Right.Data (1 .. Rlen);
end if;
@@ -577,6 +596,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -595,9 +616,9 @@ package body Ada.Strings.Superbounded is
begin
if Llen < Max_Length then
- Result.Current_Length := Llen + 1;
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
Result.Data (Llen + 1) := Right;
+ Result.Current_Length := Llen + 1;
return Result;
else
@@ -606,10 +627,10 @@ package body Ada.Strings.Superbounded is
return Left;
when Strings.Left =>
- Result.Current_Length := Max_Length;
Result.Data (1 .. Max_Length - 1) :=
Left.Data (2 .. Max_Length);
Result.Data (Max_Length) := Right;
+ Result.Current_Length := Max_Length;
return Result;
when Strings.Error =>
@@ -628,12 +649,10 @@ package body Ada.Strings.Superbounded is
begin
if Llen < Max_Length then
- Source.Current_Length := Llen + 1;
Source.Data (Llen + 1) := New_Item;
+ Source.Current_Length := Llen + 1;
else
- Source.Current_Length := Max_Length;
-
case Drop is
when Strings.Right =>
null;
@@ -663,18 +682,18 @@ package body Ada.Strings.Superbounded is
begin
if Rlen < Max_Length then
- Result.Current_Length := Rlen + 1;
Result.Data (1) := Left;
Result.Data (2 .. Rlen + 1) := Right.Data (1 .. Rlen);
+ Result.Current_Length := Rlen + 1;
return Result;
else
case Drop is
when Strings.Right =>
- Result.Current_Length := Max_Length;
Result.Data (1) := Left;
Result.Data (2 .. Max_Length) :=
Right.Data (1 .. Max_Length - 1);
+ Result.Current_Length := Max_Length;
return Result;
when Strings.Left =>
@@ -696,9 +715,7 @@ package body Ada.Strings.Superbounded is
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
is
begin
- return
- Search.Count
- (Source.Data (1 .. Source.Current_Length), Pattern, Mapping);
+ return Search.Count (Super_To_String (Source), Pattern, Mapping);
end Super_Count;
function Super_Count
@@ -707,9 +724,7 @@ package body Ada.Strings.Superbounded is
Mapping : Maps.Character_Mapping_Function) return Natural
is
begin
- return
- Search.Count
- (Source.Data (1 .. Source.Current_Length), Pattern, Mapping);
+ return Search.Count (Super_To_String (Source), Pattern, Mapping);
end Super_Count;
function Super_Count
@@ -717,7 +732,7 @@ package body Ada.Strings.Superbounded is
Set : Maps.Character_Set) return Natural
is
begin
- return Search.Count (Source.Data (1 .. Source.Current_Length), Set);
+ return Search.Count (Super_To_String (Source), Set);
end Super_Count;
------------------
@@ -737,19 +752,19 @@ package body Ada.Strings.Superbounded is
if Num_Delete <= 0 then
return Source;
- elsif From > Slen + 1 then
+ elsif From - 1 > Slen then
raise Ada.Strings.Index_Error;
elsif Through >= Slen then
- Result.Current_Length := From - 1;
Result.Data (1 .. From - 1) := Source.Data (1 .. From - 1);
+ Result.Current_Length := From - 1;
return Result;
else
- Result.Current_Length := Slen - Num_Delete;
Result.Data (1 .. From - 1) := Source.Data (1 .. From - 1);
- Result.Data (From .. Result.Current_Length) :=
+ Result.Data (From .. Slen - Num_Delete) :=
Source.Data (Through + 1 .. Slen);
+ Result.Current_Length := Slen - Num_Delete;
return Result;
end if;
end Super_Delete;
@@ -766,7 +781,7 @@ package body Ada.Strings.Superbounded is
if Num_Delete <= 0 then
return;
- elsif From > Slen + 1 then
+ elsif From - 1 > Slen then
raise Ada.Strings.Index_Error;
elsif Through >= Slen then
@@ -779,22 +794,6 @@ package body Ada.Strings.Superbounded is
end if;
end Super_Delete;
- -------------------
- -- Super_Element --
- -------------------
-
- function Super_Element
- (Source : Super_String;
- Index : Positive) return Character
- is
- begin
- if Index <= Source.Current_Length then
- return Source.Data (Index);
- else
- raise Strings.Index_Error;
- end if;
- end Super_Element;
-
----------------------
-- Super_Find_Token --
----------------------
@@ -809,7 +808,7 @@ package body Ada.Strings.Superbounded is
is
begin
Search.Find_Token
- (Source.Data (From .. Source.Current_Length), Set, Test, First, Last);
+ (Super_To_String (Source), Set, From, Test, First, Last);
end Super_Find_Token;
procedure Super_Find_Token
@@ -820,8 +819,7 @@ package body Ada.Strings.Superbounded is
Last : out Natural)
is
begin
- Search.Find_Token
- (Source.Data (1 .. Source.Current_Length), Set, Test, First, Last);
+ Search.Find_Token (Super_To_String (Source), Set, Test, First, Last);
end Super_Find_Token;
----------------
@@ -841,21 +839,22 @@ package body Ada.Strings.Superbounded is
begin
if Npad <= 0 then
- Result.Current_Length := Count;
Result.Data (1 .. Count) := Source.Data (1 .. Count);
+ Result.Current_Length := Count;
elsif Count <= Max_Length then
- Result.Current_Length := Count;
Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
Result.Data (Slen + 1 .. Count) := (others => Pad);
+ Result.Current_Length := Count;
else
- Result.Current_Length := Max_Length;
-
case Drop is
when Strings.Right =>
Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
- Result.Data (Slen + 1 .. Max_Length) := (others => Pad);
+
+ if Slen < Max_Length then
+ Result.Data (Slen + 1 .. Max_Length) := (others => Pad);
+ end if;
when Strings.Left =>
if Npad >= Max_Length then
@@ -871,6 +870,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -885,22 +886,22 @@ package body Ada.Strings.Superbounded is
Max_Length : constant Positive := Source.Max_Length;
Slen : constant Natural := Source.Current_Length;
Npad : constant Integer := Count - Slen;
- Temp : String (1 .. Max_Length);
+ Temp : Super_String_Data (1 .. Max_Length);
begin
if Npad <= 0 then
Source.Current_Length := Count;
elsif Count <= Max_Length then
- Source.Current_Length := Count;
Source.Data (Slen + 1 .. Count) := (others => Pad);
+ Source.Current_Length := Count;
else
- Source.Current_Length := Max_Length;
-
case Drop is
when Strings.Right =>
- Source.Data (Slen + 1 .. Max_Length) := (others => Pad);
+ if Slen < Max_Length then
+ Source.Data (Slen + 1 .. Max_Length) := (others => Pad);
+ end if;
when Strings.Left =>
if Npad > Max_Length then
@@ -910,15 +911,15 @@ package body Ada.Strings.Superbounded is
Temp := Source.Data;
Source.Data (1 .. Max_Length - Npad) :=
Temp (Count - Max_Length + 1 .. Slen);
-
- for J in Max_Length - Npad + 1 .. Max_Length loop
- Source.Data (J) := Pad;
- end loop;
+ Source.Data (Max_Length - Npad + 1 .. Max_Length) :=
+ (others => Pad);
end if;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Source.Current_Length := Max_Length;
end if;
end Super_Head;
@@ -933,8 +934,7 @@ package body Ada.Strings.Superbounded is
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
is
begin
- return Search.Index
- (Source.Data (1 .. Source.Current_Length), Pattern, Going, Mapping);
+ return Search.Index (Super_To_String (Source), Pattern, Going, Mapping);
end Super_Index;
function Super_Index
@@ -944,8 +944,7 @@ package body Ada.Strings.Superbounded is
Mapping : Maps.Character_Mapping_Function) return Natural
is
begin
- return Search.Index
- (Source.Data (1 .. Source.Current_Length), Pattern, Going, Mapping);
+ return Search.Index (Super_To_String (Source), Pattern, Going, Mapping);
end Super_Index;
function Super_Index
@@ -955,8 +954,7 @@ package body Ada.Strings.Superbounded is
Going : Strings.Direction := Strings.Forward) return Natural
is
begin
- return Search.Index
- (Source.Data (1 .. Source.Current_Length), Set, Test, Going);
+ return Search.Index (Super_To_String (Source), Set, Test, Going);
end Super_Index;
function Super_Index
@@ -968,8 +966,7 @@ package body Ada.Strings.Superbounded is
is
begin
return Search.Index
- (Source.Data (1 .. Source.Current_Length),
- Pattern, From, Going, Mapping);
+ (Super_To_String (Source), Pattern, From, Going, Mapping);
end Super_Index;
function Super_Index
@@ -981,8 +978,7 @@ package body Ada.Strings.Superbounded is
is
begin
return Search.Index
- (Source.Data (1 .. Source.Current_Length),
- Pattern, From, Going, Mapping);
+ (Super_To_String (Source), Pattern, From, Going, Mapping);
end Super_Index;
function Super_Index
@@ -993,8 +989,15 @@ package body Ada.Strings.Superbounded is
Going : Direction := Forward) return Natural
is
begin
- return Search.Index
- (Source.Data (1 .. Source.Current_Length), Set, From, Test, Going);
+ return Result : Natural do
+ Result :=
+ Search.Index (Super_To_String (Source), Set, From, Test, Going);
+ pragma Assert
+ (if (for all J in 1 .. Super_Length (Source) =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ (Test = Inside) /= Maps.Is_In (Source.Data (J), Set)))
+ then Result = 0);
+ end return;
end Super_Index;
---------------------------
@@ -1006,9 +1009,7 @@ package body Ada.Strings.Superbounded is
Going : Strings.Direction := Strings.Forward) return Natural
is
begin
- return
- Search.Index_Non_Blank
- (Source.Data (1 .. Source.Current_Length), Going);
+ return Search.Index_Non_Blank (Super_To_String (Source), Going);
end Super_Index_Non_Blank;
function Super_Index_Non_Blank
@@ -1017,9 +1018,7 @@ package body Ada.Strings.Superbounded is
Going : Direction := Forward) return Natural
is
begin
- return
- Search.Index_Non_Blank
- (Source.Data (1 .. Source.Current_Length), From, Going);
+ return Search.Index_Non_Blank (Super_To_String (Source), From, Going);
end Super_Index_Non_Blank;
------------------
@@ -1031,60 +1030,71 @@ package body Ada.Strings.Superbounded is
Before : Positive;
New_Item : String;
Drop : Strings.Truncation := Strings.Error) return Super_String
+ with SPARK_Mode => Off
is
Max_Length : constant Positive := Source.Max_Length;
Result : Super_String (Max_Length);
Slen : constant Natural := Source.Current_Length;
Nlen : constant Natural := New_Item'Length;
- Tlen : constant Natural := Slen + Nlen;
Blen : constant Natural := Before - 1;
Alen : constant Integer := Slen - Blen;
- Droplen : constant Integer := Tlen - Max_Length;
+ Droplen : constant Integer := Slen - Max_Length + Nlen;
- -- Tlen is the length of the total string before possible truncation.
-- Blen, Alen are the lengths of the before and after pieces of the
- -- source string.
+ -- source string. The number of dropped characters is Natural'Max (0,
+ -- Droplen).
begin
if Alen < 0 then
raise Ada.Strings.Index_Error;
elsif Droplen <= 0 then
- Result.Current_Length := Tlen;
Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
- Result.Data (Before .. Before + Nlen - 1) := New_Item;
- Result.Data (Before + Nlen .. Tlen) :=
- Source.Data (Before .. Slen);
+ Result.Data (Before .. Before - 1 + Nlen) :=
+ Super_String_Data (New_Item);
- else
- Result.Current_Length := Max_Length;
+ if Before <= Slen then
+ Result.Data (Before + Nlen .. Slen + Nlen) :=
+ Source.Data (Before .. Slen);
+ end if;
+ Result.Current_Length := Slen + Nlen;
+
+ else
case Drop is
when Strings.Right =>
Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
- if Droplen > Alen then
- Result.Data (Before .. Max_Length) :=
- New_Item (New_Item'First
- .. New_Item'First + Max_Length - Before);
+ if Droplen >= Alen then
+ Result.Data (Before .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'First
+ .. New_Item'First - Before + Max_Length));
+ pragma Assert
+ (String (Result.Data (Before .. Max_Length)) =
+ New_Item (New_Item'First
+ .. New_Item'First - Before + Max_Length));
else
- Result.Data (Before .. Before + Nlen - 1) := New_Item;
+ Result.Data (Before .. Before - 1 + Nlen) :=
+ Super_String_Data (New_Item);
Result.Data (Before + Nlen .. Max_Length) :=
Source.Data (Before .. Slen - Droplen);
end if;
when Strings.Left =>
- Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
- Source.Data (Before .. Slen);
+ if Alen > 0 then
+ Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
+ Source.Data (Before .. Slen);
+ end if;
- if Droplen >= Blen then
- Result.Data (1 .. Max_Length - Alen) :=
- New_Item (New_Item'Last - (Max_Length - Alen) + 1
- .. New_Item'Last);
+ if Droplen > Blen then
+ if Alen < Max_Length then
+ Result.Data (1 .. Max_Length - Alen) := Super_String_Data
+ (New_Item (New_Item'Last - (Max_Length - Alen) + 1
+ .. New_Item'Last));
+ end if;
else
- Result.Data
- (Blen - Droplen + 1 .. Max_Length - Alen) :=
- New_Item;
+ Result.Data (Blen - Droplen + 1 .. Max_Length - Alen) :=
+ Super_String_Data (New_Item);
Result.Data (1 .. Blen - Droplen) :=
Source.Data (Droplen + 1 .. Blen);
end if;
@@ -1092,6 +1102,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -1111,15 +1123,6 @@ package body Ada.Strings.Superbounded is
Source := Super_Insert (Source, Before, New_Item, Drop);
end Super_Insert;
- ------------------
- -- Super_Length --
- ------------------
-
- function Super_Length (Source : Super_String) return Natural is
- begin
- return Source.Current_Length;
- end Super_Length;
-
---------------------
-- Super_Overwrite --
---------------------
@@ -1132,61 +1135,61 @@ package body Ada.Strings.Superbounded is
is
Max_Length : constant Positive := Source.Max_Length;
Result : Super_String (Max_Length);
- Endpos : constant Natural := Position + New_Item'Length - 1;
Slen : constant Natural := Source.Current_Length;
Droplen : Natural;
begin
- if Position > Slen + 1 then
+ if Position - 1 > Slen then
raise Ada.Strings.Index_Error;
elsif New_Item'Length = 0 then
return Source;
- elsif Endpos <= Slen then
- Result.Current_Length := Source.Current_Length;
+ elsif Position - 1 <= Slen - New_Item'Length then
Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
- Result.Data (Position .. Endpos) := New_Item;
+ Result.Data (Position .. Position - 1 + New_Item'Length) :=
+ Super_String_Data (New_Item);
+ Result.Current_Length := Source.Current_Length;
return Result;
- elsif Endpos <= Max_Length then
- Result.Current_Length := Endpos;
+ elsif Position - 1 <= Max_Length - New_Item'Length then
Result.Data (1 .. Position - 1) := Source.Data (1 .. Position - 1);
- Result.Data (Position .. Endpos) := New_Item;
+ Result.Data (Position .. Position - 1 + New_Item'Length) :=
+ Super_String_Data (New_Item);
+ Result.Current_Length := Position - 1 + New_Item'Length;
return Result;
else
- Result.Current_Length := Max_Length;
- Droplen := Endpos - Max_Length;
+ Droplen := Position - 1 - Max_Length + New_Item'Length;
case Drop is
when Strings.Right =>
Result.Data (1 .. Position - 1) :=
Source.Data (1 .. Position - 1);
- Result.Data (Position .. Max_Length) :=
- New_Item (New_Item'First .. New_Item'Last - Droplen);
- return Result;
+ Result.Data (Position .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'First .. New_Item'Last - Droplen));
when Strings.Left =>
if New_Item'Length >= Max_Length then
- Result.Data (1 .. Max_Length) :=
- New_Item (New_Item'Last - Max_Length + 1 ..
- New_Item'Last);
- return Result;
+ Result.Data (1 .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'Last - Max_Length + 1 ..
+ New_Item'Last));
else
Result.Data (1 .. Max_Length - New_Item'Length) :=
Source.Data (Droplen + 1 .. Position - 1);
Result.Data
(Max_Length - New_Item'Length + 1 .. Max_Length) :=
- New_Item;
- return Result;
+ Super_String_Data (New_Item);
end if;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
+ return Result;
end if;
end Super_Overwrite;
@@ -1195,50 +1198,52 @@ package body Ada.Strings.Superbounded is
Position : Positive;
New_Item : String;
Drop : Strings.Truncation := Strings.Error)
+ with SPARK_Mode => Off
is
Max_Length : constant Positive := Source.Max_Length;
- Endpos : constant Positive := Position + New_Item'Length - 1;
Slen : constant Natural := Source.Current_Length;
Droplen : Natural;
begin
- if Position > Slen + 1 then
+ if Position - 1 > Slen then
raise Ada.Strings.Index_Error;
- elsif Endpos <= Slen then
- Source.Data (Position .. Endpos) := New_Item;
+ elsif Position - 1 <= Slen - New_Item'Length then
+ Source.Data (Position .. Position - 1 + New_Item'Length) :=
+ Super_String_Data (New_Item);
- elsif Endpos <= Max_Length then
- Source.Data (Position .. Endpos) := New_Item;
- Source.Current_Length := Endpos;
+ elsif Position - 1 <= Max_Length - New_Item'Length then
+ Source.Data (Position .. Position - 1 + New_Item'Length) :=
+ Super_String_Data (New_Item);
+ Source.Current_Length := Position - 1 + New_Item'Length;
else
- Source.Current_Length := Max_Length;
- Droplen := Endpos - Max_Length;
+ Droplen := Position - 1 - Max_Length + New_Item'Length;
case Drop is
when Strings.Right =>
- Source.Data (Position .. Max_Length) :=
- New_Item (New_Item'First .. New_Item'Last - Droplen);
+ Source.Data (Position .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'First .. New_Item'Last - Droplen));
when Strings.Left =>
if New_Item'Length > Max_Length then
- Source.Data (1 .. Max_Length) :=
- New_Item (New_Item'Last - Max_Length + 1 ..
- New_Item'Last);
+ Source.Data (1 .. Max_Length) := Super_String_Data
+ (New_Item
+ (New_Item'Last - Max_Length + 1 .. New_Item'Last));
else
Source.Data (1 .. Max_Length - New_Item'Length) :=
Source.Data (Droplen + 1 .. Position - 1);
-
Source.Data
(Max_Length - New_Item'Length + 1 .. Max_Length) :=
- New_Item;
+ Super_String_Data (New_Item);
end if;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Source.Current_Length := Max_Length;
end if;
end Super_Overwrite;
@@ -1269,12 +1274,13 @@ package body Ada.Strings.Superbounded is
High : Natural;
By : String;
Drop : Strings.Truncation := Strings.Error) return Super_String
+ with SPARK_Mode => Off
is
Max_Length : constant Positive := Source.Max_Length;
Slen : constant Natural := Source.Current_Length;
begin
- if Low > Slen + 1 then
+ if Low - 1 > Slen then
raise Strings.Index_Error;
elsif High < Low then
@@ -1282,51 +1288,58 @@ package body Ada.Strings.Superbounded is
else
declare
- Blen : constant Natural := Natural'Max (0, Low - 1);
+ Blen : constant Natural := Low - 1;
Alen : constant Natural := Natural'Max (0, Slen - High);
- Tlen : constant Natural := Blen + By'Length + Alen;
- Droplen : constant Integer := Tlen - Max_Length;
+ Droplen : constant Integer := Blen + Alen - Max_Length + By'Length;
Result : Super_String (Max_Length);
- -- Tlen is the total length of the result string before any
- -- truncation. Blen and Alen are the lengths of the pieces
- -- of the original string that end up in the result string
- -- before and after the replaced slice.
+ -- Blen and Alen are the lengths of the pieces of the original
+ -- string that end up in the result string before and after the
+ -- replaced slice. The number of dropped characters is Natural'Max
+ -- (0, Droplen).
begin
if Droplen <= 0 then
- Result.Current_Length := Tlen;
Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
- Result.Data (Low .. Low + By'Length - 1) := By;
- Result.Data (Low + By'Length .. Tlen) :=
- Source.Data (High + 1 .. Slen);
+ Result.Data (Low .. Blen + By'Length) :=
+ Super_String_Data (By);
- else
- Result.Current_Length := Max_Length;
+ if Alen > 0 then
+ Result.Data (Low + By'Length .. Blen + By'Length + Alen) :=
+ Source.Data (High + 1 .. Slen);
+ end if;
+ Result.Current_Length := Blen + By'Length + Alen;
+
+ else
case Drop is
when Strings.Right =>
Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
- if Droplen > Alen then
- Result.Data (Low .. Max_Length) :=
- By (By'First .. By'First + Max_Length - Low);
+ if Droplen >= Alen then
+ Result.Data (Low .. Max_Length) := Super_String_Data
+ (By (By'First .. By'First - Low + Max_Length));
else
- Result.Data (Low .. Low + By'Length - 1) := By;
+ Result.Data (Low .. Low - 1 + By'Length) :=
+ Super_String_Data (By);
Result.Data (Low + By'Length .. Max_Length) :=
Source.Data (High + 1 .. Slen - Droplen);
end if;
when Strings.Left =>
- Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
- Source.Data (High + 1 .. Slen);
+ if Alen > 0 then
+ Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
+ Source.Data (High + 1 .. Slen);
+ end if;
if Droplen >= Blen then
Result.Data (1 .. Max_Length - Alen) :=
- By (By'Last - (Max_Length - Alen) + 1 .. By'Last);
+ Super_String_Data (By
+ (By'Last - (Max_Length - Alen) + 1 .. By'Last));
else
Result.Data
- (Blen - Droplen + 1 .. Max_Length - Alen) := By;
+ (Blen - Droplen + 1 .. Max_Length - Alen) :=
+ Super_String_Data (By);
Result.Data (1 .. Blen - Droplen) :=
Source.Data (Droplen + 1 .. Blen);
end if;
@@ -1334,6 +1347,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -1370,16 +1385,17 @@ package body Ada.Strings.Superbounded is
begin
if Count <= Max_Length then
+ Result.Data (1 .. Count) := (others => Item);
Result.Current_Length := Count;
elsif Drop = Strings.Error then
raise Ada.Strings.Length_Error;
else
+ Result.Data (1 .. Max_Length) := (others => Item);
Result.Current_Length := Max_Length;
end if;
- Result.Data (1 .. Result.Current_Length) := (others => Item);
return Result;
end Super_Replicate;
@@ -1389,52 +1405,203 @@ package body Ada.Strings.Superbounded is
Drop : Truncation := Error;
Max_Length : Positive) return Super_String
is
- Length : constant Integer := Count * Item'Length;
Result : Super_String (Max_Length);
- Indx : Positive;
+ Indx : Natural;
+ Ilen : constant Natural := Item'Length;
+
+ -- Parts of the proof involving manipulations with the modulo operator
+ -- are complicated for the prover and can't be done automatically in
+ -- the global subprogram. That's why we isolate them in these two ghost
+ -- lemmas.
+
+ procedure Lemma_Mod (K : Natural; Q : Natural) with
+ Ghost,
+ Pre => Ilen /= 0
+ and then Q mod Ilen = 0
+ and then K - Q in 0 .. Ilen - 1,
+ Post => K mod Ilen = K - Q;
+ -- Lemma_Mod is applied to an index considered in Lemma_Split to prove
+ -- that it has the right value modulo Item'Length.
+
+ procedure Lemma_Mod_Zero (X : Natural) with
+ Ghost,
+ Pre => Ilen /= 0
+ and then X mod Ilen = 0
+ and then X <= Natural'Last - Ilen,
+ Post => (X + Ilen) mod Ilen = 0;
+ -- Lemma_Mod_Zero is applied to prove that the length of the range
+ -- of indexes considered in the loop, when dropping on the Left, is
+ -- a multiple of Item'Length.
+
+ procedure Lemma_Split (Going : Direction) with
+ Ghost,
+ Pre =>
+ Ilen /= 0
+ and then Indx in 0 .. Max_Length - Ilen
+ and then
+ (if Going = Forward
+ then Indx mod Ilen = 0
+ else (Max_Length - Indx - Ilen) mod Ilen = 0)
+ and then Result.Data (Indx + 1 .. Indx + Ilen)'Initialized
+ and then String (Result.Data (Indx + 1 .. Indx + Ilen)) = Item,
+ Post =>
+ (if Going = Forward then
+ (for all J in Indx + 1 .. Indx + Ilen =>
+ Result.Data (J) = Item (Item'First + (J - 1) mod Ilen))
+ else
+ (for all J in Indx + 1 .. Indx + Ilen =>
+ Result.Data (J) =
+ Item (Item'Last - (Max_Length - J) mod Ilen)));
+ -- Lemma_Split is used after Result.Data (Indx + 1 .. Indx + Ilen) is
+ -- updated to Item and concludes that the characters match for each
+ -- index when taken modulo Item'Length, as the considered slice starts
+ -- at index 1 (or ends at index Max_Length, if Going = Backward) modulo
+ -- Item'Length.
+
+ ---------------
+ -- Lemma_Mod --
+ ---------------
+
+ procedure Lemma_Mod (K : Natural; Q : Natural) is null;
+
+ --------------------
+ -- Lemma_Mod_Zero --
+ --------------------
+
+ procedure Lemma_Mod_Zero (X : Natural) is null;
+
+ -----------------
+ -- Lemma_Split --
+ -----------------
+
+ procedure Lemma_Split (Going : Direction) is
+ begin
+ if Going = Forward then
+ for K in Indx + 1 .. Indx + Ilen loop
+ Lemma_Mod (K - 1, Indx);
+ pragma Loop_Invariant
+ (for all J in Indx + 1 .. K =>
+ Result.Data (J) = Item (Item'First + (J - 1) mod Ilen));
+ end loop;
+ else
+ for K in Indx + 1 .. Indx + Ilen loop
+ Lemma_Mod (Max_Length - K, Max_Length - Indx - Ilen);
+ pragma Loop_Invariant
+ (for all J in Indx + 1 .. K =>
+ Result.Data (J) =
+ Item (Item'Last - (Max_Length - J) mod Ilen));
+ end loop;
+ end if;
+ end Lemma_Split;
begin
- if Length <= Max_Length then
- Result.Current_Length := Length;
-
- if Length > 0 then
- Indx := 1;
+ if Count = 0 or else Ilen <= Max_Length / Count then
+ if Count * Ilen > 0 then
+ Indx := 0;
for J in 1 .. Count loop
- Result.Data (Indx .. Indx + Item'Length - 1) := Item;
- Indx := Indx + Item'Length;
+ Result.Data (Indx + 1 .. Indx + Ilen) :=
+ Super_String_Data (Item);
+ pragma Assert
+ (for all K in 1 .. Ilen =>
+ Result.Data (Indx + K) = Item (Item'First - 1 + K));
+ pragma Assert
+ (String (Result.Data (Indx + 1 .. Indx + Ilen)) = Item);
+ Lemma_Split (Forward);
+ Indx := Indx + Ilen;
+ pragma Loop_Invariant (Indx = J * Ilen);
+ pragma Loop_Invariant (Result.Data (1 .. Indx)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. Indx =>
+ Result.Data (K) =
+ Item (Item'First + (K - 1) mod Ilen));
end loop;
end if;
- else
- Result.Current_Length := Max_Length;
+ Result.Current_Length := Count * Ilen;
+ else
case Drop is
when Strings.Right =>
- Indx := 1;
-
- while Indx + Item'Length <= Max_Length + 1 loop
- Result.Data (Indx .. Indx + Item'Length - 1) := Item;
- Indx := Indx + Item'Length;
+ Indx := 0;
+
+ while Indx < Max_Length - Ilen loop
+ Result.Data (Indx + 1 .. Indx + Ilen) :=
+ Super_String_Data (Item);
+ pragma Assert
+ (for all K in 1 .. Ilen =>
+ Result.Data (Indx + K) = Item (Item'First - 1 + K));
+ pragma Assert
+ (String (Result.Data (Indx + 1 .. Indx + Ilen)) = Item);
+ Lemma_Split (Forward);
+ Indx := Indx + Ilen;
+ pragma Loop_Invariant (Indx mod Ilen = 0);
+ pragma Loop_Invariant (Indx in 0 .. Max_Length - 1);
+ pragma Loop_Invariant (Result.Data (1 .. Indx)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. Indx =>
+ Result.Data (K) =
+ Item (Item'First + (K - 1) mod Ilen));
end loop;
- Result.Data (Indx .. Max_Length) :=
- Item (Item'First .. Item'First + Max_Length - Indx);
+ Result.Data (Indx + 1 .. Max_Length) := Super_String_Data
+ (Item (Item'First .. Item'First + (Max_Length - Indx - 1)));
+ pragma Assert
+ (for all J in Indx + 1 .. Max_Length =>
+ Result.Data (J) = Item (Item'First - 1 - Indx + J));
+
+ for J in Indx + 1 .. Max_Length loop
+ Lemma_Mod (J - 1, Indx);
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Result.Data (K) =
+ Item (Item'First + (K - 1) mod Ilen));
+ end loop;
when Strings.Left =>
Indx := Max_Length;
- while Indx - Item'Length >= 1 loop
- Result.Data (Indx - (Item'Length - 1) .. Indx) := Item;
- Indx := Indx - Item'Length;
+ while Indx > Ilen loop
+ Indx := Indx - Ilen;
+ Result.Data (Indx + 1 .. Indx + Ilen) :=
+ Super_String_Data (Item);
+ pragma Assert
+ (for all K in 1 .. Ilen =>
+ Result.Data (Indx + K) = Item (Item'First - 1 + K));
+ pragma Assert
+ (String (Result.Data (Indx + 1 .. Indx + Ilen)) = Item);
+ Lemma_Split (Backward);
+ Lemma_Mod_Zero (Max_Length - Indx - Ilen);
+ pragma Loop_Invariant
+ ((Max_Length - Indx) mod Ilen = 0);
+ pragma Loop_Invariant (Indx in 1 .. Max_Length);
+ pragma Loop_Invariant
+ (Result.Data (Indx + 1 .. Max_Length)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Indx + 1 .. Max_Length =>
+ Result.Data (K) =
+ Item (Item'Last - (Max_Length - K) mod Ilen));
end loop;
Result.Data (1 .. Indx) :=
- Item (Item'Last - Indx + 1 .. Item'Last);
+ Super_String_Data (Item (Item'Last - Indx + 1 .. Item'Last));
+ pragma Assert
+ (for all J in 1 .. Indx =>
+ Result.Data (J) = Item (Item'Last - Indx + J));
+
+ for J in reverse 1 .. Indx loop
+ Lemma_Mod (Max_Length - J, Max_Length - Indx);
+ pragma Loop_Invariant
+ (for all K in J .. Max_Length =>
+ Result.Data (K) =
+ Item (Item'Last - (Max_Length - K) mod Ilen));
+ end loop;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -1447,11 +1614,7 @@ package body Ada.Strings.Superbounded is
is
begin
return
- Super_Replicate
- (Count,
- Item.Data (1 .. Item.Current_Length),
- Drop,
- Item.Max_Length);
+ Super_Replicate (Count, Super_To_String (Item), Drop, Item.Max_Length);
end Super_Replicate;
-----------------
@@ -1461,42 +1624,20 @@ package body Ada.Strings.Superbounded is
function Super_Slice
(Source : Super_String;
Low : Positive;
- High : Natural) return String
- is
- begin
- -- Note: test of High > Length is in accordance with AI95-00128
-
- return R : String (Low .. High) do
- if Low > Source.Current_Length + 1
- or else High > Source.Current_Length
- then
- raise Index_Error;
- end if;
-
- -- Note: in this case, superflat bounds are not a problem, we just
- -- get the null string in accordance with normal Ada slice rules.
-
- R := Source.Data (Low .. High);
- end return;
- end Super_Slice;
-
- function Super_Slice
- (Source : Super_String;
- Low : Positive;
High : Natural) return Super_String
is
begin
return Result : Super_String (Source.Max_Length) do
- if Low > Source.Current_Length + 1
+ if Low - 1 > Source.Current_Length
or else High > Source.Current_Length
then
raise Index_Error;
end if;
- -- Note: the Max operation here deals with the superflat case
-
- Result.Current_Length := Integer'Max (0, High - Low + 1);
- Result.Data (1 .. Result.Current_Length) := Source.Data (Low .. High);
+ if High >= Low then
+ Result.Data (1 .. High - Low + 1) := Source.Data (Low .. High);
+ Result.Current_Length := High - Low + 1;
+ end if;
end return;
end Super_Slice;
@@ -1507,16 +1648,18 @@ package body Ada.Strings.Superbounded is
High : Natural)
is
begin
- if Low > Source.Current_Length + 1
+ if Low - 1 > Source.Current_Length
or else High > Source.Current_Length
then
raise Index_Error;
end if;
- -- Note: the Max operation here deals with the superflat case
-
- Target.Current_Length := Integer'Max (0, High - Low + 1);
- Target.Data (1 .. Target.Current_Length) := Source.Data (Low .. High);
+ if High >= Low then
+ Target.Data (1 .. High - Low + 1) := Source.Data (Low .. High);
+ Target.Current_Length := High - Low + 1;
+ else
+ Target.Current_Length := 0;
+ end if;
end Super_Slice;
----------------
@@ -1536,18 +1679,22 @@ package body Ada.Strings.Superbounded is
begin
if Npad <= 0 then
- Result.Current_Length := Count;
- Result.Data (1 .. Count) :=
- Source.Data (Slen - (Count - 1) .. Slen);
+ if Count > 0 then
+ Result.Data (1 .. Count) :=
+ Source.Data (Slen - (Count - 1) .. Slen);
+ Result.Current_Length := Count;
+ end if;
elsif Count <= Max_Length then
- Result.Current_Length := Count;
Result.Data (1 .. Npad) := (others => Pad);
- Result.Data (Npad + 1 .. Count) := Source.Data (1 .. Slen);
- else
- Result.Current_Length := Max_Length;
+ if Slen > 0 then
+ Result.Data (Npad + 1 .. Count) := Source.Data (1 .. Slen);
+ end if;
+
+ Result.Current_Length := Count;
+ else
case Drop is
when Strings.Right =>
if Npad >= Max_Length then
@@ -1567,6 +1714,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -1582,22 +1731,27 @@ package body Ada.Strings.Superbounded is
Slen : constant Natural := Source.Current_Length;
Npad : constant Integer := Count - Slen;
- Temp : constant String (1 .. Max_Length) := Source.Data;
+ Temp : constant Super_String_Data (1 .. Max_Length) := Source.Data;
begin
if Npad <= 0 then
Source.Current_Length := Count;
- Source.Data (1 .. Count) :=
- Temp (Slen - (Count - 1) .. Slen);
+
+ if Count > 0 then
+ Source.Data (1 .. Count) :=
+ Temp (Slen - (Count - 1) .. Slen);
+ end if;
elsif Count <= Max_Length then
- Source.Current_Length := Count;
Source.Data (1 .. Npad) := (others => Pad);
- Source.Data (Npad + 1 .. Count) := Temp (1 .. Slen);
- else
- Source.Current_Length := Max_Length;
+ if Slen > 0 then
+ Source.Data (Npad + 1 .. Count) := Temp (1 .. Slen);
+ end if;
+ Source.Current_Length := Count;
+
+ else
case Drop is
when Strings.Right =>
if Npad >= Max_Length then
@@ -1610,31 +1764,19 @@ package body Ada.Strings.Superbounded is
end if;
when Strings.Left =>
- for J in 1 .. Max_Length - Slen loop
- Source.Data (J) := Pad;
- end loop;
-
+ Source.Data (1 .. Max_Length - Slen) := (others => Pad);
Source.Data (Max_Length - Slen + 1 .. Max_Length) :=
Temp (1 .. Slen);
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Source.Current_Length := Max_Length;
end if;
end Super_Tail;
---------------------
- -- Super_To_String --
- ---------------------
-
- function Super_To_String (Source : Super_String) return String is
- begin
- return R : String (1 .. Source.Current_Length) do
- R := Source.Data (1 .. Source.Current_Length);
- end return;
- end Super_To_String;
-
- ---------------------
-- Super_Translate --
---------------------
@@ -1645,12 +1787,15 @@ package body Ada.Strings.Superbounded is
Result : Super_String (Source.Max_Length);
begin
- Result.Current_Length := Source.Current_Length;
-
for J in 1 .. Source.Current_Length loop
Result.Data (J) := Value (Mapping, Source.Data (J));
+ pragma Loop_Invariant (Result.Data (1 .. J)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Result.Data (K) = Value (Mapping, Source.Data (K)));
end loop;
+ Result.Current_Length := Source.Current_Length;
return Result;
end Super_Translate;
@@ -1661,6 +1806,9 @@ package body Ada.Strings.Superbounded is
begin
for J in 1 .. Source.Current_Length loop
Source.Data (J) := Value (Mapping, Source.Data (J));
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Source.Data (K) = Value (Mapping, Source'Loop_Entry.Data (K)));
end loop;
end Super_Translate;
@@ -1671,12 +1819,15 @@ package body Ada.Strings.Superbounded is
Result : Super_String (Source.Max_Length);
begin
- Result.Current_Length := Source.Current_Length;
-
for J in 1 .. Source.Current_Length loop
Result.Data (J) := Mapping.all (Source.Data (J));
+ pragma Loop_Invariant (Result.Data (1 .. J)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Result.Data (K) = Mapping (Source.Data (K)));
end loop;
+ Result.Current_Length := Source.Current_Length;
return Result;
end Super_Translate;
@@ -1687,6 +1838,9 @@ package body Ada.Strings.Superbounded is
begin
for J in 1 .. Source.Current_Length loop
Source.Data (J) := Mapping.all (Source.Data (J));
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Source.Data (K) = Mapping (Source'Loop_Entry.Data (K)));
end loop;
end Super_Translate;
@@ -1699,24 +1853,62 @@ package body Ada.Strings.Superbounded is
Side : Trim_End) return Super_String
is
Result : Super_String (Source.Max_Length);
- Last : Natural := Source.Current_Length;
- First : Positive := 1;
+ Last : constant Natural := Source.Current_Length;
begin
- if Side = Left or else Side = Both then
- while First <= Last and then Source.Data (First) = ' ' loop
- First := First + 1;
- end loop;
- end if;
+ case Side is
+ when Strings.Left =>
+ declare
+ Low : constant Natural :=
+ Super_Index_Non_Blank (Source, Forward);
+ begin
+ -- All blanks case
- if Side = Right or else Side = Both then
- while Last >= First and then Source.Data (Last) = ' ' loop
- Last := Last - 1;
- end loop;
- end if;
+ if Low = 0 then
+ return Result;
+ end if;
+
+ Result.Data (1 .. Last - Low + 1) := Source.Data (Low .. Last);
+ Result.Current_Length := Last - Low + 1;
+ end;
+
+ when Strings.Right =>
+ declare
+ High : constant Natural :=
+ Super_Index_Non_Blank (Source, Backward);
+ begin
+ -- All blanks case
+
+ if High = 0 then
+ return Result;
+ end if;
+
+ Result.Data (1 .. High) := Source.Data (1 .. High);
+ Result.Current_Length := High;
+ end;
+
+ when Strings.Both =>
+ declare
+ Low : constant Natural :=
+ Super_Index_Non_Blank (Source, Forward);
+ begin
+ -- All blanks case
+
+ if Low = 0 then
+ return Result;
+ end if;
+
+ declare
+ High : constant Natural :=
+ Super_Index_Non_Blank (Source, Backward);
+ begin
+ Result.Data (1 .. High - Low + 1) :=
+ Source.Data (Low .. High);
+ Result.Current_Length := High - Low + 1;
+ end;
+ end;
+ end case;
- Result.Current_Length := Last - First + 1;
- Result.Data (1 .. Result.Current_Length) := Source.Data (First .. Last);
return Result;
end Super_Trim;
@@ -1724,28 +1916,54 @@ package body Ada.Strings.Superbounded is
(Source : in out Super_String;
Side : Trim_End)
is
- Max_Length : constant Positive := Source.Max_Length;
- Last : Natural := Source.Current_Length;
- First : Positive := 1;
- Temp : String (1 .. Max_Length);
-
+ Last : constant Natural := Source.Current_Length;
begin
- Temp (1 .. Last) := Source.Data (1 .. Last);
-
- if Side = Left or else Side = Both then
- while First <= Last and then Temp (First) = ' ' loop
- First := First + 1;
- end loop;
- end if;
+ case Side is
+ when Strings.Left =>
+ declare
+ Low : constant Natural :=
+ Super_Index_Non_Blank (Source, Forward);
+ begin
+ -- All blanks case
- if Side = Right or else Side = Both then
- while Last >= First and then Temp (Last) = ' ' loop
- Last := Last - 1;
- end loop;
- end if;
-
- Source.Current_Length := Last - First + 1;
- Source.Data (1 .. Source.Current_Length) := Temp (First .. Last);
+ if Low = 0 then
+ Source.Current_Length := 0;
+ else
+ Source.Data (1 .. Last - Low + 1) :=
+ Source.Data (Low .. Last);
+ Source.Current_Length := Last - Low + 1;
+ end if;
+ end;
+
+ when Strings.Right =>
+ declare
+ High : constant Natural :=
+ Super_Index_Non_Blank (Source, Backward);
+ begin
+ Source.Current_Length := High;
+ end;
+
+ when Strings.Both =>
+ declare
+ Low : constant Natural :=
+ Super_Index_Non_Blank (Source, Forward);
+ begin
+ -- All blanks case
+
+ if Low = 0 then
+ Source.Current_Length := 0;
+ else
+ declare
+ High : constant Natural :=
+ Super_Index_Non_Blank (Source, Backward);
+ begin
+ Source.Data (1 .. High - Low + 1) :=
+ Source.Data (Low .. High);
+ Source.Current_Length := High - Low + 1;
+ end;
+ end if;
+ end;
+ end case;
end Super_Trim;
function Super_Trim
@@ -1754,22 +1972,31 @@ package body Ada.Strings.Superbounded is
Right : Maps.Character_Set) return Super_String
is
Result : Super_String (Source.Max_Length);
+ Low : Natural;
+ High : Natural;
begin
- for First in 1 .. Source.Current_Length loop
- if not Is_In (Source.Data (First), Left) then
- for Last in reverse First .. Source.Current_Length loop
- if not Is_In (Source.Data (Last), Right) then
- Result.Current_Length := Last - First + 1;
- Result.Data (1 .. Result.Current_Length) :=
- Source.Data (First .. Last);
- return Result;
- end if;
- end loop;
- end if;
- end loop;
+ Low := Super_Index (Source, Left, Outside, Forward);
+
+ -- Case where source comprises only characters in Left
+
+ if Low = 0 then
+ return Result;
+ end if;
+
+ High := Super_Index (Source, Right, Outside, Backward);
+
+ -- Case where source comprises only characters in Right
+
+ if High = 0 then
+ return Result;
+ end if;
+
+ if High >= Low then
+ Result.Data (1 .. High - Low + 1) := Source.Data (Low .. High);
+ Result.Current_Length := High - Low + 1;
+ end if;
- Result.Current_Length := 0;
return Result;
end Super_Trim;
@@ -1778,29 +2005,39 @@ package body Ada.Strings.Superbounded is
Left : Maps.Character_Set;
Right : Maps.Character_Set)
is
+ Last : constant Natural := Source.Current_Length;
+ Temp : Super_String_Data (1 .. Last);
+ Low : Natural;
+ High : Natural;
+
begin
- for First in 1 .. Source.Current_Length loop
- if not Is_In (Source.Data (First), Left) then
- for Last in reverse First .. Source.Current_Length loop
- if not Is_In (Source.Data (Last), Right) then
- if First = 1 then
- Source.Current_Length := Last;
- return;
- else
- Source.Current_Length := Last - First + 1;
- Source.Data (1 .. Source.Current_Length) :=
- Source.Data (First .. Last);
- return;
- end if;
- end if;
- end loop;
+ Temp := Source.Data (1 .. Last);
+ Low := Super_Index (Source, Left, Outside, Forward);
+
+ -- Case where source comprises only characters in Left
+
+ if Low = 0 then
+ Source.Current_Length := 0;
+
+ else
+ High := Super_Index (Source, Right, Outside, Backward);
+ -- Case where source comprises only characters in Right
+
+ if High = 0 then
Source.Current_Length := 0;
- return;
- end if;
- end loop;
- Source.Current_Length := 0;
+ elsif Low = 1 then
+ Source.Current_Length := High;
+
+ elsif High < Low then
+ Source.Current_Length := 0;
+
+ else
+ Source.Data (1 .. High - Low + 1) := Temp (Low .. High);
+ Source.Current_Length := High - Low + 1;
+ end if;
+ end if;
end Super_Trim;
-----------
@@ -1819,11 +2056,14 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
else
- Result.Current_Length := Left;
-
for J in 1 .. Left loop
Result.Data (J) := Right;
+ pragma Loop_Invariant (Result.Data (1 .. J)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. J => Result.Data (K) = Right);
end loop;
+
+ Result.Current_Length := Left;
end if;
return Result;
@@ -1835,23 +2075,88 @@ package body Ada.Strings.Superbounded is
Max_Length : Positive) return Super_String
is
Result : Super_String (Max_Length);
- Pos : Positive := 1;
+ Pos : Natural := 0;
Rlen : constant Natural := Right'Length;
Nlen : constant Natural := Left * Rlen;
+ -- Parts of the proof involving manipulations with the modulo operator
+ -- are complicated for the prover and can't be done automatically in
+ -- the global subprogram. That's why we isolate them in these two ghost
+ -- lemmas.
+
+ procedure Lemma_Mod (K : Integer) with
+ Ghost,
+ Pre =>
+ Rlen /= 0
+ and then Pos mod Rlen = 0
+ and then Pos in 0 .. Max_Length - Rlen
+ and then K in Pos .. Pos + Rlen - 1,
+ Post => K mod Rlen = K - Pos;
+ -- Lemma_Mod is applied to an index considered in Lemma_Split to prove
+ -- that it has the right value modulo Right'Length.
+
+ procedure Lemma_Split with
+ Ghost,
+ Pre =>
+ Rlen /= 0
+ and then Pos mod Rlen = 0
+ and then Pos in 0 .. Max_Length - Rlen
+ and then Result.Data (1 .. Pos + Rlen)'Initialized
+ and then String (Result.Data (Pos + 1 .. Pos + Rlen)) = Right,
+ Post =>
+ (for all K in Pos + 1 .. Pos + Rlen =>
+ Result.Data (K) = Right (Right'First + (K - 1) mod Rlen));
+ -- Lemma_Split is used after Result.Data (Pos + 1 .. Pos + Rlen) is
+ -- updated to Right and concludes that the characters match for each
+ -- index when taken modulo Right'Length, as the considered slice starts
+ -- at index 1 modulo Right'Length.
+
+ ---------------
+ -- Lemma_Mod --
+ ---------------
+
+ procedure Lemma_Mod (K : Integer) is null;
+
+ -----------------
+ -- Lemma_Split --
+ -----------------
+
+ procedure Lemma_Split is
+ begin
+ for K in Pos + 1 .. Pos + Rlen loop
+ Lemma_Mod (K - 1);
+ pragma Loop_Invariant
+ (for all J in Pos + 1 .. K =>
+ Result.Data (J) = Right (Right'First + (J - 1) mod Rlen));
+ end loop;
+ end Lemma_Split;
+
begin
if Nlen > Max_Length then
raise Ada.Strings.Length_Error;
else
- Result.Current_Length := Nlen;
-
if Nlen > 0 then
for J in 1 .. Left loop
- Result.Data (Pos .. Pos + Rlen - 1) := Right;
+ Result.Data (Pos + 1 .. Pos + Rlen) :=
+ Super_String_Data (Right);
+ pragma Assert
+ (for all K in 1 .. Rlen => Result.Data (Pos + K) =
+ Right (Right'First - 1 + K));
+ pragma Assert
+ (String (Result.Data (Pos + 1 .. Pos + Rlen)) = Right);
+ Lemma_Split;
Pos := Pos + Rlen;
+ pragma Loop_Invariant (Pos = J * Rlen);
+ pragma Loop_Invariant (Result.Data (1 .. Pos)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. Pos =>
+ Result.Data (K) =
+ Right (Right'First + (K - 1) mod Rlen));
end loop;
end if;
+
+ Result.Current_Length := Nlen;
end if;
return Result;
@@ -1862,7 +2167,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Super_String
is
Result : Super_String (Right.Max_Length);
- Pos : Positive := 1;
+ Pos : Natural := 0;
Rlen : constant Natural := Right.Current_Length;
Nlen : constant Natural := Left * Rlen;
@@ -1871,15 +2176,21 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
else
- Result.Current_Length := Nlen;
-
if Nlen > 0 then
for J in 1 .. Left loop
- Result.Data (Pos .. Pos + Rlen - 1) :=
+ Result.Data (Pos + 1 .. Pos + Rlen) :=
Right.Data (1 .. Rlen);
Pos := Pos + Rlen;
+ pragma Loop_Invariant (Pos = J * Rlen);
+ pragma Loop_Invariant (Result.Data (1 .. Pos)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. Pos =>
+ Result.Data (K) =
+ Right.Data (1 + (K - 1) mod Rlen));
end loop;
end if;
+
+ Result.Current_Length := Nlen;
end if;
return Result;
@@ -1891,7 +2202,7 @@ package body Ada.Strings.Superbounded is
function To_Super_String
(Source : String;
- Max_Length : Natural;
+ Max_Length : Positive;
Drop : Truncation := Error) return Super_String
is
Result : Super_String (Max_Length);
@@ -1899,20 +2210,20 @@ package body Ada.Strings.Superbounded is
begin
if Slen <= Max_Length then
+ Result.Data (1 .. Slen) := Super_String_Data (Source);
Result.Current_Length := Slen;
- Result.Data (1 .. Slen) := Source;
else
case Drop is
when Strings.Right =>
+ Result.Data (1 .. Max_Length) := Super_String_Data
+ (Source (Source'First .. Source'First - 1 + Max_Length));
Result.Current_Length := Max_Length;
- Result.Data (1 .. Max_Length) :=
- Source (Source'First .. Source'First - 1 + Max_Length);
when Strings.Left =>
+ Result.Data (1 .. Max_Length) := Super_String_Data
+ (Source (Source'Last - (Max_Length - 1) .. Source'Last));
Result.Current_Length := Max_Length;
- Result.Data (1 .. Max_Length) :=
- Source (Source'Last - (Max_Length - 1) .. Source'Last);
when Strings.Error =>
raise Ada.Strings.Length_Error;
diff --git a/gcc/ada/libgnat/a-strsup.ads b/gcc/ada/libgnat/a-strsup.ads
index 9e568a8..7428e9c 100644
--- a/gcc/ada/libgnat/a-strsup.ads
+++ b/gcc/ada/libgnat/a-strsup.ads
@@ -36,28 +36,47 @@
-- length as the discriminant. Individual instantiations of Strings.Bounded
-- use this type with an appropriate discriminant value set.
-with Ada.Strings.Maps;
+-- Preconditions in this unit are meant for analysis only, not for run-time
+-- checking, so that the expected exceptions are raised. This is enforced by
+-- setting the corresponding assertion policy to Ignore. Postconditions and
+-- contract cases should not be executed at runtime as well, in order not to
+-- slow down the execution of these functions.
-package Ada.Strings.Superbounded is
+pragma Assertion_Policy (Pre => Ignore,
+ Post => Ignore,
+ Contract_Cases => Ignore,
+ Ghost => Ignore);
+
+with Ada.Strings.Maps; use type Ada.Strings.Maps.Character_Mapping_Function;
+with Ada.Strings.Search;
+
+package Ada.Strings.Superbounded with SPARK_Mode is
pragma Preelaborate;
-- Type Bounded_String in Ada.Strings.Bounded.Generic_Bounded_Length is
-- derived from Super_String, with the constraint of the maximum length.
+ type Super_String_Data is new String with Relaxed_Initialization;
+
type Super_String (Max_Length : Positive) is record
Current_Length : Natural := 0;
- Data : String (1 .. Max_Length);
+ Data : Super_String_Data (1 .. Max_Length);
-- A previous version had a default initial value for Data, which is
-- no longer necessary, because we now special-case this type in the
-- compiler, so "=" composes properly for descendants of this type.
-- Leaving it out is more efficient.
- end record;
+ end record
+ with
+ Predicate =>
+ Current_Length <= Max_Length
+ and then Data (1 .. Current_Length)'Initialized;
-- The subprograms defined for Super_String are similar to those
-- defined for Bounded_String, except that they have different names, so
-- that they can be renamed in Ada.Strings.Bounded.Generic_Bounded_Length.
- function Super_Length (Source : Super_String) return Natural;
+ function Super_Length (Source : Super_String) return Natural
+ is (Source.Current_Length);
--------------------------------------------------------
-- Conversion, Concatenation, and Selection Functions --
@@ -65,109 +84,606 @@ package Ada.Strings.Superbounded is
function To_Super_String
(Source : String;
- Max_Length : Natural;
- Drop : Truncation := Error) return Super_String;
+ Max_Length : Positive;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre => (if Source'Length > Max_Length then Drop /= Error),
+ Post => To_Super_String'Result.Max_Length = Max_Length,
+ Contract_Cases =>
+ (Source'Length <= Max_Length
+ =>
+ Super_To_String (To_Super_String'Result) = Source,
+
+ Source'Length > Max_Length and then Drop = Left
+ =>
+ Super_To_String (To_Super_String'Result) =
+ Source (Source'Last - Max_Length + 1 .. Source'Last),
+
+ others -- Drop = Right
+ =>
+ Super_To_String (To_Super_String'Result) =
+ Source (Source'First .. Source'First - 1 + Max_Length)),
+ Global => null;
-- Note the additional parameter Max_Length, which specifies the maximum
-- length setting of the resulting Super_String value.
-- The following procedures have declarations (and semantics) that are
-- exactly analogous to those declared in Ada.Strings.Bounded.
- function Super_To_String (Source : Super_String) return String;
+ function Super_To_String (Source : Super_String) return String
+ is (String (Source.Data (1 .. Source.Current_Length)));
procedure Set_Super_String
(Target : out Super_String;
Source : String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ (if Source'Length > Target.Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Source'Length <= Target.Max_Length
+ =>
+ Super_To_String (Target) = Source,
+
+ Source'Length > Target.Max_Length and then Drop = Left
+ =>
+ Super_To_String (Target) =
+ Source (Source'Last - Target.Max_Length + 1 .. Source'Last),
+
+ others -- Drop = Right
+ =>
+ Super_To_String (Target) =
+ Source (Source'First .. Source'First - 1 + Target.Max_Length)),
+ Global => null;
function Super_Append
(Left : Super_String;
Right : Super_String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ Left.Max_Length = Right.Max_Length
+ and then
+ (if Super_Length (Left) > Left.Max_Length - Super_Length (Right)
+ then Drop /= Error),
+ Post => Super_Append'Result.Max_Length = Left.Max_Length,
+ Contract_Cases =>
+ (Super_Length (Left) <= Left.Max_Length - Super_Length (Right)
+ =>
+ Super_Length (Super_Append'Result) =
+ Super_Length (Left) + Super_Length (Right)
+ and then
+ Super_Slice (Super_Append'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Super_Length (Right) > 0 then
+ Super_Slice (Super_Append'Result,
+ Super_Length (Left) + 1,
+ Super_Length (Super_Append'Result)) =
+ Super_To_String (Right)),
+
+ Super_Length (Left) > Left.Max_Length - Super_Length (Right)
+ and then Drop = Strings.Left
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ (if Super_Length (Right) < Left.Max_Length then
+ String'(Super_Slice (Super_Append'Result,
+ 1, Left.Max_Length - Super_Length (Right))) =
+ Super_Slice (Left,
+ Super_Length (Left) - Left.Max_Length
+ + Super_Length (Right) + 1,
+ Super_Length (Left)))
+ and then
+ Super_Slice (Super_Append'Result,
+ Left.Max_Length - Super_Length (Right) + 1, Left.Max_Length) =
+ Super_To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ Super_Slice (Super_Append'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Super_Length (Left) < Left.Max_Length then
+ String'(Super_Slice (Super_Append'Result,
+ Super_Length (Left) + 1, Left.Max_Length)) =
+ Super_Slice (Right,
+ 1, Left.Max_Length - Super_Length (Left)))),
+ Global => null;
function Super_Append
(Left : Super_String;
Right : String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ (if Right'Length > Left.Max_Length - Super_Length (Left)
+ then Drop /= Error),
+ Post => Super_Append'Result.Max_Length = Left.Max_Length,
+ Contract_Cases =>
+ (Super_Length (Left) <= Left.Max_Length - Right'Length
+ =>
+ Super_Length (Super_Append'Result) =
+ Super_Length (Left) + Right'Length
+ and then
+ Super_Slice (Super_Append'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Right'Length > 0 then
+ Super_Slice (Super_Append'Result,
+ Super_Length (Left) + 1,
+ Super_Length (Super_Append'Result)) =
+ Right),
+
+ Super_Length (Left) > Left.Max_Length - Right'Length
+ and then Drop = Strings.Left
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ (if Right'Length < Left.Max_Length then
+
+ -- The result is the end of Left followed by Right
+
+ String'(Super_Slice (Super_Append'Result,
+ 1, Left.Max_Length - Right'Length)) =
+ Super_Slice (Left,
+ Super_Length (Left) - Left.Max_Length + Right'Length
+ + 1,
+ Super_Length (Left))
+ and then
+ Super_Slice (Super_Append'Result,
+ Left.Max_Length - Right'Length + 1, Left.Max_Length) =
+ Right
+ else
+ -- The result is the last Max_Length characters of Right
+
+ Super_To_String (Super_Append'Result) =
+ Right (Right'Last - Left.Max_Length + 1 .. Right'Last)),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ Super_Slice (Super_Append'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Super_Length (Left) < Left.Max_Length then
+ Super_Slice (Super_Append'Result,
+ Super_Length (Left) + 1, Left.Max_Length) =
+ Right (Right'First
+ .. Left.Max_Length - Super_Length (Left)
+ - 1 + Right'First))),
+ Global => null;
function Super_Append
(Left : String;
Right : Super_String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ (if Left'Length > Right.Max_Length - Super_Length (Right)
+ then Drop /= Error),
+ Post => Super_Append'Result.Max_Length = Right.Max_Length,
+ Contract_Cases =>
+ (Left'Length <= Right.Max_Length - Super_Length (Right)
+ =>
+ Super_Length (Super_Append'Result) =
+ Left'Length + Super_Length (Right)
+ and then Super_Slice (Super_Append'Result, 1, Left'Length) = Left
+ and then
+ (if Super_Length (Right) > 0 then
+ Super_Slice (Super_Append'Result,
+ Left'Length + 1, Super_Length (Super_Append'Result)) =
+ Super_To_String (Right)),
+
+ Left'Length > Right.Max_Length - Super_Length (Right)
+ and then Drop = Strings.Left
+ =>
+ Super_Length (Super_Append'Result) = Right.Max_Length
+ and then
+ (if Super_Length (Right) < Right.Max_Length then
+ Super_Slice (Super_Append'Result,
+ 1, Right.Max_Length - Super_Length (Right)) =
+ Left
+ (Left'Last - Right.Max_Length + Super_Length (Right) + 1
+ .. Left'Last))
+ and then
+ Super_Slice (Super_Append'Result,
+ Right.Max_Length - Super_Length (Right) + 1,
+ Right.Max_Length) =
+ Super_To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Super_Append'Result) = Right.Max_Length
+ and then
+ (if Left'Length < Right.Max_Length then
+
+ -- The result is Left followed by the beginning of Right
+
+ Super_Slice (Super_Append'Result, 1, Left'Length) = Left
+ and then
+ String'(Super_Slice (Super_Append'Result,
+ Left'Length + 1, Right.Max_Length)) =
+ Super_Slice (Right, 1, Right.Max_Length - Left'Length)
+ else
+ -- The result is the first Max_Length characters of Left
+
+ Super_To_String (Super_Append'Result) =
+ Left (Left'First .. Right.Max_Length - 1 + Left'First))),
+ Global => null;
function Super_Append
(Left : Super_String;
Right : Character;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ (if Super_Length (Left) = Left.Max_Length then Drop /= Error),
+ Post => Super_Append'Result.Max_Length = Left.Max_Length,
+ Contract_Cases =>
+ (Super_Length (Left) < Left.Max_Length
+ =>
+ Super_Length (Super_Append'Result) = Super_Length (Left) + 1
+ and then
+ Super_Slice (Super_Append'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ Super_Element (Super_Append'Result, Super_Length (Left) + 1) =
+ Right,
+
+ Super_Length (Left) = Left.Max_Length and then Drop = Strings.Right
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ Super_To_String (Super_Append'Result) = Super_To_String (Left),
+
+ others -- Drop = Left
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ String'(Super_Slice (Super_Append'Result,
+ 1, Left.Max_Length - 1)) =
+ Super_Slice (Left, 2, Left.Max_Length)
+ and then
+ Super_Element (Super_Append'Result, Left.Max_Length) = Right),
+ Global => null;
function Super_Append
(Left : Character;
Right : Super_String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ (if Super_Length (Right) = Right.Max_Length then Drop /= Error),
+ Post => Super_Append'Result.Max_Length = Right.Max_Length,
+ Contract_Cases =>
+ (Super_Length (Right) < Right.Max_Length
+ =>
+ Super_Length (Super_Append'Result) = Super_Length (Right) + 1
+ and then
+ Super_Slice (Super_Append'Result, 2, Super_Length (Right) + 1) =
+ Super_To_String (Right)
+ and then Super_Element (Super_Append'Result, 1) = Left,
+
+ Super_Length (Right) = Right.Max_Length and then Drop = Strings.Left
+ =>
+ Super_Length (Super_Append'Result) = Right.Max_Length
+ and then
+ Super_To_String (Super_Append'Result) = Super_To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Super_Append'Result) = Right.Max_Length
+ and then
+ String'(Super_Slice (Super_Append'Result, 2, Right.Max_Length)) =
+ Super_Slice (Right, 1, Right.Max_Length - 1)
+ and then Super_Element (Super_Append'Result, 1) = Left),
+ Global => null;
procedure Super_Append
(Source : in out Super_String;
New_Item : Super_String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ Source.Max_Length = New_Item.Max_Length
+ and then
+ (if Super_Length (Source) >
+ Source.Max_Length - Super_Length (New_Item)
+ then Drop /= Error),
+ Contract_Cases =>
+ (Super_Length (Source) <= Source.Max_Length - Super_Length (New_Item)
+ =>
+ Super_Length (Source) =
+ Super_Length (Source'Old) + Super_Length (New_Item)
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ (if Super_Length (New_Item) > 0 then
+ Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Super_Length (Source)) =
+ Super_To_String (New_Item)),
+
+ Super_Length (Source) > Source.Max_Length - Super_Length (New_Item)
+ and then Drop = Left
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then
+ (if Super_Length (New_Item) < Source.Max_Length then
+ String'(Super_Slice (Source,
+ 1, Source.Max_Length - Super_Length (New_Item))) =
+ Super_Slice (Source'Old,
+ Super_Length (Source'Old) - Source.Max_Length
+ + Super_Length (New_Item) + 1,
+ Super_Length (Source'Old)))
+ and then
+ Super_Slice (Source,
+ Source.Max_Length - Super_Length (New_Item) + 1,
+ Source.Max_Length) =
+ Super_To_String (New_Item),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ (if Super_Length (Source'Old) < Source.Max_Length then
+ String'(Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Source.Max_Length)) =
+ Super_Slice (New_Item,
+ 1, Source.Max_Length - Super_Length (Source'Old)))),
+ Global => null;
procedure Super_Append
(Source : in out Super_String;
New_Item : String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ (if New_Item'Length > Source.Max_Length - Super_Length (Source)
+ then Drop /= Error),
+ Contract_Cases =>
+ (Super_Length (Source) <= Source.Max_Length - New_Item'Length
+ =>
+ Super_Length (Source) = Super_Length (Source'Old) + New_Item'Length
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ (if New_Item'Length > 0 then
+ Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Super_Length (Source)) =
+ New_Item),
+
+ Super_Length (Source) > Source.Max_Length - New_Item'Length
+ and then Drop = Left
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then
+ (if New_Item'Length < Source.Max_Length then
+
+ -- The result is the end of Source followed by New_Item
+
+ String'(Super_Slice (Source,
+ 1, Source.Max_Length - New_Item'Length)) =
+ Super_Slice (Source'Old,
+ Super_Length (Source'Old) - Source.Max_Length
+ + New_Item'Length + 1,
+ Super_Length (Source'Old))
+ and then
+ Super_Slice (Source,
+ Source.Max_Length - New_Item'Length + 1,
+ Source.Max_Length) =
+ New_Item
+ else
+ -- The result is the last Max_Length characters of
+ -- New_Item.
+
+ Super_To_String (Source) = New_Item
+ (New_Item'Last - Source.Max_Length + 1 .. New_Item'Last)),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ (if Super_Length (Source'Old) < Source.Max_Length then
+ Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Source.Max_Length) =
+ New_Item (New_Item'First
+ .. Source.Max_Length - Super_Length (Source'Old) - 1
+ + New_Item'First))),
+ Global => null;
procedure Super_Append
(Source : in out Super_String;
New_Item : Character;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ (if Super_Length (Source) = Source.Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Super_Length (Source) < Source.Max_Length
+ =>
+ Super_Length (Source) = Super_Length (Source'Old) + 1
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ Super_Element (Source, Super_Length (Source'Old) + 1) = New_Item,
+
+ Super_Length (Source) = Source.Max_Length and then Drop = Right
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then Super_To_String (Source) = Super_To_String (Source'Old),
+
+ others -- Drop = Left
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source, 1, Source.Max_Length - 1)) =
+ Super_Slice (Source'Old, 2, Source.Max_Length)
+ and then Super_Element (Source, Source.Max_Length) = New_Item),
+ Global => null;
function Concat
(Left : Super_String;
- Right : Super_String) return Super_String;
+ Right : Super_String) return Super_String
+ with
+ Pre => Left.Max_Length = Right.Max_Length
+ and then Super_Length (Left) <= Left.Max_Length - Super_Length (Right),
+ Post => Concat'Result.Max_Length = Left.Max_Length
+ and then
+ Super_Length (Concat'Result) =
+ Super_Length (Left) + Super_Length (Right)
+ and then
+ Super_Slice (Concat'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Super_Length (Right) > 0 then
+ Super_Slice (Concat'Result,
+ Super_Length (Left) + 1, Super_Length (Concat'Result)) =
+ Super_To_String (Right)),
+ Global => null;
function Concat
(Left : Super_String;
- Right : String) return Super_String;
+ Right : String) return Super_String
+ with
+ Pre => Right'Length <= Left.Max_Length - Super_Length (Left),
+ Post => Concat'Result.Max_Length = Left.Max_Length
+ and then
+ Super_Length (Concat'Result) = Super_Length (Left) + Right'Length
+ and then
+ Super_Slice (Concat'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Right'Length > 0 then
+ Super_Slice (Concat'Result,
+ Super_Length (Left) + 1, Super_Length (Concat'Result)) =
+ Right),
+ Global => null;
function Concat
(Left : String;
- Right : Super_String) return Super_String;
+ Right : Super_String) return Super_String
+ with
+ Pre => Left'Length <= Right.Max_Length - Super_Length (Right),
+ Post => Concat'Result.Max_Length = Right.Max_Length
+ and then
+ Super_Length (Concat'Result) = Left'Length + Super_Length (Right)
+ and then Super_Slice (Concat'Result, 1, Left'Length) = Left
+ and then
+ (if Super_Length (Right) > 0 then
+ Super_Slice (Concat'Result,
+ Left'Length + 1, Super_Length (Concat'Result)) =
+ Super_To_String (Right)),
+ Global => null;
function Concat
(Left : Super_String;
- Right : Character) return Super_String;
+ Right : Character) return Super_String
+ with
+ Pre => Super_Length (Left) < Left.Max_Length,
+ Post => Concat'Result.Max_Length = Left.Max_Length
+ and then Super_Length (Concat'Result) = Super_Length (Left) + 1
+ and then
+ Super_Slice (Concat'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then Super_Element (Concat'Result, Super_Length (Left) + 1) = Right,
+ Global => null;
function Concat
(Left : Character;
- Right : Super_String) return Super_String;
+ Right : Super_String) return Super_String
+ with
+ Pre => Super_Length (Right) < Right.Max_Length,
+ Post => Concat'Result.Max_Length = Right.Max_Length
+ and then Super_Length (Concat'Result) = 1 + Super_Length (Right)
+ and then Super_Element (Concat'Result, 1) = Left
+ and then
+ Super_Slice (Concat'Result, 2, Super_Length (Concat'Result)) =
+ Super_To_String (Right),
+ Global => null;
function Super_Element
(Source : Super_String;
- Index : Positive) return Character;
+ Index : Positive) return Character
+ is (if Index <= Source.Current_Length
+ then Source.Data (Index)
+ else raise Index_Error)
+ with Pre => Index <= Super_Length (Source);
procedure Super_Replace_Element
(Source : in out Super_String;
Index : Positive;
- By : Character);
+ By : Character)
+ with
+ Pre => Index <= Super_Length (Source),
+ Post => Super_Length (Source) = Super_Length (Source'Old)
+ and then
+ (for all K in 1 .. Super_Length (Source) =>
+ Super_Element (Source, K) =
+ (if K = Index then By else Super_Element (Source'Old, K))),
+ Global => null;
function Super_Slice
(Source : Super_String;
Low : Positive;
- High : Natural) return String;
+ High : Natural) return String
+ is (if Low - 1 > Source.Current_Length or else High > Source.Current_Length
+
+ -- Note: test of High > Length is in accordance with AI95-00128
+
+ then raise Index_Error
+ else
+ -- Note: in this case, superflat bounds are not a problem, we just
+ -- get the null string in accordance with normal Ada slice rules.
+
+ String (Source.Data (Low .. High)))
+ with Pre => Low - 1 <= Super_Length (Source)
+ and then High <= Super_Length (Source);
function Super_Slice
(Source : Super_String;
Low : Positive;
- High : Natural) return Super_String;
+ High : Natural) return Super_String
+ with
+ Pre =>
+ Low - 1 <= Super_Length (Source) and then High <= Super_Length (Source),
+ Post => Super_Slice'Result.Max_Length = Source.Max_Length
+ and then
+ Super_To_String (Super_Slice'Result) =
+ Super_Slice (Source, Low, High),
+ Global => null;
procedure Super_Slice
(Source : Super_String;
Target : out Super_String;
Low : Positive;
- High : Natural);
+ High : Natural)
+ with
+ Pre => Source.Max_Length = Target.Max_Length
+ and then Low - 1 <= Super_Length (Source)
+ and then High <= Super_Length (Source),
+ Post => Super_To_String (Target) = Super_Slice (Source, Low, High),
+ Global => null;
function "="
(Left : Super_String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Pre => Left.Max_Length = Right.Max_Length,
+ Post => "="'Result = (Super_To_String (Left) = Super_To_String (Right)),
+ Global => null;
function Equal
(Left : Super_String;
@@ -175,59 +691,111 @@ package Ada.Strings.Superbounded is
function Equal
(Left : Super_String;
- Right : String) return Boolean;
+ Right : String) return Boolean
+ with
+ Post => Equal'Result = (Super_To_String (Left) = Right),
+ Global => null;
function Equal
(Left : String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Post => Equal'Result = (Left = Super_To_String (Right)),
+ Global => null;
function Less
(Left : Super_String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Pre => Left.Max_Length = Right.Max_Length,
+ Post =>
+ Less'Result = (Super_To_String (Left) < Super_To_String (Right)),
+ Global => null;
function Less
(Left : Super_String;
- Right : String) return Boolean;
+ Right : String) return Boolean
+ with
+ Post => Less'Result = (Super_To_String (Left) < Right),
+ Global => null;
function Less
(Left : String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Post => Less'Result = (Left < Super_To_String (Right)),
+ Global => null;
function Less_Or_Equal
(Left : Super_String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Pre => Left.Max_Length = Right.Max_Length,
+ Post =>
+ Less_Or_Equal'Result =
+ (Super_To_String (Left) <= Super_To_String (Right)),
+ Global => null;
function Less_Or_Equal
(Left : Super_String;
- Right : String) return Boolean;
+ Right : String) return Boolean
+ with
+ Post => Less_Or_Equal'Result = (Super_To_String (Left) <= Right),
+ Global => null;
function Less_Or_Equal
(Left : String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Post => Less_Or_Equal'Result = (Left <= Super_To_String (Right)),
+ Global => null;
function Greater
(Left : Super_String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Pre => Left.Max_Length = Right.Max_Length,
+ Post =>
+ Greater'Result = (Super_To_String (Left) > Super_To_String (Right)),
+ Global => null;
function Greater
(Left : Super_String;
- Right : String) return Boolean;
+ Right : String) return Boolean
+ with
+ Post => Greater'Result = (Super_To_String (Left) > Right),
+ Global => null;
function Greater
(Left : String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Post => Greater'Result = (Left > Super_To_String (Right)),
+ Global => null;
function Greater_Or_Equal
(Left : Super_String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Pre => Left.Max_Length = Right.Max_Length,
+ Post =>
+ Greater_Or_Equal'Result =
+ (Super_To_String (Left) >= Super_To_String (Right)),
+ Global => null;
function Greater_Or_Equal
(Left : Super_String;
- Right : String) return Boolean;
+ Right : String) return Boolean
+ with
+ Post => Greater_Or_Equal'Result = (Super_To_String (Left) >= Right),
+ Global => null;
function Greater_Or_Equal
(Left : String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Post => Greater_Or_Equal'Result = (Left >= Super_To_String (Right)),
+ Global => null;
----------------------
-- Search Functions --
@@ -237,63 +805,449 @@ package Ada.Strings.Superbounded is
(Source : Super_String;
Pattern : String;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping := Maps.Identity) return Natural;
+ Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
+ with
+ Pre => Pattern'Length > 0,
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Super_Length (Source) = 0
+ =>
+ Super_Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Super_Length (Source) > 0
+ and then
+ (for some J in 1 .. Super_Length (Source) - (Pattern'Length - 1) =>
+ Search.Match (Super_To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index'Result in
+ 1 .. Super_Length (Source) - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (Super_To_String (Source), Pattern, Mapping, Super_Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if (if Going = Forward
+ then J <= Super_Index'Result - 1
+ else J - 1 in Super_Index'Result
+ .. Super_Length (Source) - Pattern'Length)
+ then not (Search.Match
+ (Super_To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Super_Index'Result = 0),
+ Global => null;
function Super_Index
(Source : Super_String;
Pattern : String;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping_Function) return Natural;
+ Mapping : Maps.Character_Mapping_Function) return Natural
+ with
+ Pre => Pattern'Length /= 0 and then Mapping /= null,
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Super_Length (Source) = 0
+ =>
+ Super_Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Super_Length (Source) > 0
+ and then
+ (for some J in 1 .. Super_Length (Source) - (Pattern'Length - 1) =>
+ Search.Match (Super_To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index'Result in
+ 1 .. Super_Length (Source) - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (Super_To_String (Source), Pattern, Mapping, Super_Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if (if Going = Forward
+ then J <= Super_Index'Result - 1
+ else J - 1 in Super_Index'Result
+ .. Super_Length (Source) - Pattern'Length)
+ then not (Search.Match
+ (Super_To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Super_Index'Result = 0),
+ Global => null;
function Super_Index
(Source : Super_String;
Set : Maps.Character_Set;
Test : Membership := Inside;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If no character of Source satisfies the property Test on Set,
+ -- then 0 is returned.
+
+ ((for all C of Super_To_String (Source) =>
+ (Test = Inside) /= Maps.Is_In (C, Set))
+ =>
+ Super_Index'Result = 0,
+
+ -- Otherwise, an index in the range of Source is returned
+
+ others
+ =>
+ -- The result is in the range of Source
+
+ Super_Index'Result in 1 .. Super_Length (Source)
+
+ -- The character at the returned index satisfies the property
+ -- Test on Set.
+
+ and then
+ (Test = Inside) =
+ Maps.Is_In (Super_Element (Source, Super_Index'Result), Set)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the property, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J /= Super_Index'Result
+ and then (J < Super_Index'Result) = (Going = Forward)
+ then (Test = Inside)
+ /= Maps.Is_In (Super_Element (Source, J), Set)))),
+ Global => null;
function Super_Index
(Source : Super_String;
Pattern : String;
From : Positive;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping := Maps.Identity) return Natural;
+ Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
+ with
+ Pre =>
+ (if Super_Length (Source) /= 0 then From <= Super_Length (Source))
+ and then Pattern'Length /= 0,
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Super_Length (Source) = 0
+ =>
+ Super_Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Super_Length (Source) > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Super_Length (Source) else From)
+ - (Pattern'Length - 1) =>
+ Search.Match (Super_To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index'Result in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Super_Length (Source) else From)
+ - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (Super_To_String (Source), Pattern, Mapping, Super_Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if (if Going = Forward
+ then J in From .. Super_Index'Result - 1
+ else J - 1 in Super_Index'Result
+ .. From - Pattern'Length)
+ then not (Search.Match
+ (Super_To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Super_Index'Result = 0),
+ Global => null;
function Super_Index
(Source : Super_String;
Pattern : String;
From : Positive;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping_Function) return Natural;
+ Mapping : Maps.Character_Mapping_Function) return Natural
+ with
+ Pre =>
+ (if Super_Length (Source) /= 0 then From <= Super_Length (Source))
+ and then Pattern'Length /= 0
+ and then Mapping /= null,
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Super_Length (Source) = 0
+ =>
+ Super_Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Super_Length (Source) > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Super_Length (Source) else From)
+ - (Pattern'Length - 1) =>
+ Search.Match (Super_To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index'Result in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Super_Length (Source) else From)
+ - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (Super_To_String (Source), Pattern, Mapping, Super_Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if (if Going = Forward
+ then J in From .. Super_Index'Result - 1
+ else J - 1 in Super_Index'Result
+ .. From - Pattern'Length)
+ then not (Search.Match
+ (Super_To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Super_Index'Result = 0),
+ Global => null;
function Super_Index
(Source : Super_String;
Set : Maps.Character_Set;
From : Positive;
Test : Membership := Inside;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ Pre =>
+ (if Super_Length (Source) /= 0 then From <= Super_Length (Source)),
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or no character of the considered
+ -- slice of Source satisfies the property Test on Set, then 0 is
+ -- returned.
+
+ (Super_Length (Source) = 0
+ or else
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ (Test = Inside) /=
+ Maps.Is_In (Super_Element (Source, J), Set)))
+ =>
+ Super_Index'Result = 0,
+
+ -- Otherwise, an index in the considered range of Source is returned
+
+ others
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index'Result in 1 .. Super_Length (Source)
+ and then
+ (Super_Index'Result = From
+ or else (Super_Index'Result > From) = (Going = Forward))
+
+ -- The character at the returned index satisfies the property
+ -- Test on Set.
+
+ and then
+ (Test = Inside) =
+ Maps.Is_In (Super_Element (Source, Super_Index'Result), Set)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the property, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J /= Super_Index'Result
+ and then (J < Super_Index'Result) = (Going = Forward)
+ and then (J = From
+ or else (J > From) = (Going = Forward))
+ then (Test = Inside)
+ /= Maps.Is_In (Super_Element (Source, J), Set)))),
+ Global => null;
function Super_Index_Non_Blank
(Source : Super_String;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ Post => Super_Index_Non_Blank'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If all characters of Source are Space characters, then 0 is
+ -- returned.
+
+ ((for all C of Super_To_String (Source) => C = ' ')
+ =>
+ Super_Index_Non_Blank'Result = 0,
+
+ -- Otherwise, an index in the range of Source is returned
+
+ others
+ =>
+ -- The result is in the range of Source
+
+ Super_Index_Non_Blank'Result in 1 .. Super_Length (Source)
+
+ -- The character at the returned index is not a Space character
+
+ and then
+ Super_Element (Source, Super_Index_Non_Blank'Result) /= ' '
+
+ -- The result is the smallest or largest index which is not a
+ -- Space character, respectively when Going = Forward and Going
+ -- = Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J /= Super_Index_Non_Blank'Result
+ and then
+ (J < Super_Index_Non_Blank'Result) = (Going = Forward)
+ then Super_Element (Source, J) = ' '))),
+ Global => null;
function Super_Index_Non_Blank
(Source : Super_String;
From : Positive;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ Pre =>
+ (if Super_Length (Source) /= 0 then From <= Super_Length (Source)),
+ Post => Super_Index_Non_Blank'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or all characters of the
+ -- considered slice of Source are Space characters, then 0
+ -- is returned.
+
+ (Super_Length (Source) = 0
+ or else
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ Super_Element (Source, J) = ' '))
+ =>
+ Super_Index_Non_Blank'Result = 0,
+
+ -- Otherwise, an index in the considered range of Source is returned
+
+ others
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index_Non_Blank'Result in 1 .. Super_Length (Source)
+ and then
+ (Super_Index_Non_Blank'Result = From
+ or else
+ (Super_Index_Non_Blank'Result > From) = (Going = Forward))
+
+ -- The character at the returned index is not a Space character
+
+ and then
+ Super_Element (Source, Super_Index_Non_Blank'Result) /= ' '
+
+ -- The result is the smallest or largest index which isn't a
+ -- Space character, respectively when Going = Forward and Going
+ -- = Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J /= Super_Index_Non_Blank'Result
+ and then
+ (J < Super_Index_Non_Blank'Result) = (Going = Forward)
+ and then (J = From
+ or else (J > From) = (Going = Forward))
+ then Super_Element (Source, J) = ' '))),
+ Global => null;
function Super_Count
(Source : Super_String;
Pattern : String;
- Mapping : Maps.Character_Mapping := Maps.Identity) return Natural;
+ Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
+ with
+ Pre => Pattern'Length /= 0,
+ Global => null;
function Super_Count
(Source : Super_String;
Pattern : String;
- Mapping : Maps.Character_Mapping_Function) return Natural;
+ Mapping : Maps.Character_Mapping_Function) return Natural
+ with
+ Pre => Pattern'Length /= 0 and then Mapping /= null,
+ Global => null;
function Super_Count
(Source : Super_String;
- Set : Maps.Character_Set) return Natural;
+ Set : Maps.Character_Set) return Natural
+ with
+ Global => null;
procedure Super_Find_Token
(Source : Super_String;
@@ -301,14 +1255,112 @@ package Ada.Strings.Superbounded is
From : Positive;
Test : Membership;
First : out Positive;
- Last : out Natural);
+ Last : out Natural)
+ with
+ Pre =>
+ (if Super_Length (Source) /= 0 then From <= Super_Length (Source)),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or if no character of the
+ -- considered slice of Source satisfies the property Test on
+ -- Set, then First is set to From and Last is set to 0.
+
+ (Super_Length (Source) = 0
+ or else
+ (for all J in From .. Super_Length (Source) =>
+ (Test = Inside) /= Maps.Is_In (Super_Element (Source, J), Set))
+ =>
+ First = From and then Last = 0,
+
+ -- Otherwise, First and Last are set to valid indexes
+
+ others
+ =>
+ -- First and Last are in the considered range of Source
+
+ First in From .. Super_Length (Source)
+ and then Last in First .. Super_Length (Source)
+
+ -- No character between From and First satisfies the property
+ -- Test on Set.
+
+ and then
+ (for all J in From .. First - 1 =>
+ (Test = Inside) /=
+ Maps.Is_In (Super_Element (Source, J), Set))
+
+ -- All characters between First and Last satisfy the property
+ -- Test on Set.
+
+ and then
+ (for all J in First .. Last =>
+ (Test = Inside) =
+ Maps.Is_In (Super_Element (Source, J), Set))
+
+ -- If Last is not Source'Last, then the character at position
+ -- Last + 1 does not satify the property Test on Set.
+
+ and then
+ (if Last < Super_Length (Source)
+ then
+ (Test = Inside) /=
+ Maps.Is_In (Super_Element (Source, Last + 1), Set))),
+ Global => null;
procedure Super_Find_Token
(Source : Super_String;
Set : Maps.Character_Set;
Test : Membership;
First : out Positive;
- Last : out Natural);
+ Last : out Natural)
+ with
+ Contract_Cases =>
+
+ -- If Source is the empty string, or if no character of the considered
+ -- slice of Source satisfies the property Test on Set, then First is
+ -- set to 1 and Last is set to 0.
+
+ (Super_Length (Source) = 0
+ or else
+ (for all J in 1 .. Super_Length (Source) =>
+ (Test = Inside) /= Maps.Is_In (Super_Element (Source, J), Set))
+ =>
+ First = 1 and then Last = 0,
+
+ -- Otherwise, First and Last are set to valid indexes
+
+ others
+ =>
+ -- First and Last are in the considered range of Source
+
+ First in 1 .. Super_Length (Source)
+ and then Last in First .. Super_Length (Source)
+
+ -- No character between 1 and First satisfies the property Test on
+ -- Set.
+
+ and then
+ (for all J in 1 .. First - 1 =>
+ (Test = Inside) /=
+ Maps.Is_In (Super_Element (Source, J), Set))
+
+ -- All characters between First and Last satisfy the property
+ -- Test on Set.
+
+ and then
+ (for all J in First .. Last =>
+ (Test = Inside) =
+ Maps.Is_In (Super_Element (Source, J), Set))
+
+ -- If Last is not Source'Last, then the character at position
+ -- Last + 1 does not satify the property Test on Set.
+
+ and then
+ (if Last < Super_Length (Source)
+ then
+ (Test = Inside) /=
+ Maps.Is_In (Super_Element (Source, Last + 1), Set))),
+ Global => null;
------------------------------------
-- String Translation Subprograms --
@@ -316,19 +1368,51 @@ package Ada.Strings.Superbounded is
function Super_Translate
(Source : Super_String;
- Mapping : Maps.Character_Mapping) return Super_String;
+ Mapping : Maps.Character_Mapping) return Super_String
+ with
+ Post => Super_Translate'Result.Max_Length = Source.Max_Length
+ and then Super_Length (Super_Translate'Result) = Super_Length (Source)
+ and then
+ (for all K in 1 .. Super_Length (Source) =>
+ Super_Element (Super_Translate'Result, K) =
+ Ada.Strings.Maps.Value (Mapping, Super_Element (Source, K))),
+ Global => null;
procedure Super_Translate
(Source : in out Super_String;
- Mapping : Maps.Character_Mapping);
+ Mapping : Maps.Character_Mapping)
+ with
+ Post => Super_Length (Source) = Super_Length (Source'Old)
+ and then
+ (for all K in 1 .. Super_Length (Source) =>
+ Super_Element (Source, K) =
+ Ada.Strings.Maps.Value (Mapping, Super_Element (Source'Old, K))),
+ Global => null;
function Super_Translate
(Source : Super_String;
- Mapping : Maps.Character_Mapping_Function) return Super_String;
+ Mapping : Maps.Character_Mapping_Function) return Super_String
+ with
+ Pre => Mapping /= null,
+ Post => Super_Translate'Result.Max_Length = Source.Max_Length
+ and then Super_Length (Super_Translate'Result) = Super_Length (Source)
+ and then
+ (for all K in 1 .. Super_Length (Source) =>
+ Super_Element (Super_Translate'Result, K) =
+ Mapping (Super_Element (Source, K))),
+ Global => null;
procedure Super_Translate
(Source : in out Super_String;
- Mapping : Maps.Character_Mapping_Function);
+ Mapping : Maps.Character_Mapping_Function)
+ with
+ Pre => Mapping /= null,
+ Post => Super_Length (Source) = Super_Length (Source'Old)
+ and then
+ (for all K in 1 .. Super_Length (Source) =>
+ Super_Element (Source, K) =
+ Mapping (Super_Element (Source'Old, K))),
+ Global => null;
---------------------------------------
-- String Transformation Subprograms --
@@ -339,48 +1423,756 @@ package Ada.Strings.Superbounded is
Low : Positive;
High : Natural;
By : String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ Low - 1 <= Super_Length (Source)
+ and then
+ (if Drop = Error
+ then (if High >= Low
+ then Low - 1
+ <= Source.Max_Length - By'Length
+ - Integer'Max (Super_Length (Source) - High, 0)
+ else Super_Length (Source) <=
+ Source.Max_Length - By'Length)),
+ Post =>
+ Super_Replace_Slice'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Low - 1 <= Source.Max_Length - By'Length - Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0)
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ -- Note that if High < Low, the insertion is done before Low, so in
+ -- all cases the starting position of the slice of Source remaining
+ -- after the replaced Slice is Integer'Max (High + 1, Low).
+
+ Super_Length (Super_Replace_Slice'Result) =
+ Low - 1 + By'Length + Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then
+ String'(Super_Slice (Super_Replace_Slice'Result, 1, Low - 1)) =
+ Super_Slice (Source, 1, Low - 1)
+ and then
+ Super_Slice (Super_Replace_Slice'Result,
+ Low, Low - 1 + By'Length) = By
+ and then
+ (if Integer'Max (High, Low - 1) < Super_Length (Source) then
+ String'(Super_Slice (Super_Replace_Slice'Result,
+ Low + By'Length,
+ Super_Length (Super_Replace_Slice'Result))) =
+ Super_Slice (Source,
+ Integer'Max (High + 1, Low), Super_Length (Source))),
+
+ Low - 1 > Source.Max_Length - By'Length - Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then Drop = Left
+ =>
+ -- Final_Super_Slice is the length of the slice of Source remaining
+ -- after the replaced part.
+ (declare
+ Final_Super_Slice : constant Natural :=
+ Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0);
+ begin
+ -- The result is of maximal length and ends by the last
+ -- Final_Super_Slice characters of Source.
+
+ Super_Length (Super_Replace_Slice'Result) = Source.Max_Length
+ and then
+ (if Final_Super_Slice > 0 then
+ String'(Super_Slice (Super_Replace_Slice'Result,
+ Source.Max_Length - Final_Super_Slice + 1,
+ Source.Max_Length)) =
+ Super_Slice (Source,
+ Integer'Max (High + 1, Low), Super_Length (Source)))
+
+ -- Depending on when we reach Max_Length, either the first
+ -- part of Source is fully dropped and By is partly dropped,
+ -- or By is fully added and the first part of Source is partly
+ -- dropped.
+
+ and then
+ (if Source.Max_Length - Final_Super_Slice - By'Length <= 0 then
+
+ -- The first (possibly zero) characters of By are dropped
+
+ (if Final_Super_Slice < Source.Max_Length then
+ Super_Slice (Super_Replace_Slice'Result,
+ 1, Source.Max_Length - Final_Super_Slice) =
+ By (By'Last - Source.Max_Length + Final_Super_Slice
+ + 1
+ .. By'Last))
+
+ else -- By is added to the result
+
+ Super_Slice (Super_Replace_Slice'Result,
+ Source.Max_Length - Final_Super_Slice - By'Length + 1,
+ Source.Max_Length - Final_Super_Slice) =
+ By
+
+ -- The first characters of Source (1 .. Low - 1) are
+ -- dropped.
+
+ and then
+ String'(Super_Slice (Super_Replace_Slice'Result, 1,
+ Source.Max_Length - Final_Super_Slice - By'Length)) =
+ Super_Slice (Source,
+ Low - Source.Max_Length
+ + Final_Super_Slice + By'Length,
+ Low - 1))),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first Low - 1
+ -- characters of Source.
+
+ Super_Length (Super_Replace_Slice'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Replace_Slice'Result, 1, Low - 1)) =
+ Super_Slice (Source, 1, Low - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and By is partly dropped, or By
+ -- is fully added and the last part of Source is partly dropped.
+
+ and then
+ (if Low - 1 >= Source.Max_Length - By'Length then
+
+ -- The last characters of By are dropped
+
+ Super_Slice (Super_Replace_Slice'Result,
+ Low, Source.Max_Length) =
+ By (By'First .. Source.Max_Length - Low + By'First)
+
+ else -- By is fully added
+
+ Super_Slice (Super_Replace_Slice'Result,
+ Low, Low + By'Length - 1) = By
+
+ -- Then Source starting from Natural'Max (High + 1, Low)
+ -- is added but the last characters are dropped.
+
+ and then
+ String'(Super_Slice (Super_Replace_Slice'Result,
+ Low + By'Length, Source.Max_Length)) =
+ Super_Slice (Source, Integer'Max (High + 1, Low),
+ Integer'Max (High + 1, Low) +
+ (Source.Max_Length - Low - By'Length)))),
+ Global => null;
procedure Super_Replace_Slice
(Source : in out Super_String;
Low : Positive;
High : Natural;
By : String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ Low - 1 <= Super_Length (Source)
+ and then
+ (if Drop = Error
+ then (if High >= Low
+ then Low - 1
+ <= Source.Max_Length - By'Length
+ - Natural'Max (Super_Length (Source) - High, 0)
+ else Super_Length (Source) <=
+ Source.Max_Length - By'Length)),
+ Contract_Cases =>
+ (Low - 1 <= Source.Max_Length - By'Length - Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0)
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ -- Note that if High < Low, the insertion is done before Low, so in
+ -- all cases the starting position of the slice of Source remaining
+ -- after the replaced Slice is Integer'Max (High + 1, Low).
+
+ Super_Length (Source) = Low - 1 + By'Length + Integer'Max
+ (Super_Length (Source'Old) - Integer'Max (High, Low - 1), 0)
+ and then
+ String'(Super_Slice (Source, 1, Low - 1)) =
+ Super_Slice (Source'Old, 1, Low - 1)
+ and then Super_Slice (Source, Low, Low - 1 + By'Length) = By
+ and then
+ (if Integer'Max (High, Low - 1) < Super_Length (Source'Old) then
+ String'(Super_Slice (Source,
+ Low + By'Length, Super_Length (Source))) =
+ Super_Slice (Source'Old,
+ Integer'Max (High + 1, Low),
+ Super_Length (Source'Old))),
+
+ Low - 1 > Source.Max_Length - By'Length - Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then Drop = Left
+ =>
+ -- Final_Super_Slice is the length of the slice of Source remaining
+ -- after the replaced part.
+ (declare
+ Final_Super_Slice : constant Natural :=
+ Integer'Max (0,
+ Super_Length (Source'Old) - Integer'Max (High, Low - 1));
+ begin
+ -- The result is of maximal length and ends by the last
+ -- Final_Super_Slice characters of Source.
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ (if Final_Super_Slice > 0 then
+ String'(Super_Slice (Source,
+ Source.Max_Length - Final_Super_Slice + 1,
+ Source.Max_Length)) =
+ Super_Slice (Source'Old,
+ Integer'Max (High + 1, Low),
+ Super_Length (Source'Old)))
+
+ -- Depending on when we reach Max_Length, either the first
+ -- part of Source is fully dropped and By is partly dropped,
+ -- or By is fully added and the first part of Source is partly
+ -- dropped.
+
+ and then
+ (if Source.Max_Length - Final_Super_Slice - By'Length <= 0
+ then
+ -- The first characters of By are dropped
+
+ (if Final_Super_Slice < Source.Max_Length then
+ Super_Slice (Source,
+ 1, Source.Max_Length - Final_Super_Slice) =
+ By (By'Last - Source.Max_Length + Final_Super_Slice
+ + 1
+ .. By'Last))
+
+ else -- By is added to the result
+
+ Super_Slice (Source,
+ Source.Max_Length - Final_Super_Slice - By'Length + 1,
+ Source.Max_Length - Final_Super_Slice) = By
+
+ -- The first characters of Source (1 .. Low - 1) are
+ -- dropped.
+
+ and then
+ String'(Super_Slice (Source, 1,
+ Source.Max_Length - Final_Super_Slice - By'Length)) =
+ Super_Slice (Source'Old,
+ Low - Source.Max_Length + Final_Super_Slice
+ + By'Length,
+ Low - 1))),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first Low - 1
+ -- characters of Source.
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source, 1, Low - 1)) =
+ Super_Slice (Source'Old, 1, Low - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and By is partly dropped, or By
+ -- is fully added and the last part of Source is partly dropped.
+
+ and then
+ (if Low - 1 >= Source.Max_Length - By'Length then
+
+ -- The last characters of By are dropped
+
+ Super_Slice (Source, Low, Source.Max_Length) =
+ By (By'First .. Source.Max_Length - Low + By'First)
+
+ else -- By is fully added
+
+ Super_Slice (Source, Low, Low + By'Length - 1) = By
+
+ -- Then Source starting from Natural'Max (High + 1, Low)
+ -- is added but the last characters are dropped.
+
+ and then
+ String'(Super_Slice (Source,
+ Low + By'Length, Source.Max_Length)) =
+ Super_Slice (Source'Old, Integer'Max (High + 1, Low),
+ Integer'Max (High + 1, Low) +
+ (Source.Max_Length - Low - By'Length)))),
+ Global => null;
function Super_Insert
(Source : Super_String;
Before : Positive;
New_Item : String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ Before - 1 <= Super_Length (Source)
+ and then
+ (if New_Item'Length > Source.Max_Length - Super_Length (Source)
+ then Drop /= Error),
+ Post => Super_Insert'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Super_Length (Source) <= Source.Max_Length - New_Item'Length
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ Super_Length (Super_Insert'Result) =
+ Super_Length (Source) + New_Item'Length
+ and then
+ String'(Super_Slice (Super_Insert'Result, 1, Before - 1)) =
+ Super_Slice (Source, 1, Before - 1)
+ and then
+ Super_Slice (Super_Insert'Result,
+ Before, Before - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Before <= Super_Length (Source) then
+ String'(Super_Slice (Super_Insert'Result,
+ Before + New_Item'Length,
+ Super_Length (Super_Insert'Result))) =
+ Super_Slice (Source, Before, Super_Length (Source))),
+
+ Super_Length (Source) > Source.Max_Length - New_Item'Length
+ and then Drop = Left
+ =>
+ -- The result is of maximal length and ends by the last characters
+ -- of Source.
+
+ Super_Length (Super_Insert'Result) = Source.Max_Length
+ and then
+ (if Before <= Super_Length (Source) then
+ String'(Super_Slice (Super_Insert'Result,
+ Source.Max_Length - Super_Length (Source) + Before,
+ Source.Max_Length)) =
+ Super_Slice (Source, Before, Super_Length (Source)))
+
+ -- Depending on when we reach Max_Length, either the first part
+ -- of Source is fully dropped and New_Item is partly dropped, or
+ -- New_Item is fully added and the first part of Source is partly
+ -- dropped.
+
+ and then
+ (if Source.Max_Length - Super_Length (Source) - 1 + Before
+ < New_Item'Length
+ then
+ -- The first characters of New_Item are dropped
+
+ (if Super_Length (Source) - Before + 1 < Source.Max_Length
+ then
+ Super_Slice (Super_Insert'Result, 1,
+ Source.Max_Length - Super_Length (Source) - 1 + Before) =
+ New_Item
+ (New_Item'Last - Source.Max_Length
+ + Super_Length (Source) - Before + 2
+ .. New_Item'Last))
+
+ else -- New_Item is added to the result
+
+ Super_Slice (Super_Insert'Result,
+ Source.Max_Length - Super_Length (Source) - New_Item'Length
+ + Before,
+ Source.Max_Length - Super_Length (Source) - 1 + Before) =
+ New_Item
+
+ -- The first characters of Source (1 .. Before - 1) are
+ -- dropped.
+
+ and then
+ String'(Super_Slice (Super_Insert'Result,
+ 1, Source.Max_Length - Super_Length (Source)
+ - New_Item'Length - 1 + Before)) =
+ Super_Slice (Source,
+ Super_Length (Source) - Source.Max_Length
+ + New_Item'Length + 1,
+ Before - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Super_Length (Super_Insert'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Insert'Result, 1, Before - 1)) =
+ Super_Slice (Source, 1, Before - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and New_Item is partly dropped, or
+ -- New_Item is fully added and the last part of Source is partly
+ -- dropped.
+
+ and then
+ (if Before - 1 >= Source.Max_Length - New_Item'Length then
+
+ -- The last characters of New_Item are dropped
+
+ Super_Slice (Super_Insert'Result, Before, Source.Max_Length) =
+ New_Item (New_Item'First
+ .. Source.Max_Length - Before + New_Item'First)
+
+ else -- New_Item is fully added
+
+ Super_Slice (Super_Insert'Result,
+ Before, Before + New_Item'Length - 1) =
+ New_Item
+
+ -- Then Source starting from Before is added but the
+ -- last characters are dropped.
+
+ and then
+ String'(Super_Slice (Super_Insert'Result,
+ Before + New_Item'Length, Source.Max_Length)) =
+ Super_Slice (Source,
+ Before, Source.Max_Length - New_Item'Length))),
+ Global => null;
procedure Super_Insert
(Source : in out Super_String;
Before : Positive;
New_Item : String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ Before - 1 <= Super_Length (Source)
+ and then
+ (if New_Item'Length > Source.Max_Length - Super_Length (Source)
+ then Drop /= Error),
+ Contract_Cases =>
+ (Super_Length (Source) <= Source.Max_Length - New_Item'Length
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ Super_Length (Source) = Super_Length (Source'Old) + New_Item'Length
+ and then
+ String'(Super_Slice (Source, 1, Before - 1)) =
+ Super_Slice (Source'Old, 1, Before - 1)
+ and then
+ Super_Slice (Source, Before, Before - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Before <= Super_Length (Source'Old) then
+ String'(Super_Slice (Source,
+ Before + New_Item'Length, Super_Length (Source))) =
+ Super_Slice (Source'Old,
+ Before, Super_Length (Source'Old))),
+
+ Super_Length (Source) > Source.Max_Length - New_Item'Length
+ and then Drop = Left
+ =>
+ -- The result is of maximal length and ends by the last characters
+ -- of Source.
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ (if Before <= Super_Length (Source'Old) then
+ String'(Super_Slice (Source,
+ Source.Max_Length - Super_Length (Source'Old) + Before,
+ Source.Max_Length)) =
+ Super_Slice (Source'Old,
+ Before, Super_Length (Source'Old)))
+
+ -- Depending on when we reach Max_Length, either the first part
+ -- of Source is fully dropped and New_Item is partly dropped, or
+ -- New_Item is fully added and the first part of Source is partly
+ -- dropped.
+
+ and then
+ (if Source.Max_Length - Super_Length (Source'Old) - 1 + Before
+ < New_Item'Length
+ then
+ -- The first characters of New_Item are dropped
+
+ (if Super_Length (Source'Old) - Before + 1 < Source.Max_Length
+ then
+ Super_Slice (Source,
+ 1, Source.Max_Length - Super_Length (Source'Old)
+ - 1 + Before) =
+ New_Item
+ (New_Item'Last - Source.Max_Length
+ + Super_Length (Source'Old) - Before + 2
+ .. New_Item'Last))
+
+ else -- New_Item is added to the result
+
+ Super_Slice (Source,
+ Source.Max_Length - Super_Length (Source'Old)
+ - New_Item'Length + Before,
+ Source.Max_Length - Super_Length (Source'Old) - 1 + Before)
+ = New_Item
+
+ -- The first characters of Source (1 .. Before - 1) are
+ -- dropped.
+
+ and then
+ String'(Super_Slice (Source, 1,
+ Source.Max_Length - Super_Length (Source'Old)
+ - New_Item'Length - 1 + Before)) =
+ Super_Slice (Source'Old,
+ Super_Length (Source'Old)
+ - Source.Max_Length + New_Item'Length + 1,
+ Before - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source, 1, Before - 1)) =
+ Super_Slice (Source'Old, 1, Before - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and New_Item is partly dropped, or
+ -- New_Item is fully added and the last part of Source is partly
+ -- dropped.
+
+ and then
+ (if Before - 1 >= Source.Max_Length - New_Item'Length then
+
+ -- The last characters of New_Item are dropped
+
+ Super_Slice (Source, Before, Source.Max_Length) =
+ New_Item (New_Item'First
+ .. Source.Max_Length - Before + New_Item'First)
+
+ else -- New_Item is fully added
+
+ Super_Slice (Source, Before, Before + New_Item'Length - 1) =
+ New_Item
+
+ -- Then Source starting from Before is added but the
+ -- last characters are dropped.
+
+ and then
+ String'(Super_Slice (Source,
+ Before + New_Item'Length, Source.Max_Length)) =
+ Super_Slice (Source'Old,
+ Before, Source.Max_Length - New_Item'Length))),
+ Global => null;
function Super_Overwrite
(Source : Super_String;
Position : Positive;
New_Item : String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ Position - 1 <= Super_Length (Source)
+ and then (if New_Item'Length > Source.Max_Length - (Position - 1)
+ then Drop /= Error),
+ Post => Super_Overwrite'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Position - 1 <= Source.Max_Length - New_Item'Length
+ =>
+ -- The length is unchanged, unless New_Item overwrites further than
+ -- the end of Source. In this contract case, we suppose New_Item
+ -- doesn't overwrite further than Max_Length.
+
+ Super_Length (Super_Overwrite'Result) =
+ Integer'Max (Super_Length (Source), Position - 1 + New_Item'Length)
+ and then
+ String'(Super_Slice (Super_Overwrite'Result, 1, Position - 1)) =
+ Super_Slice (Source, 1, Position - 1)
+ and then Super_Slice (Super_Overwrite'Result,
+ Position, Position - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Position - 1 + New_Item'Length < Super_Length (Source) then
+
+ -- There are some unchanged characters of Source remaining
+ -- after New_Item.
+
+ String'(Super_Slice (Super_Overwrite'Result,
+ Position + New_Item'Length, Super_Length (Source))) =
+ Super_Slice (Source,
+ Position + New_Item'Length, Super_Length (Source))),
+
+ Position - 1 > Source.Max_Length - New_Item'Length and then Drop = Left
+ =>
+ Super_Length (Super_Overwrite'Result) = Source.Max_Length
+
+ -- If a part of the result has to be dropped, it means New_Item is
+ -- overwriting further than the end of Source. Thus the result is
+ -- necessarily ending by New_Item. However, we don't know whether
+ -- New_Item covers all Max_Length characters or some characters of
+ -- Source are remaining at the left.
+
+ and then
+ (if New_Item'Length > Source.Max_Length then
+
+ -- New_Item covers all Max_Length characters
+
+ Super_To_String (Super_Overwrite'Result) =
+ New_Item
+ (New_Item'Last - Source.Max_Length + 1 .. New_Item'Last)
+ else
+ -- New_Item fully appears at the end
+
+ Super_Slice (Super_Overwrite'Result,
+ Source.Max_Length - New_Item'Length + 1,
+ Source.Max_Length) =
+ New_Item
+
+ -- The left of Source is cut
+
+ and then
+ String'(Super_Slice (Super_Overwrite'Result,
+ 1, Source.Max_Length - New_Item'Length)) =
+ Super_Slice (Source,
+ Position - Source.Max_Length + New_Item'Length,
+ Position - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Super_Length (Super_Overwrite'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Overwrite'Result, 1, Position - 1)) =
+ Super_Slice (Source, 1, Position - 1)
+
+ -- Then New_Item is written until Max_Length
+
+ and then Super_Slice (Super_Overwrite'Result,
+ Position, Source.Max_Length) =
+ New_Item (New_Item'First
+ .. Source.Max_Length - Position + New_Item'First)),
+ Global => null;
procedure Super_Overwrite
(Source : in out Super_String;
Position : Positive;
New_Item : String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ Position - 1 <= Super_Length (Source)
+ and then (if New_Item'Length > Source.Max_Length - (Position - 1)
+ then Drop /= Error),
+ Contract_Cases =>
+ (Position - 1 <= Source.Max_Length - New_Item'Length
+ =>
+ -- The length is unchanged, unless New_Item overwrites further than
+ -- the end of Source. In this contract case, we suppose New_Item
+ -- doesn't overwrite further than Max_Length.
+
+ Super_Length (Source) = Integer'Max
+ (Super_Length (Source'Old), Position - 1 + New_Item'Length)
+ and then
+ String'(Super_Slice (Source, 1, Position - 1)) =
+ Super_Slice (Source'Old, 1, Position - 1)
+ and then Super_Slice (Source,
+ Position, Position - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Position - 1 + New_Item'Length < Super_Length (Source'Old)
+ then
+ -- There are some unchanged characters of Source remaining
+ -- after New_Item.
+
+ String'(Super_Slice (Source,
+ Position + New_Item'Length, Super_Length (Source'Old))) =
+ Super_Slice (Source'Old,
+ Position + New_Item'Length, Super_Length (Source'Old))),
+
+ Position - 1 > Source.Max_Length - New_Item'Length and then Drop = Left
+ =>
+ Super_Length (Source) = Source.Max_Length
+
+ -- If a part of the result has to be dropped, it means New_Item is
+ -- overwriting further than the end of Source. Thus the result is
+ -- necessarily ending by New_Item. However, we don't know whether
+ -- New_Item covers all Max_Length characters or some characters of
+ -- Source are remaining at the left.
+
+ and then
+ (if New_Item'Length > Source.Max_Length then
+
+ -- New_Item covers all Max_Length characters
+
+ Super_To_String (Source) =
+ New_Item
+ (New_Item'Last - Source.Max_Length + 1 .. New_Item'Last)
+ else
+ -- New_Item fully appears at the end
+
+ Super_Slice (Source,
+ Source.Max_Length - New_Item'Length + 1,
+ Source.Max_Length) =
+ New_Item
+
+ -- The left of Source is cut
+
+ and then
+ String'(Super_Slice (Source,
+ 1, Source.Max_Length - New_Item'Length)) =
+ Super_Slice (Source'Old,
+ Position - Source.Max_Length + New_Item'Length,
+ Position - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source, 1, Position - 1)) =
+ Super_Slice (Source'Old, 1, Position - 1)
+
+ -- New_Item is written until Max_Length
+
+ and then Super_Slice (Source, Position, Source.Max_Length) =
+ New_Item (New_Item'First
+ .. Source.Max_Length - Position + New_Item'First)),
+ Global => null;
function Super_Delete
(Source : Super_String;
From : Positive;
- Through : Natural) return Super_String;
+ Through : Natural) return Super_String
+ with
+ Pre =>
+ (if Through >= From then From - 1 <= Super_Length (Source)),
+ Post => Super_Delete'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Through >= From =>
+ Super_Length (Super_Delete'Result) =
+ From - 1 + Natural'Max (Super_Length (Source) - Through, 0)
+ and then
+ String'(Super_Slice (Super_Delete'Result, 1, From - 1)) =
+ Super_Slice (Source, 1, From - 1)
+ and then
+ (if Through < Super_Length (Source) then
+ String'(Super_Slice (Super_Delete'Result,
+ From, Super_Length (Super_Delete'Result))) =
+ Super_Slice (Source, Through + 1, Super_Length (Source))),
+ others =>
+ Super_Delete'Result = Source),
+ Global => null;
procedure Super_Delete
(Source : in out Super_String;
From : Positive;
- Through : Natural);
+ Through : Natural)
+ with
+ Pre =>
+ (if Through >= From then From - 1 <= Super_Length (Source)),
+ Contract_Cases =>
+ (Through >= From =>
+ Super_Length (Source) =
+ From - 1 + Natural'Max (Super_Length (Source'Old) - Through, 0)
+ and then
+ String'(Super_Slice (Source, 1, From - 1)) =
+ Super_Slice (Source'Old, 1, From - 1)
+ and then
+ (if Through < Super_Length (Source) then
+ String'(Super_Slice (Source, From, Super_Length (Source))) =
+ Super_Slice (Source'Old,
+ Through + 1, Super_Length (Source'Old))),
+ others =>
+ Source = Source'Old),
+ Global => null;
---------------------------------
-- String Selector Subprograms --
@@ -388,45 +2180,376 @@ package Ada.Strings.Superbounded is
function Super_Trim
(Source : Super_String;
- Side : Trim_End) return Super_String;
+ Side : Trim_End) return Super_String
+ with
+ Post => Super_Trim'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+
+ -- If all characters in Source are Space, the returned string is empty
+
+ ((for all C of Super_To_String (Source) => C = ' ')
+ =>
+ Super_Length (Super_Trim'Result) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ (if Side = Right then 1
+ else Super_Index_Non_Blank (Source, Forward));
+ High : constant Positive :=
+ (if Side = Left then Super_Length (Source)
+ else Super_Index_Non_Blank (Source, Backward));
+ begin
+ Super_To_String (Super_Trim'Result) =
+ Super_Slice (Source, Low, High))),
+ Global => null;
procedure Super_Trim
(Source : in out Super_String;
- Side : Trim_End);
+ Side : Trim_End)
+ with
+ Contract_Cases =>
+
+ -- If all characters in Source are Space, the returned string is empty
+
+ ((for all C of Super_To_String (Source) => C = ' ')
+ =>
+ Super_Length (Source) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ (if Side = Right then 1
+ else Super_Index_Non_Blank (Source'Old, Forward));
+ High : constant Positive :=
+ (if Side = Left then Super_Length (Source'Old)
+ else Super_Index_Non_Blank (Source'Old, Backward));
+ begin
+ Super_To_String (Source) = Super_Slice (Source'Old, Low, High))),
+ Global => null;
function Super_Trim
(Source : Super_String;
Left : Maps.Character_Set;
- Right : Maps.Character_Set) return Super_String;
+ Right : Maps.Character_Set) return Super_String
+ with
+ Post => Super_Trim'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+
+ -- If all characters in Source are contained in one of the sets Left or
+ -- Right, then the returned string is empty.
+
+ ((for all C of Super_To_String (Source) => Maps.Is_In (C, Left))
+ or else
+ (for all C of Super_To_String (Source) => Maps.Is_In (C, Right))
+ =>
+ Super_Length (Super_Trim'Result) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ Super_Index (Source, Left, Outside, Forward);
+ High : constant Positive :=
+ Super_Index (Source, Right, Outside, Backward);
+ begin
+ Super_To_String (Super_Trim'Result) =
+ Super_Slice (Source, Low, High))),
+ Global => null;
procedure Super_Trim
(Source : in out Super_String;
Left : Maps.Character_Set;
- Right : Maps.Character_Set);
+ Right : Maps.Character_Set)
+ with
+ Contract_Cases =>
+
+ -- If all characters in Source are contained in one of the sets Left or
+ -- Right, then the returned string is empty.
+
+ ((for all C of Super_To_String (Source) => Maps.Is_In (C, Left))
+ or else
+ (for all C of Super_To_String (Source) => Maps.Is_In (C, Right))
+ =>
+ Super_Length (Source) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ Super_Index (Source'Old, Left, Outside, Forward);
+ High : constant Positive :=
+ Super_Index (Source'Old, Right, Outside, Backward);
+ begin
+ Super_To_String (Source) = Super_Slice (Source'Old, Low, High))),
+ Global => null;
function Super_Head
(Source : Super_String;
Count : Natural;
Pad : Character := Space;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre => (if Count > Source.Max_Length then Drop /= Error),
+ Post => Super_Head'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Count <= Super_Length (Source)
+ =>
+ -- Source is cut
+
+ Super_To_String (Super_Head'Result) = Super_Slice (Source, 1, Count),
+ Count > Super_Length (Source) and then Count <= Source.Max_Length
+ =>
+ -- Source is followed by Pad characters
+
+ Super_Length (Super_Head'Result) = Count
+ and then
+ Super_Slice (Super_Head'Result, 1, Super_Length (Source)) =
+ Super_To_String (Source)
+ and then
+ String'(Super_Slice (Super_Head'Result,
+ Super_Length (Source) + 1, Count)) =
+ (1 .. Count - Super_Length (Source) => Pad),
+ Count > Source.Max_Length and then Drop = Right
+ =>
+ -- Source is followed by Pad characters
+
+ Super_Length (Super_Head'Result) = Source.Max_Length
+ and then
+ Super_Slice (Super_Head'Result, 1, Super_Length (Source)) =
+ Super_To_String (Source)
+ and then
+ String'(Super_Slice (Super_Head'Result,
+ Super_Length (Source) + 1, Source.Max_Length)) =
+ (1 .. Source.Max_Length - Super_Length (Source) => Pad),
+ Count - Super_Length (Source) > Source.Max_Length and then Drop = Left
+ =>
+ -- Source is fully dropped on the left
+
+ Super_To_String (Super_Head'Result) =
+ (1 .. Source.Max_Length => Pad),
+ others
+ =>
+ -- Source is partly dropped on the left
+
+ Super_Length (Super_Head'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Head'Result,
+ 1, Source.Max_Length - Count + Super_Length (Source))) =
+ Super_Slice (Source,
+ Count - Source.Max_Length + 1, Super_Length (Source))
+ and then
+ String'(Super_Slice (Super_Head'Result,
+ Source.Max_Length - Count + Super_Length (Source) + 1,
+ Source.Max_Length)) =
+ (1 .. Count - Super_Length (Source) => Pad)),
+ Global => null;
procedure Super_Head
(Source : in out Super_String;
Count : Natural;
Pad : Character := Space;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre => (if Count > Source.Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count <= Super_Length (Source)
+ =>
+ -- Source is cut
+
+ Super_To_String (Source) = Super_Slice (Source'Old, 1, Count),
+ Count > Super_Length (Source) and then Count <= Source.Max_Length
+ =>
+ -- Source is followed by Pad characters
+
+ Super_Length (Source) = Count
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ String'(Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Count)) =
+ (1 .. Count - Super_Length (Source'Old) => Pad),
+ Count > Source.Max_Length and then Drop = Right
+ =>
+ -- Source is followed by Pad characters
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ String'(Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Source.Max_Length)) =
+ (1 .. Source.Max_Length - Super_Length (Source'Old) => Pad),
+ Count - Super_Length (Source) > Source.Max_Length and then Drop = Left
+ =>
+ -- Source is fully dropped on the left
+
+ Super_To_String (Source) = (1 .. Source.Max_Length => Pad),
+ others
+ =>
+ -- Source is partly dropped on the left
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source,
+ 1, Source.Max_Length - Count + Super_Length (Source'Old))) =
+ Super_Slice (Source'Old,
+ Count - Source.Max_Length + 1, Super_Length (Source'Old))
+ and then
+ String'(Super_Slice (Source,
+ Source.Max_Length - Count + Super_Length (Source'Old) + 1,
+ Source.Max_Length)) =
+ (1 .. Count - Super_Length (Source'Old) => Pad)),
+ Global => null;
function Super_Tail
(Source : Super_String;
Count : Natural;
Pad : Character := Space;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre => (if Count > Source.Max_Length then Drop /= Error),
+ Post => Super_Tail'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Count < Super_Length (Source)
+ =>
+ -- Source is cut
+
+ (if Count > 0 then
+ Super_To_String (Super_Tail'Result) =
+ Super_Slice (Source,
+ Super_Length (Source) - Count + 1, Super_Length (Source))
+ else Super_Length (Super_Tail'Result) = 0),
+ Count >= Super_Length (Source) and then Count < Source.Max_Length
+ =>
+ -- Source is preceded by Pad characters
+
+ Super_Length (Super_Tail'Result) = Count
+ and then
+ String'(Super_Slice (Super_Tail'Result,
+ 1, Count - Super_Length (Source))) =
+ (1 .. Count - Super_Length (Source) => Pad)
+ and then
+ Super_Slice (Super_Tail'Result,
+ Count - Super_Length (Source) + 1, Count) =
+ Super_To_String (Source),
+ Count >= Source.Max_Length and then Drop = Left
+ =>
+ -- Source is preceded by Pad characters
+
+ Super_Length (Super_Tail'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Tail'Result,
+ 1, Source.Max_Length - Super_Length (Source))) =
+ (1 .. Source.Max_Length - Super_Length (Source) => Pad)
+ and then
+ (if Super_Length (Source) > 0 then
+ Super_Slice (Super_Tail'Result,
+ Source.Max_Length - Super_Length (Source) + 1,
+ Source.Max_Length) =
+ Super_To_String (Source)),
+ Count - Super_Length (Source) >= Source.Max_Length
+ and then Drop /= Left
+ =>
+ -- Source is fully dropped on the right
+
+ Super_To_String (Super_Tail'Result) =
+ (1 .. Source.Max_Length => Pad),
+ others
+ =>
+ -- Source is partly dropped on the right
+
+ Super_Length (Super_Tail'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Tail'Result,
+ 1, Count - Super_Length (Source))) =
+ (1 .. Count - Super_Length (Source) => Pad)
+ and then
+ String'(Super_Slice (Super_Tail'Result,
+ Count - Super_Length (Source) + 1, Source.Max_Length)) =
+ Super_Slice (Source,
+ 1, Source.Max_Length - Count + Super_Length (Source))),
+ Global => null;
procedure Super_Tail
(Source : in out Super_String;
Count : Natural;
Pad : Character := Space;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre => (if Count > Source.Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count < Super_Length (Source)
+ =>
+ -- Source is cut
+
+ (if Count > 0 then
+ Super_To_String (Source) =
+ Super_Slice (Source'Old,
+ Super_Length (Source'Old) - Count + 1,
+ Super_Length (Source'Old))
+ else Super_Length (Source) = 0),
+ Count >= Super_Length (Source) and then Count < Source.Max_Length
+ =>
+ -- Source is preceded by Pad characters
+
+ Super_Length (Source) = Count
+ and then
+ String'(Super_Slice (Source,
+ 1, Count - Super_Length (Source'Old))) =
+ (1 .. Count - Super_Length (Source'Old) => Pad)
+ and then
+ Super_Slice (Source,
+ Count - Super_Length (Source'Old) + 1, Count) =
+ Super_To_String (Source'Old),
+ Count >= Source.Max_Length and then Drop = Left
+ =>
+ -- Source is preceded by Pad characters
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source,
+ 1, Source.Max_Length - Super_Length (Source'Old))) =
+ (1 .. Source.Max_Length - Super_Length (Source'Old) => Pad)
+ and then
+ (if Super_Length (Source'Old) > 0 then
+ Super_Slice (Source,
+ Source.Max_Length - Super_Length (Source'Old) + 1,
+ Source.Max_Length) =
+ Super_To_String (Source'Old)),
+ Count - Super_Length (Source) >= Source.Max_Length
+ and then Drop /= Left
+ =>
+ -- Source is fully dropped on the right
+
+ Super_To_String (Source) = (1 .. Source.Max_Length => Pad),
+ others
+ =>
+ -- Source is partly dropped on the right
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source,
+ 1, Count - Super_Length (Source'Old))) =
+ (1 .. Count - Super_Length (Source'Old) => Pad)
+ and then
+ String'(Super_Slice (Source,
+ Count - Super_Length (Source'Old) + 1, Source.Max_Length)) =
+ Super_Slice (Source'Old,
+ 1, Source.Max_Length - Count + Super_Length (Source'Old))),
+ Global => null;
------------------------------------
-- String Constructor Subprograms --
@@ -439,37 +2562,135 @@ package Ada.Strings.Superbounded is
function Times
(Left : Natural;
Right : Character;
- Max_Length : Positive) return Super_String;
+ Max_Length : Positive) return Super_String
+ with
+ Pre => Left <= Max_Length,
+ Post => Times'Result.Max_Length = Max_Length
+ and then Super_To_String (Times'Result) = (1 .. Left => Right),
+ Global => null;
-- Note the additional parameter Max_Length
function Times
(Left : Natural;
Right : String;
- Max_Length : Positive) return Super_String;
+ Max_Length : Positive) return Super_String
+ with
+ Pre => (if Left /= 0 then Right'Length <= Max_Length / Left),
+ Post => Times'Result.Max_Length = Max_Length
+ and then Super_Length (Times'Result) = Left * Right'Length
+ and then
+ (if Right'Length > 0 then
+ (for all K in 1 .. Left * Right'Length =>
+ Super_Element (Times'Result, K) =
+ Right (Right'First + (K - 1) mod Right'Length))),
+ Global => null;
-- Note the additional parameter Max_Length
function Times
(Left : Natural;
- Right : Super_String) return Super_String;
+ Right : Super_String) return Super_String
+ with
+ Pre =>
+ (if Left /= 0 then Super_Length (Right) <= Right.Max_Length / Left),
+ Post => Times'Result.Max_Length = Right.Max_Length
+ and then Super_Length (Times'Result) = Left * Super_Length (Right)
+ and then
+ (if Super_Length (Right) > 0 then
+ (for all K in 1 .. Left * Super_Length (Right) =>
+ Super_Element (Times'Result, K) =
+ Super_Element (Right, 1 + (K - 1) mod Super_Length (Right)))),
+ Global => null;
function Super_Replicate
(Count : Natural;
Item : Character;
Drop : Truncation := Error;
- Max_Length : Positive) return Super_String;
+ Max_Length : Positive) return Super_String
+ with
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Post => Super_Replicate'Result.Max_Length = Max_Length
+ and then Super_To_String (Super_Replicate'Result) =
+ (1 .. Natural'Min (Max_Length, Count) => Item),
+ Global => null;
-- Note the additional parameter Max_Length
function Super_Replicate
(Count : Natural;
Item : String;
Drop : Truncation := Error;
- Max_Length : Positive) return Super_String;
+ Max_Length : Positive) return Super_String
+ with
+ Pre =>
+ (if Count /= 0 and then Item'Length > Max_Length / Count
+ then Drop /= Error),
+ Post => Super_Replicate'Result.Max_Length = Max_Length,
+ Contract_Cases =>
+ (Count = 0 or else Item'Length <= Max_Length / Count
+ =>
+ Super_Length (Super_Replicate'Result) = Count * Item'Length
+ and then
+ (if Item'Length > 0 then
+ (for all K in 1 .. Count * Item'Length =>
+ Super_Element (Super_Replicate'Result, K) =
+ Item (Item'First + (K - 1) mod Item'Length))),
+ Count /= 0
+ and then Item'Length > Max_Length / Count
+ and then Drop = Right
+ =>
+ Super_Length (Super_Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Super_Element (Super_Replicate'Result, K) =
+ Item (Item'First + (K - 1) mod Item'Length)),
+ others -- Drop = Left
+ =>
+ Super_Length (Super_Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Super_Element (Super_Replicate'Result, K) =
+ Item (Item'Last - (Max_Length - K) mod Item'Length))),
+ Global => null;
-- Note the additional parameter Max_Length
function Super_Replicate
(Count : Natural;
Item : Super_String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ (if Count /= 0
+ and then Super_Length (Item) > Item.Max_Length / Count
+ then Drop /= Error),
+ Post => Super_Replicate'Result.Max_Length = Item.Max_Length,
+ Contract_Cases =>
+ ((if Count /= 0 then Super_Length (Item) <= Item.Max_Length / Count)
+ =>
+ Super_Length (Super_Replicate'Result) = Count * Super_Length (Item)
+ and then
+ (if Super_Length (Item) > 0 then
+ (for all K in 1 .. Count * Super_Length (Item) =>
+ Super_Element (Super_Replicate'Result, K) =
+ Super_Element (Item,
+ 1 + (K - 1) mod Super_Length (Item)))),
+ Count /= 0
+ and then Super_Length (Item) > Item.Max_Length / Count
+ and then Drop = Right
+ =>
+ Super_Length (Super_Replicate'Result) = Item.Max_Length
+ and then
+ (for all K in 1 .. Item.Max_Length =>
+ Super_Element (Super_Replicate'Result, K) =
+ Super_Element (Item, 1 + (K - 1) mod Super_Length (Item))),
+ others -- Drop = Left
+ =>
+ Super_Length (Super_Replicate'Result) = Item.Max_Length
+ and then
+ (for all K in 1 .. Item.Max_Length =>
+ Super_Element (Super_Replicate'Result, K) =
+ Super_Element (Item,
+ Super_Length (Item)
+ - (Item.Max_Length - K) mod Super_Length (Item)))),
+ Global => null;
private
-- Pragma Inline declarations
diff --git a/gcc/ada/libgnat/a-strunb.ads b/gcc/ada/libgnat/a-strunb.ads
index 13c7612..b3050fd 100644
--- a/gcc/ada/libgnat/a-strunb.ads
+++ b/gcc/ada/libgnat/a-strunb.ads
@@ -53,11 +53,13 @@ private with Ada.Strings.Text_Buffers;
-- and selector operations are provided.
package Ada.Strings.Unbounded with
+ SPARK_Mode,
Initial_Condition => Length (Null_Unbounded_String) = 0
is
pragma Preelaborate;
- type Unbounded_String is private;
+ type Unbounded_String is private with
+ Default_Initial_Condition => Length (Unbounded_String) = 0;
pragma Preelaborable_Initialization (Unbounded_String);
Null_Unbounded_String : constant Unbounded_String;
@@ -73,7 +75,7 @@ is
-- Provides a (nonprivate) access type for explicit processing of
-- unbounded-length strings.
- procedure Free (X : in out String_Access);
+ procedure Free (X : in out String_Access) with SPARK_Mode => Off;
-- Performs an unchecked deallocation of an object of type String_Access
--------------------------------------------------------
@@ -732,6 +734,8 @@ is
-- strings applied to the string represented by Source's original value.
private
+ pragma SPARK_Mode (Off); -- Controlled types are not in SPARK
+
pragma Inline (Length);
package AF renames Ada.Finalization;
diff --git a/gcc/ada/libgnat/a-strunb__shared.ads b/gcc/ada/libgnat/a-strunb__shared.ads
index 2091bde..2cf6780 100644
--- a/gcc/ada/libgnat/a-strunb__shared.ads
+++ b/gcc/ada/libgnat/a-strunb__shared.ads
@@ -85,7 +85,8 @@ package Ada.Strings.Unbounded with
is
pragma Preelaborate;
- type Unbounded_String is private;
+ type Unbounded_String is private with
+ Default_Initial_Condition => Length (Unbounded_String) = 0;
pragma Preelaborable_Initialization (Unbounded_String);
Null_Unbounded_String : constant Unbounded_String;
diff --git a/gcc/ada/libgnat/a-textio.adb b/gcc/ada/libgnat/a-textio.adb
index 717f529..8667360 100644
--- a/gcc/ada/libgnat/a-textio.adb
+++ b/gcc/ada/libgnat/a-textio.adb
@@ -44,6 +44,7 @@ pragma Elaborate_All (System.File_IO);
-- Needed because of calls to Chain_File in package body elaboration
package body Ada.Text_IO with
+ SPARK_Mode => Off,
Refined_State => (File_System => (Standard_In,
Standard_Out,
Standard_Err,
diff --git a/gcc/ada/libgnat/a-textio.ads b/gcc/ada/libgnat/a-textio.ads
index a06a35c..f94c92d 100644
--- a/gcc/ada/libgnat/a-textio.ads
+++ b/gcc/ada/libgnat/a-textio.ads
@@ -56,8 +56,9 @@ with System.File_Control_Block;
with System.WCh_Con;
package Ada.Text_IO with
- Abstract_State => (File_System),
- Initializes => (File_System),
+ SPARK_Mode,
+ Abstract_State => File_System,
+ Initializes => File_System,
Initial_Condition => Line_Length = 0 and Page_Length = 0
is
pragma Elaborate_Body;
@@ -547,6 +548,7 @@ is
Layout_Error : exception renames IO_Exceptions.Layout_Error;
private
+ pragma SPARK_Mode (Off);
-- The following procedures have a File_Type formal of mode IN OUT because
-- they may close the original file. The Close operation may raise an
diff --git a/gcc/ada/libgnat/a-zchhan.adb b/gcc/ada/libgnat/a-zchhan.adb
index 3f2a91b..61405f7 100644
--- a/gcc/ada/libgnat/a-zchhan.adb
+++ b/gcc/ada/libgnat/a-zchhan.adb
@@ -33,6 +33,15 @@ with Ada.Wide_Wide_Characters.Unicode; use Ada.Wide_Wide_Characters.Unicode;
package body Ada.Wide_Wide_Characters.Handling is
+ ---------------------------
+ -- Character_Set_Version --
+ ---------------------------
+
+ function Character_Set_Version return String is
+ begin
+ return "Unicode 4.0";
+ end Character_Set_Version;
+
---------------------
-- Is_Alphanumeric --
---------------------
@@ -42,6 +51,13 @@ package body Ada.Wide_Wide_Characters.Handling is
return Is_Letter (Item) or else Is_Digit (Item);
end Is_Alphanumeric;
+ --------------
+ -- Is_Basic --
+ --------------
+
+ function Is_Basic (Item : Wide_Wide_Character) return Boolean
+ renames Ada.Wide_Wide_Characters.Unicode.Is_Basic;
+
----------------
-- Is_Control --
----------------
@@ -191,4 +207,22 @@ package body Ada.Wide_Wide_Characters.Handling is
return Result;
end To_Upper;
+ --------------
+ -- To_Basic --
+ --------------
+
+ function To_Basic (Item : Wide_Wide_Character) return Wide_Wide_Character
+ renames Ada.Wide_Wide_Characters.Unicode.To_Basic;
+
+ function To_Basic (Item : Wide_Wide_String) return Wide_Wide_String is
+ Result : Wide_Wide_String (Item'Range);
+
+ begin
+ for J in Result'Range loop
+ Result (J) := To_Basic (Item (J));
+ end loop;
+
+ return Result;
+ end To_Basic;
+
end Ada.Wide_Wide_Characters.Handling;
diff --git a/gcc/ada/libgnat/a-zchhan.ads b/gcc/ada/libgnat/a-zchhan.ads
index 74fab2a..6ebd1a8 100644
--- a/gcc/ada/libgnat/a-zchhan.ads
+++ b/gcc/ada/libgnat/a-zchhan.ads
@@ -15,10 +15,12 @@
package Ada.Wide_Wide_Characters.Handling is
pragma Pure;
- -- This package is clearly intended to be Pure, by analogy with the
- -- base Ada.Characters.Handling package. The version in the RM does
- -- not yet have this pragma, but that is a clear omission. This will
- -- be fixed in a future version of AI05-0266-1.
+
+ function Character_Set_Version return String;
+ pragma Inline (Character_Set_Version);
+ -- Returns an implementation-defined identifier that identifies the version
+ -- of the character set standard that is used for categorizing characters
+ -- by the implementation. For GNAT this is "Unicode v.v".
function Is_Control (Item : Wide_Wide_Character) return Boolean;
pragma Inline (Is_Control);
@@ -42,6 +44,12 @@ package Ada.Wide_Wide_Characters.Handling is
-- Returns True if the Wide_Wide_Character designated by Item is
-- categorized as letter_uppercase, otherwise returns false.
+ function Is_Basic (Item : Wide_Wide_Character) return Boolean;
+ pragma Inline (Is_Basic);
+ -- Returns True if the Wide_Wide_Character designated by Item has no
+ -- Decomposition Mapping in the code charts of ISO/IEC 10646:2017,
+ -- otherwise returns False.
+
function Is_Digit (Item : Wide_Wide_Character) return Boolean;
pragma Inline (Is_Digit);
-- Returns True if the Wide_Wide_Character designated by Item is
@@ -135,4 +143,17 @@ package Ada.Wide_Wide_Characters.Handling is
-- designated by Item. The result is the null Wide_Wide_String if the value
-- of the formal parameter is the null Wide_Wide_String.
+ function To_Basic (Item : Wide_Wide_Character) return Wide_Wide_Character;
+ pragma Inline (To_Basic);
+ -- Returns the Wide_Wide_Character whose code point is given
+ -- by the first value of its Decomposition Mapping in the code charts
+ -- of ISO/IEC 10646:2017 if any, returns Item otherwise.
+
+ function To_Basic (Item : Wide_Wide_String) return Wide_Wide_String;
+ -- Returns the result of applying the To_Basic conversion to each
+ -- Wide_Wide_Character element of the Wide_Wide_String designated by Item.
+ -- The result is the null Wide_Wide_String if the value of the formal
+ -- parameter is the null Wide_Wide_String. The lower bound of the result
+ -- Wide_Wide_String is 1.
+
end Ada.Wide_Wide_Characters.Handling;
diff --git a/gcc/ada/libgnat/a-zchuni.adb b/gcc/ada/libgnat/a-zchuni.adb
index 2bbe584..3c6e720 100644
--- a/gcc/ada/libgnat/a-zchuni.adb
+++ b/gcc/ada/libgnat/a-zchuni.adb
@@ -43,6 +43,15 @@ package body Ada.Wide_Wide_Characters.Unicode is
end Get_Category;
--------------
+ -- Is_Basic --
+ --------------
+
+ function Is_Basic (U : Wide_Wide_Character) return Boolean is
+ begin
+ return G.Is_UTF_32_Basic (Wide_Wide_Character'Pos (U));
+ end Is_Basic;
+
+ --------------
-- Is_Digit --
--------------
@@ -158,6 +167,16 @@ package body Ada.Wide_Wide_Characters.Unicode is
return G.Is_UTF_32_Space (G.Category (C));
end Is_Space;
+ --------------
+ -- To_Basic --
+ --------------
+
+ function To_Basic (U : Wide_Wide_Character) return Wide_Wide_Character is
+ begin
+ return Wide_Wide_Character'Val
+ (G.UTF_32_To_Basic (Wide_Wide_Character'Pos (U)));
+ end To_Basic;
+
-------------------
-- To_Lower_Case --
-------------------
diff --git a/gcc/ada/libgnat/a-zchuni.ads b/gcc/ada/libgnat/a-zchuni.ads
index 51f7c92..0030fd1 100644
--- a/gcc/ada/libgnat/a-zchuni.ads
+++ b/gcc/ada/libgnat/a-zchuni.ads
@@ -177,6 +177,18 @@ package Ada.Wide_Wide_Characters.Unicode is
-- in the list of categories above. This means that these characters can
-- be included in character and string literals.
+ function Is_Basic (U : Wide_Wide_Character) return Boolean;
+ pragma Inline (Is_Basic);
+ -- Returns True if the Wide_Wide_Character designated by Item has no
+ -- Decomposition Mapping in the code charts of ISO/IEC 10646:2017,
+ -- otherwise returns False.
+
+ function To_Basic (U : Wide_Wide_Character) return Wide_Wide_Character;
+ pragma Inline (To_Basic);
+ -- Returns the Wide_Wide_Character whose code point is given by the first
+ -- value of its Decomposition Mapping in the code charts of
+ -- ISO/IEC 10646:2017 if any, returns Item otherwise.
+
-- The following function is used to fold to upper case, as required by
-- the Ada 2005 standard rules for identifier case folding. Two
-- identifiers are equivalent if they are identical after folding all
diff --git a/gcc/ada/libgnat/g-forstr.adb b/gcc/ada/libgnat/g-forstr.adb
index 64c4cb6..04539be 100644
--- a/gcc/ada/libgnat/g-forstr.adb
+++ b/gcc/ada/libgnat/g-forstr.adb
@@ -420,11 +420,11 @@ package body GNAT.Formatted_String is
-- Zero padding if required and possible
- if F_Spec.Left_Justify = False
+ if not F_Spec.Left_Justify
and then F_Spec.Zero_Pad
and then F_Spec.Width > Len + Value'First - S
then
- Append (Res, String'((F_Spec.Width - Len + Value'First - S) * '0'));
+ Append (Res, String'((F_Spec.Width - (Len + Value'First - S)) * '0'));
end if;
-- Add the value now
@@ -519,7 +519,7 @@ package body GNAT.Formatted_String is
J := J + 1;
end loop;
- if F (J) /= '%' or else J = F'Last then
+ if J >= F'Last or else F (J) /= '%' then
raise Format_Error with "no format specifier found for parameter"
& Positive'Image (Format.D.Current);
end if;
diff --git a/gcc/ada/libgnat/i-vxwork.ads b/gcc/ada/libgnat/i-vxwork.ads
index c5686bb..0ba1e6e 100644
--- a/gcc/ada/libgnat/i-vxwork.ads
+++ b/gcc/ada/libgnat/i-vxwork.ads
@@ -133,6 +133,9 @@ package Interfaces.VxWorks is
OK : constant STATUS := 0;
ERROR : constant STATUS := -1;
+ type BOOL is new int;
+ -- Equivalent of the C type BOOL
+
type VOIDFUNCPTR is access procedure (parameter : System.Address);
type Interrupt_Vector is new System.Address;
type Exception_Vector is new System.Address;
@@ -145,9 +148,9 @@ package Interfaces.VxWorks is
-- The routine generates a wrapper around the user handler to save and
-- restore context
- function intContext return int;
- -- Binding to the C routine intContext. This function returns 1 only if the
- -- current execution state is in interrupt context.
+ function intContext return BOOL;
+ -- Binding to the C routine intContext. This function returns 1 (TRUE)
+ -- only if the current execution state is in interrupt context.
function intVecGet
(Vector : Interrupt_Vector) return VOIDFUNCPTR;
diff --git a/gcc/ada/libgnat/i-vxwork__x86.ads b/gcc/ada/libgnat/i-vxwork__x86.ads
index ed9bb42..659167f 100644
--- a/gcc/ada/libgnat/i-vxwork__x86.ads
+++ b/gcc/ada/libgnat/i-vxwork__x86.ads
@@ -128,6 +128,9 @@ package Interfaces.VxWorks is
OK : constant STATUS := 0;
ERROR : constant STATUS := -1;
+ type BOOL is new int;
+ -- Equivalent of the C type BOOL
+
type VOIDFUNCPTR is access procedure (parameter : System.Address);
type Interrupt_Vector is new System.Address;
type Exception_Vector is new System.Address;
@@ -140,9 +143,9 @@ package Interfaces.VxWorks is
-- The routine generates a wrapper around the user handler to save and
-- restore context
- function intContext return int;
- -- Binding to the C routine intContext. This function returns 1 only if the
- -- current execution state is in interrupt context.
+ function intContext return BOOL;
+ -- Binding to the C routine intContext. This function returns 1 (TRUE)
+ -- only if the current execution state is in interrupt context.
function intVecGet
(Vector : Interrupt_Vector) return VOIDFUNCPTR;
diff --git a/gcc/ada/libgnat/memtrack.adb b/gcc/ada/libgnat/memtrack.adb
index e622fec..b34ac04 100644
--- a/gcc/ada/libgnat/memtrack.adb
+++ b/gcc/ada/libgnat/memtrack.adb
@@ -69,10 +69,13 @@
pragma Source_File_Name (System.Memory, Body_File_Name => "memtrack.adb");
with Ada.Exceptions;
+with GNAT.IO;
+
with System.Soft_Links;
with System.Traceback;
with System.Traceback_Entries;
-with GNAT.IO;
+with System.CRTL;
+with System.OS_Lib;
with System.OS_Primitives;
package body System.Memory is
@@ -93,30 +96,14 @@ package body System.Memory is
(Ptr : System.Address; Size : size_t) return System.Address;
pragma Import (C, c_realloc, "realloc");
- subtype File_Ptr is System.Address;
-
- function fopen (Path : String; Mode : String) return File_Ptr;
- pragma Import (C, fopen);
-
- procedure OS_Exit (Status : Integer);
- pragma Import (C, OS_Exit, "__gnat_os_exit");
- pragma No_Return (OS_Exit);
-
In_Child_After_Fork : Integer;
pragma Import (C, In_Child_After_Fork, "__gnat_in_child_after_fork");
- procedure fwrite
- (Ptr : System.Address;
- Size : size_t;
- Nmemb : size_t;
- Stream : File_Ptr);
- pragma Import (C, fwrite);
+ subtype File_Ptr is CRTL.FILEs;
- procedure fputc (C : Integer; Stream : File_Ptr);
- pragma Import (C, fputc);
+ procedure Write (Ptr : System.Address; Size : size_t);
- procedure fclose (Stream : File_Ptr);
- pragma Import (C, fclose);
+ procedure Putc (Char : Character);
procedure Finalize;
pragma Export (C, Finalize, "__gnat_finalize");
@@ -210,20 +197,17 @@ package body System.Memory is
Timestamp := System.OS_Primitives.Clock;
Call_Chain
(Tracebk, Max_Call_Stack, Num_Calls, Skip_Frames => 2);
- fputc (Character'Pos ('A'), Gmemfile);
- fwrite (Result'Address, Address_Size, 1, Gmemfile);
- fwrite (Actual_Size'Address, size_t'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
+ Putc ('A');
+ Write (Result'Address, Address_Size);
+ Write (Actual_Size'Address, size_t'Max_Size_In_Storage_Elements);
+ Write (Timestamp'Address, Duration'Max_Size_In_Storage_Elements);
+ Write (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements);
for J in Tracebk'First .. Tracebk'First + Num_Calls - 1 loop
declare
Ptr : System.Address := PC_For (Tracebk (J));
begin
- fwrite (Ptr'Address, Address_Size, 1, Gmemfile);
+ Write (Ptr'Address, Address_Size);
end;
end loop;
@@ -246,8 +230,8 @@ package body System.Memory is
procedure Finalize is
begin
- if not Needs_Init then
- fclose (Gmemfile);
+ if not Needs_Init and then CRTL.fclose (Gmemfile) /= 0 then
+ Put_Line ("gmem close error: " & OS_Lib.Errno_Message);
end if;
end Finalize;
@@ -275,18 +259,16 @@ package body System.Memory is
Call_Chain
(Tracebk, Max_Call_Stack, Num_Calls, Skip_Frames => 2);
Timestamp := System.OS_Primitives.Clock;
- fputc (Character'Pos ('D'), Gmemfile);
- fwrite (Addr'Address, Address_Size, 1, Gmemfile);
- fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
+ Putc ('D');
+ Write (Addr'Address, Address_Size);
+ Write (Timestamp'Address, Duration'Max_Size_In_Storage_Elements);
+ Write (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements);
for J in Tracebk'First .. Tracebk'First + Num_Calls - 1 loop
declare
Ptr : System.Address := PC_For (Tracebk (J));
begin
- fwrite (Ptr'Address, Address_Size, 1, Gmemfile);
+ Write (Ptr'Address, Address_Size);
end;
end loop;
@@ -304,29 +286,41 @@ package body System.Memory is
procedure Gmem_Initialize is
Timestamp : aliased Duration;
-
+ File_Mode : constant String := "wb" & ASCII.NUL;
begin
if Needs_Init then
Needs_Init := False;
System.OS_Primitives.Initialize;
Timestamp := System.OS_Primitives.Clock;
- Gmemfile := fopen (Gmemfname, "wb" & ASCII.NUL);
+ Gmemfile := CRTL.fopen (Gmemfname'Address, File_Mode'Address);
if Gmemfile = System.Null_Address then
Put_Line ("Couldn't open gnatmem log file for writing");
- OS_Exit (255);
+ OS_Lib.OS_Exit (255);
end if;
declare
S : constant String := "GMEM DUMP" & ASCII.LF;
begin
- fwrite (S'Address, S'Length, 1, Gmemfile);
- fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements,
- 1, Gmemfile);
+ Write (S'Address, S'Length);
+ Write (Timestamp'Address, Duration'Max_Size_In_Storage_Elements);
end;
end if;
end Gmem_Initialize;
+ ----------
+ -- Putc --
+ ----------
+
+ procedure Putc (Char : Character) is
+ C : constant Integer := Character'Pos (Char);
+
+ begin
+ if CRTL.fputc (C, Gmemfile) /= C then
+ Put_Line ("gmem fputc error: " & OS_Lib.Errno_Message);
+ end if;
+ end Putc;
+
-------------
-- Realloc --
-------------
@@ -360,18 +354,16 @@ package body System.Memory is
Call_Chain
(Tracebk, Max_Call_Stack, Num_Calls, Skip_Frames => 2);
Timestamp := System.OS_Primitives.Clock;
- fputc (Character'Pos ('D'), Gmemfile);
- fwrite (Addr'Address, Address_Size, 1, Gmemfile);
- fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
+ Putc ('D');
+ Write (Addr'Address, Address_Size);
+ Write (Timestamp'Address, Duration'Max_Size_In_Storage_Elements);
+ Write (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements);
for J in Tracebk'First .. Tracebk'First + Num_Calls - 1 loop
declare
Ptr : System.Address := PC_For (Tracebk (J));
begin
- fwrite (Ptr'Address, Address_Size, 1, Gmemfile);
+ Write (Ptr'Address, Address_Size);
end;
end loop;
@@ -381,20 +373,17 @@ package body System.Memory is
-- Log allocation call using the same backtrace
- fputc (Character'Pos ('A'), Gmemfile);
- fwrite (Result'Address, Address_Size, 1, Gmemfile);
- fwrite (Size'Address, size_t'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
+ Putc ('A');
+ Write (Result'Address, Address_Size);
+ Write (Size'Address, size_t'Max_Size_In_Storage_Elements);
+ Write (Timestamp'Address, Duration'Max_Size_In_Storage_Elements);
+ Write (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements);
for J in Tracebk'First .. Tracebk'First + Num_Calls - 1 loop
declare
Ptr : System.Address := PC_For (Tracebk (J));
begin
- fwrite (Ptr'Address, Address_Size, 1, Gmemfile);
+ Write (Ptr'Address, Address_Size);
end;
end loop;
@@ -411,4 +400,22 @@ package body System.Memory is
return Result;
end Realloc;
+ -----------
+ -- Write --
+ -----------
+
+ procedure Write (Ptr : System.Address; Size : size_t) is
+ function fwrite
+ (buffer : System.Address;
+ size : size_t;
+ count : size_t;
+ stream : File_Ptr) return size_t;
+ pragma Import (C, fwrite);
+
+ begin
+ if fwrite (Ptr, Size, 1, Gmemfile) /= 1 then
+ Put_Line ("gmem fwrite error: " & OS_Lib.Errno_Message);
+ end if;
+ end Write;
+
end System.Memory;
diff --git a/gcc/ada/libgnat/s-arit128.ads b/gcc/ada/libgnat/s-arit128.ads
index 6213cfb..fa6fedc 100644
--- a/gcc/ada/libgnat/s-arit128.ads
+++ b/gcc/ada/libgnat/s-arit128.ads
@@ -81,4 +81,11 @@ package System.Arith_128 is
-- then Q is the rounded quotient. The remainder R is not affected by the
-- setting of the Round flag.
+private
+ -- Make it callable from strub contexts.
+ -- There is a matching setting in trans.c,
+ -- for calls issued by Gigi.
+ pragma Machine_Attribute (Multiply_With_Ovflo_Check128,
+ "strub", "callable");
+
end System.Arith_128;
diff --git a/gcc/ada/libgnat/s-arit64.ads b/gcc/ada/libgnat/s-arit64.ads
index c9141f5..68d2149 100644
--- a/gcc/ada/libgnat/s-arit64.ads
+++ b/gcc/ada/libgnat/s-arit64.ads
@@ -93,4 +93,11 @@ package System.Arith_64 is
Round : Boolean) renames Double_Divide64;
-- Renamed procedure to preserve compatibility with earlier versions
+private
+ -- Make it callable from strub contexts.
+ -- There is a matching setting in trans.c,
+ -- for calls issued by Gigi.
+ pragma Machine_Attribute (Multiply_With_Ovflo_Check64,
+ "strub", "callable");
+
end System.Arith_64;
diff --git a/gcc/ada/libgnat/s-imenne.adb b/gcc/ada/libgnat/s-imenne.adb
deleted file mode 100644
index 4ca7a12..0000000
--- a/gcc/ada/libgnat/s-imenne.adb
+++ /dev/null
@@ -1,170 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- S Y S T E M . I M G _ E N U M _ N E W --
--- --
--- B o d y --
--- --
--- Copyright (C) 2000-2021, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception 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/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
-pragma Compiler_Unit_Warning;
-
-with Ada.Unchecked_Conversion;
-
-package body System.Img_Enum_New is
-
- -------------------------
- -- Image_Enumeration_8 --
- -------------------------
-
- procedure Image_Enumeration_8
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address)
- is
- pragma Assert (S'First = 1);
-
- type Natural_8 is range 0 .. 2 ** 7 - 1;
- subtype Names_Index is
- Natural_8 range Natural_8 (Names'First)
- .. Natural_8 (Names'Last) + 1;
- subtype Index is Natural range Natural'First .. Names'Length;
- type Index_Table is array (Index) of Names_Index;
- type Index_Table_Ptr is access Index_Table;
-
- function To_Index_Table_Ptr is
- new Ada.Unchecked_Conversion (System.Address, Index_Table_Ptr);
-
- IndexesT : constant Index_Table_Ptr := To_Index_Table_Ptr (Indexes);
-
- pragma Assert (Pos in IndexesT'Range);
- pragma Assert (Pos + 1 in IndexesT'Range);
-
- Start : constant Natural := Natural (IndexesT (Pos));
- Next : constant Natural := Natural (IndexesT (Pos + 1));
-
- pragma Assert (Next - 1 >= Start);
- pragma Assert (Start >= Names'First);
- pragma Assert (Next - 1 <= Names'Last);
-
- pragma Assert (Next - Start <= S'Last);
- -- The caller should guarantee that S is large enough to contain the
- -- enumeration image.
- begin
- S (1 .. Next - Start) := Names (Start .. Next - 1);
- P := Next - Start;
- end Image_Enumeration_8;
-
- --------------------------
- -- Image_Enumeration_16 --
- --------------------------
-
- procedure Image_Enumeration_16
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address)
- is
- pragma Assert (S'First = 1);
-
- type Natural_16 is range 0 .. 2 ** 15 - 1;
- subtype Names_Index is
- Natural_16 range Natural_16 (Names'First)
- .. Natural_16 (Names'Last) + 1;
- subtype Index is Natural range Natural'First .. Names'Length;
- type Index_Table is array (Index) of Names_Index;
- type Index_Table_Ptr is access Index_Table;
-
- function To_Index_Table_Ptr is
- new Ada.Unchecked_Conversion (System.Address, Index_Table_Ptr);
-
- IndexesT : constant Index_Table_Ptr := To_Index_Table_Ptr (Indexes);
-
- pragma Assert (Pos in IndexesT'Range);
- pragma Assert (Pos + 1 in IndexesT'Range);
-
- Start : constant Natural := Natural (IndexesT (Pos));
- Next : constant Natural := Natural (IndexesT (Pos + 1));
-
- pragma Assert (Next - 1 >= Start);
- pragma Assert (Start >= Names'First);
- pragma Assert (Next - 1 <= Names'Last);
-
- pragma Assert (Next - Start <= S'Last);
- -- The caller should guarantee that S is large enough to contain the
- -- enumeration image.
- begin
- S (1 .. Next - Start) := Names (Start .. Next - 1);
- P := Next - Start;
- end Image_Enumeration_16;
-
- --------------------------
- -- Image_Enumeration_32 --
- --------------------------
-
- procedure Image_Enumeration_32
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address)
- is
- pragma Assert (S'First = 1);
-
- type Natural_32 is range 0 .. 2 ** 31 - 1;
- subtype Names_Index is
- Natural_32 range Natural_32 (Names'First)
- .. Natural_32 (Names'Last) + 1;
- subtype Index is Natural range Natural'First .. Names'Length;
- type Index_Table is array (Index) of Names_Index;
- type Index_Table_Ptr is access Index_Table;
-
- function To_Index_Table_Ptr is
- new Ada.Unchecked_Conversion (System.Address, Index_Table_Ptr);
-
- IndexesT : constant Index_Table_Ptr := To_Index_Table_Ptr (Indexes);
-
- pragma Assert (Pos in IndexesT'Range);
- pragma Assert (Pos + 1 in IndexesT'Range);
-
- Start : constant Natural := Natural (IndexesT (Pos));
- Next : constant Natural := Natural (IndexesT (Pos + 1));
-
- pragma Assert (Next - 1 >= Start);
- pragma Assert (Start >= Names'First);
- pragma Assert (Next - 1 <= Names'Last);
-
- pragma Assert (Next - Start <= S'Last);
- -- The caller should guarantee that S is large enough to contain the
- -- enumeration image.
- begin
- S (1 .. Next - Start) := Names (Start .. Next - 1);
- P := Next - Start;
- end Image_Enumeration_32;
-
-end System.Img_Enum_New;
diff --git a/gcc/ada/libgnat/s-imenne.ads b/gcc/ada/libgnat/s-imenne.ads
deleted file mode 100644
index eba31c2..0000000
--- a/gcc/ada/libgnat/s-imenne.ads
+++ /dev/null
@@ -1,85 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- S Y S T E M . I M G _ E N U M _ N E W --
--- --
--- S p e c --
--- --
--- Copyright (C) 2000-2021, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception 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/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
--- Enumeration_Type'Image for all enumeration types except those in package
--- Standard (where we have no opportunity to build image tables), and in
--- package System (where it is too early to start building image tables).
--- Special routines exist for the enumeration types in these packages.
-
--- Note: this is an obsolete package replaced by instantiations of the generic
--- package System.Image_N. The reason we maintain this package is that when
--- bootstrapping with an old compiler, the old compiler will search for this
--- unit, expecting to find these functions. The new compiler will search for
--- procedures in the instances of System.Image_N instead.
-
-pragma Compiler_Unit_Warning;
-
-package System.Img_Enum_New is
- pragma Pure;
-
- procedure Image_Enumeration_8
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address);
- -- Used to compute Enum'Image (Str) where Enum is some enumeration type
- -- other than those defined in package Standard. Names is a string with
- -- a lower bound of 1 containing the characters of all the enumeration
- -- literals concatenated together in sequence. Indexes is the address of
- -- an array of type array (0 .. N) of Natural_8, where N is the number of
- -- enumeration literals in the type. The Indexes values are the starting
- -- subscript of each enumeration literal, indexed by Pos values, with an
- -- extra entry at the end containing Names'Length + 1. The reason that
- -- Indexes is passed by address is that the actual type is created on the
- -- fly by the expander. The desired 'Image value is stored in S (1 .. P)
- -- and P is set on return. The caller guarantees that S is long enough to
- -- hold the result and that the lower bound is 1.
-
- procedure Image_Enumeration_16
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address);
- -- Identical to Set_Image_Enumeration_8 except that it handles types using
- -- array (0 .. Num) of Natural_16 for the Indexes table.
-
- procedure Image_Enumeration_32
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address);
- -- Identical to Set_Image_Enumeration_8 except that it handles types using
- -- array (0 .. Num) of Natural_32 for the Indexes table.
-
-end System.Img_Enum_New;
diff --git a/gcc/ada/libgnat/s-imglli.ads b/gcc/ada/libgnat/s-imglli.ads
index 2e0b42c..e6e3efc 100644
--- a/gcc/ada/libgnat/s-imglli.ads
+++ b/gcc/ada/libgnat/s-imglli.ads
@@ -30,8 +30,8 @@
------------------------------------------------------------------------------
-- This package contains the routines for supporting the Image attribute for
--- signed integer types larger Integer, and also for conversion operations
--- required in Text_IO.Integer_IO for such types.
+-- signed integer types larger than Integer, and also for conversion
+-- operations required in Text_IO.Integer_IO for such types.
with System.Image_I;
diff --git a/gcc/ada/libgnat/s-parame__vxworks.ads b/gcc/ada/libgnat/s-parame__vxworks.ads
index 11b408b..b22d858 100644
--- a/gcc/ada/libgnat/s-parame__vxworks.ads
+++ b/gcc/ada/libgnat/s-parame__vxworks.ads
@@ -108,11 +108,11 @@ package System.Parameters is
-- Select the appropriate time_t_bits for the VSB in use, then rebuild
-- the runtime using instructions in adainclude/libada.gpr.
- time_t_bits : constant := Long_Integer'Size;
+ -- time_t_bits : constant := Long_Integer'Size;
-- Number of bits in type time_t for SR0650 and before and SR0660 with
-- non-default configuration.
- -- time_t_bits : constant := Long_Long_Integer'Size;
+ time_t_bits : constant := Long_Long_Integer'Size;
-- Number of bits in type time_t for SR0660 with default configuration.
----------------------------------------------
diff --git a/gcc/ada/libgnat/s-regpat.adb b/gcc/ada/libgnat/s-regpat.adb
index 7e33067..b40f682 100644
--- a/gcc/ada/libgnat/s-regpat.adb
+++ b/gcc/ada/libgnat/s-regpat.adb
@@ -3463,18 +3463,58 @@ package body System.Regpat is
end;
elsif Self.First /= ASCII.NUL then
- -- We know what char it must start with
+ -- We know what char (modulo casing) it must start with
- declare
- Next_Try : Natural := Index (First_In_Data, Self.First);
+ if (Self.Flags and Case_Insensitive) = 0
+ or else Self.First not in 'a' .. 'z'
+ then
+ declare
+ Next_Try : Natural := Index (First_In_Data, Self.First);
+ begin
+ while Next_Try /= 0 loop
+ Matched := Try (Next_Try);
+ exit when Matched;
+ Next_Try := Index (Next_Try + 1, Self.First);
+ end loop;
+ end;
+ else
+ declare
+ Uc_First : constant Character := To_Upper (Self.First);
+
+ function Case_Insensitive_Index
+ (Start : Positive) return Natural;
+ -- Search for both Self.First and To_Upper (Self.First).
+ -- If both are nonzero, return the smaller one; if exactly
+ -- one is nonzero, return it; if both are zero, return zero.
+
+ ---------------------------
+ -- Case_Insenstive_Index --
+ ---------------------------
+
+ function Case_Insensitive_Index
+ (Start : Positive) return Natural
+ is
+ Lc_Index : constant Natural := Index (Start, Self.First);
+ Uc_Index : constant Natural := Index (Start, Uc_First);
+ begin
+ if Lc_Index = 0 then
+ return Uc_Index;
+ elsif Uc_Index = 0 then
+ return Lc_Index;
+ else
+ return Natural'Min (Lc_Index, Uc_Index);
+ end if;
+ end Case_Insensitive_Index;
- begin
- while Next_Try /= 0 loop
- Matched := Try (Next_Try);
- exit when Matched;
- Next_Try := Index (Next_Try + 1, Self.First);
- end loop;
- end;
+ Next_Try : Natural := Case_Insensitive_Index (First_In_Data);
+ begin
+ while Next_Try /= 0 loop
+ Matched := Try (Next_Try);
+ exit when Matched;
+ Next_Try := Case_Insensitive_Index (Next_Try + 1);
+ end loop;
+ end;
+ end if;
else
-- Messy cases: try all locations (including for the empty string)
@@ -3634,6 +3674,9 @@ package body System.Regpat is
if Program (Scan) = EXACT then
Self.First := Program (String_Operand (Scan));
+ elsif Program (Scan) = EXACTF then
+ Self.First := To_Lower (Program (String_Operand (Scan)));
+
elsif Program (Scan) = BOL
or else Program (Scan) = SBOL
or else Program (Scan) = MBOL
diff --git a/gcc/ada/libgnat/s-regpat.ads b/gcc/ada/libgnat/s-regpat.ads
index b1a1366f..8fac30a 100644
--- a/gcc/ada/libgnat/s-regpat.ads
+++ b/gcc/ada/libgnat/s-regpat.ads
@@ -482,18 +482,17 @@ package System.Regpat is
-- Data_First is the lower bound for the match, i.e. Data (Data_First)
-- will be the first character to be examined. If Data_First is set to
-- the special value of -1 (the default), then the first character to
- -- be examined is Data (Data_First). However, the regular expression
- -- character ^ (start of string) still refers to the first character
+ -- be examined is Data (Data'First). However, the regular expression
+ -- character ^ (start of string) always refers to the first character
-- of the full string (Data (Data'First)), which is why there is a
-- separate mechanism for specifying Data_First.
-- Data_Last is the upper bound for the match, i.e. Data (Data_Last)
-- will be the last character to be examined. If Data_Last is set to
-- the special value of Positive'Last (the default), then the last
- -- character to be examined is Data (Data_Last). However, the regular
- -- expression character $ (end of string) still refers to the last
- -- character of the full string (Data (Data'Last)), which is why there
- -- is a separate mechanism for specifying Data_Last.
+ -- character to be examined is Data (Data'Last). However, the regular
+ -- expression character $ (end of string) always refers to the last
+ -- character of the full string (Data (Data'Last)).
-- Note: the use of Data_First and Data_Last is not equivalent to
-- simply passing a slice as Expression because of the handling of
diff --git a/gcc/ada/libgnat/s-secsta.ads b/gcc/ada/libgnat/s-secsta.ads
index 7d6b1b9..6648c23 100644
--- a/gcc/ada/libgnat/s-secsta.ads
+++ b/gcc/ada/libgnat/s-secsta.ads
@@ -440,4 +440,9 @@ private
function Get_Stack_Info (Stack : SS_Stack_Ptr) return Stack_Info;
-- Obtain the information attributes of secondary stack Stack
+ pragma Machine_Attribute (SS_Allocate, "strub", "callable");
+ pragma Machine_Attribute (SS_Mark, "strub", "callable");
+ pragma Machine_Attribute (SS_Release, "strub", "callable");
+ -- Enable these to be called from within strub contexts.
+
end System.Secondary_Stack;
diff --git a/gcc/ada/live.adb b/gcc/ada/live.adb
index 5a74f8b..db0a5f2 100644
--- a/gcc/ada/live.adb
+++ b/gcc/ada/live.adb
@@ -45,7 +45,8 @@ package body Live is
-- any valuable per-node space and possibly results in better locality and
-- cache usage.
- type Name_Set is array (Node_Id range <>) of Boolean;
+ type Name_Set is array (Node_Id'Base range <>) of Boolean;
+ -- We use 'Base here, in case we want to add a predicate to Node_Id
pragma Pack (Name_Set);
function Marked (Marks : Name_Set; Name : Node_Id) return Boolean;
diff --git a/gcc/ada/make.adb b/gcc/ada/make.adb
index 6e74e90..10276fa 100644
--- a/gcc/ada/make.adb
+++ b/gcc/ada/make.adb
@@ -1168,7 +1168,7 @@ package body Make is
end if;
else
- ALI := Scan_ALI (Lib_File, Text, Ignore_ED => False, Err => True);
+ ALI := Scan_ALI (Lib_File, Text, Err => True);
Free (Text);
if ALI = No_ALI_Id then
@@ -2647,7 +2647,7 @@ package body Make is
if Text /= null then
ALI :=
Scan_ALI
- (Data.Lib_File, Text, Ignore_ED => False, Err => True);
+ (Data.Lib_File, Text, Err => True);
if ALI = No_ALI_Id then
diff --git a/gcc/ada/opt.ads b/gcc/ada/opt.ads
index 3786d2c..3ccd630 100644
--- a/gcc/ada/opt.ads
+++ b/gcc/ada/opt.ads
@@ -1031,22 +1031,6 @@ package Opt is
-- GNATBIND
-- Set to True to enable XDR in s-stratt.adb. Set by -xdr.
- type Create_Repinfo_File_Proc is access procedure (Src : String);
- type Write_Repinfo_Line_Proc is access procedure (Info : String);
- type Close_Repinfo_File_Proc is access procedure;
- -- Types used for procedure addresses below
-
- Create_Repinfo_File_Access : Create_Repinfo_File_Proc := null;
- Write_Repinfo_Line_Access : Write_Repinfo_Line_Proc := null;
- Close_Repinfo_File_Access : Close_Repinfo_File_Proc := null;
- -- GNAT
- -- These three locations are left null when operating in non-compiler (e.g.
- -- ASIS mode), but when operating in compiler mode, they are set to point
- -- to the three corresponding procedures in Osint-C. The reason for this
- -- slightly strange interface is to stop Repinfo from dragging in Osint in
- -- ASIS mode, which would include lots of unwanted units in the ASIS build.
- -- ??? Revisit this now that ASIS mode is gone.
-
type Create_List_File_Proc is access procedure (S : String);
type Write_List_Info_Proc is access procedure (S : String);
type Close_List_File_Proc is access procedure;
diff --git a/gcc/ada/osint-c.adb b/gcc/ada/osint-c.adb
index 14c6993..d08b082 100644
--- a/gcc/ada/osint-c.adb
+++ b/gcc/ada/osint-c.adb
@@ -520,10 +520,6 @@ package body Osint.C is
begin
Adjust_OS_Resource_Limits;
- Opt.Create_Repinfo_File_Access := Create_Repinfo_File'Access;
- Opt.Write_Repinfo_Line_Access := Write_Repinfo_Line'Access;
- Opt.Close_Repinfo_File_Access := Close_Repinfo_File'Access;
-
Opt.Create_List_File_Access := Create_List_File'Access;
Opt.Write_List_Info_Access := Write_List_Info'Access;
Opt.Close_List_File_Access := Close_List_File'Access;
diff --git a/gcc/ada/osint.adb b/gcc/ada/osint.adb
index 4ee6aa8..cf39128 100644
--- a/gcc/ada/osint.adb
+++ b/gcc/ada/osint.adb
@@ -2373,14 +2373,12 @@ package body Osint is
Nb_Relative_Dir := 0;
for J in 1 .. Len loop
- -- Treat any control character as a path separator. Note that we do
+ -- Treat any EOL character as a path separator. Note that we do
-- not treat space as a path separator (we used to treat space as a
-- path separator in an earlier version). That way space can appear
-- as a legitimate character in a path name.
- -- Why do we treat all control characters as path separators???
-
- if S (J) in ASCII.NUL .. ASCII.US then
+ if S (J) = ASCII.LF or else S (J) = ASCII.CR then
S (J) := Path_Separator;
end if;
diff --git a/gcc/ada/output.adb b/gcc/ada/output.adb
index e886b92..00202fd 100644
--- a/gcc/ada/output.adb
+++ b/gcc/ada/output.adb
@@ -467,6 +467,32 @@ package body Output is
end if;
end Write_Int;
+ ------------------
+ -- Write_Int_64 --
+ ------------------
+
+ procedure Write_Int_64 (Val : Int_64) is
+ subtype Nonpositive is Int_64 range Int_64'First .. 0;
+ procedure Write_Abs (Val : Nonpositive);
+
+ procedure Write_Abs (Val : Nonpositive) is
+ begin
+ if Val < -9 then
+ Write_Abs (Val / 10);
+ end if;
+
+ Write_Char (Character'Val (-(Val rem 10) + Character'Pos ('0')));
+ end Write_Abs;
+
+ begin
+ if Val < 0 then
+ Write_Char ('-');
+ Write_Abs (Val);
+ else
+ Write_Abs (-Val);
+ end if;
+ end Write_Int_64;
+
----------------
-- Write_Line --
----------------
diff --git a/gcc/ada/output.ads b/gcc/ada/output.ads
index 6a36533..5058d6d 100644
--- a/gcc/ada/output.ads
+++ b/gcc/ada/output.ads
@@ -124,6 +124,7 @@ package Output is
-- Similar as Write_Eol, except that trailing spaces are not removed
procedure Write_Int (Val : Int);
+ procedure Write_Int_64 (Val : Int_64);
-- Write an integer value with no leading blanks or zeroes. Negative values
-- are preceded by a minus sign).
diff --git a/gcc/ada/par-ch4.adb b/gcc/ada/par-ch4.adb
index 20f8dd1..b6cc1a0 100644
--- a/gcc/ada/par-ch4.adb
+++ b/gcc/ada/par-ch4.adb
@@ -3518,62 +3518,62 @@ package body Ch4 is
Assoc_Node :=
New_Node (N_Iterated_Component_Association, Prev_Token_Ptr);
- if Token = Tok_In then
- Set_Defining_Identifier (Assoc_Node, Id);
- T_In;
- Set_Discrete_Choices (Assoc_Node, P_Discrete_Choice_List);
+ case Token is
+ when Tok_In =>
+ Set_Defining_Identifier (Assoc_Node, Id);
+ T_In;
+ Set_Discrete_Choices (Assoc_Node, P_Discrete_Choice_List);
- -- The iterator may include a filter
+ -- The iterator may include a filter
- if Token = Tok_When then
- Scan; -- past WHEN
- Filter := P_Condition;
- end if;
+ if Token = Tok_When then
+ Scan; -- past WHEN
+ Filter := P_Condition;
+ end if;
- if Token = Tok_Use then
+ if Token = Tok_Use then
- -- Ada 2022 Key-expression is present, rewrite node as an
- -- Iterated_Element_Association.
+ -- Ada 2022 Key-expression is present, rewrite node as an
+ -- Iterated_Element_Association.
- Scan; -- past USE
- Build_Iterated_Element_Association;
- Set_Key_Expression (Assoc_Node, P_Expression);
+ Scan; -- past USE
+ Build_Iterated_Element_Association;
+ Set_Key_Expression (Assoc_Node, P_Expression);
- elsif Present (Filter) then
- -- A loop_parameter_specification also indicates an Ada 2022
- -- construct, in contrast with a subtype indication used in
- -- array aggregates.
+ elsif Present (Filter) then
+ -- A loop_parameter_specification also indicates an Ada 2022
+ -- construct, in contrast with a subtype indication used in
+ -- array aggregates.
- Build_Iterated_Element_Association;
- end if;
+ Build_Iterated_Element_Association;
+ end if;
- TF_Arrow;
- Set_Expression (Assoc_Node, P_Expression);
+ TF_Arrow;
+ Set_Expression (Assoc_Node, P_Expression);
- elsif Ada_Version >= Ada_2022
- and then Token = Tok_Of
- then
- Restore_Scan_State (State);
- Scan; -- past OF
- Set_Defining_Identifier (Assoc_Node, Id);
- Iter_Spec := P_Iterator_Specification (Id);
- Set_Iterator_Specification (Assoc_Node, Iter_Spec);
-
- if Token = Tok_Use then
- Scan; -- past USE
- -- This is an iterated_element_association
-
- Assoc_Node :=
- New_Node (N_Iterated_Element_Association, Prev_Token_Ptr);
+ when Tok_Of =>
+ Restore_Scan_State (State);
+ Scan; -- past OF
+ Set_Defining_Identifier (Assoc_Node, Id);
+ Iter_Spec := P_Iterator_Specification (Id);
Set_Iterator_Specification (Assoc_Node, Iter_Spec);
- Set_Key_Expression (Assoc_Node, P_Expression);
- end if;
- TF_Arrow;
- Set_Expression (Assoc_Node, P_Expression);
- end if;
+ if Token = Tok_Use then
+ Scan; -- past USE
+ -- This is an iterated_element_association
- Error_Msg_Ada_2022_Feature ("iterated component", Token_Ptr);
+ Assoc_Node :=
+ New_Node (N_Iterated_Element_Association, Prev_Token_Ptr);
+ Set_Iterator_Specification (Assoc_Node, Iter_Spec);
+ Set_Key_Expression (Assoc_Node, P_Expression);
+ end if;
+
+ TF_Arrow;
+ Set_Expression (Assoc_Node, P_Expression);
+
+ when others =>
+ Error_Msg_AP ("missing IN or OF");
+ end case;
return Assoc_Node;
end P_Iterated_Component_Association;
diff --git a/gcc/ada/par-prag.adb b/gcc/ada/par-prag.adb
index 06c7d87..e1258e0 100644
--- a/gcc/ada/par-prag.adb
+++ b/gcc/ada/par-prag.adb
@@ -1338,6 +1338,7 @@ begin
| Pragma_CPP_Virtual
| Pragma_CPP_Vtable
| Pragma_CPU
+ | Pragma_CUDA_Device
| Pragma_CUDA_Execute
| Pragma_CUDA_Global
| Pragma_C_Pass_By_Copy
diff --git a/gcc/ada/par_sco.adb b/gcc/ada/par_sco.adb
index 513275a..09e4d50 100644
--- a/gcc/ada/par_sco.adb
+++ b/gcc/ada/par_sco.adb
@@ -216,9 +216,6 @@ package body Par_SCO is
-- Parameter D, when present, indicates the dominant of the first
-- declaration or statement within N.
- -- Why is Traverse_Sync_Definition commented specifically, whereas
- -- the others are not???
-
procedure Traverse_Generic_Package_Declaration (N : Node_Id);
procedure Traverse_Handled_Statement_Sequence
@@ -235,8 +232,7 @@ package body Par_SCO is
(N : Node_Id;
D : Dominant_Info := No_Dominant);
- procedure Traverse_Sync_Definition (N : Node_Id);
- -- Traverse a protected definition or task definition
+ procedure Traverse_Protected_Or_Task_Definition (N : Node_Id);
-- Note regarding traversals: In a few cases where an Alternatives list is
-- involved, pragmas such as "pragma Page" may show up before the first
@@ -690,9 +686,6 @@ package body Par_SCO is
-- fully equivalent to the "To" sloc computed by
-- Sloc_Range (Guard, To, From).
- -- Doesn't this requirement of using First_Sloc need to be
- -- documented in the spec ???
-
if Nkind (Parent (N)) in N_Accept_Alternative
| N_Delay_Alternative
| N_Terminate_Alternative
@@ -834,6 +827,14 @@ package body Par_SCO is
return Skip;
end;
+ when N_Quantified_Expression =>
+ declare
+ Cond : constant Node_Id := Condition (N);
+ begin
+ Process_Decisions (Cond, 'W', Pragma_Sloc);
+ return Skip;
+ end;
+
-- All other cases, continue scan
when others =>
@@ -2331,7 +2332,7 @@ package body Par_SCO is
Process_Decisions_Defer (Discriminant_Specifications (N), 'X');
Set_Statement_Entry;
- Traverse_Sync_Definition (N);
+ Traverse_Protected_Or_Task_Definition (N);
when N_Single_Protected_Declaration
| N_Single_Task_Declaration
@@ -2339,7 +2340,7 @@ package body Par_SCO is
Extend_Statement_Sequence (N, 'o');
Set_Statement_Entry;
- Traverse_Sync_Definition (N);
+ Traverse_Protected_Or_Task_Definition (N);
when others =>
@@ -2517,11 +2518,11 @@ package body Par_SCO is
Traverse_Declarations_Or_Statements (Private_Declarations (Spec), Dom);
end Traverse_Package_Declaration;
- ------------------------------
- -- Traverse_Sync_Definition --
- ------------------------------
+ -------------------------------------------
+ -- Traverse_Protected_Or_Task_Definition --
+ -------------------------------------------
- procedure Traverse_Sync_Definition (N : Node_Id) is
+ procedure Traverse_Protected_Or_Task_Definition (N : Node_Id) is
Dom_Info : Dominant_Info := ('S', N);
-- The first declaration is dominated by the protected or task [type]
-- declaration.
@@ -2570,7 +2571,7 @@ package body Par_SCO is
Traverse_Declarations_Or_Statements
(L => Priv_Decl,
D => Dom_Info);
- end Traverse_Sync_Definition;
+ end Traverse_Protected_Or_Task_Definition;
--------------------------------------
-- Traverse_Subprogram_Or_Task_Body --
diff --git a/gcc/ada/pprint.adb b/gcc/ada/pprint.adb
index f7717bf..b76bd91 100644
--- a/gcc/ada/pprint.adb
+++ b/gcc/ada/pprint.adb
@@ -100,7 +100,7 @@ package body Pprint is
Add_Space : Boolean := True;
Add_Paren : Boolean := True;
Num : Natural := 1) return String;
- -- ??? what does this do
+ -- Created for purposes of recursing on embedded lists
------------------------
-- Internal_List_Name --
@@ -113,30 +113,6 @@ package body Pprint is
Add_Paren : Boolean := True;
Num : Natural := 1) return String
is
- function Prepend (S : String) return String;
- -- ??? what does this do
-
- -------------
- -- Prepend --
- -------------
-
- function Prepend (S : String) return String is
- begin
- if Add_Space then
- if Add_Paren then
- return " (" & S;
- else
- return ' ' & S;
- end if;
- elsif Add_Paren then
- return '(' & S;
- else
- return S;
- end if;
- end Prepend;
-
- -- Start of processing for Internal_List_Name
-
begin
if not Present (List) then
if First or else not Add_Paren then
@@ -152,23 +128,22 @@ package body Pprint is
end if;
end if;
- -- ??? the Internal_List_Name calls can be factored out
-
- if First then
- return Prepend (Expr_Name (List)
- & Internal_List_Name
- (List => Next (List),
- First => False,
- Add_Paren => Add_Paren,
- Num => Num + 1));
- else
- return ", " & Expr_Name (List)
- & Internal_List_Name
- (List => Next (List),
- First => False,
- Add_Paren => Add_Paren,
- Num => Num + 1);
- end if;
+ -- Continue recursing on the list - handling the first element
+ -- in a special way.
+
+ return
+ (if First then
+ (if Add_Space and Add_Paren then " ("
+ elsif Add_Paren then "("
+ elsif Add_Space then " "
+ else "")
+ else ", ")
+ & Expr_Name (List)
+ & Internal_List_Name
+ (List => Next (List),
+ First => False,
+ Add_Paren => Add_Paren,
+ Num => Num + 1);
end Internal_List_Name;
-- Start of processing for List_Name
diff --git a/gcc/ada/prep.adb b/gcc/ada/prep.adb
index 37556d5..e01161c 100644
--- a/gcc/ada/prep.adb
+++ b/gcc/ada/prep.adb
@@ -1410,7 +1410,12 @@ package body Prep is
Scan.all;
- if Token /= Tok_If then
+ -- Ignore all recoverable errors if Relaxed_RM_Semantics
+
+ if Relaxed_RM_Semantics then
+ null;
+
+ elsif Token /= Tok_If then
Error_Msg -- CODEFIX
("IF expected", Token_Ptr);
No_Error_Found := False;
@@ -1453,21 +1458,31 @@ package body Prep is
-- Illegal preprocessor line
when others =>
- No_Error_Found := False;
-
if Pp_States.Last = 0 then
Error_Msg -- CODEFIX
("IF expected", Token_Ptr);
+ No_Error_Found := False;
- elsif
- Pp_States.Table (Pp_States.Last).Else_Ptr = 0
+ elsif Relaxed_RM_Semantics
+ and then Get_Name_String (Token_Name) = "endif"
then
+ -- In relaxed mode, accept "endif" instead of
+ -- "end if".
+
+ -- Decrement the depth of the #if stack
+
+ if Pp_States.Last > 0 then
+ Pp_States.Decrement_Last;
+ end if;
+ elsif Pp_States.Table (Pp_States.Last).Else_Ptr = 0 then
Error_Msg
("IF, ELSIF, ELSE, or `END IF` expected",
Token_Ptr);
+ No_Error_Found := False;
else
Error_Msg ("IF or `END IF` expected", Token_Ptr);
+ No_Error_Found := False;
end if;
-- Skip to the end of this illegal line
diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb
index 58e0161..084ca91 100644
--- a/gcc/ada/repinfo.adb
+++ b/gcc/ada/repinfo.adb
@@ -35,6 +35,7 @@ with Namet; use Namet;
with Nlists; use Nlists;
with Opt; use Opt;
with Output; use Output;
+with Osint.C; use Osint.C;
with Sem_Aux; use Sem_Aux;
with Sem_Eval; use Sem_Eval;
with Sinfo; use Sinfo;
@@ -1724,7 +1725,7 @@ package body Repinfo is
-- List representation information to file
else
- Create_Repinfo_File_Access.all
+ Create_Repinfo_File
(Get_Name_String (File_Name (Source_Index (U))));
Set_Special_Output (Write_Info_Line'Access);
if List_Representation_Info_To_JSON then
@@ -1736,7 +1737,7 @@ package body Repinfo is
Write_Line ("]");
end if;
Cancel_Special_Output;
- Close_Repinfo_File_Access.all;
+ Close_Repinfo_File;
end if;
end if;
end loop;
@@ -2328,7 +2329,7 @@ package body Repinfo is
procedure Write_Info_Line (S : String) is
begin
- Write_Repinfo_Line_Access.all (S (S'First .. S'Last - 1));
+ Write_Repinfo_Line (S (S'First .. S'Last - 1));
end Write_Info_Line;
---------------------
diff --git a/gcc/ada/scng.adb b/gcc/ada/scng.adb
index bf1307c..fb42e30b 100644
--- a/gcc/ada/scng.adb
+++ b/gcc/ada/scng.adb
@@ -1743,13 +1743,13 @@ package body Scng is
Code := Character'Pos (' ');
-- In Ada 95 mode we allow any wide character in a character
- -- literal, but in Ada 2005, the set of characters allowed
- -- is restricted to graphic characters.
+ -- literal, but in later versions, the set of characters
+ -- allowed is restricted to graphic characters.
elsif Ada_Version >= Ada_2005
and then Is_UTF_32_Non_Graphic (UTF_32 (Code))
then
- Error_Msg -- CODEFIX????
+ Error_Msg -- CODEFIX
("(Ada 2005) non-graphic character not permitted " &
"in character literal", Wptr);
end if;
diff --git a/gcc/ada/scos.ads b/gcc/ada/scos.ads
index d8e88dd..cdac552 100644
--- a/gcc/ada/scos.ads
+++ b/gcc/ada/scos.ads
@@ -257,7 +257,7 @@ package SCOs is
-- I decision in IF statement or if expression
-- P decision in pragma Assert / Check / Pre/Post_Condition
-- A[name] decision in aspect Pre/Post (aspect name optional)
- -- W decision in WHILE iteration scheme
+ -- W decision in WHILE iteration scheme or quantified expression
-- X decision in some other expression context
-- For E, G, I, P, W, sloc is the source location of the EXIT, ENTRY, IF,
diff --git a/gcc/ada/sem.adb b/gcc/ada/sem.adb
index 783c94aa..3eee2ee 100644
--- a/gcc/ada/sem.adb
+++ b/gcc/ada/sem.adb
@@ -1402,7 +1402,9 @@ package body Sem is
procedure Do_Analyze is
Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
- -- Save the Ghost-related attributes to restore on exit
+ Saved_ISMP : constant Boolean :=
+ Ignore_SPARK_Mode_Pragmas_In_Instance;
+ -- Save Ghost and SPARK mode-related data to restore on exit
-- Generally style checks are preserved across compilations, with
-- one exception: s-oscons.ads, which allows arbitrary long lines
@@ -1421,6 +1423,7 @@ package body Sem is
-- Set up a clean environment before analyzing
Install_Ghost_Region (None, Empty);
+ Ignore_SPARK_Mode_Pragmas_In_Instance := False;
Outer_Generic_Scope := Empty;
Scope_Suppress := Suppress_Options;
@@ -1443,9 +1446,11 @@ package body Sem is
Pop_Scope;
Restore_Scope_Stack (List);
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
Style_Max_Line_Length := Saved_ML;
Style_Check_Max_Line_Length := Saved_CML;
+
+ Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Ignore_SPARK_Mode_Pragmas_In_Instance := Saved_ISMP;
end Do_Analyze;
-- Local variables
diff --git a/gcc/ada/sem.ads b/gcc/ada/sem.ads
index 2fdccf7..699f685 100644
--- a/gcc/ada/sem.ads
+++ b/gcc/ada/sem.ads
@@ -291,6 +291,10 @@ package Sem is
-- freezing nodes can modify the status of this flag, any other client
-- should regard it as read-only.
+ Inside_Class_Condition_Preanalysis : Boolean := False;
+ -- Flag indicating whether we are preanalyzing a class-wide precondition
+ -- or postcondition.
+
Inside_Preanalysis_Without_Freezing : Nat := 0;
-- Flag indicating whether we are preanalyzing an expression performing no
-- freezing. Non-zero means we are inside (it is actually a level counter
diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb
index 9ad9629..9ae5ff6 100644
--- a/gcc/ada/sem_aggr.adb
+++ b/gcc/ada/sem_aggr.adb
@@ -365,7 +365,7 @@ package body Sem_Aggr is
-- to the expansion phase. As an optimization, if the discrete choice
-- specifies a single value we do not delay resolution.
- function Array_Aggr_Subtype (N : Node_Id; Typ : Node_Id) return Entity_Id;
+ function Array_Aggr_Subtype (N : Node_Id; Typ : Entity_Id) return Entity_Id;
-- This routine returns the type or subtype of an array aggregate.
--
-- N is the array aggregate node whose type we return.
@@ -545,6 +545,14 @@ package body Sem_Aggr is
-- Make sure that the list of index constraints is properly attached to
-- the tree, and then collect the aggregate bounds.
+ -- If no aggregaate bounds have been set, this is an aggregate with
+ -- iterator specifications and a dynamic size to be determined by
+ -- first pass of expanded code.
+
+ if No (Aggregate_Bounds (N)) then
+ return Typ;
+ end if;
+
Set_Parent (Index_Constraints, N);
Collect_Aggr_Bounds (N, 1);
@@ -1597,6 +1605,8 @@ package body Sem_Aggr is
Loc : constant Source_Ptr := Sloc (N);
Id : constant Entity_Id := Defining_Identifier (N);
+ Id_Typ : Entity_Id := Any_Type;
+
-----------------------
-- Remove_References --
-----------------------
@@ -1630,42 +1640,65 @@ package body Sem_Aggr is
-- Start of processing for Resolve_Iterated_Component_Association
begin
- -- An element iterator specification cannot appear in
- -- an array aggregate because it does not provide index
- -- values for the association. This must be a semantic
- -- check because the parser cannot tell whether this is
- -- an array aggregate or a container aggregate.
+ Error_Msg_Ada_2022_Feature ("iterated component", Loc);
if Present (Iterator_Specification (N)) then
- Error_Msg_N ("container element Iterator cannot appear "
- & "in an array aggregate", N);
- return;
- end if;
+ Analyze (Name (Iterator_Specification (N)));
- Choice := First (Discrete_Choices (N));
+ -- We assume that the domain of iteration cannot be overloaded.
- while Present (Choice) loop
- if Nkind (Choice) = N_Others_Choice then
- Others_Present := True;
+ declare
+ Domain : constant Node_Id := Name (Iterator_Specification (N));
+ D_Type : constant Entity_Id := Etype (Domain);
+ Elt : Entity_Id;
+ begin
+ if Is_Array_Type (D_Type) then
+ Id_Typ := Component_Type (D_Type);
- else
- Analyze (Choice);
+ else
+ if Has_Aspect (D_Type, Aspect_Iterable) then
+ Elt :=
+ Get_Iterable_Type_Primitive (D_Type, Name_Element);
+ if No (Elt) then
+ Error_Msg_N
+ ("missing Element primitive for iteration", Domain);
+ else
+ Id_Typ := Etype (Elt);
+ end if;
+ else
+ Error_Msg_N ("cannot iterate over", Domain);
+ end if;
+ end if;
+ end;
- -- Choice can be a subtype name, a range, or an expression
+ else
+ Id_Typ := Index_Typ;
+ Choice := First (Discrete_Choices (N));
- if Is_Entity_Name (Choice)
- and then Is_Type (Entity (Choice))
- and then Base_Type (Entity (Choice)) = Base_Type (Index_Typ)
- then
- null;
+ while Present (Choice) loop
+ if Nkind (Choice) = N_Others_Choice then
+ Others_Present := True;
else
- Analyze_And_Resolve (Choice, Index_Typ);
+ Analyze (Choice);
+
+ -- Choice can be a subtype name, a range, or an expression
+
+ if Is_Entity_Name (Choice)
+ and then Is_Type (Entity (Choice))
+ and then
+ Base_Type (Entity (Choice)) = Base_Type (Index_Typ)
+ then
+ null;
+
+ else
+ Analyze_And_Resolve (Choice, Index_Typ);
+ end if;
end if;
- end if;
- Next (Choice);
- end loop;
+ Next (Choice);
+ end loop;
+ end if;
-- Create a scope in which to introduce an index, which is usually
-- visible in the expression for the component, and needed for its
@@ -1681,7 +1714,7 @@ package body Sem_Aggr is
-- directly visible.
Enter_Name (Id);
- Set_Etype (Id, Index_Typ);
+ Set_Etype (Id, Id_Typ);
Mutate_Ekind (Id, E_Variable);
Set_Scope (Id, Ent);
@@ -1735,6 +1768,12 @@ package body Sem_Aggr is
Delete_Choice : Boolean;
-- Used when replacing a subtype choice with predicate by a list
+ Has_Iterator_Specifications : Boolean := False;
+ -- Flag to indicate that all named associations are iterated component
+ -- associations with iterator specifications, in which case the
+ -- expansion will create two loops: one to evaluate the size and one
+ -- to generate the elements (4.3.3 (20.2/5)).
+
Nb_Elements : Uint := Uint_0;
-- The number of elements in a positional aggregate
@@ -1756,6 +1795,54 @@ package body Sem_Aggr is
-- STEP 1: make sure the aggregate is correctly formatted
if Present (Component_Associations (N)) then
+
+ -- Verify that all or none of the component associations
+ -- include an iterator specification.
+
+ Assoc := First (Component_Associations (N));
+ if Nkind (Assoc) = N_Iterated_Component_Association
+ and then Present (Iterator_Specification (Assoc))
+ then
+ -- All other component associations must have an iterator spec.
+
+ Next (Assoc);
+ while Present (Assoc) loop
+ if Nkind (Assoc) /= N_Iterated_Component_Association
+ or else No (Iterator_Specification (Assoc))
+ then
+ Error_Msg_N ("mixed iterated component association"
+ & " (RM 4.4.3 (17.1/5))",
+ Assoc);
+ return False;
+ end if;
+
+ Next (Assoc);
+ end loop;
+
+ Has_Iterator_Specifications := True;
+
+ else
+ -- or none of them do.
+
+ Next (Assoc);
+ while Present (Assoc) loop
+ if Nkind (Assoc) = N_Iterated_Component_Association
+ and then Present (Iterator_Specification (Assoc))
+ then
+ Error_Msg_N ("mixed iterated component association"
+ & " (RM 4.4.3 (17.1/5))",
+ Assoc);
+ return False;
+ end if;
+
+ Next (Assoc);
+ end loop;
+
+ while Present (Assoc) loop
+ Next (Assoc);
+ end loop;
+ end if;
+
Assoc := First (Component_Associations (N));
while Present (Assoc) loop
if Nkind (Assoc) = N_Iterated_Component_Association then
@@ -1867,7 +1954,7 @@ package body Sem_Aggr is
or else (Nb_Choices = 1 and then not Others_Present))
then
Error_Msg_N
- ("named association cannot follow positional association",
+ ("cannot mix named and positional associations in array aggregate",
First (Choice_List (First (Component_Associations (N)))));
return Failure;
end if;
@@ -1948,9 +2035,12 @@ package body Sem_Aggr is
begin
-- STEP 2 (A): Check discrete choices validity
+ -- No need if this is an element iteration.
Assoc := First (Component_Associations (N));
- while Present (Assoc) loop
+ while Present (Assoc)
+ and then Present (Choice_List (Assoc))
+ loop
Prev_Nb_Discrete_Choices := Nb_Discrete_Choices;
Choice := First (Choice_List (Assoc));
@@ -2391,6 +2481,12 @@ package body Sem_Aggr is
end Check_Choices;
end if;
+ if Has_Iterator_Specifications then
+ -- Bounds will be determined dynamically.
+
+ return Success;
+ end if;
+
-- STEP 2 (B): Compute aggregate bounds and min/max choices values
if Nb_Discrete_Choices > 0 then
@@ -2706,7 +2802,10 @@ package body Sem_Aggr is
-- Exp_Aggr.Convert_To_Positional, so we don't want to change those
-- bounds.
- if Present (Aggregate_Bounds (N)) and then not Others_Allowed then
+ if Present (Aggregate_Bounds (N))
+ and then not Others_Allowed
+ and then not Comes_From_Source (N)
+ then
Aggr_Low := Low_Bound (Aggregate_Bounds (N));
Aggr_High := High_Bound (Aggregate_Bounds (N));
end if;
@@ -2770,6 +2869,7 @@ package body Sem_Aggr is
Key_Type : Entity_Id;
Elmt_Type : Entity_Id)
is
+ Loc : constant Source_Ptr := Sloc (N);
Choice : Node_Id;
Ent : Entity_Id;
Expr : Node_Id;
@@ -2780,6 +2880,8 @@ package body Sem_Aggr is
Typ : Entity_Id := Empty;
begin
+ Error_Msg_Ada_2022_Feature ("iterated component", Loc);
+
-- If this is an Iterated_Element_Association then either a
-- an Iterator_Specification or a Loop_Parameter specification
-- is present. In both cases a Key_Expression is present.
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index b44bbe3..4d69d58 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -1339,6 +1339,16 @@ package body Sem_Attr is
Legal := False;
Spec_Id := Empty;
+ -- Skip processing during preanalysis of class-wide preconditions and
+ -- postconditions since at this stage the expression is not installed
+ -- yet on its definite context.
+
+ if Inside_Class_Condition_Preanalysis then
+ Legal := True;
+ Spec_Id := Current_Scope;
+ return;
+ end if;
+
-- Traverse the parent chain to find the aspect or pragma where the
-- attribute resides.
@@ -1519,14 +1529,6 @@ package body Sem_Attr is
Check_E1;
Set_Etype (N, Str_Typ);
- -- ???It's not clear why 'Img should behave any differently than
- -- 'Image.
-
- if Attr_Id = Attribute_Img then
- Error_Attr_P
- ("prefix of % attribute must be a scalar object name");
- end if;
-
pragma Assert (Is_Entity_Name (P) and then Is_Type (Entity (P)));
if Ekind (Entity (P)) = E_Incomplete_Type
@@ -6641,7 +6643,9 @@ package body Sem_Attr is
Initialize (CRC);
Compute_Type_Key (Entity (P));
- if not Is_Frozen (Entity (P)) then
+ if not Is_Frozen (Entity (P))
+ and then not Is_Generic_Type (Entity (P))
+ then
Error_Msg_N ("premature usage of Type_Key?", N);
end if;
@@ -9131,12 +9135,26 @@ package body Sem_Attr is
-- Leading_Part --
------------------
- when Attribute_Leading_Part =>
+ when Attribute_Leading_Part => Leading_Part : declare
+ Radix_Digits : constant Uint := Expr_Value (E2);
+
+ begin
+ if UI_Le (Radix_Digits, Uint_0) then
+ Apply_Compile_Time_Constraint_Error
+ (N, "Radix_Digits in Leading_Part is zero or negative",
+ CE_Explicit_Raise,
+ Warn => not Static);
+
+ Check_Expressions;
+ return;
+ end if;
+
Fold_Ureal
(N,
Eval_Fat.Leading_Part
- (P_Base_Type, Expr_Value_R (E1), Expr_Value (E2)),
+ (P_Base_Type, Expr_Value_R (E1), Radix_Digits),
Static);
+ end Leading_Part;
------------
-- Length --
@@ -11488,28 +11506,45 @@ package body Sem_Attr is
-- in such a context - unless the restriction
-- No_Dynamic_Accessibility_Checks is active.
- if Attr_Id /= Attribute_Unchecked_Access
- and then
- (Ekind (Btyp) = E_General_Access_Type
- or else No_Dynamic_Accessibility_Checks_Enabled (Btyp))
-
- -- Call Accessibility_Level directly to avoid returning zero
- -- on cases where the prefix is an explicitly aliased
- -- parameter in a return statement, instead of using the
- -- normal Static_Accessibility_Level function.
-
- -- Shouldn't this be handled somehow in
- -- Static_Accessibility_Level ???
+ declare
+ No_Dynamic_Acc_Checks : constant Boolean :=
+ No_Dynamic_Accessibility_Checks_Enabled (Btyp);
- and then Nkind (Accessibility_Level (P, Dynamic_Level))
- = N_Integer_Literal
- and then
- Intval (Accessibility_Level (P, Dynamic_Level))
- > Deepest_Type_Access_Level (Btyp)
- then
- Accessibility_Message;
- return;
- end if;
+ Compatible_Alt_Checks : constant Boolean :=
+ No_Dynamic_Acc_Checks and then not Debug_Flag_Underscore_B;
+ begin
+ if Attr_Id /= Attribute_Unchecked_Access
+ and then (Ekind (Btyp) = E_General_Access_Type
+ or else No_Dynamic_Acc_Checks)
+
+ -- In the case of the alternate "compatibility"
+ -- accessibility model we do not perform a static
+ -- accessibility check on actuals for anonymous access
+ -- types - so exclude them here.
+
+ and then not (Compatible_Alt_Checks
+ and then Is_Actual_Parameter (N)
+ and then Ekind (Btyp)
+ = E_Anonymous_Access_Type)
+
+ -- Call Accessibility_Level directly to avoid returning
+ -- zero on cases where the prefix is an explicitly aliased
+ -- parameter in a return statement, instead of using the
+ -- normal Static_Accessibility_Level function.
+
+ -- Shouldn't this be handled somehow in
+ -- Static_Accessibility_Level ???
+
+ and then Nkind (Accessibility_Level (P, Dynamic_Level))
+ = N_Integer_Literal
+ and then
+ Intval (Accessibility_Level (P, Dynamic_Level))
+ > Deepest_Type_Access_Level (Btyp)
+ then
+ Accessibility_Message;
+ return;
+ end if;
+ end;
end if;
if Ekind (Btyp) in E_Access_Protected_Subprogram_Type
@@ -12477,7 +12512,7 @@ package body Sem_Attr is
function Stream_Attribute_Available
(Typ : Entity_Id;
Nam : TSS_Name_Type;
- Partial_View : Node_Id := Empty) return Boolean
+ Partial_View : Entity_Id := Empty) return Boolean
is
Etyp : Entity_Id := Typ;
diff --git a/gcc/ada/sem_aux.adb b/gcc/ada/sem_aux.adb
index bce7c38..dcced7e 100644
--- a/gcc/ada/sem_aux.adb
+++ b/gcc/ada/sem_aux.adb
@@ -1402,6 +1402,31 @@ package body Sem_Aux is
end Object_Type_Has_Constrained_Partial_View;
------------------
+ -- Package_Body --
+ ------------------
+
+ function Package_Body (E : Entity_Id) return Node_Id is
+ Body_Decl : Node_Id;
+ Body_Id : constant Opt_E_Package_Body_Id :=
+ Corresponding_Body (Package_Spec (E));
+
+ begin
+ if Present (Body_Id) then
+ Body_Decl := Parent (Body_Id);
+
+ if Nkind (Body_Decl) = N_Defining_Program_Unit_Name then
+ Body_Decl := Parent (Body_Decl);
+ end if;
+
+ pragma Assert (Nkind (Body_Decl) = N_Package_Body);
+
+ return Body_Decl;
+ else
+ return Empty;
+ end if;
+ end Package_Body;
+
+ ------------------
-- Package_Spec --
------------------
diff --git a/gcc/ada/sem_aux.ads b/gcc/ada/sem_aux.ads
index 810e2d8..3adaee4 100644
--- a/gcc/ada/sem_aux.ads
+++ b/gcc/ada/sem_aux.ads
@@ -377,6 +377,10 @@ package Sem_Aux is
-- derived type, and the subtype is not an unconstrained array subtype
-- (RM 3.3(23.10/3)).
+ function Package_Body (E : Entity_Id) return Node_Id;
+ -- Given an entity for a package, return the corresponding package body, if
+ -- any, or else Empty.
+
function Package_Spec (E : Entity_Id) return Node_Id;
-- Given an entity for a package spec, return the corresponding package
-- spec if any, or else Empty.
diff --git a/gcc/ada/sem_case.adb b/gcc/ada/sem_case.adb
index 7d08da5..31f14d5 100644
--- a/gcc/ada/sem_case.adb
+++ b/gcc/ada/sem_case.adb
@@ -44,6 +44,7 @@ with Stand; use Stand;
with Sinfo; use Sinfo;
with Sinfo.Nodes; use Sinfo.Nodes;
with Sinfo.Utils; use Sinfo.Utils;
+with Stringt; use Stringt;
with Table;
with Tbuild; use Tbuild;
with Uintp; use Uintp;
@@ -105,25 +106,70 @@ package body Sem_Case is
package Composite_Case_Ops is
+ function Choice_Count (Alternatives : List_Id) return Nat;
+ -- The sum of the number of choices for each alternative in the given
+ -- list.
+
function Scalar_Part_Count (Subtyp : Entity_Id) return Nat;
-- Given the composite type Subtyp of a case selector, returns the
-- number of scalar parts in an object of this type. This is the
-- dimensionality of the associated Cartesian product space.
- function Choice_Count (Alternatives : List_Id) return Nat;
- -- The sum of the number of choices for each alternative in the given
- -- list.
+ package Array_Case_Ops is
+ function Array_Choice_Length (Choice : Node_Id) return Nat;
+ -- Given a choice expression of an array type, returns its length.
+
+ function Normalized_Case_Expr_Type
+ (Case_Statement : Node_Id) return Entity_Id;
+ -- Usually returns the Etype of the selector expression of the
+ -- case statement. However, in the case of a constrained array
+ -- subtype with a nonstatic constraint, returns the unconstrained
+ -- array base type.
+
+ function Unconstrained_Array_Effective_Length
+ (Array_Type : Entity_Id; Case_Statement : Node_Id) return Nat;
+ -- If the nominal subtype of the case selector is unconstrained,
+ -- then use the length of the longest choice of the case statement.
+ -- Components beyond that index value will not influence the case
+ -- selection decision.
+
+ function Unconstrained_Array_Scalar_Part_Count
+ (Array_Type : Entity_Id; Case_Statement : Node_Id) return Nat;
+ -- Same as Scalar_Part_Count except that the value used for the
+ -- "length" of the array subtype being cased on is determined by
+ -- calling Unconstrained_Array_Effective_Length.
+ end Array_Case_Ops;
generic
Case_Statement : Node_Id;
package Choice_Analysis is
+ use Array_Case_Ops;
+
type Alternative_Id is
new Int range 1 .. List_Length (Alternatives (Case_Statement));
type Choice_Id is
new Int range 1 .. Choice_Count (Alternatives (Case_Statement));
+
+ Case_Expr_Type : constant Entity_Id :=
+ Normalized_Case_Expr_Type (Case_Statement);
+
+ Unconstrained_Array_Case : constant Boolean :=
+ Is_Array_Type (Case_Expr_Type)
+ and then not Is_Constrained (Case_Expr_Type);
+
+ -- If Unconstrained_Array_Case is True, choice lengths may differ:
+ -- when "Aaa" | "Bb" | "C" | "" =>
+ --
+ -- Strictly speaking, the name "Unconstrained_Array_Case" is
+ -- slightly imprecise; a subtype with a nonstatic constraint is
+ -- also treated as unconstrained (see Normalize_Case_Expr_Type).
+
type Part_Id is new Int range
- 1 .. Scalar_Part_Count (Etype (Expression (Case_Statement)));
+ 1 .. (if Unconstrained_Array_Case
+ then Unconstrained_Array_Scalar_Part_Count
+ (Case_Expr_Type, Case_Statement)
+ else Scalar_Part_Count (Case_Expr_Type));
type Discrete_Range_Info is
record
@@ -1118,6 +1164,21 @@ package body Sem_Case is
return UI_To_Int (Len);
end Static_Array_Length;
+ ------------------
+ -- Choice_Count --
+ ------------------
+
+ function Choice_Count (Alternatives : List_Id) return Nat is
+ Result : Nat := 0;
+ Alt : Node_Id := First (Alternatives);
+ begin
+ while Present (Alt) loop
+ Result := Result + List_Length (Discrete_Choices (Alt));
+ Next (Alt);
+ end loop;
+ return Result;
+ end Choice_Count;
+
-----------------------
-- Scalar_Part_Count --
-----------------------
@@ -1147,20 +1208,118 @@ package body Sem_Case is
end if;
end Scalar_Part_Count;
- ------------------
- -- Choice_Count --
- ------------------
+ package body Array_Case_Ops is
- function Choice_Count (Alternatives : List_Id) return Nat is
- Result : Nat := 0;
- Alt : Node_Id := First (Alternatives);
- begin
- while Present (Alt) loop
- Result := Result + List_Length (Discrete_Choices (Alt));
- Next (Alt);
- end loop;
- return Result;
- end Choice_Count;
+ -------------------------
+ -- Array_Choice_Length --
+ -------------------------
+
+ function Array_Choice_Length (Choice : Node_Id) return Nat is
+ begin
+ case Nkind (Choice) is
+ when N_String_Literal =>
+ return String_Length (Strval (Choice));
+ when N_Aggregate =>
+ declare
+ Bounds : constant Node_Id :=
+ Aggregate_Bounds (Choice);
+ pragma Assert (Is_OK_Static_Range (Bounds));
+ Lo : constant Uint :=
+ Expr_Value (Low_Bound (Bounds));
+ Hi : constant Uint :=
+ Expr_Value (High_Bound (Bounds));
+ Len : constant Uint := (Hi - Lo) + 1;
+ begin
+ return UI_To_Int (Len);
+ end;
+ when N_Has_Entity =>
+ if Present (Entity (Choice))
+ and then Ekind (Entity (Choice)) = E_Constant
+ then
+ return Array_Choice_Length
+ (Expression (Parent (Entity (Choice))));
+ end if;
+ when N_Others_Choice =>
+ return 0;
+ when others =>
+ null;
+ end case;
+
+ if Nkind (Original_Node (Choice))
+ in N_String_Literal | N_Aggregate
+ then
+ return Array_Choice_Length (Original_Node (Choice));
+ end if;
+
+ Error_Msg_N ("Unsupported case choice", Choice);
+ return 0;
+ end Array_Choice_Length;
+
+ -------------------------------
+ -- Normalized_Case_Expr_Type --
+ -------------------------------
+
+ function Normalized_Case_Expr_Type
+ (Case_Statement : Node_Id) return Entity_Id
+ is
+ Unnormalized : constant Entity_Id :=
+ Etype (Expression (Case_Statement));
+ begin
+ if Is_Array_Type (Unnormalized)
+ and then Is_Constrained (Unnormalized)
+ and then not Has_Static_Array_Bounds (Unnormalized)
+ then
+ return Base_Type (Unnormalized);
+ else
+ return Unnormalized;
+ end if;
+ end Normalized_Case_Expr_Type;
+
+ ------------------------------------------
+ -- Unconstrained_Array_Effective_Length --
+ ------------------------------------------
+
+ function Unconstrained_Array_Effective_Length
+ (Array_Type : Entity_Id; Case_Statement : Node_Id) return Nat
+ is
+ pragma Assert (Is_Array_Type (Array_Type));
+ -- Array_Type is otherwise unreferenced for now.
+
+ Result : Nat := 0;
+ Alt : Node_Id := First (Alternatives (Case_Statement));
+ begin
+ while Present (Alt) loop
+ declare
+ Choice : Node_Id := First (Discrete_Choices (Alt));
+ begin
+ while Present (Choice) loop
+ Result := Nat'Max (Result, Array_Choice_Length (Choice));
+ Next (Choice);
+ end loop;
+ end;
+ Next (Alt);
+ end loop;
+
+ return Result;
+ end Unconstrained_Array_Effective_Length;
+
+ -------------------------------------------
+ -- Unconstrained_Array_Scalar_Part_Count --
+ -------------------------------------------
+
+ function Unconstrained_Array_Scalar_Part_Count
+ (Array_Type : Entity_Id; Case_Statement : Node_Id) return Nat
+ is
+ begin
+ -- Add one for the length, which is treated like a discriminant
+
+ return 1 + (Unconstrained_Array_Effective_Length
+ (Array_Type => Array_Type,
+ Case_Statement => Case_Statement)
+ * Scalar_Part_Count (Component_Type (Array_Type)));
+ end Unconstrained_Array_Scalar_Part_Count;
+
+ end Array_Case_Ops;
package body Choice_Analysis is
@@ -1220,9 +1379,32 @@ package body Sem_Case is
((Low => Expr_Value (Type_Low_Bound (Subtyp)),
High => Expr_Value (Type_High_Bound (Subtyp))));
elsif Is_Array_Type (Subtyp) then
- for I in 1 .. Static_Array_Length (Subtyp) loop
- Traverse_Discrete_Parts (Component_Type (Subtyp));
- end loop;
+ declare
+ Len : Nat;
+ begin
+ if Is_Constrained (Subtyp) then
+ Len := Static_Array_Length (Subtyp);
+ else
+ -- Length will be treated like a discriminant;
+ -- We could compute High more precisely as
+ -- 1 + Index_Subtype'Last - Index_Subtype'First
+ -- (we currently require that those bounds be
+ -- static, so this is an option), but only downside of
+ -- overshooting is if somebody wants to omit a
+ -- "when others" choice and exhaustively cover all
+ -- possibilities explicitly.
+ Update_Result
+ ((Low => Uint_0,
+ High => Uint_2 ** Uint_32));
+
+ Len := Unconstrained_Array_Effective_Length
+ (Array_Type => Subtyp,
+ Case_Statement => Case_Statement);
+ end if;
+ for I in 1 .. Len loop
+ Traverse_Discrete_Parts (Component_Type (Subtyp));
+ end loop;
+ end;
elsif Is_Record_Type (Subtyp) then
if Has_Static_Discriminant_Constraint (Subtyp) then
@@ -1274,7 +1456,7 @@ package body Sem_Case is
end Traverse_Discrete_Parts;
begin
- Traverse_Discrete_Parts (Etype (Expression (Case_Statement)));
+ Traverse_Discrete_Parts (Case_Expr_Type);
pragma Assert (Done or else Serious_Errors_Detected > 0);
return Result;
end Component_Bounds_Info;
@@ -1531,6 +1713,19 @@ package body Sem_Case is
& "choice not implemented", Expr);
end if;
+ if not Unconstrained_Array_Case
+ and then List_Length (Expressions (Expr))
+ /= Nat (Part_Id'Last)
+ then
+ Error_Msg_Uint_1 := UI_From_Int
+ (List_Length (Expressions (Expr)));
+ Error_Msg_Uint_2 := UI_From_Int (Int (Part_Id'Last));
+ Error_Msg_N
+ ("array aggregate length ^ does not match length " &
+ "of statically constrained case selector ^", Expr);
+ return;
+ end if;
+
declare
Subexpr : Node_Id := First (Expressions (Expr));
begin
@@ -1542,9 +1737,51 @@ package body Sem_Case is
else
raise Program_Error;
end if;
+ elsif Nkind (Expr) = N_String_Literal then
+ if not Is_Array_Type (Etype (Expr)) then
+ Error_Msg_N
+ ("User-defined string literal not allowed as/within"
+ & "case choice", Expr);
+ else
+ declare
+ Char_Type : constant Entity_Id :=
+ Root_Type (Component_Type (Etype (Expr)));
+
+ -- If the component type is not a standard character
+ -- type then this string lit should have already been
+ -- transformed into an aggregate in
+ -- Resolve_String_Literal.
+ --
+ pragma Assert (Is_Standard_Character_Type (Char_Type));
+
+ Str : constant String_Id := Strval (Expr);
+ Strlen : constant Nat := String_Length (Str);
+ Char_Val : Uint;
+ begin
+ if not Unconstrained_Array_Case
+ and then Strlen /= Nat (Part_Id'Last)
+ then
+ Error_Msg_Uint_1 := UI_From_Int (Strlen);
+ Error_Msg_Uint_2 := UI_From_Int
+ (Int (Part_Id'Last));
+ Error_Msg_N
+ ("String literal length ^ does not match length" &
+ " of statically constrained case selector ^",
+ Expr);
+ return;
+ end if;
+
+ for Idx in 1 .. Strlen loop
+ Char_Val :=
+ UI_From_CC (Get_String_Char (Str, Idx));
+ Update_Result ((Low | High => Char_Val));
+ end loop;
+ end;
+ end if;
elsif Is_Discrete_Type (Etype (Expr)) then
- if Nkind (Expr) in N_Has_Entity and then
- Is_Type (Entity (Expr))
+ if Nkind (Expr) in N_Has_Entity
+ and then Present (Entity (Expr))
+ and then Is_Type (Entity (Expr))
then
declare
Low : constant Node_Id :=
@@ -1559,10 +1796,20 @@ package body Sem_Case is
pragma Assert (Compile_Time_Known_Value (Expr));
Update_Result ((Low | High => Expr_Value (Expr)));
end if;
+ elsif Nkind (Expr) in N_Has_Entity
+ and then Present (Entity (Expr))
+ and then Ekind (Entity (Expr)) = E_Constant
+ then
+ Traverse_Choice (Expression (Parent (Entity (Expr))));
+ elsif Nkind (Original_Node (Expr))
+ in N_Aggregate | N_String_Literal
+ then
+ Traverse_Choice (Original_Node (Expr));
else
Error_Msg_N
- ("non-aggregate case choice subexpression which is not"
- & " of a discrete type not implemented", Expr);
+ ("non-aggregate case choice (or subexpression thereof)"
+ & " that is not of a discrete type not implemented",
+ Expr);
end if;
end Traverse_Choice;
@@ -1572,8 +1819,26 @@ package body Sem_Case is
if Nkind (Choice) = N_Others_Choice then
return (Is_Others => True);
end if;
+
+ if Unconstrained_Array_Case then
+ -- Treat length like a discriminant
+ Update_Result ((Low | High =>
+ UI_From_Int (Array_Choice_Length (Choice))));
+ end if;
+
Traverse_Choice (Choice);
+ if Unconstrained_Array_Case then
+ -- This is somewhat tricky. Suppose we are casing on String,
+ -- the longest choice in the case statement is length 10, and
+ -- the choice we are looking at now is of length 6. We fill
+ -- in the trailing 4 slots here.
+ while Next_Part <= Part_Id'Last loop
+ Update_Result_For_Full_Coverage
+ (Comp_Type => Component_Type (Case_Expr_Type));
+ end loop;
+ end if;
+
-- Avoid returning uninitialized garbage in error case
if Next_Part /= Part_Id'Last + 1 then
pragma Assert (Serious_Errors_Detected > 0);
@@ -2098,6 +2363,12 @@ package body Sem_Case is
Result := Result * Value_Index_Base (Uint_Sets.Size (Set));
end loop;
return Result;
+ exception
+ when Constraint_Error =>
+ Error_Msg_N
+ ("Capacity exceeded in compiling case statement with"
+ & " composite selector type", Case_Statement);
+ raise;
end Value_Index_Count;
Max_Value_Index : constant Value_Index_Base := Value_Index_Count;
@@ -3014,12 +3285,20 @@ package body Sem_Case is
"an enumeration representation clause", N);
end if;
elsif Is_Array_Type (Subtyp) then
- pragma Assert (Is_Constrained (Subtyp));
-
if Number_Dimensions (Subtyp) /= 1 then
Error_Msg_N
("dimensionality of array type of case selector (or " &
"subcomponent thereof) is greater than 1", N);
+
+ elsif not Is_Constrained (Subtyp) then
+ if not Is_Static_Subtype
+ (Etype (First_Index (Subtyp)))
+ then
+ Error_Msg_N
+ ("Unconstrained array subtype of case selector" &
+ " has nonstatic index subtype", N);
+ end if;
+
elsif not Is_OK_Static_Range (First_Index (Subtyp)) then
Error_Msg_N
("array subtype of case selector (or " &
@@ -3077,10 +3356,6 @@ package body Sem_Case is
elsif Needs_Finalization (Subtyp) then
Error_Msg_N ("case selector type requires finalization", N);
- elsif Is_Array_Type (Subtyp) and not Is_Constrained (Subtyp) then
- Error_Msg_N
- ("case selector subtype is unconstrained array subtype", N);
-
else
Check_Component_Subtype (Subtyp);
end if;
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index eca2abf..e4cb7e3 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -13047,7 +13047,7 @@ package body Sem_Ch12 is
while Present (Index) loop
Num := Num + 1;
- Next_Index (Index);
+ Next (Index);
end loop;
return Num;
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index 228fd39..fb1be47 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -26,6 +26,7 @@
with Aspects; use Aspects;
with Atree; use Atree;
with Checks; use Checks;
+with Contracts; use Contracts;
with Debug; use Debug;
with Einfo; use Einfo;
with Einfo.Entities; use Einfo.Entities;
@@ -261,6 +262,19 @@ package body Sem_Ch13 is
-- Check legality of functions given in the Ada 2022 Stable_Properties
-- (or Stable_Properties'Class) aspect.
+ procedure Validate_Storage_Model_Type_Aspect
+ (Typ : Entity_Id; ASN : Node_Id);
+ -- Check legality and completeness of the aggregate associations given in
+ -- the Storage_Model_Type aspect associated with Typ.
+
+ procedure Resolve_Storage_Model_Type_Argument
+ (N : Node_Id;
+ Typ : Entity_Id;
+ Addr_Type : in out Entity_Id;
+ Nam : Name_Id);
+ -- Resolve argument N to be of the proper kind (when a type or constant)
+ -- or to have the proper profile (when a subprogram).
+
procedure Resolve_Aspect_Stable_Properties
(Typ_Or_Subp : Entity_Id;
Expr : Node_Id;
@@ -860,6 +874,7 @@ package body Sem_Ch13 is
if Known_Alignment (Typ)
and then not Has_Alignment_Clause (Typ)
+ and then Present (Size)
and then Size mod (Alignment (Typ) * SSU) /= 0
then
Reinit_Alignment (Typ);
@@ -1515,6 +1530,32 @@ package body Sem_Ch13 is
when Aspect_Iterable =>
Validate_Iterable_Aspect (E, ASN);
+ when Aspect_Designated_Storage_Model =>
+ Analyze_And_Resolve (Expression (ASN));
+
+ if not Is_Entity_Name (Expression (ASN))
+ or else not Is_Object (Entity (Expression (ASN)))
+ or else
+ not Present (Find_Aspect (Etype (Expression (ASN)),
+ Aspect_Storage_Model_Type))
+ then
+ Error_Msg_N
+ ("must specify name of stand-alone object of type "
+ & "with aspect Storage_Model_Type",
+ Expression (ASN));
+
+ -- Set access type's Associated_Storage_Pool to denote
+ -- the Storage_Model_Type object given for the aspect
+ -- (even though that isn't actually an Ada storage pool).
+
+ else
+ Set_Associated_Storage_Pool
+ (E, Entity (Expression (ASN)));
+ end if;
+
+ when Aspect_Storage_Model_Type =>
+ Validate_Storage_Model_Type_Aspect (E, ASN);
+
when Aspect_Aggregate =>
null;
@@ -2989,7 +3030,15 @@ package body Sem_Ch13 is
-- Copy expression for later processing by the procedures
-- Check_Aspect_At_[Freeze_Point | End_Of_Declarations]
- Set_Entity (Id, New_Copy_Tree (Expr));
+ -- The expression may be a subprogram name, and can
+ -- be an operator name that appears as a string, but
+ -- requires its own analysis procedure (see sem_ch6).
+
+ if Nkind (Expr) = N_Operator_Symbol then
+ Set_Entity (Id, Expr);
+ else
+ Set_Entity (Id, New_Copy_Tree (Expr));
+ end if;
-- Set Delay_Required as appropriate to aspect
@@ -3055,10 +3104,11 @@ package body Sem_Ch13 is
if Delay_Required
- and then A_Id = Aspect_Stable_Properties
+ and then (A_Id = Aspect_Stable_Properties
+ or else A_Id = Aspect_Designated_Storage_Model
+ or else A_Id = Aspect_Storage_Model_Type)
-- ??? It seems like we should do this for all aspects, not
- -- just Stable_Properties, but that causes as-yet-undiagnosed
- -- regressions.
+ -- just these, but that causes as-yet-undiagnosed regressions.
then
Set_Has_Delayed_Aspects (E);
@@ -4358,6 +4408,44 @@ package body Sem_Ch13 is
Record_Rep_Item (E, Aspect);
goto Continue;
+ when Aspect_Designated_Storage_Model =>
+ if not Extensions_Allowed then
+ Error_Msg_N
+ ("aspect only allowed if extensions enabled",
+ Aspect);
+ Error_Msg_N
+ ("\unit must be compiled with -gnatX switch", Aspect);
+
+ elsif not Is_Type (E)
+ or else Ekind (E) /= E_Access_Type
+ then
+ Error_Msg_N
+ ("can only be specified for pool-specific access type",
+ Aspect);
+ end if;
+
+ Record_Rep_Item (E, Aspect);
+ goto Continue;
+
+ when Aspect_Storage_Model_Type =>
+ if not Extensions_Allowed then
+ Error_Msg_N
+ ("aspect only allowed if extensions enabled",
+ Aspect);
+ Error_Msg_N
+ ("\unit must be compiled with -gnatX switch", Aspect);
+
+ elsif not Is_Type (E)
+ or else not Is_Immutably_Limited_Type (E)
+ then
+ Error_Msg_N
+ ("can only be specified for immutably limited type",
+ Aspect);
+ end if;
+
+ Record_Rep_Item (E, Aspect);
+ goto Continue;
+
when Aspect_Integer_Literal
| Aspect_Real_Literal
| Aspect_String_Literal
@@ -4445,6 +4533,38 @@ package body Sem_Ch13 is
goto Continue;
end if;
+ -- Remember class-wide conditions; they will be merged
+ -- with inherited conditions.
+
+ if Class_Present (Aspect)
+ and then A_Id in Aspect_Pre | Aspect_Post
+ and then Is_Subprogram (E)
+ and then not Is_Ignored_Ghost_Entity (E)
+ then
+ if A_Id = Aspect_Pre then
+ if Is_Ignored (Aspect) then
+ Set_Ignored_Class_Preconditions (E,
+ New_Copy_Tree (Expr));
+ else
+ Set_Class_Preconditions (E, New_Copy_Tree (Expr));
+ end if;
+
+ -- Postconditions may split into separate aspects, and we
+ -- remember the expression before such split (i.e. when
+ -- the first postcondition is processed).
+
+ elsif No (Class_Postconditions (E))
+ and then No (Ignored_Class_Postconditions (E))
+ then
+ if Is_Ignored (Aspect) then
+ Set_Ignored_Class_Postconditions (E,
+ New_Copy_Tree (Expr));
+ else
+ Set_Class_Postconditions (E, New_Copy_Tree (Expr));
+ end if;
+ end if;
+ end if;
+
-- If the expressions is of the form A and then B, then
-- we generate separate Pre/Post aspects for the separate
-- clauses. Since we allow multiple pragmas, there is no
@@ -7125,7 +7245,7 @@ package body Sem_Ch13 is
else
Check_Size (Expr, U_Ent, Size, Biased);
- if Size <= 0 then
+ if No (Size) or else Size <= 0 then
Error_Msg_N ("Object_Size must be positive", Expr);
elsif Is_Scalar_Type (U_Ent) then
@@ -10103,7 +10223,10 @@ package body Sem_Ch13 is
-- If the type is private, check whether full view has inherited
-- predicates.
- if Is_Private_Type (Typ) and then No (Ritem) then
+ if Is_Private_Type (Typ)
+ and then No (Ritem)
+ and then Present (Full_View (Typ))
+ then
Ritem := First_Rep_Item (Full_View (Typ));
end if;
@@ -10191,6 +10314,9 @@ package body Sem_Ch13 is
or else
(Is_Itype (Typ)
and then not Comes_From_Source (Typ)
+ and then Ekind (Typ) in E_Array_Subtype
+ | E_Record_Subtype
+ | E_Record_Subtype_With_Private
and then Present (Predicated_Parent (Typ)))
then
return;
@@ -11181,6 +11307,34 @@ package body Sem_Ch13 is
-- Here is the list of aspects that don't require delay analysis
+ when Aspect_Designated_Storage_Model =>
+ return;
+
+ when Aspect_Storage_Model_Type =>
+ T := Entity (ASN);
+
+ declare
+ Assoc : Node_Id;
+ Expr : Node_Id;
+ Addr_Type : Entity_Id := Empty;
+
+ begin
+ Assoc := First (Component_Associations (Expression (ASN)));
+ while Present (Assoc) loop
+ Expr := Expression (Assoc);
+ Analyze (Expr);
+
+ if not Error_Posted (Expr) then
+ Resolve_Storage_Model_Type_Argument
+ (Expr, T, Addr_Type, Chars (First (Choices (Assoc))));
+ end if;
+
+ Next (Assoc);
+ end loop;
+ end;
+
+ return;
+
when Aspect_Abstract_State
| Aspect_Annotate
| Aspect_Async_Readers
@@ -12361,8 +12515,8 @@ package body Sem_Ch13 is
end if;
-- Outer level of record definition, check discriminants
- -- but be careful not to flag a non-girder discriminant
- -- and the girder discriminant it renames as overlapping.
+ -- but be careful not to flag a non-stored discriminant
+ -- and the stored discriminant it renames as overlapping.
if Nkind (Clist) in N_Full_Type_Declaration
| N_Private_Type_Declaration
@@ -13162,6 +13316,13 @@ package body Sem_Ch13 is
end if;
end Check_Variant_Part;
end if;
+
+ if not In_Generic_Scope (E)
+ and then Ekind (E) = E_Record_Type
+ and then Is_Tagged_Type (E)
+ then
+ Process_Class_Conditions_At_Freeze_Point (E);
+ end if;
end Freeze_Entity_Checks;
-------------------------
@@ -16144,6 +16305,334 @@ package body Sem_Ch13 is
Set_Analyzed (Expr);
end Resolve_Aspect_Stable_Properties;
+ -----------------------------------------
+ -- Resolve_Storage_Model_Type_Argument --
+ -----------------------------------------
+
+ procedure Resolve_Storage_Model_Type_Argument
+ (N : Node_Id;
+ Typ : Entity_Id;
+ Addr_Type : in out Entity_Id;
+ Nam : Name_Id)
+ is
+
+ type Formal_Profile is record
+ Subt : Entity_Id;
+ Mode : Formal_Kind;
+ end record;
+
+ type Formal_Profiles is array (Positive range <>) of Formal_Profile;
+
+ function Aspect_Argument_Profile_Matches
+ (Subp : Entity_Id;
+ Profiles : Formal_Profiles;
+ Result_Subt : Entity_Id;
+ Err_On_Mismatch : Boolean) return Boolean;
+ -- Checks that the formal parameters of subprogram Subp conform to the
+ -- subtypes and modes specified by Profiles, as well as to the result
+ -- subtype Result_Subt when that is nonempty.
+
+ function Aspect_Argument_Profile_Matches
+ (Subp : Entity_Id;
+ Profiles : Formal_Profiles;
+ Result_Subt : Entity_Id;
+ Err_On_Mismatch : Boolean) return Boolean
+ is
+
+ procedure Report_Argument_Error
+ (Msg : String;
+ Formal : Entity_Id := Empty;
+ Subt : Entity_Id := Empty);
+ -- If Err_On_Mismatch is True, reports an argument error given by Msg
+ -- associated with Formal and/or Subt.
+
+ procedure Report_Argument_Error
+ (Msg : String;
+ Formal : Entity_Id := Empty;
+ Subt : Entity_Id := Empty)
+ is
+ begin
+ if Err_On_Mismatch then
+ if Present (Formal) then
+ if Present (Subt) then
+ Error_Msg_Node_2 := Subt;
+ end if;
+ Error_Msg_NE (Msg, N, Formal);
+
+ elsif Present (Subt) then
+ Error_Msg_NE (Msg, N, Subt);
+
+ else
+ Error_Msg_N (Msg, N);
+ end if;
+ end if;
+ end Report_Argument_Error;
+
+ -- Local variables
+
+ Formal : Entity_Id := First_Formal (Subp);
+ Is_Error : Boolean := False;
+
+ -- Start of processing for Aspect_Argument_Profile_Matches
+
+ begin
+ for FP of Profiles loop
+ if not Present (Formal) then
+ Is_Error := True;
+ Report_Argument_Error ("missing formal of }", Subt => FP.Subt);
+ exit;
+
+ elsif not Subtypes_Statically_Match
+ (Etype (Formal), FP.Subt)
+ then
+ Is_Error := True;
+ Report_Argument_Error
+ ("formal& must be of subtype&",
+ Formal => Formal, Subt => FP.Subt);
+ exit;
+
+ elsif Ekind (Formal) /= FP.Mode then
+ Is_Error := True;
+ Report_Argument_Error
+ ("formal& has wrong mode", Formal => Formal);
+ exit;
+ end if;
+
+ Formal := Next_Formal (Formal);
+ end loop;
+
+ if not Is_Error
+ and then Present (Formal)
+ then
+ Is_Error := True;
+ Report_Argument_Error
+ ("too many formals for subprogram in aspect");
+ end if;
+
+ if not Is_Error
+ and then Present (Result_Subt)
+ and then not Subtypes_Statically_Match (Etype (Subp), Result_Subt)
+ then
+ Is_Error := True;
+ Report_Argument_Error
+ ("subprogram must have result}", Subt => Result_Subt);
+ end if;
+
+ return not Is_Error;
+ end Aspect_Argument_Profile_Matches;
+
+ -- Local variables
+
+ Ent : Entity_Id;
+
+ Storage_Count_Type : constant Entity_Id := RTE (RE_Storage_Count);
+ System_Address_Type : constant Entity_Id := RTE (RE_Address);
+
+ -- Start of processing for Resolve_Storage_Model_Type_Argument
+
+ begin
+ if Nam = Name_Address_Type then
+ if not Is_Entity_Name (N)
+ or else not Is_Type (Entity (N))
+ or else (Root_Type (Entity (N)) /= System_Address_Type
+ and then not Is_Integer_Type (Entity (N)))
+ then
+ Error_Msg_N ("named entity must be a descendant of System.Address "
+ & "or an integer type", N);
+ end if;
+
+ Addr_Type := Entity (N);
+
+ return;
+
+ elsif not Present (Addr_Type) then
+ Error_Msg_N ("argument association for Address_Type missing; "
+ & "must be specified as first aspect argument", N);
+ return;
+
+ elsif Nam = Name_Null_Address then
+ if not Is_Entity_Name (N)
+ or else not Is_Constant_Object (Entity (N))
+ or else
+ not Subtypes_Statically_Match (Etype (Entity (N)), Addr_Type)
+ then
+ Error_Msg_NE
+ ("named entity must be constant of subtype}", N, Addr_Type);
+ end if;
+
+ return;
+
+ elsif not Is_Overloaded (N) then
+ if not Is_Entity_Name (N)
+ or else Ekind (Entity (N)) not in E_Function | E_Procedure
+ or else Scope (Entity (N)) /= Scope (Typ)
+ then
+ Error_Msg_N ("argument must be local subprogram name", N);
+ return;
+ end if;
+
+ Ent := Entity (N);
+
+ if Nam = Name_Allocate then
+ if not Aspect_Argument_Profile_Matches
+ (Ent,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (Addr_Type, E_Out_Parameter),
+ (Storage_Count_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => True)
+ then
+ Error_Msg_N ("no match for Allocate operation", N);
+ end if;
+
+ elsif Nam = Name_Deallocate then
+ if not Aspect_Argument_Profile_Matches
+ (Ent,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (Addr_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => True)
+ then
+ Error_Msg_N ("no match for Deallocate operation", N);
+ end if;
+
+ elsif Nam = Name_Copy_From then
+ if not Aspect_Argument_Profile_Matches
+ (Ent,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (System_Address_Type, E_In_Parameter),
+ (Addr_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => True)
+ then
+ Error_Msg_N ("no match for Copy_From operation", N);
+ end if;
+
+ elsif Nam = Name_Copy_To then
+ if not Aspect_Argument_Profile_Matches
+ (Ent,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (Addr_Type, E_In_Parameter),
+ (System_Address_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => True)
+ then
+ Error_Msg_N ("no match for Copy_To operation", N);
+ end if;
+
+ elsif Nam = Name_Storage_Size then
+ if not Aspect_Argument_Profile_Matches
+ (Ent,
+ Profiles => (1 => (Typ, E_In_Parameter)),
+ Result_Subt => Storage_Count_Type,
+ Err_On_Mismatch => True)
+ then
+ Error_Msg_N ("no match for Storage_Size operation", N);
+ end if;
+
+ else
+ null; -- Error will be caught in Validate_Storage_Model_Type_Aspect
+ end if;
+
+ else
+ -- Overloaded case: find subprogram with proper signature
+
+ declare
+ I : Interp_Index;
+ It : Interp;
+ Found_Match : Boolean := False;
+
+ begin
+ Get_First_Interp (N, I, It);
+ while Present (It.Typ) loop
+ if Ekind (It.Nam) in E_Function | E_Procedure
+ and then Scope (It.Nam) = Scope (Typ)
+ then
+ if Nam = Name_Allocate then
+ Found_Match :=
+ Aspect_Argument_Profile_Matches
+ (It.Nam,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (Addr_Type, E_Out_Parameter),
+ (Storage_Count_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => False);
+
+ elsif Nam = Name_Deallocate then
+ Found_Match :=
+ Aspect_Argument_Profile_Matches
+ (It.Nam,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (Addr_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => False);
+
+ elsif Nam = Name_Copy_From then
+ Found_Match :=
+ Aspect_Argument_Profile_Matches
+ (It.Nam,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (System_Address_Type, E_In_Parameter),
+ (Addr_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => False);
+
+ elsif Nam = Name_Copy_To then
+ Found_Match :=
+ Aspect_Argument_Profile_Matches
+ (It.Nam,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (Addr_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter),
+ (System_Address_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => False);
+
+ elsif Nam = Name_Storage_Size then
+ Found_Match :=
+ Aspect_Argument_Profile_Matches
+ (It.Nam,
+ Profiles => (1 => (Typ, E_In_Parameter)),
+ Result_Subt => Storage_Count_Type,
+ Err_On_Mismatch => False);
+ end if;
+
+ if Found_Match then
+ Set_Entity (N, It.Nam);
+ exit;
+ end if;
+ end if;
+
+ Get_Next_Interp (I, It);
+ end loop;
+
+ if not Found_Match then
+ Error_Msg_N
+ ("no match found for Storage_Model_Type operation", N);
+ end if;
+ end;
+ end if;
+ end Resolve_Storage_Model_Type_Argument;
+
----------------
-- Set_Biased --
----------------
@@ -16621,7 +17110,15 @@ package body Sem_Ch13 is
end if;
if not Overloaded and then not Present (Entity (Func_Name)) then
- Analyze (Func_Name);
+ -- The aspect is specified by a subprogram name, which
+ -- may be an operator name given originally by a string.
+
+ if Is_Operator_Name (Chars (Func_Name)) then
+ Analyze_Operator_Symbol (Func_Name);
+ else
+ Analyze (Func_Name);
+ end if;
+
Overloaded := Is_Overloaded (Func_Name);
end if;
@@ -16718,6 +17215,116 @@ package body Sem_Ch13 is
end if;
end Validate_Literal_Aspect;
+ ----------------------------------------
+ -- Validate_Storage_Model_Type_Aspect --
+ ----------------------------------------
+
+ procedure Validate_Storage_Model_Type_Aspect
+ (Typ : Entity_Id; ASN : Node_Id)
+ is
+ Assoc : Node_Id;
+ Choice : Entity_Id;
+ Expr : Node_Id;
+
+ Address_Type_Id : Entity_Id := Empty;
+ Null_Address_Id : Entity_Id := Empty;
+ Allocate_Id : Entity_Id := Empty;
+ Deallocate_Id : Entity_Id := Empty;
+ Copy_From_Id : Entity_Id := Empty;
+ Copy_To_Id : Entity_Id := Empty;
+ Storage_Size_Id : Entity_Id := Empty;
+
+ begin
+ -- Each expression must resolve to an entity of the right kind or proper
+ -- profile.
+
+ Assoc := First (Component_Associations (Expression (ASN)));
+ while Present (Assoc) loop
+ Expr := Expression (Assoc);
+ Analyze (Expr);
+
+ Choice := First (Choices (Assoc));
+
+ if Nkind (Choice) /= N_Identifier or else Present (Next (Choice)) then
+ Error_Msg_N ("illegal name in association", Choice);
+
+ elsif Chars (Choice) = Name_Address_Type then
+ if Assoc /= First (Component_Associations (Expression (ASN))) then
+ Error_Msg_N ("Address_Type must be first association", Choice);
+ end if;
+
+ Resolve_Storage_Model_Type_Argument
+ (Expr, Typ, Address_Type_Id, Name_Address_Type);
+ Address_Type_Id := Entity (Expr);
+
+ -- Shouldn't we check for duplicates of the same subaspect name,
+ -- and issue an error in such cases???
+
+ elsif not Present (Address_Type_Id) then
+ Error_Msg_N
+ ("Address_Type missing, must be first association", Choice);
+
+ elsif Chars (Choice) = Name_Null_Address then
+ Resolve_Storage_Model_Type_Argument
+ (Expr, Typ, Address_Type_Id, Name_Null_Address);
+ Null_Address_Id := Entity (Expr);
+
+ elsif Chars (Choice) = Name_Allocate then
+ Resolve_Storage_Model_Type_Argument
+ (Expr, Typ, Address_Type_Id, Name_Allocate);
+ Allocate_Id := Entity (Expr);
+
+ elsif Chars (Choice) = Name_Deallocate then
+ Resolve_Storage_Model_Type_Argument
+ (Expr, Typ, Address_Type_Id, Name_Deallocate);
+ Deallocate_Id := Entity (Expr);
+
+ elsif Chars (Choice) = Name_Copy_From then
+ Resolve_Storage_Model_Type_Argument
+ (Expr, Typ, Address_Type_Id, Name_Copy_From);
+ Copy_From_Id := Entity (Expr);
+
+ elsif Chars (Choice) = Name_Copy_To then
+ Resolve_Storage_Model_Type_Argument
+ (Expr, Typ, Address_Type_Id, Name_Copy_To);
+ Copy_To_Id := Entity (Expr);
+
+ elsif Chars (Choice) = Name_Storage_Size then
+ Resolve_Storage_Model_Type_Argument
+ (Expr, Typ, Address_Type_Id, Name_Storage_Size);
+ Storage_Size_Id := Entity (Expr);
+
+ else
+ Error_Msg_N
+ ("invalid name for Storage_Model_Type argument", Choice);
+ end if;
+
+ Next (Assoc);
+ end loop;
+
+ if No (Address_Type_Id) then
+ Error_Msg_N ("match for Address_Type not found", ASN);
+
+ elsif No (Null_Address_Id) then
+ Error_Msg_N ("match for Null_Address primitive not found", ASN);
+
+ elsif No (Allocate_Id) then
+ Error_Msg_N ("match for Allocate primitive not found", ASN);
+
+ elsif No (Deallocate_Id) then
+ Error_Msg_N ("match for Deallocate primitive not found", ASN);
+
+ elsif No (Copy_From_Id) then
+ Error_Msg_N ("match for Copy_From primitive not found", ASN);
+
+ elsif No (Copy_To_Id) then
+ Error_Msg_N ("match for Copy_To primitive not found", ASN);
+
+ elsif No (Storage_Size_Id) then
+ Error_Msg_N ("match for Storage_Size primitive not found", ASN);
+ end if;
+ end Validate_Storage_Model_Type_Aspect;
+
-----------------------------------
-- Validate_Unchecked_Conversion --
-----------------------------------
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index cc8a9b7..f1a56ad 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -696,8 +696,8 @@ package body Sem_Ch3 is
-- copy will leave the references to the ancestor discriminants unchanged
-- in the declaration tree and they need to be fixed up. If the derived
-- type has a known discriminant part, then the remapping done during the
- -- copy will only create references to the girder discriminants and they
- -- need to be replaced with references to the non-girder discriminants.
+ -- copy will only create references to the stored discriminants and they
+ -- need to be replaced with references to the non-stored discriminants.
procedure Set_Fixed_Range
(E : Entity_Id;
@@ -4505,7 +4505,7 @@ package body Sem_Ch3 is
-- default initial value (including via a Default_Value or
-- Default_Component_Value aspect, see AI12-0301) and then this is not
-- an internal declaration whose initialization comes later (as for an
- -- aggregate expansion).
+ -- aggregate expansion) or a deferred constant.
-- If expression is an aggregate it may be expanded into assignments
-- and the declaration itself is marked with No_Initialization, but
-- the predicate still applies.
@@ -4519,6 +4519,7 @@ package body Sem_Ch3 is
(Present (E)
or else
Is_Partially_Initialized_Type (T, Include_Implicit => False))
+ and then not (Constant_Present (N) and then No (E))
then
-- If the type has a static predicate and the expression is known at
-- compile time, see if the expression satisfies the predicate.
@@ -6253,7 +6254,7 @@ package body Sem_Ch3 is
-- Move to next index
- Next_Index (Index);
+ Next (Index);
Nb_Index := Nb_Index + 1;
end loop;
@@ -6766,6 +6767,7 @@ package body Sem_Ch3 is
Make_Procedure_Specification (Loc,
Defining_Unit_Name => Subp,
Parameter_Specifications => Profile);
+ Mutate_Ekind (Subp, E_Procedure);
else
Spec :=
Make_Function_Specification (Loc,
@@ -6774,13 +6776,32 @@ package body Sem_Ch3 is
Result_Definition =>
New_Copy_Tree
(Result_Definition (Type_Definition (Decl))));
+ Mutate_Ekind (Subp, E_Function);
end if;
New_Decl :=
Make_Subprogram_Declaration (Loc, Specification => Spec);
Set_Aspect_Specifications (New_Decl, Contracts);
+ Set_Is_Wrapper (Subp);
+
+ -- The wrapper is declared in the freezing actions to facilitate its
+ -- identification and thus avoid handling it as a primitive operation
+ -- of a tagged type (see Is_Access_To_Subprogram_Wrapper); otherwise it
+ -- may be handled as a dispatching operation and erroneously registered
+ -- in a dispatch table.
+
+ if not GNATprove_Mode then
+ Ensure_Freeze_Node (Id);
+ Append_Freeze_Actions (Id, New_List (New_Decl));
+
+ -- Under GNATprove mode there is no such problem but we do not declare
+ -- it in the freezing actions since they are not analyzed under this
+ -- mode.
+
+ else
+ Insert_After (Decl, New_Decl);
+ end if;
- Insert_After (Decl, New_Decl);
Set_Access_Subprogram_Wrapper (Designated_Type (Id), Subp);
Build_Access_Subprogram_Wrapper_Body (Decl, New_Decl);
end Build_Access_Subprogram_Wrapper;
@@ -8475,11 +8496,11 @@ package body Sem_Ch3 is
-- discriminants in R and T1 through T4:
-- Type Discrim Stored Discrim Comment
- -- R (D1, D2, D3) (D1, D2, D3) Girder discrims implicit in R
- -- T1 (D1, D2, D3) (D1, D2, D3) Girder discrims implicit in T1
- -- T2 (X1, X2) (D1, D2, D3) Girder discrims EXPLICIT in T2
- -- T3 (X1, X2) (D1, D2, D3) Girder discrims EXPLICIT in T3
- -- T4 (Y) (D1, D2, D3) Girder discrims EXPLICIT in T4
+ -- R (D1, D2, D3) (D1, D2, D3) Stored discrims implicit in R
+ -- T1 (D1, D2, D3) (D1, D2, D3) Stored discrims implicit in T1
+ -- T2 (X1, X2) (D1, D2, D3) Stored discrims EXPLICIT in T2
+ -- T3 (X1, X2) (D1, D2, D3) Stored discrims EXPLICIT in T3
+ -- T4 (Y) (D1, D2, D3) Stored discrims EXPLICIT in T4
-- Field Corresponding_Discriminant (abbreviated CD below) allows us to
-- find the corresponding discriminant in the parent type, while
@@ -15133,7 +15154,7 @@ package body Sem_Ch3 is
Add_Discriminants : declare
Num_Disc : Nat;
- Num_Gird : Nat;
+ Num_Stor : Nat;
begin
Num_Disc := 0;
@@ -15154,7 +15175,7 @@ package body Sem_Ch3 is
-- the GCC 4.x back-end decides to break apart assignments between
-- objects using the parent view into member-wise assignments.
- Num_Gird := 0;
+ Num_Stor := 0;
if Is_Derived_Type (Typ)
and then not Is_Tagged_Type (Typ)
@@ -15162,12 +15183,12 @@ package body Sem_Ch3 is
Old_C := First_Stored_Discriminant (Typ);
while Present (Old_C) loop
- Num_Gird := Num_Gird + 1;
+ Num_Stor := Num_Stor + 1;
Next_Stored_Discriminant (Old_C);
end loop;
end if;
- if Num_Gird > Num_Disc then
+ if Num_Stor > Num_Disc then
-- Find out multiple uses of new discriminants, and add hidden
-- components for the extra renamed discriminants. We recognize
@@ -16090,6 +16111,14 @@ package body Sem_Ch3 is
Set_No_Return (New_Subp, No_Return (Parent_Subp));
+ -- If the parent subprogram is marked as Ghost, then so is the derived
+ -- subprogram. The ghost policy for the derived subprogram is set from
+ -- the effective ghost policy at the point of derived type declaration.
+
+ if Is_Ghost_Entity (Parent_Subp) then
+ Set_Is_Ghost_Entity (New_Subp);
+ end if;
+
-- A derived function with a controlling result is abstract. If the
-- Derived_Type is a nonabstract formal generic derived type, then
-- inherited operations are not abstract: the required check is done at
@@ -19793,6 +19822,8 @@ package body Sem_Ch3 is
Set_Is_Non_Static_Subtype (Def_Id);
end if;
end if;
+
+ Set_Parent (Def_Id, N);
end if;
-- Final step is to label the index with this constructed type
diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb
index 7a8d0cc..45d2457 100644
--- a/gcc/ada/sem_ch5.adb
+++ b/gcc/ada/sem_ch5.adb
@@ -1681,6 +1681,13 @@ package body Sem_Ch5 is
Error_Msg_N
("(Ada 83) case expression cannot be of a generic type", Exp);
return;
+
+ elsif not Extensions_Allowed
+ and then not Is_Discrete_Type (Exp_Type)
+ then
+ Error_Msg_N
+ ("expression in case statement must be of a discrete_Type", Exp);
+ return;
end if;
-- If the case expression is a formal object of mode in out, then treat
@@ -3028,6 +3035,10 @@ package body Sem_Ch5 is
then
Analyze_And_Resolve (Original_Bound, Typ);
return Original_Bound;
+
+ elsif Inside_Class_Condition_Preanalysis then
+ Analyze_And_Resolve (Original_Bound, Typ);
+ return Original_Bound;
end if;
-- Normally, the best approach is simply to generate a constant
@@ -3333,11 +3344,17 @@ package body Sem_Ch5 is
-- or post-condition has been expanded. Update the type of the loop
-- variable to reflect the proper itype at each stage of analysis.
+ -- Loop_Nod might not be present when we are preanalyzing a class-wide
+ -- pre/postcondition since preanalysis occurs in a place unrelated to
+ -- the actual code and the quantified expression may be the outermost
+ -- expression of the class-wide condition.
+
if No (Etype (Id))
or else Etype (Id) = Any_Type
or else
(Present (Etype (Id))
and then Is_Itype (Etype (Id))
+ and then Present (Loop_Nod)
and then Nkind (Parent (Loop_Nod)) = N_Expression_With_Actions
and then Nkind (Original_Node (Parent (Loop_Nod))) =
N_Quantified_Expression)
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 304dc19..e32c4ad 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -385,15 +385,9 @@ package body Sem_Ch6 is
Analyze (New_Body);
Set_Is_Inlined (Prev);
- -- If the expression function is a completion, the previous declaration
- -- must come from source. We know already that it appears in the current
- -- scope. The entity itself may be internally created if within a body
- -- to be inlined.
-
elsif Present (Prev)
and then Is_Overloadable (Prev)
and then not Is_Formal_Subprogram (Prev)
- and then Comes_From_Source (Parent (Prev))
then
Set_Has_Completion (Prev, False);
Set_Is_Inlined (Prev);
@@ -2132,8 +2126,15 @@ package body Sem_Ch6 is
and then Attribute_Name (Par) /= Name_Value)
or else (Nkind (Maybe_Aspect_Spec) = N_Aspect_Specification
and then Get_Aspect_Id (Maybe_Aspect_Spec)
- -- include other aspects here ???
- in Aspect_Stable_Properties | Aspect_Aggregate)
+
+ -- Include aspects that can be specified by a
+ -- subprogram name, which can be an operator.
+
+ in Aspect_Stable_Properties
+ | Aspect_Integer_Literal
+ | Aspect_Real_Literal
+ | Aspect_String_Literal
+ | Aspect_Aggregate)
then
Find_Direct_Name (N);
@@ -4504,29 +4505,6 @@ package body Sem_Ch6 is
end if;
end if;
- -- If the subprogram has a class-wide clone, build its body as a copy
- -- of the original body, and rewrite body of original subprogram as a
- -- wrapper that calls the clone. If N is a stub, this construction will
- -- take place when the proper body is analyzed. No action needed if this
- -- subprogram has been eliminated.
-
- if Present (Spec_Id)
- and then Present (Class_Wide_Clone (Spec_Id))
- and then (Comes_From_Source (N) or else Was_Expression_Function (N))
- and then Nkind (N) /= N_Subprogram_Body_Stub
- and then not (Expander_Active and then Is_Eliminated (Spec_Id))
- then
- Build_Class_Wide_Clone_Body (Spec_Id, N);
-
- -- This is the new body for the existing primitive operation
-
- Rewrite (N, Build_Class_Wide_Clone_Call
- (Sloc (N), New_List, Spec_Id, Parent (Spec_Id)));
- Set_Has_Completion (Spec_Id, False);
- Analyze (N);
- return;
- end if;
-
-- Place subprogram on scope stack, and make formals visible. If there
-- is a spec, the visible entity remains that of the spec.
@@ -7760,7 +7738,7 @@ package body Sem_Ch6 is
("RETURN statement missing following this statement<<!",
Last_Stm);
Error_Msg_N
- ("\Program_Error ]<<!", Last_Stm);
+ ("\Program_Error [<<!", Last_Stm);
end if;
-- Note: we set Err even though we have not issued a warning
@@ -9480,13 +9458,12 @@ package body Sem_Ch6 is
end if;
-- Here if type is not frozen yet. It is illegal to have a primitive
- -- equality declared in the private part if the type is visible.
+ -- equality declared in the private part if the type is visible
+ -- (RM 4.5.2(9.8)).
elsif not In_Same_List (Parent (Typ), Decl)
and then not Is_Limited_Type (Typ)
then
- -- Shouldn't we give an RM reference here???
-
if Ada_Version >= Ada_2012 then
Error_Msg_N
("equality operator appears too late<<", Eq_Op);
@@ -9817,7 +9794,8 @@ package body Sem_Ch6 is
-- conform when they do not, e.g. by converting 1+2 into 3.
function FCE (Given_E1 : Node_Id; Given_E2 : Node_Id) return Boolean;
- -- ???
+ -- Convenience function to abbreviate recursive calls to
+ -- Fully_Conformant_Expressions without having to pass Report.
function FCL (L1 : List_Id; L2 : List_Id) return Boolean;
-- Compare elements of two lists for conformance. Elements have to be
@@ -10419,6 +10397,7 @@ package body Sem_Ch6 is
begin
Set_Is_Immediately_Visible (E);
Set_Current_Entity (E);
+ pragma Assert (Prev /= E);
Set_Homonym (E, Prev);
end Install_Entity;
@@ -10778,7 +10757,7 @@ package body Sem_Ch6 is
Error_Msg_Node_2 := F_Typ;
Error_Msg_NE
("private operation& in generic unit does not override "
- & "any primitive operation of& (RM 12.3 (18))??",
+ & "any primitive operation of& (RM 12.3(18))??",
New_E, New_E);
end if;
diff --git a/gcc/ada/sem_ch7.adb b/gcc/ada/sem_ch7.adb
index 095bcda..3852a9a 100644
--- a/gcc/ada/sem_ch7.adb
+++ b/gcc/ada/sem_ch7.adb
@@ -1768,19 +1768,34 @@ package body Sem_Ch7 is
end if;
-- Check preelaborable initialization for full type completing a
- -- private type when aspect Preelaborable_Initialization is True.
- -- We pass True for the parameter Formal_Types_Have_Preelab_Init
- -- to take into account the rule that presumes that subcomponents
- -- of generic formal types mentioned in the type's P_I aspect have
- -- preelaborable initialization (see RM 10.2.1(11.8/5)).
-
- if Is_Type (E)
- and then Must_Have_Preelab_Init (E)
- and then not Has_Preelaborable_Initialization
- (E, Formal_Types_Have_Preelab_Init => True)
- then
- Error_Msg_N
- ("full view of & does not have preelaborable initialization", E);
+ -- private type when aspect Preelaborable_Initialization is True
+ -- or is specified by Preelaborable_Initialization attributes
+ -- (in the case of a private type in a generic unit). We pass
+ -- the expression of the aspect (when present) to the parameter
+ -- Preelab_Init_Expr to take into account the rule that presumes
+ -- that subcomponents of generic formal types mentioned in the
+ -- type's P_I aspect have preelaborable initialization (see
+ -- AI12-0409 and RM 10.2.1(11.8/5)).
+
+ if Is_Type (E) and then Must_Have_Preelab_Init (E) then
+ declare
+ PI_Aspect : constant Node_Id :=
+ Find_Aspect
+ (E, Aspect_Preelaborable_Initialization);
+ PI_Expr : Node_Id := Empty;
+ begin
+ if Present (PI_Aspect) then
+ PI_Expr := Expression (PI_Aspect);
+ end if;
+
+ if not Has_Preelaborable_Initialization
+ (E, Preelab_Init_Expr => PI_Expr)
+ then
+ Error_Msg_N
+ ("full view of & does not have "
+ & "preelaborable initialization", E);
+ end if;
+ end;
end if;
Next_Entity (E);
diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
index a9f0f13..494ec64 100644
--- a/gcc/ada/sem_ch8.adb
+++ b/gcc/ada/sem_ch8.adb
@@ -426,12 +426,10 @@ package body Sem_Ch8 is
-- body at the point of freezing will not work. Subp is the subprogram
-- for which N provides the Renaming_As_Body.
- procedure Check_In_Previous_With_Clause
- (N : Node_Id;
- Nam : Node_Id);
+ procedure Check_In_Previous_With_Clause (N, Nam : Node_Id);
-- N is a use_package clause and Nam the package name, or N is a use_type
-- clause and Nam is the prefix of the type name. In either case, verify
- -- that the package is visible at that point in the context: either it
+ -- that the package is visible at that point in the context: either it
-- appears in a previous with_clause, or because it is a fully qualified
-- name and the root ancestor appears in a previous with_clause.
@@ -2541,8 +2539,8 @@ package body Sem_Ch8 is
and then Is_Class_Wide_Type (Get_Instance_Of (Etype (Formal)))
then
Formal_Typ := Etype (Formal);
- Actual_Typ := Get_Instance_Of (Formal_Typ);
- Root_Typ := Etype (Actual_Typ);
+ Actual_Typ := Base_Type (Get_Instance_Of (Formal_Typ));
+ Root_Typ := Root_Type (Actual_Typ);
exit;
end if;
@@ -2592,6 +2590,15 @@ package body Sem_Ch8 is
elsif CW_Prim_Op = Root_Prim_Op then
Prim_Op := Root_Prim_Op;
+ -- The two subprograms are legal but the class-wide subprogram is
+ -- a class-wide wrapper built for a previous instantiation; the
+ -- wrapper has precedence.
+
+ elsif Present (Alias (CW_Prim_Op))
+ and then Is_Class_Wide_Wrapper (Ultimate_Alias (CW_Prim_Op))
+ then
+ Prim_Op := CW_Prim_Op;
+
-- Otherwise both candidate subprograms are user-defined and
-- ambiguous.
@@ -2690,6 +2697,8 @@ package body Sem_Ch8 is
Set_Corresponding_Body (Spec_Decl, Defining_Entity (Body_Decl));
end if;
+ Set_Is_Class_Wide_Wrapper (Wrap_Id);
+
-- If the operator carries an Eliminated pragma, indicate that the
-- wrapper is also to be eliminated, to prevent spurious error when
-- using gnatelim on programs that include box-initialization of
@@ -4670,10 +4679,7 @@ package body Sem_Ch8 is
-- Check_In_Previous_With_Clause --
-----------------------------------
- procedure Check_In_Previous_With_Clause
- (N : Node_Id;
- Nam : Entity_Id)
- is
+ procedure Check_In_Previous_With_Clause (N, Nam : Node_Id) is
Pack : constant Entity_Id := Entity (Original_Node (Nam));
Item : Node_Id;
Par : Node_Id;
diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb
index 064e2b5..cba3c9d 100644
--- a/gcc/ada/sem_disp.adb
+++ b/gcc/ada/sem_disp.adb
@@ -32,9 +32,11 @@ with Einfo.Entities; use Einfo.Entities;
with Einfo.Utils; use Einfo.Utils;
with Exp_Disp; use Exp_Disp;
with Exp_Util; use Exp_Util;
+with Exp_Ch6; use Exp_Ch6;
with Exp_Ch7; use Exp_Ch7;
with Exp_Tss; use Exp_Tss;
with Errout; use Errout;
+with Freeze; use Freeze;
with Lib.Xref; use Lib.Xref;
with Namet; use Namet;
with Nlists; use Nlists;
@@ -197,6 +199,91 @@ package body Sem_Disp is
return Empty;
end Covered_Interface_Op;
+ ----------------------------------
+ -- Covered_Interface_Primitives --
+ ----------------------------------
+
+ function Covered_Interface_Primitives (Prim : Entity_Id) return Elist_Id is
+ Tagged_Type : constant Entity_Id := Find_Dispatching_Type (Prim);
+ Elmt : Elmt_Id;
+ E : Entity_Id;
+ Result : Elist_Id := No_Elist;
+
+ begin
+ pragma Assert (Is_Dispatching_Operation (Prim));
+
+ -- Although this is a dispatching primitive we must check if its
+ -- dispatching type is available because it may be the primitive
+ -- of a private type not defined as tagged in its partial view.
+
+ if Present (Tagged_Type) and then Has_Interfaces (Tagged_Type) then
+
+ -- If the tagged type is frozen then the internal entities associated
+ -- with interfaces are available in the list of primitives of the
+ -- tagged type and can be used to speed up this search.
+
+ if Is_Frozen (Tagged_Type) then
+ Elmt := First_Elmt (Primitive_Operations (Tagged_Type));
+ while Present (Elmt) loop
+ E := Node (Elmt);
+
+ if Present (Interface_Alias (E))
+ and then Alias (E) = Prim
+ then
+ if No (Result) then
+ Result := New_Elmt_List;
+ end if;
+
+ Append_Elmt (Interface_Alias (E), Result);
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+
+ -- Otherwise we must collect all the interface primitives and check
+ -- whether the Prim overrides (implements) some interface primitive.
+
+ else
+ declare
+ Ifaces_List : Elist_Id;
+ Iface_Elmt : Elmt_Id;
+ Iface : Entity_Id;
+ Iface_Prim : Entity_Id;
+
+ begin
+ Collect_Interfaces (Tagged_Type, Ifaces_List);
+
+ Iface_Elmt := First_Elmt (Ifaces_List);
+ while Present (Iface_Elmt) loop
+ Iface := Node (Iface_Elmt);
+
+ Elmt := First_Elmt (Primitive_Operations (Iface));
+ while Present (Elmt) loop
+ Iface_Prim := Node (Elmt);
+
+ if Chars (Iface_Prim) = Chars (Prim)
+ and then Is_Interface_Conformant
+ (Tagged_Type, Iface_Prim, Prim)
+ then
+ if No (Result) then
+ Result := New_Elmt_List;
+ end if;
+
+ Append_Elmt (Iface_Prim, Result);
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+
+ Next_Elmt (Iface_Elmt);
+ end loop;
+ end;
+ end if;
+ end if;
+
+ return Result;
+ end Covered_Interface_Primitives;
+
-------------------------------
-- Check_Controlling_Formals --
-------------------------------
@@ -592,6 +679,14 @@ package body Sem_Disp is
-- Start of processing for Check_Dispatching_Context
begin
+ -- Skip checking context of dispatching calls during preanalysis of
+ -- class-wide conditions since at that stage the expression is not
+ -- installed yet on its definite context.
+
+ if Inside_Class_Condition_Preanalysis then
+ return;
+ end if;
+
-- If the called subprogram is a private overriding, replace it
-- with its alias, which has the correct body. Verify that the
-- two subprograms have the same controlling type (this is not the
@@ -992,10 +1087,17 @@ package body Sem_Disp is
-- nonstatic values, then report an error. This is specified by
-- RM 6.1.1(18.2/5) (by AI12-0412).
+ -- Skip reporting this error on helpers and indirect-call wrappers
+ -- built to support class-wide preconditions.
+
if No (Control)
and then not Is_Abstract_Subprogram (Subp_Entity)
and then
Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post (Subp_Entity)
+ and then not
+ (Is_Subprogram (Current_Scope)
+ and then
+ Present (Class_Preconditions_Subprogram (Current_Scope)))
then
Error_Msg_N
("nondispatching call to nonabstract subprogram of "
@@ -1018,6 +1120,9 @@ package body Sem_Disp is
---------------------------------
procedure Check_Dispatching_Operation (Subp, Old_Subp : Entity_Id) is
+ function Is_Access_To_Subprogram_Wrapper (E : Entity_Id) return Boolean;
+ -- Return True if E is an access to subprogram wrapper
+
procedure Warn_On_Late_Primitive_After_Private_Extension
(Typ : Entity_Id;
Prim : Entity_Id);
@@ -1025,6 +1130,22 @@ package body Sem_Disp is
-- if it is a public primitive defined after some private extension of
-- the tagged type.
+ -------------------------------------
+ -- Is_Access_To_Subprogram_Wrapper --
+ -------------------------------------
+
+ function Is_Access_To_Subprogram_Wrapper (E : Entity_Id) return Boolean
+ is
+ Decl_N : constant Node_Id := Unit_Declaration_Node (E);
+ Par_N : constant Node_Id := Parent (List_Containing (Decl_N));
+
+ begin
+ -- Access to subprogram wrappers are declared in the freezing actions
+
+ return Nkind (Par_N) = N_Freeze_Entity
+ and then Ekind (Entity (Par_N)) = E_Access_Subprogram_Type;
+ end Is_Access_To_Subprogram_Wrapper;
+
----------------------------------------------------
-- Warn_On_Late_Primitive_After_Private_Extension --
----------------------------------------------------
@@ -1095,6 +1216,13 @@ package body Sem_Disp is
or else Is_Partial_Invariant_Procedure (Subp)
then
return;
+
+ -- Wrappers of access to subprograms are not primitive subprograms.
+
+ elsif Is_Wrapper (Subp)
+ and then Is_Access_To_Subprogram_Wrapper (Subp)
+ then
+ return;
end if;
Set_Is_Dispatching_Operation (Subp, False);
@@ -1407,7 +1535,39 @@ package body Sem_Disp is
Generate_Reference (Tagged_Type, Subp, 'P', False);
Override_Dispatching_Operation
(Tagged_Type, Old_Subp, Subp);
+ Set_Is_Dispatching_Operation (Subp);
+
+ -- Inherit decoration of controlling formals and
+ -- controlling result.
+
+ if Ekind (Old_Subp) = E_Function
+ and then Has_Controlling_Result (Old_Subp)
+ then
+ Set_Has_Controlling_Result (Subp);
+ end if;
+
+ if Present (First_Formal (Old_Subp)) then
+ declare
+ Old_Formal : Entity_Id;
+ Formal : Entity_Id;
+
+ begin
+ Formal := First_Formal (Subp);
+ Old_Formal := First_Formal (Old_Subp);
+
+ while Present (Old_Formal) loop
+ Set_Is_Controlling_Formal (Formal,
+ Is_Controlling_Formal (Old_Formal));
+
+ Next_Formal (Formal);
+ Next_Formal (Old_Formal);
+ end loop;
+ end;
+ end if;
end if;
+
+ Check_Inherited_Conditions (Tagged_Type,
+ Late_Overriding => True);
end if;
end if;
end;
@@ -2420,12 +2580,27 @@ package body Sem_Disp is
if No (Tag_Typ) then
return Result (1 .. 0);
+
+ -- Prevent cascaded errors
+
+ elsif Is_Concurrent_Type (Tag_Typ)
+ and then No (Corresponding_Record_Type (Tag_Typ))
+ and then Serious_Errors_Detected > 0
+ then
+ return Result (1 .. 0);
end if;
if Is_Concurrent_Type (Tag_Typ) then
Tag_Typ := Corresponding_Record_Type (Tag_Typ);
end if;
+ if Present (Tag_Typ)
+ and then Is_Private_Type (Tag_Typ)
+ and then Present (Full_View (Tag_Typ))
+ then
+ Tag_Typ := Full_View (Tag_Typ);
+ end if;
+
-- Search primitive operations of dispatching type
if Present (Tag_Typ)
@@ -2855,6 +3030,11 @@ package body Sem_Disp is
Next_Actual (Arg);
end loop;
+ -- Add class-wide precondition check if the target of this dispatching
+ -- call has or inherits class-wide preconditions.
+
+ Install_Class_Preconditions_Check (Call_Node);
+
-- Expansion of dispatching calls is suppressed on VM targets, because
-- the VM back-ends directly handle the generation of dispatching calls
-- and would have to undo any expansion to an indirect call.
diff --git a/gcc/ada/sem_disp.ads b/gcc/ada/sem_disp.ads
index 7b42cf5..f37391b 100644
--- a/gcc/ada/sem_disp.ads
+++ b/gcc/ada/sem_disp.ads
@@ -74,6 +74,10 @@ package Sem_Disp is
-- The Alias of Old_Subp is adjusted to point to the inherited procedure
-- of the full view because it is always this one which has to be called.
+ function Covered_Interface_Primitives (Prim : Entity_Id) return Elist_Id;
+ -- Returns all the interface primitives covered by Prim, when its
+ -- controlling type has progenitors.
+
function Covered_Interface_Op (Prim : Entity_Id) return Entity_Id;
-- Returns the interface primitive that Prim covers, when its controlling
-- type has progenitors.
diff --git a/gcc/ada/sem_elab.adb b/gcc/ada/sem_elab.adb
index f6edcac..122a837 100644
--- a/gcc/ada/sem_elab.adb
+++ b/gcc/ada/sem_elab.adb
@@ -2070,7 +2070,7 @@ package body Sem_Elab is
-- Change the status of the elaboration phase of the compiler to Status
procedure Spec_And_Body_From_Entity
- (Id : Node_Id;
+ (Id : Entity_Id;
Spec_Decl : out Node_Id;
Body_Decl : out Node_Id);
pragma Inline (Spec_And_Body_From_Entity);
@@ -13621,6 +13621,13 @@ package body Sem_Elab is
then
return True;
+ -- A call to an expression function that is not a completion cannot
+ -- cause an ABE because it has no prior declaration; this remains
+ -- true even if the FE transforms the callee into something else.
+
+ elsif Nkind (Original_Node (Spec_Decl)) = N_Expression_Function then
+ return True;
+
-- Subprogram bodies which wrap attribute references used as actuals
-- in instantiations are always ABE-safe. These bodies are artifacts
-- of expansion.
@@ -15835,7 +15842,7 @@ package body Sem_Elab is
-------------------------------
procedure Spec_And_Body_From_Entity
- (Id : Node_Id;
+ (Id : Entity_Id;
Spec_Decl : out Node_Id;
Body_Decl : out Node_Id)
is
diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb
index 6f81406..20bc03a 100644
--- a/gcc/ada/sem_eval.adb
+++ b/gcc/ada/sem_eval.adb
@@ -118,7 +118,8 @@ package body Sem_Eval is
subtype CV_Range is Nat range 0 .. CV_Cache_Size;
type CV_Entry is record
- N : Node_Id;
+ N : Node_Id'Base;
+ -- We use 'Base here, in case we want to add a predicate to Node_Id
V : Uint;
end record;
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 9cad55d..0163ff9 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -9532,7 +9532,11 @@ package body Sem_Prag is
Process_Import_Predefined_Type;
- else
+ -- Emit an error unless Relaxed_RM_Semantics since some legacy Ada
+ -- compilers may accept more cases, e.g. JGNAT allowed importing
+ -- a Java package.
+
+ elsif not Relaxed_RM_Semantics then
if From_Aspect_Specification (N) then
Error_Pragma_Arg
("entity for aspect% must be object, subprogram "
@@ -14202,6 +14206,16 @@ package body Sem_Prag is
when Pragma_Compile_Time_Error | Pragma_Compile_Time_Warning =>
GNAT_Pragma;
+
+ -- These pragmas rely on the context. In adc files they raise
+ -- Constraint_Error. Ban them from use as configuration pragmas
+ -- even in cases where such a use could work.
+
+ if Is_Configuration_Pragma then
+ Error_Pragma
+ ("pragma% is not allowed as a configuration pragma");
+ end if;
+
Process_Compile_Time_Warning_Or_Error;
---------------------------
@@ -14835,9 +14849,41 @@ package body Sem_Prag is
& "effect?j?", N);
end if;
- --------------------
+ -----------------
+ -- CUDA_Device --
+ -----------------
+
+ when Pragma_CUDA_Device => CUDA_Device : declare
+ Arg_Node : Node_Id;
+ Device_Entity : Entity_Id;
+ begin
+ GNAT_Pragma;
+ Check_Arg_Count (1);
+ Check_Arg_Is_Library_Level_Local_Name (Arg1);
+
+ Arg_Node := Get_Pragma_Arg (Arg1);
+ Device_Entity := Entity (Arg_Node);
+
+ if Ekind (Device_Entity) in E_Variable
+ | E_Constant
+ | E_Procedure
+ | E_Function
+ then
+ Add_CUDA_Device_Entity
+ (Package_Specification_Of_Scope (Scope (Device_Entity)),
+ Device_Entity);
+
+ else
+ Error_Msg_NE ("& must be constant, variable or subprogram",
+ N,
+ Device_Entity);
+ end if;
+
+ end CUDA_Device;
+
+ ------------------
-- CUDA_Execute --
- --------------------
+ ------------------
-- pragma CUDA_Execute (PROCEDURE_CALL_STATEMENT,
-- EXPRESSION,
@@ -25892,23 +25938,6 @@ package body Sem_Prag is
("operation in class-wide condition must be primitive "
& "of &", Nod, Disp_Typ);
end if;
-
- -- Otherwise we have a call to an overridden primitive, and we
- -- will create a common class-wide clone for the body of
- -- original operation and its eventual inherited versions. If
- -- the original operation dispatches on result it is never
- -- inherited and there is no need for a clone. There is not
- -- need for a clone either in GNATprove mode, as cases that
- -- would require it are rejected (when an inherited primitive
- -- calls an overridden operation in a class-wide contract), and
- -- the clone would make proof impossible in some cases.
-
- elsif not Is_Abstract_Subprogram (Spec_Id)
- and then No (Class_Wide_Clone (Spec_Id))
- and then not Has_Controlling_Result (Spec_Id)
- and then not GNATprove_Mode
- then
- Build_Class_Wide_Clone_Decl (Spec_Id);
end if;
end;
@@ -26029,15 +26058,6 @@ package body Sem_Prag is
End_Scope;
end if;
- -- If analysis of the condition indicates that a class-wide clone
- -- has been created, build and analyze its declaration.
-
- if Is_Subprogram (Spec_Id)
- and then Present (Class_Wide_Clone (Spec_Id))
- then
- Analyze (Unit_Declaration_Node (Class_Wide_Clone (Spec_Id)));
- end if;
-
-- Currently it is not possible to inline pre/postconditions on a
-- subprogram subject to pragma Inline_Always.
@@ -29524,9 +29544,6 @@ package body Sem_Prag is
Msg_Arg : Node_Id;
Nam : Name_Id;
- Needs_Wrapper : Boolean;
- pragma Unreferenced (Needs_Wrapper);
-
-- Start of processing for Build_Pragma_Check_Equivalent
begin
@@ -29553,11 +29570,10 @@ package body Sem_Prag is
-- Build the inherited class-wide condition
Build_Class_Wide_Expression
- (Prag => Check_Prag,
- Subp => Subp_Id,
- Par_Subp => Inher_Id,
- Adjust_Sloc => True,
- Needs_Wrapper => Needs_Wrapper);
+ (Pragma_Or_Expr => Check_Prag,
+ Subp => Subp_Id,
+ Par_Subp => Inher_Id,
+ Adjust_Sloc => True);
-- If not an inherited condition simply copy the original pragma
@@ -31274,6 +31290,7 @@ package body Sem_Prag is
Pragma_C_Pass_By_Copy => 0,
Pragma_Comment => -1,
Pragma_Common_Object => 0,
+ Pragma_CUDA_Device => -1,
Pragma_CUDA_Execute => -1,
Pragma_CUDA_Global => -1,
Pragma_Compile_Time_Error => -1,
diff --git a/gcc/ada/sem_prag.ads b/gcc/ada/sem_prag.ads
index e166481..fed24fd 100644
--- a/gcc/ada/sem_prag.ads
+++ b/gcc/ada/sem_prag.ads
@@ -49,6 +49,7 @@ package Sem_Prag is
Pragma_Contract_Cases => True,
Pragma_Convention => True,
Pragma_CPU => True,
+ Pragma_CUDA_Device => True,
Pragma_CUDA_Global => True,
Pragma_Default_Initial_Condition => True,
Pragma_Default_Storage_Pool => True,
@@ -429,7 +430,7 @@ package Sem_Prag is
function Get_Argument
(Prag : Node_Id;
- Context_Id : Node_Id := Empty) return Node_Id;
+ Context_Id : Entity_Id := Empty) return Node_Id;
-- Obtain the argument of pragma Prag depending on context and the nature
-- of the pragma. The argument is extracted in the following manner:
--
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index 12b3295..0bdc463 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -2920,6 +2920,16 @@ package body Sem_Res is
Expr : Node_Id;
begin
+ if Is_Derived_Type (Typ)
+ and then Is_Tagged_Type (Typ)
+ and then Base_Type (Etype (Callee)) /= Base_Type (Typ)
+ then
+ Callee :=
+ Corresponding_Primitive_Op
+ (Ancestor_Op => Callee,
+ Descendant_Type => Base_Type (Typ));
+ end if;
+
if Nkind (N) = N_Identifier then
Expr := Expression (Declaration_Node (Entity (N)));
@@ -2990,16 +3000,23 @@ package body Sem_Res is
Set_Etype (Call, Etype (Callee));
- -- Conversion needed in case of an inherited aspect
- -- of a derived type.
- --
- -- ??? Need to do something different here for downward
- -- tagged conversion case (which is only possible in the
- -- case of a null extension); the current call to
- -- Convert_To results in an error message about an illegal
- -- downward conversion.
+ if Base_Type (Etype (Call)) /= Base_Type (Typ) then
+ -- Conversion may be needed in case of an inherited
+ -- aspect of a derived type. For a null extension, we
+ -- use a null extension aggregate instead because the
+ -- downward type conversion would be illegal.
- Call := Convert_To (Typ, Call);
+ if Is_Null_Extension_Of
+ (Descendant => Typ,
+ Ancestor => Etype (Call))
+ then
+ Call := Make_Extension_Aggregate (Loc,
+ Ancestor_Part => Call,
+ Null_Record_Present => True);
+ else
+ Call := Convert_To (Typ, Call);
+ end if;
+ end if;
Rewrite (N, Call);
end;
@@ -3081,6 +3098,24 @@ package body Sem_Res is
Error_Msg_N ("\use -gnatf for details", N);
end if;
+ -- Recognize the case of a quantified expression being mistaken
+ -- for an iterated component association because the user
+ -- forgot the "all" or "some" keyword after "for". Because the
+ -- error message starts with "missing ALL", we automatically
+ -- benefit from the associated CODEFIX, which requires that
+ -- the message is located on the identifier following "for"
+ -- in order for the CODEFIX to insert "all" in the right place.
+
+ elsif Nkind (N) = N_Aggregate
+ and then List_Length (Component_Associations (N)) = 1
+ and then Nkind (First (Component_Associations (N)))
+ = N_Iterated_Component_Association
+ and then Is_Boolean_Type (Typ)
+ then
+ Error_Msg_N -- CODEFIX
+ ("missing ALL or SOME in quantified expression",
+ Defining_Identifier (First (Component_Associations (N))));
+
else
Wrong_Type (N, Typ);
end if;
@@ -4874,10 +4909,15 @@ package body Sem_Res is
-- Apply legality rule 3.9.2 (9/1)
+ -- Skip this check on helpers and indirect-call wrappers built to
+ -- support class-wide preconditions.
+
if (Is_Class_Wide_Type (A_Typ) or else Is_Dynamically_Tagged (A))
and then not Is_Class_Wide_Type (F_Typ)
and then not Is_Controlling_Formal (F)
and then not In_Instance
+ and then (not Is_Subprogram (Nam)
+ or else No (Class_Preconditions_Subprogram (Nam)))
then
Error_Msg_N ("class-wide argument not allowed here!", A);
@@ -4975,9 +5015,13 @@ package body Sem_Res is
-- "False" cannot act as an actual in a subprogram with value
-- "True" (SPARK RM 6.1.7(3)).
+ -- No check needed for helpers and indirect-call wrappers built to
+ -- support class-wide preconditions.
+
if Is_EVF_Expression (A)
and then Extensions_Visible_Status (Nam) =
Extensions_Visible_True
+ and then No (Class_Preconditions_Subprogram (Current_Scope))
then
Error_Msg_N
("formal parameter cannot act as actual parameter when "
@@ -7461,66 +7505,76 @@ package body Sem_Res is
(N : Node_Id;
Typ : Entity_Id)
is
- Decl : Node_Id;
- Need_Transient_Scope : Boolean := False;
- begin
- -- Install the scope created for local declarations, if
- -- any. The syntax allows a Declare_Expression with no
- -- declarations, in analogy with block statements.
- -- Note that that scope has no explicit declaration, but
- -- appears as the scope of all entities declared therein.
+ Expr : constant Node_Id := Expression (N);
- Decl := First (Actions (N));
- while Present (Decl) loop
- exit when Nkind (Decl)
- in N_Object_Declaration | N_Object_Renaming_Declaration;
- Next (Decl);
- end loop;
+ Decl : Node_Id;
+ Local : Entity_Id := Empty;
- if Present (Decl) then
+ function Replace_Local (N : Node_Id) return Traverse_Result;
+ -- Use a tree traversal to replace each ocurrence of the name of
+ -- a local object declared in the construct, with the corresponding
+ -- entity. This replaces the usual way to perform name capture by
+ -- visibility, because it is not possible to place on the scope
+ -- stack the fake scope created for the analysis of the local
+ -- declarations; such a scope conflicts with the transient scopes
+ -- that may be generated if the expression includes function calls
+ -- requiring finalization.
- -- Need to establish a transient scope in case Expression (N)
- -- requires actions to be wrapped.
+ -------------------
+ -- Replace_Local --
+ -------------------
- declare
- Node : Node_Id;
- begin
- Node := First (Actions (N));
- while Present (Node) loop
- if Nkind (Node) = N_Object_Declaration
- and then Requires_Transient_Scope
- (Etype (Defining_Identifier (Node)))
- then
- Need_Transient_Scope := True;
- exit;
- end if;
+ function Replace_Local (N : Node_Id) return Traverse_Result is
+ begin
+ -- The identifier may be the prefix of a selected component,
+ -- but not a selector name, because the local entities do not
+ -- have a scope that can be named: a selected component whose
+ -- selector is a homonym of a local entity must denote some
+ -- global entity.
+
+ if Nkind (N) = N_Identifier
+ and then Chars (N) = Chars (Local)
+ and then No (Entity (N))
+ and then
+ (Nkind (Parent (N)) /= N_Selected_Component
+ or else N = Prefix (Parent (N)))
+ then
+ Set_Entity (N, Local);
+ Set_Etype (N, Etype (Local));
+ end if;
- Next (Node);
- end loop;
- end;
+ return OK;
+ end Replace_Local;
- if Need_Transient_Scope then
- Establish_Transient_Scope (Decl, Manage_Sec_Stack => True);
- else
- Push_Scope (Scope (Defining_Identifier (Decl)));
+ procedure Replace_Local_Ref is new Traverse_Proc (Replace_Local);
+
+ -- Start of processing for Resolve_Declare_Expression
+
+ begin
+
+ Decl := First (Actions (N));
+
+ while Present (Decl) loop
+ if Nkind (Decl) in
+ N_Object_Declaration | N_Object_Renaming_Declaration
+ and then Comes_From_Source (Defining_Identifier (Decl))
+ then
+ Local := Defining_Identifier (Decl);
+ Replace_Local_Ref (Expr);
end if;
- declare
- E : Entity_Id := First_Entity (Current_Scope);
- begin
- while Present (E) loop
- Set_Current_Entity (E);
- Set_Is_Immediately_Visible (E);
- Next_Entity (E);
- end loop;
- end;
+ Next (Decl);
+ end loop;
- Resolve (Expression (N), Typ);
- End_Scope;
+ -- The end of the declarative list is a freeze point for the
+ -- local declarations.
- else
- Resolve (Expression (N), Typ);
+ if Present (Local) then
+ Decl := Parent (Local);
+ Freeze_All (First_Entity (Scope (Local)), Decl);
end if;
+
+ Resolve (Expr, Typ);
end Resolve_Declare_Expression;
-----------------------------------------
@@ -9217,7 +9271,7 @@ package body Sem_Res is
-------------------------------
procedure Resolve_Indexed_Component (N : Node_Id; Typ : Entity_Id) is
- Name : constant Node_Id := Prefix (N);
+ Pref : constant Node_Id := Prefix (N);
Expr : Node_Id;
Array_Type : Entity_Id := Empty; -- to prevent junk warning
Index : Node_Id;
@@ -9228,7 +9282,7 @@ package body Sem_Res is
return;
end if;
- if Is_Overloaded (Name) then
+ if Is_Overloaded (Pref) then
-- Use the context type to select the prefix that yields the correct
-- component type.
@@ -9237,11 +9291,10 @@ package body Sem_Res is
I : Interp_Index;
It : Interp;
I1 : Interp_Index := 0;
- P : constant Node_Id := Prefix (N);
Found : Boolean := False;
begin
- Get_First_Interp (P, I, It);
+ Get_First_Interp (Pref, I, It);
while Present (It.Typ) loop
if (Is_Array_Type (It.Typ)
and then Covers (Typ, Component_Type (It.Typ)))
@@ -9253,7 +9306,7 @@ package body Sem_Res is
Component_Type (Designated_Type (It.Typ))))
then
if Found then
- It := Disambiguate (P, I1, I, Any_Type);
+ It := Disambiguate (Pref, I1, I, Any_Type);
if It = No_Interp then
Error_Msg_N ("ambiguous prefix for indexing", N);
@@ -9278,11 +9331,11 @@ package body Sem_Res is
end;
else
- Array_Type := Etype (Name);
+ Array_Type := Etype (Pref);
end if;
- Resolve (Name, Array_Type);
- Array_Type := Get_Actual_Subtype_If_Available (Name);
+ Resolve (Pref, Array_Type);
+ Array_Type := Get_Actual_Subtype_If_Available (Pref);
-- If the prefix's type is an access type, get to the real array type.
-- Note: we do not apply an access check because an explicit dereference
@@ -9325,19 +9378,18 @@ package body Sem_Res is
end loop;
end if;
- Resolve_Implicit_Dereference (Prefix (N));
+ Resolve_Implicit_Dereference (Pref);
Analyze_Dimension (N);
-- Do not generate the warning on suspicious index if we are analyzing
-- package Ada.Tags; otherwise we will report the warning with the
-- Prims_Ptr field of the dispatch table.
- if Scope (Etype (Prefix (N))) = Standard_Standard
+ if Scope (Etype (Pref)) = Standard_Standard
or else not
- Is_RTU (Cunit_Entity (Get_Source_Unit (Etype (Prefix (N)))),
- Ada_Tags)
+ Is_RTU (Cunit_Entity (Get_Source_Unit (Etype (Pref))), Ada_Tags)
then
- Warn_On_Suspicious_Index (Name, First (Expressions (N)));
+ Warn_On_Suspicious_Index (Pref, First (Expressions (N)));
Eval_Indexed_Component (N);
end if;
@@ -9349,16 +9401,16 @@ package body Sem_Res is
if Nkind (N) = N_Indexed_Component
and then Is_Atomic_Ref_With_Address (N)
and then not (Has_Atomic_Components (Array_Type)
- or else (Is_Entity_Name (Prefix (N))
+ or else (Is_Entity_Name (Pref)
and then Has_Atomic_Components
- (Entity (Prefix (N)))))
+ (Entity (Pref))))
and then not Is_Atomic (Component_Type (Array_Type))
and then Ada_Version < Ada_2022
then
Error_Msg_N
- ("??access to non-atomic component of atomic array", Prefix (N));
+ ("??access to non-atomic component of atomic array", Pref);
Error_Msg_N
- ("??\may cause unexpected accesses to atomic object", Prefix (N));
+ ("??\may cause unexpected accesses to atomic object", Pref);
end if;
end Resolve_Indexed_Component;
@@ -11166,13 +11218,13 @@ package body Sem_Res is
procedure Resolve_Slice (N : Node_Id; Typ : Entity_Id) is
Drange : constant Node_Id := Discrete_Range (N);
- Name : constant Node_Id := Prefix (N);
+ Pref : constant Node_Id := Prefix (N);
Array_Type : Entity_Id := Empty;
Dexpr : Node_Id := Empty;
Index_Type : Entity_Id;
begin
- if Is_Overloaded (Name) then
+ if Is_Overloaded (Pref) then
-- Use the context type to select the prefix that yields the correct
-- array type.
@@ -11181,11 +11233,10 @@ package body Sem_Res is
I : Interp_Index;
I1 : Interp_Index := 0;
It : Interp;
- P : constant Node_Id := Prefix (N);
Found : Boolean := False;
begin
- Get_First_Interp (P, I, It);
+ Get_First_Interp (Pref, I, It);
while Present (It.Typ) loop
if (Is_Array_Type (It.Typ)
and then Covers (Typ, It.Typ))
@@ -11194,7 +11245,7 @@ package body Sem_Res is
and then Covers (Typ, Designated_Type (It.Typ)))
then
if Found then
- It := Disambiguate (P, I1, I, Any_Type);
+ It := Disambiguate (Pref, I1, I, Any_Type);
if It = No_Interp then
Error_Msg_N ("ambiguous prefix for slicing", N);
@@ -11217,10 +11268,10 @@ package body Sem_Res is
end;
else
- Array_Type := Etype (Name);
+ Array_Type := Etype (Pref);
end if;
- Resolve (Name, Array_Type);
+ Resolve (Pref, Array_Type);
-- If the prefix's type is an access type, get to the real array type.
-- Note: we do not apply an access check because an explicit dereference
@@ -11236,12 +11287,12 @@ package body Sem_Res is
-- subtype.
if not Is_Constrained (Array_Type) then
- Remove_Side_Effects (Prefix (N));
+ Remove_Side_Effects (Pref);
declare
Obj : constant Node_Id :=
Make_Explicit_Dereference (Sloc (N),
- Prefix => New_Copy_Tree (Prefix (N)));
+ Prefix => New_Copy_Tree (Pref));
begin
Set_Etype (Obj, Array_Type);
Set_Parent (Obj, Parent (N));
@@ -11249,25 +11300,35 @@ package body Sem_Res is
end;
end if;
- elsif Is_Entity_Name (Name)
- or else Nkind (Name) = N_Explicit_Dereference
- or else (Nkind (Name) = N_Function_Call
- and then not Is_Constrained (Etype (Name)))
+ -- In CodePeer mode the attribute Image is not expanded, so when it
+ -- acts as a prefix of a slice, we handle it like a call to function
+ -- returning an unconstrained string. Same for the Wide variants of
+ -- attribute Image.
+
+ elsif Is_Entity_Name (Pref)
+ or else Nkind (Pref) = N_Explicit_Dereference
+ or else (Nkind (Pref) = N_Function_Call
+ and then not Is_Constrained (Etype (Pref)))
+ or else (CodePeer_Mode
+ and then Nkind (Pref) = N_Attribute_Reference
+ and then Attribute_Name (Pref) in Name_Image
+ | Name_Wide_Image
+ | Name_Wide_Wide_Image)
then
- Array_Type := Get_Actual_Subtype (Name);
+ Array_Type := Get_Actual_Subtype (Pref);
-- If the name is a selected component that depends on discriminants,
-- build an actual subtype for it. This can happen only when the name
-- itself is overloaded; otherwise the actual subtype is created when
-- the selected component is analyzed.
- elsif Nkind (Name) = N_Selected_Component
+ elsif Nkind (Pref) = N_Selected_Component
and then Full_Analysis
and then Depends_On_Discriminant (First_Index (Array_Type))
then
declare
Act_Decl : constant Node_Id :=
- Build_Actual_Subtype_Of_Component (Array_Type, Name);
+ Build_Actual_Subtype_Of_Component (Array_Type, Pref);
begin
Insert_Action (N, Act_Decl);
Array_Type := Defining_Identifier (Act_Decl);
@@ -11280,8 +11341,8 @@ package body Sem_Res is
-- check applied below (the range check won't get done if the
-- unconstrained subtype of the 'Image is used).
- elsif Nkind (Name) = N_Slice then
- Array_Type := Etype (Name);
+ elsif Nkind (Pref) = N_Slice then
+ Array_Type := Etype (Pref);
end if;
-- Obtain the type of the array index
@@ -11304,27 +11365,32 @@ package body Sem_Res is
if Tagged_Type_Expansion
and then RTU_Loaded (Ada_Tags)
- and then Nkind (Prefix (N)) = N_Selected_Component
- and then Present (Entity (Selector_Name (Prefix (N))))
- and then Entity (Selector_Name (Prefix (N))) =
+ and then Nkind (Pref) = N_Selected_Component
+ and then Present (Entity (Selector_Name (Pref)))
+ and then Entity (Selector_Name (Pref)) =
RTE_Record_Component (RE_Prims_Ptr)
then
null;
- -- The discrete_range is specified by a subtype indication. Create a
- -- shallow copy and inherit the type, parent and source location from
- -- the discrete_range. This ensures that the range check is inserted
- -- relative to the slice and that the runtime exception points to the
- -- proper construct.
+ -- The discrete_range is specified by a subtype name. Create an
+ -- equivalent range attribute, apply checks to this attribute, but
+ -- insert them into the range expression of the slice itself.
elsif Is_Entity_Name (Drange) then
- Dexpr := New_Copy (Scalar_Range (Entity (Drange)));
+ Dexpr :=
+ Make_Attribute_Reference
+ (Sloc (Drange),
+ Prefix =>
+ New_Occurrence_Of (Entity (Drange), Sloc (Drange)),
+ Attribute_Name => Name_Range);
+
+ Analyze_And_Resolve (Dexpr, Etype (Drange));
- Set_Etype (Dexpr, Etype (Drange));
- Set_Parent (Dexpr, Parent (Drange));
- Set_Sloc (Dexpr, Sloc (Drange));
+ elsif Nkind (Drange) = N_Subtype_Indication then
+ Dexpr := Range_Expression (Constraint (Drange));
- -- The discrete_range is a regular range. Resolve the bounds and remove
+ -- The discrete_range is a regular range (or a range attribute, which
+ -- will be resolved into a regular range). Resolve the bounds and remove
-- their side effects.
else
@@ -11339,7 +11405,7 @@ package body Sem_Res is
end if;
if Present (Dexpr) then
- Apply_Range_Check (Dexpr, Index_Type);
+ Apply_Range_Check (Dexpr, Index_Type, Insert_Node => Drange);
end if;
Set_Slice_Subtype (N);
@@ -11367,11 +11433,11 @@ package body Sem_Res is
-- Otherwise here is where we check suspicious indexes
if Nkind (Drange) = N_Range then
- Warn_On_Suspicious_Index (Name, Low_Bound (Drange));
- Warn_On_Suspicious_Index (Name, High_Bound (Drange));
+ Warn_On_Suspicious_Index (Pref, Low_Bound (Drange));
+ Warn_On_Suspicious_Index (Pref, High_Bound (Drange));
end if;
- Resolve_Implicit_Dereference (Prefix (N));
+ Resolve_Implicit_Dereference (Pref);
Analyze_Dimension (N);
Eval_Slice (N);
end Resolve_Slice;
diff --git a/gcc/ada/sem_type.adb b/gcc/ada/sem_type.adb
index 396f616..8e5b067 100644
--- a/gcc/ada/sem_type.adb
+++ b/gcc/ada/sem_type.adb
@@ -444,6 +444,12 @@ package body Sem_Type is
Find_Dispatching_Type (E))
then
Add_One_Interp (N, Interface_Alias (E), T);
+
+ -- Otherwise this is the first interpretation, N has type Any_Type
+ -- and we must place the new type on the node.
+
+ else
+ Set_Etype (N, T);
end if;
return;
@@ -1403,7 +1409,9 @@ package body Sem_Type is
and then Nkind (Unit_Declaration_Node (S)) =
N_Subprogram_Renaming_Declaration
- -- Why the Comes_From_Source test here???
+ -- Determine if the renaming came from source or was generated as a
+ -- a result of generic expansion since the actual is represented by
+ -- a constructed subprogram renaming.
and then not Comes_From_Source (Unit_Declaration_Node (S))
@@ -1460,7 +1468,8 @@ package body Sem_Type is
then
return True;
- -- ??? There are possibly other cases to consider
+ -- Formal_Typ is a private view, or Opnd_Typ and Formal_Typ are
+ -- compatible only on a base-type basis.
else
return False;
@@ -3415,7 +3424,8 @@ package body Sem_Type is
-- Ada 2005 (AI-251): T1 is a concrete type that implements the
-- class-wide interface T2
- elsif Is_Class_Wide_Type (T2)
+ elsif Is_Tagged_Type (T1)
+ and then Is_Class_Wide_Type (T2)
and then Is_Interface (Etype (T2))
and then Interface_Present_In_Ancestor (Typ => T1,
Iface => Etype (T2))
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 45a338a..b5f3d4c 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -391,8 +391,7 @@ package body Sem_Util is
and then (Is_Static_Coextension (N)
or else Is_Dynamic_Coextension (N))
then
- return Make_Level_Literal
- (Scope_Depth (Standard_Standard));
+ return Make_Level_Literal (Scope_Depth (Standard_Standard));
end if;
-- Named access types have a designated level
@@ -416,11 +415,14 @@ package body Sem_Util is
if Debug_Flag_Underscore_B then
return Make_Level_Literal (Typ_Access_Level (Etype (N)));
- -- Otherwise the level is that of the subprogram
+ -- For function calls the level is that of the innermost
+ -- master, otherwise (for allocators etc.) we get the level
+ -- of the corresponding anonymous access type, which is
+ -- calculated through the normal path of execution.
- else
+ elsif Nkind (N) = N_Function_Call then
return Make_Level_Literal
- (Subprogram_Access_Level (Entity (Name (N))));
+ (Innermost_Master_Scope_Depth (Expr));
end if;
end if;
@@ -713,15 +715,25 @@ package body Sem_Util is
return Make_Level_Literal (Typ_Access_Level (E) + 1);
- -- Move up the renamed entity if it came from source since
- -- expansion may have created a dummy renaming under certain
- -- circumstances.
+ -- Move up the renamed entity or object if it came from source
+ -- since expansion may have created a dummy renaming under
+ -- certain circumstances.
+
+ -- Note: We check if the original node of the renaming comes
+ -- from source because the node may have been rewritten.
elsif Present (Renamed_Object (E))
- and then Comes_From_Source (Renamed_Object (E))
+ and then Comes_From_Source (Original_Node (Renamed_Object (E)))
then
return Accessibility_Level (Renamed_Object (E));
+ -- Move up renamed entities
+
+ elsif Present (Renamed_Entity (E))
+ and then Comes_From_Source (Original_Node (Renamed_Entity (E)))
+ then
+ return Accessibility_Level (Renamed_Entity (E));
+
-- Named access types get their level from their associated type
elsif Is_Named_Access_Type (Etype (E)) then
@@ -2212,180 +2224,6 @@ package body Sem_Util is
return Empty;
end Build_Actual_Subtype_Of_Component;
- ---------------------------------
- -- Build_Class_Wide_Clone_Body --
- ---------------------------------
-
- procedure Build_Class_Wide_Clone_Body
- (Spec_Id : Entity_Id;
- Bod : Node_Id)
- is
- Loc : constant Source_Ptr := Sloc (Bod);
- Clone_Id : constant Entity_Id := Class_Wide_Clone (Spec_Id);
- Clone_Body : Node_Id;
- Assoc_List : constant Elist_Id := New_Elmt_List;
-
- begin
- -- The declaration of the class-wide clone was created when the
- -- corresponding class-wide condition was analyzed.
-
- -- The body of the original condition may contain references to
- -- the formals of Spec_Id. In the body of the class-wide clone,
- -- these must be replaced with the corresponding formals of
- -- the clone.
-
- declare
- Spec_Formal_Id : Entity_Id := First_Formal (Spec_Id);
- Clone_Formal_Id : Entity_Id := First_Formal (Clone_Id);
- begin
- while Present (Spec_Formal_Id) loop
- Append_Elmt (Spec_Formal_Id, Assoc_List);
- Append_Elmt (Clone_Formal_Id, Assoc_List);
-
- Next_Formal (Spec_Formal_Id);
- Next_Formal (Clone_Formal_Id);
- end loop;
- end;
-
- Clone_Body :=
- Make_Subprogram_Body (Loc,
- Specification =>
- Copy_Subprogram_Spec (Parent (Clone_Id)),
- Declarations => Declarations (Bod),
- Handled_Statement_Sequence =>
- New_Copy_Tree (Handled_Statement_Sequence (Bod),
- Map => Assoc_List));
-
- -- The new operation is internal and overriding indicators do not apply
- -- (the original primitive may have carried one).
-
- Set_Must_Override (Specification (Clone_Body), False);
-
- -- If the subprogram body is the proper body of a stub, insert the
- -- subprogram after the stub, i.e. the same declarative region as
- -- the original sugprogram.
-
- if Nkind (Parent (Bod)) = N_Subunit then
- Insert_After (Corresponding_Stub (Parent (Bod)), Clone_Body);
-
- else
- Insert_Before (Bod, Clone_Body);
- end if;
-
- Analyze (Clone_Body);
- end Build_Class_Wide_Clone_Body;
-
- ---------------------------------
- -- Build_Class_Wide_Clone_Call --
- ---------------------------------
-
- function Build_Class_Wide_Clone_Call
- (Loc : Source_Ptr;
- Decls : List_Id;
- Spec_Id : Entity_Id;
- Spec : Node_Id) return Node_Id
- is
- Clone_Id : constant Entity_Id := Class_Wide_Clone (Spec_Id);
- Par_Type : constant Entity_Id := Find_Dispatching_Type (Spec_Id);
-
- Actuals : List_Id;
- Call : Node_Id;
- Formal : Entity_Id;
- New_Body : Node_Id;
- New_F_Spec : Entity_Id;
- New_Formal : Entity_Id;
-
- begin
- Actuals := Empty_List;
- Formal := First_Formal (Spec_Id);
- New_F_Spec := First (Parameter_Specifications (Spec));
-
- -- Build parameter association for call to class-wide clone.
-
- while Present (Formal) loop
- New_Formal := Defining_Identifier (New_F_Spec);
-
- -- If controlling argument and operation is inherited, add conversion
- -- to parent type for the call.
-
- if Etype (Formal) = Par_Type
- and then not Is_Empty_List (Decls)
- then
- Append_To (Actuals,
- Make_Type_Conversion (Loc,
- New_Occurrence_Of (Par_Type, Loc),
- New_Occurrence_Of (New_Formal, Loc)));
-
- else
- Append_To (Actuals, New_Occurrence_Of (New_Formal, Loc));
- end if;
-
- Next_Formal (Formal);
- Next (New_F_Spec);
- end loop;
-
- if Ekind (Spec_Id) = E_Procedure then
- Call :=
- Make_Procedure_Call_Statement (Loc,
- Name => New_Occurrence_Of (Clone_Id, Loc),
- Parameter_Associations => Actuals);
- else
- Call :=
- Make_Simple_Return_Statement (Loc,
- Expression =>
- Make_Function_Call (Loc,
- Name => New_Occurrence_Of (Clone_Id, Loc),
- Parameter_Associations => Actuals));
- end if;
-
- New_Body :=
- Make_Subprogram_Body (Loc,
- Specification =>
- Copy_Subprogram_Spec (Spec),
- Declarations => Decls,
- Handled_Statement_Sequence =>
- Make_Handled_Sequence_Of_Statements (Loc,
- Statements => New_List (Call),
- End_Label => Make_Identifier (Loc, Chars (Spec_Id))));
-
- return New_Body;
- end Build_Class_Wide_Clone_Call;
-
- ---------------------------------
- -- Build_Class_Wide_Clone_Decl --
- ---------------------------------
-
- procedure Build_Class_Wide_Clone_Decl (Spec_Id : Entity_Id) is
- Loc : constant Source_Ptr := Sloc (Spec_Id);
- Clone_Id : constant Entity_Id :=
- Make_Defining_Identifier (Loc,
- New_External_Name (Chars (Spec_Id), Suffix => "CL"));
-
- Decl : Node_Id;
- Spec : Node_Id;
-
- begin
- Spec := Copy_Subprogram_Spec (Parent (Spec_Id));
- Set_Must_Override (Spec, False);
- Set_Must_Not_Override (Spec, False);
- Set_Defining_Unit_Name (Spec, Clone_Id);
-
- Decl := Make_Subprogram_Declaration (Loc, Spec);
- Append (Decl, List_Containing (Unit_Declaration_Node (Spec_Id)));
-
- -- Link clone to original subprogram, for use when building body and
- -- wrapper call to inherited operation.
-
- Set_Class_Wide_Clone (Spec_Id, Clone_Id);
-
- -- Inherit debug info flag from Spec_Id to Clone_Id to allow debugging
- -- of the class-wide clone subprogram.
-
- if Needs_Debug_Info (Spec_Id) then
- Set_Debug_Info_Needed (Clone_Id);
- end if;
- end Build_Class_Wide_Clone_Decl;
-
-----------------------------
-- Build_Component_Subtype --
-----------------------------
@@ -5012,6 +4850,7 @@ package body Sem_Util is
and then not Mentions_Post_State (Expr)
and then not (Is_Ghost_Entity (Subp_Id)
and then Has_No_Output (Subp_Id))
+ and then not Is_Wrapper (Subp_Id)
then
if Pragma_Name (Prag) = Name_Contract_Cases then
Error_Msg_NE (Adjust_Message
@@ -5877,6 +5716,30 @@ package body Sem_Util is
end if;
end Choice_List;
+ ---------------------
+ -- Class_Condition --
+ ---------------------
+
+ function Class_Condition
+ (Kind : Condition_Kind;
+ Subp : Entity_Id) return Node_Id is
+
+ begin
+ case Kind is
+ when Class_Postcondition =>
+ return Class_Postconditions (Subp);
+
+ when Class_Precondition =>
+ return Class_Preconditions (Subp);
+
+ when Ignored_Class_Postcondition =>
+ return Ignored_Class_Postconditions (Subp);
+
+ when Ignored_Class_Precondition =>
+ return Ignored_Class_Preconditions (Subp);
+ end case;
+ end Class_Condition;
+
-------------------------
-- Collect_Body_States --
-------------------------
@@ -7072,6 +6935,79 @@ package body Sem_Util is
end if;
end Corresponding_Generic_Type;
+ --------------------------------
+ -- Corresponding_Primitive_Op --
+ --------------------------------
+
+ function Corresponding_Primitive_Op
+ (Ancestor_Op : Entity_Id;
+ Descendant_Type : Entity_Id) return Entity_Id
+ is
+ Typ : constant Entity_Id := Find_Dispatching_Type (Ancestor_Op);
+ Elmt : Elmt_Id;
+ Subp : Entity_Id;
+ Prim : Entity_Id;
+ begin
+ pragma Assert (Is_Dispatching_Operation (Ancestor_Op));
+ pragma Assert (Is_Ancestor (Typ, Descendant_Type)
+ or else Is_Progenitor (Typ, Descendant_Type));
+
+ Elmt := First_Elmt (Primitive_Operations (Descendant_Type));
+
+ while Present (Elmt) loop
+ Subp := Node (Elmt);
+
+ -- For regular primitives we only need to traverse the chain of
+ -- ancestors when the name matches the name of Ancestor_Op, but
+ -- for predefined dispatching operations we cannot rely on the
+ -- name of the primitive to identify a candidate since their name
+ -- is internally built adding a suffix to the name of the tagged
+ -- type.
+
+ if Chars (Subp) = Chars (Ancestor_Op)
+ or else Is_Predefined_Dispatching_Operation (Subp)
+ then
+ -- Handle case where Ancestor_Op is a primitive of a progenitor.
+ -- We rely on internal entities that map interface primitives:
+ -- their attribute Interface_Alias references the interface
+ -- primitive, and their Alias attribute references the primitive
+ -- of Descendant_Type implementing that interface primitive.
+
+ if Present (Interface_Alias (Subp)) then
+ if Interface_Alias (Subp) = Ancestor_Op then
+ return Alias (Subp);
+ end if;
+
+ -- Traverse the chain of ancestors searching for Ancestor_Op.
+ -- Overridden primitives have attribute Overridden_Operation;
+ -- inherited primitives have attribute Alias.
+
+ else
+ Prim := Subp;
+
+ while Present (Overridden_Operation (Prim))
+ or else Present (Alias (Prim))
+ loop
+ if Present (Overridden_Operation (Prim)) then
+ Prim := Overridden_Operation (Prim);
+ else
+ Prim := Alias (Prim);
+ end if;
+
+ if Prim = Ancestor_Op then
+ return Subp;
+ end if;
+ end loop;
+ end if;
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+
+ pragma Assert (False);
+ return Empty;
+ end Corresponding_Primitive_Op;
+
--------------------
-- Current_Entity --
--------------------
@@ -7444,7 +7380,7 @@ package body Sem_Util is
return False;
end if;
- Next_Index (Indx);
+ Next (Indx);
end loop;
end;
@@ -8732,6 +8668,10 @@ package body Sem_Util is
and then Comes_From_Source (C)
and then Comes_From_Source (Def_Id)
+ -- Don't warn within a generic instantiation
+
+ and then not In_Instance
+
-- Don't warn unless entity in question is in extended main source
and then In_Extended_Main_Source_Unit (Def_Id)
@@ -13389,8 +13329,8 @@ package body Sem_Util is
--------------------------------------
function Has_Preelaborable_Initialization
- (E : Entity_Id;
- Formal_Types_Have_Preelab_Init : Boolean := False) return Boolean
+ (E : Entity_Id;
+ Preelab_Init_Expr : Node_Id := Empty) return Boolean
is
Has_PE : Boolean;
@@ -13398,6 +13338,12 @@ package body Sem_Util is
-- Check component/discriminant chain, sets Has_PE False if a component
-- or discriminant does not meet the preelaborable initialization rules.
+ function Type_Named_In_Preelab_Init_Expression
+ (Typ : Entity_Id;
+ Expr : Node_Id) return Boolean;
+ -- Returns True iff Typ'Preelaborable_Initialization occurs in Expr
+ -- (where Expr may be a conjunction of one or more P_I attributes).
+
----------------------
-- Check_Components --
----------------------
@@ -13446,7 +13392,7 @@ package body Sem_Util is
if No (Exp) then
if not Has_Preelaborable_Initialization
- (Etype (Ent), Formal_Types_Have_Preelab_Init)
+ (Etype (Ent), Preelab_Init_Expr)
then
Has_PE := False;
exit;
@@ -13464,6 +13410,44 @@ package body Sem_Util is
end loop;
end Check_Components;
+ --------------------------------------
+ -- Type_Named_In_Preelab_Expression --
+ --------------------------------------
+
+ function Type_Named_In_Preelab_Init_Expression
+ (Typ : Entity_Id;
+ Expr : Node_Id) return Boolean
+ is
+ begin
+ -- Return True if Expr is a Preelaborable_Initialization attribute
+ -- and the prefix is a subtype that has the same type as Typ.
+
+ if Nkind (Expr) = N_Attribute_Reference
+ and then Attribute_Name (Expr) = Name_Preelaborable_Initialization
+ and then Is_Entity_Name (Prefix (Expr))
+ and then Base_Type (Entity (Prefix (Expr))) = Base_Type (Typ)
+ then
+ return True;
+
+ -- In the case where Expr is a conjunction, test whether either
+ -- operand is a Preelaborable_Initialization attribute whose prefix
+ -- has the same type as Typ, and return True if so.
+
+ elsif Nkind (Expr) = N_Op_And
+ and then
+ (Type_Named_In_Preelab_Init_Expression (Typ, Left_Opnd (Expr))
+ or else
+ Type_Named_In_Preelab_Init_Expression (Typ, Right_Opnd (Expr)))
+ then
+ return True;
+
+ -- Typ not named in a Preelaborable_Initialization attribute of Expr
+
+ else
+ return False;
+ end if;
+ end Type_Named_In_Preelab_Init_Expression;
+
-- Start of processing for Has_Preelaborable_Initialization
begin
@@ -13494,7 +13478,7 @@ package body Sem_Util is
elsif Is_Array_Type (E) then
Has_PE := Has_Preelaborable_Initialization
- (Component_Type (E), Formal_Types_Have_Preelab_Init);
+ (Component_Type (E), Preelab_Init_Expr);
-- A derived type has preelaborable initialization if its parent type
-- has preelaborable initialization and (in the case of a derived record
@@ -13509,7 +13493,11 @@ package body Sem_Util is
-- of a generic formal derived type has preelaborable initialization.
-- (See comment on spec of Has_Preelaborable_Initialization.)
- if Is_Generic_Type (E) and then Formal_Types_Have_Preelab_Init then
+ if Is_Generic_Type (E)
+ and then Present (Preelab_Init_Expr)
+ and then
+ Type_Named_In_Preelab_Init_Expression (E, Preelab_Init_Expr)
+ then
return True;
end if;
@@ -13522,7 +13510,8 @@ package body Sem_Util is
-- First check whether ancestor type has preelaborable initialization
- Has_PE := Has_Preelaborable_Initialization (Etype (Base_Type (E)));
+ Has_PE := Has_Preelaborable_Initialization
+ (Etype (Base_Type (E)), Preelab_Init_Expr);
-- If OK, check extension components (if any)
@@ -13553,7 +13542,11 @@ package body Sem_Util is
-- of a generic formal private type has preelaborable initialization.
-- (See comment on spec of Has_Preelaborable_Initialization.)
- if Is_Generic_Type (E) and then Formal_Types_Have_Preelab_Init then
+ if Is_Generic_Type (E)
+ and then Present (Preelab_Init_Expr)
+ and then
+ Type_Named_In_Preelab_Init_Expression (E, Preelab_Init_Expr)
+ then
return True;
else
return False;
@@ -16264,12 +16257,14 @@ package body Sem_Util is
Names_Match (Assign_Indexed_1, Assign_Indexed_2);
end;
+ -- Checking for this aspect is performed elsewhere during freezing
+ when Aspect_No_Controlled_Parts =>
+ return True;
+
-- scalar-valued aspects; compare (static) values.
- when Aspect_Max_Entry_Queue_Length -- | Aspect_No_Controlled_Parts
- =>
- -- This should be unreachable. No_Controlled_Parts is
- -- not yet supported at all in GNAT and Max_Entry_Queue_Length
- -- is supported only for protected entries, not for types.
+ when Aspect_Max_Entry_Queue_Length =>
+ -- This should be unreachable. Max_Entry_Queue_Length is
+ -- supported only for protected entries, not for types.
pragma Assert (Serious_Errors_Detected /= 0);
return True;
@@ -16924,6 +16919,15 @@ package body Sem_Util is
end if;
if Is_Entity_Name (P) then
+ -- The Etype may not be set on P (which is wrong) in certain
+ -- corner cases involving the deprecated front-end inlining of
+ -- subprograms (via -gnatN), so use the Etype set on the
+ -- the entity for these instances since we know it is present.
+
+ if No (Prefix_Type) then
+ Prefix_Type := Etype (Entity (P));
+ end if;
+
if Ekind (Entity (P)) = E_Generic_In_Out_Parameter then
Prefix_Type := Base_Type (Prefix_Type);
end if;
@@ -18167,6 +18171,19 @@ package body Sem_Util is
if Is_Formal (E) then
return False;
+
+ -- If we somehow got an empty value for Scope, the tree must be
+ -- malformed. Rather than blow up we return True in this case.
+
+ elsif No (Scope (E)) then
+ return True;
+
+ -- Handle loops since Enclosing_Dynamic_Scope skips them; required to
+ -- properly handle entities local to quantified expressions in library
+ -- level specifications.
+
+ elsif Ekind (Scope (E)) = E_Loop then
+ return False;
end if;
-- Normal test is simply that the enclosing dynamic scope is Standard
@@ -21188,6 +21205,9 @@ package body Sem_Util is
-- Is_Variable --
-----------------
+ -- Should Is_Variable be refactored to better handle dereferences and
+ -- technical debt ???
+
function Is_Variable
(N : Node_Id;
Use_Original_Node : Boolean := True) return Boolean
@@ -21356,6 +21376,10 @@ package body Sem_Util is
and then Nkind (Parent (E)) /= N_Exception_Handler)
or else (K = E_Component
and then not In_Protected_Function (E))
+ or else (Present (Etype (E))
+ and then Is_Access_Object_Type (Etype (E))
+ and then Is_Access_Variable (Etype (E))
+ and then Is_Dereferenced (N))
or else K = E_Out_Parameter
or else K = E_In_Out_Parameter
or else K = E_Generic_In_Out_Parameter
@@ -22713,6 +22737,61 @@ package body Sem_Util is
return Result;
end Might_Raise;
+ ----------------------------------------
+ -- Nearest_Class_Condition_Subprogram --
+ ----------------------------------------
+
+ function Nearest_Class_Condition_Subprogram
+ (Kind : Condition_Kind;
+ Spec_Id : Entity_Id) return Entity_Id
+ is
+ Subp_Id : constant Entity_Id := Ultimate_Alias (Spec_Id);
+
+ begin
+ -- Prevent cascaded errors
+
+ if not Is_Dispatching_Operation (Subp_Id) then
+ return Empty;
+
+ -- No need to search if this subprogram has class-wide postconditions
+
+ elsif Present (Class_Condition (Kind, Subp_Id)) then
+ return Subp_Id;
+ end if;
+
+ -- Process the contracts of inherited subprograms, looking for
+ -- class-wide pre/postconditions.
+
+ declare
+ Subps : constant Subprogram_List := Inherited_Subprograms (Subp_Id);
+ Subp_Id : Entity_Id;
+
+ begin
+ for Index in Subps'Range loop
+ Subp_Id := Subps (Index);
+
+ if Present (Alias (Subp_Id)) then
+ Subp_Id := Ultimate_Alias (Subp_Id);
+ end if;
+
+ -- Wrappers of class-wide pre/postconditions reference the
+ -- parent primitive that has the inherited contract.
+
+ if Is_Wrapper (Subp_Id)
+ and then Present (LSP_Subprogram (Subp_Id))
+ then
+ Subp_Id := LSP_Subprogram (Subp_Id);
+ end if;
+
+ if Present (Class_Condition (Kind, Subp_Id)) then
+ return Subp_Id;
+ end if;
+ end loop;
+ end;
+
+ return Empty;
+ end Nearest_Class_Condition_Subprogram;
+
--------------------------------
-- Nearest_Enclosing_Instance --
--------------------------------
@@ -24707,7 +24786,7 @@ package body Sem_Util is
-- Visit_Node --
----------------
- procedure Visit_Node (N : Node_Or_Entity_Id) is
+ procedure Visit_Node (N : Node_Id) is
begin
pragma Assert (Nkind (N) not in N_Entity);
@@ -29279,7 +29358,7 @@ package body Sem_Util is
(Designated_Type (Btyp), Allow_Alt_Model);
end if;
- -- When an anonymous access type's Assoc_Ent is specifiedi,
+ -- When an anonymous access type's Assoc_Ent is specified,
-- calculate the result based on the general accessibility
-- level routine.
@@ -29301,10 +29380,22 @@ package body Sem_Util is
(Associated_Node_For_Itype (Typ));
if Present (Def_Ent) then
- -- When the type comes from an anonymous access parameter,
- -- the level is that of the subprogram declaration.
+ -- When the defining entity is a subprogram then we know the
+ -- anonymous access type Typ has been generated to either
+ -- describe an anonymous access type formal or an anonymous
+ -- access result type.
+
+ -- Since we are only interested in the formal case, avoid
+ -- the anonymous access result type.
+
+ if Ekind (Def_Ent) in Subprogram_Kind
+ and then not (Ekind (Def_Ent) = E_Function
+ and then Etype (Def_Ent) = Typ)
+ then
+ -- When the type comes from an anonymous access
+ -- parameter, the level is that of the subprogram
+ -- declaration.
- if Ekind (Def_Ent) in Subprogram_Kind then
return Scope_Depth (Def_Ent);
-- When the type is an access discriminant, the level is
@@ -31459,8 +31550,16 @@ package body Sem_Util is
-- type case correctly, so we avoid that problem by
-- returning True here.
return True;
+
elsif Ada_Version < Ada_2022 then
return False;
+
+ elsif Inside_Class_Condition_Preanalysis then
+ -- No need to evaluate it during preanalysis of a class-wide
+ -- pre/postcondition since the expression is not installed yet
+ -- on its definite context.
+ return False;
+
elsif not Is_Conditionally_Evaluated (Expr) then
return False;
else
@@ -31517,7 +31616,12 @@ package body Sem_Util is
-- quantified_expression.
if Nkind (Par) = N_Quantified_Expression
- and then Trailer = Condition (Par)
+ and then Trailer = Condition (Par)
+ then
+ return True;
+ elsif Nkind (Par) = N_Expression_With_Actions
+ and then
+ Nkind (Original_Node (Par)) = N_Quantified_Expression
then
return True;
end if;
@@ -32043,11 +32147,172 @@ package body Sem_Util is
end if;
end;
end if;
+
return False;
end Is_Access_Type_For_Indirect_Temp;
end Indirect_Temps;
end Old_Attr_Util;
+
+ package body Storage_Model_Support is
+
+ -----------------------------------
+ -- Get_Storage_Model_Type_Entity --
+ -----------------------------------
+
+ function Get_Storage_Model_Type_Entity
+ (Typ : Entity_Id;
+ Nam : Name_Id) return Entity_Id
+ is
+ pragma Assert
+ (Is_Type (Typ)
+ and then
+ Nam in Name_Address_Type
+ | Name_Null_Address
+ | Name_Allocate
+ | Name_Deallocate
+ | Name_Copy_From
+ | Name_Copy_To
+ | Name_Storage_Size);
+
+ SMT_Aspect_Value : constant Node_Id :=
+ Find_Value_Of_Aspect (Typ, Aspect_Storage_Model_Type);
+ Assoc : Node_Id;
+
+ begin
+ if No (SMT_Aspect_Value) then
+ return Empty;
+
+ else
+ Assoc := First (Component_Associations (SMT_Aspect_Value));
+ while Present (Assoc) loop
+ if Chars (First (Choices (Assoc))) = Nam then
+ return Entity (Expression (Assoc));
+ end if;
+
+ Next (Assoc);
+ end loop;
+
+ return Empty;
+ end if;
+ end Get_Storage_Model_Type_Entity;
+
+ -----------------------------------------
+ -- Has_Designated_Storage_Model_Aspect --
+ -----------------------------------------
+
+ function Has_Designated_Storage_Model_Aspect
+ (Typ : Entity_Id) return Boolean
+ is
+ begin
+ return Present (Find_Aspect (Typ, Aspect_Designated_Storage_Model));
+ end Has_Designated_Storage_Model_Aspect;
+
+ -----------------------------------
+ -- Has_Storage_Model_Type_Aspect --
+ -----------------------------------
+
+ function Has_Storage_Model_Type_Aspect (Typ : Entity_Id) return Boolean
+ is
+ begin
+ return Present (Find_Aspect (Typ, Aspect_Storage_Model_Type));
+ end Has_Storage_Model_Type_Aspect;
+
+ --------------------------
+ -- Storage_Model_Object --
+ --------------------------
+
+ function Storage_Model_Object (Typ : Entity_Id) return Entity_Id is
+ begin
+ if Has_Designated_Storage_Model_Aspect (Typ) then
+ return
+ Entity
+ (Find_Value_Of_Aspect (Typ, Aspect_Designated_Storage_Model));
+ else
+ return Empty;
+ end if;
+ end Storage_Model_Object;
+
+ ------------------------
+ -- Storage_Model_Type --
+ ------------------------
+
+ function Storage_Model_Type (Obj : Entity_Id) return Entity_Id is
+ begin
+ if Present
+ (Find_Value_Of_Aspect (Etype (Obj), Aspect_Storage_Model_Type))
+ then
+ return Etype (Obj);
+ else
+ return Empty;
+ end if;
+ end Storage_Model_Type;
+
+ --------------------------------
+ -- Storage_Model_Address_Type --
+ --------------------------------
+
+ function Storage_Model_Address_Type (Typ : Entity_Id) return Entity_Id is
+ begin
+ return Get_Storage_Model_Type_Entity (Typ, Name_Address_Type);
+ end Storage_Model_Address_Type;
+
+ --------------------------------
+ -- Storage_Model_Null_Address --
+ --------------------------------
+
+ function Storage_Model_Null_Address (Typ : Entity_Id) return Entity_Id is
+ begin
+ return Get_Storage_Model_Type_Entity (Typ, Name_Null_Address);
+ end Storage_Model_Null_Address;
+
+ ----------------------------
+ -- Storage_Model_Allocate --
+ ----------------------------
+
+ function Storage_Model_Allocate (Typ : Entity_Id) return Entity_Id is
+ begin
+ return Get_Storage_Model_Type_Entity (Typ, Name_Allocate);
+ end Storage_Model_Allocate;
+
+ ------------------------------
+ -- Storage_Model_Deallocate --
+ ------------------------------
+
+ function Storage_Model_Deallocate (Typ : Entity_Id) return Entity_Id is
+ begin
+ return Get_Storage_Model_Type_Entity (Typ, Name_Deallocate);
+ end Storage_Model_Deallocate;
+
+ -----------------------------
+ -- Storage_Model_Copy_From --
+ -----------------------------
+
+ function Storage_Model_Copy_From (Typ : Entity_Id) return Entity_Id is
+ begin
+ return Get_Storage_Model_Type_Entity (Typ, Name_Copy_From);
+ end Storage_Model_Copy_From;
+
+ ---------------------------
+ -- Storage_Model_Copy_To --
+ ---------------------------
+
+ function Storage_Model_Copy_To (Typ : Entity_Id) return Entity_Id is
+ begin
+ return Get_Storage_Model_Type_Entity (Typ, Name_Copy_To);
+ end Storage_Model_Copy_To;
+
+ --------------------------------
+ -- Storage_Model_Storage_Size --
+ --------------------------------
+
+ function Storage_Model_Storage_Size (Typ : Entity_Id) return Entity_Id is
+ begin
+ return Get_Storage_Model_Type_Entity (Typ, Name_Storage_Size);
+ end Storage_Model_Storage_Size;
+
+ end Storage_Model_Support;
+
begin
Erroutc.Subprogram_Name_Ptr := Subprogram_Name'Access;
end Sem_Util;
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index 7c89585..85010b5 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -283,30 +283,6 @@ package Sem_Util is
-- take care of constructing declaration and body of the clone, and
-- building the calls to it within the appropriate wrappers.
- procedure Build_Class_Wide_Clone_Body
- (Spec_Id : Entity_Id;
- Bod : Node_Id);
- -- Build body of subprogram that has a class-wide condition that contains
- -- calls to other primitives. Spec_Id is the Id of the subprogram, and B
- -- is its source body, which becomes the body of the clone.
-
- function Build_Class_Wide_Clone_Call
- (Loc : Source_Ptr;
- Decls : List_Id;
- Spec_Id : Entity_Id;
- Spec : Node_Id) return Node_Id;
- -- Build a call to the common class-wide clone of a subprogram with
- -- class-wide conditions. The body of the subprogram becomes a wrapper
- -- for a call to the clone. The inherited operation becomes a similar
- -- wrapper to which modified conditions apply, and the call to the
- -- clone includes the proper conversion in a call the parent operation.
-
- procedure Build_Class_Wide_Clone_Decl (Spec_Id : Entity_Id);
- -- For a subprogram that has a class-wide condition that contains calls
- -- to other primitives, build an internal subprogram that is invoked
- -- through a type-specific wrapper for all inherited subprograms that
- -- may have a modified condition.
-
procedure Build_Constrained_Itype
(N : Node_Id;
Typ : Entity_Id;
@@ -356,7 +332,7 @@ package Sem_Util is
-- carries the name of the reference discriminant.
function Build_Overriding_Spec
- (Op : Node_Id;
+ (Op : Entity_Id;
Typ : Entity_Id) return Node_Id;
-- Build a subprogram specification for the wrapper of an inherited
-- operation with a modified pre- or postcondition (See AI12-0113).
@@ -527,6 +503,18 @@ package Sem_Util is
-- reasons these nodes have a different structure even though they play
-- similar roles in array aggregates.
+ type Condition_Kind is
+ (Ignored_Class_Precondition,
+ Ignored_Class_Postcondition,
+ Class_Precondition,
+ Class_Postcondition);
+ -- Kind of class-wide conditions
+
+ function Class_Condition
+ (Kind : Condition_Kind;
+ Subp : Entity_Id) return Node_Id;
+ -- Class-wide Kind condition of Subp
+
function Collect_Body_States (Body_Id : Entity_Id) return Elist_Id;
-- Gather the entities of all abstract states and objects declared in the
-- body state space of package body Body_Id.
@@ -638,6 +626,13 @@ package Sem_Util is
-- attribute, except in the case of formal private and derived types.
-- Possible optimization???
+ function Corresponding_Primitive_Op
+ (Ancestor_Op : Entity_Id;
+ Descendant_Type : Entity_Id) return Entity_Id;
+ -- Given a primitive subprogram of a tagged type and a (distinct)
+ -- descendant type of that type, find the corresponding primitive
+ -- subprogram of the descendant type.
+
function Current_Entity (N : Node_Id) return Entity_Id;
pragma Inline (Current_Entity);
-- Find the currently visible definition for a given identifier, that is to
@@ -1531,17 +1526,15 @@ package Sem_Util is
-- initialization.
function Has_Preelaborable_Initialization
- (E : Entity_Id;
- Formal_Types_Have_Preelab_Init : Boolean := False) return Boolean;
+ (E : Entity_Id;
+ Preelab_Init_Expr : Node_Id := Empty) return Boolean;
-- Return True iff type E has preelaborable initialization as defined in
-- Ada 2005 (see AI-161 for details of the definition of this attribute).
- -- If Formal_Types_Have_Preelab_Init is True, indicates that the function
- -- should presume that for any subcomponents of formal private or derived
- -- types, the types have preelaborable initialization (RM 10.2.1(11.8/5)).
- -- NOTE: The treatment of subcomponents of formal types should only apply
- -- for types actually specified in the P_I aspect of the outer type, but
- -- for now we take a more liberal interpretation. This needs addressing,
- -- perhaps by passing the outermost type instead of the simple flag. ???
+ -- If Preelab_Init_Expr is present, indicates that the function should
+ -- presume that for any subcomponent of E that is of a formal private or
+ -- derived type that is referenced by a Preelaborable_Initialization
+ -- attribute within the expression Preelab_Init_Expr, the formal type has
+ -- preelaborable initialization (RM 10.2.1(11.8/5) and AI12-0409).
function Has_Prefix (N : Node_Id) return Boolean;
-- Return True if N has attribute Prefix
@@ -2614,6 +2607,12 @@ package Sem_Util is
-- if we're not sure, we return True. If N is a subprogram body, this is
-- about whether execution of that body can raise.
+ function Nearest_Class_Condition_Subprogram
+ (Kind : Condition_Kind;
+ Spec_Id : Entity_Id) return Entity_Id;
+ -- Return the nearest ancestor containing the merged class-wide conditions
+ -- that statically apply to Spec_Id; return Empty otherwise.
+
function Nearest_Enclosing_Instance (E : Entity_Id) return Entity_Id;
-- Return the entity of the nearest enclosing instance which encapsulates
-- entity E. If no such instance exits, return Empty.
@@ -3551,4 +3550,76 @@ package Sem_Util is
end Indirect_Temps;
end Old_Attr_Util;
+
+ package Storage_Model_Support is
+
+ -- This package provides a set of utility functions related to support
+ -- for the Storage_Model feature. These functions provide an interface
+ -- that the compiler (in particular back-end phases such as gigi and
+ -- GNAT-LLVM) can use to easily obtain entities and operations that
+ -- are specified for types in the aspects Storage_Model_Type and
+ -- Designated_Storage_Model.
+
+ function Get_Storage_Model_Type_Entity
+ (Typ : Entity_Id;
+ Nam : Name_Id) return Entity_Id;
+ -- Given type Typ with aspect Storage_Model_Type, returns the Entity_Id
+ -- corresponding to the entity associated with Nam in the aspect. If the
+ -- type does not specify the aspect, or such an entity is not present,
+ -- then returns Empty. (Note: This function is modeled on function
+ -- Get_Iterable_Type_Primitive.)
+
+ function Has_Designated_Storage_Model_Aspect
+ (Typ : Entity_Id) return Boolean;
+ -- Returns True iff Typ specifies aspect Designated_Storage_Model
+
+ function Has_Storage_Model_Type_Aspect (Typ : Entity_Id) return Boolean;
+ -- Returns True iff Typ specifies aspect Storage_Model_Type
+
+ function Storage_Model_Object (Typ : Entity_Id) return Entity_Id;
+ -- Given an access type with aspect Designated_Storage_Model, returns
+ -- the storage-model object associated with that type; returns Empty
+ -- if there is no associated object.
+
+ 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; otherwise returns Empty.
+
+ function Storage_Model_Address_Type (Typ : Entity_Id) return Entity_Id;
+ -- Given a type Typ that specifies aspect Storage_Model_Type, returns
+ -- the type specified for the Address_Type choice in that aspect;
+ -- returns Empty if the aspect or the type isn't specified.
+
+ function Storage_Model_Null_Address (Typ : Entity_Id) return Entity_Id;
+ -- Given a type Typ that specifies aspect Storage_Model_Type, returns
+ -- constant specified for Null_Address choice in that aspect; returns
+ -- Empty if the aspect or the constant object isn't specified.
+
+ function Storage_Model_Allocate (Typ : Entity_Id) return Entity_Id;
+ -- Given a type Typ that specifies aspect Storage_Model_Type, returns
+ -- procedure specified for the Allocate choice in that aspect; returns
+ -- Empty if the aspect or the procedure isn't specified.
+
+ function Storage_Model_Deallocate (Typ : Entity_Id) return Entity_Id;
+ -- Given a type Typ that specifies aspect Storage_Model_Type, returns
+ -- procedure specified for the Deallocate choice in that aspect; returns
+ -- Empty if the aspect or the procedure isn't specified.
+
+ function Storage_Model_Copy_From (Typ : Entity_Id) return Entity_Id;
+ -- Given a type Typ that specifies aspect Storage_Model_Type, returns
+ -- procedure specified for the Copy_From choice in that aspect; returns
+ -- Empty if the aspect or the procedure isn't specified.
+
+ function Storage_Model_Copy_To (Typ : Entity_Id) return Entity_Id;
+ -- Given a type Typ that specifies aspect Storage_Model_Type, returns
+ -- procedure specified for the Copy_To choice in that aspect; returns
+ -- Empty if the aspect or the procedure isn't specified.
+
+ function Storage_Model_Storage_Size (Typ : Entity_Id) return Entity_Id;
+ -- Given a type Typ that specifies aspect Storage_Model_Type, returns
+ -- function specified for Storage_Size choice in that aspect; returns
+ -- Empty if the aspect or the procedure isn't specified.
+
+ end Storage_Model_Support;
+
end Sem_Util;
diff --git a/gcc/ada/sinfo-utils.adb b/gcc/ada/sinfo-utils.adb
index 083c12e..cf0ecc1 100644
--- a/gcc/ada/sinfo-utils.adb
+++ b/gcc/ada/sinfo-utils.adb
@@ -23,7 +23,7 @@
-- --
------------------------------------------------------------------------------
-with Atree;
+with Atree; use Atree;
with Debug; use Debug;
with Output; use Output;
with Seinfo;
@@ -55,7 +55,7 @@ package body Sinfo.Utils is
-- The second method is much faster if the amount of Ada code being
-- compiled is large.
- ww : Node_Id'Base := Node_Id'First - 1;
+ ww : Node_Id'Base := Node_Low_Bound - 1;
pragma Export (Ada, ww);
Watch_Node : Node_Id'Base renames ww;
-- Node to "watch"; that is, whenever a node is created, we check if it
@@ -72,8 +72,8 @@ package body Sinfo.Utils is
procedure nnd (N : Node_Id);
pragma Export (Ada, nnd);
- -- For debugging. If debugging is turned on, New_Node and New_Entity call
- -- this. If debug flag N is turned on, this prints out the new node.
+ -- For debugging. If debugging is turned on, New_Node and New_Entity (etc.)
+ -- call this. If debug flag N is turned on, this prints out the new node.
--
-- If Node = Watch_Node, this prints out the new node and calls
-- New_Node_Breakpoint. Otherwise, does nothing.
@@ -265,7 +265,7 @@ package body Sinfo.Utils is
if Fields (J) /= F_Link then -- Don't walk Parent!
declare
Desc : Field_Descriptor renames
- Node_Field_Descriptors (Fields (J));
+ Field_Descriptors (Fields (J));
begin
if Is_In_Union_Id (Desc.Kind) then
Action (Get_Node_Field_Union (N, Desc.Offset));
@@ -290,7 +290,7 @@ package body Sinfo.Utils is
if Fields (J) /= F_Link then -- Don't walk Parent!
declare
Desc : Field_Descriptor renames
- Node_Field_Descriptors (Fields (J));
+ Field_Descriptors (Fields (J));
begin
if Is_In_Union_Id (Desc.Kind) then
Set_Node_Field_Union
diff --git a/gcc/ada/sinfo-utils.ads b/gcc/ada/sinfo-utils.ads
index 2023e67..e3bb8d4 100644
--- a/gcc/ada/sinfo-utils.ads
+++ b/gcc/ada/sinfo-utils.ads
@@ -23,7 +23,7 @@
-- --
------------------------------------------------------------------------------
-with Sinfo.Nodes; use Sinfo.Nodes;
+with Sinfo.Nodes; use Sinfo.Nodes;
package Sinfo.Utils is
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index 20a6125..b99edf7 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -411,10 +411,6 @@ package Sinfo is
-- Assignment_OK set if modification is OK
-- Is_Controlling_Actual set for controlling argument
- -- Note: the utility program that creates the Treeprs spec (in the file
- -- xtreeprs.adb) knows about the special fields here, so it must be
- -- modified if any change is made to these fields.
-
-- Note: see under (EXPRESSION) for further details on the use of
-- the Paren_Count field to record the number of parentheses levels.
diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl
index 34f1cef..e1af28b 100644
--- a/gcc/ada/snames.ads-tmpl
+++ b/gcc/ada/snames.ads-tmpl
@@ -149,6 +149,7 @@ package Snames is
Name_Default_Value : constant Name_Id := N + $;
Name_Default_Component_Value : constant Name_Id := N + $;
+ Name_Designated_Storage_Model : constant Name_Id := N + $;
Name_Dimension : constant Name_Id := N + $;
Name_Dimension_System : constant Name_Id := N + $;
Name_Disable_Controlled : constant Name_Id := N + $;
@@ -162,6 +163,8 @@ package Snames is
Name_Relaxed_Initialization : constant Name_Id := N + $;
Name_Stable_Properties : constant Name_Id := N + $;
Name_Static_Predicate : constant Name_Id := N + $;
+ Name_Storage_Model : constant Name_Id := N + $;
+ Name_Storage_Model_Type : constant Name_Id := N + $;
Name_String_Literal : constant Name_Id := N + $;
Name_Synchronization : constant Name_Id := N + $;
Name_Unimplemented : constant Name_Id := N + $;
@@ -526,6 +529,7 @@ package Snames is
Name_CPP_Constructor : constant Name_Id := N + $; -- GNAT
Name_CPP_Virtual : constant Name_Id := N + $; -- GNAT
Name_CPP_Vtable : constant Name_Id := N + $; -- GNAT
+ Name_CUDA_Device : constant Name_Id := N + $; -- GNAT
Name_CUDA_Execute : constant Name_Id := N + $; -- GNAT
Name_CUDA_Global : constant Name_Id := N + $; -- GNAT
@@ -778,6 +782,7 @@ package Snames is
-- Other special names used in processing attributes, aspects, and pragmas
+ Name_Address_Type : constant Name_Id := N + $;
Name_Aggregate : constant Name_Id := N + $;
Name_Allow : constant Name_Id := N + $;
Name_Amount : constant Name_Id := N + $;
@@ -797,6 +802,8 @@ package Snames is
Name_Component : constant Name_Id := N + $;
Name_Component_Size_4 : constant Name_Id := N + $;
Name_Copy : constant Name_Id := N + $;
+ Name_Copy_From : constant Name_Id := N + $;
+ Name_Copy_To : constant Name_Id := N + $;
Name_D_Float : constant Name_Id := N + $;
Name_Decreases : constant Name_Id := N + $;
Name_Disable : constant Name_Id := N + $;
@@ -866,6 +873,7 @@ package Snames is
Name_Nominal : constant Name_Id := N + $;
Name_Non_Volatile : constant Name_Id := N + $;
Name_None : constant Name_Id := N + $;
+ Name_Null_Address : constant Name_Id := N + $;
Name_On : constant Name_Id := N + $;
Name_Optional : constant Name_Id := N + $;
Name_Policy : constant Name_Id := N + $;
@@ -963,8 +971,8 @@ package Snames is
Name_Elaborated : constant Name_Id := N + $; -- GNAT
Name_Emax : constant Name_Id := N + $; -- Ada 83
Name_Enabled : constant Name_Id := N + $; -- GNAT
- Name_Enum_Rep : constant Name_Id := N + $; -- GNAT
- Name_Enum_Val : constant Name_Id := N + $; -- GNAT
+ Name_Enum_Rep : constant Name_Id := N + $; -- Ada 22
+ Name_Enum_Val : constant Name_Id := N + $; -- Ada 22
Name_Epsilon : constant Name_Id := N + $; -- Ada 83
Name_Exponent : constant Name_Id := N + $;
Name_External_Tag : constant Name_Id := N + $;
@@ -1017,7 +1025,7 @@ package Snames is
Name_Modulus : constant Name_Id := N + $;
Name_Null_Parameter : constant Name_Id := N + $; -- GNAT
Name_Object_Size : constant Name_Id := N + $; -- GNAT
- Name_Old : constant Name_Id := N + $; -- GNAT
+ Name_Old : constant Name_Id := N + $; -- Ada 12
Name_Overlaps_Storage : constant Name_Id := N + $; -- GNAT
Name_Partition_ID : constant Name_Id := N + $;
Name_Passed_By_Reference : constant Name_Id := N + $; -- GNAT
@@ -1028,7 +1036,7 @@ package Snames is
Name_Priority : constant Name_Id := N + $; -- Ada 05
Name_Range : constant Name_Id := N + $;
Name_Range_Length : constant Name_Id := N + $; -- GNAT
- Name_Reduce : constant Name_Id := N + $; -- GNAT
+ Name_Reduce : constant Name_Id := N + $; -- Ada 22
Name_Ref : constant Name_Id := N + $; -- GNAT
Name_Restriction_Set : constant Name_Id := N + $; -- GNAT
Name_Result : constant Name_Id := N + $; -- GNAT
@@ -1392,7 +1400,6 @@ package Snames is
-- Note that the UP_ prefix means use the rest of the name in uppercase,
-- e.g. Name_UP_RESULT corresponds to the name "RESULT".
- Name_Unaligned_Valid : constant Name_Id := N + $;
Name_UP_RESULT : constant Name_Id := N + $;
Name_Suspension_Object : constant Name_Id := N + $;
Name_Synchronous_Task_Control : constant Name_Id := N + $;
@@ -1862,6 +1869,7 @@ package Snames is
Pragma_CPP_Constructor,
Pragma_CPP_Virtual,
Pragma_CPP_Vtable,
+ Pragma_CUDA_Device,
Pragma_CUDA_Execute,
Pragma_CUDA_Global,
Pragma_Deadline_Floor,
diff --git a/gcc/ada/socket.c b/gcc/ada/socket.c
index 82e0c5a..5074c8e 100644
--- a/gcc/ada/socket.c
+++ b/gcc/ada/socket.c
@@ -314,6 +314,7 @@ __gnat_gethostbyaddr (const char *addr, int len, int type,
ret->h_addrtype = AF_INET;
ret->h_length = 4;
ret->h_addr_list = &vxw_h_addr_list;
+ return 0;
}
int
@@ -587,6 +588,9 @@ __gnat_inet_pton (int af, const char *src, void *dst) {
*(in_addr_t *)dst = addr;
}
return rc;
+
+#else
+ return -1;
#endif
}
#endif
diff --git a/gcc/ada/sprint.adb b/gcc/ada/sprint.adb
index 8dc96a4..9b78ada 100644
--- a/gcc/ada/sprint.adb
+++ b/gcc/ada/sprint.adb
@@ -2075,7 +2075,7 @@ package body Sprint is
Sprint_Node (Name (Node));
Write_Char (';');
- when N_Generic_Package_Declaration =>
+ when N_Generic_Declaration =>
Extra_Blank_Line;
Write_Indent_Str_Sloc ("generic ");
Sprint_Indented_List (Generic_Formal_Declarations (Node));
@@ -2097,14 +2097,6 @@ package body Sprint is
Sprint_Node (Name (Node));
Write_Char (';');
- when N_Generic_Subprogram_Declaration =>
- Extra_Blank_Line;
- Write_Indent_Str_Sloc ("generic ");
- Sprint_Indented_List (Generic_Formal_Declarations (Node));
- Write_Indent;
- Sprint_Node (Specification (Node));
- Write_Char (';');
-
when N_Goto_Statement =>
Write_Indent_Str_Sloc ("goto ");
Sprint_Node (Name (Node));
diff --git a/gcc/ada/sysdep.c b/gcc/ada/sysdep.c
index ee951e3..2c50b36 100644
--- a/gcc/ada/sysdep.c
+++ b/gcc/ada/sysdep.c
@@ -907,6 +907,10 @@ __gnat_is_file_not_found_error (int errno_val)
if (errno_val == ENOENT)
return 1;
#ifdef __vxworks
+ /* Starting with VxWorks 21.03, the fopen() function can set errno to
+ * ENODEV when the prefix of the path does not match any known device. */
+ else if (errno_val == ENODEV)
+ return 1;
/* In the case of VxWorks, we also have to take into account various
* filesystem-specific variants of this error.
*/
diff --git a/gcc/ada/treepr.adb b/gcc/ada/treepr.adb
index 48f76cb..4c7833b 100644
--- a/gcc/ada/treepr.adb
+++ b/gcc/ada/treepr.adb
@@ -130,9 +130,7 @@ package body Treepr is
procedure Capitalize (S : in out String);
-- Turns an identifier into Mixed_Case
- function Image (F : Node_Field) return String;
-
- function Image (F : Entity_Field) return String;
+ function Image (F : Node_Or_Entity_Field) return String;
procedure Print_Init;
-- Initialize for printing of tree with descendants
@@ -281,7 +279,7 @@ package body Treepr is
-- Image --
-----------
- function Image (F : Node_Field) return String is
+ function Image (F : Node_Or_Entity_Field) return String is
begin
case F is
when F_Alloc_For_BIP_Return =>
@@ -321,18 +319,6 @@ package body Treepr is
when F_TSS_Elist =>
return "TSS_Elist";
- when others =>
- declare
- Result : constant String := Capitalize (F'Img);
- begin
- return Result (3 .. Result'Last); -- Remove "F_"
- end;
- end case;
- end Image;
-
- function Image (F : Entity_Field) return String is
- begin
- case F is
when F_BIP_Initialization_Call =>
return "BIP_Initialization_Call";
when F_Body_Needed_For_SAL =>
@@ -666,7 +652,7 @@ package body Treepr is
for Field_Index in Fields'Range loop
declare
FD : Field_Descriptor renames
- Entity_Field_Descriptors (Fields (Field_Index));
+ Field_Descriptors (Fields (Field_Index));
begin
if Should_Print (Fields (Field_Index))
and then (FD.Kind = Flag_Field) = Print_Flags
@@ -1266,14 +1252,21 @@ package body Treepr is
-- Print Chars field if present
- if Nkind (N) in N_Has_Chars and then Chars (N) /= No_Name then
- Print_Str (Prefix);
- Print_Str ("Chars = ");
- Print_Name (Chars (N));
- Write_Str (" (Name_Id=");
- Write_Int (Int (Chars (N)));
- Write_Char (')');
- Print_Eol;
+ if Nkind (N) in N_Has_Chars then
+ if Field_Is_Initial_Zero (N, F_Chars) then
+ Print_Str (Prefix);
+ Print_Str ("Chars = initial zero");
+ Print_Eol;
+
+ elsif Chars (N) /= No_Name then
+ Print_Str (Prefix);
+ Print_Str ("Chars = ");
+ Print_Name (Chars (N));
+ Write_Str (" (Name_Id=");
+ Write_Int (Int (Chars (N)));
+ Write_Char (')');
+ Print_Eol;
+ end if;
end if;
-- Special field print operations for non-entity nodes
@@ -1454,7 +1447,7 @@ package body Treepr is
for Field_Index in Fields'Range loop
declare
FD : Field_Descriptor renames
- Node_Field_Descriptors (Fields (Field_Index));
+ Field_Descriptors (Fields (Field_Index));
begin
if Should_Print (Fields (Field_Index))
and then (FD.Kind = Flag_Field) = Print_Flags
@@ -1624,7 +1617,14 @@ package body Treepr is
if Nkind (N) in N_Has_Chars then
Write_Char (' ');
- Print_Name (Chars (N));
+
+ if Field_Is_Initial_Zero (N, F_Chars) then
+ Print_Str ("Chars = initial zero");
+ Print_Eol;
+
+ else
+ Print_Name (Chars (N));
+ end if;
end if;
if Nkind (N) in N_Entity then
@@ -2265,7 +2265,7 @@ package body Treepr is
for Field_Index in A'Range loop
declare
F : constant Node_Field := A (Field_Index);
- FD : Field_Descriptor renames Node_Field_Descriptors (F);
+ FD : Field_Descriptor renames Field_Descriptors (F);
begin
if FD.Kind in Node_Id_Field | List_Id_Field | Elist_Id_Field
-- For all other kinds of descendants (strings, names, uints
@@ -2293,7 +2293,7 @@ package body Treepr is
for Field_Index in A'Range loop
declare
F : constant Entity_Field := A (Field_Index);
- FD : Field_Descriptor renames Entity_Field_Descriptors (F);
+ FD : Field_Descriptor renames Field_Descriptors (F);
begin
if FD.Kind in Node_Id_Field | List_Id_Field | Elist_Id_Field
then
diff --git a/gcc/ada/types.ads b/gcc/ada/types.ads
index 2caaf50..673f7c6 100644
--- a/gcc/ada/types.ads
+++ b/gcc/ada/types.ads
@@ -61,6 +61,13 @@ package Types is
subtype Nonzero_Int is Int with Predicate => Nonzero_Int /= 0;
+ type Int_64 is range -2 ** 63 .. +2 ** 63 - 1;
+ -- Signed 64-bit integer
+
+ subtype Nat_64 is Int_64 range 0 .. Int_64'Last;
+ subtype Pos_64 is Int_64 range 1 .. Int_64'Last;
+ subtype Nonzero_Int_64 is Int_64 with Predicate => Nonzero_Int_64 /= 0;
+
type Word is mod 2 ** 32;
-- Unsigned 32-bit integer
@@ -991,6 +998,8 @@ package Types is
-- Offset of a node field, in units of the size of the field, which is
-- always a power of 2.
+ subtype Node_Offset is Field_Offset'Base range 1 .. Field_Offset'Base'Last;
+
subtype Slot_Count is Field_Offset;
-- Count of number of slots. Same type as Field_Offset to avoid
-- proliferation of type conversions.
diff --git a/gcc/btfout.c b/gcc/btfout.c
index cdc6c63..a787815 100644
--- a/gcc/btfout.c
+++ b/gcc/btfout.c
@@ -70,7 +70,7 @@ static char btf_info_section_label[MAX_BTF_LABEL_BYTES];
converted to BTF_KIND_VAR type records. Strictly accounts for the index
from the start of the variable type entries, does not include the number
of types emitted prior to the variable records. */
-static hash_map <ctf_dvdef_ref, unsigned int> *btf_var_ids;
+static GTY (()) hash_map <ctf_dvdef_ref, unsigned> *btf_var_ids;
/* Mapping of type IDs from original CTF ID to BTF ID. Types do not map
1-to-1 from CTF to BTF. To avoid polluting the CTF container when updating
@@ -1119,12 +1119,12 @@ btf_finalize (void)
funcs = NULL;
+ btf_var_ids->empty ();
+ btf_var_ids = NULL;
+
free (btf_id_map);
btf_id_map = NULL;
- ggc_free (btf_var_ids);
- btf_var_ids = NULL;
-
ctf_container_ref tu_ctfc = ctf_get_tu_ctfc ();
ctfc_delete_container (tu_ctfc);
tu_ctfc = NULL;
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 9c59035..a6484f4 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,75 @@
+2021-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/102571
+ * c-omp.c (c_finish_omp_atomic): Optimize the case where type has
+ padding, but the non-padding bits are contiguous set of bytes
+ by adjusting the memcmp call arguments instead of emitting
+ __builtin_clear_padding and then comparing all the type's bytes.
+
+2021-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102612
+ * c-cppbuiltin.c (c_cpp_builtins): For -std=c++23 predefine
+ __cpp_constexpr to 202110L rather than 201907L.
+
+2021-10-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * c-common.h (do_warn_array_compare): Declare.
+ * c-warn.c (do_warn_array_compare): New.
+ * c.opt (Warray-compare): New option.
+
+2021-10-02 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-format.c: Remove a test of TARGET_FORMAT_TYPES with
+ NULL, this is not needed.
+
+2021-10-01 Martin Sebor <msebor@redhat.com>
+
+ PR c/102103
+ * c-common.c (decl_with_nonnull_addr_p): Handle members.
+ Check and perform warning suppression.
+ (c_common_truthvalue_conversion): Enhance warning suppression.
+
+2021-10-01 Martin Liska <mliska@suse.cz>
+
+ PR target/102552
+ * c-common.c (parse_optimize_options): decoded_options[0] is
+ used for program name, so merged_decoded_options should also
+ respect that.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+ Richard Biener <rguenther@suse.de>
+
+ PR sanitizer/102515
+ * c-ubsan.c (ubsan_instrument_division): Check the right
+ flag_sanitize_recover bit, depending on which sanitization
+ is done. Sanitize INT_MIN / -1 under SANITIZE_SI_OVERFLOW
+ rather than SANITIZE_DIVIDE. If both SANITIZE_SI_OVERFLOW
+ and SANITIZE_DIVIDE is enabled, neither check is known
+ to be false and flag_sanitize_recover bits for those two
+ aren't the same, emit both __ubsan_handle_divrem_overflow
+ and __ubsan_handle_divrem_overflow_abort calls.
+
+2021-10-01 Martin Liska <mliska@suse.cz>
+
+ * c-common.c (parse_optimize_options): Combine optimize
+ options with what was provided on the command line.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * c-omp.c (c_omp_split_clauses): Also copy
+ OMP_CLAUSE_ORDER_REPRODUCIBLE.
+
+2021-09-27 Martin Liska <mliska@suse.cz>
+
+ * c-opts.c (c_common_init_options_struct): Set also
+ x_flag_default_complex_method.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ * c-omp.c (c_omp_split_clauses): Copy over OMP_CLAUSE_ALLOCATE_ALIGN.
+
2021-09-20 Matthias Kretz <m.kretz@gsi.de>
* c-cppbuiltin.c (c_cpp_builtins_optimize_pragma): Define or
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index c6757f0..32c7e3e 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -3393,14 +3393,16 @@ c_wrap_maybe_const (tree expr, bool non_const)
return expr;
}
-/* Return whether EXPR is a declaration whose address can never be
- NULL. */
+/* Return whether EXPR is a declaration whose address can never be NULL.
+ The address of the first struct member could be NULL only if it were
+ accessed through a NULL pointer, and such an access would be invalid. */
bool
decl_with_nonnull_addr_p (const_tree expr)
{
return (DECL_P (expr)
- && (TREE_CODE (expr) == PARM_DECL
+ && (TREE_CODE (expr) == FIELD_DECL
+ || TREE_CODE (expr) == PARM_DECL
|| TREE_CODE (expr) == LABEL_DECL
|| !DECL_WEAK (expr)));
}
@@ -3488,13 +3490,17 @@ c_common_truthvalue_conversion (location_t location, tree expr)
case ADDR_EXPR:
{
tree inner = TREE_OPERAND (expr, 0);
- if (decl_with_nonnull_addr_p (inner))
+ if (decl_with_nonnull_addr_p (inner)
+ /* Check both EXPR and INNER for suppression. */
+ && !warning_suppressed_p (expr, OPT_Waddress)
+ && !warning_suppressed_p (inner, OPT_Waddress))
{
- /* Common Ada programmer's mistake. */
+ /* Common Ada programmer's mistake. */
warning_at (location,
OPT_Waddress,
"the address of %qD will always evaluate as %<true%>",
inner);
+ suppress_warning (inner, OPT_Waddress);
return truthvalue_true_node;
}
break;
@@ -3627,8 +3633,17 @@ c_common_truthvalue_conversion (location_t location, tree expr)
break;
/* If this isn't narrowing the argument, we can ignore it. */
if (TYPE_PRECISION (totype) >= TYPE_PRECISION (fromtype))
- return c_common_truthvalue_conversion (location,
- TREE_OPERAND (expr, 0));
+ {
+ tree op0 = TREE_OPERAND (expr, 0);
+ if ((TREE_CODE (fromtype) == POINTER_TYPE
+ && TREE_CODE (totype) == INTEGER_TYPE)
+ || warning_suppressed_p (expr, OPT_Waddress))
+ /* Suppress -Waddress for casts to intptr_t, propagating
+ any suppression from the enclosing expression to its
+ operand. */
+ suppress_warning (op0, OPT_Waddress);
+ return c_common_truthvalue_conversion (location, op0);
+ }
}
break;
@@ -5904,9 +5919,23 @@ parse_optimize_options (tree args, bool attr_p)
j++;
}
decoded_options_count = j;
- /* And apply them. */
+
+ /* Merge the decoded options with save_decoded_options. */
+ unsigned save_opt_count = save_opt_decoded_options->length ();
+ unsigned merged_decoded_options_count
+ = save_opt_count + decoded_options_count;
+ cl_decoded_option *merged_decoded_options
+ = XNEWVEC (cl_decoded_option, merged_decoded_options_count);
+
+ /* Note the first decoded_options is used for the program name. */
+ for (unsigned i = 0; i < save_opt_count; ++i)
+ merged_decoded_options[i + 1] = (*save_opt_decoded_options)[i];
+ for (unsigned i = 1; i < decoded_options_count; ++i)
+ merged_decoded_options[save_opt_count + i] = decoded_options[i];
+
+ /* And apply them. */
decode_options (&global_options, &global_options_set,
- decoded_options, decoded_options_count,
+ merged_decoded_options, merged_decoded_options_count,
input_location, global_dc, NULL);
free (decoded_options);
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 849cefa..078730f 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1421,6 +1421,7 @@ extern bool warn_for_restrict (unsigned, tree *, unsigned);
extern void warn_for_address_or_pointer_of_packed_member (tree, tree);
extern void warn_parm_array_mismatch (location_t, tree, tree);
extern void maybe_warn_sizeof_array_div (location_t, tree, tree, tree, tree);
+extern void do_warn_array_compare (location_t, tree_code, tree, tree);
/* Places where an lvalue, or modifiable lvalue, may be required.
Used to select diagnostic messages in lvalue_error and
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index a299273..60e9e05 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -1052,7 +1052,8 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__cpp_init_captures=201803L");
cpp_define (pfile, "__cpp_generic_lambdas=201707L");
cpp_define (pfile, "__cpp_designated_initializers=201707L");
- cpp_define (pfile, "__cpp_constexpr=201907L");
+ if (cxx_dialect <= cxx20)
+ cpp_define (pfile, "__cpp_constexpr=201907L");
cpp_define (pfile, "__cpp_constexpr_in_decltype=201711L");
cpp_define (pfile, "__cpp_conditional_explicit=201806L");
cpp_define (pfile, "__cpp_consteval=201811L");
@@ -1071,6 +1072,7 @@ c_cpp_builtins (cpp_reader *pfile)
/* Set feature test macros for C++23. */
cpp_define (pfile, "__cpp_size_t_suffix=202011L");
cpp_define (pfile, "__cpp_if_consteval=202106L");
+ cpp_define (pfile, "__cpp_constexpr=202110L");
}
if (flag_concepts)
{
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index b4cb765a..ca66c81 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -5150,7 +5150,7 @@ handle_format_attribute (tree *node, tree atname, tree args,
#ifdef TARGET_FORMAT_TYPES
/* If the target provides additional format types, we need to
add them to FORMAT_TYPES at first use. */
- if (TARGET_FORMAT_TYPES != NULL && !dynamic_format_types)
+ if (!dynamic_format_types)
{
dynamic_format_types = XNEWVEC (format_kind_info,
n_format_types + TARGET_N_FORMAT_TYPES);
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index b606cf4..d8b9855 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -379,6 +379,8 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
if (SCALAR_FLOAT_TYPE_P (cmptype) && !test)
{
bool clear_padding = false;
+ HOST_WIDE_INT non_padding_start = 0;
+ HOST_WIDE_INT non_padding_end = 0;
if (BITS_PER_UNIT == 8 && CHAR_BIT == 8)
{
HOST_WIDE_INT sz = int_size_in_bytes (cmptype), i;
@@ -392,6 +394,40 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
clear_padding = true;
break;
}
+ if (clear_padding && buf[i] == 0)
+ {
+ /* Try to optimize. In the common case where
+ non-padding bits are all continuous and start
+ and end at a byte boundary, we can just adjust
+ the memcmp call arguments and don't need to
+ emit __builtin_clear_padding calls. */
+ if (i == 0)
+ {
+ for (i = 0; i < sz; i++)
+ if (buf[i] != 0)
+ break;
+ if (i < sz && buf[i] == (unsigned char) ~0)
+ {
+ non_padding_start = i;
+ for (; i < sz; i++)
+ if (buf[i] != (unsigned char) ~0)
+ break;
+ }
+ else
+ i = 0;
+ }
+ if (i != 0)
+ {
+ non_padding_end = i;
+ for (; i < sz; i++)
+ if (buf[i] != 0)
+ {
+ non_padding_start = 0;
+ non_padding_end = 0;
+ break;
+ }
+ }
+ }
}
tree inttype = NULL_TREE;
if (!clear_padding && tree_fits_uhwi_p (TYPE_SIZE (cmptype)))
@@ -428,12 +464,22 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
tmp2 = build4 (TARGET_EXPR, cmptype, tmp2,
TREE_OPERAND (rhs1, 1), NULL, NULL);
tmp2 = build1 (ADDR_EXPR, pcmptype, tmp2);
+ if (non_padding_start)
+ {
+ tmp1 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp1,
+ size_int (non_padding_start));
+ tmp2 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp2,
+ size_int (non_padding_start));
+ }
tree fndecl = builtin_decl_explicit (BUILT_IN_MEMCMP);
rhs1 = build_call_expr_loc (loc, fndecl, 3, tmp1, tmp2,
- TYPE_SIZE_UNIT (cmptype));
+ non_padding_end
+ ? size_int (non_padding_end
+ - non_padding_start)
+ : TYPE_SIZE_UNIT (cmptype));
rhs1 = build2 (EQ_EXPR, boolean_type_node, rhs1,
integer_zero_node);
- if (clear_padding)
+ if (clear_padding && non_padding_end == 0)
{
fndecl = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING);
tree cp1 = build_call_expr_loc (loc, fndecl, 1, tmp1);
@@ -2128,6 +2174,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
OMP_CLAUSE_ORDER);
OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
= OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
+ = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
}
@@ -2139,6 +2187,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
OMP_CLAUSE_ORDER);
OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
= OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
+ = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
s = C_OMP_CLAUSE_SPLIT_SIMD;
@@ -2511,6 +2561,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
= OMP_CLAUSE_DECL (clauses);
OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
= OMP_CLAUSE_ALLOCATE_ALLOCATOR (clauses);
+ OMP_CLAUSE_ALLOCATE_ALIGN (c)
+ = OMP_CLAUSE_ALLOCATE_ALIGN (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[s];
cclauses[s] = c;
has_dup_allocate = true;
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index fdde082..3eaab5e 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -222,6 +222,7 @@ c_common_init_options_struct (struct gcc_options *opts)
/* By default, C99-like requirements for complex multiply and divide. */
opts->x_flag_complex_method = 2;
+ opts->x_flag_default_complex_method = opts->x_flag_complex_method;
}
/* Common initialization before calling option handlers. */
diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c
index 12a7bca..a4509c6 100644
--- a/gcc/c-family/c-ubsan.c
+++ b/gcc/c-family/c-ubsan.c
@@ -39,8 +39,9 @@ along with GCC; see the file COPYING3. If not see
tree
ubsan_instrument_division (location_t loc, tree op0, tree op1)
{
- tree t, tt;
+ tree t, tt, x = NULL_TREE;
tree type = TREE_TYPE (op0);
+ enum sanitize_code flag = SANITIZE_DIVIDE;
/* At this point both operands should have the same type,
because they are already converted to RESULT_TYPE.
@@ -58,24 +59,42 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
op1, build_int_cst (type, 0));
else if (TREE_CODE (type) == REAL_TYPE
&& sanitize_flags_p (SANITIZE_FLOAT_DIVIDE))
- t = fold_build2 (EQ_EXPR, boolean_type_node,
- op1, build_real (type, dconst0));
+ {
+ t = fold_build2 (EQ_EXPR, boolean_type_node,
+ op1, build_real (type, dconst0));
+ flag = SANITIZE_FLOAT_DIVIDE;
+ }
else
- return NULL_TREE;
+ t = NULL_TREE;
/* We check INT_MIN / -1 only for signed types. */
if (TREE_CODE (type) == INTEGER_TYPE
- && sanitize_flags_p (SANITIZE_DIVIDE)
+ && sanitize_flags_p (SANITIZE_SI_OVERFLOW)
&& !TYPE_UNSIGNED (type))
{
- tree x;
tt = fold_build2 (EQ_EXPR, boolean_type_node, unshare_expr (op1),
build_int_cst (type, -1));
x = fold_build2 (EQ_EXPR, boolean_type_node, op0,
TYPE_MIN_VALUE (type));
x = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, x, tt);
- t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x);
+ if (t == NULL_TREE || integer_zerop (t))
+ {
+ t = x;
+ x = NULL_TREE;
+ flag = SANITIZE_SI_OVERFLOW;
+ }
+ else if (flag_sanitize_undefined_trap_on_error
+ || (((flag_sanitize_recover & SANITIZE_DIVIDE) == 0)
+ == ((flag_sanitize_recover & SANITIZE_SI_OVERFLOW) == 0)))
+ {
+ t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x);
+ x = NULL_TREE;
+ }
+ else if (integer_zerop (x))
+ x = NULL_TREE;
}
+ else if (t == NULL_TREE)
+ return NULL_TREE;
/* If the condition was folded to 0, no need to instrument
this expression. */
@@ -95,7 +114,7 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
NULL_TREE);
data = build_fold_addr_expr_loc (loc, data);
enum built_in_function bcode
- = (flag_sanitize_recover & SANITIZE_DIVIDE)
+ = (flag_sanitize_recover & flag)
? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
: BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
tt = builtin_decl_explicit (bcode);
@@ -103,8 +122,20 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
op1 = unshare_expr (op1);
tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
ubsan_encode_value (op1));
+ if (x)
+ {
+ bcode = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
+ ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
+ : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
+ tree xt = builtin_decl_explicit (bcode);
+ op0 = unshare_expr (op0);
+ op1 = unshare_expr (op1);
+ xt = build_call_expr_loc (loc, xt, 3, data, ubsan_encode_value (op0),
+ ubsan_encode_value (op1));
+ x = fold_build3 (COND_EXPR, void_type_node, x, xt, void_node);
+ }
}
- t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
+ t = fold_build3 (COND_EXPR, void_type_node, t, tt, x ? x : void_node);
return t;
}
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index 84ad663..99cde4a 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -3726,3 +3726,35 @@ maybe_warn_sizeof_array_div (location_t loc, tree arr, tree arr_type,
}
}
}
+
+/* Warn about C++20 [depr.array.comp] array comparisons: "Equality
+ and relational comparisons between two operands of array type are
+ deprecated." We also warn in C and earlier C++ standards. CODE is
+ the code for this comparison, OP0 and OP1 are the operands. */
+
+void
+do_warn_array_compare (location_t location, tree_code code, tree op0, tree op1)
+{
+ STRIP_NOPS (op0);
+ STRIP_NOPS (op1);
+ if (TREE_CODE (op0) == ADDR_EXPR)
+ op0 = TREE_OPERAND (op0, 0);
+ if (TREE_CODE (op1) == ADDR_EXPR)
+ op1 = TREE_OPERAND (op1, 0);
+
+ auto_diagnostic_group d;
+ if (warning_at (location, OPT_Warray_compare,
+ (c_dialect_cxx () && cxx_dialect >= cxx20)
+ ? G_("comparison between two arrays is deprecated in C++20")
+ : G_("comparison between two arrays")))
+ {
+ /* C doesn't allow +arr. */
+ if (c_dialect_cxx ())
+ inform (location, "use unary %<+%> which decays operands to pointers "
+ "or %<&%D[0] %s &%D[0]%> to compare the addresses",
+ op0, op_symbol_code (code), op1);
+ else
+ inform (location, "use %<&%D[0] %s &%D[0]%> to compare the addresses",
+ op0, op_symbol_code (code), op1);
+ }
+}
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 9c151d1..06457ac 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -350,6 +350,10 @@ Warray-bounds=
LangEnabledBy(C ObjC C++ LTO ObjC++,Wall,1,0)
; in common.opt
+Warray-compare
+C ObjC C++ ObjC++ Var(warn_array_compare) Warning LangEnabledBy(C ObjC C++ ObjC++, Wall)
+Warn about comparisons between two operands of array type.
+
Warray-parameter
C ObjC C++ ObjC++ Warning Alias(Warray-parameter=, 2, 0)
Warn about mismatched declarations of array parameters and unsafe accesses to them.
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 794cbe7..24096bb 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,47 @@
+2021-10-05 Richard Biener <rguenther@suse.de>
+
+ PR c/102605
+ * gimple-parser.c (c_parser_gimple_postfix_expression):
+ Accept more address _Literals.
+
+2021-10-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * c-typeck.c (parser_build_binary_op): Call do_warn_array_compare.
+
+2021-10-01 Martin Sebor <msebor@redhat.com>
+
+ PR c/102103
+ * c-typeck.c (maybe_warn_for_null_address): New function.
+ (build_binary_op): Call it.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+ Richard Biener <rguenther@suse.de>
+
+ PR sanitizer/102515
+ * c-typeck.c (build_binary_op): Call ubsan_instrument_division
+ for division even for SANITIZE_SI_OVERFLOW.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_clause_order): Set
+ OMP_CLAUSE_ORDER_REPRODUCIBLE for explicit reproducible: modifier.
+
+2021-09-28 Andrew Pinski <apinski@marvell.com>
+
+ PR c/32122
+ * c-parser.c (c_parser_statement_after_labels): Pass
+ the c_expr instead of the tree to c_finish_goto_ptr.
+ * c-typeck.c (c_finish_goto_ptr): Change the second
+ argument type to c_expr.
+ * c-tree.h (c_finish_goto_ptr): Likewise.
+ Error out if the expression was not of a pointer type.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_clause_allocate): Parse allocate clause
+ modifiers.
+
2021-09-18 Jakub Jelinek <jakub@redhat.com>
* c-parser.c (c_parser_omp_clause_order): Parse unconstrained
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index fb1399e..a66f43f 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -6141,7 +6141,7 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
c_parser_consume_token (parser);
val = c_parser_expression (parser);
val = convert_lvalue_to_rvalue (loc, val, false, true);
- stmt = c_finish_goto_ptr (loc, val.value);
+ stmt = c_finish_goto_ptr (loc, val);
}
else
c_parser_error (parser, "expected identifier or %<*%>");
@@ -14626,6 +14626,7 @@ c_parser_omp_clause_order (c_parser *parser, tree list)
tree c;
const char *p;
bool unconstrained = false;
+ bool reproducible = false;
matching_parens parens;
if (!parens.require_open (parser))
@@ -14636,7 +14637,9 @@ c_parser_omp_clause_order (c_parser *parser, tree list)
p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
if (strcmp (p, "unconstrained") == 0)
unconstrained = true;
- else if (strcmp (p, "reproducible") != 0)
+ else if (strcmp (p, "reproducible") == 0)
+ reproducible = true;
+ else
{
c_parser_error (parser, "expected %<reproducible%> or "
"%<unconstrained%>");
@@ -14661,6 +14664,7 @@ c_parser_omp_clause_order (c_parser *parser, tree list)
check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order");
c = build_omp_clause (loc, OMP_CLAUSE_ORDER);
OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained;
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible;
OMP_CLAUSE_CHAIN (c) = list;
return c;
@@ -15305,7 +15309,15 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list)
/* OpenMP 5.0:
allocate ( variable-list )
- allocate ( expression : variable-list ) */
+ allocate ( expression : variable-list )
+
+ OpenMP 5.1:
+ allocate ( allocator-modifier : variable-list )
+ allocate ( allocator-modifier , allocator-modifier : variable-list )
+
+ allocator-modifier:
+ allocator ( expression )
+ align ( expression ) */
static tree
c_parser_omp_clause_allocate (c_parser *parser, tree list)
@@ -15313,6 +15325,7 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list)
location_t clause_loc = c_parser_peek_token (parser)->location;
tree nl, c;
tree allocator = NULL_TREE;
+ tree align = NULL_TREE;
matching_parens parens;
if (!parens.require_open (parser))
@@ -15323,17 +15336,128 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list)
|| (c_parser_peek_2nd_token (parser)->type != CPP_COMMA
&& c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN))
{
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- allocator = expr.value;
- allocator = c_fully_fold (allocator, false, NULL);
- tree orig_type
- = expr.original_type ? expr.original_type : TREE_TYPE (allocator);
- orig_type = TYPE_MAIN_VARIANT (orig_type);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
- || TREE_CODE (orig_type) != ENUMERAL_TYPE
- || TYPE_NAME (orig_type) != get_identifier ("omp_allocator_handle_t"))
+ bool has_modifiers = false;
+ tree orig_type = NULL_TREE;
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
+ {
+ unsigned int n = 3;
+ const char *p
+ = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if ((strcmp (p, "allocator") == 0 || strcmp (p, "align") == 0)
+ && c_parser_check_balanced_raw_token_sequence (parser, &n)
+ && (c_parser_peek_nth_token_raw (parser, n)->type
+ == CPP_CLOSE_PAREN))
+ {
+ if (c_parser_peek_nth_token_raw (parser, n + 1)->type
+ == CPP_COLON)
+ has_modifiers = true;
+ else if (c_parser_peek_nth_token_raw (parser, n + 1)->type
+ == CPP_COMMA
+ && (c_parser_peek_nth_token_raw (parser, n + 2)->type
+ == CPP_NAME)
+ && (c_parser_peek_nth_token_raw (parser, n + 3)->type
+ == CPP_OPEN_PAREN))
+ {
+ c_token *tok = c_parser_peek_nth_token_raw (parser, n + 2);
+ const char *q = IDENTIFIER_POINTER (tok->value);
+ n += 4;
+ if ((strcmp (q, "allocator") == 0
+ || strcmp (q, "align") == 0)
+ && c_parser_check_balanced_raw_token_sequence (parser,
+ &n)
+ && (c_parser_peek_nth_token_raw (parser, n)->type
+ == CPP_CLOSE_PAREN)
+ && (c_parser_peek_nth_token_raw (parser, n + 1)->type
+ == CPP_COLON))
+ has_modifiers = true;
+ }
+ }
+ if (has_modifiers)
+ {
+ c_parser_consume_token (parser);
+ matching_parens parens2;;
+ parens2.require_open (parser);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ if (strcmp (p, "allocator") == 0)
+ {
+ allocator = expr.value;
+ allocator = c_fully_fold (allocator, false, NULL);
+ orig_type = expr.original_type
+ ? expr.original_type : TREE_TYPE (allocator);
+ orig_type = TYPE_MAIN_VARIANT (orig_type);
+ }
+ else
+ {
+ align = expr.value;
+ align = c_fully_fold (align, false, NULL);
+ }
+ parens2.skip_until_found_close (parser);
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ c_parser_consume_token (parser);
+ c_token *tok = c_parser_peek_token (parser);
+ const char *q = "";
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ q = IDENTIFIER_POINTER (tok->value);
+ if (strcmp (q, "allocator") != 0 && strcmp (q, "align") != 0)
+ {
+ c_parser_error (parser, "expected %<allocator%> or "
+ "%<align%>");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ else if (strcmp (p, q) == 0)
+ {
+ error_at (tok->location, "duplicate %qs modifier", p);
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ c_parser_consume_token (parser);
+ if (!parens2.require_open (parser))
+ {
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ expr_loc = c_parser_peek_token (parser)->location;
+ expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
+ true);
+ if (strcmp (q, "allocator") == 0)
+ {
+ allocator = expr.value;
+ allocator = c_fully_fold (allocator, false, NULL);
+ orig_type = expr.original_type
+ ? expr.original_type : TREE_TYPE (allocator);
+ orig_type = TYPE_MAIN_VARIANT (orig_type);
+ }
+ else
+ {
+ align = expr.value;
+ align = c_fully_fold (align, false, NULL);
+ }
+ parens2.skip_until_found_close (parser);
+ }
+ }
+ }
+ if (!has_modifiers)
+ {
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ allocator = expr.value;
+ allocator = c_fully_fold (allocator, false, NULL);
+ orig_type = expr.original_type
+ ? expr.original_type : TREE_TYPE (allocator);
+ orig_type = TYPE_MAIN_VARIANT (orig_type);
+ }
+ if (allocator
+ && (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
+ || TREE_CODE (orig_type) != ENUMERAL_TYPE
+ || (TYPE_NAME (orig_type)
+ != get_identifier ("omp_allocator_handle_t"))))
{
error_at (clause_loc, "%<allocate%> clause allocator expression "
"has type %qT rather than "
@@ -15341,6 +15465,16 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list)
TREE_TYPE (allocator));
allocator = NULL_TREE;
}
+ if (align
+ && (!INTEGRAL_TYPE_P (TREE_TYPE (align))
+ || !tree_fits_uhwi_p (align)
+ || !integer_pow2p (align)))
+ {
+ error_at (clause_loc, "%<allocate%> clause %<align%> modifier "
+ "argument needs to be positive constant "
+ "power of two integer expression");
+ align = NULL_TREE;
+ }
if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
{
parens.skip_until_found_close (parser);
@@ -15351,9 +15485,12 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list)
nl = c_parser_omp_variable_list (parser, clause_loc,
OMP_CLAUSE_ALLOCATE, list);
- if (allocator)
+ if (allocator || align)
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+ {
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+ OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
+ }
parens.skip_until_found_close (parser);
return nl;
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index d50d0cb..a046c6b 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -746,7 +746,7 @@ extern tree c_finish_expr_stmt (location_t, tree);
extern tree c_finish_return (location_t, tree, tree);
extern tree c_finish_bc_stmt (location_t, tree, bool);
extern tree c_finish_goto_label (location_t, tree);
-extern tree c_finish_goto_ptr (location_t, tree);
+extern tree c_finish_goto_ptr (location_t, c_expr val);
extern tree c_expr_to_decl (tree, bool *, bool *);
extern tree c_finish_omp_construct (location_t, enum tree_code, tree, tree);
extern tree c_finish_oacc_data (location_t, tree, tree);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 49d1bb0..0aac978 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -3940,7 +3940,14 @@ parser_build_binary_op (location_t location, enum tree_code code,
else if (TREE_CODE_CLASS (code) == tcc_comparison
&& (code1 == STRING_CST || code2 == STRING_CST))
warning_at (location, OPT_Waddress,
- "comparison with string literal results in unspecified behavior");
+ "comparison with string literal results in unspecified "
+ "behavior");
+
+ if (warn_array_compare
+ && TREE_CODE_CLASS (code) == tcc_comparison
+ && TREE_CODE (type1) == ARRAY_TYPE
+ && TREE_CODE (type2) == ARRAY_TYPE)
+ do_warn_array_compare (location, code, arg1.value, arg2.value);
if (TREE_OVERFLOW_P (result.value)
&& !TREE_OVERFLOW_P (arg1.value)
@@ -4961,6 +4968,10 @@ lvalue_p (const_tree ref)
case STRING_CST:
return true;
+ case MEM_REF:
+ case TARGET_MEM_REF:
+ /* MEM_REFs can appear from -fgimple parsing or folding, so allow them
+ here as well. */
case INDIRECT_REF:
case ARRAY_REF:
case VAR_DECL:
@@ -10783,10 +10794,19 @@ c_finish_goto_label (location_t loc, tree label)
the GOTO. */
tree
-c_finish_goto_ptr (location_t loc, tree expr)
+c_finish_goto_ptr (location_t loc, c_expr val)
{
+ tree expr = val.value;
tree t;
pedwarn (loc, OPT_Wpedantic, "ISO C forbids %<goto *expr;%>");
+ if (expr != error_mark_node
+ && !POINTER_TYPE_P (TREE_TYPE (expr))
+ && !null_pointer_constant_p (expr))
+ {
+ error_at (val.get_location (),
+ "computed goto must be pointer type");
+ expr = build_zero_cst (ptr_type_node);
+ }
expr = c_fully_fold (expr, false, NULL);
expr = convert (ptr_type_node, expr);
t = build1 (GOTO_EXPR, void_type_node, expr);
@@ -11545,6 +11565,110 @@ build_vec_cmp (tree_code code, tree type,
return build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec);
}
+/* Possibly warn about an address of OP never being NULL in a comparison
+ operation CODE involving null. */
+
+static void
+maybe_warn_for_null_address (location_t loc, tree op, tree_code code)
+{
+ if (!warn_address || warning_suppressed_p (op, OPT_Waddress))
+ return;
+
+ if (TREE_CODE (op) == NOP_EXPR)
+ {
+ /* Allow casts to intptr_t to suppress the warning. */
+ tree type = TREE_TYPE (op);
+ if (TREE_CODE (type) == INTEGER_TYPE)
+ return;
+ op = TREE_OPERAND (op, 0);
+ }
+
+ if (TREE_CODE (op) == POINTER_PLUS_EXPR)
+ {
+ /* Allow a cast to void* to suppress the warning. */
+ tree type = TREE_TYPE (TREE_TYPE (op));
+ if (VOID_TYPE_P (type))
+ return;
+
+ /* Adding any value to a null pointer, including zero, is undefined
+ in C. This includes the expression &p[0] where p is the null
+ pointer, although &p[0] will have been folded to p by this point
+ and so not diagnosed. */
+ if (code == EQ_EXPR)
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<false%> "
+ "for the pointer operand in %qE must not be NULL",
+ op);
+ else
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<true%> "
+ "for the pointer operand in %qE must not be NULL",
+ op);
+
+ return;
+ }
+
+ if (TREE_CODE (op) != ADDR_EXPR)
+ return;
+
+ op = TREE_OPERAND (op, 0);
+
+ if (TREE_CODE (op) == IMAGPART_EXPR
+ || TREE_CODE (op) == REALPART_EXPR)
+ {
+ /* The address of either complex part may not be null. */
+ if (code == EQ_EXPR)
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<false%> "
+ "for the address of %qE will never be NULL",
+ op);
+ else
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<true%> "
+ "for the address of %qE will never be NULL",
+ op);
+ return;
+ }
+
+ /* Set to true in the loop below if OP dereferences is operand.
+ In such a case the ultimate target need not be a decl for
+ the null [in]equality test to be constant. */
+ bool deref = false;
+
+ /* Get the outermost array or object, or member. */
+ while (handled_component_p (op))
+ {
+ if (TREE_CODE (op) == COMPONENT_REF)
+ {
+ /* Get the member (its address is never null). */
+ op = TREE_OPERAND (op, 1);
+ break;
+ }
+
+ /* Get the outer array/object to refer to in the warning. */
+ op = TREE_OPERAND (op, 0);
+ deref = true;
+ }
+
+ if ((!deref && !decl_with_nonnull_addr_p (op))
+ || from_macro_expansion_at (loc))
+ return;
+
+ if (code == EQ_EXPR)
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<false%> "
+ "for the address of %qE will never be NULL",
+ op);
+ else
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<true%> "
+ "for the address of %qE will never be NULL",
+ op);
+
+ if (DECL_P (op))
+ inform (DECL_SOURCE_LOCATION (op), "%qD declared here", op);
+}
+
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
LOCATION is the operator's location.
@@ -12180,44 +12304,12 @@ build_binary_op (location_t location, enum tree_code code,
short_compare = 1;
else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
{
- if (TREE_CODE (op0) == ADDR_EXPR
- && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0))
- && !from_macro_expansion_at (location))
- {
- if (code == EQ_EXPR)
- warning_at (location,
- OPT_Waddress,
- "the comparison will always evaluate as %<false%> "
- "for the address of %qD will never be NULL",
- TREE_OPERAND (op0, 0));
- else
- warning_at (location,
- OPT_Waddress,
- "the comparison will always evaluate as %<true%> "
- "for the address of %qD will never be NULL",
- TREE_OPERAND (op0, 0));
- }
+ maybe_warn_for_null_address (location, op0, code);
result_type = type0;
}
else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
{
- if (TREE_CODE (op1) == ADDR_EXPR
- && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0))
- && !from_macro_expansion_at (location))
- {
- if (code == EQ_EXPR)
- warning_at (location,
- OPT_Waddress,
- "the comparison will always evaluate as %<false%> "
- "for the address of %qD will never be NULL",
- TREE_OPERAND (op1, 0));
- else
- warning_at (location,
- OPT_Waddress,
- "the comparison will always evaluate as %<true%> "
- "for the address of %qD will never be NULL",
- TREE_OPERAND (op1, 0));
- }
+ maybe_warn_for_null_address (location, op1, code);
result_type = type1;
}
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
@@ -12724,7 +12816,9 @@ build_binary_op (location_t location, enum tree_code code,
}
if (sanitize_flags_p ((SANITIZE_SHIFT
- | SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
+ | SANITIZE_DIVIDE
+ | SANITIZE_FLOAT_DIVIDE
+ | SANITIZE_SI_OVERFLOW))
&& current_function_decl != NULL_TREE
&& (doing_div_or_mod || doing_shift)
&& !require_constant_value)
@@ -12735,7 +12829,8 @@ build_binary_op (location_t location, enum tree_code code,
op0 = c_fully_fold (op0, false, NULL);
op1 = c_fully_fold (op1, false, NULL);
if (doing_div_or_mod && (sanitize_flags_p ((SANITIZE_DIVIDE
- | SANITIZE_FLOAT_DIVIDE))))
+ | SANITIZE_FLOAT_DIVIDE
+ | SANITIZE_SI_OVERFLOW))))
instrument_expr = ubsan_instrument_division (location, op0, op1);
else if (doing_shift && sanitize_flags_p (SANITIZE_SHIFT))
instrument_expr = ubsan_instrument_shift (location, code, op0, op1);
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index c8d9db6..c43ee38 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -1622,16 +1622,20 @@ c_parser_gimple_postfix_expression (gimple_parser &parser)
tree val = c_parser_gimple_postfix_expression (parser).value;
if (! val
|| val == error_mark_node
- || (!CONSTANT_CLASS_P (val)
- && !(addr_p
- && (TREE_CODE (val) == STRING_CST
- || DECL_P (val)))))
+ || (!CONSTANT_CLASS_P (val) && !addr_p))
{
c_parser_error (parser, "invalid _Literal");
return expr;
}
if (addr_p)
- val = build1 (ADDR_EXPR, type, val);
+ {
+ val = build1 (ADDR_EXPR, type, val);
+ if (!is_gimple_invariant_address (val))
+ {
+ c_parser_error (parser, "invalid _Literal");
+ return expr;
+ }
+ }
if (neg_p)
{
val = const_unop (NEGATE_EXPR, TREE_TYPE (val), val);
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 7b1e1ba..82fc505 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -3239,7 +3239,8 @@ pass_jump::execute (function *)
if (dump_file)
dump_flow_info (dump_file, dump_flags);
cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0)
- | (flag_thread_jumps ? CLEANUP_THREADING : 0));
+ | (flag_thread_jumps && flag_expensive_optimizations
+ ? CLEANUP_THREADING : 0));
return 0;
}
@@ -3274,7 +3275,10 @@ public:
{}
/* opt_pass methods: */
- virtual bool gate (function *) { return flag_thread_jumps; }
+ virtual bool gate (function *)
+ {
+ return flag_thread_jumps && flag_expensive_optimizations;
+ }
virtual unsigned int execute (function *);
}; // class pass_jump_after_combine
diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
index 50b9b17..6446e16 100644
--- a/gcc/cfghooks.c
+++ b/gcc/cfghooks.c
@@ -161,6 +161,12 @@ verify_flow_info (void)
err = 1;
}
+ if (bb->flags & ~cfun->cfg->bb_flags_allocated)
+ {
+ error ("verify_flow_info: unallocated flag set on BB %d", bb->index);
+ err = 1;
+ }
+
FOR_EACH_EDGE (e, ei, bb->succs)
{
if (last_visited [e->dest->index] == bb)
@@ -202,6 +208,13 @@ verify_flow_info (void)
err = 1;
}
+ if (e->flags & ~cfun->cfg->edge_flags_allocated)
+ {
+ error ("verify_flow_info: unallocated edge flag set on %d -> %d",
+ e->src->index, e->dest->index);
+ err = 1;
+ }
+
edge_checksum[e->dest->index] += (size_t) e;
}
if (n_fallthru > 1)
diff --git a/gcc/common.opt b/gcc/common.opt
index b921f5e..a9644ca 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -59,6 +59,9 @@ enum incremental_link flag_incremental_link = INCREMENTAL_LINK_NONE
Variable
int flag_complex_method = 1
+Variable
+int flag_default_complex_method = 1
+
; Language specific warning pass for unused results.
Variable
bool flag_warn_unused_result = false
diff --git a/gcc/common/config/avr/avr-common.c b/gcc/common/config/avr/avr-common.c
index 6486659..a6939ad 100644
--- a/gcc/common/config/avr/avr-common.c
+++ b/gcc/common/config/avr/avr-common.c
@@ -77,7 +77,8 @@ static const struct default_options avr_option_optimization_table[] =
static bool
avr_handle_option (struct gcc_options *opts, struct gcc_options*,
- const struct cl_decoded_option *decoded, location_t loc)
+ const struct cl_decoded_option *decoded,
+ location_t loc ATTRIBUTE_UNUSED)
{
int value = decoded->value;
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 498c51e..aa5bd5d 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -1531,7 +1531,6 @@ bpf-*-*)
use_collect2=no
extra_headers="bpf-helpers.h"
use_gcc_stdint=provide
- extra_headers="coreout.h"
extra_objs="coreout.o"
target_gtfiles="$target_gtfiles \$(srcdir)/config/bpf/coreout.c"
;;
diff --git a/gcc/config.in b/gcc/config.in
index 61cafe4..b5bec39 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1463,30 +1463,66 @@
#endif
-/* Define if your assembler allows -mattr=+sram-ecc for fiji. */
+/* Define if your assembler expects amdgcn_target gfx908+xnack syntax. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_ASM_V3_SYNTAX
+#endif
+
+
+/* Define if your assembler expects amdgcn_target gfx908:xnack+ syntax. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_ASM_V4_SYNTAX
+#endif
+
+
+/* Define if your assembler allows -mattr=+sramecc for fiji. */
#ifndef USED_FOR_TARGET
#undef HAVE_GCN_SRAM_ECC_FIJI
#endif
-/* Define if your assembler allows -mattr=+sram-ecc for gfx900. */
+/* Define if your assembler allows -mattr=+sramecc for gfx900. */
#ifndef USED_FOR_TARGET
#undef HAVE_GCN_SRAM_ECC_GFX900
#endif
-/* Define if your assembler allows -mattr=+sram-ecc for gfx906. */
+/* Define if your assembler allows -mattr=+sramecc for gfx906. */
#ifndef USED_FOR_TARGET
#undef HAVE_GCN_SRAM_ECC_GFX906
#endif
-/* Define if your assembler allows -mattr=+sram-ecc for gfx908. */
+/* Define if your assembler allows -mattr=+sramecc for gfx908. */
#ifndef USED_FOR_TARGET
#undef HAVE_GCN_SRAM_ECC_GFX908
#endif
+/* Define if your assembler allows -mattr=+xnack for fiji. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_FIJI
+#endif
+
+
+/* Define if your assembler allows -mattr=+xnack for gfx900. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_GFX900
+#endif
+
+
+/* Define if your assembler allows -mattr=+xnack for gfx906. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_GFX906
+#endif
+
+
+/* Define if your assembler allows -mattr=+xnack for gfx908. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_GFX908
+#endif
+
+
/* Define to 1 if you have the `getchar_unlocked' function. */
#ifndef USED_FOR_TARGET
#undef HAVE_GETCHAR_UNLOCKED
diff --git a/gcc/config/aarch64/aarch64-arches.def b/gcc/config/aarch64/aarch64-arches.def
index b749727..a3b32e0 100644
--- a/gcc/config/aarch64/aarch64-arches.def
+++ b/gcc/config/aarch64/aarch64-arches.def
@@ -37,6 +37,8 @@ AARCH64_ARCH("armv8.3-a", generic, 8_3A, 8, AARCH64_FL_FOR_ARCH8_3)
AARCH64_ARCH("armv8.4-a", generic, 8_4A, 8, AARCH64_FL_FOR_ARCH8_4)
AARCH64_ARCH("armv8.5-a", generic, 8_5A, 8, AARCH64_FL_FOR_ARCH8_5)
AARCH64_ARCH("armv8.6-a", generic, 8_6A, 8, AARCH64_FL_FOR_ARCH8_6)
+AARCH64_ARCH("armv8.7-a", generic, 8_7A, 8, AARCH64_FL_FOR_ARCH8_7)
AARCH64_ARCH("armv8-r", generic, 8R , 8, AARCH64_FL_FOR_ARCH8_R)
+AARCH64_ARCH("armv9-a", generic, 9A , 9, AARCH64_FL_FOR_ARCH9)
#undef AARCH64_ARCH
diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 119f67d..1a507ea 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -182,6 +182,10 @@ static enum aarch64_type_qualifiers
aarch64_types_binopp_qualifiers[SIMD_MAX_BUILTIN_ARGS]
= { qualifier_poly, qualifier_poly, qualifier_poly };
#define TYPES_BINOPP (aarch64_types_binopp_qualifiers)
+static enum aarch64_type_qualifiers
+aarch64_types_binop_ppu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+ = { qualifier_poly, qualifier_poly, qualifier_unsigned };
+#define TYPES_BINOP_PPU (aarch64_types_binop_ppu_qualifiers)
static enum aarch64_type_qualifiers
aarch64_types_ternop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
@@ -207,6 +211,10 @@ aarch64_types_ternopu_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
qualifier_unsigned, qualifier_immediate };
#define TYPES_TERNOPUI (aarch64_types_ternopu_imm_qualifiers)
static enum aarch64_type_qualifiers
+aarch64_types_ternop_sssu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+ = { qualifier_none, qualifier_none, qualifier_none, qualifier_unsigned };
+#define TYPES_TERNOP_SSSU (aarch64_types_ternop_sssu_qualifiers)
+static enum aarch64_type_qualifiers
aarch64_types_ternop_ssus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
= { qualifier_none, qualifier_none, qualifier_unsigned, qualifier_none };
#define TYPES_TERNOP_SSUS (aarch64_types_ternop_ssus_qualifiers)
@@ -214,6 +222,10 @@ static enum aarch64_type_qualifiers
aarch64_types_ternop_suss_qualifiers[SIMD_MAX_BUILTIN_ARGS]
= { qualifier_none, qualifier_unsigned, qualifier_none, qualifier_none };
#define TYPES_TERNOP_SUSS (aarch64_types_ternop_suss_qualifiers)
+static enum aarch64_type_qualifiers
+aarch64_types_binop_pppu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+ = { qualifier_poly, qualifier_poly, qualifier_poly, qualifier_unsigned };
+#define TYPES_TERNOP_PPPU (aarch64_types_binop_pppu_qualifiers)
static enum aarch64_type_qualifiers
diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
index b2aa167..77da310 100644
--- a/gcc/config/aarch64/aarch64-cores.def
+++ b/gcc/config/aarch64/aarch64-cores.def
@@ -162,4 +162,13 @@ AARCH64_CORE("cortex-a76.cortex-a55", cortexa76cortexa55, cortexa53, 8_2A, AAR
/* Armv8-R Architecture Processors. */
AARCH64_CORE("cortex-r82", cortexr82, cortexa53, 8R, AARCH64_FL_FOR_ARCH8_R, cortexa53, 0x41, 0xd15, -1)
+/* Armv9.0-A Architecture Processors. */
+
+/* Arm ('A') cores. */
+AARCH64_CORE("cortex-a510", cortexa510, cortexa55, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, cortexa53, 0x41, 0xd46, -1)
+
+AARCH64_CORE("cortex-a710", cortexa710, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, neoversen2, 0x41, 0xd47, -1)
+
+AARCH64_CORE("cortex-x2", cortexx2, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, neoversen2, 0x41, 0xd48, -1)
+
#undef AARCH64_CORE
diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
index 579328c..b61f1df 100644
--- a/gcc/config/aarch64/aarch64-option-extensions.def
+++ b/gcc/config/aarch64/aarch64-option-extensions.def
@@ -232,4 +232,7 @@ AARCH64_OPT_EXTENSION("flagm", AARCH64_FL_FLAGM, 0, 0, false, "flagm")
/* Enabling/Disabling "pauth" only changes "pauth". */
AARCH64_OPT_EXTENSION("pauth", AARCH64_FL_PAUTH, 0, 0, false, "paca pacg")
+/* Enabling/Disabling "ls64" only changes "ls64". */
+AARCH64_OPT_EXTENSION("ls64", AARCH64_FL_LS64, 0, 0, false, "")
+
#undef AARCH64_OPT_EXTENSION
diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def b/gcc/config/aarch64/aarch64-simd-builtins.def
index 402453a..35dc075 100644
--- a/gcc/config/aarch64/aarch64-simd-builtins.def
+++ b/gcc/config/aarch64/aarch64-simd-builtins.def
@@ -721,6 +721,8 @@
/* Implemented by aarch64_qtbl1<mode>. */
VAR2 (BINOP, qtbl1, 0, NONE, v8qi, v16qi)
VAR2 (BINOPU, qtbl1, 0, NONE, v8qi, v16qi)
+ VAR2 (BINOP_PPU, qtbl1, 0, NONE, v8qi, v16qi)
+ VAR2 (BINOP_SSU, qtbl1, 0, NONE, v8qi, v16qi)
/* Implemented by aarch64_qtbl2<mode>. */
VAR2 (BINOP, qtbl2, 0, NONE, v8qi, v16qi)
@@ -734,6 +736,8 @@
/* Implemented by aarch64_qtbx1<mode>. */
VAR2 (TERNOP, qtbx1, 0, NONE, v8qi, v16qi)
VAR2 (TERNOPU, qtbx1, 0, NONE, v8qi, v16qi)
+ VAR2 (TERNOP_PPPU, qtbx1, 0, NONE, v8qi, v16qi)
+ VAR2 (TERNOP_SSSU, qtbx1, 0, NONE, v8qi, v16qi)
/* Implemented by aarch64_qtbx2<mode>. */
VAR2 (TERNOP, qtbx2, 0, NONE, v8qi, v16qi)
diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md
index e491c29..12be913 100644
--- a/gcc/config/aarch64/aarch64-tune.md
+++ b/gcc/config/aarch64/aarch64-tune.md
@@ -1,5 +1,5 @@
;; -*- buffer-read-only: t -*-
;; Generated automatically by gentune.sh from aarch64-cores.def
(define_attr "tune"
- "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,ares,neoversen1,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,tsv110,thunderx3t110,zeus,neoversev1,neoverse512tvb,saphira,neoversen2,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82"
+ "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,ares,neoversen1,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,tsv110,thunderx3t110,zeus,neoversev1,neoverse512tvb,saphira,neoversen2,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexa510,cortexa710,cortexx2"
(const (symbol_ref "((enum attr_tune) aarch64_tune)")))
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 36519cc..a9a1800 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -23390,7 +23390,8 @@ aarch64_copy_one_block_and_progress_pointers (rtx *src, rtx *dst,
}
/* Expand cpymem, as if from a __builtin_memcpy. Return true if
- we succeed, otherwise return false. */
+ we succeed, otherwise return false, indicating that a libcall to
+ memcpy should be emitted. */
bool
aarch64_expand_cpymem (rtx *operands)
@@ -23407,11 +23408,13 @@ aarch64_expand_cpymem (rtx *operands)
unsigned HOST_WIDE_INT size = INTVAL (operands[2]);
- /* Inline up to 256 bytes when optimizing for speed. */
+ /* Try to inline up to 256 bytes. */
unsigned HOST_WIDE_INT max_copy_size = 256;
- if (optimize_function_for_size_p (cfun))
- max_copy_size = 128;
+ bool size_p = optimize_function_for_size_p (cfun);
+
+ if (size > max_copy_size)
+ return false;
int copy_bits = 256;
@@ -23421,13 +23424,14 @@ aarch64_expand_cpymem (rtx *operands)
|| !TARGET_SIMD
|| (aarch64_tune_params.extra_tuning_flags
& AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS))
- {
- copy_bits = 128;
- max_copy_size = max_copy_size / 2;
- }
+ copy_bits = 128;
- if (size > max_copy_size)
- return false;
+ /* Emit an inline load+store sequence and count the number of operations
+ involved. We use a simple count of just the loads and stores emitted
+ rather than rtx_insn count as all the pointer adjustments and reg copying
+ in this function will get optimized away later in the pipeline. */
+ start_sequence ();
+ unsigned nops = 0;
base = copy_to_mode_reg (Pmode, XEXP (dst, 0));
dst = adjust_automodify_address (dst, VOIDmode, base, 0);
@@ -23456,7 +23460,8 @@ aarch64_expand_cpymem (rtx *operands)
cur_mode = V4SImode;
aarch64_copy_one_block_and_progress_pointers (&src, &dst, cur_mode);
-
+ /* A single block copy is 1 load + 1 store. */
+ nops += 2;
n -= mode_bits;
/* Emit trailing copies using overlapping unaligned accesses - this is
@@ -23471,7 +23476,16 @@ aarch64_expand_cpymem (rtx *operands)
n = n_bits;
}
}
+ rtx_insn *seq = get_insns ();
+ end_sequence ();
+
+ /* A memcpy libcall in the worst case takes 3 instructions to prepare the
+ arguments + 1 for the call. */
+ unsigned libcall_cost = 4;
+ if (size_p && libcall_cost < nops)
+ return false;
+ emit_insn (seq);
return true;
}
@@ -23534,40 +23548,37 @@ aarch64_expand_setmem (rtx *operands)
if (!CONST_INT_P (operands[1]))
return false;
- bool speed_p = !optimize_function_for_size_p (cfun);
+ bool size_p = optimize_function_for_size_p (cfun);
/* Default the maximum to 256-bytes. */
unsigned max_set_size = 256;
- /* In case we are optimizing for size or if the core does not
- want to use STP Q regs, lower the max_set_size. */
- max_set_size = (!speed_p
- || (aarch64_tune_params.extra_tuning_flags
- & AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS))
- ? max_set_size / 2 : max_set_size;
-
len = INTVAL (operands[1]);
/* Upper bound check. */
if (len > max_set_size)
return false;
+ /* Attempt a sequence with a vector broadcast followed by stores.
+ Count the number of operations involved to see if it's worth it for
+ code size. */
+ start_sequence ();
+ unsigned nops = 0;
base = copy_to_mode_reg (Pmode, XEXP (dst, 0));
dst = adjust_automodify_address (dst, VOIDmode, base, 0);
/* Prepare the val using a DUP/MOVI v0.16B, val. */
src = expand_vector_broadcast (V16QImode, val);
src = force_reg (V16QImode, src);
-
+ nops++;
/* Convert len to bits to make the rest of the code simpler. */
n = len * BITS_PER_UNIT;
/* Maximum amount to copy in one go. We allow 256-bit chunks based on the
AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS tuning parameter. setmem expand
pattern is only turned on for TARGET_SIMD. */
- const int copy_limit = (speed_p
- && (aarch64_tune_params.extra_tuning_flags
- & AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS))
+ const int copy_limit = (aarch64_tune_params.extra_tuning_flags
+ & AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS)
? GET_MODE_BITSIZE (TImode) : 256;
while (n > 0)
@@ -23583,7 +23594,7 @@ aarch64_expand_setmem (rtx *operands)
mode_bits = GET_MODE_BITSIZE (cur_mode).to_constant ();
aarch64_set_one_block_and_progress_pointer (src, &dst, cur_mode);
-
+ nops++;
n -= mode_bits;
/* Do certain trailing copies as overlapping if it's going to be
@@ -23599,7 +23610,15 @@ aarch64_expand_setmem (rtx *operands)
n = n_bits;
}
}
+ rtx_insn *seq = get_insns ();
+ end_sequence ();
+ /* A call to memset in the worst case requires 3 instructions to prepare
+ the arguments + 1 for the call. Prefer the inline sequence for size if
+ it is no longer than that. */
+ if (size_p && nops > 4)
+ return false;
+ emit_insn (seq);
return true;
}
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index a5ba6c2..2792bb2 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -231,6 +231,15 @@ extern unsigned aarch64_architecture_version;
/* Pointer Authentication (PAUTH) extension. */
#define AARCH64_FL_PAUTH (1ULL << 40)
+/* 64-byte atomic load/store extensions. */
+#define AARCH64_FL_LS64 (1ULL << 41)
+
+/* Armv8.7-a architecture extensions. */
+#define AARCH64_FL_V8_7 (1ULL << 42)
+
+/* Armv9.0-A. */
+#define AARCH64_FL_V9 (1ULL << 43) /* Armv9.0-A Architecture. */
+
/* Has FP and SIMD. */
#define AARCH64_FL_FPSIMD (AARCH64_FL_FP | AARCH64_FL_SIMD)
@@ -255,8 +264,13 @@ extern unsigned aarch64_architecture_version;
#define AARCH64_FL_FOR_ARCH8_6 \
(AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_V8_6 | AARCH64_FL_FPSIMD \
| AARCH64_FL_I8MM | AARCH64_FL_BF16)
+#define AARCH64_FL_FOR_ARCH8_7 \
+ (AARCH64_FL_FOR_ARCH8_6 | AARCH64_FL_V8_7 | AARCH64_FL_LS64)
+
#define AARCH64_FL_FOR_ARCH8_R \
(AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_V8_R)
+#define AARCH64_FL_FOR_ARCH9 \
+ (AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_V9)
/* Macros to test ISA flags. */
@@ -295,6 +309,7 @@ extern unsigned aarch64_architecture_version;
#define AARCH64_ISA_SB (aarch64_isa_flags & AARCH64_FL_SB)
#define AARCH64_ISA_V8_R (aarch64_isa_flags & AARCH64_FL_V8_R)
#define AARCH64_ISA_PAUTH (aarch64_isa_flags & AARCH64_FL_PAUTH)
+#define AARCH64_ISA_V9 (aarch64_isa_flags & AARCH64_FL_V9)
/* Crypto is an optional extension to AdvSIMD. */
#define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO)
diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
index 635a223..2d5bf34 100644
--- a/gcc/config/aarch64/arm_neon.h
+++ b/gcc/config/aarch64/arm_neon.h
@@ -10416,15 +10416,14 @@ __extension__ extern __inline poly8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbl1_p8 (poly8x16_t __tab, uint8x8_t __idx)
{
- return (poly8x8_t) __builtin_aarch64_qtbl1v8qi ((int8x16_t) __tab,
- (int8x8_t) __idx);
+ return __builtin_aarch64_qtbl1v8qi_ppu (__tab, __idx);
}
__extension__ extern __inline int8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbl1_s8 (int8x16_t __tab, uint8x8_t __idx)
{
- return __builtin_aarch64_qtbl1v8qi (__tab, (int8x8_t) __idx);
+ return __builtin_aarch64_qtbl1v8qi_ssu (__tab, __idx);
}
__extension__ extern __inline uint8x8_t
@@ -10438,15 +10437,14 @@ __extension__ extern __inline poly8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbl1q_p8 (poly8x16_t __tab, uint8x16_t __idx)
{
- return (poly8x16_t) __builtin_aarch64_qtbl1v16qi ((int8x16_t) __tab,
- (int8x16_t) __idx);
+ return __builtin_aarch64_qtbl1v16qi_ppu (__tab, __idx);
}
__extension__ extern __inline int8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbl1q_s8 (int8x16_t __tab, uint8x16_t __idx)
{
- return __builtin_aarch64_qtbl1v16qi (__tab, (int8x16_t) __idx);
+ return __builtin_aarch64_qtbl1v16qi_ssu (__tab, __idx);
}
__extension__ extern __inline uint8x16_t
@@ -10460,7 +10458,7 @@ __extension__ extern __inline int8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbx1_s8 (int8x8_t __r, int8x16_t __tab, uint8x8_t __idx)
{
- return __builtin_aarch64_qtbx1v8qi (__r, __tab, (int8x8_t) __idx);
+ return __builtin_aarch64_qtbx1v8qi_sssu (__r, __tab, __idx);
}
__extension__ extern __inline uint8x8_t
@@ -10474,16 +10472,14 @@ __extension__ extern __inline poly8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbx1_p8 (poly8x8_t __r, poly8x16_t __tab, uint8x8_t __idx)
{
- return (poly8x8_t) __builtin_aarch64_qtbx1v8qi ((int8x8_t) __r,
- (int8x16_t) __tab,
- (int8x8_t) __idx);
+ return __builtin_aarch64_qtbx1v8qi_pppu (__r, __tab, __idx);
}
__extension__ extern __inline int8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbx1q_s8 (int8x16_t __r, int8x16_t __tab, uint8x16_t __idx)
{
- return __builtin_aarch64_qtbx1v16qi (__r, __tab, (int8x16_t) __idx);
+ return __builtin_aarch64_qtbx1v16qi_sssu (__r, __tab, __idx);
}
__extension__ extern __inline uint8x16_t
@@ -10497,9 +10493,7 @@ __extension__ extern __inline poly8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbx1q_p8 (poly8x16_t __r, poly8x16_t __tab, uint8x16_t __idx)
{
- return (poly8x16_t) __builtin_aarch64_qtbx1v16qi ((int8x16_t) __r,
- (int8x16_t) __tab,
- (int8x16_t) __idx);
+ return __builtin_aarch64_qtbx1v16qi_pppu (__r, __tab, __idx);
}
/* V7 legacy table intrinsics. */
@@ -10528,8 +10522,7 @@ vtbl1_p8 (poly8x8_t __tab, uint8x8_t __idx)
{
poly8x16_t __temp = vcombine_p8 (__tab,
vcreate_p8 (__AARCH64_UINT64_C (0x0)));
- return (poly8x8_t) __builtin_aarch64_qtbl1v8qi ((int8x16_t) __temp,
- (int8x8_t) __idx);
+ return __builtin_aarch64_qtbl1v8qi_ppu (__temp, __idx);
}
__extension__ extern __inline int8x8_t
@@ -10553,8 +10546,7 @@ __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vtbl2_p8 (poly8x8x2_t __tab, uint8x8_t __idx)
{
poly8x16_t __temp = vcombine_p8 (__tab.val[0], __tab.val[1]);
- return (poly8x8_t) __builtin_aarch64_qtbl1v8qi ((int8x16_t) __temp,
- (int8x8_t) __idx);
+ return __builtin_aarch64_qtbl1v8qi_ppu (__temp, __idx);
}
__extension__ extern __inline int8x8_t
@@ -10653,9 +10645,7 @@ __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vtbx2_p8 (poly8x8_t __r, poly8x8x2_t __tab, uint8x8_t __idx)
{
poly8x16_t __temp = vcombine_p8 (__tab.val[0], __tab.val[1]);
- return (poly8x8_t) __builtin_aarch64_qtbx1v8qi ((int8x8_t) __r,
- (int8x16_t) __temp,
- (int8x8_t) __idx);
+ return __builtin_aarch64_qtbx1v8qi_pppu (__r, __temp, __idx);
}
/* End of temporary inline asm. */
diff --git a/gcc/config/arm/arm-cpus.in b/gcc/config/arm/arm-cpus.in
index bcc9ebe..d0d0d0f 100644
--- a/gcc/config/arm/arm-cpus.in
+++ b/gcc/config/arm/arm-cpus.in
@@ -1612,6 +1612,16 @@ begin cpu cortex-r52
part d13
end cpu cortex-r52
+begin cpu cortex-r52plus
+ cname cortexr52plus
+ tune flags LDSCHED
+ architecture armv8-r+crc+simd
+ option nofp.dp remove FP_DBL ALL_SIMD
+ costs cortex
+ vendor 41
+ part d16
+end cpu cortex-r52plus
+
# FPU entries
# format:
# begin fpu <name>
diff --git a/gcc/config/arm/arm-tables.opt b/gcc/config/arm/arm-tables.opt
index 5692d4f..8bb0c9f 100644
--- a/gcc/config/arm/arm-tables.opt
+++ b/gcc/config/arm/arm-tables.opt
@@ -282,6 +282,9 @@ Enum(processor_type) String(cortex-m55) Value( TARGET_CPU_cortexm55)
EnumValue
Enum(processor_type) String(cortex-r52) Value( TARGET_CPU_cortexr52)
+EnumValue
+Enum(processor_type) String(cortex-r52plus) Value( TARGET_CPU_cortexr52plus)
+
Enum
Name(arm_arch) Type(int)
Known ARM architectures (for use with the -march= option):
diff --git a/gcc/config/arm/arm-tune.md b/gcc/config/arm/arm-tune.md
index b9df864..6482833 100644
--- a/gcc/config/arm/arm-tune.md
+++ b/gcc/config/arm/arm-tune.md
@@ -49,5 +49,5 @@
cortexx1,neoversen1,cortexa75cortexa55,
cortexa76cortexa55,neoversev1,neoversen2,
cortexm23,cortexm33,cortexm35p,
- cortexm55,cortexr52"
+ cortexm55,cortexr52,cortexr52plus"
(const (symbol_ref "((enum attr_tune) arm_tune)")))
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index 50524a5..0fa1c57 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -251,7 +251,7 @@ extern GTY(()) int darwin_ms_struct;
%{v} \
%{g*:%{!gctf:%{!gbtf:%{!gstabs*:%{%:debug-level-gt(0): -idsym}}}}}\
%{.c|.cc|.C|.cpp|.cp|.c++|.cxx|.CPP|.m|.mm|.s|.f|.f90|\
- .f95|.f03|.f77|.for|.F|.F90|.F95|.F03: \
+ .f95|.f03|.f77|.for|.F|.F90|.F95|.F03|.d: \
%{g*:%{!gctf:%{!gbtf:%{!gstabs*:%{%:debug-level-gt(0): -dsym}}}}}}}}}}}}}"
#define LINK_COMMAND_SPEC LINK_COMMAND_SPEC_A DSYMUTIL_SPEC
diff --git a/gcc/config/gcn/gcn-hsa.h b/gcc/config/gcn/gcn-hsa.h
index fc99c8d..6a432d1 100644
--- a/gcc/config/gcn/gcn-hsa.h
+++ b/gcc/config/gcn/gcn-hsa.h
@@ -75,25 +75,66 @@ extern unsigned int gcn_local_sym_hash (const char *name);
supported for gcn. */
#define GOMP_SELF_SPECS ""
+#ifdef HAVE_GCN_XNACK_FIJI
+#define X_FIJI
+#else
+#define X_FIJI "!march=*:;march=fiji:;"
+#endif
+#ifdef HAVE_GCN_XNACK_GFX900
+#define X_900
+#else
+#define X_900 "march=gfx900:;"
+#endif
+#ifdef HAVE_GCN_XNACK_GFX906
+#define X_906
+#else
+#define X_906 "march=gfx906:;"
+#endif
+#ifdef HAVE_GCN_XNACK_GFX908
+#define X_908
+#else
+#define X_908 "march=gfx908:;"
+#endif
+
#ifdef HAVE_GCN_SRAM_ECC_FIJI
-#define A_FIJI
+#define S_FIJI
#else
-#define A_FIJI "!march=*:;march=fiji:;"
+#define S_FIJI "!march=*:;march=fiji:;"
#endif
#ifdef HAVE_GCN_SRAM_ECC_GFX900
-#define A_900
+#define S_900
#else
-#define A_900 "march=gfx900:;"
+#define S_900 "march=gfx900:;"
#endif
#ifdef HAVE_GCN_SRAM_ECC_GFX906
-#define A_906
+#define S_906
#else
-#define A_906 "march=gfx906:;"
+#define S_906 "march=gfx906:;"
#endif
#ifdef HAVE_GCN_SRAM_ECC_GFX908
-#define A_908
+#define S_908
+#else
+#define S_908 "march=gfx908:;"
+#endif
+
+#ifdef HAVE_GCN_ASM_V3_SYNTAX
+#define SRAMOPT "!msram-ecc=off:-mattr=+sram-ecc;:-mattr=-sram-ecc"
+#endif
+#ifdef HAVE_GCN_ASM_V4_SYNTAX
+/* In HSACOv4 no attribute setting means the binary supports "any" hardware
+ configuration. The name of the attribute also changed. */
+#define SRAMOPT "msram-ecc=on:-mattr=+sramecc;msram-ecc=off:-mattr=-sramecc"
+#endif
+#if !defined(SRAMOPT) && !defined(IN_LIBGCC2)
+#error "No assembler syntax configured"
+#endif
+
+#ifdef HAVE_GCN_ASM_V4_SYNTAX
+/* FIJI cards don't seem to support drivers new enough to allow HSACOv4. */
+#define HSACO3_SELECT_OPT \
+ "%{!march=*|march=fiji:--amdhsa-code-object-version=3} "
#else
-#define A_908 "march=gfx908:;"
+#define HSACO3_SELECT_OPT
#endif
/* These targets can't have SRAM-ECC, even if a broken assembler allows it. */
@@ -103,10 +144,10 @@ extern unsigned int gcn_local_sym_hash (const char *name);
/* Use LLVM assembler and linker options. */
#define ASM_SPEC "-triple=amdgcn--amdhsa " \
"%:last_arg(%{march=*:-mcpu=%*}) " \
- "-mattr=%{mxnack:+xnack;:-xnack} " \
- /* FIXME: support "any" when we move to HSACOv4. */ \
- "-mattr=%{" A_FIJI A_900 A_906 A_908 \
- "!msram-ecc=off:+sram-ecc;:-sram-ecc} " \
+ HSACO3_SELECT_OPT \
+ "%{" X_FIJI X_900 X_906 X_908 \
+ "mxnack:-mattr=+xnack;:-mattr=-xnack} " \
+ "%{" S_FIJI S_900 S_906 S_908 SRAMOPT "} " \
"-filetype=obj"
#define LINK_SPEC "--pie --export-dynamic"
#define LIB_SPEC "-lc"
diff --git a/gcc/config/gcn/gcn-valu.md b/gcc/config/gcn/gcn-valu.md
index 84ff675..01fdce6 100644
--- a/gcc/config/gcn/gcn-valu.md
+++ b/gcc/config/gcn/gcn-valu.md
@@ -827,8 +827,12 @@
/* Work around assembler bug in which a 64-bit register is expected,
but a 32-bit value would be correct. */
int reg = REGNO (operands[2]) - FIRST_VGPR_REG;
- sprintf (buf, "global_load%%o0\t%%0, v[%d:%d], %%1 offset:%%3%s\;"
- "s_waitcnt\tvmcnt(0)", reg, reg + 1, glc);
+ if (HAVE_GCN_ASM_GLOBAL_LOAD_FIXED)
+ sprintf (buf, "global_load%%o0\t%%0, v%d, %%1 offset:%%3%s\;"
+ "s_waitcnt\tvmcnt(0)", reg, glc);
+ else
+ sprintf (buf, "global_load%%o0\t%%0, v[%d:%d], %%1 offset:%%3%s\;"
+ "s_waitcnt\tvmcnt(0)", reg, reg + 1, glc);
}
else
gcc_unreachable ();
@@ -958,8 +962,12 @@
/* Work around assembler bug in which a 64-bit register is expected,
but a 32-bit value would be correct. */
int reg = REGNO (operands[1]) - FIRST_VGPR_REG;
- sprintf (buf, "global_store%%s3\tv[%d:%d], %%3, %%0 offset:%%2%s",
- reg, reg + 1, glc);
+ if (HAVE_GCN_ASM_GLOBAL_LOAD_FIXED)
+ sprintf (buf, "global_store%%s3\tv%d, %%3, %%0 offset:%%2%s",
+ reg, glc);
+ else
+ sprintf (buf, "global_store%%s3\tv[%d:%d], %%3, %%0 offset:%%2%s",
+ reg, reg + 1, glc);
}
else
gcc_unreachable ();
diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c
index 2a3fc96..2e90f32 100644
--- a/gcc/config/gcn/gcn.c
+++ b/gcc/config/gcn/gcn.c
@@ -5217,42 +5217,76 @@ static void
output_file_start (void)
{
const char *cpu;
- bool use_sram = flag_sram_ecc;
+ bool use_xnack_attr = true;
+ bool use_sram_attr = true;
switch (gcn_arch)
{
case PROCESSOR_FIJI:
cpu = "gfx803";
+#ifndef HAVE_GCN_XNACK_FIJI
+ use_xnack_attr = false;
+#endif
#ifndef HAVE_GCN_SRAM_ECC_FIJI
- use_sram = false;
+ use_sram_attr = false;
#endif
break;
case PROCESSOR_VEGA10:
cpu = "gfx900";
+#ifndef HAVE_GCN_XNACK_GFX900
+ use_xnack_attr = false;
+#endif
#ifndef HAVE_GCN_SRAM_ECC_GFX900
- use_sram = false;
+ use_sram_attr = false;
#endif
break;
case PROCESSOR_VEGA20:
cpu = "gfx906";
+#ifndef HAVE_GCN_XNACK_GFX906
+ use_xnack_attr = false;
+#endif
#ifndef HAVE_GCN_SRAM_ECC_GFX906
- use_sram = false;
+ use_sram_attr = false;
#endif
break;
case PROCESSOR_GFX908:
cpu = "gfx908";
+#ifndef HAVE_GCN_XNACK_GFX908
+ use_xnack_attr = false;
+#endif
#ifndef HAVE_GCN_SRAM_ECC_GFX908
- use_sram = false;
+ use_sram_attr = false;
#endif
break;
default: gcc_unreachable ();
}
+#if HAVE_GCN_ASM_V3_SYNTAX
const char *xnack = (flag_xnack ? "+xnack" : "");
- /* FIXME: support "any" when we move to HSACOv4. */
- const char *sram_ecc = (use_sram ? "+sram-ecc" : "");
+ const char *sram_ecc = (flag_sram_ecc ? "+sram-ecc" : "");
+#endif
+#if HAVE_GCN_ASM_V4_SYNTAX
+ /* In HSACOv4 no attribute setting means the binary supports "any" hardware
+ configuration. In GCC binaries, this is true for SRAM ECC, but not
+ XNACK. */
+ const char *xnack = (flag_xnack ? ":xnack+" : ":xnack-");
+ const char *sram_ecc = (flag_sram_ecc == SRAM_ECC_ON ? ":sramecc+"
+ : flag_sram_ecc == SRAM_ECC_OFF ? ":sramecc-"
+ : "");
+#endif
+ if (!use_xnack_attr)
+ xnack = "";
+ if (!use_sram_attr)
+ sram_ecc = "";
fprintf(asm_out_file, "\t.amdgcn_target \"amdgcn-unknown-amdhsa--%s%s%s\"\n",
- cpu, xnack, sram_ecc);
+ cpu,
+#if HAVE_GCN_ASM_V3_SYNTAX
+ xnack, sram_ecc
+#endif
+#ifdef HAVE_GCN_ASM_V4_SYNTAX
+ sram_ecc, xnack
+#endif
+ );
}
/* Implement ASM_DECLARE_FUNCTION_NAME via gcn-hsa.h.
diff --git a/gcc/config/gcn/mkoffload.c b/gcc/config/gcn/mkoffload.c
index 732bdfd..a3b22d0 100644
--- a/gcc/config/gcn/mkoffload.c
+++ b/gcc/config/gcn/mkoffload.c
@@ -54,8 +54,51 @@
#undef EF_AMDGPU_MACH_AMDGCN_GFX908
#define EF_AMDGPU_MACH_AMDGCN_GFX908 0x30
-#define EF_AMDGPU_XNACK 0x100
-#define EF_AMDGPU_SRAM_ECC 0x200
+#define EF_AMDGPU_XNACK_V3 0x100
+#define EF_AMDGPU_SRAM_ECC_V3 0x200
+
+#define EF_AMDGPU_FEATURE_XNACK_V4 0x300 /* Mask. */
+#define EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4 0x000
+#define EF_AMDGPU_FEATURE_XNACK_ANY_V4 0x100
+#define EF_AMDGPU_FEATURE_XNACK_OFF_V4 0x200
+#define EF_AMDGPU_FEATURE_XNACK_ON_V4 0x300
+
+#define EF_AMDGPU_FEATURE_SRAMECC_V4 0xc00 /* Mask. */
+#define EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4 0x000
+#define EF_AMDGPU_FEATURE_SRAMECC_ANY_V4 0x400
+#define EF_AMDGPU_FEATURE_SRAMECC_OFF_V4 0x800
+#define EF_AMDGPU_FEATURE_SRAMECC_ON_V4 0xc00
+
+#ifdef HAVE_GCN_ASM_V3_SYNTAX
+#define SET_XNACK_ON(VAR) VAR |= EF_AMDGPU_XNACK_V3
+#define SET_XNACK_OFF(VAR) VAR &= ~EF_AMDGPU_XNACK_V3
+#define TEST_XNACK(VAR) (VAR & EF_AMDGPU_XNACK_V3)
+
+#define SET_SRAM_ECC_ON(VAR) VAR |= EF_AMDGPU_SRAM_ECC_V3
+#define SET_SRAM_ECC_ANY(VAR) SET_SRAM_ECC_ON (VAR)
+#define SET_SRAM_ECC_OFF(VAR) VAR &= ~EF_AMDGPU_SRAM_ECC_V3
+#define TEST_SRAM_ECC_ANY(VAR) 0 /* Not supported. */
+#define TEST_SRAM_ECC_ON(VAR) (VAR & EF_AMDGPU_SRAM_ECC_V3)
+#endif
+#ifdef HAVE_GCN_ASM_V4_SYNTAX
+#define SET_XNACK_ON(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_XNACK_V4) \
+ | EF_AMDGPU_FEATURE_XNACK_ON_V4)
+#define SET_XNACK_OFF(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_XNACK_V4) \
+ | EF_AMDGPU_FEATURE_XNACK_OFF_V4)
+#define TEST_XNACK(VAR) ((VAR & EF_AMDGPU_FEATURE_XNACK_V4) \
+ == EF_AMDGPU_FEATURE_XNACK_ON_V4)
+
+#define SET_SRAM_ECC_ON(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_SRAMECC_V4) \
+ | EF_AMDGPU_FEATURE_SRAMECC_ON_V4)
+#define SET_SRAM_ECC_ANY(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_SRAMECC_V4) \
+ | EF_AMDGPU_FEATURE_SRAMECC_ANY_V4)
+#define SET_SRAM_ECC_OFF(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_SRAMECC_V4) \
+ | EF_AMDGPU_FEATURE_SRAMECC_OFF_V4)
+#define TEST_SRAM_ECC_ANY(VAR) ((VAR & EF_AMDGPU_FEATURE_SRAMECC_V4) \
+ == EF_AMDGPU_FEATURE_SRAMECC_ANY_V4)
+#define TEST_SRAM_ECC_ON(VAR) ((VAR & EF_AMDGPU_FEATURE_SRAMECC_V4) \
+ == EF_AMDGPU_FEATURE_SRAMECC_ON_V4)
+#endif
#ifndef R_AMDGPU_NONE
#define R_AMDGPU_NONE 0
@@ -80,7 +123,13 @@ static struct obstack files_to_cleanup;
enum offload_abi offload_abi = OFFLOAD_ABI_UNSET;
uint32_t elf_arch = EF_AMDGPU_MACH_AMDGCN_GFX803; // Default GPU architecture.
-uint32_t elf_flags = 0;
+uint32_t elf_flags =
+#ifdef HAVE_GCN_ASM_V3_SYNTAX
+ 0;
+#endif
+#ifdef HAVE_GCN_ASM_V4_SYNTAX
+ (EF_AMDGPU_FEATURE_XNACK_ANY_V4 | EF_AMDGPU_FEATURE_SRAMECC_ANY_V4);
+#endif
/* Delete tempfiles. */
@@ -851,23 +900,22 @@ main (int argc, char **argv)
else if (strcmp (argv[i], "-fpic") == 0)
fpic = true;
else if (strcmp (argv[i], "-mxnack") == 0)
- elf_flags |= EF_AMDGPU_XNACK;
+ SET_XNACK_ON (elf_flags);
else if (strcmp (argv[i], "-mno-xnack") == 0)
- elf_flags &= ~EF_AMDGPU_XNACK;
+ SET_XNACK_OFF (elf_flags);
else if (strcmp (argv[i], "-msram-ecc=on") == 0)
{
- elf_flags |= EF_AMDGPU_SRAM_ECC;
+ SET_SRAM_ECC_ON (elf_flags);
sram_seen = true;
}
else if (strcmp (argv[i], "-msram-ecc=any") == 0)
{
- /* FIXME: change this when we move to HSACOv4. */
- elf_flags |= EF_AMDGPU_SRAM_ECC;
+ SET_SRAM_ECC_ANY (elf_flags);
sram_seen = true;
}
else if (strcmp (argv[i], "-msram-ecc=off") == 0)
{
- elf_flags &= ~EF_AMDGPU_SRAM_ECC;
+ SET_SRAM_ECC_OFF (elf_flags);
sram_seen = true;
}
else if (strcmp (argv[i], "-save-temps") == 0)
@@ -890,23 +938,27 @@ main (int argc, char **argv)
if (!(fopenacc ^ fopenmp))
fatal_error (input_location, "either -fopenacc or -fopenmp must be set");
- /* The SRAM-ECC feature defaults to "any" on GPUs where the feature is
- available. */
if (!sram_seen)
- switch (elf_arch)
- {
- case EF_AMDGPU_MACH_AMDGCN_GFX803:
- case EF_AMDGPU_MACH_AMDGCN_GFX900:
- case EF_AMDGPU_MACH_AMDGCN_GFX906:
+ {
+#ifdef HAVE_GCN_ASM_V3_SYNTAX
+ /* For HSACOv3, the SRAM-ECC feature defaults to "on" on GPUs where the
+ feature is available.
+ (HSACOv4 has elf_flags initialsed to "any" in all cases.) */
+ switch (elf_arch)
+ {
+ case EF_AMDGPU_MACH_AMDGCN_GFX803:
+ case EF_AMDGPU_MACH_AMDGCN_GFX900:
+ case EF_AMDGPU_MACH_AMDGCN_GFX906:
#ifndef HAVE_GCN_SRAM_ECC_GFX908
- case EF_AMDGPU_MACH_AMDGCN_GFX908:
+ case EF_AMDGPU_MACH_AMDGCN_GFX908:
#endif
- break;
- default:
- /* FIXME: change this when we move to HSACOv4. */
- elf_flags |= EF_AMDGPU_SRAM_ECC;
- break;
- }
+ break;
+ default:
+ SET_SRAM_ECC_ON (elf_flags);
+ break;
+ }
+#endif
+ }
const char *abi;
switch (offload_abi)
@@ -936,11 +988,12 @@ main (int argc, char **argv)
if (fopenmp)
obstack_ptr_grow (&cc_argv_obstack, "-mgomp");
obstack_ptr_grow (&cc_argv_obstack,
- (elf_flags & EF_AMDGPU_XNACK
+ (TEST_XNACK (elf_flags)
? "-mxnack" : "-mno-xnack"));
obstack_ptr_grow (&cc_argv_obstack,
- (elf_flags & EF_AMDGPU_SRAM_ECC
- ? "-msram-ecc=on" : "-msram-ecc=off"));
+ (TEST_SRAM_ECC_ON (elf_flags) ? "-msram-ecc=on"
+ : TEST_SRAM_ECC_ANY (elf_flags) ? "-msram-ecc=any"
+ : "-msram-ecc=off"));
for (int ix = 1; ix != argc; ix++)
{
@@ -1043,11 +1096,12 @@ main (int argc, char **argv)
obstack_ptr_grow (&ld_argv_obstack, gcn_s2_name);
obstack_ptr_grow (&ld_argv_obstack, "-lgomp");
obstack_ptr_grow (&ld_argv_obstack,
- (elf_flags & EF_AMDGPU_XNACK
+ (TEST_XNACK (elf_flags)
? "-mxnack" : "-mno-xnack"));
obstack_ptr_grow (&ld_argv_obstack,
- (elf_flags & EF_AMDGPU_SRAM_ECC
- ? "-msram-ecc=on" : "-msram-ecc=off"));
+ (TEST_SRAM_ECC_ON (elf_flags) ? "-msram-ecc=on"
+ : TEST_SRAM_ECC_ANY (elf_flags) ? "-msram-ecc=any"
+ : "-msram-ecc=off"));
if (verbose)
obstack_ptr_grow (&ld_argv_obstack, "-v");
diff --git a/gcc/config/i386/avx512fp16intrin.h b/gcc/config/i386/avx512fp16intrin.h
index 4714696..29cf679 100644
--- a/gcc/config/i386/avx512fp16intrin.h
+++ b/gcc/config/i386/avx512fp16intrin.h
@@ -45,6 +45,14 @@ typedef _Float16 __m128h __attribute__ ((__vector_size__ (16), __may_alias__));
typedef _Float16 __m256h __attribute__ ((__vector_size__ (32), __may_alias__));
typedef _Float16 __m512h __attribute__ ((__vector_size__ (64), __may_alias__));
+/* Unaligned version of the same type. */
+typedef _Float16 __m128h_u __attribute__ ((__vector_size__ (16), \
+ __may_alias__, __aligned__ (1)));
+typedef _Float16 __m256h_u __attribute__ ((__vector_size__ (32), \
+ __may_alias__, __aligned__ (1)));
+typedef _Float16 __m512h_u __attribute__ ((__vector_size__ (64), \
+ __may_alias__, __aligned__ (1)));
+
extern __inline __m128h
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm_set_ph (_Float16 __A7, _Float16 __A6, _Float16 __A5,
@@ -362,6 +370,48 @@ _mm_load_sh (void const *__P)
*(_Float16 const *) __P);
}
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_load_ph (void const *__P)
+{
+ return *(const __m512h *) __P;
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_load_ph (void const *__P)
+{
+ return *(const __m256h *) __P;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_load_ph (void const *__P)
+{
+ return *(const __m128h *) __P;
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_loadu_ph (void const *__P)
+{
+ return *(const __m512h_u *) __P;
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_loadu_ph (void const *__P)
+{
+ return *(const __m256h_u *) __P;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_loadu_ph (void const *__P)
+{
+ return *(const __m128h_u *) __P;
+}
+
/* Stores the lower _Float16 value. */
extern __inline void
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
@@ -370,6 +420,56 @@ _mm_store_sh (void *__P, __m128h __A)
*(_Float16 *) __P = ((__v8hf)__A)[0];
}
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_store_ph (void *__P, __m512h __A)
+{
+ *(__m512h *) __P = __A;
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_store_ph (void *__P, __m256h __A)
+{
+ *(__m256h *) __P = __A;
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_store_ph (void *__P, __m128h __A)
+{
+ *(__m128h *) __P = __A;
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_storeu_ph (void *__P, __m512h __A)
+{
+ *(__m512h_u *) __P = __A;
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_storeu_ph (void *__P, __m256h __A)
+{
+ *(__m256h_u *) __P = __A;
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_storeu_ph (void *__P, __m128h __A)
+{
+ *(__m128h_u *) __P = __A;
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_abs_ph (__m512h __A)
+{
+ return (__m512h) _mm512_and_epi32 ( _mm512_set1_epi32 (0x7FFF7FFF),
+ (__m512i) __A);
+}
+
/* Intrinsics v[add,sub,mul,div]ph. */
extern __inline __m512h
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
@@ -621,6 +721,33 @@ _mm512_maskz_div_round_ph (__mmask32 __A, __m512h __B, __m512h __C,
(A), (D)))
#endif /* __OPTIMIZE__ */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_conj_pch (__m512h __A)
+{
+ return (__m512h) _mm512_xor_epi32 ((__m512i) __A, _mm512_set1_epi32 (1<<31));
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_conj_pch (__m512h __W, __mmask16 __U, __m512h __A)
+{
+ return (__m512h)
+ __builtin_ia32_movaps512_mask ((__v16sf) _mm512_conj_pch (__A),
+ (__v16sf) __W,
+ (__mmask16) __U);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_conj_pch (__mmask16 __U, __m512h __A)
+{
+ return (__m512h)
+ __builtin_ia32_movaps512_mask ((__v16sf) _mm512_conj_pch (__A),
+ (__v16sf) _mm512_setzero_ps (),
+ (__mmask16) __U);
+}
+
/* Intrinsics of v[add,sub,mul,div]sh. */
extern __inline __m128h
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
@@ -6115,6 +6242,1006 @@ _mm_maskz_fnmsub_round_sh (__mmask8 __U, __m128h __W, __m128h __A,
#endif /* __OPTIMIZE__ */
+/* Intrinsics vf[,c]maddcph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fcmadd_pch (__m512h __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmaddcph512_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fcmadd_pch (__m512h __A, __mmask16 __B, __m512h __C, __m512h __D)
+{
+ return (__m512h) __builtin_ia32_movaps512_mask
+ ((__v16sf)
+ __builtin_ia32_vfcmaddcph512_mask_round ((__v32hf) __A,
+ (__v32hf) __C,
+ (__v32hf) __D, __B,
+ _MM_FROUND_CUR_DIRECTION),
+ (__v16sf) __A, __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fcmadd_pch (__m512h __A, __m512h __B, __m512h __C, __mmask16 __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmaddcph512_mask_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ __D, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fcmadd_pch (__mmask16 __A, __m512h __B, __m512h __C, __m512h __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmaddcph512_maskz_round ((__v32hf) __B,
+ (__v32hf) __C,
+ (__v32hf) __D,
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fmadd_pch (__m512h __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddcph512_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmadd_pch (__m512h __A, __mmask16 __B, __m512h __C, __m512h __D)
+{
+ return (__m512h) __builtin_ia32_movaps512_mask
+ ((__v16sf)
+ __builtin_ia32_vfmaddcph512_mask_round ((__v32hf) __A,
+ (__v32hf) __C,
+ (__v32hf) __D, __B,
+ _MM_FROUND_CUR_DIRECTION),
+ (__v16sf) __A, __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fmadd_pch (__m512h __A, __m512h __B, __m512h __C, __mmask16 __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddcph512_mask_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ __D, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmadd_pch (__mmask16 __A, __m512h __B, __m512h __C, __m512h __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddcph512_maskz_round ((__v32hf) __B,
+ (__v32hf) __C,
+ (__v32hf) __D,
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fcmadd_round_pch (__m512h __A, __m512h __B, __m512h __C, const int __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmaddcph512_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ __D);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fcmadd_round_pch (__m512h __A, __mmask16 __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return (__m512h) __builtin_ia32_movaps512_mask
+ ((__v16sf)
+ __builtin_ia32_vfcmaddcph512_mask_round ((__v32hf) __A,
+ (__v32hf) __C,
+ (__v32hf) __D, __B,
+ __E),
+ (__v16sf) __A, __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fcmadd_round_pch (__m512h __A, __m512h __B, __m512h __C,
+ __mmask16 __D, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmaddcph512_mask_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ __D, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fcmadd_round_pch (__mmask16 __A, __m512h __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmaddcph512_maskz_round ((__v32hf) __B,
+ (__v32hf) __C,
+ (__v32hf) __D,
+ __A, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fmadd_round_pch (__m512h __A, __m512h __B, __m512h __C, const int __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddcph512_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ __D);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmadd_round_pch (__m512h __A, __mmask16 __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return (__m512h) __builtin_ia32_movaps512_mask
+ ((__v16sf)
+ __builtin_ia32_vfmaddcph512_mask_round ((__v32hf) __A,
+ (__v32hf) __C,
+ (__v32hf) __D, __B,
+ __E),
+ (__v16sf) __A, __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fmadd_round_pch (__m512h __A, __m512h __B, __m512h __C,
+ __mmask16 __D, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddcph512_mask_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ __D, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmadd_round_pch (__mmask16 __A, __m512h __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddcph512_maskz_round ((__v32hf) __B,
+ (__v32hf) __C,
+ (__v32hf) __D,
+ __A, __E);
+}
+
+#else
+#define _mm512_fcmadd_round_pch(A, B, C, D) \
+ (__m512h) __builtin_ia32_vfcmaddcph512_round ((A), (B), (C), (D))
+
+#define _mm512_mask_fcmadd_round_pch(A, B, C, D, E) \
+ ((__m512h) __builtin_ia32_movaps512_mask ( \
+ (__v16sf) \
+ __builtin_ia32_vfcmaddcph512_mask_round ((__v32hf) (A), \
+ (__v32hf) (C), \
+ (__v32hf) (D), \
+ (B), (E)), \
+ (__v16sf) (A), (B)));
+
+
+#define _mm512_mask3_fcmadd_round_pch(A, B, C, D, E) \
+ ((__m512h) \
+ __builtin_ia32_vfcmaddcph512_mask_round ((A), (B), (C), (D), (E)))
+
+#define _mm512_maskz_fcmadd_round_pch(A, B, C, D, E) \
+ (__m512h) \
+ __builtin_ia32_vfcmaddcph512_maskz_round ((B), (C), (D), (A), (E))
+
+#define _mm512_fmadd_round_pch(A, B, C, D) \
+ (__m512h) __builtin_ia32_vfmaddcph512_round ((A), (B), (C), (D))
+
+#define _mm512_mask_fmadd_round_pch(A, B, C, D, E) \
+ ((__m512h) __builtin_ia32_movaps512_mask ( \
+ (__v16sf) \
+ __builtin_ia32_vfmaddcph512_mask_round ((__v32hf) (A), \
+ (__v32hf) (C), \
+ (__v32hf) (D), \
+ (B), (E)), \
+ (__v16sf) (A), (B)));
+
+#define _mm512_mask3_fmadd_round_pch(A, B, C, D, E) \
+ (__m512h) \
+ __builtin_ia32_vfmaddcph512_mask_round ((A), (B), (C), (D), (E))
+
+#define _mm512_maskz_fmadd_round_pch(A, B, C, D, E) \
+ (__m512h) \
+ __builtin_ia32_vfmaddcph512_maskz_round ((B), (C), (D), (A), (E))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vf[,c]mulcph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fcmul_pch (__m512h __A, __m512h __B)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmulcph512_round ((__v32hf) __A,
+ (__v32hf) __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fcmul_pch (__m512h __A, __mmask16 __B, __m512h __C, __m512h __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmulcph512_mask_round ((__v32hf) __C,
+ (__v32hf) __D,
+ (__v32hf) __A,
+ __B, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fcmul_pch (__mmask16 __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmulcph512_mask_round ((__v32hf) __B,
+ (__v32hf) __C,
+ _mm512_setzero_ph (),
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fmul_pch (__m512h __A, __m512h __B)
+{
+ return (__m512h)
+ __builtin_ia32_vfmulcph512_round ((__v32hf) __A,
+ (__v32hf) __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmul_pch (__m512h __A, __mmask16 __B, __m512h __C, __m512h __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfmulcph512_mask_round ((__v32hf) __C,
+ (__v32hf) __D,
+ (__v32hf) __A,
+ __B, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmul_pch (__mmask16 __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmulcph512_mask_round ((__v32hf) __B,
+ (__v32hf) __C,
+ _mm512_setzero_ph (),
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fcmul_round_pch (__m512h __A, __m512h __B, const int __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmulcph512_round ((__v32hf) __A,
+ (__v32hf) __B, __D);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fcmul_round_pch (__m512h __A, __mmask16 __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmulcph512_mask_round ((__v32hf) __C,
+ (__v32hf) __D,
+ (__v32hf) __A,
+ __B, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fcmul_round_pch (__mmask16 __A, __m512h __B,
+ __m512h __C, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmulcph512_mask_round ((__v32hf) __B,
+ (__v32hf) __C,
+ _mm512_setzero_ph (),
+ __A, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fmul_round_pch (__m512h __A, __m512h __B, const int __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfmulcph512_round ((__v32hf) __A,
+ (__v32hf) __B,
+ __D);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmul_round_pch (__m512h __A, __mmask16 __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfmulcph512_mask_round ((__v32hf) __C,
+ (__v32hf) __D,
+ (__v32hf) __A,
+ __B, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmul_round_pch (__mmask16 __A, __m512h __B,
+ __m512h __C, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfmulcph512_mask_round ((__v32hf) __B,
+ (__v32hf) __C,
+ _mm512_setzero_ph (),
+ __A, __E);
+}
+
+#else
+#define _mm512_fcmul_round_pch(A, B, D) \
+ (__m512h) __builtin_ia32_vfcmulcph512_round ((A), (B), (D))
+
+#define _mm512_mask_fcmul_round_pch(A, B, C, D, E) \
+ (__m512h) __builtin_ia32_vfcmulcph512_mask_round ((C), (D), (A), (B), (E))
+
+#define _mm512_maskz_fcmul_round_pch(A, B, C, E) \
+ (__m512h) __builtin_ia32_vfcmulcph512_mask_round ((B), (C), \
+ (__v32hf) \
+ _mm512_setzero_ph (), \
+ (A), (E))
+
+#define _mm512_fmul_round_pch(A, B, D) \
+ (__m512h) __builtin_ia32_vfmulcph512_round ((A), (B), (D))
+
+#define _mm512_mask_fmul_round_pch(A, B, C, D, E) \
+ (__m512h) __builtin_ia32_vfmulcph512_mask_round ((C), (D), (A), (B), (E))
+
+#define _mm512_maskz_fmul_round_pch(A, B, C, E) \
+ (__m512h) __builtin_ia32_vfmulcph512_mask_round ((B), (C), \
+ (__v32hf) \
+ _mm512_setzero_ph (), \
+ (A), (E))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vf[,c]maddcsh. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fcmadd_sch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+#ifdef __AVX512VL__
+ return (__m128h) __builtin_ia32_movaps128_mask (
+ (__v4sf)
+ __builtin_ia32_vfcmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D, __B,
+ _MM_FROUND_CUR_DIRECTION),
+ (__v4sf) __A, __B);
+#else
+ return (__m128h) __builtin_ia32_blendvps ((__v4sf) __A,
+ (__v4sf)
+ __builtin_ia32_vfcmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D, __B,
+ _MM_FROUND_CUR_DIRECTION),
+ (__v4sf) _mm_set_ss ((float) ((int) __B << 31)));
+#endif
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fcmadd_sch (__m128h __A, __m128h __B, __m128h __C, __mmask8 __D)
+{
+ return (__m128h) _mm_move_ss ((__m128) __C,
+ (__m128)
+ __builtin_ia32_vfcmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C, __D,
+ _MM_FROUND_CUR_DIRECTION));
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fcmadd_sch (__mmask8 __A, __m128h __B, __m128h __C, __m128h __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmaddcsh_maskz_round ((__v8hf) __B,
+ (__v8hf) __C,
+ (__v8hf) __D,
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fcmadd_sch (__m128h __A, __m128h __B, __m128h __C)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmaddcsh_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmadd_sch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+#ifdef __AVX512VL__
+ return (__m128h) __builtin_ia32_movaps128_mask (
+ (__v4sf)
+ __builtin_ia32_vfmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D, __B,
+ _MM_FROUND_CUR_DIRECTION),
+ (__v4sf) __A, __B);
+#else
+ return (__m128h) __builtin_ia32_blendvps ((__v4sf) __A,
+ (__v4sf)
+ __builtin_ia32_vfmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D, __B,
+ _MM_FROUND_CUR_DIRECTION),
+ (__v4sf) _mm_set_ss ((float) ((int) __B << 31)));
+#endif
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fmadd_sch (__m128h __A, __m128h __B, __m128h __C, __mmask8 __D)
+{
+ return (__m128h) _mm_move_ss ((__m128) __C,
+ (__m128)
+ __builtin_ia32_vfmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C, __D,
+ _MM_FROUND_CUR_DIRECTION));
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmadd_sch (__mmask8 __A, __m128h __B, __m128h __C, __m128h __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfmaddcsh_maskz_round ((__v8hf) __B,
+ (__v8hf) __C,
+ (__v8hf) __D,
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmadd_sch (__m128h __A, __m128h __B, __m128h __C)
+{
+ return (__m128h)
+ __builtin_ia32_vfmaddcsh_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fcmadd_round_sch (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+#ifdef __AVX512VL__
+ return (__m128h) __builtin_ia32_movaps128_mask (
+ (__v4sf)
+ __builtin_ia32_vfcmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D,
+ __B, __E),
+ (__v4sf) __A, __B);
+#else
+ return (__m128h) __builtin_ia32_blendvps ((__v4sf) __A,
+ (__v4sf)
+ __builtin_ia32_vfcmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D,
+ __B, __E),
+ (__v4sf) _mm_set_ss ((float) ((int) __B << 31)));
+#endif
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fcmadd_round_sch (__m128h __A, __m128h __B, __m128h __C,
+ __mmask8 __D, const int __E)
+{
+ return (__m128h) _mm_move_ss ((__m128) __C,
+ (__m128)
+ __builtin_ia32_vfcmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ __D, __E));
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fcmadd_round_sch (__mmask8 __A, __m128h __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmaddcsh_maskz_round ((__v8hf) __B,
+ (__v8hf) __C,
+ (__v8hf) __D,
+ __A, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fcmadd_round_sch (__m128h __A, __m128h __B, __m128h __C, const int __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmaddcsh_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmadd_round_sch (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+#ifdef __AVX512VL__
+ return (__m128h) __builtin_ia32_movaps128_mask (
+ (__v4sf)
+ __builtin_ia32_vfmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D,
+ __B, __E),
+ (__v4sf) __A, __B);
+#else
+ return (__m128h) __builtin_ia32_blendvps ((__v4sf) __A,
+ (__v4sf)
+ __builtin_ia32_vfmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D,
+ __B, __E),
+ (__v4sf) _mm_set_ss ((float) ((int) __B << 31)));
+#endif
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fmadd_round_sch (__m128h __A, __m128h __B, __m128h __C,
+ __mmask8 __D, const int __E)
+{
+ return (__m128h) _mm_move_ss ((__m128) __C,
+ (__m128)
+ __builtin_ia32_vfmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ __D, __E));
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmadd_round_sch (__mmask8 __A, __m128h __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfmaddcsh_maskz_round ((__v8hf) __B,
+ (__v8hf) __C,
+ (__v8hf) __D,
+ __A, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmadd_round_sch (__m128h __A, __m128h __B, __m128h __C, const int __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfmaddcsh_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ __D);
+}
+#else
+#ifdef __AVX512VL__
+#define _mm_mask_fcmadd_round_sch(A, B, C, D, E) \
+ ((__m128h) __builtin_ia32_movaps128_mask ( \
+ (__v4sf) \
+ __builtin_ia32_vfcmaddcsh_mask_round ((__v8hf) (A), \
+ (__v8hf) (C), \
+ (__v8hf) (D), \
+ (B), (E)), \
+ (__v4sf) (A), (B)))
+
+#else
+#define _mm_mask_fcmadd_round_sch(A, B, C, D, E) \
+ ((__m128h) __builtin_ia32_blendvps ((__v4sf) (A), \
+ (__v4sf) \
+ __builtin_ia32_vfcmaddcsh_mask_round ((__v8hf) (A), \
+ (__v8hf) (C), \
+ (__v8hf) (D), \
+ (B), (E)), \
+ (__v4sf) _mm_set_ss ((float) ((int) (B) << 31))))
+#endif
+
+#define _mm_mask3_fcmadd_round_sch(A, B, C, D, E) \
+ ((__m128h) _mm_move_ss ((__m128) (C), \
+ (__m128) \
+ __builtin_ia32_vfcmaddcsh_mask_round ((__v8hf) (A), \
+ (__v8hf) (B), \
+ (__v8hf) (C), \
+ (D), (E))))
+
+#define _mm_maskz_fcmadd_round_sch(A, B, C, D, E) \
+ __builtin_ia32_vfcmaddcsh_maskz_round ((B), (C), (D), (A), (E))
+
+#define _mm_fcmadd_round_sch(A, B, C, D) \
+ __builtin_ia32_vfcmaddcsh_round ((A), (B), (C), (D))
+
+#ifdef __AVX512VL__
+#define _mm_mask_fmadd_round_sch(A, B, C, D, E) \
+ ((__m128h) __builtin_ia32_movaps128_mask ( \
+ (__v4sf) \
+ __builtin_ia32_vfmaddcsh_mask_round ((__v8hf) (A), \
+ (__v8hf) (C), \
+ (__v8hf) (D), \
+ (B), (E)), \
+ (__v4sf) (A), (B)))
+
+#else
+#define _mm_mask_fmadd_round_sch(A, B, C, D, E) \
+ ((__m128h) __builtin_ia32_blendvps ((__v4sf) (A), \
+ (__v4sf) \
+ __builtin_ia32_vfmaddcsh_mask_round ((__v8hf) (A), \
+ (__v8hf) (C), \
+ (__v8hf) (D), \
+ (B), (E)), \
+ (__v4sf) _mm_set_ss ((float) ((int) (B) << 31))))
+#endif
+
+#define _mm_mask3_fmadd_round_sch(A, B, C, D, E) \
+ ((__m128h) _mm_move_ss ((__m128) (C), \
+ (__m128) \
+ __builtin_ia32_vfmaddcsh_mask_round ((__v8hf) (A), \
+ (__v8hf) (B), \
+ (__v8hf) (C), \
+ (D), (E))))
+
+#define _mm_maskz_fmadd_round_sch(A, B, C, D, E) \
+ __builtin_ia32_vfmaddcsh_maskz_round ((B), (C), (D), (A), (E))
+
+#define _mm_fmadd_round_sch(A, B, C, D) \
+ __builtin_ia32_vfmaddcsh_round ((A), (B), (C), (D))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vf[,c]mulcsh. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fcmul_sch (__m128h __A, __m128h __B)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmulcsh_round ((__v8hf) __A,
+ (__v8hf) __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fcmul_sch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __C,
+ (__v8hf) __D,
+ (__v8hf) __A,
+ __B, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fcmul_sch (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __B,
+ (__v8hf) __C,
+ _mm_setzero_ph (),
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmul_sch (__m128h __A, __m128h __B)
+{
+ return (__m128h)
+ __builtin_ia32_vfmulcsh_round ((__v8hf) __A,
+ (__v8hf) __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmul_sch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __C,
+ (__v8hf) __D,
+ (__v8hf) __A,
+ __B, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmul_sch (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return (__m128h)
+ __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __B,
+ (__v8hf) __C,
+ _mm_setzero_ph (),
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fcmul_round_sch (__m128h __A, __m128h __B, const int __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmulcsh_round ((__v8hf) __A,
+ (__v8hf) __B,
+ __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fcmul_round_sch (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __C,
+ (__v8hf) __D,
+ (__v8hf) __A,
+ __B, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fcmul_round_sch (__mmask8 __A, __m128h __B, __m128h __C,
+ const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __B,
+ (__v8hf) __C,
+ _mm_setzero_ph (),
+ __A, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmul_round_sch (__m128h __A, __m128h __B, const int __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfmulcsh_round ((__v8hf) __A,
+ (__v8hf) __B, __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmul_round_sch (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __C,
+ (__v8hf) __D,
+ (__v8hf) __A,
+ __B, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmul_round_sch (__mmask8 __A, __m128h __B, __m128h __C, const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __B,
+ (__v8hf) __C,
+ _mm_setzero_ph (),
+ __A, __E);
+}
+
+#else
+#define _mm_fcmul_round_sch(__A, __B, __D) \
+ (__m128h) __builtin_ia32_vfcmulcsh_round ((__v8hf) __A, \
+ (__v8hf) __B, __D)
+
+#define _mm_mask_fcmul_round_sch(__A, __B, __C, __D, __E) \
+ (__m128h) __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __C, \
+ (__v8hf) __D, \
+ (__v8hf) __A, \
+ __B, __E)
+
+#define _mm_maskz_fcmul_round_sch(__A, __B, __C, __E) \
+ (__m128h) __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __B, \
+ (__v8hf) __C, \
+ _mm_setzero_ph (), \
+ __A, __E)
+
+#define _mm_fmul_round_sch(__A, __B, __D) \
+ (__m128h) __builtin_ia32_vfmulcsh_round ((__v8hf) __A, \
+ (__v8hf) __B, __D)
+
+#define _mm_mask_fmul_round_sch(__A, __B, __C, __D, __E) \
+ (__m128h) __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __C, \
+ (__v8hf) __D, \
+ (__v8hf) __A, \
+ __B, __E)
+
+#define _mm_maskz_fmul_round_sch(__A, __B, __C, __E) \
+ (__m128h) __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __B, \
+ (__v8hf) __C, \
+ _mm_setzero_ph (), \
+ __A, __E)
+
+#endif /* __OPTIMIZE__ */
+
+#define _MM512_REDUCE_OP(op) \
+ __m256h __T1 = (__m256h) _mm512_extractf64x4_pd ((__m512d) __A, 0); \
+ __m256h __T2 = (__m256h) _mm512_extractf64x4_pd ((__m512d) __A, 1); \
+ __m256h __T3 = (__T1 op __T2); \
+ __m128h __T4 = (__m128h) _mm256_extractf128_pd ((__m256d) __T3, 0); \
+ __m128h __T5 = (__m128h) _mm256_extractf128_pd ((__m256d) __T3, 1); \
+ __m128h __T6 = (__T4 op __T5); \
+ __m128h __T7 = (__m128h) __builtin_shuffle ((__m128h)__T6, \
+ (__v8hi) { 4, 5, 6, 7, 0, 1, 2, 3 }); \
+ __m128h __T8 = (__T6 op __T7); \
+ __m128h __T9 = (__m128h) __builtin_shuffle ((__m128h)__T8, \
+ (__v8hi) { 2, 3, 0, 1, 4, 5, 6, 7 }); \
+ __m128h __T10 = __T8 op __T9; \
+ return __T10[0] op __T10[1]
+
+// TODO reduce
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_reduce_add_ph (__m512h __A)
+{
+ _MM512_REDUCE_OP (+);
+}
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_reduce_mul_ph (__m512h __A)
+{
+ _MM512_REDUCE_OP (*);
+}
+
+#undef _MM512_REDUCE_OP
+
+#ifdef __AVX512VL__
+
+#define _MM512_REDUCE_OP(op) \
+ __m256h __T1 = (__m256h) _mm512_extractf64x4_pd ((__m512d) __A, 0); \
+ __m256h __T2 = (__m256h) _mm512_extractf64x4_pd ((__m512d) __A, 1); \
+ __m256h __T3 = __builtin_ia32_##op##ph256_mask (__T1, __T2, \
+ _mm256_setzero_ph (), (__mmask16) -1); \
+ __m128h __T4 = (__m128h) _mm256_extractf128_pd ((__m256d) __T3, 0); \
+ __m128h __T5 = (__m128h) _mm256_extractf128_pd ((__m256d) __T3, 1); \
+ __m128h __T6 = __builtin_ia32_##op##ph128_mask \
+ (__T4, __T5, _mm_setzero_ph (),(__mmask8) -1); \
+ __m128h __T7 = (__m128h) __builtin_shuffle ((__m128h)__T6, \
+ (__v8hi) { 2, 3, 0, 1, 6, 7, 4, 5 }); \
+ __m128h __T8 = (__m128h) __builtin_ia32_##op##ph128_mask \
+ (__T6, __T7, _mm_setzero_ph (),(__mmask8) -1); \
+ __m128h __T9 = (__m128h) __builtin_shuffle ((__m128h)__T8, \
+ (__v8hi) { 4, 5 }); \
+ __m128h __T10 = __builtin_ia32_##op##ph128_mask \
+ (__T8, __T9, _mm_setzero_ph (),(__mmask8) -1); \
+ __m128h __T11 = (__m128h) __builtin_shuffle (__T10, \
+ (__v8hi) { 1, 0 }); \
+ __m128h __T12 = __builtin_ia32_##op##ph128_mask \
+ (__T10, __T11, _mm_setzero_ph (),(__mmask8) -1); \
+ return __T12[0]
+
+#else
+
+#define _MM512_REDUCE_OP(op) \
+ __m512h __T1 = (__m512h) __builtin_shuffle ((__m512d) __A, \
+ (__v8di) { 4, 5, 6, 7, 0, 0, 0, 0 }); \
+ __m512h __T2 = _mm512_##op##_ph (__A, __T1); \
+ __m512h __T3 = (__m512h) __builtin_shuffle ((__m512d) __T2, \
+ (__v8di) { 2, 3, 0, 0, 0, 0, 0, 0 }); \
+ __m512h __T4 = _mm512_##op##_ph (__T2, __T3); \
+ __m512h __T5 = (__m512h) __builtin_shuffle ((__m512d) __T4, \
+ (__v8di) { 1, 0, 0, 0, 0, 0, 0, 0 }); \
+ __m512h __T6 = _mm512_##op##_ph (__T4, __T5); \
+ __m512h __T7 = (__m512h) __builtin_shuffle ((__m512) __T6, \
+ (__v16si) { 1, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0 }); \
+ __m512h __T8 = _mm512_##op##_ph (__T6, __T7); \
+ __m512h __T9 = (__m512h) __builtin_shuffle (__T8, \
+ (__v32hi) { 1, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0 }); \
+ __m512h __T10 = _mm512_##op##_ph (__T8, __T9); \
+ return __T10[0]
+#endif
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_reduce_min_ph (__m512h __A)
+{
+ _MM512_REDUCE_OP (min);
+}
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_reduce_max_ph (__m512h __A)
+{
+ _MM512_REDUCE_OP (max);
+}
+
+#undef _MM512_REDUCE_OP
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_blend_ph (__mmask32 __U, __m512h __A, __m512h __W)
+{
+ return (__m512h) __builtin_ia32_movdquhi512_mask ((__v32hi) __W,
+ (__v32hi) __A,
+ (__mmask32) __U);
+
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_permutex2var_ph (__m512h __A, __m512i __I, __m512h __B)
+{
+ return (__m512h) __builtin_ia32_vpermi2varhi512_mask ((__v32hi) __A,
+ (__v32hi) __I,
+ (__v32hi) __B,
+ (__mmask32)-1);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_permutexvar_ph (__m512i __A, __m512h __B)
+{
+ return (__m512h) __builtin_ia32_permvarhi512_mask ((__v32hi) __B,
+ (__v32hi) __A,
+ (__v32hi)
+ (_mm512_setzero_ph ()),
+ (__mmask32)-1);
+}
+
#ifdef __DISABLE_AVX512FP16__
#undef __DISABLE_AVX512FP16__
#pragma GCC pop_options
diff --git a/gcc/config/i386/avx512fp16vlintrin.h b/gcc/config/i386/avx512fp16vlintrin.h
index 1292c02..3d3de96 100644
--- a/gcc/config/i386/avx512fp16vlintrin.h
+++ b/gcc/config/i386/avx512fp16vlintrin.h
@@ -151,6 +151,59 @@ _mm256_zextph128_ph256 (__m128h __A)
(__m128) __A, 0);
}
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_conj_pch (__m256h __A)
+{
+ return (__m256h) _mm256_xor_epi32 ((__m256i) __A, _mm256_set1_epi32 (1<<31));
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_conj_pch (__m256h __W, __mmask8 __U, __m256h __A)
+{
+ return (__m256h) __builtin_ia32_movaps256_mask ((__v8sf)
+ _mm256_conj_pch (__A),
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_conj_pch (__mmask8 __U, __m256h __A)
+{
+ return (__m256h) __builtin_ia32_movaps256_mask ((__v8sf)
+ _mm256_conj_pch (__A),
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_conj_pch (__m128h __A)
+{
+ return (__m128h) _mm_xor_epi32 ((__m128i) __A, _mm_set1_epi32 (1<<31));
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_conj_pch (__m128h __W, __mmask8 __U, __m128h __A)
+{
+ return (__m128h) __builtin_ia32_movaps128_mask ((__v4sf) _mm_conj_pch (__A),
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_conj_pch (__mmask8 __U, __m128h __A)
+{
+ return (__m128h) __builtin_ia32_movaps128_mask ((__v4sf) _mm_conj_pch (__A),
+ (__v4sf) _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
/* Intrinsics v[add,sub,mul,div]ph. */
extern __inline __m128h
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
@@ -425,6 +478,22 @@ _mm256_maskz_min_ph (__mmask16 __A, __m256h __B, __m256h __C)
_mm256_setzero_ph (), __A);
}
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_abs_ph (__m128h __A)
+{
+ return (__m128h) _mm_and_si128 ( _mm_set1_epi32 (0x7FFF7FFF),
+ (__m128i) __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_abs_ph (__m256h __A)
+{
+ return (__m256h) _mm256_and_si256 ( _mm256_set1_epi32 (0x7FFF7FFF),
+ (__m256i) __A);
+}
+
/* vcmpph */
#ifdef __OPTIMIZE
extern __inline __mmask8
@@ -2815,6 +2884,437 @@ _mm_maskz_fnmsub_ph (__mmask8 __U, __m128h __A, __m128h __B,
__U);
}
+/* Intrinsics vf[,c]maddcph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmadd_pch (__m128h __A, __m128h __B, __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfmaddcph128 ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmadd_pch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return (__m128h) __builtin_ia32_movaps128_mask
+ ((__v4sf)
+ __builtin_ia32_vfmaddcph128_mask ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D, __B),
+ (__v4sf) __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fmadd_pch (__m128h __A, __m128h __B, __m128h __C, __mmask8 __D)
+{
+ return (__m128h) __builtin_ia32_vfmaddcph128_mask ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C, __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmadd_pch (__mmask8 __A, __m128h __B, __m128h __C, __m128h __D)
+{
+ return (__m128h) __builtin_ia32_vfmaddcph128_maskz ((__v8hf) __B,
+ (__v8hf) __C,
+ (__v8hf) __D, __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_fmadd_pch (__m256h __A, __m256h __B, __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfmaddcph256 ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_fmadd_pch (__m256h __A, __mmask8 __B, __m256h __C, __m256h __D)
+{
+ return (__m256h) __builtin_ia32_movaps256_mask
+ ((__v8sf)
+ __builtin_ia32_vfmaddcph256_mask ((__v16hf) __A,
+ (__v16hf) __C,
+ (__v16hf) __D, __B),
+ (__v8sf) __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask3_fmadd_pch (__m256h __A, __m256h __B, __m256h __C, __mmask8 __D)
+{
+ return (__m256h) __builtin_ia32_vfmaddcph256_mask ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C, __D);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_fmadd_pch (__mmask8 __A, __m256h __B, __m256h __C, __m256h __D)
+{
+ return (__m256h)__builtin_ia32_vfmaddcph256_maskz ((__v16hf) __B,
+ (__v16hf) __C,
+ (__v16hf) __D, __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fcmadd_pch (__m128h __A, __m128h __B, __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfcmaddcph128 ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fcmadd_pch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return (__m128h) __builtin_ia32_movaps128_mask
+ ((__v4sf)
+ __builtin_ia32_vfcmaddcph128_mask ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D, __B),
+ (__v4sf) __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fcmadd_pch (__m128h __A, __m128h __B, __m128h __C, __mmask8 __D)
+{
+ return (__m128h) __builtin_ia32_vfcmaddcph128_mask ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C, __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fcmadd_pch (__mmask8 __A, __m128h __B, __m128h __C, __m128h __D)
+{
+ return (__m128h)__builtin_ia32_vfcmaddcph128_maskz ((__v8hf) __B,
+ (__v8hf) __C,
+ (__v8hf) __D, __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_fcmadd_pch (__m256h __A, __m256h __B, __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfcmaddcph256 ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_fcmadd_pch (__m256h __A, __mmask8 __B, __m256h __C, __m256h __D)
+{
+ return (__m256h) __builtin_ia32_movaps256_mask
+ ((__v8sf)
+ __builtin_ia32_vfcmaddcph256_mask ((__v16hf) __A,
+ (__v16hf) __C,
+ (__v16hf) __D, __B),
+ (__v8sf) __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask3_fcmadd_pch (__m256h __A, __m256h __B, __m256h __C, __mmask8 __D)
+{
+ return (__m256h) __builtin_ia32_vfcmaddcph256_mask ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C, __D);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_fcmadd_pch (__mmask8 __A, __m256h __B, __m256h __C, __m256h __D)
+{
+ return (__m256h) __builtin_ia32_vfcmaddcph256_maskz ((__v16hf) __B,
+ (__v16hf) __C,
+ (__v16hf) __D, __A);
+}
+
+/* Intrinsics vf[,c]mulcph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmul_pch (__m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfmulcph128 ((__v8hf) __A, (__v8hf) __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmul_pch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return (__m128h) __builtin_ia32_vfmulcph128_mask ((__v8hf) __C,
+ (__v8hf) __D,
+ (__v8hf) __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmul_pch (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfmulcph128_mask ((__v8hf) __B,
+ (__v8hf) __C,
+ _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_fmul_pch (__m256h __A, __m256h __B)
+{
+ return (__m256h) __builtin_ia32_vfmulcph256 ((__v16hf) __A,
+ (__v16hf) __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_fmul_pch (__m256h __A, __mmask8 __B, __m256h __C, __m256h __D)
+{
+ return (__m256h) __builtin_ia32_vfmulcph256_mask ((__v16hf) __C,
+ (__v16hf) __D,
+ (__v16hf) __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_fmul_pch (__mmask8 __A, __m256h __B, __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfmulcph256_mask ((__v16hf) __B,
+ (__v16hf) __C,
+ _mm256_setzero_ph (),
+ __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fcmul_pch (__m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfcmulcph128 ((__v8hf) __A,
+ (__v8hf) __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fcmul_pch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return (__m128h) __builtin_ia32_vfcmulcph128_mask ((__v8hf) __C,
+ (__v8hf) __D,
+ (__v8hf) __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fcmul_pch (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfcmulcph128_mask ((__v8hf) __B,
+ (__v8hf) __C,
+ _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_fcmul_pch (__m256h __A, __m256h __B)
+{
+ return (__m256h) __builtin_ia32_vfcmulcph256 ((__v16hf) __A, (__v16hf) __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_fcmul_pch (__m256h __A, __mmask8 __B, __m256h __C, __m256h __D)
+{
+ return (__m256h) __builtin_ia32_vfcmulcph256_mask ((__v16hf) __C,
+ (__v16hf) __D,
+ (__v16hf) __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_fcmul_pch (__mmask8 __A, __m256h __B, __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfcmulcph256_mask ((__v16hf) __B,
+ (__v16hf) __C,
+ _mm256_setzero_ph (),
+ __A);
+}
+
+#define _MM256_REDUCE_OP(op) \
+ __m128h __T1 = (__m128h) _mm256_extractf128_pd ((__m256d) __A, 0); \
+ __m128h __T2 = (__m128h) _mm256_extractf128_pd ((__m256d) __A, 1); \
+ __m128h __T3 = (__T1 op __T2); \
+ __m128h __T4 = (__m128h) __builtin_shuffle (__T3, \
+ (__v8hi) { 4, 5, 6, 7, 0, 1, 2, 3 }); \
+ __m128h __T5 = (__T3) op (__T4); \
+ __m128h __T6 = (__m128h) __builtin_shuffle (__T5, \
+ (__v8hi) { 2, 3, 0, 1, 4, 5, 6, 7 }); \
+ __m128h __T7 = __T5 op __T6; \
+ return __T7[0] op __T7[1]
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_reduce_add_ph (__m256h __A)
+{
+ _MM256_REDUCE_OP (+);
+}
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_reduce_mul_ph (__m256h __A)
+{
+ _MM256_REDUCE_OP (*);
+}
+
+#undef _MM256_REDUCE_OP
+#define _MM256_REDUCE_OP(op) \
+ __m128h __T1 = (__m128h) _mm256_extractf128_pd ((__m256d) __A, 0); \
+ __m128h __T2 = (__m128h) _mm256_extractf128_pd ((__m256d) __A, 1); \
+ __m128h __T3 = _mm_##op (__T1, __T2); \
+ __m128h __T4 = (__m128h) __builtin_shuffle (__T3, \
+ (__v8hi) { 2, 3, 0, 1, 6, 7, 4, 5 }); \
+ __m128h __T5 = _mm_##op (__T3, __T4); \
+ __m128h __T6 = (__m128h) __builtin_shuffle (__T5, (__v8hi) { 4, 5 }); \
+ __m128h __T7 = _mm_##op (__T5, __T6); \
+ __m128h __T8 = (__m128h) __builtin_shuffle (__T7, (__v8hi) { 1, 0 }); \
+ __m128h __T9 = _mm_##op (__T7, __T8); \
+ return __T9[0]
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_reduce_min_ph (__m256h __A)
+{
+ _MM256_REDUCE_OP (min_ph);
+}
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_reduce_max_ph (__m256h __A)
+{
+ _MM256_REDUCE_OP (max_ph);
+}
+
+#define _MM_REDUCE_OP(op) \
+ __m128h __T1 = (__m128h) __builtin_shuffle (__A, \
+ (__v8hi) { 4, 5, 6, 7, 0, 1, 2, 3 }); \
+ __m128h __T2 = (__A) op (__T1); \
+ __m128h __T3 = (__m128h) __builtin_shuffle (__T2, \
+ (__v8hi){ 2, 3, 0, 1, 4, 5, 6, 7 }); \
+ __m128h __T4 = __T2 op __T3; \
+ return __T4[0] op __T4[1]
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_reduce_add_ph (__m128h __A)
+{
+ _MM_REDUCE_OP (+);
+}
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_reduce_mul_ph (__m128h __A)
+{
+ _MM_REDUCE_OP (*);
+}
+
+#undef _MM_REDUCE_OP
+#define _MM_REDUCE_OP(op) \
+ __m128h __T1 = (__m128h) __builtin_shuffle (__A, \
+ (__v8hi) { 2, 3, 0, 1, 6, 7, 4, 5 }); \
+ __m128h __T2 = _mm_##op (__A, __T1); \
+ __m128h __T3 = (__m128h) __builtin_shuffle (__T2, (__v8hi){ 4, 5 }); \
+ __m128h __T4 = _mm_##op (__T2, __T3); \
+ __m128h __T5 = (__m128h) __builtin_shuffle (__T4, (__v8hi){ 1, 0 }); \
+ __m128h __T6 = _mm_##op (__T4, __T5); \
+ return __T6[0]
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_reduce_min_ph (__m128h __A)
+{
+ _MM_REDUCE_OP (min_ph);
+}
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_reduce_max_ph (__m128h __A)
+{
+ _MM_REDUCE_OP (max_ph);
+}
+
+#undef _MM256_REDUCE_OP
+#undef _MM_REDUCE_OP
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_blend_ph (__mmask16 __U, __m256h __A, __m256h __W)
+{
+ return (__m256h) __builtin_ia32_movdquhi256_mask ((__v16hi) __W,
+ (__v16hi) __A,
+ (__mmask16) __U);
+
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_permutex2var_ph (__m256h __A, __m256i __I, __m256h __B)
+{
+ return (__m256h) __builtin_ia32_vpermi2varhi256_mask ((__v16hi) __A,
+ (__v16hi) __I,
+ (__v16hi) __B,
+ (__mmask16)-1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_permutexvar_ph (__m256i __A, __m256h __B)
+{
+ return (__m256h) __builtin_ia32_permvarhi256_mask ((__v16hi) __B,
+ (__v16hi) __A,
+ (__v16hi)
+ (_mm256_setzero_ph ()),
+ (__mmask16)-1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_blend_ph (__mmask8 __U, __m128h __A, __m128h __W)
+{
+ return (__m128h) __builtin_ia32_movdquhi128_mask ((__v8hi) __W,
+ (__v8hi) __A,
+ (__mmask8) __U);
+
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_permutex2var_ph (__m128h __A, __m128i __I, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vpermi2varhi128_mask ((__v8hi) __A,
+ (__v8hi) __I,
+ (__v8hi) __B,
+ (__mmask8)-1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_permutexvar_ph (__m128i __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_permvarhi128_mask ((__v8hi) __B,
+ (__v8hi) __A,
+ (__v8hi)
+ (_mm_setzero_ph ()),
+ (__mmask8)-1);
+}
+
#ifdef __DISABLE_AVX512FP16VL__
#undef __DISABLE_AVX512FP16VL__
#pragma GCC pop_options
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 5eae4d0..4c355c5 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -1348,6 +1348,7 @@ DEF_FUNCTION_TYPE (V8DI, V8HF, V8DI, UQI, INT)
DEF_FUNCTION_TYPE (V8DF, V8HF, V8DF, UQI, INT)
DEF_FUNCTION_TYPE (V8HF, V8DI, V8HF, UQI, INT)
DEF_FUNCTION_TYPE (V8HF, V8DF, V8HF, UQI, INT)
+DEF_FUNCTION_TYPE (V8HF, V8HF, V8HF, V8HF)
DEF_FUNCTION_TYPE (V8HF, V8HF, V8HF, V8HF, UQI, INT)
DEF_FUNCTION_TYPE (V8HF, V2DF, V8HF, V8HF, UQI, INT)
DEF_FUNCTION_TYPE (V8HF, V4SF, V8HF, V8HF, UQI, INT)
@@ -1358,12 +1359,14 @@ DEF_FUNCTION_TYPE (V16HF, V16HF, V16HF)
DEF_FUNCTION_TYPE (V16HI, V16HF, V16HI, UHI)
DEF_FUNCTION_TYPE (V16HF, V16HI, V16HF, UHI)
DEF_FUNCTION_TYPE (V16HF, V16HF, V16HF, UHI)
+DEF_FUNCTION_TYPE (V16HF, V16HF, V16HF, V16HF)
DEF_FUNCTION_TYPE (V16SI, V16HF, V16SI, UHI, INT)
DEF_FUNCTION_TYPE (V16SF, V16HF, V16SF, UHI, INT)
DEF_FUNCTION_TYPE (V16HF, V16HF, INT, V16HF, UHI)
DEF_FUNCTION_TYPE (UHI, V16HF, V16HF, INT, UHI)
DEF_FUNCTION_TYPE (V16HF, V16SI, V16HF, UHI, INT)
DEF_FUNCTION_TYPE (V16HF, V16SF, V16HF, UHI, INT)
+DEF_FUNCTION_TYPE (V16HF, V16HF, V16HF, V16HF, UQI)
DEF_FUNCTION_TYPE (V16HF, V16HF, V16HF, V16HF, UHI)
DEF_FUNCTION_TYPE (V32HF, V32HF, V32HF, USI)
DEF_FUNCTION_TYPE (V32HF, V32HF, V32HF, INT)
@@ -1371,7 +1374,9 @@ DEF_FUNCTION_TYPE (V32HI, V32HF, V32HI, USI, INT)
DEF_FUNCTION_TYPE (V32HF, V32HI, V32HF, USI, INT)
DEF_FUNCTION_TYPE (USI, V32HF, V32HF, INT, USI)
DEF_FUNCTION_TYPE (V32HF, V32HF, V32HF, USI, INT)
+DEF_FUNCTION_TYPE (V32HF, V32HF, V32HF, V32HF, INT)
DEF_FUNCTION_TYPE (V32HF, V32HF, V32HF, V32HF, USI)
DEF_FUNCTION_TYPE (USI, V32HF, V32HF, INT, USI, INT)
+DEF_FUNCTION_TYPE (V32HF, V32HF, V32HF, V32HF, UHI, INT)
DEF_FUNCTION_TYPE (V32HF, V32HF, V32HF, V32HF, USI, INT)
DEF_FUNCTION_TYPE (V32HF, V32HF, INT, V32HF, USI, INT)
diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def
index 5950d5e..302e1bc 100644
--- a/gcc/config/i386/i386-builtin.def
+++ b/gcc/config/i386/i386-builtin.def
@@ -2911,6 +2911,26 @@ BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_
BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fnmsub_v8hf_mask, "__builtin_ia32_vfnmsubph128_mask", IX86_BUILTIN_VFNMSUBPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fnmsub_v8hf_mask3, "__builtin_ia32_vfnmsubph128_mask3", IX86_BUILTIN_VFNMSUBPH128_MASK3, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fnmsub_v8hf_maskz, "__builtin_ia32_vfnmsubph128_maskz", IX86_BUILTIN_VFNMSUBPH128_MASKZ, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_fma_fmaddc_v8hf, "__builtin_ia32_vfmaddcph128", IX86_BUILTIN_VFMADDCPH_V8HF, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmaddc_v8hf_mask, "__builtin_ia32_vfmaddcph128_mask", IX86_BUILTIN_VFMADDCPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmaddc_v8hf_maskz, "__builtin_ia32_vfmaddcph128_maskz", IX86_BUILTIN_VFMADDCPH128_MASKZ, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_fma_fmaddc_v16hf, "__builtin_ia32_vfmaddcph256", IX86_BUILTIN_VFMADDCPH_V16HF, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmaddc_v16hf_mask, "__builtin_ia32_vfmaddcph256_mask", IX86_BUILTIN_VFMADDCPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmaddc_v16hf_maskz, "__builtin_ia32_vfmaddcph256_maskz", IX86_BUILTIN_VFMADDCPH256_MASKZ, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_fma_fcmaddc_v8hf, "__builtin_ia32_vfcmaddcph128", IX86_BUILTIN_VFCMADDCPH_V8HF, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmaddc_v8hf_mask, "__builtin_ia32_vfcmaddcph128_mask", IX86_BUILTIN_VFCMADDCPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmaddc_v8hf_maskz, "__builtin_ia32_vfcmaddcph128_maskz", IX86_BUILTIN_VFCMADDCPH128_MASKZ, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_fma_fcmaddc_v16hf, "__builtin_ia32_vfcmaddcph256", IX86_BUILTIN_VFCMADDCPH_V16HF, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fcmaddc_v16hf_mask, "__builtin_ia32_vfcmaddcph256_mask", IX86_BUILTIN_VFCMADDCPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fcmaddc_v16hf_maskz, "__builtin_ia32_vfcmaddcph256_maskz", IX86_BUILTIN_VFCMADDCPH256_MASKZ, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmulc_v8hf, "__builtin_ia32_vfcmulcph128", IX86_BUILTIN_VFCMULCPH_V8HF, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmulc_v8hf_mask, "__builtin_ia32_vfcmulcph128_mask", IX86_BUILTIN_VFCMULCPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fcmulc_v16hf, "__builtin_ia32_vfcmulcph256", IX86_BUILTIN_VFCMULCPH_V16HF, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fcmulc_v16hf_mask, "__builtin_ia32_vfcmulcph256_mask", IX86_BUILTIN_VFCMULCPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmulc_v8hf, "__builtin_ia32_vfmulcph128", IX86_BUILTIN_VFMULCPH_V8HF, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmulc_v8hf_mask, "__builtin_ia32_vfmulcph128_mask", IX86_BUILTIN_VFMULCPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmulc_v16hf, "__builtin_ia32_vfmulcph256", IX86_BUILTIN_VFMULCPH_V16HF, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmulc_v16hf_mask, "__builtin_ia32_vfmulcph256_mask", IX86_BUILTIN_VFMULCPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UQI)
/* Builtins with rounding support. */
BDESC_END (ARGS, ROUND_ARGS)
@@ -3201,6 +3221,26 @@ BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_vmfnmadd_v8hf_mask_round
BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_vmfnmadd_v8hf_mask3_round, "__builtin_ia32_vfnmaddsh3_mask3", IX86_BUILTIN_VFNMADDSH3_MASK3, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_vmfnmadd_v8hf_maskz_round, "__builtin_ia32_vfnmaddsh3_maskz", IX86_BUILTIN_VFNMADDSH3_MASKZ, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_vmfmsub_v8hf_mask3_round, "__builtin_ia32_vfmsubsh3_mask3", IX86_BUILTIN_VFMSUBSH3_MASK3, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_fma_fmaddc_v32hf_round, "__builtin_ia32_vfmaddcph512_round", IX86_BUILTIN_VFMADDCPH512_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmaddc_v32hf_mask_round, "__builtin_ia32_vfmaddcph512_mask_round", IX86_BUILTIN_VFMADDCPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmaddc_v32hf_maskz_round, "__builtin_ia32_vfmaddcph512_maskz_round", IX86_BUILTIN_VFMADDCPH512_MASKZ_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_fma_fcmaddc_v32hf_round, "__builtin_ia32_vfcmaddcph512_round", IX86_BUILTIN_VFCMADDCPH512_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fcmaddc_v32hf_mask_round, "__builtin_ia32_vfcmaddcph512_mask_round", IX86_BUILTIN_VFCMADDCPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fcmaddc_v32hf_maskz_round, "__builtin_ia32_vfcmaddcph512_maskz_round", IX86_BUILTIN_VFCMADDCPH512_MASKZ_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fcmulc_v32hf_round, "__builtin_ia32_vfcmulcph512_round", IX86_BUILTIN_VFCMULCPH512_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fcmulc_v32hf_mask_round, "__builtin_ia32_vfcmulcph512_mask_round", IX86_BUILTIN_VFCMULCPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmulc_v32hf_round, "__builtin_ia32_vfmulcph512_round", IX86_BUILTIN_VFMULCPH512_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmulc_v32hf_mask_round, "__builtin_ia32_vfmulcph512_mask_round", IX86_BUILTIN_VFMULCPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fma_fcmaddcsh_v8hf_round, "__builtin_ia32_vfcmaddcsh_round", IX86_BUILTIN_VFCMADDCSH_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmaddcsh_v8hf_mask_round, "__builtin_ia32_vfcmaddcsh_mask_round", IX86_BUILTIN_VFCMADDCSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmaddcsh_v8hf_maskz_round, "__builtin_ia32_vfcmaddcsh_maskz_round", IX86_BUILTIN_VFCMADDCSH_MASKZ_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fma_fmaddcsh_v8hf_round, "__builtin_ia32_vfmaddcsh_round", IX86_BUILTIN_VFMADDCSH_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmaddcsh_v8hf_mask_round, "__builtin_ia32_vfmaddcsh_mask_round", IX86_BUILTIN_VFMADDCSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmaddcsh_v8hf_maskz_round, "__builtin_ia32_vfmaddcsh_maskz_round", IX86_BUILTIN_VFMADDCSH_MASKZ_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmulcsh_v8hf_round, "__builtin_ia32_vfcmulcsh_round", IX86_BUILTIN_VFCMULCSH_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmulcsh_v8hf_mask_round, "__builtin_ia32_vfcmulcsh_mask_round", IX86_BUILTIN_VFCMULCSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmulcsh_v8hf_round, "__builtin_ia32_vfmulcsh_round", IX86_BUILTIN_VFMULCSH_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmulcsh_v8hf_mask_round, "__builtin_ia32_vfmulcsh_mask_round", IX86_BUILTIN_VFMULCSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
BDESC_END (ROUND_ARGS, MULTI_ARG)
diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c
index c88cb14..4780b99 100644
--- a/gcc/config/i386/i386-expand.c
+++ b/gcc/config/i386/i386-expand.c
@@ -3638,6 +3638,8 @@ ix86_use_mask_cmp_p (machine_mode mode, machine_mode cmp_mode,
return false;
else if (vector_size == 64)
return true;
+ else if (GET_MODE_INNER (cmp_mode) == HFmode)
+ return true;
/* When op_true is NULL, op_false must be NULL, or vice versa. */
gcc_assert (!op_true == !op_false);
@@ -9762,6 +9764,7 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case V2DI_FTYPE_V8HF_V2DI_UQI:
case V2DI_FTYPE_V4SF_V2DI_UQI:
case V8HF_FTYPE_V8HF_V8HF_UQI:
+ case V8HF_FTYPE_V8HF_V8HF_V8HF:
case V8HF_FTYPE_V8HI_V8HF_UQI:
case V8HF_FTYPE_V8SI_V8HF_UQI:
case V8HF_FTYPE_V8SF_V8HF_UQI:
@@ -9840,6 +9843,7 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case V16SF_FTYPE_V8SF_V16SF_UHI:
case V16SI_FTYPE_V8SI_V16SI_UHI:
case V16HF_FTYPE_V16HI_V16HF_UHI:
+ case V16HF_FTYPE_V16HF_V16HF_V16HF:
case V16HI_FTYPE_V16HF_V16HI_UHI:
case V16HI_FTYPE_V16HI_V16HI_UHI:
case V8HI_FTYPE_V16QI_V8HI_UQI:
@@ -9996,6 +10000,7 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case V8HI_FTYPE_V8HI_V8HI_V8HI_UQI:
case V8SI_FTYPE_V8SI_V8SI_V8SI_UQI:
case V4SI_FTYPE_V4SI_V4SI_V4SI_UQI:
+ case V16HF_FTYPE_V16HF_V16HF_V16HF_UQI:
case V16HF_FTYPE_V16HF_V16HF_V16HF_UHI:
case V8SF_FTYPE_V8SF_V8SF_V8SF_UQI:
case V16QI_FTYPE_V16QI_V16QI_V16QI_UHI:
@@ -10725,6 +10730,7 @@ ix86_expand_round_builtin (const struct builtin_description *d,
case V16SF_FTYPE_V16HF_V16SF_UHI_INT:
case V32HF_FTYPE_V32HI_V32HF_USI_INT:
case V32HF_FTYPE_V32HF_V32HF_USI_INT:
+ case V32HF_FTYPE_V32HF_V32HF_V32HF_INT:
case V16SF_FTYPE_V16SF_V16SF_HI_INT:
case V8DI_FTYPE_V8SF_V8DI_QI_INT:
case V16SF_FTYPE_V16SI_V16SF_HI_INT:
@@ -10754,6 +10760,7 @@ ix86_expand_round_builtin (const struct builtin_description *d,
case V4SF_FTYPE_V4SF_V4SF_V4SF_UQI_INT:
case V4SF_FTYPE_V8HF_V4SF_V4SF_UQI_INT:
case V16SF_FTYPE_V16SF_V16SF_V16SF_HI_INT:
+ case V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT:
case V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT:
case V2DF_FTYPE_V8HF_V2DF_V2DF_UQI_INT:
case V2DF_FTYPE_V2DF_V2DF_V2DF_QI_INT:
@@ -16038,6 +16045,7 @@ emit_reduc_half (rtx dest, rtx src, int i)
break;
case E_V16QImode:
case E_V8HImode:
+ case E_V8HFmode:
case E_V4SImode:
case E_V2DImode:
d = gen_reg_rtx (V1TImode);
@@ -16059,6 +16067,7 @@ emit_reduc_half (rtx dest, rtx src, int i)
break;
case E_V32QImode:
case E_V16HImode:
+ case E_V16HFmode:
case E_V8SImode:
case E_V4DImode:
if (i == 256)
@@ -16078,6 +16087,7 @@ emit_reduc_half (rtx dest, rtx src, int i)
break;
case E_V64QImode:
case E_V32HImode:
+ case E_V32HFmode:
if (i < 64)
{
d = gen_reg_rtx (V4TImode);
diff --git a/gcc/config/i386/i386-features.c b/gcc/config/i386/i386-features.c
index 14f816f..43bb676 100644
--- a/gcc/config/i386/i386-features.c
+++ b/gcc/config/i386/i386-features.c
@@ -2258,15 +2258,22 @@ remove_partial_avx_dependency (void)
rtx zero;
machine_mode dest_vecmode;
- if (dest_mode == E_SFmode)
+ switch (dest_mode)
{
+ case E_HFmode:
+ dest_vecmode = V8HFmode;
+ zero = gen_rtx_SUBREG (V8HFmode, v4sf_const0, 0);
+ break;
+ case E_SFmode:
dest_vecmode = V4SFmode;
zero = v4sf_const0;
- }
- else
- {
+ break;
+ case E_DFmode:
dest_vecmode = V2DFmode;
zero = gen_rtx_SUBREG (V2DFmode, v4sf_const0, 0);
+ break;
+ default:
+ gcc_unreachable ();
}
/* Change source to vector mode. */
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index ba89e11..a566d84 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2462,6 +2462,8 @@ classify_argument (machine_mode mode, const_tree type,
case E_V2SFmode:
case E_V2SImode:
case E_V4HImode:
+ case E_V4HFmode:
+ case E_V2HFmode:
case E_V8QImode:
classes[0] = X86_64_SSE_CLASS;
return 1;
@@ -2902,6 +2904,7 @@ pass_in_reg:
case E_V8QImode:
case E_V4HImode:
+ case E_V4HFmode:
case E_V2SImode:
case E_V2SFmode:
case E_V1TImode:
@@ -3149,6 +3152,7 @@ pass_in_reg:
case E_V8QImode:
case E_V4HImode:
+ case E_V4HFmode:
case E_V2SImode:
case E_V2SFmode:
case E_V1TImode:
@@ -5035,7 +5039,8 @@ standard_80387_constant_p (rtx x)
/* For XFmode constants, try to find a special 80387 instruction when
optimizing for size or on those CPUs that benefit from them. */
if (mode == XFmode
- && (optimize_function_for_size_p (cfun) || TARGET_EXT_80387_CONSTANTS))
+ && (optimize_function_for_size_p (cfun) || TARGET_EXT_80387_CONSTANTS)
+ && !flag_rounding_math)
{
int i;
@@ -10703,24 +10708,19 @@ legitimate_pic_address_disp_p (rtx disp)
if (is_imported_p (op0))
return true;
- if (SYMBOL_REF_FAR_ADDR_P (op0)
- || !SYMBOL_REF_LOCAL_P (op0))
+ if (SYMBOL_REF_FAR_ADDR_P (op0) || !SYMBOL_REF_LOCAL_P (op0))
break;
- /* Function-symbols need to be resolved only for
- large-model.
- For the small-model we don't need to resolve anything
- here. */
+ /* Non-external-weak function symbols need to be resolved only
+ for the large model. Non-external symbols don't need to be
+ resolved for large and medium models. For the small model,
+ we don't need to resolve anything here. */
if ((ix86_cmodel != CM_LARGE_PIC
- && SYMBOL_REF_FUNCTION_P (op0))
+ && SYMBOL_REF_FUNCTION_P (op0)
+ && !(SYMBOL_REF_EXTERNAL_P (op0) && SYMBOL_REF_WEAK (op0)))
+ || !SYMBOL_REF_EXTERNAL_P (op0)
|| ix86_cmodel == CM_SMALL_PIC)
return true;
- /* Non-external symbols don't need to be resolved for
- large, and medium-model. */
- if ((ix86_cmodel == CM_LARGE_PIC
- || ix86_cmodel == CM_MEDIUM_PIC)
- && !SYMBOL_REF_EXTERNAL_P (op0))
- return true;
}
else if (!SYMBOL_REF_FAR_ADDR_P (op0)
&& (SYMBOL_REF_LOCAL_P (op0)
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 8a4251b..cba6d83 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -1033,7 +1033,8 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
|| (MODE) == TImode)
#define VALID_AVX512FP16_REG_MODE(MODE) \
- ((MODE) == V8HFmode || (MODE) == V16HFmode || (MODE) == V32HFmode)
+ ((MODE) == V8HFmode || (MODE) == V16HFmode || (MODE) == V32HFmode \
+ || (MODE) == V2HFmode)
#define VALID_SSE2_REG_MODE(MODE) \
((MODE) == V16QImode || (MODE) == V8HImode || (MODE) == V2DFmode \
@@ -1041,7 +1042,8 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
|| (MODE) == V2DImode || (MODE) == DFmode || (MODE) == HFmode)
#define VALID_SSE2_REG_VHF_MODE(MODE) \
- (VALID_SSE2_REG_MODE (MODE) || (MODE) == V8HFmode)
+ (VALID_SSE2_REG_MODE (MODE) || (MODE) == V8HFmode \
+ || (MODE) == V4HFmode || (MODE) == V2HFmode)
#define VALID_SSE_REG_MODE(MODE) \
((MODE) == V1TImode || (MODE) == TImode \
@@ -1051,10 +1053,12 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
#define VALID_MMX_REG_MODE_3DNOW(MODE) \
((MODE) == V2SFmode || (MODE) == SFmode)
+/* To match ia32 psABI, V4HFmode should be added here. */
#define VALID_MMX_REG_MODE(MODE) \
((MODE) == V1DImode || (MODE) == DImode \
|| (MODE) == V2SImode || (MODE) == SImode \
- || (MODE) == V4HImode || (MODE) == V8QImode)
+ || (MODE) == V4HImode || (MODE) == V8QImode \
+ || (MODE) == V4HFmode)
#define VALID_MASK_REG_MODE(MODE) ((MODE) == HImode || (MODE) == QImode)
@@ -1087,7 +1091,8 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
|| (MODE) == V4DImode || (MODE) == V8SFmode || (MODE) == V4DFmode \
|| (MODE) == V2TImode || (MODE) == V8DImode || (MODE) == V64QImode \
|| (MODE) == V16SImode || (MODE) == V32HImode || (MODE) == V8DFmode \
- || (MODE) == V16SFmode || VALID_AVX512FP16_REG_MODE (MODE))
+ || (MODE) == V16SFmode || (MODE) == V32HFmode || (MODE) == V16HFmode \
+ || (MODE) == V8HFmode)
#define X87_FLOAT_MODE_P(MODE) \
(TARGET_80387 && ((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode))
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 188f431..04cb3bf 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -498,7 +498,7 @@
;; Main data type used by the insn
(define_attr "mode"
"unknown,none,QI,HI,SI,DI,TI,OI,XI,HF,SF,DF,XF,TF,V32HF,V16HF,V8HF,
- V16SF,V8SF,V4DF,V4SF,V2DF,V2SF,V1DF,V8DF"
+ V16SF,V8SF,V4DF,V4SF,V2DF,V2SF,V1DF,V8DF,V4HF,V2HF"
(const_string "unknown"))
;; The CPU unit operations uses.
@@ -832,7 +832,7 @@
x64_avx,x64_avx512bw,x64_avx512dq,
sse_noavx,sse2,sse2_noavx,sse3,sse3_noavx,sse4,sse4_noavx,
avx,noavx,avx2,noavx2,bmi,bmi2,fma4,fma,avx512f,noavx512f,
- avx512bw,noavx512bw,avx512dq,noavx512dq,
+ avx512bw,noavx512bw,avx512dq,noavx512dq,fma_or_avx512vl,
avx512vl,noavx512vl,avxvnni,avx512vnnivl,avx512fp16"
(const_string "base"))
@@ -874,6 +874,8 @@
(eq_attr "isa" "bmi2") (symbol_ref "TARGET_BMI2")
(eq_attr "isa" "fma4") (symbol_ref "TARGET_FMA4")
(eq_attr "isa" "fma") (symbol_ref "TARGET_FMA")
+ (eq_attr "isa" "fma_or_avx512vl")
+ (symbol_ref "TARGET_FMA || TARGET_AVX512VL")
(eq_attr "isa" "avx512f") (symbol_ref "TARGET_AVX512F")
(eq_attr "isa" "noavx512f") (symbol_ref "!TARGET_AVX512F")
(eq_attr "isa" "avx512bw") (symbol_ref "TARGET_AVX512BW")
@@ -1104,7 +1106,8 @@
(V1TI "16") (V2TI "32") (V4TI "64")
(V2DF "16") (V4DF "32") (V8DF "64")
(V4SF "16") (V8SF "32") (V16SF "64")
- (V8HF "16") (V16HF "32") (V32HF "64")])
+ (V8HF "16") (V16HF "32") (V32HF "64")
+ (V4HF "8") (V2HF "4")])
;; Double word integer modes as mode attribute.
(define_mode_attr DWI [(QI "HI") (HI "SI") (SI "DI") (DI "TI") (TI "OI")])
@@ -1541,6 +1544,21 @@
DONE;
})
+(define_expand "cstorehf4"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:HF 2 "cmp_fp_expander_operand")
+ (match_operand:HF 3 "cmp_fp_expander_operand")))
+ (set (match_operand:QI 0 "register_operand")
+ (match_operator 1 "ix86_fp_comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)]))]
+ "TARGET_AVX512FP16"
+{
+ ix86_expand_setcc (operands[0], GET_CODE (operands[1]),
+ operands[2], operands[3]);
+ DONE;
+})
+
(define_expand "cstore<mode>4"
[(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:MODEF 2 "cmp_fp_expander_operand")
@@ -4793,6 +4811,16 @@
}
})
+(define_insn "fix<fixunssuffix>_trunchf<mode>2"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (any_fix:SWI48
+ (match_operand:HF 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512FP16"
+ "vcvttsh2<fixsuffix>si\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
;; Signed conversion to SImode.
(define_expand "fix_truncxfsi2"
@@ -4900,6 +4928,17 @@
(set_attr "prefix" "evex")
(set_attr "mode" "SI")])
+(define_insn "*fixuns_trunchfsi2zext"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI
+ (unsigned_fix:SI
+ (match_operand:HF 1 "nonimmediate_operand" "vm"))))]
+ "TARGET_64BIT && TARGET_AVX512FP16"
+ "vcvttsh2usi\t{%1, %k0|%k0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "SI")])
+
(define_insn "*fixuns_trunc<mode>si2_avx512f_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
@@ -4932,6 +4971,14 @@
;; Without these patterns, we'll try the unsigned SI conversion which
;; is complex for SSE, rather than the signed SI conversion, which isn't.
+(define_expand "fixuns_trunchfhi2"
+ [(set (match_dup 2)
+ (fix:SI (match_operand:HF 1 "nonimmediate_operand")))
+ (set (match_operand:HI 0 "nonimmediate_operand")
+ (subreg:HI (match_dup 2) 0))]
+ "TARGET_AVX512FP16"
+ "operands[2] = gen_reg_rtx (SImode);")
+
(define_expand "fixuns_trunc<mode>hi2"
[(set (match_dup 2)
(fix:SI (match_operand:MODEF 1 "nonimmediate_operand")))
@@ -10163,6 +10210,40 @@
[(set_attr "type" "alu")
(set_attr "mode" "<MODE>")])
+;; convert (sign_extend:WIDE (any_logic:NARROW (memory, immediate)))
+;; to (any_logic:WIDE (sign_extend (memory)), (sign_extend (immediate))).
+;; This eliminates sign extension after logic operation.
+
+(define_split
+ [(set (match_operand:SWI248 0 "register_operand")
+ (sign_extend:SWI248
+ (any_logic:QI (match_operand:QI 1 "memory_operand")
+ (match_operand:QI 2 "const_int_operand"))))]
+ ""
+ [(set (match_dup 3) (sign_extend:SWI248 (match_dup 1)))
+ (set (match_dup 0) (any_logic:SWI248 (match_dup 3) (match_dup 2)))]
+ "operands[3] = gen_reg_rtx (<MODE>mode);")
+
+(define_split
+ [(set (match_operand:SWI48 0 "register_operand")
+ (sign_extend:SWI48
+ (any_logic:HI (match_operand:HI 1 "memory_operand")
+ (match_operand:HI 2 "const_int_operand"))))]
+ ""
+ [(set (match_dup 3) (sign_extend:SWI48 (match_dup 1)))
+ (set (match_dup 0) (any_logic:SWI48 (match_dup 3) (match_dup 2)))]
+ "operands[3] = gen_reg_rtx (<MODE>mode);")
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand")
+ (sign_extend:DI
+ (any_logic:SI (match_operand:SI 1 "memory_operand")
+ (match_operand:SI 2 "const_int_operand"))))]
+ "TARGET_64BIT"
+ [(set (match_dup 3) (sign_extend:DI (match_dup 1)))
+ (set (match_dup 0) (any_logic:DI (match_dup 3) (match_dup 2)))]
+ "operands[3] = gen_reg_rtx (DImode);")
+
(define_insn "*<code><mode>_2"
[(set (reg FLAGS_REG)
(compare (any_or:SWI
@@ -17041,6 +17122,19 @@
DONE;
})
+(define_insn "sqrthf2"
+ [(set (match_operand:HF 0 "register_operand" "=v,v")
+ (sqrt:HF
+ (match_operand:HF 1 "nonimmediate_operand" "v,m")))]
+ "TARGET_AVX512FP16"
+ "@
+ vsqrtsh\t{%d1, %0|%0, %d1}
+ vsqrtsh\t{%1, %d0|%d0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "avx_partial_xmm_update" "false,true")
+ (set_attr "mode" "HF")])
+
(define_insn "*sqrt<mode>2_sse"
[(set (match_operand:MODEF 0 "register_operand" "=v,v,v")
(sqrt:MODEF
@@ -18220,9 +18314,9 @@
(define_insn "sse4_1_round<mode>2"
- [(set (match_operand:MODEF 0 "register_operand" "=x,x,x,v,v")
- (unspec:MODEF
- [(match_operand:MODEF 1 "nonimmediate_operand" "0,x,m,v,m")
+ [(set (match_operand:MODEFH 0 "register_operand" "=x,x,x,v,v")
+ (unspec:MODEFH
+ [(match_operand:MODEFH 1 "nonimmediate_operand" "0,x,m,v,m")
(match_operand:SI 2 "const_0_to_15_operand" "n,n,n,n,n")]
UNSPEC_ROUND))]
"TARGET_SSE4_1"
@@ -18257,6 +18351,17 @@
(set_attr "znver1_decode" "vector")
(set_attr "mode" "XF")])
+(define_expand "rinthf2"
+ [(match_operand:HF 0 "register_operand")
+ (match_operand:HF 1 "nonimmediate_operand")]
+ "TARGET_AVX512FP16"
+{
+ emit_insn (gen_sse4_1_roundhf2 (operands[0],
+ operands[1],
+ GEN_INT (ROUND_MXCSR)));
+ DONE;
+})
+
(define_expand "rint<mode>2"
[(use (match_operand:MODEF 0 "register_operand"))
(use (match_operand:MODEF 1 "nonimmediate_operand"))]
@@ -18290,6 +18395,17 @@
"TARGET_USE_FANCY_MATH_387
&& !flag_trapping_math")
+(define_expand "nearbyinthf2"
+ [(match_operand:HF 0 "register_operand")
+ (match_operand:HF 1 "nonimmediate_operand")]
+ "TARGET_AVX512FP16"
+{
+ emit_insn (gen_sse4_1_roundhf2 (operands[0],
+ operands[1],
+ GEN_INT (ROUND_MXCSR | ROUND_NO_EXC)));
+ DONE;
+})
+
(define_expand "nearbyint<mode>2"
[(use (match_operand:MODEF 0 "register_operand"))
(use (match_operand:MODEF 1 "nonimmediate_operand"))]
@@ -18479,6 +18595,18 @@
"TARGET_USE_FANCY_MATH_387
&& (flag_fp_int_builtin_inexact || !flag_trapping_math)")
+(define_expand "<rounding_insn>hf2"
+ [(parallel [(set (match_operand:HF 0 "register_operand")
+ (unspec:HF [(match_operand:HF 1 "register_operand")]
+ FRNDINT_ROUNDING))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_AVX512FP16"
+{
+ emit_insn (gen_sse4_1_roundhf2 (operands[0], operands[1],
+ GEN_INT (ROUND_<ROUNDING> | ROUND_NO_EXC)));
+ DONE;
+})
+
(define_expand "<rounding_insn><mode>2"
[(parallel [(set (match_operand:MODEF 0 "register_operand")
(unspec:MODEF [(match_operand:MODEF 1 "register_operand")]
@@ -19882,6 +20010,17 @@
(set_attr "type" "sseadd")
(set_attr "mode" "<MODE>")])
+(define_insn "<code>hf3"
+ [(set (match_operand:HF 0 "register_operand" "=v")
+ (smaxmin:HF
+ (match_operand:HF 1 "nonimmediate_operand" "%v")
+ (match_operand:HF 2 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512FP16"
+ "v<maxmin_float>sh\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "prefix" "evex")
+ (set_attr "type" "sseadd")
+ (set_attr "mode" "HF")])
+
;; These versions of the min/max patterns implement exactly the operations
;; min = (op1 < op2 ? op1 : op2)
;; max = (!(op1 < op2) ? op1 : op2)
diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md
index 2d3b63f..c9467bc 100644
--- a/gcc/config/i386/mmx.md
+++ b/gcc/config/i386/mmx.md
@@ -48,7 +48,7 @@
(define_mode_iterator MMXMODEI8 [V8QI V4HI V2SI (V1DI "TARGET_SSE2")])
;; All 8-byte vector modes handled by MMX
-(define_mode_iterator MMXMODE [V8QI V4HI V2SI V1DI V2SF])
+(define_mode_iterator MMXMODE [V8QI V4HI V2SI V1DI V2SF V4HF])
(define_mode_iterator MMXMODE124 [V8QI V4HI V2SI V2SF])
;; Mix-n-match
@@ -57,8 +57,8 @@
(define_mode_iterator MMXMODE24 [V4HI V2SI])
(define_mode_iterator MMXMODE248 [V4HI V2SI V1DI])
-;; All 4-byte integer vector modes
-(define_mode_iterator V_32 [V4QI V2HI V1SI])
+;; All 4-byte integer/float16 vector modes
+(define_mode_iterator V_32 [V4QI V2HI V1SI V2HF])
;; 4-byte integer vector modes
(define_mode_iterator VI_32 [V4QI V2HI])
@@ -66,6 +66,9 @@
;; V2S* modes
(define_mode_iterator V2FI [V2SF V2SI])
+;; 4-byte and 8-byte float16 vector modes
+(define_mode_iterator VHF_32_64 [V4HF V2HF])
+
;; Mapping from integer vector mode to mnemonic suffix
(define_mode_attr mmxvecsize
[(V8QI "b") (V4QI "b") (V4HI "w") (V2HI "w") (V2SI "d") (V1DI "q")])
@@ -191,6 +194,8 @@
(eq_attr "alternative" "11,12")
(cond [(match_test "<MODE>mode == V2SFmode")
(const_string "V4SF")
+ (match_test "<MODE>mode == V4HFmode")
+ (const_string "V4SF")
(ior (not (match_test "TARGET_SSE2"))
(match_test "optimize_function_for_size_p (cfun)"))
(const_string "V4SF")
@@ -198,14 +203,16 @@
(const_string "TI"))
(and (eq_attr "alternative" "13")
- (ior (and (match_test "<MODE>mode == V2SFmode")
- (not (match_test "TARGET_MMX_WITH_SSE")))
- (not (match_test "TARGET_SSE2"))))
+ (ior (ior (and (match_test "<MODE>mode == V2SFmode")
+ (not (match_test "TARGET_MMX_WITH_SSE")))
+ (not (match_test "TARGET_SSE2")))
+ (match_test "<MODE>mode == V4HFmode")))
(const_string "V2SF")
(and (eq_attr "alternative" "14")
- (ior (match_test "<MODE>mode == V2SFmode")
- (not (match_test "TARGET_SSE2"))))
+ (ior (ior (match_test "<MODE>mode == V2SFmode")
+ (not (match_test "TARGET_SSE2")))
+ (match_test "<MODE>mode == V4HFmode")))
(const_string "V2SF")
]
(const_string "DI")))
@@ -289,12 +296,17 @@
(const_string "*")))
(set (attr "mode")
(cond [(eq_attr "alternative" "2,3")
- (cond [(match_test "TARGET_AVX")
+ (cond [(match_test "<MODE>mode == V2HFmode")
+ (const_string "V4SF")
+ (match_test "TARGET_AVX")
(const_string "TI")
(match_test "optimize_function_for_size_p (cfun)")
(const_string "V4SF")
]
(const_string "TI"))
+ (and (eq_attr "alternative" "4,5")
+ (match_test "<MODE>mode == V2HFmode"))
+ (const_string "SF")
]
(const_string "SI")))
(set (attr "preferred_for_speed")
@@ -1019,12 +1031,13 @@
(match_operand:V2SF 1 "register_operand" "%0,v,x")
(match_operand:V2SF 2 "register_operand" "v,v,x")
(match_operand:V2SF 3 "register_operand" "v,0,x")))]
- "(TARGET_FMA || TARGET_FMA4) && TARGET_MMX_WITH_SSE"
+ "(TARGET_FMA || TARGET_FMA4 || TARGET_AVX512VL)
+ && TARGET_MMX_WITH_SSE"
"@
vfmadd132ps\t{%2, %3, %0|%0, %3, %2}
vfmadd231ps\t{%2, %1, %0|%0, %1, %2}
vfmaddps\t{%3, %2, %1, %0|%0, %1, %2, %3}"
- [(set_attr "isa" "fma,fma,fma4")
+ [(set_attr "isa" "fma_or_avx512vl,fma_or_avx512vl,fma4")
(set_attr "type" "ssemuladd")
(set_attr "mode" "V4SF")])
@@ -1035,12 +1048,13 @@
(match_operand:V2SF 2 "register_operand" "v,v,x")
(neg:V2SF
(match_operand:V2SF 3 "register_operand" "v,0,x"))))]
- "(TARGET_FMA || TARGET_FMA4) && TARGET_MMX_WITH_SSE"
+ "(TARGET_FMA || TARGET_FMA4 || TARGET_AVX512VL)
+ && TARGET_MMX_WITH_SSE"
"@
vfmsub132ps\t{%2, %3, %0|%0, %3, %2}
vfmsub231ps\t{%2, %1, %0|%0, %1, %2}
vfmsubps\t{%3, %2, %1, %0|%0, %1, %2, %3}"
- [(set_attr "isa" "fma,fma,fma4")
+ [(set_attr "isa" "fma_or_avx512vl,fma_or_avx512vl,fma4")
(set_attr "type" "ssemuladd")
(set_attr "mode" "V4SF")])
@@ -1051,12 +1065,13 @@
(match_operand:V2SF 1 "register_operand" "%0,v,x"))
(match_operand:V2SF 2 "register_operand" "v,v,x")
(match_operand:V2SF 3 "register_operand" "v,0,x")))]
- "(TARGET_FMA || TARGET_FMA4) && TARGET_MMX_WITH_SSE"
+ "(TARGET_FMA || TARGET_FMA4 || TARGET_AVX512VL)
+ && TARGET_MMX_WITH_SSE"
"@
vfnmadd132ps\t{%2, %3, %0|%0, %3, %2}
vfnmadd231ps\t{%2, %1, %0|%0, %1, %2}
vfnmaddps\t{%3, %2, %1, %0|%0, %1, %2, %3}"
- [(set_attr "isa" "fma,fma,fma4")
+ [(set_attr "isa" "fma_or_avx512vl,fma_or_avx512vl,fma4")
(set_attr "type" "ssemuladd")
(set_attr "mode" "V4SF")])
@@ -1068,12 +1083,13 @@
(match_operand:V2SF 2 "register_operand" "v,v,x")
(neg:V2SF
(match_operand:V2SF 3 "register_operand" "v,0,x"))))]
- "(TARGET_FMA || TARGET_FMA4) && TARGET_MMX_WITH_SSE"
+ "(TARGET_FMA || TARGET_FMA4 || TARGET_AVX512VL)
+ && TARGET_MMX_WITH_SSE"
"@
vfnmsub132ps\t{%2, %3, %0|%0, %3, %2}
vfnmsub231ps\t{%2, %1, %0|%0, %1, %2}
vfnmsubps\t{%3, %2, %1, %0|%0, %1, %2, %3}"
- [(set_attr "isa" "fma,fma,fma4")
+ [(set_attr "isa" "fma_or_avx512vl,fma_or_avx512vl,fma4")
(set_attr "type" "ssemuladd")
(set_attr "mode" "V4SF")])
@@ -1389,6 +1405,28 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
+;; Parallel half-precision floating point arithmetic
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "<insn><mode>3"
+ [(set (match_operand:VHF_32_64 0 "register_operand" "=v")
+ (plusminusmultdiv:VHF_32_64
+ (match_operand:VHF_32_64 1 "register_operand" "<comm>v")
+ (match_operand:VHF_32_64 2 "register_operand" "v")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "v<insn>ph\t{%2, %1, %0|%0, %1, %2}"
+ [(set (attr "type")
+ (cond [(match_test "<CODE> == MULT")
+ (const_string "ssemul")
+ (match_test "<CODE> == DIV")
+ (const_string "ssediv")]
+ (const_string "sseadd")))
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V8HF")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
;; Parallel integral arithmetic
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 0016c02..4559b0c 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -191,6 +191,14 @@
UNSPEC_VCVTNE2PS2BF16
UNSPEC_VCVTNEPS2BF16
UNSPEC_VDPBF16PS
+
+ ;; For AVX512FP16 suppport
+ UNSPEC_COMPLEX_FMA
+ UNSPEC_COMPLEX_FCMA
+ UNSPEC_COMPLEX_FMUL
+ UNSPEC_COMPLEX_FCMUL
+ UNSPEC_COMPLEX_MASK
+
])
(define_c_enum "unspecv" [
@@ -939,6 +947,10 @@
(V16SF "HI") (V8SF "QI") (V4SF "QI")
(V8DF "QI") (V4DF "QI") (V2DF "QI")])
+;; Mapping of vector modes to corresponding complex mask size
+(define_mode_attr avx512fmaskcmode
+ [(V32HF "HI") (V16HF "QI") (V8HF "QI")])
+
;; Mapping of vector modes to corresponding mask size
(define_mode_attr avx512fmaskmodelower
[(V64QI "di") (V32QI "si") (V16QI "hi")
@@ -977,9 +989,9 @@
(V16HF "OI") (V8HF "TI")])
(define_mode_attr sseintvecmodelower
- [(V16SF "v16si") (V8DF "v8di")
- (V8SF "v8si") (V4DF "v4di")
- (V4SF "v4si") (V2DF "v2di")
+ [(V32HF "v32hi") (V16SF "v16si") (V8DF "v8di")
+ (V16HF "v16hi") (V8SF "v8si") (V4DF "v4di")
+ (V8HF "v8hi") (V4SF "v4si") (V2DF "v2di")
(V8SI "v8si") (V4DI "v4di")
(V4SI "v4si") (V2DI "v2di")
(V16HI "v16hi") (V8HI "v8hi")
@@ -1022,6 +1034,13 @@
(V8DI "V8HF") (V4DI "V8HF") (V2DI "V8HF")
(V8DF "V8HF") (V16SF "V16HF") (V8SF "V8HF")])
+;; Mapping of vector modes to vector hf modes of same element.
+(define_mode_attr ssePHmodelower
+ [(V32HI "v32hf") (V16HI "v16hf") (V8HI "v8hf")
+ (V16SI "v16hf") (V8SI "v8hf") (V4SI "v4hf")
+ (V8DI "v8hf") (V4DI "v4hf") (V2DI "v2hf")
+ (V8DF "v8hf") (V16SF "v16hf") (V8SF "v8hf")])
+
;; Mapping of vector modes to packed single mode of the same size
(define_mode_attr ssePSmode
[(V16SI "V16SF") (V8DF "V16SF")
@@ -1549,9 +1568,9 @@
(set_attr "mode" "<sseinsnmode>")])
(define_insn "<avx512>_store<mode>_mask"
- [(set (match_operand:VI12_AVX512VL 0 "memory_operand" "=m")
- (vec_merge:VI12_AVX512VL
- (match_operand:VI12_AVX512VL 1 "register_operand" "v")
+ [(set (match_operand:VI12HF_AVX512VL 0 "memory_operand" "=m")
+ (vec_merge:VI12HF_AVX512VL
+ (match_operand:VI12HF_AVX512VL 1 "register_operand" "v")
(match_dup 0)
(match_operand:<avx512fmaskmode> 2 "register_operand" "Yk")))]
"TARGET_AVX512BW"
@@ -2106,12 +2125,12 @@
[(set_attr "isa" "noavx,noavx,avx,avx")])
(define_expand "cond_<insn><mode>"
- [(set (match_operand:VF 0 "register_operand")
- (vec_merge:VF
- (plusminus:VF
- (match_operand:VF 2 "vector_operand")
- (match_operand:VF 3 "vector_operand"))
- (match_operand:VF 4 "nonimm_or_0_operand")
+ [(set (match_operand:VFH 0 "register_operand")
+ (vec_merge:VFH
+ (plusminus:VFH
+ (match_operand:VFH 2 "vector_operand")
+ (match_operand:VFH 3 "vector_operand"))
+ (match_operand:VFH 4 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"<MODE_SIZE> == 64 || TARGET_AVX512VL"
{
@@ -2195,12 +2214,12 @@
(set_attr "mode" "<ssescalarmode>")])
(define_expand "cond_mul<mode>"
- [(set (match_operand:VF 0 "register_operand")
- (vec_merge:VF
- (mult:VF
- (match_operand:VF 2 "vector_operand")
- (match_operand:VF 3 "vector_operand"))
- (match_operand:VF 4 "nonimm_or_0_operand")
+ [(set (match_operand:VFH 0 "register_operand")
+ (vec_merge:VFH
+ (mult:VFH
+ (match_operand:VFH 2 "vector_operand")
+ (match_operand:VFH 3 "vector_operand"))
+ (match_operand:VFH 4 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"<MODE_SIZE> == 64 || TARGET_AVX512VL"
{
@@ -2310,12 +2329,12 @@
})
(define_expand "cond_div<mode>"
- [(set (match_operand:VF 0 "register_operand")
- (vec_merge:VF
- (div:VF
- (match_operand:VF 2 "register_operand")
- (match_operand:VF 3 "vector_operand"))
- (match_operand:VF 4 "nonimm_or_0_operand")
+ [(set (match_operand:VFH 0 "register_operand")
+ (vec_merge:VFH
+ (div:VFH
+ (match_operand:VFH 2 "register_operand")
+ (match_operand:VFH 3 "vector_operand"))
+ (match_operand:VFH 4 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"<MODE_SIZE> == 64 || TARGET_AVX512VL"
{
@@ -2510,12 +2529,12 @@
(set_attr "mode" "<ssescalarmode>")])
(define_insn "*<sse>_vmsqrt<mode>2<mask_scalar_name><round_scalar_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=x,v")
- (vec_merge:VF_128
- (vec_duplicate:VF_128
+ [(set (match_operand:VFH_128 0 "register_operand" "=x,v")
+ (vec_merge:VFH_128
+ (vec_duplicate:VFH_128
(sqrt:<ssescalarmode>
(match_operand:<ssescalarmode> 1 "nonimmediate_operand" "xm,<round_scalar_constraint>")))
- (match_operand:VF_128 2 "register_operand" "0,v")
+ (match_operand:VFH_128 2 "register_operand" "0,v")
(const_int 1)))]
"TARGET_SSE"
"@
@@ -2648,12 +2667,12 @@
(set_attr "mode" "HF")])
(define_expand "cond_<code><mode>"
- [(set (match_operand:VF 0 "register_operand")
- (vec_merge:VF
- (smaxmin:VF
- (match_operand:VF 2 "vector_operand")
- (match_operand:VF 3 "vector_operand"))
- (match_operand:VF 4 "nonimm_or_0_operand")
+ [(set (match_operand:VFH 0 "register_operand")
+ (vec_merge:VFH
+ (smaxmin:VFH
+ (match_operand:VFH 2 "vector_operand")
+ (match_operand:VFH 3 "vector_operand"))
+ (match_operand:VFH 4 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"<MODE_SIZE> == 64 || TARGET_AVX512VL"
{
@@ -3137,36 +3156,20 @@
(set_attr "prefix_rep" "1,*")
(set_attr "mode" "V4SF")])
-(define_expand "reduc_plus_scal_v4sf"
- [(plus:V4SF
- (match_operand:SF 0 "register_operand")
- (match_operand:V4SF 1 "register_operand"))]
- "TARGET_SSE"
-{
- rtx vtmp = gen_reg_rtx (V4SFmode);
- rtx stmp = gen_reg_rtx (SFmode);
- if (TARGET_SSE3)
- emit_insn (gen_sse3_movshdup (vtmp, operands[1]));
- else
- emit_insn (gen_sse_shufps (vtmp, operands[1], operands[1], GEN_INT(177)));
-
- emit_insn (gen_addv4sf3 (operands[1], operands[1], vtmp));
- emit_insn (gen_sse_movhlps (vtmp, vtmp, operands[1]));
- emit_insn (gen_vec_extractv4sfsf (stmp, vtmp, const0_rtx));
- emit_insn (gen_vec_extractv4sfsf (operands[0], operands[1], const0_rtx));
- emit_insn (gen_addsf3 (operands[0], operands[0], stmp));
- DONE;
-})
+(define_mode_iterator REDUC_SSE_PLUS_MODE
+ [(V2DF "TARGET_SSE") (V4SF "TARGET_SSE")
+ (V8HF "TARGET_AVX512FP16 && TARGET_AVX512VL")])
-(define_expand "reduc_plus_scal_v2df"
- [(plus:V2DF
- (match_operand:DF 0 "register_operand")
- (match_operand:V2DF 1 "register_operand"))]
- "TARGET_SSE"
+(define_expand "reduc_plus_scal_<mode>"
+ [(plus:REDUC_SSE_PLUS_MODE
+ (match_operand:<ssescalarmode> 0 "register_operand")
+ (match_operand:REDUC_SSE_PLUS_MODE 1 "register_operand"))]
+ ""
{
- rtx tmp = gen_reg_rtx (V2DFmode);
- ix86_expand_reduc (gen_addv2df3, tmp, operands[1]);
- emit_insn (gen_vec_extractv2dfdf (operands[0], tmp, const0_rtx));
+ rtx tmp = gen_reg_rtx (<MODE>mode);
+ ix86_expand_reduc (gen_add<mode>3, tmp, operands[1]);
+ emit_insn (gen_vec_extract<mode><ssescalarmodelower> (operands[0], tmp,
+ const0_rtx));
DONE;
})
@@ -3192,7 +3195,9 @@
(define_mode_iterator REDUC_PLUS_MODE
[(V4DF "TARGET_AVX") (V8SF "TARGET_AVX")
+ (V16HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
(V8DF "TARGET_AVX512F") (V16SF "TARGET_AVX512F")
+ (V32HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
(V32QI "TARGET_AVX") (V64QI "TARGET_AVX512F")])
(define_expand "reduc_plus_scal_<mode>"
@@ -3212,7 +3217,8 @@
;; Modes handled by reduc_sm{in,ax}* patterns.
(define_mode_iterator REDUC_SSE_SMINMAX_MODE
- [(V4SF "TARGET_SSE") (V2DF "TARGET_SSE")
+ [(V8HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (V4SF "TARGET_SSE") (V2DF "TARGET_SSE")
(V4SI "TARGET_SSE2") (V8HI "TARGET_SSE2") (V16QI "TARGET_SSE2")
(V2DI "TARGET_SSE4_2")])
@@ -3231,9 +3237,11 @@
(define_mode_iterator REDUC_SMINMAX_MODE
[(V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2")
+ (V16HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
(V8SI "TARGET_AVX2") (V4DI "TARGET_AVX2")
(V8SF "TARGET_AVX") (V4DF "TARGET_AVX")
(V64QI "TARGET_AVX512BW")
+ (V32HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
(V32HI "TARGET_AVX512BW") (V16SI "TARGET_AVX512F")
(V8DI "TARGET_AVX512F") (V16SF "TARGET_AVX512F")
(V8DF "TARGET_AVX512F")])
@@ -3791,8 +3799,8 @@
(define_expand "vec_cmp<mode><avx512fmaskmodelower>"
[(set (match_operand:<avx512fmaskmode> 0 "register_operand")
(match_operator:<avx512fmaskmode> 1 ""
- [(match_operand:V48_AVX512VL 2 "register_operand")
- (match_operand:V48_AVX512VL 3 "nonimmediate_operand")]))]
+ [(match_operand:V48H_AVX512VL 2 "register_operand")
+ (match_operand:V48H_AVX512VL 3 "nonimmediate_operand")]))]
"TARGET_AVX512F"
{
bool ok = ix86_expand_mask_vec_cmp (operands[0], GET_CODE (operands[1]),
@@ -3999,6 +4007,51 @@
DONE;
})
+(define_expand "vcond<mode><mode>"
+ [(set (match_operand:VF_AVX512FP16VL 0 "register_operand")
+ (if_then_else:VF_AVX512FP16VL
+ (match_operator 3 ""
+ [(match_operand:VF_AVX512FP16VL 4 "vector_operand")
+ (match_operand:VF_AVX512FP16VL 5 "vector_operand")])
+ (match_operand:VF_AVX512FP16VL 1 "general_operand")
+ (match_operand:VF_AVX512FP16VL 2 "general_operand")))]
+ "TARGET_AVX512FP16"
+{
+ bool ok = ix86_expand_fp_vcond (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "vcond<mode><sseintvecmodelower>"
+ [(set (match_operand:VF_AVX512FP16VL 0 "register_operand")
+ (if_then_else:VF_AVX512FP16VL
+ (match_operator 3 ""
+ [(match_operand:<sseintvecmode> 4 "vector_operand")
+ (match_operand:<sseintvecmode> 5 "vector_operand")])
+ (match_operand:VF_AVX512FP16VL 1 "general_operand")
+ (match_operand:VF_AVX512FP16VL 2 "general_operand")))]
+ "TARGET_AVX512FP16"
+{
+ bool ok = ix86_expand_int_vcond (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "vcond<sseintvecmodelower><mode>"
+ [(set (match_operand:<sseintvecmode> 0 "register_operand")
+ (if_then_else:<sseintvecmode>
+ (match_operator 3 ""
+ [(match_operand:VF_AVX512FP16VL 4 "vector_operand")
+ (match_operand:VF_AVX512FP16VL 5 "vector_operand")])
+ (match_operand:<sseintvecmode> 1 "general_operand")
+ (match_operand:<sseintvecmode> 2 "general_operand")))]
+ "TARGET_AVX512FP16"
+{
+ bool ok = ix86_expand_fp_vcond (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
(define_expand "vcond_mask_<mode><avx512fmaskmodelower>"
[(set (match_operand:V48_AVX512VL 0 "register_operand")
(vec_merge:V48_AVX512VL
@@ -4008,10 +4061,10 @@
"TARGET_AVX512F")
(define_expand "vcond_mask_<mode><avx512fmaskmodelower>"
- [(set (match_operand:VI12_AVX512VL 0 "register_operand")
- (vec_merge:VI12_AVX512VL
- (match_operand:VI12_AVX512VL 1 "nonimmediate_operand")
- (match_operand:VI12_AVX512VL 2 "nonimm_or_0_operand")
+ [(set (match_operand:VI12HF_AVX512VL 0 "register_operand")
+ (vec_merge:VI12HF_AVX512VL
+ (match_operand:VI12HF_AVX512VL 1 "nonimmediate_operand")
+ (match_operand:VI12HF_AVX512VL 2 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 3 "register_operand")))]
"TARGET_AVX512BW")
@@ -4638,7 +4691,11 @@
(V8SF "TARGET_FMA || TARGET_FMA4 || TARGET_AVX512VL")
(V4DF "TARGET_FMA || TARGET_FMA4 || TARGET_AVX512VL")
(V16SF "TARGET_AVX512F")
- (V8DF "TARGET_AVX512F")])
+ (V8DF "TARGET_AVX512F")
+ (HF "TARGET_AVX512FP16")
+ (V8HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (V16HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (V32HF "TARGET_AVX512FP16")])
(define_expand "fma<mode>4"
[(set (match_operand:FMAMODEM 0 "register_operand")
@@ -4746,14 +4803,11 @@
(set_attr "mode" "<MODE>")])
;; Suppose AVX-512F as baseline
-(define_mode_iterator VF_SF_AVX512VL
- [SF V16SF (V8SF "TARGET_AVX512VL") (V4SF "TARGET_AVX512VL")
- DF V8DF (V4DF "TARGET_AVX512VL") (V2DF "TARGET_AVX512VL")])
-
(define_mode_iterator VFH_SF_AVX512VL
[(V32HF "TARGET_AVX512FP16")
(V16HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
(V8HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (HF "TARGET_AVX512FP16")
SF V16SF (V8SF "TARGET_AVX512VL") (V4SF "TARGET_AVX512VL")
DF V8DF (V4DF "TARGET_AVX512VL") (V2DF "TARGET_AVX512VL")])
@@ -4772,13 +4826,13 @@
(set_attr "mode" "<MODE>")])
(define_expand "cond_fma<mode>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (match_operand:VF_AVX512VL 2 "vector_operand")
- (match_operand:VF_AVX512VL 3 "vector_operand")
- (match_operand:VF_AVX512VL 4 "vector_operand"))
- (match_operand:VF_AVX512VL 5 "nonimm_or_0_operand")
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 2 "vector_operand")
+ (match_operand:VFH_AVX512VL 3 "vector_operand")
+ (match_operand:VFH_AVX512VL 4 "vector_operand"))
+ (match_operand:VFH_AVX512VL 5 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"TARGET_AVX512F"
{
@@ -4872,14 +4926,14 @@
(set_attr "mode" "<MODE>")])
(define_expand "cond_fms<mode>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (match_operand:VF_AVX512VL 2 "vector_operand")
- (match_operand:VF_AVX512VL 3 "vector_operand")
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 4 "vector_operand")))
- (match_operand:VF_AVX512VL 5 "nonimm_or_0_operand")
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 2 "vector_operand")
+ (match_operand:VFH_AVX512VL 3 "vector_operand")
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 4 "vector_operand")))
+ (match_operand:VFH_AVX512VL 5 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"TARGET_AVX512F"
{
@@ -4975,14 +5029,14 @@
(set_attr "mode" "<MODE>")])
(define_expand "cond_fnma<mode>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 2 "vector_operand"))
- (match_operand:VF_AVX512VL 3 "vector_operand")
- (match_operand:VF_AVX512VL 4 "vector_operand"))
- (match_operand:VF_AVX512VL 5 "nonimm_or_0_operand")
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 2 "vector_operand"))
+ (match_operand:VFH_AVX512VL 3 "vector_operand")
+ (match_operand:VFH_AVX512VL 4 "vector_operand"))
+ (match_operand:VFH_AVX512VL 5 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"TARGET_AVX512F"
{
@@ -5080,15 +5134,15 @@
(set_attr "mode" "<MODE>")])
(define_expand "cond_fnms<mode>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 2 "vector_operand"))
- (match_operand:VF_AVX512VL 3 "vector_operand")
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 4 "vector_operand")))
- (match_operand:VF_AVX512VL 5 "nonimm_or_0_operand")
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 2 "vector_operand"))
+ (match_operand:VFH_AVX512VL 3 "vector_operand")
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 4 "vector_operand")))
+ (match_operand:VFH_AVX512VL 5 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"TARGET_AVX512F"
{
@@ -5793,6 +5847,168 @@
[(set_attr "type" "ssemuladd")
(set_attr "mode" "<MODE>")])
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Complex type operations
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_int_iterator UNSPEC_COMPLEX_F_C_MA
+ [UNSPEC_COMPLEX_FMA UNSPEC_COMPLEX_FCMA])
+
+(define_int_iterator UNSPEC_COMPLEX_F_C_MUL
+ [UNSPEC_COMPLEX_FMUL UNSPEC_COMPLEX_FCMUL])
+
+(define_int_attr complexopname
+ [(UNSPEC_COMPLEX_FMA "fmaddc")
+ (UNSPEC_COMPLEX_FCMA "fcmaddc")
+ (UNSPEC_COMPLEX_FMUL "fmulc")
+ (UNSPEC_COMPLEX_FCMUL "fcmulc")])
+
+(define_expand "<avx512>_fmaddc_<mode>_maskz<round_expand_name>"
+ [(match_operand:VF_AVX512FP16VL 0 "register_operand")
+ (match_operand:VF_AVX512FP16VL 1 "<round_expand_nimm_predicate>")
+ (match_operand:VF_AVX512FP16VL 2 "<round_expand_nimm_predicate>")
+ (match_operand:VF_AVX512FP16VL 3 "<round_expand_nimm_predicate>")
+ (match_operand:<avx512fmaskcmode> 4 "register_operand")]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+{
+ emit_insn (gen_fma_fmaddc_<mode>_maskz_1<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ CONST0_RTX (<MODE>mode), operands[4]<round_expand_operand>));
+ DONE;
+})
+
+(define_expand "<avx512>_fcmaddc_<mode>_maskz<round_expand_name>"
+ [(match_operand:VF_AVX512FP16VL 0 "register_operand")
+ (match_operand:VF_AVX512FP16VL 1 "<round_expand_nimm_predicate>")
+ (match_operand:VF_AVX512FP16VL 2 "<round_expand_nimm_predicate>")
+ (match_operand:VF_AVX512FP16VL 3 "<round_expand_nimm_predicate>")
+ (match_operand:<avx512fmaskcmode> 4 "register_operand")]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+{
+ emit_insn (gen_fma_fcmaddc_<mode>_maskz_1<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ CONST0_RTX (<MODE>mode), operands[4]<round_expand_operand>));
+ DONE;
+})
+
+(define_insn "fma_<complexopname>_<mode><sdc_maskz_name><round_name>"
+ [(set (match_operand:VF_AVX512FP16VL 0 "register_operand" "=&v")
+ (unspec:VF_AVX512FP16VL
+ [(match_operand:VF_AVX512FP16VL 1 "<round_nimm_predicate>" "%v")
+ (match_operand:VF_AVX512FP16VL 2 "<round_nimm_predicate>" "<round_constraint>")
+ (match_operand:VF_AVX512FP16VL 3 "<round_nimm_predicate>" "0")]
+ UNSPEC_COMPLEX_F_C_MA))]
+ "TARGET_AVX512FP16 && <sdc_mask_mode512bit_condition> && <round_mode512bit_condition>"
+ "v<complexopname><ssemodesuffix>\t{<round_sdc_mask_op4>%2, %1, %0<sdc_mask_op4>|%0<sdc_mask_op4>, %1, %2<round_sdc_mask_op4>}"
+ [(set_attr "type" "ssemuladd")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "<avx512>_<complexopname>_<mode>_mask<round_name>"
+ [(set (match_operand:VF_AVX512FP16VL 0 "register_operand" "=&v")
+ (vec_merge:VF_AVX512FP16VL
+ (unspec:VF_AVX512FP16VL
+ [(match_operand:VF_AVX512FP16VL 1 "nonimmediate_operand" "%v")
+ (match_operand:VF_AVX512FP16VL 2 "nonimmediate_operand" "<round_constraint>")
+ (match_operand:VF_AVX512FP16VL 3 "register_operand" "0")]
+ UNSPEC_COMPLEX_F_C_MA)
+ (match_dup 1)
+ (unspec:<avx512fmaskmode>
+ [(match_operand:<avx512fmaskcmode> 4 "register_operand" "Yk")]
+ UNSPEC_COMPLEX_MASK)))]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+ "v<complexopname><ssemodesuffix>\t{<round_op5>%2, %1, %0%{%4%}|%0%{%4%}, %1, %2<round_op5>}"
+ [(set_attr "type" "ssemuladd")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "<avx512>_<complexopname>_<mode><maskc_name><round_name>"
+ [(set (match_operand:VF_AVX512FP16VL 0 "register_operand" "=&v")
+ (unspec:VF_AVX512FP16VL
+ [(match_operand:VF_AVX512FP16VL 1 "nonimmediate_operand" "%v")
+ (match_operand:VF_AVX512FP16VL 2 "nonimmediate_operand" "<round_constraint>")]
+ UNSPEC_COMPLEX_F_C_MUL))]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+ "v<complexopname><ssemodesuffix>\t{<round_maskc_op3>%2, %1, %0<maskc_operand3>|%0<maskc_operand3>, %1, %2<round_maskc_op3>}"
+ [(set_attr "type" "ssemul")
+ (set_attr "mode" "<MODE>")])
+
+(define_expand "avx512fp16_fmaddcsh_v8hf_maskz<round_expand_name>"
+ [(match_operand:V8HF 0 "register_operand")
+ (match_operand:V8HF 1 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 2 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 3 "<round_expand_nimm_predicate>")
+ (match_operand:QI 4 "register_operand")]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+{
+ emit_insn (gen_avx512fp16_fma_fmaddcsh_v8hf_maskz<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ CONST0_RTX (V8HFmode), operands[4]<round_expand_operand>));
+ DONE;
+})
+
+(define_expand "avx512fp16_fcmaddcsh_v8hf_maskz<round_expand_name>"
+ [(match_operand:V8HF 0 "register_operand")
+ (match_operand:V8HF 1 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 2 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 3 "<round_expand_nimm_predicate>")
+ (match_operand:QI 4 "register_operand")]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+{
+ emit_insn (gen_avx512fp16_fma_fcmaddcsh_v8hf_maskz<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ CONST0_RTX (V8HFmode), operands[4]<round_expand_operand>));
+ DONE;
+})
+
+(define_insn "avx512fp16_fma_<complexopname>sh_v8hf<mask_scalarcz_name><round_scalarcz_name>"
+ [(set (match_operand:V8HF 0 "register_operand" "=&v")
+ (vec_merge:V8HF
+ (unspec:V8HF
+ [(match_operand:V8HF 1 "<round_scalarcz_nimm_predicate>" "v")
+ (match_operand:V8HF 2 "<round_scalarcz_nimm_predicate>" "<round_scalarcz_constraint>")
+ (match_operand:V8HF 3 "<round_scalarcz_nimm_predicate>" "0")]
+ UNSPEC_COMPLEX_F_C_MA)
+ (match_dup 2)
+ (const_int 3)))]
+ "TARGET_AVX512FP16"
+ "v<complexopname>sh\t{<round_scalarcz_mask_op4>%2, %1, %0<mask_scalarcz_operand4>|%0<mask_scalarcz_operand4>, %1, %2<round_scalarcz_maskcz_mask_op4>}"
+ [(set_attr "type" "ssemuladd")
+ (set_attr "mode" "V8HF")])
+
+(define_insn "avx512fp16_<complexopname>sh_v8hf_mask<round_name>"
+ [(set (match_operand:V8HF 0 "register_operand" "=&v")
+ (vec_merge:V8HF
+ (vec_merge:V8HF
+ (unspec:V8HF
+ [(match_operand:V8HF 1 "<round_nimm_predicate>" "v")
+ (match_operand:V8HF 2 "<round_nimm_predicate>" "<round_constraint>")
+ (match_operand:V8HF 3 "<round_nimm_predicate>" "0")]
+ UNSPEC_COMPLEX_F_C_MA)
+ (match_dup 1)
+ (unspec:QI [(match_operand:QI 4 "register_operand" "Yk")]
+ UNSPEC_COMPLEX_MASK))
+ (match_dup 2)
+ (const_int 3)))]
+ "TARGET_AVX512FP16"
+ "v<complexopname>sh\t{<round_op5>%2, %1, %0%{%4%}|%0%{%4%}, %1, %2<round_op5>}"
+ [(set_attr "type" "ssemuladd")
+ (set_attr "mode" "V8HF")])
+
+(define_insn "avx512fp16_<complexopname>sh_v8hf<mask_scalarc_name><round_scalarcz_name>"
+ [(set (match_operand:V8HF 0 "register_operand" "=&v")
+ (vec_merge:V8HF
+ (unspec:V8HF
+ [(match_operand:V8HF 1 "nonimmediate_operand" "v")
+ (match_operand:V8HF 2 "<round_scalarcz_nimm_predicate>" "<round_scalarcz_constraint>")]
+ UNSPEC_COMPLEX_F_C_MUL)
+ (match_dup 1)
+ (const_int 3)))]
+ "TARGET_AVX512FP16"
+ "v<complexopname>sh\t{<round_scalarc_mask_op3>%2, %1, %0<mask_scalarc_operand3>|%0<mask_scalarc_operand3>, %1, %2<round_scalarc_mask_op3>}"
+ [(set_attr "type" "ssemul")
+ (set_attr "mode" "V8HF")])
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Parallel half-precision floating point conversion operations
@@ -5824,6 +6040,12 @@
(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
+(define_expand "float<floatunssuffix><mode><ssePHmodelower>2"
+ [(set (match_operand:<ssePHmode> 0 "register_operand")
+ (any_float:<ssePHmode>
+ (match_operand:VI2H_AVX512VL 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16")
+
(define_insn "avx512fp16_vcvt<floatsuffix><sseintconvert>2ph_<mode><mask_name><round_name>"
[(set (match_operand:<ssePHmode> 0 "register_operand" "=v")
(any_float:<ssePHmode>
@@ -5834,11 +6056,23 @@
(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
-(define_expand "avx512fp16_vcvt<floatsuffix><sseintconvert>2ph_<mode>"
- [(set (match_operand:V8HF 0 "register_operand" "=v")
+(define_expand "float<floatunssuffix><mode>v4hf2"
+ [(set (match_operand:V4HF 0 "register_operand")
+ (any_float:V4HF
+ (match_operand:VI4_128_8_256 1 "vector_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ operands[0] = lowpart_subreg (V8HFmode, operands[0], V4HFmode);
+ emit_insn (gen_avx512fp16_float<floatunssuffix><mode>v4hf2 (operands[0],
+ operands[1]));
+ DONE;
+})
+
+(define_expand "avx512fp16_float<floatunssuffix><mode>v4hf2"
+ [(set (match_operand:V8HF 0 "register_operand")
(vec_concat:V8HF
- (any_float:V4HF (match_operand:VI4_128_8_256 1 "vector_operand" "vm"))
- (match_dup 2)))]
+ (any_float:V4HF (match_operand:VI4_128_8_256 1 "vector_operand"))
+ (match_dup 2)))]
"TARGET_AVX512FP16 && TARGET_AVX512VL"
"operands[2] = CONST0_RTX (V4HFmode);")
@@ -5897,11 +6131,23 @@
(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
-(define_expand "avx512fp16_vcvt<floatsuffix>qq2ph_v2di"
- [(set (match_operand:V8HF 0 "register_operand" "=v")
+(define_expand "float<floatunssuffix>v2div2hf2"
+ [(set (match_operand:V2HF 0 "register_operand")
+ (any_float:V2HF
+ (match_operand:V2DI 1 "vector_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ operands[0] = lowpart_subreg (V8HFmode, operands[0], V2HFmode);
+ emit_insn (gen_avx512fp16_float<floatunssuffix>v2div2hf2 (operands[0],
+ operands[1]));
+ DONE;
+})
+
+(define_expand "avx512fp16_float<floatunssuffix>v2div2hf2"
+ [(set (match_operand:V8HF 0 "register_operand")
(vec_concat:V8HF
- (any_float:V2HF (match_operand:V2DI 1 "vector_operand" "vm"))
- (match_dup 2)))]
+ (any_float:V2HF (match_operand:V2DI 1 "vector_operand"))
+ (match_dup 2)))]
"TARGET_AVX512FP16 && TARGET_AVX512VL"
"operands[2] = CONST0_RTX (V6HFmode);")
@@ -6000,6 +6246,12 @@
(set_attr "prefix" "evex")
(set_attr "mode" "HF")])
+(define_expand "fix<fixunssuffix>_trunc<ssePHmodelower><mode>2"
+ [(set (match_operand:VI2H_AVX512VL 0 "register_operand")
+ (any_fix:VI2H_AVX512VL
+ (match_operand:<ssePHmode> 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16")
+
(define_insn "avx512fp16_fix<fixunssuffix>_trunc<mode>2<mask_name><round_saeonly_name>"
[(set (match_operand:VI2H_AVX512VL 0 "register_operand" "=v")
(any_fix:VI2H_AVX512VL
@@ -6010,6 +6262,21 @@
(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
+(define_expand "fix<fixunssuffix>_truncv4hf<mode>2"
+ [(set (match_operand:VI4_128_8_256 0 "register_operand")
+ (any_fix:VI4_128_8_256
+ (match_operand:V4HF 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ if (!MEM_P (operands[1]))
+ {
+ operands[1] = lowpart_subreg (V8HFmode, operands[1], V4HFmode);
+ emit_insn (gen_avx512fp16_fix<fixunssuffix>_trunc<mode>2 (operands[0],
+ operands[1]));
+ DONE;
+ }
+})
+
(define_insn "avx512fp16_fix<fixunssuffix>_trunc<mode>2<mask_name>"
[(set (match_operand:VI4_128_8_256 0 "register_operand" "=v")
(any_fix:VI4_128_8_256
@@ -6032,6 +6299,21 @@
(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
+(define_expand "fix<fixunssuffix>_truncv2hfv2di2"
+ [(set (match_operand:V2DI 0 "register_operand")
+ (any_fix:V2DI
+ (match_operand:V2HF 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ if (!MEM_P (operands[1]))
+ {
+ operands[1] = lowpart_subreg (V8HFmode, operands[1], V2HFmode);
+ emit_insn (gen_avx512fp16_fix<fixunssuffix>_truncv2di2 (operands[0],
+ operands[1]));
+ DONE;
+ }
+})
+
(define_insn "avx512fp16_fix<fixunssuffix>_truncv2di2<mask_name>"
[(set (match_operand:V2DI 0 "register_operand" "=v")
(any_fix:V2DI
@@ -6080,6 +6362,12 @@
[(V16SF "x") (V8SF "x") (V4SF "x")
(V8DF "") (V4DF "") (V2DF "")])
+(define_expand "extend<ssePHmodelower><mode>2"
+ [(set (match_operand:VF48H_AVX512VL 0 "register_operand")
+ (float_extend:VF48H_AVX512VL
+ (match_operand:<ssePHmode> 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16")
+
(define_insn "avx512fp16_float_extend_ph<mode>2<mask_name><round_saeonly_name>"
[(set (match_operand:VF48H_AVX512VL 0 "register_operand" "=v")
(float_extend:VF48H_AVX512VL
@@ -6090,6 +6378,21 @@
(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
+(define_expand "extendv4hf<mode>2"
+ [(set (match_operand:VF4_128_8_256 0 "register_operand")
+ (float_extend:VF4_128_8_256
+ (match_operand:V4HF 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ if (!MEM_P (operands[1]))
+ {
+ operands[1] = lowpart_subreg (V8HFmode, operands[1], V4HFmode);
+ emit_insn (gen_avx512fp16_float_extend_ph<mode>2
+ (operands[0], operands[1]));
+ DONE;
+ }
+})
+
(define_insn "avx512fp16_float_extend_ph<mode>2<mask_name>"
[(set (match_operand:VF4_128_8_256 0 "register_operand" "=v")
(float_extend:VF4_128_8_256
@@ -6112,6 +6415,21 @@
(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
+(define_expand "extendv2hfv2df2"
+ [(set (match_operand:V2DF 0 "register_operand")
+ (float_extend:V2DF
+ (match_operand:V2HF 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ if (!MEM_P (operands[1]))
+ {
+ operands[1] = lowpart_subreg (V8HFmode, operands[1], V2HFmode);
+ emit_insn (gen_avx512fp16_float_extend_phv2df2
+ (operands[0], operands[1]));
+ DONE;
+ }
+})
+
(define_insn "avx512fp16_float_extend_phv2df2<mask_name>"
[(set (match_operand:V2DF 0 "register_operand" "=v")
(float_extend:V2DF
@@ -6134,6 +6452,12 @@
(set_attr "prefix" "evex")
(set_attr "mode" "TI")])
+(define_expand "trunc<mode><ssePHmodelower>2"
+ [(set (match_operand:<ssePHmode> 0 "register_operand")
+ (float_truncate:<ssePHmode>
+ (match_operand:VF48H_AVX512VL 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16")
+
(define_insn "avx512fp16_vcvt<castmode>2ph_<mode><mask_name><round_name>"
[(set (match_operand:<ssePHmode> 0 "register_operand" "=v")
(float_truncate:<ssePHmode>
@@ -6144,11 +6468,21 @@
(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
-(define_expand "avx512fp16_vcvt<castmode>2ph_<mode>"
- [(set (match_operand:V8HF 0 "register_operand" "=v")
+(define_expand "trunc<mode>v4hf2"
+ [(set (match_operand:V4HF 0 "register_operand")
+ (float_truncate:V4HF (match_operand:VF4_128_8_256 1 "vector_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ operands[0] = lowpart_subreg (V8HFmode, operands[0], V4HFmode);
+ emit_insn (gen_avx512fp16_trunc<mode>v4hf2 (operands[0], operands[1]));
+ DONE;
+})
+
+(define_expand "avx512fp16_trunc<mode>v4hf2"
+ [(set (match_operand:V8HF 0 "register_operand")
(vec_concat:V8HF
(float_truncate:V4HF
- (match_operand:VF4_128_8_256 1 "vector_operand" "vm"))
+ (match_operand:VF4_128_8_256 1 "vector_operand"))
(match_dup 2)))]
"TARGET_AVX512FP16 && TARGET_AVX512VL"
"operands[2] = CONST0_RTX (V4HFmode);")
@@ -6213,11 +6547,20 @@
(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
-(define_expand "avx512fp16_vcvtpd2ph_v2df"
- [(set (match_operand:V8HF 0 "register_operand" "=v")
+(define_expand "truncv2dfv2hf2"
+ [(set (match_operand:V2HF 0 "register_operand")
+ (float_truncate:V2HF (match_operand:V2DF 1 "vector_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ operands[0] = lowpart_subreg (V8HFmode, operands[0], V2HFmode);
+ emit_insn (gen_avx512fp16_truncv2dfv2hf2 (operands[0], operands[1]));
+ DONE;
+})
+
+(define_expand "avx512fp16_truncv2dfv2hf2"
+ [(set (match_operand:V8HF 0 "register_operand")
(vec_concat:V8HF
- (float_truncate:V2HF
- (match_operand:V2DF 1 "vector_operand" "vm"))
+ (float_truncate:V2HF (match_operand:V2DF 1 "vector_operand"))
(match_dup 2)))]
"TARGET_AVX512FP16 && TARGET_AVX512VL"
"operands[2] = CONST0_RTX (V6HFmode);")
@@ -15229,6 +15572,21 @@
DONE;
})
+(define_expand "vcondu<mode><sseintvecmodelower>"
+ [(set (match_operand:VF_AVX512FP16VL 0 "register_operand")
+ (if_then_else:VF_AVX512FP16VL
+ (match_operator 3 ""
+ [(match_operand:<sseintvecmode> 4 "vector_operand")
+ (match_operand:<sseintvecmode> 5 "vector_operand")])
+ (match_operand:VF_AVX512FP16VL 1 "general_operand")
+ (match_operand:VF_AVX512FP16VL 2 "general_operand")))]
+ "TARGET_AVX512FP16"
+{
+ bool ok = ix86_expand_int_vcond (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
(define_expand "vcondeq<VI8F_128:mode>v2di"
[(set (match_operand:VI8F_128 0 "register_operand")
(if_then_else:VI8F_128
@@ -21298,14 +21656,14 @@
(set_attr "mode" "<MODE>")])
(define_insn "*sse4_1_round<ssescalarmodesuffix>"
- [(set (match_operand:VF_128 0 "register_operand" "=Yr,*x,x,v")
- (vec_merge:VF_128
- (vec_duplicate:VF_128
+ [(set (match_operand:VFH_128 0 "register_operand" "=Yr,*x,x,v")
+ (vec_merge:VFH_128
+ (vec_duplicate:VFH_128
(unspec:<ssescalarmode>
[(match_operand:<ssescalarmode> 2 "nonimmediate_operand" "Yrm,*xm,xm,vm")
(match_operand:SI 3 "const_0_to_15_operand" "n,n,n,n")]
UNSPEC_ROUND))
- (match_operand:VF_128 1 "register_operand" "0,0,x,v")
+ (match_operand:VFH_128 1 "register_operand" "0,0,x,v")
(const_int 1)))]
"TARGET_SSE4_1"
"@
diff --git a/gcc/config/i386/subst.md b/gcc/config/i386/subst.md
index 157d49f..11e62c6 100644
--- a/gcc/config/i386/subst.md
+++ b/gcc/config/i386/subst.md
@@ -28,6 +28,9 @@
V16SF V8SF V4SF
V8DF V4DF V2DF])
+(define_mode_iterator SUBST_CV
+ [V32HF V16HF V8HF])
+
(define_mode_iterator SUBST_S
[QI HI SI DI])
@@ -42,9 +45,11 @@
QI HI SI DI SF DF])
(define_subst_attr "mask_name" "mask" "" "_mask")
+(define_subst_attr "maskc_name" "maskc" "" "_mask")
(define_subst_attr "mask_applied" "mask" "false" "true")
(define_subst_attr "mask_operand2" "mask" "" "%{%3%}%N2")
(define_subst_attr "mask_operand3" "mask" "" "%{%4%}%N3")
+(define_subst_attr "maskc_operand3" "maskc" "" "%{%4%}%N3")
(define_subst_attr "mask_operand3_1" "mask" "" "%%{%%4%%}%%N3") ;; for sprintf
(define_subst_attr "mask_operand4" "mask" "" "%{%5%}%N4")
(define_subst_attr "mask_operand6" "mask" "" "%{%7%}%N6")
@@ -89,6 +94,18 @@
(match_dup 0)
(match_operand:<avx512fmaskmode> 2 "register_operand" "Yk")))])
+(define_subst "maskc"
+ [(set (match_operand:SUBST_CV 0)
+ (match_operand:SUBST_CV 1))]
+ "TARGET_AVX512F"
+ [(set (match_dup 0)
+ (vec_merge:SUBST_CV
+ (match_dup 1)
+ (match_operand:SUBST_CV 2 "nonimm_or_0_operand" "0C")
+ (unspec:<avx512fmaskmode>
+ [(match_operand:<avx512fmaskcmode> 3 "register_operand" "Yk")]
+ UNSPEC_COMPLEX_MASK)))])
+
(define_subst_attr "mask_scalar_merge_name" "mask_scalar_merge" "" "_mask")
(define_subst_attr "mask_scalar_merge_operand3" "mask_scalar_merge" "" "%{%3%}")
(define_subst_attr "mask_scalar_merge_operand4" "mask_scalar_merge" "" "%{%4%}")
@@ -137,12 +154,31 @@
(match_operand:<avx512fmaskmode> 4 "register_operand" "Yk"))
(match_dup 2)
(const_int 1)))])
+(define_subst_attr "sdc_maskz_name" "sdc" "" "_maskz_1")
+(define_subst_attr "sdc_mask_op4" "sdc" "" "%{%5%}%N4")
+(define_subst_attr "sdc_mask_op5" "sdc" "" "%{%6%}%N5")
+(define_subst_attr "sdc_mask_mode512bit_condition" "sdc" "1" "(<MODE_SIZE> == 64 || TARGET_AVX512VL)")
+
+(define_subst "sdc"
+ [(set (match_operand:SUBST_CV 0)
+ (match_operand:SUBST_CV 1))]
+ ""
+ [(set (match_dup 0)
+ (vec_merge:SUBST_CV
+ (match_dup 1)
+ (match_operand:SUBST_CV 2 "const0_operand" "C")
+ (unspec:<avx512fmaskmode>
+ [(match_operand:<avx512fmaskcmode> 3 "register_operand" "Yk")]
+ UNSPEC_COMPLEX_MASK)))
+])
(define_subst_attr "round_name" "round" "" "_round")
(define_subst_attr "round_mask_operand2" "mask" "%R2" "%R4")
(define_subst_attr "round_mask_operand3" "mask" "%R3" "%R5")
+(define_subst_attr "round_maskc_operand3" "maskc" "%R3" "%R5")
(define_subst_attr "round_mask_operand4" "mask" "%R4" "%R6")
(define_subst_attr "round_sd_mask_operand4" "sd" "%R4" "%R6")
+(define_subst_attr "round_sdc_mask_operand4" "sdc" "%R4" "%R6")
(define_subst_attr "round_op2" "round" "" "%R2")
(define_subst_attr "round_op3" "round" "" "%R3")
(define_subst_attr "round_op4" "round" "" "%R4")
@@ -150,8 +186,10 @@
(define_subst_attr "round_op6" "round" "" "%R6")
(define_subst_attr "round_mask_op2" "round" "" "<round_mask_operand2>")
(define_subst_attr "round_mask_op3" "round" "" "<round_mask_operand3>")
+(define_subst_attr "round_maskc_op3" "round" "" "<round_maskc_operand3>")
(define_subst_attr "round_mask_op4" "round" "" "<round_mask_operand4>")
(define_subst_attr "round_sd_mask_op4" "round" "" "<round_sd_mask_operand4>")
+(define_subst_attr "round_sdc_mask_op4" "round" "" "<round_sdc_mask_operand4>")
(define_subst_attr "round_constraint" "round" "vm" "v")
(define_subst_attr "round_qq2phsuff" "round" "<qq2phsuff>" "")
(define_subst_attr "bcst_round_constraint" "round" "vmBr" "v")
@@ -189,6 +227,7 @@
(define_subst_attr "round_saeonly_mask_scalar_merge_operand4" "mask_scalar_merge" "%r4" "%r5")
(define_subst_attr "round_saeonly_maskz_scalar_operand5" "maskz_scalar" "%r5" "%r7")
(define_subst_attr "round_saeonly_sd_mask_operand5" "sd" "%r5" "%r7")
+(define_subst_attr "round_saeonly_sdc_mask_operand5" "sdc" "%r5" "%r7")
(define_subst_attr "round_saeonly_op2" "round_saeonly" "" "%r2")
(define_subst_attr "round_saeonly_op3" "round_saeonly" "" "%r3")
(define_subst_attr "round_saeonly_op4" "round_saeonly" "" "%r4")
@@ -289,8 +328,12 @@
(match_operand:<avx512fmaskmode> 5 "register_operand")])
(define_subst_attr "mask_scalar_name" "mask_scalar" "" "_mask")
+(define_subst_attr "mask_scalarcz_name" "mask_scalarcz" "" "_maskz")
+(define_subst_attr "mask_scalarc_name" "mask_scalarc" "" "_mask")
+(define_subst_attr "mask_scalarc_operand3" "mask_scalarc" "" "%{%4%}%N3")
(define_subst_attr "mask_scalar_operand3" "mask_scalar" "" "%{%4%}%N3")
(define_subst_attr "mask_scalar_operand4" "mask_scalar" "" "%{%5%}%N4")
+(define_subst_attr "mask_scalarcz_operand4" "mask_scalarcz" "" "%{%5%}%N4")
(define_subst "mask_scalar"
[(set (match_operand:SUBST_V 0)
@@ -308,12 +351,55 @@
(match_dup 2)
(const_int 1)))])
+(define_subst "mask_scalarcz"
+ [(set (match_operand:SUBST_CV 0)
+ (vec_merge:SUBST_CV
+ (match_operand:SUBST_CV 1)
+ (match_operand:SUBST_CV 2)
+ (const_int 3)))]
+ "TARGET_AVX512F"
+ [(set (match_dup 0)
+ (vec_merge:SUBST_CV
+ (vec_merge:SUBST_CV
+ (match_dup 1)
+ (match_operand:SUBST_CV 3 "const0_operand" "C")
+ (unspec:<avx512fmaskmode>
+ [(match_operand:<avx512fmaskcmode> 4 "register_operand" "Yk")]
+ UNSPEC_COMPLEX_MASK))
+ (match_dup 2)
+ (const_int 3)))])
+
+(define_subst "mask_scalarc"
+ [(set (match_operand:SUBST_CV 0)
+ (vec_merge:SUBST_CV
+ (match_operand:SUBST_CV 1)
+ (match_operand:SUBST_CV 2)
+ (const_int 3)))]
+ "TARGET_AVX512F"
+ [(set (match_dup 0)
+ (vec_merge:SUBST_CV
+ (vec_merge:SUBST_CV
+ (match_dup 1)
+ (match_operand:SUBST_CV 3 "nonimm_or_0_operand" "0C")
+ (unspec:<avx512fmaskmode>
+ [(match_operand:<avx512fmaskcmode> 4 "register_operand" "Yk")]
+ UNSPEC_COMPLEX_MASK))
+ (match_dup 2)
+ (const_int 3)))])
+
(define_subst_attr "round_scalar_name" "round_scalar" "" "_round")
+(define_subst_attr "round_scalarcz_name" "round_scalarcz" "" "_round")
(define_subst_attr "round_scalar_mask_operand3" "mask_scalar" "%R3" "%R5")
+(define_subst_attr "round_scalarc_mask_operand3" "mask_scalarc" "%R3" "%R5")
+(define_subst_attr "round_scalarcz_mask_operand4" "mask_scalarcz" "%R4" "%R6")
(define_subst_attr "round_scalar_mask_op3" "round_scalar" "" "<round_scalar_mask_operand3>")
+(define_subst_attr "round_scalarc_mask_op3" "round_scalarcz" "" "<round_scalarc_mask_operand3>")
+(define_subst_attr "round_scalarcz_mask_op4" "round_scalarcz" "" "<round_scalarcz_mask_operand4>")
(define_subst_attr "round_scalar_constraint" "round_scalar" "vm" "v")
+(define_subst_attr "round_scalarcz_constraint" "round_scalarcz" "vm" "v")
(define_subst_attr "round_scalar_prefix" "round_scalar" "vex" "evex")
(define_subst_attr "round_scalar_nimm_predicate" "round_scalar" "nonimmediate_operand" "register_operand")
+(define_subst_attr "round_scalarcz_nimm_predicate" "round_scalarcz" "vector_operand" "register_operand")
(define_subst "round_scalar"
[(set (match_operand:SUBST_V 0)
@@ -331,6 +417,22 @@
(match_operand:SI 3 "const_4_or_8_to_11_operand")]
UNSPEC_EMBEDDED_ROUNDING))])
+(define_subst "round_scalarcz"
+ [(set (match_operand:SUBST_V 0)
+ (vec_merge:SUBST_V
+ (match_operand:SUBST_V 1)
+ (match_operand:SUBST_V 2)
+ (const_int 3)))]
+ "TARGET_AVX512F"
+ [(set (match_dup 0)
+ (unspec:SUBST_V [
+ (vec_merge:SUBST_V
+ (match_dup 1)
+ (match_dup 2)
+ (const_int 3))
+ (match_operand:SI 3 "const_4_or_8_to_11_operand")]
+ UNSPEC_EMBEDDED_ROUNDING))])
+
(define_subst_attr "round_saeonly_scalar_name" "round_saeonly_scalar" "" "_round")
(define_subst_attr "round_saeonly_scalar_mask_operand3" "mask_scalar" "%r3" "%r5")
(define_subst_attr "round_saeonly_scalar_mask_operand4" "mask_scalar" "%r4" "%r6")
diff --git a/gcc/config/lm32/uclinux-elf.h b/gcc/config/lm32/uclinux-elf.h
index 370df4c5..5b638fa 100644
--- a/gcc/config/lm32/uclinux-elf.h
+++ b/gcc/config/lm32/uclinux-elf.h
@@ -67,6 +67,7 @@
#define TARGET_OS_CPP_BUILTINS() GNU_USER_TARGET_OS_CPP_BUILTINS()
+#undef LINK_GCC_C_SEQUENCE_SPEC
#define LINK_GCC_C_SEQUENCE_SPEC \
"%{static|static-pie:--start-group} %G %{!nolibc:%L} \
%{static|static-pie:--end-group}%{!static:%{!static-pie:%G}}"
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 0614302..69ba5bd 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -541,6 +541,16 @@ pa_option_override (void)
write_symbols = NO_DEBUG;
}
+ if (TARGET_64BIT && TARGET_HPUX)
+ {
+ /* DWARF5 is not supported by gdb. Don't emit DWARF5 unless
+ specifically selected. */
+ if (!global_options_set.x_dwarf_strict)
+ dwarf_strict = 1;
+ if (!global_options_set.x_dwarf_version)
+ dwarf_version = 4;
+ }
+
/* We only support the "big PIC" model now. And we always generate PIC
code when in 64bit mode. */
if (flag_pic == 1 || TARGET_64BIT)
diff --git a/gcc/config/pru/constraints.md b/gcc/config/pru/constraints.md
index a31ae93..1e0e703 100644
--- a/gcc/config/pru/constraints.md
+++ b/gcc/config/pru/constraints.md
@@ -34,6 +34,7 @@
;; The following constraints are intended for internal use only:
;; Rmd0, Rms0, Rms1: Registers for MUL instruction operands.
;; Rsib: Jump address register suitable for sibling calls.
+;; Rrio: The R30 and R31 I/O registers.
;; M: -255 to 0 (for converting ADD to SUB with suitable UBYTE OP2).
;; N: -32768 to 32767 (16-bit signed integer).
;; O: -128 to 127 (8-bit signed integer).
@@ -57,6 +58,10 @@
"@internal
The multiply source 1 register.")
+(define_register_constraint "Rrio" "REGIO_REGS"
+ "@internal
+ The R30 and R31 I/O registers.")
+
;; Integer constraints.
(define_constraint "I"
diff --git a/gcc/config/pru/predicates.md b/gcc/config/pru/predicates.md
index 469002f..1a4b98e 100644
--- a/gcc/config/pru/predicates.md
+++ b/gcc/config/pru/predicates.md
@@ -121,6 +121,25 @@
return 0;
})
+(define_predicate "regio_operand"
+ (match_code "subreg,reg")
+{
+ if (register_operand (op, mode))
+ {
+ int regno;
+
+ if (REG_P (op))
+ regno = REGNO (op);
+ else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
+ regno = REGNO (SUBREG_REG (op));
+ else
+ return 0;
+
+ return REGNO_REG_CLASS (regno) == REGIO_REGS;
+ }
+ return 0;
+})
+
(define_predicate "reg_or_const_int_operand"
(ior (match_operand 0 "const_int_operand")
(match_operand 0 "register_operand")))
diff --git a/gcc/config/pru/pru-pragma.c b/gcc/config/pru/pru-pragma.c
index 01d0761..3beec23 100644
--- a/gcc/config/pru/pru-pragma.c
+++ b/gcc/config/pru/pru-pragma.c
@@ -83,4 +83,6 @@ pru_register_pragmas (void)
{
c_register_pragma (NULL, "ctable_entry", pru_pragma_ctable_entry);
c_register_pragma (NULL, "CTABLE_ENTRY", pru_pragma_ctable_entry);
+
+ c_register_addr_space ("__regio_symbol", ADDR_SPACE_REGIO);
}
diff --git a/gcc/config/pru/pru-protos.h b/gcc/config/pru/pru-protos.h
index 74129e9..031ea9e 100644
--- a/gcc/config/pru/pru-protos.h
+++ b/gcc/config/pru/pru-protos.h
@@ -62,7 +62,10 @@ extern int pru_get_ctable_exact_base_index (unsigned HOST_WIDE_INT caddr);
extern int pru_get_ctable_base_index (unsigned HOST_WIDE_INT caddr);
extern int pru_get_ctable_base_offset (unsigned HOST_WIDE_INT caddr);
+extern int pru_symref2ioregno (rtx op);
+
extern void pru_register_abicheck_pass (void);
+
#endif /* RTX_CODE */
#ifdef TREE_CODE
diff --git a/gcc/config/pru/pru.c b/gcc/config/pru/pru.c
index 30d0da1..9f264b4 100644
--- a/gcc/config/pru/pru.c
+++ b/gcc/config/pru/pru.c
@@ -1403,11 +1403,42 @@ pru_valid_addr_expr_p (machine_mode mode, rtx base, rtx offset, bool strict_p)
return false;
}
-/* Implement TARGET_LEGITIMATE_ADDRESS_P. */
+/* Return register number (either for r30 or r31) which maps to the
+ corresponding symbol OP's name in the __regio_symbol address namespace.
+
+ If no mapping can be established (i.e. symbol name is invalid), then
+ return -1. */
+int pru_symref2ioregno (rtx op)
+{
+ if (!SYMBOL_REF_P (op))
+ return -1;
+
+ const char *name = XSTR (op, 0);
+ if (!strcmp (name, "__R30"))
+ return R30_REGNUM;
+ else if (!strcmp (name, "__R31"))
+ return R31_REGNUM;
+ else
+ return -1;
+}
+
+/* Implement TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P. */
static bool
-pru_legitimate_address_p (machine_mode mode,
- rtx operand, bool strict_p)
+pru_addr_space_legitimate_address_p (machine_mode mode, rtx operand,
+ bool strict_p, addr_space_t as)
{
+ if (as == ADDR_SPACE_REGIO)
+ {
+ /* Address space constraints for __regio_symbol have been checked in
+ TARGET_INSERT_ATTRIBUTES, and some more checks will be done
+ during RTL expansion of "mov<mode>". */
+ return true;
+ }
+ else if (as != ADDR_SPACE_GENERIC)
+ {
+ gcc_unreachable ();
+ }
+
switch (GET_CODE (operand))
{
/* Direct. */
@@ -2002,6 +2033,117 @@ pru_file_start (void)
need to confuse users with this warning. */
fprintf (asm_out_file, "\t.set no_warn_regname_label\n");
}
+
+/* Scan type TYP for pointer references to address space other than
+ ADDR_SPACE_GENERIC. Return true if such reference is found.
+ Much of this code was taken from the avr port. */
+
+static bool
+pru_nongeneric_pointer_addrspace (tree typ)
+{
+ while (ARRAY_TYPE == TREE_CODE (typ))
+ typ = TREE_TYPE (typ);
+
+ if (POINTER_TYPE_P (typ))
+ {
+ addr_space_t as;
+ tree target = TREE_TYPE (typ);
+
+ /* Pointer to function: Test the function's return type. */
+ if (FUNCTION_TYPE == TREE_CODE (target))
+ return pru_nongeneric_pointer_addrspace (TREE_TYPE (target));
+
+ /* "Ordinary" pointers... */
+
+ while (TREE_CODE (target) == ARRAY_TYPE)
+ target = TREE_TYPE (target);
+
+ as = TYPE_ADDR_SPACE (target);
+
+ if (!ADDR_SPACE_GENERIC_P (as))
+ return true;
+
+ /* Scan pointer's target type. */
+ return pru_nongeneric_pointer_addrspace (target);
+ }
+
+ return false;
+}
+
+/* Implement `TARGET_INSERT_ATTRIBUTES'. For PRU it's used as a hook to
+ provide better diagnostics for some invalid usages of the __regio_symbol
+ address space.
+
+ Any escapes of the following checks are supposed to be caught
+ during the "mov<mode>" pattern expansion. */
+
+static void
+pru_insert_attributes (tree node, tree *attributes ATTRIBUTE_UNUSED)
+{
+
+ /* Validate __regio_symbol variable declarations. */
+ if (VAR_P (node))
+ {
+ const char *name = DECL_NAME (node)
+ ? IDENTIFIER_POINTER (DECL_NAME (node))
+ : "<unknown>";
+ tree typ = TREE_TYPE (node);
+ addr_space_t as = TYPE_ADDR_SPACE (typ);
+
+ if (as == ADDR_SPACE_GENERIC)
+ return;
+
+ if (AGGREGATE_TYPE_P (typ))
+ {
+ error ("aggregate types are prohibited in "
+ "%<__regio_symbol%> address space");
+ /* Don't bother anymore. Below checks would pile
+ meaningless errors, which would confuse user. */
+ return;
+ }
+ if (DECL_INITIAL (node) != NULL_TREE)
+ error ("variables in %<__regio_symbol%> address space "
+ "cannot have initial value");
+ if (DECL_REGISTER (node))
+ error ("variables in %<__regio_symbol%> address space "
+ "cannot be declared %<register%>");
+ if (!TYPE_VOLATILE (typ))
+ error ("variables in %<__regio_symbol%> address space "
+ "must be declared %<volatile%>");
+ if (!DECL_EXTERNAL (node))
+ error ("variables in %<__regio_symbol%> address space "
+ "must be declared %<extern%>");
+ if (TYPE_MODE (typ) != SImode)
+ error ("only 32-bit access is supported "
+ "for %<__regio_symbol%> address space");
+ if (strcmp (name, "__R30") != 0 && strcmp (name, "__R31") != 0)
+ error ("register name %<%s%> not recognized "
+ "in %<__regio_symbol%> address space", name);
+ }
+
+ tree typ = NULL_TREE;
+
+ switch (TREE_CODE (node))
+ {
+ case FUNCTION_DECL:
+ typ = TREE_TYPE (TREE_TYPE (node));
+ break;
+ case TYPE_DECL:
+ case RESULT_DECL:
+ case VAR_DECL:
+ case FIELD_DECL:
+ case PARM_DECL:
+ typ = TREE_TYPE (node);
+ break;
+ case POINTER_TYPE:
+ typ = node;
+ break;
+ default:
+ break;
+ }
+ if (typ != NULL_TREE && pru_nongeneric_pointer_addrspace (typ))
+ error ("pointers to %<__regio_symbol%> address space are prohibited");
+}
/* Function argument related. */
@@ -2933,6 +3075,9 @@ pru_unwind_word_mode (void)
#undef TARGET_ASM_FILE_START
#define TARGET_ASM_FILE_START pru_file_start
+#undef TARGET_INSERT_ATTRIBUTES
+#define TARGET_INSERT_ATTRIBUTES pru_insert_attributes
+
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS pru_init_builtins
#undef TARGET_EXPAND_BUILTIN
@@ -2979,8 +3124,9 @@ pru_unwind_word_mode (void)
#undef TARGET_MUST_PASS_IN_STACK
#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
-#undef TARGET_LEGITIMATE_ADDRESS_P
-#define TARGET_LEGITIMATE_ADDRESS_P pru_legitimate_address_p
+#undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
+#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
+ pru_addr_space_legitimate_address_p
#undef TARGET_INIT_LIBFUNCS
#define TARGET_INIT_LIBFUNCS pru_init_libfuncs
diff --git a/gcc/config/pru/pru.h b/gcc/config/pru/pru.h
index 9b6be32..03f08b1 100644
--- a/gcc/config/pru/pru.h
+++ b/gcc/config/pru/pru.h
@@ -215,6 +215,7 @@ enum reg_class
MULDST_REGS,
MULSRC0_REGS,
MULSRC1_REGS,
+ REGIO_REGS,
GP_REGS,
ALL_REGS,
LIM_REG_CLASSES
@@ -229,6 +230,7 @@ enum reg_class
"MULDST_REGS", \
"MULSRC0_REGS", \
"MULSRC1_REGS", \
+ "REGIO_REGS", \
"GP_REGS", \
"ALL_REGS" }
@@ -242,6 +244,7 @@ enum reg_class
/* MULDST_REGS */ { 0, 0, 0, 0x00000f00, 0}, \
/* MULSRC0_REGS */ { 0, 0, 0, 0x000f0000, 0}, \
/* MULSRC1_REGS */ { 0, 0, 0, 0x00f00000, 0}, \
+ /* REGIO_REGS */ { 0, 0, 0, 0xff000000, 0}, \
/* GP_REGS */ { ~0, ~0, ~0, ~0, 0}, \
/* ALL_REGS */ { ~0,~0, ~0, ~0, ~0} \
}
@@ -252,6 +255,8 @@ enum reg_class
((REGNO) == MULDST_REGNUM ? MULDST_REGS \
: (REGNO) == MULSRC0_REGNUM ? MULSRC0_REGS \
: (REGNO) == MULSRC1_REGNUM ? MULSRC1_REGS \
+ : (REGNO) == R30_REGNUM ? REGIO_REGS \
+ : (REGNO) == R31_REGNUM ? REGIO_REGS \
: (REGNO) >= FIRST_ARG_REGNUM \
&& (REGNO) <= LAST_ARG_REGNUM ? SIB_REGS \
: (REGNO) == STATIC_CHAIN_REGNUM ? SIB_REGS \
diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md
index e6cfa8e..c0ded8e 100644
--- a/gcc/config/pru/pru.md
+++ b/gcc/config/pru/pru.md
@@ -36,6 +36,8 @@
(MULSRC0_REGNUM 112) ; Multiply source register.
(MULSRC1_REGNUM 116) ; Multiply source register.
(LAST_NONIO_GP_REGNUM 119) ; Last non-I/O general purpose register.
+ (R30_REGNUM 120) ; R30 I/O register.
+ (R31_REGNUM 124) ; R31 I/O register.
(LOOPCNTR_REGNUM 128) ; internal LOOP counter register
(LAST_GP_REGNUM 132) ; Last general purpose register.
@@ -49,6 +51,13 @@
]
)
+;; Enumerate address spaces.
+(define_constants
+ [
+ (ADDR_SPACE_REGIO 1) ; Access to R30 and R31 I/O registers.
+ ]
+)
+
;; Enumeration of UNSPECs.
(define_c_enum "unspec" [
@@ -68,6 +77,9 @@
UNSPECV_HALT
UNSPECV_BLOCKAGE
+
+ UNSPECV_REGIO_READ
+ UNSPECV_REGIO_WRITE
])
; Length of an instruction (in bytes).
@@ -129,11 +141,62 @@
(match_operand:MOV8_16_32 1 "general_operand"))]
""
{
- /* It helps to split constant loading and memory access
- early, so that the LDI/LDI32 instructions can be hoisted
- outside a loop body. */
- if (MEM_P (operands[0]))
- operands[1] = force_reg (<MODE>mode, operands[1]);
+ if (MEM_P (operands[0])
+ && MEM_ADDR_SPACE (operands[0]) == ADDR_SPACE_REGIO)
+
+ {
+ /* Intercept writes to the SImode register I/O "address space". */
+ gcc_assert (<MODE>mode == SImode);
+
+ if (!SYMBOL_REF_P (XEXP (operands[0], 0)))
+ {
+ error ("invalid access to %<__regio_symbol%> address space");
+ FAIL;
+ }
+
+ if (!REG_P (operands[1]))
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+
+ int regiono = pru_symref2ioregno (XEXP (operands[0], 0));
+ gcc_assert (regiono >= 0);
+ rtx regio = gen_rtx_REG (<MODE>mode, regiono);
+ rtx unspecv = gen_rtx_UNSPEC_VOLATILE (<MODE>mode,
+ gen_rtvec (1, operands[1]),
+ UNSPECV_REGIO_WRITE);
+ emit_insn (gen_rtx_SET (regio, unspecv));
+ DONE;
+ }
+ else if (MEM_P (operands[1])
+ && MEM_ADDR_SPACE (operands[1]) == ADDR_SPACE_REGIO)
+ {
+ /* Intercept reads from the SImode register I/O "address space". */
+ gcc_assert (<MODE>mode == SImode);
+
+ if (!SYMBOL_REF_P (XEXP (operands[1], 0)))
+ {
+ error ("invalid access to %<__regio_symbol%> address space");
+ FAIL;
+ }
+
+ if (MEM_P (operands[0]))
+ operands[0] = force_reg (<MODE>mode, operands[0]);
+
+ int regiono = pru_symref2ioregno (XEXP (operands[1], 0));
+ gcc_assert (regiono >= 0);
+ rtx regio = gen_rtx_REG (<MODE>mode, regiono);
+ rtx unspecv = gen_rtx_UNSPEC_VOLATILE (<MODE>mode,
+ gen_rtvec (1, regio),
+ UNSPECV_REGIO_READ);
+ emit_insn (gen_rtx_SET (operands[0], unspecv));
+ DONE;
+ }
+ else if (MEM_P (operands[0]))
+ {
+ /* It helps to split constant loading and memory access
+ early, so that the LDI/LDI32 instructions can be hoisted
+ outside a loop body. */
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+ }
})
;; Keep a single pattern for 32 bit MOV operations. LRA requires that the
@@ -546,6 +609,35 @@
(include "alu-zext.md")
+;; Patterns for accessing the R30/R31 I/O registers.
+
+(define_insn "*regio_readsi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "regio_operand" "Rrio")]
+ UNSPECV_REGIO_READ))]
+ ""
+ "mov\\t%0, %1"
+ [(set_attr "type" "alu")])
+
+(define_insn "*regio_nozext_writesi"
+ [(set (match_operand:SI 0 "regio_operand" "=Rrio")
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "register_operand" "r")]
+ UNSPECV_REGIO_WRITE))]
+ ""
+ "mov\\t%0, %1"
+ [(set_attr "type" "alu")])
+
+(define_insn "*regio_zext_write_r30<EQS0:mode>"
+ [(set (match_operand:SI 0 "regio_operand" "=Rrio")
+ (unspec_volatile:SI
+ [(zero_extend:SI (match_operand:EQS0 1 "register_operand" "r"))]
+ UNSPECV_REGIO_WRITE))]
+ ""
+ "mov\\t%0, %1"
+ [(set_attr "type" "alu")])
+
;; DI logical ops could be automatically split into WORD-mode ops in
;; expand_binop(). But then we'll miss an opportunity to use SI mode
;; operations, since WORD mode for PRU is QI.
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index f88877f..98364f0 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -802,7 +802,7 @@
rtx hp = gen_reg_rtx (<MODE>mode);
rtx lp = gen_reg_rtx (<MODE>mode);
- emit_insn (gen_mul<mode>3_highpart (hp, operands[1], operands[2]));
+ emit_insn (gen_smul<mode>3_highpart (hp, operands[1], operands[2]));
emit_insn (gen_mul<mode>3 (operands[0], operands[1], operands[2]));
emit_insn (gen_ashr<mode>3 (lp, operands[0],
GEN_INT (BITS_PER_WORD - 1)));
@@ -899,14 +899,14 @@
emit_insn (gen_muldi3 (low, operands[1], operands[2]));
rtx high = gen_reg_rtx (DImode);
- emit_insn (gen_<u>muldi3_highpart (high, operands[1], operands[2]));
+ emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
emit_move_insn (gen_lowpart (DImode, operands[0]), low);
emit_move_insn (gen_highpart (DImode, operands[0]), high);
DONE;
})
-(define_insn "<u>muldi3_highpart"
+(define_insn "<su>muldi3_highpart"
[(set (match_operand:DI 0 "register_operand" "=r")
(truncate:DI
(lshiftrt:TI
@@ -961,13 +961,13 @@
{
rtx temp = gen_reg_rtx (SImode);
emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
- emit_insn (gen_<u>mulsi3_highpart (riscv_subword (operands[0], true),
+ emit_insn (gen_<su>mulsi3_highpart (riscv_subword (operands[0], true),
operands[1], operands[2]));
emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
DONE;
})
-(define_insn "<u>mulsi3_highpart"
+(define_insn "<su>mulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=r")
(truncate:SI
(lshiftrt:DI
diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h
index 6abf8e8..120b01f 100644
--- a/gcc/config/rs6000/darwin.h
+++ b/gcc/config/rs6000/darwin.h
@@ -203,7 +203,7 @@
/* Make both r2 and r13 available for allocation. */
#define FIXED_R2 0
-#define FIXED_R13 0
+#define FIXED_R13 TARGET_64BIT
/* Base register for access to local variables of the function. */
@@ -213,6 +213,9 @@
#undef RS6000_PIC_OFFSET_TABLE_REGNUM
#define RS6000_PIC_OFFSET_TABLE_REGNUM 31
+#undef FIRST_SAVED_GP_REGNO
+#define FIRST_SAVED_GP_REGNO 13
+
/* Darwin's stack must remain 16-byte aligned for both 32 and 64 bit
ABIs. */
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index 7d48548..2eceb2c7 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -6223,11 +6223,19 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
or vector type. If a non-floating point or vector type is found, or
if a floating point or vector type that doesn't match a non-VOIDmode
*MODEP is found, then return -1, otherwise return the count in the
- sub-tree. */
+ sub-tree.
+
+ There have been some ABI snafus along the way with C++. Modify
+ EMPTY_BASE_SEEN to a nonzero value iff a C++ empty base class makes
+ an appearance; separate flag bits indicate whether or not such a
+ field is marked "no unique address". Modify ZERO_WIDTH_BF_SEEN
+ to 1 iff a C++ zero-length bitfield makes an appearance, but
+ in this case otherwise treat this as still being a homogeneous
+ aggregate. */
static int
rs6000_aggregate_candidate (const_tree type, machine_mode *modep,
- int *empty_base_seen)
+ int *empty_base_seen, int *zero_width_bf_seen)
{
machine_mode mode;
HOST_WIDE_INT size;
@@ -6298,7 +6306,8 @@ rs6000_aggregate_candidate (const_tree type, machine_mode *modep,
return -1;
count = rs6000_aggregate_candidate (TREE_TYPE (type), modep,
- empty_base_seen);
+ empty_base_seen,
+ zero_width_bf_seen);
if (count == -1
|| !index
|| !TYPE_MAX_VALUE (index)
@@ -6336,6 +6345,26 @@ rs6000_aggregate_candidate (const_tree type, machine_mode *modep,
if (TREE_CODE (field) != FIELD_DECL)
continue;
+ if (DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (field))
+ {
+ /* GCC 11 and earlier generated incorrect code in a rare
+ corner case for C++. When a RECORD_TYPE looks like a
+ homogeneous aggregate, except that it also contains
+ one or more zero-width bit fields, these earlier
+ compilers would incorrectly pass the fields in FPRs
+ or VSRs. This occurred because the front end wrongly
+ removed these bitfields from the RECORD_TYPE. In
+ GCC 12 and later, the front end flaw was corrected.
+ We want to diagnose this case. To do this, we pretend
+ that we don't see the zero-width bit fields (hence
+ the continue statement here), but pass back a flag
+ indicating what happened. The caller then diagnoses
+ the issue and rejects the RECORD_TYPE as a homogeneous
+ aggregate. */
+ *zero_width_bf_seen = 1;
+ continue;
+ }
+
if (DECL_FIELD_ABI_IGNORED (field))
{
if (lookup_attribute ("no_unique_address",
@@ -6347,7 +6376,8 @@ rs6000_aggregate_candidate (const_tree type, machine_mode *modep,
}
sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep,
- empty_base_seen);
+ empty_base_seen,
+ zero_width_bf_seen);
if (sub_count < 0)
return -1;
count += sub_count;
@@ -6381,7 +6411,8 @@ rs6000_aggregate_candidate (const_tree type, machine_mode *modep,
continue;
sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep,
- empty_base_seen);
+ empty_base_seen,
+ zero_width_bf_seen);
if (sub_count < 0)
return -1;
count = count > sub_count ? count : sub_count;
@@ -6423,8 +6454,10 @@ rs6000_discover_homogeneous_aggregate (machine_mode mode, const_tree type,
{
machine_mode field_mode = VOIDmode;
int empty_base_seen = 0;
+ int zero_width_bf_seen = 0;
int field_count = rs6000_aggregate_candidate (type, &field_mode,
- &empty_base_seen);
+ &empty_base_seen,
+ &zero_width_bf_seen);
if (field_count > 0)
{
@@ -6460,6 +6493,25 @@ rs6000_discover_homogeneous_aggregate (machine_mode mode, const_tree type,
last_reported_type_uid = uid;
}
}
+ if (zero_width_bf_seen && warn_psabi)
+ {
+ static unsigned last_reported_type_uid;
+ unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (type));
+ if (uid != last_reported_type_uid)
+ {
+ inform (input_location,
+ "ELFv2 parameter passing for an argument "
+ "containing zero-width bit fields but that is "
+ "otherwise a homogeneous aggregate was "
+ "corrected in GCC 12");
+ last_reported_type_uid = uid;
+ }
+ if (elt_mode)
+ *elt_mode = mode;
+ if (n_elts)
+ *n_elts = 1;
+ return false;
+ }
return true;
}
}
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 060f51a..ad86072 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -5289,9 +5289,6 @@ struct rs6000_cost_data
static void
rs6000_density_test (rs6000_cost_data *data)
{
- const int DENSITY_PCT_THRESHOLD = 85;
- const int DENSITY_SIZE_THRESHOLD = 70;
- const int DENSITY_PENALTY = 10;
struct loop *loop = data->loop_info;
basic_block *bbs = get_loop_body (loop);
int nbbs = loop->num_nodes;
@@ -5327,26 +5324,21 @@ rs6000_density_test (rs6000_cost_data *data)
free (bbs);
density_pct = (vec_cost * 100) / (vec_cost + not_vec_cost);
- if (density_pct > DENSITY_PCT_THRESHOLD
- && vec_cost + not_vec_cost > DENSITY_SIZE_THRESHOLD)
+ if (density_pct > rs6000_density_pct_threshold
+ && vec_cost + not_vec_cost > rs6000_density_size_threshold)
{
- data->cost[vect_body] = vec_cost * (100 + DENSITY_PENALTY) / 100;
+ data->cost[vect_body] = vec_cost * (100 + rs6000_density_penalty) / 100;
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"density %d%%, cost %d exceeds threshold, penalizing "
- "loop body cost by %d%%\n", density_pct,
- vec_cost + not_vec_cost, DENSITY_PENALTY);
+ "loop body cost by %u%%\n", density_pct,
+ vec_cost + not_vec_cost, rs6000_density_penalty);
}
/* Check whether we need to penalize the body cost to account
for excess strided or elementwise loads. */
if (data->extra_ctor_cost > 0)
{
- /* Threshold for load stmts percentage in all vectorized stmts. */
- const int DENSITY_LOAD_PCT_THRESHOLD = 45;
- /* Threshold for total number of load stmts. */
- const int DENSITY_LOAD_NUM_THRESHOLD = 20;
-
gcc_assert (data->nloads <= data->nstmts);
unsigned int load_pct = (data->nloads * 100) / data->nstmts;
@@ -5360,8 +5352,8 @@ rs6000_density_test (rs6000_cost_data *data)
the loads.
One typical case is the innermost loop of the hotspot of SPEC2017
503.bwaves_r without loop interchange. */
- if (data->nloads > DENSITY_LOAD_NUM_THRESHOLD
- && load_pct > DENSITY_LOAD_PCT_THRESHOLD)
+ if (data->nloads > (unsigned int) rs6000_density_load_num_threshold
+ && load_pct > (unsigned int) rs6000_density_load_pct_threshold)
{
data->cost[vect_body] += data->extra_ctor_cost;
if (dump_enabled_p ())
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index c1cb9ab..9d7878f 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -639,3 +639,41 @@ Enable instructions that guard against return-oriented programming attacks.
mprivileged
Target Var(rs6000_privileged) Init(0)
Generate code that will run in privileged state.
+
+-param=rs6000-density-pct-threshold=
+Target Undocumented Joined UInteger Var(rs6000_density_pct_threshold) Init(85) IntegerRange(0, 100) Param
+When costing for loop vectorization, we probably need to penalize the loop body
+cost if the existing cost model may not adequately reflect delays from
+unavailable vector resources. We collect the cost for vectorized statements
+and non-vectorized statements separately, check the proportion of vec_cost to
+total cost of vec_cost and non vec_cost, and penalize only if the proportion
+exceeds the threshold specified by this parameter. The default value is 85.
+
+-param=rs6000-density-size-threshold=
+Target Undocumented Joined UInteger Var(rs6000_density_size_threshold) Init(70) IntegerRange(0, 1000) Param
+Like parameter rs6000-density-pct-threshold, we also check the total sum of
+vec_cost and non vec_cost, and penalize only if the sum exceeds the threshold
+specified by this parameter. The default value is 70.
+
+-param=rs6000-density-penalty=
+Target Undocumented Joined UInteger Var(rs6000_density_penalty) Init(10) IntegerRange(0, 1000) Param
+When both heuristics with rs6000-density-pct-threshold and
+rs6000-density-size-threshold are satisfied, we decide to penalize the loop
+body cost by the value which is specified by this parameter. The default
+value is 10.
+
+-param=rs6000-density-load-pct-threshold=
+Target Undocumented Joined UInteger Var(rs6000_density_load_pct_threshold) Init(45) IntegerRange(0, 100) Param
+When costing for loop vectorization, we probably need to penalize the loop body
+cost by accounting for excess strided or elementwise loads. We collect the
+numbers for general statements and load statements according to the information
+for statements to be vectorized, check the proportion of load statements, and
+penalize only if the proportion exceeds the threshold specified by this
+parameter. The default value is 45.
+
+-param=rs6000-density-load-num-threshold=
+Target Undocumented Joined UInteger Var(rs6000_density_load_num_threshold) Init(20) IntegerRange(0, 1000) Param
+Like parameter rs6000-density-load-pct-threshold, we also check if the total
+number of load statements exceeds the threshold specified by this parameter,
+and penalize only if it's satisfied. The default value is 20.
+
diff --git a/gcc/config/rs6000/vxworks.h b/gcc/config/rs6000/vxworks.h
index 5facbbb..d8ecc02 100644
--- a/gcc/config/rs6000/vxworks.h
+++ b/gcc/config/rs6000/vxworks.h
@@ -147,10 +147,6 @@ along with GCC; see the file COPYING3. If not see
#undef FUNCTION_PROFILER
#define FUNCTION_PROFILER(FILE,LABELNO) VXWORKS_FUNCTION_PROFILER(FILE,LABELNO)
-/* Initialize library function table. */
-#undef TARGET_INIT_LIBFUNCS
-#define TARGET_INIT_LIBFUNCS rs6000_vxworks_init_libfuncs
-
/* Nor sdata, for kernel mode. We use this in
SUBSUBTARGET_INITIALIZE_OPTIONS, after rs6000_rtp has been initialized. */
#undef SDATA_DEFAULT_SIZE
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 54dd633..e043854 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -6414,6 +6414,15 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
if (bitsize + bitpos > GET_MODE_BITSIZE (mode))
return false;
+ /* Just a move. */
+ if (bitpos == 0
+ && bitsize == GET_MODE_BITSIZE (GET_MODE (src))
+ && mode == GET_MODE (src))
+ {
+ emit_move_insn (dest, src);
+ return true;
+ }
+
/* Generate INSERT IMMEDIATE (IILL et al). */
/* (set (ze (reg)) (const_int)). */
if (TARGET_ZARCH
@@ -6510,6 +6519,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
&& (bitpos & 32) == ((bitpos + bitsize - 1) & 32)
&& MEM_P (src)
&& (mode == DImode || mode == SImode)
+ && mode != smode
&& register_operand (dest, mode))
{
/* Emit a strict_low_part pattern if possible. */
diff --git a/gcc/config/s390/tpf.md b/gcc/config/s390/tpf.md
index 297e9d1..35b3719 100644
--- a/gcc/config/s390/tpf.md
+++ b/gcc/config/s390/tpf.md
@@ -21,7 +21,8 @@
[(unspec_volatile [(match_operand 0 "const_int_operand" "J")
(match_operand 1 "const_int_operand" "J")]
UNSPECV_TPF_PROLOGUE)
- (clobber (reg:DI 1))]
+ (clobber (reg:DI 1))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_TPF_PROFILING"
"larl\t%%r1,.+14\;tm\t%0,255\;bnz\t%1"
[(set_attr "length" "14")])
@@ -31,7 +32,8 @@
[(unspec_volatile [(match_operand 0 "const_int_operand" "J")
(match_operand 1 "const_int_operand" "J")]
UNSPECV_TPF_EPILOGUE)
- (clobber (reg:DI 1))]
+ (clobber (reg:DI 1))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_TPF_PROFILING"
"larl\t%%r1,.+14\;tm\t%0,255\;bnz\t%1"
[(set_attr "length" "14")])
diff --git a/gcc/configure b/gcc/configure
index b3de170..5ea5a1b 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -1826,7 +1826,8 @@ Optional Packages:
Root for documentation URLs
--with-changes-root-url=URL
Root for GCC changes URLs
- --with-multilib-list select multilibs (AArch64, SH and x86-64 only)
+ --with-multilib-list select multilibs (AArch64, ARM, OR1K, RISC-V, SH and
+ x86-64 only)
--with-multilib-generator
Multi-libs configuration string (RISC-V only)
--with-zstd=PATH specify prefix directory for installed zstd library.
@@ -19454,7 +19455,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 19457 "configure"
+#line 19458 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -19560,7 +19561,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 19563 "configure"
+#line 19564 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -28756,22 +28757,241 @@ esac
case "$target" in
amdgcn-* | gcn-*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+sram-ecc for fiji" >&5
-$as_echo_n "checking assembler for assembler accepts -mattr=+sram-ecc for fiji... " >&6; }
+ # Test the LLVM assembler syntax dialect; they have made a number of
+ # changes between LLVM 12 & 13 without any backward compatibility.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler amdgcn_target v2/3 syntax" >&5
+$as_echo_n "checking assembler for assembler amdgcn_target v2/3 syntax... " >&6; }
+if ${gcc_cv_as_gcn_asm_v3_syntax+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_asm_v3_syntax=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx906+xnack"' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ gcc_cv_as_gcn_asm_v3_syntax=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_gcn_asm_v3_syntax" >&5
+$as_echo "$gcc_cv_as_gcn_asm_v3_syntax" >&6; }
+if test $gcc_cv_as_gcn_asm_v3_syntax = yes; then
+
+$as_echo "#define HAVE_GCN_ASM_V3_SYNTAX 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler amdgcn_target v4 syntax" >&5
+$as_echo_n "checking assembler for assembler amdgcn_target v4 syntax... " >&6; }
+if ${gcc_cv_as_gcn_asm_v4_syntax+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_asm_v4_syntax=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx908:xnack+"' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ gcc_cv_as_gcn_asm_v4_syntax=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_gcn_asm_v4_syntax" >&5
+$as_echo "$gcc_cv_as_gcn_asm_v4_syntax" >&6; }
+if test $gcc_cv_as_gcn_asm_v4_syntax = yes; then
+
+$as_echo "#define HAVE_GCN_ASM_V4_SYNTAX 1" >>confdefs.h
+
+fi
+
+
+ # Some attribute names changed in the move to v4 ...
+ if test $gcc_cv_as_gcn_asm_v3_syntax = yes; then
+ sramopt="+sram-ecc"
+ sramattr="+sram-ecc"
+ xnackattr="+xnack"
+ elif test $gcc_cv_as_gcn_asm_v4_syntax = yes; then
+ sramopt="+sramecc"
+ sramattr=":sramecc+"
+ xnackattr=":xnack+"
+ else
+ as_fn_error $? "Unrecognised assembler version" "$LINENO" 5
+ fi
+
+ # Test whether the LLVM assembler accepts -mattr=+xnack without any
+ # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+ # LLVM 12+ throws a warning for GPUs without support.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for fiji" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for fiji... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_fiji+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_xnack_ecc_fiji=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=fiji -mattr=+xnack 2>conftest.err -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_xnack_ecc_fiji=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_gcn_xnack_ecc_fiji" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_fiji" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_fiji = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_FIJI 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for gfx900" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for gfx900... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_gfx900+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_xnack_ecc_gfx900=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=+xnack 2>conftest.err -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_xnack_ecc_gfx900=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_gcn_xnack_ecc_gfx900" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_gfx900" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_gfx900 = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_GFX900 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for gfx906" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for gfx906... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_gfx906+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_xnack_ecc_gfx906=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack 2>conftest.err -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_xnack_ecc_gfx906=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_gcn_xnack_ecc_gfx906" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_gfx906" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_gfx906 = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_GFX906 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for gfx908" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for gfx908... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_gfx908+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_xnack_ecc_gfx908=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack 2>conftest.err -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_xnack_ecc_gfx908=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_gcn_xnack_ecc_gfx908" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_gfx908" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_gfx908 = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_GFX908 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+
+ # Test whether the LLVM assembler accepts -mattr=+sramecc without any
+ # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+ # (some?) LLVM 12 rejects it for all GPUs, and LLVM13 throws a warning
+ # for GPUs without support.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for fiji" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for fiji... " >&6; }
if ${gcc_cv_as_gcn_sram_ecc_fiji+:} false; then :
$as_echo_n "(cached) " >&6
else
gcc_cv_as_gcn_sram_ecc_fiji=no
if test x$gcc_cv_as != x; then
- $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx803+sram-ecc"' > conftest.s
- if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=fiji -mattr=-xnack -mattr=+sram-ecc -o conftest.o conftest.s >&5'
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=fiji -mattr=$sramopt 2>conftest.err -o conftest.o conftest.s >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then
- gcc_cv_as_gcn_sram_ecc_fiji=yes
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_sram_ecc_fiji=yes
else
echo "configure: failed program was" >&5
cat conftest.s >&5
@@ -28787,22 +29007,24 @@ $as_echo "#define HAVE_GCN_SRAM_ECC_FIJI 1" >>confdefs.h
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+sram-ecc for gfx900" >&5
-$as_echo_n "checking assembler for assembler accepts -mattr=+sram-ecc for gfx900... " >&6; }
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for gfx900" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for gfx900... " >&6; }
if ${gcc_cv_as_gcn_sram_ecc_gfx900+:} false; then :
$as_echo_n "(cached) " >&6
else
gcc_cv_as_gcn_sram_ecc_gfx900=no
if test x$gcc_cv_as != x; then
- $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx900+sram-ecc"' > conftest.s
- if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=-xnack -mattr=+sram-ecc -o conftest.o conftest.s >&5'
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=$sramopt 2>conftest.err -o conftest.o conftest.s >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then
- gcc_cv_as_gcn_sram_ecc_gfx900=yes
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_sram_ecc_gfx900=yes
else
echo "configure: failed program was" >&5
cat conftest.s >&5
@@ -28818,22 +29040,24 @@ $as_echo "#define HAVE_GCN_SRAM_ECC_GFX900 1" >>confdefs.h
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+sram-ecc for gfx906" >&5
-$as_echo_n "checking assembler for assembler accepts -mattr=+sram-ecc for gfx906... " >&6; }
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for gfx906" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for gfx906... " >&6; }
if ${gcc_cv_as_gcn_sram_ecc_gfx906+:} false; then :
$as_echo_n "(cached) " >&6
else
gcc_cv_as_gcn_sram_ecc_gfx906=no
if test x$gcc_cv_as != x; then
- $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx906+sram-ecc"' > conftest.s
- if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=-xnack -mattr=+sram-ecc -o conftest.o conftest.s >&5'
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=$sramopt 2>conftest.err -o conftest.o conftest.s >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then
- gcc_cv_as_gcn_sram_ecc_gfx906=yes
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_sram_ecc_gfx906=yes
else
echo "configure: failed program was" >&5
cat conftest.s >&5
@@ -28849,22 +29073,24 @@ $as_echo "#define HAVE_GCN_SRAM_ECC_GFX906 1" >>confdefs.h
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+sram-ecc for gfx908" >&5
-$as_echo_n "checking assembler for assembler accepts -mattr=+sram-ecc for gfx908... " >&6; }
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for gfx908" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for gfx908... " >&6; }
if ${gcc_cv_as_gcn_sram_ecc_gfx908+:} false; then :
$as_echo_n "(cached) " >&6
else
gcc_cv_as_gcn_sram_ecc_gfx908=no
if test x$gcc_cv_as != x; then
- $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx908+sram-ecc"' > conftest.s
- if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=-xnack -mattr=+sram-ecc -o conftest.o conftest.s >&5'
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=$sramopt 2>conftest.err -o conftest.o conftest.s >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then
- gcc_cv_as_gcn_sram_ecc_gfx908=yes
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_sram_ecc_gfx908=yes
else
echo "configure: failed program was" >&5
cat conftest.s >&5
@@ -28880,6 +29106,7 @@ $as_echo "#define HAVE_GCN_SRAM_ECC_GFX908 1" >>confdefs.h
fi
+ rm -f conftest.err
;;
arm*)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler for arm accepts context-specific architecture extensions" >&5
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 7d3aab4..344b2f5 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1169,7 +1169,7 @@ if test "x$enable_offload_defaulted" = xyes; then
fi
AC_ARG_WITH(multilib-list,
-[AS_HELP_STRING([--with-multilib-list], [select multilibs (AArch64, SH and x86-64 only)])],
+[AS_HELP_STRING([--with-multilib-list], [select multilibs (AArch64, ARM, OR1K, RISC-V, SH and x86-64 only)])],
:,
with_multilib_list=default)
@@ -5332,30 +5332,106 @@ esac
case "$target" in
amdgcn-* | gcn-*)
- gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+sram-ecc for fiji],
+ # Test the LLVM assembler syntax dialect; they have made a number of
+ # changes between LLVM 12 & 13 without any backward compatibility.
+ gcc_GAS_CHECK_FEATURE([assembler amdgcn_target v2/3 syntax],
+ gcc_cv_as_gcn_asm_v3_syntax,
+ [-triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack],
+ [.amdgcn_target "amdgcn-unknown-amdhsa--gfx906+xnack"],,
+ [AC_DEFINE(HAVE_GCN_ASM_V3_SYNTAX, 1,
+ [Define if your assembler expects amdgcn_target gfx908+xnack syntax.])])
+ gcc_GAS_CHECK_FEATURE([assembler amdgcn_target v4 syntax],
+ gcc_cv_as_gcn_asm_v4_syntax,
+ [-triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack],
+ [.amdgcn_target "amdgcn-unknown-amdhsa--gfx908:xnack+"],,
+ [AC_DEFINE(HAVE_GCN_ASM_V4_SYNTAX, 1,
+ [Define if your assembler expects amdgcn_target gfx908:xnack+ syntax.])])
+
+ # Some attribute names changed in the move to v4 ...
+ if test $gcc_cv_as_gcn_asm_v3_syntax = yes; then
+ sramopt="+sram-ecc"
+ sramattr="+sram-ecc"
+ xnackattr="+xnack"
+ elif test $gcc_cv_as_gcn_asm_v4_syntax = yes; then
+ sramopt="+sramecc"
+ sramattr=":sramecc+"
+ xnackattr=":xnack+"
+ else
+ AC_MSG_ERROR([Unrecognised assembler version])
+ fi
+
+ # Test whether the LLVM assembler accepts -mattr=+xnack without any
+ # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+ # LLVM 12+ throws a warning for GPUs without support.
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for fiji],
+ gcc_cv_as_gcn_xnack_ecc_fiji,
+ [-triple=amdgcn--amdhsa -mcpu=fiji -mattr=+xnack 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_xnack_ecc_fiji=yes],
+ [AC_DEFINE(HAVE_GCN_XNACK_FIJI, 1,
+ [Define if your assembler allows -mattr=+xnack for fiji.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for gfx900],
+ gcc_cv_as_gcn_xnack_ecc_gfx900,
+ [-triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=+xnack 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_xnack_ecc_gfx900=yes],
+ [AC_DEFINE(HAVE_GCN_XNACK_GFX900, 1,
+ [Define if your assembler allows -mattr=+xnack for gfx900.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for gfx906],
+ gcc_cv_as_gcn_xnack_ecc_gfx906,
+ [-triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_xnack_ecc_gfx906=yes],
+ [AC_DEFINE(HAVE_GCN_XNACK_GFX906, 1,
+ [Define if your assembler allows -mattr=+xnack for gfx906.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for gfx908],
+ gcc_cv_as_gcn_xnack_ecc_gfx908,
+ [-triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_xnack_ecc_gfx908=yes],
+ [AC_DEFINE(HAVE_GCN_XNACK_GFX908, 1,
+ [Define if your assembler allows -mattr=+xnack for gfx908.])])
+ rm -f conftest.err
+
+ # Test whether the LLVM assembler accepts -mattr=+sramecc without any
+ # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+ # (some?) LLVM 12 rejects it for all GPUs, and LLVM13 throws a warning
+ # for GPUs without support.
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for fiji],
gcc_cv_as_gcn_sram_ecc_fiji,
- [-triple=amdgcn--amdhsa -mcpu=fiji -mattr=-xnack -mattr=+sram-ecc],
- [.amdgcn_target "amdgcn-unknown-amdhsa--gfx803+sram-ecc"],,
+ [-triple=amdgcn--amdhsa -mcpu=fiji -mattr=$sramopt 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_sram_ecc_fiji=yes],
[AC_DEFINE(HAVE_GCN_SRAM_ECC_FIJI, 1,
- [Define if your assembler allows -mattr=+sram-ecc for fiji.])])
- gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+sram-ecc for gfx900],
+ [Define if your assembler allows -mattr=+sramecc for fiji.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for gfx900],
gcc_cv_as_gcn_sram_ecc_gfx900,
- [-triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=-xnack -mattr=+sram-ecc],
- [.amdgcn_target "amdgcn-unknown-amdhsa--gfx900+sram-ecc"],,
+ [-triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=$sramopt 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_sram_ecc_gfx900=yes],
[AC_DEFINE(HAVE_GCN_SRAM_ECC_GFX900, 1,
- [Define if your assembler allows -mattr=+sram-ecc for gfx900.])])
- gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+sram-ecc for gfx906],
+ [Define if your assembler allows -mattr=+sramecc for gfx900.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for gfx906],
gcc_cv_as_gcn_sram_ecc_gfx906,
- [-triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=-xnack -mattr=+sram-ecc],
- [.amdgcn_target "amdgcn-unknown-amdhsa--gfx906+sram-ecc"],,
+ [-triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=$sramopt 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_sram_ecc_gfx906=yes],
[AC_DEFINE(HAVE_GCN_SRAM_ECC_GFX906, 1,
- [Define if your assembler allows -mattr=+sram-ecc for gfx906.])])
- gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+sram-ecc for gfx908],
+ [Define if your assembler allows -mattr=+sramecc for gfx906.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for gfx908],
gcc_cv_as_gcn_sram_ecc_gfx908,
- [-triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=-xnack -mattr=+sram-ecc],
- [.amdgcn_target "amdgcn-unknown-amdhsa--gfx908+sram-ecc"],,
+ [-triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=$sramopt 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_sram_ecc_gfx908=yes],
[AC_DEFINE(HAVE_GCN_SRAM_ECC_GFX908, 1,
- [Define if your assembler allows -mattr=+sram-ecc for gfx908.])])
+ [Define if your assembler allows -mattr=+sramecc for gfx908.])])
+ rm -f conftest.err
;;
arm*)
gcc_GAS_CHECK_FEATURE([assembler for arm accepts context-specific architecture extensions],
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d04d84f..97d0a35 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,237 @@
+2021-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102612
+ * parser.c (cp_parser_jump_statement): Implement C++23 P2242R3.
+ Allow goto expressions in constexpr function bodies for C++23.
+ Adjust error message for older standards to mention it.
+ * decl.c (start_decl): Allow static and thread_local declarations
+ in constexpr function bodies for C++23. Adjust error message for
+ older standards to mention it.
+ * constexpr.c (ensure_literal_type_for_constexpr_object): Allow
+ declarations of variables with non-literal type in constexpr function
+ bodies for C++23. Adjust error message for older standards to mention
+ it.
+ (cxx_eval_constant_expression) <case DECL_EXPR>: Diagnose declarations
+ of initialization of static or thread_local vars.
+ (cxx_eval_constant_expression) <case GOTO_EXPR>: Diagnose goto
+ statements for C++23.
+ (potential_constant_expression_1) <case DECL_EXPR>: Swap the
+ CP_DECL_THREAD_LOCAL_P and TREE_STATIC checks.
+ (potential_constant_expression_1) <case LABEL_EXPR>: Allow labels for
+ C++23. Adjust error message for older standards to mention it.
+
+2021-10-06 Jakub Jelinek <jakub@redhat.com>
+ Jason Merrill <jason@redhat.com>
+
+ PR c++/98712
+ PR c++/102490
+ * cp-tree.h (maybe_synthesize_method): Declare.
+ * method.c (genericize_spaceship): Use
+ LOOKUP_NORMAL | LOOKUP_NONVIRTUAL | LOOKUP_DEFAULTED instead of
+ LOOKUP_NORMAL for flags.
+ (comp_info): Remove defining member. Add complain, code, retcat.
+ (comp_info::comp_info): Adjust.
+ (do_one_comp): Split out from build_comparison_op. Use
+ LOOKUP_NORMAL | LOOKUP_NONVIRTUAL | LOOKUP_DEFAULTED instead of
+ LOOKUP_NORMAL for flags.
+ (build_comparison_op): Add defining argument. Adjust comp_info
+ construction. Use defining instead of info.defining. Assert that
+ if defining, ctype is a complete type. Walk base binfos.
+ (synthesize_method, maybe_explain_implicit_delete,
+ explain_implicit_non_constexpr): Adjust build_comparison_op callers.
+ (maybe_synthesize_method): New function.
+ * class.c (check_bases_and_members): Don't call defaulted_late_check
+ for sfk_comparison.
+ (finish_struct_1): Call it here instead after class has been
+ completed.
+ * pt.c (maybe_instantiate_noexcept): Call maybe_synthesize_method
+ instead of synthesize_method.
+
+2021-10-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102548
+ * tree.c (apply_identity_attributes): Fix handling of the
+ case where an attribute in the list doesn't affect type
+ identity but some attribute before it does.
+
+2021-10-05 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102547
+ * constexpr.c (potential_constant_expression_1): Handle
+ NONTYPE_ARGUMENT_PACK.
+
+2021-10-05 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/98930
+ * pt.c (has_value_dependent_address): Return true for a static
+ local variable from a function template.
+
+2021-10-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * typeck.c (cp_build_binary_op): Call do_warn_array_compare.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/101765
+ * coroutines.cc (register_local_var_uses): Emit a sorry if
+ we encounter a VLA in the coroutine local variables.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/99710
+ * coroutines.cc (await_statement_walker): Report an error if
+ an await expression is found in a handler body.
+
+2021-10-03 John Eivind Helset <jehelset@gmail.com>
+
+ PR c++/100673
+ * coroutines.cc (build_co_await): Guard against NULL
+ await_suspend types.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/101133
+ * coroutines.cc (build_co_await): Mark co_await_expr trees
+ with TREE_SIDE_EFFECTS, also mark any containing expression.
+ (finish_co_await_expr): Mark type-dependent co_await_expr
+ trees with TREE_SIDE_EFFECTS.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/99575
+ * coroutines.cc (build_co_await): Strip NOPs from
+ candidate awaiter expressions before testing to see
+ if they need a temporary.
+
+2021-10-01 Martin Sebor <msebor@redhat.com>
+
+ PR c/102103
+ * typeck.c (warn_for_null_address): Enhance.
+ (cp_build_binary_op): Call it also for member pointers.
+
+2021-10-01 qingzhe huang <nickhuang99@hotmail.com>
+
+ PR c++/101783
+ * tree.c (cp_build_qualified_type_real): Exclude typedef from
+ error.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+ Richard Biener <rguenther@suse.de>
+
+ PR sanitizer/102515
+ * typeck.c (cp_build_binary_op): Call ubsan_instrument_division
+ for division even for SANITIZE_SI_OVERFLOW.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.c (cp_parser_omp_clause_order): Set
+ OMP_CLAUSE_ORDER_REPRODUCIBLE for explicit reproducible: modifier.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102496
+ * name-lookup.c (push_local_extern_decl_alias): Return early even for
+ tls vars with non-dependent type when processing_template_decl. For
+ CP_DECL_THREAD_LOCAL_P vars call set_decl_tls_model on alias.
+
+2021-09-30 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102535
+ * method.c (is_xible_helper): Don't exit early for multi-arg
+ ctors in C++20.
+
+2021-09-30 Patrick Palka <ppalka@redhat.com>
+
+ * parser.c (cp_parser_trait_expr): Call nreverse on the reversed
+ list of trailing arguments.
+
+2021-09-30 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/95567
+ * method.c (build_comparison_op): Skip DECL_VIRTUAL_P fields.
+
+2021-09-28 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/99909
+ * pt.c (coerce_template_template_parms): Keep
+ processing_template_decl set around the call to unify as well.
+
+2021-09-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/102454
+ * coroutines.cc (analyze_fn_parms): Clean up synthetic names for
+ unnamed function params.
+ (morph_fn_to_coro): Do not try to set a guard variable for param
+ DTORs in the ramp, unless we have exceptions active.
+
+2021-09-27 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102479
+ * pt.c (rewrite_template_parm): Handle single-level tsubst_args.
+ Avoid a tree cycle when assigning the DECL_TEMPLATE_PARMS for a
+ rewritten ttp.
+ (alias_ctad_tweaks): Set current_template_parms accordingly.
+
+2021-09-23 Michel Morin <mimomorin@gmail.com>
+
+ * parser.c (cp_keyword_starts_decl_specifier_p): Do not
+ handle RID_ATTRIBUTE.
+ (cp_parser_constructor_declarator_p): Remove now-redundant
+ checks.
+ (cp_parser_lambda_declarator_opt): Likewise.
+
+2021-09-23 Michel Morin <mimomorin@gmail.com>
+
+ PR c++/77565
+ * parser.c (cp_keyword_starts_decl_specifier_p): Handle more
+ decl-specifiers (typedef/inline/cv/explicit/virtual/friend).
+
+2021-09-23 Patrick Palka <ppalka@redhat.com>
+
+ * ptree.c (cxx_print_decl): Dump the DECL_TEMPLATE_RESULT of
+ a TEMPLATE_DECL. Dump the DECL_TEMPLATE_INFO rather than just
+ printing its pointer value.
+
+2021-09-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102413
+ * parser.c (cp_parser_omp_directive_args): Diagnose if omp::directive
+ is not followed by a balanced token sequence starting with open paren.
+
+2021-09-22 Patrick Palka <ppalka@redhat.com>
+
+ DR 2446
+ PR c++/102412
+ * constexpr.c (cxx_eval_constant_expression)
+ <case TEMPLATE_ID_EXPR>: Check value_dependent_expression_p
+ instead of processing_template_decl.
+ * pt.c (value_dependent_expression_p) <case TEMPLATE_ID_EXPR>:
+ Return true only if any_dependent_template_arguments_p.
+ (instantiation_dependent_r) <case CALL_EXPR>: Remove this case.
+ <case TEMPLATE_ID_EXPR>: Likewise.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.c (cp_parser_omp_clause_allocate): Parse allocate clause
+ modifiers.
+ * semantics.c (finish_omp_clauses) <OMP_CLAUSE_ALLOCATE>: Perform
+ semantic analysis of OMP_CLAUSE_ALLOCATE_ALIGN.
+ * pt.c (tsubst_omp_clauses) <case OMP_CLAUSE_ALLOCATE>: Handle
+ also OMP_CLAUSE_ALLOCATE_ALIGN.
+
+2021-09-22 Barrett Adair <barrettellisadair@gmail.com>
+
+ * pt.c (find_parm_usage_r): New walk_tree callback to find func
+ parms.
+ (any_template_arguments_need_structural_equality_p): New special
+ case.
+
+2021-09-21 wangpc <pc.wang@linux.alibaba.com>
+
+ * decl.c (start_decl_1): Move verify_type_context to ...
+ (cp_finish_decl): ... to here.
+
2021-09-18 Jakub Jelinek <jakub@redhat.com>
* parser.c (cp_parser_omp_clause_order): Parse unconstrained
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index fe225c6..5961162 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6119,6 +6119,10 @@ check_bases_and_members (tree t)
&& !DECL_ARTIFICIAL (fn)
&& DECL_DEFAULTED_IN_CLASS_P (fn))
{
+ /* ...except handle comparisons later, in finish_struct_1. */
+ if (special_function_p (fn) == sfk_comparison)
+ continue;
+
int copy = copy_fn_p (fn);
if (copy > 0)
{
@@ -7467,7 +7471,14 @@ finish_struct_1 (tree t)
for any static member objects of the type we're working on. */
for (x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x))
if (DECL_DECLARES_FUNCTION_P (x))
- DECL_IN_AGGR_P (x) = false;
+ {
+ /* Synthesize constexpr defaulted comparisons. */
+ if (!DECL_ARTIFICIAL (x)
+ && DECL_DEFAULTED_IN_CLASS_P (x)
+ && special_function_p (x) == sfk_comparison)
+ defaulted_late_check (x);
+ DECL_IN_AGGR_P (x) = false;
+ }
else if (VAR_P (x) && TREE_STATIC (x)
&& TREE_TYPE (x) != error_mark_node
&& same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (x)), t))
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 8a5dd06..66d5221 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -109,14 +109,15 @@ ensure_literal_type_for_constexpr_object (tree decl)
explain_non_literal_class (type);
decl = error_mark_node;
}
- else
+ else if (cxx_dialect < cxx23)
{
if (!is_instantiation_of_constexpr (current_function_decl))
{
auto_diagnostic_group d;
error_at (DECL_SOURCE_LOCATION (decl),
"variable %qD of non-literal type %qT in "
- "%<constexpr%> function", decl, type);
+ "%<constexpr%> function only available with "
+ "%<-std=c++2b%> or %<-std=gnu++2b%>", decl, type);
explain_non_literal_class (type);
decl = error_mark_node;
}
@@ -6345,6 +6346,26 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
r = void_node;
break;
}
+
+ if (VAR_P (r)
+ && (TREE_STATIC (r) || CP_DECL_THREAD_LOCAL_P (r))
+ /* Allow __FUNCTION__ etc. */
+ && !DECL_ARTIFICIAL (r))
+ {
+ gcc_assert (cxx_dialect >= cxx23);
+ if (!ctx->quiet)
+ {
+ if (CP_DECL_THREAD_LOCAL_P (r))
+ error_at (loc, "control passes through declaration of %qD "
+ "with thread storage duration", r);
+ else
+ error_at (loc, "control passes through declaration of %qD "
+ "with static storage duration", r);
+ }
+ *non_constant_p = true;
+ break;
+ }
+
if (AGGREGATE_TYPE_P (TREE_TYPE (r))
|| VECTOR_TYPE_P (TREE_TYPE (r)))
{
@@ -7049,10 +7070,18 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
break;
case GOTO_EXPR:
- *jump_target = TREE_OPERAND (t, 0);
- gcc_assert (breaks (jump_target) || continues (jump_target)
- /* Allow for jumping to a cdtor_label. */
- || returns (jump_target));
+ if (breaks (&TREE_OPERAND (t, 0))
+ || continues (&TREE_OPERAND (t, 0))
+ /* Allow for jumping to a cdtor_label. */
+ || returns (&TREE_OPERAND (t, 0)))
+ *jump_target = TREE_OPERAND (t, 0);
+ else
+ {
+ gcc_assert (cxx_dialect >= cxx23);
+ if (!ctx->quiet)
+ error_at (loc, "%<goto%> is not a constant expression");
+ *non_constant_p = true;
+ }
break;
case LOOP_EXPR:
@@ -7117,7 +7146,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
break;
}
- if (!processing_template_decl
+ if (!value_dependent_expression_p (t)
&& !uid_sensitive_constexpr_evaluation_p ())
r = evaluate_concept_check (t);
else
@@ -8736,18 +8765,18 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
tmp = DECL_EXPR_DECL (t);
if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp))
{
- if (TREE_STATIC (tmp))
+ if (CP_DECL_THREAD_LOCAL_P (tmp))
{
if (flags & tf_error)
error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared "
- "%<static%> in %<constexpr%> context", tmp);
+ "%<thread_local%> in %<constexpr%> context", tmp);
return false;
}
- else if (CP_DECL_THREAD_LOCAL_P (tmp))
+ else if (TREE_STATIC (tmp))
{
if (flags & tf_error)
error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared "
- "%<thread_local%> in %<constexpr%> context", tmp);
+ "%<static%> in %<constexpr%> context", tmp);
return false;
}
else if (!check_for_uninitialized_const_var
@@ -9025,10 +9054,11 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case LABEL_EXPR:
t = LABEL_EXPR_LABEL (t);
- if (DECL_ARTIFICIAL (t))
+ if (DECL_ARTIFICIAL (t) || cxx_dialect >= cxx23)
return true;
else if (flags & tf_error)
- error_at (loc, "label definition is not a constant expression");
+ error_at (loc, "label definition in %<constexpr%> function only "
+ "available with %<-std=c++2b%> or %<-std=gnu++2b%>");
return false;
case ANNOTATE_EXPR:
@@ -9043,6 +9073,16 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case CO_RETURN_EXPR:
return false;
+ case NONTYPE_ARGUMENT_PACK:
+ {
+ tree args = ARGUMENT_PACK_ARGS (t);
+ int len = TREE_VEC_LENGTH (args);
+ for (int i = 0; i < len; ++i)
+ if (!RECUR (TREE_VEC_ELT (args, i), any))
+ return false;
+ return true;
+ }
+
default:
if (objc_non_constant_expr_p (t))
return false;
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index fbd5c49..9017902 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -1008,6 +1008,7 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
}
/* Only build a temporary if we need it. */
+ STRIP_NOPS (e_proxy);
if (TREE_CODE (e_proxy) == PARM_DECL
|| (VAR_P (e_proxy) && !is_local_temp (e_proxy)))
{
@@ -1052,7 +1053,8 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
else if (same_type_p (susp_return_type, boolean_type_node))
ok = true;
else if (TREE_CODE (susp_return_type) == RECORD_TYPE
- && CLASS_TYPE_P (susp_return_type))
+ && CLASS_TYPE_P (susp_return_type)
+ && CLASSTYPE_TEMPLATE_INFO (susp_return_type))
{
tree tt = CLASSTYPE_TI_TEMPLATE (susp_return_type);
if (tt == coro_handle_templ)
@@ -1116,13 +1118,15 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
a, e_proxy, o, awaiter_calls,
build_int_cst (integer_type_node,
(int) suspend_kind));
+ TREE_SIDE_EFFECTS (await_expr) = true;
if (te)
{
TREE_OPERAND (te, 1) = await_expr;
+ TREE_SIDE_EFFECTS (te) = true;
await_expr = te;
}
- tree t = convert_from_reference (await_expr);
- return t;
+ SET_EXPR_LOCATION (await_expr, loc);
+ return convert_from_reference (await_expr);
}
tree
@@ -1148,8 +1152,13 @@ finish_co_await_expr (location_t kw, tree expr)
co_await with the expression unchanged. */
tree functype = TREE_TYPE (current_function_decl);
if (dependent_type_p (functype) || type_dependent_expression_p (expr))
- return build5_loc (kw, CO_AWAIT_EXPR, unknown_type_node, expr,
- NULL_TREE, NULL_TREE, NULL_TREE, integer_zero_node);
+ {
+ tree aw_expr = build5_loc (kw, CO_AWAIT_EXPR, unknown_type_node, expr,
+ NULL_TREE, NULL_TREE, NULL_TREE,
+ integer_zero_node);
+ TREE_SIDE_EFFECTS (aw_expr) = true;
+ return aw_expr;
+ }
/* We must be able to look up the "await_transform" method in the scope of
the promise type, and obtain its return type. */
@@ -1186,14 +1195,7 @@ finish_co_await_expr (location_t kw, tree expr)
}
/* Now we want to build co_await a. */
- tree op = build_co_await (kw, a, CO_AWAIT_SUSPEND_POINT);
- if (op != error_mark_node)
- {
- TREE_SIDE_EFFECTS (op) = 1;
- SET_EXPR_LOCATION (op, kw);
- }
-
- return op;
+ return build_co_await (kw, a, CO_AWAIT_SUSPEND_POINT);
}
/* Take the EXPR given and attempt to build:
@@ -3686,7 +3688,22 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
*do_subtree = 0;
return res;
}
- break;
+ break;
+ case HANDLER:
+ {
+ /* [expr.await] An await-expression shall appear only in a
+ potentially-evaluated expression within the compound-statement
+ of a function-body outside of a handler. */
+ tree *await_ptr;
+ hash_set<tree> visited;
+ if (!(cp_walk_tree (&HANDLER_BODY (expr), find_any_await,
+ &await_ptr, &visited)))
+ return NULL_TREE; /* All OK. */
+ location_t loc = EXPR_LOCATION (*await_ptr);
+ error_at (loc, "await expressions are not permitted in handlers");
+ return NULL_TREE; /* This is going to fail later anyway. */
+ }
+ break;
}
else if (EXPR_P (expr))
{
@@ -3829,13 +3846,13 @@ analyze_fn_parms (tree orig)
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (parm.frame_type))
{
- char *buf = xasprintf ("_Coro_%s_live", IDENTIFIER_POINTER (name));
- parm.guard_var = build_lang_decl (VAR_DECL, get_identifier (buf),
- boolean_type_node);
+ char *buf = xasprintf ("%s%s_live", DECL_NAME (arg) ? "_Coro_" : "",
+ IDENTIFIER_POINTER (name));
+ parm.guard_var
+ = coro_build_artificial_var (UNKNOWN_LOCATION, get_identifier (buf),
+ boolean_type_node, orig,
+ boolean_false_node);
free (buf);
- DECL_ARTIFICIAL (parm.guard_var) = true;
- DECL_CONTEXT (parm.guard_var) = orig;
- DECL_INITIAL (parm.guard_var) = boolean_false_node;
parm.trivial_dtor = false;
}
else
@@ -3910,6 +3927,16 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d)
if (local_var.is_static)
continue;
+ poly_uint64 size;
+ if (TREE_CODE (lvtype) == ARRAY_TYPE
+ && !poly_int_tree_p (DECL_SIZE_UNIT (lvar), &size))
+ {
+ sorry_at (local_var.def_loc, "variable length arrays are not"
+ " yet supported in coroutines");
+ /* Ignore it, this is broken anyway. */
+ continue;
+ }
+
lvd->local_var_seen = true;
/* If this var is a lambda capture proxy, we want to leave it alone,
and later rewrite the DECL_VALUE_EXPR to indirect through the
@@ -4843,11 +4870,14 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
NULL, parm.frame_type,
LOOKUP_NORMAL,
tf_warning_or_error);
- /* This var is now live. */
- r = build_modify_expr (fn_start, parm.guard_var,
- boolean_type_node, INIT_EXPR, fn_start,
- boolean_true_node, boolean_type_node);
- finish_expr_stmt (r);
+ if (flag_exceptions)
+ {
+ /* This var is now live. */
+ r = build_modify_expr (fn_start, parm.guard_var,
+ boolean_type_node, INIT_EXPR, fn_start,
+ boolean_true_node, boolean_type_node);
+ finish_expr_stmt (r);
+ }
}
}
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1fcd50c..5248ecd 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7013,6 +7013,7 @@ extern void explain_implicit_non_constexpr (tree);
extern bool deduce_inheriting_ctor (tree);
extern bool decl_remember_implicit_trigger_p (tree);
extern void synthesize_method (tree);
+extern void maybe_synthesize_method (tree);
extern tree lazily_declare_fn (special_function_kind,
tree);
extern tree skip_artificial_parms_for (const_tree, tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 722e540..2d30c79 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5709,17 +5709,20 @@ start_decl (const cp_declarator *declarator,
}
if (current_function_decl && VAR_P (decl)
- && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+ && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+ && cxx_dialect < cxx23)
{
bool ok = false;
if (CP_DECL_THREAD_LOCAL_P (decl))
error_at (DECL_SOURCE_LOCATION (decl),
- "%qD declared %<thread_local%> in %qs function", decl,
+ "%qD declared %<thread_local%> in %qs function only "
+ "available with %<-std=c++2b%> or %<-std=gnu++2b%>", decl,
DECL_IMMEDIATE_FUNCTION_P (current_function_decl)
? "consteval" : "constexpr");
else if (TREE_STATIC (decl))
error_at (DECL_SOURCE_LOCATION (decl),
- "%qD declared %<static%> in %qs function", decl,
+ "%qD declared %<static%> in %qs function only available "
+ "with %<-std=c++2b%> or %<-std=gnu++2b%>", decl,
DECL_IMMEDIATE_FUNCTION_P (current_function_decl)
? "consteval" : "constexpr");
else
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 1426f9a..771a19b 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -749,8 +749,15 @@ maybe_warn_list_ctor (tree member, tree init)
|| !is_list_ctor (current_function_decl))
return;
- tree parms = FUNCTION_FIRST_USER_PARMTYPE (current_function_decl);
- tree initlist = non_reference (TREE_VALUE (parms));
+ tree parm = FUNCTION_FIRST_USER_PARMTYPE (current_function_decl);
+ parm = TREE_VALUE (parm);
+ tree initlist = non_reference (parm);
+
+ /* Do not warn if the parameter is an lvalue reference to non-const. */
+ if (TYPE_REF_P (parm) && !TYPE_REF_IS_RVALUE (parm)
+ && !CP_TYPE_CONST_P (initlist))
+ return;
+
tree targs = CLASSTYPE_TI_ARGS (initlist);
tree elttype = TREE_VEC_ELT (targs, 0);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 32f7186..1023aef 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1288,21 +1288,19 @@ struct comp_info
{
tree fndecl;
location_t loc;
- bool defining;
+ tsubst_flags_t complain;
+ tree_code code;
+ comp_cat_tag retcat;
bool first_time;
bool constexp;
bool was_constexp;
bool noex;
- comp_info (tree fndecl, tsubst_flags_t &complain)
- : fndecl (fndecl)
+ comp_info (tree fndecl, tsubst_flags_t complain)
+ : fndecl (fndecl), complain (complain)
{
loc = DECL_SOURCE_LOCATION (fndecl);
- /* We only have tf_error set when we're called from
- explain_invalid_constexpr_fn or maybe_explain_implicit_delete. */
- defining = !(complain & tf_error);
-
first_time = DECL_MAYBE_DELETED (fndecl);
DECL_MAYBE_DELETED (fndecl) = false;
@@ -1358,23 +1356,99 @@ struct comp_info
}
};
+/* Subroutine of build_comparison_op, to compare a single subobject. */
+
+static tree
+do_one_comp (location_t loc, const comp_info &info, tree sub, tree lhs, tree rhs)
+{
+ const tree_code code = info.code;
+ const tree fndecl = info.fndecl;
+ const comp_cat_tag retcat = info.retcat;
+ const tsubst_flags_t complain = info.complain;
+
+ tree overload = NULL_TREE;
+ int flags = LOOKUP_NORMAL | LOOKUP_NONVIRTUAL | LOOKUP_DEFAULTED;
+ /* If we have an explicit comparison category return type we can fall back
+ to </=, so don't give an error yet if <=> lookup fails. */
+ bool tentative = retcat != cc_last;
+ tree comp = build_new_op (loc, code, flags, lhs, rhs,
+ NULL_TREE, &overload,
+ tentative ? tf_none : complain);
+
+ if (code != SPACESHIP_EXPR)
+ return comp;
+
+ tree rettype = TREE_TYPE (TREE_TYPE (fndecl));
+
+ if (comp == error_mark_node)
+ {
+ if (overload == NULL_TREE && (tentative || complain))
+ {
+ /* No viable <=>, try using op< and op==. */
+ tree lteq = genericize_spaceship (loc, rettype, lhs, rhs);
+ if (lteq != error_mark_node)
+ {
+ /* We found usable < and ==. */
+ if (retcat != cc_last)
+ /* Return type is a comparison category, use them. */
+ comp = lteq;
+ else if (complain & tf_error)
+ /* Return type is auto, suggest changing it. */
+ inform (info.loc, "changing the return type from %qs "
+ "to a comparison category type will allow the "
+ "comparison to use %qs and %qs", "auto",
+ "operator<", "operator==");
+ }
+ else if (tentative && complain)
+ /* No usable < and ==, give an error for op<=>. */
+ build_new_op (loc, code, flags, lhs, rhs, complain);
+ }
+ if (comp == error_mark_node)
+ return error_mark_node;
+ }
+
+ if (FNDECL_USED_AUTO (fndecl)
+ && cat_tag_for (TREE_TYPE (comp)) == cc_last)
+ {
+ /* The operator function is defined as deleted if ... Ri is not a
+ comparison category type. */
+ if (complain & tf_error)
+ inform (loc,
+ "three-way comparison of %qD has type %qT, not a "
+ "comparison category type", sub, TREE_TYPE (comp));
+ return error_mark_node;
+ }
+ else if (!FNDECL_USED_AUTO (fndecl)
+ && !can_convert (rettype, TREE_TYPE (comp), complain))
+ {
+ if (complain & tf_error)
+ error_at (loc,
+ "three-way comparison of %qD has type %qT, which "
+ "does not convert to %qT",
+ sub, TREE_TYPE (comp), rettype);
+ return error_mark_node;
+ }
+
+ return comp;
+}
+
/* Build up the definition of a defaulted comparison operator. Unlike other
defaulted functions that use synthesized_method_walk to determine whether
the function is e.g. deleted, for comparisons we use the same code. We try
to use synthesize_method at the earliest opportunity and bail out if the
function ends up being deleted. */
-static void
-build_comparison_op (tree fndecl, tsubst_flags_t complain)
+void
+build_comparison_op (tree fndecl, bool defining, tsubst_flags_t complain)
{
comp_info info (fndecl, complain);
- if (!info.defining && !(complain & tf_error) && !DECL_MAYBE_DELETED (fndecl))
+ if (!defining && !(complain & tf_error) && !DECL_MAYBE_DELETED (fndecl))
return;
int flags = LOOKUP_NORMAL;
const ovl_op_info_t *op = IDENTIFIER_OVL_OP_INFO (DECL_NAME (fndecl));
- tree_code code = op->tree_code;
+ tree_code code = info.code = op->tree_code;
tree lhs = DECL_ARGUMENTS (fndecl);
tree rhs = DECL_CHAIN (lhs);
@@ -1384,6 +1458,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
lhs = convert_from_reference (lhs);
rhs = convert_from_reference (rhs);
tree ctype = TYPE_MAIN_VARIANT (TREE_TYPE (lhs));
+ gcc_assert (!defining || COMPLETE_TYPE_P (ctype));
iloc_sentinel ils (info.loc);
@@ -1399,7 +1474,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
}
tree compound_stmt = NULL_TREE;
- if (info.defining)
+ if (defining)
compound_stmt = begin_compound_stmt (0);
else
++cp_unevaluated_operand;
@@ -1413,19 +1488,44 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
if (code == EQ_EXPR || code == SPACESHIP_EXPR)
{
- comp_cat_tag retcat = cc_last;
+ comp_cat_tag &retcat = (info.retcat = cc_last);
if (code == SPACESHIP_EXPR && !FNDECL_USED_AUTO (fndecl))
retcat = cat_tag_for (rettype);
bool bad = false;
auto_vec<tree> comps;
- /* Compare each of the subobjects. Note that we get bases from
- next_initializable_field because we're past C++17. */
+ /* Compare the base subobjects. We handle them this way, rather than in
+ the field loop below, because maybe_instantiate_noexcept might bring
+ us here before we've built the base fields. */
+ for (tree base_binfo : BINFO_BASE_BINFOS (TYPE_BINFO (ctype)))
+ {
+ tree lhs_base
+ = build_base_path (PLUS_EXPR, lhs, base_binfo, 0, complain);
+ tree rhs_base
+ = build_base_path (PLUS_EXPR, rhs, base_binfo, 0, complain);
+
+ location_t loc = DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (ctype));
+ tree comp = do_one_comp (loc, info, BINFO_TYPE (base_binfo),
+ lhs_base, rhs_base);
+ if (comp == error_mark_node)
+ {
+ bad = true;
+ continue;
+ }
+
+ comps.safe_push (comp);
+ }
+
+ /* Now compare the field subobjects. */
for (tree field = next_initializable_field (TYPE_FIELDS (ctype));
field;
field = next_initializable_field (DECL_CHAIN (field)))
{
+ if (DECL_VIRTUAL_P (field) || DECL_FIELD_IS_BASE (field))
+ /* We ignore the vptr, and we already handled bases. */
+ continue;
+
tree expr_type = TREE_TYPE (field);
location_t field_loc = DECL_SOURCE_LOCATION (field);
@@ -1474,8 +1574,8 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
break;
tree idx;
/* [1] array, no loop needed, just add [0] ARRAY_REF.
- Similarly if !info.defining. */
- if (integer_zerop (maxval) || !info.defining)
+ Similarly if !defining. */
+ if (integer_zerop (maxval) || !defining)
idx = size_zero_node;
/* Some other array, will need runtime loop. */
else
@@ -1492,69 +1592,13 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
if (TREE_CODE (expr_type) == ARRAY_TYPE)
continue;
- tree overload = NULL_TREE;
- tree comp = build_new_op (field_loc, code, flags, lhs_mem, rhs_mem,
- NULL_TREE, &overload,
- retcat != cc_last ? tf_none : complain);
+ tree comp = do_one_comp (field_loc, info, field, lhs_mem, rhs_mem);
if (comp == error_mark_node)
{
- if (overload == NULL_TREE && code == SPACESHIP_EXPR
- && (retcat != cc_last || complain))
- {
- tree comptype = (retcat != cc_last ? rettype
- : DECL_SAVED_AUTO_RETURN_TYPE (fndecl));
- /* No viable <=>, try using op< and op==. */
- tree lteq = genericize_spaceship (field_loc, comptype,
- lhs_mem, rhs_mem);
- if (lteq != error_mark_node)
- {
- /* We found usable < and ==. */
- if (retcat != cc_last)
- /* Return type is a comparison category, use them. */
- comp = lteq;
- else if (complain & tf_error)
- /* Return type is auto, suggest changing it. */
- inform (info.loc, "changing the return type from %qs "
- "to a comparison category type will allow the "
- "comparison to use %qs and %qs", "auto",
- "operator<", "operator==");
- }
- else if (retcat != cc_last && complain != tf_none)
- /* No usable < and ==, give an error for op<=>. */
- build_new_op (field_loc, code, flags, lhs_mem, rhs_mem,
- complain);
- }
- if (comp == error_mark_node)
- {
- bad = true;
- continue;
- }
- }
- if (code != SPACESHIP_EXPR)
- ;
- else if (FNDECL_USED_AUTO (fndecl)
- && cat_tag_for (TREE_TYPE (comp)) == cc_last)
- {
- /* The operator function is defined as deleted if ... Ri is not a
- comparison category type. */
- if (complain & tf_error)
- inform (field_loc,
- "three-way comparison of %qD has type %qT, not a "
- "comparison category type", field, TREE_TYPE (comp));
- bad = true;
- continue;
- }
- else if (!FNDECL_USED_AUTO (fndecl)
- && !can_convert (rettype, TREE_TYPE (comp), complain))
- {
- if (complain & tf_error)
- error_at (field_loc,
- "three-way comparison of %qD has type %qT, which "
- "does not convert to %qT",
- field, TREE_TYPE (comp), rettype);
bad = true;
continue;
}
+
/* Most of the time, comp is the expression that should be evaluated
to compare the two members. If the expression needs to be
evaluated more than once in a loop, it will be a TREE_LIST
@@ -1584,7 +1628,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
tree comp = comps[i];
tree eq, retval = NULL_TREE, if_ = NULL_TREE;
tree loop_indexes = NULL_TREE;
- if (info.defining)
+ if (defining)
{
if (TREE_CODE (comp) == TREE_LIST)
{
@@ -1632,7 +1676,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
comp = build_static_cast (input_location, rettype, comp,
complain);
info.check (comp);
- if (info.defining)
+ if (defining)
{
tree var = create_temporary_var (rettype);
pushdecl (var);
@@ -1645,7 +1689,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
}
tree ceq = contextual_conv_bool (eq, complain);
info.check (ceq);
- if (info.defining)
+ if (defining)
{
finish_if_stmt_cond (ceq, if_);
finish_then_clause (if_);
@@ -1658,7 +1702,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
finish_for_stmt (TREE_VALUE (loop_index));
}
}
- if (info.defining)
+ if (defining)
{
tree val;
if (code == EQ_EXPR)
@@ -1679,7 +1723,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
NULL_TREE, NULL, complain);
comp = contextual_conv_bool (comp, complain);
info.check (comp);
- if (info.defining)
+ if (defining)
{
tree neg = build1 (TRUTH_NOT_EXPR, boolean_type_node, comp);
finish_return_stmt (neg);
@@ -1692,12 +1736,12 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
tree comp2 = build_new_op (info.loc, code, flags, comp, integer_zero_node,
NULL_TREE, NULL, complain);
info.check (comp2);
- if (info.defining)
+ if (defining)
finish_return_stmt (comp2);
}
out:
- if (info.defining)
+ if (defining)
finish_compound_stmt (compound_stmt);
else
--cp_unevaluated_operand;
@@ -1776,7 +1820,7 @@ synthesize_method (tree fndecl)
else if (sfk == sfk_comparison)
{
/* Pass tf_none so the function is just deleted if there's a problem. */
- build_comparison_op (fndecl, tf_none);
+ build_comparison_op (fndecl, true, tf_none);
need_body = false;
}
@@ -1810,6 +1854,32 @@ synthesize_method (tree fndecl)
fndecl);
}
+/* Like synthesize_method, but don't actually synthesize defaulted comparison
+ methods if their class is still incomplete. Just deduce the return
+ type in that case. */
+
+void
+maybe_synthesize_method (tree fndecl)
+{
+ if (special_function_p (fndecl) == sfk_comparison)
+ {
+ tree lhs = DECL_ARGUMENTS (fndecl);
+ if (is_this_parameter (lhs))
+ lhs = cp_build_fold_indirect_ref (lhs);
+ else
+ lhs = convert_from_reference (lhs);
+ tree ctype = TYPE_MAIN_VARIANT (TREE_TYPE (lhs));
+ if (!COMPLETE_TYPE_P (ctype))
+ {
+ push_deferring_access_checks (dk_no_deferred);
+ build_comparison_op (fndecl, false, tf_none);
+ pop_deferring_access_checks ();
+ return;
+ }
+ }
+ return synthesize_method (fndecl);
+}
+
/* Build a reference to type TYPE with cv-quals QUALS, which is an
rvalue if RVALUE is true. */
@@ -2090,8 +2160,10 @@ is_xible_helper (enum tree_code code, tree to, tree from, bool trivial)
tree expr;
if (code == MODIFY_EXPR)
expr = assignable_expr (to, from);
- else if (trivial && from && TREE_CHAIN (from))
+ else if (trivial && from && TREE_CHAIN (from)
+ && cxx_dialect < cxx20)
return error_mark_node; // only 0- and 1-argument ctors can be trivial
+ // before C++20 aggregate paren init
else if (TREE_CODE (to) == ARRAY_TYPE && !TYPE_DOMAIN (to))
return error_mark_node; // can't construct an array of unknown bound
else
@@ -2747,7 +2819,7 @@ maybe_explain_implicit_delete (tree decl)
inform (DECL_SOURCE_LOCATION (decl),
"%q#D is implicitly deleted because the default "
"definition would be ill-formed:", decl);
- build_comparison_op (decl, tf_warning_or_error);
+ build_comparison_op (decl, false, tf_warning_or_error);
}
else if (!informed)
{
@@ -2808,7 +2880,7 @@ explain_implicit_non_constexpr (tree decl)
if (sfk == sfk_comparison)
{
DECL_DECLARED_CONSTEXPR_P (decl) = true;
- build_comparison_op (decl, tf_warning_or_error);
+ build_comparison_op (decl, false, tf_warning_or_error);
DECL_DECLARED_CONSTEXPR_P (decl) = false;
}
else
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index ddee8b3..c414a10 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3375,7 +3375,10 @@ set_decl_context_in_fn (tree ctx, tree decl)
void
push_local_extern_decl_alias (tree decl)
{
- if (dependent_type_p (TREE_TYPE (decl)))
+ if (dependent_type_p (TREE_TYPE (decl))
+ || (processing_template_decl
+ && VAR_P (decl)
+ && CP_DECL_THREAD_LOCAL_P (decl)))
return;
/* EH specs were not part of the function type prior to c++17, but
we still can't go pushing dependent eh specs into the namespace. */
@@ -3471,6 +3474,8 @@ push_local_extern_decl_alias (tree decl)
push_nested_namespace (ns);
alias = do_pushdecl (alias, /* hiding= */true);
pop_nested_namespace (ns);
+ if (VAR_P (decl) && CP_DECL_THREAD_LOCAL_P (decl))
+ set_decl_tls_model (alias, DECL_TLS_MODEL (decl));
}
}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 62908da..d285a45 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1051,8 +1051,17 @@ cp_keyword_starts_decl_specifier_p (enum rid keyword)
case RID_FLOAT:
case RID_DOUBLE:
case RID_VOID:
+ /* CV qualifiers. */
+ case RID_CONST:
+ case RID_VOLATILE:
+ /* Function specifiers. */
+ case RID_EXPLICIT:
+ case RID_VIRTUAL:
+ /* friend/typdef/inline specifiers. */
+ case RID_FRIEND:
+ case RID_TYPEDEF:
+ case RID_INLINE:
/* GNU extensions. */
- case RID_ATTRIBUTE:
case RID_TYPEOF:
/* C++11 extensions. */
case RID_DECLTYPE:
@@ -10823,6 +10832,7 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
return error_mark_node;
type2 = tree_cons (NULL_TREE, elt, type2);
}
+ type2 = nreverse (type2);
}
location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location;
@@ -11456,8 +11466,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
/* In the decl-specifier-seq of the lambda-declarator, each
decl-specifier shall either be mutable or constexpr. */
int declares_class_or_enum;
- if (cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer)
- && !cp_next_tokens_can_be_gnu_attribute_p (parser))
+ if (cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer))
cp_parser_decl_specifier_seq (parser,
CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR,
&lambda_specs, &declares_class_or_enum);
@@ -14167,9 +14176,11 @@ cp_parser_jump_statement (cp_parser* parser)
case RID_GOTO:
if (parser->in_function_body
- && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+ && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+ && cxx_dialect < cxx23)
{
- error ("%<goto%> in %<constexpr%> function");
+ error ("%<goto%> in %<constexpr%> function only available with "
+ "%<-std=c++2b%> or %<-std=gnu++2b%>");
cp_function_chain->invalid_constexpr = true;
}
@@ -28628,7 +28639,16 @@ cp_parser_omp_directive_args (cp_parser *parser, tree attribute)
TREE_VALUE (attribute) = NULL_TREE;
return;
}
- for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 2; n; --n)
+ size_t n = cp_parser_skip_balanced_tokens (parser, 1);
+ if (n == 1)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ error_at (first->location, "expected attribute argument as balanced "
+ "token sequence");
+ TREE_VALUE (attribute) = NULL_TREE;
+ return;
+ }
+ for (n = n - 2; n; --n)
cp_lexer_consume_token (parser->lexer);
cp_token *last = cp_lexer_peek_token (parser->lexer);
cp_lexer_consume_token (parser->lexer);
@@ -30825,23 +30845,22 @@ cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags,
/* A parameter declaration begins with a decl-specifier,
which is either the "attribute" keyword, a storage class
specifier, or (usually) a type-specifier. */
- && (!cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer)
- /* GNU attributes can actually appear both at the start of
- a parameter and parenthesized declarator.
- S (__attribute__((unused)) int);
- is a constructor, but
- S (__attribute__((unused)) foo) (int);
- is a function declaration. */
- || (cp_parser_allow_gnu_extensions_p (parser)
- && cp_next_tokens_can_be_gnu_attribute_p (parser)))
- /* A parameter declaration can also begin with [[attribute]]. */
+ && !cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer)
+ /* GNU attributes can actually appear both at the start of
+ a parameter and parenthesized declarator.
+ S (__attribute__((unused)) int);
+ is a constructor, but
+ S (__attribute__((unused)) foo) (int);
+ is a function declaration. [[attribute]] can appear in the
+ first form too, but not in the second form. */
&& !cp_next_tokens_can_be_std_attribute_p (parser))
{
tree type;
tree pushed_scope = NULL_TREE;
unsigned saved_num_template_parameter_lists;
- if (cp_next_tokens_can_be_gnu_attribute_p (parser))
+ if (cp_parser_allow_gnu_extensions_p (parser)
+ && cp_next_tokens_can_be_gnu_attribute_p (parser))
{
unsigned int n = cp_parser_skip_gnu_attributes_opt (parser, 1);
while (--n)
@@ -37718,6 +37737,7 @@ cp_parser_omp_clause_order (cp_parser *parser, tree list, location_t location)
tree c, id;
const char *p;
bool unconstrained = false;
+ bool reproducible = false;
matching_parens parens;
if (!parens.require_open (parser))
@@ -37730,7 +37750,9 @@ cp_parser_omp_clause_order (cp_parser *parser, tree list, location_t location)
p = IDENTIFIER_POINTER (id);
if (strcmp (p, "unconstrained") == 0)
unconstrained = true;
- else if (strcmp (p, "reproducible") != 0)
+ else if (strcmp (p, "reproducible") == 0)
+ reproducible = true;
+ else
{
cp_parser_error (parser, "expected %<reproducible%> or "
"%<unconstrained%>");
@@ -37761,6 +37783,7 @@ cp_parser_omp_clause_order (cp_parser *parser, tree list, location_t location)
check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order", location);
c = build_omp_clause (location, OMP_CLAUSE_ORDER);
OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained;
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible;
OMP_CLAUSE_CHAIN (c) = list;
return c;
@@ -38337,13 +38360,21 @@ cp_parser_omp_clause_aligned (cp_parser *parser, tree list)
/* OpenMP 5.0:
allocate ( variable-list )
- allocate ( expression : variable-list ) */
+ allocate ( expression : variable-list )
+
+ OpenMP 5.1:
+ allocate ( allocator-modifier : variable-list )
+ allocate ( allocator-modifier , allocator-modifier : variable-list )
+
+ allocator-modifier:
+ allocator ( expression )
+ align ( expression ) */
static tree
cp_parser_omp_clause_allocate (cp_parser *parser, tree list)
{
- tree nlist, c, allocator = NULL_TREE;
- bool colon;
+ tree nlist, c, allocator = NULL_TREE, align = NULL_TREE;
+ bool colon, has_modifiers = false;
matching_parens parens;
if (!parens.require_open (parser))
@@ -38352,7 +38383,51 @@ cp_parser_omp_clause_allocate (cp_parser *parser, tree list)
cp_parser_parse_tentatively (parser);
bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
parser->colon_corrects_to_scope_p = false;
- allocator = cp_parser_assignment_expression (parser);
+ for (int mod = 0; mod < 2; mod++)
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+ if (strcmp (p, "allocator") != 0 && strcmp (p, "align") != 0)
+ break;
+ cp_lexer_consume_token (parser->lexer);
+ matching_parens parens2;
+ if (!parens2.require_open (parser))
+ break;
+ if (strcmp (p, "allocator") == 0)
+ {
+ if (allocator != NULL_TREE)
+ break;
+ allocator = cp_parser_assignment_expression (parser);
+ }
+ else
+ {
+ if (align != NULL_TREE)
+ break;
+ align = cp_parser_assignment_expression (parser);
+ }
+ if (!parens2.require_close (parser))
+ break;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ {
+ has_modifiers = true;
+ break;
+ }
+ if (mod != 0 || cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
+ break;
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else
+ break;
+ if (!has_modifiers)
+ {
+ cp_parser_abort_tentative_parse (parser);
+ align = NULL_TREE;
+ allocator = NULL_TREE;
+ cp_parser_parse_tentatively (parser);
+ allocator = cp_parser_assignment_expression (parser);
+ }
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
{
@@ -38360,18 +38435,25 @@ cp_parser_omp_clause_allocate (cp_parser *parser, tree list)
cp_lexer_consume_token (parser->lexer);
if (allocator == error_mark_node)
allocator = NULL_TREE;
+ if (align == error_mark_node)
+ align = NULL_TREE;
}
else
{
cp_parser_abort_tentative_parse (parser);
allocator = NULL_TREE;
+ align = NULL_TREE;
}
nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_ALLOCATE, list,
&colon);
- for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+ if (allocator || align)
+ for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+ {
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+ OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
+ }
return nlist;
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 4d42899..009fe6d 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6760,8 +6760,15 @@ has_value_dependent_address (tree op)
if (DECL_P (op))
{
tree ctx = CP_DECL_CONTEXT (op);
+
if (TYPE_P (ctx) && dependent_type_p (ctx))
return true;
+
+ if (VAR_P (op)
+ && TREE_STATIC (op)
+ && TREE_CODE (ctx) == FUNCTION_DECL
+ && type_dependent_expression_p (ctx))
+ return true;
}
return false;
@@ -7994,12 +8001,12 @@ coerce_template_template_parms (tree parm_parms,
/* So coerce P's args to apply to A's parms, and then deduce between A's
args and the converted args. If that succeeds, A is at least as
specialized as P, so they match.*/
+ processing_template_decl_sentinel ptds (/*reset*/false);
+ ++processing_template_decl;
tree pargs = template_parms_level_to_args (parm_parms);
pargs = add_outermost_template_args (outer_args, pargs);
- ++processing_template_decl;
pargs = coerce_template_parms (arg_parms, pargs, NULL_TREE, tf_none,
/*require_all*/true, /*use_default*/true);
- --processing_template_decl;
if (pargs != error_mark_node)
{
tree targs = make_tree_vec (nargs);
@@ -8223,8 +8230,10 @@ is_compatible_template_arg (tree parm, tree arg)
{
tree aparms = DECL_INNERMOST_TEMPLATE_PARMS (arg);
new_args = template_parms_level_to_args (aparms);
+ ++processing_template_decl;
parm_cons = tsubst_constraint_info (parm_cons, new_args,
tf_none, NULL_TREE);
+ --processing_template_decl;
if (parm_cons == error_mark_node)
return false;
}
@@ -8521,6 +8530,10 @@ convert_template_argument (tree parm,
else
t = tsubst (t, args, complain, in_decl);
+ /* Perform array-to-pointer and function-to-pointer conversion
+ as per [temp.param]/10. */
+ t = type_decays_to (t);
+
if (invalid_nontype_parm_type_p (t, complain))
return error_mark_node;
@@ -17489,6 +17502,13 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
break;
case OMP_CLAUSE_GANG:
case OMP_CLAUSE_ALIGNED:
+ OMP_CLAUSE_DECL (nc)
+ = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
+ in_decl, NULL);
+ OMP_CLAUSE_OPERAND (nc, 1)
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
+ break;
case OMP_CLAUSE_ALLOCATE:
OMP_CLAUSE_DECL (nc)
= tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
@@ -17496,6 +17516,9 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
OMP_CLAUSE_OPERAND (nc, 1)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
+ OMP_CLAUSE_OPERAND (nc, 2)
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 2), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
break;
case OMP_CLAUSE_LINEAR:
OMP_CLAUSE_DECL (nc)
@@ -25756,7 +25779,7 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
return true;
++function_depth;
- synthesize_method (fn);
+ maybe_synthesize_method (fn);
--function_depth;
return !DECL_MAYBE_DELETED (fn);
}
@@ -27237,7 +27260,8 @@ value_dependent_expression_p (tree expression)
}
case TEMPLATE_ID_EXPR:
- return concept_definition_p (TREE_OPERAND (expression, 0));
+ return concept_definition_p (TREE_OPERAND (expression, 0))
+ && any_dependent_template_arguments_p (TREE_OPERAND (expression, 1));
case CONSTRUCTOR:
{
@@ -27644,18 +27668,6 @@ instantiation_dependent_r (tree *tp, int *walk_subtrees,
case REQUIRES_EXPR:
return *tp;
- case CALL_EXPR:
- /* Treat concept checks as dependent. */
- if (concept_check_p (*tp))
- return *tp;
- break;
-
- case TEMPLATE_ID_EXPR:
- /* Treat concept checks as dependent. */
- if (concept_check_p (*tp))
- return *tp;
- break;
-
case CONSTRUCTOR:
if (CONSTRUCTOR_IS_DEPENDENT (*tp))
return *tp;
@@ -27813,6 +27825,20 @@ dependent_template_arg_p (tree arg)
return value_dependent_expression_p (arg);
}
+/* Identify any expressions that use function parms. */
+
+static tree
+find_parm_usage_r (tree *tp, int *walk_subtrees, void*)
+{
+ tree t = *tp;
+ if (TREE_CODE (t) == PARM_DECL)
+ {
+ *walk_subtrees = 0;
+ return t;
+ }
+ return NULL_TREE;
+}
+
/* Returns true if ARGS (a collection of template arguments) contains
any types that require structural equality testing. */
@@ -27857,6 +27883,13 @@ any_template_arguments_need_structural_equality_p (tree args)
else if (!TYPE_P (arg) && TREE_TYPE (arg)
&& TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (arg)))
return true;
+ /* Checking current_function_decl because this structural
+ comparison is only necessary for redeclaration. */
+ else if (!current_function_decl
+ && dependent_template_arg_p (arg)
+ && (cp_walk_tree_without_duplicates
+ (&arg, find_parm_usage_r, NULL)))
+ return true;
}
}
}
@@ -28734,7 +28767,7 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level,
const int depth = TMPL_ARGS_DEPTH (tsubst_args);
tree ttargs = make_tree_vec (depth + 1);
for (int i = 0; i < depth; ++i)
- TREE_VEC_ELT (ttargs, i) = TREE_VEC_ELT (tsubst_args, i);
+ TREE_VEC_ELT (ttargs, i) = TMPL_ARGS_LEVEL (tsubst_args, i + 1);
TREE_VEC_ELT (ttargs, depth)
= template_parms_level_to_args (ttparms);
// Substitute ttargs into ttparms to fix references to
@@ -28747,8 +28780,17 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level,
ttparms = tsubst_template_parms_level (ttparms, ttargs,
complain);
// Finally, tack the adjusted parms onto tparms.
- ttparms = tree_cons (size_int (depth), ttparms,
- current_template_parms);
+ ttparms = tree_cons (size_int (level + 1), ttparms,
+ copy_node (current_template_parms));
+ // As with all template template parms, the parameter list captured
+ // by this template template parm that corresponds to its own level
+ // should be empty. This avoids infinite recursion when structurally
+ // comparing two such rewritten template template parms (PR102479).
+ gcc_assert (!TREE_VEC_LENGTH
+ (TREE_VALUE (TREE_CHAIN (DECL_TEMPLATE_PARMS (olddecl)))));
+ gcc_assert (TMPL_PARMS_DEPTH (TREE_CHAIN (ttparms)) == level);
+ TREE_VALUE (TREE_CHAIN (ttparms)) = make_tree_vec (0);
+ // All done.
DECL_TEMPLATE_PARMS (newdecl) = ttparms;
}
}
@@ -29246,6 +29288,11 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
++ndlen;
tree gtparms = make_tree_vec (natparms + ndlen);
+ /* Set current_template_parms as in build_deduction_guide. */
+ auto ctp = make_temp_override (current_template_parms);
+ current_template_parms = copy_node (DECL_TEMPLATE_PARMS (tmpl));
+ TREE_VALUE (current_template_parms) = gtparms;
+
/* First copy over the parms of A. */
for (j = 0; j < natparms; ++j)
TREE_VEC_ELT (gtparms, j) = TREE_VEC_ELT (atparms, j);
diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c
index 7f140f5..1dcd764 100644
--- a/gcc/cp/ptree.c
+++ b/gcc/cp/ptree.c
@@ -51,6 +51,7 @@ cxx_print_decl (FILE *file, tree node, int indent)
}
else if (TREE_CODE (node) == TEMPLATE_DECL)
{
+ print_node (file, "result", DECL_TEMPLATE_RESULT (node), indent + 4);
print_node (file, "parms", DECL_TEMPLATE_PARMS (node), indent + 4);
indent_to (file, indent + 3);
fprintf (file, " full-name \"%s\"",
@@ -115,13 +116,8 @@ cxx_print_decl (FILE *file, tree node, int indent)
if (VAR_OR_FUNCTION_DECL_P (node)
&& DECL_TEMPLATE_INFO (node))
- {
- if (need_indent)
- indent_to (file, indent + 3);
- fprintf (file, " template-info %p",
- (void *) DECL_TEMPLATE_INFO (node));
- need_indent = false;
- }
+ print_node (file, "template-info", DECL_TEMPLATE_INFO (node),
+ indent + 4);
}
void
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 35a7b9f..0d8e5fd 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7527,7 +7527,44 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bitmap_set_bit (&aligned_head, DECL_UID (t));
allocate_seen = true;
}
- tree allocator;
+ tree allocator, align;
+ align = OMP_CLAUSE_ALLOCATE_ALIGN (c);
+ if (error_operand_p (align))
+ {
+ remove = true;
+ break;
+ }
+ if (align)
+ {
+ if (!type_dependent_expression_p (align)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (align)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<allocate%> clause %<align%> modifier "
+ "argument needs to be positive constant "
+ "power of two integer expression");
+ remove = true;
+ }
+ else
+ {
+ align = mark_rvalue_use (align);
+ if (!processing_template_decl)
+ {
+ align = maybe_constant_value (align);
+ if (TREE_CODE (align) != INTEGER_CST
+ || !tree_fits_uhwi_p (align)
+ || !integer_pow2p (align))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<allocate%> clause %<align%> modifier "
+ "argument needs to be positive constant "
+ "power of two integer expression");
+ remove = true;
+ }
+ }
+ }
+ OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
+ }
allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
if (error_operand_p (allocator))
{
@@ -7552,6 +7589,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
"type %qT rather than %<omp_allocator_handle_t%>",
TREE_TYPE (allocator));
remove = true;
+ break;
}
else
{
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 3c62dd7..32ddf83 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1403,11 +1403,18 @@ cp_build_qualified_type_real (tree type,
/* A reference or method type shall not be cv-qualified.
[dcl.ref], [dcl.fct]. This used to be an error, but as of DR 295
(in CD1) we always ignore extra cv-quals on functions. */
+
+ /* [dcl.ref/1] Cv-qualified references are ill-formed except when
+ the cv-qualifiers are introduced through the use of a typedef-name
+ ([dcl.typedef], [temp.param]) or decltype-specifier
+ ([dcl.type.decltype]),in which case the cv-qualifiers are
+ ignored. */
if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
&& (TYPE_REF_P (type)
|| FUNC_OR_METHOD_TYPE_P (type)))
{
- if (TYPE_REF_P (type))
+ if (TYPE_REF_P (type)
+ && (!typedef_variant_p (type) || FUNC_OR_METHOD_TYPE_P (type)))
bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
}
@@ -1492,9 +1499,9 @@ apply_identity_attributes (tree result, tree attribs, bool *remove_attributes)
p = &TREE_CHAIN (*p);
}
}
- else if (first_ident)
+ else if (first_ident && first_ident != error_mark_node)
{
- for (tree a2 = first_ident; a2; a2 = TREE_CHAIN (a2))
+ for (tree a2 = first_ident; a2 != a; a2 = TREE_CHAIN (a2))
{
*p = tree_cons (TREE_PURPOSE (a2), TREE_VALUE (a2), NULL_TREE);
p = &TREE_CHAIN (*p);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a2398db..ab0f9da 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4603,25 +4603,93 @@ warn_for_null_address (location_t location, tree op, tsubst_flags_t complain)
|| warning_suppressed_p (op, OPT_Waddress))
return;
+ if (TREE_CODE (op) == NON_DEPENDENT_EXPR)
+ op = TREE_OPERAND (op, 0);
+
tree cop = fold_for_warn (op);
- if (TREE_CODE (cop) == ADDR_EXPR
- && decl_with_nonnull_addr_p (TREE_OPERAND (cop, 0))
- && !warning_suppressed_p (cop, OPT_Waddress))
- warning_at (location, OPT_Waddress, "the address of %qD will never "
- "be NULL", TREE_OPERAND (cop, 0));
+ if (TREE_CODE (cop) == NON_LVALUE_EXPR)
+ /* Unwrap the expression for C++ 98. */
+ cop = TREE_OPERAND (cop, 0);
- if (CONVERT_EXPR_P (op)
+ if (TREE_CODE (cop) == PTRMEM_CST)
+ {
+ /* The address of a nonstatic data member is never null. */
+ warning_at (location, OPT_Waddress,
+ "the address %qE will never be NULL",
+ cop);
+ return;
+ }
+
+ if (TREE_CODE (cop) == NOP_EXPR)
+ {
+ /* Allow casts to intptr_t to suppress the warning. */
+ tree type = TREE_TYPE (cop);
+ if (TREE_CODE (type) == INTEGER_TYPE)
+ return;
+
+ STRIP_NOPS (cop);
+ }
+
+ bool warned = false;
+ if (TREE_CODE (cop) == ADDR_EXPR)
+ {
+ cop = TREE_OPERAND (cop, 0);
+
+ /* Set to true in the loop below if OP dereferences its operand.
+ In such a case the ultimate target need not be a decl for
+ the null [in]equality test to be necessarily constant. */
+ bool deref = false;
+
+ /* Get the outermost array or object, or member. */
+ while (handled_component_p (cop))
+ {
+ if (TREE_CODE (cop) == COMPONENT_REF)
+ {
+ /* Get the member (its address is never null). */
+ cop = TREE_OPERAND (cop, 1);
+ break;
+ }
+
+ /* Get the outer array/object to refer to in the warning. */
+ cop = TREE_OPERAND (cop, 0);
+ deref = true;
+ }
+
+ if ((!deref && !decl_with_nonnull_addr_p (cop))
+ || from_macro_expansion_at (location)
+ || warning_suppressed_p (cop, OPT_Waddress))
+ return;
+
+ warned = warning_at (location, OPT_Waddress,
+ "the address of %qD will never be NULL", cop);
+ op = cop;
+ }
+ else if (TREE_CODE (cop) == POINTER_PLUS_EXPR)
+ {
+ /* Adding zero to the null pointer is well-defined in C++. When
+ the offset is unknown (i.e., not a constant) warn anyway since
+ it's less likely that the pointer operand is null than not. */
+ tree off = TREE_OPERAND (cop, 1);
+ if (!integer_zerop (off)
+ && !warning_suppressed_p (cop, OPT_Waddress))
+ warning_at (location, OPT_Waddress, "comparing the result of pointer "
+ "addition %qE and NULL", cop);
+ return;
+ }
+ else if (CONVERT_EXPR_P (op)
&& TYPE_REF_P (TREE_TYPE (TREE_OPERAND (op, 0))))
{
- tree inner_op = op;
- STRIP_NOPS (inner_op);
+ STRIP_NOPS (op);
- if (DECL_P (inner_op))
- warning_at (location, OPT_Waddress,
- "the compiler can assume that the address of "
- "%qD will never be NULL", inner_op);
+ if (DECL_P (op))
+ warned = warning_at (location, OPT_Waddress,
+ "the compiler can assume that the address of "
+ "%qD will never be NULL", op);
}
+
+ if (warned && DECL_P (op))
+ inform (DECL_SOURCE_LOCATION (op), "%qD declared here", op);
}
/* Warn about [expr.arith.conv]/2: If one operand is of enumeration type and
@@ -5289,6 +5357,11 @@ cp_build_binary_op (const op_location_t &location,
warning_at (location, OPT_Waddress,
"comparison with string literal results in "
"unspecified behavior");
+ else if (warn_array_compare
+ && TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE)
+ do_warn_array_compare (location, code, stripped_orig_op0,
+ stripped_orig_op1);
}
build_type = boolean_type_node;
@@ -5411,6 +5484,8 @@ cp_build_binary_op (const op_location_t &location,
op1 = cp_convert (TREE_TYPE (op0), op1, complain);
}
result_type = TREE_TYPE (op0);
+
+ warn_for_null_address (location, orig_op0, complain);
}
else if (TYPE_PTRMEMFUNC_P (type1) && null_ptr_cst_p (orig_op0))
return cp_build_binary_op (location, code, op1, op0, complain);
@@ -5559,6 +5634,14 @@ cp_build_binary_op (const op_location_t &location,
"comparison with string literal results "
"in unspecified behavior");
}
+ else if (warn_array_compare
+ && TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE
+ && code != SPACESHIP_EXPR
+ && (complain & tf_warning))
+ do_warn_array_compare (location, code,
+ tree_strip_any_location_wrapper (orig_op0),
+ tree_strip_any_location_wrapper (orig_op1));
if (gnu_vector_type_p (type0) && gnu_vector_type_p (type1))
{
@@ -6038,7 +6121,9 @@ cp_build_binary_op (const op_location_t &location,
}
if (sanitize_flags_p ((SANITIZE_SHIFT
- | SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
+ | SANITIZE_DIVIDE
+ | SANITIZE_FLOAT_DIVIDE
+ | SANITIZE_SI_OVERFLOW))
&& current_function_decl != NULL_TREE
&& !processing_template_decl
&& (doing_div_or_mod || doing_shift))
@@ -6050,7 +6135,9 @@ cp_build_binary_op (const op_location_t &location,
op1 = fold_non_dependent_expr (op1, complain);
tree instrument_expr1 = NULL_TREE;
if (doing_div_or_mod
- && sanitize_flags_p (SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
+ && sanitize_flags_p (SANITIZE_DIVIDE
+ | SANITIZE_FLOAT_DIVIDE
+ | SANITIZE_SI_OVERFLOW))
{
/* For diagnostics we want to use the promoted types without
shorten_binary_op. So convert the arguments to the
diff --git a/gcc/ctfc.c b/gcc/ctfc.c
index 73c118e..b76277f 100644
--- a/gcc/ctfc.c
+++ b/gcc/ctfc.c
@@ -944,11 +944,14 @@ ctfc_delete_strtab (ctf_strtable_t * strtab)
void
ctfc_delete_container (ctf_container_ref ctfc)
{
- /* FIXME - CTF container can be cleaned up now.
- Will the ggc machinery take care of cleaning up the container structure
- including the hash_map members etc. ? */
if (ctfc)
{
+ ctfc->ctfc_types->empty ();
+ ctfc->ctfc_types = NULL;
+
+ ctfc->ctfc_vars->empty ();
+ ctfc->ctfc_types = NULL;
+
ctfc_delete_strtab (&ctfc->ctfc_strtable);
ctfc_delete_strtab (&ctfc->ctfc_aux_strtable);
if (ctfc->ctfc_vars_list)
diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog
index 94882e8..7f1f510 100644
--- a/gcc/d/ChangeLog
+++ b/gcc/d/ChangeLog
@@ -1,3 +1,20 @@
+2021-10-05 Iain Sandoe <iain@sandoe.co.uk>
+
+ * d-spec.cc (lang_specific_driver): Push the -static-libstdc++
+ option back onto the command line for targets without support
+ for -Bstatic/dynamic.
+
+2021-10-04 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/102574
+ * d-spec.cc (lang_specific_driver): Link libstdc++ statically if
+ -static-libstdc++ was given on command-line.
+
+2021-10-04 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * d-attribs.cc (d_handle_optimize_attribute): Save target node before
+ calling parse_optimize_options in case it changes.
+
2021-09-12 Iain Buclaw <ibuclaw@gdcproject.org>
PR d/102185
diff --git a/gcc/d/d-attribs.cc b/gcc/d/d-attribs.cc
index 0708660..d81b7d1 100644
--- a/gcc/d/d-attribs.cc
+++ b/gcc/d/d-attribs.cc
@@ -896,6 +896,8 @@ d_handle_optimize_attribute (tree *node, tree name, tree args, int,
/* Save current options. */
cl_optimization_save (&cur_opts, &global_options, &global_options_set);
+ tree prev_target_node = build_target_option_node (&global_options,
+ &global_options_set);
/* If we previously had some optimization options, use them as the
default. */
@@ -914,10 +916,16 @@ d_handle_optimize_attribute (tree *node, tree name, tree args, int,
parse_optimize_options (args);
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
= build_optimization_node (&global_options, &global_options_set);
+ tree target_node = build_target_option_node (&global_options,
+ &global_options_set);
+ if (prev_target_node != target_node)
+ DECL_FUNCTION_SPECIFIC_TARGET (*node) = target_node;
/* Restore current options. */
cl_optimization_restore (&global_options, &global_options_set,
&cur_opts);
+ cl_target_option_restore (&global_options, &global_options_set,
+ TREE_TARGET_OPTION (prev_target_node));
if (saved_global_options != NULL)
{
cl_optimization_compare (saved_global_options, &global_options);
diff --git a/gcc/d/d-spec.cc b/gcc/d/d-spec.cc
index 16ff153..b12d28f 100644
--- a/gcc/d/d-spec.cc
+++ b/gcc/d/d-spec.cc
@@ -83,6 +83,9 @@ lang_specific_driver (cl_decoded_option **in_decoded_options,
/* "-lstdc++" if it appears on the command line. */
const cl_decoded_option *saw_libcxx = 0;
+ /* True if we saw `-static-libstdc++'. */
+ bool saw_static_libcxx = false;
+
/* Whether we need the C++ STD library. */
bool need_stdcxx = false;
@@ -248,6 +251,11 @@ lang_specific_driver (cl_decoded_option **in_decoded_options,
shared_libgcc = false;
break;
+ case OPT_static_libstdc__:
+ saw_static_libcxx = true;
+ args[i] |= SKIPOPT;
+ break;
+
case OPT_static_libphobos:
if (phobos_library != PHOBOS_NOLINK)
phobos_library = PHOBOS_STATIC;
@@ -452,16 +460,39 @@ lang_specific_driver (cl_decoded_option **in_decoded_options,
#endif
}
- if (saw_libcxx)
- new_decoded_options[j++] = *saw_libcxx;
- else if (need_stdcxx)
+ if (saw_libcxx || need_stdcxx)
{
- generate_option (OPT_l,
- (saw_profile_flag
- ? LIBSTDCXX_PROFILE
- : LIBSTDCXX),
- 1, CL_DRIVER, &new_decoded_options[j++]);
- added_libraries++;
+#ifdef HAVE_LD_STATIC_DYNAMIC
+ if (saw_static_libcxx && !static_link)
+ {
+ generate_option (OPT_Wl_, LD_STATIC_OPTION, 1, CL_DRIVER,
+ &new_decoded_options[j++]);
+ }
+#else
+ /* Push the -static-libstdc++ option back onto the command so that
+ a target without LD_STATIC_DYNAMIC can use outfile substitution. */
+ if (saw_static_libcxx && !static_link)
+ generate_option (OPT_static_libstdc__, NULL, 1, CL_DRIVER,
+ &new_decoded_options[j++]);
+#endif
+ if (saw_libcxx)
+ new_decoded_options[j++] = *saw_libcxx;
+ else if (need_stdcxx)
+ {
+ generate_option (OPT_l,
+ (saw_profile_flag
+ ? LIBSTDCXX_PROFILE
+ : LIBSTDCXX),
+ 1, CL_DRIVER, &new_decoded_options[j++]);
+ added_libraries++;
+ }
+#ifdef HAVE_LD_STATIC_DYNAMIC
+ if (saw_static_libcxx && !static_link)
+ {
+ generate_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1, CL_DRIVER,
+ &new_decoded_options[j++]);
+ }
+#endif
}
if (shared_libgcc && !static_link)
diff --git a/gcc/dbgcnt.c b/gcc/dbgcnt.c
index 934bbe0..6a7eb34c 100644
--- a/gcc/dbgcnt.c
+++ b/gcc/dbgcnt.c
@@ -98,6 +98,14 @@ dbg_cnt (enum debug_counter index)
return false;
}
+/* Return the counter for INDEX. */
+
+unsigned
+dbg_cnt_counter (enum debug_counter index)
+{
+ return count[index];
+}
+
/* Compare limit_tuple intervals by first item in descending order. */
static int
diff --git a/gcc/dbgcnt.h b/gcc/dbgcnt.h
index 17f2091..3c35dcc 100644
--- a/gcc/dbgcnt.h
+++ b/gcc/dbgcnt.h
@@ -33,6 +33,7 @@ enum debug_counter {
extern bool dbg_cnt_is_enabled (enum debug_counter index);
extern bool dbg_cnt (enum debug_counter index);
+extern unsigned dbg_cnt_counter (enum debug_counter index);
extern void dbg_cnt_process_opt (const char *arg);
extern void dbg_cnt_list_all_counters (void);
diff --git a/gcc/defaults.h b/gcc/defaults.h
index ba79a8e..04d9bb1 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -61,36 +61,35 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#ifndef ASM_OUTPUT_ASCII
#define ASM_OUTPUT_ASCII(MYFILE, MYSTRING, MYLENGTH) \
do { \
- FILE *_hide_asm_out_file = (MYFILE); \
+ FILE *_my_file = (MYFILE); \
const unsigned char *_hide_p = (const unsigned char *) (MYSTRING); \
int _hide_thissize = (MYLENGTH); \
{ \
- FILE *asm_out_file = _hide_asm_out_file; \
const unsigned char *p = _hide_p; \
int thissize = _hide_thissize; \
int i; \
- fprintf (asm_out_file, "\t.ascii \""); \
+ fprintf (_my_file, "\t.ascii \""); \
\
for (i = 0; i < thissize; i++) \
{ \
int c = p[i]; \
if (c == '\"' || c == '\\') \
- putc ('\\', asm_out_file); \
+ putc ('\\', _my_file); \
if (ISPRINT (c)) \
- putc (c, asm_out_file); \
+ putc (c, _my_file); \
else \
{ \
- fprintf (asm_out_file, "\\%o", c); \
+ fprintf (_my_file, "\\%o", c); \
/* After an octal-escape, if a digit follows, \
terminate one string constant and start another. \
The VAX assembler fails to stop reading the escape \
after three digits, so this is the only way we \
can get it to parse the data properly. */ \
if (i < thissize - 1 && ISDIGIT (p[i + 1])) \
- fprintf (asm_out_file, "\"\n\t.ascii \""); \
+ fprintf (_my_file, "\"\n\t.ascii \""); \
} \
} \
- fprintf (asm_out_file, "\"\n"); \
+ fprintf (_my_file, "\"\n"); \
} \
} \
while (0)
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 9501a60..133b82e 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -1156,12 +1156,11 @@ It is recommended that portable code use the @code{_Float16} type defined
by ISO/IEC TS 18661-3:2015. @xref{Floating Types}.
On x86 targets with SSE2 enabled, without @option{-mavx512fp16},
-@code{_Float16} type is storage only, all operations will be emulated by
-software emulation and the @code{float} instructions. The default behavior
-for @code{FLT_EVAL_METHOD} is to keep the intermediate result of the operation
-as 32-bit precision. This may lead to inconsistent behavior between software
-emulation and AVX512-FP16 instructions. Using @option{-fexcess-precision=16}
-will force round back after each operation.
+all operations will be emulated by software emulation and the @code{float}
+instructions. The default behavior for @code{FLT_EVAL_METHOD} is to keep the
+intermediate result of the operation as 32-bit precision. This may lead to
+inconsistent behavior between software emulation and AVX512-FP16 instructions.
+Using @option{-fexcess-precision=16} will force round back after each operation.
Using @option{-mavx512fp16} will generate AVX512-FP16 instructions instead of
software emulation. The default behavior of @code{FLT_EVAL_METHOD} is to round
@@ -1406,7 +1405,7 @@ As an extension, GNU C supports named address spaces as
defined in the N1275 draft of ISO/IEC DTR 18037. Support for named
address spaces in GCC will evolve as the draft technical report
changes. Calling conventions for any target might also change. At
-present, only the AVR, M32C, RL78, and x86 targets support
+present, only the AVR, M32C, PRU, RL78, and x86 targets support
address spaces other than the generic address space.
Address space identifiers may be used exactly like any other C type
@@ -1586,6 +1585,23 @@ order to access memory beyond the first 64@tie{}Ki bytes. If
@code{__far} is used with the M32CM or M32C CPU variants, it has no
effect.
+@subsection PRU Named Address Spaces
+@cindex @code{__regio_symbol} PRU Named Address Spaces
+
+On the PRU target, variables qualified with @code{__regio_symbol} are
+aliases used to access the special I/O CPU registers. They must be
+declared as @code{extern} because such variables will not be allocated in
+any data memory. They must also be marked as @code{volatile}, and can
+only be 32-bit integer types. The only names those variables can have
+are @code{__R30} and @code{__R31}, representing respectively the
+@code{R30} and @code{R31} special I/O CPU registers. Hence the following
+example is the only valid usage of @code{__regio_symbol}:
+
+@smallexample
+extern volatile __regio_symbol uint32_t __R30;
+extern volatile __regio_symbol uint32_t __R31;
+@end smallexample
+
@subsection RL78 Named Address Spaces
@cindex @code{__far} RL78 Named Address Spaces
@@ -3647,7 +3663,10 @@ take function pointer arguments.
@cindex @code{optimize} function attribute
The @code{optimize} attribute is used to specify that a function is to
be compiled with different optimization options than specified on the
-command line. Valid arguments are constant non-negative integers and
+command line. The optimize attribute arguments of a function behave
+behave as if appended to the command-line.
+
+Valid arguments are constant non-negative integers and
strings. Each numeric argument specifies an optimization @var{level}.
Each @var{string} argument consists of one or more comma-separated
substrings. Each substring that begins with the letter @code{O} refers
@@ -3851,7 +3870,8 @@ This attribute prevents stack protection code for the function.
Multiple target back ends implement the @code{target} attribute
to specify that a function is to
be compiled with different target options than specified on the
-command line. One or more strings can be provided as arguments.
+command line. The original target command-line options are ignored.
+One or more strings can be provided as arguments.
Each string consists of one or more comma-separated suffixes to
the @code{-m} prefix jointly forming the name of a machine-dependent
option. @xref{Submodel Options,,Machine-Dependent Options}.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 4acb941..0500773 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -249,7 +249,8 @@ in the following sections.
-Wcomma-subscript -Wconditionally-supported @gol
-Wno-conversion-null -Wctad-maybe-unsupported @gol
-Wctor-dtor-privacy -Wno-delete-incomplete @gol
--Wdelete-non-virtual-dtor -Wdeprecated-copy -Wdeprecated-copy-dtor @gol
+-Wdelete-non-virtual-dtor -Wno-deprecated-array-compare @gol
+-Wdeprecated-copy -Wdeprecated-copy-dtor @gol
-Wno-deprecated-enum-enum-conversion -Wno-deprecated-enum-float-conversion @gol
-Weffc++ -Wno-exceptions -Wextra-semi -Wno-inaccessible-base @gol
-Wno-inherited-variadic-ctor -Wno-init-list-lifetime @gol
@@ -323,7 +324,7 @@ Objective-C and Objective-C++ Dialects}.
-Walloca -Walloca-larger-than=@var{byte-size} @gol
-Wno-aggressive-loop-optimizations @gol
-Warith-conversion @gol
--Warray-bounds -Warray-bounds=@var{n} @gol
+-Warray-bounds -Warray-bounds=@var{n} -Warray-compare @gol
-Wno-attributes -Wattribute-alias=@var{n} -Wno-attribute-alias @gol
-Wno-attribute-warning -Wbool-compare -Wbool-operation @gol
-Wno-builtin-declaration-mismatch @gol
@@ -3125,7 +3126,7 @@ errors if these functions are not inlined everywhere they are called.
@itemx -fno-modules-ts
@opindex fmodules-ts
@opindex fno-modules-ts
-Enable support for C++20 modules (@xref{C++ Modules}). The
+Enable support for C++20 modules (@pxref{C++ Modules}). The
@option{-fno-modules-ts} is usually not needed, as that is the
default. Even though this is a C++20 feature, it is not currently
implicitly enabled by selecting that standard version.
@@ -5562,6 +5563,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
@gccoptlist{-Waddress @gol
-Warray-bounds=1 @r{(only with} @option{-O2}@r{)} @gol
+-Warray-compare @gol
-Warray-parameter=2 @r{(C and Objective-C only)} @gol
-Wbool-compare @gol
-Wbool-operation @gol
@@ -6459,10 +6461,12 @@ int b[2][2] = @{ @{ 0, 1 @}, @{ 2, 3 @} @};
This warning is enabled by @option{-Wall}.
-@item -Wmissing-include-dirs @r{(C, C++, Objective-C and Objective-C++ only)}
+@item -Wmissing-include-dirs @r{(C, C++, Objective-C, Objective-C++ and Fortran only)}
@opindex Wmissing-include-dirs
@opindex Wno-missing-include-dirs
-Warn if a user-supplied include directory does not exist.
+Warn if a user-supplied include directory does not exist. This opions is disabled
+by default for C, C++, Objective-C and Objective-C++. For Fortran, it is partially
+enabled by default by warning for -I and -J, only.
@item -Wno-missing-profile
@opindex Wmissing-profile
@@ -7531,6 +7535,20 @@ pointers. This warning level may give a larger number of
false positives and is deactivated by default.
@end table
+@item -Warray-compare
+@opindex Warray-compare
+@opindex Wno-array-compare
+Warn about equality and relational comparisons between two operands of array
+type. This comparison was deprecated in C++20. For example:
+
+@smallexample
+int arr1[5];
+int arr2[5];
+bool same = arr1 == arr2;
+@end smallexample
+
+@option{-Warray-compare} is enabled by @option{-Wall}.
+
@item -Warray-parameter
@itemx -Warray-parameter=@var{n}
@opindex Wno-array-parameter
@@ -8549,17 +8567,43 @@ by @option{-Wall}.
@item -Waddress
@opindex Waddress
@opindex Wno-address
-Warn about suspicious uses of memory addresses. These include using
-the address of a function in a conditional expression, such as
-@code{void func(void); if (func)}, and comparisons against the memory
-address of a string literal, such as @code{if (x == "abc")}. Such
-uses typically indicate a programmer error: the address of a function
-always evaluates to true, so their use in a conditional usually
-indicate that the programmer forgot the parentheses in a function
-call; and comparisons against string literals result in unspecified
-behavior and are not portable in C, so they usually indicate that the
-programmer intended to use @code{strcmp}. This warning is enabled by
-@option{-Wall}.
+Warn about suspicious uses of address expressions. These include comparing
+the address of a function or a declared object to the null pointer constant
+such as in
+@smallexample
+void f (void);
+void g (void)
+@{
+ if (!func) // warning: expression evaluates to false
+ abort ();
+@}
+@end smallexample
+comparisons of a pointer to a string literal, such as in
+@smallexample
+void f (const char *x)
+@{
+ if (x == "abc") // warning: expression evaluates to false
+ puts ("equal");
+@}
+@end smallexample
+and tests of the results of pointer addition or subtraction for equality
+to null, such as in
+@smallexample
+void f (const int *p, int i)
+@{
+ return p + i == NULL;
+@}
+@end smallexample
+Such uses typically indicate a programmer error: the address of most
+functions and objects necessarily evaluates to true (the exception are
+weak symbols), so their use in a conditional might indicate missing
+parentheses in a function call or a missing dereference in an array
+expression. The subset of the warning for object pointers can be
+suppressed by casting the pointer operand to an integer type such
+as @code{inptr_t} or @code{uinptr_t}.
+Comparisons against string literals result in unspecified behavior
+and are not portable, and suggest the intent was to call @code{strcmp}.
+@option{-Waddress} warning is enabled by @option{-Wall}.
@item -Wno-address-of-packed-member
@opindex Waddress-of-packed-member
@@ -10779,7 +10823,7 @@ so, the first branch is redirected to either the destination of the
second branch or a point immediately following it, depending on whether
the condition is known to be true or false.
-Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+Enabled at levels @option{-O1}, @option{-O2}, @option{-O3}, @option{-Os}.
@item -fsplit-wide-types
@opindex fsplit-wide-types
@@ -14461,6 +14505,9 @@ Maximum number of basic blocks before EVRP uses a sparse cache.
@item evrp-mode
Specifies the mode Early VRP should operate in.
+@item evrp-switch-limit
+Specifies the maximum number of switch cases before EVRP ignores a switch.
+
@item unroll-jam-min-percent
The minimum percentage of memory references that must be optimized
away for the unroll-and-jam transformation to be considered profitable.
@@ -15227,7 +15274,7 @@ ISO C90 and C99, etc.
@item -fsanitize=integer-divide-by-zero
@opindex fsanitize=integer-divide-by-zero
-Detect integer division by zero as well as @code{INT_MIN / -1} division.
+Detect integer division by zero.
@item -fsanitize=unreachable
@opindex fsanitize=unreachable
@@ -15259,7 +15306,8 @@ returning a value. This option works in C++ only.
@opindex fsanitize=signed-integer-overflow
This option enables signed integer overflow checking. We check that
the result of @code{+}, @code{*}, and both unary and binary @code{-}
-does not overflow in the signed arithmetics. Note, integer promotion
+does not overflow in the signed arithmetics. This also detects
+@code{INT_MIN / -1} signed division. Note, integer promotion
rules must be taken into account. That is, the following is not an
overflow:
@smallexample
@@ -18568,6 +18616,8 @@ and the features that they enable by default:
@item @samp{armv8.4-a} @tab Armv8.4-A @tab @samp{armv8.3-a}, @samp{+flagm}, @samp{+fp16fml}, @samp{+dotprod}
@item @samp{armv8.5-a} @tab Armv8.5-A @tab @samp{armv8.4-a}, @samp{+sb}, @samp{+ssbs}, @samp{+predres}
@item @samp{armv8.6-a} @tab Armv8.6-A @tab @samp{armv8.5-a}, @samp{+bf16}, @samp{+i8mm}
+@item @samp{armv8.7-a} @tab Armv8.7-A @tab @samp{armv8.6-a}, @samp{+ls64}
+@item @samp{armv9-a} @tab Armv9-A @tab @samp{armv8.5-a}, @samp{+sve}, @samp{+sve2}
@item @samp{armv8-r} @tab Armv8-R @tab @samp{armv8-r}
@end multitable
@@ -18611,7 +18661,8 @@ performance of the code. Permissible values for this option are:
@samp{cortex-a57.cortex-a53}, @samp{cortex-a72.cortex-a53},
@samp{cortex-a73.cortex-a35}, @samp{cortex-a73.cortex-a53},
@samp{cortex-a75.cortex-a55}, @samp{cortex-a76.cortex-a55},
-@samp{cortex-r82}, @samp{cortex-x1}, @samp{native}.
+@samp{cortex-r82}, @samp{cortex-x1}, @samp{cortex-x2},
+@samp{cortex-a510}, @samp{cortex-a710}, @samp{native}.
The values @samp{cortex-a57.cortex-a53}, @samp{cortex-a72.cortex-a53},
@samp{cortex-a73.cortex-a35}, @samp{cortex-a73.cortex-a53},
@@ -18854,6 +18905,9 @@ Enable brain half-precision floating-point instructions. This also enables
Advanced SIMD and floating-point instructions. This option is enabled by
default for @option{-march=armv8.6-a}. Use of this option with architectures
prior to Armv8.2-A is not supported.
+@item ls64
+Enable the 64-byte atomic load and store instructions for accelerators.
+This option is enabled by default for @option{-march=armv8.7-a}.
@item flagm
Enable the Flag Manipulation instructions Extension.
@item pauth
@@ -19983,6 +20037,7 @@ Permissible names are:
@samp{armv8.4-a},
@samp{armv8.5-a},
@samp{armv8.6-a},
+@samp{armv9-a},
@samp{armv7-r},
@samp{armv8-r},
@samp{armv6-m}, @samp{armv6s-m},
@@ -20472,8 +20527,8 @@ Permissible names are: @samp{arm7tdmi}, @samp{arm7tdmi-s}, @samp{arm710t},
@samp{cortex-a57}, @samp{cortex-a72}, @samp{cortex-a73}, @samp{cortex-a75},
@samp{cortex-a76}, @samp{cortex-a76ae}, @samp{cortex-a77},
@samp{cortex-a78}, @samp{cortex-a78ae}, @samp{cortex-a78c},
-@samp{ares}, @samp{cortex-r4}, @samp{cortex-r4f},
-@samp{cortex-r5}, @samp{cortex-r7}, @samp{cortex-r8}, @samp{cortex-r52},
+@samp{ares}, @samp{cortex-r4}, @samp{cortex-r4f}, @samp{cortex-r5},
+@samp{cortex-r7}, @samp{cortex-r8}, @samp{cortex-r52}, @samp{cortex-r52plus},
@samp{cortex-m0}, @samp{cortex-m0plus}, @samp{cortex-m1}, @samp{cortex-m3},
@samp{cortex-m4}, @samp{cortex-m7}, @samp{cortex-m23}, @samp{cortex-m33},
@samp{cortex-m35p}, @samp{cortex-m55}, @samp{cortex-x1},
@@ -20557,8 +20612,8 @@ Disables the floating-point and SIMD instructions on
@item +nofp.dp
Disables the double-precision component of the floating-point instructions
-on @samp{cortex-r5}, @samp{cortex-r7}, @samp{cortex-r8}, @samp{cortex-r52} and
-@samp{cortex-m7}.
+on @samp{cortex-r5}, @samp{cortex-r7}, @samp{cortex-r8}, @samp{cortex-r52},
+@samp{cortex-r52plus} and @samp{cortex-m7}.
@item +nosimd
Disables the SIMD (but not floating-point) instructions on
@@ -33553,7 +33608,7 @@ version selected, although in pre-C++20 versions, it is of course an
extension.
No new source file suffixes are required or supported. If you wish to
-use a non-standard suffix (@xref{Overall Options}), you also need
+use a non-standard suffix (@pxref{Overall Options}), you also need
to provide a @option{-x c++} option too.@footnote{Some users like to
distinguish module interface files with a new suffix, such as naming
the source @code{module.cppm}, which involves
@@ -33615,8 +33670,8 @@ to be resolved at the end of compilation. Without this, imported
macros are only resolved when expanded or (re)defined. This option
detects conflicting import definitions for all macros.
-@xref{C++ Module Mapper} for details of the @option{-fmodule-mapper}
-family of options.
+For details of the @option{-fmodule-mapper} family of options,
+@pxref{C++ Module Mapper}.
@menu
* C++ Module Mapper:: Module Mapper
@@ -33833,8 +33888,8 @@ dialect used and imports of the module.@footnote{The precise contents
of this output may change.} The timestamp is the same value as that
provided by the @code{__DATE__} & @code{__TIME__} macros, and may be
explicitly specified with the environment variable
-@code{SOURCE_DATE_EPOCH}. @xref{Environment Variables} for further
-details.
+@code{SOURCE_DATE_EPOCH}. For further details
+@pxref{Environment Variables}.
A set of related CMIs may be copied, provided the relative pathnames
are preserved.
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 2b41cb7..ed35b8f 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -5776,11 +5776,13 @@ multiplication.
@item @samp{smul@var{m}3_highpart}
Perform a signed multiplication of operands 1 and 2, which have mode
@var{m}, and store the most significant half of the product in operand 0.
-The least significant half of the product is discarded.
+The least significant half of the product is discarded. This may be
+represented in RTL using a @code{smul_highpart} RTX expression.
@cindex @code{umul@var{m}3_highpart} instruction pattern
@item @samp{umul@var{m}3_highpart}
-Similar, but the multiplication is unsigned.
+Similar, but the multiplication is unsigned. This may be represented
+in RTL using an @code{umul_highpart} RTX expression.
@cindex @code{madd@var{m}@var{n}4} instruction pattern
@item @samp{madd@var{m}@var{n}4}
diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
index e1e76a9..2058997 100644
--- a/gcc/doc/rtl.texi
+++ b/gcc/doc/rtl.texi
@@ -2524,7 +2524,19 @@ not be the same.
For unsigned widening multiplication, use the same idiom, but with
@code{zero_extend} instead of @code{sign_extend}.
+@findex smul_highpart
+@findex umul_highpart
+@cindex high-part multiplication
+@cindex multiplication high part
+@item (smul_highpart:@var{m} @var{x} @var{y})
+@itemx (umul_highpart:@var{m} @var{x} @var{y})
+Represents the high-part multiplication of @var{x} and @var{y} carried
+out in machine mode @var{m}. @code{smul_highpart} returns the high part
+of a signed multiplication, @code{umul_highpart} returns the high part
+of an unsigned multiplication.
+
@findex fma
+@cindex fused multiply-add
@item (fma:@var{m} @var{x} @var{y} @var{z})
Represents the @code{fma}, @code{fmaf}, and @code{fmal} builtin
functions, which compute @samp{@var{x} * @var{y} + @var{z}}
diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
index 8169daf..e6ead5d 100644
--- a/gcc/dumpfile.c
+++ b/gcc/dumpfile.c
@@ -145,6 +145,7 @@ static const kv_pair<dump_flags_t> dump_options[] =
{"missed", MSG_MISSED_OPTIMIZATION},
{"note", MSG_NOTE},
{"optall", MSG_ALL_KINDS},
+ {"threading", TDF_THREADING},
{"all", dump_flags_t (TDF_ALL_VALUES
& ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH
| TDF_STMTADDR | TDF_RHS_ONLY | TDF_NOUID
diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h
index 892bfc9..7622675 100644
--- a/gcc/dumpfile.h
+++ b/gcc/dumpfile.h
@@ -74,7 +74,7 @@ enum dump_kind
the DUMP_OPTIONS array in dumpfile.c. The TDF_* flags coexist with
MSG_* flags (for -fopt-info) and the bit values must be chosen to
allow that. */
-enum dump_flag
+enum dump_flag : uint32_t
{
/* Value of TDF_NONE is used just for bits filtered by TDF_KIND_MASK. */
TDF_NONE = 0,
@@ -140,23 +140,26 @@ enum dump_flag
/* Dump SCEV details. */
TDF_SCEV = (1 << 19),
- /* Dump in GIMPLE FE syntax */
+ /* Dump in GIMPLE FE syntax. */
TDF_GIMPLE = (1 << 20),
/* Dump folding details. */
TDF_FOLDING = (1 << 21),
+ /* Dumping for range path solver. */
+ TDF_THREADING = (1 << 22),
+
/* MSG_* flags for expressing the kinds of message to
be emitted by -fopt-info. */
/* -fopt-info optimized sources. */
- MSG_OPTIMIZED_LOCATIONS = (1 << 22),
+ MSG_OPTIMIZED_LOCATIONS = (1 << 23),
/* Missed opportunities. */
- MSG_MISSED_OPTIMIZATION = (1 << 23),
+ MSG_MISSED_OPTIMIZATION = (1 << 24),
/* General optimization info. */
- MSG_NOTE = (1 << 24),
+ MSG_NOTE = (1 << 25),
/* Mask for selecting MSG_-kind flags. */
MSG_ALL_KINDS = (MSG_OPTIMIZED_LOCATIONS
@@ -175,30 +178,33 @@ enum dump_flag
sub-option of -fopt-info to show the internal messages. */
/* Implicitly supplied for messages at the top-level dump scope. */
- MSG_PRIORITY_USER_FACING = (1 << 25),
+ MSG_PRIORITY_USER_FACING = (1 << 26),
/* Implicitly supplied for messages within nested dump scopes. */
- MSG_PRIORITY_INTERNALS = (1 << 26),
+ MSG_PRIORITY_INTERNALS = (1 << 27),
/* Supplied when an opt_problem generated in a nested scope is re-emitted
at the top-level. We want to default to showing these in -fopt-info
output, but to *not* show them in dump files, as the message would be
shown twice, messing up "scan-tree-dump-times" in DejaGnu tests. */
- MSG_PRIORITY_REEMITTED = (1 << 27),
+ MSG_PRIORITY_REEMITTED = (1 << 28),
/* Mask for selecting MSG_PRIORITY_* flags. */
MSG_ALL_PRIORITIES = (MSG_PRIORITY_USER_FACING
| MSG_PRIORITY_INTERNALS
| MSG_PRIORITY_REEMITTED),
+ /* All -fdump- flags. */
+ TDF_ALL_VALUES = (1 << 29) - 1,
+
/* Dumping for -fcompare-debug. */
- TDF_COMPARE_DEBUG = (1 << 28),
+ TDF_COMPARE_DEBUG = (1 << 29),
- /* For error. */
- TDF_ERROR = (1 << 26),
+ /* Dump a GIMPLE value which means wrapping certain things with _Literal. */
+ TDF_GIMPLE_VAL = (1 << 30),
- /* All values. */
- TDF_ALL_VALUES = (1 << 29) - 1
+ /* For error. */
+ TDF_ERROR = ((uint32_t)1 << 31),
};
/* Dump flags type. */
@@ -208,32 +214,36 @@ typedef enum dump_flag dump_flags_t;
static inline dump_flags_t
operator| (dump_flags_t lhs, dump_flags_t rhs)
{
- return (dump_flags_t)((int)lhs | (int)rhs);
+ return (dump_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ | (std::underlying_type<dump_flags_t>::type)rhs);
}
static inline dump_flags_t
operator& (dump_flags_t lhs, dump_flags_t rhs)
{
- return (dump_flags_t)((int)lhs & (int)rhs);
+ return (dump_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ & (std::underlying_type<dump_flags_t>::type)rhs);
}
static inline dump_flags_t
operator~ (dump_flags_t flags)
{
- return (dump_flags_t)~((int)flags);
+ return (dump_flags_t)~((std::underlying_type<dump_flags_t>::type)flags);
}
static inline dump_flags_t &
operator|= (dump_flags_t &lhs, dump_flags_t rhs)
{
- lhs = (dump_flags_t)((int)lhs | (int)rhs);
+ lhs = (dump_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ | (std::underlying_type<dump_flags_t>::type)rhs);
return lhs;
}
static inline dump_flags_t &
operator&= (dump_flags_t &lhs, dump_flags_t rhs)
{
- lhs = (dump_flags_t)((int)lhs & (int)rhs);
+ lhs = (dump_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ & (std::underlying_type<dump_flags_t>::type)rhs);
return lhs;
}
@@ -272,13 +282,15 @@ typedef enum optgroup_flag optgroup_flags_t;
static inline optgroup_flags_t
operator| (optgroup_flags_t lhs, optgroup_flags_t rhs)
{
- return (optgroup_flags_t)((int)lhs | (int)rhs);
+ return (optgroup_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ | (std::underlying_type<dump_flags_t>::type)rhs);
}
static inline optgroup_flags_t &
operator|= (optgroup_flags_t &lhs, optgroup_flags_t rhs)
{
- lhs = (optgroup_flags_t)((int)lhs | (int)rhs);
+ lhs = (optgroup_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ | (std::underlying_type<dump_flags_t>::type)rhs);
return lhs;
}
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 9876750..20f2c5d 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -16809,6 +16809,8 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
case CONST_FIXED:
case CLRSB:
case CLOBBER:
+ case SMUL_HIGHPART:
+ case UMUL_HIGHPART:
break;
case CONST_STRING:
diff --git a/gcc/explow.c b/gcc/explow.c
index b6da277..a35423f 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
#include "recog.h"
#include "diagnostic-core.h"
#include "stor-layout.h"
+#include "langhooks.h"
#include "except.h"
#include "dojump.h"
#include "explow.h"
@@ -1641,8 +1642,14 @@ set_stack_check_libfunc (const char *libfunc_name)
{
gcc_assert (stack_check_libfunc == NULL_RTX);
stack_check_libfunc = gen_rtx_SYMBOL_REF (Pmode, libfunc_name);
+ tree ptype
+ = Pmode == ptr_mode
+ ? ptr_type_node
+ : lang_hooks.types.type_for_mode (Pmode, 1);
+ tree ftype
+ = build_function_type_list (void_type_node, ptype, NULL_TREE);
tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
- get_identifier (libfunc_name), void_type_node);
+ get_identifier (libfunc_name), ftype);
DECL_EXTERNAL (decl) = 1;
SET_SYMBOL_REF_DECL (stack_check_libfunc, decl);
}
diff --git a/gcc/expr.c b/gcc/expr.c
index e0bcbcc..eb33643 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -5305,7 +5305,7 @@ get_bit_range (poly_uint64_pod *bitstart, poly_uint64_pod *bitend, tree exp,
has non-BLKmode. DECL_RTL must not be a MEM; if
DECL_RTL was not set yet, return false. */
-static inline bool
+bool
non_mem_decl_p (tree base)
{
if (!DECL_P (base)
@@ -5322,7 +5322,7 @@ non_mem_decl_p (tree base)
/* Returns true if REF refers to an object that does not
reside in memory and has non-BLKmode. */
-static inline bool
+bool
mem_ref_refers_to_non_mem_p (tree ref)
{
tree base;
diff --git a/gcc/expr.h b/gcc/expr.h
index 94a85b4..890ec19 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -346,4 +346,7 @@ extern void expand_operands (tree, tree, rtx, rtx*, rtx*,
/* Return an rtx for the size in bytes of the value of an expr. */
extern rtx expr_size (tree);
+extern bool mem_ref_refers_to_non_mem_p (tree);
+extern bool non_mem_decl_p (tree);
+
#endif /* GCC_EXPR_H */
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 08e7d4c..b296797 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,186 @@
+2021-10-06 Tobias Burnus <tobias@codesourcery.com>
+
+ * resolve.c (resolve_values): Only show
+ deprecated warning if attr.referenced.
+
+2021-10-04 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/54753
+ * resolve.c (can_generate_init, resolve_fl_variable_derived,
+ resolve_symbol): Only do initialization with intent(out) if not
+ inside of an interface block.
+
+2021-10-01 Martin Sebor <msebor@redhat.com>
+
+ PR c/102103
+ * array.c: Remove an unnecessary test.
+ * trans-array.c: Same.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * gfortran.h (gfc_omp_clauses): Add order_reproducible bitfield.
+ * dump-parse-tree.c (show_omp_clauses): Print REPRODUCIBLE: for it.
+ * openmp.c (gfc_match_omp_clauses): Set order_reproducible for
+ explicit reproducible: modifier.
+ * trans-openmp.c (gfc_trans_omp_clauses): Set
+ OMP_CLAUSE_ORDER_REPRODUCIBLE for order_reproducible.
+ (gfc_split_omp_clauses): Also copy order_reproducible.
+
+2021-09-30 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102458
+ * simplify.c (simplify_size): Resolve expressions used in array
+ specifications so that SIZE can be simplified.
+
+2021-09-30 Harald Anlauf <anlauf@gmx.de>
+
+ * expr.c: The correct reference to Fortran standard is: F2018:10.1.12.
+
+2021-09-30 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/71703
+ PR fortran/84007
+ * trans-intrinsic.c (gfc_conv_same_type_as): Fix handling
+ of UNLIMITED_POLY.
+ * trans.h (gfc_vtpr_hash_get): Renamed prototype to ...
+ (gfc_vptr_hash_get): ... this to match function name.
+
+2021-09-29 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102520
+ * array.c (expand_constructor): Do not dereference NULL pointer.
+
+2021-09-27 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/94070
+ * trans-array.c (gfc_tree_array_size): New function to
+ find size inline (whole array or one dimension).
+ (array_parameter_size): Use it, take stmt_block as arg.
+ (gfc_conv_array_parameter): Update call.
+ * trans-array.h (gfc_tree_array_size): Add prototype.
+ * trans-decl.c (gfor_fndecl_size0, gfor_fndecl_size1): Remove
+ these global vars.
+ (gfc_build_intrinsic_function_decls): Remove their initialization.
+ * trans-expr.c (gfc_conv_procedure_call): Update
+ bounds of pointer/allocatable actual args to nonallocatable/nonpointer
+ dummies to be one based.
+ * trans-intrinsic.c (gfc_conv_intrinsic_shape): Fix case for
+ assumed rank with allocatable/pointer dummy.
+ (gfc_conv_intrinsic_size): Update to use inline function.
+ * trans.h (gfor_fndecl_size0, gfor_fndecl_size1): Remove var decl.
+
+2021-09-26 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/101334
+ * trans-intrinsic.c (gfc_conv_associated): Support assumed-rank
+ 'pointer' with scalar/array 'target' argument.
+
+2021-09-24 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102458
+ * expr.c (is_non_constant_intrinsic): Check for intrinsics
+ excluded in constant expressions (F2018:10.1.2).
+ (gfc_is_constant_expr): Use that check.
+
+2021-09-24 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101333
+ * interface.c (compare_parameter): Enforce F2018 C711.
+
+2021-09-24 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * scanner.c (load_file): Return void, call (gfc_)fatal_error for
+ all errors.
+ (include_line, include_stmt, gfc_new_file): Remove exit call
+ for failed load_file run.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101320
+ * decl.c (gfc_verify_c_interop_param): Handle F2018 C1557,
+ aka TS29113 C516.
+
+2021-09-23 Harald Anlauf <anlauf@gmx.de>
+ Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/93834
+ * trans-intrinsic.c (gfc_conv_allocated): Cleanup. Handle
+ coindexed scalar coarrays.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101319
+ * interface.c (gfc_compare_actual_formal): Extend existing
+ assumed-type diagnostic to also check for argument with type
+ parameters.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101334
+ * check.c (gfc_check_associated): Allow an assumed-rank
+ array for the pointer argument.
+ * interface.c (compare_parameter): Also give rank mismatch
+ error on assumed-rank array.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ * trans-stmt.c (trans_associate_var): Check that result of
+ GFC_DECL_SAVED_DESCRIPTOR is not null before using it.
+
+2021-09-22 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * cpp.c (gfc_cpp_register_include_paths, gfc_cpp_post_options):
+ Add new bool verbose_missing_dir_warn argument.
+ * cpp.h (gfc_cpp_post_options): Update prototype.
+ * f95-lang.c (gfc_init): Remove duplicated file-not found diag.
+ * gfortran.h (gfc_check_include_dirs): Takes bool
+ verbose_missing_dir_warn arg.
+ (gfc_new_file): Returns now void.
+ * options.c (gfc_post_options): Update to warn for -I and -J,
+ only, by default but for all when user requested.
+ * scanner.c (gfc_do_check_include_dir):
+ (gfc_do_check_include_dirs, gfc_check_include_dirs): Take bool
+ verbose warn arg and update to avoid printing the same message
+ twice or never.
+ (load_file): Fix indent.
+ (gfc_new_file): Return void and exit when load_file failed
+ as all other load_file users do.
+
+2021-09-22 Tobias Burnus <tobias@codesourcery.com>
+
+ * trans-expr.c (gfc_simple_for_loop): New.
+ * trans.h (gfc_simple_for_loop): New prototype.
+
+2021-09-21 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * cpp.c: Define GCC_C_COMMON_C for #include "options.h" to make
+ cpp_reason_option_codes available.
+ (gfc_cpp_register_include_paths): Make static, set pfile's
+ warn_missing_include_dirs and move before caller.
+ (gfc_cpp_init_cb): New, cb code moved from ...
+ (gfc_cpp_init_0): ... here.
+ (gfc_cpp_post_options): Call gfc_cpp_init_cb.
+ (cb_cpp_diagnostic_cpp_option): New. As implemented in c-family
+ to match CppReason flags to -W... names.
+ (cb_cpp_diagnostic): Use it to replace single special case.
+ * cpp.h (gfc_cpp_register_include_paths): Remove as now static.
+ * gfortran.h (gfc_check_include_dirs): New prototype.
+ (gfc_add_include_path): Add new bool arg.
+ * options.c (gfc_init_options): Don't set -Wmissing-include-dirs.
+ (gfc_post_options): Set it here after commandline processing. Call
+ gfc_add_include_path with defer_warn=false.
+ (gfc_handle_option): Call it with defer_warn=true.
+ * scanner.c (gfc_do_check_include_dir, gfc_do_check_include_dirs,
+ gfc_check_include_dirs): New. Diagnostic moved from ...
+ (add_path_to_list): ... here, which came before cmdline processing.
+ Take additional bool defer_warn argument.
+ (gfc_add_include_path): Take additional defer_warn arg.
+ * scanner.h (struct gfc_directorylist): Reorder for alignment issues,
+ add new 'bool warn'.
+
2021-09-20 Tobias Burnus <tobias@codesourcery.com>
* gfortran.h (gfc_omp_clauses): Add order_unconstrained.
diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c
index b858bad..6552eaf 100644
--- a/gcc/fortran/array.c
+++ b/gcc/fortran/array.c
@@ -1798,6 +1798,9 @@ expand_constructor (gfc_constructor_base base)
e = c->expr;
+ if (e == NULL)
+ return false;
+
if (empty_constructor)
empty_ts = e->ts;
@@ -2578,7 +2581,7 @@ gfc_array_dimen_size (gfc_expr *array, int dimen, mpz_t *result)
}
}
- if (array->shape && array->shape[dimen])
+ if (array->shape)
{
mpz_init_set (*result, array->shape[dimen]);
return true;
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index 851af1b..f31ad68 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -1520,7 +1520,9 @@ gfc_check_associated (gfc_expr *pointer, gfc_expr *target)
t = true;
if (!same_type_check (pointer, 0, target, 1, true))
t = false;
- if (!rank_check (target, 0, pointer->rank))
+ /* F2018 C838 explicitly allows an assumed-rank variable as the first
+ argument of intrinsic inquiry functions. */
+ if (pointer->rank != -1 && !rank_check (target, 0, pointer->rank))
t = false;
if (target->rank > 0)
{
diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c
index 3ff8954..e86386c 100644
--- a/gcc/fortran/cpp.c
+++ b/gcc/fortran/cpp.c
@@ -245,11 +245,12 @@ gfc_cpp_temporary_file (void)
}
static void
-gfc_cpp_register_include_paths (void)
+gfc_cpp_register_include_paths (bool verbose_missing_dir_warn)
{
int cxx_stdinc = 0;
cpp_get_options (cpp_in)->warn_missing_include_dirs
- = global_options.x_cpp_warn_missing_include_dirs;
+ = (global_options.x_cpp_warn_missing_include_dirs
+ && verbose_missing_dir_warn);
register_include_chains (cpp_in, gfc_cpp_option.sysroot,
gfc_cpp_option.prefix, gfc_cpp_option.multilib,
gfc_cpp_option.standard_include_paths, cxx_stdinc,
@@ -484,7 +485,7 @@ gfc_cpp_init_cb (void)
}
void
-gfc_cpp_post_options (void)
+gfc_cpp_post_options (bool verbose_missing_dir_warn)
{
/* Any preprocessing-related option without '-cpp' is considered
an error. */
@@ -547,7 +548,7 @@ gfc_cpp_post_options (void)
diagnostic_initialize_input_context (global_dc, nullptr, true);
gfc_cpp_init_cb ();
- gfc_cpp_register_include_paths ();
+ gfc_cpp_register_include_paths (verbose_missing_dir_warn);
}
diff --git a/gcc/fortran/cpp.h b/gcc/fortran/cpp.h
index 5cb7e5a..44644a2 100644
--- a/gcc/fortran/cpp.h
+++ b/gcc/fortran/cpp.h
@@ -41,7 +41,7 @@ void gfc_cpp_init_options (unsigned int decoded_options_count,
int gfc_cpp_handle_option(size_t scode, const char *arg, int value);
-void gfc_cpp_post_options (void);
+void gfc_cpp_post_options (bool);
bool gfc_cpp_preprocess (const char *source_file);
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index f2e8896..b3c65b7 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -1557,6 +1557,20 @@ gfc_verify_c_interop_param (gfc_symbol *sym)
"CONTIGUOUS attribute as procedure %qs is BIND(C)",
sym->name, &sym->declared_at, sym->ns->proc_name->name);
+ /* Per F2018, C1557, pointer/allocatable dummies to a bind(c)
+ procedure that are default-initialized are not permitted. */
+ if ((sym->attr.pointer || sym->attr.allocatable)
+ && sym->ts.type == BT_DERIVED
+ && gfc_has_default_initializer (sym->ts.u.derived))
+ {
+ gfc_error ("Default-initialized %s dummy argument %qs "
+ "at %L is not permitted in BIND(C) procedure %qs",
+ (sym->attr.pointer ? "pointer" : "allocatable"),
+ sym->name, &sym->declared_at,
+ sym->ns->proc_name->name);
+ retval = false;
+ }
+
/* Character strings are only C interoperable if they have a
length of 1. However, as an argument they are also iteroperable
when passed as descriptor (which requires len=: or len=*). */
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 28eb09e..64e04c0 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -1634,6 +1634,8 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
fputs (" ORDER(", dumpfile);
if (omp_clauses->order_unconstrained)
fputs ("UNCONSTRAINED:", dumpfile);
+ else if (omp_clauses->order_reproducible)
+ fputs ("REPRODUCIBLE:", dumpfile);
fputs ("CONCURRENT)", dumpfile);
}
if (omp_clauses->ordered)
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 604e63e..6c38935 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -990,6 +990,34 @@ done:
}
+/* Standard intrinsics listed under F2018:10.1.12 (6), which are excluded in
+ constant expressions, except TRANSFER (c.f. item (8)), which would need
+ separate treatment. */
+
+static bool
+is_non_constant_intrinsic (gfc_expr *e)
+{
+ if (e->expr_type == EXPR_FUNCTION
+ && e->value.function.isym)
+ {
+ switch (e->value.function.isym->id)
+ {
+ case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
+ case GFC_ISYM_GET_TEAM:
+ case GFC_ISYM_NULL:
+ case GFC_ISYM_NUM_IMAGES:
+ case GFC_ISYM_TEAM_NUMBER:
+ case GFC_ISYM_THIS_IMAGE:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
+
/* Determine if an expression is constant in the sense of F08:7.1.12.
* This function expects that the expression has already been simplified. */
@@ -1023,6 +1051,10 @@ gfc_is_constant_expr (gfc_expr *e)
gcc_assert (e->symtree || e->value.function.esym
|| e->value.function.isym);
+ /* Check for intrinsics excluded in constant expressions. */
+ if (e->value.function.isym && is_non_constant_intrinsic (e))
+ return false;
+
/* Call to intrinsic with at least one argument. */
if (e->value.function.isym && e->value.function.actual)
{
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index 026228d..58dcaf0 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -259,8 +259,8 @@ gfc_init (void)
gfc_init_1 ();
- if (!gfc_new_file ())
- fatal_error (input_location, "cannot open input file: %s", gfc_source_file);
+ /* Calls exit in case of a fail. */
+ gfc_new_file ();
if (flag_preprocess_only)
return false;
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 3c7a843..c25d1cc 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1491,8 +1491,8 @@ typedef struct gfc_omp_clauses
unsigned inbranch:1, notinbranch:1, nogroup:1;
unsigned sched_simd:1, sched_monotonic:1, sched_nonmonotonic:1;
unsigned simd:1, threads:1, depend_source:1, destroy:1, order_concurrent:1;
- unsigned order_unconstrained:1, capture:1, grainsize_strict:1;
- unsigned num_tasks_strict:1;
+ unsigned order_unconstrained:1, order_reproducible:1, capture:1;
+ unsigned grainsize_strict:1, num_tasks_strict:1;
ENUM_BITFIELD (gfc_omp_sched_kind) sched_kind:3;
ENUM_BITFIELD (gfc_omp_device_type) device_type:2;
ENUM_BITFIELD (gfc_omp_memorder) memorder:3;
@@ -3032,7 +3032,7 @@ void gfc_scanner_init_1 (void);
void gfc_add_include_path (const char *, bool, bool, bool, bool);
void gfc_add_intrinsic_modules_path (const char *);
void gfc_release_include_path (void);
-void gfc_check_include_dirs (void);
+void gfc_check_include_dirs (bool);
FILE *gfc_open_included_file (const char *, bool, bool);
int gfc_at_end (void);
@@ -3064,7 +3064,7 @@ gfc_char_t gfc_peek_char (void);
char gfc_peek_ascii_char (void);
void gfc_error_recovery (void);
void gfc_gobble_whitespace (void);
-bool gfc_new_file (void);
+void gfc_new_file (void);
const char * gfc_read_orig_filename (const char *, const char **);
extern gfc_source_form gfc_current_form;
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 9e3e8aa..a2fea0e 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -2448,6 +2448,21 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
return false;
}
+ /* TS29113 C407c; F2018 C711. */
+ if (actual->ts.type == BT_ASSUMED
+ && symbol_rank (formal) == -1
+ && actual->rank != -1
+ && !(actual->symtree->n.sym->as
+ && actual->symtree->n.sym->as->type == AS_ASSUMED_SHAPE))
+ {
+ if (where)
+ gfc_error ("Assumed-type actual argument at %L corresponding to "
+ "assumed-rank dummy argument %qs must be "
+ "assumed-shape or assumed-rank",
+ &actual->where, formal->name);
+ return false;
+ }
+
/* F2008, 12.5.2.5; IR F08/0073. */
if (formal->ts.type == BT_CLASS && formal->attr.class_ok
&& actual->expr_type != EXPR_NULL
@@ -2634,7 +2649,9 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
&& formal->as->type == AS_ASSUMED_SHAPE))
&& actual->expr_type != EXPR_NULL)
|| (actual->rank == 0 && formal->attr.dimension
- && gfc_is_coindexed (actual)))
+ && gfc_is_coindexed (actual))
+ /* Assumed-rank actual argument; F2018 C838. */
+ || actual->rank == -1)
{
if (where
&& (!formal->attr.artificial || (!formal->maybe_array
@@ -3181,21 +3198,21 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
is_elemental, where))
return false;
- /* TS 29113, 6.3p2. */
+ /* TS 29113, 6.3p2; F2018 15.5.2.4. */
if (f->sym->ts.type == BT_ASSUMED
&& (a->expr->ts.type == BT_DERIVED
|| (a->expr->ts.type == BT_CLASS && CLASS_DATA (a->expr))))
{
- gfc_namespace *f2k_derived;
-
- f2k_derived = a->expr->ts.type == BT_DERIVED
- ? a->expr->ts.u.derived->f2k_derived
- : CLASS_DATA (a->expr)->ts.u.derived->f2k_derived;
-
- if (f2k_derived
- && (f2k_derived->finalizers || f2k_derived->tb_sym_root))
+ gfc_symbol *derived = (a->expr->ts.type == BT_DERIVED
+ ? a->expr->ts.u.derived
+ : CLASS_DATA (a->expr)->ts.u.derived);
+ gfc_namespace *f2k_derived = derived->f2k_derived;
+ if (derived->attr.pdt_type
+ || (f2k_derived
+ && (f2k_derived->finalizers || f2k_derived->tb_sym_root)))
{
- gfc_error ("Actual argument at %L to assumed-type dummy is of "
+ gfc_error ("Actual argument at %L to assumed-type dummy "
+ "has type parameters or is of "
"derived type with type-bound or FINAL procedures",
&a->expr->where);
return false;
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 9ee52d6..6a4ca28 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -2374,8 +2374,9 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
{
if (m == MATCH_ERROR)
goto error;
- if (gfc_match (" reproducible : concurrent )") == MATCH_YES
- || gfc_match (" concurrent )") == MATCH_YES)
+ if (gfc_match (" reproducible : concurrent )") == MATCH_YES)
+ c->order_reproducible = true;
+ else if (gfc_match (" concurrent )") == MATCH_YES)
;
else if (gfc_match (" unconstrained : concurrent )") == MATCH_YES)
c->order_unconstrained = true;
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index d789397..016b704 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -251,14 +251,20 @@ gfc_post_options (const char **pfilename)
{
const char *filename = *pfilename, *canon_source_file = NULL;
char *source_path;
+ bool verbose_missing_dir_warn;
int i;
/* This needs to be after the commandline has been processed.
In Fortran, the options is by default enabled, in C/C++
- by default disabled. */
+ by default disabled.
+ If not enabled explicitly by the user, only warn for -I
+ and -J, otherwise warn for all include paths. */
+ verbose_missing_dir_warn
+ = (global_options_set.x_cpp_warn_missing_include_dirs
+ && global_options.x_cpp_warn_missing_include_dirs);
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
cpp_warn_missing_include_dirs, 1);
- gfc_check_include_dirs ();
+ gfc_check_include_dirs (verbose_missing_dir_warn);
/* Finalize DEC flags. */
post_dec_flags (flag_dec);
@@ -339,10 +345,13 @@ gfc_post_options (const char **pfilename)
source_path = (char *) alloca (i + 1);
memcpy (source_path, canon_source_file, i);
source_path[i] = 0;
- gfc_add_include_path (source_path, true, true, true, false);
+ /* Only warn if the directory is different from the input file as
+ if that one is not found, already an error is shown. */
+ bool warn = gfc_option.flag_preprocessed && gfc_source_file != filename;
+ gfc_add_include_path (source_path, true, true, warn, false);
}
else
- gfc_add_include_path (".", true, true, true, false);
+ gfc_add_include_path (".", true, true, false, false);
if (canon_source_file != gfc_source_file)
free (CONST_CAST (char *, canon_source_file));
@@ -490,7 +499,7 @@ gfc_post_options (const char **pfilename)
gfc_fatal_error ("Maximum subrecord length cannot exceed %d",
MAX_SUBRECORD_LENGTH);
- gfc_cpp_post_options ();
+ gfc_cpp_post_options (verbose_missing_dir_warn);
if (gfc_option.allow_std & GFC_STD_F2008)
lang_hooks.name = "GNU Fortran2008";
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 30b96b2..0d0af39 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -12351,7 +12351,7 @@ resolve_values (gfc_symbol *sym)
if (sym->value == NULL)
return;
- if (sym->attr.ext_attr & (1 << EXT_ATTR_DEPRECATED))
+ if (sym->attr.ext_attr & (1 << EXT_ATTR_DEPRECATED) && sym->attr.referenced)
gfc_warning (OPT_Wdeprecated_declarations,
"Using parameter %qs declared at %L is deprecated",
sym->name, &sym->declared_at);
@@ -12676,7 +12676,8 @@ can_generate_init (gfc_symbol *sym)
|| a->cray_pointer
|| sym->assoc
|| (!a->referenced && !a->result)
- || (a->dummy && a->intent != INTENT_OUT)
+ || (a->dummy && (a->intent != INTENT_OUT
+ || sym->ns->proc_name->attr.if_source == IFSRC_IFBODY))
|| (a->function && sym != sym->result)
);
}
@@ -12913,7 +12914,9 @@ resolve_fl_variable_derived (gfc_symbol *sym, int no_init_flag)
/* Assign default initializer. */
if (!(sym->value || sym->attr.pointer || sym->attr.allocatable)
- && (!no_init_flag || sym->attr.intent == INTENT_OUT))
+ && (!no_init_flag
+ || (sym->attr.intent == INTENT_OUT
+ && sym->ns->proc_name->attr.if_source != IFSRC_IFBODY)))
sym->value = gfc_generate_initializer (&sym->ts, can_generate_init (sym));
return true;
@@ -16154,7 +16157,8 @@ resolve_symbol (gfc_symbol *sym)
|| sym->ts.u.derived->attr.alloc_comp
|| sym->ts.u.derived->attr.pointer_comp))
&& !(a->function && sym != sym->result))
- || (a->dummy && a->intent == INTENT_OUT && !a->pointer))
+ || (a->dummy && !a->pointer && a->intent == INTENT_OUT
+ && sym->ns->proc_name->attr.if_source != IFSRC_IFBODY))
apply_default_init (sym);
else if (a->function && sym->result && a->access != ACCESS_PRIVATE
&& (sym->ts.u.derived->attr.alloc_comp
@@ -16166,6 +16170,7 @@ resolve_symbol (gfc_symbol *sym)
if (sym->ts.type == BT_CLASS && sym->ns == gfc_current_ns
&& sym->attr.dummy && sym->attr.intent == INTENT_OUT
+ && sym->ns->proc_name->attr.if_source != IFSRC_IFBODY
&& !CLASS_DATA (sym)->attr.class_pointer
&& !CLASS_DATA (sym)->attr.allocatable)
apply_default_init (sym);
diff --git a/gcc/fortran/scanner.c b/gcc/fortran/scanner.c
index 6fe74bd..5a45069 100644
--- a/gcc/fortran/scanner.c
+++ b/gcc/fortran/scanner.c
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
#include "toplev.h" /* For set_src_pwd. */
#include "debug.h"
#include "options.h"
+#include "diagnostic-core.h" /* For fatal_error. */
#include "cpp.h"
#include "scanner.h"
@@ -307,9 +308,9 @@ gfc_do_check_include_dir (const char *path, bool warn)
if (errno != ENOENT)
gfc_warning_now (0, "Include directory %qs: %s",
path, xstrerror(errno));
- else if (warn && !gfc_cpp_enabled ())
+ else if (warn)
gfc_warning_now (OPT_Wmissing_include_dirs,
- "Nonexistent include directory %qs", path);
+ "Nonexistent include directory %qs", path);
return false;
}
else if (!S_ISDIR (st.st_mode))
@@ -323,7 +324,7 @@ gfc_do_check_include_dir (const char *path, bool warn)
/* In order that -W(no-)missing-include-dirs works, the diagnostic can only be
run after processing the commandline. */
static void
-gfc_do_check_include_dirs (gfc_directorylist **list)
+gfc_do_check_include_dirs (gfc_directorylist **list, bool do_warn)
{
gfc_directorylist *prev, *q, *n;
prev = NULL;
@@ -331,7 +332,7 @@ gfc_do_check_include_dirs (gfc_directorylist **list)
while (n)
{
q = n; n = n->next;
- if (gfc_do_check_include_dir (q->path, q->warn))
+ if (gfc_do_check_include_dir (q->path, q->warn && do_warn))
{
prev = q;
continue;
@@ -346,10 +347,16 @@ gfc_do_check_include_dirs (gfc_directorylist **list)
}
void
-gfc_check_include_dirs ()
+gfc_check_include_dirs (bool verbose_missing_dir_warn)
{
- gfc_do_check_include_dirs (&include_dirs);
- gfc_do_check_include_dirs (&intrinsic_modules_dirs);
+ /* This is a bit convoluted: If gfc_cpp_enabled () and
+ verbose_missing_dir_warn, the warning is shown by libcpp. Otherwise,
+ it is shown here, still conditional on OPT_Wmissing_include_dirs. */
+ bool warn = !gfc_cpp_enabled () || !verbose_missing_dir_warn;
+ gfc_do_check_include_dirs (&include_dirs, warn);
+ gfc_do_check_include_dirs (&intrinsic_modules_dirs, verbose_missing_dir_warn);
+ if (gfc_option.module_dir && gfc_cpp_enabled ())
+ gfc_do_check_include_dirs (&include_dirs, true);
}
/* Adds path to the list pointed to by list. */
@@ -2224,7 +2231,7 @@ preprocessor_line (gfc_char_t *c)
}
-static bool load_file (const char *, const char *, bool);
+static void load_file (const char *, const char *, bool);
/* include_line()-- Checks a line buffer to see if it is an include
line. If so, we call load_file() recursively to load the included
@@ -2390,9 +2397,7 @@ include_line (gfc_char_t *line)
read by anything else. */
filename = gfc_widechar_to_char (begin, -1);
- if (!load_file (filename, NULL, false))
- exit (FATAL_EXIT_CODE);
-
+ load_file (filename, NULL, false);
free (filename);
return 1;
}
@@ -2499,9 +2504,7 @@ include_stmt (gfc_linebuf *b)
filename[i] = (unsigned char) c;
}
filename[length] = '\0';
- if (!load_file (filename, NULL, false))
- exit (FATAL_EXIT_CODE);
-
+ load_file (filename, NULL, false);
free (filename);
do_ret:
@@ -2519,9 +2522,11 @@ do_ret:
return ret;
}
+
+
/* Load a file into memory by calling load_line until the file ends. */
-static bool
+static void
load_file (const char *realfilename, const char *displayedname, bool initial)
{
gfc_char_t *line;
@@ -2543,13 +2548,8 @@ load_file (const char *realfilename, const char *displayedname, bool initial)
for (f = current_file; f; f = f->up)
if (filename_cmp (filename, f->filename) == 0)
- {
- fprintf (stderr, "%s:%d: Error: File '%s' is being included "
- "recursively\n", current_file->filename, current_file->line,
- filename);
- return false;
- }
-
+ fatal_error (linemap_line_start (line_table, current_file->line, 0),
+ "File %qs is being included recursively", filename);
if (initial)
{
if (gfc_src_file)
@@ -2561,10 +2561,7 @@ load_file (const char *realfilename, const char *displayedname, bool initial)
input = gfc_open_file (realfilename);
if (input == NULL)
- {
- gfc_error_now ("Cannot open file %qs", filename);
- return false;
- }
+ gfc_fatal_error ("Cannot open file %qs", filename);
}
else
{
@@ -2573,22 +2570,20 @@ load_file (const char *realfilename, const char *displayedname, bool initial)
{
/* For -fpre-include file, current_file is NULL. */
if (current_file)
- fprintf (stderr, "%s:%d: Error: Can't open included file '%s'\n",
- current_file->filename, current_file->line, filename);
+ fatal_error (linemap_line_start (line_table, current_file->line, 0),
+ "Cannot open included file %qs", filename);
else
- fprintf (stderr, "Error: Can't open pre-included file '%s'\n",
- filename);
-
- return false;
+ gfc_fatal_error ("Cannot open pre-included file %qs", filename);
}
stat_result = stat (realfilename, &st);
- if (stat_result == 0 && !S_ISREG(st.st_mode))
+ if (stat_result == 0 && !S_ISREG (st.st_mode))
{
- fprintf (stderr, "%s:%d: Error: Included path '%s'"
- " is not a regular file\n",
- current_file->filename, current_file->line, filename);
fclose (input);
- return false;
+ if (current_file)
+ fatal_error (linemap_line_start (line_table, current_file->line, 0),
+ "Included file %qs is not a regular file", filename);
+ else
+ gfc_fatal_error ("Included file %qs is not a regular file", filename);
}
}
@@ -2762,7 +2757,6 @@ load_file (const char *realfilename, const char *displayedname, bool initial)
add_file_change (NULL, current_file->inclusion_line + 1);
current_file = current_file->up;
linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
- return true;
}
@@ -2771,23 +2765,20 @@ load_file (const char *realfilename, const char *displayedname, bool initial)
it tries to determine the source form from the filename, defaulting
to free form. */
-bool
+void
gfc_new_file (void)
{
- bool result;
-
- if (flag_pre_include != NULL
- && !load_file (flag_pre_include, NULL, false))
- exit (FATAL_EXIT_CODE);
+ if (flag_pre_include != NULL)
+ load_file (flag_pre_include, NULL, false);
if (gfc_cpp_enabled ())
{
- result = gfc_cpp_preprocess (gfc_source_file);
+ gfc_cpp_preprocess (gfc_source_file);
if (!gfc_cpp_preprocess_only ())
- result = load_file (gfc_cpp_temporary_file (), gfc_source_file, true);
+ load_file (gfc_cpp_temporary_file (), gfc_source_file, true);
}
else
- result = load_file (gfc_source_file, NULL, true);
+ load_file (gfc_source_file, NULL, true);
gfc_current_locus.lb = line_head;
gfc_current_locus.nextc = (line_head == NULL) ? NULL : line_head->line;
@@ -2799,8 +2790,6 @@ gfc_new_file (void)
exit (SUCCESS_EXIT_CODE);
#endif
-
- return result;
}
static char *
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index b46cbfa..f40e493 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -7471,6 +7471,7 @@ simplify_size (gfc_expr *array, gfc_expr *dim, int k)
mpz_t size;
gfc_expr *return_value;
int d;
+ gfc_ref *ref;
/* For unary operations, the size of the result is given by the size
of the operand. For binary ones, it's the size of the first operand
@@ -7527,6 +7528,10 @@ simplify_size (gfc_expr *array, gfc_expr *dim, int k)
return simplified;
}
+ for (ref = array->ref; ref; ref = ref->next)
+ if (ref->type == REF_ARRAY && ref->u.ar.as)
+ gfc_resolve_array_spec (ref->u.ar.as, 0);
+
if (dim == NULL)
{
if (!gfc_array_size (array, &size))
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 0d013de..e2f59e0 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -5104,7 +5104,6 @@ set_loop_bounds (gfc_loopinfo *loop)
if (info->shape)
{
- gcc_assert (info->shape[dim]);
/* The frontend has worked out the size for us. */
if (!loopspec[n]
|| !specinfo->shape
@@ -7901,31 +7900,143 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
gfc_cleanup_loop (&loop);
}
+
+/* Calculate the array size (number of elements); if dim != NULL_TREE,
+ return size for that dim (dim=0..rank-1; only for GFC_DESCRIPTOR_TYPE_P). */
+tree
+gfc_tree_array_size (stmtblock_t *block, tree desc, gfc_expr *expr, tree dim)
+{
+ if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
+ {
+ gcc_assert (dim == NULL_TREE);
+ return GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
+ }
+ tree size, tmp, rank = NULL_TREE, cond = NULL_TREE;
+ symbol_attribute attr = gfc_expr_attr (expr);
+ gfc_array_spec *as = gfc_get_full_arrayspec_from_expr (expr);
+ gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
+ if ((!attr.pointer && !attr.allocatable && as && as->type == AS_ASSUMED_RANK)
+ || !dim)
+ {
+ if (expr->rank < 0)
+ rank = fold_convert (signed_char_type_node,
+ gfc_conv_descriptor_rank (desc));
+ else
+ rank = build_int_cst (signed_char_type_node, expr->rank);
+ }
+
+ if (dim || expr->rank == 1)
+ {
+ if (!dim)
+ dim = gfc_index_zero_node;
+ tree ubound = gfc_conv_descriptor_ubound_get (desc, dim);
+ tree lbound = gfc_conv_descriptor_lbound_get (desc, dim);
+
+ size = fold_build2_loc (input_location, MINUS_EXPR,
+ gfc_array_index_type, ubound, lbound);
+ size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
+ size, gfc_index_one_node);
+ /* if (!allocatable && !pointer && assumed rank)
+ size = (idx == rank && ubound[rank-1] == -1 ? -1 : size;
+ else
+ size = max (0, size); */
+ size = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
+ size, gfc_index_zero_node);
+ if (!attr.pointer && !attr.allocatable
+ && as && as->type == AS_ASSUMED_RANK)
+ {
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, signed_char_type_node,
+ rank, build_int_cst (signed_char_type_node, 1));
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
+ fold_convert (signed_char_type_node, dim),
+ tmp);
+ tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
+ gfc_conv_descriptor_ubound_get (desc, dim),
+ build_int_cst (gfc_array_index_type, -1));
+ cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_type_node,
+ cond, tmp);
+ tmp = build_int_cst (gfc_array_index_type, -1);
+ size = build3_loc (input_location, COND_EXPR, gfc_array_index_type,
+ cond, tmp, size);
+ }
+ return size;
+ }
+
+ /* size = 1. */
+ size = gfc_create_var (gfc_array_index_type, "size");
+ gfc_add_modify (block, size, build_int_cst (TREE_TYPE (size), 1));
+ tree extent = gfc_create_var (gfc_array_index_type, "extent");
+
+ stmtblock_t cond_block, loop_body;
+ gfc_init_block (&cond_block);
+ gfc_init_block (&loop_body);
+
+ /* Loop: for (i = 0; i < rank; ++i). */
+ tree idx = gfc_create_var (signed_char_type_node, "idx");
+ /* Loop body. */
+ /* #if (assumed-rank + !allocatable && !pointer)
+ if (idx == rank - 1 && dim[idx].ubound == -1)
+ extent = -1;
+ else
+ #endif
+ extent = gfc->dim[i].ubound - gfc->dim[i].lbound + 1
+ if (extent < 0)
+ extent = 0
+ size *= extent. */
+ cond = NULL_TREE;
+ if (!attr.pointer && !attr.allocatable && as && as->type == AS_ASSUMED_RANK)
+ {
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, signed_char_type_node,
+ rank, build_int_cst (signed_char_type_node, 1));
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
+ idx, tmp);
+ tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
+ gfc_conv_descriptor_ubound_get (desc, idx),
+ build_int_cst (gfc_array_index_type, -1));
+ cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_type_node,
+ cond, tmp);
+ }
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
+ gfc_conv_descriptor_ubound_get (desc, idx),
+ gfc_conv_descriptor_lbound_get (desc, idx));
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
+ tmp, gfc_index_one_node);
+ gfc_add_modify (&cond_block, extent, tmp);
+ tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
+ extent, gfc_index_zero_node);
+ tmp = build3_v (COND_EXPR, tmp,
+ fold_build2_loc (input_location, MODIFY_EXPR,
+ gfc_array_index_type,
+ extent, gfc_index_zero_node),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&cond_block, tmp);
+ tmp = gfc_finish_block (&cond_block);
+ if (cond)
+ tmp = build3_v (COND_EXPR, cond,
+ fold_build2_loc (input_location, MODIFY_EXPR,
+ gfc_array_index_type, extent,
+ build_int_cst (gfc_array_index_type, -1)),
+ tmp);
+ gfc_add_expr_to_block (&loop_body, tmp);
+ /* size *= extent. */
+ gfc_add_modify (&loop_body, size,
+ fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
+ size, extent));
+ /* Generate loop. */
+ gfc_simple_for_loop (block, idx, build_int_cst (TREE_TYPE (idx), 0), rank, LT_EXPR,
+ build_int_cst (TREE_TYPE (idx), 1),
+ gfc_finish_block (&loop_body));
+ return size;
+}
+
/* Helper function for gfc_conv_array_parameter if array size needs to be
computed. */
static void
-array_parameter_size (tree desc, gfc_expr *expr, tree *size)
+array_parameter_size (stmtblock_t *block, tree desc, gfc_expr *expr, tree *size)
{
tree elem;
- if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
- *size = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
- else if (expr->rank > 1)
- *size = build_call_expr_loc (input_location,
- gfor_fndecl_size0, 1,
- gfc_build_addr_expr (NULL, desc));
- else
- {
- tree ubound = gfc_conv_descriptor_ubound_get (desc, gfc_index_zero_node);
- tree lbound = gfc_conv_descriptor_lbound_get (desc, gfc_index_zero_node);
-
- *size = fold_build2_loc (input_location, MINUS_EXPR,
- gfc_array_index_type, ubound, lbound);
- *size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
- *size, gfc_index_one_node);
- *size = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
- *size, gfc_index_zero_node);
- }
+ *size = gfc_tree_array_size (block, desc, expr, NULL);
elem = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
*size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
*size, fold_convert (gfc_array_index_type, elem));
@@ -8035,7 +8146,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
else
se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
if (size)
- array_parameter_size (tmp, expr, size);
+ array_parameter_size (&se->pre, tmp, expr, size);
return;
}
@@ -8047,7 +8158,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
tmp = se->expr;
}
if (size)
- array_parameter_size (tmp, expr, size);
+ array_parameter_size (&se->pre, tmp, expr, size);
se->expr = gfc_conv_array_data (tmp);
return;
}
@@ -8122,7 +8233,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
if (expr->ts.type == BT_CHARACTER && expr->expr_type != EXPR_FUNCTION)
se->string_length = expr->ts.u.cl->backend_decl;
if (size)
- array_parameter_size (se->expr, expr, size);
+ array_parameter_size (&se->pre, se->expr, expr, size);
se->expr = gfc_conv_array_data (se->expr);
return;
}
@@ -8132,7 +8243,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
/* Result of the enclosing function. */
gfc_conv_expr_descriptor (se, expr);
if (size)
- array_parameter_size (se->expr, expr, size);
+ array_parameter_size (&se->pre, se->expr, expr, size);
se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
@@ -8149,9 +8260,10 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
gfc_conv_expr_descriptor (se, expr);
if (size)
- array_parameter_size (build_fold_indirect_ref_loc (input_location,
- se->expr),
- expr, size);
+ array_parameter_size (&se->pre,
+ build_fold_indirect_ref_loc (input_location,
+ se->expr),
+ expr, size);
}
/* Deallocate the allocatable components of structures that are
diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h
index e4d443d..85ff216 100644
--- a/gcc/fortran/trans-array.h
+++ b/gcc/fortran/trans-array.h
@@ -39,6 +39,8 @@ void gfc_trans_dummy_array_bias (gfc_symbol *, tree, gfc_wrapped_block *);
/* Generate entry and exit code for g77 calling convention arrays. */
void gfc_trans_g77_array (gfc_symbol *, gfc_wrapped_block *);
+tree gfc_tree_array_size (stmtblock_t *, tree, gfc_expr *, tree);
+
tree gfc_full_array_size (stmtblock_t *, tree, int);
tree gfc_duplicate_allocatable (tree, tree, tree, int, tree);
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 3bd8a0f..c758d26 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -214,8 +214,6 @@ tree gfor_fndecl_convert_char4_to_char1;
/* Other misc. runtime library functions. */
-tree gfor_fndecl_size0;
-tree gfor_fndecl_size1;
tree gfor_fndecl_iargc;
tree gfor_fndecl_kill;
tree gfor_fndecl_kill_sub;
@@ -3692,18 +3690,6 @@ gfc_build_intrinsic_function_decls (void)
}
/* Other functions. */
- gfor_fndecl_size0 = gfc_build_library_function_decl_with_spec (
- get_identifier (PREFIX("size0")), ". R ",
- gfc_array_index_type, 1, pvoid_type_node);
- DECL_PURE_P (gfor_fndecl_size0) = 1;
- TREE_NOTHROW (gfor_fndecl_size0) = 1;
-
- gfor_fndecl_size1 = gfc_build_library_function_decl_with_spec (
- get_identifier (PREFIX("size1")), ". R . ",
- gfc_array_index_type, 2, pvoid_type_node, gfc_array_index_type);
- DECL_PURE_P (gfor_fndecl_size1) = 1;
- TREE_NOTHROW (gfor_fndecl_size1) = 1;
-
gfor_fndecl_iargc = gfc_build_library_function_decl (
get_identifier (PREFIX ("iargc")), gfc_int4_type_node, 0);
TREE_NOTHROW (gfor_fndecl_iargc) = 1;
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 4a81f46..1c24556 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -6450,6 +6450,29 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
parmse.force_tmp = 1;
}
+ /* Special case for assumed-rank arrays: when passing an
+ argument to a nonallocatable/nonpointer dummy, the bounds have
+ to be reset as otherwise a last-dim ubound of -1 is
+ indistinguishable from an assumed-size array in the callee. */
+ if (!sym->attr.is_bind_c && e && fsym && fsym->as
+ && fsym->as->type == AS_ASSUMED_RANK
+ && e->rank != -1
+ && e->expr_type == EXPR_VARIABLE
+ && ((fsym->ts.type == BT_CLASS
+ && !CLASS_DATA (fsym)->attr.class_pointer
+ && !CLASS_DATA (fsym)->attr.allocatable)
+ || (fsym->ts.type != BT_CLASS
+ && !fsym->attr.pointer && !fsym->attr.allocatable)))
+ {
+ /* Change AR_FULL to a (:,:,:) ref to force bounds update. */
+ gfc_ref *ref;
+ for (ref = e->ref; ref->next; ref = ref->next)
+ ;
+ if (ref->u.ar.type == AR_FULL
+ && ref->u.ar.as->type != AS_ASSUMED_SIZE)
+ ref->u.ar.type = AR_SECTION;
+ }
+
if (sym->attr.is_bind_c && e
&& (is_CFI_desc (fsym, NULL) || assumed_length_string))
/* Implement F2018, 18.3.6, list item (5), bullet point 2. */
@@ -6510,16 +6533,26 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
gfc_conv_array_parameter (&parmse, e, nodesc_arg, fsym,
sym->name, NULL);
- /* Unallocated allocatable arrays and unassociated pointer arrays
- need their dtype setting if they are argument associated with
- assumed rank dummies, unless already assumed rank. */
+ /* Special case for assumed-rank arrays. */
if (!sym->attr.is_bind_c && e && fsym && fsym->as
&& fsym->as->type == AS_ASSUMED_RANK
&& e->rank != -1)
{
- if (gfc_expr_attr (e).pointer
+ if ((gfc_expr_attr (e).pointer
|| gfc_expr_attr (e).allocatable)
- set_dtype_for_unallocated (&parmse, e);
+ && ((fsym->ts.type == BT_CLASS
+ && (CLASS_DATA (fsym)->attr.class_pointer
+ || CLASS_DATA (fsym)->attr.allocatable))
+ || (fsym->ts.type != BT_CLASS
+ && (fsym->attr.pointer || fsym->attr.allocatable))))
+ {
+ /* Unallocated allocatable arrays and unassociated pointer
+ arrays need their dtype setting if they are argument
+ associated with assumed rank dummies. However, if the
+ dummy is nonallocate/nonpointer, the user may not
+ pass those. Hence, it can be skipped. */
+ set_dtype_for_unallocated (&parmse, e);
+ }
else if (e->expr_type == EXPR_VARIABLE
&& e->ref
&& e->ref->u.ar.type == AR_FULL
@@ -11728,3 +11761,37 @@ gfc_trans_assign (gfc_code * code)
{
return gfc_trans_assignment (code->expr1, code->expr2, false, true);
}
+
+/* Generate a simple loop for internal use of the form
+ for (var = begin; var <cond> end; var += step)
+ body; */
+void
+gfc_simple_for_loop (stmtblock_t *block, tree var, tree begin, tree end,
+ enum tree_code cond, tree step, tree body)
+{
+ tree tmp;
+
+ /* var = begin. */
+ gfc_add_modify (block, var, begin);
+
+ /* Loop: for (var = begin; var <cond> end; var += step). */
+ tree label_loop = gfc_build_label_decl (NULL_TREE);
+ tree label_cond = gfc_build_label_decl (NULL_TREE);
+ TREE_USED (label_loop) = 1;
+ TREE_USED (label_cond) = 1;
+
+ gfc_add_expr_to_block (block, build1_v (GOTO_EXPR, label_cond));
+ gfc_add_expr_to_block (block, build1_v (LABEL_EXPR, label_loop));
+
+ /* Loop body. */
+ gfc_add_expr_to_block (block, body);
+
+ /* End of loop body. */
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var, step);
+ gfc_add_modify (block, var, tmp);
+ gfc_add_expr_to_block (block, build1_v (LABEL_EXPR, label_cond));
+ tmp = fold_build2_loc (input_location, cond, boolean_type_node, var, end);
+ tmp = build3_v (COND_EXPR, tmp, build1_v (GOTO_EXPR, label_loop),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (block, tmp);
+}
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 42a995b..2a2829c 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -6697,6 +6697,8 @@ gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr)
gfc_expr *e;
gfc_array_spec *as;
gfc_ss *ss;
+ symbol_attribute attr;
+ tree result_desc = se->expr;
/* Remove the KIND argument, if present. */
s = expr->value.function.actual;
@@ -6707,17 +6709,25 @@ gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr)
gfc_conv_intrinsic_funcall (se, expr);
- as = gfc_get_full_arrayspec_from_expr (s->expr);;
- ss = gfc_walk_expr (s->expr);
-
/* According to F2018 16.9.172, para 5, an assumed rank entity, argument
associated with an assumed size array, has the ubound of the final
dimension set to -1 and SHAPE must return this. */
- if (as && as->type == AS_ASSUMED_RANK
- && se->expr && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr))
- && ss && ss->info->type == GFC_SS_SECTION)
+
+ as = gfc_get_full_arrayspec_from_expr (s->expr);
+ if (!as || as->type != AS_ASSUMED_RANK)
+ return;
+ attr = gfc_expr_attr (s->expr);
+ ss = gfc_walk_expr (s->expr);
+ if (attr.pointer || attr.allocatable
+ || !ss || ss->info->type != GFC_SS_SECTION)
+ return;
+ if (se->expr)
+ result_desc = se->expr;
+ if (POINTER_TYPE_P (TREE_TYPE (result_desc)))
+ result_desc = build_fold_indirect_ref_loc (input_location, result_desc);
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (result_desc)))
{
- tree desc, rank, minus_one, cond, ubound, tmp;
+ tree rank, minus_one, cond, ubound, tmp;
stmtblock_t block;
gfc_se ase;
@@ -6745,8 +6755,7 @@ gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr)
/* Obtain the last element of the result from the library shape
intrinsic and set it to -1 if that is the value of ubound. */
- desc = se->expr;
- tmp = gfc_conv_array_data (desc);
+ tmp = gfc_conv_array_data (result_desc);
tmp = build_fold_indirect_ref_loc (input_location, tmp);
tmp = gfc_build_array_ref (tmp, rank, NULL, NULL);
@@ -6758,7 +6767,6 @@ gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr)
build_empty_stmt (input_location));
gfc_add_expr_to_block (&se->pre, cond);
}
-
}
static void
@@ -7968,8 +7976,7 @@ gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
gfc_actual_arglist *actual;
tree arg1;
tree type;
- tree fncall0;
- tree fncall1;
+ tree size;
gfc_se argse;
gfc_expr *e;
gfc_symbol *sym = NULL;
@@ -8046,37 +8053,31 @@ gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
/* For functions that return a class array conv_expr_descriptor is not
able to get the descriptor right. Therefore this special case. */
gfc_conv_expr_reference (&argse, e);
- argse.expr = gfc_build_addr_expr (NULL_TREE,
- gfc_class_data_get (argse.expr));
+ argse.expr = gfc_class_data_get (argse.expr);
}
else if (sym && sym->backend_decl)
{
gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (sym->backend_decl)));
- argse.expr = sym->backend_decl;
- argse.expr = gfc_build_addr_expr (NULL_TREE,
- gfc_class_data_get (argse.expr));
+ argse.expr = gfc_class_data_get (sym->backend_decl);
}
else
- {
- argse.want_pointer = 1;
- gfc_conv_expr_descriptor (&argse, actual->expr);
- }
+ gfc_conv_expr_descriptor (&argse, actual->expr);
gfc_add_block_to_block (&se->pre, &argse.pre);
gfc_add_block_to_block (&se->post, &argse.post);
- arg1 = gfc_evaluate_now (argse.expr, &se->pre);
-
- /* Build the call to size0. */
- fncall0 = build_call_expr_loc (input_location,
- gfor_fndecl_size0, 1, arg1);
+ arg1 = argse.expr;
actual = actual->next;
-
if (actual->expr)
{
+ stmtblock_t block;
+ gfc_init_block (&block);
gfc_init_se (&argse, NULL);
gfc_conv_expr_type (&argse, actual->expr,
gfc_array_index_type);
- gfc_add_block_to_block (&se->pre, &argse.pre);
+ gfc_add_block_to_block (&block, &argse.pre);
+ tree tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
+ argse.expr, gfc_index_one_node);
+ size = gfc_tree_array_size (&block, arg1, e, tmp);
/* Unusually, for an intrinsic, size does not exclude
an optional arg2, so we must test for it. */
@@ -8084,59 +8085,35 @@ gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
&& actual->expr->symtree->n.sym->attr.dummy
&& actual->expr->symtree->n.sym->attr.optional)
{
- tree tmp;
- /* Build the call to size1. */
- fncall1 = build_call_expr_loc (input_location,
- gfor_fndecl_size1, 2,
- arg1, argse.expr);
-
+ tree cond;
+ stmtblock_t block2;
+ gfc_init_block (&block2);
gfc_init_se (&argse, NULL);
argse.want_pointer = 1;
argse.data_not_needed = 1;
gfc_conv_expr (&argse, actual->expr);
gfc_add_block_to_block (&se->pre, &argse.pre);
- tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
- argse.expr, null_pointer_node);
- tmp = gfc_evaluate_now (tmp, &se->pre);
- se->expr = fold_build3_loc (input_location, COND_EXPR,
- pvoid_type_node, tmp, fncall1, fncall0);
+ cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+ argse.expr, null_pointer_node);
+ cond = gfc_evaluate_now (cond, &se->pre);
+ /* 'block2' contains the arg2 absent case, 'block' the arg2 present
+ case; size_var can be used in both blocks. */
+ tree size_var = gfc_tree_array_size (&block2, arg1, e, NULL_TREE);
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR,
+ TREE_TYPE (size_var), size_var, size);
+ gfc_add_expr_to_block (&block, tmp);
+ tmp = build3_v (COND_EXPR, cond, gfc_finish_block (&block),
+ gfc_finish_block (&block2));
+ gfc_add_expr_to_block (&se->pre, tmp);
+ size = size_var;
}
else
- {
- se->expr = NULL_TREE;
- argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
- gfc_array_index_type,
- argse.expr, gfc_index_one_node);
- }
- }
- else if (expr->value.function.actual->expr->rank == 1)
- {
- argse.expr = gfc_index_zero_node;
- se->expr = NULL_TREE;
+ gfc_add_block_to_block (&se->pre, &block);
}
else
- se->expr = fncall0;
-
- if (se->expr == NULL_TREE)
- {
- tree ubound, lbound;
-
- arg1 = build_fold_indirect_ref_loc (input_location,
- arg1);
- ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
- lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
- se->expr = fold_build2_loc (input_location, MINUS_EXPR,
- gfc_array_index_type, ubound, lbound);
- se->expr = fold_build2_loc (input_location, PLUS_EXPR,
- gfc_array_index_type,
- se->expr, gfc_index_one_node);
- se->expr = fold_build2_loc (input_location, MAX_EXPR,
- gfc_array_index_type, se->expr,
- gfc_index_zero_node);
- }
-
+ size = gfc_tree_array_size (&se->pre, arg1, e, NULL_TREE);
type = gfc_typenode_for_spec (&expr->ts);
- se->expr = convert (type, se->expr);
+ se->expr = convert (type, size);
}
@@ -8887,50 +8864,63 @@ caf_this_image_ref (gfc_ref *ref)
static void
gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
{
- gfc_actual_arglist *arg1;
gfc_se arg1se;
tree tmp;
- symbol_attribute caf_attr;
+ bool coindexed_caf_comp = false;
+ gfc_expr *e = expr->value.function.actual->expr;
gfc_init_se (&arg1se, NULL);
- arg1 = expr->value.function.actual;
-
- if (arg1->expr->ts.type == BT_CLASS)
+ if (e->ts.type == BT_CLASS)
{
/* Make sure that class array expressions have both a _data
component reference and an array reference.... */
- if (CLASS_DATA (arg1->expr)->attr.dimension)
- gfc_add_class_array_ref (arg1->expr);
+ if (CLASS_DATA (e)->attr.dimension)
+ gfc_add_class_array_ref (e);
/* .... whilst scalars only need the _data component. */
else
- gfc_add_data_component (arg1->expr);
+ gfc_add_data_component (e);
}
- /* When arg1 references an allocatable component in a coarray, then call
+ /* When 'e' references an allocatable component in a coarray, then call
the caf-library function caf_is_present (). */
- if (flag_coarray == GFC_FCOARRAY_LIB && arg1->expr->expr_type == EXPR_FUNCTION
- && arg1->expr->value.function.isym
- && arg1->expr->value.function.isym->id == GFC_ISYM_CAF_GET)
- caf_attr = gfc_caf_attr (arg1->expr->value.function.actual->expr);
- else
- gfc_clear_attr (&caf_attr);
- if (flag_coarray == GFC_FCOARRAY_LIB && caf_attr.codimension
- && !caf_this_image_ref (arg1->expr->value.function.actual->expr->ref))
- tmp = trans_caf_is_present (se, arg1->expr->value.function.actual->expr);
+ if (flag_coarray == GFC_FCOARRAY_LIB && e->expr_type == EXPR_FUNCTION
+ && e->value.function.isym
+ && e->value.function.isym->id == GFC_ISYM_CAF_GET)
+ {
+ e = e->value.function.actual->expr;
+ if (gfc_expr_attr (e).codimension)
+ {
+ /* Last partref is the coindexed coarray. As coarrays are collectively
+ (de)allocated, the allocation status must be the same as the one of
+ the local allocation. Convert to local access. */
+ for (gfc_ref *ref = e->ref; ref; ref = ref->next)
+ if (ref->type == REF_ARRAY && ref->u.ar.codimen)
+ {
+ for (int i = ref->u.ar.dimen;
+ i < ref->u.ar.dimen + ref->u.ar.codimen; ++i)
+ ref->u.ar.dimen_type[i] = DIMEN_THIS_IMAGE;
+ break;
+ }
+ }
+ else if (!caf_this_image_ref (e->ref))
+ coindexed_caf_comp = true;
+ }
+ if (coindexed_caf_comp)
+ tmp = trans_caf_is_present (se, e);
else
{
- if (arg1->expr->rank == 0)
+ if (e->rank == 0)
{
/* Allocatable scalar. */
arg1se.want_pointer = 1;
- gfc_conv_expr (&arg1se, arg1->expr);
+ gfc_conv_expr (&arg1se, e);
tmp = arg1se.expr;
}
else
{
/* Allocatable array. */
arg1se.descriptor_only = 1;
- gfc_conv_expr_descriptor (&arg1se, arg1->expr);
+ gfc_conv_expr_descriptor (&arg1se, e);
tmp = gfc_conv_descriptor_data_get (arg1se.expr);
}
@@ -8961,7 +8951,7 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr)
gfc_se arg2se;
tree tmp2;
tree tmp;
- tree nonzero_arraylen;
+ tree nonzero_arraylen = NULL_TREE;
gfc_ss *ss;
bool scalar;
@@ -9061,14 +9051,16 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr)
{
tmp = gfc_conv_descriptor_rank (arg1se.expr);
tmp = fold_build2_loc (input_location, MINUS_EXPR,
- TREE_TYPE (tmp), tmp, gfc_index_one_node);
+ TREE_TYPE (tmp), tmp,
+ build_int_cst (TREE_TYPE (tmp), 1));
}
else
tmp = gfc_rank_cst[arg1->expr->rank - 1];
tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
- nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
- logical_type_node, tmp,
- build_int_cst (TREE_TYPE (tmp), 0));
+ if (arg2->expr->rank != 0)
+ nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node, tmp,
+ build_int_cst (TREE_TYPE (tmp), 0));
/* A pointer to an array, call library function _gfor_associated. */
arg1se.want_pointer = 1;
@@ -9078,16 +9070,26 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr)
arg2se.want_pointer = 1;
arg2se.force_no_tmp = 1;
- gfc_conv_expr_descriptor (&arg2se, arg2->expr);
+ if (arg2->expr->rank != 0)
+ gfc_conv_expr_descriptor (&arg2se, arg2->expr);
+ else
+ {
+ gfc_conv_expr (&arg2se, arg2->expr);
+ arg2se.expr
+ = gfc_conv_scalar_to_descriptor (&arg2se, arg2se.expr,
+ gfc_expr_attr (arg2->expr));
+ arg2se.expr = gfc_build_addr_expr (NULL_TREE, arg2se.expr);
+ }
gfc_add_block_to_block (&se->pre, &arg2se.pre);
gfc_add_block_to_block (&se->post, &arg2se.post);
se->expr = build_call_expr_loc (input_location,
gfor_fndecl_associated, 2,
arg1se.expr, arg2se.expr);
se->expr = convert (logical_type_node, se->expr);
- se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
- logical_type_node, se->expr,
- nonzero_arraylen);
+ if (arg2->expr->rank != 0)
+ se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+ logical_type_node, se->expr,
+ nonzero_arraylen);
}
/* If target is present zero character length pointers cannot
@@ -9124,21 +9126,14 @@ gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
a = expr->value.function.actual->expr;
b = expr->value.function.actual->next->expr;
- if (UNLIMITED_POLY (a))
- {
- tmp = gfc_class_vptr_get (a->symtree->n.sym->backend_decl);
- conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
- tmp, build_int_cst (TREE_TYPE (tmp), 0));
- }
-
- if (UNLIMITED_POLY (b))
+ bool unlimited_poly_a = UNLIMITED_POLY (a);
+ bool unlimited_poly_b = UNLIMITED_POLY (b);
+ if (unlimited_poly_a)
{
- tmp = gfc_class_vptr_get (b->symtree->n.sym->backend_decl);
- condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
- tmp, build_int_cst (TREE_TYPE (tmp), 0));
+ se1.want_pointer = 1;
+ gfc_add_vptr_component (a);
}
-
- if (a->ts.type == BT_CLASS)
+ else if (a->ts.type == BT_CLASS)
{
gfc_add_vptr_component (a);
gfc_add_hash_component (a);
@@ -9147,7 +9142,12 @@ gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
a->ts.u.derived->hash_value);
- if (b->ts.type == BT_CLASS)
+ if (unlimited_poly_b)
+ {
+ se2.want_pointer = 1;
+ gfc_add_vptr_component (b);
+ }
+ else if (b->ts.type == BT_CLASS)
{
gfc_add_vptr_component (b);
gfc_add_hash_component (b);
@@ -9159,6 +9159,22 @@ gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
gfc_conv_expr (&se1, a);
gfc_conv_expr (&se2, b);
+ if (unlimited_poly_a)
+ {
+ conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+ se1.expr,
+ build_int_cst (TREE_TYPE (se1.expr), 0));
+ se1.expr = gfc_vptr_hash_get (se1.expr);
+ }
+
+ if (unlimited_poly_b)
+ {
+ condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+ se2.expr,
+ build_int_cst (TREE_TYPE (se2.expr), 0));
+ se2.expr = gfc_vptr_hash_get (se2.expr);
+ }
+
tmp = fold_build2_loc (input_location, EQ_EXPR,
logical_type_node, se1.expr,
fold_convert (TREE_TYPE (se1.expr), se2.expr));
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 4ca2c3f..d234d1b 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -3804,6 +3804,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
{
c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDER);
OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = clauses->order_unconstrained;
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = clauses->order_reproducible;
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
@@ -5895,6 +5896,8 @@ gfc_split_omp_clauses (gfc_code *code,
= code->ext.omp_clauses->order_concurrent;
clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_unconstrained
= code->ext.omp_clauses->order_unconstrained;
+ clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_reproducible
+ = code->ext.omp_clauses->order_reproducible;
}
if (mask & GFC_OMP_MASK_PARALLEL)
{
@@ -5951,6 +5954,8 @@ gfc_split_omp_clauses (gfc_code *code,
= code->ext.omp_clauses->order_concurrent;
clausesa[GFC_OMP_SPLIT_DO].order_unconstrained
= code->ext.omp_clauses->order_unconstrained;
+ clausesa[GFC_OMP_SPLIT_DO].order_reproducible
+ = code->ext.omp_clauses->order_reproducible;
}
if (mask & GFC_OMP_MASK_SIMD)
{
@@ -5969,6 +5974,8 @@ gfc_split_omp_clauses (gfc_code *code,
= code->ext.omp_clauses->order_concurrent;
clausesa[GFC_OMP_SPLIT_SIMD].order_unconstrained
= code->ext.omp_clauses->order_unconstrained;
+ clausesa[GFC_OMP_SPLIT_SIMD].order_reproducible
+ = code->ext.omp_clauses->order_reproducible;
/* And this is copied to all. */
clausesa[GFC_OMP_SPLIT_SIMD].if_expr
= code->ext.omp_clauses->if_expr;
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 11df186..a8ff473 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -1788,9 +1788,10 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
/* Go straight to the class data. */
if (sym2->attr.dummy && !sym2->attr.optional)
{
- class_decl = DECL_LANG_SPECIFIC (sym2->backend_decl) ?
- GFC_DECL_SAVED_DESCRIPTOR (sym2->backend_decl) :
- sym2->backend_decl;
+ class_decl = sym2->backend_decl;
+ if (DECL_LANG_SPECIFIC (class_decl)
+ && GFC_DECL_SAVED_DESCRIPTOR (class_decl))
+ class_decl = GFC_DECL_SAVED_DESCRIPTOR (class_decl);
if (POINTER_TYPE_P (TREE_TYPE (class_decl)))
class_decl = build_fold_indirect_ref_loc (input_location,
class_decl);
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 78578cf..fa3e865 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -438,7 +438,7 @@ tree gfc_class_vtab_def_init_get (tree);
tree gfc_class_vtab_copy_get (tree);
tree gfc_class_vtab_final_get (tree);
/* Get an accessor to the vtab's * field, when a vptr handle is present. */
-tree gfc_vtpr_hash_get (tree);
+tree gfc_vptr_hash_get (tree);
tree gfc_vptr_size_get (tree);
tree gfc_vptr_extends_get (tree);
tree gfc_vptr_def_init_get (tree);
@@ -518,6 +518,8 @@ tree gfc_string_to_single_character (tree len, tree str, int kind);
tree gfc_get_tree_for_caf_expr (gfc_expr *);
void gfc_get_caf_token_offset (gfc_se*, tree *, tree *, tree, tree, gfc_expr *);
tree gfc_caf_get_image_index (stmtblock_t *, gfc_expr *, tree);
+void gfc_simple_for_loop (stmtblock_t *, tree, tree, tree, enum tree_code, tree,
+ tree);
/* Find the decl containing the auxiliary variables for assigned variables. */
void gfc_conv_label_variable (gfc_se * se, gfc_expr * expr);
@@ -958,8 +960,6 @@ extern GTY(()) tree gfor_fndecl_convert_char1_to_char4;
extern GTY(()) tree gfor_fndecl_convert_char4_to_char1;
/* Other misc. runtime library functions. */
-extern GTY(()) tree gfor_fndecl_size0;
-extern GTY(()) tree gfor_fndecl_size1;
extern GTY(()) tree gfor_fndecl_iargc;
extern GTY(()) tree gfor_fndecl_kill;
extern GTY(()) tree gfor_fndecl_kill_sub;
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 31d4bf4..a77cfd9 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -3685,8 +3685,8 @@ write_types (outf_p output_header, type_p structures,
output_mangled_typename (output_header, s);
oprintf (output_header, "(X) do { \\\n");
oprintf (output_header,
- " if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix,
- s_id_for_tag);
+ " if ((intptr_t)(X) != 0) gt_%sx_%s (X);\\\n",
+ wtd->prefix, s_id_for_tag);
oprintf (output_header, " } while (0)\n");
for (opt = s->u.s.opt; opt; opt = opt->next)
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 6fea8a6..474d0f4 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -1001,9 +1001,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
return false;
scalar_int_mode mode;
- tree type = lang_hooks.types.type_for_size (ilen * 8, 1);
- if (type
- && is_a <scalar_int_mode> (TYPE_MODE (type), &mode)
+ if (int_mode_for_size (ilen * 8, 0).exists (&mode)
&& GET_MODE_SIZE (mode) * BITS_PER_UNIT == ilen * 8
&& have_insn_for (SET, mode)
/* If the destination pointer is not aligned we must be able
@@ -1013,6 +1011,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
|| (optab_handler (movmisalign_optab, mode)
!= CODE_FOR_nothing)))
{
+ tree type = build_nonstandard_integer_type (ilen * 8, 1);
tree srctype = type;
tree desttype = type;
if (src_align < GET_MODE_ALIGNMENT (mode))
diff --git a/gcc/gimple-isel.cc b/gcc/gimple-isel.cc
index 2c78a08..38e9093 100644
--- a/gcc/gimple-isel.cc
+++ b/gcc/gimple-isel.cc
@@ -260,10 +260,7 @@ gimple_expand_vec_cond_expr (gimple_stmt_iterator *gsi,
return gimple_build_call_internal (IFN_VCONDEQ, 5, op0a, op0b, op1,
op2, tcode_tree);
}
- }
- if (icode == CODE_FOR_nothing)
- {
gcc_assert (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (op0))
&& can_compute_op0
&& (get_vcond_mask_icode (mode, TYPE_MODE (TREE_TYPE (op0)))
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 0ca4a94..1cd1597 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -677,11 +677,18 @@ dump_gimple_assign (pretty_printer *buffer, const gassign *gs, int spc,
}
if (gimple_num_ops (gs) == 2)
- dump_unary_rhs (buffer, gs, spc, flags);
+ dump_unary_rhs (buffer, gs, spc,
+ ((flags & TDF_GIMPLE)
+ && gimple_assign_rhs_class (gs) != GIMPLE_SINGLE_RHS)
+ ? (flags | TDF_GIMPLE_VAL) : flags);
else if (gimple_num_ops (gs) == 3)
- dump_binary_rhs (buffer, gs, spc, flags);
+ dump_binary_rhs (buffer, gs, spc,
+ (flags & TDF_GIMPLE)
+ ? (flags | TDF_GIMPLE_VAL) : flags);
else if (gimple_num_ops (gs) == 4)
- dump_ternary_rhs (buffer, gs, spc, flags);
+ dump_ternary_rhs (buffer, gs, spc,
+ (flags & TDF_GIMPLE)
+ ? (flags | TDF_GIMPLE_VAL) : flags);
else
gcc_unreachable ();
if (!(flags & TDF_RHS_ONLY))
@@ -1085,11 +1092,15 @@ dump_gimple_cond (pretty_printer *buffer, const gcond *gs, int spc,
{
if (!(flags & TDF_RHS_ONLY))
pp_string (buffer, "if (");
- dump_generic_node (buffer, gimple_cond_lhs (gs), spc, flags, false);
+ dump_generic_node (buffer, gimple_cond_lhs (gs), spc,
+ flags | ((flags & TDF_GIMPLE) ? TDF_GIMPLE_VAL : TDF_NONE),
+ false);
pp_space (buffer);
pp_string (buffer, op_symbol_code (gimple_cond_code (gs)));
pp_space (buffer);
- dump_generic_node (buffer, gimple_cond_rhs (gs), spc, flags, false);
+ dump_generic_node (buffer, gimple_cond_rhs (gs), spc,
+ flags | ((flags & TDF_GIMPLE) ? TDF_GIMPLE_VAL : TDF_NONE),
+ false);
if (!(flags & TDF_RHS_ONLY))
{
edge_iterator ei;
diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index b856b21..7d99479 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -98,15 +98,16 @@ non_null_ref::adjust_range (irange &r, tree name, basic_block bb,
return false;
// We only care about the null / non-null property of pointers.
- if (!POINTER_TYPE_P (TREE_TYPE (name)) || r.zero_p () || r.nonzero_p ())
+ if (!POINTER_TYPE_P (TREE_TYPE (name)))
+ return false;
+ if (r.undefined_p () || r.lower_bound () != 0 || r.upper_bound () == 0)
return false;
-
// Check if pointers have any non-null dereferences.
if (non_null_deref_p (name, bb, search_dom))
{
- int_range<2> nz;
- nz.set_nonzero (TREE_TYPE (name));
- r.intersect (nz);
+ // Remove zero from the range.
+ unsigned prec = TYPE_PRECISION (TREE_TYPE (name));
+ r.intersect (wi::one (prec), wi::max_value (prec, UNSIGNED));
return true;
}
return false;
@@ -750,7 +751,8 @@ temporal_cache::set_always_current (tree name)
// --------------------------------------------------------------------------
-ranger_cache::ranger_cache ()
+ranger_cache::ranger_cache (int not_executable_flag)
+ : m_gori (not_executable_flag)
{
m_workback.create (0);
m_workback.safe_grow_cleared (last_basic_block_for_fn (cfun));
diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h
index 3b55673..4937a0b 100644
--- a/gcc/gimple-range-cache.h
+++ b/gcc/gimple-range-cache.h
@@ -92,7 +92,7 @@ private:
class ranger_cache : public range_query
{
public:
- ranger_cache ();
+ ranger_cache (int not_executable_flag);
~ranger_cache ();
virtual bool range_of_expr (irange &r, tree name, gimple *stmt);
diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc
index d11153e..afffc8d 100644
--- a/gcc/gimple-range-edge.cc
+++ b/gcc/gimple-range-edge.cc
@@ -65,9 +65,10 @@ gcond_edge_range (irange &r, edge e)
}
-gimple_outgoing_range::gimple_outgoing_range ()
+gimple_outgoing_range::gimple_outgoing_range (int max_sw_edges)
{
m_edge_table = NULL;
+ m_max_edges = max_sw_edges;
}
@@ -192,6 +193,10 @@ gimple_outgoing_range::edge_range_p (irange &r, edge e)
return s;
}
+ // Only process switches if it within the size limit.
+ if (EDGE_COUNT (e->src->succs) > (unsigned)m_max_edges)
+ return NULL;
+
gcc_checking_assert (is_a<gswitch *> (s));
gswitch *sw = as_a<gswitch *> (s);
tree type = TREE_TYPE (gimple_switch_index (sw));
diff --git a/gcc/gimple-range-edge.h b/gcc/gimple-range-edge.h
index 87b4124..03e8e82 100644
--- a/gcc/gimple-range-edge.h
+++ b/gcc/gimple-range-edge.h
@@ -38,13 +38,14 @@ along with GCC; see the file COPYING3. If not see
class gimple_outgoing_range
{
public:
- gimple_outgoing_range ();
+ gimple_outgoing_range (int max_sw_edges = INT_MAX);
~gimple_outgoing_range ();
gimple *edge_range_p (irange &r, edge e);
private:
void calc_switch_ranges (gswitch *sw);
bool get_edge_range (irange &r, gimple *s, edge e);
+ int m_max_edges;
hash_map<edge, irange *> *m_edge_table;
irange_allocator m_range_allocator;
};
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index d7fa0f2..ed2fbe1 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -360,12 +360,9 @@ adjust_pointer_diff_expr (irange &res, const gimple *diff_stmt)
&& integer_zerop (gimple_call_arg (call, 1)))
{
tree max = vrp_val_max (ptrdiff_type_node);
- wide_int wmax = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max)));
- tree expr_type = gimple_range_type (diff_stmt);
- tree range_min = build_zero_cst (expr_type);
- tree range_max = wide_int_to_tree (expr_type, wmax - 1);
- int_range<2> r (range_min, range_max);
- res.intersect (r);
+ unsigned prec = TYPE_PRECISION (TREE_TYPE (max));
+ wide_int wmaxm1 = wi::to_wide (max, prec) - 1;
+ res.intersect (wi::zero (prec), wmaxm1);
}
}
@@ -405,9 +402,8 @@ adjust_imagpart_expr (irange &res, const gimple *stmt)
tree cst = gimple_assign_rhs1 (def_stmt);
if (TREE_CODE (cst) == COMPLEX_CST)
{
- tree imag = TREE_IMAGPART (cst);
- int_range<2> tmp (imag, imag);
- res.intersect (tmp);
+ wide_int imag = wi::to_wide (TREE_IMAGPART (cst));
+ res.intersect (imag, imag);
}
}
}
@@ -650,7 +646,9 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
src.register_relation (s, rel, lhs, op2);
}
}
- else if (is_a<gcond *> (s))
+ // Check for an existing BB, as we maybe asked to fold an
+ // artificial statement not in the CFG.
+ else if (is_a<gcond *> (s) && gimple_bb (s))
{
basic_block bb = gimple_bb (s);
edge e0 = EDGE_SUCC (bb, 0);
@@ -824,9 +822,7 @@ fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src)
}
// If SCEV is available, query if this PHI has any knonwn values.
- if (dom_info_available_p (CDI_DOMINATORS)
- && scev_initialized_p ()
- && !POINTER_TYPE_P (TREE_TYPE (phi_def)))
+ if (scev_initialized_p () && !POINTER_TYPE_P (TREE_TYPE (phi_def)))
{
value_range loop_range;
class loop *l = loop_containing_stmt (phi);
@@ -1358,6 +1354,10 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s,
range_operator *handler1 = gimple_range_handler (SSA_NAME_DEF_STMT (ssa1));
range_operator *handler2 = gimple_range_handler (SSA_NAME_DEF_STMT (ssa2));
+ // If either handler is not present, no relation is found.
+ if (!handler1 || !handler2)
+ return;
+
int_range<2> bool_one (boolean_true_node, boolean_true_node);
relation_kind relation1 = handler1->op1_op2_relation (bool_one);
@@ -1404,10 +1404,6 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
range_operator *handler;
basic_block bb = gimple_bb (s);
- // We may get asked to fold an artificial statement not in the CFG.
- if (!bb)
- return;
-
if (e0)
{
// If this edge is never taken, ignore it.
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index f5a3528..6946fa6 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -565,6 +565,9 @@ gori_map::calculate_gori (basic_block bb)
}
else
{
+ // Do not process switches if they are too large.
+ if (EDGE_COUNT (bb->succs) > (unsigned)param_evrp_switch_limit)
+ return;
gswitch *gs = as_a<gswitch *>(stmt);
name = gimple_range_ssa_p (gimple_switch_index (gs));
maybe_add_gori (name, gimple_bb (stmt));
@@ -634,8 +637,10 @@ debug (gori_map &g)
// Construct a gori_compute object.
-gori_compute::gori_compute () : tracer ("GORI ")
+gori_compute::gori_compute (int not_executable_flag)
+ : outgoing (param_evrp_switch_limit), tracer ("GORI ")
{
+ m_not_executable_flag = not_executable_flag;
// Create a boolean_type true and false range.
m_bool_zero = int_range<2> (boolean_false_node, boolean_false_node);
m_bool_one = int_range<2> (boolean_true_node, boolean_true_node);
@@ -1214,7 +1219,7 @@ gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name,
int_range_max lhs;
unsigned idx;
- if ((e->flags & EDGE_EXECUTABLE) == 0)
+ if ((e->flags & m_not_executable_flag))
{
r.set_undefined ();
if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h
index 688468c..ec0b951 100644
--- a/gcc/gimple-range-gori.h
+++ b/gcc/gimple-range-gori.h
@@ -147,12 +147,16 @@ private:
// expr_range_in_bb is simply a wrapper which calls ssa_range_in_bb for
// SSA_NAMES and otherwise simply calculates the range of the expression.
//
+// The constructor takes a flag value to use on edges to check for the
+// NON_EXECUTABLE_EDGE property. The zero default means no flag is checked.
+// All value requests from NON_EXECUTABLE_EDGE edges are returned UNDEFINED.
+//
// The remaining routines are internal use only.
class gori_compute : public gori_map
{
public:
- gori_compute ();
+ gori_compute (int not_executable_flag = 0);
bool outgoing_edge_range_p (irange &r, edge e, tree name, range_query &q);
bool has_edge_range_p (tree name, edge e = NULL);
void dump (FILE *f);
@@ -181,6 +185,7 @@ private:
gimple_outgoing_range outgoing; // Edge values for COND_EXPR & SWITCH_EXPR.
range_tracer tracer;
+ int m_not_executable_flag;
};
// These routines provide a GIMPLE interface to the range-ops code.
diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
index e65c799..422abfd 100644
--- a/gcc/gimple-range-path.cc
+++ b/gcc/gimple-range-path.cc
@@ -34,14 +34,11 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-iterator.h"
// Internal construct to help facilitate debugging of solver.
-#define DEBUG_SOLVER (0 && dump_file)
+#define DEBUG_SOLVER (dump_file && dump_flags & TDF_THREADING)
path_range_query::path_range_query (gimple_ranger &ranger, bool resolve)
: m_ranger (ranger)
{
- if (DEBUG_SOLVER)
- fprintf (dump_file, "\n*********** path_range_query ******************\n");
-
m_cache = new ssa_global_cache;
m_has_cache_entry = BITMAP_ALLOC (NULL);
m_path = NULL;
@@ -139,14 +136,23 @@ path_range_query::range_on_path_entry (irange &r, tree name)
{
int_range_max tmp;
basic_block entry = entry_bb ();
+ bool changed = false;
+
r.set_undefined ();
for (unsigned i = 0; i < EDGE_COUNT (entry->preds); ++i)
{
edge e = EDGE_PRED (entry, i);
if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun)
&& m_ranger.range_on_edge (tmp, e, name))
- r.union_ (tmp);
+ {
+ r.union_ (tmp);
+ changed = true;
+ }
}
+
+ // Make sure we don't return UNDEFINED by mistake.
+ if (!changed)
+ r.set_varying (TREE_TYPE (name));
}
// Return the range of NAME at the end of the path being analyzed.
@@ -163,10 +169,6 @@ path_range_query::internal_range_of_expr (irange &r, tree name, gimple *stmt)
if (m_resolve && defined_outside_path (name))
{
range_on_path_entry (r, name);
-
- if (r.varying_p ())
- improve_range_with_equivs (r, name);
-
set_cache (r, name);
return true;
}
@@ -177,9 +179,6 @@ path_range_query::internal_range_of_expr (irange &r, tree name, gimple *stmt)
if (TREE_CODE (name) == SSA_NAME)
r.intersect (gimple_range_global (name));
- if (m_resolve && r.varying_p ())
- improve_range_with_equivs (r, name);
-
set_cache (r, name);
return true;
}
@@ -201,33 +200,6 @@ path_range_query::range_of_expr (irange &r, tree name, gimple *stmt)
return false;
}
-// Improve the range of NAME with the range of any of its equivalences.
-
-void
-path_range_query::improve_range_with_equivs (irange &r, tree name)
-{
- if (TREE_CODE (name) != SSA_NAME)
- return;
-
- basic_block entry = entry_bb ();
- relation_oracle *oracle = m_ranger.oracle ();
-
- if (const bitmap_head *equivs = oracle->equiv_set (name, entry))
- {
- int_range_max t;
- bitmap_iterator bi;
- unsigned i;
-
- EXECUTE_IF_SET_IN_BITMAP (equivs, 0, i, bi)
- if (i != SSA_NAME_VERSION (name) && r.varying_p ())
- {
- tree equiv = ssa_name (i);
- range_on_path_entry (t, equiv);
- r.intersect (t);
- }
- }
-}
-
bool
path_range_query::unreachable_path_p ()
{
@@ -330,11 +302,11 @@ path_range_query::range_defined_in_block (irange &r, tree name, basic_block bb)
return true;
}
-// Precompute ranges defined in the current block, or ranges
-// that are exported on an edge to the next block.
+// Compute ranges defined in the current block, or exported to the
+// next block.
void
-path_range_query::precompute_ranges_in_block (basic_block bb)
+path_range_query::compute_ranges_in_block (basic_block bb)
{
bitmap_iterator bi;
int_range_max r, cached_range;
@@ -489,15 +461,18 @@ path_range_query::add_copies_to_imports ()
}
}
-// Precompute the ranges for IMPORTS along PATH.
+// Compute the ranges for IMPORTS along PATH.
//
// IMPORTS are the set of SSA names, any of which could potentially
// change the value of the final conditional in PATH.
void
-path_range_query::precompute_ranges (const vec<basic_block> &path,
- const bitmap_head *imports)
+path_range_query::compute_ranges (const vec<basic_block> &path,
+ const bitmap_head *imports)
{
+ if (DEBUG_SOLVER)
+ fprintf (dump_file, "\n*********** path_range_query ******************\n");
+
set_path (path);
bitmap_copy (m_imports, imports);
m_undefined_path = false;
@@ -505,13 +480,13 @@ path_range_query::precompute_ranges (const vec<basic_block> &path,
if (m_resolve)
{
add_copies_to_imports ();
- m_oracle->reset_path ();
- precompute_relations (path);
+ get_path_oracle ()->reset_path ();
+ compute_relations (path);
}
if (DEBUG_SOLVER)
{
- fprintf (dump_file, "\npath_range_query: precompute_ranges for path: ");
+ fprintf (dump_file, "\npath_range_query: compute_ranges for path: ");
for (unsigned i = path.length (); i > 0; --i)
{
basic_block bb = path[i - 1];
@@ -538,7 +513,7 @@ path_range_query::precompute_ranges (const vec<basic_block> &path,
bitmap_set_bit (m_imports, SSA_NAME_VERSION (name));
}
- precompute_ranges_in_block (bb);
+ compute_ranges_in_block (bb);
adjust_for_non_null_uses (bb);
if (at_exit ())
@@ -645,12 +620,12 @@ path_range_query::range_of_stmt (irange &r, gimple *stmt, tree)
return true;
}
-// Precompute relations on a path. This involves two parts: relations
+// Compute relations on a path. This involves two parts: relations
// along the conditionals joining a path, and relations determined by
// examining PHIs.
void
-path_range_query::precompute_relations (const vec<basic_block> &path)
+path_range_query::compute_relations (const vec<basic_block> &path)
{
if (!dom_info_available_p (CDI_DOMINATORS))
return;
@@ -662,7 +637,7 @@ path_range_query::precompute_relations (const vec<basic_block> &path)
basic_block bb = path[i - 1];
gimple *stmt = last_stmt (bb);
- precompute_phi_relations (bb, prev);
+ compute_phi_relations (bb, prev);
// Compute relations in outgoing edges along the path. Skip the
// final conditional which we don't know yet.
@@ -674,30 +649,30 @@ path_range_query::precompute_relations (const vec<basic_block> &path)
basic_block next = path[i - 2];
int_range<2> r;
gcond *cond = as_a<gcond *> (stmt);
+ edge e0 = EDGE_SUCC (bb, 0);
+ edge e1 = EDGE_SUCC (bb, 1);
- if (EDGE_SUCC (bb, 0)->dest == next)
- gcond_edge_range (r, EDGE_SUCC (bb, 0));
- else if (EDGE_SUCC (bb, 1)->dest == next)
- gcond_edge_range (r, EDGE_SUCC (bb, 1));
+ if (e0->dest == next)
+ gcond_edge_range (r, e0);
+ else if (e1->dest == next)
+ gcond_edge_range (r, e1);
else
gcc_unreachable ();
- edge e0 = EDGE_SUCC (bb, 0);
- edge e1 = EDGE_SUCC (bb, 1);
src.register_outgoing_edges (cond, r, e0, e1);
}
prev = bb;
}
}
-// Precompute relations for each PHI in BB. For example:
+// Compute relations for each PHI in BB. For example:
//
// x_5 = PHI<y_9(5),...>
//
// If the path flows through BB5, we can register that x_5 == y_9.
void
-path_range_query::precompute_phi_relations (basic_block bb, basic_block prev)
+path_range_query::compute_phi_relations (basic_block bb, basic_block prev)
{
if (prev == NULL)
return;
diff --git a/gcc/gimple-range-path.h b/gcc/gimple-range-path.h
index 6f81f21..5f4e73a 100644
--- a/gcc/gimple-range-path.h
+++ b/gcc/gimple-range-path.h
@@ -26,9 +26,6 @@ along with GCC; see the file COPYING3. If not see
// will calculate the range of an SSA or STMT as if the BBs in the
// path would have been executed in order.
//
-// Only SSA names passed in IMPORTS are precomputed, and can be
-// queried.
-//
// Note that the blocks are in reverse order, thus the exit block is
// path[0].
@@ -37,12 +34,10 @@ class path_range_query : public range_query
public:
path_range_query (class gimple_ranger &ranger, bool resolve);
virtual ~path_range_query ();
- void precompute_ranges (const vec<basic_block> &path,
- const bitmap_head *imports);
+ void compute_ranges (const vec<basic_block> &, const bitmap_head *imports);
bool range_of_expr (irange &r, tree name, gimple * = NULL) override;
bool range_of_stmt (irange &r, gimple *, tree name = NULL) override;
bool unreachable_path_p ();
- path_oracle *oracle () { return m_oracle; }
void dump (FILE *) override;
void debug ();
@@ -50,20 +45,20 @@ private:
bool internal_range_of_expr (irange &r, tree name, gimple *);
bool defined_outside_path (tree name);
void range_on_path_entry (irange &r, tree name);
+ path_oracle *get_path_oracle () { return (path_oracle *)m_oracle; }
// Cache manipulation.
void set_cache (const irange &r, tree name);
bool get_cache (irange &r, tree name);
void clear_cache (tree name);
- // Methods to precompute ranges for the given path.
+ // Methods to compute ranges for the given path.
bool range_defined_in_block (irange &, tree name, basic_block bb);
- void precompute_ranges_in_block (basic_block bb);
+ void compute_ranges_in_block (basic_block bb);
void adjust_for_non_null_uses (basic_block bb);
void ssa_range_in_phi (irange &r, gphi *phi);
- void precompute_relations (const vec<basic_block> &);
- void precompute_phi_relations (basic_block bb, basic_block prev);
- void improve_range_with_equivs (irange &r, tree name);
+ void compute_relations (const vec<basic_block> &);
+ void compute_phi_relations (basic_block bb, basic_block prev);
void add_copies_to_imports ();
bool add_to_imports (tree name, bitmap imports);
@@ -90,7 +85,6 @@ private:
auto_bitmap m_imports;
gimple_ranger &m_ranger;
non_null_ref m_non_null;
- path_oracle *m_oracle;
// Current path position.
unsigned m_pos;
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index 625d136..6eb3f71 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -34,15 +34,29 @@ along with GCC; see the file COPYING3. If not see
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
#include "gimple-range.h"
-#include "domwalk.h"
-gimple_ranger::gimple_ranger () : tracer ("")
+gimple_ranger::gimple_ranger () :
+ non_executable_edge_flag (cfun),
+ m_cache (non_executable_edge_flag),
+ tracer ("")
{
// If the cache has a relation oracle, use it.
m_oracle = m_cache.oracle ();
if (dump_file && (param_evrp_mode & EVRP_MODE_TRACE))
tracer.enable_trace ();
- set_all_edges_as_executable (cfun);
+
+ // Ensure the not_executable flag is clear everywhere.
+ if (flag_checking)
+ {
+ basic_block bb;
+ FOR_ALL_BB_FN (bb, cfun)
+ {
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ gcc_checking_assert ((e->flags & non_executable_edge_flag) == 0);
+ }
+ }
}
bool
@@ -174,7 +188,7 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name)
}
// Check to see if the edge is executable.
- if ((e->flags & EDGE_EXECUTABLE) == 0)
+ if ((e->flags & non_executable_edge_flag))
{
r.set_undefined ();
if (idx)
@@ -398,6 +412,12 @@ gimple_ranger::dump (FILE *f)
m_cache.dump (f);
}
+void
+gimple_ranger::debug ()
+{
+ dump (stderr);
+}
+
/* Create a new ranger instance and associate it with function FUN.
Each call must be paired with a call to disable_ranger to release
resources. */
diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h
index eaebb9c5..0713af4 100644
--- a/gcc/gimple-range.h
+++ b/gcc/gimple-range.h
@@ -55,7 +55,9 @@ public:
void export_global_ranges ();
inline gori_compute &gori () { return m_cache.m_gori; }
virtual void dump (FILE *f) OVERRIDE;
+ void debug ();
void dump_bb (FILE *f, basic_block bb);
+ auto_edge_flag non_executable_edge_flag;
protected:
bool fold_range_internal (irange &r, gimple *s, tree name);
ranger_cache m_cache;
diff --git a/gcc/gimple-ssa-evrp-analyze.h b/gcc/gimple-ssa-evrp-analyze.h
index 0a70a1e..4cf82e6 100644
--- a/gcc/gimple-ssa-evrp-analyze.h
+++ b/gcc/gimple-ssa-evrp-analyze.h
@@ -38,13 +38,6 @@ class evrp_range_analyzer : public vr_values
/* Record a new unwindable range. */
void push_value_range (tree var, value_range_equiv *vr);
- /* A bit of a wart. This should ideally go away. */
- void vrp_visit_cond_stmt (gcond *cond, edge *e)
- {
- simplify_using_ranges simpl (this);
- simpl.vrp_visit_cond_stmt (cond, e);
- }
-
private:
DISABLE_COPY_AND_ASSIGN (evrp_range_analyzer);
diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c
index 254542e..437f194 100644
--- a/gcc/gimple-ssa-evrp.c
+++ b/gcc/gimple-ssa-evrp.c
@@ -121,7 +121,7 @@ public:
rvrp_folder () : substitute_and_fold_engine (), m_simplifier ()
{
m_ranger = enable_ranger (cfun);
- m_simplifier.set_range_query (m_ranger);
+ m_simplifier.set_range_query (m_ranger, m_ranger->non_executable_edge_flag);
m_pta = new pointer_equiv_analyzer (m_ranger);
}
@@ -205,12 +205,16 @@ public:
if (evrp_first)
{
first = &m_range_analyzer;
+ first_exec_flag = 0;
second = m_ranger;
+ second_exec_flag = m_ranger->non_executable_edge_flag;
}
else
{
first = m_ranger;
+ first_exec_flag = m_ranger->non_executable_edge_flag;
second = &m_range_analyzer;
+ second_exec_flag = 0;
}
m_pta = new pointer_equiv_analyzer (m_ranger);
}
@@ -227,11 +231,11 @@ public:
bool fold_stmt (gimple_stmt_iterator *gsi) OVERRIDE
{
- simplifier.set_range_query (first);
+ simplifier.set_range_query (first, first_exec_flag);
if (simplifier.simplify (gsi))
return true;
- simplifier.set_range_query (second);
+ simplifier.set_range_query (second, second_exec_flag);
if (simplifier.simplify (gsi))
{
if (dump_file)
@@ -267,7 +271,9 @@ private:
DISABLE_COPY_AND_ASSIGN (hybrid_folder);
gimple_ranger *m_ranger;
range_query *first;
+ int first_exec_flag;
range_query *second;
+ int second_exec_flag;
pointer_equiv_analyzer *m_pta;
tree choose_value (tree evrp_val, tree ranger_val);
};
diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c
index 4fc7125..d59cea8 100644
--- a/gcc/gimple-ssa-warn-alloca.c
+++ b/gcc/gimple-ssa-warn-alloca.c
@@ -221,10 +221,9 @@ alloca_call_type (gimple *stmt, bool is_vla)
&& !r.varying_p ())
{
// The invalid bits are anything outside of [0, MAX_SIZE].
- static int_range<2> invalid_range (build_int_cst (size_type_node, 0),
- build_int_cst (size_type_node,
- max_size),
- VR_ANTI_RANGE);
+ int_range<2> invalid_range (build_int_cst (size_type_node, 0),
+ build_int_cst (size_type_node, max_size),
+ VR_ANTI_RANGE);
r.intersect (invalid_range);
if (r.undefined_p ())
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 9163dcd..d8e4b13 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1825,6 +1825,8 @@ static bool
is_var_need_auto_init (tree decl)
{
if (auto_var_p (decl)
+ && (TREE_CODE (decl) != VAR_DECL
+ || !DECL_HARD_REGISTER (decl))
&& (flag_auto_var_init > AUTO_INIT_UNINITIALIZED)
&& (!lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl)))
&& !is_empty_type (TREE_TYPE (decl)))
@@ -1870,6 +1872,12 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
{
tree init = DECL_INITIAL (decl);
bool is_vla = false;
+ /* Check whether a decl has FE created VALUE_EXPR here BEFORE
+ gimplify_vla_decl creates VALUE_EXPR for a vla decl.
+ If the decl has VALUE_EXPR that was created by FE (usually
+ C++FE), it's a proxy varaible, and FE already initialized
+ the VALUE_EXPR of it, we should not initialize it anymore. */
+ bool decl_had_value_expr_p = DECL_HAS_VALUE_EXPR_P (decl);
poly_uint64 size;
if (!poly_int_tree_p (DECL_SIZE_UNIT (decl), &size)
@@ -1932,7 +1940,8 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
/* When there is no explicit initializer, if the user requested,
We should insert an artifical initializer for this automatic
variable. */
- else if (is_var_need_auto_init (decl))
+ else if (is_var_need_auto_init (decl)
+ && !decl_had_value_expr_p)
{
gimple_add_init_for_auto_var (decl,
flag_auto_var_init,
@@ -6232,6 +6241,9 @@ gimplify_save_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
gcc_assert (TREE_CODE (*expr_p) == SAVE_EXPR);
val = TREE_OPERAND (*expr_p, 0);
+ if (TREE_TYPE (val) == error_mark_node)
+ return GS_ERROR;
+
/* If the SAVE_EXPR has not been resolved, then evaluate it once. */
if (!SAVE_EXPR_RESOLVED_P (*expr_p))
{
@@ -10192,7 +10204,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
if (outer_ctx)
omp_notice_variable (outer_ctx, decl, true);
if (check_non_private
- && region_type == ORT_WORKSHARE
+ && (region_type == ORT_WORKSHARE || code == OMP_SCOPE)
&& (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
|| decl == OMP_CLAUSE_DECL (c)
|| (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
@@ -10914,8 +10926,12 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
*list_p = clause;
struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
gimplify_omp_ctxp = ctx->outer_context;
- lang_hooks.decls.omp_finish_clause (clause, pre_p,
- (ctx->region_type & ORT_ACC) != 0);
+ /* Don't call omp_finish_clause on implicitly added OMP_CLAUSE_PRIVATE
+ in simd. Those are only added for the local vars inside of simd body
+ and they don't need to be e.g. default constructible. */
+ if (code != OMP_CLAUSE_PRIVATE || ctx->region_type != ORT_SIMD)
+ lang_hooks.decls.omp_finish_clause (clause, pre_p,
+ (ctx->region_type & ORT_ACC) != 0);
if (gimplify_omp_ctxp)
for (; clause != chain; clause = OMP_CLAUSE_CHAIN (clause))
if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index 60ebb89..c17e3a4 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,8 @@
+2021-09-27 Martin Liska <mliska@suse.cz>
+
+ * go-lang.c (go_langhook_init_options_struct): Set also
+ x_flag_default_complex_method.
+
2021-06-29 Ian Lance Taylor <iant@golang.org>
* go-gcc.cc (Gcc_backend::static_chain_variable): Set
diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
index a01db8d..c3ae6f0 100644
--- a/gcc/go/go-lang.c
+++ b/gcc/go/go-lang.c
@@ -174,6 +174,7 @@ go_langhook_init_options_struct (struct gcc_options *opts)
/* Default to avoiding range issues for complex multiply and
divide. */
opts->x_flag_complex_method = 2;
+ opts->x_flag_default_complex_method = opts->x_flag_complex_method;
/* The builtin math functions should not set errno. */
opts->x_flag_errno_math = 0;
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index edfbe46..affba73 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-e3bfc0889237a5bb8aa7ae30e1cff14f90a5f941
+925ace70ac7426c3f8b5c0bfb75aa9601f071de4
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.h b/gcc/go/gofrontend/expressions.h
index 9f8f4e9..9348354 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -999,7 +999,9 @@ class Expression
determine_type_no_context();
// Return the current type of the expression. This may be changed
- // by determine_type.
+ // by determine_type. This should not be called before the lowering
+ // pass, unless the is_type_expression method returns true (i.e.,
+ // this is an EXPRESSION_TYPE).
Type*
type()
{ return this->do_type(); }
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index cd69250..0f66661 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -2259,7 +2259,7 @@ Named_object*
Type::build_equal_function(Gogo* gogo, Named_type* name, int64_t size,
Function_type* equal_fntype)
{
- std::pair<Type*, Named_object*> val(name != NULL ? name : this, NULL);
+ std::pair<Type*, Named_object*> val(name != NULL ? name : this, nullptr);
std::pair<Type_function::iterator, bool> ins =
Type::type_equal_functions_table.insert(val);
if (!ins.second)
@@ -6413,7 +6413,7 @@ Struct_type::interface_method_table(Interface_type* interface,
bool is_pointer)
{
std::pair<Struct_type*, Struct_type::Struct_method_table_pair*>
- val(this, NULL);
+ val(this, nullptr);
std::pair<Struct_type::Struct_method_tables::iterator, bool> ins =
Struct_type::struct_method_tables.insert(val);
@@ -11789,8 +11789,9 @@ Type::build_stub_methods(Gogo* gogo, const Type* type, const Methods* methods,
{
stub = gogo->start_function(stub_name, stub_type, false,
fntype->location());
- Type::build_one_stub_method(gogo, m, buf, stub_params,
- fntype->is_varargs(), location);
+ Type::build_one_stub_method(gogo, m, buf, receiver_type, stub_params,
+ fntype->is_varargs(), stub_results,
+ location);
gogo->finish_function(fntype->location());
if (type->named_type() == NULL && stub->is_function())
@@ -11810,16 +11811,20 @@ Type::build_stub_methods(Gogo* gogo, const Type* type, const Methods* methods,
void
Type::build_one_stub_method(Gogo* gogo, Method* method,
const char* receiver_name,
+ const Type* receiver_type,
const Typed_identifier_list* params,
bool is_varargs,
+ const Typed_identifier_list* results,
Location location)
{
Named_object* receiver_object = gogo->lookup(receiver_name, NULL);
go_assert(receiver_object != NULL);
Expression* expr = Expression::make_var_reference(receiver_object, location);
- expr = Type::apply_field_indexes(expr, method->field_indexes(), location);
- if (expr->type()->points_to() == NULL)
+ const Type* expr_type = receiver_type;
+ expr = Type::apply_field_indexes(expr, method->field_indexes(), location,
+ &expr_type);
+ if (expr_type->points_to() == NULL)
expr = Expression::make_unary(OPERATOR_AND, expr, location);
Expression_list* arguments;
@@ -11844,8 +11849,7 @@ Type::build_one_stub_method(Gogo* gogo, Method* method,
go_assert(func != NULL);
Call_expression* call = Expression::make_call(func, arguments, is_varargs,
location);
-
- gogo->add_statement(Statement::make_return_from_call(call, location));
+ Type::add_return_from_results(gogo, call, results, location);
}
// Build direct interface stub methods for TYPE as needed. METHODS
@@ -11954,8 +11958,9 @@ Type::build_direct_iface_stub_methods(Gogo* gogo, const Type* type,
{
stub = gogo->start_function(stub_name, stub_type, false,
fntype->location());
- Type::build_one_iface_stub_method(gogo, m, buf, stub_params,
- fntype->is_varargs(), loc);
+ Type::build_one_iface_stub_method(gogo, m, buf, stub_params,
+ fntype->is_varargs(), stub_results,
+ loc);
gogo->finish_function(fntype->location());
if (type->named_type() == NULL && stub->is_function())
@@ -11982,7 +11987,9 @@ void
Type::build_one_iface_stub_method(Gogo* gogo, Method* method,
const char* receiver_name,
const Typed_identifier_list* params,
- bool is_varargs, Location loc)
+ bool is_varargs,
+ const Typed_identifier_list* results,
+ Location loc)
{
Named_object* receiver_object = gogo->lookup(receiver_name, NULL);
go_assert(receiver_object != NULL);
@@ -12014,31 +12021,63 @@ Type::build_one_iface_stub_method(Gogo* gogo, Method* method,
go_assert(func != NULL);
Call_expression* call = Expression::make_call(func, arguments, is_varargs,
loc);
+ Type::add_return_from_results(gogo, call, results, loc);
+}
- gogo->add_statement(Statement::make_return_from_call(call, loc));
+// Build and add a return statement from a call expression and a list
+// of result parameters. All we need to know is the number of
+// results.
+
+void
+Type::add_return_from_results(Gogo* gogo, Call_expression* call,
+ const Typed_identifier_list* results,
+ Location loc)
+{
+ Statement* s;
+ if (results == NULL || results->empty())
+ s = Statement::make_statement(call, true);
+ else
+ {
+ Expression_list* vals = new Expression_list();
+ size_t rc = results->size();
+ if (rc == 1)
+ vals->push_back(call);
+ else
+ {
+ for (size_t i = 0; i < rc; ++i)
+ vals->push_back(Expression::make_call_result(call, i));
+ }
+ s = Statement::make_return_statement(vals, loc);
+ }
+
+ gogo->add_statement(s);
}
// Apply FIELD_INDEXES to EXPR. The field indexes have to be applied
-// in reverse order.
+// in reverse order. *PEXPR_TYPE maintains the type of EXPR; we use
+// this to avoid calling EXPR->type() before the lowering pass.
Expression*
Type::apply_field_indexes(Expression* expr,
const Method::Field_indexes* field_indexes,
- Location location)
+ Location location,
+ const Type** pexpr_type)
{
if (field_indexes == NULL)
return expr;
- expr = Type::apply_field_indexes(expr, field_indexes->next, location);
- Struct_type* stype = expr->type()->deref()->struct_type();
+ expr = Type::apply_field_indexes(expr, field_indexes->next, location,
+ pexpr_type);
+ const Type* expr_type = *pexpr_type;
+ const Struct_type* stype = expr_type->deref()->struct_type();
go_assert(stype != NULL
&& field_indexes->field_index < stype->field_count());
- if (expr->type()->struct_type() == NULL)
+ if (expr_type->struct_type() == NULL)
{
- go_assert(expr->type()->points_to() != NULL);
+ go_assert(expr_type->points_to()->struct_type() == stype);
expr = Expression::make_dereference(expr, Expression::NIL_CHECK_DEFAULT,
location);
- go_assert(expr->type()->struct_type() == stype);
}
+ *pexpr_type = stype->field(field_indexes->field_index)->type();
return Expression::make_field_reference(expr, field_indexes->field_index,
location);
}
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index 0c51806..a33453a 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -1355,8 +1355,9 @@ class Type
static void
build_one_stub_method(Gogo*, Method*, const char* receiver_name,
+ const Type* receiver_type,
const Typed_identifier_list*, bool is_varargs,
- Location);
+ const Typed_identifier_list*, Location);
// Build direct interface stub methods for a type.
static void
@@ -1364,12 +1365,16 @@ class Type
static void
build_one_iface_stub_method(Gogo*, Method*, const char*,
- const Typed_identifier_list*,
- bool, Location);
+ const Typed_identifier_list*, bool,
+ const Typed_identifier_list*, Location);
+
+ static void
+ add_return_from_results(Gogo*, Call_expression*,
+ const Typed_identifier_list*, Location);
static Expression*
apply_field_indexes(Expression*, const Method::Field_indexes*,
- Location);
+ Location, const Type**);
// Look for a field or method named NAME in TYPE.
static bool
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 8312d08..78db25b 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -3015,8 +3015,11 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt)
reg_lhs = true;
else
{
- rtx tem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
- reg_lhs = !MEM_P (tem);
+ tree lhs_base = lhs;
+ while (handled_component_p (lhs_base))
+ lhs_base = TREE_OPERAND (lhs_base, 0);
+ reg_lhs = (mem_ref_refers_to_non_mem_p (lhs_base)
+ || non_mem_decl_p (lhs_base));
}
if (!reg_lhs)
@@ -3037,16 +3040,16 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt)
}
else
{
- /* If this variable is in a register, use expand_assignment might
- generate better code. */
- tree init = build_zero_cst (var_type);
- unsigned HOST_WIDE_INT total_bytes
- = tree_to_uhwi (TYPE_SIZE_UNIT (var_type));
-
- if (init_type == AUTO_INIT_PATTERN)
+ /* If this variable is in a register use expand_assignment. */
+ tree init;
+ if (tree_fits_uhwi_p (var_size)
+ && (init_type == AUTO_INIT_PATTERN
+ || !is_gimple_reg_type (var_type)))
{
+ unsigned HOST_WIDE_INT total_bytes = tree_to_uhwi (var_size);
unsigned char *buf = (unsigned char *) xmalloc (total_bytes);
- memset (buf, INIT_PATTERN_VALUE, total_bytes);
+ memset (buf, (init_type == AUTO_INIT_PATTERN
+ ? INIT_PATTERN_VALUE : 0), total_bytes);
if (can_native_interpret_type_p (var_type))
init = native_interpret_expr (var_type, buf, total_bytes);
else
@@ -3054,10 +3057,14 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt)
tree itype = build_nonstandard_integer_type
(total_bytes * BITS_PER_UNIT, 1);
wide_int w = wi::from_buffer (buf, total_bytes);
- init = build1 (VIEW_CONVERT_EXPR, var_type,
- wide_int_to_tree (itype, w));
+ init = wide_int_to_tree (itype, w);
+ /* Pun the LHS to make sure its type has constant size. */
+ lhs = build1 (VIEW_CONVERT_EXPR, itype, lhs);
}
}
+ else
+ /* Use zero-init also for variable-length sizes. */
+ init = build_zero_cst (var_type);
expand_assignment (lhs, init, false);
}
diff --git a/gcc/ipa-modref-tree.h b/gcc/ipa-modref-tree.h
index 6a9ed5c..8e9b89b 100644
--- a/gcc/ipa-modref-tree.h
+++ b/gcc/ipa-modref-tree.h
@@ -110,8 +110,11 @@ struct GTY(()) modref_access_node
if (!a.parm_offset_known)
return false;
/* Accesses are never below parm_offset, so look
- for smaller offset. */
- if (!known_le (parm_offset, a.parm_offset))
+ for smaller offset.
+ If access ranges are known still allow merging
+ when bit offsets comparsion passes. */
+ if (!known_le (parm_offset, a.parm_offset)
+ && !range_info_useful_p ())
return false;
aoffset_adj = (a.parm_offset - parm_offset)
<< LOG2_BITS_PER_UNIT;
@@ -618,6 +621,7 @@ private:
found = true;
if (!found && n->merge (*a, false))
found = restart = true;
+ gcc_checking_assert (found || !a->merge (*n, false));
if (found)
{
accesses->unordered_remove (i);
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 1c69d97..443f21c 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -4428,19 +4428,33 @@ ipa_edge_args_sum_t::duplicate (cgraph_edge *src, cgraph_edge *dst,
dst_jf->value.constant.rdesc = NULL;
else if (src->caller == dst->caller)
{
- struct ipa_ref *ref;
- symtab_node *n = symtab_node_for_jfunc (src_jf);
- gcc_checking_assert (n);
- ref = src->caller->find_reference (n, src->call_stmt,
- src->lto_stmt_uid);
- gcc_checking_assert (ref);
- dst->caller->clone_reference (ref, ref->stmt);
-
- struct ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate ();
- dst_rdesc->cs = dst;
- dst_rdesc->refcount = src_rdesc->refcount;
- dst_rdesc->next_duplicate = NULL;
- dst_jf->value.constant.rdesc = dst_rdesc;
+ /* Creation of a speculative edge. If the source edge is the one
+ grabbing a reference, we must create a new (duplicate)
+ reference description. Otherwise they refer to the same
+ description corresponding to a reference taken in a function
+ src->caller is inlined to. In that case we just must
+ increment the refcount. */
+ if (src_rdesc->cs == src)
+ {
+ symtab_node *n = symtab_node_for_jfunc (src_jf);
+ gcc_checking_assert (n);
+ ipa_ref *ref
+ = src->caller->find_reference (n, src->call_stmt,
+ src->lto_stmt_uid);
+ gcc_checking_assert (ref);
+ dst->caller->clone_reference (ref, ref->stmt);
+
+ ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate ();
+ dst_rdesc->cs = dst;
+ dst_rdesc->refcount = src_rdesc->refcount;
+ dst_rdesc->next_duplicate = NULL;
+ dst_jf->value.constant.rdesc = dst_rdesc;
+ }
+ else
+ {
+ src_rdesc->refcount++;
+ dst_jf->value.constant.rdesc = src_rdesc;
+ }
}
else if (src_rdesc->cs == src)
{
diff --git a/gcc/ira-build.c b/gcc/ira-build.c
index 4212065..2a30efc 100644
--- a/gcc/ira-build.c
+++ b/gcc/ira-build.c
@@ -629,7 +629,7 @@ ior_hard_reg_conflicts (ira_allocno_t a, const_hard_reg_set set)
bool
ira_conflict_vector_profitable_p (ira_object_t obj, int num)
{
- int nw;
+ int nbytes;
int max = OBJECT_MAX (obj);
int min = OBJECT_MIN (obj);
@@ -638,9 +638,14 @@ ira_conflict_vector_profitable_p (ira_object_t obj, int num)
in allocation. */
return false;
- nw = (max - min + IRA_INT_BITS) / IRA_INT_BITS;
- return (2 * sizeof (ira_object_t) * (num + 1)
- < 3 * nw * sizeof (IRA_INT_TYPE));
+ nbytes = (max - min) / 8 + 1;
+ STATIC_ASSERT (sizeof (ira_object_t) <= 8);
+ /* Don't use sizeof (ira_object_t), use constant 8. Size of ira_object_t (a
+ pointer) is different on 32-bit and 64-bit targets. Usage sizeof
+ (ira_object_t) can result in different code generation by GCC built as 32-
+ and 64-bit program. In any case the profitability is just an estimation
+ and border cases are rare. */
+ return (2 * 8 /* sizeof (ira_object_t) */ * (num + 1) < 3 * nbytes);
}
/* Allocates and initialize the conflict vector of OBJ for NUM
diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index 903c258..7b9e488 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -1983,7 +1983,9 @@ cont:
output_name = XOBFINISH (&env_obstack, char *);
/* Adjust the dumpbase if the linker output file was seen. */
- int dumpbase_len = (strlen (dumppfx) + sizeof (DUMPBASE_SUFFIX));
+ int dumpbase_len = (strlen (dumppfx)
+ + sizeof (DUMPBASE_SUFFIX)
+ + sizeof (".ltrans"));
char *dumpbase = (char *) xmalloc (dumpbase_len + 1);
snprintf (dumpbase, dumpbase_len, "%sltrans%u.ltrans", dumppfx, i);
argv_ptr[0] = dumpbase;
@@ -2009,9 +2011,11 @@ cont:
}
else
{
- char argsuffix[sizeof (DUMPBASE_SUFFIX) + 1];
+ char argsuffix[sizeof (DUMPBASE_SUFFIX)
+ + sizeof (".ltrans_args") + 1];
if (save_temps)
- snprintf (argsuffix, sizeof (DUMPBASE_SUFFIX),
+ snprintf (argsuffix,
+ sizeof (DUMPBASE_SUFFIX) + sizeof (".ltrans_args"),
"ltrans%u.ltrans_args", i);
fork_execute (new_argv[0], CONST_CAST (char **, new_argv),
true, save_temps ? argsuffix : NULL);
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 0a2d2d1..1aea3f8 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,8 @@
+2021-09-27 Martin Liska <mliska@suse.cz>
+
+ * lto-lang.c (lto_init_options_struct): Set also
+ x_flag_default_complex_method.
+
2021-09-03 Jakub Jelinek <jakub@redhat.com>
PR target/102024
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index 92f4996..a014e58 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -813,6 +813,7 @@ lto_init_options_struct (struct gcc_options *opts)
safe choice. This will pessimize Fortran code with LTO unless
people specify a complex method manually or use -ffast-math. */
opts->x_flag_complex_method = 2;
+ opts->x_flag_default_complex_method = opts->x_flag_complex_method;
}
/* Handle command-line option SCODE. If the option takes an argument, it is
diff --git a/gcc/match.pd b/gcc/match.pd
index a063a15..a9791ce 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1481,6 +1481,36 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (!FIXED_POINT_TYPE_P (type))
(plus @0 (negate @1))))
+/* Other simplifications of negation (c.f. fold_negate_expr_1). */
+(simplify
+ (negate (mult:c@0 @1 negate_expr_p@2))
+ (if (! TYPE_UNSIGNED (type)
+ && ! HONOR_SIGN_DEPENDENT_ROUNDING (type)
+ && single_use (@0))
+ (mult @1 (negate @2))))
+
+(simplify
+ (negate (rdiv@0 @1 negate_expr_p@2))
+ (if (! HONOR_SIGN_DEPENDENT_ROUNDING (type)
+ && single_use (@0))
+ (rdiv @1 (negate @2))))
+
+(simplify
+ (negate (rdiv@0 negate_expr_p@1 @2))
+ (if (! HONOR_SIGN_DEPENDENT_ROUNDING (type)
+ && single_use (@0))
+ (rdiv (negate @1) @2)))
+
+/* Fold -((int)x >> (prec - 1)) into (unsigned)x >> (prec - 1). */
+(simplify
+ (negate (convert? (rshift @0 INTEGER_CST@1)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
+ && wi::to_wide (@1) == element_precision (type) - 1)
+ (with { tree stype = TREE_TYPE (@0);
+ tree ntype = TYPE_UNSIGNED (stype) ? signed_type_for (stype)
+ : unsigned_type_for (stype); }
+ (convert (rshift:ntype (convert:ntype @0) @1)))))
+
/* Try to fold (type) X op CST -> (type) (X op ((type-x) CST))
when profitable.
For bitwise binary operations apply operand conversions to the
diff --git a/gcc/omp-expand.c b/gcc/omp-expand.c
index 159ae0e..496c0e6 100644
--- a/gcc/omp-expand.c
+++ b/gcc/omp-expand.c
@@ -8433,11 +8433,17 @@ expand_omp_single (struct omp_region *region)
exit_bb = region->exit;
si = gsi_last_nondebug_bb (entry_bb);
- gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
- || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SCOPE);
+ enum gimple_code code = gimple_code (gsi_stmt (si));
+ gcc_assert (code == GIMPLE_OMP_SINGLE || code == GIMPLE_OMP_SCOPE);
gsi_remove (&si, true);
single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
+ if (exit_bb == NULL)
+ {
+ gcc_assert (code == GIMPLE_OMP_SCOPE);
+ return;
+ }
+
si = gsi_last_nondebug_bb (exit_bb);
if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
{
diff --git a/gcc/omp-general.c b/gcc/omp-general.c
index cc6aecb..1e4c0b2 100644
--- a/gcc/omp-general.c
+++ b/gcc/omp-general.c
@@ -193,6 +193,7 @@ omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
== GF_OMP_FOR_KIND_DISTRIBUTE;
bool taskloop = gimple_omp_for_kind (for_stmt)
== GF_OMP_FOR_KIND_TASKLOOP;
+ bool order_reproducible = false;
tree iterv, countv;
fd->for_stmt = for_stmt;
@@ -277,10 +278,25 @@ omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
&& !OMP_CLAUSE__SCANTEMP__CONTROL (t))
fd->have_nonctrl_scantemp = true;
break;
+ case OMP_CLAUSE_ORDER:
+ /* FIXME: For OpenMP 5.2 this should change to
+ if (OMP_CLAUSE_ORDER_REPRODUCIBLE (t))
+ (with the exception of loop construct but that lowers to
+ no schedule/dist_schedule clauses currently). */
+ if (!OMP_CLAUSE_ORDER_UNCONSTRAINED (t))
+ order_reproducible = true;
default:
break;
}
+ /* For order(reproducible:concurrent) schedule ({dynamic,guided,runtime})
+ we have either the option to expensively remember at runtime how we've
+ distributed work from first loop and reuse that in following loops with
+ the same number of iterations and schedule, or just force static schedule.
+ OpenMP API calls etc. aren't allowed in order(concurrent) bodies so
+ users can't observe it easily anyway. */
+ if (order_reproducible)
+ fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
if (fd->collapse > 1 || fd->tiling)
fd->loops = loops;
else
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 27a513e..f7242df 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -1161,14 +1161,17 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
&& (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
/* omp_default_mem_alloc is 1 */
- || !integer_onep (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))))
+ || !integer_onep (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
+ || OMP_CLAUSE_ALLOCATE_ALIGN (c) != NULL_TREE))
{
if (ctx->allocate_map == NULL)
ctx->allocate_map = new hash_map<tree, tree>;
- ctx->allocate_map->put (OMP_CLAUSE_DECL (c),
- OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
- ? OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
- : integer_zero_node);
+ tree val = integer_zero_node;
+ if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
+ val = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
+ if (OMP_CLAUSE_ALLOCATE_ALIGN (c))
+ val = build_tree_list (val, OMP_CLAUSE_ALLOCATE_ALIGN (c));
+ ctx->allocate_map->put (OMP_CLAUSE_DECL (c), val);
}
for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
@@ -3918,8 +3921,12 @@ omp_runtime_api_call (const_tree fndecl)
{
/* This array has 3 sections. First omp_* calls that don't
have any suffixes. */
- "omp_alloc",
- "omp_free",
+ "aligned_alloc",
+ "aligned_calloc",
+ "alloc",
+ "calloc",
+ "free",
+ "realloc",
"target_alloc",
"target_associate_ptr",
"target_disassociate_ptr",
@@ -4725,6 +4732,12 @@ lower_private_allocate (tree var, tree new_var, tree &allocator,
return false;
}
+ unsigned HOST_WIDE_INT ialign = 0;
+ if (TREE_CODE (allocator) == TREE_LIST)
+ {
+ ialign = tree_to_uhwi (TREE_VALUE (allocator));
+ allocator = TREE_PURPOSE (allocator);
+ }
if (TREE_CODE (allocator) != INTEGER_CST)
allocator = build_outer_var_ref (allocator, ctx);
allocator = fold_convert (pointer_sized_int_node, allocator);
@@ -4739,21 +4752,21 @@ lower_private_allocate (tree var, tree new_var, tree &allocator,
if (TYPE_P (new_var))
{
ptr_type = build_pointer_type (new_var);
- align = build_int_cst (size_type_node, TYPE_ALIGN_UNIT (new_var));
+ ialign = MAX (ialign, TYPE_ALIGN_UNIT (new_var));
}
else if (is_ref)
{
ptr_type = build_pointer_type (TREE_TYPE (TREE_TYPE (new_var)));
- align = build_int_cst (size_type_node,
- TYPE_ALIGN_UNIT (TREE_TYPE (ptr_type)));
+ ialign = MAX (ialign, TYPE_ALIGN_UNIT (TREE_TYPE (ptr_type)));
}
else
{
ptr_type = build_pointer_type (TREE_TYPE (new_var));
- align = build_int_cst (size_type_node, DECL_ALIGN_UNIT (new_var));
+ ialign = MAX (ialign, DECL_ALIGN_UNIT (new_var));
if (sz == NULL_TREE)
sz = fold_convert (size_type_node, DECL_SIZE_UNIT (new_var));
}
+ align = build_int_cst (size_type_node, ialign);
if (TREE_CODE (sz) != INTEGER_CST)
{
tree szvar = create_tmp_var (size_type_node);
@@ -5707,6 +5720,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (tree *allocatep = ctx->allocate_map->get (var))
{
allocator = *allocatep;
+ if (TREE_CODE (allocator) == TREE_LIST)
+ allocator = TREE_PURPOSE (allocator);
if (TREE_CODE (allocator) != INTEGER_CST)
allocator = build_outer_var_ref (allocator, ctx);
allocator = fold_convert (pointer_sized_int_node,
@@ -6025,6 +6040,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (tree *allocatep = ctx->allocate_map->get (var))
{
allocator = *allocatep;
+ if (TREE_CODE (allocator) == TREE_LIST)
+ allocator = TREE_PURPOSE (allocator);
if (TREE_CODE (allocator) != INTEGER_CST)
allocator = build_outer_var_ref (allocator, ctx);
allocator = fold_convert (pointer_sized_int_node,
@@ -12070,6 +12087,12 @@ create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
if (tree *allocatorp = ctx->allocate_map->get (decl))
{
tree allocator = *allocatorp;
+ HOST_WIDE_INT ialign = 0;
+ if (TREE_CODE (allocator) == TREE_LIST)
+ {
+ ialign = tree_to_uhwi (TREE_VALUE (allocator));
+ allocator = TREE_PURPOSE (allocator);
+ }
if (TREE_CODE (allocator) != INTEGER_CST)
{
n = splay_tree_lookup (ctx->sfield_map,
@@ -12083,7 +12106,8 @@ create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
allocator = fold_convert (pointer_sized_int_node, allocator);
tree a = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
tree align = build_int_cst (size_type_node,
- DECL_ALIGN_UNIT (decl));
+ MAX (ialign,
+ DECL_ALIGN_UNIT (decl)));
tree sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dst)));
tree ptr = build_call_expr_loc (loc, a, 3, align, sz,
allocator);
diff --git a/gcc/opts.c b/gcc/opts.c
index 1d2d22d..6503980 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -569,6 +569,7 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_1_PLUS, OPT_freorder_blocks, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_fshrink_wrap, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_fsplit_wide_types, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fthread_jumps, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_builtin_call_dce, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_ccp, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_ch, NULL, 1 },
@@ -629,7 +630,6 @@ static const struct default_options default_options_table[] =
#endif
{ OPT_LEVELS_2_PLUS, OPT_fstrict_aliasing, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fstore_merging, NULL, 1 },
- { OPT_LEVELS_2_PLUS, OPT_fthread_jumps, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ftree_pre, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ftree_switch_conversion, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ftree_tail_merge, NULL, 1 },
@@ -1331,6 +1331,18 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
= (opts->x_flag_unroll_loops
|| opts->x_flag_peel_loops
|| opts->x_optimize >= 3);
+
+ /* With -fcx-limited-range, we do cheap and quick complex arithmetic. */
+ if (opts->x_flag_cx_limited_range)
+ opts->x_flag_complex_method = 0;
+ else if (opts_set->x_flag_cx_limited_range)
+ opts->x_flag_complex_method = opts->x_flag_default_complex_method;
+
+ /* With -fcx-fortran-rules, we do something in-between cheap and C99. */
+ if (opts->x_flag_cx_fortran_rules)
+ opts->x_flag_complex_method = 1;
+ else if (opts_set->x_flag_cx_fortran_rules)
+ opts->x_flag_complex_method = opts->x_flag_default_complex_method;
}
#define LEFT_COLUMN 27
diff --git a/gcc/output.h b/gcc/output.h
index 73ca454..8f6f153 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -365,44 +365,53 @@ extern void default_function_switched_text_sections (FILE *, tree, bool);
extern void no_asm_to_stream (FILE *);
/* Flags controlling properties of a section. */
-#define SECTION_ENTSIZE 0x000ff /* entity size in section */
-#define SECTION_CODE 0x00100 /* contains code */
-#define SECTION_WRITE 0x00200 /* data is writable */
-#define SECTION_DEBUG 0x00400 /* contains debug data */
-#define SECTION_LINKONCE 0x00800 /* is linkonce */
-#define SECTION_SMALL 0x01000 /* contains "small data" */
-#define SECTION_BSS 0x02000 /* contains zeros only */
-#define SECTION_FORGET 0x04000 /* forget that we've entered the section */
-#define SECTION_MERGE 0x08000 /* contains mergeable data */
-#define SECTION_STRINGS 0x10000 /* contains zero terminated strings without
- embedded zeros */
-#define SECTION_OVERRIDE 0x20000 /* allow override of default flags */
-#define SECTION_TLS 0x40000 /* contains thread-local storage */
-#define SECTION_NOTYPE 0x80000 /* don't output @progbits */
-#define SECTION_DECLARED 0x100000 /* section has been used */
-#define SECTION_STYLE_MASK 0x600000 /* bits used for SECTION_STYLE */
-#define SECTION_COMMON 0x800000 /* contains common data */
-#define SECTION_RELRO 0x1000000 /* data is readonly after relocation processing */
-#define SECTION_EXCLUDE 0x2000000 /* discarded by the linker */
-#define SECTION_RETAIN 0x4000000 /* retained by the linker. */
-#define SECTION_LINK_ORDER 0x8000000 /* section needs link-order. */
-
-/* NB: The maximum SECTION_MACH_DEP is 0x10000000 since AVR needs 4 bits
- in SECTION_MACH_DEP. */
-#define SECTION_MACH_DEP 0x10000000 /* subsequent bits reserved for target */
-
-/* This SECTION_STYLE is used for unnamed sections that we can switch
- to using a special assembler directive. */
-#define SECTION_UNNAMED 0x000000
-
-/* This SECTION_STYLE is used for named sections that we can switch
- to using a general section directive. */
-#define SECTION_NAMED 0x200000
-
-/* This SECTION_STYLE is used for sections that we cannot switch to at
- all. The choice of section is implied by the directive that we use
- to declare the object. */
-#define SECTION_NOSWITCH 0x400000
+enum section_flag
+{
+ /* This SECTION_STYLE is used for unnamed sections that we can switch
+ to using a special assembler directive. */
+ SECTION_UNNAMED = 0,
+
+ SECTION_ENTSIZE = (1UL << 8) - 1, /* entity size in section */
+ SECTION_CODE = 1UL << 8, /* contains code */
+ SECTION_WRITE = 1UL << 9, /* data is writable */
+
+ SECTION_DEBUG = 1UL << 10, /* contains debug data */
+ SECTION_LINKONCE = 1UL << 11, /* is linkonce */
+ SECTION_SMALL = 1UL << 12, /* contains "small data" */
+ SECTION_BSS = 1UL << 13, /* contains zeros only */
+ SECTION_MERGE = 1UL << 14, /* contains mergeable data */
+ SECTION_STRINGS = 1UL << 15, /* contains zero terminated strings
+ without embedded zeros */
+ SECTION_OVERRIDE = 1UL << 16, /* allow override of default flags */
+ SECTION_TLS = 1UL << 17, /* contains thread-local storage */
+ SECTION_NOTYPE = 1UL << 18, /* don't output @progbits */
+ SECTION_DECLARED = 1UL << 19, /* section has been used */
+
+ /* This SECTION_STYLE is used for named sections that we can switch
+ to using a general section directive. */
+ SECTION_NAMED = 1UL << 20,
+
+ /* This SECTION_STYLE is used for sections that we cannot switch to at
+ all. The choice of section is implied by the directive that we use
+ to declare the object. */
+ SECTION_NOSWITCH = 1UL << 21,
+
+ /* bits used for SECTION_STYLE */
+ SECTION_STYLE_MASK = SECTION_NAMED | SECTION_NOSWITCH,
+
+ SECTION_COMMON = 1UL << 22, /* contains common data */
+ SECTION_RELRO = 1UL << 23, /* data is readonly after
+ relocation processing */
+ SECTION_EXCLUDE = 1UL << 24, /* discarded by the linker */
+ SECTION_RETAIN = 1UL << 25, /* retained by the linker. */
+ SECTION_LINK_ORDER = 1UL << 26, /* section needs link-order. */
+
+ /* NB: The maximum SECTION_MACH_DEP is (1UL << 28) since AVR needs 4 bits
+ in SECTION_MACH_DEP. */
+ SECTION_MACH_DEP = 1UL << 27,
+
+ /* subsequent bits reserved for target */
+};
/* A helper function for default_elf_select_section and
default_elf_unique_section. Categorizes the DECL. */
diff --git a/gcc/params.opt b/gcc/params.opt
index 658ca02..82ddbb8 100644
--- a/gcc/params.opt
+++ b/gcc/params.opt
@@ -130,6 +130,10 @@ Maximal estimated growth of function body caused by early inlining of single cal
Common Joined UInteger Var(param_evrp_sparse_threshold) Init(800) Optimization Param
Maximum number of basic blocks before EVRP uses a sparse cache.
+-param=evrp-switch-limit=
+Common Joined UInteger Var(param_evrp_switch_limit) Init(50) Optimization Param
+Maximum number of outgoing edges in a switch before EVRP will not process it.
+
-param=evrp-mode=
Common Joined Var(param_evrp_mode) Enum(evrp_mode) Init(EVRP_MODE_RVRP_ONLY) Param Optimization
--param=evrp-mode=[legacy|ranger|legacy-first|ranger-first|trace|gori|cache|tracegori|debug] Specifies the mode Early VRP should operate in.
diff --git a/gcc/passes.def b/gcc/passes.def
index d7a1f8c..c11c237 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -212,6 +212,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_merge_phi);
NEXT_PASS (pass_thread_jumps);
NEXT_PASS (pass_vrp, true /* warn_array_bounds_p */);
+ NEXT_PASS (pass_vrp_threader);
NEXT_PASS (pass_dse);
NEXT_PASS (pass_dce);
/* pass_stdarg is always run and at this point we execute
@@ -242,7 +243,7 @@ along with GCC; see the file COPYING3. If not see
/* Identify paths that should never be executed in a conforming
program and isolate those paths. */
NEXT_PASS (pass_isolate_erroneous_paths);
- NEXT_PASS (pass_reassoc, true /* insert_powi_p */);
+ NEXT_PASS (pass_reassoc, true /* early_p */);
NEXT_PASS (pass_dce);
NEXT_PASS (pass_forwprop);
NEXT_PASS (pass_phiopt, false /* early_p */);
@@ -325,7 +326,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_lower_vector_ssa);
NEXT_PASS (pass_lower_switch);
NEXT_PASS (pass_cse_reciprocals);
- NEXT_PASS (pass_reassoc, false /* insert_powi_p */);
+ NEXT_PASS (pass_reassoc, false /* early_p */);
NEXT_PASS (pass_strength_reduction);
NEXT_PASS (pass_split_paths);
NEXT_PASS (pass_tracer);
@@ -337,6 +338,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_strlen);
NEXT_PASS (pass_thread_jumps);
NEXT_PASS (pass_vrp, false /* warn_array_bounds_p */);
+ NEXT_PASS (pass_vrp_threader);
/* Threading can leave many const/copy propagations in the IL.
Clean them up. Instead of just copy_prop, we use ccp to
compute alignment and nonzero bits. */
diff --git a/gcc/poly-int.h b/gcc/poly-int.h
index f47f9e4..94e7b70 100644
--- a/gcc/poly-int.h
+++ b/gcc/poly-int.h
@@ -324,10 +324,10 @@ struct poly_result<T1, T2, 2>
routine can take the address of RES rather than the address of
a temporary.
- The dummy comparison against a null C * is just a way of checking
+ The dummy self-comparison against C * is just a way of checking
that C gives the right type. */
#define POLY_SET_COEFF(C, RES, I, VALUE) \
- ((void) (&(RES).coeffs[0] == (C *) 0), \
+ ((void) (&(RES).coeffs[0] == (C *) (void *) &(RES).coeffs[0]), \
wi::int_traits<C>::precision_type == wi::FLEXIBLE_PRECISION \
? (void) ((RES).coeffs[I] = VALUE) \
: (void) ((RES).coeffs[I].~C (), new (&(RES).coeffs[I]) C (VALUE)))
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 5e37133..bbf2924 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -2078,6 +2078,12 @@ operator_lshift::op1_range (irange &r,
relation_kind rel ATTRIBUTE_UNUSED) const
{
tree shift_amount;
+
+ if (!lhs.contains_p (build_zero_cst (type)))
+ r.set_nonzero (type);
+ else
+ r.set_varying (type);
+
if (op2.singleton_p (&shift_amount))
{
wide_int shift = wi::to_wide (shift_amount);
@@ -2089,21 +2095,22 @@ operator_lshift::op1_range (irange &r,
return false;
if (shift == 0)
{
- r = lhs;
+ r.intersect (lhs);
return true;
}
// Work completely in unsigned mode to start.
tree utype = type;
+ int_range_max tmp_range;
if (TYPE_SIGN (type) == SIGNED)
{
int_range_max tmp = lhs;
utype = unsigned_type_for (type);
range_cast (tmp, utype);
- op_rshift.fold_range (r, utype, tmp, op2);
+ op_rshift.fold_range (tmp_range, utype, tmp, op2);
}
else
- op_rshift.fold_range (r, utype, lhs, op2);
+ op_rshift.fold_range (tmp_range, utype, lhs, op2);
// Start with ranges which can produce the LHS by right shifting the
// result by the shift amount.
@@ -2119,16 +2126,19 @@ operator_lshift::op1_range (irange &r,
unsigned low_bits = TYPE_PRECISION (utype)
- TREE_INT_CST_LOW (shift_amount);
wide_int up_mask = wi::mask (low_bits, true, TYPE_PRECISION (utype));
- wide_int new_ub = wi::bit_or (up_mask, r.upper_bound ());
- wide_int new_lb = wi::set_bit (r.lower_bound (), low_bits);
+ wide_int new_ub = wi::bit_or (up_mask, tmp_range.upper_bound ());
+ wide_int new_lb = wi::set_bit (tmp_range.lower_bound (), low_bits);
int_range<2> fill_range (utype, new_lb, new_ub);
- r.union_ (fill_range);
+ tmp_range.union_ (fill_range);
if (utype != type)
- range_cast (r, type);
+ range_cast (tmp_range, type);
+
+ r.intersect (tmp_range);
return true;
}
- return false;
+
+ return !r.varying_p ();
}
bool
diff --git a/gcc/real.c b/gcc/real.c
index 555cf44..8c7a47a 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -3150,9 +3150,10 @@ encode_ieee_double (const struct real_format *fmt, long *buf,
const REAL_VALUE_TYPE *r)
{
unsigned long image_lo, image_hi, sig_lo, sig_hi, exp;
+ unsigned long sign = r->sign;
bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
- image_hi = r->sign << 31;
+ image_hi = sign << 31;
image_lo = 0;
if (HOST_BITS_PER_LONG == 64)
@@ -3938,10 +3939,11 @@ encode_ieee_quad (const struct real_format *fmt, long *buf,
const REAL_VALUE_TYPE *r)
{
unsigned long image3, image2, image1, image0, exp;
+ unsigned long sign = r->sign;
bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
REAL_VALUE_TYPE u;
- image3 = r->sign << 31;
+ image3 = sign << 31;
image2 = 0;
image1 = 0;
image0 = 0;
diff --git a/gcc/rtl.def b/gcc/rtl.def
index c80144b..5710a2e 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -467,6 +467,11 @@ DEF_RTL_EXPR(SS_MULT, "ss_mult", "ee", RTX_COMM_ARITH)
/* Multiplication with unsigned saturation */
DEF_RTL_EXPR(US_MULT, "us_mult", "ee", RTX_COMM_ARITH)
+/* Signed high-part multiplication. */
+DEF_RTL_EXPR(SMUL_HIGHPART, "smul_highpart", "ee", RTX_COMM_ARITH)
+/* Unsigned high-part multiplication. */
+DEF_RTL_EXPR(UMUL_HIGHPART, "umul_highpart", "ee", RTX_COMM_ARITH)
+
/* Operand 0 divided by operand 1. */
DEF_RTL_EXPR(DIV, "div", "ee", RTX_BIN_ARITH)
/* Division with signed saturation */
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index ebad5cb..e4fae0b 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -4142,11 +4142,36 @@ simplify_context::simplify_binary_operation_1 (rtx_code code,
case US_PLUS:
case SS_MINUS:
case US_MINUS:
+ /* Simplify x +/- 0 to x, if possible. */
+ if (trueop1 == CONST0_RTX (mode))
+ return op0;
+ return 0;
+
case SS_MULT:
case US_MULT:
+ /* Simplify x * 0 to 0, if possible. */
+ if (trueop1 == CONST0_RTX (mode)
+ && !side_effects_p (op0))
+ return op1;
+
+ /* Simplify x * 1 to x, if possible. */
+ if (trueop1 == CONST1_RTX (mode))
+ return op0;
+ return 0;
+
+ case SMUL_HIGHPART:
+ case UMUL_HIGHPART:
+ /* Simplify x * 0 to 0, if possible. */
+ if (trueop1 == CONST0_RTX (mode)
+ && !side_effects_p (op0))
+ return op1;
+ return 0;
+
case SS_DIV:
case US_DIV:
- /* ??? There are simplifications that can be done. */
+ /* Simplify x / 1 to x, if possible. */
+ if (trueop1 == CONST1_RTX (mode))
+ return op0;
return 0;
case VEC_SERIES:
@@ -4587,7 +4612,8 @@ simplify_context::simplify_binary_operation_1 (rtx_code code,
if (GET_CODE (trueop0) == VEC_SELECT
&& GET_CODE (trueop1) == VEC_SELECT
&& rtx_equal_p (XEXP (trueop0, 0), XEXP (trueop1, 0))
- && GET_MODE (XEXP (trueop0, 0)) == mode)
+ && GET_MODE_INNER (GET_MODE (XEXP (trueop0, 0)))
+ == GET_MODE_INNER(mode))
{
rtx par0 = XEXP (trueop0, 1);
rtx par1 = XEXP (trueop1, 1);
@@ -5011,6 +5037,51 @@ simplify_const_binary_operation (enum rtx_code code, machine_mode mode,
}
break;
}
+
+ case SS_PLUS:
+ result = wi::add (pop0, pop1, SIGNED, &overflow);
+ clamp_signed_saturation:
+ if (overflow == wi::OVF_OVERFLOW)
+ result = wi::max_value (GET_MODE_PRECISION (int_mode), SIGNED);
+ else if (overflow == wi::OVF_UNDERFLOW)
+ result = wi::min_value (GET_MODE_PRECISION (int_mode), SIGNED);
+ else if (overflow != wi::OVF_NONE)
+ return NULL_RTX;
+ break;
+
+ case US_PLUS:
+ result = wi::add (pop0, pop1, UNSIGNED, &overflow);
+ clamp_unsigned_saturation:
+ if (overflow != wi::OVF_NONE)
+ result = wi::max_value (GET_MODE_PRECISION (int_mode), UNSIGNED);
+ break;
+
+ case SS_MINUS:
+ result = wi::sub (pop0, pop1, SIGNED, &overflow);
+ goto clamp_signed_saturation;
+
+ case US_MINUS:
+ result = wi::sub (pop0, pop1, UNSIGNED, &overflow);
+ if (overflow != wi::OVF_NONE)
+ result = wi::min_value (GET_MODE_PRECISION (int_mode), UNSIGNED);
+ break;
+
+ case SS_MULT:
+ result = wi::mul (pop0, pop1, SIGNED, &overflow);
+ goto clamp_signed_saturation;
+
+ case US_MULT:
+ result = wi::mul (pop0, pop1, UNSIGNED, &overflow);
+ goto clamp_unsigned_saturation;
+
+ case SMUL_HIGHPART:
+ result = wi::mul_high (pop0, pop1, SIGNED);
+ break;
+
+ case UMUL_HIGHPART:
+ result = wi::mul_high (pop0, pop1, UNSIGNED);
+ break;
+
default:
return NULL_RTX;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index aca4514..a3159bd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,883 @@
+2021-10-06 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp2a/spaceship-synth8a.C: New test.
+
+2021-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102612
+ * g++.dg/cpp23/feat-cxx2b.C: Expect __cpp_constexpr 202110L rather
+ than 201907L.
+ * g++.dg/cpp23/constexpr-nonlit1.C: New test.
+ * g++.dg/cpp23/constexpr-nonlit2.C: New test.
+ * g++.dg/cpp23/constexpr-nonlit3.C: New test.
+ * g++.dg/cpp23/constexpr-nonlit4.C: New test.
+ * g++.dg/cpp23/constexpr-nonlit5.C: New test.
+ * g++.dg/cpp23/constexpr-nonlit6.C: New test.
+ * g++.dg/diagnostic/constexpr1.C: Only expect some diagnostics for
+ c++20_down.
+ * g++.dg/cpp1y/constexpr-label.C: Likewise.
+ * g++.dg/cpp1y/constexpr-neg1.C: Likewise.
+ * g++.dg/cpp2a/constexpr-try5.C: Likewise. Adjust some expected
+ wording.
+ * g++.dg/cpp2a/constexpr-dtor3.C: Likewise.
+ * g++.dg/cpp2a/consteval3.C: Likewise. Add effective target c++20
+ and remove dg-options.
+
+2021-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/cpp/gnu11-elifdef-1.c: New test.
+ * gcc.dg/cpp/gnu11-elifdef-2.c: New test.
+ * gcc.dg/cpp/gnu11-elifdef-3.c: New test.
+ * gcc.dg/cpp/gnu11-elifdef-4.c: New test.
+ * g++.dg/cpp/elifdef-1.C: New test.
+ * g++.dg/cpp/elifdef-2.C: New test.
+ * g++.dg/cpp/elifdef-3.C: New test.
+ * g++.dg/cpp/elifdef-4.C: New test.
+ * g++.dg/cpp/elifdef-5.C: New test.
+ * g++.dg/cpp/elifdef-6.C: New test.
+ * g++.dg/cpp/elifdef-7.C: New test.
+
+2021-10-06 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/attr_deprecated-2.f90: New test.
+
+2021-10-06 Jakub Jelinek <jakub@redhat.com>
+ Jason Merrill <jason@redhat.com>
+
+ PR c++/98712
+ PR c++/102490
+ * g++.dg/cpp2a/spaceship-synth8.C (std::strong_ordering): Provide
+ more complete definition.
+ (std::strong_ordering::less, std::strong_ordering::equal,
+ std::strong_ordering::greater): Define.
+ * g++.dg/cpp2a/spaceship-synth12.C: New test.
+ * g++.dg/cpp2a/spaceship-synth13.C: New test.
+ * g++.dg/cpp2a/spaceship-synth14.C: New test.
+ * g++.dg/cpp2a/spaceship-eq11.C: New test.
+ * g++.dg/cpp2a/spaceship-eq12.C: New test.
+ * g++.dg/cpp2a/spaceship-eq13.C: New test.
+
+2021-10-05 qing zhao <qing.zhao@oracle.com>
+
+ PR middle-end/102359
+ * g++.dg/pr102359_1.C: New test.
+ * g++.dg/pr102359_2.C: New test.
+
+2021-10-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102548
+ * g++.target/i386/pr102548.C: New test.
+
+2021-10-05 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102547
+ * g++.dg/cpp0x/variadic-partial2.C: New test.
+ * g++.dg/cpp0x/variadic-partial2a.C: New test.
+
+2021-10-05 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/tree-ssa/ssa-thread-valid.c: New test.
+
+2021-10-05 Jeff Law <jeffreyalaw@gmail.com>
+
+ * gcc.target/s390/pr80725.c: Ensure computed goto is used on
+ a pointer type.
+
+2021-10-05 Richard Biener <rguenther@suse.de>
+
+ PR c/102605
+ * gcc.dg/gimplefe-46.c: New testcase.
+
+2021-10-05 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/98930
+ * g++.dg/cpp1z/nontype4.C: New test.
+ * g++.dg/cpp1z/nontype4a.C: New test.
+
+2021-10-05 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/gomp/pr43711.f90: Add dg-error + dg-prune-output,
+ remove dg-excess-errors to change XFAIL to PASS.
+
+2021-10-05 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102587
+ PR middle-end/102285
+ * gcc.target/aarch64/sve/pr102587-1.c: Add -march=armv8.3-a+sve.
+ * gcc.target/aarch64/sve/pr102587-2.c: Likewise.
+
+2021-10-05 Richard Biener <rguenther@suse.de>
+
+ * gfortran.dg/predict-2.f90: Adjust to avoid redundant
+ inner loop preheader checking code.
+
+2021-10-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * c-c++-common/Warray-compare-1.c: New test.
+ * c-c++-common/Warray-compare-2.c: New test.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/auto-init-hardreg-1.c: New testcase.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ * c-c++-common/pr102285.c: New testcase.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102570
+ * gcc.dg/tree-ssa/ssa-fre-96.c: New testcase.
+ * gcc.dg/tree-ssa/ssa-pre-33.c: Likewise.
+
+2021-10-04 Aldy Hernandez <aldyh@redhat.com>
+
+ * g++.dg/Walloca2.C: New test.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102587
+ * gcc.target/aarch64/sve/pr102587-1.c: New testcase.
+ * gcc.target/aarch64/sve/pr102587-2.c: Likewise.
+
+2021-10-04 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/54753
+ * gfortran.dg/assumed_rank_23.f90: New file.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/101765
+ * g++.dg/coroutines/pr101765.C: New test.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/99710
+ * g++.dg/coroutines/pr99710.C: New test.
+
+2021-10-03 John Eivind Helset <jehelset@gmail.com>
+
+ PR c++/100673
+ * g++.dg/coroutines/pr100673.C: New test.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/101133
+ * g++.dg/coroutines/pr101133.C: New test.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/99575
+ * g++.dg/coroutines/pr99575.C: New test.
+
+2021-10-02 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/tree-ssa/pr102563.c: New test.
+
+2021-10-02 H.J. Lu <hjl.tools@gmail.com>
+
+ * gcc.dg/analyzer/torture/asm-x86-linux-rdmsr.c (DECLARE_ARGS):
+ Use unsigned long long for x86-64.
+
+2021-10-01 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/102546
+ * gcc.dg/tree-ssa/pr102546.c: New file.
+
+2021-10-01 Martin Sebor <msebor@redhat.com>
+
+ PR c/102103
+ * g++.dg/cpp0x/constexpr-array-ptr10.C: Suppress a valid warning.
+ * g++.dg/warn/Wreturn-local-addr-6.C: Correct a cast.
+ * gcc.dg/Waddress.c: Expect a warning.
+ * c-c++-common/Waddress-3.c: New test.
+ * c-c++-common/Waddress-4.c: New test.
+ * g++.dg/warn/Waddress-5.C: New test.
+ * g++.dg/warn/Waddress-6.C: New test.
+ * g++.dg/warn/pr101219.C: Expect a warning.
+ * gcc.dg/Waddress-3.c: New test.
+
+2021-10-01 H.J. Lu <hjl.tools@gmail.com>
+
+ * c-c++-common/tsan/atomic_stack.c: Don't expect print out from
+ __tsan_atomic32_fetch_add.
+
+2021-10-01 qingzhe huang <nickhuang99@hotmail.com>
+
+ PR c++/101783
+ * g++.dg/parse/pr101783.C: New test.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+ Richard Biener <rguenther@suse.de>
+
+ PR sanitizer/102515
+ * c-c++-common/ubsan/div-by-zero-3.c: Use
+ -fsanitize=signed-integer-overflow instead of
+ -fsanitize=integer-divide-by-zero.
+ * c-c++-common/ubsan/div-by-zero-5.c: Likewise.
+ * c-c++-common/ubsan/div-by-zero-4.c: Likewise. Add
+ -fsanitize-undefined-trap-on-error.
+ * c-c++-common/ubsan/float-div-by-zero-2.c: New test.
+ * c-c++-common/ubsan/overflow-div-1.c: New test.
+ * c-c++-common/ubsan/overflow-div-2.c: New test.
+ * c-c++-common/ubsan/overflow-div-3.c: New test.
+
+2021-10-01 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/cpymem-size.c: Adjust scan for ilp32.
+
+2021-10-01 Andrew Pinski <apinski@marvell.com>
+
+ * gcc.dg/vect/bb-slp-pr97709.c: Fix for computed goto
+ pointers.
+
+2021-10-01 Martin Liska <mliska@suse.cz>
+
+ * gcc.target/i386/avx512er-vrsqrt28ps-3.c: Disable fast math.
+ * gcc.target/i386/avx512er-vrsqrt28ps-5.c: Likewise.
+ * gcc.target/i386/attr-optimize.c: New test.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * gfortran.dg/gomp/order-5.f90: Adjust scan-tree-dump-times regexps.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102496
+ * g++.dg/tls/pr102496-1.C: New test.
+ * g++.dg/tls/pr102496-2.C: New test.
+
+2021-10-01 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102518
+ * gcc.dg/torture/pr102518.c: New testcase.
+
+2021-09-30 David Edelsohn <dje.gcc@gmail.com>
+
+ * gfortran.dg/c-interop/cf-descriptor-5-c.c: Include alloca.h.
+
+2021-09-30 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102535
+ * g++.dg/ext/is_trivially_constructible7.C: New test.
+
+2021-09-30 Patrick Palka <ppalka@redhat.com>
+
+ * g++.dg/ext/is_constructible6.C: New test.
+
+2021-09-30 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/95567
+ * g++.dg/cpp2a/spaceship-virtual1.C: New test.
+
+2021-09-30 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102458
+ * gfortran.dg/pr102458b.f90: New test.
+
+2021-09-30 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/89954
+ * gcc.target/i386/pr89954.c: New test.
+
+2021-09-30 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/71703
+ PR fortran/84007
+ * gfortran.dg/c-interop/c535b-1.f90: Remove wrong comment.
+ * gfortran.dg/unlimited_polymorphic_1.f03: Extend.
+ * gfortran.dg/unlimited_polymorphic_32.f90: New test.
+
+2021-09-30 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/102476
+ * gdc.dg/pr102476.d: New test.
+
+2021-09-30 Martin Liska <mliska@suse.cz>
+
+ PR testsuite/102509
+ * gcc.c-torture/compile/attr-complex-method.c: Skip if LTO is
+ used.
+ * gcc.c-torture/compile/attr-complex-method-2.c: Likewise.
+
+2021-09-29 Aldy Hernandez <aldyh@redhat.com>
+
+ PR testsuite/102501
+ * gcc.dg/tree-ssa/pr66752-3.c: Adjust.
+ * gcc.dg/tree-ssa/pr77445-2.c: Adjust.
+
+2021-09-29 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102520
+ * gfortran.dg/pr102520.f90: New test.
+
+2021-09-29 Jeff Law <jeffreyalaw@gmail.com>
+
+ * gcc.c-torture/compile/920831-1.c: Fix computed goto types.
+ * gcc.c-torture/compile/pr27863.c: Likewise.
+
+2021-09-29 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/102517
+ * gcc.dg/pr78408-1.c: Make S not power-of-two size.
+
+2021-09-29 Richard Biener <rguenther@suse.de>
+
+ * gcc.target/i386/vect-alignment-peeling-1.c: New testcase.
+ * gcc.target/i386/vect-alignment-peeling-2.c: Likewise.
+
+2021-09-29 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+ Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/cpymem-size.c: New test.
+
+2021-09-29 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+ Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/memset-corner-cases-2.c: New test.
+ * gcc.target/aarch64/memset-strict-align-1.c: Adjust.
+
+2021-09-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/102504
+ * c-c++-common/gomp/scope-4.c: New test.
+
+2021-09-29 Andrew Pinski <apinski@marvell.com>
+
+ * gcc.c-torture/compile/920826-1.c: Fix computed goto.
+ * gcc.c-torture/compile/pr27863.c: Likewise.
+ * gcc.c-torture/compile/pr70190.c: Likewise.
+ * gcc.dg/torture/pr89135.c: Likewise.
+ * gcc.dg/torture/pr90071.c: Likewise.
+ * gcc.dg/vect/bb-slp-pr97709.c: Likewise.
+
+2021-09-29 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/out-of-bounds-1.c: Make memcpied size not power-of-two.
+
+2021-09-28 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/99909
+ * g++.dg/cpp2a/concepts-ttp3.C: New test.
+
+2021-09-28 Andrew Pinski <apinski@marvell.com>
+
+ PR c/32122
+ * gcc.dg/comp-goto-5.c: New test.
+ * gcc.dg/comp-goto-6.c: New test.
+
+2021-09-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/102454
+ * g++.dg/coroutines/pr102454.C: New test.
+
+2021-09-28 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * gcc.dg/tree-ssa/reassoc-46.c: New test.
+ * gcc.dg/tree-ssa/reassoc-46.h: Common code for new tests.
+ * gcc.dg/tree-ssa/reassoc-47.c: New test.
+ * gcc.dg/tree-ssa/reassoc-48.c: New test.
+ * gcc.dg/tree-ssa/reassoc-49.c: New test.
+ * gcc.dg/tree-ssa/reassoc-50.c: New test.
+ * gcc.dg/tree-ssa/reassoc-51.c: New test.
+
+2021-09-28 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/auto-init-uninit-1.c: Adjust.
+ * gcc.dg/auto-init-uninit-15.c: Same.
+ * gcc.dg/guality/example.c: Same.
+ * gcc.dg/loop-8.c: Same.
+ * gcc.dg/strlenopt-40.c: Same.
+ * gcc.dg/tree-ssa/pr18133-2.c: Same.
+ * gcc.dg/tree-ssa/pr18134.c: Same.
+ * gcc.dg/uninit-1.c: Same.
+ * gcc.dg/uninit-pr44547.c: Same.
+ * gcc.dg/uninit-pr59970.c: Same.
+
+2021-09-28 Thomas Schwinge <thomas@codesourcery.com>
+
+ * gfortran.dg/assumed_rank_22_aux.c: Adjust messages printed.
+
+2021-09-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/102498
+ * gcc.target/i386/pr102498.c: New test.
+
+2021-09-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/99793
+ * gcc.dg/tree-ssa/pr99793.c: New testcase.
+
+2021-09-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/100112
+ * gcc.dg/tree-ssa/ssa-fre-95.c: New testcase.
+
+2021-09-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/102492
+ * g++.dg/gomp/simd-3.C: New test.
+
+2021-09-28 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/102511
+ * gcc.dg/pr102511.c: New test.
+ * gcc.dg/tree-ssa/ssa-dom-thread-14.c: Adjust.
+
+2021-09-28 Hongyu Wang <hongyu.wang@intel.com>
+
+ PR target/102230
+ * gcc.target/i386/avx512fp16-floatvnhf.c: Remove xfail.
+ * gcc.target/i386/avx512fp16-trunc-extendvnhf.c: Ditto.
+ * gcc.target/i386/avx512fp16-truncvnhf.c: Ditto.
+ * gcc.target/i386/avx512fp16-64-32-vecop-1.c: New test.
+ * gcc.target/i386/avx512fp16-64-32-vecop-2.c: Ditto.
+ * gcc.target/i386/pr102230.c: Ditto.
+
+2021-09-28 Richard Biener <rguenther@suse.de>
+
+ * gcc.target/i386/vect-pr97352.c: Pass -mno-avx2 -mno-avx512f.
+
+2021-09-28 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/102500
+ * gfortran.dg/include_15.f90: Add 'dg-prune-output' to prune
+ -Wmissing-include-dirs output printed or not depending on
+ how the testsuite is run.
+
+2021-09-28 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/bb-slp-pr65935.c: Prefer 128bit vectorization
+ on x86.
+
+2021-09-28 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/auto-init-uninit-1.c: Add -fthread-jumps.
+ * gcc.dg/auto-init-uninit-15.c: Same.
+ * gcc.dg/guality/example.c: Same.
+ * gcc.dg/loop-8.c: Same.
+ * gcc.dg/strlenopt-40.c: Same.
+ * gcc.dg/tree-ssa/pr18133-2.c: Same.
+ * gcc.dg/tree-ssa/pr18134.c: Same.
+ * gcc.dg/uninit-1.c: Same.
+ * gcc.dg/uninit-pr44547.c: Same.
+ * gcc.dg/uninit-pr59970.c: Same.
+
+2021-09-28 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/vect-rebuild.c: Adjust testcases.
+ * gcc.target/i386/avx512f-vect-rebuild.c: New test.
+
+2021-09-28 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-reduce-op-2.c: New test.
+ * gcc.target/i386/avx512fp16-reduce-op-3.c: New test.
+
+2021-09-27 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102479
+ * g++.dg/cpp1z/class-deduction12.C: Also test alias CTAD in the
+ same way.
+ * g++.dg/cpp1z/class-deduction99.C: New test.
+
+2021-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/torture/pr55107.c: Adjust.
+ * gcc.dg/tree-ssa/phi_on_compare-1.c: Adjust.
+ * gcc.dg/tree-ssa/phi_on_compare-2.c: Adjust.
+ * gcc.dg/tree-ssa/phi_on_compare-3.c: Adjust.
+ * gcc.dg/tree-ssa/phi_on_compare-4.c: Adjust.
+ * gcc.dg/tree-ssa/pr21559.c: Adjust.
+ * gcc.dg/tree-ssa/pr59597.c: Adjust.
+ * gcc.dg/tree-ssa/pr61839_1.c: Adjust.
+ * gcc.dg/tree-ssa/pr61839_3.c: Adjust.
+ * gcc.dg/tree-ssa/pr71437.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-dom-thread-11.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-dom-thread-16.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-dom-thread-18.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-dom-thread-2a.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-dom-thread-4.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-thread-14.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-vrp-thread-1.c: Adjust.
+ * gcc.dg/tree-ssa/vrp106.c: Adjust.
+ * gcc.dg/tree-ssa/vrp55.c: Adjust.
+
+2021-09-27 Martin Liska <mliska@suse.cz>
+
+ * gcc.c-torture/compile/attr-complex-method-2.c: New test.
+ * gcc.c-torture/compile/attr-complex-method.c: New test.
+
+2021-09-27 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/94070
+ * gfortran.dg/c-interop/cf-out-descriptor-6.f90: Remove xfail.
+ * gfortran.dg/c-interop/size.f90: Remove xfail.
+ * gfortran.dg/intrinsic_size_3.f90: Update scan-tree-dump-times.
+ * gfortran.dg/transpose_optimization_2.f90: Likewise.
+ * gfortran.dg/size_optional_dim_1.f90: Add scan-tree-dump-not.
+ * gfortran.dg/assumed_rank_22.f90: New test.
+ * gfortran.dg/assumed_rank_22_aux.c: New test.
+
+2021-09-27 Andrew Pinski <apinski@marvell.com>
+
+ PR c/94726
+ * gcc.dg/pr94726.c: New test.
+
+2021-09-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97351
+ PR tree-optimization/97352
+ PR tree-optimization/82426
+ * gcc.target/i386/vect-pr82426.c: New testcase.
+ * gcc.target/i386/vect-pr97352.c: Likewise.
+
+2021-09-27 liuhongt <hongtao.liu@intel.com>
+
+ Revert:
+ 2021-09-27 liuhongt <hongtao.liu@intel.com>
+
+ PR target/101059
+ * gcc.target/i386/sse2-pr101059.c: New test.
+ * gcc.target/i386/sse3-pr101059.c: New test.
+
+2021-09-26 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/101334
+ * gfortran.dg/associated_assumed_rank.f90: New test.
+
+2021-09-25 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * gcc.target/pru/regio-as-pointer.c: New negative test.
+ * gcc.target/pru/regio-as-pointer-2.c: New negative test.
+ * gcc.target/pru/regio-decl-2.c: New negative test.
+ * gcc.target/pru/regio-decl-3.c: New negative test.
+ * gcc.target/pru/regio-decl-4.c: New negative test.
+ * gcc.target/pru/regio-decl.c: New negative test.
+ * gcc.target/pru/regio-di.c: New negative test.
+ * gcc.target/pru/regio-hi.c: New negative test.
+ * gcc.target/pru/regio-qi.c: New negative test.
+ * gcc.target/pru/regio.c: New test.
+ * gcc.target/pru/regio.h: New helper header.
+
+2021-09-24 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102458
+ * gfortran.dg/pr102458.f90: New test.
+
+2021-09-24 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101333
+ * gfortran.dg/c-interop/c407c-1.f90: Remove xfails.
+
+2021-09-24 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/98216
+ PR c++/91292
+ * g++.dg/cpp2a/nontype-float2.C: New test.
+
+2021-09-24 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * gfortran.dg/include_9.f90: Add dg-prune-output.
+ * gfortran.dg/include_23.f90: New test.
+ * gfortran.dg/include_24.f90: New test.
+
+2021-09-24 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/tree-ssa/20030714-2.c: Adjust.
+ * gcc.dg/tree-ssa/pr66752-3.c: Adjust.
+ * gcc.dg/tree-ssa/pr77445-2.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-dom-thread-18.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-dom-thread-7.c: Adjust.
+ * gcc.dg/vect/bb-slp-16.c: Adjust.
+
+2021-09-24 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/cond_op_addsubmuldiv__Float16-1.c: New test.
+ * gcc.target/i386/cond_op_addsubmuldiv__Float16-2.c: Ditto.
+ * gcc.target/i386/cond_op_fma__Float16-1.c: Ditto.
+ * gcc.target/i386/cond_op_fma__Float16-2.c: Ditto.
+ * gcc.target/i386/cond_op_maxmin__Float16-1.c: Ditto.
+ * gcc.target/i386/cond_op_maxmin__Float16-2.c: Ditto.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101320
+ * gfortran.dg/c-interop/c516.f90: Remove xfails. Add more
+ tests.
+
+2021-09-23 Michel Morin <mimomorin@gmail.com>
+
+ PR c++/77565
+ * g++.dg/spellcheck-pr77565.C: New test.
+
+2021-09-23 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr102463.c: New.
+
+2021-09-23 Harald Anlauf <anlauf@gmx.de>
+ Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/93834
+ * gfortran.dg/coarray/coarray_allocated.f90: New test.
+
+2021-09-23 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ PR target/102024
+ * g++.target/powerpc/pr102024.C: New.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * g++.target/i386/avx512fp16-vcondmn-vec.C: New test.
+ * g++.target/i386/avx512fp16-vcondmn-minmax.C: Ditto.
+ * gcc.target/i386/avx512fp16-vcondmn-loop-1.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcondmn-loop-2.c: Ditto.
+ * gcc.target/i386/avx512fp16-vec_cmpmn.c: Ditto.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/avx512fp16-trunc-extendvnhf.c: New test.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/avx512fp16-floatvnhf.c: New test.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/avx512fp16-trunchf.c: New test.
+ * gcc.target/i386/avx512fp16-truncvnhf.c: Ditto.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/avx512fp16-builtin-minmax-1.c: New test.
+
+2021-09-23 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-fma-1.c: New test.
+ * gcc.target/i386/avx512fp16vl-fma-1.c: New test.
+ * gcc.target/i386/avx512fp16vl-fma-vectorize-1.c: New test.
+
+2021-09-23 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-builtin-round-1.c: Add new testcase.
+
+2021-09-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102413
+ * g++.dg/gomp/attrs-14.C: New test.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101319
+ * gfortran.dg/c-interop/assumed-type-dummy.f90: Remove xfail.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101334
+ * gfortran.dg/c-interop/c535b-2.f90: Remove xfails.
+ * gfortran.dg/c-interop/c535b-3.f90: Likewise.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ * gfortran.dg/assumed_rank_18.f90 (g): Wrap call to h in
+ select rank.
+ * gfortran.dg/assumed_type_10.f90 (test_array): Likewise for
+ call to test_lib.
+ * gfortran.dg/assumed_type_11.f90 (test_array): Likewise.
+
+2021-09-22 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * gfortran.dg/include_14.f90: Add -J testcase and update dg-output.
+ * gfortran.dg/include_15.f90: Likewise.
+ * gfortran.dg/include_16.f90: Likewise.
+ * gfortran.dg/include_17.f90: Likewise.
+ * gfortran.dg/include_18.f90: Likewise.
+ * gfortran.dg/include_19.f90: Likewise.
+
+2021-09-22 Roger Sayle <roger@nextmovesoftware.com>
+ Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/fold-negate-1.c: New test case.
+
+2021-09-22 H.J. Lu <hjl.tools@gmail.com>
+
+ * gcc.target/i386/auto-init-2.c: Replace ia32 with { ! lp64 }.
+ * gcc.target/i386/auto-init-3.c (dg-options): Add -msse.
+ (dg-additional-options): Add -mfpmath=387 for ia32.
+ Replace lp64 with { ! ia32 }. Add a space after ia32.
+ * gcc.target/i386/auto-init-4.c: Replace lp64 with { ! ia32 }.
+ * gcc.target/i386/auto-init-5.c: Likewise.
+ * gcc.target/i386/auto-init-padding-3.c: Likewise.
+ * gcc.target/i386/auto-init-padding-7.c: Likewise.
+ * gcc.target/i386/auto-init-padding-8.c: Likewise.
+ * gcc.target/i386/auto-init-padding-9.c: Likewise.
+
+2021-09-22 Patrick Palka <ppalka@redhat.com>
+
+ DR 2446
+ PR c++/102412
+ * g++.dg/cpp2a/concepts-nondep2.C: New test.
+ * g++.dg/cpp2a/concepts-nondep3.C: New test.
+
+2021-09-22 Jiufu Guo <guojiufu@linux.ibm.com>
+
+ PR tree-optimization/102087
+ * gcc.dg/pr102087.c: New test.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * gcc.target/i386/avx512fp16-14.c: New test.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * gcc.target/i386/avx512fp16-conjugation-1.c: New test.
+ * gcc.target/i386/avx512fp16vl-conjugation-1.c: New test.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * gcc.target/i386/avx512fp16-reduce-op-1.c: New test.
+ * gcc.target/i386/avx512fp16vl-reduce-op-1.c: Ditto.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * gcc.target/i386/avx512fp16-13.c: New test.
+
+2021-09-22 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * gcc.target/s390/pr102222.c: New test.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/102415
+ * c-c++-common/gomp/scope-3.c: New test.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/allocate-6.c: New test.
+ * c-c++-common/gomp/allocate-7.c: New test.
+ * g++.dg/gomp/allocate-4.C: New test.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512vl-pr95046.c: New test.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/pr92658-avx512f.c: Refine testcase.
+ * gcc.target/i386/pr92658-avx512vl.c: Adjust scan-assembler,
+ only v2di->v2qi truncate is not supported, v4di->v4qi should
+ be supported.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-builtin-fpcompare-1.c: New test.
+ * gcc.target/i386/avx512fp16-builtin-fpcompare-2.c: New test.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-builtin-round-1.c: New test.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-builtin-sqrt-1.c: New test.
+ * gcc.target/i386/avx512fp16vl-builtin-sqrt-1.c: New test.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-vfcmaddcsh-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vfcmaddcsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfcmulcsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfcmulcsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmaddcsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmaddcsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmulcsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmulcsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-complex-constraints.c: Ditto.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-helper.h
+ (init_src): Adjust init value.
+ (NET_CMASK): New net mask for complex input.
+ * gcc.target/i386/avx512fp16-vfcmaddcph-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vfcmaddcph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfcmulcph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfcmulcph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmaddcph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmaddcph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmulcph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmulcph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfcmaddcph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfcmaddcph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfcmulcph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmaddcph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmaddcph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmulcph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmulcph-1b.c: Ditto.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-22 Barrett Adair <barrettellisadair@gmail.com>
+
+ * g++.dg/cpp0x/constexpr-52830.C: Remove unwanted dg-ice.
+ * g++.dg/template/canon-type-15.C: New test.
+ * g++.dg/template/canon-type-16.C: New test.
+ * g++.dg/template/canon-type-17.C: New test.
+ * g++.dg/template/canon-type-18.C: New test.
+ * g++.dg/template/dependent-name15.C: New regression test.
+ * g++.dg/template/dependent-name16.C: New regression test.
+
+2021-09-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102421
+ * g++.dg/vect/pr102421.cc: New testcase.
+
+2021-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * lib/target-supports.exp (no_fsanitize_address): Add missing bits.
+ * gcc.dg/uninit-pr93100.c: Skip if no_fsanitize_address.
+ * gcc.dg/pr91441.c: Likewise.
+ * gcc.dg/pr96260.c: Likewise.
+ * gcc.dg/pr96307.c: Likewise.
+ * g++.dg/warn/uninit-pr93100.C: Likewise.
+ * gnat.dg/asan1.adb: Likewise.
+ * gcc.dg/Wstringop-overflow-70.c: Adjust for SPARC.
+ * g++.dg/abi/anon4.C: Likewise.
+
+2021-09-21 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/include_6.f90: Change dg-error to
+ dg-warning and update pattern.
+ * gfortran.dg/include_14.f90: New test.
+ * gfortran.dg/include_15.f90: New test.
+ * gfortran.dg/include_16.f90: New test.
+ * gfortran.dg/include_17.f90: New test.
+ * gfortran.dg/include_18.f90: New test.
+ * gfortran.dg/include_19.f90: New test.
+ * gfortran.dg/include_20.f90: New test.
+ * gfortran.dg/include_21.f90: New test.
+
+2021-09-21 wangpc <pc.wang@linux.alibaba.com>
+
+ * g++.target/aarch64/sve/static-var-in-template.C: New test.
+
2021-09-20 Andrew MacLeod <amacleod@redhat.com>
* gcc.dg/tree-ssa/evrp-ignore.c: New.
diff --git a/gcc/testsuite/c-c++-common/Waddress-3.c b/gcc/testsuite/c-c++-common/Waddress-3.c
new file mode 100644
index 0000000..9a13a44
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Waddress-3.c
@@ -0,0 +1,125 @@
+/* PR c/102103 - missing warning comparing array address to null
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __UINTPTR_TYPE__ uintptr_t;
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+struct S { void *p, *a1[2], *a2[2][2]; } s, *p;
+
+extern const void *a1[2];
+extern void *a2[2][2], *ax[];
+
+void T (bool);
+
+void test_array_eq_0 (int i)
+{
+ // Verify that casts intptr_t suppress the warning.
+ T ((intptr_t)a1 == 0);
+ T ((uintptr_t)a1 == 0);
+ T (a1 == 0); // { dg-warning "-Waddress" }
+ T (0 == &a1); // { dg-warning "-Waddress" }
+ // Verify that casts to other pointer types don't suppress it.
+ T ((void *)a1 == 0); // { dg-warning "-Waddress" }
+ T ((char *)a1 == 0); // { dg-warning "-Waddress" }
+ T (a1[0] == 0);
+ T (0 == (intptr_t)&a1[0]);
+ T (0 == &a1[0]); // { dg-warning "-Waddress" }
+ T (a1[i] == 0);
+ T (0 == (uintptr_t)&a1[i]);
+ T (0 == &a1[i]); // { dg-warning "-Waddress" }
+
+ T ((intptr_t)a2 == 0);
+ T (a2 == 0); // { dg-warning "-Waddress" }
+ T (0 == &a2); // { dg-warning "-Waddress" }
+ T (a2[0] == 0); // { dg-warning "-Waddress" }
+ T (0 == &a1[0]); // { dg-warning "-Waddress" }
+ T (a2[i] == 0); // { dg-warning "-Waddress" }
+ T (0 == &a2[i]); // { dg-warning "-Waddress" }
+ T (a2[0][0] == 0);
+ T (0 == &a2[0][0]); // { dg-warning "-Waddress" }
+ T (&ax == 0); // { dg-warning "-Waddress" }
+ T (0 == &ax); // { dg-warning "-Waddress" }
+ T (&ax[0] == 0); // { dg-warning "-Waddress" }
+ T (0 == ax[0]);
+}
+
+
+void test_array_neq_0 (int i)
+{
+ // Verify that casts to intptr_t suppress the warning.
+ T ((uintptr_t)a1);
+
+ T (a1); // { dg-warning "-Waddress" }
+ T ((void *)a1); // { dg-warning "-Waddress" }
+ T (&a1 != 0); // { dg-warning "-Waddress" }
+ T (a1[0]);
+ T (&a1[0] != 0); // { dg-warning "-Waddress" }
+ T (a1[i]);
+ T (&a1[i] != 0); // { dg-warning "-Waddress" }
+
+ T ((intptr_t)a2);
+ T (a2); // { dg-warning "-Waddress" }
+ T ((void *)a2); // { dg-warning "-Waddress" }
+ T ((char *)a2); // { dg-warning "-Waddress" }
+ T (&a2 != 0); // { dg-warning "-Waddress" }
+ T (a2[0]); // { dg-warning "-Waddress" }
+ T (&a1[0] != 0); // { dg-warning "-Waddress" }
+ T (a2[i]); // { dg-warning "-Waddress" }
+ T (&a2[i] != 0); // { dg-warning "-Waddress" }
+ T (a2[0][0]);
+ T (&a2[0][0] != 0); // { dg-warning "-Waddress" }
+}
+
+
+void test_member_array_eq_0 (int i)
+{
+ // Verify that casts to intptr_t suppress the warning.
+ T ((intptr_t)s.a1 == 0);
+ T (s.a1 == 0); // { dg-warning "-Waddress" }
+ T (0 == &a1); // { dg-warning "-Waddress" }
+ T (s.a1[0] == 0);
+ T ((void*)s.a1); // { dg-warning "-Waddress" }
+ T (0 == &a1[0]); // { dg-warning "-Waddress" }
+ T (s.a1[i] == 0);
+ T (0 == &a1[i]); // { dg-warning "-Waddress" }
+
+ T ((uintptr_t)s.a2 == 0);
+ T (s.a2 == 0); // { dg-warning "-Waddress" }
+ T (0 == &a2); // { dg-warning "-Waddress" }
+ T ((void *)s.a2 == 0);// { dg-warning "-Waddress" }
+ T (s.a2[0] == 0); // { dg-warning "-Waddress" }
+ T (0 == &a1[0]); // { dg-warning "-Waddress" }
+ T (s.a2[i] == 0); // { dg-warning "-Waddress" }
+ T (0 == &a2[i]); // { dg-warning "-Waddress" }
+ T (s.a2[0][0] == 0);
+ T (0 == &a2[0][0]); // { dg-warning "-Waddress" }
+}
+
+
+void test_member_array_neq_0 (int i)
+{
+ // Verify that casts to intptr_t suppress the warning.
+ T ((uintptr_t)s.a1);
+ T (s.a1); // { dg-warning "-Waddress" }
+ T (&s.a1 != 0); // { dg-warning "-Waddress" }
+ T ((void *)&s.a1[0]); // { dg-warning "-Waddress" }
+ T (s.a1[0]);
+ T (&s.a1[0] != 0); // { dg-warning "-Waddress" }
+ T (s.a1[i]);
+ T (&s.a1[i] != 0); // { dg-warning "-Waddress" }
+
+ T ((intptr_t)s.a2);
+ T (s.a2); // { dg-warning "-Waddress" }
+ T (&s.a2 != 0); // { dg-warning "-Waddress" }
+ T (s.a2[0]); // { dg-warning "-Waddress" }
+ T (&s.a1[0] != 0); // { dg-warning "-Waddress" }
+ T (s.a2[i]); // { dg-warning "-Waddress" }
+ T (&s.a2[i] != 0); // { dg-warning "-Waddress" }
+ T (s.a2[0][0]);
+ T (&s.a2[0][0] != 0); // { dg-warning "-Waddress" }
+}
diff --git a/gcc/testsuite/c-c++-common/Waddress-4.c b/gcc/testsuite/c-c++-common/Waddress-4.c
new file mode 100644
index 0000000..489a0cd
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Waddress-4.c
@@ -0,0 +1,106 @@
+/* PR c/102103 - missing warning comparing array address to null
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __INTPTR_TYPE__ uintptr_t;
+
+extern char *ax[], *a2[][2];
+
+void T (int);
+
+void test_ax_plus_eq_0 (int i)
+{
+ // Verify that casts to intptr_t suppress the warning.
+ T ((intptr_t)(ax + 0) == 0);
+ T ((uintptr_t)(ax + 1) == 0);
+
+ T (ax + 0 == 0); // { dg-warning "-Waddress" }
+ T (&ax[0] == 0); // { dg-warning "-Waddress" }
+ T (ax - 1 == 0); // { dg-warning "-Waddress" }
+ T (0 == &ax[-1]); // { dg-warning "-Waddress" }
+ T ((void *)(&ax[0] + 2) == 0); // { dg-warning "-Waddress" }
+ T (&ax[0] + 2 == 0); // { dg-warning "-Waddress" }
+ T (ax + 3 == 0); // { dg-warning "-Waddress" }
+ T (0 == &ax[-4]); // { dg-warning "-Waddress" }
+ T (ax - i == 0); // { dg-warning "-Waddress" }
+ T (&ax[i] == 0); // { dg-warning "-Waddress" }
+ T (0 == &ax[1] + i); // { dg-warning "-Waddress" }
+}
+
+void test_a2_plus_eq_0 (int i)
+{
+ // Verify that casts to intptr_t suppress the warning.
+ T ((intptr_t)(a2 + 0) == 0);
+ T ((uintptr_t)(a2 + 1) == 0);
+
+ T (a2 + 0 == 0); // { dg-warning "-Waddress" }
+ // Verify that a cast to another pointer type doesn't suppress it.
+ T ((void*)(a2 + 0) == 0); // { dg-warning "-Waddress" }
+ T ((char*)a2 + 1 == 0); // { dg-warning "-Waddress" }
+ T (&a2[0] == 0); // { dg-warning "-Waddress" }
+ T (a2 - 1 == 0); // { dg-warning "-Waddress" }
+ T (0 == &a2[-1]); // { dg-warning "-Waddress" }
+ T (a2 + 2 == 0); // { dg-warning "-Waddress" }
+ T (0 == &a2[-2]); // { dg-warning "-Waddress" }
+ T (a2 - i == 0); // { dg-warning "-Waddress" }
+ T (&a2[i] == 0); // { dg-warning "-Waddress" }
+}
+
+// Exercise a pointer.
+void test_p_plus_eq_0 (int *p, int i)
+{
+ /* P + 0 and equivalently &P[0] are invalid for a null P but they're
+ folded to p before the warning has a chance to trigger. */
+ T (p + 0 == 0); // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } }
+ T (&p[0] == 0); // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } }
+
+ T (p - 1 == 0); // { dg-warning "-Waddress" }
+ T (0 == &p[-1]); // { dg-warning "-Waddress" }
+ T (p + 2 == 0); // { dg-warning "-Waddress" }
+ T (0 == &p[-2]); // { dg-warning "-Waddress" }
+ T (p - i == 0); // { dg-warning "-Waddress" }
+ T (&p[i] == 0); // { dg-warning "-Waddress" }
+}
+
+// Exercise pointer to array.
+void test_pa_plus_eq_0 (int (*p)[], int (*p2)[][2], int i)
+{
+ // The array pointer may be null.
+ T (*p == 0);
+ /* &**P is equivalent to *P and might be the result od macro expansion.
+ Verify it doesn't cause a warning. */
+ T (&**p == 0);
+
+ /* *P + 0 is invalid but folded to *P before the warning has a chance
+ to trigger. */
+ T (*p + 0 == 0); // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } }
+
+ T (&(*p)[0] == 0); // { dg-warning "-Waddress" }
+ T (*p - 1 == 0); // { dg-warning "-Waddress" }
+ T (0 == &(*p)[-1]); // { dg-warning "-Waddress" }
+ T (*p + 2 == 0); // { dg-warning "-Waddress" }
+ T (0 == &(*p)[-2]); // { dg-warning "-Waddress" }
+ T (*p - i == 0); // { dg-warning "-Waddress" }
+ T (&(*p)[i] == 0); // { dg-warning "-Waddress" }
+
+
+ /* Similar to the above but for a pointer to a two-dimensional array,
+ referring to the higher-level element (i.e., an array itself). */
+ T (*p2 == 0);
+ T (**p2 == 0); // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } }
+ T (&**p2 == 0); // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } }
+ T (&***p2 == 0); // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } }
+ T (&**p2 == 0);
+
+ T (*p2 + 0 == 0); // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } }
+ T (&(*p2)[0] == 0); // { dg-warning "-Waddress" }
+ T (&(*p2)[0][1] == 0); // { dg-warning "-Waddress" }
+ T (*p2 - 1 == 0); // { dg-warning "-Waddress" }
+ T (0 == &(*p2)[-1]); // { dg-warning "-Waddress" }
+ T (0 == &(*p2)[1][2]); // { dg-warning "-Waddress" }
+ T (*p2 + 2 == 0); // { dg-warning "-Waddress" }
+ T (0 == &(*p2)[-2]); // { dg-warning "-Waddress" }
+ T (*p2 - i == 0); // { dg-warning "-Waddress" }
+ T (&(*p2)[i] == 0); // { dg-warning "-Waddress" }
+}
diff --git a/gcc/testsuite/c-c++-common/Warray-compare-1.c b/gcc/testsuite/c-c++-common/Warray-compare-1.c
new file mode 100644
index 0000000..922396c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Warray-compare-1.c
@@ -0,0 +1,44 @@
+/* PR c++/97573 */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+int arr1[5];
+int arr2[5];
+int arr3[2][2];
+int arr4[2][2];
+
+bool
+g ()
+{
+ bool b = arr1 == arr2; /* { dg-warning "comparison between two arrays" } */
+ b &= arr1 != arr2; /* { dg-warning "comparison between two arrays" } */
+ b &= arr1 > arr2; /* { dg-warning "comparison between two arrays" } */
+ b &= arr1 >= arr2; /* { dg-warning "comparison between two arrays" } */
+ b &= arr1 < arr2; /* { dg-warning "comparison between two arrays" } */
+ b &= arr1 <= arr2; /* { dg-warning "comparison between two arrays" } */
+#ifdef __cplusplus
+ b &= +arr1 == +arr2;
+ b &= +arr1 != +arr2;
+ b &= +arr1 > +arr2;
+ b &= +arr1 >= +arr2;
+ b &= +arr1 < +arr2;
+ b &= +arr1 <= +arr2;
+#endif
+ b &= &arr1[0] == &arr2[0];
+ b &= &arr1[0] != &arr2[0];
+ b &= &arr1[0] > &arr2[0];
+ b &= &arr1[0] >= &arr2[0];
+ b &= &arr1[0] < &arr2[0];
+ b &= &arr1[0] <= &arr2[0];
+
+ b &= arr3 == arr4; /* { dg-warning "comparison between two arrays" } */
+
+#if defined(__cplusplus) && __cplusplus > 201703L
+ auto cmp = arr1 <=> arr2; /* { dg-error "invalid operands" "" { target c++20 } } */
+#endif
+ return b;
+}
diff --git a/gcc/testsuite/c-c++-common/Warray-compare-2.c b/gcc/testsuite/c-c++-common/Warray-compare-2.c
new file mode 100644
index 0000000..b3688e6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Warray-compare-2.c
@@ -0,0 +1,44 @@
+/* PR c++/97573 */
+/* { dg-do compile } */
+/* { dg-options "-Wall -Wno-array-compare" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+int arr1[5];
+int arr2[5];
+int arr3[2][2];
+int arr4[2][2];
+
+bool
+g ()
+{
+ bool b = arr1 == arr2; /* { dg-bogus "comparison between two arrays" } */
+ b &= arr1 != arr2; /* { dg-bogus "comparison between two arrays" } */
+ b &= arr1 > arr2; /* { dg-bogus "comparison between two arrays" } */
+ b &= arr1 >= arr2; /* { dg-bogus "comparison between two arrays" } */
+ b &= arr1 < arr2; /* { dg-bogus "comparison between two arrays" } */
+ b &= arr1 <= arr2; /* { dg-bogus "comparison between two arrays" } */
+#ifdef __cplusplus
+ b &= +arr1 == +arr2;
+ b &= +arr1 != +arr2;
+ b &= +arr1 > +arr2;
+ b &= +arr1 >= +arr2;
+ b &= +arr1 < +arr2;
+ b &= +arr1 <= +arr2;
+#endif
+ b &= &arr1[0] == &arr2[0];
+ b &= &arr1[0] != &arr2[0];
+ b &= &arr1[0] > &arr2[0];
+ b &= &arr1[0] >= &arr2[0];
+ b &= &arr1[0] < &arr2[0];
+ b &= &arr1[0] <= &arr2[0];
+
+ b &= arr3 == arr4; /* { dg-bogus "comparison between two arrays" } */
+
+#if defined(__cplusplus) && __cplusplus > 201703L
+ auto cmp = arr1 <=> arr2; /* { dg-error "invalid operands" "" { target c++20 } } */
+#endif
+ return b;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-6.c b/gcc/testsuite/c-c++-common/gomp/allocate-6.c
new file mode 100644
index 0000000..059fd72
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/allocate-6.c
@@ -0,0 +1,84 @@
+typedef enum omp_allocator_handle_t
+#if __cplusplus >= 201103L
+: __UINTPTR_TYPE__
+#endif
+{
+ omp_null_allocator = 0,
+ omp_default_mem_alloc = 1,
+ omp_large_cap_mem_alloc = 2,
+ omp_const_mem_alloc = 3,
+ omp_high_bw_mem_alloc = 4,
+ omp_low_lat_mem_alloc = 5,
+ omp_cgroup_mem_alloc = 6,
+ omp_pteam_mem_alloc = 7,
+ omp_thread_mem_alloc = 8,
+ __omp_allocator_handle_t_max__ = __UINTPTR_MAX__
+} omp_allocator_handle_t;
+
+int bar (int, int *, int);
+omp_allocator_handle_t baz (void);
+
+void
+foo (int x, int z)
+{
+ int y[16] = { 0 }, r = 0, i;
+ omp_allocator_handle_t h = baz ();
+ #pragma omp parallel allocate (align (sizeof (int)) : x) allocate (allocator (omp_default_mem_alloc) : y) \
+ allocate (align (8), allocator ((omp_allocator_handle_t) omp_default_mem_alloc):z) firstprivate (x, y, z)
+ bar (x, y, z);
+ #pragma omp task private (x) firstprivate (z) allocate (allocator (omp_low_lat_mem_alloc) :x,z)
+ bar (0, &x, z);
+ #pragma omp taskwait
+ #pragma omp target teams distribute parallel for private (x) firstprivate (y) \
+ allocate (allocator ((omp_allocator_handle_t)(omp_default_mem_alloc + 0)), align (16) : z) \
+ allocate (allocator (omp_default_mem_alloc) : x, y) allocate (align (32), allocator (omp_low_lat_mem_alloc): r) \
+ lastprivate (z) reduction(+:r)
+ for (i = 0; i < 64; i++)
+ {
+ z = bar (0, &x, 0);
+ r += bar (1, y, 0);
+ }
+ #pragma omp single private (x) allocate (allocator (h):x)
+ ;
+ #pragma omp single allocate (align (2 * sizeof (int)), allocator (*&h) : x) private (x)
+ ;
+ #pragma omp parallel shared (r, x, z)
+ #pragma omp single firstprivate (r) allocate (align (4) : x, r, z) private (x, z)
+ ;
+ #pragma omp for allocate (align (2 * 2 * 2) : x) private (x)
+ for (i = 0; i < 64; i++)
+ x = 1;
+ #pragma omp sections private (x) allocate (allocator (omp_low_lat_mem_alloc), align (8): x)
+ {
+ x = 1;
+ #pragma omp section
+ x = 2;
+ #pragma omp section
+ x = 3;
+ }
+ #pragma omp taskgroup task_reduction(+:r) allocate (allocator (omp_default_mem_alloc), align (__alignof (r)) : r)
+ #pragma omp task in_reduction(+:r) allocate (align (2 * sizeof (r)), allocator (omp_default_mem_alloc) : r)
+ r += bar (r, &r, 0);
+ #pragma omp teams private (x) firstprivate (y) allocate (allocator (h), align (8) : x, y)
+ bar (x, y, 0);
+ #pragma omp taskloop lastprivate (x) reduction (+:r) allocate (align (16), allocator (h) : x, r)
+ for (i = 0; i < 16; i++)
+ {
+ r += bar (0, &r, 0);
+ x = i;
+ }
+ #pragma omp taskgroup task_reduction(+:r) allocate (allocator (omp_default_mem_alloc), align (64) : r)
+ #pragma omp taskloop firstprivate (x) in_reduction (+:r) \
+ allocate (allocator (omp_default_mem_alloc), align (128) : x, r)
+ for (i = 0; i < 16; i++)
+ r += bar (x, &r, 0);
+ #pragma omp taskwait
+}
+
+void
+qux (const omp_allocator_handle_t h)
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (align (16), allocator (h): x)
+ x = 1;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-7.c b/gcc/testsuite/c-c++-common/gomp/allocate-7.c
new file mode 100644
index 0000000..d125d92
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/allocate-7.c
@@ -0,0 +1,41 @@
+typedef enum omp_allocator_handle_t
+#if __cplusplus >= 201103L
+: __UINTPTR_TYPE__
+#endif
+{
+ omp_null_allocator = 0,
+ omp_default_mem_alloc = 1,
+ omp_large_cap_mem_alloc = 2,
+ omp_const_mem_alloc = 3,
+ omp_high_bw_mem_alloc = 4,
+ omp_low_lat_mem_alloc = 5,
+ omp_cgroup_mem_alloc = 6,
+ omp_pteam_mem_alloc = 7,
+ omp_thread_mem_alloc = 8,
+ __omp_allocator_handle_t_max__ = __UINTPTR_MAX__
+} omp_allocator_handle_t;
+
+int bar (int *);
+omp_allocator_handle_t baz (void);
+
+void
+foo (int x, int z)
+{
+ int i;
+ #pragma omp parallel private (x) allocate (allocator (0.0) : x) /* { dg-error "'allocate' clause allocator expression has type 'double' rather than 'omp_allocator_handle_t'" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (allocator (0) : x) /* { dg-error "'allocate' clause allocator expression has type 'int' rather than 'omp_allocator_handle_t'" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (align (z) : x) /* { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (align (16.0) : x) /* { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (align (14) : x) /* { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (align (0) : x) /* { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (align (16), align (16) : x) /* { dg-error "expected|duplicate|declared|specified" } */
+ bar (&x); /* { dg-warning "more than once" "" { target c++ } .-1 } */
+ #pragma omp parallel private (x) allocate (allocator (omp_default_mem_alloc), allocator (omp_default_mem_alloc) : x) /* { dg-error "expected|duplicate|declared|specified" } */
+ bar (&x); /* { dg-warning "more than once" "" { target c++ } .-1 } */
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/scope-3.c b/gcc/testsuite/c-c++-common/gomp/scope-3.c
new file mode 100644
index 0000000..78bb1a3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/scope-3.c
@@ -0,0 +1,21 @@
+/* PR middle-end/102415 */
+
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort ();
+
+void
+foo (void)
+{
+ #pragma omp scope nowait
+ abort ();
+}
+
+void
+bar (void)
+{
+ #pragma omp scope
+ abort ();
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/scope-4.c b/gcc/testsuite/c-c++-common/gomp/scope-4.c
new file mode 100644
index 0000000..924ae9c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/scope-4.c
@@ -0,0 +1,11 @@
+/* PR middle-end/102504 */
+/* { dg-do compile } */
+
+int
+foo ()
+{
+ int r = 0;
+ #pragma omp scope reduction(+:r) /* { dg-error "reduction variable 'r' is private in outer context" } */
+ r++;
+ return r;
+}
diff --git a/gcc/testsuite/c-c++-common/pr102285.c b/gcc/testsuite/c-c++-common/pr102285.c
new file mode 100644
index 0000000..644054b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr102285.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O -ftrivial-auto-var-init=zero -Wuninitialized" } */
+
+int
+qy (void)
+{
+ int tw = 4;
+ int fb[tw];
+ return fb[2]; /* { dg-warning "uninitialized" } */
+}
diff --git a/gcc/testsuite/c-c++-common/tsan/atomic_stack.c b/gcc/testsuite/c-c++-common/tsan/atomic_stack.c
index 746afa7..09ac7c7 100644
--- a/gcc/testsuite/c-c++-common/tsan/atomic_stack.c
+++ b/gcc/testsuite/c-c++-common/tsan/atomic_stack.c
@@ -31,5 +31,4 @@ int main() {
/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */
/* { dg-output " Atomic write of size 4.*" } */
-/* { dg-output " #0 __tsan_atomic32_fetch_add.*" } */
-/* { dg-output " #1 Thread1.*" } */
+/* { dg-output " #0 Thread1.*" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-3.c b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-3.c
index 266423a..1d51e35 100644
--- a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-3.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-overflow" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-overflow" } */
#include <limits.h>
diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-4.c b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-4.c
index 02162e1..ef431c9 100644
--- a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-4.c
+++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-4.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-overflow" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -fsanitize-undefined-trap-on-error -Wno-overflow" } */
#define INT_MIN (-__INT_MAX__ - 1)
diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c
index bb391c5..853a3dc 100644
--- a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c
+++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-fsanitize=integer-divide-by-zero" } */
+/* { dg-options "-fsanitize=signed-integer-overflow" } */
void
foo (void)
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-div-by-zero-2.c b/gcc/testsuite/c-c++-common/ubsan/float-div-by-zero-2.c
new file mode 100644
index 0000000..61d050a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/float-div-by-zero-2.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-options "-fsanitize=float-divide-by-zero -fno-sanitize-recover=float-divide-by-zero -fsanitize-recover=integer-divide-by-zero" } */
+
+int
+main (void)
+{
+ volatile float a = 1.3f;
+ volatile double b = 0.0;
+ volatile int c = 4;
+ volatile float res;
+
+ res = a / b;
+
+ return 0;
+}
+
+/* { dg-output "division by zero" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-div-1.c b/gcc/testsuite/c-c++-common/ubsan/overflow-div-1.c
new file mode 100644
index 0000000..d781660
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-div-1.c
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=integer-divide-by-zero -fno-sanitize-recover=undefined,float-divide-by-zero -Wno-overflow" } */
+
+#include <limits.h>
+
+int
+main (void)
+{
+ volatile int min = INT_MIN;
+ volatile int zero = 0;
+
+ INT_MIN / -1;
+ min / -1;
+ min / (10 * zero - (2 - 1));
+
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-div-2.c b/gcc/testsuite/c-c++-common/ubsan/overflow-div-2.c
new file mode 100644
index 0000000..dfef1b0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-div-2.c
@@ -0,0 +1,41 @@
+/* { dg-do run { target *-*-linux* *-*-gnu* } } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=integer-divide-by-zero" } */
+
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+
+int cnt;
+
+__attribute__((noipa)) int
+foo (int x, int y)
+{
+ return x / y;
+}
+
+void
+handler (int i)
+{
+ if (cnt++ != 0)
+ exit (0);
+ volatile int b = foo (5, 0);
+ exit (0);
+}
+
+int
+main (void)
+{
+ struct sigaction s;
+ sigemptyset (&s.sa_mask);
+ s.sa_handler = handler;
+ s.sa_flags = 0;
+ sigaction (SIGFPE, &s, NULL);
+ volatile int a = foo (INT_MIN, -1);
+ cnt++;
+ volatile int b = foo (5, 0);
+ return 0;
+}
+
+/* { dg-output "division of -2147483648 by -1 cannot be represented in type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*division by zero\[^\n\r]*" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-div-3.c b/gcc/testsuite/c-c++-common/ubsan/overflow-div-3.c
new file mode 100644
index 0000000..479dffb
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-div-3.c
@@ -0,0 +1,41 @@
+/* { dg-do run { target *-*-linux* *-*-gnu* } } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=signed-integer-overflow" } */
+
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+
+int cnt;
+
+__attribute__((noipa)) int
+foo (int x, int y)
+{
+ return x / y;
+}
+
+void
+handler (int i)
+{
+ if (cnt++ != 0)
+ exit (0);
+ volatile int b = foo (INT_MIN, -1);
+ exit (0);
+}
+
+int
+main (void)
+{
+ struct sigaction s;
+ sigemptyset (&s.sa_mask);
+ s.sa_handler = handler;
+ s.sa_flags = 0;
+ sigaction (SIGFPE, &s, NULL);
+ volatile int a = foo (42, 0);
+ cnt++;
+ volatile int b = foo (INT_MIN, -1);
+ return 0;
+}
+
+/* { dg-output "division by zero\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*division of -2147483648 by -1 cannot be represented in type 'int'" } */
diff --git a/gcc/testsuite/g++.dg/Walloca2.C b/gcc/testsuite/g++.dg/Walloca2.C
new file mode 100644
index 0000000..b6992d0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/Walloca2.C
@@ -0,0 +1,6 @@
+// { dg-do compile }
+// { dg-options "-Walloca-larger-than=4207115063 -Wvla-larger-than=1233877270 -O2 --param ggc-min-heapsize=0 --param ggc-min-expand=0 -w" }
+// { dg-require-effective-target alloca }
+
+int a;
+char *b = static_cast<char *>(__builtin_alloca (a));
diff --git a/gcc/testsuite/g++.dg/coroutines/pr100673.C b/gcc/testsuite/g++.dg/coroutines/pr100673.C
new file mode 100644
index 0000000..750ce66
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr100673.C
@@ -0,0 +1,18 @@
+// { dg-additional-options "-fsyntax-only -w" }
+
+// Diagnose bad coroutine awatiable type.
+
+#include<coroutine>
+
+struct coro{
+ struct not_a_template{};
+ using promise_type = coro;
+ static constexpr std::suspend_always initial_suspend()noexcept{ return {}; }
+ constexpr bool await_ready()noexcept{ return false; }
+ constexpr not_a_template await_suspend(std::coroutine_handle<>)noexcept{ return{}; }
+ constexpr void await_resume()noexcept{}
+ static coro body()
+ {
+ co_await coro{}; // { dg-error {'await_suspend' must return 'void', 'bool' or a coroutine handle} }
+ }
+};
diff --git a/gcc/testsuite/g++.dg/coroutines/pr101133.C b/gcc/testsuite/g++.dg/coroutines/pr101133.C
new file mode 100644
index 0000000..6c6bc16
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr101133.C
@@ -0,0 +1,31 @@
+#include <coroutine>
+#include <string>
+
+template<typename T>
+struct Awaiter
+{
+ bool await_ready() const { return false; }
+ void await_suspend(std::coroutine_handle<>) const {}
+ T await_resume() const { return T{}; }
+};
+
+struct ReturnObject
+{
+ struct promise_type
+ {
+ ReturnObject get_return_object() { return {}; }
+ std::suspend_never initial_suspend() noexcept { return {}; }
+ std::suspend_never final_suspend() noexcept { return {}; }
+ void return_void() {}
+ void unhandled_exception() {}
+ };
+};
+
+ReturnObject f()
+{
+ auto a1 = Awaiter<int>{};
+ auto a2 = Awaiter<std::string>{};
+
+ [[maybe_unused]] auto v1 = co_await a1; // ok
+ [[maybe_unused]] std::string v2 = co_await a2; // error
+}
diff --git a/gcc/testsuite/g++.dg/coroutines/pr101765.C b/gcc/testsuite/g++.dg/coroutines/pr101765.C
new file mode 100644
index 0000000..49a49d1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr101765.C
@@ -0,0 +1,45 @@
+// We cannot compile this yet, much run it - but one day it might be
+// feasible, so do the minimum for now.
+// { dg-additional-options " -fsyntax-only -Wno-vla" }
+
+#include "coro.h"
+
+// boiler-plate for tests of codegen
+#include "coro1-ret-int-yield-int.h"
+
+struct coro1
+foo (int arg) noexcept
+{
+ PRINTF ("foo arg = %d\n", arg);
+ char arr[arg]; /* { dg-message "sorry, unimplemented: variable length arrays are not yet supported in coroutines" "" { target *-*-* } } */
+ if (arg < 4)
+ co_return -6174;
+ else
+ for (int i = 0; i < arg; ++i) arr[i] = (char) i;
+ co_yield (int) arr[2];
+ co_return (int) arr[3];
+}
+
+int main ()
+{
+ PRINT ("main: create coro1");
+ struct coro1 x = foo (10);
+ PRINT ("main: got coro1 - resuming");
+ if (x.handle.done())
+ abort();
+ x.handle.resume();
+ PRINT ("main: after resume");
+ int y = x.handle.promise().get_value();
+ if ( y == -6174 )
+ {
+ PRINT ("main: saw -6174");
+ return 1;
+ }
+ else if ( y != 2 )
+ abort;
+ x.handle.resume();
+ y = x.handle.promise().get_value();
+ if ( y != 3 )
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/coroutines/pr102454.C b/gcc/testsuite/g++.dg/coroutines/pr102454.C
new file mode 100644
index 0000000..41aeda7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr102454.C
@@ -0,0 +1,38 @@
+// { dg-additional-options "-fno-exceptions" }
+
+#include <coroutine>
+#include <string>
+
+template <typename T>
+struct looper {
+ struct promise_type {
+ auto get_return_object () { return handle_type::from_promise (*this); }
+ auto initial_suspend () { return suspend_always_prt {}; }
+ auto final_suspend () noexcept { return suspend_always_prt {}; }
+ void return_value (T);
+ void unhandled_exception ();
+ };
+
+ using handle_type = std::coroutine_handle<promise_type>;
+
+ looper (handle_type);
+
+ struct suspend_always_prt {
+ bool await_ready () noexcept;
+ void await_suspend (handle_type) noexcept;
+ void await_resume () noexcept;
+ };
+};
+
+template <typename T>
+looper<T>
+with_ctorable_state (T)
+{
+ co_return T ();
+}
+
+auto
+foo ()
+{
+ return with_ctorable_state<std::string>;
+}
diff --git a/gcc/testsuite/g++.dg/coroutines/pr99575.C b/gcc/testsuite/g++.dg/coroutines/pr99575.C
new file mode 100644
index 0000000..d5f86c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr99575.C
@@ -0,0 +1,35 @@
+
+#include <coroutine>
+
+class Task {
+ public:
+ struct promise_type {
+ Task get_return_object() { return Task{}; }
+ std::suspend_always initial_suspend() { return {}; }
+ std::suspend_always final_suspend() noexcept { return {}; }
+ void unhandled_exception() {}
+ void return_void() {}
+ };
+
+ bool await_ready() const { return false; }
+ void await_suspend(std::coroutine_handle<void> continuation) {}
+ void await_resume() {}
+};
+
+class NonMoveableTask {
+ public:
+ NonMoveableTask() = default;
+ NonMoveableTask(const NonMoveableTask&) = delete;
+ NonMoveableTask(NonMoveableTask&&) = delete;
+
+ NonMoveableTask& operator=(const NonMoveableTask&) = delete;
+ NonMoveableTask& operator=(NonMoveableTask&& other) = delete;
+
+ bool await_ready() const { return false; }
+ void await_suspend(std::coroutine_handle<void>) {}
+ void await_resume() {}
+};
+
+Task Foo(NonMoveableTask* task) { co_await* task; }
+
+int main() {}
diff --git a/gcc/testsuite/g++.dg/coroutines/pr99710.C b/gcc/testsuite/g++.dg/coroutines/pr99710.C
new file mode 100644
index 0000000..e4f7116
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr99710.C
@@ -0,0 +1,25 @@
+#include <coroutine>
+
+struct task {
+ struct promise_type {
+ std::suspend_always initial_suspend();
+ std::suspend_always final_suspend() noexcept;
+ task get_return_object();
+ void return_void();
+ void unhandled_exception();
+ };
+};
+
+task
+my_coro ()
+{
+ try
+ { }
+ catch (...)
+ {
+ // [expr.await] An await-expression shall appear only in a potentially-
+ // evaluated expression within the compound-statement of a function-body
+ // outside of a handler
+ co_await std::suspend_always{}; // { dg-error "await expressions are not permitted in handlers" }
+ }
+}
diff --git a/gcc/testsuite/g++.dg/cpp/elifdef-1.C b/gcc/testsuite/g++.dg/cpp/elifdef-1.C
new file mode 100644
index 0000000..f7965e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/elifdef-1.C
@@ -0,0 +1,3 @@
+// { dg-do preprocess { target { ! c++23 } } }
+
+#include "../../gcc.dg/cpp/c11-elifdef-1.c"
diff --git a/gcc/testsuite/g++.dg/cpp/elifdef-2.C b/gcc/testsuite/g++.dg/cpp/elifdef-2.C
new file mode 100644
index 0000000..6408271
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/elifdef-2.C
@@ -0,0 +1,4 @@
+// P2334R1
+// { dg-do preprocess { target c++23 } }
+
+#include "../../gcc.dg/cpp/c2x-elifdef-1.c"
diff --git a/gcc/testsuite/g++.dg/cpp/elifdef-3.C b/gcc/testsuite/g++.dg/cpp/elifdef-3.C
new file mode 100644
index 0000000..d9acce0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/elifdef-3.C
@@ -0,0 +1,62 @@
+// P2334R1
+// { dg-do preprocess { target c++23 } }
+
+#define A
+#undef B
+
+#elifdef A // { dg-error "#elifdef without #if" }
+#elifdef B // { dg-error "#elifdef without #if" }
+#elifndef A // { dg-error "#elifndef without #if" }
+#elifndef B // { dg-error "#elifndef without #if" }
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifdef A // { dg-error "#elifdef after #else" }
+#endif
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifdef B // { dg-error "#elifdef after #else" }
+#endif
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifndef A // { dg-error "#elifndef after #else" }
+#endif
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifndef B // { dg-error "#elifndef after #else" }
+#endif
+
+#if 0
+#elifdef A = // { dg-error "extra tokens at end of #elifdef directive" }
+#endif
+
+#if 0
+#elifdef B = // { dg-error "extra tokens at end of #elifdef directive" }
+#endif
+
+#if 0
+#elifndef A = // { dg-error "extra tokens at end of #elifndef directive" }
+#endif
+
+#if 0
+#elifndef B = // { dg-error "extra tokens at end of #elifndef directive" }
+#endif
+
+#if 0
+#elifdef // { dg-error "no macro name given in #elifdef directive" }
+#endif
+
+#if 0
+#elifndef // { dg-error "no macro name given in #elifndef directive" }
+#endif
+
+#if 0
+#elifdef , // { dg-error "macro names must be identifiers" }
+#endif
+
+#if 0
+#elifndef , // { dg-error "macro names must be identifiers" }
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp/elifdef-4.C b/gcc/testsuite/g++.dg/cpp/elifdef-4.C
new file mode 100644
index 0000000..08edf58
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/elifdef-4.C
@@ -0,0 +1,5 @@
+// P2334R1
+// { dg-do preprocess }
+// { dg-options "" }
+
+#include "../../gcc.dg/cpp/c2x-elifdef-1.c"
diff --git a/gcc/testsuite/g++.dg/cpp/elifdef-5.C b/gcc/testsuite/g++.dg/cpp/elifdef-5.C
new file mode 100644
index 0000000..f7d4007
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/elifdef-5.C
@@ -0,0 +1,63 @@
+// P2334R1
+// { dg-do preprocess }
+// { dg-options "" }
+
+#define A
+#undef B
+
+#elifdef A // { dg-error "#elifdef without #if" }
+#elifdef B // { dg-error "#elifdef without #if" }
+#elifndef A // { dg-error "#elifndef without #if" }
+#elifndef B // { dg-error "#elifndef without #if" }
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifdef A // { dg-error "#elifdef after #else" }
+#endif
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifdef B // { dg-error "#elifdef after #else" }
+#endif
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifndef A // { dg-error "#elifndef after #else" }
+#endif
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifndef B // { dg-error "#elifndef after #else" }
+#endif
+
+#if 0
+#elifdef A = // { dg-warning "extra tokens at end of #elifdef directive" }
+#endif
+
+#if 0
+#elifdef B = // { dg-warning "extra tokens at end of #elifdef directive" }
+#endif
+
+#if 0
+#elifndef A = // { dg-warning "extra tokens at end of #elifndef directive" }
+#endif
+
+#if 0
+#elifndef B = // { dg-warning "extra tokens at end of #elifndef directive" }
+#endif
+
+#if 0
+#elifdef // { dg-error "no macro name given in #elifdef directive" }
+#endif
+
+#if 0
+#elifndef // { dg-error "no macro name given in #elifndef directive" }
+#endif
+
+#if 0
+#elifdef , // { dg-error "macro names must be identifiers" }
+#endif
+
+#if 0
+#elifndef , // { dg-error "macro names must be identifiers" }
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp/elifdef-6.C b/gcc/testsuite/g++.dg/cpp/elifdef-6.C
new file mode 100644
index 0000000..94d2118
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/elifdef-6.C
@@ -0,0 +1,65 @@
+// P2334R1
+// { dg-do preprocess }
+// { dg-options "-pedantic" }
+
+#define A
+#undef B
+
+#if 0
+#elifdef A // { dg-warning "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#define M1 1
+#endif
+
+#if M1 != 1
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifdef B
+#error "#elifdef B applied"
+#endif
+
+#if 0
+#elifndef A
+#error "#elifndef A applied"
+#endif
+
+#if 0
+#elifndef B // { dg-warning "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#define M2 2
+#endif
+
+#if M2 != 2
+#error "#elifndef B did not apply"
+#endif
+
+#if 0
+#elifdef A // { dg-warning "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#else
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifndef B // { dg-warning "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#else
+#error "#elifndef B did not apply"
+#endif
+
+#if 1
+#elifdef A // { dg-warning "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
+
+#if 1
+#elifndef B // { dg-warning "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
+
+// As with #elif, the syntax of the new directives is relaxed after a
+ non-skipped group.
+
+#if 1
+#elifdef x * y // { dg-warning "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
+
+#if 1
+#elifndef ! // { dg-warning "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp/elifdef-7.C b/gcc/testsuite/g++.dg/cpp/elifdef-7.C
new file mode 100644
index 0000000..bb9b8ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/elifdef-7.C
@@ -0,0 +1,65 @@
+// P2334R1
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+
+#define A
+#undef B
+
+#if 0
+#elifdef A // { dg-error "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#define M1 1
+#endif
+
+#if M1 != 1
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifdef B
+#error "#elifdef B applied"
+#endif
+
+#if 0
+#elifndef A
+#error "#elifndef A applied"
+#endif
+
+#if 0
+#elifndef B // { dg-error "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#define M2 2
+#endif
+
+#if M2 != 2
+#error "#elifndef B did not apply"
+#endif
+
+#if 0
+#elifdef A // { dg-error "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#else
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifndef B // { dg-error "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#else
+#error "#elifndef B did not apply"
+#endif
+
+#if 1
+#elifdef A // { dg-error "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
+
+#if 1
+#elifndef B // { dg-error "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
+
+// As with #elif, the syntax of the new directives is relaxed after a
+ non-skipped group.
+
+#if 1
+#elifdef x * y // { dg-error "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
+
+#if 1
+#elifndef ! // { dg-error "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C
index eae0d8c..d6057f1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C
@@ -1,7 +1,6 @@
// PR c++/52830
// { dg-do compile { target c++11 } }
// { dg-additional-options "-fchecking" }
-// { dg-ice "comptypes" }
template<bool b> struct eif { typedef void type; };
template<> struct eif<false> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C
index 5224bb1..6329523 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C
@@ -85,8 +85,11 @@ extern __attribute__ ((weak)) int i;
constexpr int *p1 = &i + 1;
#pragma GCC diagnostic push
+// Suppress warning: ordered comparison of pointer with integer zero.
#pragma GCC diagnostic ignored "-Wextra"
-// Suppress warning: ordered comparison of pointer with integer zero
+// Also suppress -Waddress for comparisons of constant addresses to
+// to null.
+#pragma GCC diagnostic ignored "-Waddress"
constexpr bool b0 = p1; // { dg-error "not a constant expression" }
constexpr bool b1 = p1 == 0; // { dg-error "not a constant expression" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-partial2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-partial2.C
new file mode 100644
index 0000000..df61f26
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-partial2.C
@@ -0,0 +1,16 @@
+// PR c++/102547
+// { dg-do compile { target c++11 } }
+
+template<int... Vs>
+struct vals { };
+
+template<class V, class T>
+struct vals_client { };
+
+template<int V0, int V1, class T>
+struct vals_client<vals<V0, V1>, T> { };
+
+template<int V0, int V1>
+struct vals_client<vals<V0, V1>, void> { };
+
+template struct vals_client<vals<1, 2>, void>; //- "sorry, unimplemented..., ICE"
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-partial2a.C b/gcc/testsuite/g++.dg/cpp0x/variadic-partial2a.C
new file mode 100644
index 0000000..e98bdbb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-partial2a.C
@@ -0,0 +1,22 @@
+// PR c++/102547
+// { dg-do compile { target c++11 } }
+// A version of variadic-partial2.C where partial ordering is performed
+// on function templates instead of class templates.
+
+template<int... Vs>
+struct vals { };
+
+template<class V, class T>
+void f(V, T) { };
+
+template<int V0, int V1, class T>
+void f(vals<V0, V1>, T) { };
+
+template<int V0, int V1>
+void f(vals<V0, V1>, char) { };
+
+template void f(vals<1, 2>, char); //- "sorry, unimplemented..., ICE"
+
+int main() {
+ f(vals<1, 3>{}, 'a'); //- "sorry, unimplemented..., ICE"
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-label.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-label.C
index a2d113c..4994008 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-label.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-label.C
@@ -4,6 +4,6 @@
constexpr int
f ()
{
-x: // { dg-error "label definition is not a constant expression" }
+x: // { dg-error "label definition in 'constexpr' function only available with" "" { target c++20_down } }
return 42;
}
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C
index 53f0f1f..8e9d1ea 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C
@@ -4,12 +4,12 @@ struct A { A(); };
constexpr int f(int i) {
static int j = i; // { dg-error "static" }
- thread_local int l = i; // { dg-error "thread_local" }
- goto foo; // { dg-error "goto" }
+ thread_local int l = i; // { dg-error "thread_local" "" { target c++20_down } }
+ goto foo; // { dg-error "goto" "" { target c++20_down } }
foo:
asm("foo"); // { dg-error "asm" "" { target c++17_down } }
int k; // { dg-error "uninitialized" "" { target c++17_down } }
- A a; // { dg-error "non-literal" }
+ A a; // { dg-error "non-literal" "" { target c++20_down } }
return i;
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction12.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction12.C
index a31cc15..f0d7ea0 100644
--- a/gcc/testsuite/g++.dg/cpp1z/class-deduction12.C
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction12.C
@@ -15,3 +15,9 @@ A a(&i,2,B<42>());
template <class,class> class same;
template <class T> class same<T,T> {};
same<decltype(a), A<int*>> s;
+
+#if __cpp_deduction_guides >= 201907
+template <class T> using C = A<const T*>;
+
+same<decltype(C(&i, 2, B<42>())), A<const int*>> t;
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction99.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction99.C
new file mode 100644
index 0000000..6daa4b7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction99.C
@@ -0,0 +1,35 @@
+// PR c++/102479
+// { dg-do compile { target c++17 } }
+
+template<class T> struct A;
+
+template<class T>
+struct tuple {
+ tuple(T);
+
+ template<template<class> class Tmpl>
+ tuple(Tmpl<T>);
+
+ template<template<class> class Tmpl, typename A<Tmpl<char>>::type = 0>
+ tuple(Tmpl<T>);
+
+ template<template<class> class Tmpl, typename A<Tmpl<long>>::type = 0>
+ tuple(Tmpl<T>);
+};
+
+template<class T> struct B { };
+
+using ty1 = tuple<int>;
+using ty1 = decltype(tuple(0));
+using ty1 = decltype(tuple(B<int>{}));
+
+#if __cpp_deduction_guides >= 201907
+template<class T> using const_tuple = tuple<const T>;
+
+using ty2 = const_tuple<int>;
+using ty2 = decltype(const_tuple(0));
+using ty2 = decltype(const_tuple(B<const int>{}));
+
+using ty3 = const_tuple<B<int>>;
+using ty3 = decltype(const_tuple(B<int>{}));
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype4.C b/gcc/testsuite/g++.dg/cpp1z/nontype4.C
new file mode 100644
index 0000000..ff476dc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/nontype4.C
@@ -0,0 +1,14 @@
+// PR c++/98930
+// { dg-do compile { target c++17 } }
+
+template<int*>
+struct A { A() { } };
+
+template<class T>
+void impl() {
+ static int i;
+ static A<&i> a;
+}
+
+template void impl<int>();
+template void impl<char>();
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype4a.C b/gcc/testsuite/g++.dg/cpp1z/nontype4a.C
new file mode 100644
index 0000000..5b74292
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/nontype4a.C
@@ -0,0 +1,14 @@
+// PR c++/98930
+// { dg-do compile { target c++17 } }
+
+template<int*>
+struct A { };
+
+template<class T>
+auto impl() {
+ static int i;
+ return A<&i>();
+}
+
+using type = decltype(impl<int>());
+using type = decltype(impl<char>()); // { dg-error "conflicting declaration" }
diff --git a/gcc/testsuite/g++.dg/cpp23/charlit-encoding1.C b/gcc/testsuite/g++.dg/cpp23/charlit-encoding1.C
new file mode 100644
index 0000000..736f022
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/charlit-encoding1.C
@@ -0,0 +1,33 @@
+// PR c++/102615 - P2316R2 - Consistent character literal encoding
+// { dg-do run }
+
+extern "C" void abort ();
+
+int
+main ()
+{
+#if ' ' == 0x20
+ if (' ' != 0x20)
+ abort ();
+#elif ' ' == 0x40
+ if (' ' != 0x40)
+ abort ();
+#else
+ if (' ' == 0x20 || ' ' == 0x40)
+ abort ();
+#endif
+#if 'a' == 0x61
+ if ('a' != 0x61)
+ abort ();
+#elif 'a' == 0x81
+ if ('a' != 0x81)
+ abort ();
+#elif 'a' == -0x7F
+ if ('a' != -0x7F)
+ abort ();
+#else
+ if ('a' == 0x61 || 'a' == 0x81 || 'a' == -0x7F)
+ abort ();
+#endif
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C
new file mode 100644
index 0000000..c80ea38
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C
@@ -0,0 +1,68 @@
+// P2242R3
+// { dg-do compile { target c++14 } }
+
+constexpr int
+foo ()
+{
+lab: // { dg-error "label definition in 'constexpr' function only available with" "" { target c++20_down } }
+ return 1;
+}
+
+constexpr int
+bar (int x)
+{
+ if (x)
+ goto lab; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } }
+ return 1;
+lab:
+ return 0;
+}
+
+constexpr int
+baz (int x)
+{
+ if (!x)
+ return 1;
+ static int a; // { dg-error "'a' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } }
+ return ++a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } .-1 }
+}
+
+constexpr int
+qux (int x)
+{
+ if (!x)
+ return 1;
+ thread_local int a; // { dg-error "'a' declared 'thread_local' in 'constexpr' function only available with" "" { target c++20_down } }
+ return ++a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } .-1 }
+}
+
+constexpr int
+garply (int x)
+{
+ if (!x)
+ return 1;
+ extern thread_local int a; // { dg-error "'a' declared 'thread_local' in 'constexpr' function only available with" "" { target c++20_down } }
+ return ++a;
+}
+
+struct S { S (); ~S (); int s; }; // { dg-message "'S' is not literal because:" "" { target c++20_down } }
+ // { dg-message "'S' has a non-trivial destructor" "" { target c++17_down } .-1 }
+ // { dg-message "'S' does not have 'constexpr' destructor" "" { target { c++20_only } } .-2 }
+
+constexpr int
+corge (int x)
+{
+ if (!x)
+ return 1;
+ S s; // { dg-error "variable 's' of non-literal type 'S' in 'constexpr' function only available with" "" { target c++20_down } }
+ return 0;
+}
+
+#if __cpp_constexpr >= 202110L
+static_assert (foo ());
+static_assert (bar (0));
+static_assert (baz (0));
+static_assert (qux (0));
+static_assert (garply (0));
+static_assert (corge (0));
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C
new file mode 100644
index 0000000..0f7b229
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C
@@ -0,0 +1,54 @@
+// P2242R3
+// { dg-do compile }
+// { dg-options "-std=c++2b" }
+
+constexpr int
+foo ()
+{
+lab:
+ return 1;
+}
+
+constexpr int
+bar (int x)
+{
+ if (x)
+ goto lab; // { dg-error "'goto' is not a constant expression" }
+ return 1;
+lab:
+ return 0;
+}
+
+constexpr int
+baz (int x)
+{
+ if (!x)
+ return 1;
+ static int a; // { dg-error "control passes through declaration of 'a' with static storage duration" }
+ return ++a;
+}
+
+constexpr int
+qux (int x)
+{
+ if (!x)
+ return 1;
+ thread_local int a; // { dg-error "control passes through declaration of 'a' with thread storage duration" }
+ return ++a;
+}
+
+struct S { S (); ~S (); int s; }; // { dg-message "'S::S\\\(\\\)' declared here" }
+
+constexpr int
+corge (int x)
+{
+ if (!x)
+ return 1;
+ S s; // { dg-error "call to non-'constexpr' function 'S::S\\\(\\\)'" }
+ return 0;
+}
+
+constexpr int a = bar (1); // { dg-message "in 'constexpr' expansion of" }
+constexpr int b = baz (1); // { dg-message "in 'constexpr' expansion of" }
+constexpr int c = qux (1); // { dg-message "in 'constexpr' expansion of" }
+constexpr int d = corge (1); // { dg-message "in 'constexpr' expansion of" }
diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit3.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit3.C
new file mode 100644
index 0000000..3b5585d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit3.C
@@ -0,0 +1,10 @@
+// P2242R3
+// { dg-do compile { target c++14 } }
+
+constexpr int
+foo ()
+{
+ goto lab; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } }
+lab: // { dg-error "'goto' is not a constant expression" "" { target { c++23 } } .-1 }
+ return 1;
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C
new file mode 100644
index 0000000..e4ed2e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C
@@ -0,0 +1,57 @@
+// { dg-do compile }
+// { dg-options "-std=c++2b" }
+
+int qux ();
+
+constexpr int
+foo (int x)
+{
+ switch (x)
+ {
+ static int v = qux ();
+ case 12:
+ return 1;
+ }
+ return 0;
+}
+
+constexpr int
+bar (int x)
+{
+ switch (x)
+ {
+ thread_local int v = qux ();
+ case 12:
+ return 1;
+ }
+ return 0;
+}
+
+constexpr int
+baz (int x)
+{
+ switch (x)
+ {
+ static const int v = qux (); // { dg-message "'v' was not initialized with a constant expression" }
+ case 12:
+ return v;
+ }
+ return 0;
+}
+
+constexpr int
+corge (int x)
+{
+ switch (x)
+ {
+ const thread_local int v = qux (); // { dg-message "'v' was not initialized with a constant expression" }
+ case 12:
+ return v;
+ }
+ return 0;
+}
+
+constexpr int a = foo (12);
+constexpr int b = bar (12);
+constexpr int c = baz (12); // { dg-error "the value of 'v' is not usable in a constant expression" }
+constexpr int d = corge (12); // { dg-error "the value of 'v' is not usable in a constant expression" }
diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C
new file mode 100644
index 0000000..838f282
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C
@@ -0,0 +1,57 @@
+// { dg-do compile }
+// { dg-options "-std=c++2b" }
+
+int qux ();
+
+constexpr int
+foo (int x)
+{
+ switch (x)
+ {
+ static const int v = 6;
+ case 12:
+ return v;
+ }
+ return 0;
+}
+
+constexpr int
+bar (int x)
+{
+ switch (x)
+ {
+ thread_local const int v = 7;
+ case 12:
+ return 7;
+ }
+ return 0;
+}
+
+constexpr int
+baz (int x)
+{
+ switch (x)
+ {
+ static int v = 6; // { dg-message "int v' is not const" }
+ case 12:
+ return v;
+ }
+ return 0;
+}
+
+constexpr int
+corge (int x)
+{
+ switch (x)
+ {
+ thread_local int v = 6; // { dg-message "int v' is not const" }
+ case 12:
+ return v;
+ }
+ return 0;
+}
+
+constexpr int a = foo (12);
+constexpr int b = bar (12);
+constexpr int c = baz (12); // { dg-error "the value of 'v' is not usable in a constant expression" }
+constexpr int d = corge (12); // { dg-error "the value of 'v' is not usable in a constant expression" }
diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C
new file mode 100644
index 0000000..11cb518
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C
@@ -0,0 +1,25 @@
+// P2242R3
+// { dg-do compile }
+// { dg-options "-std=c++2b" }
+
+constexpr int
+foo ()
+{
+ goto lab; // { dg-error "'goto' is not a constant expression" }
+lab:
+ return 1;
+}
+
+constexpr int
+bar ()
+{
+ static int a; // { dg-error "'a' declared 'static' in 'constexpr' context" }
+ return ++a;
+}
+
+constexpr int
+baz (int x)
+{
+ thread_local int a; // { dg-error "'a' declared 'thread_local' in 'constexpr' context" }
+ return ++a;
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
index 7070f59..8bb3bf1 100644
--- a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
+++ b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
@@ -134,8 +134,8 @@
#ifndef __cpp_constexpr
# error "__cpp_constexpr"
-#elif __cpp_constexpr != 201907
-# error "__cpp_constexpr != 201907"
+#elif __cpp_constexpr != 202110
+# error "__cpp_constexpr != 202110"
#endif
#ifndef __cpp_decltype_auto
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-nondep2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-nondep2.C
new file mode 100644
index 0000000..e9867f8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-nondep2.C
@@ -0,0 +1,21 @@
+// PR c++/102412
+// { dg-do link { target c++20 } }
+
+template<class T, class U> concept C = __is_same(T, U);
+
+template<class T, bool = C<int, T>> void f();
+template<> void f<int, true>() { }
+template<> void f<char, false>() { }
+
+template<bool = C<int, char>> void g();
+template<> void g<false>() { }
+
+template<bool = C<int, int>> void h();
+template<> void h<true>() { }
+
+int main() {
+ f<int>();
+ f<char>();
+ g();
+ h();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-nondep3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-nondep3.C
new file mode 100644
index 0000000..4aae287
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-nondep3.C
@@ -0,0 +1,9 @@
+// DR 2446
+// { dg-do compile { target c++20 } }
+
+template <typename T> concept C = true;
+template <typename T> struct A;
+template <> struct A<bool> { using type = bool; };
+
+template <typename T>
+void f(A<decltype(C<T>)>::type); // OK, no 'typename' needed
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-ttp3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp3.C
new file mode 100644
index 0000000..11b6293
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp3.C
@@ -0,0 +1,11 @@
+// PR c++/99909
+// { dg-do compile { target c++20 } }
+
+template<class T> constexpr bool always_true = true;
+template<class T> concept C = always_true<T>;
+
+template<C auto> struct S;
+
+template<template<auto> class TT> void f() { }
+
+template void f<S>();
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-ttp4.C b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp4.C
new file mode 100644
index 0000000..cf3e71e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp4.C
@@ -0,0 +1,9 @@
+// PR c++/99904
+// { dg-do compile { target c++20 } }
+
+template<class... Ts> concept C = (Ts::value && ...);
+template<class... Ts> requires C<Ts...> struct A;
+template<class T> requires true struct B;
+template<template<class... Ts> requires C<Ts...> class TT> struct S;
+using ty1 = S<A>;
+using ty2 = S<B>; // { dg-error "constraint" } TT's constraints don't subsume B's
diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval3.C b/gcc/testsuite/g++.dg/cpp2a/consteval3.C
index 9fb1f1a..8f93164 100644
--- a/gcc/testsuite/g++.dg/cpp2a/consteval3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/consteval3.C
@@ -1,5 +1,4 @@
-// { dg-do compile }
-// { dg-options "-std=c++2a" }
+// { dg-do compile { target c++20 } }
struct S { S () : a (0), b (1) {} int a, b; };
int f1 (); // { dg-message "previous declaration 'int f1\\(\\)'" }
@@ -57,7 +56,8 @@ template consteval float f12 (float x); // { dg-error "explicit instantiation sh
consteval int
f13 (int x)
{
- static int a = 5; // { dg-error "'a' declared 'static' in 'consteval' function" }
- thread_local int b = 6; // { dg-error "'b' declared 'thread_local' in 'consteval' function" }
+ static int a = 5; // { dg-error "'a' declared 'static' in 'consteval' function only available with" "" { target c++20_only } }
+ // { dg-error "'a' declared 'static' in 'constexpr' context" "" { target c++23 } .-1 }
+ thread_local int b = 6; // { dg-error "'b' declared 'thread_local' in 'consteval' function only available with" "" { target c++20_only } }
return x;
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C
index 7700bb7..69fe9e2 100644
--- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C
@@ -180,6 +180,6 @@ f7 ()
constexpr int
f8 ()
{
- T t4; // { dg-error "variable 't4' of non-literal type 'T' in 'constexpr' function" }
+ T t4; // { dg-error "variable 't4' of non-literal type 'T' in 'constexpr' function only available with" "" { target c++20_down } }
return 0;
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C
index 3b51bf7..ed5e40d 100644
--- a/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C
@@ -5,14 +5,15 @@
constexpr int foo ()
try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
int a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } }
- static double b = 1.0;// { dg-error "'b' declared 'static' in 'constexpr' function" }
- goto l; // { dg-error "'goto' in 'constexpr' function" }
+ static double b = 1.0;// { dg-error "'b' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } }
+ // { dg-error "'b' declared 'static' in 'constexpr' context" "" { target c++23 } .-1 }
+ goto l; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } }
l:;
return 0;
} catch (...) {
long int c; // { dg-error "uninitialized variable 'c' in 'constexpr' function" "" { target c++17_down } }
- static float d = 2.0f;// { dg-error "'d' declared 'static' in 'constexpr' function" }
- goto l2; // { dg-error "'goto' in 'constexpr' function" }
+ static float d = 2.0f;// { dg-error "'d' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } }
+ goto l2; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } }
l2:;
return -1;
}
@@ -20,20 +21,21 @@ try { // { dg-warning "function-try-block body of 'constexpr' function only av
constexpr int bar ()
{
int a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } }
- static long double b = 3.0;// { dg-error "'b' declared 'static' in 'constexpr' function" }
- goto l; // { dg-error "'goto' in 'constexpr' function" }
+ static long double b = 3.0;// { dg-error "'b' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } }
+ // { dg-error "'b' declared 'static' in 'constexpr' context" "" { target c++23 } .-1 }
+ goto l; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } }
l:;
try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
short c; // { dg-error "uninitialized variable 'c' in 'constexpr' function" "" { target c++17_down } }
- static float d; // { dg-error "'d' declared 'static' in 'constexpr' function" }
+ static float d; // { dg-error "'d' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } }
// { dg-error "uninitialized variable 'd' in 'constexpr' function" "" { target c++17_down } .-1 }
- goto l2; // { dg-error "'goto' in 'constexpr' function" }
+ goto l2; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } }
l2:;
return 0;
} catch (int) {
char e; // { dg-error "uninitialized variable 'e' in 'constexpr' function" "" { target c++17_down } }
- static int f = 5; // { dg-error "'f' declared 'static' in 'constexpr' function" }
- goto l3; // { dg-error "'goto' in 'constexpr' function" }
+ static int f = 5; // { dg-error "'f' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } }
+ goto l3; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } }
l3:;
return 1;
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-float2.C b/gcc/testsuite/g++.dg/cpp2a/nontype-float2.C
new file mode 100644
index 0000000..40b42b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-float2.C
@@ -0,0 +1,14 @@
+// PR c++/98216
+// PR c++/91292
+// { dg-do compile { target c++20 } }
+
+template<auto> void f() { }
+
+template void f<-1.0f>();
+template void f<-2.0f>();
+
+template void f<-1.0>();
+template void f<-2.0>();
+
+template void f<-1.0L>();
+template void f<-2.0L>();
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq11.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq11.C
new file mode 100644
index 0000000..b71ed4f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq11.C
@@ -0,0 +1,43 @@
+// PR c++/102490
+// { dg-do run { target c++20 } }
+
+struct A
+{
+ unsigned char a : 1;
+ unsigned char b : 1;
+ constexpr bool operator== (const A &) const = default;
+};
+
+struct B
+{
+ unsigned char a : 8;
+ int : 0;
+ unsigned char b : 7;
+ constexpr bool operator== (const B &) const = default;
+};
+
+struct C
+{
+ unsigned char a : 3;
+ unsigned char b : 1;
+ constexpr bool operator== (const C &) const = default;
+};
+
+void
+foo (C &x, int y)
+{
+ x.b = y;
+}
+
+int
+main ()
+{
+ A a{}, b{};
+ B c{}, d{};
+ C e{}, f{};
+ a.b = 1;
+ d.b = 1;
+ foo (e, 0);
+ foo (f, 1);
+ return a == b || c == d || e == f;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq12.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq12.C
new file mode 100644
index 0000000..8346e7e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq12.C
@@ -0,0 +1,5 @@
+// PR c++/102490
+// { dg-do run { target c++20 } }
+// { dg-options "-O2" }
+
+#include "spaceship-eq11.C"
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq13.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq13.C
new file mode 100644
index 0000000..cb521ed
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq13.C
@@ -0,0 +1,22 @@
+// PR c++/98712
+// { dg-do run { target c++20 } }
+
+struct S
+{
+ int s = 0;
+ S(int s) : s(s) {}
+ bool operator==(const S&) const = default;
+};
+
+struct T : S
+{
+ T(int s) : S(s) {}
+ constexpr bool operator==(const T&) const = default;
+};
+
+int
+main()
+{
+ if (T(0) == T(1))
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth12.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth12.C
new file mode 100644
index 0000000..85b4784
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth12.C
@@ -0,0 +1,24 @@
+// PR c++/98712
+// { dg-do run { target c++20 } }
+
+#include <compare>
+
+struct S
+{
+ int s = 0;
+ S(int s) : s(s) {}
+ auto operator<=>(const S&) const = default;
+};
+
+struct T : S
+{
+ T(int s) : S(s) {}
+ constexpr auto operator<=>(const T&) const = default;
+};
+
+int
+main()
+{
+ if (T(0) >= T(1))
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth13.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth13.C
new file mode 100644
index 0000000..ab479d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth13.C
@@ -0,0 +1,29 @@
+// { dg-do compile { target c++20 } }
+
+#include <compare>
+#include <type_traits>
+
+struct E;
+struct D {
+ auto operator<=>(const D&) const = default;
+ float f;
+};
+struct E : D {
+ auto operator<=>(const E&) const = default;
+ int i;
+};
+extern E e1, e2;
+auto a = e1 <=> e2;
+static_assert (std::is_same_v <decltype (a), std::partial_ordering>);
+struct G;
+struct H {
+ constexpr auto operator<=>(const H&) const = default;
+ float f;
+};
+struct G : H {
+ constexpr auto operator<=>(const G&) const = default;
+ int i;
+};
+extern G g1, g2;
+auto c = g1 <=> g2;
+static_assert (std::is_same_v <decltype (c), std::partial_ordering>);
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth14.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth14.C
new file mode 100644
index 0000000..369d3a3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth14.C
@@ -0,0 +1,26 @@
+// Test virtual <=>.
+// { dg-do run { target c++20 } }
+
+#include <compare>
+
+struct E;
+struct D {
+ std::partial_ordering operator<=>(const D&) const = default;
+ virtual std::partial_ordering operator<=>(const E&) const = 0;
+ float f;
+ D(float f): f(f) {}
+};
+struct E : D {
+ std::partial_ordering operator<=>(const E&) const override = default;
+ int i;
+ E(float f, int i): D(f), i(i) {}
+};
+
+int main()
+{
+ E e1{0.0,42};
+ E e2{1.0,24};
+ auto a = e1 <=> e2;
+ if (!is_lt (e1 <=> e2))
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth8.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth8.C
index bd1c4d2..8861765 100644
--- a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth8.C
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth8.C
@@ -1,7 +1,18 @@
// PR c++/94907
// { dg-do compile { target c++20 } }
-namespace std { struct strong_ordering { }; }
+namespace std { struct strong_ordering {
+ int _v;
+ constexpr strong_ordering (int v) :_v(v) {}
+ constexpr operator int (void) const { return _v; }
+ static const strong_ordering less;
+ static const strong_ordering equal;
+ static const strong_ordering greater;
+};
+constexpr strong_ordering strong_ordering::less = -1;
+constexpr strong_ordering strong_ordering::equal = 0;
+constexpr strong_ordering strong_ordering::greater = 1;
+}
struct E;
struct D {
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth8a.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth8a.C
new file mode 100644
index 0000000..42a32da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth8a.C
@@ -0,0 +1,25 @@
+// PR c++/94907
+// { dg-do compile { target c++20 } }
+
+namespace std { struct strong_ordering {
+ int _v;
+ constexpr strong_ordering (int v) :_v(v) {}
+ constexpr operator int (void) const { return _v; }
+ static const strong_ordering less;
+ static const strong_ordering equal;
+ static const strong_ordering greater;
+};
+constexpr strong_ordering strong_ordering::less = -1;
+constexpr strong_ordering strong_ordering::equal = 0;
+constexpr strong_ordering strong_ordering::greater = 1;
+}
+
+struct E;
+struct D {
+ virtual std::strong_ordering operator<=>(const struct E&) const = 0;
+};
+struct E : D { // { dg-error "no match" }
+ std::strong_ordering operator<=>(const E&) const override = default; // { dg-message "default" }
+};
+
+auto x = E() <=> E(); // { dg-error "deleted" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-virtual1.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-virtual1.C
new file mode 100644
index 0000000..8067d3c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-virtual1.C
@@ -0,0 +1,20 @@
+// PR c++/95567
+// { dg-do run { target c++20 } }
+
+struct B {
+ B(int i) : i(i) {}
+ virtual ~B() = default;
+
+ bool operator==(B const&) const = default;
+ int i;
+};
+
+struct D : B {
+ D(int i, int j) : B(i), j(j) {}
+ int j;
+};
+
+int main() {
+ if (B(2) != D(2, 3))
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/constexpr1.C b/gcc/testsuite/g++.dg/diagnostic/constexpr1.C
index f029e86..f2bcec6 100644
--- a/gcc/testsuite/g++.dg/diagnostic/constexpr1.C
+++ b/gcc/testsuite/g++.dg/diagnostic/constexpr1.C
@@ -1,5 +1,7 @@
// { dg-do compile { target c++11 } }
-constexpr int foo() { thread_local int i __attribute__((unused)) {}; return 1; } // { dg-error "40:.i. declared .thread_local." }
+constexpr int foo() { thread_local int i __attribute__((unused)) {}; return 1; } // { dg-error "40:.i. declared .thread_local." "" { target c++20_down } }
+// { dg-error "40:.i. declared .thread_local. in .constexpr. context" "" { target c++23 } .-1 }
-constexpr int bar() { static int i __attribute__((unused)) {}; return 1; } // { dg-error "34:.i. declared .static." }
+constexpr int bar() { static int i __attribute__((unused)) {}; return 1; } // { dg-error "34:.i. declared .static." "" { target c++20_down } }
+// { dg-error "34:.i. declared .static. in .constexpr. context" "" { target c++23 } .-1 }
diff --git a/gcc/testsuite/g++.dg/ext/is_constructible6.C b/gcc/testsuite/g++.dg/ext/is_constructible6.C
new file mode 100644
index 0000000..7fce153
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_constructible6.C
@@ -0,0 +1,10 @@
+// Verify we respect the order of trailing arguments passed to
+// __is_constructible.
+
+struct A { };
+struct B { };
+struct C { C(A, B); };
+
+extern int n[true];
+extern int n[ __is_constructible(C, A, B)];
+extern int n[!__is_constructible(C, B, A)];
diff --git a/gcc/testsuite/g++.dg/ext/is_trivially_constructible7.C b/gcc/testsuite/g++.dg/ext/is_trivially_constructible7.C
new file mode 100644
index 0000000..f6fbf8f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_trivially_constructible7.C
@@ -0,0 +1,17 @@
+// PR c++/102535
+// Verify __is_trivially_constructible works with multi-arg paren init of
+// aggrs.
+
+struct A { int x; };
+struct B { float y; };
+struct C { char z; };
+struct D { A a; B b; C c; };
+
+extern int n[1 + __is_trivially_constructible(D, A)];
+extern int n[1 + __is_trivially_constructible(D, A, B)];
+extern int n[1 + __is_trivially_constructible(D, A, B, C)];
+#if __cpp_aggregate_paren_init
+extern int n[1 + true];
+#else
+extern int n[1 + false];
+#endif
diff --git a/gcc/testsuite/g++.dg/gomp/allocate-4.C b/gcc/testsuite/g++.dg/gomp/allocate-4.C
new file mode 100644
index 0000000..dd5e5f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/allocate-4.C
@@ -0,0 +1,108 @@
+// { dg-do compile }
+// { dg-additional-options "-std=c++11" }
+
+typedef enum omp_allocator_handle_t
+#if __cplusplus >= 201103L
+: __UINTPTR_TYPE__
+#endif
+{
+ omp_null_allocator = 0,
+ omp_default_mem_alloc = 1,
+ omp_large_cap_mem_alloc = 2,
+ omp_const_mem_alloc = 3,
+ omp_high_bw_mem_alloc = 4,
+ omp_low_lat_mem_alloc = 5,
+ omp_cgroup_mem_alloc = 6,
+ omp_pteam_mem_alloc = 7,
+ omp_thread_mem_alloc = 8,
+ __omp_allocator_handle_t_max__ = __UINTPTR_MAX__
+} omp_allocator_handle_t;
+
+namespace N1
+{
+ using ::omp_allocator_handle_t;
+ void
+ foo (const omp_allocator_handle_t h)
+ {
+ int x = 0;
+ #pragma omp parallel allocate (allocator (h): x) private (x)
+ x = 1;
+ }
+}
+
+namespace N2
+{
+ typedef enum omp_allocator_handle_t { my = 0 } omp_allocator_handle_t;
+ void
+ foo (omp_allocator_handle_t h)
+ {
+ int x = 0;
+ #pragma omp parallel allocate (allocator (h): x) private (x) // { dg-error "'allocate' clause allocator expression has type 'N2::omp_allocator_handle_t' rather than 'omp_allocator_handle_t'" }
+ x = 1;
+ }
+}
+
+struct S
+{
+ void foo ()
+ {
+ #pragma omp parallel allocate (allocator(omp_default_mem_alloc):s) firstprivate (s)
+ s++;
+ }
+ int s;
+};
+
+template <typename T>
+struct U
+{
+ int foo ()
+ {
+ #pragma omp parallel allocate (allocator(omp_default_mem_alloc):s) firstprivate (s)
+ s++;
+ return 1;
+ }
+ T s;
+};
+
+template <typename T, int N>
+int foo (T t)
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (allocator(t), align (N): x)
+ x = 1;
+ return 0;
+}
+
+template <typename T>
+int bar (T t)
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (allocator(t): x) // { dg-error "'allocate' clause allocator expression has type 'int' rather than 'omp_allocator_handle_t'" }
+ x = 1;
+ return 0;
+}
+
+template <typename T, int N>
+int baz (T t)
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (allocator(t), align (N): x) // { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" }
+ x = 1;
+ return 0;
+}
+
+template <typename T>
+int qux ()
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (align ((T) 16): x) // { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" }
+ x = 1;
+ return 0;
+}
+
+omp_allocator_handle_t h;
+int a = foo<omp_allocator_handle_t, 16> (h);
+int b = bar (0);
+int c = U<int> ().foo ();
+int d = baz<omp_allocator_handle_t, 13> (h);
+int e = qux<long double> ();
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-14.C b/gcc/testsuite/g++.dg/gomp/attrs-14.C
new file mode 100644
index 0000000..959f776
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/attrs-14.C
@@ -0,0 +1,4 @@
+// PR c++/102413
+// { dg-do compile { target c++11 } }
+
+[[omp::directive(error]]; // { dg-error "expected|declare" }
diff --git a/gcc/testsuite/g++.dg/gomp/simd-3.C b/gcc/testsuite/g++.dg/gomp/simd-3.C
new file mode 100644
index 0000000..db66c08
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/simd-3.C
@@ -0,0 +1,16 @@
+// PR middle-end/102492
+// { dg-do compile }
+
+struct S { S (int); };
+void bar (S &);
+
+void
+foo ()
+{
+ #pragma omp simd
+ for (int i = 0; i < 64; i++)
+ {
+ S s = 26;
+ bar (s);
+ }
+}
diff --git a/gcc/testsuite/g++.dg/parse/pr101783.C b/gcc/testsuite/g++.dg/parse/pr101783.C
new file mode 100644
index 0000000..4e0a435
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr101783.C
@@ -0,0 +1,5 @@
+template<class T> struct A{
+ typedef T& Type;
+};
+template<class T> void f(const typename A<T>::Type){}
+template <> void f<int>(const typename A<int>::Type){}
diff --git a/gcc/testsuite/g++.dg/pr102359_1.C b/gcc/testsuite/g++.dg/pr102359_1.C
new file mode 100644
index 0000000..da643cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr102359_1.C
@@ -0,0 +1,13 @@
+/* PR middle-end/102359 ICE gimplification failed since
+ r12-3433-ga25e0b5e6ac8a77a. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+/* { dg-require-effective-target c++17 } */
+
+struct A {
+ double a = 111;
+ auto foo() {
+ return [*this] { return a; };
+ }
+};
+int X = A{}.foo()();
diff --git a/gcc/testsuite/g++.dg/pr102359_2.C b/gcc/testsuite/g++.dg/pr102359_2.C
new file mode 100644
index 0000000..d026d72
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr102359_2.C
@@ -0,0 +1,13 @@
+/* PR middle-end/102359 ICE gimplification failed since
+ r12-3433-ga25e0b5e6ac8a77a. */
+/* { dg-do run} */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+/* { dg-require-effective-target c++17 } */
+
+int main()
+{
+ int i = 42;
+ auto l = [=]() mutable { return i; };
+ if (l() != i)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/spellcheck-pr77565.C b/gcc/testsuite/g++.dg/spellcheck-pr77565.C
new file mode 100644
index 0000000..2257f7b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/spellcheck-pr77565.C
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+typdef int my_int; // { dg-error "1: 'typdef' does not name a type; did you mean 'typedef'\\?" }
+inlien int i_fn(); // { dg-error "1: 'inlien' does not name a type; did you mean 'inline'\\?" }
+coonst int ci = 1; // { dg-error "1: 'coonst' does not name a type; did you mean 'const'\\?" }
+voltil int vi = 2; // { dg-error "1: 'voltil' does not name a type; did you mean 'volatile'\\?" }
+
+class my_class {
+ explict my_class(int); // { dg-error "3: 'explict' does not name a type; did you mean 'explicit'\\?" }
+ friends double f_fn(); // { dg-error "3: 'friends' does not name a type; did you mean 'friend'\\?" }
+ virtial double v_fn(); // { dg-error "3: 'virtial' does not name a type; did you mean 'virtual'\\?" }
+};
diff --git a/gcc/testsuite/g++.dg/template/canon-type-15.C b/gcc/testsuite/g++.dg/template/canon-type-15.C
new file mode 100644
index 0000000..b001b5c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-15.C
@@ -0,0 +1,7 @@
+// { dg-do compile { target c++11 } }
+template<unsigned u> struct size_c{ static constexpr unsigned value = u; };
+namespace g {
+template<class T> auto return_size(T t) -> size_c<sizeof(t)>;
+template<class T> auto return_size(T t) -> size_c<sizeof(t)>;
+}
+static_assert(decltype(g::return_size('a'))::value == 1u, "");
diff --git a/gcc/testsuite/g++.dg/template/canon-type-16.C b/gcc/testsuite/g++.dg/template/canon-type-16.C
new file mode 100644
index 0000000..99361cb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-16.C
@@ -0,0 +1,6 @@
+// { dg-do compile { target c++11 } }
+template<bool u> struct bool_c{ static constexpr bool value = u; };
+template<class T> auto noexcepty(T t) -> bool_c<noexcept(t())>;
+template<class T> auto noexcepty(T t) -> bool_c<noexcept(t())>;
+struct foo { void operator()() noexcept; };
+static_assert(decltype(noexcepty(foo{}))::value, "");
diff --git a/gcc/testsuite/g++.dg/template/canon-type-17.C b/gcc/testsuite/g++.dg/template/canon-type-17.C
new file mode 100644
index 0000000..0555c8d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-17.C
@@ -0,0 +1,5 @@
+// { dg-do compile { target c++11 } }
+template<unsigned u> struct size_c{ static constexpr unsigned value = u; };
+template<class... T> auto return_size(T... t) -> size_c<sizeof...(t)>;
+template<class... T> auto return_size(T... t) -> size_c<sizeof...(t)>;
+static_assert(decltype(return_size('a'))::value == 1u, "");
diff --git a/gcc/testsuite/g++.dg/template/canon-type-18.C b/gcc/testsuite/g++.dg/template/canon-type-18.C
new file mode 100644
index 0000000..2510181
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-18.C
@@ -0,0 +1,6 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wno-pedantic" }
+template<unsigned u> struct size_c{ static constexpr unsigned value = u; };
+template<class T> auto get_align(T t) -> size_c<alignof(t)>;
+template<class T> auto get_align(T t) -> size_c<alignof(t)>;
+static_assert(decltype(get_align('a'))::value == 1u, "");
diff --git a/gcc/testsuite/g++.dg/template/dependent-name15.C b/gcc/testsuite/g++.dg/template/dependent-name15.C
new file mode 100644
index 0000000..1c34bc7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dependent-name15.C
@@ -0,0 +1,18 @@
+// { dg-do compile { target c++11 } }
+template <int N> struct A { static void foo(){} };
+template <> struct A<sizeof(char)> { using foo = int; };
+
+template <class T> void f(T t1) {
+ A<sizeof(t1)>::foo();
+}
+
+template <class T> void g(T t2) {
+ /* if the comparing_specializations check breaks in cp_tree_equal
+ case PARM_DECL, the error will incorrectly report A<sizeof (t1)> */
+ A<sizeof(t2)>::foo(); // { dg-error "dependent-name .A<sizeof .t2.>::foo" }
+}
+
+void h() {
+ f(0);
+ g('0');
+}
diff --git a/gcc/testsuite/g++.dg/template/dependent-name16.C b/gcc/testsuite/g++.dg/template/dependent-name16.C
new file mode 100644
index 0000000..ef8c4f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dependent-name16.C
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++11 } }
+template <int N> struct A { static void foo(){} };
+template <> struct A<sizeof(char)> { using foo = int; };
+
+template<class T1> auto f(T1 t1) -> decltype(A<sizeof(t1)>::foo());
+
+/* if the comparing_specializations check breaks in cp_tree_equal
+case PARM_DECL, the error will incorrectly report A<sizeof (t1)> */
+template<class T2> auto g(T2 t2) -> decltype(A<sizeof(t2)>::foo()); // { dg-error "dependent-name .A<sizeof .t2.>::foo" }
+
+void h() {
+ f(0);
+ g('0'); // { dg-error "no matching function" }
+}
diff --git a/gcc/testsuite/g++.dg/template/param6.C b/gcc/testsuite/g++.dg/template/param6.C
new file mode 100644
index 0000000..8306e75
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/param6.C
@@ -0,0 +1,32 @@
+// PR c++/61355
+// Verify we perform array-to-pointer and function-to-pointer conversion
+// on the substituted/deduced type of an NTTP.
+
+int f();
+int p[5];
+
+namespace cpp98 {
+ template<class T, T> struct X;
+ typedef X<int(), f> ty1;
+ typedef X<int[5], p> ty2;
+}
+
+namespace cpp11 {
+#if __cpp_variadic_templates
+ template<class T, T...> struct X;
+ using ty1 = X<int(), f>;
+ using ty2 = X<int[5], p>;
+#endif
+}
+
+namespace cpp17 {
+#if __cpp_nontype_template_parameter_auto
+ template<decltype(auto)> struct X;
+ using ty1 = X<f>;
+ using ty2 = X<p>;
+
+ template<decltype(auto)...> struct Y;
+ using ty3 = Y<f>;
+ using ty4 = Y<p>;
+#endif
+}
diff --git a/gcc/testsuite/g++.dg/tls/pr102496-1.C b/gcc/testsuite/g++.dg/tls/pr102496-1.C
new file mode 100644
index 0000000..8220e1e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tls/pr102496-1.C
@@ -0,0 +1,20 @@
+// PR c++/102496
+// { dg-do link { target c++11 } }
+// { dg-require-effective-target tls }
+// { dg-add-options tls }
+// { dg-additional-sources pr102496-2.C }
+
+template <int N>
+int
+foo ()
+{
+ extern __thread int t1;
+ return t1;
+}
+
+int
+main ()
+{
+ extern __thread int t2;
+ return foo <0> () + t2;
+}
diff --git a/gcc/testsuite/g++.dg/tls/pr102496-2.C b/gcc/testsuite/g++.dg/tls/pr102496-2.C
new file mode 100644
index 0000000..a71a9cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tls/pr102496-2.C
@@ -0,0 +1,6 @@
+// PR c++/102496
+// { dg-do compile { target c++11 } }
+// { dg-require-effective-target tls }
+
+__thread int t1;
+__thread int t2;
diff --git a/gcc/testsuite/g++.dg/torture/pr102581.C b/gcc/testsuite/g++.dg/torture/pr102581.C
new file mode 100644
index 0000000..7f172d0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr102581.C
@@ -0,0 +1,51 @@
+// { dg-do compile }
+/* { dg-additional-options "-fno-strict-aliasing" } */
+enum VkStructureType {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR
+} typedef VkPhysicalDeviceSparseProperties;
+struct VkPhysicalDeviceProperties {
+ int apiVersion;
+ VkPhysicalDeviceSparseProperties sparseProperties;
+};
+typedef struct {
+ VkStructureType sType;
+ int *pPhysicalDevices;
+} VkPhysicalDeviceFeatures2;
+typedef struct VkPhysicalDeviceProperties2 {
+ VkStructureType sType;
+ void *pNext;
+} VkPhysicalDeviceMemoryProperties2;
+struct VulkanVersion {
+ int major;
+ int minor;
+ int patch;
+};
+int make_vulkan_version_version;
+VulkanVersion make_vulkan_version() {
+ return {make_vulkan_version_version, make_vulkan_version_version,
+ make_vulkan_version_version};
+}
+struct AppGpu {
+ int &inst;
+ int id;
+ int *phys_device = nullptr;
+ VulkanVersion api_version{};
+ VkPhysicalDeviceProperties props{};
+ VkPhysicalDeviceProperties2 props2{};
+ int memory_props{};
+ VkPhysicalDeviceMemoryProperties2 memory_props2{};
+ int features{};
+ VkPhysicalDeviceFeatures2 features2{};
+ int *dev = nullptr;
+ int enabled_features{};
+ int AppGpu_phys_device;
+ int AppGpu_inst;
+ AppGpu() : inst(AppGpu_inst), id() {
+ api_version = make_vulkan_version();
+ props2.sType = memory_props2.sType = features2.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
+ }
+};
+int
+main() { AppGpu(); return 0; }
diff --git a/gcc/testsuite/g++.dg/warn/Waddress-5.C b/gcc/testsuite/g++.dg/warn/Waddress-5.C
new file mode 100644
index 0000000..b1ad38a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Waddress-5.C
@@ -0,0 +1,115 @@
+/* PR c/102103 - missing warning comparing array address to null
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+#if __cplusplus < 201103L
+# define nullptr __null
+#endif
+
+struct A
+{
+ void f ();
+ virtual void vf ();
+ virtual void pvf () = 0;
+
+ void sf ();
+
+ int *p;
+ int a[2];
+};
+
+void T (bool);
+
+void warn_memptr_if ()
+{
+ // Exercise warnings for addresses of nonstatic member functions.
+ if (&A::f == 0) // { dg-warning "the address '&A::f'" }
+ T (0);
+
+ if (&A::vf) // { dg-warning "-Waddress" }
+ T (0);
+
+ if (&A::pvf != 0) // { dg-warning "-Waddress" }
+ T (0);
+
+ // Exercise warnings for addresses of static member functions.
+ if (&A::sf == 0) // { dg-warning "-Waddress" }
+ T (0);
+
+ if (&A::sf) // { dg-warning "-Waddress" }
+ T (0);
+
+ // Exercise warnings for addresses of nonstatic data members.
+ if (&A::p == 0) // { dg-warning "the address '&A::p'" }
+ T (0);
+
+ if (&A::a == nullptr) // { dg-warning "-Waddress" }
+ T (0);
+}
+
+void warn_memptr_bool ()
+{
+ // Exercise warnings for addresses of nonstatic member functions.
+ T (&A::f == 0); // { dg-warning "-Waddress" }
+ T (&A::vf); // { dg-warning "-Waddress" }
+ T (&A::pvf != 0); // { dg-warning "-Waddress" }
+
+ // Exercise warnings for addresses of static member functions.
+ T (&A::sf == 0); // { dg-warning "-Waddress" }
+ T (&A::sf); // { dg-warning "-Waddress" }
+
+ // Exercise warnings for addresses of nonstatic data members.
+ T (&A::p == 0); // { dg-warning "-Waddress" }
+ T (&A::a == nullptr); // { dg-warning "-Waddress" }
+}
+
+
+/* Verify that no warnings are issued for a dependent expression in
+ a template. */
+
+template <int>
+struct B
+{
+ // This is why.
+ struct F { void* operator& () const { return 0; } } f;
+};
+
+template <class Type, int N>
+void nowarn_dependent (Type targ)
+{
+ T (&Type::x == 0);
+ T (&targ == 0);
+
+ Type tarr[1];
+ T (&tarr[0] == nullptr);
+
+ T (&B<N>::f == 0);
+
+ /* Like in the case above, the address-of operator could be a member
+ of B<N>::vf that returns zero. */
+ T (&B<N>::vf);
+ T (&B<N>::pvf != 0);
+ T (&B<N>::p == 0);
+ T (&B<N>::a == 0);
+}
+
+
+/* Verify that in an uninstantiated template warnings are not issued
+ for dependent expressions but are issued otherwise. */
+
+template <class Type>
+void warn_non_dependent (Type targ, Type *tptr, int i)
+{
+ /* The address of a pointer to a dependent type cannot be null but
+ the warning doesn't have a chance to see it. */
+ T (&tptr == 0); // { dg-warning "-Waddress" "pr102378" { xfail *-*-* } }
+ T (&i == 0); // { dg-warning "-Waddress" }
+
+ int iarr[1];
+ T (&iarr == 0); // { dg-warning "-Waddress" }
+ T (&*iarr != 0); // { dg-warning "-Waddress" "pr102378" { xfail *-*-* } }
+ T (&iarr[0] == 0); // { dg-warning "-Waddress" }
+
+ Type tarr[1];
+ T (&tarr == nullptr); // { dg-warning "-Waddress" "pr102378" { xfail *-*-* } }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Waddress-6.C b/gcc/testsuite/g++.dg/warn/Waddress-6.C
new file mode 100644
index 0000000..c22a83a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Waddress-6.C
@@ -0,0 +1,79 @@
+/* PR c/102103 - missing warning comparing array address to null
+ { dg-do compile }
+ Verify -Waddress for member arrays of structs and notes.
+ { dg-options "-Wall" } */
+
+#if __cplusplus < 201103L
+# define nullptr __null
+#endif
+
+void T (bool);
+
+struct A
+{
+ int n;
+ int ia[]; // { dg-message "'A::ia' declared here" }
+};
+
+struct B
+{
+ A a[3]; // { dg-message "'B::a' declared here" }
+};
+
+struct C
+{
+ B b[3]; // { dg-message "'C::b' declared here" }
+};
+
+struct D
+{
+ C c[3]; // { dg-message "'D::c' declared here" }
+};
+
+
+void test_waddress_1d ()
+{
+ D d[2]; // { dg-message "'d' declared here" }
+
+ T (d); // { dg-warning "address of 'd'" }
+ T (d == nullptr); // { dg-warning "address of 'd'" }
+ T (&d); // { dg-warning "address of 'd'" }
+ T (d->c); // { dg-warning "address of 'D::c'" }
+ T (d->c != nullptr); // { dg-warning "address of 'D::c'" }
+ T (d->c->b); // { dg-warning "address of 'C::b'" }
+ T (d->c[1].b->a); // { dg-warning "address of 'B::a'" }
+ T (d->c->b[2].a->ia); // { dg-warning "address of 'A::ia'" }
+
+ if (d->c->b[2].a[1].ia) // { dg-warning "address of 'A::ia'" }
+ T (0);
+
+ if (bool b = d->c->b[1].a) // { dg-warning "address of 'B::a'" }
+ T (b);
+
+ /* The following is represented as a declaration of P followed
+ by an if statement and so it isn't diagnosed. It's not clear
+ that it should be since the pointer is then used.
+ void *p = d->c->b[2].a;
+ if (p) ...
+ */
+ if (void *p = d->c->b[2].a) // { dg-warning "address of 'A::ia'" "" { xfail *-*-* } }
+ T (p);
+}
+
+
+void test_waddress_2d (int i)
+{
+ D d[2][3]; // { dg-message "'d' declared here" }
+
+ T (d); // { dg-warning "address of 'd'" }
+ T (d == nullptr); // { dg-warning "address of 'd'" }
+ T (&d); // { dg-warning "address of 'd'" }
+ T (*d); // { dg-warning "address of 'd'" }
+ T (d[1] != nullptr); // { dg-warning "address of 'd'" }
+ T (&d[1]->c); // { dg-warning "address of 'D::c'" }
+ T (d[1]->c); // { dg-warning "address of 'D::c'" }
+ T (d[1]->c == nullptr); // { dg-warning "address of 'D::c'" }
+ T (d[i]->c[1].b); // { dg-warning "address of 'C::b'" }
+ T ((*(d + i))->c->b->a); // { dg-warning "address of 'B::a'" }
+ T (d[1][2].c->b->a->ia); // { dg-warning "address of 'A::ia'" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Winit-list5.C b/gcc/testsuite/g++.dg/warn/Winit-list5.C
new file mode 100644
index 0000000..07b3a69
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winit-list5.C
@@ -0,0 +1,61 @@
+// PR c++/102482
+// { dg-do compile { target c++11 } }
+// Test we don't warn for non-const lvalue refs.
+
+#include <initializer_list>
+
+struct X { };
+
+struct span
+{
+ span(std::initializer_list<int>& il)
+ : begin(il.begin()) // { dg-bogus "initializer_list" }
+ { }
+
+ const int* begin;
+};
+
+struct span_warn
+{
+ span_warn(std::initializer_list<int> il)
+ : begin(il.begin()) // { dg-warning "initializer_list" }
+ { }
+
+ const int* begin;
+};
+
+struct span_warn2
+{
+ span_warn2(std::initializer_list<int>&& il)
+ : begin(il.begin()) // { dg-warning "initializer_list" }
+ { }
+
+ const int* begin;
+};
+
+struct span_warn3
+{
+ span_warn3(std::initializer_list<int> const& il)
+ : begin(il.begin()) // { dg-warning "initializer_list" }
+ { }
+
+ const int* begin;
+};
+
+struct span_warn4
+{
+ span_warn4(std::initializer_list<int> const il)
+ : begin(il.begin()) // { dg-warning "initializer_list" }
+ { }
+
+ const int* begin;
+};
+
+struct span_warn5
+{
+ span_warn5(std::initializer_list<int> const&& il)
+ : begin(il.begin()) // { dg-warning "initializer_list" }
+ { }
+
+ const int* begin;
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
index bfe1445..fae8b7e 100644
--- a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
+++ b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
@@ -9,7 +9,7 @@ const intptr_t&
return_addr_label_as_intref (void)
{
label:
- if ((const intptr_t*)&&label == 0)
+ if ((const intptr_t)&&label == 0)
__builtin_exit (1);
return *(const intptr_t*)&&label; // { dg-warning "\\\[-Wreturn-local-addr]" } */
@@ -19,7 +19,7 @@ const intptr_t&
return_addr_local_as_intref (void)
{
int a[1];
- if ((const intptr_t*)a == 0)
+ if ((const intptr_t)a == 0)
__builtin_exit (1);
return (const intptr_t&)a; // { dg-warning "\\\[-Wreturn-local-addr]" } */
diff --git a/gcc/testsuite/g++.dg/warn/pr101219.C b/gcc/testsuite/g++.dg/warn/pr101219.C
index 0d23d73..d5d44e4 100644
--- a/gcc/testsuite/g++.dg/warn/pr101219.C
+++ b/gcc/testsuite/g++.dg/warn/pr101219.C
@@ -7,5 +7,7 @@ struct S { void m(); };
template <int> bool f() {
void (S::*mp)();
- return &S::m == mp; // no warning emitted here (no instantiation)
+ /* The expression below isn't type-dependent so also verify
+ it's diagnosed even though the template isn't instantiated. */
+ return &S::m == mp; // { dg-warning "\\\[-Waddress" }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/nontype5.C b/gcc/testsuite/g++.old-deja/g++.pt/nontype5.C
index 2678cf7..e24dca4 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/nontype5.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/nontype5.C
@@ -19,5 +19,5 @@ static int g() { return f(); }
int f() { return 0; }
int main() {
-return B<int,&f>::g(); // { dg-error "" } could not convert arg
+return B<int,&f>::g();
}
diff --git a/gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-minmax.C b/gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-minmax.C
new file mode 100644
index 0000000..6d50f49
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-minmax.C
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+/* { dg-final { scan-assembler-times "vminph" 3 } } */
+/* { dg-final { scan-assembler-times "vmaxph" 3 } } */
+
+typedef _Float16 v8hf __attribute__ ((vector_size (16)));
+typedef _Float16 v16hf __attribute__ ((vector_size (32)));
+typedef _Float16 v32hf __attribute__ ((vector_size (64)));
+
+#define VCONDMINMAX(size, op, name) \
+v##size##hf \
+__attribute__ ((noinline, noclone)) \
+vminmax_##v##size##hf##v##size##hf##name (v##size##hf a, v##size##hf b) \
+{ \
+ return (a op b) ? a : b; \
+}
+
+VCONDMINMAX (8, <, min)
+VCONDMINMAX (8, >, max)
+VCONDMINMAX (16, <, min)
+VCONDMINMAX (16, >, max)
+VCONDMINMAX (32, <, min)
+VCONDMINMAX (32, >, max)
+
diff --git a/gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-vec.C b/gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-vec.C
new file mode 100644
index 0000000..de93e2c
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-vec.C
@@ -0,0 +1,70 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+/* { dg-final { scan-assembler-times "vcmpph" 45 } } */
+/* { dg-final { scan-assembler-times "vpcmpuw" 12 } } */
+/* { dg-final { scan-assembler-times "vpcmpw" 18 } } */
+/* { dg-final { scan-assembler-times "(?:vpblendmw|vmovdqu16\[^\{\n\]+\{%k\[1-7\]\})" 75 } } */
+
+typedef _Float16 v8hf __attribute__ ((vector_size (16)));
+typedef _Float16 v16hf __attribute__ ((vector_size (32)));
+typedef _Float16 v32hf __attribute__ ((vector_size (64)));
+typedef short v8hi __attribute__ ((vector_size (16)));
+typedef short v16hi __attribute__ ((vector_size (32)));
+typedef short v32hi __attribute__ ((vector_size (64)));
+typedef unsigned short v8uhi __attribute__ ((vector_size (16)));
+typedef unsigned short v16uhi __attribute__ ((vector_size (32)));
+typedef unsigned short v32uhi __attribute__ ((vector_size (64)));
+
+#define VCONDMOV(size, op, name) \
+v##size##hf \
+__attribute__ ((noinline, noclone)) \
+vcond_##v##size##hf##v##size##hf##name (v##size##hf a, v##size##hf b, \
+ v##size##hf c, v##size##hf d) \
+{ \
+ return (a op b) ? c : d; \
+}\
+v##size##hf \
+__attribute__ ((noinline, noclone)) \
+vcond_##v##size##hi##v##size##hf##name (v##size##hi a, v##size##hi b, \
+ v##size##hf c, v##size##hf d) \
+{ \
+ return (a op b) ? c : d; \
+}\
+v##size##hi \
+__attribute__ ((noinline, noclone)) \
+vcond_##v##size##hf##v##size##hi##name (v##size##hi a, v##size##hi b, \
+ v##size##hf c, v##size##hf d) \
+{ \
+ return (c op d) ? a : b; \
+} \
+v##size##hf \
+__attribute__ ((noinline, noclone)) \
+vcond_##v##size##uhi##v##size##hf##name (v##size##uhi a, v##size##uhi b, \
+ v##size##hf c, v##size##hf d) \
+{ \
+ return (a op b) ? c : d; \
+}\
+v##size##uhi \
+__attribute__ ((noinline, noclone)) \
+vcond_##v##size##hf##v##size##uhi##name (v##size##uhi a, v##size##uhi b, \
+ v##size##hf c, v##size##hf d) \
+{ \
+ return (c op d) ? a : b; \
+} \
+
+VCONDMOV (8, <, lt)
+VCONDMOV (8, >, gt)
+VCONDMOV (8, ==, eq)
+VCONDMOV (8, <=, le)
+VCONDMOV (8, >=, ge)
+VCONDMOV (16, <, lt)
+VCONDMOV (16, >, gt)
+VCONDMOV (16, <=, le)
+VCONDMOV (16, >=, ge)
+VCONDMOV (16, ==, eq)
+VCONDMOV (32, <, lt)
+VCONDMOV (32, >, gt)
+VCONDMOV (32, <=, le)
+VCONDMOV (32, >=, ge)
+VCONDMOV (32, ==, eq)
diff --git a/gcc/testsuite/g++.target/i386/pr102548.C b/gcc/testsuite/g++.target/i386/pr102548.C
new file mode 100644
index 0000000..e1238c3
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr102548.C
@@ -0,0 +1,12 @@
+// PR c++/102548
+// { dg-do compile { target { c++14 && ia32 } } }
+
+typedef decltype(sizeof(0)) size_t;
+struct tm;
+extern "C" size_t __attribute__((__cdecl__)) strftime (char *, size_t, const char *, const struct tm *);
+
+auto
+foo (void)
+{
+ return strftime;
+}
diff --git a/gcc/testsuite/g++.target/powerpc/pr102024.C b/gcc/testsuite/g++.target/powerpc/pr102024.C
new file mode 100644
index 0000000..7695850
--- /dev/null
+++ b/gcc/testsuite/g++.target/powerpc/pr102024.C
@@ -0,0 +1,23 @@
+// PR target/102024
+// { dg-do compile { target powerpc_elfv2 } }
+// { dg-options "-O2" }
+
+// Test that a zero-width bit field in an otherwise homogeneous aggregate
+// generates a psabi warning and passes arguments in GPRs.
+
+// { dg-final { scan-assembler-times {\mstd\M} 4 } }
+
+struct a_thing
+{
+ double x;
+ double y;
+ double z;
+ int : 0;
+ double w;
+};
+
+double
+foo (a_thing a) // { dg-message "ELFv2 parameter passing for an argument containing zero-width bit fields but that is otherwise a homogeneous aggregate was corrected in GCC 12" }
+{
+ return a.x * a.y + a.z - a.w;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/920826-1.c b/gcc/testsuite/gcc.c-torture/compile/920826-1.c
index c2d8843..2a175456 100644
--- a/gcc/testsuite/gcc.c-torture/compile/920826-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/920826-1.c
@@ -1,3 +1,3 @@
/* { dg-require-effective-target indirect_jumps } */
-f(int*x){goto*(char)*x;}
+f(int*x){goto*(void*)(__INTPTR_TYPE__)(char)*x;}
diff --git a/gcc/testsuite/gcc.c-torture/compile/920831-1.c b/gcc/testsuite/gcc.c-torture/compile/920831-1.c
index 9e422a9..945c521 100644
--- a/gcc/testsuite/gcc.c-torture/compile/920831-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/920831-1.c
@@ -1,3 +1,3 @@
/* { dg-require-effective-target indirect_jumps } */
-f(x){goto*(char)x;}
+f(x){goto*(void *)x;}
diff --git a/gcc/testsuite/gcc.c-torture/compile/attr-complex-method-2.c b/gcc/testsuite/gcc.c-torture/compile/attr-complex-method-2.c
new file mode 100644
index 0000000..121ae17
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-complex-method-2.c
@@ -0,0 +1,11 @@
+/* { dg-additional-options "-fcx-limited-range -fdump-tree-optimized" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+#pragma GCC optimize "-fno-cx-limited-range"
+
+void do_div (_Complex double *a, _Complex double *b)
+{
+ *a = *b / (4.0 - 5.0fi);
+}
+
+/* { dg-final { scan-tree-dump "__divdc3" "optimized" } } */
diff --git a/gcc/testsuite/gcc.c-torture/compile/attr-complex-method.c b/gcc/testsuite/gcc.c-torture/compile/attr-complex-method.c
new file mode 100644
index 0000000..046de7e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-complex-method.c
@@ -0,0 +1,11 @@
+/* { dg-additional-options "-fdump-tree-optimized" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+#pragma GCC optimize "-fcx-limited-range"
+
+void do_div (_Complex double *a, _Complex double *b)
+{
+ *a = *b / (4.0 - 5.0fi);
+}
+
+/* { dg-final { scan-tree-dump-not "__divdc3" "optimized" } } */
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr27863.c b/gcc/testsuite/gcc.c-torture/compile/pr27863.c
index 926312e4..1428ce3 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr27863.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr27863.c
@@ -14,7 +14,7 @@ int main(int argc,char**argv,char **envp)
_loc1:;
*++esp=(long)&&_loc35;
_loc35:;
-goto *(*esp--);
+goto *(void *)(*esp--);
*++esp=(long)&&_loc36;
_loc36:;
*++esp=(long)&&_loc37;
@@ -27,5 +27,5 @@ _loc66:;
*++esp=(long)&&_loc119;
_loc119:;
SetTermStruc:
- goto *(*esp--);
+ goto *(void*)(__INTPTR_TYPE__)(*esp--);
}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr70190.c b/gcc/testsuite/gcc.c-torture/compile/pr70190.c
index d3d209a..6c57b50 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr70190.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr70190.c
@@ -8,7 +8,7 @@ fn1 ()
static char a[] = "foo";
static void *b[] = { &&l1, &&l2 };
goto *(b[1]);
- l1: goto *(a[0]);
+ l1: goto *(void*)(__INTPTR_TYPE__)(a[0]);
l2: return 0;
}
diff --git a/gcc/testsuite/gcc.dg/Waddress-3.c b/gcc/testsuite/gcc.dg/Waddress-3.c
new file mode 100644
index 0000000..c404f6b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Waddress-3.c
@@ -0,0 +1,35 @@
+/* PR c/102103 - missing warning comparing array address to null
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+typedef _Complex float Cflt;
+
+extern Cflt cf, cfa[], cfa2[][2];
+
+Cflt *pcf (void);
+
+void T (int);
+
+void test_complex (Cflt *p, int i)
+{
+ T (&__real__ cf == 0); // { dg-warning "address of '__real__ cf'" }
+ T (&__imag__ cf == 0); // { dg-warning "address of '__imag__ cf'" }
+
+ T (0 != &__real__ cf); // { dg-warning "-Waddress" }
+ T (0 != &__imag__ cf); // { dg-warning "-Waddress" }
+
+ T (&__real__ cfa[0] == 0); // { dg-warning "-Waddress" }
+ T (&__imag__ cfa[1] == 0); // { dg-warning "-Waddress" }
+
+ T (0 != &__real__ cfa2[i][i]); // { dg-warning "-Waddress" }
+ T (0 != &__imag__ cfa2[i][i]); // { dg-warning "-Waddress" }
+
+ T (0 == &__real__ *p); // { dg-warning "-Waddress" }
+ T (0 == &__imag__ *p); // { dg-warning "-Waddress" }
+
+ T (0 == &__real__ p[i]); // { dg-warning "-Waddress" }
+ T (0 == &__imag__ p[i]); // { dg-warning "-Waddress" }
+
+ T (&__real__ *pcf () == 0); // { dg-warning "-Waddress" }
+ T (0 != &__imag__ *pcf ()); // { dg-warning "-Waddress" }
+}
diff --git a/gcc/testsuite/gcc.dg/Waddress.c b/gcc/testsuite/gcc.dg/Waddress.c
index 146b1a9..b26e7b1 100644
--- a/gcc/testsuite/gcc.dg/Waddress.c
+++ b/gcc/testsuite/gcc.dg/Waddress.c
@@ -6,5 +6,5 @@ int
foo(void)
{
char a[1];
- return a == 0;
+ return a == 0; // { dg-warning "-Waddress" }
}
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/asm-x86-linux-rdmsr.c b/gcc/testsuite/gcc.dg/analyzer/torture/asm-x86-linux-rdmsr.c
index 0a1c48f..69d0165 100644
--- a/gcc/testsuite/gcc.dg/analyzer/torture/asm-x86-linux-rdmsr.c
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/asm-x86-linux-rdmsr.c
@@ -6,7 +6,7 @@
/* Adapted from Linux: arch/x86/include/asm/msr.h (GPL-2.0) */
#ifdef __x86_64__
-#define DECLARE_ARGS(val, low, high) unsigned long low, high
+#define DECLARE_ARGS(val, low, high) unsigned long long low, high
#define EAX_EDX_VAL(val, low, high) ((low) | (high) << 32)
#define EAX_EDX_RET(val, low, high) "=a" (low), "=d" (high)
#else
diff --git a/gcc/testsuite/gcc.dg/auto-init-hardreg-1.c b/gcc/testsuite/gcc.dg/auto-init-hardreg-1.c
new file mode 100644
index 0000000..7c9de99
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-hardreg-1.c
@@ -0,0 +1,9 @@
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+int
+main ()
+{
+ register long *sp __asm__("sp");
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/comp-goto-5.c b/gcc/testsuite/gcc.dg/comp-goto-5.c
new file mode 100644
index 0000000..d487729
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/comp-goto-5.c
@@ -0,0 +1,11 @@
+/* PR c/32122 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+enum {a=1};
+void foo()
+{
+ goto *
+ a; /* { dg-error "computed goto must be pointer type" } */
+}
+
diff --git a/gcc/testsuite/gcc.dg/comp-goto-6.c b/gcc/testsuite/gcc.dg/comp-goto-6.c
new file mode 100644
index 0000000..497f6cd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/comp-goto-6.c
@@ -0,0 +1,6 @@
+/* PR c/32122 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+void foo(void *a) { goto *10000000; } /* { dg-error "computed goto must be pointer type" } */
+void foo1(void *a) { goto *a; }
+
diff --git a/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-1.c b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-1.c
new file mode 100644
index 0000000..efcfbc9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-1.c
@@ -0,0 +1,5 @@
+/* Test #elifdef and #elifndef in GNU11. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=gnu11" } */
+
+#include "c2x-elifdef-1.c"
diff --git a/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-2.c b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-2.c
new file mode 100644
index 0000000..e5bd705
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-2.c
@@ -0,0 +1,63 @@
+/* Test #elifdef and #elifndef in GNU11: erroneous usages. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=gnu11" } */
+
+#define A
+#undef B
+
+#elifdef A /* { dg-error "#elifdef without #if" } */
+#elifdef B /* { dg-error "#elifdef without #if" } */
+#elifndef A /* { dg-error "#elifndef without #if" } */
+#elifndef B /* { dg-error "#elifndef without #if" } */
+
+#if 1 /* { dg-error "-:began here" } */
+#else
+#elifdef A /* { dg-error "#elifdef after #else" } */
+#endif
+
+#if 1 /* { dg-error "-:began here" } */
+#else
+#elifdef B /* { dg-error "#elifdef after #else" } */
+#endif
+
+#if 1 /* { dg-error "-:began here" } */
+#else
+#elifndef A /* { dg-error "#elifndef after #else" } */
+#endif
+
+#if 1 /* { dg-error "-:began here" } */
+#else
+#elifndef B /* { dg-error "#elifndef after #else" } */
+#endif
+
+#if 0
+#elifdef A = /* { dg-warning "extra tokens at end of #elifdef directive" } */
+#endif
+
+#if 0
+#elifdef B = /* { dg-warning "extra tokens at end of #elifdef directive" } */
+#endif
+
+#if 0
+#elifndef A = /* { dg-warning "extra tokens at end of #elifndef directive" } */
+#endif
+
+#if 0
+#elifndef B = /* { dg-warning "extra tokens at end of #elifndef directive" } */
+#endif
+
+#if 0
+#elifdef /* { dg-error "no macro name given in #elifdef directive" } */
+#endif
+
+#if 0
+#elifndef /* { dg-error "no macro name given in #elifndef directive" } */
+#endif
+
+#if 0
+#elifdef , /* { dg-error "macro names must be identifiers" } */
+#endif
+
+#if 0
+#elifndef , /* { dg-error "macro names must be identifiers" } */
+#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-3.c b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-3.c
new file mode 100644
index 0000000..0b769a7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-3.c
@@ -0,0 +1,65 @@
+/* Test #elifdef and #elifndef in GNU11. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=gnu11 -pedantic" } */
+
+#define A
+#undef B
+
+#if 0
+#elifdef A /* { dg-warning "#elifdef before C2X is a GCC extension" } */
+#define M1 1
+#endif
+
+#if M1 != 1
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifdef B
+#error "#elifdef B applied"
+#endif
+
+#if 0
+#elifndef A
+#error "#elifndef A applied"
+#endif
+
+#if 0
+#elifndef B /* { dg-warning "#elifndef before C2X is a GCC extension" } */
+#define M2 2
+#endif
+
+#if M2 != 2
+#error "#elifndef B did not apply"
+#endif
+
+#if 0
+#elifdef A /* { dg-warning "#elifdef before C2X is a GCC extension" } */
+#else
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifndef B /* { dg-warning "#elifndef before C2X is a GCC extension" } */
+#else
+#error "#elifndef B did not apply"
+#endif
+
+#if 1
+#elifdef A /* { dg-warning "#elifdef before C2X is a GCC extension" } */
+#endif
+
+#if 1
+#elifndef B /* { dg-warning "#elifndef before C2X is a GCC extension" } */
+#endif
+
+/* As with #elif, the syntax of the new directives is relaxed after a
+ non-skipped group. */
+
+#if 1
+#elifdef x * y /* { dg-warning "#elifdef before C2X is a GCC extension" } */
+#endif
+
+#if 1
+#elifndef ! /* { dg-warning "#elifndef before C2X is a GCC extension" } */
+#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-4.c b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-4.c
new file mode 100644
index 0000000..aba3467
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-4.c
@@ -0,0 +1,65 @@
+/* Test #elifdef and #elifndef in GNU11. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=gnu11 -pedantic-errors" } */
+
+#define A
+#undef B
+
+#if 0
+#elifdef A /* { dg-error "#elifdef before C2X is a GCC extension" } */
+#define M1 1
+#endif
+
+#if M1 != 1
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifdef B
+#error "#elifdef B applied"
+#endif
+
+#if 0
+#elifndef A
+#error "#elifndef A applied"
+#endif
+
+#if 0
+#elifndef B /* { dg-error "#elifndef before C2X is a GCC extension" } */
+#define M2 2
+#endif
+
+#if M2 != 2
+#error "#elifndef B did not apply"
+#endif
+
+#if 0
+#elifdef A /* { dg-error "#elifdef before C2X is a GCC extension" } */
+#else
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifndef B /* { dg-error "#elifndef before C2X is a GCC extension" } */
+#else
+#error "#elifndef B did not apply"
+#endif
+
+#if 1
+#elifdef A /* { dg-error "#elifdef before C2X is a GCC extension" } */
+#endif
+
+#if 1
+#elifndef B /* { dg-error "#elifndef before C2X is a GCC extension" } */
+#endif
+
+/* As with #elif, the syntax of the new directives is relaxed after a
+ non-skipped group. */
+
+#if 1
+#elifdef x * y /* { dg-error "#elifdef before C2X is a GCC extension" } */
+#endif
+
+#if 1
+#elifndef ! /* { dg-error "#elifndef before C2X is a GCC extension" } */
+#endif
diff --git a/gcc/testsuite/gcc.dg/fold-negate-1.c b/gcc/testsuite/gcc.dg/fold-negate-1.c
new file mode 100644
index 0000000..00ec8b4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-negate-1.c
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+#define SHIFT ((8*__SIZEOF_INT__)-1)
+
+int test_rshift_1(int x)
+{
+ int t = x >> SHIFT;
+ return -t;
+}
+
+int test_rshift_2(int x)
+{
+ unsigned int t = (unsigned int)x >> SHIFT;
+ return -t;
+}
+
+int test_rshift_3(int x)
+{
+ int t = (unsigned int)x >> SHIFT;
+ return -t;
+}
+
+int test_rshift_4(int x)
+{
+ unsigned int t = x >> SHIFT;
+ return -t;
+}
+
+double test_mul_1(double x)
+{
+ double t = -5.0 * x;
+ return -t;
+}
+
+double test_mul_2(double x, double y)
+{
+ double t1 = -x;
+ double t2 = t1 * y;
+ return -t2;
+}
+
+double test_rdiv_1(double x, double y)
+{
+ double t1 = -x;
+ double t2 = t1 / y;
+ return -t2;
+}
+
+double test_rdiv_2(double x, double y)
+{
+ double t1 = -y;
+ double t2 = x / t1;
+ return -t2;
+}
+
+/* { dg-final { scan-tree-dump-not " -" "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/gimplefe-46.c b/gcc/testsuite/gcc.dg/gimplefe-46.c
new file mode 100644
index 0000000..fb91f7d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-46.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+char global[10];
+
+void bar (void);
+
+void __GIMPLE (ssa)
+foo (char * p)
+{
+ __BB(2):
+ if (p_2(D) == _Literal (char *)&global[2])
+ goto __BB3;
+ else
+ goto __BB4;
+
+ __BB(3):
+ bar ();
+ goto __BB4;
+
+ __BB(4):
+ return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-47.c b/gcc/testsuite/gcc.dg/gimplefe-47.c
new file mode 100644
index 0000000..3bbd34d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-47.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+char * begfield (int tab, char * ptr, char * lim, int sword, int schar);
+
+int __GIMPLE (ssa)
+main ()
+{
+ char * lim;
+ char * s;
+ char * _1;
+
+ __BB(2):
+ _1 = begfield (58, ":ab", &__MEM <char[4]> ((void *)&":ab" + _Literal
+(void *) 3), 1, 1);
+ if (_1 != _Literal (char *) &__MEM <char[4]> ((void *)&":ab" + _Literal (void *) 2))
+ goto __BB3;
+ else
+ goto __BB4;
+
+ __BB(3):
+ __builtin_abort ();
+
+ __BB(4):
+ __builtin_exit (0);
+}
+
diff --git a/gcc/testsuite/gcc.dg/guality/example.c b/gcc/testsuite/gcc.dg/guality/example.c
index 6f1c017..32014e2b 100644
--- a/gcc/testsuite/gcc.dg/guality/example.c
+++ b/gcc/testsuite/gcc.dg/guality/example.c
@@ -1,5 +1,5 @@
-/* { dg-do run { xfail { ! aarch64*-*-* } } } */
/* { dg-options "-g" } */
+/* { dg-do run { xfail { ! aarch64*-*-* } } } */
/* { dg-xfail-run-if "" aarch64*-*-* "*" { "-O[01g]" } } */
#define GUALITY_DONT_FORCE_LIVE_AFTER -1
diff --git a/gcc/testsuite/gcc.dg/out-of-bounds-1.c b/gcc/testsuite/gcc.dg/out-of-bounds-1.c
index 1c76341..5c134c0 100644
--- a/gcc/testsuite/gcc.dg/out-of-bounds-1.c
+++ b/gcc/testsuite/gcc.dg/out-of-bounds-1.c
@@ -8,6 +8,6 @@
void ProjectOverlay(const float localTextureAxis[2], char *lump)
{
const void *d = &localTextureAxis;
- int size = sizeof(float)*8 ;
+ int size = sizeof(float)*7 ;
__builtin_memcpy( &lump[ 0 ], d, size ); /* { dg-warning "reading" } */
}
diff --git a/gcc/testsuite/gcc.dg/pr102087.c b/gcc/testsuite/gcc.dg/pr102087.c
new file mode 100644
index 0000000..5cd094f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102087.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+unsigned __attribute__ ((noinline))
+foo (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n)
+{
+ while (n < ++l)
+ *a++ = *b++ + 1;
+ return l;
+}
+
+volatile int a[1];
+unsigned b;
+int c;
+
+int
+check ()
+{
+ int d;
+ for (; b > 1; b++)
+ for (c = 0; c < 2; c++)
+ for (d = 0; d < 2; d++)
+ a[0];
+ return 0;
+}
+
+char **clip_image_gfi_0;
+int clip_image_y, clip_image_shift;
+void
+clip_image ()
+{
+ for (; clip_image_y >= clip_image_shift; clip_image_y++)
+ clip_image_gfi_0[clip_image_shift]
+ = clip_image_gfi_0[clip_image_y];
+}
diff --git a/gcc/testsuite/gcc.dg/pr102463.c b/gcc/testsuite/gcc.dg/pr102463.c
new file mode 100644
index 0000000..ca63f0b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102463.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+_Bool _bfd_elf_merge_symbol_h, _bfd_elf_merge_symbol_h_1;
+_Bool _bfd_elf_merge_symbol_olddef;
+_Bool bfd_is_com_section();
+
+void
+_bfd_elf_merge_symbol() {
+ _Bool newdef = bfd_is_com_section(), ntdef, tdef;
+ _bfd_elf_merge_symbol_olddef = _bfd_elf_merge_symbol_h;
+ if (_bfd_elf_merge_symbol_h_1) {
+ ntdef = newdef;
+ tdef = _bfd_elf_merge_symbol_h;
+ } else {
+ ntdef = _bfd_elf_merge_symbol_h;
+ tdef = newdef;
+ }
+ if (tdef && ntdef)
+ ;
+}
diff --git a/gcc/testsuite/gcc.dg/pr102511.c b/gcc/testsuite/gcc.dg/pr102511.c
new file mode 100644
index 0000000..8a9af34
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102511.c
@@ -0,0 +1,21 @@
+// { dg-do run }
+// { dg-options "-O3" }
+
+char arr_15 [8];
+__attribute__((noipa))
+void test(signed char a, unsigned short b, unsigned long long c,
+ unsigned short f) {
+ for (int d = b - 8; d < b; d += 2)
+ for (short e = 0; e < (unsigned short)((f ? 122 : 0) ^ (a ? c : 0)) - 64055;
+ e += 3)
+ arr_15[d] = 42;
+}
+int main() {
+ test(37, 8, 12325048486467861044ULL, 45936);
+ for (int i = 0; i < 8; ++i)
+ {
+ if (arr_15[i] != ((i&1) ? 0 : 42))
+ __builtin_abort();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr78408-1.c b/gcc/testsuite/gcc.dg/pr78408-1.c
index 94e2090..dc9870a 100644
--- a/gcc/testsuite/gcc.dg/pr78408-1.c
+++ b/gcc/testsuite/gcc.dg/pr78408-1.c
@@ -3,7 +3,7 @@
/* { dg-options "-O2 -fdump-tree-fab1-details" } */
/* { dg-final { scan-tree-dump-times "after previous" 17 "fab1" } } */
-struct S { char a[32]; };
+struct S { char a[33]; };
struct T { char a[65536]; };
void bar (int, struct S *, struct S *, struct T *, struct T *);
void baz (char *, char *);
diff --git a/gcc/testsuite/gcc.dg/pr94726.c b/gcc/testsuite/gcc.dg/pr94726.c
new file mode 100644
index 0000000..d6911a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr94726.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+typedef unsigned int type __attribute__ ( ( vector_size ( 2*sizeof(int) ) ) ) ;
+type a , b;
+/* { dg-message "note: previous declaration" "previous declaration" { target *-*-* } .-1 } */
+void foo ( void ) {
+ type var = { 2 , 2 } ;
+ b = __builtin_shuffle ( a , var ) ;
+}
+
+void * a [ ] = { } ; /* { dg-error "conflicting types" } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr102518.c b/gcc/testsuite/gcc.dg/torture/pr102518.c
new file mode 100644
index 0000000..bd181ec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr102518.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+struct A {
+ int *x;
+};
+int i;
+int f(int *const c) {
+ struct A * b = (struct A *)(&c);
+ return b->x != 0;
+}
+void g() { f(&i); }
+
diff --git a/gcc/testsuite/gcc.dg/torture/pr55107.c b/gcc/testsuite/gcc.dg/torture/pr55107.c
index d757c04..2edb75f 100644
--- a/gcc/testsuite/gcc.dg/torture/pr55107.c
+++ b/gcc/testsuite/gcc.dg/torture/pr55107.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-additional-options "-fno-split-loops" } */
+/* { dg-additional-options "-fno-split-loops -w" } */
typedef unsigned short uint16_t;
diff --git a/gcc/testsuite/gcc.dg/torture/pr89135.c b/gcc/testsuite/gcc.dg/torture/pr89135.c
index 278303f..4cf0533 100644
--- a/gcc/testsuite/gcc.dg/torture/pr89135.c
+++ b/gcc/testsuite/gcc.dg/torture/pr89135.c
@@ -28,7 +28,7 @@ h:
g = foo ();
*o = g;
if (c)
- goto *d;
+ goto *(void*)d;
}
}
goto *i;
diff --git a/gcc/testsuite/gcc.dg/torture/pr90071.c b/gcc/testsuite/gcc.dg/torture/pr90071.c
index 702c143..1c4099c 100644
--- a/gcc/testsuite/gcc.dg/torture/pr90071.c
+++ b/gcc/testsuite/gcc.dg/torture/pr90071.c
@@ -21,6 +21,6 @@ h: ++e;
goto i;
}
f:
- goto *({ d || e < 0 || e >= 2; });
+ goto *(void*)(__INTPTR_TYPE__)({ d || e < 0 || e >= 2; });
&e;
}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030714-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030714-2.c
index eb663f2..9585ff1 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/20030714-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/20030714-2.c
@@ -32,7 +32,8 @@ get_alias_set (t)
}
}
-/* There should be exactly three IF conditionals if we thread jumps
- properly. */
-/* { dg-final { scan-tree-dump-times "if " 3 "dom2"} } */
+/* There should be exactly 4 IF conditionals if we thread jumps
+ properly. There used to be 3, but one thread was crossing
+ loops. */
+/* { dg-final { scan-tree-dump-times "if " 4 "dom2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c
index 5227c87..59663dd 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-Ofast -fdump-tree-vrp1" } */
+/* { dg-options "-Ofast -fdump-tree-vrp-thread1" } */
void g (int);
void g1 (int);
@@ -27,4 +27,4 @@ f (long a, long b, long c, long d, long x)
g (a);
}
-/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c
index eaf89bb..0c2f6e0 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-Ofast -fdump-tree-vrp1" } */
+/* { dg-options "-Ofast -fdump-tree-vrp-thread1" } */
void g (void);
void g1 (void);
@@ -20,4 +20,4 @@ f (long a, long b, long c, long d, int x)
}
}
-/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c
index d5a1e0b..6a3d359 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-Ofast -fdump-tree-vrp1" } */
+/* { dg-options "-Ofast -fdump-tree-vrp-thread1" } */
void g (void);
void g1 (void);
@@ -22,4 +22,4 @@ f (long a, long b, long c, long d, int x)
}
}
-/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c
index 53acabc..9bc4c6d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-Ofast -fdump-tree-vrp1" } */
+/* { dg-options "-Ofast -fdump-tree-vrp-thread1" } */
void g (int);
void g1 (int);
@@ -37,4 +37,4 @@ f (long a, long b, long c, long d, int x)
g (c + d);
}
-/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c b/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c
new file mode 100644
index 0000000..4bd9874
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// { dg-options "-O3 -fdump-tree-optimized" }
+
+static int a;
+static char b, c, d;
+void bar(void);
+void foo(void);
+
+int main() {
+ int f = 0;
+ for (; f <= 5; f++) {
+ bar();
+ b = b && f;
+ d = f << f;
+ if (!(a >= d || f))
+ foo();
+ c = 1;
+ for (; c; c = 0)
+ ;
+ }
+}
+
+// { dg-final { scan-tree-dump-not "foo" "optimized" } }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr102563.c b/gcc/testsuite/gcc.dg/tree-ssa/pr102563.c
new file mode 100644
index 0000000..8871dff
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr102563.c
@@ -0,0 +1,16 @@
+// { dg-do compile }
+// { dg-options "-O2 -w" }
+
+int _bdf_parse_glyphs_bp;
+long _bdf_parse_glyphs_nibbles;
+
+void _bdf_parse_glyphs_p()
+{
+ long p_2;
+
+ _bdf_parse_glyphs_nibbles = p_2 << 1;
+
+ for (; 0 < _bdf_parse_glyphs_nibbles;)
+ if (1 < _bdf_parse_glyphs_nibbles)
+ _bdf_parse_glyphs_bp = _bdf_parse_glyphs_p;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c
index b406566..51b3b7a 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-evrp-details -fdump-tree-vrp1-details" } */
+/* { dg-options "-O2 -fdump-tree-evrp-details -fdump-tree-vrp-thread1-details" } */
static int blocksize = 4096;
@@ -39,6 +39,6 @@ void foo (void)
statement. We also realize that the final bytes == 0 test is useless,
and thread over it. We also know that toread != 0 is useless when
entering while loop and thread over it. */
-/* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c b/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c
index dab16ab..2caa1f5 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-Ofast -fdump-tree-vrp1-details" } */
+/* { dg-options "-Ofast -fdump-tree-vrp-thread1-details" } */
typedef unsigned short u16;
typedef unsigned char u8;
@@ -56,6 +56,11 @@ main (int argc, char argv[])
return crc;
}
-/* { dg-final { scan-tree-dump-times "Registering jump thread" 3 "vrp1" } } */
-/* { dg-final { scan-tree-dump-not "joiner" "vrp1" } } */
-/* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp1" } } */
+/* Previously we had 3 jump threads, but one of them crossed loops.
+ The reason the old threader was allowing it, was because there was
+ an ASSERT_EXPR getting in the way. Without the ASSERT_EXPR, we
+ have an empty pre-header block as the final block in the thread,
+ which the threader will simply join with the next block which *is*
+ in a different loop. */
+/* { dg-final { scan-tree-dump-times "Registering jump thread" 2 "vrp-thread1" } } */
+/* { dg-final { scan-tree-dump-not "joiner" "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c
index ddc53fb..0229a82 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/61839. */
/* { dg-do run } */
-/* { dg-options "-O2 -fdump-tree-vrp1 -fdisable-tree-evrp -fdump-tree-optimized -fdisable-tree-ethread -fdisable-tree-thread1" } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1 -fdisable-tree-evrp -fdump-tree-optimized -fdisable-tree-ethread -fdisable-tree-thread1" } */
/* { dg-require-effective-target int32plus } */
__attribute__ ((noinline))
@@ -38,7 +38,11 @@ int main ()
}
/* Scan for c = 972195717) >> [0, 1] in function foo. */
-/* { dg-final { scan-tree-dump-times "486097858 : 972195717" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "486097858 : 972195717" 1 "vrp-thread1" } } */
+
+/* Previously we were checking for two ?: with constant PHI arguments,
+ but now we collapse them into one. */
/* Scan for c = 972195717) >> [2, 3] in function bar. */
-/* { dg-final { scan-tree-dump-times "243048929 : 121524464" 2 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "243048929 : 121524464" 1 "vrp-thread1" } } */
+
/* { dg-final { scan-tree-dump-times "486097858" 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c
index cc322d6..7be1873 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/61839. */
/* { dg-do run } */
-/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-optimized -fdisable-tree-ethread -fdisable-tree-thread1" } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1 -fdump-tree-optimized -fdisable-tree-ethread -fdisable-tree-thread1" } */
__attribute__ ((noinline))
int foo (int a, unsigned b)
@@ -22,5 +22,5 @@ int main ()
}
/* Scan for c [12, 13] << 8 in function foo. */
-/* { dg-final { scan-tree-dump-times "3072 : 3328" 2 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "3072 : 3328" 1 "vrp-thread1" } } */
/* { dg-final { scan-tree-dump-times "3072" 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c
index e1464e2..ba7025a 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-thread1-details -fdump-tree-dce2" } */
+/* { dg-options "-O2 -fdump-tree-thread1-details -fdump-tree-thread4" } */
extern int status, pt;
extern int count;
@@ -32,10 +32,15 @@ foo (int N, int c, int b, int *a)
pt--;
}
-/* There are 4 jump threading opportunities, all of which will be
- realized, which will eliminate testing of FLAG, completely. */
-/* { dg-final { scan-tree-dump-times "Registering jump" 4 "thread1"} } */
+/* There are 2 jump threading opportunities (which don't cross loops),
+ all of which will be realized, which will eliminate testing of
+ FLAG, completely. */
+/* { dg-final { scan-tree-dump-times "Registering jump" 2 "thread1"} } */
-/* There should be no assignments or references to FLAG, verify they're
- eliminated as early as possible. */
-/* { dg-final { scan-tree-dump-not "if .flag" "dce2"} } */
+/* We used to remove references to FLAG by DCE2, but this was
+ depending on early threaders threading through loop boundaries
+ (which we shouldn't do). However, the late threading passes, which
+ run after loop optimizations , can successfully eliminate the
+ references to FLAG. Verify that ther are no references by the late
+ threading passes. */
+/* { dg-final { scan-tree-dump-not "if .flag" "thread4"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c
index 66a5405..a2386ba 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-ffast-math -O3 -fdump-tree-vrp1-details" } */
+/* { dg-options "-ffast-math -O3 -fdump-tree-vrp-thread1-details" } */
int I = 50, J = 50;
int S, L;
@@ -39,4 +39,4 @@ void foo (int K)
bar (LD, SD);
}
}
-/* { dg-final { scan-tree-dump-times "Threaded jump " 2 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Threaded jump " 2 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c
index f9fc212..18f7aab 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c
@@ -123,8 +123,8 @@ enum STATES FMS( u8 **in , u32 *transitions) {
aarch64 has the highest CASE_VALUES_THRESHOLD in GCC. It's high enough
to change decisions in switch expansion which in turn can expose new
jump threading opportunities. Skip the later tests on aarch64. */
-/* { dg-final { scan-tree-dump "Jumps threaded: 1\[1-9\]" "thread1" } } */
-/* { dg-final { scan-tree-dump-times "Invalid sum" 4 "thread1" } } */
+/* { dg-final { scan-tree-dump "Jumps threaded: \[7-9\]" "thread1" } } */
+/* { dg-final { scan-tree-dump-times "Invalid sum" 1 "thread1" } } */
/* { dg-final { scan-tree-dump-not "optimizing for size" "thread1" } } */
/* { dg-final { scan-tree-dump-not "optimizing for size" "thread2" } } */
/* { dg-final { scan-tree-dump-not "optimizing for size" "thread3" { target { ! aarch64*-*-* } } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr99793.c b/gcc/testsuite/gcc.dg/tree-ssa/pr99793.c
new file mode 100644
index 0000000..9127449
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr99793.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fstrict-aliasing -fdump-tree-optimized" } */
+
+extern void foo(void);
+static int a, *b = &a, c, *d = &c;
+int main()
+{
+ int **e = &d;
+ if (!((unsigned)((*e = d) == 0) - (*b = 1)))
+ foo();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "foo" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.c
new file mode 100644
index 0000000..97563dd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -ftree-vectorize" } */
+
+#include "reassoc-46.h"
+
+/* Check that the loop accumulator is added last. */
+/* { dg-final { scan-tree-dump-times {(?:vect_)?sum_[\d._]+ = (?:(?:vect_)?_[\d._]+ \+ (?:vect_)?sum_[\d._]+|(?:vect_)?sum_[\d._]+ \+ (?:vect_)?_[\d._]+)} 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.h b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.h
new file mode 100644
index 0000000..e60b490
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.h
@@ -0,0 +1,33 @@
+#define M 1024
+unsigned int arr1[M];
+unsigned int arr2[M];
+volatile unsigned int sink;
+
+unsigned int
+test (void)
+{
+ unsigned int sum = 0;
+ for (int i = 0; i < M; i++)
+ {
+#ifdef MODIFY
+ /* Modify the loop accumulator using a chain of operations - this should
+ not affect its rank biasing. */
+ sum |= 1;
+ sum ^= 2;
+#endif
+#ifdef STORE
+ /* Save the loop accumulator into a global variable - this should not
+ affect its rank biasing. */
+ sink = sum;
+#endif
+#ifdef USE
+ /* Add a tricky use of the loop accumulator - this should prevent its
+ rank biasing. */
+ i = (i + sum) % M;
+#endif
+ /* Use addends with different ranks. */
+ sum += arr1[i];
+ sum += arr2[((i ^ 1) + 1) % M];
+ }
+ return sum;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-47.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-47.c
new file mode 100644
index 0000000..1b0f0fd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-47.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -ftree-vectorize" } */
+
+#define MODIFY
+#include "reassoc-46.h"
+
+/* Check that if the loop accumulator is saved into a global variable, it's
+ still added last. */
+/* { dg-final { scan-tree-dump-times {(?:vect_)?sum_[\d._]+ = (?:(?:vect_)?_[\d._]+ \+ (?:vect_)?sum_[\d._]+|(?:vect_)?sum_[\d._]+ \+ (?:vect_)?_[\d._]+)} 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-48.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-48.c
new file mode 100644
index 0000000..13836eb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-48.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -ftree-vectorize" } */
+
+#define STORE
+#include "reassoc-46.h"
+
+/* Check that if the loop accumulator is modified using a chain of operations
+ other than addition, its new value is still added last. */
+/* { dg-final { scan-tree-dump-times {(?:vect_)?sum_[\d._]+ = (?:(?:vect_)?_[\d._]+ \+ (?:vect_)?sum_[\d._]+|(?:vect_)?sum_[\d._]+ \+ (?:vect_)?_[\d._]+)} 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-49.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-49.c
new file mode 100644
index 0000000..c1136a4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-49.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -ftree-vectorize" } */
+
+#define MODIFY
+#define STORE
+#include "reassoc-46.h"
+
+/* Check that if the loop accumulator is both modified using a chain of
+ operations other than addition and stored into a global variable, its new
+ value is still added last. */
+/* { dg-final { scan-tree-dump-times {(?:vect_)?sum_[\d._]+ = (?:(?:vect_)?_[\d._]+ \+ (?:vect_)?sum_[\d._]+|(?:vect_)?sum_[\d._]+ \+ (?:vect_)?_[\d._]+)} 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-50.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-50.c
new file mode 100644
index 0000000..e35a4ff
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-50.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -ftree-vectorize" } */
+
+#define MODIFY
+#define USE
+#include "reassoc-46.h"
+
+/* Check that if the loop accumulator has multiple uses inside the loop, it's
+ not forced to the end of the reassociation chain. */
+/* { dg-final { scan-tree-dump-times {(?:vect_)?sum_[\d._]+ = (?:(?:vect_)?_[\d._]+ \+ (?:vect_)?sum_[\d._]+|(?:vect_)?sum_[\d._]+ \+ (?:vect_)?_[\d._]+)} 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-51.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-51.c
new file mode 100644
index 0000000..0717567
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-51.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -ftree-vectorize" } */
+
+#define MODIFY
+#define STORE
+#define USE
+#include "reassoc-46.h"
+
+/* Check that if the loop accumulator has multiple uses inside the loop, it's
+ not forced to the end of the reassociation chain. */
+/* { dg-final { scan-tree-dump-times {(?:vect_)?sum_[\d._]+ = (?:(?:vect_)?_[\d._]+ \+ (?:vect_)?sum_[\d._]+|(?:vect_)?sum_[\d._]+ \+ (?:vect_)?_[\d._]+)} 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c
index 856ab38..73969bb 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dom2-details --param logical-op-non-short-circuit=1 -fdisable-tree-thread1 -fdisable-tree-thread2" } */
+/* { dg-options "-O2 -fdump-tree-dom2-details --param logical-op-non-short-circuit=1 -fdisable-tree-thread1 -fdisable-tree-thread2 -fdisable-tree-vrp-thread1 " } */
static int *bb_ticks;
extern void frob (void);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-14.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-14.c
index 3bc4b37..a25fe8b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-14.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-14.c
@@ -37,5 +37,5 @@ expand_shift_1 (int code, int unsignedp, int rotate,
we will enter the TRUE arm of the conditional and we can thread
the test to compute the first first argument of the expand_binop
call if we look backwards through the boolean logicals. */
-/* { dg-final { scan-tree-dump-times "Threaded" 1 "dom2"} } */
+/* { dg-final { scan-tree-dump-times "Threaded" 2 "dom2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c
index ffbdc98..1b677f4 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dom2-details -w --param logical-op-non-short-circuit=1" } */
+/* { dg-options "-O2 -fdump-tree-dom2-details -w --param logical-op-non-short-circuit=1 -fdisable-tree-vrp-thread1" } */
unsigned char
validate_subreg (unsigned int offset, unsigned int isize, unsigned int osize, int zz, int qq)
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c
index 60d4f76..0246ebf 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-details -fdump-tree-thread1-details -std=gnu89 --param logical-op-non-short-circuit=0" } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1-details -std=gnu89 --param logical-op-non-short-circuit=0" } */
#include "ssa-dom-thread-4.c"
@@ -21,5 +21,7 @@
condition.
All the cases are picked up by VRP1 as jump threads. */
-/* { dg-final { scan-tree-dump-times "Registering jump" 6 "thread1" } } */
-/* { dg-final { scan-tree-dump-times "Threaded" 2 "vrp1" } } */
+
+/* There used to be 6 jump threads found by thread1, but they all
+ depended on threading through distinct loops in ethread. */
+/* { dg-final { scan-tree-dump-times "Threaded" 2 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c
index b972f64..8f0a12c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-stats -fdump-tree-dom2-stats" } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1-stats -fdump-tree-dom2-stats" } */
void bla();
@@ -16,6 +16,6 @@ void thread_entry_through_header (void)
/* There's a single jump thread that should be handled by the VRP
jump threading pass. */
-/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 1 "vrp1"} } */
-/* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 0 "vrp1"} } */
+/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 1 "vrp-thread1"} } */
+/* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 0 "vrp-thread1"} } */
/* { dg-final { scan-tree-dump-not "Jumps threaded" "dom2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c
index 521754f..46e464f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-details -fdump-tree-dom2-details -std=gnu89 --param logical-op-non-short-circuit=1" } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1-details -fdump-tree-dom2-details -std=gnu89 --param logical-op-non-short-circuit=1" } */
struct bitmap_head_def;
typedef struct bitmap_head_def *bitmap;
typedef const struct bitmap_head_def *const_bitmap;
@@ -58,4 +58,5 @@ bitmap_ior_and_compl (bitmap dst, const_bitmap a, const_bitmap b,
code we missed the edge when the first conditional is false
(b_elt is zero, which means the second conditional is always
zero. VRP1 catches all three. */
-/* { dg-final { scan-tree-dump-times "Threaded" 3 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Registering jump thread" 2 "vrp-thread1" } } */
+/* { dg-final { scan-tree-dump-times "Path crosses loops" 1 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c
index e3d4b31..16abcde 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c
@@ -1,8 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-thread1-stats -fdump-tree-thread2-stats -fdump-tree-dom2-stats -fdump-tree-thread3-stats -fdump-tree-dom3-stats -fdump-tree-vrp2-stats -fno-guess-branch-probability" } */
-/* { dg-final { scan-tree-dump "Jumps threaded: 18" "thread1" } } */
-/* { dg-final { scan-tree-dump "Jumps threaded: 8" "thread3" { target { ! aarch64*-*-* } } } } */
+/* { dg-final { scan-tree-dump "Jumps threaded: 12" "thread1" } } */
+/* { dg-final { scan-tree-dump "Jumps threaded: 5" "thread3" { target { ! aarch64*-*-* } } } } */
/* { dg-final { scan-tree-dump-not "Jumps threaded" "dom2" } } */
/* aarch64 has the highest CASE_VALUES_THRESHOLD in GCC. It's high enough
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-95.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-95.c
new file mode 100644
index 0000000..b0936be
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-95.c
@@ -0,0 +1,25 @@
+/* PR100112 and dups. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-fre1-details -fdump-tree-optimized" } */
+
+int *c, *b;
+void foo()
+{
+ int *tem = b;
+ *tem = 0;
+ int *footem = c;
+ c = footem;
+}
+
+void bar()
+{
+ int *tem = b;
+ int *bartem = c;
+ *tem = 0;
+ c = bartem;
+}
+
+/* We should elide the redundant store in foo, in bar it is not redundant since
+ the *tem = 0 store might alias. */
+/* { dg-final { scan-tree-dump "Deleted redundant store c = footem" "fre1" } } */
+/* { dg-final { scan-tree-dump "c = bartem" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-96.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-96.c
new file mode 100644
index 0000000..fd1d571
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-96.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1" } */
+
+_Bool f1(unsigned x, unsigned y, unsigned *res)
+{
+ _Bool t = __builtin_add_overflow(x, y, res);
+ unsigned res1;
+ _Bool t1 = __builtin_add_overflow(x, y, &res1);
+ *res -= res1;
+ return t==t1;
+}
+
+/* { dg-final { scan-tree-dump-times "ADD_OVERFLOW" 1 "fre1" } } */
+/* { dg-final { scan-tree-dump "return 1;" "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-33.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-33.c
new file mode 100644
index 0000000..3b3bd62
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-33.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre" } */
+
+_Bool f1(unsigned x, unsigned y, unsigned *res, int flag, _Bool *t)
+{
+ if (flag)
+ *t = __builtin_add_overflow(x, y, res);
+ unsigned res1;
+ _Bool t1 = __builtin_add_overflow(x, y, &res1);
+ *res -= res1;
+ return *t==t1;
+}
+
+/* We should hoist the .ADD_OVERFLOW to before the check. */
+/* { dg-final { scan-tree-dump-times "ADD_OVERFLOW" 1 "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c
index f9152b9..8c5cc82 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
-/* { dg-additional-options "-O2 -fdump-tree-vrp-details --param logical-op-non-short-circuit=1" } */
+/* { dg-additional-options "-O2 -fdump-tree-vrp-thread1-details --param logical-op-non-short-circuit=1" } */
/* { dg-additional-options "-fdisable-tree-thread1" } */
-/* { dg-final { scan-tree-dump-times "Threaded jump" 8 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Threaded jump" 8 "vrp-thread1" } } */
void foo (void);
void bar (void);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-valid.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-valid.c
new file mode 100644
index 0000000..7adca97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-valid.c
@@ -0,0 +1,39 @@
+// { dg-do compile }
+// { dg-options "-O2 -fgimple -fdump-statistics" }
+
+// This is a collection of threadable paths. To simplify maintenance,
+// there should only be one threadable path per function.
+
+int global;
+
+// The thread from 3->4->5 crosses loops but is allowed because it
+// never crosses the latch (BB3) and is just an early exit out of the
+// loop.
+int __GIMPLE (ssa)
+foo1 (int x)
+{
+ int D_1420;
+ int a;
+
+ __BB(2):
+ a_4 = ~x_3(D);
+ goto __BB4;
+
+ // Latch.
+ __BB(3):
+ global = a_1;
+ goto __BB4;
+
+ __BB(4,loop_header(1)):
+ a_1 = __PHI (__BB2: a_4, __BB3: 0);
+ if (a_1 != 0)
+ goto __BB3;
+ else
+ goto __BB5;
+
+ __BB(5):
+ return;
+
+}
+
+// { dg-final { scan-tree-dump "Jumps threaded\" \"foo1\" 1" "statistics" } }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-vrp-thread-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-vrp-thread-1.c
index ef5611f..86d07ef 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-vrp-thread-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-vrp-thread-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1-details -fdelete-null-pointer-checks" } */
/* { dg-skip-if "" keeps_null_pointer_checks } */
void oof (void);
@@ -29,5 +29,5 @@ build_omp_regions_1 (basic_block bb, struct omp_region *parent,
/* ARM Cortex-M defined LOGICAL_OP_NON_SHORT_CIRCUIT to false,
so skip below test. */
-/* { dg-final { scan-tree-dump-times "Threaded" 1 "vrp1" { target { ! arm_cortex_m } } } } */
+/* { dg-final { scan-tree-dump-times "Threaded" 1 "vrp-thread1" { target { ! arm_cortex_m } } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp106.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp106.c
index e2e48d8..f25ea9c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp106.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp106.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/18046 */
-/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
-/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp1" } } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1-details" } */
+/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp-thread1" } } */
/* During VRP we expect to thread the true arm of the conditional through the switch
and to the BB that corresponds to the 7 ... 9 case label. */
extern void foo (void);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp55.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp55.c
index 8ae9b8d..a478a69 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp55.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp55.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-blocks-vops-details -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1-blocks-vops-details -fdelete-null-pointer-checks" } */
void arf (void);
@@ -12,6 +12,6 @@ fu (char *p, int x)
arf ();
}
-/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp1" { target { ! keeps_null_pointer_checks } } } } */
-/* { dg-final { scan-tree-dump-times "Threaded jump" 0 "vrp1" { target { keeps_null_pointer_checks } } } } */
+/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp-thread1" { target { ! keeps_null_pointer_checks } } } } */
+/* { dg-final { scan-tree-dump-times "Threaded jump" 0 "vrp-thread1" { target { keeps_null_pointer_checks } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-16.c b/gcc/testsuite/gcc.dg/vect/bb-slp-16.c
index 664e93e..e68a9b6 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-16.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-16.c
@@ -1,8 +1,5 @@
/* { dg-require-effective-target vect_int } */
-/* See note below as to why we disable threading. */
-/* { dg-additional-options "-fdisable-tree-thread1" } */
-
#include <stdarg.h>
#include "tree-vect.h"
@@ -30,10 +27,6 @@ main1 (int dummy)
*pout++ = *pin++ + a;
*pout++ = *pin++ + a;
*pout++ = *pin++ + a;
- /* In some architectures like ppc64, jump threading may thread
- the iteration where i==0 such that we no longer optimize the
- BB. Another alternative to disable jump threading would be
- to wrap the read from `i' into a function returning i. */
if (arr[i] = i)
a = i;
else
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c
index 5d80f56..ee12136 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c
@@ -1,5 +1,6 @@
/* { dg-additional-options "-O3" } */
/* { dg-require-effective-target vect_double } */
+/* { dg-additional-options "-mprefer-vector-width=128" { target x86_64-*-* i?86-*-* } } */
#include "tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr97709.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97709.c
index 672807f..56ec0f6 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr97709.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97709.c
@@ -12,12 +12,12 @@ e()
void *f[] = {&&g, &&h, &&i, &&j};
int d, c;
j:
- goto *a;
+ goto *(void*)(__INTPTR_TYPE__)a;
g:
d = 0;
h:
c = 1;
- goto *a;
+ goto *(void*)(__INTPTR_TYPE__)a;
i:
{
struct b b = {c, d};
diff --git a/gcc/testsuite/gcc.target/aarch64/cpymem-size.c b/gcc/testsuite/gcc.target/aarch64/cpymem-size.c
new file mode 100644
index 0000000..4a6f249
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/cpymem-size.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+
+#include <stdlib.h>
+
+/*
+** cpy_127:
+** mov (w|x)2, 127
+** b memcpy
+*/
+void
+cpy_127 (char *out, char *in)
+{
+ __builtin_memcpy (out, in, 127);
+}
+
+/*
+** cpy_128:
+** mov (w|x)2, 128
+** b memcpy
+*/
+void
+cpy_128 (char *out, char *in)
+{
+ __builtin_memcpy (out, in, 128);
+}
+
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/memset-corner-cases-2.c b/gcc/testsuite/gcc.target/aarch64/memset-corner-cases-2.c
new file mode 100644
index 0000000..9ee96f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memset-corner-cases-2.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdint.h>
+
+/* 127 bytes should use libcall for size.
+**set127byte:
+** mov x2, 127
+** b memset
+*/
+void __attribute__((__noinline__))
+set127byte (int64_t *src, int c)
+{
+ __builtin_memset (src, c, 127);
+}
+
+/* 128 bytes should use libcall for size.
+**set128byte:
+** mov x2, 128
+** b memset
+*/
+void __attribute__((__noinline__))
+set128byte (int64_t *src, int c)
+{
+ __builtin_memset (src, c, 128);
+}
+
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/memset-strict-align-1.c b/gcc/testsuite/gcc.target/aarch64/memset-strict-align-1.c
index 5cdc8a4..664d43a 100644
--- a/gcc/testsuite/gcc.target/aarch64/memset-strict-align-1.c
+++ b/gcc/testsuite/gcc.target/aarch64/memset-strict-align-1.c
@@ -1,14 +1,14 @@
/* { dg-do compile } */
-/* { dg-options "-Os -mstrict-align" } */
+/* { dg-options "-O2 -mstrict-align" } */
-struct s { char x[95]; };
+struct s { char x[255]; };
void foo (struct s *);
void bar (void) { struct s s1 = {}; foo (&s1); }
-/* memset (s1 = {}, sizeof = 95) should be expanded out
+/* memset (s1 = {}, sizeof = 255) should be expanded out
such that there are no overlap stores when -mstrict-align
is in use.
- so 2 pair 16 bytes stores (64 bytes).
+ so 7 pairs of 16 bytes stores (224 bytes).
1 16 byte stores
1 8 byte store
1 4 byte store
@@ -16,7 +16,7 @@ void bar (void) { struct s s1 = {}; foo (&s1); }
1 1 byte store
*/
-/* { dg-final { scan-assembler-times "stp\tq" 2 } } */
+/* { dg-final { scan-assembler-times "stp\tq" 7 } } */
/* { dg-final { scan-assembler-times "str\tq" 1 } } */
/* { dg-final { scan-assembler-times "str\txzr" 1 } } */
/* { dg-final { scan-assembler-times "str\twzr" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr102587-1.c b/gcc/testsuite/gcc.target/aarch64/sve/pr102587-1.c
new file mode 100644
index 0000000..af2ae59
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr102587-1.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8.3-a+sve -ftrivial-auto-var-init=zero" } */
+
+void foo() { __SVFloat64_t f64; }
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr102587-2.c b/gcc/testsuite/gcc.target/aarch64/sve/pr102587-2.c
new file mode 100644
index 0000000..8c9d9908
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr102587-2.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8.3-a+sve -ftrivial-auto-var-init=pattern" } */
+
+void foo() { __SVFloat64_t f64; }
diff --git a/gcc/testsuite/gcc.target/i386/attr-optimize.c b/gcc/testsuite/gcc.target/i386/attr-optimize.c
new file mode 100644
index 0000000..f5db028f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/attr-optimize.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O1 -ftree-slp-vectorize -march=znver1 -fdump-tree-optimized" } */
+
+/* Use -O2, but -ftree-slp-vectorize option should be preserved and used. */
+#pragma GCC optimize "-O2"
+
+typedef struct {
+ long n[4];
+} secp256k1_fe;
+
+void *a;
+int c;
+static void
+fn1(secp256k1_fe *p1, int p2)
+{
+ p1->n[0] = p1->n[1] = p2;
+}
+void
+fn2()
+{
+ fn1(a, !c);
+}
+
+/* { dg-final { scan-tree-dump { MEM <vector\(2\) long int> \[[^]]*\] = } "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-2.c b/gcc/testsuite/gcc.target/i386/auto-init-2.c
index b23f733..e22930a 100644
--- a/gcc/testsuite/gcc.target/i386/auto-init-2.c
+++ b/gcc/testsuite/gcc.target/i386/auto-init-2.c
@@ -33,6 +33,5 @@ void foo()
/* { dg-final { scan-rtl-dump-times "0xfffffffffffffefe" 1 "expand" } } */
/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 2 "expand" { target lp64 } } } */
/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefe" 3 "expand" { target lp64 } } } */
-/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 4 "expand" { target ia32 } } } */
-/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefe" 1 "expand" { target ia32 } } } */
-
+/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 4 "expand" { target { ! lp64 } } } } */
+/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefe" 1 "expand" { target { ! lp64 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-3.c b/gcc/testsuite/gcc.target/i386/auto-init-3.c
index df31761..891eab1 100644
--- a/gcc/testsuite/gcc.target/i386/auto-init-3.c
+++ b/gcc/testsuite/gcc.target/i386/auto-init-3.c
@@ -1,6 +1,7 @@
/* Verify zero initialization for floating point type automatic variables. */
/* { dg-do compile } */
-/* { dg-options "-ftrivial-auto-var-init=zero -march=x86-64 -mtune=generic" } */
+/* { dg-options "-ftrivial-auto-var-init=zero -march=x86-64 -mtune=generic -msse" } */
+/* { dg-additional-options "-mfpmath=387" { target ia32 } } */
long double result;
@@ -14,5 +15,5 @@ long double foo()
return result;
}
-/* { dg-final { scan-assembler-times "pxor\t\\\%xmm0, \\\%xmm0" 3 { target lp64 } } } */
-/* { dg-final { scan-assembler-times "fldz" 3 { target ia32} } } */
+/* { dg-final { scan-assembler-times "pxor\t\\\%xmm0, \\\%xmm0" 3 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "fldz" 3 { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-4.c b/gcc/testsuite/gcc.target/i386/auto-init-4.c
index 554a2c5..7b46c74 100644
--- a/gcc/testsuite/gcc.target/i386/auto-init-4.c
+++ b/gcc/testsuite/gcc.target/i386/auto-init-4.c
@@ -14,9 +14,8 @@ long double foo()
return result;
}
-/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 1 "expand" { target lp64 } } } */
-/* { dg-final { scan-rtl-dump-times "\\\[0xfefefefefefefefe\\\]" 1 "expand" { target lp64 } } } */
-/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 1 "expand" { target lp64 } } } */
+/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 1 "expand" { target { ! ia32 } } } } */
+/* { dg-final { scan-rtl-dump-times "\\\[0xfefefefefefefefe\\\]" 1 "expand" { target { ! ia32 } } } } */
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 1 "expand" { target { ! ia32 } } } } */
/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 2 "expand" { target ia32 } } } */
/* { dg-final { scan-rtl-dump-times "\\\[0xfefefefefefefefe\\\]" 2 "expand" { target ia32 } } } */
-
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-5.c b/gcc/testsuite/gcc.target/i386/auto-init-5.c
index 27d971f..0e9d74f 100644
--- a/gcc/testsuite/gcc.target/i386/auto-init-5.c
+++ b/gcc/testsuite/gcc.target/i386/auto-init-5.c
@@ -15,7 +15,5 @@ _Complex long double foo()
return result;
}
-/* { dg-final { scan-assembler-times "\\.long\t0" 14 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "\\.long\t0" 14 { target { ! ia32 } } } } */
/* { dg-final { scan-assembler-times "\\.long\t0" 12 { target ia32 } } } */
-
-
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-3.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-3.c
index 220a9f2..7c20a28 100644
--- a/gcc/testsuite/gcc.target/i386/auto-init-padding-3.c
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-3.c
@@ -24,9 +24,7 @@ int foo ()
}
/* { dg-final { scan-assembler "movl\t\\\$0," } } */
-/* { dg-final { scan-assembler "movl\t\\\$16," { target lp64 } } } */
-/* { dg-final { scan-assembler "rep stosq" { target lp64 } } } */
+/* { dg-final { scan-assembler "movl\t\\\$16," { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "rep stosq" { target { ! ia32 } } } } */
/* { dg-final { scan-assembler "movl\t\\\$32," { target ia32 } } } */
/* { dg-final { scan-assembler "rep stosl" { target ia32 } } } */
-
-
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-7.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-7.c
index c136e1c..c3823de 100644
--- a/gcc/testsuite/gcc.target/i386/auto-init-padding-7.c
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-7.c
@@ -18,6 +18,4 @@ int foo ()
}
/* { dg-final { scan-rtl-dump-times "const_int 0 \\\[0\\\]\\\) repeated x16" 1 "expand" { target ia32 } } } */
-/* { dg-final { scan-rtl-dump-times "const_int 0 \\\[0\\\]\\\)" 1 "expand" { target lp64 } } } */
-
-
+/* { dg-final { scan-rtl-dump-times "const_int 0 \\\[0\\\]\\\)" 1 "expand" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-8.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-8.c
index 45baa3c..4f45755 100644
--- a/gcc/testsuite/gcc.target/i386/auto-init-padding-8.c
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-8.c
@@ -18,4 +18,4 @@ int foo ()
}
/* { dg-final { scan-rtl-dump-times "const_int 0 \\\[0\\\]\\\) repeated x16" 1 "expand" { target ia32 } } } */
-/* { dg-final { scan-rtl-dump-times "const_int 0 \\\[0\\\]\\\)" 1 "expand" { target lp64 } } } */
+/* { dg-final { scan-rtl-dump-times "const_int 0 \\\[0\\\]\\\)" 1 "expand" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-9.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-9.c
index eafa327..a87b68b 100644
--- a/gcc/testsuite/gcc.target/i386/auto-init-padding-9.c
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-9.c
@@ -19,7 +19,7 @@ int foo ()
}
/* { dg-final { scan-assembler "movl\t\\\$0," } } */
-/* { dg-final { scan-assembler "movl\t\\\$20," { target lp64} } } */
-/* { dg-final { scan-assembler "rep stosq" { target lp64 } } } */
+/* { dg-final { scan-assembler "movl\t\\\$20," { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "rep stosq" { target { ! ia32 } } } } */
/* { dg-final { scan-assembler "movl\t\\\$40," { target ia32} } } */
/* { dg-final { scan-assembler "rep stosl" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx-1.c b/gcc/testsuite/gcc.target/i386/avx-1.c
index a04c678..8744aa7 100644
--- a/gcc/testsuite/gcc.target/i386/avx-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx-1.c
@@ -787,6 +787,26 @@
#define __builtin_ia32_vfnmsubsh3_mask(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_mask(A, B, C, D, 8)
#define __builtin_ia32_vfnmsubsh3_mask3(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_mask3(A, B, C, D, 8)
#define __builtin_ia32_vfnmsubsh3_maskz(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfcmaddcph512_round(A, B, C, D) __builtin_ia32_vfcmaddcph512_round(A, B, C, 8)
+#define __builtin_ia32_vfcmaddcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfcmaddcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcph512_maskz_round(B, C, D, A, E) __builtin_ia32_vfcmaddcph512_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmaddcph512_round(A, B, C, D) __builtin_ia32_vfmaddcph512_round(A, B, C, 8)
+#define __builtin_ia32_vfmaddcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfmaddcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcph512_maskz_round(B, C, D, A, E) __builtin_ia32_vfmaddcph512_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmulcph512_round(A, B, C) __builtin_ia32_vfmulcph512_round(A, B, 8)
+#define __builtin_ia32_vfmulcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfmulcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmulcph512_round(A, B, C) __builtin_ia32_vfcmulcph512_round(A, B, 8)
+#define __builtin_ia32_vfcmulcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfcmulcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcsh_round(A, B, C, D) __builtin_ia32_vfmaddcsh_round(A, B, C, 8)
+#define __builtin_ia32_vfmaddcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfmaddcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcsh_maskz_round(B, C, D, A, E) __builtin_ia32_vfmaddcsh_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfcmaddcsh_round(A, B, C, D) __builtin_ia32_vfcmaddcsh_round(A, B, C, 8)
+#define __builtin_ia32_vfcmaddcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfcmaddcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcsh_maskz_round(B, C, D, A, E) __builtin_ia32_vfcmaddcsh_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmulcsh_round(A, B, C) __builtin_ia32_vfmulcsh_round(A, B, 8)
+#define __builtin_ia32_vfmulcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfmulcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmulcsh_round(A, B, C) __builtin_ia32_vfcmulcsh_round(A, B, 8)
+#define __builtin_ia32_vfcmulcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfcmulcsh_mask_round(A, C, D, B, 8)
/* avx512fp16vlintrin.h */
#define __builtin_ia32_cmpph128_mask(A, B, C, D) __builtin_ia32_cmpph128_mask(A, B, 1, D)
diff --git a/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-3.c b/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-3.c
index 1ba8172..40aefb5 100644
--- a/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-3.c
@@ -8,7 +8,7 @@
#define MAX 1000
#define EPS 0.00001
-__attribute__ ((noinline, optimize (1)))
+__attribute__ ((noinline, optimize (1, "-fno-fast-math")))
void static
compute_rsqrt_ref (float *a, float *r)
{
diff --git a/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-5.c b/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-5.c
index e067a81..498f4d5 100644
--- a/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-5.c
+++ b/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-5.c
@@ -8,7 +8,7 @@
#define MAX 1000
#define EPS 0.00001
-__attribute__ ((noinline, optimize (1)))
+__attribute__ ((noinline, optimize (1, "-fno-fast-math")))
void static
compute_sqrt_ref (float *a, float *r)
{
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vect-rebuild.c b/gcc/testsuite/gcc.target/i386/avx512f-vect-rebuild.c
new file mode 100644
index 0000000..aef6855
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vect-rebuild.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mavx512vl -mavx512dq -fno-tree-forwprop" } */
+
+typedef double v2df __attribute__ ((__vector_size__ (16)));
+typedef double v4df __attribute__ ((__vector_size__ (32)));
+
+v2df h (v4df x)
+{
+ v2df xx = { x[2], x[3] };
+ return xx;
+}
+
+v4df f2 (v4df x)
+{
+ v4df xx = { x[0], x[1], x[2], x[3] };
+ return xx;
+}
+
+/* { dg-final { scan-assembler-not "unpck" } } */
+/* { dg-final { scan-assembler-not "valign" } } */
+/* { dg-final { scan-assembler-times "\tv?extract(?:f128|f64x2)\[ \t\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-13.c b/gcc/testsuite/gcc.target/i386/avx512fp16-13.c
new file mode 100644
index 0000000..c3bae65
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-13.c
@@ -0,0 +1,140 @@
+/* { dg-do compile} */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+#include <immintrin.h>
+void
+__attribute__ ((noinline, noclone))
+store512_ph (void *p, __m512h a)
+{
+ _mm512_store_ph (p, a);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*\\)" 1 } } */
+
+void
+__attribute__ ((noinline, noclone))
+store256_ph (void *p, __m256h a)
+{
+ _mm256_store_ph (p, a);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*\\)" 1 } } */
+
+void
+__attribute__ ((noinline, noclone))
+store_ph (void *p, __m128h a)
+{
+ _mm_store_ph (p, a);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*\\)" 1 } } */
+
+__m512h
+__attribute__ ((noinline, noclone))
+load512_ph (void const *p)
+{
+ return _mm512_load_ph (p);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*\\)" 1 } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+load256_ph (void const *p)
+{
+ return _mm256_load_ph (p);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*\\)" 1 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+load_ph (void const *p)
+{
+ return _mm_load_ph (p);
+}
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*\\)" 1 } } */
+
+__m512h
+__attribute__ ((noinline, noclone))
+load512u_ph (void const *p)
+{
+ return _mm512_loadu_ph (p);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]*\[^,\]*,\[^\{\n\]*%zmm\[0-9\]" 1 } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+load256u_ph (void const *p)
+{
+ return _mm256_loadu_ph (p);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]*\[^,\]*,\[^\{\n\]*%ymm\[0-9\]" 1 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+load128u_ph (void const *p)
+{
+ return _mm_loadu_ph (p);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]*\[^,\]*,\[^\{\n\]*%xmm\[0-9\]" 1 } } */
+
+void
+__attribute__ ((noinline, noclone))
+store512u_ph (void *p, __m512h a)
+{
+ return _mm512_storeu_ph (p, a);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]*\[^\{\n\]*%zmm\[0-9\], *\[^,\]*" 1 } } */
+
+void
+__attribute__ ((noinline, noclone))
+store256u_ph (void *p, __m256h a)
+{
+ return _mm256_storeu_ph (p, a);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]*\[^\{\n\]*%ymm\[0-9\], *\[^,\]*" 1 } } */
+
+void
+__attribute__ ((noinline, noclone))
+storeu_ph (void *p, __m128h a)
+{
+ return _mm_storeu_ph (p, a);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]*\[^\{\n\]*%xmm\[0-9\], *\[^,\]*" 1 } } */
+
+__m512h
+__attribute__ ((noinline, noclone))
+abs512_ph (__m512h a)
+{
+ return _mm512_abs_ph (a);
+}
+
+/* { dg-final { scan-assembler-times "vpbroadcastd\[^\n\]*%zmm\[0-9\]+" 1 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vpandd\[^\n\]*%zmm\[0-9\]+" 1 } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+abs256_ph (__m256h a)
+{
+ return _mm256_abs_ph (a);
+}
+
+/* { dg-final { scan-assembler-times "vpbroadcastq\[^\n\]*%ymm\[0-9\]+" 1 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vpand\[^\n\]*%ymm\[0-9\]+" 1 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+abs_ph (__m128h a)
+{
+ return _mm_abs_ph (a);
+}
+
+/* { dg-final { scan-assembler-times "vpbroadcastq\[^\n\]*%xmm\[0-9\]+" 1 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vpand\[^\n\]*%xmm\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-14.c b/gcc/testsuite/gcc.target/i386/avx512fp16-14.c
new file mode 100644
index 0000000..5c670ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-14.c
@@ -0,0 +1,85 @@
+/* { dg-do compile} */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512bw" } */
+
+#include <immintrin.h>
+
+__m512h
+__attribute__ ((noinline, noclone))
+test_mm512_mask_blend_ph (__mmask32 U, __m512h A, __m512h B )
+{
+ return _mm512_mask_blend_ph (U, A, B);
+}
+
+/* { dg-final { scan-assembler-times "(?:vmovdqu16|vpblendmw)\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+__m512h
+__attribute__ ((noinline, noclone))
+test_mm512_permutex2var_ph (__m512h A, __m512i I, __m512h B)
+{
+ return _mm512_permutex2var_ph (A, I, B);
+}
+
+/* { dg-final { scan-assembler-times "vperm\[ti\]2w\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+" 1 } } */
+
+__m512h
+__attribute__ ((noinline, noclone))
+test_mm512_permutexvar_ph (__m512i A, __m512h B)
+{
+ return _mm512_permutexvar_ph (A, B);
+}
+
+/* { dg-final { scan-assembler-times "vpermw\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+" 1 } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+test_mm256_mask_blend_ph (__mmask16 U, __m256h A, __m256h B )
+{
+ return _mm256_mask_blend_ph (U, A, B);
+}
+
+/* { dg-final { scan-assembler-times "(?:vmovdqu16|vpblendmw)\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+test_mm256_permutex2var_ph (__m256h A, __m256i I, __m256h B)
+{
+ return _mm256_permutex2var_ph (A, I, B);
+}
+
+/* { dg-final { scan-assembler-times "vperm\[ti\]2w\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+" 1 { target { ! ia32 } } } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+test_mm256_permutexvar_ph (__m256i A, __m256h B)
+{
+ return _mm256_permutexvar_ph (A, B);
+}
+
+/* { dg-final { scan-assembler-times "vpermw\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+" 1 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+test_mm_mask_blend_ph (__mmask8 U, __m128h A, __m128h B )
+{
+ return _mm_mask_blend_ph (U, A, B);
+}
+
+/* { dg-final { scan-assembler-times "(?:vmovdqu16|vpblendmw)\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+test_mm_permutex2var_ph (__m128h A, __m128i I, __m128h B)
+{
+ return _mm_permutex2var_ph (A, I, B);
+}
+
+/* { dg-final { scan-assembler-times "vperm\[it\]2w\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+" 1 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+test_mm_permutexvar_ph (__m128i A, __m128h B)
+{
+ return _mm_permutexvar_ph (A, B);
+}
+
+/* { dg-final { scan-assembler-times "vpermw\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-1.c
new file mode 100644
index 0000000..754e909
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-1.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+/* { dg-final { scan-assembler-times "vaddph" 2 } } */
+/* { dg-final { scan-assembler-times "vsubph" 2 } } */
+/* { dg-final { scan-assembler-times "vmulph" 2 } } */
+/* { dg-final { scan-assembler-times "vdivph" 2 } } */
+
+#define DO_PRAGMA(X) _Pragma(#X)
+
+#define VEC_OP_VV(size, op, name) \
+void \
+__attribute__ ((noinline, noclone, optimize("tree-slp-vectorize"))) \
+vecop_v##size##hf##name (_Float16 * restrict dst, \
+ _Float16 * restrict src1, _Float16 * restrict src2) \
+{ \
+ int i; \
+ DO_PRAGMA (GCC unroll size) \
+ for (i = 0; i < size; i++) \
+ dst[i] = src1[i] op src2[i]; \
+}
+
+VEC_OP_VV(4, +, add)
+VEC_OP_VV(2, +, add)
+VEC_OP_VV(4, -, sub)
+VEC_OP_VV(2, -, sub)
+VEC_OP_VV(4, *, mul)
+VEC_OP_VV(2, *, mul)
+VEC_OP_VV(4, /, div)
+VEC_OP_VV(2, /, div)
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-2.c b/gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-2.c
new file mode 100644
index 0000000..4dc6f9f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-2.c
@@ -0,0 +1,75 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+static void vec_op_test (void);
+#define DO_TEST vec_op_test
+#define AVX512FP16
+#define AVX512VL
+#include "avx512f-check.h"
+#include "avx512fp16-64-32-vecop-1.c"
+
+_Float16 a[4], b[4], fexp[4], fref[4];
+
+#define EMULATE_VEC_OP_VV(size, op, name) \
+void \
+__attribute__ ((noinline, noclone)) \
+scalar_vecop_v##size##hf##name ( \
+ _Float16 * restrict dst, _Float16 * restrict src1, \
+ _Float16 * restrict src2) \
+{ \
+ int i; \
+ for (i = 0; i < size; i++) \
+ dst[i] = src1[i] op src2[i]; \
+}
+
+EMULATE_VEC_OP_VV (4, +, add)
+EMULATE_VEC_OP_VV (2, +, add)
+EMULATE_VEC_OP_VV (4, -, sub)
+EMULATE_VEC_OP_VV (2, -, sub)
+EMULATE_VEC_OP_VV (4, *, mul)
+EMULATE_VEC_OP_VV (2, *, mul)
+EMULATE_VEC_OP_VV (4, /, div)
+EMULATE_VEC_OP_VV (2, /, div)
+
+void init()
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ a[i] = i + 0.5;
+ b[i] = i * 1.5;
+ fexp[i] = fref[i] = 2.75 * i;
+ }
+}
+
+int check_cond(void *a, void *b, int size)
+{
+ int i;
+ unsigned short *pa = (unsigned short *)a,
+ *pb = (unsigned short *)b;
+ for (i = 0; i < size; i++)
+ if (pa[i] != pb[i])
+ return 0;
+ return 1;
+}
+
+#define TEST_VEC_OP_VV(size, name) \
+{ \
+ init (); \
+ scalar_vecop_v##size##hf##name (a, b, fexp); \
+ vecop_v##size##hf##name (a, b, fref); \
+ if (!check_cond ((void *)fexp, (void *)fref, size)) \
+ abort(); \
+}
+
+static void vec_op_test()
+{
+ TEST_VEC_OP_VV (4, add)
+ TEST_VEC_OP_VV (2, add)
+ TEST_VEC_OP_VV (4, sub)
+ TEST_VEC_OP_VV (2, sub)
+ TEST_VEC_OP_VV (4, mul)
+ TEST_VEC_OP_VV (2, mul)
+ TEST_VEC_OP_VV (4, div)
+ TEST_VEC_OP_VV (2, div)
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-1.c
new file mode 100644
index 0000000..62115f1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-1.c
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16" } */
+
+int
+f1 (_Float16 x, _Float16 y)
+{
+ return x > y;
+}
+
+int
+f2 (_Float16 x, _Float16 y)
+{
+ return x < y;
+}
+
+/* { dg-final { scan-assembler-times "seta" 2 } } */
+
+int
+f3 (_Float16 x, _Float16 y)
+{
+ return x >= y;
+}
+
+int
+f4 (_Float16 x, _Float16 y)
+{
+ return x <= y;
+}
+
+/* { dg-final { scan-assembler-times "setnb" 2 } } */
+
+int
+f5 (_Float16 x, _Float16 y)
+{
+ return __builtin_isunordered (x, y);
+}
+
+/* { dg-final { scan-assembler-not "vcvtsh2s\[sd\]" } } */
+/* { dg-final { scan-assembler-times "xorl" 5 } } */
+/* { dg-final { scan-assembler-times "vcomish\[^\n\r\]*xmm\[0-9\]" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-2.c b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-2.c
new file mode 100644
index 0000000..150c351
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-2.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfpmath=sse -mavx512fp16" } */
+
+int
+foo (_Float16 y)
+{
+ return __builtin_isinf (y);
+}
+
+int
+foo2 (_Float16 y)
+{
+ return __builtin_isfinite (y);
+}
+
+int
+foo3 (_Float16 y)
+{
+ return __builtin_signbit(y);
+}
+
+int
+foo4 (_Float16 y)
+{
+ return __builtin_isnormal (y);
+}
+
+/* { dg-final { scan-assembler-not "vcvtsh2s\[sd\]" } } */
+/* { dg-final { scan-assembler-times "vucomish\[^\n\r\]*xmm\[0-9\]" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-minmax-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-minmax-1.c
new file mode 100644
index 0000000..90080e4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-minmax-1.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16 -mprefer-vector-width=512" } */
+
+_Float16
+minf1 (_Float16 a, _Float16 b)
+{
+ return __builtin_fminf16 (a, b);
+}
+
+void
+minf2 (_Float16* __restrict psrc1, _Float16* __restrict psrc2,
+ _Float16* __restrict pdst)
+{
+ for (int i = 0; i != 32; i++)
+ pdst[i] = __builtin_fminf16 (psrc1[i], psrc2[i]);
+}
+
+_Float16
+maxf1 (_Float16 a, _Float16 b)
+{
+ return __builtin_fmaxf16 (a, b);
+}
+
+void
+maxf2 (_Float16* __restrict psrc1, _Float16* __restrict psrc2,
+ _Float16* __restrict pdst)
+{
+ for (int i = 0; i != 32; i++)
+ pdst[i] = __builtin_fmaxf16 (psrc1[i], psrc2[i]);
+}
+
+/* { dg-final { scan-assembler-times "vmaxsh\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxph\[^\n\r\]*zmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vminsh\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vminph\[^\n\r\]*zmm\[0-9\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-round-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-round-1.c
new file mode 100644
index 0000000..a1c6636
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-round-1.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16" } */
+
+_Float16
+f1 (_Float16 x)
+{
+ return __builtin_truncf16 (x);
+}
+
+_Float16
+f2 (_Float16 x)
+{
+ return __builtin_floorf16 (x);
+}
+
+_Float16
+f3 (_Float16 x)
+{
+ return __builtin_ceilf16 (x);
+}
+
+_Float16
+f4 (_Float16 x)
+{
+ return __builtin_roundevenf16 (x);
+}
+
+_Float16
+f5 (_Float16 x)
+{
+ return __builtin_rintf16 (x);
+}
+
+_Float16
+f6 (_Float16 x)
+{
+ return __builtin_nearbyintf16 (x);
+}
+
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\\\$11\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\\\$10\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\\\$9\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\\\$8\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\\\$4\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\\\$12\[^\n\r\]*xmm\[0-9\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-sqrt-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-sqrt-1.c
new file mode 100644
index 0000000..b4efc84
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-sqrt-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16 -mprefer-vector-width=512" } */
+
+_Float16
+f1 (_Float16 x)
+{
+ return __builtin_sqrtf16 (x);
+}
+
+void
+f2 (_Float16* __restrict psrc, _Float16* __restrict pdst)
+{
+ for (int i = 0; i != 32; i++)
+ pdst[i] = __builtin_sqrtf16 (psrc[i]);
+}
+
+/* { dg-final { scan-assembler-times "vsqrtsh\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vsqrtph\[^\n\r\]*zmm\[0-9\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-complex-constraints.c b/gcc/testsuite/gcc.target/i386/avx512fp16-complex-constraints.c
new file mode 100644
index 0000000..fcd3794
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-complex-constraints.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+
+/* { dg-final { scan-assembler-not "vfmulcph\[ \\t\]+\[^\{\n\]*%zmm1+\[^\n\r]*%zmm0+\[^\n\r]*%zmm0+(?:\n|\[ \\t\]+#)" } } */
+/* { dg-final { scan-assembler-not "vfmaddcph\[ \\t\]+\[^\{\n\]*%zmm0+\[^\n\r]*%zmm0+\[^\n\r]*%zmm0+(?:\n|\[ \\t\]+#)" } } */
+/* { dg-final { scan-assembler-not "vfmulcsh\[ \\t\]+\[^\{\n\]*%xmm1+\[^\n\r]*%xmm0+\[^\n\r]*%xmm0+(?:\n|\[ \\t\]+#)" } } */
+/* { dg-final { scan-assembler-not "vfmaddcsh\[ \\t\]+\[^\{\n\]*%xmm0+\[^\n\r]*%xmm0+\[^\n\r]*%xmm0+(?:\n|\[ \\t\]+#)" } } */
+
+#include <immintrin.h>
+
+volatile __m512h a1;
+volatile __m128h a2;
+__m512h b1;
+__m128h b2;
+
+void extern
+avx512f_test (void)
+{
+ a1 = _mm512_fmul_pch (a1, a1);
+ b1 = _mm512_fmadd_pch (b1, b1, b1);
+ a2 = _mm_fmul_sch (a2, a2);
+ b2 = _mm_fmadd_sch (b2, b2, b2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-conjugation-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-conjugation-1.c
new file mode 100644
index 0000000..662b23c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-conjugation-1.c
@@ -0,0 +1,34 @@
+/* { dg-do compile} */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <immintrin.h>
+__m512h
+__attribute__ ((noinline, noclone))
+test_mm512_conj_pch (__m512h __A)
+{
+ return _mm512_conj_pch (__A);
+}
+
+/* { dg-final { scan-assembler-times "vpxord\[^\n\]*%zmm\[0-9\]+" 3 } } */
+
+__m512h
+__attribute__ ((noinline, noclone))
+test_mm512_mask_conj_pch (__m512h __W, __mmask16 __U, __m512h __A)
+{
+ return _mm512_mask_conj_pch (__W, __U, __A);
+}
+
+/* { dg-final { scan-assembler-times "vpxord\[^\n\]*%zmm\[0-9\]+" 3 } } */
+/* { dg-final { scan-assembler-times "kmovw\[^\n\]*%k\[1-9\]+" 2 } } */
+/* { dg-final { scan-assembler-times "vmovaps\[^\n]" 2 } } */
+
+__m512h
+__attribute__ ((noinline, noclone))
+test_mm512_maskz_conj_pch (__mmask16 __U, __m512h __A)
+{
+ return _mm512_maskz_conj_pch (__U, __A);
+}
+
+/* { dg-final { scan-assembler-times "vpxord\[^\n\]*%zmm\[0-9\]+" 3 } } */
+/* { dg-final { scan-assembler-times "kmovw\[^\n\]*%k\[1-9\]+" 2 } } */
+/* { dg-final { scan-assembler-times "vmovaps\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-floatvnhf.c b/gcc/testsuite/gcc.target/i386/avx512fp16-floatvnhf.c
new file mode 100644
index 0000000..8471a1d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-floatvnhf.c
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -ftree-slp-vectorize -mprefer-vector-width=512" } */
+
+extern long long di[8];
+extern unsigned long long udi[8];
+extern int si[16];
+extern unsigned int usi[16];
+extern short hi[32];
+extern unsigned short uhi[32];
+extern _Float16 hf[32];
+
+#define DO_PRAGMA(X) _Pragma(#X)
+
+#define FLOATHFVV(size, mode) \
+ void __attribute__ ((noinline, noclone)) \
+float##v##size##mode##v##size##hf () \
+{\
+ int i; \
+ DO_PRAGMA (GCC unroll size) \
+ for (i = 0; i < size; i++) \
+ hf[i] = (_Float16) mode[i]; \
+}
+
+FLOATHFVV(32, hi)
+FLOATHFVV(16, hi)
+FLOATHFVV(8, hi)
+FLOATHFVV(16, si)
+FLOATHFVV(8, si)
+FLOATHFVV(4, si)
+FLOATHFVV(8, di)
+FLOATHFVV(4, di)
+FLOATHFVV(2, di)
+
+FLOATHFVV(32, uhi)
+FLOATHFVV(16, uhi)
+FLOATHFVV(8, uhi)
+FLOATHFVV(16, usi)
+FLOATHFVV(8, usi)
+FLOATHFVV(4, usi)
+FLOATHFVV(8, udi)
+FLOATHFVV(4, udi)
+FLOATHFVV(2, udi)
+
+/* { dg-final { scan-assembler-times "vcvtqq2phz\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuqq2phz\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtqq2phy\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuqq2phy\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtqq2phx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuqq2phx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtdq2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtudq2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtdq2phy\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtudq2phy\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtdq2phx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtudq2phx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-fma-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-fma-1.c
new file mode 100644
index 0000000..d78d762
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-fma-1.c
@@ -0,0 +1,69 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16" } */
+
+typedef _Float16 v32hf __attribute__ ((__vector_size__ (64)));
+
+_Float16
+foo1 (_Float16 a, _Float16 b, _Float16 c)
+{
+ return a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfmadd132sh\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+_Float16
+foo2 (_Float16 a, _Float16 b, _Float16 c)
+{
+ return -a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmadd132sh\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+_Float16
+foo3 (_Float16 a, _Float16 b, _Float16 c)
+{
+ return a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfmsub132sh\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+_Float16
+foo4 (_Float16 a, _Float16 b, _Float16 c)
+{
+ return -a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmsub132sh\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+v32hf
+foo5 (v32hf a, v32hf b, v32hf c)
+{
+ return a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfmadd132ph\[^\n\r\]*zmm\[0-9\]" 1 } } */
+
+v32hf
+foo6 (v32hf a, v32hf b, v32hf c)
+{
+ return -a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmadd132ph\[^\n\r\]*zmm\[0-9\]" 1 } } */
+
+v32hf
+foo7 (v32hf a, v32hf b, v32hf c)
+{
+ return a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfmsub132ph\[^\n\r\]*zmm\[0-9\]" 1 } } */
+
+v32hf
+foo8 (v32hf a, v32hf b, v32hf c)
+{
+ return -a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmsub132ph\[^\n\r\]*zmm\[0-9\]" 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-helper.h b/gcc/testsuite/gcc.target/i386/avx512fp16-helper.h
index ce3cfdc..69948f8 100644
--- a/gcc/testsuite/gcc.target/i386/avx512fp16-helper.h
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-helper.h
@@ -172,9 +172,9 @@ init_src()
for (i = 0; i < AVX512F_MAX_ELEM; i++) {
v1.f32[i] = i + 1;
- v2.f32[i] = i * 0.5f;
+ v2.f32[i] = (i + 2) * 0.5f;
v3.f32[i] = i * 1.5f;
- v4.f32[i] = i - 0.5f;
+ v4.f32[i] = i - 1.5f;
src3.u32[i] = (i + 1) * 10;
}
@@ -234,10 +234,12 @@ init_dest(V512 * res, V512 * exp)
#undef DF
#undef H_HF
#undef NET_MASK
+#undef NET_CMASK
#undef MASK_VALUE
#undef HALF_MASK
#undef ZMASK_VALUE
#define NET_MASK 0xffff
+#define NET_CMASK 0xff
#define MASK_VALUE 0xcccc
#define ZMASK_VALUE 0xfcc1
#define HALF_MASK 0xcc
@@ -253,10 +255,12 @@ init_dest(V512 * res, V512 * exp)
#undef SI
#undef H_HF
#undef NET_MASK
+#undef NET_CMASK
#undef MASK_VALUE
#undef ZMASK_VALUE
#undef HALF_MASK
#define NET_MASK 0xff
+#define NET_CMASK 0xff
#define MASK_VALUE 0xcc
#define HALF_MASK MASK_VALUE
#define ZMASK_VALUE 0xc1
@@ -267,6 +271,7 @@ init_dest(V512 * res, V512 * exp)
#define H_HF(x) x.xmmh[0]
#else
#define NET_MASK 0xffffffff
+#define NET_CMASK 0xffff
#define MASK_VALUE 0xcccccccc
#define ZMASK_VALUE 0xfcc1fcc1
#define HALF_MASK 0xcccc
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-1.c
new file mode 100644
index 0000000..3556316
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-1.c
@@ -0,0 +1,132 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+
+#include <immintrin.h>
+#include "avx512-check.h"
+
+__m512h a1 = { -39.3f16, -180.9f16, 13.4f16, 35.4f16, -41.1f16, -14.4f16, 24.5f16, 53.54f16,
+ 238.4f16, -134.8f16, 24.5f16, 35.6f16, -346.7f16, -43.4f16, -535.3f16, 324.7f16,
+ 82.5f16, 21.4f16, 24.4f16, 53.4f16, 23.5f16, -24.4f16, -34.5f16, -32.5f16,
+ 23.6f16, -13.4f16, 24.5f16, 35.5f16, -34.4f16, -24.5f16, -34.5f16, 13.5f16 };
+
+__m512h a2 = { 1.25f16, 2.25f16, -0.25f16, 4.0f16, -2.0f16, 4.0f16, -3.0f16, 2.0f16,
+ -0.5f16, -1.0f16, 1.0f16, -1.0f16, 1.0f16, 1.0f16, 2.0f16, 4.0f16,
+ 1.25f16, 2.25f16, -4.25f16, 4.0f16, -2.4f16, 4.0f16, -3.0f, 2.0f16,
+ -4.5f16, 7.6f16, 0.7f16, -8.2f16, 2.1f16, 2.4f16, -2.0f16, 19.4f16 };
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_add_ph (__m512h a)
+{
+ return _mm512_reduce_add_ph (a);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_mul_ph (__m512h a)
+{
+ return _mm512_reduce_mul_ph (a);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_max_ph (__m512h a)
+{
+ return _mm512_reduce_max_ph (a);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_min_ph (__m512h a)
+{
+ return _mm512_reduce_min_ph (a);
+}
+
+#define SIZE 32
+#define REF_ADDMUL(op, a) \
+ __m256h __a1 = _mm256_setzero_ph (); \
+ for (int i =0; i < 16; i++) { \
+ __a1[i] = (_Float16) a[i] op (_Float16) a[i + 16]; \
+ } \
+ __m128h __a2 = _mm_setzero_ph (); \
+ for (int i =0; i < 8; i++) { \
+ __a2[i] = (_Float16) __a1[i] op (_Float16) __a1[i + 8]; \
+ } \
+ _Float16 __c0 = __a2[0] op __a2[4]; \
+ _Float16 __c1 = __a2[1] op __a2[5]; \
+ _Float16 __c2 = __a2[2] op __a2[6]; \
+ _Float16 __c3 = __a2[3] op __a2[7]; \
+ _Float16 __d0 = __c0 op __c2; \
+ _Float16 __d1 = __c1 op __c3; \
+ _Float16 __e0 = __d0 op __d1; \
+ r3 = __e0
+
+#define TESTOP(opname, op, a) \
+ do { \
+ _Float16 r1 = _mm512_reduce_##opname##_ph (a); \
+ _Float16 r2 = test_reduce_##opname##_ph (a); \
+ _Float16 r3 = a[0]; \
+ if (r1 != r2) { \
+ __builtin_abort (); \
+ } \
+ REF_ADDMUL (op, a); \
+ if (r1 != r3) { \
+ __builtin_abort (); \
+ } \
+ } while (0)
+
+#define TEST_ADDMUL_PH(a) \
+ do { \
+ TESTOP (add, +, a); \
+ TESTOP (mul, *, a); \
+ } while (0)
+
+ static void
+ test_512_addmul_ph (void)
+ {
+ TEST_ADDMUL_PH (a1);
+ TEST_ADDMUL_PH (a2);
+ }
+
+#undef TESTOP
+#define TESTOP(opname, op, a) \
+ do { \
+ _Float16 r1 = _mm512_reduce_##opname##_ph (a); \
+ _Float16 r2 = test_reduce_##opname##_ph (a); \
+ _Float16 r3 = a[0]; \
+ if (r1 != r2) { \
+ __builtin_abort (); \
+ } \
+ for (int i = 1; i < SIZE; i++) \
+ r3 = r3 op a[i]; \
+ if (r1 != r3) { \
+ __builtin_abort (); \
+ } \
+ } while (0)
+
+#define TEST_MINMAX_PH(a) \
+ do { \
+ TESTOP (min, < a[i] ? r3 :, a); \
+ TESTOP (max, > a[i] ? r3 :, a); \
+ } while (0)
+
+static void
+test_512_minmax_ph (void)
+{
+ TEST_MINMAX_PH (a1);
+ TEST_MINMAX_PH (a2);
+}
+
+static void
+do_test (void)
+{
+ test_512_addmul_ph();
+ test_512_minmax_ph();
+}
+
+#undef SIZE
+#undef REF_ADDMUL
+#undef TESTOP
+#undef TEST_ADDMUL_PH
+#undef TEST_MINMAX_PH
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-2.c b/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-2.c
new file mode 100644
index 0000000..593340e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-2.c
@@ -0,0 +1,96 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mprefer-vector-width=512 -fdump-tree-optimized" } */
+
+/* { dg-final { scan-tree-dump-times "\.REDUC_PLUS" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\.REDUC_MIN" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\.REDUC_MAX" 3 "optimized" } } */
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_add_128 (_Float16* p)
+{
+ _Float16 sum = 0;
+ for (int i = 0; i != 8; i++)
+ sum += p[i];
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_add_256 (_Float16* p)
+{
+ _Float16 sum = 0;
+ for (int i = 0; i != 16; i++)
+ sum += p[i];
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_add_512 (_Float16* p)
+{
+ _Float16 sum = 0;
+ for (int i = 0; i != 32; i++)
+ sum += p[i];
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_min_128 (_Float16* p)
+{
+ _Float16 sum = p[0];
+ for (int i = 0; i != 8; i++)
+ sum = sum > p[i] ? p[i] : sum;
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_min_256 (_Float16* p)
+{
+ _Float16 sum = p[0];
+ for (int i = 0; i != 16; i++)
+ sum = sum > p[i] ? p[i] : sum;
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_min_512 (_Float16* p)
+{
+ _Float16 sum = p[0];
+ for (int i = 0; i != 32; i++)
+ sum = sum > p[i] ? p[i] : sum;
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_max_128 (_Float16* p)
+{
+ _Float16 sum = p[0];
+ for (int i = 0; i != 8; i++)
+ sum = sum < p[i] ? p[i] : sum;
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_max_256 (_Float16* p)
+{
+ _Float16 sum = p[0];
+ for (int i = 0; i != 16; i++)
+ sum = sum < p[i] ? p[i] : sum;
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_max_512 (_Float16* p)
+{
+ _Float16 sum = p[0];
+ for (int i = 0; i != 32; i++)
+ sum = sum < p[i] ? p[i] : sum;
+ return sum;
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-3.c b/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-3.c
new file mode 100644
index 0000000..9281a3b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-3.c
@@ -0,0 +1,91 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512fp16" } */
+/* { dg-require-effective-target avx512fp16 } */
+/* { dg-require-effective-target avx512vl } */
+
+#define AVX512FP16
+#define AVX512VL
+
+#include "avx512f-helper.h"
+
+#include "avx512fp16-reduce-op-2.c"
+
+void
+test_256 (void)
+{
+ _Float16 a[32];
+ int sign = 1;
+ _Float16 res1 = 0, exp1;
+ _Float16 res2 = 0, exp2;
+ _Float16 res3 = 0, exp3;
+
+ for (int i = 0; i != 32; i++)
+ {
+ a[i] = sign * (4.0 * i);
+ sign *= -1;
+ if (i < 8)
+ res1 += a[i];
+ if (i < 16)
+ res2 += a[i];
+ res3 += a[i];
+ }
+
+ exp1 = reduc_add_128 (a);
+ exp2 = reduc_add_256 (a);
+ exp3 = reduc_add_512 (a);
+ if (exp1 != res1 || exp2 != res2 || exp3 != res3)
+ abort();
+}
+
+#define MAX(A, B) ((A) > (B) ? (A) : (B))
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+
+void
+test_128 ()
+{
+ _Float16 a[32];
+ int sign = 1;
+ _Float16 min_res1, min_exp1, max_res1, max_exp1;
+ _Float16 min_res2, min_exp2, max_res2, max_exp2;
+ _Float16 min_res3, min_exp3, max_res3, max_exp3;
+
+ for (int i = 0; i != 32; i++)
+ {
+ a[i] = sign * (4.9 * i * i - 8.3 * i + 14.8);
+ sign *= -1;
+ }
+
+ min_res1 = max_res1 = a[0];
+ for (int i = 0 ; i != 8; i++)
+ {
+ min_res1 = MIN (min_res1, a[i]);
+ max_res1 = MAX (max_res1, a[i]);
+ }
+
+ min_res2 = min_res1;
+ max_res2 = max_res1;
+ for (int i = 8 ; i != 16; i++)
+ {
+ min_res2 = MIN (min_res2, a[i]);
+ max_res2 = MAX (max_res2, a[i]);
+ }
+
+ min_res3 = min_res2;
+ max_res3 = max_res2;
+ for (int i = 16 ; i != 32; i++)
+ {
+ min_res3 = MIN (min_res3, a[i]);
+ max_res3 = MAX (max_res3, a[i]);
+ }
+
+ min_exp1 = reduc_min_128 (a);
+ min_exp2 = reduc_min_256 (a);
+ min_exp3 = reduc_min_512 (a);
+ max_exp1 = reduc_max_128 (a);
+ max_exp2 = reduc_max_256 (a);
+ max_exp3 = reduc_max_512 (a);
+
+ if (min_exp1 != min_res1 || min_exp2 != min_res2 || min_exp3 != min_res3
+ || max_exp1 != max_res1 || max_exp2 != max_res2 || max_exp3 != max_res3)
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-trunc-extendvnhf.c b/gcc/testsuite/gcc.target/i386/avx512fp16-trunc-extendvnhf.c
new file mode 100644
index 0000000..2ef901a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-trunc-extendvnhf.c
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -ftree-slp-vectorize -mprefer-vector-width=512" } */
+
+extern double df[8];
+extern float sf[16];
+extern _Float16 hf[32];
+
+#define DO_PRAGMA(X) _Pragma(#X)
+
+#define TRUNCHFVV(size, mode) \
+ void __attribute__ ((noinline, noclone)) \
+truncv##size##mode##v##size##hf () \
+{\
+ int i; \
+ DO_PRAGMA (GCC unroll size) \
+ for (i = 0; i < size; i++) \
+ hf[i] = mode[i]; \
+}
+
+#define EXTENDHFVV(size, mode) \
+ void __attribute__ ((noinline, noclone)) \
+extendv##size##hf##v##size##mode () \
+{\
+ int i; \
+ DO_PRAGMA (GCC unroll size) \
+ for (i = 0; i < size; i++) \
+ mode[i] = hf[i]; \
+}
+
+TRUNCHFVV(8, df)
+TRUNCHFVV(4, df)
+TRUNCHFVV(2, df)
+TRUNCHFVV(16, sf)
+TRUNCHFVV(8, sf)
+TRUNCHFVV(4, sf)
+EXTENDHFVV(8, df)
+EXTENDHFVV(4, df)
+EXTENDHFVV(2, df)
+EXTENDHFVV(16, sf)
+EXTENDHFVV(8, sf)
+EXTENDHFVV(4, sf)
+
+/* { dg-final { scan-assembler-times "vcvtpd2phz\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtpd2phy\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtpd2phx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtps2phx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtps2phxy\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtps2phxx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-trunchf.c b/gcc/testsuite/gcc.target/i386/avx512fp16-trunchf.c
new file mode 100644
index 0000000..2c025b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-trunchf.c
@@ -0,0 +1,59 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+/* { dg-final { scan-assembler-times "vcvttsh2si\[ \\t\]+\[^\{\n\]*(?:%xmm\[0-9\]|\\(%esp\\))+, %eax(?:\n|\[ \\t\]+#)" 3 } } */
+/* { dg-final { scan-assembler-times "vcvttsh2usi\[ \\t\]+\[^\{\n\]*(?:%xmm\[0-9\]|\\(%esp\\))+, %eax(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvttsh2si\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+, %rax(?:\n|\[ \\t\]+#)" 1 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vcvttsh2usi\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+, %rax(?:\n|\[ \\t\]+#)" 1 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xorl\[ \\t\]+%edx, %edx" { target ia32 } } } */
+
+#include <immintrin.h>
+
+short
+__attribute__ ((noinline, noclone))
+trunc_f16_to_si16 (_Float16 f)
+{
+ return f;
+}
+
+unsigned short
+__attribute__ ((noinline, noclone))
+trunc_f16_to_su16 (_Float16 f)
+{
+ return f;
+}
+
+int
+__attribute__ ((noinline, noclone))
+trunc_f16_to_si32 (_Float16 f)
+{
+ return f;
+}
+
+unsigned int
+__attribute__ ((noinline, noclone))
+trunc_f16_to_su32 (_Float16 f)
+{
+ return f;
+}
+
+long long
+__attribute__ ((noinline, noclone))
+trunc_f16_to_si64 (_Float16 f)
+{
+ return f;
+}
+
+unsigned long long
+__attribute__ ((noinline, noclone))
+trunc_f16_to_su64 (_Float16 f)
+{
+ return f;
+}
+
+unsigned long long
+__attribute__ ((noinline, noclone))
+trunc_f16_to_su64_zext (_Float16 f)
+{
+ return (unsigned int) f;
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-truncvnhf.c b/gcc/testsuite/gcc.target/i386/avx512fp16-truncvnhf.c
new file mode 100644
index 0000000..7a51c9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-truncvnhf.c
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -ftree-slp-vectorize -mprefer-vector-width=512" } */
+
+extern long long di[8];
+extern unsigned long long udi[8];
+extern int si[16];
+extern unsigned int usi[16];
+extern short hi[32];
+extern unsigned short uhi[32];
+extern _Float16 hf[32];
+
+#define DO_PRAGMA(X) _Pragma(#X)
+
+#define FIX_TRUNCHFVV(size, mode) \
+ void __attribute__ ((noinline, noclone)) \
+fix_trunc##size##hf##v##size##mode () \
+{\
+ int i; \
+ DO_PRAGMA (GCC unroll size) \
+ for (i = 0; i < size; i++) \
+ mode[i] = hf[i]; \
+}
+
+FIX_TRUNCHFVV(32, hi)
+FIX_TRUNCHFVV(16, hi)
+FIX_TRUNCHFVV(8, hi)
+FIX_TRUNCHFVV(16, si)
+FIX_TRUNCHFVV(8, si)
+FIX_TRUNCHFVV(4, si)
+FIX_TRUNCHFVV(8, di)
+FIX_TRUNCHFVV(4, di)
+FIX_TRUNCHFVV(2, di)
+
+FIX_TRUNCHFVV(32, uhi)
+FIX_TRUNCHFVV(16, uhi)
+FIX_TRUNCHFVV(8, uhi)
+FIX_TRUNCHFVV(16, usi)
+FIX_TRUNCHFVV(8, usi)
+FIX_TRUNCHFVV(4, usi)
+FIX_TRUNCHFVV(8, udi)
+FIX_TRUNCHFVV(4, udi)
+FIX_TRUNCHFVV(2, udi)
+
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-1.c
new file mode 100644
index 0000000..e8745ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-1.c
@@ -0,0 +1,70 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mprefer-vector-width=512" } */
+
+/* { dg-final { scan-assembler-times "vcmpph" 27 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpw|vpcmpeqw)" 12 } } */
+/* { dg-final { scan-assembler-times "vpcmpuw" 6 } } */
+
+typedef unsigned short u16;
+typedef short s16;
+
+#define CONDMOV_LOOP(size, type, ptype, op, name) \
+void \
+__attribute__ ((noinline, noclone, optimize("tree-vectorize"))) \
+loop_cond_##size##ptype##type##name ( \
+ ptype * restrict a, ptype * restrict b, \
+ type * restrict c, type * restrict d) \
+{ \
+ int i; \
+ for (i = 0; i < size; i++) \
+ { \
+ if (a[i] op b[i]) \
+ d[i] = c[i]; \
+ } \
+}
+
+CONDMOV_LOOP (32, _Float16, _Float16, <, lt)
+CONDMOV_LOOP (32, _Float16, _Float16, >, gt)
+CONDMOV_LOOP (32, _Float16, _Float16, ==, eq)
+CONDMOV_LOOP (16, _Float16, _Float16, <, lt)
+CONDMOV_LOOP (16, _Float16, _Float16, >, gt)
+CONDMOV_LOOP (16, _Float16, _Float16, ==, eq)
+CONDMOV_LOOP (8, _Float16, _Float16, <, lt)
+CONDMOV_LOOP (8, _Float16, _Float16, >, gt)
+CONDMOV_LOOP (8, _Float16, _Float16, ==, eq)
+CONDMOV_LOOP (32, _Float16, s16, <, lt)
+CONDMOV_LOOP (32, _Float16, s16, >, gt)
+CONDMOV_LOOP (32, _Float16, s16, ==, eq)
+CONDMOV_LOOP (16, _Float16, s16, <, lt)
+CONDMOV_LOOP (16, _Float16, s16, >, gt)
+CONDMOV_LOOP (16, _Float16, s16, ==, eq)
+CONDMOV_LOOP (8, _Float16, s16, <, lt)
+CONDMOV_LOOP (8, _Float16, s16, >, gt)
+CONDMOV_LOOP (8, _Float16, s16, ==, eq)
+CONDMOV_LOOP (32, s16, _Float16, <, lt)
+CONDMOV_LOOP (32, s16, _Float16, >, gt)
+CONDMOV_LOOP (32, s16, _Float16, ==, eq)
+CONDMOV_LOOP (16, s16, _Float16, <, lt)
+CONDMOV_LOOP (16, s16, _Float16, >, gt)
+CONDMOV_LOOP (16, s16, _Float16, ==, eq)
+CONDMOV_LOOP (8, s16, _Float16, <, lt)
+CONDMOV_LOOP (8, s16, _Float16, >, gt)
+CONDMOV_LOOP (8, s16, _Float16, ==, eq)
+CONDMOV_LOOP (32, _Float16, u16, <, lt)
+CONDMOV_LOOP (32, _Float16, u16, >, gt)
+CONDMOV_LOOP (32, _Float16, u16, ==, eq)
+CONDMOV_LOOP (16, _Float16, u16, <, lt)
+CONDMOV_LOOP (16, _Float16, u16, >, gt)
+CONDMOV_LOOP (16, _Float16, u16, ==, eq)
+CONDMOV_LOOP (8, _Float16, u16, <, lt)
+CONDMOV_LOOP (8, _Float16, u16, >, gt)
+CONDMOV_LOOP (8, _Float16, u16, ==, eq)
+CONDMOV_LOOP (32, u16, _Float16, <, lt)
+CONDMOV_LOOP (32, u16, _Float16, >, gt)
+CONDMOV_LOOP (32, u16, _Float16, ==, eq)
+CONDMOV_LOOP (16, u16, _Float16, <, lt)
+CONDMOV_LOOP (16, u16, _Float16, >, gt)
+CONDMOV_LOOP (16, u16, _Float16, ==, eq)
+CONDMOV_LOOP (8, u16, _Float16, <, lt)
+CONDMOV_LOOP (8, u16, _Float16, >, gt)
+CONDMOV_LOOP (8, u16, _Float16, ==, eq)
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-2.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-2.c
new file mode 100644
index 0000000..a0d5f98
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-2.c
@@ -0,0 +1,143 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mprefer-vector-width=512" } */
+
+static void condmov_test (void);
+#define DO_TEST condmov_test
+#define AVX512FP16
+#define AVX512VL
+#include "avx512f-check.h"
+#include "avx512fp16-vcondmn-loop-1.c"
+
+_Float16 a[32], b[32], c[32], fexp[32], fref[32];
+s16 sa[32], sb[32], sc[32], sexp[32], sref[32];
+u16 ua[32], ub[32], uc[32], uexp[32], uref[32];
+
+#define EMULATE_CONDMOV_LOOP(size, type, ptype, op, name) \
+void \
+__attribute__ ((noinline, noclone)) \
+scalar_cond_##size##ptype##type##name ( \
+ ptype * restrict a, ptype * restrict b, \
+ type * restrict c, type * restrict d) \
+{ \
+ int i; \
+ for (i = 0; i < size; i++) \
+ { \
+ if (a[i] op b[i]) \
+ d[i] = c[i]; \
+ } \
+}
+
+EMULATE_CONDMOV_LOOP (32, _Float16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (32, _Float16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (32, _Float16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (16, _Float16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (16, _Float16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (16, _Float16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (8, _Float16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (8, _Float16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (8, _Float16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (32, _Float16, s16, <, lt)
+EMULATE_CONDMOV_LOOP (32, _Float16, s16, >, gt)
+EMULATE_CONDMOV_LOOP (32, _Float16, s16, ==, eq)
+EMULATE_CONDMOV_LOOP (16, _Float16, s16, <, lt)
+EMULATE_CONDMOV_LOOP (16, _Float16, s16, >, gt)
+EMULATE_CONDMOV_LOOP (16, _Float16, s16, ==, eq)
+EMULATE_CONDMOV_LOOP (8, _Float16, s16, <, lt)
+EMULATE_CONDMOV_LOOP (8, _Float16, s16, >, gt)
+EMULATE_CONDMOV_LOOP (8, _Float16, s16, ==, eq)
+EMULATE_CONDMOV_LOOP (32, s16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (32, s16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (32, s16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (16, s16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (16, s16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (16, s16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (8, s16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (8, s16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (8, s16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (32, _Float16, u16, <, lt)
+EMULATE_CONDMOV_LOOP (32, _Float16, u16, >, gt)
+EMULATE_CONDMOV_LOOP (32, _Float16, u16, ==, eq)
+EMULATE_CONDMOV_LOOP (16, _Float16, u16, <, lt)
+EMULATE_CONDMOV_LOOP (16, _Float16, u16, >, gt)
+EMULATE_CONDMOV_LOOP (16, _Float16, u16, ==, eq)
+EMULATE_CONDMOV_LOOP (8, _Float16, u16, <, lt)
+EMULATE_CONDMOV_LOOP (8, _Float16, u16, >, gt)
+EMULATE_CONDMOV_LOOP (8, _Float16, u16, ==, eq)
+EMULATE_CONDMOV_LOOP (32, u16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (32, u16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (32, u16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (16, u16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (16, u16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (16, u16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (8, u16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (8, u16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (8, u16, _Float16, ==, eq)
+
+void init()
+{
+ int i;
+ for (i = 0; i < 32; i++)
+ {
+ ua[i] = sa[i] = a[i] = i;
+ ub[i] = sb[i] = b[i] = i;
+ uc[i] = sc[i] = c[i] = (32 - i) * 2;
+ uexp[i] = sexp[i] = fexp[i] = -1;
+ uref[i] = sref[i] = fref[i] = -1;
+ }
+}
+
+int check_cond(void *a, void *b, int size)
+{
+ int i;
+ u16 *pa = (u16 *)a, *pb = (u16 *)b;
+ for (i = 0; i < size; i++)
+ if (pa[i] != pb[i])
+ return 0;
+ return 1;
+}
+
+#define TEST_CONDMOV_LOOP(size, name) \
+{ \
+ init (); \
+ scalar_cond_##size##_Float16_Float16##name (a, b, c, fexp); \
+ loop_cond_##size##_Float16_Float16##name (a, b, c, fref); \
+ if (!check_cond ((void *)fexp, (void *)fref, size)) \
+ abort(); \
+ \
+ init (); \
+ scalar_cond_##size##_Float16s16##name (a, b, sc, sexp); \
+ loop_cond_##size##_Float16s16##name (a, b, sc, sref); \
+ if (!check_cond ((void *)sexp, (void *)sref, size)) \
+ abort(); \
+ \
+ init (); \
+ scalar_cond_##size##s16_Float16##name (sa, sb, c, fexp); \
+ loop_cond_##size##s16_Float16##name (sa, sb, c, fref); \
+ if (!check_cond ((void *)fexp, (void *)fref, size)) \
+ abort(); \
+ \
+ init (); \
+ scalar_cond_##size##_Float16u16##name (a, b, uc, uexp); \
+ loop_cond_##size##_Float16u16##name (a, b, uc, uref); \
+ if (!check_cond ((void *)uexp, (void *)uref, size)) \
+ abort(); \
+ \
+ init (); \
+ scalar_cond_##size##u16_Float16##name (ua, ub, c, fexp); \
+ loop_cond_##size##u16_Float16##name (ua, ub, c, fref); \
+ if (!check_cond ((void *)fexp, (void *)fref, size)) \
+ abort(); \
+}
+
+static void condmov_test()
+{
+ TEST_CONDMOV_LOOP (32, lt)
+ TEST_CONDMOV_LOOP (32, gt)
+ TEST_CONDMOV_LOOP (32, eq)
+ TEST_CONDMOV_LOOP (16, lt)
+ TEST_CONDMOV_LOOP (16, gt)
+ TEST_CONDMOV_LOOP (16, eq)
+ TEST_CONDMOV_LOOP (8, lt)
+ TEST_CONDMOV_LOOP (8, gt)
+ TEST_CONDMOV_LOOP (8, eq)
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vec_cmpmn.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vec_cmpmn.c
new file mode 100644
index 0000000..ef9f853
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vec_cmpmn.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+/* { dg-final { scan-assembler-times "vcmpph" 15 } } */
+
+typedef _Float16 v8hf __attribute__ ((vector_size (16)));
+typedef _Float16 v16hf __attribute__ ((vector_size (32)));
+typedef _Float16 v32hf __attribute__ ((vector_size (64)));
+
+#define VCMPMN(type, op, name) \
+type \
+__attribute__ ((noinline, noclone)) \
+vec_cmp_##type##type##name (type a, type b) \
+{ \
+ return a op b; \
+}
+
+VCMPMN (v8hf, <, lt)
+VCMPMN (v16hf, <, lt)
+VCMPMN (v32hf, <, lt)
+VCMPMN (v8hf, <=, le)
+VCMPMN (v16hf, <=, le)
+VCMPMN (v32hf, <=, le)
+VCMPMN (v8hf, >, gt)
+VCMPMN (v16hf, >, gt)
+VCMPMN (v32hf, >, gt)
+VCMPMN (v8hf, >=, ge)
+VCMPMN (v16hf, >=, ge)
+VCMPMN (v32hf, >=, ge)
+VCMPMN (v8hf, ==, eq)
+VCMPMN (v16hf, ==, eq)
+VCMPMN (v32hf, ==, eq)
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1a.c
new file mode 100644
index 0000000..6c2c34c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res, res1, res2;
+volatile __m512h x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_fcmadd_pch (x1, x2, x3);
+ res1 = _mm512_mask_fcmadd_pch (res1, m16, x1, x2);
+ res1 = _mm512_mask3_fcmadd_pch (res1, x1, x2, m16);
+ res2 = _mm512_maskz_fcmadd_pch (m16, x1, x2, x3);
+ res = _mm512_fcmadd_round_pch (x1, x2, x3, 8);
+ res1 = _mm512_mask_fcmadd_round_pch (res1, m16, x1, x2, 8);
+ res1 = _mm512_mask3_fcmadd_round_pch (res1, x1, x2, m16, 8);
+ res2 = _mm512_maskz_fcmadd_round_pch (m16, x1, x2, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1b.c
new file mode 100644
index 0000000..835699b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1b.c
@@ -0,0 +1,133 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(c_fmadd_pch) (V512 * dest, V512 op1, V512 op2,
+ __mmask16 k, int zero_mask, int c_flag,
+ int is_mask3)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << (i / 2)) & k) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = is_mask3 ? v3.u32[i] : v7.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v5.f32[i] = v1.f32[i] * v7.f32[i]
+ - invert * (v1.f32[i+1] * v7.f32[i+1]) + v3.f32[i];
+ }
+ else {
+ v5.f32[i] = v1.f32[i-1] * v7.f32[i]
+ + invert * (v1.f32[i] * v7.f32[i-1]) + v3.f32[i];
+
+ }
+ }
+ if (((1 << (i / 2 + 8)) & k) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = is_mask3 ? v4.u32[i] : v8.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v6.f32[i] = v2.f32[i] * v8.f32[i]
+ - invert * (v2.f32[i+1] * v8.f32[i+1]) + v4.f32[i];
+ }
+ else {
+ v6.f32[i] = v2.f32[i-1] * v8.f32[i]
+ + invert * (v2.f32[i] * v8.f32[i-1]) + v4.f32[i];
+ }
+
+ }
+ }
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, NET_CMASK, 0, 1, 0);
+ HF(res) = INTRINSIC (_fcmadd_pch) (HF(res), HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fcmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 1, 0);
+ HF(res) = INTRINSIC (_mask_fcmadd_pch) (HF(res) ,HALF_MASK, HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fcmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 1, 1);
+ HF(res) = INTRINSIC (_mask3_fcmadd_pch) (HF(res), HF(src1),
+ HF(src2), HALF_MASK);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fcmadd_pch);
+
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 1, 1, 0);
+ HF(res) = INTRINSIC (_maskz_fcmadd_pch) (HALF_MASK, HF(res),
+ HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fcmadd_pch);
+
+#if AVX512F_LEN == 512
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, NET_CMASK, 0, 1, 0);
+ HF(res) = INTRINSIC (_fcmadd_round_pch) (HF(res), HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fcmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 1, 0);
+ HF(res) = INTRINSIC (_mask_fcmadd_round_pch) (HF(res) ,HALF_MASK, HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fcmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 1, 1);
+ HF(res) = INTRINSIC (_mask3_fcmadd_round_pch) (HF(res), HF(src1),
+ HF(src2), HALF_MASK, _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fcmadd_pch);
+
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 1, 1, 0);
+ HF(res) = INTRINSIC (_maskz_fcmadd_round_pch) (HALF_MASK, HF(res),
+ HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fcmadd_pch);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1a.c
new file mode 100644
index 0000000..8bd8eeb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, res1, res2;
+volatile __m128h x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx128f_test (void)
+{
+ res = _mm_fcmadd_sch (x1, x2, x3);
+ res1 = _mm_mask_fcmadd_sch (res1, m8, x1, x2);
+ res1 = _mm_mask3_fcmadd_sch (res1, x1, x2, m8);
+ res2 = _mm_maskz_fcmadd_sch (m8, x1, x2, x3);
+ res = _mm_fcmadd_round_sch (x1, x2, x3, 8);
+ res1 = _mm_mask_fcmadd_round_sch (res1, m8, x1, x2, 8);
+ res1 = _mm_mask3_fcmadd_round_sch (res1, x1, x2, m8, 8);
+ res2 = _mm_maskz_fcmadd_round_sch (m8, x1, x2, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1b.c
new file mode 100644
index 0000000..c479068
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1b.c
@@ -0,0 +1,78 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+EMULATE(c_fmadd_csh) (V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask, int c_flag,
+ int is_mask3)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k) {
+ v5.f32[0] = v1.f32[0] * v7.f32[0]
+ - invert * (v1.f32[1] * v7.f32[1]) + v3.f32[0];
+ v5.f32[1] = v1.f32[0] * v7.f32[1]
+ + invert * (v1.f32[1] * v7.f32[0]) + v3.f32[1];
+ }
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 2; i < 8; i++)
+ v5.f32[i] = is_mask3? v3.f32[i] : v7.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x1, 0, 1, 0);
+ res.xmmh[0] = _mm_fcmadd_round_sch(res.xmmh[0], src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_fcmadd_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x1, 0, 1, 0);
+ res.xmmh[0] = _mm_mask_fcmadd_round_sch(res.xmmh[0], 0x1,
+ src1.xmmh[0], src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_mask_fcmadd_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x1, 0, 1, 1);
+ res.xmmh[0] = _mm_mask3_fcmadd_round_sch(res.xmmh[0], src1.xmmh[0], src2.xmmh[0],
+ 0x1, _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_mask3_fcmadd_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x3, 1, 1, 0);
+ res.xmmh[0] = _mm_maskz_fcmadd_round_sch(0x3, res.xmmh[0], src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_maskz_fcmadd_sch);
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1a.c
new file mode 100644
index 0000000..ca2f140
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1a.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res, res1, res2;
+volatile __m512h x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_fcmul_pch (x1, x2);
+ res1 = _mm512_mask_fcmul_pch (res1, m16, x1, x2);
+ res2 = _mm512_maskz_fcmul_pch (m16, x1, x2);
+ res = _mm512_fcmul_round_pch (x1, x2, 8);
+ res1 = _mm512_mask_fcmul_round_pch (res1, m16, x1, x2, 8);
+ res2 = _mm512_maskz_fcmul_round_pch (m16, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1b.c
new file mode 100644
index 0000000..ee41f6c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1b.c
@@ -0,0 +1,111 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(c_fmul_pch) (V512 * dest, V512 op1, V512 op2,
+ __mmask16 k, int zero_mask, int c_flag)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << (i / 2)) & k) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v5.f32[i] = v1.f32[i] * v3.f32[i]
+ - invert * (v1.f32[i+1] * v3.f32[i+1]);
+ }
+ else {
+ v5.f32[i] = v1.f32[i] * v3.f32[i-1]
+ + invert * (v1.f32[i-1] * v3.f32[i]);
+
+ }
+ }
+ if (((1 << (i / 2 + 8)) & k) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v6.f32[i] = v2.f32[i] * v4.f32[i]
+ - invert * (v2.f32[i+1] * v4.f32[i+1]);
+ }
+ else {
+ v6.f32[i] = v2.f32[i] * v4.f32[i-1]
+ + invert * (v2.f32[i-1] * v4.f32[i]);
+ }
+
+ }
+ }
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(c_fmul_pch)(&exp, src1, src2, NET_CMASK, 0, 1);
+ HF(res) = INTRINSIC (_fcmul_pch) (HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fcmul_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 0, 1);
+ HF(res) = INTRINSIC (_mask_fcmul_pch) (HF(res) ,HALF_MASK, HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fcmul_pch);
+
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 1, 1);
+ HF(res) = INTRINSIC (_maskz_fcmul_pch) ( HALF_MASK, HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fcmul_pch);
+
+#if AVX512F_LEN == 512
+ EMULATE(c_fmul_pch)(&exp, src1, src2, NET_CMASK, 0, 1);
+ HF(res) = INTRINSIC (_fcmul_round_pch) (HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fcmul_round_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 0, 1);
+ HF(res) = INTRINSIC (_mask_fcmul_round_pch) (HF(res) ,HALF_MASK, HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fcmul_round_pch);
+
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 1, 1);
+ HF(res) = INTRINSIC (_maskz_fcmul_round_pch) ( HALF_MASK, HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fcmul_round_pch);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1a.c
new file mode 100644
index 0000000..872d91a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1a.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, res1, res2;
+volatile __m128h x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_fcmul_sch (x1, x2);
+ res1 = _mm_mask_fcmul_sch (res1, m8, x1, x2);
+ res2 = _mm_maskz_fcmul_sch (m8, x1, x2);
+ res = _mm_fcmul_round_sch (x1, x2, 8);
+ res1 = _mm_mask_fcmul_round_sch (res1, m8, x1, x2, 8);
+ res2 = _mm_maskz_fcmul_round_sch (m8, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1b.c
new file mode 100644
index 0000000..995df84
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1b.c
@@ -0,0 +1,71 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+EMULATE(c_fmul_csh) (V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask, int c_flag)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k) {
+ v5.f32[0] = v1.f32[0] * v3.f32[0]
+ - invert * (v1.f32[1] * v3.f32[1]);
+ v5.f32[1] = v1.f32[1] * v3.f32[0]
+ + invert * (v1.f32[0] * v3.f32[1]);
+ }
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 2; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_csh)(&exp, src1, src2, 0x1, 0 , 1);
+ res.xmmh[0] = _mm_fcmul_round_sch(src1.xmmh[0], src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_fcmul_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_csh)(&exp, src1, src2, 0x1, 0, 1);
+ res.xmmh[0] = _mm_mask_fcmul_round_sch(res.xmmh[0], 0x1,
+ src1.xmmh[0], src2.xmmh[0],
+ _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_mask_fcmul_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_csh)(&exp, src1, src2, 0x3, 1, 1);
+ res.xmmh[0] = _mm_maskz_fcmul_round_sch(0x3, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_maskz_fcmul_sch);
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1a.c
new file mode 100644
index 0000000..4dae5f0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res, res1, res2;
+volatile __m512h x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_fmadd_pch (x1, x2, x3);
+ res1 = _mm512_mask_fmadd_pch (res1, m16, x1, x2);
+ res1 = _mm512_mask3_fmadd_pch (res1, x1, x2, m16);
+ res2 = _mm512_maskz_fmadd_pch (m16, x1, x2, x3);
+ res = _mm512_fmadd_round_pch (x1, x2, x3, 8);
+ res1 = _mm512_mask_fmadd_round_pch (res1, m16, x1, x2, 8);
+ res1 = _mm512_mask3_fmadd_round_pch (res1, x1, x2, m16, 8);
+ res2 = _mm512_maskz_fmadd_round_pch (m16, x1, x2, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1b.c
new file mode 100644
index 0000000..1da6f01
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1b.c
@@ -0,0 +1,131 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(c_fmadd_pch) (V512 * dest, V512 op1, V512 op2,
+ __mmask16 k, int zero_mask, int c_flag,
+ int is_mask3)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << (i / 2)) & k) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = is_mask3 ? v3.u32[i] : v7.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v5.f32[i] = v1.f32[i] * v7.f32[i]
+ - invert * (v1.f32[i+1] * v7.f32[i+1]) + v3.f32[i];
+ }
+ else {
+ v5.f32[i] = v1.f32[i-1] * v7.f32[i]
+ + invert * (v1.f32[i] * v7.f32[i-1]) + v3.f32[i];
+
+ }
+ }
+ if (((1 << (i / 2 + 8)) & k) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = is_mask3 ? v4.u32[i] : v8.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v6.f32[i] = v2.f32[i] * v8.f32[i]
+ - invert * (v2.f32[i+1] * v8.f32[i+1]) + v4.f32[i];
+ }
+ else {
+ v6.f32[i] = v2.f32[i-1] * v8.f32[i]
+ + invert * (v2.f32[i] * v8.f32[i-1]) + v4.f32[i];
+ }
+
+ }
+ }
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, NET_CMASK, 0, 0, 0);
+ HF(res) = INTRINSIC (_fmadd_pch) (HF(res), HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 0, 0);
+ HF(res) = INTRINSIC (_mask_fmadd_pch) (HF(res), HALF_MASK, HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 0, 1);
+ HF(res) = INTRINSIC (_mask3_fmadd_pch) (HF(res), HF(src1), HF(src2),
+ HALF_MASK);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 1, 0, 0);
+ HF(res) = INTRINSIC (_maskz_fmadd_pch) (HALF_MASK, HF(res), HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmadd_pch);
+
+#if AVX512F_LEN == 512
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, NET_CMASK, 0, 0, 0);
+ HF(res) = INTRINSIC (_fmadd_round_pch) (HF(res), HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 0, 0);
+ HF(res) = INTRINSIC (_mask_fmadd_round_pch) (HF(res), HALF_MASK, HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 0, 1);
+ HF(res) = INTRINSIC (_mask3_fmadd_round_pch) (HF(res), HF(src1), HF(src2),
+ HALF_MASK, _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 1, 0, 0);
+ HF(res) = INTRINSIC (_maskz_fmadd_round_pch) (HALF_MASK, HF(res), HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmadd_pch);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1a.c
new file mode 100644
index 0000000..1e376b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, res1, res2;
+volatile __m128h x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx128f_test (void)
+{
+ res = _mm_fmadd_sch (x1, x2, x3);
+ res1 = _mm_mask_fmadd_sch (res1, m8, x1, x2);
+ res1 = _mm_mask3_fmadd_sch (res1, x1, x2, m8);
+ res2 = _mm_maskz_fmadd_sch (m8, x1, x2, x3);
+ res = _mm_fmadd_round_sch (x1, x2, x3, 8);
+ res1 = _mm_mask_fmadd_round_sch (res1, m8, x1, x2, 8);
+ res1 = _mm_mask3_fmadd_round_sch (res1, x1, x2, m8, 8);
+ res2 = _mm_maskz_fmadd_round_sch (m8, x1, x2, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1b.c
new file mode 100644
index 0000000..4c74e01
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1b.c
@@ -0,0 +1,77 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+EMULATE(c_fmadd_csh) (V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask, int c_flag,
+ int is_mask3)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k) {
+ v5.f32[0] = v1.f32[0] * v7.f32[0]
+ - invert * (v1.f32[1] * v7.f32[1]) + v3.f32[0];
+ v5.f32[1] = v1.f32[0] * v7.f32[1]
+ + invert * (v1.f32[1] * v7.f32[0]) + v3.f32[1];
+ }
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 2; i < 8; i++)
+ v5.f32[i] = is_mask3? v3.f32[i] : v7.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x1, 0, 0, 0);
+ res.xmmh[0] = _mm_fmadd_round_sch(res.xmmh[0], src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_fmadd_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x1, 0, 0, 0);
+ res.xmmh[0] = _mm_mask_fmadd_round_sch(res.xmmh[0], 0x1, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_mask_fmadd_sch);
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x1, 0, 0, 1);
+ res.xmmh[0] = _mm_mask3_fmadd_round_sch(res.xmmh[0], src1.xmmh[0], src2.xmmh[0],
+ 0x1, _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_mask3_fmadd_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x3, 1, 0, 0);
+ res.xmmh[0] = _mm_maskz_fmadd_round_sch(0x3, res.xmmh[0], src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_maskz_fmadd_sch);
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1a.c
new file mode 100644
index 0000000..f31cbca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1a.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res, res1, res2;
+volatile __m512h x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_fmul_pch (x1, x2);
+ res1 = _mm512_mask_fmul_pch (res1, m16, x1, x2);
+ res2 = _mm512_maskz_fmul_pch (m16, x1, x2);
+ res = _mm512_fmul_round_pch (x1, x2, 8);
+ res1 = _mm512_mask_fmul_round_pch (res1, m16, x1, x2, 8);
+ res2 = _mm512_maskz_fmul_round_pch (m16, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1b.c
new file mode 100644
index 0000000..d9bb1b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1b.c
@@ -0,0 +1,115 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(c_fmul_pch) (V512 * dest, V512 op1, V512 op2,
+ __mmask16 k, int zero_mask, int c_flag)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << (i / 2)) & k) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v5.f32[i] = v1.f32[i] * v3.f32[i]
+ - invert * (v1.f32[i+1] * v3.f32[i+1]);
+ }
+ else {
+ v5.f32[i] = v1.f32[i-1] * v3.f32[i]
+ + invert * (v1.f32[i] * v3.f32[i-1]);
+
+ }
+ }
+ if (((1 << (i / 2 + 8)) & k) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v6.f32[i] = v2.f32[i] * v4.f32[i]
+ - invert * (v2.f32[i+1] * v4.f32[i+1]);
+ }
+ else {
+ v6.f32[i] = v2.f32[i-1] * v4.f32[i]
+ + invert * (v2.f32[i] * v4.f32[i-1]);
+ }
+
+ }
+ }
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(c_fmul_pch)(&exp, src1, src2, NET_CMASK, 0, 0);
+ HF(res) = INTRINSIC (_fmul_pch) (HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmul_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 0, 0);
+ HF(res) = INTRINSIC (_mask_fmul_pch) (HF(res),HALF_MASK, HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmul_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 1, 0);
+ HF(res) = INTRINSIC (_maskz_fmul_pch) (HALF_MASK, HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmul_pch);
+
+#if AVX512F_LEN == 512
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_pch)(&exp, src1, src2, NET_CMASK, 0, 0);
+ HF(res) = INTRINSIC (_fmul_round_pch) (HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmul_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 0, 0);
+ HF(res) = INTRINSIC (_mask_fmul_round_pch) (HF(res),HALF_MASK, HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmul_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 1, 0);
+ HF(res) = INTRINSIC (_maskz_fmul_round_pch) (HALF_MASK, HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmul_pch);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1a.c
new file mode 100644
index 0000000..5d48874
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1a.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, res1, res2;
+volatile __m128h x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_fmul_sch (x1, x2);
+ res1 = _mm_mask_fmul_sch (res1, m8, x1, x2);
+ res2 = _mm_maskz_fmul_sch (m8, x1, x2);
+ res = _mm_fmul_round_sch (x1, x2, 8);
+ res1 = _mm_mask_fmul_round_sch (res1, m8, x1, x2, 8);
+ res2 = _mm_maskz_fmul_round_sch (m8, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1b.c
new file mode 100644
index 0000000..45840d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1b.c
@@ -0,0 +1,71 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+EMULATE(c_fmul_csh) (V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask, int c_flag)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k) {
+ v5.f32[0] = v1.f32[0] * v3.f32[0]
+ - invert * (v1.f32[1] * v3.f32[1]);
+ v5.f32[1] = v1.f32[0] * v3.f32[1]
+ + invert * (v1.f32[1] * v3.f32[0]);
+ }
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 2; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_csh)(&exp, src1, src2, 0x1, 0 , 0);
+ res.xmmh[0] = _mm_fmul_round_sch(src1.xmmh[0], src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_fmul_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_csh)(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_mask_fmul_round_sch(res.xmmh[0], 0x1,
+ src1.xmmh[0], src2.xmmh[0],
+ _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_mask_fmul_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_csh)(&exp, src1, src2, 0x3, 1, 0);
+ res.xmmh[0] = _mm_maskz_fmul_round_sch(0x3, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_maskz_fmul_sch);
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-builtin-sqrt-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-builtin-sqrt-1.c
new file mode 100644
index 0000000..08deb3e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-builtin-sqrt-1.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16 -mavx512vl" } */
+
+void
+f1 (_Float16* __restrict psrc, _Float16* __restrict pdst)
+{
+ for (int i = 0; i != 8; i++)
+ pdst[i] = __builtin_sqrtf16 (psrc[i]);
+}
+
+void
+f2 (_Float16* __restrict psrc, _Float16* __restrict pdst)
+{
+ for (int i = 0; i != 16; i++)
+ pdst[i] = __builtin_sqrtf16 (psrc[i]);
+}
+
+/* { dg-final { scan-assembler-times "vsqrtph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vsqrtph\[^\n\r\]*ymm\[0-9\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-conjugation-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-conjugation-1.c
new file mode 100644
index 0000000..d8fdab7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-conjugation-1.c
@@ -0,0 +1,55 @@
+/* { dg-do compile} */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#include <immintrin.h>
+__m256h
+__attribute__ ((noinline, noclone))
+test_mm256_conj_pch (__m256h __A)
+{
+ return _mm256_conj_pch (__A);
+}
+
+/* { dg-final { scan-assembler-times "vpxor\[^\n\]*%ymm\[0-9\]+" 3 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+test_mm_conj_pch (__m128h __A)
+{
+ return _mm_conj_pch (__A);
+}
+
+/* { dg-final { scan-assembler-times "vpxor\[^\n\]*%xmm\[0-9\]+" 3 } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+test_mm256_mask_conj_pch (__m256h __W, __mmask8 __U, __m256h __A)
+{
+ return _mm256_mask_conj_pch (__W, __U, __A);
+}
+
+/* { dg-final { scan-assembler-times "vmovaps\[^\n\]*%ymm\[0-9\]+" 2 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+test_mm_mask_conj_pch (__m128h __W, __mmask8 __U, __m128h __A)
+{
+ return _mm_mask_conj_pch (__W, __U, __A);
+}
+
+/* { dg-final { scan-assembler-times "vmovaps\[^\n\]*%xmm\[0-9\]+" 2 } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+test_mm256_maskz_conj_pch (__mmask8 __U, __m256h __A)
+{
+ return _mm256_maskz_conj_pch (__U, __A);
+}
+/* { dg-final { scan-assembler-times "vmovaps\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+test_mm_maskz_conj_pch (__mmask8 __U, __m128h __A) {
+ return _mm_maskz_conj_pch (__U, __A);
+}
+
+/* { dg-final { scan-assembler-times "vmovaps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-1.c
new file mode 100644
index 0000000..1a832f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-1.c
@@ -0,0 +1,70 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16 -mavx512vl" } */
+
+typedef _Float16 v8hf __attribute__ ((__vector_size__ (16)));
+typedef _Float16 v16hf __attribute__ ((__vector_size__ (32)));
+
+v8hf
+foo1 (v8hf a, v8hf b, v8hf c)
+{
+ return a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfmadd132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+v8hf
+foo2 (v8hf a, v8hf b, v8hf c)
+{
+ return -a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmadd132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+v8hf
+foo3 (v8hf a, v8hf b, v8hf c)
+{
+ return a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfmsub132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+v8hf
+foo4 (v8hf a, v8hf b, v8hf c)
+{
+ return -a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmsub132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+v16hf
+foo5 (v16hf a, v16hf b, v16hf c)
+{
+ return a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfmadd132ph\[^\n\r\]*ymm\[0-9\]" 1 } } */
+
+v16hf
+foo6 (v16hf a, v16hf b, v16hf c)
+{
+ return -a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmadd132ph\[^\n\r\]*ymm\[0-9\]" 1 } } */
+
+v16hf
+foo7 (v16hf a, v16hf b, v16hf c)
+{
+ return a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfmsub132ph\[^\n\r\]*ymm\[0-9\]" 1 } } */
+
+v16hf
+foo8 (v16hf a, v16hf b, v16hf c)
+{
+ return -a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmsub132ph\[^\n\r\]*ymm\[0-9\]" 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-vectorize-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-vectorize-1.c
new file mode 100644
index 0000000..d0b8bec
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-vectorize-1.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16 -mavx512vl" } */
+
+typedef _Float16 v8hf __attribute__ ((__vector_size__ (16)));
+typedef _Float16 v16hf __attribute__ ((__vector_size__ (32)));
+
+void
+foo1 (_Float16* __restrict pa, _Float16* __restrict pb,
+ _Float16* __restrict pc, _Float16* __restrict pd)
+{
+ for (int i = 0; i != 8; i++)
+ pd[i] = pa[i] * pb[i] + pc[i];
+}
+
+/* { dg-final { scan-assembler-times "vfmadd132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+void
+foo2 (_Float16* __restrict pa, _Float16* __restrict pb,
+ _Float16* __restrict pc, _Float16* __restrict pd)
+{
+ for (int i = 0; i != 8; i++)
+ pd[i] = -pa[i] * pb[i] + pc[i];
+}
+
+/* { dg-final { scan-assembler-times "vfnmadd132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+void
+foo3 (_Float16* __restrict pa, _Float16* __restrict pb,
+ _Float16* __restrict pc, _Float16* __restrict pd)
+{
+ for (int i = 0; i != 8; i++)
+ pd[i] = pa[i] * pb[i] - pc[i];
+}
+
+/* { dg-final { scan-assembler-times "vfmsub132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+void
+foo4 (_Float16* __restrict pa, _Float16* __restrict pb,
+ _Float16* __restrict pc, _Float16* __restrict pd)
+{
+ for (int i = 0; i != 8; i++)
+ pd[i] = -pa[i] * pb[i] - pc[i];
+}
+
+/* { dg-final { scan-assembler-times "vfnmsub132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-reduce-op-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-reduce-op-1.c
new file mode 100644
index 0000000..70485d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-reduce-op-1.c
@@ -0,0 +1,244 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+
+#include <immintrin.h>
+#include "avx512-check.h"
+
+__m256h a1 = { -39.3f16, -180.9f16, 13.4f16, 35.4f16, -41.1f16, -14.4f16, 24.5f16, 53.54f16,
+ 238.4f16, -134.8f16, 24.5f16, 35.6f16, -346.7f16, -43.4f16, -535.3f16, 324.7f16 };
+__m256h a2 = { 82.5f16, 21.4f16, 24.4f16, 53.4f16, 23.5f16, -24.4f16, -34.5f16, -32.5f16,
+ 23.6f16, -13.4f16, 24.5f16, 35.5f16, -34.4f16, -24.5f16, -34.5f16, 13.5f16 };
+
+__m128h b1 = { 1.25f16, 2.25f16, -0.25f16, 4.0f16, -2.0f16, 4.0f16, -3.0f16, 2.0f16 };
+__m128h b2 = { -0.5f16, -1.0f16, 1.0f16, -1.0f16, 1.0f16, 1.0f16, 2.0f16, 4.0f16 };
+__m128h b3 = { 1.25f16, 2.25f16, -4.25f16, 4.0f16, -2.4f16, 4.0f16, -3.0f, 2.0f16 };
+__m128h b4 = { -4.5f16, 7.6f16, 0.7f16, -8.2f16, 2.1f16, 2.4f16, -2.0f16, 1.4f16 };
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_256_add_ph (__m256h a)
+{
+ return _mm256_reduce_add_ph (a);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_256_mul_ph (__m256h a)
+{
+ return _mm256_reduce_mul_ph (a);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_256_max_ph (__m256h a)
+{
+ return _mm256_reduce_max_ph (a);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_256_min_ph (__m256h a)
+{
+ return _mm256_reduce_min_ph (a);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_add_ph (__m128h b)
+{
+ return _mm_reduce_add_ph (b);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_mul_ph (__m128h b)
+{
+ return _mm_reduce_mul_ph (b);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_max_ph (__m128h b)
+{
+ return _mm_reduce_max_ph (b);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_min_ph (__m128h b)
+{
+ return _mm_reduce_min_ph (b);
+}
+
+#define SIZE 16
+#define REF_ADDMUL(op, a) \
+ __m128h __a1 = _mm_setzero_ph (); \
+ for (int i = 0; i < 8; i++) { \
+ __a1[i] = (_Float16) a[i] op (_Float16) a[i + 8]; \
+ } \
+ _Float16 __c0 = __a1[0] op __a1[4]; \
+ _Float16 __c1 = __a1[1] op __a1[5]; \
+ _Float16 __c2 = __a1[2] op __a1[6]; \
+ _Float16 __c3 = __a1[3] op __a1[7]; \
+ _Float16 __d0 = __c0 op __c2; \
+ _Float16 __d1 = __c1 op __c3; \
+ _Float16 __e0 = __d0 op __d1; \
+ r3 = __e0
+
+#define TESTOP(opname, op, a) \
+ do { \
+ _Float16 r1 = _mm256_reduce_##opname##_ph (a); \
+ _Float16 r2 = test_reduce_256_##opname##_ph (a); \
+ _Float16 r3 = a[0]; \
+ if (r1 != r2) { \
+ __builtin_abort (); \
+ } \
+ REF_ADDMUL (op, a); \
+ if (r1 != r3) { \
+ __builtin_abort (); \
+ } \
+ } while (0)
+
+#define TEST_ADDMUL_PH(a) \
+ do { \
+ TESTOP (add, +, a); \
+ TESTOP (mul, *, a); \
+ } while (0)
+
+static void
+test_256_addmul_ph (void)
+{
+ TEST_ADDMUL_PH (a1);
+ TEST_ADDMUL_PH (a2);
+}
+
+#undef TESTOP
+#define TESTOP(opname, op, a) \
+ do { \
+ _Float16 r1 = _mm256_reduce_##opname##_ph (a); \
+ _Float16 r2 = test_reduce_256_##opname##_ph (a); \
+ _Float16 r3 = a[0]; \
+ if (r1 != r2) { \
+ __builtin_abort (); \
+ } \
+ for (int i = 1; i < SIZE; i++) \
+ r3 = r3 op a[i]; \
+ if (r1 != r3) { \
+ __builtin_abort (); \
+ } \
+ } while (0)
+
+#define TEST_MINMAX_PH(a) \
+ do { \
+ TESTOP (min, < a[i] ? r3 :, a); \
+ TESTOP (max, > a[i] ? r3 :, a); \
+ } while (0)
+
+static void
+test_256_minmax_ph (void)
+{
+ TEST_MINMAX_PH (a1);
+ TEST_MINMAX_PH (a2);
+}
+
+static void
+test_256_ph (void)
+{
+ test_256_addmul_ph ();
+ test_256_minmax_ph ();
+}
+
+#undef SIZE
+#define SIZE 8
+
+#undef REF_ADDMUL
+#define REF_ADDMUL(op, a) \
+ _Float16 __c0 = a[0] op a[4]; \
+ _Float16 __c1 = a[1] op a[5]; \
+ _Float16 __c2 = a[2] op a[6]; \
+ _Float16 __c3 = a[3] op a[7]; \
+ _Float16 __d0 = __c0 op __c2; \
+ _Float16 __d1 = __c1 op __c3; \
+ _Float16 __e0 = __d0 op __d1; \
+ r3 = __e0
+
+#undef TESTOP
+#define TESTOP(opname, op, a) \
+ do { \
+ _Float16 r1 = _mm_reduce_##opname##_ph (a); \
+ _Float16 r2 = test_reduce_##opname##_ph (a); \
+ _Float16 r3 = a[0]; \
+ if (r1 != r2) { \
+ __builtin_abort (); \
+ } \
+ REF_ADDMUL (op, a); \
+ if (r1 != r3) { \
+ __builtin_abort (); \
+ } \
+ } while (0)
+
+#undef TEST_ADDMUL_PH
+#define TEST_ADDMUL_PH(a) \
+ do { \
+ TESTOP (add, +, a); \
+ TESTOP (mul, *, a); \
+ } while (0)
+
+static void
+test_128_addmul_ph (void)
+{
+ TEST_ADDMUL_PH (b1);
+ TEST_ADDMUL_PH (b2);
+ TEST_ADDMUL_PH (b3);
+ TEST_ADDMUL_PH (b4);
+}
+
+#undef TESTOP
+#define TESTOP(opname, op, b) \
+ do { \
+ _Float16 r1 = _mm_reduce_##opname##_ph (b); \
+ _Float16 r2 = test_reduce_##opname##_ph (b); \
+ _Float16 r3 = b[0]; \
+ if (r1 != r2) { \
+ __builtin_abort (); \
+ } \
+ for (int i = 1; i < SIZE; i++) \
+ r3 = r3 op b[i]; \
+ if (r1 != r3) { \
+ __builtin_abort (); \
+ } \
+ } while (0)
+
+#undef TEST_MINMAX_PH
+#define TEST_MINMAX_PH(b) \
+ do { \
+ TESTOP (min, < b[i] ? r3 :, b); \
+ TESTOP (max, > b[i] ? r3 :, b); \
+ } while (0)
+
+static void
+test_128_minmax_ph (void)
+{
+ TEST_MINMAX_PH (b1);
+ TEST_MINMAX_PH (b2);
+ TEST_MINMAX_PH (b3);
+ TEST_MINMAX_PH (b4);
+}
+
+static void
+test_128_ph (void)
+{
+ test_128_addmul_ph ();
+ test_128_minmax_ph ();
+}
+
+static void
+do_test (void)
+{
+ test_256_ph ();
+ test_128_ph ();
+}
+
+
+#undef SIZE
+#undef REF_ADDMUL
+#undef TESTOP
+#undef TEST_ADDMUL_PH
+#undef TEST_MINMAX_PH
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1a.c
new file mode 100644
index 0000000..eff1381
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1a.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1, x2, x3;
+volatile __m128h x4, x5, x6;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_fcmadd_pch (x1, x2, x3);
+ res1 = _mm256_mask_fcmadd_pch (res1, m8, x1, x2);
+ res1 = _mm256_mask3_fcmadd_pch (res1, x1, x2, m8);
+ res1 = _mm256_maskz_fcmadd_pch (m8, x1, x2, x3);
+
+ res2 = _mm_fcmadd_pch (x4, x5, x6);
+ res2 = _mm_mask_fcmadd_pch (res2, m8, x4, x5);
+ res2 = _mm_mask3_fcmadd_pch (res2, x4, x5, m8);
+ res2 = _mm_maskz_fcmadd_pch (m8, x4, x5, x6);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1b.c
new file mode 100644
index 0000000..5e3a54e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfcmaddcph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfcmaddcph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c
new file mode 100644
index 0000000..4e48e9c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512f -mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1, x2, x3;
+volatile __m128h x4, x5, x6;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_fcmul_pch (x1, x2);
+ res1 = _mm256_mask_fcmul_pch (res1, m8, x1, x2);
+ res1 = _mm256_maskz_fcmul_pch (m8, x1, x2);
+
+ res2 = _mm_fcmul_pch (x4, x5);
+ res2 = _mm_mask_fcmul_pch (res2, m8, x4, x5);
+ res2 = _mm_maskz_fcmul_pch (m8, x4, x5);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1b.c
new file mode 100644
index 0000000..19564a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfcmulcph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfcmulcph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1a.c
new file mode 100644
index 0000000..b9a24d0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1a.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1, x2, x3;
+volatile __m128h x4, x5, x6;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_fmadd_pch (x1, x2, x3);
+ res1 = _mm256_mask_fmadd_pch (res1, m8, x1, x2);
+ res1 = _mm256_mask3_fmadd_pch (res1, x1, x2, m8);
+ res1 = _mm256_maskz_fmadd_pch (m8, x1, x2, x3);
+
+ res2 = _mm_fmadd_pch (x4, x5, x6);
+ res2 = _mm_mask_fmadd_pch (res2, m8, x4, x5);
+ res2 = _mm_mask3_fmadd_pch (res2, x4, x5, m8);
+ res2 = _mm_maskz_fmadd_pch (m8, x4, x5, x6);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1b.c
new file mode 100644
index 0000000..bf85fea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmaddcph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmaddcph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1a.c
new file mode 100644
index 0000000..54e58c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512f -mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1, x2, x3;
+volatile __m128h x4, x5, x6;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_fmul_pch (x1, x2);
+ res1 = _mm256_mask_fmul_pch (res1, m8, x1, x2);
+ res1 = _mm256_maskz_fmul_pch (m8, x1, x2);
+
+ res2 = _mm_fmul_pch (x4, x5);
+ res2 = _mm_mask_fmul_pch (res2, m8, x4, x5);
+ res2 = _mm_maskz_fmul_pch (m8, x4, x5);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1b.c
new file mode 100644
index 0000000..f88d842
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmulcph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmulcph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-pr95046.c b/gcc/testsuite/gcc.target/i386/avx512vl-pr95046.c
new file mode 100644
index 0000000..02204d0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-pr95046.c
@@ -0,0 +1,10 @@
+/* PR target/95046 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O3 -mavx512vl" } */
+
+#include "pr95046-3.c"
+
+/* { dg-final { scan-assembler "\tvfmadd\[123\]+ps" } } */
+/* { dg-final { scan-assembler "\tvfmsub\[123\]+ps" } } */
+/* { dg-final { scan-assembler "\tvfnmadd\[123\]+ps" } } */
+/* { dg-final { scan-assembler "\tvfnmsub\[123\]+ps" } } */
diff --git a/gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-1.c b/gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-1.c
new file mode 100644
index 0000000..b503b75
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=sapphirerapids -DTYPE=_Float16 -fdump-tree-vect" } */
+/* { dg-final { scan-tree-dump ".COND_ADD" "vect" } } */
+/* { dg-final { scan-tree-dump ".COND_SUB" "vect" } } */
+/* { dg-final { scan-tree-dump ".COND_MUL" "vect" } } */
+/* { dg-final { scan-tree-dump ".COND_RDIV" "vect" } } */
+
+#include "cond_op_addsubmuldiv_double-1.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-2.c b/gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-2.c
new file mode 100644
index 0000000..e8397bb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-2.c
@@ -0,0 +1,7 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mprefer-vector-width=256 -DTYPE=_Float16" } */
+/* { dg-require-effective-target avx512vl } */
+/* { dg-require-effective-target avx512fp16 } */
+
+#define AVX512FP16
+#include "cond_op_addsubmuldiv_double-2.c"
diff --git a/gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-1.c b/gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-1.c
new file mode 100644
index 0000000..9ea45d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=sapphirerapids -DTYPE=_Float16 -fdump-tree-optimized -D__BUILTIN_FMA=__builtin_fmaf16" } */
+/* { dg-final { scan-tree-dump-times ".COND_FMA" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times ".COND_FNMA" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times ".COND_FMS" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times ".COND_FNMS" 3 "optimized" } } */
+/* { dg-final { scan-assembler-times "vfmadd132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd231ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub231ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include "cond_op_fma_double-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-2.c b/gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-2.c
new file mode 100644
index 0000000..b384ab8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-2.c
@@ -0,0 +1,7 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mprefer-vector-width=256 -DTYPE=_Float16 -D__BUILTIN_FMA=__builtin_fmaf16 -DNUM=100" } */
+/* { dg-require-effective-target avx512fp16 } */
+/* { dg-require-effective-target avx512vl } */
+
+#define AVX512FP16
+#include "cond_op_fma_double-2.c"
diff --git a/gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-1.c b/gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-1.c
new file mode 100644
index 0000000..b094102
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=sapphirerapids -DTYPE=_Float16 -fdump-tree-optimized -DFN_MAX=__builtin_fmaxf16 -DFN_MIN=__builtin_fminf16" } */
+/* { dg-final { scan-tree-dump ".COND_MAX" "optimized" } } */
+/* { dg-final { scan-tree-dump ".COND_MIN" "optimized" } } */
+/* { dg-final { scan-assembler-times "vmaxph" 1 } } */
+/* { dg-final { scan-assembler-times "vminph" 1 } } */
+
+#include "cond_op_maxmin_double-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-2.c b/gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-2.c
new file mode 100644
index 0000000..b07d044
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-2.c
@@ -0,0 +1,7 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mprefer-vector-width=256 -DTYPE=_Float16 -DFN_MAX=__builtin_fmaxf16 -DFN_MIN=__builtin_fminf16 -ffast-math" } */
+/* { dg-require-effective-target avx512vl } */
+/* { dg-require-effective-target avx512fp16 } */
+
+#define AVX512FP16
+#include "cond_op_maxmin_double-2.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr102230.c b/gcc/testsuite/gcc.target/i386/pr102230.c
new file mode 100644
index 0000000..ad37f4f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr102230.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+typedef _Float16 v4hf __attribute__ ((vector_size (8)));
+typedef _Float16 v2hf __attribute__ ((vector_size (4)));
+
+v4hf
+v4hf_abi_1 (v4hf a)
+{
+ return a;
+}
+
+v4hf
+v4hf_abi_3 (v4hf a, v4hf b, v4hf c)
+{
+ return c;
+}
+
+/* { dg-final { scan-assembler-times "movq\[\\t \]*%mm2, %mm0" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "vmovaps\[\\t \]*%xmm2, %xmm0" 1 { target { ! ia32 } } } } */
+
+v4hf
+v4hf_abi_4 (v4hf a, v4hf b, v4hf c, v4hf d)
+{
+ return d;
+}
+
+/* { dg-final { scan-assembler-times "movq\[\\t \]*4\\(%esp\\), %mm0" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "vmovaps\[\\t \]*%xmm3, %xmm0" 1 { target { ! ia32 } } } } */
+
+v2hf
+v2hf_test (v2hf a, v2hf b, v2hf c, v2hf d)
+{
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "movl\[\\t \]*8\\(%esp\\), %eax" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "vmovaps\[\\t \]*%xmm1, %xmm0" 1 { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr102498.c b/gcc/testsuite/gcc.target/i386/pr102498.c
new file mode 100644
index 0000000..44161c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr102498.c
@@ -0,0 +1,59 @@
+/* PR target/102498 */
+/* { dg-do run { target fenv } } */
+/* { dg-options "-frounding-math" } */
+
+#include <fenv.h>
+#include <stdlib.h>
+
+__attribute__((noipa)) long double
+fldlg2 (void)
+{
+ return 0.3010299956639811952256464283594894482L;
+}
+
+__attribute__((noipa)) long double
+fldln2 (void)
+{
+ return 0.6931471805599453094286904741849753009L;
+}
+
+__attribute__((noipa)) long double
+fldl2e (void)
+{
+ return 1.4426950408889634073876517827983434472L;
+}
+
+__attribute__((noipa)) long double
+fldl2t (void)
+{
+ return 3.3219280948873623478083405569094566090L;
+}
+
+__attribute__((noipa)) long double
+fldpi (void)
+{
+ return 3.1415926535897932385128089594061862044L;
+}
+
+int
+main ()
+{
+ long double a = fldlg2 ();
+ long double b = fldln2 ();
+ long double c = fldl2e ();
+ long double d = fldl2t ();
+ long double e = fldpi ();
+ static int f[] = { FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD, FE_DOWNWARD };
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ fesetround (f[i]);
+ if (a != fldlg2 ()
+ || b != fldln2 ()
+ || c != fldl2e ()
+ || d != fldl2t ()
+ || e != fldpi ())
+ abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr89954.c b/gcc/testsuite/gcc.target/i386/pr89954.c
new file mode 100644
index 0000000..c1e9f3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr89954.c
@@ -0,0 +1,45 @@
+/* PR target/89954 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+signed char ab;
+
+short aw;
+
+int al;
+
+short sext_andbw (void) { return ab & -2; }
+short sext_orbw (void) { return ab | -3; }
+short sext_xorbw (void) { return ab ^ -4; }
+
+int sext_andbl (void) { return ab & -2; }
+int sext_orbl (void) { return ab | -3; }
+int sext_xorbl (void) { return ab ^ -4; }
+
+int sext_andwl (void) { return aw & -2; }
+int sext_orwl (void) { return aw | -3; }
+int sext_xorwl (void) { return aw ^ -4; }
+
+#ifdef __x86_64__
+
+long long sext_andbq (void) { return ab & -2; }
+long long sext_orbq (void) { return ab | -3; }
+long long sext_xorbq (void) { return ab ^ -4; }
+
+long long sext_andwq (void) { return aw & -2; }
+long long sext_orwq (void) { return aw | -3; }
+long long sext_xorwq (void) { return aw ^ -4; }
+
+long long sext_andlq (void) { return al & -2; }
+long long sext_orlq (void) { return al | -3; }
+long long sext_xorlq (void) { return al ^ -4; }
+
+#endif
+
+/* { dg-final { scan-assembler-times "movsbw" 3 } } */
+/* { dg-final { scan-assembler-times "movsbl" 3 } } */
+/* { dg-final { scan-assembler-times "movswl" 3 } } */
+
+/* { dg-final { scan-assembler-times "movsbq" 3 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "movswq" 3 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "movslq" 3 { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr92658-avx512f.c b/gcc/testsuite/gcc.target/i386/pr92658-avx512f.c
index e26b06e..9afb195 100644
--- a/gcc/testsuite/gcc.target/i386/pr92658-avx512f.c
+++ b/gcc/testsuite/gcc.target/i386/pr92658-avx512f.c
@@ -48,6 +48,10 @@ truncqb (v8qi * dst, v8di * __restrict src)
tem[1] = (*src)[1];
tem[2] = (*src)[2];
tem[3] = (*src)[3];
+ tem[4] = (*src)[4];
+ tem[5] = (*src)[5];
+ tem[6] = (*src)[6];
+ tem[7] = (*src)[7];
dst[0] = *(v8qi *) tem;
}
@@ -100,7 +104,7 @@ truncdb (v16qi * dst, v16si * __restrict src)
/* { dg-final { scan-assembler-times "vpmovqd" 1 } } */
/* { dg-final { scan-assembler-times "vpmovqw" 1 } } */
-/* { dg-final { scan-assembler-times "vpmovqb" 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "vpmovqb" 1 } } */
/* { dg-final { scan-assembler-times "vpmovdw" 1 } } */
/* { dg-final { scan-assembler-times "vpmovdb" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr92658-avx512vl.c b/gcc/testsuite/gcc.target/i386/pr92658-avx512vl.c
index 7ff9c19..ae6959e 100644
--- a/gcc/testsuite/gcc.target/i386/pr92658-avx512vl.c
+++ b/gcc/testsuite/gcc.target/i386/pr92658-avx512vl.c
@@ -123,6 +123,7 @@ truncdb_128 (v16qi * dst, v4si * __restrict src)
/* { dg-final { scan-assembler-times "vpmovqd" 2 } } */
/* { dg-final { scan-assembler-times "vpmovqw" 2 } } */
-/* { dg-final { scan-assembler-times "vpmovqb" 2 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "vpmovqb\[ \t]*%ymm" 1 } } */
+/* { dg-final { scan-assembler-times "vpmovqb\[ \t]*%xmm" 1 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "vpmovdw" 2 } } */
/* { dg-final { scan-assembler-times "vpmovdb" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse-13.c b/gcc/testsuite/gcc.target/i386/sse-13.c
index e9a838e..f6d54e3 100644
--- a/gcc/testsuite/gcc.target/i386/sse-13.c
+++ b/gcc/testsuite/gcc.target/i386/sse-13.c
@@ -804,6 +804,26 @@
#define __builtin_ia32_vfnmsubsh3_mask(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_mask(A, B, C, D, 8)
#define __builtin_ia32_vfnmsubsh3_mask3(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_mask3(A, B, C, D, 8)
#define __builtin_ia32_vfnmsubsh3_maskz(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfcmaddcph512_round(A, B, C, D) __builtin_ia32_vfcmaddcph512_round(A, B, C, 8)
+#define __builtin_ia32_vfcmaddcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfcmaddcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcph512_maskz_round(B, C, D, A, E) __builtin_ia32_vfcmaddcph512_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmaddcph512_round(A, B, C, D) __builtin_ia32_vfmaddcph512_round(A, B, C, 8)
+#define __builtin_ia32_vfmaddcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfmaddcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcph512_maskz_round(B, C, D, A, E) __builtin_ia32_vfmaddcph512_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmulcph512_round(A, B, C) __builtin_ia32_vfmulcph512_round(A, B, 8)
+#define __builtin_ia32_vfmulcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfmulcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmulcph512_round(A, B, C) __builtin_ia32_vfcmulcph512_round(A, B, 8)
+#define __builtin_ia32_vfcmulcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfcmulcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcsh_round(A, B, C, D) __builtin_ia32_vfmaddcsh_round(A, B, C, 8)
+#define __builtin_ia32_vfmaddcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfmaddcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcsh_maskz_round(B, C, D, A, E) __builtin_ia32_vfmaddcsh_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfcmaddcsh_round(A, B, C, D) __builtin_ia32_vfcmaddcsh_round(A, B, C, 8)
+#define __builtin_ia32_vfcmaddcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfcmaddcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcsh_maskz_round(B, C, D, A, E) __builtin_ia32_vfcmaddcsh_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmulcsh_round(A, B, C) __builtin_ia32_vfmulcsh_round(A, B, 8)
+#define __builtin_ia32_vfmulcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfmulcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmulcsh_round(A, B, C) __builtin_ia32_vfcmulcsh_round(A, B, 8)
+#define __builtin_ia32_vfcmulcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfcmulcsh_mask_round(A, C, D, B, 8)
/* avx512fp16vlintrin.h */
#define __builtin_ia32_cmpph128_mask(A, B, C, D) __builtin_ia32_cmpph128_mask(A, B, 1, D)
diff --git a/gcc/testsuite/gcc.target/i386/sse-14.c b/gcc/testsuite/gcc.target/i386/sse-14.c
index 01ac4e0..956a9d1 100644
--- a/gcc/testsuite/gcc.target/i386/sse-14.c
+++ b/gcc/testsuite/gcc.target/i386/sse-14.c
@@ -772,6 +772,10 @@ test_2 (_mm_cvt_roundss_sh, __m128h, __m128h, __m128, 8)
test_2 (_mm_cvt_roundsd_sh, __m128h, __m128h, __m128d, 8)
test_2 (_mm_cvt_roundi32_sh, __m128h, __m128h, int, 8)
test_2 (_mm_cvt_roundu32_sh, __m128h, __m128h, unsigned, 8)
+test_2 (_mm512_fmul_round_pch, __m512h, __m512h, __m512h, 8)
+test_2 (_mm512_fcmul_round_pch, __m512h, __m512h, __m512h, 8)
+test_2 (_mm_fmul_round_sch, __m128h, __m128h, __m128h, 8)
+test_2 (_mm_fcmul_round_sch, __m128h, __m128h, __m128h, 8)
test_2x (_mm512_cmp_round_ph_mask, __mmask32, __m512h, __m512h, 1, 8)
test_2x (_mm_cmp_round_sh_mask, __mmask8, __m128h, __m128h, 1, 8)
test_2x (_mm_comi_round_sh, int, __m128h, __m128h, 1, 8)
@@ -846,6 +850,14 @@ test_3 (_mm_fmadd_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
test_3 (_mm_fnmadd_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
test_3 (_mm_fmsub_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
test_3 (_mm_fnmsub_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
+test_3 (_mm512_fmadd_round_pch, __m512h, __m512h, __m512h, __m512h, 8)
+test_3 (_mm512_fcmadd_round_pch, __m512h, __m512h, __m512h, __m512h, 8)
+test_3 (_mm_fmadd_round_sch, __m128h, __m128h, __m128h, __m128h, 8)
+test_3 (_mm_fcmadd_round_sch, __m128h, __m128h, __m128h, __m128h, 8)
+test_3 (_mm512_maskz_fmul_round_pch, __m512h, __mmask16, __m512h, __m512h, 8)
+test_3 (_mm512_maskz_fcmul_round_pch, __m512h, __mmask16, __m512h, __m512h, 8)
+test_3 (_mm_maskz_fmul_round_sch, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm_maskz_fcmul_round_sch, __m128h, __mmask8, __m128h, __m128h, 8)
test_3x (_mm512_mask_cmp_round_ph_mask, __mmask32, __mmask32, __m512h, __m512h, 1, 8)
test_3x (_mm_mask_cmp_round_sh_mask, __mmask8, __mmask8, __m128h, __m128h, 1, 8)
test_3x (_mm512_mask_reduce_round_ph, __m512h, __m512h, __mmask32, __m512h, 123, 8)
@@ -908,6 +920,22 @@ test_4 (_mm_maskz_fmsub_round_sh, __m128h, __mmask8, __m128h, __m128h, __m128h,
test_4 (_mm_mask_fnmsub_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 9)
test_4 (_mm_mask3_fnmsub_round_sh, __m128h, __m128h, __m128h, __m128h, __mmask8, 9)
test_4 (_mm_maskz_fnmsub_round_sh, __m128h, __mmask8, __m128h, __m128h, __m128h, 9)
+test_4 (_mm512_mask_fmadd_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm512_mask_fcmadd_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm512_mask3_fmadd_round_pch, __m512h, __m512h, __m512h, __m512h, __mmask16, 8)
+test_4 (_mm512_mask3_fcmadd_round_pch, __m512h, __m512h, __m512h, __m512h, __mmask16, 8)
+test_4 (_mm512_maskz_fmadd_round_pch, __m512h, __mmask16, __m512h, __m512h, __m512h, 8)
+test_4 (_mm512_maskz_fcmadd_round_pch, __m512h, __mmask16, __m512h, __m512h, __m512h, 8)
+test_4 (_mm_mask_fmadd_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_fcmadd_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask3_fmadd_round_sch, __m128h, __m128h, __m128h, __m128h, __mmask8, 8)
+test_4 (_mm_mask3_fcmadd_round_sch, __m128h, __m128h, __m128h, __m128h, __mmask8, 8)
+test_4 (_mm_maskz_fmadd_round_sch, __m128h, __mmask8, __m128h, __m128h, __m128h, 8)
+test_4 (_mm_maskz_fcmadd_round_sch, __m128h, __mmask8, __m128h, __m128h, __m128h, 8)
+test_4 (_mm512_mask_fmul_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm512_mask_fcmul_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm_mask_fmul_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_fcmul_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
test_4x (_mm_mask_reduce_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 123, 8)
test_4x (_mm_mask_roundscale_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 123, 8)
test_4x (_mm_mask_getmant_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 1, 1)
diff --git a/gcc/testsuite/gcc.target/i386/sse-22.c b/gcc/testsuite/gcc.target/i386/sse-22.c
index 79e3f35..31492ef 100644
--- a/gcc/testsuite/gcc.target/i386/sse-22.c
+++ b/gcc/testsuite/gcc.target/i386/sse-22.c
@@ -876,6 +876,10 @@ test_2 (_mm_cvt_roundsh_ss, __m128, __m128, __m128h, 8)
test_2 (_mm_cvt_roundsh_sd, __m128d, __m128d, __m128h, 8)
test_2 (_mm_cvt_roundss_sh, __m128h, __m128h, __m128, 8)
test_2 (_mm_cvt_roundsd_sh, __m128h, __m128h, __m128d, 8)
+test_2 (_mm512_fmul_round_pch, __m512h, __m512h, __m512h, 8)
+test_2 (_mm512_fcmul_round_pch, __m512h, __m512h, __m512h, 8)
+test_2 (_mm_fmul_round_sch, __m128h, __m128h, __m128h, 8)
+test_2 (_mm_fcmul_round_sch, __m128h, __m128h, __m128h, 8)
test_2x (_mm512_cmp_round_ph_mask, __mmask32, __m512h, __m512h, 1, 8)
test_2x (_mm_cmp_round_sh_mask, __mmask8, __m128h, __m128h, 1, 8)
test_2x (_mm_comi_round_sh, int, __m128h, __m128h, 1, 8)
@@ -949,6 +953,14 @@ test_3 (_mm_fmadd_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
test_3 (_mm_fnmadd_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
test_3 (_mm_fmsub_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
test_3 (_mm_fnmsub_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
+test_3 (_mm512_fmadd_round_pch, __m512h, __m512h, __m512h, __m512h, 8)
+test_3 (_mm512_fcmadd_round_pch, __m512h, __m512h, __m512h, __m512h, 8)
+test_3 (_mm512_maskz_fmul_round_pch, __m512h, __mmask16, __m512h, __m512h, 8)
+test_3 (_mm_maskz_fmul_round_sch, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm_maskz_fcmul_round_sch, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm_fmadd_round_sch, __m128h, __m128h, __m128h, __m128h, 8)
+test_3 (_mm_fcmadd_round_sch, __m128h, __m128h, __m128h, __m128h, 8)
+test_3 (_mm512_maskz_fcmul_round_pch, __m512h, __mmask16, __m512h, __m512h, 8)
test_3x (_mm512_mask_cmp_round_ph_mask, __mmask32, __mmask32, __m512h, __m512h, 1, 8)
test_3x (_mm_mask_cmp_round_sh_mask, __mmask8, __mmask8, __m128h, __m128h, 1, 8)
test_3x (_mm512_mask_reduce_round_ph, __m512h, __m512h, __mmask32, __m512h, 123, 8)
@@ -1010,6 +1022,22 @@ test_4 (_mm_maskz_fmsub_round_sh, __m128h, __mmask8, __m128h, __m128h, __m128h,
test_4 (_mm_mask_fnmsub_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 9)
test_4 (_mm_mask3_fnmsub_round_sh, __m128h, __m128h, __m128h, __m128h, __mmask8, 9)
test_4 (_mm_maskz_fnmsub_round_sh, __m128h, __mmask8, __m128h, __m128h, __m128h, 9)
+test_4 (_mm512_mask_fmadd_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm512_mask_fcmadd_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm512_mask3_fmadd_round_pch, __m512h, __m512h, __m512h, __m512h, __mmask16, 8)
+test_4 (_mm512_mask3_fcmadd_round_pch, __m512h, __m512h, __m512h, __m512h, __mmask16, 8)
+test_4 (_mm512_maskz_fmadd_round_pch, __m512h, __mmask16, __m512h, __m512h, __m512h, 8)
+test_4 (_mm512_maskz_fcmadd_round_pch, __m512h, __mmask16, __m512h, __m512h, __m512h, 8)
+test_4 (_mm_mask_fmadd_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_fcmadd_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask3_fmadd_round_sch, __m128h, __m128h, __m128h, __m128h, __mmask8, 8)
+test_4 (_mm_mask3_fcmadd_round_sch, __m128h, __m128h, __m128h, __m128h, __mmask8, 8)
+test_4 (_mm_maskz_fmadd_round_sch, __m128h, __mmask8, __m128h, __m128h, __m128h, 8)
+test_4 (_mm_maskz_fcmadd_round_sch, __m128h, __mmask8, __m128h, __m128h, __m128h, 8)
+test_4 (_mm512_mask_fmul_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm512_mask_fcmul_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm_mask_fmul_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_fcmul_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
test_4x (_mm_mask_reduce_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 123, 8)
test_4x (_mm_mask_roundscale_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 123, 8)
test_4x (_mm_mask_getmant_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 1, 1)
diff --git a/gcc/testsuite/gcc.target/i386/sse-23.c b/gcc/testsuite/gcc.target/i386/sse-23.c
index 4be2c1e..9825126 100644
--- a/gcc/testsuite/gcc.target/i386/sse-23.c
+++ b/gcc/testsuite/gcc.target/i386/sse-23.c
@@ -805,6 +805,26 @@
#define __builtin_ia32_vfnmsubsh3_mask(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_mask(A, B, C, D, 8)
#define __builtin_ia32_vfnmsubsh3_mask3(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_mask3(A, B, C, D, 8)
#define __builtin_ia32_vfnmsubsh3_maskz(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfcmaddcph512_round(A, B, C, D) __builtin_ia32_vfcmaddcph512_round(A, B, C, 8)
+#define __builtin_ia32_vfcmaddcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfcmaddcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcph512_maskz_round(B, C, D, A, E) __builtin_ia32_vfcmaddcph512_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmaddcph512_round(A, B, C, D) __builtin_ia32_vfmaddcph512_round(A, B, C, 8)
+#define __builtin_ia32_vfmaddcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfmaddcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcph512_maskz_round(B, C, D, A, E) __builtin_ia32_vfmaddcph512_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmulcph512_round(A, B, C) __builtin_ia32_vfmulcph512_round(A, B, 8)
+#define __builtin_ia32_vfmulcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfmulcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmulcph512_round(A, B, C) __builtin_ia32_vfcmulcph512_round(A, B, 8)
+#define __builtin_ia32_vfcmulcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfcmulcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcsh_round(A, B, C, D) __builtin_ia32_vfmaddcsh_round(A, B, C, 8)
+#define __builtin_ia32_vfmaddcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfmaddcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcsh_maskz_round(B, C, D, A, E) __builtin_ia32_vfmaddcsh_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfcmaddcsh_round(A, B, C, D) __builtin_ia32_vfcmaddcsh_round(A, B, C, 8)
+#define __builtin_ia32_vfcmaddcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfcmaddcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcsh_maskz_round(B, C, D, A, E) __builtin_ia32_vfcmaddcsh_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmulcsh_round(A, B, C) __builtin_ia32_vfmulcsh_round(A, B, 8)
+#define __builtin_ia32_vfmulcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfmulcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmulcsh_round(A, B, C) __builtin_ia32_vfcmulcsh_round(A, B, 8)
+#define __builtin_ia32_vfcmulcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfcmulcsh_mask_round(A, C, D, B, 8)
/* avx512fp16vlintrin.h */
#define __builtin_ia32_cmpph128_mask(A, B, C, D) __builtin_ia32_cmpph128_mask(A, B, 1, D)
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-paddsb-2.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddsb-2.c
new file mode 100644
index 0000000..c677884
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddsb-2.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2" } */
+
+typedef char v8qi __attribute__ ((vector_size (8)));
+
+char foo()
+{
+ v8qi tx = { 1, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 2, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_paddsb(tx, ty);
+ return t[0];
+}
+
+char bar()
+{
+ v8qi tx = { 100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_paddsb(tx, ty);
+ return t[0];
+}
+
+char baz()
+{
+ v8qi tx = { -100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { -100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_paddsb(tx, ty);
+ return t[0];
+}
+
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$3," 1 } } */
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$127," 1 } } */
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$-128," 1 } } */
+/* { dg-final { scan-assembler-not "paddsb\[ \\t\]+%xmm\[0-9\]+" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-paddusb-2.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddusb-2.c
new file mode 100644
index 0000000..b20891c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddusb-2.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2" } */
+
+typedef char v8qi __attribute__ ((vector_size (8)));
+
+char foo()
+{
+ v8qi tx = { 1, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 2, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_paddusb(tx, ty);
+ return t[0];
+}
+
+char bar()
+{
+ v8qi tx = { 200, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 200, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_paddusb(tx, ty);
+ return t[0];
+}
+
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$3," 1 } } */
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$-1," 1 } } */
+/* { dg-final { scan-assembler-not "paddusb\[ \\t\]+%xmm\[0-9\]+" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psubsb-2.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubsb-2.c
new file mode 100644
index 0000000..4fc2920
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubsb-2.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2" } */
+
+typedef char v8qi __attribute__ ((vector_size (8)));
+
+char foo()
+{
+ v8qi tx = { 5, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 2, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_psubsb(tx, ty);
+ return t[0];
+}
+
+char bar()
+{
+ v8qi tx = { -100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_psubsb(tx, ty);
+ return t[0];
+}
+
+char baz()
+{
+ v8qi tx = { 100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { -100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_psubsb(tx, ty);
+ return t[0];
+}
+
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$3," 1 } } */
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$-128," 1 } } */
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$127," 1 } } */
+/* { dg-final { scan-assembler-not "paddsb\[ \\t\]+%xmm\[0-9\]+" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psubusb-2.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubusb-2.c
new file mode 100644
index 0000000..5fc58ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubusb-2.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2" } */
+
+typedef char v8qi __attribute__ ((vector_size (8)));
+
+char foo()
+{
+ v8qi tx = { 5, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 2, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_psubusb(tx, ty);
+ return t[0];
+}
+
+char bar()
+{
+ v8qi tx = { 100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 200, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_psubusb(tx, ty);
+ return t[0];
+}
+
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$3," 1 } } */
+/* { dg-final { scan-assembler-times "xorl\[ \\t\]+" 1 } } */
+/* { dg-final { scan-assembler-not "psubusb\[ \\t\]+%xmm\[0-9\]+" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/sse2-pr101059.c b/gcc/testsuite/gcc.target/i386/sse2-pr101059.c
deleted file mode 100644
index d155bf5..0000000
--- a/gcc/testsuite/gcc.target/i386/sse2-pr101059.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* { dg-do run } */
-/* { dg-options "-O2 -ffast-math -msse2" } */
-/* { dg-require-effective-target sse2 } */
-
-#ifndef CHECK_H
-#define CHECK_H "sse2-check.h"
-#endif
-
-#ifndef TEST
-#define TEST sse2_test
-#endif
-
-#include CHECK_H
-
-float
-__attribute__((noipa, optimize("tree-vectorize")))
-foo (float* p)
-{
- float sum = 0.f;
- for (int i = 0; i != 4; i++)
- sum += p[i];
- return sum;
-}
-
-static void
-TEST (void)
-{
- float p[4] = {1.0f, 2.0f, 3.0f, 4.0f};
- float res = foo (p);
- if (res != 10.0f)
- abort();
-}
diff --git a/gcc/testsuite/gcc.target/i386/sse3-pr101059.c b/gcc/testsuite/gcc.target/i386/sse3-pr101059.c
deleted file mode 100644
index 4795e89..0000000
--- a/gcc/testsuite/gcc.target/i386/sse3-pr101059.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/* { dg-do run } */
-/* { dg-options "-O2 -ffast-math -msse3" } */
-/* { dg-require-effective-target sse3 } */
-
-#ifndef CHECK_H
-#define CHECK_H "sse3-check.h"
-#endif
-
-#ifndef TEST
-#define TEST sse3_test
-#endif
-
-#include "sse2-pr101059.c"
diff --git a/gcc/testsuite/gcc.target/i386/vect-alignment-peeling-1.c b/gcc/testsuite/gcc.target/i386/vect-alignment-peeling-1.c
new file mode 100644
index 0000000..4aa536b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-alignment-peeling-1.c
@@ -0,0 +1,90 @@
+/* { dg-do run { target lp64 } } */
+/* This is a test exercising peeling for alignment for a negative step
+ vector loop. We're forcing atom tuning here because that has a higher
+ unaligned vs aligned cost unlike most other archs. */
+/* { dg-options "-O3 -march=x86-64 -mtune=atom -fdump-tree-vect-details -save-temps" } */
+
+float a[1024], b[1024];
+
+void __attribute__((noipa)) foo1 ()
+{
+ for (int i = 507; i > 1; --i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo2 ()
+{
+ for (int i = 506; i > 1; --i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo3 ()
+{
+ for (int i = 505; i > 1; --i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo4 ()
+{
+ for (int i = 504; i > 1; --i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo5 (int start)
+{
+ for (int i = start; i > 1; --i)
+ a[i] = b[i] * 2.;
+}
+
+int main()
+{
+ for (int i = 2; i < 508; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo1 ();
+ for (int i = 2; i < 508; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 2; i < 507; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo2 ();
+ for (int i = 2; i < 507; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 2; i < 506; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo3 ();
+ for (int i = 2; i < 506; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 2; i < 505; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo4 ();
+ for (int i = 2; i < 505; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 2; i < 506; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo5 (505);
+ for (int i = 2; i < 506; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 4 "vect" } } */
+/* Verify all vector accesses are emitted as aligned. */
+/* { dg-final { scan-assembler-not "movup" } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-alignment-peeling-2.c b/gcc/testsuite/gcc.target/i386/vect-alignment-peeling-2.c
new file mode 100644
index 0000000..834bf0f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-alignment-peeling-2.c
@@ -0,0 +1,90 @@
+/* { dg-do run { target lp64 } } */
+/* This is a test exercising peeling for alignment for a positive step
+ vector loop. We're forcing atom tuning here because that has a higher
+ unaligned vs aligned cost unlike most other archs. */
+/* { dg-options "-O3 -march=x86-64 -mtune=atom -fdump-tree-vect-details -save-temps" } */
+
+float a[1024], b[1024];
+
+void __attribute__((noipa)) foo1 ()
+{
+ for (int i = 2; i < 508; ++i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo2 ()
+{
+ for (int i = 3; i < 508; ++i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo3 ()
+{
+ for (int i = 4; i < 508; ++i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo4 ()
+{
+ for (int i = 5; i < 508; ++i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo5 (int start)
+{
+ for (int i = start; i < 508; ++i)
+ a[i] = b[i] * 2.;
+}
+
+int main()
+{
+ for (int i = 2; i < 508; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo1 ();
+ for (int i = 2; i < 508; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 3; i < 508; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo2 ();
+ for (int i = 3; i < 508; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 4; i < 508; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo3 ();
+ for (int i = 4; i < 508; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 5; i < 508; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo4 ();
+ for (int i = 5; i < 508; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 3; i < 508; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo5 (3);
+ for (int i = 3; i < 508; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 4 "vect" } } */
+/* Verify all vector accesses are emitted as aligned. */
+/* { dg-final { scan-assembler-not "movup" } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-pr82426.c b/gcc/testsuite/gcc.target/i386/vect-pr82426.c
new file mode 100644
index 0000000..03b10ad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-pr82426.c
@@ -0,0 +1,31 @@
+/* i?86 does not have V2SF, x32 does though. */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O3 -mavx -mfma" } */
+
+struct Matrix
+{
+ float m11;
+ float m12;
+ float m21;
+ float m22;
+ float dx;
+ float dy;
+};
+
+struct Matrix multiply(const struct Matrix *a, const struct Matrix *b)
+{
+ struct Matrix out;
+ out.m11 = a->m11*b->m11 + a->m12*b->m21;
+ out.m12 = a->m11*b->m12 + a->m12*b->m22;
+ out.m21 = a->m21*b->m11 + a->m22*b->m21;
+ out.m22 = a->m21*b->m12 + a->m22*b->m22;
+
+ out.dx = a->dx*b->m11 + a->dy*b->m21 + b->dx;
+ out.dy = a->dx*b->m12 + a->dy*b->m22 + b->dy;
+ return out;
+}
+
+/* The whole kernel should be vectorized with V4SF and V2SF operations. */
+/* { dg-final { scan-assembler-times "vadd" 1 } } */
+/* { dg-final { scan-assembler-times "vmul" 2 } } */
+/* { dg-final { scan-assembler-times "vfma" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-pr97352.c b/gcc/testsuite/gcc.target/i386/vect-pr97352.c
new file mode 100644
index 0000000..f6cbf36
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-pr97352.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx -mno-avx2 -mno-avx512f" } */
+
+double x[2], a[4], b[4], c[5];
+
+void foo ()
+{
+ a[0] = c[0];
+ a[1] = c[1];
+ a[2] = c[0];
+ a[3] = c[1];
+ b[0] = c[2];
+ b[1] = c[3];
+ b[2] = c[2];
+ b[3] = c[3];
+ x[0] = c[4];
+ x[1] = c[4];
+}
+
+/* We should vectorize all three stores and the load from c apart
+ from c[4] which should be duped. */
+/* { dg-final { scan-assembler-times "vmov.pd" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-rebuild.c b/gcc/testsuite/gcc.target/i386/vect-rebuild.c
index 570967f..8e85b98 100644
--- a/gcc/testsuite/gcc.target/i386/vect-rebuild.c
+++ b/gcc/testsuite/gcc.target/i386/vect-rebuild.c
@@ -30,4 +30,4 @@ v2df h (v4df x)
/* { dg-final { scan-assembler-not "unpck" } } */
/* { dg-final { scan-assembler-times "\tv?permilpd\[ \t\]" 1 } } */
-/* { dg-final { scan-assembler-times "\tv?extractf128\[ \t\]" 1 } } */
+/* { dg-final { scan-assembler-times "\tv?extract(?:f128|f64x2)\[ \t\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/pru/regio-as-pointer-2.c b/gcc/testsuite/gcc.target/pru/regio-as-pointer-2.c
new file mode 100644
index 0000000..06d9473
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-as-pointer-2.c
@@ -0,0 +1,11 @@
+/* Test __regio_symbol invalid attempt to get regio variable address. */
+
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+#include "regio.h"
+
+uint32_t test(void)
+{
+ return *(&__R30+1); /* { dg-error "invalid access to '__regio_symbol' address space" } */
+}
diff --git a/gcc/testsuite/gcc.target/pru/regio-as-pointer.c b/gcc/testsuite/gcc.target/pru/regio-as-pointer.c
new file mode 100644
index 0000000..885464f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-as-pointer.c
@@ -0,0 +1,11 @@
+/* Test __regio_symbol invalid attempt to get regio variable address. */
+
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+#include "regio.h"
+
+uint32_t *test(void)
+{
+ return &__R31; /* { dg-error "return from pointer to non-enclosed address space" } */
+}
diff --git a/gcc/testsuite/gcc.target/pru/regio-decl-2.c b/gcc/testsuite/gcc.target/pru/regio-decl-2.c
new file mode 100644
index 0000000..9a9338e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-decl-2.c
@@ -0,0 +1,13 @@
+/* Test __regio_symbol diagnostics for unsupported declarations. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+#include <stdint.h>
+
+extern volatile __regio_symbol
+uint32_t __R30[10]; /* { dg-error "aggregate types are prohibited in '__regio_symbol' address space" } */
+
+/* { dg-warning "'__R31' initialized and declared 'extern'" "" { target *-*-* } 0 } */
+extern volatile __regio_symbol
+uint32_t __R31 = 2; /* { dg-error "variables in '__regio_symbol' address space cannot have initial value" } */
diff --git a/gcc/testsuite/gcc.target/pru/regio-decl-3.c b/gcc/testsuite/gcc.target/pru/regio-decl-3.c
new file mode 100644
index 0000000..36fcd8a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-decl-3.c
@@ -0,0 +1,19 @@
+/* Test __regio_symbol diagnostics for unsupported declarations. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+#include <stdint.h>
+
+uint32_t __regio_symbol *test1(void); /* { dg-error "pointers to '__regio_symbol' address space are prohibited" } */
+
+void test2(uint32_t __regio_symbol __R30); /* { dg-error "'__regio_symbol' specified for parameter '__R30'" } */
+
+void test3(uint32_t __regio_symbol *__R30); /* { dg-error "pointers to '__regio_symbol' address space are prohibited" } */
+
+typedef volatile uint32_t __regio_symbol * regio_type1_t; /* { dg-error "pointers to '__regio_symbol' address space are prohibited" } */
+
+struct A {
+ uint32_t __regio_symbol *__R30; /* { dg-error "pointers to '__regio_symbol' address space are prohibited" } */
+ uint32_t __regio_symbol __R31; /* { dg-error "__regio_symbol' specified for structure field '__R31'" } */
+};
diff --git a/gcc/testsuite/gcc.target/pru/regio-decl-4.c b/gcc/testsuite/gcc.target/pru/regio-decl-4.c
new file mode 100644
index 0000000..48c45a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-decl-4.c
@@ -0,0 +1,17 @@
+/* Test __regio_symbol diagnostics for unsupported access. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+#include <stdint.h>
+
+extern volatile uint32_t __regio_symbol *__R30;
+uint32_t test_r(void)
+{
+ return *__R30; /* { dg-error "invalid access to '__regio_symbol' address space" } */
+}
+
+void test_w(uint32_t a)
+{
+ *__R30 = a; /* { dg-error "invalid access to '__regio_symbol' address space" } */
+}
diff --git a/gcc/testsuite/gcc.target/pru/regio-decl.c b/gcc/testsuite/gcc.target/pru/regio-decl.c
new file mode 100644
index 0000000..a4962aa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-decl.c
@@ -0,0 +1,15 @@
+/* Test __regio_symbol diagnostics for unsupported declarations. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+#include <stdint.h>
+
+volatile __regio_symbol
+uint32_t __R30; /* { dg-error "variables in '__regio_symbol' address space must be declared 'extern'" } */
+
+extern __regio_symbol
+uint32_t __R31; /* { dg-error "variables in '__regio_symbol' address space must be declared 'volatile'" } */
+
+extern volatile
+__regio_symbol uint32_t __R32; /* { dg-error "register name '__R32' not recognized in '__regio_symbol' address space" } */
diff --git a/gcc/testsuite/gcc.target/pru/regio-di.c b/gcc/testsuite/gcc.target/pru/regio-di.c
new file mode 100644
index 0000000..a422627
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-di.c
@@ -0,0 +1,9 @@
+/* Test __regio_symbol invalid access diagnostic for DImode. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+#include <stdint.h>
+
+extern volatile
+__regio_symbol uint64_t __R31; /* { dg-error "only 32-bit access is supported for '__regio_symbol' address space" } */
diff --git a/gcc/testsuite/gcc.target/pru/regio-hi.c b/gcc/testsuite/gcc.target/pru/regio-hi.c
new file mode 100644
index 0000000..5b89e8c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-hi.c
@@ -0,0 +1,9 @@
+/* Test __regio_symbol invalid access diagnostic for HImode. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+#include <stdint.h>
+
+extern volatile __regio_symbol
+uint16_t __R31; /* { dg-error "only 32-bit access is supported for '__regio_symbol' address space" } */
diff --git a/gcc/testsuite/gcc.target/pru/regio-qi.c b/gcc/testsuite/gcc.target/pru/regio-qi.c
new file mode 100644
index 0000000..a3f6306
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-qi.c
@@ -0,0 +1,9 @@
+/* Test __regio_symbol invalid access diagnostic for QImode. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+#include <stdint.h>
+
+extern volatile __regio_symbol
+uint8_t __R31; /* { dg-error "only 32-bit access is supported for '__regio_symbol' address space" } */
diff --git a/gcc/testsuite/gcc.target/pru/regio.c b/gcc/testsuite/gcc.target/pru/regio.c
new file mode 100644
index 0000000..2f01263
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio.c
@@ -0,0 +1,58 @@
+/* __regio_symbol operations. */
+
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+
+#include "regio.h"
+
+void
+test_r30_w_const (void)
+{
+ /* { dg-final { scan-assembler "mov\\tr30, r\[012\]\[0-9\]?" } } */
+ __R30 = 1;
+}
+
+void
+test_r31_w_zext_qi (unsigned char val1)
+{
+ /* { dg-final { scan-assembler "mov\\tr31, r14.b0" } } */
+ __R31 = val1;
+}
+
+void
+test_r31_w_zext_hi (unsigned short val1)
+{
+ /* { dg-final { scan-assembler "mov\\tr31, r14.w0" } } */
+ __R31 = val1;
+}
+
+void
+test_r31_w (unsigned int val1)
+{
+ /* { dg-final { scan-assembler "mov\\tr31, r14" } } */
+ __R31 = val1;
+}
+
+uint32_t
+test_r30_r (void)
+{
+ /* { dg-final { scan-assembler "mov\\tr14, r30" } } */
+ return __R30;
+}
+
+void
+test_r30_rw (void)
+{
+ /* { dg-final { scan-assembler "mov\\tr\[012\]\[0-9\]?, r30" } } */
+ /* { dg-final { scan-assembler "mov\\tr30, r\[012\]\[0-9\]?" } } */
+ __R30 = __R30;
+}
+
+void
+test_r31_rw (void)
+{
+ /* { dg-final { scan-assembler "mov\\tr\[012\]\[0-9\]?, r31" } } */
+ /* { dg-final { scan-assembler "mov\\tr31, r\[012\]\[0-9\]?" } } */
+ __R31 |= 101;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/regio.h b/gcc/testsuite/gcc.target/pru/regio.h
new file mode 100644
index 0000000..3a120c1d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio.h
@@ -0,0 +1,7 @@
+
+#include <stdint.h>
+
+/* Declare the I/O registers. */
+extern volatile __regio_symbol uint32_t __R30;
+extern volatile __regio_symbol uint32_t __R31;
+
diff --git a/gcc/testsuite/gcc.target/s390/pr102222.c b/gcc/testsuite/gcc.target/s390/pr102222.c
new file mode 100644
index 0000000..47d075e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr102222.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -m31 -mesa" } */
+
+struct squashfs_reg_inode_header_1 read_inode_inode;
+
+int read_inode_val;
+
+struct squashfs_reg_inode_header_1
+{
+ int file_size:32;
+} __attribute__((packed)) read_inode ();
+
+void foo (void)
+{
+ read_inode_inode.file_size = read_inode_val;
+}
diff --git a/gcc/testsuite/gcc.target/s390/pr80725.c b/gcc/testsuite/gcc.target/s390/pr80725.c
index 4a402c4..d556e6b 100644
--- a/gcc/testsuite/gcc.target/s390/pr80725.c
+++ b/gcc/testsuite/gcc.target/s390/pr80725.c
@@ -18,7 +18,7 @@ foo (int x, int y)
while (a < x)
{
if (y)
- goto *d;
+ goto *(void *)d;
g = b | b + g;
bar (g);
c = (char) (long) foo;
diff --git a/gcc/testsuite/gdc.dg/pr102476.d b/gcc/testsuite/gdc.dg/pr102476.d
new file mode 100644
index 0000000..543716e
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr102476.d
@@ -0,0 +1,3 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102476
+// { dg-do link }
+// { dg-options "-fmain -fno-druntime" }
diff --git a/gcc/testsuite/gfortran.dg/associated_assumed_rank.f90 b/gcc/testsuite/gfortran.dg/associated_assumed_rank.f90
new file mode 100644
index 0000000..8bb7ea1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/associated_assumed_rank.f90
@@ -0,0 +1,126 @@
+! { dg-do run }
+
+! PR fortran/101334
+
+implicit none (type, external)
+real, target :: AT(10,10), BT
+real, contiguous, pointer :: A(:,:)
+real, pointer :: B
+real, pointer :: AP(:,:), BP
+real, pointer :: CP(:), DP(:,:), D, EP(:)
+
+call test_char()
+
+A => AT
+B => BT
+
+AP => A
+BP => B
+call foo(AP,B, A, 1) ! OK - associated
+call foo(BP,B, A, 2) ! OK - associated
+
+! Those are all not associated:
+
+AP => null()
+BP => null()
+call foo(AP, B, A, 3) ! LHS not associated
+call foo(BP, B, A, 4) ! LHS not associated
+
+DP => null()
+D => null()
+call foo(AP, B, DP, 5) ! LHS+RHS not associated
+call foo(BP, D, A, 6) ! LHS+RHS not associated
+
+AP => A
+BP => B
+call foo(AP, B, DP, 7) ! RHS not associated
+call foo(BP, D, A, 8) ! RHS not associated
+
+CP(1:size(A)) => A
+call foo(CP, B, A, 9) ! Shape (rank) differs
+
+AP => A(2:,:)
+call foo(AP, B, A, 10) ! Shape differs
+
+AP => A(:,2:)
+call foo(AP, B, A, 11) ! Shape differs
+
+AP(10:,10:) => A
+call foo(AP, B, A, 12) ! OK - bounds different, shape same
+
+CP => AT(1:-1, 5)
+EP => AT(1:-1, 5) ! Case(i) + case(iv)
+call foo2(CP, EP) ! CP associated - but CP not associated with EP
+contains
+subroutine foo2(p, lpd)
+ implicit none (type, external)
+ real, pointer :: p(..) ! "pointer"
+ real, pointer :: lpd(:) ! array "target"
+ if (.not.associated(p)) stop 18 ! OK - associated
+ if (associated(p, lpd)) stop 19 ! .. but for zero-sized array
+end
+
+subroutine foo(p, lp, lpd, cnt)
+ implicit none (type, external)
+ real, pointer :: p(..) ! "pointer"
+ real, pointer :: lp ! scalar "target"
+ real, pointer :: lpd(:,:) ! array "target"
+ integer, value :: cnt
+
+ if (cnt == 1) then
+ if (.not. associated(p, lpd)) stop 1 ! OK
+ elseif (cnt == 2) then
+ if (.not. associated(p, lp)) stop 2 ! OK
+ elseif (cnt == 3) then
+ if (associated(p, lpd)) stop 3 ! LHS NULL ptr
+ if (associated(p)) stop 4 ! LHS NULL ptr
+ elseif (cnt == 4) then
+ if (associated(p, lp)) stop 5 ! LHS NULL ptr
+ if (associated(p)) stop 6 ! LHS NULL ptr
+ elseif (cnt == 5) then
+ if (associated(p, lpd)) stop 7 ! LHS+RHS NULL ptr
+ if (associated(p)) stop 8 ! LHS+RHS NULL ptr
+ elseif (cnt == 6) then
+ if (associated(p, lp)) stop 9 ! LHS+RHS NULL ptr
+ if (associated(p)) stop 10 ! LHS+RHS NULL ptr
+ elseif (cnt == 7) then
+ if (associated(p, lpd)) stop 11 ! RHS NULL ptr
+ elseif (cnt == 8) then
+ if (associated(p, lp)) stop 12 ! RHS NULL ptr
+ elseif (cnt == 9) then
+ if (associated(p, lpd)) stop 13 ! rank differs
+ if (associated(p, lp)) stop 14 ! rank differs
+ elseif (cnt == 10) then
+ if (associated(p, lpd)) stop 15 ! shape differs
+ elseif (cnt == 11) then
+ if (associated(p, lpd)) stop 16 ! shape differs
+ elseif (cnt == 12) then
+ if (.not.associated(p, lpd)) stop 17 ! OK - shape same, lbound different
+ else
+ stop 99
+ endif
+end
+subroutine test_char()
+ character(len=0), target :: str0
+ character(len=2), target :: str2
+ character(len=:), pointer :: ptr
+ ptr => str0
+ call test_char2(ptr, str0)
+ ptr => str2
+ call test_char2(ptr, str2)
+end
+subroutine test_char2(x,y)
+ character(len=:), pointer :: x
+ character(len=*), target :: y
+ if (len(y) == 0) then
+ if (len(x) /= 0) stop 20
+ if (.not. associated(x)) stop 21
+ if (associated(x, y)) stop 22
+ else
+ if (len(y) /= 2) stop 23
+ if (len(x) /= 2) stop 24
+ if (.not. associated(x)) stop 25
+ if (.not. associated(x, y)) stop 26
+ end if
+end
+end
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_18.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_18.f90
index a8fa3ff..0bc419a 100644
--- a/gcc/testsuite/gfortran.dg/assumed_rank_18.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_18.f90
@@ -7,7 +7,10 @@ program p
contains
subroutine g(x)
real :: x(..)
- call h(x)
+ select rank (x)
+ rank (1)
+ call h(x)
+ end select
end
subroutine h(x)
real :: x(*)
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_22.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_22.f90
new file mode 100644
index 0000000..8be0c10
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_22.f90
@@ -0,0 +1,169 @@
+! { dg-do run }
+! { dg-additional-sources assumed_rank_22_aux.c }
+! { dg-additional-options "-fdump-tree-original" }
+!
+! FIXME: wrong extend in array descriptor, see C file.
+! { dg-output "c_assumed - 40 - OK" { xfail *-*-* } }
+! { dg-output "c_assumed - 100 - OK" { xfail *-*-* } }
+!
+! PR fortran/94070
+!
+! Contributed by Tobias Burnus
+! and José Rui Faustino de Sousa
+!
+program main
+ implicit none
+ integer :: A(5,4,2)
+ integer, allocatable :: B(:,:,:)
+ integer :: C(5,4,-2:-1)
+
+ interface
+ subroutine c_assumed (x, num) bind(C)
+ integer :: x(..)
+ integer, value :: num
+ end subroutine
+ subroutine c_allocated (x) bind(C)
+ integer, allocatable :: x(..)
+ end subroutine
+ end interface
+
+ allocate (B(-1:3,4,-1:-1))
+
+ call caller (a) ! num=0: assumed-size
+ call test (b, num=20) ! full array
+ call test (b(:,:,0:-1), num=40) ! zero-sized array
+ call test (c, num=60)
+ call test (c(:,:,:-1), num=80) ! full-size slice
+ call test (c(:,:,1:-1), num=100) !zero-size array
+
+ call test_alloc(b)
+
+ call c_assumed (b, num=20)
+ call c_assumed (b(:,:,0:-1), num=40)
+ call c_assumed (c, num=60)
+ call c_assumed (c(:,:,:-1), num=80)
+ call c_assumed (c(:,:,1:-1), num=100)
+
+ call c_allocated (b)
+contains
+ subroutine caller(y)
+ integer :: y(-1:3,4,*)
+ call test(y, num=0)
+ call c_assumed (y, num=0)
+ end
+ subroutine test (x, num)
+ integer :: x(..), num
+
+ ! SIZE (x)
+ if (num == 0) then
+ if (size (x) /= -20) stop 1
+ elseif (num == 20) then
+ if (size (x) /= 20) stop 21
+ elseif (num == 40) then
+ if (size (x) /= 0) stop 41
+ elseif (num == 60) then
+ if (size (x) /= 40) stop 61
+ elseif (num == 80) then
+ if (size (x) /= 40) stop 81
+ elseif (num == 100) then
+ if (size (x) /= 0) stop 101
+ else
+ stop 99 ! Invalid num
+ endif
+
+ ! SIZE (x, dim=...)
+ if (size (x, dim=1) /= 5) stop num + 2
+ if (size (x, dim=2) /= 4) stop num + 3
+
+ if (num == 0) then
+ if (size (x, dim=3) /= -1) stop 4
+ elseif (num == 20) then
+ if (size (x, dim=3) /= 1) stop 24
+ elseif (num == 40) then
+ if (size (x, dim=3) /= 0) stop 44
+ elseif (num == 60) then
+ if (size (x, dim=3) /= 2) stop 64
+ elseif (num == 80) then
+ if (size (x, dim=3) /= 2) stop 84
+ elseif (num == 100) then
+ if (size (x, dim=3) /= 0) stop 104
+ endif
+
+ ! SHAPE (x)
+ if (num == 0) then
+ if (any (shape (x) /= [5, 4, -1])) stop 5
+ elseif (num == 20) then
+ if (any (shape (x) /= [5, 4, 1])) stop 25
+ elseif (num == 40) then
+ if (any (shape (x) /= [5, 4, 0])) stop 45
+ elseif (num == 60) then
+ if (any (shape (x) /= [5, 4, 2])) stop 65
+ elseif (num == 80) then
+ if (any (shape (x) /= [5, 4, 2])) stop 85
+ elseif (num == 100) then
+ if (any (shape (x) /= [5, 4, 0])) stop 105
+ endif
+
+ ! LBOUND (X)
+ if (any (lbound (x) /= [1, 1, 1])) stop num + 6
+
+ ! LBOUND (X, dim=...)
+ if (lbound (x, dim=1) /= 1) stop num + 7
+ if (lbound (x, dim=2) /= 1) stop num + 8
+ if (lbound (x, dim=3) /= 1) stop num + 9
+
+ ! UBOUND (X)
+ if (num == 0) then
+ if (any (ubound (x) /= [5, 4, -1])) stop 11
+ elseif (num == 20) then
+ if (any (ubound (x) /= [5, 4, 1])) stop 31
+ elseif (num == 40) then
+ if (any (ubound (x) /= [5, 4, 0])) stop 51
+ elseif (num == 60) then
+ if (any (ubound (x) /= [5, 4, 2])) stop 71
+ elseif (num == 80) then
+ if (any (ubound (x) /= [5, 4, 2])) stop 91
+ elseif (num == 100) then
+ if (any (ubound (x) /= [5, 4, 0])) stop 111
+ endif
+
+ ! UBOUND (X, dim=...)
+ if (ubound (x, dim=1) /= 5) stop num + 12
+ if (ubound (x, dim=2) /= 4) stop num + 13
+ if (num == 0) then
+ if (ubound (x, dim=3) /= -1) stop 14
+ elseif (num == 20) then
+ if (ubound (x, dim=3) /= 1) stop 34
+ elseif (num == 40) then
+ if (ubound (x, dim=3) /= 0) stop 54
+ elseif (num == 60) then
+ if (ubound (x, dim=3) /= 2) stop 74
+ elseif (num == 80) then
+ if (ubound (x, dim=3) /= 2) stop 94
+ elseif (num == 100) then
+ if (ubound (x, dim=3) /= 0) stop 114
+ endif
+ end
+
+ subroutine test_alloc (x)
+ integer, allocatable :: x(..)
+
+ if (size (x) /= 20) stop 61
+ if (size (x, dim=1) /= 5) stop 62
+ if (size (x, dim=2) /= 4) stop 63
+ if (size (x, dim=3) /= 1) stop 64
+
+ if (any (shape (x) /= [5, 4, 1])) stop 65
+
+ if (any (lbound (x) /= [-1, 1, -1])) stop 66
+ if (lbound (x, dim=1) /= -1) stop 77
+ if (lbound (x, dim=2) /= 1) stop 78
+ if (lbound (x, dim=3) /= -1) stop 79
+
+ if (any (ubound (x) /= [3, 4, -1])) stop 80
+ if (ubound (x, dim=1) /= 3) stop 92
+ if (ubound (x, dim=2) /= 4) stop 93
+ if (ubound (x, dim=3) /= -1) stop 94
+ end
+end
+! { dg-final { scan-tree-dump-not "_gfortran_size" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_22_aux.c b/gcc/testsuite/gfortran.dg/assumed_rank_22_aux.c
new file mode 100644
index 0000000..e5fe021
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_22_aux.c
@@ -0,0 +1,68 @@
+/* Called by assumed_rank_22.f90. */
+
+#include <ISO_Fortran_binding.h>
+#include <assert.h>
+
+void
+c_assumed (CFI_cdesc_t *x, int num)
+{
+ assert (num == 0 || num == 20 || num == 40 || num == 60 || num == 80
+ || num == 100);
+ assert (x->elem_len == sizeof (int));
+ assert (x->rank == 3);
+ assert (x->type == CFI_type_int32_t);
+
+ assert (x->attribute == CFI_attribute_other);
+ assert (x->dim[0].lower_bound == 0);
+ assert (x->dim[1].lower_bound == 0);
+ assert (x->dim[2].lower_bound == 0);
+ assert (x->dim[0].extent == 5);
+ assert (x->dim[1].extent == 4);
+ if (num == 0)
+ assert (x->dim[2].extent == -1);
+ else if (num == 20)
+ assert (x->dim[2].extent == 1);
+ else if (num == 40)
+ {
+ /* FIXME: - dg-output = 'c_assumed ... OK' checked in .f90 file. */
+ /* assert (x->dim[2].extent == 0); */
+ if (x->dim[2].extent == 0)
+ __builtin_printf ("c_assumed - 40 - OK\n");
+ else
+ __builtin_printf ("error: c_assumed num=%d: "
+ "x->dim[2].extent = %d != 0\n",
+ num, x->dim[2].extent);
+ }
+ else if (num == 60)
+ assert (x->dim[2].extent == 2);
+ else if (num == 80)
+ assert (x->dim[2].extent == 2);
+ else if (num == 100)
+ {
+ /* FIXME: - dg-output = 'c_assumed ... OK' checked in .f90 file. */
+ /* assert (x->dim[2].extent == 0); */
+ if (x->dim[2].extent == 0)
+ __builtin_printf ("c_assumed - 100 - OK\n");
+ else
+ __builtin_printf ("error: c_assumed num=%d: "
+ "x->dim[2].extent = %d != 0\n",
+ num, x->dim[2].extent);
+ }
+ else
+ assert (0);
+}
+
+void
+c_allocated (CFI_cdesc_t *x)
+{
+ assert (x->elem_len == sizeof (int));
+ assert (x->rank == 3);
+ assert (x->type == CFI_type_int32_t);
+ assert (x->attribute == CFI_attribute_allocatable);
+ assert (x->dim[0].lower_bound == -1);
+ assert (x->dim[1].lower_bound == 1);
+ assert (x->dim[2].lower_bound == -1);
+ assert (x->dim[0].extent == 5);
+ assert (x->dim[1].extent == 4);
+ assert (x->dim[2].extent == 1);
+}
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_23.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_23.f90
new file mode 100644
index 0000000..c83aa7d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_23.f90
@@ -0,0 +1,16 @@
+! { dg-do compile }
+!
+! PR fortran/54753
+! TS29113:C535c
+! F2018:C839
+!
+module m
+
+ interface
+ subroutine s1 (x, y)
+ class(*) :: x(..)
+ class(*), intent (out) :: y(..)
+ end subroutine
+ end interface
+
+end module
diff --git a/gcc/testsuite/gfortran.dg/assumed_type_10.f90 b/gcc/testsuite/gfortran.dg/assumed_type_10.f90
index bf0c873..a8bbf2d 100644
--- a/gcc/testsuite/gfortran.dg/assumed_type_10.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_type_10.f90
@@ -31,7 +31,10 @@ contains
subroutine test_array (a)
use iso_c_binding, only: c_size_t
class(*), dimension(..), target :: a
- call test_lib (a, int (sizeof (a), kind=c_size_t))
+ select rank (a)
+ rank (1)
+ call test_lib (a, int (sizeof (a), kind=c_size_t))
+ end select
end subroutine
end module
diff --git a/gcc/testsuite/gfortran.dg/assumed_type_11.f90 b/gcc/testsuite/gfortran.dg/assumed_type_11.f90
index df6572d..391fa0d 100644
--- a/gcc/testsuite/gfortran.dg/assumed_type_11.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_type_11.f90
@@ -31,7 +31,10 @@ contains
subroutine test_array (a)
use iso_c_binding, only: c_size_t
class(*), dimension(..), target :: a
- call test_lib (a, int (sizeof (a), kind=c_size_t))
+ select rank (a)
+ rank (1)
+ call test_lib (a, int (sizeof (a), kind=c_size_t))
+ end select
end subroutine
end module
diff --git a/gcc/testsuite/gfortran.dg/attr_deprecated-2.f90 b/gcc/testsuite/gfortran.dg/attr_deprecated-2.f90
new file mode 100644
index 0000000..97a365a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/attr_deprecated-2.f90
@@ -0,0 +1,22 @@
+! { dg-do compile }
+! { dg-additional-options "-Wall" }
+!
+! Ensure that only those parameters are warned for which are actually used
+!
+module m
+ implicit none
+ integer, parameter :: parm = 4 ! unused
+ integer, parameter :: parm2 = 4 ! used in the main program
+ integer, parameter :: parm3 = 4 ! used in "f()" - { dg-warning "Using parameter 'parm3' declared at .1. is deprecated" }
+ integer, save :: var, var2
+!GCC$ ATTRIBUTES DEPRECATED :: parm, parm2, parm3, var, var2
+contains
+ subroutine f()
+ print *, parm3 ! warning shown above
+ end
+end module m
+
+use m ! { dg-warning "Using parameter 'parm2' declared at .1. is deprecated" }
+implicit none
+print *, var2, parm2 ! { dg-warning "Using variable 'var2' at .1. is deprecated" }
+end
diff --git a/gcc/testsuite/gfortran.dg/c-interop/assumed-type-dummy.f90 b/gcc/testsuite/gfortran.dg/c-interop/assumed-type-dummy.f90
index a14c9a5..24bdf2b 100644
--- a/gcc/testsuite/gfortran.dg/c-interop/assumed-type-dummy.f90
+++ b/gcc/testsuite/gfortran.dg/c-interop/assumed-type-dummy.f90
@@ -73,7 +73,7 @@ contains
type(t4) :: a4
call s1 (a1) ! OK
- call s1 (a2) ! { dg-error "assumed-type dummy" "pr101319" { xfail *-*-* } }
+ call s1 (a2) ! { dg-error "assumed-type dummy" }
call s1 (a3) ! { dg-error "assumed-type dummy" }
call s1 (a4) ! { dg-error "assumed-type dummy" }
end subroutine
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c407c-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/c407c-1.f90
index e4da66a..c77e6ac 100644
--- a/gcc/testsuite/gfortran.dg/c-interop/c407c-1.f90
+++ b/gcc/testsuite/gfortran.dg/c-interop/c407c-1.f90
@@ -44,7 +44,7 @@ subroutine s2 (x)
implicit none
type(*) :: x(*)
- call g (x, 1) ! { dg-error "Assumed.type" "pr101333" { xfail *-*-* } }
+ call g (x, 1) ! { dg-error "Assumed.type" }
end subroutine
! Check that a scalar gives an error.
@@ -53,7 +53,7 @@ subroutine s3 (x)
implicit none
type(*) :: x
- call g (x, 1) ! { dg-error "Assumed.type" "pr101333" { xfail *-*-* } }
+ call g (x, 1) ! { dg-error "Assumed.type" }
end subroutine
! Explicit-shape assumed-type actual arguments are forbidden implicitly
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c516.f90 b/gcc/testsuite/gfortran.dg/c-interop/c516.f90
index 208eb84..d6a65af 100644
--- a/gcc/testsuite/gfortran.dg/c-interop/c516.f90
+++ b/gcc/testsuite/gfortran.dg/c-interop/c516.f90
@@ -27,6 +27,10 @@ module m2
interface
+ ! First test versions with optional attributes on the argument.
+ ! TS29113 removed the constraint disallowing optional arguments
+ ! that previously used to be in C516.
+
! good, no default initialization, no pointer/allocatable attribute
subroutine s1a (x) bind (c)
use m1
@@ -52,16 +56,54 @@ module m2
end subroutine
! bad, default initialization + allocatable
- subroutine s2b (x) bind (c) ! { dg-error "BIND\\(C\\)" "pr101320" { xfail *-*-* } }
+ subroutine s2b (x) bind (c) ! { dg-error "BIND\\(C\\)" }
use m1
type(t2), allocatable, optional :: x
end subroutine
! bad, default initialization + pointer
- subroutine s2c (x) bind (c) ! { dg-error "BIND\\(C\\)" "pr101320" { xfail *-*-* } }
+ subroutine s2c (x) bind (c) ! { dg-error "BIND\\(C\\)" }
use m1
type(t2), pointer, optional :: x
end subroutine
+ ! Now do all the same tests without the optional attribute.
+
+ ! good, no default initialization, no pointer/allocatable attribute
+ subroutine s3a (x) bind (c)
+ use m1
+ type(t1) :: x
+ end subroutine
+
+ ! good, no default initialization
+ subroutine s3b (x) bind (c)
+ use m1
+ type(t1), allocatable :: x
+ end subroutine
+
+ ! good, no default initialization
+ subroutine s3c (x) bind (c)
+ use m1
+ type(t1), pointer :: x
+ end subroutine
+
+ ! good, default initialization but no pointer/allocatable attribute
+ subroutine s4a (x) bind (c)
+ use m1
+ type(t2) :: x
+ end subroutine
+
+ ! bad, default initialization + allocatable
+ subroutine s4b (x) bind (c) ! { dg-error "BIND\\(C\\)" }
+ use m1
+ type(t2), allocatable :: x
+ end subroutine
+
+ ! bad, default initialization + pointer
+ subroutine s4c (x) bind (c) ! { dg-error "BIND\\(C\\)" }
+ use m1
+ type(t2), pointer :: x
+ end subroutine
+
end interface
end module
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c535b-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/c535b-1.f90
index 3de77b0..748e027 100644
--- a/gcc/testsuite/gfortran.dg/c-interop/c535b-1.f90
+++ b/gcc/testsuite/gfortran.dg/c-interop/c535b-1.f90
@@ -297,8 +297,6 @@ end function
! coshape, lcobound, ucobound: requires CODIMENSION attribute, which is
! not permitted on an assumed-rank variable.
!
-! extends_type_of, same_type_as: require a class argument.
-
! F2018 additionally permits the first arg to C_SIZEOF to be
! assumed-rank (C838).
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c535b-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/c535b-2.f90
index 7bff14f..2dafd44 100644
--- a/gcc/testsuite/gfortran.dg/c-interop/c535b-2.f90
+++ b/gcc/testsuite/gfortran.dg/c-interop/c535b-2.f90
@@ -61,15 +61,14 @@ subroutine test_calls (x, y)
! assumed-rank dummies
call g (x, y) ! OK
! assumed-size dummies
- call h (x, & ! { dg-error "(A|a)ssumed.rank" "pr101334" { xfail *-*-* } }
+ call h (x, & ! { dg-error "(A|a)ssumed.rank" "pr101334" }
y) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
! assumed-shape dummies
call i (x, & ! { dg-error "(A|a)ssumed.rank" }
y) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
! fixed-size array dummies
- call j (x, & ! { dg-error "(A|a)ssumed.rank" "pr101334" { xfail *-*-* } }
+ call j (x, & ! { dg-error "(A|a)ssumed.rank" "pr101334" }
y) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
- ! { dg-bogus "Actual argument contains too few elements" "pr101334" { xfail *-*-* } .-2 }
end subroutine
! Check that you can't use an assumed-rank array variable in an array
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c535b-3.f90 b/gcc/testsuite/gfortran.dg/c-interop/c535b-3.f90
index 6427bd6..23862e5 100644
--- a/gcc/testsuite/gfortran.dg/c-interop/c535b-3.f90
+++ b/gcc/testsuite/gfortran.dg/c-interop/c535b-3.f90
@@ -29,7 +29,7 @@ function test_associated3 (a, b)
integer, target :: b
logical :: test_associated3
- test_associated3 = associated (a, b) ! { dg-bogus "must be of rank -1" "pr101334" { xfail *-*-* } }
+ test_associated3 = associated (a, b) ! { dg-bogus "must be of rank -1" "pr101334" }
end function
function test_associated4 (a, b)
@@ -38,7 +38,7 @@ function test_associated4 (a, b)
integer, target :: b(:)
logical :: test_associated4
- test_associated4 = associated (a, b) ! { dg-bogus "must be of rank -1" "pr101334" { xfail *-*-* } }
+ test_associated4 = associated (a, b) ! { dg-bogus "must be of rank -1" "pr101334" }
end function
function test_associated5 (a, b)
@@ -47,7 +47,7 @@ function test_associated5 (a, b)
integer, target :: b(20)
logical :: test_associated5
- test_associated5 = associated (a, b) ! { dg-bogus "must be of rank -1" "pr101334" { xfail *-*-* } }
+ test_associated5 = associated (a, b) ! { dg-bogus "must be of rank -1" "pr101334" }
end function
function test_associated6 (a, b)
@@ -65,7 +65,7 @@ function test_associated7 (a, b)
integer, pointer :: b
logical :: test_associated7
- test_associated7 = associated (a, b) ! { dg-bogus "must be of rank -1" "pr101334" { xfail *-*-* } }
+ test_associated7 = associated (a, b) ! { dg-bogus "must be of rank -1" "pr101334" }
end function
function test_associated8 (a, b)
@@ -74,6 +74,6 @@ function test_associated8 (a, b)
integer, pointer :: b(:)
logical :: test_associated8
- test_associated8 = associated (a, b) ! { dg-bogus "must be of rank -1" "pr101334" { xfail *-*-* } }
+ test_associated8 = associated (a, b) ! { dg-bogus "must be of rank -1" "pr101334" }
end function
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-5-c.c b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-5-c.c
index 0cd92e7..12464b5 100644
--- a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-5-c.c
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-5-c.c
@@ -1,5 +1,6 @@
#include <stdlib.h>
#include <stdio.h>
+#include <alloca.h>
#include <ISO_Fortran_binding.h>
#include "dump-descriptors.h"
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-6.f90 b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-6.f90
index b1a8c53..bc19a71 100644
--- a/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-6.f90
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-6.f90
@@ -1,5 +1,5 @@
! Reported as pr94070.
-! { dg-do run { xfail *-*-* } }
+! { dg-do run }
! { dg-additional-sources "cf-out-descriptor-6-c.c dump-descriptors.c" }
! { dg-additional-options "-g" }
!
diff --git a/gcc/testsuite/gfortran.dg/c-interop/size.f90 b/gcc/testsuite/gfortran.dg/c-interop/size.f90
index 6c66997..58b32b0 100644
--- a/gcc/testsuite/gfortran.dg/c-interop/size.f90
+++ b/gcc/testsuite/gfortran.dg/c-interop/size.f90
@@ -1,5 +1,5 @@
! Reported as pr94070.
-! { dg-do run { xfail *-*-* } }
+! { dg-do run }
!
! TS 29113
! 6.4.2 SIZE
diff --git a/gcc/testsuite/gfortran.dg/coarray/coarray_allocated.f90 b/gcc/testsuite/gfortran.dg/coarray/coarray_allocated.f90
new file mode 100644
index 0000000..a423d1f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray/coarray_allocated.f90
@@ -0,0 +1,55 @@
+! { dg-do run }
+! { dg-additional-options "-fdump-tree-original" }
+! PR fortran/93834 - ICE in trans_caf_is_present
+
+program p
+ type t
+ integer, allocatable :: x[:,:,:]
+ end type t
+ integer, allocatable :: a[:]
+ type(t) :: c
+ if (allocated (a)) stop 1
+ if (allocated (c%x)) stop 2
+
+ ! The coindexed scalar (!) variable is regarded as allocatable but
+ ! we can check the value on any image of the team as they are
+ ! established collectively. As tested by the dump, we do it on
+ ! this_image ().
+ !
+ ! For this reason, -fcoarray=single and -fcoarray=lib give the
+ ! same result
+ if (allocated (a[1])) stop 3
+ if (allocated (c%x[1,2,3])) stop 4
+
+ ! Allocate collectively
+ allocate(a[*])
+ allocate(c%x[4,10,*])
+
+ if (.not. allocated (a)) stop 5
+ if (.not. allocated (c%x)) stop 6
+ if (.not. allocated (a[1])) stop 7
+ if (.not. allocated (c%x[1,2,3])) stop 8
+
+ ! Dellocate collectively
+ deallocate(a)
+ deallocate(c%x)
+
+ if (allocated (a)) stop 9
+ if (allocated (c%x)) stop 10
+ if (allocated (a[1])) stop 11
+ if (allocated (c%x[1,2,3])) stop 12
+end
+
+! twice == 0 for .not. allocated' (coindexed vs. not)
+! four times != for allocated (before alloc after dealloc, coindexed and not)
+
+! There are also == 0 and != 0 for (de)allocate checks with -fcoarray=single but those
+! aren't prefixed by '(integer(kind=4) *)'
+
+! { dg-final { scan-tree-dump-times "\\(integer\\(kind=4\\) \\*\\) a.data != 0B" 4 "original" } }
+! { dg-final { scan-tree-dump-times "\\(integer\\(kind=4\\) \\*\\) c.x.data != 0B" 4 "original" } }
+! { dg-final { scan-tree-dump-times "\\(integer\\(kind=4\\) \\*\\) a.data == 0B" 2 "original" } }
+! { dg-final { scan-tree-dump-times "\\(integer\\(kind=4\\) \\*\\) c.x.data == 0B" 2 "original" } }
+
+! Expected: always local access and never a call to _gfortran_caf_get
+! { dg-final { scan-tree-dump-not "caf_get" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/order-5.f90 b/gcc/testsuite/gfortran.dg/gomp/order-5.f90
index 4d9e336..0dddb96 100644
--- a/gcc/testsuite/gfortran.dg/gomp/order-5.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/order-5.f90
@@ -116,14 +116,14 @@ subroutine f4 (a)
end do
end
-! { dg-final { scan-tree-dump-times "#pragma omp distribute order\\(concurrent\\)" 6 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp distribute order\\(reproducible:concurrent\\)" 6 "original"} }
! { dg-final { scan-tree-dump-times "#pragma omp distribute order\\(unconstrained:concurrent\\)" 6 "original"} }
-! { dg-final { scan-tree-dump-times "#pragma omp for nowait order\\(concurrent\\)" 6 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp for nowait order\\(reproducible:concurrent\\)" 6 "original"} }
! { dg-final { scan-tree-dump-times "#pragma omp for nowait order\\(unconstrained:concurrent\\)" 6 "original"} }
-! { dg-final { scan-tree-dump-times "#pragma omp for order\\(concurrent\\)" 2 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp for order\\(reproducible:concurrent\\)" 2 "original"} }
! { dg-final { scan-tree-dump-times "#pragma omp for order\\(unconstrained:concurrent\\)" 2 "original"} }
! { dg-final { scan-tree-dump-times "#pragma omp parallel" 12 "original"} }
-! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) order\\(concurrent\\)" 6 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) order\\(reproducible:concurrent\\)" 6 "original"} }
! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) order\\(unconstrained:concurrent\\)" 6 "original"} }
! { dg-final { scan-tree-dump-times "#pragma omp taskloop" 2 "original"} }
! { dg-final { scan-tree-dump-times "#pragma omp teams" 8 "original"} }
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr43711.f90 b/gcc/testsuite/gfortran.dg/gomp/pr43711.f90
index e47e586..d790e3e 100644
--- a/gcc/testsuite/gfortran.dg/gomp/pr43711.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr43711.f90
@@ -11,8 +11,8 @@ program NF03_2_5_2_1a
print *, 'FAIL'
!$omp section
print *, 'FAIL'
- !$omp end sections nowait nowait ! { dg-error "Unexpected junk" }
- !$omp end parallel
-end program NF03_2_5_2_1a
+ !$omp end sections nowait nowait ! { dg-error "Unexpected junk after NOWAIT clause" }
+ !$omp end parallel ! { dg-error "Unexpected !.OMP END PARALLEL statement" }
+end program NF03_2_5_2_1a ! { dg-error "Unexpected END statement" }
-! { dg-excess-errors "Unexpected" }
+! { dg-prune-output "Unexpected end of file" }
diff --git a/gcc/testsuite/gfortran.dg/include_14.f90 b/gcc/testsuite/gfortran.dg/include_14.f90
index b306b2c..8110e49 100644
--- a/gcc/testsuite/gfortran.dg/include_14.f90
+++ b/gcc/testsuite/gfortran.dg/include_14.f90
@@ -1,5 +1,6 @@
-! { dg-additional-options "-cpp -idirafter /fdaf/ -I bar" }
+! { dg-additional-options "-cpp -idirafter /fdaf/ -I bar -J foo/bar" }
end
+! default: warn for -I and -J but ignore other options.
+! { dg-warning "Nonexistent include directory 'bar/'" "" { target *-*-* } 0 }
+! { dg-warning "Nonexistent include directory 'foo/bar/'" "" { target *-*-* } 0 }
-! { dg-warning "/fdaf/: No such file or directory" "" { target *-*-* } 0 }
-! { dg-warning "bar: No such file or directory" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/gfortran.dg/include_15.f90 b/gcc/testsuite/gfortran.dg/include_15.f90
index 4944282..18d91f6 100644
--- a/gcc/testsuite/gfortran.dg/include_15.f90
+++ b/gcc/testsuite/gfortran.dg/include_15.f90
@@ -1,5 +1,9 @@
-! { dg-additional-options "-cpp -idirafter /fdaf/ -I bar -Wmissing-include-dirs" }
+! { dg-additional-options "-cpp -idirafter /fdaf/ -I bar -J foo/bar -Wmissing-include-dirs" }
end
-! { dg-warning "/fdaf/: No such file or directory" "" { target *-*-* } 0 }
-! { dg-warning "bar: No such file or directory" "" { target *-*-* } 0 }
+! { dg-warning " /fdaf/: No such file or directory" "" { target *-*-* } 0 }
+! { dg-warning " bar: No such file or directory" "" { target *-*-* } 0 }
+! { dg-warning " foo/bar: No such file or directory" "" { target *-*-* } 0 }
+
+! Depending how the testsuite is run, it may or may not print the following warning:
+! { dg-prune-output "Warning: finclude: No such file or directory" }
diff --git a/gcc/testsuite/gfortran.dg/include_16.f90 b/gcc/testsuite/gfortran.dg/include_16.f90
index 45794f2..65e4c7e 100644
--- a/gcc/testsuite/gfortran.dg/include_16.f90
+++ b/gcc/testsuite/gfortran.dg/include_16.f90
@@ -1,2 +1,2 @@
-! { dg-additional-options "-cpp -idirafter /fdaf/ -I bar -Wno-missing-include-dirs" }
+! { dg-additional-options "-cpp -idirafter /fdaf/ -I bar -J foo/bar -Wno-missing-include-dirs" }
end
diff --git a/gcc/testsuite/gfortran.dg/include_17.f90 b/gcc/testsuite/gfortran.dg/include_17.f90
index 0ed5c86d..0667759 100644
--- a/gcc/testsuite/gfortran.dg/include_17.f90
+++ b/gcc/testsuite/gfortran.dg/include_17.f90
@@ -1,4 +1,6 @@
! { dg-do compile }
-! { dg-options "-I foo-bar -Wno-missing-include-dirs" }
+! { dg-options "-I foo-bar -J foo/bar" }
end
+! { dg-warning "Nonexistent include directory 'foo-bar/'" "" { target *-*-* } 0 }
+! { dg-warning "Nonexistent include directory 'foo/bar/'" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/gfortran.dg/include_18.f90 b/gcc/testsuite/gfortran.dg/include_18.f90
index ca69df3..b74a585 100644
--- a/gcc/testsuite/gfortran.dg/include_18.f90
+++ b/gcc/testsuite/gfortran.dg/include_18.f90
@@ -1,3 +1,5 @@
! { dg-do compile }
-! { dg-options "-I nothere -Wno-missing-include-dirs" }
+! { dg-options "-I nothere -J neither/here -Wmissing-include-dirs" }
end
+! { dg-warning "Nonexistent include directory 'nothere/'" "" { target *-*-* } 0 }
+! { dg-warning "Nonexistent include directory 'neither/here/'" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/gfortran.dg/include_19.f90 b/gcc/testsuite/gfortran.dg/include_19.f90
index 2a06817..7404929 100644
--- a/gcc/testsuite/gfortran.dg/include_19.f90
+++ b/gcc/testsuite/gfortran.dg/include_19.f90
@@ -1,4 +1,4 @@
! { dg-do compile }
-! { dg-options "-J foobar/foo -Wno-missing-include-dirs" }
+! { dg-options "-I nothere -J foobar/foo -Wno-missing-include-dirs" }
program main
end program main
diff --git a/gcc/testsuite/gfortran.dg/include_23.f90 b/gcc/testsuite/gfortran.dg/include_23.f90
new file mode 100644
index 0000000..421ddda
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/include_23.f90
@@ -0,0 +1,4 @@
+implicit none
+include "nonexisting/file.f90" ! { dg-error "Cannot open included file 'nonexisting/file.f90'" }
+end
+! { dg-prune-output "compilation terminated." }
diff --git a/gcc/testsuite/gfortran.dg/include_24.f90 b/gcc/testsuite/gfortran.dg/include_24.f90
new file mode 100644
index 0000000..1fe9eb5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/include_24.f90
@@ -0,0 +1,4 @@
+implicit none
+include "." ! { dg-error "Included file '.' is not a regular file" }
+end
+! { dg-prune-output "compilation terminated." }
diff --git a/gcc/testsuite/gfortran.dg/include_9.f90 b/gcc/testsuite/gfortran.dg/include_9.f90
index c4ef50f..6b0648b 100644
--- a/gcc/testsuite/gfortran.dg/include_9.f90
+++ b/gcc/testsuite/gfortran.dg/include_9.f90
@@ -4,3 +4,4 @@
program main
end program
! { dg-error "is not a regular file" " " { target *-*-* } 3 }
+! { dg-prune-output "compilation terminated." }
diff --git a/gcc/testsuite/gfortran.dg/intrinsic_size_3.f90 b/gcc/testsuite/gfortran.dg/intrinsic_size_3.f90
index 923cbc3..afdf9b3 100644
--- a/gcc/testsuite/gfortran.dg/intrinsic_size_3.f90
+++ b/gcc/testsuite/gfortran.dg/intrinsic_size_3.f90
@@ -22,4 +22,4 @@ program bug
stop
end program bug
-! { dg-final { scan-tree-dump-times "iszs = \\(integer\\(kind=2\\)\\) MAX_EXPR <\\(D.\[0-9\]+->dim.0..ubound - D.\[0-9\]+->dim.0..lbound\\) \\+ 1, 0>;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "iszs = \\(integer\\(kind=2\\)\\) MAX_EXPR <\\(a.dim.0..ubound - a.dim.0..lbound\\) \\+ 1, 0>;" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/pr102458.f90 b/gcc/testsuite/gfortran.dg/pr102458.f90
new file mode 100644
index 0000000..555e497
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr102458.f90
@@ -0,0 +1,42 @@
+! { dg-do compile }
+! { dg-options "-fcoarray=lib" }
+! PR fortran/102458 - standard intrinsics excluded in constant expressions
+
+subroutine s1
+ integer :: a(command_argument_count()) = 1 ! { dg-error "Automatic array" }
+ print *, a
+end
+
+program p
+ block
+ integer :: a(get_team()) = 1 ! { dg-error "Automatic array" }
+ print *, a
+ end block
+end
+
+subroutine s2
+ integer :: a(num_images()) = 1 ! { dg-error "Automatic array" }
+ print *, a
+end
+
+function f()
+ block
+ integer :: a(team_number()) = 0 ! { dg-error "Automatic array" }
+ a = 1
+ end block
+end
+
+subroutine s3
+ integer :: a(this_image()) = 1 ! { dg-error "Automatic array" }
+ print *, a
+end
+
+subroutine s4
+ integer, parameter :: n = 4
+ integer, parameter :: x(transfer(n, n)) = 1 ! legal
+ integer :: y(transfer(n, n)) = 2 ! legal
+ integer, parameter :: k = size (x) ! ok
+! integer, parameter :: m = size (y) ! fails, tracked separately
+ print *, k, x, y
+ if (k /= size (y)) stop 1
+end
diff --git a/gcc/testsuite/gfortran.dg/pr102458b.f90 b/gcc/testsuite/gfortran.dg/pr102458b.f90
new file mode 100644
index 0000000..3e1026e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr102458b.f90
@@ -0,0 +1,21 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original" }
+! { dg-final { scan-tree-dump-times "_gfortran_stop_numeric" 0 "original" } }
+! PR fortran/102458
+
+subroutine s4
+ integer, parameter :: n = 4
+ integer :: w(transfer(n, n)) = 1
+ integer :: x(transfer(n, n))
+ integer :: y(2*int(n) - n)
+ type t
+ integer :: z(int(n))
+ end type t
+ type(t) :: tt, uu(3)
+ integer, parameter :: i = size (w)
+ integer, parameter :: k = size (x)
+ integer, parameter :: m = size (y)
+ integer, parameter :: j = size (tt% z)
+ integer, parameter :: l = size (uu(2)% z)
+ if (i /= n .or. k /= n .or. m /= n .or. j /= n .or. l /= n) stop 1
+end
diff --git a/gcc/testsuite/gfortran.dg/pr102520.f90 b/gcc/testsuite/gfortran.dg/pr102520.f90
new file mode 100644
index 0000000..1c98c18
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr102520.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! PR fortran/102520 - ICE in expand_constructor, at fortran/array.c:1802
+
+program p
+ type t
+ end type
+ type(t), parameter :: a(4) = shape(1) ! { dg-error "Incompatible" }
+ type(t), parameter :: b(2,2) = reshape(a,[2,2]) ! { dg-error "Incompatible" }
+ type(t), parameter :: c(2,2) = transpose(b) ! { dg-error "Unclassifiable" }
+end
+
+! { dg-error "Different shape for array assignment" " " { target *-*-* } 7 }
diff --git a/gcc/testsuite/gfortran.dg/predict-2.f90 b/gcc/testsuite/gfortran.dg/predict-2.f90
index 11a9ec5..93e3ad6 100644
--- a/gcc/testsuite/gfortran.dg/predict-2.f90
+++ b/gcc/testsuite/gfortran.dg/predict-2.f90
@@ -2,10 +2,10 @@
! { dg-options "-O2 -fdump-tree-profile_estimate" }
subroutine test(block, array)
-integer :: i,j, block(9), array(2)
+integer :: i,j, block(9), array(4)
do i = array(1), array(2), 2
- do j = array(1), array(2), 3
+ do j = array(3), array(4), 3
block(i) = j
end do
end do
diff --git a/gcc/testsuite/gfortran.dg/size_optional_dim_1.f90 b/gcc/testsuite/gfortran.dg/size_optional_dim_1.f90
index c6e8f76..cbf4aa4 100644
--- a/gcc/testsuite/gfortran.dg/size_optional_dim_1.f90
+++ b/gcc/testsuite/gfortran.dg/size_optional_dim_1.f90
@@ -1,4 +1,5 @@
! { dg-do run }
+! { dg-additional-options "-fdump-tree-original" }
! PR 30865 - passing a subroutine optional argument to size(dim=...)
! used to segfault.
program main
@@ -19,3 +20,6 @@ contains
ires = size (a1, dim=opt1)
end subroutine checkv
end program main
+
+! Ensure inline code is generated, cf. PR fortran/94070
+! { dg-final { scan-tree-dump-not "_gfortran_size" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90 b/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90
index c49cd42..54271b1 100644
--- a/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90
+++ b/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90
@@ -60,5 +60,5 @@ end
!
! The check below for temporaries gave 14 and 33 for "parm" and "atmp".
!
-! { dg-final { scan-tree-dump-times "parm" 72 "original" } }
+! { dg-final { scan-tree-dump-times "parm" 76 "original" } }
! { dg-final { scan-tree-dump-times "atmp" 13 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_1.f03 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_1.f03
index afd7522..8634031 100644
--- a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_1.f03
+++ b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_1.f03
@@ -196,16 +196,25 @@ END MODULE
! Check assumed rank calls
- call foobar (u3, 0)
- call foobar (u4, 1)
+ call foobar (u3, 0, is_u3=.true.)
+ call foobar (u4, 1, is_u3=.false.)
contains
- subroutine foobar (arg, ranki)
+ subroutine foobar (arg, ranki, is_u3)
class(*) :: arg (..)
integer :: ranki
+ logical, value :: is_u3
integer i
i = rank (arg)
- if (i .ne. ranki) STOP 1
+ if (i .ne. ranki) STOP 1
+ if (is_u3) then
+ if (EXTENDS_TYPE_OF (arg, obj1) .neqv. .FALSE.) STOP 1
+ else
+ ! arg == u4
+ if (EXTENDS_TYPE_OF (arg, obj1) .neqv. .FALSE.) STOP 1
+ end if
+ ! if (.NOT. SAME_TYPE_AS (arg, u3)) STOP 1
+ ! if (.NOT. SAME_TYPE_AS (arg, u4)) STOP 1
end subroutine
END
diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_32.f90 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_32.f90
new file mode 100644
index 0000000..df57bcd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_32.f90
@@ -0,0 +1,254 @@
+implicit none
+type t2
+ integer :: x
+end type t2
+
+type, extends(t2) :: t2e
+ integer :: y
+end type t2e
+
+type t
+ class(*), allocatable :: au, au2(:,:)
+ class(t2), allocatable :: at, at2(:,:)
+end type t
+
+type(t), target :: var, var0, var2(4), var2a(4)
+class(*), allocatable :: au, au2(:,:)
+class(t2), allocatable :: at, at2(:,:)
+
+
+if (same_type_as (var%au, var%at)) error stop 1
+if (same_type_as (var%au2, var%at)) error stop 2
+if (same_type_as (var%au, var%at)) error stop 3
+! Note: class(*) has no declared type, hence .false.
+if (same_type_as (var%au, var0%au)) error stop 4
+if (same_type_as (var%au2, var0%au2)) error stop 5
+if (same_type_as (var%au, var0%au2)) error stop 6
+call c1(var%au, var%au, var%au2)
+
+if (.not.same_type_as (var%at, var%at)) error stop 7
+if (.not.same_type_as (var%at2, var%at)) error stop 8
+if (.not.same_type_as (var%at, var%at2)) error stop 9
+if (.not.extends_type_of (var%at, var%at)) error stop 10
+if (.not.extends_type_of (var%at2, var%at)) error stop 11
+if (.not.extends_type_of (var%at, var%at2)) error stop 12
+if (same_type_as (var%at, var0%au)) error stop 13
+if (same_type_as (var%at2, var0%au2)) error stop 14
+if (same_type_as (var%at, var0%au2)) error stop 15
+call c2(var%at, var%at, var%at2)
+
+if (same_type_as (au, var%at)) error stop 16
+if (same_type_as (au2, var%at)) error stop 17
+if (same_type_as (au, var%at)) error stop 18
+! Note: class(*) has no declared type, hence .false.
+if (same_type_as (au, var0%au)) error stop 19
+if (same_type_as (au2, var0%au2)) error stop 20
+if (same_type_as (au, var0%au2)) error stop 21
+call c1(au, var%au, var%au2)
+
+if (.not.same_type_as (at, var%at)) error stop 22
+if (.not.same_type_as (at2, var%at)) error stop 23
+if (.not.same_type_as (at, var%at2)) error stop 24
+if (.not.extends_type_of (at, var%at)) error stop 25
+if (.not.extends_type_of (at2, var%at)) error stop 26
+if (.not.extends_type_of (at, var%at2)) error stop 27
+if (same_type_as (at, var0%au)) error stop 28
+if (same_type_as (at2, var0%au2)) error stop 29
+if (same_type_as (at, var0%au2)) error stop 30
+call c2(var%at, var%at, var%at2)
+
+if (same_type_as (var%au, at)) error stop 31
+if (same_type_as (var%au2, at)) error stop 32
+if (same_type_as (var%au, at)) error stop 33
+! Note: class(*) has no declared type, hence .false.
+if (same_type_as (var%au, au)) error stop 34
+if (same_type_as (var%au2, au2)) error stop 35
+if (same_type_as (var%au, au2)) error stop 36
+call c1(var%au, var%au, au2)
+
+if (.not.same_type_as (var%at, at)) error stop 37
+if (.not.same_type_as (var%at2, at)) error stop 38
+if (.not.same_type_as (var%at, at2)) error stop 39
+if (.not.extends_type_of (var%at, at)) error stop 40
+if (.not.extends_type_of (var%at2, at)) error stop 41
+if (.not.extends_type_of (var%at, at2)) error stop 42
+if (same_type_as (var%at, au)) error stop 43
+if (same_type_as (var%at2, au2)) error stop 44
+if (same_type_as (var%at, au2)) error stop 45
+call c2(var%at, var%at, at2)
+
+allocate(t2e :: var0%at, var0%at2(4,4))
+allocate(t2 :: var0%au, var0%au2(4,4))
+
+if (.not.same_type_as (var0%au, var%at)) error stop 46
+if (.not.same_type_as (var0%au2, var%at)) error stop 47
+if (.not.same_type_as (var0%au, var%at)) error stop 48
+if (.not.same_type_as (var0%au, var0%au2)) error stop 49
+if (.not.same_type_as (var0%au2, var0%au2)) error stop 50
+if (.not.same_type_as (var0%au, var0%au2)) error stop 51
+if (.not.extends_type_of (var0%au, var%at)) error stop 52
+if (.not.extends_type_of (var0%au2, var%at)) error stop 53
+if (.not.extends_type_of (var0%au, var%at)) error stop 54
+if (.not.extends_type_of (var0%au, var0%au2)) error stop 55
+if (.not.extends_type_of (var0%au2, var0%au2)) error stop 56
+if (.not.extends_type_of (var0%au, var0%au2)) error stop 57
+
+if (.not.same_type_as (var0%au, at)) error stop 58
+if (.not.same_type_as (var0%au2, at)) error stop 59
+if (.not.same_type_as (var0%au, at2)) error stop 60
+if (.not.extends_type_of (var0%au, at)) error stop 61
+if (.not.extends_type_of (var0%au2, at)) error stop 62
+if (.not.extends_type_of (var0%au, at2)) error stop 63
+
+if (same_type_as (var0%at, var%at)) error stop 64
+if (same_type_as (var0%at2, var%at)) error stop 65
+if (same_type_as (var0%at, var%at)) error stop 66
+if (same_type_as (var0%at, var0%au2)) error stop 67
+if (same_type_as (var0%at2, var0%au2)) error stop 68
+if (same_type_as (var0%at, var0%au2)) error stop 69
+if (.not.extends_type_of (var0%at, var%at)) error stop 70
+if (.not.extends_type_of (var0%at2, var%at)) error stop 71
+if (.not.extends_type_of (var0%at, var%at)) error stop 72
+if (.not.extends_type_of (var0%at, var0%au2)) error stop 73
+if (.not.extends_type_of (var0%at2, var0%au2)) error stop 74
+if (.not.extends_type_of (var0%at, var0%au2)) error stop 75
+
+if (same_type_as (var0%at, at)) error stop 76
+if (same_type_as (var0%at2, at)) error stop 77
+if (same_type_as (var0%at, at2)) error stop 78
+if (.not.extends_type_of (var0%at, at)) error stop 79
+if (.not.extends_type_of (var0%at2, at)) error stop 80
+if (.not.extends_type_of (var0%at, at2)) error stop 81
+
+call c3(var0%au, var0%au2, var0%at, var0%at2)
+call c4(var0%au, var0%au2, var0%at, var0%at2)
+
+contains
+ subroutine c1(x, y, z)
+ class(*) :: x, y(..), z(..)
+ if (same_type_as (x, var0%at)) error stop 82
+ if (same_type_as (y, var0%at)) error stop 83
+ if (same_type_as (z, var0%at)) error stop 84
+ if (same_type_as (x, var%au)) error stop 85
+ if (same_type_as (y, var%au2)) error stop 86
+ if (same_type_as (z, var%au2)) error stop 87
+
+ if (same_type_as (x, at)) error stop 88
+ if (same_type_as (y, at)) error stop 89
+ if (same_type_as (z, at)) error stop 90
+ if (same_type_as (x, au)) error stop 91
+ if (same_type_as (y, au2)) error stop 92
+ if (same_type_as (z, au2)) error stop 93
+ end
+
+ subroutine c2(x, y, z)
+ class(*) :: x, y(..), z(..)
+ if (.not.same_type_as (x, var0%at)) error stop 94
+ if (.not.same_type_as (y, var0%at)) error stop 95
+ if (.not.same_type_as (z, var0%at)) error stop 96
+ if (.not.extends_type_of (x, var0%at)) error stop 97
+ if (.not.extends_type_of (y, var0%at)) error stop 98
+ if (.not.extends_type_of (z, var0%at)) error stop 99
+ if (same_type_as (x, var%au)) error stop 100
+ if (same_type_as (y, var%au2)) error stop 101
+ if (same_type_as (z, var%au2)) error stop 102
+
+ if (.not.same_type_as (x, at)) error stop 103
+ if (.not.same_type_as (y, at)) error stop 104
+ if (.not.same_type_as (z, at)) error stop 105
+ if (.not.extends_type_of (x, at)) error stop 106
+ if (.not.extends_type_of (y, at)) error stop 107
+ if (.not.extends_type_of (z, at)) error stop 108
+ if (same_type_as (x, au)) error stop 109
+ if (same_type_as (y, au2)) error stop 110
+ if (same_type_as (z, au2)) error stop 111
+ end
+
+ subroutine c3(mau, mau2, mat, mat2)
+ class(*) :: mau, mau2(:,:), mat, mat2(:,:)
+
+ if (.not.same_type_as (mau, var%at)) error stop 112
+ if (.not.same_type_as (mau2, var%at)) error stop 113
+ if (.not.same_type_as (mau, var%at)) error stop 114
+ if (.not.same_type_as (mau, var0%au2)) error stop 115
+ if (.not.same_type_as (mau2, var0%au2)) error stop 116
+ if (.not.same_type_as (mau, var0%au2)) error stop 117
+ if (.not.extends_type_of (mau, var%at)) error stop 118
+ if (.not.extends_type_of (mau2, var%at)) error stop 119
+ if (.not.extends_type_of (mau, var%at)) error stop 120
+ if (.not.extends_type_of (mau, var0%au2)) error stop 121
+ if (.not.extends_type_of (mau2, var0%au2)) error stop 122
+ if (.not.extends_type_of (mau, var0%au2)) error stop 123
+
+ if (.not.same_type_as (mau, at)) error stop 124
+ if (.not.same_type_as (mau2, at)) error stop 125
+ if (.not.same_type_as (mau, at2)) error stop 126
+ if (.not.extends_type_of (mau, at)) error stop 127
+ if (.not.extends_type_of (mau2, at)) error stop 128
+ if (.not.extends_type_of (mau, at2)) error stop 129
+
+ if (same_type_as (mat, var%at)) error stop 130
+ if (same_type_as (mat2, var%at)) error stop 131
+ if (same_type_as (mat, var%at)) error stop 132
+ if (same_type_as (mat, var0%au2)) error stop 133
+ if (same_type_as (mat2, var0%au2)) error stop 134
+ if (same_type_as (mat, var0%au2)) error stop 135
+ if (.not.extends_type_of (mat, var%at)) error stop 136
+ if (.not.extends_type_of (mat2, var%at)) error stop 137
+ if (.not.extends_type_of (mat, var%at)) error stop 138
+ if (.not.extends_type_of (mat, var0%au2)) error stop 139
+ if (.not.extends_type_of (mat2, var0%au2)) error stop 140
+ if (.not.extends_type_of (mat, var0%au2)) error stop 141
+
+ if (same_type_as (mat, at)) error stop 142
+ if (same_type_as (mat2, at)) error stop 143
+ if (same_type_as (mat, at2)) error stop 144
+ if (.not.extends_type_of (mat, at)) error stop 145
+ if (.not.extends_type_of (mat2, at)) error stop 147
+ if (.not.extends_type_of (mat, at2)) error stop 148
+ end
+
+ subroutine c4(mau, mau2, mat, mat2)
+ class(*) :: mau(..), mau2(..), mat(..), mat2(..)
+
+ if (.not.same_type_as (mau, var%at)) error stop 149
+ if (.not.same_type_as (mau2, var%at)) error stop 150
+ if (.not.same_type_as (mau, var%at)) error stop 151
+ if (.not.same_type_as (mau, var0%au2)) error stop 152
+ if (.not.same_type_as (mau2, var0%au2)) error stop 153
+ if (.not.same_type_as (mau, var0%au2)) error stop 154
+ if (.not.extends_type_of (mau, var%at)) error stop 155
+ if (.not.extends_type_of (mau2, var%at)) error stop 156
+ if (.not.extends_type_of (mau, var%at)) error stop 157
+ if (.not.extends_type_of (mau, var0%au2)) error stop 158
+ if (.not.extends_type_of (mau2, var0%au2)) error stop 159
+ if (.not.extends_type_of (mau, var0%au2)) error stop 160
+
+ if (.not.same_type_as (mau, at)) error stop 161
+ if (.not.same_type_as (mau2, at)) error stop 162
+ if (.not.same_type_as (mau, at2)) error stop 163
+ if (.not.extends_type_of (mau, at)) error stop 164
+ if (.not.extends_type_of (mau2, at)) error stop 165
+ if (.not.extends_type_of (mau, at2)) error stop 166
+
+ if (same_type_as (mat, var%at)) error stop 167
+ if (same_type_as (mat2, var%at)) error stop 168
+ if (same_type_as (mat, var%at)) error stop 169
+ if (same_type_as (mat, var0%au2)) error stop 170
+ if (same_type_as (mat2, var0%au2)) error stop 171
+ if (same_type_as (mat, var0%au2)) error stop 172
+ if (.not.extends_type_of (mat, var%at)) error stop 173
+ if (.not.extends_type_of (mat2, var%at)) error stop 174
+ if (.not.extends_type_of (mat, var%at)) error stop 175
+ if (.not.extends_type_of (mat, var0%au2)) error stop 176
+ if (.not.extends_type_of (mat2, var0%au2)) error stop 178
+ if (.not.extends_type_of (mat, var0%au2)) error stop 179
+
+ if (same_type_as (mat, at)) error stop 180
+ if (same_type_as (mat2, at)) error stop 181
+ if (same_type_as (mat, at2)) error stop 182
+ if (.not.extends_type_of (mat, at)) error stop 183
+ if (.not.extends_type_of (mat2, at)) error stop 184
+ if (.not.extends_type_of (mat, at2)) error stop 185
+ end
+end
diff --git a/gcc/timevar.def b/gcc/timevar.def
index 16d1657..f903833 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -158,6 +158,7 @@ DEFTIMEVAR (TV_TREE_CFG , "tree CFG construction")
DEFTIMEVAR (TV_TREE_CLEANUP_CFG , "tree CFG cleanup")
DEFTIMEVAR (TV_TREE_TAIL_MERGE , "tree tail merge")
DEFTIMEVAR (TV_TREE_VRP , "tree VRP")
+DEFTIMEVAR (TV_TREE_VRP_THREADER , "tree VRP threader")
DEFTIMEVAR (TV_TREE_EARLY_VRP , "tree Early VRP")
DEFTIMEVAR (TV_TREE_COPY_PROP , "tree copy propagation")
DEFTIMEVAR (TV_FIND_REFERENCED_VARS , "tree find ref. vars")
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 14d1335..1bb1794 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -104,8 +104,6 @@ along with GCC; see the file COPYING3. If not see
#endif
static void general_init (const char *, bool);
-static void do_compile ();
-static void process_options (void);
static void backend_init (void);
static int lang_dependent_init (const char *);
static void init_asm_output (const char *);
@@ -114,13 +112,13 @@ static void finalize (bool);
static void crash_signal (int) ATTRIBUTE_NORETURN;
static void compile_file (void);
-/* True if we don't need a backend (e.g. preprocessing only). */
-static bool no_backend;
-
/* Decoded options, and number of such options. */
struct cl_decoded_option *save_decoded_options;
unsigned int save_decoded_options_count;
+/* Vector of saved Optimization decoded command line options. */
+vec<cl_decoded_option> *save_opt_decoded_options;
+
/* Used to enable -fvar-tracking, -fweb and -frename-registers according
to optimize in process_options (). */
#define AUTODETECT_VALUE 2
@@ -1230,7 +1228,7 @@ parse_alignment_opts (void)
/* Process the options that have been parsed. */
static void
-process_options (void)
+process_options (bool no_backend)
{
const char *language_string = lang_hooks.name;
/* Just in case lang_hooks.post_options ends up calling a debug_hook.
@@ -1239,12 +1237,6 @@ process_options (void)
maximum_field_alignment = initial_max_fld_align * BITS_PER_UNIT;
- /* Allow the front end to perform consistency checks and do further
- initialization based on the command line options. This hook also
- sets the original filename if appropriate (e.g. foo.i -> foo.c)
- so we can correctly initialize debug output. */
- no_backend = lang_hooks.post_options (&main_input_filename);
-
/* Some machines may reject certain combinations of options. */
location_t saved_location = input_location;
input_location = UNKNOWN_LOCATION;
@@ -1416,14 +1408,16 @@ process_options (void)
debug_info_level = DINFO_LEVEL_NONE;
}
- /* CTF is supported for only C at this time.
- Compiling with -flto results in frontend language of GNU GIMPLE. */
+ /* CTF is supported for only C at this time. */
if (!lang_GNU_C ()
&& ctf_debug_info_level > CTFINFO_LEVEL_NONE)
{
- inform (UNKNOWN_LOCATION,
- "CTF debug info requested, but not supported for %qs frontend",
- language_string);
+ /* Compiling with -flto results in frontend language of GNU GIMPLE. It
+ is not useful to warn in that case. */
+ if (!startswith (lang_hooks.name, "GNU GIMPLE"))
+ inform (UNKNOWN_LOCATION,
+ "CTF debug info requested, but not supported for %qs frontend",
+ language_string);
ctf_debug_info_level = CTFINFO_LEVEL_NONE;
}
@@ -1695,14 +1689,6 @@ process_options (void)
flag_stack_check = NO_STACK_CHECK;
}
- /* With -fcx-limited-range, we do cheap and quick complex arithmetic. */
- if (flag_cx_limited_range)
- flag_complex_method = 0;
-
- /* With -fcx-fortran-rules, we do something in-between cheap and C99. */
- if (flag_cx_fortran_rules)
- flag_complex_method = 1;
-
/* Targets must be able to place spill slots at lower addresses. If the
target already uses a soft frame pointer, the transition is trivial. */
if (!FRAME_GROWS_DOWNWARD && flag_stack_protect)
@@ -2150,10 +2136,8 @@ standard_type_bitsize (int bitsize)
/* Initialize the compiler, and compile the input file. */
static void
-do_compile ()
+do_compile (bool no_backend)
{
- process_options ();
-
/* Don't do any more if an error has already occurred. */
if (!seen_error ())
{
@@ -2282,11 +2266,6 @@ toplev::start_timevars ()
void
toplev::run_self_tests ()
{
- if (no_backend)
- {
- error_at (UNKNOWN_LOCATION, "self-tests incompatible with %<-E%>");
- return;
- }
#if CHECKING_P
/* Reset some state. */
input_location = UNKNOWN_LOCATION;
@@ -2342,6 +2321,13 @@ toplev::main (int argc, char **argv)
&save_decoded_options,
&save_decoded_options_count);
+ /* Save Optimization decoded options. */
+ save_opt_decoded_options = new vec<cl_decoded_option> ();
+ for (unsigned i = 1; i < save_decoded_options_count; ++i)
+ if (save_decoded_options[i].opt_index < cl_options_count
+ && cl_options[save_decoded_options[i].opt_index].flags & CL_OPTIMIZATION)
+ save_opt_decoded_options->safe_push (save_decoded_options[i]);
+
/* Perform language-specific options initialization. */
lang_hooks.init_options (save_decoded_options_count, save_decoded_options);
@@ -2367,17 +2353,30 @@ toplev::main (int argc, char **argv)
/* Exit early if we can (e.g. -help). */
if (!exit_after_options)
{
+ /* Allow the front end to perform consistency checks and do further
+ initialization based on the command line options. This hook also
+ sets the original filename if appropriate (e.g. foo.i -> foo.c)
+ so we can correctly initialize debug output. */
+ bool no_backend = lang_hooks.post_options (&main_input_filename);
+
+ process_options (no_backend);
+
if (m_use_TV_TOTAL)
start_timevars ();
- do_compile ();
+ do_compile (no_backend);
+
+ if (flag_self_test)
+ {
+ if (no_backend)
+ error_at (UNKNOWN_LOCATION, "self-tests incompatible with %<-E%>");
+ else
+ run_self_tests ();
+ }
}
if (warningcount || errorcount || werrorcount)
print_ignored_options ();
- if (flag_self_test)
- run_self_tests ();
-
/* Invoke registered plugin callbacks if any. Some plugins could
emit some diagnostics here. */
invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
diff --git a/gcc/toplev.h b/gcc/toplev.h
index f543554..493f7eb 100644
--- a/gcc/toplev.h
+++ b/gcc/toplev.h
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
/* Decoded options, and number of such options. */
extern struct cl_decoded_option *save_decoded_options;
extern unsigned int save_decoded_options_count;
+extern vec<cl_decoded_option> *save_opt_decoded_options;
class timer;
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 367dcfa..4b4b0b5 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -8127,14 +8127,22 @@ dump_function_to_file (tree fndecl, FILE *file, dump_flags_t flags)
fprintf (file, ",%s(%" PRIu64 ")",
profile_quality_as_string (bb->count.quality ()),
bb->count.value ());
- fprintf (file, ")\n%s (", function_name (fun));
+ if (dump_flags & TDF_UID)
+ fprintf (file, ")\n%sD_%u (", function_name (fun),
+ DECL_UID (fndecl));
+ else
+ fprintf (file, ")\n%s (", function_name (fun));
}
}
else
{
print_generic_expr (file, TREE_TYPE (fntype), dump_flags);
- fprintf (file, " %s %s(", function_name (fun),
- tmclone ? "[tm-clone] " : "");
+ if (dump_flags & TDF_UID)
+ fprintf (file, " %sD.%u %s(", function_name (fun), DECL_UID (fndecl),
+ tmclone ? "[tm-clone] " : "");
+ else
+ fprintf (file, " %s %s(", function_name (fun),
+ tmclone ? "[tm-clone] " : "");
}
arg = DECL_ARGUMENTS (fndecl);
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 5e50e80..e292a14 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3490,7 +3490,11 @@ setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn,
/* We may produce non-gimple trees by adding NOPs or introduce invalid
sharing when the value is not constant or DECL. And we need to make
sure that it cannot be modified from another path in the callee. */
- if ((is_gimple_min_invariant (value)
+ if (((is_gimple_min_invariant (value)
+ /* When the parameter is used in a context that forces it to
+ not be a GIMPLE register avoid substituting something that
+ is not a decl there. */
+ && ! DECL_NOT_GIMPLE_REG_P (p))
|| (DECL_P (value) && TREE_READONLY (value))
|| (auto_var_in_fn_p (value, id->dst_fn)
&& !TREE_ADDRESSABLE (value)))
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index 744748d..6a4dc72 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -54,8 +54,7 @@ static const unsigned HOST_WIDE_INT unknown[4] = {
static tree compute_object_offset (const_tree, const_tree);
static bool addr_object_size (struct object_size_info *,
- const_tree, int, unsigned HOST_WIDE_INT *,
- tree * = NULL, tree * = NULL);
+ const_tree, int, unsigned HOST_WIDE_INT *);
static unsigned HOST_WIDE_INT alloc_object_size (const gcall *, int);
static tree pass_through_call (const gcall *);
static void collect_object_sizes_for (struct object_size_info *, tree);
@@ -209,17 +208,10 @@ decl_init_size (tree decl, bool min)
static bool
addr_object_size (struct object_size_info *osi, const_tree ptr,
- int object_size_type, unsigned HOST_WIDE_INT *psize,
- tree *pdecl /* = NULL */, tree *poff /* = NULL */)
+ int object_size_type, unsigned HOST_WIDE_INT *psize)
{
tree pt_var, pt_var_size = NULL_TREE, var_size, bytes;
- tree dummy_decl, dummy_off = size_zero_node;
- if (!pdecl)
- pdecl = &dummy_decl;
- if (!poff)
- poff = &dummy_off;
-
gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
/* Set to unknown and overwrite just before returning if the size
@@ -241,7 +233,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
|| TREE_CODE (TREE_OPERAND (pt_var, 0)) != SSA_NAME)
{
compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
- object_size_type & ~1, &sz, pdecl, poff);
+ object_size_type & ~1, &sz);
}
else
{
@@ -259,11 +251,6 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
offset_int mem_offset;
if (mem_ref_offset (pt_var).is_constant (&mem_offset))
{
- if (*poff)
- *poff = wide_int_to_tree (ptrdiff_type_node,
- mem_offset + wi::to_offset (*poff));
- else
- *poff = wide_int_to_tree (ptrdiff_type_node, mem_offset);
offset_int dsz = wi::sub (sz, mem_offset);
if (wi::neg_p (dsz))
sz = 0;
@@ -281,7 +268,6 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
}
else if (DECL_P (pt_var))
{
- *pdecl = pt_var;
pt_var_size = decl_init_size (pt_var, object_size_type & 2);
if (!pt_var_size)
return false;
@@ -418,7 +404,6 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
if (bytes != error_mark_node)
{
- *poff = bytes;
if (TREE_CODE (bytes) == INTEGER_CST
&& tree_int_cst_lt (var_size, bytes))
bytes = size_zero_node;
@@ -438,7 +423,6 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
bytes2 = size_zero_node;
else
bytes2 = size_binop (MINUS_EXPR, pt_var_size, bytes2);
- *poff = size_binop (PLUS_EXPR, *poff, bytes2);
bytes = size_binop (MIN_EXPR, bytes, bytes2);
}
}
@@ -446,11 +430,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
else if (!pt_var_size)
return false;
else
- {
- bytes = pt_var_size;
- if (!*poff)
- *poff = size_zero_node;
- }
+ bytes = pt_var_size;
if (tree_fits_uhwi_p (bytes))
{
@@ -548,17 +528,10 @@ pass_through_call (const gcall *call)
bool
compute_builtin_object_size (tree ptr, int object_size_type,
- unsigned HOST_WIDE_INT *psize,
- tree *pdecl /* = NULL */, tree *poff /* = NULL */)
+ unsigned HOST_WIDE_INT *psize)
{
gcc_assert (object_size_type >= 0 && object_size_type <= 3);
- tree dummy_decl, dummy_off = size_zero_node;
- if (!pdecl)
- pdecl = &dummy_decl;
- if (!poff)
- poff = &dummy_off;
-
/* Set to unknown and overwrite just before returning if the size
could be determined. */
*psize = unknown[object_size_type];
@@ -567,7 +540,7 @@ compute_builtin_object_size (tree ptr, int object_size_type,
init_offset_limit ();
if (TREE_CODE (ptr) == ADDR_EXPR)
- return addr_object_size (NULL, ptr, object_size_type, psize, pdecl, poff);
+ return addr_object_size (NULL, ptr, object_size_type, psize);
if (TREE_CODE (ptr) != SSA_NAME
|| !POINTER_TYPE_P (TREE_TYPE (ptr)))
@@ -592,12 +565,11 @@ compute_builtin_object_size (tree ptr, int object_size_type,
if (tree_fits_shwi_p (offset)
&& compute_builtin_object_size (ptr, object_size_type,
- psize, pdecl, poff))
+ psize))
{
/* Return zero when the offset is out of bounds. */
unsigned HOST_WIDE_INT off = tree_to_shwi (offset);
*psize = off < *psize ? *psize - off : 0;
- *poff = offset;
return true;
}
}
diff --git a/gcc/tree-object-size.h b/gcc/tree-object-size.h
index 358b902..ef18aea 100644
--- a/gcc/tree-object-size.h
+++ b/gcc/tree-object-size.h
@@ -22,8 +22,7 @@ along with GCC; see the file COPYING3. If not see
extern void init_object_sizes (void);
extern void fini_object_sizes (void);
-extern bool compute_builtin_object_size (tree, int, unsigned HOST_WIDE_INT *,
- tree * = NULL, tree * = NULL);
+extern bool compute_builtin_object_size (tree, int, unsigned HOST_WIDE_INT *);
extern tree decl_init_size (tree, bool);
#endif // GCC_TREE_OBJECT_SIZE_H
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index eb75eb1..84477a4 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -462,6 +462,7 @@ extern gimple_opt_pass *make_pass_copy_prop (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_isolate_erroneous_paths (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_early_vrp (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_vrp (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_vrp_threader (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_uncprop (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_return_slot (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_reassoc (gcc::context *ctxt);
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 7de12f3..275dc7d 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -344,7 +344,16 @@ dump_function_name (pretty_printer *pp, tree node, dump_flags_t flags)
if (CONVERT_EXPR_P (node))
node = TREE_OPERAND (node, 0);
if (DECL_NAME (node) && (flags & TDF_ASMNAME) == 0)
- pp_string (pp, lang_hooks.decl_printable_name (node, 1));
+ {
+ pp_string (pp, lang_hooks.decl_printable_name (node, 1));
+ if (flags & TDF_UID)
+ {
+ char uid_sep = (flags & TDF_GIMPLE) ? '_' : '.';
+ pp_character (pp, 'D');
+ pp_character (pp, uid_sep);
+ pp_scalar (pp, "%u", DECL_UID (node));
+ }
+ }
else
dump_decl_name (pp, node, flags);
}
@@ -735,10 +744,23 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
pp_string (pp, "allocate(");
if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause))
{
+ pp_string (pp, "allocator(");
dump_generic_node (pp, OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause),
spc, flags, false);
- pp_colon (pp);
+ pp_right_paren (pp);
+ }
+ if (OMP_CLAUSE_ALLOCATE_ALIGN (clause))
+ {
+ if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause))
+ pp_comma (pp);
+ pp_string (pp, "align(");
+ dump_generic_node (pp, OMP_CLAUSE_ALLOCATE_ALIGN (clause),
+ spc, flags, false);
+ pp_right_paren (pp);
}
+ if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause)
+ || OMP_CLAUSE_ALLOCATE_ALIGN (clause))
+ pp_colon (pp);
dump_generic_node (pp, OMP_CLAUSE_DECL (clause),
spc, flags, false);
pp_right_paren (pp);
@@ -1152,6 +1174,8 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
pp_string (pp, "order(");
if (OMP_CLAUSE_ORDER_UNCONSTRAINED (clause))
pp_string (pp, "unconstrained:");
+ else if (OMP_CLAUSE_ORDER_REPRODUCIBLE (clause))
+ pp_string (pp, "reproducible:");
pp_string (pp, "concurrent)");
break;
@@ -2849,17 +2873,28 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
break;
/* Unary arithmetic and logic expressions. */
+ case ADDR_EXPR:
+ if (flags & TDF_GIMPLE_VAL)
+ {
+ pp_string (pp, "_Literal (");
+ dump_generic_node (pp, TREE_TYPE (node), spc,
+ flags & ~TDF_GIMPLE_VAL, false);
+ pp_character (pp, ')');
+ }
+ /* Fallthru. */
case NEGATE_EXPR:
case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR:
- case ADDR_EXPR:
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case INDIRECT_REF:
- if (TREE_CODE (node) == ADDR_EXPR
+ if (!(flags & TDF_GIMPLE)
+ && TREE_CODE (node) == ADDR_EXPR
&& (TREE_CODE (TREE_OPERAND (node, 0)) == STRING_CST
|| TREE_CODE (TREE_OPERAND (node, 0)) == FUNCTION_DECL))
- ; /* Do not output '&' for strings and function pointers. */
+ /* Do not output '&' for strings and function pointers when not
+ dumping GIMPLE FE syntax. */
+ ;
else
pp_string (pp, op_symbol (node));
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 49d8f96..a8a5b34 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -585,31 +585,137 @@ record_edge_info (basic_block bb)
}
}
-class dom_jump_threader_simplifier : public jump_threader_simplifier
+class dom_jt_state : public jt_state
{
public:
- dom_jump_threader_simplifier (vr_values *v,
- avail_exprs_stack *avails)
- : jump_threader_simplifier (v), m_avail_exprs_stack (avails) { }
+ dom_jt_state (const_and_copies *copies, avail_exprs_stack *avails,
+ evrp_range_analyzer *evrp)
+ : m_copies (copies), m_avails (avails), m_evrp (evrp)
+ {
+ }
+ void push (edge e) override
+ {
+ m_copies->push_marker ();
+ m_avails->push_marker ();
+ m_evrp->push_marker ();
+ jt_state::push (e);
+ }
+ void pop () override
+ {
+ m_copies->pop_to_marker ();
+ m_avails->pop_to_marker ();
+ m_evrp->pop_to_marker ();
+ jt_state::pop ();
+ }
+ void register_equivs_edge (edge e) override
+ {
+ record_temporary_equivalences (e, m_copies, m_avails);
+ }
+ void record_ranges_from_stmt (gimple *stmt, bool temporary) override
+ {
+ m_evrp->record_ranges_from_stmt (stmt, temporary);
+ }
+ void register_equiv (tree dest, tree src, bool update) override;
+private:
+ const_and_copies *m_copies;
+ avail_exprs_stack *m_avails;
+ evrp_range_analyzer *m_evrp;
+};
+
+void
+dom_jt_state::register_equiv (tree dest, tree src, bool update)
+{
+ m_copies->record_const_or_copy (dest, src);
+
+ /* If requested, update the value range associated with DST, using
+ the range from SRC. */
+ if (update)
+ {
+ /* Get new VR we can pass to push_value_range. */
+ value_range_equiv *new_vr = m_evrp->allocate_value_range_equiv ();
+ new (new_vr) value_range_equiv ();
+
+ /* There are three cases to consider:
+
+ First if SRC is an SSA_NAME, then we can copy the value range
+ from SRC into NEW_VR.
+
+ Second if SRC is an INTEGER_CST, then we can just set NEW_VR
+ to a singleton range. Note that even if SRC is a constant we
+ need to set a suitable output range so that VR_UNDEFINED
+ ranges do not leak through.
+
+ Otherwise set NEW_VR to varying. This may be overly
+ conservative. */
+ if (TREE_CODE (src) == SSA_NAME)
+ new_vr->deep_copy (m_evrp->get_value_range (src));
+ else if (TREE_CODE (src) == INTEGER_CST)
+ new_vr->set (src);
+ else
+ new_vr->set_varying (TREE_TYPE (src));
+
+ /* This is a temporary range for DST, so push it. */
+ m_evrp->push_value_range (dest, new_vr);
+ }
+}
+
+class dom_jt_simplifier : public jt_simplifier
+{
+public:
+ dom_jt_simplifier (vr_values *v, avail_exprs_stack *avails)
+ : m_vr_values (v), m_avails (avails) { }
private:
tree simplify (gimple *, gimple *, basic_block, jt_state *) override;
- avail_exprs_stack *m_avail_exprs_stack;
+ vr_values *m_vr_values;
+ avail_exprs_stack *m_avails;
};
tree
-dom_jump_threader_simplifier::simplify (gimple *stmt,
- gimple *within_stmt,
- basic_block bb,
- jt_state *state)
+dom_jt_simplifier::simplify (gimple *stmt, gimple *within_stmt,
+ basic_block, jt_state *)
{
/* First see if the conditional is in the hash table. */
- tree cached_lhs = m_avail_exprs_stack->lookup_avail_expr (stmt,
- false, true);
+ tree cached_lhs = m_avails->lookup_avail_expr (stmt, false, true);
if (cached_lhs)
return cached_lhs;
- return jump_threader_simplifier::simplify (stmt, within_stmt, bb, state);
+ if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
+ {
+ simplify_using_ranges simplifier (m_vr_values);
+ return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
+ gimple_cond_lhs (cond_stmt),
+ gimple_cond_rhs (cond_stmt),
+ within_stmt);
+ }
+ if (gswitch *switch_stmt = dyn_cast <gswitch *> (stmt))
+ {
+ tree op = gimple_switch_index (switch_stmt);
+ if (TREE_CODE (op) != SSA_NAME)
+ return NULL_TREE;
+
+ const value_range_equiv *vr = m_vr_values->get_value_range (op);
+ return find_case_label_range (switch_stmt, vr);
+ }
+ if (gassign *assign_stmt = dyn_cast <gassign *> (stmt))
+ {
+ tree lhs = gimple_assign_lhs (assign_stmt);
+ if (TREE_CODE (lhs) == SSA_NAME
+ && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+ || POINTER_TYPE_P (TREE_TYPE (lhs)))
+ && stmt_interesting_for_vrp (stmt))
+ {
+ edge dummy_e;
+ tree dummy_tree;
+ value_range_equiv new_vr;
+ m_vr_values->extract_range_from_stmt (stmt, &dummy_e, &dummy_tree,
+ &new_vr);
+ tree singleton;
+ if (new_vr.singleton_p (&singleton))
+ return singleton;
+ }
+ }
+ return NULL;
}
class dom_opt_dom_walker : public dom_walker
@@ -752,8 +858,8 @@ pass_dominator::execute (function *fun)
/* Recursively walk the dominator tree optimizing statements. */
evrp_range_analyzer analyzer (true);
- dom_jump_threader_simplifier simplifier (&analyzer, avail_exprs_stack);
- jt_state state (const_and_copies, avail_exprs_stack, &analyzer);
+ dom_jt_simplifier simplifier (&analyzer, avail_exprs_stack);
+ dom_jt_state state (const_and_copies, avail_exprs_stack, &analyzer);
jump_threader threader (&simplifier, &state);
dom_opt_dom_walker walker (CDI_DOMINATORS,
&threader,
@@ -1704,7 +1810,7 @@ record_equivalences_from_stmt (gimple *stmt, int may_optimize_p,
CONST_AND_COPIES. */
static void
-cprop_operand (gimple *stmt, use_operand_p op_p, vr_values *vr_values)
+cprop_operand (gimple *stmt, use_operand_p op_p, range_query *query)
{
tree val;
tree op = USE_FROM_PTR (op_p);
@@ -1714,7 +1820,12 @@ cprop_operand (gimple *stmt, use_operand_p op_p, vr_values *vr_values)
CONST_AND_COPIES. */
val = SSA_NAME_VALUE (op);
if (!val)
- val = vr_values->op_with_constant_singleton_value_range (op);
+ {
+ value_range r;
+ tree single;
+ if (query->range_of_expr (r, op, stmt) && r.singleton_p (&single))
+ val = single;
+ }
if (val && val != op)
{
@@ -1772,7 +1883,7 @@ cprop_operand (gimple *stmt, use_operand_p op_p, vr_values *vr_values)
vdef_ops of STMT. */
static void
-cprop_into_stmt (gimple *stmt, vr_values *vr_values)
+cprop_into_stmt (gimple *stmt, range_query *query)
{
use_operand_p op_p;
ssa_op_iter iter;
@@ -1789,7 +1900,7 @@ cprop_into_stmt (gimple *stmt, vr_values *vr_values)
operands. */
if (old_op != last_copy_propagated_op)
{
- cprop_operand (stmt, op_p, vr_values);
+ cprop_operand (stmt, op_p, query);
tree new_op = USE_FROM_PTR (op_p);
if (new_op != old_op && TREE_CODE (new_op) == SSA_NAME)
@@ -2097,8 +2208,8 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator *si,
SSA_NAMES. */
update_stmt_if_modified (stmt);
edge taken_edge = NULL;
- m_evrp_range_analyzer->vrp_visit_cond_stmt
- (as_a <gcond *> (stmt), &taken_edge);
+ simplify_using_ranges simpl (m_evrp_range_analyzer);
+ simpl.vrp_visit_cond_stmt (as_a <gcond *> (stmt), &taken_edge);
if (taken_edge)
{
if (taken_edge->flags & EDGE_TRUE_VALUE)
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c
index 98daa8a..27287fe 100644
--- a/gcc/tree-ssa-dse.c
+++ b/gcc/tree-ssa-dse.c
@@ -978,6 +978,7 @@ delete_dead_or_redundant_call (gimple_stmt_iterator *gsi, const char *type)
fprintf (dump_file, "\n");
}
+ basic_block bb = gimple_bb (stmt);
tree lhs = gimple_call_lhs (stmt);
if (lhs)
{
@@ -985,7 +986,7 @@ delete_dead_or_redundant_call (gimple_stmt_iterator *gsi, const char *type)
gimple *new_stmt = gimple_build_assign (lhs, ptr);
unlink_stmt_vdef (stmt);
if (gsi_replace (gsi, new_stmt, true))
- bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index);
+ bitmap_set_bit (need_eh_cleanup, bb->index);
}
else
{
@@ -994,7 +995,7 @@ delete_dead_or_redundant_call (gimple_stmt_iterator *gsi, const char *type)
/* Remove the dead store. */
if (gsi_remove (gsi, true))
- bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index);
+ bitmap_set_bit (need_eh_cleanup, bb->index);
release_defs (stmt);
}
}
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 7af92d1..7510940 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -1482,7 +1482,7 @@ number_of_iterations_until_wrap (class loop *, tree type, affine_iv *iv0,
affine_iv *iv1, class tree_niter_desc *niter)
{
tree niter_type = unsigned_type_for (type);
- tree step, num, assumptions, may_be_zero;
+ tree step, num, assumptions, may_be_zero, span;
wide_int high, low, max, min;
may_be_zero = fold_build2 (LE_EXPR, boolean_type_node, iv1->base, iv0->base);
@@ -1557,6 +1557,20 @@ number_of_iterations_until_wrap (class loop *, tree type, affine_iv *iv0,
niter->control.no_overflow = false;
+ /* Update bound and exit condition as:
+ bound = niter * STEP + (IVbase - STEP).
+ { IVbase - STEP, +, STEP } != bound
+ Here, biasing IVbase by 1 step makes 'bound' be the value before wrap.
+ */
+ niter->control.base = fold_build2 (MINUS_EXPR, niter_type,
+ niter->control.base, niter->control.step);
+ span = fold_build2 (MULT_EXPR, niter_type, niter->niter,
+ fold_convert (niter_type, niter->control.step));
+ niter->bound = fold_build2 (PLUS_EXPR, niter_type, span,
+ fold_convert (niter_type, niter->control.base));
+ niter->bound = fold_convert (type, niter->bound);
+ niter->cmp = NE_EXPR;
+
return true;
}
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 0875584..1cc1aae 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -2855,9 +2855,13 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
unsigned int operand = 1;
vn_reference_op_t currop = &ref->operands[0];
tree sc = NULL_TREE;
- tree fn = find_or_generate_expression (block, currop->op0, stmts);
- if (!fn)
- return NULL_TREE;
+ tree fn = NULL_TREE;
+ if (currop->op0)
+ {
+ fn = find_or_generate_expression (block, currop->op0, stmts);
+ if (!fn)
+ return NULL_TREE;
+ }
if (currop->op1)
{
sc = find_or_generate_expression (block, currop->op1, stmts);
@@ -2873,12 +2877,19 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
return NULL_TREE;
args.quick_push (arg);
}
- gcall *call = gimple_build_call_vec (fn, args);
+ gcall *call;
+ if (currop->op0)
+ {
+ call = gimple_build_call_vec (fn, args);
+ gimple_call_set_fntype (call, currop->type);
+ }
+ else
+ call = gimple_build_call_internal_vec ((internal_fn)currop->clique,
+ args);
gimple_set_location (call, expr->loc);
- gimple_call_set_fntype (call, currop->type);
if (sc)
gimple_call_set_chain (call, sc);
- tree forcedname = make_ssa_name (TREE_TYPE (currop->type));
+ tree forcedname = make_ssa_name (ref->type);
gimple_call_set_lhs (call, forcedname);
/* There's no CCP pass after PRE which would re-compute alignment
information so make sure we re-materialize this here. */
@@ -4004,10 +4015,6 @@ compute_avail (function *fun)
vn_reference_s ref1;
pre_expr result = NULL;
- /* We can value number only calls to real functions. */
- if (gimple_call_internal_p (stmt))
- continue;
-
vn_reference_lookup_call (as_a <gcall *> (stmt), &ref, &ref1);
/* There is no point to PRE a call without a value. */
if (!ref || !ref->result)
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 8498cfc..db9fb4e 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -180,6 +180,10 @@ along with GCC; see the file COPYING3. If not see
point 3a in the pass header comment. */
static bool reassoc_insert_powi_p;
+/* Enable biasing ranks of loop accumulators. We don't want this before
+ vectorization, since it interferes with reduction chains. */
+static bool reassoc_bias_loop_carried_phi_ranks_p;
+
/* Statistics */
static struct
{
@@ -207,6 +211,10 @@ static int64_t *bb_rank;
/* Operand->rank hashtable. */
static hash_map<tree, int64_t> *operand_rank;
+/* SSA_NAMEs that are forms of loop accumulators and whose ranks need to be
+ biased. */
+static auto_bitmap biased_names;
+
/* Vector of SSA_NAMEs on which after reassociate_bb is done with
all basic blocks the CFG should be adjusted - basic blocks
split right after that SSA_NAME's definition statement and before
@@ -252,6 +260,53 @@ reassoc_remove_stmt (gimple_stmt_iterator *gsi)
the rank difference between two blocks. */
#define PHI_LOOP_BIAS (1 << 15)
+/* Return TRUE iff PHI_LOOP_BIAS should be propagated from one of the STMT's
+ operands to the STMT's left-hand side. The goal is to preserve bias in code
+ like this:
+
+ x_1 = phi(x_0, x_2)
+ a = x_1 | 1
+ b = a ^ 2
+ .MEM = b
+ c = b + d
+ x_2 = c + e
+
+ That is, we need to preserve bias along single-use chains originating from
+ loop-carried phis. Only GIMPLE_ASSIGNs to SSA_NAMEs are considered to be
+ uses, because only they participate in rank propagation. */
+static bool
+propagate_bias_p (gimple *stmt)
+{
+ use_operand_p use;
+ imm_use_iterator use_iter;
+ gimple *single_use_stmt = NULL;
+
+ if (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_reference)
+ return false;
+
+ FOR_EACH_IMM_USE_FAST (use, use_iter, gimple_assign_lhs (stmt))
+ {
+ gimple *current_use_stmt = USE_STMT (use);
+
+ if (is_gimple_assign (current_use_stmt)
+ && TREE_CODE (gimple_assign_lhs (current_use_stmt)) == SSA_NAME)
+ {
+ if (single_use_stmt != NULL && single_use_stmt != current_use_stmt)
+ return false;
+ single_use_stmt = current_use_stmt;
+ }
+ }
+
+ if (single_use_stmt == NULL)
+ return false;
+
+ if (gimple_bb (stmt)->loop_father
+ != gimple_bb (single_use_stmt)->loop_father)
+ return false;
+
+ return true;
+}
+
/* Rank assigned to a phi statement. If STMT is a loop-carried phi of
an innermost loop, and the phi has only a single use which is inside
the loop, then the rank is the block rank of the loop latch plus an
@@ -269,6 +324,9 @@ phi_rank (gimple *stmt)
use_operand_p use;
gimple *use_stmt;
+ if (!reassoc_bias_loop_carried_phi_ranks_p)
+ return bb_rank[bb->index];
+
/* We only care about real loops (those with a latch). */
if (!father->latch)
return bb_rank[bb->index];
@@ -306,49 +364,27 @@ phi_rank (gimple *stmt)
return bb_rank[bb->index];
}
-/* If EXP is an SSA_NAME defined by a PHI statement that represents a
- loop-carried dependence of an innermost loop, return TRUE; else
- return FALSE. */
-static bool
-loop_carried_phi (tree exp)
-{
- gimple *phi_stmt;
- int64_t block_rank;
-
- if (TREE_CODE (exp) != SSA_NAME
- || SSA_NAME_IS_DEFAULT_DEF (exp))
- return false;
-
- phi_stmt = SSA_NAME_DEF_STMT (exp);
-
- if (gimple_code (SSA_NAME_DEF_STMT (exp)) != GIMPLE_PHI)
- return false;
-
- /* Non-loop-carried phis have block rank. Loop-carried phis have
- an additional bias added in. If this phi doesn't have block rank,
- it's biased and should not be propagated. */
- block_rank = bb_rank[gimple_bb (phi_stmt)->index];
-
- if (phi_rank (phi_stmt) != block_rank)
- return true;
-
- return false;
-}
-
/* Return the maximum of RANK and the rank that should be propagated
from expression OP. For most operands, this is just the rank of OP.
For loop-carried phis, the value is zero to avoid undoing the bias
in favor of the phi. */
static int64_t
-propagate_rank (int64_t rank, tree op)
+propagate_rank (int64_t rank, tree op, bool *maybe_biased_p)
{
int64_t op_rank;
- if (loop_carried_phi (op))
- return rank;
-
op_rank = get_rank (op);
+ /* Check whether op is biased after the get_rank () call, since it might have
+ updated biased_names. */
+ if (TREE_CODE (op) == SSA_NAME
+ && bitmap_bit_p (biased_names, SSA_NAME_VERSION (op)))
+ {
+ if (maybe_biased_p == NULL)
+ return rank;
+ *maybe_biased_p = true;
+ }
+
return MAX (rank, op_rank);
}
@@ -426,13 +462,20 @@ get_rank (tree e)
stmt = SSA_NAME_DEF_STMT (e);
if (gimple_code (stmt) == GIMPLE_PHI)
- rank = phi_rank (stmt);
+ {
+ rank = phi_rank (stmt);
+ if (rank != bb_rank[gimple_bb (stmt)->index])
+ bitmap_set_bit (biased_names, SSA_NAME_VERSION (e));
+ }
else if (!is_gimple_assign (stmt))
rank = bb_rank[gimple_bb (stmt)->index];
else
{
+ bool biased_p = false;
+ bool *maybe_biased_p = propagate_bias_p (stmt) ? &biased_p : NULL;
+
/* Otherwise, find the maximum rank for the operands. As an
exception, remove the bias from loop-carried phis when propagating
the rank so that dependent operations are not also biased. */
@@ -441,9 +484,11 @@ get_rank (tree e)
thus have rank 0. */
rank = 0;
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
- rank = propagate_rank (rank, op);
+ rank = propagate_rank (rank, op, maybe_biased_p);
rank += 1;
+ if (biased_p)
+ bitmap_set_bit (biased_names, SSA_NAME_VERSION (e));
}
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -6926,6 +6971,7 @@ fini_reassoc (void)
reassociate_stats.pows_created);
delete operand_rank;
+ bitmap_clear (biased_names);
operand_entry_pool.release ();
free (bb_rank);
plus_negates.release ();
@@ -6940,9 +6986,10 @@ fini_reassoc (void)
optimization of a gimple conditional. Otherwise returns zero. */
static unsigned int
-execute_reassoc (bool insert_powi_p)
+execute_reassoc (bool insert_powi_p, bool bias_loop_carried_phi_ranks_p)
{
reassoc_insert_powi_p = insert_powi_p;
+ reassoc_bias_loop_carried_phi_ranks_p = bias_loop_carried_phi_ranks_p;
init_reassoc ();
@@ -6983,15 +7030,19 @@ public:
{
gcc_assert (n == 0);
insert_powi_p = param;
+ bias_loop_carried_phi_ranks_p = !param;
}
virtual bool gate (function *) { return flag_tree_reassoc != 0; }
virtual unsigned int execute (function *)
- { return execute_reassoc (insert_powi_p); }
+ {
+ return execute_reassoc (insert_powi_p, bias_loop_carried_phi_ranks_p);
+ }
private:
/* Enable insertion of __builtin_powi calls during execute_reassoc. See
point 3a in the pass header comment. */
bool insert_powi_p;
+ bool bias_loop_carried_phi_ranks_p;
}; // class pass_reassoc
} // anon namespace
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index bfa516b..ae0172a 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h"
#include "tree-ssa-loop-niter.h"
#include "builtins.h"
+#include "fold-const-call.h"
#include "tree-ssa-sccvn.h"
/* This algorithm is based on the SCC algorithm presented by Keith
@@ -212,7 +213,8 @@ vn_reference_op_eq (const void *p1, const void *p2)
TYPE_MAIN_VARIANT (vro2->type))))
&& expressions_equal_p (vro1->op0, vro2->op0)
&& expressions_equal_p (vro1->op1, vro2->op1)
- && expressions_equal_p (vro1->op2, vro2->op2));
+ && expressions_equal_p (vro1->op2, vro2->op2)
+ && (vro1->opcode != CALL_EXPR || vro1->clique == vro2->clique));
}
/* Free a reference operation structure VP. */
@@ -264,15 +266,18 @@ print_vn_reference_ops (FILE *outfile, const vec<vn_reference_op_s> ops)
&& TREE_CODE_CLASS (vro->opcode) != tcc_declaration)
{
fprintf (outfile, "%s", get_tree_code_name (vro->opcode));
- if (vro->op0)
+ if (vro->op0 || vro->opcode == CALL_EXPR)
{
fprintf (outfile, "<");
closebrace = true;
}
}
- if (vro->op0)
+ if (vro->op0 || vro->opcode == CALL_EXPR)
{
- print_generic_expr (outfile, vro->op0);
+ if (!vro->op0)
+ fprintf (outfile, internal_fn_name ((internal_fn)vro->clique));
+ else
+ print_generic_expr (outfile, vro->op0);
if (vro->op1)
{
fprintf (outfile, ",");
@@ -684,6 +689,8 @@ static void
vn_reference_op_compute_hash (const vn_reference_op_t vro1, inchash::hash &hstate)
{
hstate.add_int (vro1->opcode);
+ if (vro1->opcode == CALL_EXPR && !vro1->op0)
+ hstate.add_int (vro1->clique);
if (vro1->op0)
inchash::add_expr (vro1->op0, hstate);
if (vro1->op1)
@@ -769,11 +776,16 @@ vn_reference_eq (const_vn_reference_t const vr1, const_vn_reference_t const vr2)
if (vr1->type != vr2->type)
return false;
}
+ else if (vr1->type == vr2->type)
+ ;
else if (COMPLETE_TYPE_P (vr1->type) != COMPLETE_TYPE_P (vr2->type)
|| (COMPLETE_TYPE_P (vr1->type)
&& !expressions_equal_p (TYPE_SIZE (vr1->type),
TYPE_SIZE (vr2->type))))
return false;
+ else if (vr1->operands[0].opcode == CALL_EXPR
+ && !types_compatible_p (vr1->type, vr2->type))
+ return false;
else if (INTEGRAL_TYPE_P (vr1->type)
&& INTEGRAL_TYPE_P (vr2->type))
{
@@ -1270,6 +1282,8 @@ copy_reference_ops_from_call (gcall *call,
temp.type = gimple_call_fntype (call);
temp.opcode = CALL_EXPR;
temp.op0 = gimple_call_fn (call);
+ if (gimple_call_internal_p (call))
+ temp.clique = gimple_call_internal_fn (call);
temp.op1 = gimple_call_chain (call);
if (stmt_could_throw_p (cfun, call) && (lr = lookup_stmt_eh_lp (call)) > 0)
temp.op2 = size_int (lr);
@@ -1459,9 +1473,11 @@ fully_constant_vn_reference_p (vn_reference_t ref)
a call to a builtin function with at most two arguments. */
op = &operands[0];
if (op->opcode == CALL_EXPR
- && TREE_CODE (op->op0) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (op->op0, 0)) == FUNCTION_DECL
- && fndecl_built_in_p (TREE_OPERAND (op->op0, 0))
+ && (!op->op0
+ || (TREE_CODE (op->op0) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (op->op0, 0)) == FUNCTION_DECL
+ && fndecl_built_in_p (TREE_OPERAND (op->op0, 0),
+ BUILT_IN_NORMAL)))
&& operands.length () >= 2
&& operands.length () <= 3)
{
@@ -1481,13 +1497,17 @@ fully_constant_vn_reference_p (vn_reference_t ref)
anyconst = true;
if (anyconst)
{
- tree folded = build_call_expr (TREE_OPERAND (op->op0, 0),
- arg1 ? 2 : 1,
- arg0->op0,
- arg1 ? arg1->op0 : NULL);
- if (folded
- && TREE_CODE (folded) == NOP_EXPR)
- folded = TREE_OPERAND (folded, 0);
+ combined_fn fn;
+ if (op->op0)
+ fn = as_combined_fn (DECL_FUNCTION_CODE
+ (TREE_OPERAND (op->op0, 0)));
+ else
+ fn = as_combined_fn ((internal_fn) op->clique);
+ tree folded;
+ if (arg1)
+ folded = fold_const_call (fn, ref->type, arg0->op0, arg1->op0);
+ else
+ folded = fold_const_call (fn, ref->type, arg0->op0);
if (folded
&& is_gimple_min_invariant (folded))
return folded;
@@ -2321,11 +2341,13 @@ vn_reference_lookup_or_insert_for_pieces (tree vuse,
}
/* Return a value-number for RCODE OPS... either by looking up an existing
- value-number for the simplified result or by inserting the operation if
- INSERT is true. */
+ value-number for the possibly simplified result or by inserting the
+ operation if INSERT is true. If SIMPLIFY is false, return a value
+ number for the unsimplified expression. */
static tree
-vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert)
+vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert,
+ bool simplify)
{
tree result = NULL_TREE;
/* We will be creating a value number for
@@ -2333,15 +2355,16 @@ vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert)
So first simplify and lookup this expression to see if it
is already available. */
/* For simplification valueize. */
- unsigned i;
- for (i = 0; i < res_op->num_ops; ++i)
- if (TREE_CODE (res_op->ops[i]) == SSA_NAME)
- {
- tree tem = vn_valueize (res_op->ops[i]);
- if (!tem)
- break;
- res_op->ops[i] = tem;
- }
+ unsigned i = 0;
+ if (simplify)
+ for (i = 0; i < res_op->num_ops; ++i)
+ if (TREE_CODE (res_op->ops[i]) == SSA_NAME)
+ {
+ tree tem = vn_valueize (res_op->ops[i]);
+ if (!tem)
+ break;
+ res_op->ops[i] = tem;
+ }
/* If valueization of an operand fails (it is not available), skip
simplification. */
bool res = false;
@@ -2440,7 +2463,7 @@ vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert)
static tree
vn_nary_build_or_lookup (gimple_match_op *res_op)
{
- return vn_nary_build_or_lookup_1 (res_op, true);
+ return vn_nary_build_or_lookup_1 (res_op, true, true);
}
/* Try to simplify the expression RCODE OPS... of type TYPE and return
@@ -2454,7 +2477,7 @@ vn_nary_simplify (vn_nary_op_t nary)
gimple_match_op op (gimple_match_cond::UNCOND, nary->opcode,
nary->type, nary->length);
memcpy (op.ops, nary->op, sizeof (tree) * nary->length);
- return vn_nary_build_or_lookup_1 (&op, false);
+ return vn_nary_build_or_lookup_1 (&op, false, true);
}
/* Elimination engine. */
@@ -3808,6 +3831,7 @@ vn_reference_insert_pieces (tree vuse, alias_set_type set,
if (result && TREE_CODE (result) == SSA_NAME)
result = SSA_VAL (result);
vr1->result = result;
+ vr1->result_vdef = NULL_TREE;
slot = valid_info->references->find_slot_with_hash (vr1, vr1->hashcode,
INSERT);
@@ -5006,7 +5030,7 @@ visit_nary_op (tree lhs, gassign *stmt)
tree ops[2];
gimple_match_op match_op (gimple_match_cond::UNCOND,
NEGATE_EXPR, type, rhs[i]);
- ops[i] = vn_nary_build_or_lookup_1 (&match_op, false);
+ ops[i] = vn_nary_build_or_lookup_1 (&match_op, false, true);
ops[j] = rhs[j];
if (ops[i]
&& (ops[0] = vn_nary_op_lookup_pieces (2, code,
@@ -5014,7 +5038,7 @@ visit_nary_op (tree lhs, gassign *stmt)
{
gimple_match_op match_op (gimple_match_cond::UNCOND,
NEGATE_EXPR, type, ops[0]);
- result = vn_nary_build_or_lookup (&match_op);
+ result = vn_nary_build_or_lookup_1 (&match_op, true, false);
if (result)
{
bool changed = set_ssa_val_to (lhs, result);
@@ -5121,13 +5145,12 @@ static bool
visit_reference_op_load (tree lhs, tree op, gimple *stmt)
{
bool changed = false;
- tree last_vuse;
tree result;
vn_reference_t res;
- last_vuse = gimple_vuse (stmt);
- result = vn_reference_lookup (op, gimple_vuse (stmt),
- default_vn_walk_kind, &res, true, &last_vuse);
+ tree vuse = gimple_vuse (stmt);
+ tree last_vuse = vuse;
+ result = vn_reference_lookup (op, vuse, default_vn_walk_kind, &res, true, &last_vuse);
/* We handle type-punning through unions by value-numbering based
on offset and size of the access. Be prepared to handle a
@@ -5170,6 +5193,16 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt)
{
changed = set_ssa_val_to (lhs, lhs);
vn_reference_insert (op, lhs, last_vuse, NULL_TREE);
+ if (vuse && SSA_VAL (last_vuse) != SSA_VAL (vuse))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Using extra use virtual operand ");
+ print_generic_expr (dump_file, last_vuse);
+ fprintf (dump_file, "\n");
+ }
+ vn_reference_insert (op, lhs, vuse, NULL_TREE);
+ }
}
return changed;
@@ -5635,28 +5668,30 @@ visit_stmt (gimple *stmt, bool backedges_varying_p = false)
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL)
extra_fnflags = flags_from_decl_or_type (TREE_OPERAND (fn, 0));
}
- if (!gimple_call_internal_p (call_stmt)
- && (/* Calls to the same function with the same vuse
- and the same operands do not necessarily return the same
- value, unless they're pure or const. */
- ((gimple_call_flags (call_stmt) | extra_fnflags)
- & (ECF_PURE | ECF_CONST))
- /* If calls have a vdef, subsequent calls won't have
- the same incoming vuse. So, if 2 calls with vdef have the
- same vuse, we know they're not subsequent.
- We can value number 2 calls to the same function with the
- same vuse and the same operands which are not subsequent
- the same, because there is no code in the program that can
- compare the 2 values... */
- || (gimple_vdef (call_stmt)
- /* ... unless the call returns a pointer which does
- not alias with anything else. In which case the
- information that the values are distinct are encoded
- in the IL. */
- && !(gimple_call_return_flags (call_stmt) & ERF_NOALIAS)
- /* Only perform the following when being called from PRE
- which embeds tail merging. */
- && default_vn_walk_kind == VN_WALK)))
+ if ((/* Calls to the same function with the same vuse
+ and the same operands do not necessarily return the same
+ value, unless they're pure or const. */
+ ((gimple_call_flags (call_stmt) | extra_fnflags)
+ & (ECF_PURE | ECF_CONST))
+ /* If calls have a vdef, subsequent calls won't have
+ the same incoming vuse. So, if 2 calls with vdef have the
+ same vuse, we know they're not subsequent.
+ We can value number 2 calls to the same function with the
+ same vuse and the same operands which are not subsequent
+ the same, because there is no code in the program that can
+ compare the 2 values... */
+ || (gimple_vdef (call_stmt)
+ /* ... unless the call returns a pointer which does
+ not alias with anything else. In which case the
+ information that the values are distinct are encoded
+ in the IL. */
+ && !(gimple_call_return_flags (call_stmt) & ERF_NOALIAS)
+ /* Only perform the following when being called from PRE
+ which embeds tail merging. */
+ && default_vn_walk_kind == VN_WALK))
+ /* Do not process .DEFERRED_INIT since that confuses uninit
+ analysis. */
+ && !gimple_call_internal_p (call_stmt, IFN_DEFERRED_INIT))
changed = visit_reference_op_call (lhs, call_stmt);
else
changed = defs_to_varying (call_stmt);
diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h
index 9610059..8a1b649 100644
--- a/gcc/tree-ssa-sccvn.h
+++ b/gcc/tree-ssa-sccvn.h
@@ -106,7 +106,8 @@ typedef const struct vn_phi_s *const_vn_phi_t;
typedef struct vn_reference_op_struct
{
ENUM_BITFIELD(tree_code) opcode : 16;
- /* Dependence info, used for [TARGET_]MEM_REF only. */
+ /* Dependence info, used for [TARGET_]MEM_REF only. For internal
+ function calls clique is also used for the internal function code. */
unsigned short clique;
unsigned short base;
unsigned reverse : 1;
diff --git a/gcc/tree-ssa-threadbackward.c b/gcc/tree-ssa-threadbackward.c
index 9554207..28c7ef8 100644
--- a/gcc/tree-ssa-threadbackward.c
+++ b/gcc/tree-ssa-threadbackward.c
@@ -192,7 +192,7 @@ back_threader::find_taken_edge_switch (const vec<basic_block> &path,
tree name = gimple_switch_index (sw);
int_range_max r;
- m_solver.precompute_ranges (path, m_imports);
+ m_solver.compute_ranges (path, m_imports);
m_solver.range_of_expr (r, name, sw);
if (r.undefined_p ())
@@ -216,7 +216,7 @@ back_threader::find_taken_edge_cond (const vec<basic_block> &path,
{
int_range_max r;
- m_solver.precompute_ranges (path, m_imports);
+ m_solver.compute_ranges (path, m_imports);
m_solver.range_of_stmt (r, cond);
if (m_solver.unreachable_path_p ())
@@ -943,7 +943,7 @@ public:
bool
pass_thread_jumps::gate (function *fun ATTRIBUTE_UNUSED)
{
- return flag_expensive_optimizations;
+ return flag_thread_jumps && flag_expensive_optimizations;
}
// Try to thread blocks in FUN. Return TRUE if any jump thread paths were
@@ -1013,7 +1013,7 @@ public:
bool
pass_early_thread_jumps::gate (function *fun ATTRIBUTE_UNUSED)
{
- return true;
+ return flag_thread_jumps;
}
unsigned int
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 04138cb..a63a976 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -33,12 +33,13 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-threadupdate.h"
#include "tree-ssa-scopedtables.h"
#include "tree-ssa-threadedge.h"
-#include "tree-ssa-dom.h"
#include "gimple-fold.h"
#include "cfganal.h"
#include "alloc-pool.h"
#include "vr-values.h"
#include "gimple-ssa-evrp-analyze.h"
+#include "gimple-range.h"
+#include "gimple-range-path.h"
/* To avoid code explosion due to jump threading, we limit the
number of statements we are going to copy. This variable
@@ -61,8 +62,7 @@ set_ssa_name_value (tree name, tree value)
ssa_name_values[SSA_NAME_VERSION (name)] = value;
}
-jump_threader::jump_threader (jump_threader_simplifier *simplifier,
- jt_state *state)
+jump_threader::jump_threader (jt_simplifier *simplifier, jt_state *state)
{
/* Initialize the per SSA_NAME value-handles array. */
gcc_assert (!ssa_name_values.exists ());
@@ -228,8 +228,6 @@ jump_threader::record_temporary_equivalences_from_stmts_at_dest (edge e)
when we're finished processing E. */
for (gsi = gsi_start_bb (e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
{
- tree cached_lhs = NULL;
-
stmt = gsi_stmt (gsi);
/* Ignore empty statements and labels. */
@@ -326,75 +324,7 @@ jump_threader::record_temporary_equivalences_from_stmts_at_dest (edge e)
continue;
}
- /* At this point we have a statement which assigns an RHS to an
- SSA_VAR on the LHS. We want to try and simplify this statement
- to expose more context sensitive equivalences which in turn may
- allow us to simplify the condition at the end of the loop.
-
- Handle simple copy operations as well as implied copies from
- ASSERT_EXPRs. */
- if (gimple_assign_single_p (stmt)
- && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
- cached_lhs = gimple_assign_rhs1 (stmt);
- else if (gimple_assign_single_p (stmt)
- && TREE_CODE (gimple_assign_rhs1 (stmt)) == ASSERT_EXPR)
- cached_lhs = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
- else
- {
- /* A statement that is not a trivial copy or ASSERT_EXPR.
- Try to fold the new expression. Inserting the
- expression into the hash table is unlikely to help. */
- /* ??? The DOM callback below can be changed to setting
- the mprts_hook around the call to thread_across_edge,
- avoiding the use substitution. The VRP hook should be
- changed to properly valueize operands itself using
- SSA_NAME_VALUE in addition to its own lattice. */
- cached_lhs = gimple_fold_stmt_to_constant_1 (stmt,
- threadedge_valueize);
- if (NUM_SSA_OPERANDS (stmt, SSA_OP_ALL_USES) != 0
- && (!cached_lhs
- || (TREE_CODE (cached_lhs) != SSA_NAME
- && !is_gimple_min_invariant (cached_lhs))))
- {
- /* We're going to temporarily copy propagate the operands
- and see if that allows us to simplify this statement. */
- tree *copy;
- ssa_op_iter iter;
- use_operand_p use_p;
- unsigned int num, i = 0;
-
- num = NUM_SSA_OPERANDS (stmt, SSA_OP_ALL_USES);
- copy = XALLOCAVEC (tree, num);
-
- /* Make a copy of the uses & vuses into USES_COPY, then cprop into
- the operands. */
- FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
- {
- tree tmp = NULL;
- tree use = USE_FROM_PTR (use_p);
-
- copy[i++] = use;
- if (TREE_CODE (use) == SSA_NAME)
- tmp = SSA_NAME_VALUE (use);
- if (tmp)
- SET_USE (use_p, tmp);
- }
-
- cached_lhs = m_simplifier->simplify (stmt, stmt, e->src, m_state);
-
- /* Restore the statement's original uses/defs. */
- i = 0;
- FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
- SET_USE (use_p, copy[i++]);
- }
- }
-
- /* Record the context sensitive equivalence if we were able
- to simplify this statement. */
- if (cached_lhs
- && (TREE_CODE (cached_lhs) == SSA_NAME
- || is_gimple_min_invariant (cached_lhs)))
- m_state->register_equiv (gimple_get_lhs (stmt), cached_lhs);
+ m_state->register_equivs_stmt (stmt, e->src, m_simplifier);
}
return stmt;
}
@@ -899,6 +829,7 @@ jump_threader::thread_around_empty_blocks (vec<jump_thread_edge *> *path,
if (!bitmap_bit_p (visited, taken_edge->dest->index))
{
m_registry->push_edge (path, taken_edge, EDGE_NO_COPY_SRC_BLOCK);
+ m_state->append_path (taken_edge->dest);
bitmap_set_bit (visited, taken_edge->dest->index);
return thread_around_empty_blocks (path, taken_edge, visited);
}
@@ -940,6 +871,7 @@ jump_threader::thread_around_empty_blocks (vec<jump_thread_edge *> *path,
bitmap_set_bit (visited, taken_edge->dest->index);
m_registry->push_edge (path, taken_edge, EDGE_NO_COPY_SRC_BLOCK);
+ m_state->append_path (taken_edge->dest);
thread_around_empty_blocks (path, taken_edge, visited);
return true;
@@ -970,7 +902,7 @@ int
jump_threader::thread_through_normal_block (vec<jump_thread_edge *> *path,
edge e, bitmap visited)
{
- m_state->register_equivs_on_edge (e);
+ m_state->register_equivs_edge (e);
/* PHIs create temporary equivalences.
Note that if we found a PHI that made the block non-threadable, then
@@ -1048,6 +980,7 @@ jump_threader::thread_through_normal_block (vec<jump_thread_edge *> *path,
m_registry->push_edge (path, e, EDGE_START_JUMP_THREAD);
m_registry->push_edge (path, taken_edge, EDGE_COPY_SRC_BLOCK);
+ m_state->append_path (taken_edge->dest);
/* See if we can thread through DEST as well, this helps capture
secondary effects of threading without having to re-run DOM or
@@ -1263,6 +1196,9 @@ jump_threader::thread_outgoing_edges (basic_block bb)
int flags = (EDGE_IGNORE | EDGE_COMPLEX | EDGE_ABNORMAL);
gimple *last;
+ if (!flag_thread_jumps)
+ return;
+
/* If we have an outgoing edge to a block with multiple incoming and
outgoing edges, then we may be able to thread the edge, i.e., we
may be able to statically determine which of the outgoing edges
@@ -1290,26 +1226,18 @@ jump_threader::thread_outgoing_edges (basic_block bb)
}
}
-jt_state::jt_state (const_and_copies *copies,
- avail_exprs_stack *exprs,
- evrp_range_analyzer *evrp)
-{
- m_copies = copies;
- m_exprs = exprs;
- m_evrp = evrp;
-}
+// Marker to keep track of the start of the current path.
+const basic_block jt_state::BB_MARKER = (basic_block) -1;
// Record that E is being crossed.
void
-jt_state::push (edge)
+jt_state::push (edge e)
{
- if (m_copies)
- m_copies->push_marker ();
- if (m_exprs)
- m_exprs->push_marker ();
- if (m_evrp)
- m_evrp->push_marker ();
+ m_blocks.safe_push (BB_MARKER);
+ if (m_blocks.length () == 1)
+ m_blocks.safe_push (e->src);
+ m_blocks.safe_push (e->dest);
}
// Pop to the last pushed state.
@@ -1317,127 +1245,223 @@ jt_state::push (edge)
void
jt_state::pop ()
{
- if (m_copies)
- m_copies->pop_to_marker ();
- if (m_exprs)
- m_exprs->pop_to_marker ();
- if (m_evrp)
- m_evrp->pop_to_marker ();
+ if (!m_blocks.is_empty ())
+ {
+ while (m_blocks.last () != BB_MARKER)
+ m_blocks.pop ();
+ // Pop marker.
+ m_blocks.pop ();
+ }
}
-// Record an equivalence from DST to SRC. If UPDATE_RANGE is TRUE,
-// update the value range associated with DST.
+// Add BB to the list of blocks seen.
void
-jt_state::register_equiv (tree dst, tree src, bool update_range)
+jt_state::append_path (basic_block bb)
{
- if (m_copies)
- m_copies->record_const_or_copy (dst, src);
+ gcc_checking_assert (!m_blocks.is_empty ());
+ m_blocks.safe_push (bb);
+}
- /* If requested, update the value range associated with DST, using
- the range from SRC. */
- if (m_evrp && update_range)
+void
+jt_state::dump (FILE *out)
+{
+ if (!m_blocks.is_empty ())
{
- /* Get new VR we can pass to push_value_range. */
- value_range_equiv *new_vr = m_evrp->allocate_value_range_equiv ();
- new (new_vr) value_range_equiv ();
-
- /* There are three cases to consider:
-
- First if SRC is an SSA_NAME, then we can copy the value range
- from SRC into NEW_VR.
-
- Second if SRC is an INTEGER_CST, then we can just set NEW_VR
- to a singleton range. Note that even if SRC is a constant we
- need to set a suitable output range so that VR_UNDEFINED
- ranges do not leak through.
-
- Otherwise set NEW_VR to varying. This may be overly
- conservative. */
- if (TREE_CODE (src) == SSA_NAME)
- new_vr->deep_copy (m_evrp->get_value_range (src));
- else if (TREE_CODE (src) == INTEGER_CST)
- new_vr->set (src);
- else
- new_vr->set_varying (TREE_TYPE (src));
+ auto_vec<basic_block> path;
+ get_path (path);
+ dump_ranger (out, path);
+ }
+}
+
+void
+jt_state::debug ()
+{
+ push_dump_file save (stderr, TDF_DETAILS);
+ dump (stderr);
+}
+
+// Convert the current path in jt_state into a path suitable for the
+// path solver. Return the resulting path in PATH.
+
+void
+jt_state::get_path (vec<basic_block> &path)
+{
+ path.truncate (0);
+
+ for (int i = (int) m_blocks.length () - 1; i >= 0; --i)
+ {
+ basic_block bb = m_blocks[i];
- /* This is a temporary range for DST, so push it. */
- m_evrp->push_value_range (dst, new_vr);
+ if (bb != BB_MARKER)
+ path.safe_push (bb);
}
}
+// Record an equivalence from DST to SRC. If UPDATE_RANGE is TRUE,
+// update the value range associated with DST.
+
+void
+jt_state::register_equiv (tree dest ATTRIBUTE_UNUSED,
+ tree src ATTRIBUTE_UNUSED,
+ bool update_range ATTRIBUTE_UNUSED)
+{
+}
+
// Record any ranges calculated in STMT. If TEMPORARY is TRUE, then
// this is a temporary equivalence and should be recorded into the
// unwind table, instead of the global table.
void
-jt_state::record_ranges_from_stmt (gimple *stmt, bool temporary)
+jt_state::record_ranges_from_stmt (gimple *,
+ bool temporary ATTRIBUTE_UNUSED)
{
- if (m_evrp)
- m_evrp->record_ranges_from_stmt (stmt, temporary);
}
// Record any equivalences created by traversing E.
void
-jt_state::register_equivs_on_edge (edge e)
+jt_state::register_equivs_edge (edge)
{
- if (m_copies && m_exprs)
- record_temporary_equivalences (e, m_copies, m_exprs);
}
-jump_threader_simplifier::jump_threader_simplifier (vr_values *v)
+void
+jt_state::register_equivs_stmt (gimple *stmt, basic_block bb,
+ jt_simplifier *simplifier)
{
- m_vr_values = v;
+ /* At this point we have a statement which assigns an RHS to an
+ SSA_VAR on the LHS. We want to try and simplify this statement
+ to expose more context sensitive equivalences which in turn may
+ allow us to simplify the condition at the end of the loop.
+
+ Handle simple copy operations as well as implied copies from
+ ASSERT_EXPRs. */
+ tree cached_lhs = NULL;
+ if (gimple_assign_single_p (stmt)
+ && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
+ cached_lhs = gimple_assign_rhs1 (stmt);
+ else if (gimple_assign_single_p (stmt)
+ && TREE_CODE (gimple_assign_rhs1 (stmt)) == ASSERT_EXPR)
+ cached_lhs = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
+ else
+ {
+ /* A statement that is not a trivial copy or ASSERT_EXPR.
+ Try to fold the new expression. Inserting the
+ expression into the hash table is unlikely to help. */
+ /* ??? The DOM callback below can be changed to setting
+ the mprts_hook around the call to thread_across_edge,
+ avoiding the use substitution. The VRP hook should be
+ changed to properly valueize operands itself using
+ SSA_NAME_VALUE in addition to its own lattice. */
+ cached_lhs = gimple_fold_stmt_to_constant_1 (stmt,
+ threadedge_valueize);
+ if (NUM_SSA_OPERANDS (stmt, SSA_OP_ALL_USES) != 0
+ && (!cached_lhs
+ || (TREE_CODE (cached_lhs) != SSA_NAME
+ && !is_gimple_min_invariant (cached_lhs))))
+ {
+ /* We're going to temporarily copy propagate the operands
+ and see if that allows us to simplify this statement. */
+ tree *copy;
+ ssa_op_iter iter;
+ use_operand_p use_p;
+ unsigned int num, i = 0;
+
+ num = NUM_SSA_OPERANDS (stmt, SSA_OP_ALL_USES);
+ copy = XALLOCAVEC (tree, num);
+
+ /* Make a copy of the uses & vuses into USES_COPY, then cprop into
+ the operands. */
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
+ {
+ tree tmp = NULL;
+ tree use = USE_FROM_PTR (use_p);
+
+ copy[i++] = use;
+ if (TREE_CODE (use) == SSA_NAME)
+ tmp = SSA_NAME_VALUE (use);
+ if (tmp)
+ SET_USE (use_p, tmp);
+ }
+
+ cached_lhs = simplifier->simplify (stmt, stmt, bb, this);
+
+ /* Restore the statement's original uses/defs. */
+ i = 0;
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
+ SET_USE (use_p, copy[i++]);
+ }
+ }
+
+ /* Record the context sensitive equivalence if we were able
+ to simplify this statement. */
+ if (cached_lhs
+ && (TREE_CODE (cached_lhs) == SSA_NAME
+ || is_gimple_min_invariant (cached_lhs)))
+ register_equiv (gimple_get_lhs (stmt), cached_lhs,
+ /*update_range=*/false);
}
-// Return the singleton that resolves STMT, if it is possible to
-// simplify it.
-//
-// STMT may be a dummy statement, not necessarily in the CFG, in which
-// case WITHIN_STMT can be used to determine the position in the CFG
-// where STMT should be evaluated as being in.
+// Hybrid threader implementation.
+
+
+hybrid_jt_simplifier::hybrid_jt_simplifier (gimple_ranger *r,
+ path_range_query *q)
+{
+ m_ranger = r;
+ m_query = q;
+}
tree
-jump_threader_simplifier::simplify (gimple *stmt,
- gimple *within_stmt,
- basic_block,
- jt_state *)
+hybrid_jt_simplifier::simplify (gimple *stmt, gimple *, basic_block,
+ jt_state *state)
{
- if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
+ int_range_max r;
+
+ compute_ranges_from_state (stmt, state);
+
+ if (gimple_code (stmt) == GIMPLE_COND
+ || gimple_code (stmt) == GIMPLE_ASSIGN)
{
- simplify_using_ranges simplifier (m_vr_values);
- return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
- gimple_cond_lhs (cond_stmt),
- gimple_cond_rhs (cond_stmt),
- within_stmt);
+ tree ret;
+ if (m_query->range_of_stmt (r, stmt) && r.singleton_p (&ret))
+ return ret;
}
- if (gswitch *switch_stmt = dyn_cast <gswitch *> (stmt))
+ else if (gimple_code (stmt) == GIMPLE_SWITCH)
{
- tree op = gimple_switch_index (switch_stmt);
- if (TREE_CODE (op) != SSA_NAME)
- return NULL_TREE;
-
- const value_range_equiv *vr = m_vr_values->get_value_range (op);
- return find_case_label_range (switch_stmt, vr);
+ gswitch *switch_stmt = dyn_cast <gswitch *> (stmt);
+ tree index = gimple_switch_index (switch_stmt);
+ if (m_query->range_of_expr (r, index, stmt))
+ return find_case_label_range (switch_stmt, &r);
}
- if (gassign *assign_stmt = dyn_cast <gassign *> (stmt))
+ return NULL;
+}
+
+// Use STATE to generate the list of imports needed for the solver,
+// and calculate the ranges along the path.
+
+void
+hybrid_jt_simplifier::compute_ranges_from_state (gimple *stmt, jt_state *state)
+{
+ auto_bitmap imports;
+ gori_compute &gori = m_ranger->gori ();
+
+ state->get_path (m_path);
+
+ // Start with the imports to the final conditional.
+ bitmap_copy (imports, gori.imports (m_path[0]));
+
+ // Add any other interesting operands we may have missed.
+ if (gimple_bb (stmt) != m_path[0])
{
- tree lhs = gimple_assign_lhs (assign_stmt);
- if (TREE_CODE (lhs) == SSA_NAME
- && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
- || POINTER_TYPE_P (TREE_TYPE (lhs)))
- && stmt_interesting_for_vrp (stmt))
+ for (unsigned i = 0; i < gimple_num_ops (stmt); ++i)
{
- edge dummy_e;
- tree dummy_tree;
- value_range_equiv new_vr;
- m_vr_values->extract_range_from_stmt (stmt, &dummy_e, &dummy_tree,
- &new_vr);
- tree singleton;
- if (new_vr.singleton_p (&singleton))
- return singleton;
+ tree op = gimple_op (stmt, i);
+ if (op
+ && TREE_CODE (op) == SSA_NAME
+ && irange::supports_type_p (TREE_TYPE (op)))
+ bitmap_set_bit (imports, SSA_NAME_VERSION (op));
}
}
- return NULL;
+ m_query->compute_ranges (m_path, imports);
}
diff --git a/gcc/tree-ssa-threadedge.h b/gcc/tree-ssa-threadedge.h
index 18e6bd4..c46a5c6 100644
--- a/gcc/tree-ssa-threadedge.h
+++ b/gcc/tree-ssa-threadedge.h
@@ -26,19 +26,54 @@ along with GCC; see the file COPYING3. If not see
class jt_state
{
public:
- jt_state (class const_and_copies *,
- class avail_exprs_stack *,
- class evrp_range_analyzer *);
- void push (edge);
- void pop ();
- void register_equiv (tree dest, tree src, bool update_range = false);
- void register_equivs_on_edge (edge e);
- void record_ranges_from_stmt (gimple *stmt, bool temporary);
+ virtual ~jt_state () { }
+ virtual void push (edge);
+ virtual void pop ();
+ virtual void register_equiv (tree dest, tree src, bool update_range);
+ virtual void register_equivs_edge (edge e);
+ virtual void register_equivs_stmt (gimple *, basic_block,
+ class jt_simplifier *);
+ virtual void record_ranges_from_stmt (gimple *stmt, bool temporary);
+ void get_path (vec<basic_block> &);
+ void append_path (basic_block);
+ void dump (FILE *);
+ void debug ();
private:
- const_and_copies *m_copies;
- avail_exprs_stack *m_exprs;
- evrp_range_analyzer *m_evrp;
+ auto_vec<basic_block> m_blocks;
+ static const basic_block BB_MARKER;
+};
+
+// Statement simplifier callback for the jump threader.
+
+class jt_simplifier
+{
+public:
+ virtual ~jt_simplifier () { }
+ virtual tree simplify (gimple *, gimple *, basic_block, jt_state *) = 0;
+};
+
+class hybrid_jt_state : public jt_state
+{
+private:
+ void register_equivs_stmt (gimple *, basic_block, jt_simplifier *) override
+ {
+ // Ranger has no need to simplify anything.
+ }
+};
+
+class hybrid_jt_simplifier : public jt_simplifier
+{
+public:
+ hybrid_jt_simplifier (class gimple_ranger *r, class path_range_query *q);
+ tree simplify (gimple *stmt, gimple *, basic_block, jt_state *) override;
+
+private:
+ void compute_ranges_from_state (gimple *stmt, jt_state *);
+
+ gimple_ranger *m_ranger;
+ path_range_query *m_query;
+ auto_vec<basic_block> m_path;
};
// This is the high level threader. The entry point is
@@ -49,7 +84,7 @@ private:
class jump_threader
{
public:
- jump_threader (class jump_threader_simplifier *, class jt_state *);
+ jump_threader (jt_simplifier *, class jt_state *);
~jump_threader ();
void thread_outgoing_edges (basic_block);
void remove_jump_threads_including (edge_def *);
@@ -76,23 +111,10 @@ private:
gcond *dummy_cond;
class fwd_jt_path_registry *m_registry;
- jump_threader_simplifier *m_simplifier;
+ jt_simplifier *m_simplifier;
jt_state *m_state;
};
-// Statement simplifier callback for the jump threader.
-
-class jump_threader_simplifier
-{
-public:
- jump_threader_simplifier (class vr_values *v);
- virtual ~jump_threader_simplifier () { }
- virtual tree simplify (gimple *, gimple *, basic_block, jt_state *);
-
-protected:
- vr_values *m_vr_values;
-};
-
extern void propagate_threaded_block_debug_into (basic_block, basic_block);
extern bool single_succ_to_potentially_threadable_block (basic_block);
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
index baac112..32ce1e3 100644
--- a/gcc/tree-ssa-threadupdate.c
+++ b/gcc/tree-ssa-threadupdate.c
@@ -218,10 +218,15 @@ dump_jump_thread_path (FILE *dump_file,
const vec<jump_thread_edge *> &path,
bool registering)
{
- fprintf (dump_file,
- " %s jump thread: (%d, %d) incoming edge; ",
- (registering ? "Registering" : "Cancelling"),
- path[0]->e->src->index, path[0]->e->dest->index);
+ if (registering)
+ fprintf (dump_file,
+ " [%u] Registering jump thread: (%d, %d) incoming edge; ",
+ dbg_cnt_counter (registered_jump_thread),
+ path[0]->e->src->index, path[0]->e->dest->index);
+ else
+ fprintf (dump_file,
+ " Cancelling jump thread: (%d, %d) incoming edge; ",
+ path[0]->e->src->index, path[0]->e->dest->index);
for (unsigned int i = 1; i < path.length (); i++)
{
@@ -2570,7 +2575,7 @@ valid_jump_thread_path (vec<jump_thread_edge *> *path)
void
fwd_jt_path_registry::remove_jump_threads_including (edge_def *e)
{
- if (!m_paths.exists ())
+ if (!m_paths.exists () || !flag_thread_jumps)
return;
edge *slot = m_removed_edges->find_slot (e, INSERT);
@@ -2757,6 +2762,76 @@ fwd_jt_path_registry::update_cfg (bool may_peel_loop_headers)
return retval;
}
+bool
+jt_path_registry::cancel_invalid_paths (vec<jump_thread_edge *> &path)
+{
+ gcc_checking_assert (!path.is_empty ());
+ edge entry = path[0]->e;
+ edge exit = path[path.length () - 1]->e;
+ bool seen_latch = false;
+ int loops_crossed = 0;
+ bool crossed_latch = false;
+ // Use ->dest here instead of ->src to ignore the first block. The
+ // first block is allowed to be in a different loop, since it'll be
+ // redirected. See similar comment in profitable_path_p: "we don't
+ // care about that block...".
+ loop_p loop = entry->dest->loop_father;
+ loop_p curr_loop = loop;
+
+ for (unsigned int i = 0; i < path.length (); i++)
+ {
+ edge e = path[i]->e;
+
+ if (e == NULL)
+ {
+ // NULL outgoing edges on a path can happen for jumping to a
+ // constant address.
+ cancel_thread (&path, "Found NULL edge in jump threading path");
+ return true;
+ }
+
+ if (loop->latch == e->src || loop->latch == e->dest)
+ {
+ seen_latch = true;
+ // Like seen_latch, but excludes the first block.
+ if (e->src != entry->src)
+ crossed_latch = true;
+ }
+
+ if (e->dest->loop_father != curr_loop)
+ {
+ curr_loop = e->dest->loop_father;
+ ++loops_crossed;
+ }
+
+ if (flag_checking && !m_backedge_threads)
+ gcc_assert ((path[i]->e->flags & EDGE_DFS_BACK) == 0);
+ }
+
+ // If we crossed a loop into an outer loop without crossing the
+ // latch, this is just an early exit from the loop.
+ if (loops_crossed == 1
+ && !crossed_latch
+ && flow_loop_nested_p (exit->dest->loop_father, exit->src->loop_father))
+ return false;
+
+ if (cfun->curr_properties & PROP_loop_opts_done)
+ return false;
+
+ if (seen_latch && empty_block_p (loop->latch))
+ {
+ cancel_thread (&path, "Threading through latch before loop opts "
+ "would create non-empty latch");
+ return true;
+ }
+ if (loops_crossed)
+ {
+ cancel_thread (&path, "Path crosses loops");
+ return true;
+ }
+ return false;
+}
+
/* Register a jump threading opportunity. We queue up all the jump
threading opportunities discovered by a pass and update the CFG
and SSA form all at once.
@@ -2770,25 +2845,16 @@ fwd_jt_path_registry::update_cfg (bool may_peel_loop_headers)
bool
jt_path_registry::register_jump_thread (vec<jump_thread_edge *> *path)
{
+ gcc_checking_assert (flag_thread_jumps);
+
if (!dbg_cnt (registered_jump_thread))
{
path->release ();
return false;
}
- /* First make sure there are no NULL outgoing edges on the jump threading
- path. That can happen for jumping to a constant address. */
- for (unsigned int i = 0; i < path->length (); i++)
- {
- if ((*path)[i]->e == NULL)
- {
- cancel_thread (path, "Found NULL edge in jump threading path");
- return false;
- }
-
- if (flag_checking && !m_backedge_threads)
- gcc_assert (((*path)[i]->e->flags & EDGE_DFS_BACK) == 0);
- }
+ if (cancel_invalid_paths (*path))
+ return false;
if (dump_file && (dump_flags & TDF_DETAILS))
dump_jump_thread_path (dump_file, *path, true);
diff --git a/gcc/tree-ssa-threadupdate.h b/gcc/tree-ssa-threadupdate.h
index 8b48a67..d68795c 100644
--- a/gcc/tree-ssa-threadupdate.h
+++ b/gcc/tree-ssa-threadupdate.h
@@ -75,6 +75,7 @@ protected:
unsigned long m_num_threaded_edges;
private:
virtual bool update_cfg (bool peel_loop_headers) = 0;
+ bool cancel_invalid_paths (vec<jump_thread_edge *> &path);
jump_thread_path_allocator m_allocator;
// True if threading through back edges is allowed. This is only
// allowed in the generic copier in the backward threader.
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 2165ad7..f427c5a 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa.h"
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
+#include "value-query.h"
/* Rewriting a function into SSA form can create a huge number of SSA_NAMEs,
many of which may be thrown away shortly after their creation if jumps
@@ -484,7 +485,7 @@ get_nonzero_bits (const_tree name)
This can be because it is a boolean type, any unsigned integral
type with a single bit of precision, or has known range of [0..1]
- via VRP analysis. */
+ via range analysis. */
bool
ssa_name_has_boolean_range (tree op)
@@ -502,12 +503,20 @@ ssa_name_has_boolean_range (tree op)
return true;
/* An integral type with more precision, but the object
- only takes on values [0..1] as determined by VRP
+ only takes on values [0..1] as determined by range
analysis. */
if (INTEGRAL_TYPE_P (TREE_TYPE (op))
- && (TYPE_PRECISION (TREE_TYPE (op)) > 1)
- && wi::eq_p (get_nonzero_bits (op), 1))
- return true;
+ && (TYPE_PRECISION (TREE_TYPE (op)) > 1))
+ {
+ int_range<2> onezero (build_zero_cst (TREE_TYPE (op)),
+ build_one_cst (TREE_TYPE (op)));
+ int_range<2> r;
+ if (get_range_query (cfun)->range_of_expr (r, op) && r == onezero)
+ return true;
+
+ if (wi::eq_p (get_nonzero_bits (op), 1))
+ return true;
+ }
return false;
}
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index a57700f..07b5ba1 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -887,37 +887,53 @@ vect_slp_analyze_instance_dependence (vec_info *vinfo, slp_instance instance)
return res;
}
-/* Return the misalignment of DR_INFO. */
+/* Return the misalignment of DR_INFO accessed in VECTYPE. */
int
-dr_misalignment (dr_vec_info *dr_info)
+dr_misalignment (dr_vec_info *dr_info, tree vectype)
{
+ HOST_WIDE_INT diff = 0;
+ /* Alignment is only analyzed for the first element of a DR group,
+ use that but adjust misalignment by the offset of the access. */
if (STMT_VINFO_GROUPED_ACCESS (dr_info->stmt))
{
dr_vec_info *first_dr
= STMT_VINFO_DR_INFO (DR_GROUP_FIRST_ELEMENT (dr_info->stmt));
- int misalign = first_dr->misalignment;
- gcc_assert (misalign != DR_MISALIGNMENT_UNINITIALIZED);
- if (misalign == DR_MISALIGNMENT_UNKNOWN)
- return misalign;
/* vect_analyze_data_ref_accesses guarantees that DR_INIT are
INTEGER_CSTs and the first element in the group has the lowest
- address. Likewise vect_compute_data_ref_alignment will
- have ensured that target_alignment is constant and otherwise
- set misalign to DR_MISALIGNMENT_UNKNOWN. */
- HOST_WIDE_INT diff = (TREE_INT_CST_LOW (DR_INIT (dr_info->dr))
- - TREE_INT_CST_LOW (DR_INIT (first_dr->dr)));
+ address. */
+ diff = (TREE_INT_CST_LOW (DR_INIT (dr_info->dr))
+ - TREE_INT_CST_LOW (DR_INIT (first_dr->dr)));
gcc_assert (diff >= 0);
- unsigned HOST_WIDE_INT target_alignment_c
- = first_dr->target_alignment.to_constant ();
- return (misalign + diff) % target_alignment_c;
- }
- else
- {
- int misalign = dr_info->misalignment;
- gcc_assert (misalign != DR_MISALIGNMENT_UNINITIALIZED);
- return misalign;
+ dr_info = first_dr;
}
+
+ int misalign = dr_info->misalignment;
+ gcc_assert (misalign != DR_MISALIGNMENT_UNINITIALIZED);
+ if (misalign == DR_MISALIGNMENT_UNKNOWN)
+ return misalign;
+
+ /* If the access is only aligned for a vector type with smaller alignment
+ requirement the access has unknown misalignment. */
+ if (maybe_lt (dr_info->target_alignment * BITS_PER_UNIT,
+ targetm.vectorize.preferred_vector_alignment (vectype)))
+ return DR_MISALIGNMENT_UNKNOWN;
+
+ /* If this is a backward running DR then first access in the larger
+ vectype actually is N-1 elements before the address in the DR.
+ Adjust misalign accordingly. */
+ poly_int64 misalignment = misalign + diff;
+ if (tree_int_cst_sgn (DR_STEP (dr_info->dr)) < 0)
+ misalignment += ((TYPE_VECTOR_SUBPARTS (vectype) - 1)
+ * -TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (vectype))));
+
+ /* vect_compute_data_ref_alignment will have ensured that target_alignment
+ is constant and otherwise set misalign to DR_MISALIGNMENT_UNKNOWN. */
+ unsigned HOST_WIDE_INT target_alignment_c
+ = dr_info->target_alignment.to_constant ();
+ if (!known_misalignment (misalignment, target_alignment_c, &misalign))
+ return DR_MISALIGNMENT_UNKNOWN;
+ return misalign;
}
/* Record the base alignment guarantee given by DRB, which occurs
@@ -978,34 +994,26 @@ vect_record_base_alignments (vec_info *vinfo)
}
}
-/* Return the target alignment for the vectorized form of DR_INFO. */
-
-static poly_uint64
-vect_calculate_target_alignment (dr_vec_info *dr_info)
-{
- tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt);
- return targetm.vectorize.preferred_vector_alignment (vectype);
-}
-
/* Function vect_compute_data_ref_alignment
- Compute the misalignment of the data reference DR_INFO.
+ Compute the misalignment of the data reference DR_INFO when vectorizing
+ with VECTYPE.
Output:
- 1. DR_MISALIGNMENT (DR_INFO) is defined.
+ 1. initialized misalignment info for DR_INFO
FOR NOW: No analysis is actually performed. Misalignment is calculated
only for trivial cases. TODO. */
static void
-vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info)
+vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info,
+ tree vectype)
{
stmt_vec_info stmt_info = dr_info->stmt;
vec_base_alignments *base_alignments = &vinfo->base_alignments;
loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
class loop *loop = NULL;
tree ref = DR_REF (dr_info->dr);
- tree vectype = STMT_VINFO_VECTYPE (stmt_info);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -1024,7 +1032,8 @@ vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info)
bool step_preserves_misalignment_p;
poly_uint64 vector_alignment
- = exact_div (vect_calculate_target_alignment (dr_info), BITS_PER_UNIT);
+ = exact_div (targetm.vectorize.preferred_vector_alignment (vectype),
+ BITS_PER_UNIT);
SET_DR_TARGET_ALIGNMENT (dr_info, vector_alignment);
/* If the main loop has peeled for alignment we have no way of knowing
@@ -1147,14 +1156,6 @@ vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info)
poly_int64 misalignment
= base_misalignment + wi::to_poly_offset (drb->init).force_shwi ();
- /* If this is a backward running DR then first access in the larger
- vectype actually is N-1 elements before the address in the DR.
- Adjust misalign accordingly. */
- if (tree_int_cst_sgn (drb->step) < 0)
- /* PLUS because STEP is negative. */
- misalignment += ((TYPE_VECTOR_SUBPARTS (vectype) - 1)
- * -TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (vectype))));
-
unsigned int const_misalignment;
if (!known_misalignment (misalignment, vect_align_c, &const_misalignment))
{
@@ -1169,7 +1170,7 @@ vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info)
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"misalign = %d bytes of ref %T\n",
- DR_MISALIGNMENT (dr_info), ref);
+ const_misalignment, ref);
return;
}
@@ -1213,6 +1214,29 @@ vect_dr_aligned_if_peeled_dr_is (dr_vec_info *dr_info,
return vect_dr_aligned_if_related_peeled_dr_is (dr_info, dr_peel_info);
}
+/* Compute the value for dr_info->misalign so that the access appears
+ aligned. This is used by peeling to compensate for dr_misalignment
+ applying the offset for negative step. */
+
+int
+vect_dr_misalign_for_aligned_access (dr_vec_info *dr_info)
+{
+ if (tree_int_cst_sgn (DR_STEP (dr_info->dr)) >= 0)
+ return 0;
+
+ tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt);
+ poly_int64 misalignment
+ = ((TYPE_VECTOR_SUBPARTS (vectype) - 1)
+ * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (vectype))));
+
+ unsigned HOST_WIDE_INT target_alignment_c;
+ int misalign;
+ if (!dr_info->target_alignment.is_constant (&target_alignment_c)
+ || !known_misalignment (misalignment, target_alignment_c, &misalign))
+ return DR_MISALIGNMENT_UNKNOWN;
+ return misalign;
+}
+
/* Function vect_update_misalignment_for_peel.
Sets DR_INFO's misalignment
- to 0 if it has the same alignment as DR_PEEL_INFO,
@@ -1232,19 +1256,22 @@ vect_update_misalignment_for_peel (dr_vec_info *dr_info,
/* If dr_info is aligned of dr_peel_info is, then mark it so. */
if (vect_dr_aligned_if_peeled_dr_is (dr_info, dr_peel_info))
{
- SET_DR_MISALIGNMENT (dr_info, 0);
+ SET_DR_MISALIGNMENT (dr_info,
+ vect_dr_misalign_for_aligned_access (dr_peel_info));
return;
}
unsigned HOST_WIDE_INT alignment;
if (DR_TARGET_ALIGNMENT (dr_info).is_constant (&alignment)
- && known_alignment_for_access_p (dr_info)
- && known_alignment_for_access_p (dr_peel_info))
+ && known_alignment_for_access_p (dr_info,
+ STMT_VINFO_VECTYPE (dr_info->stmt))
+ && known_alignment_for_access_p (dr_peel_info,
+ STMT_VINFO_VECTYPE (dr_peel_info->stmt)))
{
- int misal = DR_MISALIGNMENT (dr_info);
+ int misal = dr_info->misalignment;
misal += npeel * TREE_INT_CST_LOW (DR_STEP (dr_info->dr));
misal &= alignment - 1;
- SET_DR_MISALIGNMENT (dr_info, misal);
+ set_dr_misalignment (dr_info, misal);
return;
}
@@ -1316,13 +1343,13 @@ vector_alignment_reachable_p (dr_vec_info *dr_info)
int elem_size, mis_in_elements;
/* FORNOW: handle only known alignment. */
- if (!known_alignment_for_access_p (dr_info))
+ if (!known_alignment_for_access_p (dr_info, vectype))
return false;
poly_uint64 nelements = TYPE_VECTOR_SUBPARTS (vectype);
poly_uint64 vector_size = GET_MODE_SIZE (TYPE_MODE (vectype));
elem_size = vector_element_size (vector_size, nelements);
- mis_in_elements = DR_MISALIGNMENT (dr_info) / elem_size;
+ mis_in_elements = dr_misalignment (dr_info, vectype) / elem_size;
if (!multiple_p (nelements - mis_in_elements, DR_GROUP_SIZE (stmt_info)))
return false;
@@ -1330,7 +1357,8 @@ vector_alignment_reachable_p (dr_vec_info *dr_info)
/* If misalignment is known at the compile time then allow peeling
only if natural alignment is reachable through peeling. */
- if (known_alignment_for_access_p (dr_info) && !aligned_access_p (dr_info))
+ if (known_alignment_for_access_p (dr_info, vectype)
+ && !aligned_access_p (dr_info, vectype))
{
HOST_WIDE_INT elmsize =
int_cst_value (TYPE_SIZE_UNIT (TREE_TYPE (vectype)));
@@ -1338,9 +1366,9 @@ vector_alignment_reachable_p (dr_vec_info *dr_info)
{
dump_printf_loc (MSG_NOTE, vect_location,
"data size = %wd. misalignment = %d.\n", elmsize,
- DR_MISALIGNMENT (dr_info));
+ dr_misalignment (dr_info, vectype));
}
- if (DR_MISALIGNMENT (dr_info) % elmsize)
+ if (dr_misalignment (dr_info, vectype) % elmsize)
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -1349,7 +1377,7 @@ vector_alignment_reachable_p (dr_vec_info *dr_info)
}
}
- if (!known_alignment_for_access_p (dr_info))
+ if (!known_alignment_for_access_p (dr_info, vectype))
{
tree type = TREE_TYPE (DR_REF (dr_info->dr));
bool is_packed = not_size_aligned (DR_REF (dr_info->dr));
@@ -1441,8 +1469,9 @@ vect_peeling_hash_insert (hash_table<peel_info_hasher> *peeling_htab,
{
struct _vect_peel_info elem, *slot;
_vect_peel_info **new_slot;
+ tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt);
bool supportable_dr_alignment
- = vect_supportable_dr_alignment (loop_vinfo, dr_info, true);
+ = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, true);
elem.npeel = npeel;
slot = peeling_htab->find (&elem);
@@ -1487,7 +1516,8 @@ vect_peeling_hash_get_most_frequent (_vect_peel_info **slot,
/* Get the costs of peeling NPEEL iterations for LOOP_VINFO, checking
data access costs for all data refs. If UNKNOWN_MISALIGNMENT is true,
- we assume DR0_INFO's misalignment will be zero after peeling. */
+ npeel is computed at runtime but DR0_INFO's misalignment will be zero
+ after peeling. */
static void
vect_get_peeling_costs_all_drs (loop_vec_info loop_vinfo,
@@ -1508,11 +1538,12 @@ vect_get_peeling_costs_all_drs (loop_vec_info loop_vinfo,
continue;
int save_misalignment;
- save_misalignment = DR_MISALIGNMENT (dr_info);
+ save_misalignment = dr_info->misalignment;
if (npeel == 0)
;
else if (unknown_misalignment && dr_info == dr0_info)
- SET_DR_MISALIGNMENT (dr_info, 0);
+ SET_DR_MISALIGNMENT (dr_info,
+ vect_dr_misalign_for_aligned_access (dr0_info));
else
vect_update_misalignment_for_peel (dr_info, dr0_info, npeel);
vect_get_data_access_cost (loop_vinfo, dr_info, inside_cost, outside_cost,
@@ -1625,10 +1656,11 @@ vect_peeling_supportable (loop_vec_info loop_vinfo, dr_vec_info *dr0_info,
if (!vect_relevant_for_alignment_p (dr_info))
continue;
- save_misalignment = DR_MISALIGNMENT (dr_info);
+ save_misalignment = dr_info->misalignment;
vect_update_misalignment_for_peel (dr_info, dr0_info, npeel);
+ tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt);
supportable_dr_alignment
- = vect_supportable_dr_alignment (loop_vinfo, dr_info, false);
+ = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, false);
SET_DR_MISALIGNMENT (dr_info, save_misalignment);
if (!supportable_dr_alignment)
@@ -1782,7 +1814,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
bool one_misalignment_unknown = false;
bool one_dr_unsupportable = false;
dr_vec_info *unsupportable_dr_info = NULL;
- unsigned int mis, dr0_same_align_drs = 0, first_store_same_align_drs = 0;
+ unsigned int dr0_same_align_drs = 0, first_store_same_align_drs = 0;
hash_table<peel_info_hasher> peeling_htab (1);
DUMP_VECT_SCOPE ("vect_enhance_data_refs_alignment");
@@ -1878,12 +1910,13 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
continue;
stmt_vec_info stmt_info = dr_info->stmt;
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
supportable_dr_alignment
- = vect_supportable_dr_alignment (loop_vinfo, dr_info, true);
+ = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, true);
do_peeling = vector_alignment_reachable_p (dr_info);
if (do_peeling)
{
- if (known_alignment_for_access_p (dr_info))
+ if (known_alignment_for_access_p (dr_info, vectype))
{
unsigned int npeel_tmp = 0;
bool negative = tree_int_cst_compare (DR_STEP (dr),
@@ -1896,10 +1929,9 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
unsigned int target_align =
DR_TARGET_ALIGNMENT (dr_info).to_constant ();
unsigned int dr_size = vect_get_scalar_dr_size (dr_info);
- mis = (negative
- ? DR_MISALIGNMENT (dr_info)
- : -DR_MISALIGNMENT (dr_info));
- if (DR_MISALIGNMENT (dr_info) != 0)
+ unsigned int mis = dr_misalignment (dr_info, vectype);
+ mis = negative ? mis : -mis;
+ if (mis != 0)
npeel_tmp = (mis & (target_align - 1)) / dr_size;
/* For multiple types, it is possible that the bigger type access
@@ -1982,7 +2014,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
}
else
{
- if (!aligned_access_p (dr_info))
+ if (!aligned_access_p (dr_info, vectype))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -2152,7 +2184,8 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
if (do_peeling)
{
stmt_vec_info stmt_info = dr0_info->stmt;
- if (known_alignment_for_access_p (dr0_info))
+ if (known_alignment_for_access_p (dr0_info,
+ STMT_VINFO_VECTYPE (stmt_info)))
{
bool negative = tree_int_cst_compare (DR_STEP (dr0_info->dr),
size_zero_node) < 0;
@@ -2163,9 +2196,9 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
updating DR_MISALIGNMENT values. The peeling factor is the
vectorization factor minus the misalignment as an element
count. */
- mis = (negative
- ? DR_MISALIGNMENT (dr0_info)
- : -DR_MISALIGNMENT (dr0_info));
+ unsigned int mis
+ = dr_misalignment (dr0_info, STMT_VINFO_VECTYPE (stmt_info));
+ mis = negative ? mis : -mis;
/* If known_alignment_for_access_p then we have set
DR_MISALIGNMENT which is only done if we know it at compiler
time, so it is safe to assume target alignment is constant.
@@ -2192,7 +2225,10 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
do_peeling = false;
/* Check if all datarefs are supportable and log. */
- if (do_peeling && known_alignment_for_access_p (dr0_info) && npeel == 0)
+ if (do_peeling
+ && npeel == 0
+ && known_alignment_for_access_p (dr0_info,
+ STMT_VINFO_VECTYPE (stmt_info)))
return opt_result::success ();
/* Cost model #1 - honor --param vect-max-peeling-for-alignment. */
@@ -2269,7 +2305,8 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) = npeel;
else
LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) = -1;
- SET_DR_MISALIGNMENT (dr0_info, 0);
+ SET_DR_MISALIGNMENT (dr0_info,
+ vect_dr_misalign_for_aligned_access (dr0_info));
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location,
@@ -2304,11 +2341,12 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
FOR_EACH_VEC_ELT (datarefs, i, dr)
{
dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr);
- if (aligned_access_p (dr_info)
+ stmt_vec_info stmt_info = dr_info->stmt;
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+ if (aligned_access_p (dr_info, vectype)
|| !vect_relevant_for_alignment_p (dr_info))
continue;
- stmt_vec_info stmt_info = dr_info->stmt;
if (STMT_VINFO_STRIDED_P (stmt_info))
{
do_versioning = false;
@@ -2316,14 +2354,11 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
}
supportable_dr_alignment
- = vect_supportable_dr_alignment (loop_vinfo, dr_info, false);
-
+ = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype,
+ false);
if (!supportable_dr_alignment)
{
- int mask;
- tree vectype;
-
- if (known_alignment_for_access_p (dr_info)
+ if (known_alignment_for_access_p (dr_info, vectype)
|| LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo).length ()
>= (unsigned) param_vect_max_version_for_alignment_checks)
{
@@ -2331,9 +2366,6 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
break;
}
- vectype = STMT_VINFO_VECTYPE (stmt_info);
- gcc_assert (vectype);
-
/* At present we don't support versioning for alignment
with variable VF, since there's no guarantee that the
VF is a power of two. We could relax this if we added
@@ -2363,7 +2395,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
Construct the mask needed for this test. For example,
GET_MODE_SIZE for the vector mode V4SI is 16 bytes so the
mask must be 15 = 0xf. */
- mask = size - 1;
+ int mask = size - 1;
/* FORNOW: use the same mask to test all potentially unaligned
references in the loop. */
@@ -2398,7 +2430,8 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
FOR_EACH_VEC_ELT (may_misalign_stmts, i, stmt_info)
{
dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
- SET_DR_MISALIGNMENT (dr_info, 0);
+ SET_DR_MISALIGNMENT (dr_info,
+ vect_dr_misalign_for_aligned_access (dr_info));
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"Alignment of access forced using versioning.\n");
@@ -2444,7 +2477,8 @@ vect_analyze_data_refs_alignment (loop_vec_info loop_vinfo)
if (STMT_VINFO_GROUPED_ACCESS (dr_info->stmt)
&& DR_GROUP_FIRST_ELEMENT (dr_info->stmt) != dr_info->stmt)
continue;
- vect_compute_data_ref_alignment (loop_vinfo, dr_info);
+ vect_compute_data_ref_alignment (loop_vinfo, dr_info,
+ STMT_VINFO_VECTYPE (dr_info->stmt));
}
}
@@ -2460,21 +2494,30 @@ vect_slp_analyze_node_alignment (vec_info *vinfo, slp_tree node)
/* Alignment is maintained in the first element of the group. */
stmt_vec_info first_stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
first_stmt_info = DR_GROUP_FIRST_ELEMENT (first_stmt_info);
-
- /* We need to commit to a vector type for the group now. */
- if (is_a <bb_vec_info> (vinfo)
- && !vect_update_shared_vectype (first_stmt_info, SLP_TREE_VECTYPE (node)))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "desired vector type conflicts with earlier one "
- "for %G", first_stmt_info->stmt);
- return false;
- }
-
dr_vec_info *dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
+ tree vectype = SLP_TREE_VECTYPE (node);
+ poly_uint64 vector_alignment
+ = exact_div (targetm.vectorize.preferred_vector_alignment (vectype),
+ BITS_PER_UNIT);
if (dr_info->misalignment == DR_MISALIGNMENT_UNINITIALIZED)
- vect_compute_data_ref_alignment (vinfo, dr_info);
+ vect_compute_data_ref_alignment (vinfo, dr_info, SLP_TREE_VECTYPE (node));
+ /* Re-analyze alignment when we're facing a vectorization with a bigger
+ alignment requirement. */
+ else if (known_lt (dr_info->target_alignment, vector_alignment))
+ {
+ poly_uint64 old_target_alignment = dr_info->target_alignment;
+ int old_misalignment = dr_info->misalignment;
+ vect_compute_data_ref_alignment (vinfo, dr_info, SLP_TREE_VECTYPE (node));
+ /* But keep knowledge about a smaller alignment. */
+ if (old_misalignment != DR_MISALIGNMENT_UNKNOWN
+ && dr_info->misalignment == DR_MISALIGNMENT_UNKNOWN)
+ {
+ dr_info->target_alignment = old_target_alignment;
+ dr_info->misalignment = old_misalignment;
+ }
+ }
+ /* When we ever face unordered target alignments the first one wins in terms
+ of analyzing and the other will become unknown in dr_misalignment. */
return true;
}
@@ -3259,12 +3302,12 @@ vect_vfa_access_size (vec_info *vinfo, dr_vec_info *dr_info)
gcc_assert (DR_GROUP_FIRST_ELEMENT (stmt_vinfo) == stmt_vinfo);
access_size *= DR_GROUP_SIZE (stmt_vinfo) - DR_GROUP_GAP (stmt_vinfo);
}
+ tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
if (STMT_VINFO_VEC_STMTS (stmt_vinfo).exists ()
- && (vect_supportable_dr_alignment (vinfo, dr_info, false)
+ && (vect_supportable_dr_alignment (vinfo, dr_info, vectype, false)
== dr_explicit_realign_optimized))
{
/* We might access a full vector's worth. */
- tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
access_size += tree_to_uhwi (TYPE_SIZE_UNIT (vectype)) - ref_size;
}
return access_size;
@@ -4629,12 +4672,15 @@ vect_get_new_ssa_name (tree type, enum vect_var_kind var_kind, const char *name)
return new_vect_var;
}
-/* Duplicate ptr info and set alignment/misaligment on NAME from DR_INFO. */
+/* Duplicate points-to info on NAME from DR_INFO. */
static void
vect_duplicate_ssa_name_ptr_info (tree name, dr_vec_info *dr_info)
{
duplicate_ssa_name_ptr_info (name, DR_PTR_INFO (dr_info->dr));
+ /* DR_PTR_INFO is for a base SSA name, not including constant or
+ variable offsets in the ref so its alignment info does not apply. */
+ mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (name));
}
/* Function vect_create_addr_base_for_vector_ref.
@@ -4730,7 +4776,7 @@ vect_create_addr_base_for_vector_ref (vec_info *vinfo, stmt_vec_info stmt_info,
unshare_expr (DR_REF (dr)));
}
- vect_ptr_type = build_pointer_type (STMT_VINFO_VECTYPE (stmt_info));
+ vect_ptr_type = build_pointer_type (TREE_TYPE (DR_REF (dr)));
dest = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var, base_name);
addr_base = force_gimple_operand (addr_base, &seq, true, dest);
gimple_seq_add_seq (new_stmt_list, seq);
@@ -4738,11 +4784,7 @@ vect_create_addr_base_for_vector_ref (vec_info *vinfo, stmt_vec_info stmt_info,
if (DR_PTR_INFO (dr)
&& TREE_CODE (addr_base) == SSA_NAME
&& !SSA_NAME_PTR_INFO (addr_base))
- {
- vect_duplicate_ssa_name_ptr_info (addr_base, dr_info);
- if (offset || byte_offset)
- mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (addr_base));
- }
+ vect_duplicate_ssa_name_ptr_info (addr_base, dr_info);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "created %T\n", addr_base);
@@ -6581,17 +6623,16 @@ vect_can_force_dr_alignment_p (const_tree decl, poly_uint64 alignment)
enum dr_alignment_support
vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info,
- bool check_aligned_accesses)
+ tree vectype, bool check_aligned_accesses)
{
data_reference *dr = dr_info->dr;
stmt_vec_info stmt_info = dr_info->stmt;
- tree vectype = STMT_VINFO_VECTYPE (stmt_info);
machine_mode mode = TYPE_MODE (vectype);
loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
class loop *vect_loop = NULL;
bool nested_in_vect_loop = false;
- if (aligned_access_p (dr_info) && !check_aligned_accesses)
+ if (aligned_access_p (dr_info, vectype) && !check_aligned_accesses)
return dr_aligned;
/* For now assume all conditional loads/stores support unaligned
@@ -6680,8 +6721,6 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info,
&& (!targetm.vectorize.builtin_mask_for_load
|| targetm.vectorize.builtin_mask_for_load ()))
{
- tree vectype = STMT_VINFO_VECTYPE (stmt_info);
-
/* If we are doing SLP then the accesses need not have the
same alignment, instead it depends on the SLP group size. */
if (loop_vinfo
@@ -6699,11 +6738,11 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info,
else
return dr_explicit_realign_optimized;
}
- if (!known_alignment_for_access_p (dr_info))
+ if (!known_alignment_for_access_p (dr_info, vectype))
is_packed = not_size_aligned (DR_REF (dr));
if (targetm.vectorize.support_vector_misalignment
- (mode, type, DR_MISALIGNMENT (dr_info), is_packed))
+ (mode, type, dr_misalignment (dr_info, vectype), is_packed))
/* Can't software pipeline the loads, but can at least do them. */
return dr_unaligned_supported;
}
@@ -6712,11 +6751,11 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info,
bool is_packed = false;
tree type = (TREE_TYPE (DR_REF (dr)));
- if (!known_alignment_for_access_p (dr_info))
+ if (!known_alignment_for_access_p (dr_info, vectype))
is_packed = not_size_aligned (DR_REF (dr));
if (targetm.vectorize.support_vector_misalignment
- (mode, type, DR_MISALIGNMENT (dr_info), is_packed))
+ (mode, type, dr_misalignment (dr_info, vectype), is_packed))
return dr_unaligned_supported;
}
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 024a1c3..c70d06e 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -779,56 +779,6 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char swap,
return 0;
}
-/* Try to assign vector type VECTYPE to STMT_INFO for BB vectorization.
- Return true if we can, meaning that this choice doesn't conflict with
- existing SLP nodes that use STMT_INFO. */
-
-bool
-vect_update_shared_vectype (stmt_vec_info stmt_info, tree vectype)
-{
- tree old_vectype = STMT_VINFO_VECTYPE (stmt_info);
- if (old_vectype)
- return useless_type_conversion_p (vectype, old_vectype);
-
- if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
- {
- /* We maintain the invariant that if any statement in the group is
- used, all other members of the group have the same vector type. */
- stmt_vec_info first_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
- stmt_vec_info member_info = first_info;
- for (; member_info; member_info = DR_GROUP_NEXT_ELEMENT (member_info))
- if (is_pattern_stmt_p (member_info)
- && !useless_type_conversion_p (vectype,
- STMT_VINFO_VECTYPE (member_info)))
- break;
-
- if (!member_info)
- {
- for (member_info = first_info; member_info;
- member_info = DR_GROUP_NEXT_ELEMENT (member_info))
- STMT_VINFO_VECTYPE (member_info) = vectype;
- return true;
- }
- }
- else if (!is_pattern_stmt_p (stmt_info))
- {
- STMT_VINFO_VECTYPE (stmt_info) = vectype;
- return true;
- }
-
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: incompatible vector"
- " types for: %G", stmt_info->stmt);
- dump_printf_loc (MSG_NOTE, vect_location,
- " old vector type: %T\n", old_vectype);
- dump_printf_loc (MSG_NOTE, vect_location,
- " new vector type: %T\n", vectype);
- }
- return false;
-}
-
/* Return true if call statements CALL1 and CALL2 are similar enough
to be combined into the same SLP group. */
@@ -4508,15 +4458,6 @@ vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node,
return vectorizable_slp_permutation (vinfo, NULL, node, cost_vec);
gcc_assert (STMT_SLP_TYPE (stmt_info) != loop_vect);
- if (is_a <bb_vec_info> (vinfo)
- && !vect_update_shared_vectype (stmt_info, SLP_TREE_VECTYPE (node)))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "desired vector type conflicts with earlier one "
- "for %G", stmt_info->stmt);
- return false;
- }
bool dummy;
return vect_analyze_stmt (vinfo, stmt_info, &dummy,
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 17849b5..a9c9e3d 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1026,8 +1026,9 @@ vect_get_store_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies,
stmt_vector_for_cost *body_cost_vec)
{
dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
int alignment_support_scheme
- = vect_supportable_dr_alignment (vinfo, dr_info, false);
+ = vect_supportable_dr_alignment (vinfo, dr_info, vectype, false);
switch (alignment_support_scheme)
{
@@ -1048,7 +1049,7 @@ vect_get_store_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies,
/* Here, we assign an additional cost for the unaligned store. */
*inside_cost += record_stmt_cost (body_cost_vec, ncopies,
unaligned_store, stmt_info,
- DR_MISALIGNMENT (dr_info),
+ dr_misalignment (dr_info, vectype),
vect_body);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -1216,8 +1217,9 @@ vect_get_load_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies,
bool record_prologue_costs)
{
dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
int alignment_support_scheme
- = vect_supportable_dr_alignment (vinfo, dr_info, false);
+ = vect_supportable_dr_alignment (vinfo, dr_info, vectype, false);
switch (alignment_support_scheme)
{
@@ -1237,7 +1239,7 @@ vect_get_load_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies,
/* Here, we assign an additional cost for the unaligned load. */
*inside_cost += record_stmt_cost (body_cost_vec, ncopies,
unaligned_load, stmt_info,
- DR_MISALIGNMENT (dr_info),
+ dr_misalignment (dr_info, vectype),
vect_body);
if (dump_enabled_p ())
@@ -1984,8 +1986,8 @@ get_negative_load_store_type (vec_info *vinfo,
return VMAT_ELEMENTWISE;
}
- alignment_support_scheme = vect_supportable_dr_alignment (vinfo,
- dr_info, false);
+ alignment_support_scheme = vect_supportable_dr_alignment (vinfo, dr_info,
+ vectype, false);
if (alignment_support_scheme != dr_aligned
&& alignment_support_scheme != dr_unaligned_supported)
{
@@ -2169,7 +2171,8 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
be a multiple of B and so we are guaranteed to access a
non-gap element in the same B-sized block. */
if (overrun_p
- && gap < (vect_known_alignment_in_bytes (first_dr_info)
+ && gap < (vect_known_alignment_in_bytes (first_dr_info,
+ vectype)
/ vect_get_scalar_dr_size (first_dr_info)))
overrun_p = false;
@@ -2182,8 +2185,8 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
if (overrun_p
&& !masked_p
&& (((alignment_support_scheme
- = vect_supportable_dr_alignment (vinfo,
- first_dr_info, false)))
+ = vect_supportable_dr_alignment (vinfo, first_dr_info,
+ vectype, false)))
== dr_aligned
|| alignment_support_scheme == dr_unaligned_supported)
&& known_eq (nunits, (group_size - gap) * 2)
@@ -2240,7 +2243,7 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
same B-sized block. */
if (would_overrun_p
&& !masked_p
- && gap < (vect_known_alignment_in_bytes (first_dr_info)
+ && gap < (vect_known_alignment_in_bytes (first_dr_info, vectype)
/ vect_get_scalar_dr_size (first_dr_info)))
would_overrun_p = false;
@@ -2294,7 +2297,7 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
*alignment_support_scheme = dr_unaligned_supported;
else
*alignment_support_scheme
- = vect_supportable_dr_alignment (vinfo, first_dr_info, false);
+ = vect_supportable_dr_alignment (vinfo, first_dr_info, vectype, false);
if (vls_type != VLS_LOAD && first_stmt_info == stmt_info)
{
@@ -2435,7 +2438,7 @@ get_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
*alignment_support_scheme
= vect_supportable_dr_alignment (vinfo,
STMT_VINFO_DR_INFO (stmt_info),
- false);
+ vectype, false);
}
}
@@ -7907,7 +7910,7 @@ vectorizable_store (vec_info *vinfo,
alignment_support_scheme = dr_unaligned_supported;
else
alignment_support_scheme
- = vect_supportable_dr_alignment (vinfo, first_dr_info, false);
+ = vect_supportable_dr_alignment (vinfo, first_dr_info, vectype, false);
gcc_assert (alignment_support_scheme);
vec_loop_masks *loop_masks
@@ -8218,15 +8221,16 @@ vectorizable_store (vec_info *vinfo,
vec_oprnd = result_chain[i];
align = known_alignment (DR_TARGET_ALIGNMENT (first_dr_info));
- if (aligned_access_p (first_dr_info))
+ if (aligned_access_p (first_dr_info, vectype))
misalign = 0;
- else if (DR_MISALIGNMENT (first_dr_info) == -1)
+ else if (dr_misalignment (first_dr_info, vectype)
+ == DR_MISALIGNMENT_UNKNOWN)
{
align = dr_alignment (vect_dr_behavior (vinfo, first_dr_info));
misalign = 0;
}
else
- misalign = DR_MISALIGNMENT (first_dr_info);
+ misalign = dr_misalignment (first_dr_info, vectype);
if (dataref_offset == NULL_TREE
&& TREE_CODE (dataref_ptr) == SSA_NAME)
set_ptr_info_alignment (get_ptr_info (dataref_ptr), align,
@@ -8303,7 +8307,7 @@ vectorizable_store (vec_info *vinfo,
dataref_offset
? dataref_offset
: build_int_cst (ref_type, 0));
- if (aligned_access_p (first_dr_info))
+ if (aligned_access_p (first_dr_info, vectype))
;
else
TREE_TYPE (data_ref)
@@ -9551,17 +9555,17 @@ vectorizable_load (vec_info *vinfo,
known_alignment (DR_TARGET_ALIGNMENT (first_dr_info));
if (alignment_support_scheme == dr_aligned)
{
- gcc_assert (aligned_access_p (first_dr_info));
+ gcc_assert (aligned_access_p (first_dr_info, vectype));
misalign = 0;
}
- else if (DR_MISALIGNMENT (first_dr_info) == -1)
+ else if (dr_misalignment (first_dr_info, vectype) == -1)
{
align = dr_alignment
(vect_dr_behavior (vinfo, first_dr_info));
misalign = 0;
}
else
- misalign = DR_MISALIGNMENT (first_dr_info);
+ misalign = dr_misalignment (first_dr_info, vectype);
if (dataref_offset == NULL_TREE
&& TREE_CODE (dataref_ptr) == SSA_NAME)
set_ptr_info_alignment (get_ptr_info (dataref_ptr),
@@ -9624,7 +9628,8 @@ vectorizable_load (vec_info *vinfo,
unsigned HOST_WIDE_INT gap
= DR_GROUP_GAP (first_stmt_info);
unsigned int vect_align
- = vect_known_alignment_in_bytes (first_dr_info);
+ = vect_known_alignment_in_bytes (first_dr_info,
+ vectype);
unsigned int scalar_dr_size
= vect_get_scalar_dr_size (first_dr_info);
/* If there's no peeling for gaps but we have a gap
@@ -10897,6 +10902,10 @@ vect_analyze_stmt (vec_info *vinfo,
gcc_unreachable ();
}
+ tree saved_vectype = STMT_VINFO_VECTYPE (stmt_info);
+ if (node)
+ STMT_VINFO_VECTYPE (stmt_info) = SLP_TREE_VECTYPE (node);
+
if (STMT_VINFO_RELEVANT_P (stmt_info))
{
gcall *call = dyn_cast <gcall *> (stmt_info->stmt);
@@ -10967,6 +10976,9 @@ vect_analyze_stmt (vec_info *vinfo,
|| vectorizable_phi (vinfo, stmt_info, NULL, node, cost_vec));
}
+ if (node)
+ STMT_VINFO_VECTYPE (stmt_info) = saved_vectype;
+
if (!ok)
return opt_result::failure_at (stmt_info->stmt,
"not vectorized:"
@@ -11005,6 +11017,10 @@ vect_transform_stmt (vec_info *vinfo,
gcc_assert (slp_node || !PURE_SLP_STMT (stmt_info));
+ tree saved_vectype = STMT_VINFO_VECTYPE (stmt_info);
+ if (slp_node)
+ STMT_VINFO_VECTYPE (stmt_info) = SLP_TREE_VECTYPE (slp_node);
+
switch (STMT_VINFO_TYPE (stmt_info))
{
case type_demotion_vec_info_type:
@@ -11123,16 +11139,19 @@ vect_transform_stmt (vec_info *vinfo,
if (!slp_node && vec_stmt)
gcc_assert (STMT_VINFO_VEC_STMTS (stmt_info).exists ());
- if (STMT_VINFO_TYPE (stmt_info) == store_vec_info_type)
- return is_store;
+ if (STMT_VINFO_TYPE (stmt_info) != store_vec_info_type)
+ {
+ /* Handle stmts whose DEF is used outside the loop-nest that is
+ being vectorized. */
+ done = can_vectorize_live_stmts (vinfo, stmt_info, gsi, slp_node,
+ slp_node_instance, true, NULL);
+ gcc_assert (done);
+ }
- /* Handle stmts whose DEF is used outside the loop-nest that is
- being vectorized. */
- done = can_vectorize_live_stmts (vinfo, stmt_info, gsi, slp_node,
- slp_node_instance, true, NULL);
- gcc_assert (done);
+ if (slp_node)
+ STMT_VINFO_VECTYPE (stmt_info) = saved_vectype;
- return false;
+ return is_store;
}
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index c4c5678..ed4a7ff 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -1606,11 +1606,8 @@ set_dr_misalignment (dr_vec_info *dr_info, int val)
dr_info->misalignment = val;
}
-extern int dr_misalignment (dr_vec_info *dr_info);
+extern int dr_misalignment (dr_vec_info *dr_info, tree vectype);
-/* Reflects actual alignment of first access in the vectorized loop,
- taking into account peeling/versioning if applied. */
-#define DR_MISALIGNMENT(DR) dr_misalignment (DR)
#define SET_DR_MISALIGNMENT(DR, VAL) set_dr_misalignment (DR, VAL)
/* Only defined once DR_MISALIGNMENT is defined. */
@@ -1630,35 +1627,37 @@ set_dr_target_alignment (dr_vec_info *dr_info, poly_uint64 val)
}
#define SET_DR_TARGET_ALIGNMENT(DR, VAL) set_dr_target_alignment (DR, VAL)
-/* Return true if data access DR_INFO is aligned to its target alignment
- (which may be less than a full vector). */
+/* Return true if data access DR_INFO is aligned to the targets
+ preferred alignment for VECTYPE (which may be less than a full vector). */
static inline bool
-aligned_access_p (dr_vec_info *dr_info)
+aligned_access_p (dr_vec_info *dr_info, tree vectype)
{
- return (DR_MISALIGNMENT (dr_info) == 0);
+ return (dr_misalignment (dr_info, vectype) == 0);
}
-/* Return TRUE if the alignment of the data access is known, and FALSE
+/* Return TRUE if the (mis-)alignment of the data access is known with
+ respect to the targets preferred alignment for VECTYPE, and FALSE
otherwise. */
static inline bool
-known_alignment_for_access_p (dr_vec_info *dr_info)
+known_alignment_for_access_p (dr_vec_info *dr_info, tree vectype)
{
- return (DR_MISALIGNMENT (dr_info) != DR_MISALIGNMENT_UNKNOWN);
+ return (dr_misalignment (dr_info, vectype) != DR_MISALIGNMENT_UNKNOWN);
}
/* Return the minimum alignment in bytes that the vectorized version
of DR_INFO is guaranteed to have. */
static inline unsigned int
-vect_known_alignment_in_bytes (dr_vec_info *dr_info)
+vect_known_alignment_in_bytes (dr_vec_info *dr_info, tree vectype)
{
- if (DR_MISALIGNMENT (dr_info) == DR_MISALIGNMENT_UNKNOWN)
+ int misalignment = dr_misalignment (dr_info, vectype);
+ if (misalignment == DR_MISALIGNMENT_UNKNOWN)
return TYPE_ALIGN_UNIT (TREE_TYPE (DR_REF (dr_info->dr)));
- if (DR_MISALIGNMENT (dr_info) == 0)
+ else if (misalignment == 0)
return known_alignment (DR_TARGET_ALIGNMENT (dr_info));
- return DR_MISALIGNMENT (dr_info) & -DR_MISALIGNMENT (dr_info);
+ return misalignment & -misalignment;
}
/* Return the behavior of DR_INFO with respect to the vectorization context
@@ -1971,7 +1970,7 @@ extern opt_tree vect_get_mask_type_for_stmt (stmt_vec_info, unsigned int = 0);
/* In tree-vect-data-refs.c. */
extern bool vect_can_force_dr_alignment_p (const_tree, poly_uint64);
extern enum dr_alignment_support vect_supportable_dr_alignment
- (vec_info *, dr_vec_info *, bool);
+ (vec_info *, dr_vec_info *, tree, bool);
extern tree vect_get_smallest_scalar_type (stmt_vec_info, tree);
extern opt_result vect_analyze_data_ref_dependences (loop_vec_info, unsigned int *);
extern bool vect_slp_analyze_instance_dependence (vec_info *, slp_instance);
@@ -2110,7 +2109,6 @@ extern bool can_duplicate_and_interleave_p (vec_info *, unsigned int, tree,
extern void duplicate_and_interleave (vec_info *, gimple_seq *, tree,
const vec<tree> &, unsigned int, vec<tree> &);
extern int vect_get_place_in_interleaving_chain (stmt_vec_info, stmt_vec_info);
-extern bool vect_update_shared_vectype (stmt_vec_info, tree);
extern slp_tree vect_create_new_slp_node (unsigned, tree_code);
extern void vect_free_slp_tree (slp_tree);
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 26e71e7..c24c67f 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -21,51 +21,34 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "backend.h"
-#include "insn-codes.h"
-#include "rtl.h"
+#include "basic-block.h"
+#include "bitmap.h"
+#include "sbitmap.h"
+#include "options.h"
+#include "dominance.h"
+#include "function.h"
+#include "cfg.h"
#include "tree.h"
#include "gimple.h"
-#include "cfghooks.h"
#include "tree-pass.h"
#include "ssa.h"
-#include "optabs-tree.h"
#include "gimple-pretty-print.h"
-#include "flags.h"
#include "fold-const.h"
-#include "stor-layout.h"
-#include "calls.h"
#include "cfganal.h"
-#include "gimple-fold.h"
-#include "tree-eh.h"
#include "gimple-iterator.h"
-#include "gimple-walk.h"
#include "tree-cfg.h"
#include "tree-ssa-loop-manip.h"
#include "tree-ssa-loop-niter.h"
-#include "tree-ssa-loop.h"
#include "tree-into-ssa.h"
-#include "tree-ssa.h"
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
#include "tree-ssa-propagate.h"
-#include "tree-chrec.h"
-#include "tree-ssa-threadupdate.h"
-#include "tree-ssa-scopedtables.h"
#include "tree-ssa-threadedge.h"
-#include "omp-general.h"
-#include "target.h"
-#include "case-cfn-macros.h"
-#include "alloc-pool.h"
#include "domwalk.h"
-#include "tree-cfgcleanup.h"
-#include "stringpool.h"
-#include "attribs.h"
#include "vr-values.h"
-#include "builtins.h"
-#include "range-op.h"
-#include "value-range-equiv.h"
#include "gimple-array-bounds.h"
+#include "gimple-range.h"
+#include "gimple-range-path.h"
/* Set of SSA names found live during the RPO traversal of the function
for still active basic-blocks. */
@@ -2346,34 +2329,6 @@ stmt_interesting_for_vrp (gimple *stmt)
return false;
}
-
-/* Return the LHS of any ASSERT_EXPR where OP appears as the first
- argument to the ASSERT_EXPR and in which the ASSERT_EXPR dominates
- BB. If no such ASSERT_EXPR is found, return OP. */
-
-static tree
-lhs_of_dominating_assert (tree op, basic_block bb, gimple *stmt)
-{
- imm_use_iterator imm_iter;
- gimple *use_stmt;
- use_operand_p use_p;
-
- if (TREE_CODE (op) == SSA_NAME)
- {
- FOR_EACH_IMM_USE_FAST (use_p, imm_iter, op)
- {
- use_stmt = USE_STMT (use_p);
- if (use_stmt != stmt
- && gimple_assign_single_p (use_stmt)
- && TREE_CODE (gimple_assign_rhs1 (use_stmt)) == ASSERT_EXPR
- && TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0) == op
- && dominated_by_p (CDI_DOMINATORS, bb, gimple_bb (use_stmt)))
- return gimple_assign_lhs (use_stmt);
- }
- }
- return op;
-}
-
/* Searches the case label vector VEC for the index *IDX of the CASE_LABEL
that includes the value VAL. The search is restricted to the range
[START_IDX, n - 1] where n is the size of VEC.
@@ -4160,200 +4115,6 @@ vrp_folder::fold_stmt (gimple_stmt_iterator *si)
return simplifier.simplify (si);
}
-class vrp_jump_threader_simplifier : public jump_threader_simplifier
-{
-public:
- vrp_jump_threader_simplifier (vr_values *v, avail_exprs_stack *avails)
- : jump_threader_simplifier (v), m_avail_exprs_stack (avails) { }
-
-private:
- tree simplify (gimple *, gimple *, basic_block, jt_state *) OVERRIDE;
- avail_exprs_stack *m_avail_exprs_stack;
-};
-
-tree
-vrp_jump_threader_simplifier::simplify (gimple *stmt,
- gimple *within_stmt,
- basic_block bb,
- jt_state *state)
-{
- /* First see if the conditional is in the hash table. */
- tree cached_lhs = m_avail_exprs_stack->lookup_avail_expr (stmt, false, true);
- if (cached_lhs && is_gimple_min_invariant (cached_lhs))
- return cached_lhs;
-
- if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
- {
- tree op0 = gimple_cond_lhs (cond_stmt);
- op0 = lhs_of_dominating_assert (op0, bb, stmt);
-
- tree op1 = gimple_cond_rhs (cond_stmt);
- op1 = lhs_of_dominating_assert (op1, bb, stmt);
-
- simplify_using_ranges simplifier (m_vr_values);
- return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
- op0, op1, within_stmt);
- }
-
- if (gswitch *switch_stmt = dyn_cast <gswitch *> (stmt))
- {
- tree op = gimple_switch_index (switch_stmt);
- if (TREE_CODE (op) != SSA_NAME)
- return NULL_TREE;
-
- op = lhs_of_dominating_assert (op, bb, stmt);
-
- const value_range_equiv *vr = m_vr_values->get_value_range (op);
- return find_case_label_range (switch_stmt, vr);
- }
-
- return jump_threader_simplifier::simplify (stmt, within_stmt, bb, state);
-}
-
-/* Blocks which have more than one predecessor and more than
- one successor present jump threading opportunities, i.e.,
- when the block is reached from a specific predecessor, we
- may be able to determine which of the outgoing edges will
- be traversed. When this optimization applies, we are able
- to avoid conditionals at runtime and we may expose secondary
- optimization opportunities.
-
- This class is effectively a driver for the generic jump
- threading code. It basically just presents the generic code
- with edges that may be suitable for jump threading.
-
- Unlike DOM, we do not iterate VRP if jump threading was successful.
- While iterating may expose new opportunities for VRP, it is expected
- those opportunities would be very limited and the compile time cost
- to expose those opportunities would be significant.
-
- As jump threading opportunities are discovered, they are registered
- for later realization. */
-
-class vrp_jump_threader : public dom_walker
-{
-public:
- vrp_jump_threader (function *, vr_values *);
- ~vrp_jump_threader ();
-
- void thread_jumps ()
- {
- walk (m_fun->cfg->x_entry_block_ptr);
- }
-
- void thread_through_all_blocks ()
- {
- // FIXME: Put this in the destructor?
- m_threader->thread_through_all_blocks (false);
- }
-
-private:
- virtual edge before_dom_children (basic_block);
- virtual void after_dom_children (basic_block);
-
- function *m_fun;
- vr_values *m_vr_values;
- const_and_copies *m_const_and_copies;
- avail_exprs_stack *m_avail_exprs_stack;
- hash_table<expr_elt_hasher> *m_avail_exprs;
- vrp_jump_threader_simplifier *m_simplifier;
- jump_threader *m_threader;
- jt_state *m_state;
-};
-
-vrp_jump_threader::vrp_jump_threader (struct function *fun, vr_values *v)
- : dom_walker (CDI_DOMINATORS, REACHABLE_BLOCKS)
-{
- /* Ugh. When substituting values earlier in this pass we can wipe
- the dominance information. So rebuild the dominator information
- as we need it within the jump threading code. */
- calculate_dominance_info (CDI_DOMINATORS);
-
- /* We do not allow VRP information to be used for jump threading
- across a back edge in the CFG. Otherwise it becomes too
- difficult to avoid eliminating loop exit tests. Of course
- EDGE_DFS_BACK is not accurate at this time so we have to
- recompute it. */
- mark_dfs_back_edges ();
-
- /* Allocate our unwinder stack to unwind any temporary equivalences
- that might be recorded. */
- m_const_and_copies = new const_and_copies ();
-
- m_fun = fun;
- m_vr_values = v;
- m_avail_exprs = new hash_table<expr_elt_hasher> (1024);
- m_avail_exprs_stack = new avail_exprs_stack (m_avail_exprs);
- m_state = new jt_state (m_const_and_copies, m_avail_exprs_stack, NULL);
-
- m_simplifier = new vrp_jump_threader_simplifier (m_vr_values,
- m_avail_exprs_stack);
- m_threader = new jump_threader (m_simplifier, m_state);
-}
-
-vrp_jump_threader::~vrp_jump_threader ()
-{
- /* We do not actually update the CFG or SSA graphs at this point as
- ASSERT_EXPRs are still in the IL and cfg cleanup code does not
- yet handle ASSERT_EXPRs gracefully. */
- delete m_const_and_copies;
- delete m_avail_exprs;
- delete m_avail_exprs_stack;
- delete m_simplifier;
- delete m_threader;
- delete m_state;
-}
-
-/* Called before processing dominator children of BB. We want to look
- at ASSERT_EXPRs and record information from them in the appropriate
- tables.
-
- We could look at other statements here. It's not seen as likely
- to significantly increase the jump threads we discover. */
-
-edge
-vrp_jump_threader::before_dom_children (basic_block bb)
-{
- gimple_stmt_iterator gsi;
-
- m_avail_exprs_stack->push_marker ();
- m_const_and_copies->push_marker ();
- for (gsi = gsi_start_nondebug_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gimple *stmt = gsi_stmt (gsi);
- if (gimple_assign_single_p (stmt)
- && TREE_CODE (gimple_assign_rhs1 (stmt)) == ASSERT_EXPR)
- {
- tree rhs1 = gimple_assign_rhs1 (stmt);
- tree cond = TREE_OPERAND (rhs1, 1);
- tree inverted = invert_truthvalue (cond);
- vec<cond_equivalence> p;
- p.create (3);
- record_conditions (&p, cond, inverted);
- for (unsigned int i = 0; i < p.length (); i++)
- m_avail_exprs_stack->record_cond (&p[i]);
-
- tree lhs = gimple_assign_lhs (stmt);
- m_const_and_copies->record_const_or_copy (lhs,
- TREE_OPERAND (rhs1, 0));
- p.release ();
- continue;
- }
- break;
- }
- return NULL;
-}
-
-/* Called after processing dominator children of BB. This is where we
- actually call into the threader. */
-void
-vrp_jump_threader::after_dom_children (basic_block bb)
-{
- m_threader->thread_outgoing_edges (bb);
- m_avail_exprs_stack->pop_to_marker ();
- m_const_and_copies->pop_to_marker ();
-}
-
/* STMT is a conditional at the end of a basic block.
If the conditional is of the form SSA_NAME op constant and the SSA_NAME
@@ -4538,11 +4299,6 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p)
array_checker.check ();
}
- /* We must identify jump threading opportunities before we release
- the datastructures built by VRP. */
- vrp_jump_threader threader (fun, &vrp_vr_values);
- threader.thread_jumps ();
-
simplify_casted_conds (fun, &vrp_vr_values);
free_numbers_of_iterations_estimates (fun);
@@ -4552,21 +4308,6 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p)
does not properly handle ASSERT_EXPRs. */
assert_engine.remove_range_assertions ();
- /* If we exposed any new variables, go ahead and put them into
- SSA form now, before we handle jump threading. This simplifies
- interactions between rewriting of _DECL nodes into SSA form
- and rewriting SSA_NAME nodes into SSA form after block
- duplication and CFG manipulation. */
- update_ssa (TODO_update_ssa);
-
- /* We identified all the jump threading opportunities earlier, but could
- not transform the CFG at that time. This routine transforms the
- CFG and arranges for the dominator tree to be rebuilt if necessary.
-
- Note the SSA graph update will occur during the normal TODO
- processing by the pass manager. */
- threader.thread_through_all_blocks ();
-
scev_finalize ();
loop_optimizer_finalize ();
return 0;
@@ -4616,3 +4357,126 @@ make_pass_vrp (gcc::context *ctxt)
{
return new pass_vrp (ctxt);
}
+
+// This is the dom walker for the hybrid threader. The reason this is
+// here, as opposed to the generic threading files, is because the
+// other client would be DOM, and they have their own custom walker.
+
+class hybrid_threader : public dom_walker
+{
+public:
+ hybrid_threader ();
+ ~hybrid_threader ();
+
+ void thread_jumps (function *fun)
+ {
+ walk (fun->cfg->x_entry_block_ptr);
+ }
+ bool thread_through_all_blocks ()
+ {
+ return m_threader->thread_through_all_blocks (false);
+ }
+
+private:
+ edge before_dom_children (basic_block) override;
+ void after_dom_children (basic_block bb) override;
+
+ hybrid_jt_simplifier *m_simplifier;
+ jump_threader *m_threader;
+ jt_state *m_state;
+ gimple_ranger *m_ranger;
+ path_range_query *m_query;
+};
+
+hybrid_threader::hybrid_threader () : dom_walker (CDI_DOMINATORS, REACHABLE_BLOCKS)
+{
+ loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
+ scev_initialize ();
+ calculate_dominance_info (CDI_DOMINATORS);
+ mark_dfs_back_edges ();
+
+ m_ranger = new gimple_ranger;
+ m_query = new path_range_query (*m_ranger, /*resolve=*/true);
+ m_simplifier = new hybrid_jt_simplifier (m_ranger, m_query);
+ m_state = new hybrid_jt_state;
+ m_threader = new jump_threader (m_simplifier, m_state);
+}
+
+hybrid_threader::~hybrid_threader ()
+{
+ delete m_simplifier;
+ delete m_threader;
+ delete m_state;
+ delete m_ranger;
+ delete m_query;
+
+ scev_finalize ();
+ loop_optimizer_finalize ();
+}
+
+edge
+hybrid_threader::before_dom_children (basic_block bb)
+{
+ gimple_stmt_iterator gsi;
+ int_range<2> r;
+
+ for (gsi = gsi_start_nondebug_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ m_ranger->range_of_stmt (r, stmt);
+ }
+ return NULL;
+}
+
+void
+hybrid_threader::after_dom_children (basic_block bb)
+{
+ m_threader->thread_outgoing_edges (bb);
+}
+
+static unsigned int
+execute_vrp_threader (function *fun)
+{
+ hybrid_threader threader;
+ threader.thread_jumps (fun);
+ if (threader.thread_through_all_blocks ())
+ return (TODO_cleanup_cfg | TODO_update_ssa);
+ return 0;
+}
+
+namespace {
+
+const pass_data pass_data_vrp_threader =
+{
+ GIMPLE_PASS, /* type */
+ "vrp-thread", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_TREE_VRP_THREADER, /* tv_id */
+ PROP_ssa, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0 /* todo_flags_finish */
+};
+
+class pass_vrp_threader : public gimple_opt_pass
+{
+public:
+ pass_vrp_threader (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_vrp_threader, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ opt_pass * clone () { return new pass_vrp_threader (m_ctxt); }
+ virtual bool gate (function *) { return flag_tree_vrp != 0; }
+ virtual unsigned int execute (function *fun)
+ { return execute_vrp_threader (fun); }
+};
+
+} // namespace {
+
+gimple_opt_pass *
+make_pass_vrp_threader (gcc::context *ctxt)
+{
+ return new pass_vrp_threader (ctxt);
+}
diff --git a/gcc/tree.c b/gcc/tree.c
index 994775d..561b9cd5 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -291,7 +291,7 @@ unsigned const char omp_clause_num_ops[] =
3, /* OMP_CLAUSE_LINEAR */
1, /* OMP_CLAUSE_AFFINITY */
2, /* OMP_CLAUSE_ALIGNED */
- 2, /* OMP_CLAUSE_ALLOCATE */
+ 3, /* OMP_CLAUSE_ALLOCATE */
1, /* OMP_CLAUSE_DEPEND */
1, /* OMP_CLAUSE_NONTEMPORAL */
1, /* OMP_CLAUSE_UNIFORM */
diff --git a/gcc/tree.h b/gcc/tree.h
index 091ad3d..7542d97 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1718,6 +1718,9 @@ class auto_suppress_location_wrappers
/* True for unconstrained modifier on order(concurrent) clause. */
#define OMP_CLAUSE_ORDER_UNCONSTRAINED(NODE) \
(OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDER)->base.public_flag)
+/* True for reproducible modifier on order(concurrent) clause. */
+#define OMP_CLAUSE_ORDER_REPRODUCIBLE(NODE) \
+ TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDER))
#define OMP_CLAUSE_REDUCTION_CODE(NODE) \
(OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \
@@ -1790,6 +1793,9 @@ class auto_suppress_location_wrappers
#define OMP_CLAUSE_ALLOCATE_ALLOCATOR(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALLOCATE), 1)
+#define OMP_CLAUSE_ALLOCATE_ALIGN(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALLOCATE), 2)
+
/* True if an ALLOCATE clause was present on a combined or composite
construct and the code for splitting the clauses has already performed
checking if the listed variable has explicit privatization on the
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index f113fd7..147c4b0 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -1648,6 +1648,8 @@ void
irange::irange_intersect (const irange &r)
{
gcc_checking_assert (!legacy_mode_p () && !r.legacy_mode_p ());
+ gcc_checking_assert (undefined_p () || r.undefined_p ()
+ || range_compatible_p (type (), r.type ()));
if (undefined_p () || r.varying_p ())
return;
@@ -1662,6 +1664,13 @@ irange::irange_intersect (const irange &r)
return;
}
+ if (r.num_pairs () == 1)
+ {
+ // R cannot be undefined, use more efficent pair routine.
+ intersect (r.lower_bound(), r.upper_bound ());
+ return;
+ }
+
signop sign = TYPE_SIGN (TREE_TYPE(m_base[0]));
unsigned bld_pair = 0;
unsigned bld_lim = m_max_ranges;
@@ -1737,6 +1746,66 @@ irange::irange_intersect (const irange &r)
verify_range ();
}
+// Multirange intersect for a specified wide_int [lb, ub] range.
+
+void
+irange::intersect (const wide_int& lb, const wide_int& ub)
+{
+ // Undefined remains undefined.
+ if (undefined_p ())
+ return;
+
+ if (legacy_mode_p ())
+ {
+ intersect (int_range<1> (type (), lb, ub));
+ return;
+ }
+
+ tree range_type = type();
+ signop sign = TYPE_SIGN (range_type);
+
+ gcc_checking_assert (TYPE_PRECISION (range_type) == wi::get_precision (lb));
+ gcc_checking_assert (TYPE_PRECISION (range_type) == wi::get_precision (ub));
+
+ unsigned bld_index = 0;
+ unsigned pair_lim = num_pairs ();
+ for (unsigned i = 0; i < pair_lim; i++)
+ {
+ tree pairl = m_base[i * 2];
+ tree pairu = m_base[i * 2 + 1];
+ // Once UB is less than a pairs lower bound, we're done.
+ if (wi::lt_p (ub, wi::to_wide (pairl), sign))
+ break;
+ // if LB is greater than this pairs upper, this pair is excluded.
+ if (wi::lt_p (wi::to_wide (pairu), lb, sign))
+ continue;
+
+ // Must be some overlap. Find the highest of the lower bounds,
+ // and set it
+ if (wi::gt_p (lb, wi::to_wide (pairl), sign))
+ m_base[bld_index * 2] = wide_int_to_tree (range_type, lb);
+ else
+ m_base[bld_index * 2] = pairl;
+
+ // ...and choose the lower of the upper bounds and if the base pair
+ // has the lower upper bound, need to check next pair too.
+ if (wi::lt_p (ub, wi::to_wide (pairu), sign))
+ {
+ m_base[bld_index++ * 2 + 1] = wide_int_to_tree (range_type, ub);
+ break;
+ }
+ else
+ m_base[bld_index++ * 2 + 1] = pairu;
+ }
+
+ m_num_ranges = bld_index;
+
+ m_kind = VR_RANGE;
+ normalize_kind ();
+
+ if (flag_checking)
+ verify_range ();
+}
// Signed 1-bits are strange. You can't subtract 1, because you can't
// represent the number 1. This works around that for the invert routine.
diff --git a/gcc/value-range.h b/gcc/value-range.h
index a8adc50..ff6c0a6 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -73,6 +73,7 @@ public:
// In-place operators.
void union_ (const irange &);
void intersect (const irange &);
+ void intersect (const wide_int& lb, const wide_int& ub);
void invert ();
// Operator overloads.
@@ -476,10 +477,21 @@ irange::set_varying (tree type)
if (INTEGRAL_TYPE_P (type))
{
+ // Strict enum's require varying to be not TYPE_MIN/MAX, but rather
+ // min_value and max_value.
wide_int min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
- m_base[0] = wide_int_to_tree (type, min);
- m_base[1] = wide_int_to_tree (type, max);
+ if (wi::eq_p (max, wi::to_wide (TYPE_MAX_VALUE (type)))
+ && wi::eq_p (min, wi::to_wide (TYPE_MIN_VALUE (type))))
+ {
+ m_base[0] = TYPE_MIN_VALUE (type);
+ m_base[1] = TYPE_MAX_VALUE (type);
+ }
+ else
+ {
+ m_base[0] = wide_int_to_tree (type, min);
+ m_base[1] = wide_int_to_tree (type, max);
+ }
}
else if (POINTER_TYPE_P (type))
{
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 2d261b3..09316c6 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -7827,10 +7827,7 @@ switch_to_section (section *new_section, tree decl)
else if (in_section == new_section)
return;
- if (new_section->common.flags & SECTION_FORGET)
- in_section = NULL;
- else
- in_section = new_section;
+ in_section = new_section;
switch (SECTION_STYLE (new_section))
{
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 3b8d067..9bf58f4 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -3460,19 +3460,21 @@ range_fits_type_p (const value_range *vr,
void
simplify_using_ranges::set_and_propagate_unexecutable (edge e)
{
- // If EXECUUTABLE is already clear, we're done.
- if ((e->flags & EDGE_EXECUTABLE) == 0)
+ // If not_executable is already set, we're done.
+ // This works in the absence of a flag as well.
+ if ((e->flags & m_not_executable_flag) == m_not_executable_flag)
return;
- e->flags &= ~EDGE_EXECUTABLE;
+ e->flags |= m_not_executable_flag;
+ m_flag_set_edges.safe_push (e);
// Check if the destination block needs to propagate the property.
basic_block bb = e->dest;
- // If any entry edge is marked EXECUTABLE, we are done.
+ // If any incoming edge is executable, we are done.
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->preds)
- if (e->flags & EDGE_EXECUTABLE)
+ if ((e->flags & m_not_executable_flag) == 0)
return;
// This block is also unexecutable, propagate to all exit edges as well.
@@ -3805,6 +3807,7 @@ simplify_using_ranges::simplify_switch_using_ranges (gswitch *stmt)
}
to_remove_edges.safe_push (e);
set_and_propagate_unexecutable (e);
+ e->flags &= ~EDGE_EXECUTABLE;
e->flags |= EDGE_IGNORE;
}
@@ -3822,6 +3825,12 @@ simplify_using_ranges::cleanup_edges_and_switches (void)
edge e;
switch_update *su;
+ /* Clear any edges marked as not executable. */
+ if (m_not_executable_flag)
+ {
+ FOR_EACH_VEC_ELT (m_flag_set_edges, i, e)
+ e->flags &= ~m_not_executable_flag;
+ }
/* Remove dead edges from SWITCH_EXPR optimization. This leaves the
CFG in a broken state and requires a cfg_cleanup run. */
FOR_EACH_VEC_ELT (to_remove_edges, i, e)
@@ -4124,11 +4133,14 @@ simplify_using_ranges::two_valued_val_range_p (tree var, tree *a, tree *b,
return false;
}
-simplify_using_ranges::simplify_using_ranges (range_query *query)
+simplify_using_ranges::simplify_using_ranges (range_query *query,
+ int not_executable_flag)
: query (query)
{
to_remove_edges = vNULL;
to_update_switch_stmts = vNULL;
+ m_not_executable_flag = not_executable_flag;
+ m_flag_set_edges = vNULL;
}
simplify_using_ranges::~simplify_using_ranges ()
diff --git a/gcc/vr-values.h b/gcc/vr-values.h
index 4693908..821bcb9 100644
--- a/gcc/vr-values.h
+++ b/gcc/vr-values.h
@@ -30,9 +30,11 @@ along with GCC; see the file COPYING3. If not see
class simplify_using_ranges
{
public:
- simplify_using_ranges (class range_query *query = NULL);
+ simplify_using_ranges (range_query *query = NULL,
+ int not_executable_flag = 0);
~simplify_using_ranges ();
- void set_range_query (class range_query *q) { query = q; }
+ void set_range_query (class range_query *q, int not_executable_flag = 0)
+ { query = q; m_not_executable_flag = not_executable_flag; }
bool simplify (gimple_stmt_iterator *);
@@ -82,6 +84,8 @@ private:
vec<edge> to_remove_edges;
vec<switch_update> to_update_switch_stmts;
class range_query *query;
+ int m_not_executable_flag; // Non zero if not_executable flag exists.
+ vec<edge> m_flag_set_edges; // List of edges with flag to be cleared.
};
/* The VR_VALUES class holds the current view of range information
diff --git a/gotools/ChangeLog b/gotools/ChangeLog
index e8e2495..f1ecf18 100644
--- a/gotools/ChangeLog
+++ b/gotools/ChangeLog
@@ -1,3 +1,8 @@
+2021-09-21 Ian Lance Taylor <iant@golang.org>
+
+ * Makefile.am (check-runtime): Add goroot.go to --extrafiles.
+ * Makefile.in: Regenerate.
+
2021-02-02 Ian Lance Taylor <iant@golang.org>
* Makefile.am (check-embed): New target.
diff --git a/include/ChangeLog b/include/ChangeLog
index 23e0fa2..9a639c0 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,12 @@
+2021-09-27 Vincent Lefevre <vincent@vinc17.net>
+
+ * floatformat.h: Update pathname for IBM long double description.
+
+2021-09-22 Alan Modra <amodra@gmail.com>
+
+ * obstack.h (__PTR_ALIGN): Expand and simplify __BPTR_ALIGN
+ rather than calculating relative to a NULL pointer.
+
2021-08-23 Jakub Jelinek <jakub@redhat.com>
* gomp-constants.h (GOMP_TASK_FLAG_STRICT): Define.
diff --git a/include/floatformat.h b/include/floatformat.h
index 5f9c143..288aedd 100644
--- a/include/floatformat.h
+++ b/include/floatformat.h
@@ -91,7 +91,7 @@ struct floatformat
/* Is the format actually the sum of two smaller floating point
formats (IBM long double, as described in
- gcc/config/rs6000/darwin-ldouble-format)? If so, this is the
+ libgcc/config/rs6000/ibm-ldouble-format)? If so, this is the
smaller format in question, and the fields sign_start through
intbit describe the first half. If not, this is NULL. */
const struct floatformat *split_half;
diff --git a/include/obstack.h b/include/obstack.h
index a6eb6c9..0d8746f 100644
--- a/include/obstack.h
+++ b/include/obstack.h
@@ -137,9 +137,9 @@
relative to B. Otherwise, use the faster strategy of computing the
alignment relative to 0. */
-#define __PTR_ALIGN(B, P, A) \
- __BPTR_ALIGN (sizeof (ptrdiff_t) < sizeof (void *) ? (B) : (char *) 0, \
- P, A)
+#define __PTR_ALIGN(B, P, A) \
+ (sizeof (ptrdiff_t) < sizeof (void *) ? __BPTR_ALIGN (B, P, A) \
+ : (char *) (((ptrdiff_t) (P) + (A)) & ~(A)))
#ifndef __attribute_pure__
# if defined __GNUC_MINOR__ && __GNUC__ * 1000 + __GNUC_MINOR__ >= 2096
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 35f952d..3fca7fd 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,12 @@
+2021-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ * init.c (lang_defaults): Implement P2334R1, enable elifdef for
+ -std=c++23 and -std=gnu++23.
+ * directives.c (_cpp_handle_directive): Support elifdef/elifndef if
+ either CPP_OPTION (pfile, elifdef) or !CPP_OPTION (pfile, std).
+ (do_elif): For older non-std modes if pedantic pedwarn about
+ #elifdef/#elifndef directives that change behavior.
+
2021-09-01 Jakub Jelinek <jakub@redhat.com>
PR c++/100977
diff --git a/libcpp/directives.c b/libcpp/directives.c
index 261a584..b4bc8b4 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -447,7 +447,11 @@ _cpp_handle_directive (cpp_reader *pfile, bool indented)
if (dname->val.node.node->is_directive)
{
dir = &dtable[dname->val.node.node->directive_index];
- if ((dir->flags & ELIFDEF) && !CPP_OPTION (pfile, elifdef))
+ if ((dir->flags & ELIFDEF)
+ && !CPP_OPTION (pfile, elifdef)
+ /* For -std=gnu* modes elifdef is supported with
+ a pedwarn if pedantic. */
+ && CPP_OPTION (pfile, std))
dir = 0;
}
}
@@ -2117,7 +2121,26 @@ do_elif (cpp_reader *pfile)
are skipped and their controlling directives are processed as
if they were in a group that is skipped." */
if (ifs->skip_elses)
- pfile->state.skipping = 1;
+ {
+ /* In older GNU standards, #elifdef/#elifndef is supported
+ as an extension, but pedwarn if -pedantic if the presence
+ of the directive would be rejected. */
+ if (pfile->directive != &dtable[T_ELIF]
+ && ! CPP_OPTION (pfile, elifdef)
+ && CPP_PEDANTIC (pfile)
+ && !pfile->state.skipping)
+ {
+ if (CPP_OPTION (pfile, cplusplus))
+ cpp_error (pfile, CPP_DL_PEDWARN,
+ "#%s before C++23 is a GCC extension",
+ pfile->directive->name);
+ else
+ cpp_error (pfile, CPP_DL_PEDWARN,
+ "#%s before C2X is a GCC extension",
+ pfile->directive->name);
+ }
+ pfile->state.skipping = 1;
+ }
else
{
if (pfile->directive == &dtable[T_ELIF])
@@ -2139,6 +2162,22 @@ do_elif (cpp_reader *pfile)
if (pfile->cb.used)
pfile->cb.used (pfile, pfile->directive_line, node);
check_eol (pfile, false);
+ /* In older GNU standards, #elifdef/#elifndef is supported
+ as an extension, but pedwarn if -pedantic if the presence
+ of the directive would change behavior. */
+ if (! CPP_OPTION (pfile, elifdef)
+ && CPP_PEDANTIC (pfile)
+ && pfile->state.skipping != skip)
+ {
+ if (CPP_OPTION (pfile, cplusplus))
+ cpp_error (pfile, CPP_DL_PEDWARN,
+ "#%s before C++23 is a GCC extension",
+ pfile->directive->name);
+ else
+ cpp_error (pfile, CPP_DL_PEDWARN,
+ "#%s before C2X is a GCC extension",
+ pfile->directive->name);
+ }
pfile->state.skipping = skip;
}
}
diff --git a/libcpp/init.c b/libcpp/init.c
index eda17a6a..5a424e2 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -122,8 +122,8 @@ static const struct lang_flags lang_defaults[] =
/* CXX17 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0 },
/* GNUCXX20 */ { 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0 },
/* CXX20 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0 },
- /* GNUCXX23 */ { 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0 },
- /* CXX23 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0 },
+ /* GNUCXX23 */ { 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1 },
+ /* CXX23 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1 },
/* ASM */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 4a1b261..5ecd436 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,19 @@
+2021-10-03 Patrick McGehearty <patrick.mcgehearty@oracle.com>
+
+ PR target/101104
+ * libgcc2.c (RMIN2, RMINSCAL, RMAX2):
+ Use more correct values for native IBM 128-bit.
+
+2021-09-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/i386/libgcc-darwin.ver: Add Symbols for
+ __cpu_model, __cpu_indicator_init.
+
+2021-09-22 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/i386/sfp-machine.h: Guard Mach-O-specific code
+ using __APPLE__.
+
2021-09-19 Iain Sandoe <iain@sandoe.co.uk>
* config/t-slibgcc-darwin: Delete unused code.
diff --git a/libgcc/config/i386/libgcc-darwin.ver b/libgcc/config/i386/libgcc-darwin.ver
index 5224cdc..c97dae7 100644
--- a/libgcc/config/i386/libgcc-darwin.ver
+++ b/libgcc/config/i386/libgcc-darwin.ver
@@ -1,4 +1,7 @@
-
+GCC_4.8.0 {
+ __cpu_model
+ __cpu_indicator_init
+}
%inherit GCC_12.0.0 GCC_7.0.0
GCC_12.0.0 {
diff --git a/libgcc/config/i386/sfp-machine.h b/libgcc/config/i386/sfp-machine.h
index 172ebc7..c451ae7 100644
--- a/libgcc/config/i386/sfp-machine.h
+++ b/libgcc/config/i386/sfp-machine.h
@@ -74,7 +74,7 @@ void __sfp_handle_exceptions (int);
#define __BYTE_ORDER __LITTLE_ENDIAN
/* Define ALIASNAME as a strong alias for NAME. */
-#if defined __MACH__
+#if defined __APPLE__
/* Mach-O doesn't support aliasing, so we build a secondary function for
the alias - we need to do a bit of a dance to find out what the type of
the arguments is and then apply that to the secondary function.
diff --git a/libgcc/libgcc2.c b/libgcc/libgcc2.c
index 38f935e..e66e6f0 100644
--- a/libgcc/libgcc2.c
+++ b/libgcc/libgcc2.c
@@ -1904,10 +1904,17 @@ NAME (TYPE x, int m)
# define MODE tc
# define CEXT __LIBGCC_TF_FUNC_EXT__
# define NOTRUNC (!__LIBGCC_TF_EXCESS_PRECISION__)
-# define RBIG (__LIBGCC_TF_MAX__ / 2)
-# define RMIN (__LIBGCC_TF_MIN__)
-# define RMIN2 (__LIBGCC_TF_EPSILON__)
-# define RMINSCAL (1 / __LIBGCC_TF_EPSILON__)
+# if __LIBGCC_TF_MANT_DIG__ == 106
+# define RBIG (__LIBGCC_DF_MAX__ / 2)
+# define RMIN (__LIBGCC_DF_MIN__)
+# define RMIN2 (__LIBGCC_DF_EPSILON__)
+# define RMINSCAL (1 / __LIBGCC_DF_EPSILON__)
+# else
+# define RBIG (__LIBGCC_TF_MAX__ / 2)
+# define RMIN (__LIBGCC_TF_MIN__)
+# define RMIN2 (__LIBGCC_TF_EPSILON__)
+# define RMINSCAL (1 / __LIBGCC_TF_EPSILON__)
+# endif
# define RMAX2 (RBIG * RMIN2)
#else
# error
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 779ef06..12816cc 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,27 @@
+2021-09-27 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/94070
+ * intrinsics/size.c (size0, size1): Comment that now not
+ used by newer compiler code.
+
+2021-09-26 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/101334
+ * intrinsics/associated.c (associated): Also check for same rank.
+
+2021-09-22 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * configure.ac (AM_FCFLAGS): Revert r12-3722 by removing
+ -Wno-missing-include-dirs.
+ * configure: Regenerate.
+
+2021-09-21 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * configure.ac (AM_FCFLAGS): Add -Wno-missing-include-dirs.
+ * configure: Regenerate.
+
2021-09-17 Sandra Loosemore <sandra@codesourcery.com>
* ISO_Fortran_binding.h: Update comments.
diff --git a/libgfortran/configure b/libgfortran/configure
index 350159a..4810b9b 100755
--- a/libgfortran/configure
+++ b/libgfortran/configure
@@ -5985,7 +5985,7 @@ fi
# Add -Wall -fno-repack-arrays -fno-underscoring if we are using GCC.
if test "x$GCC" = "xyes"; then
- AM_FCFLAGS="-I . -Wall -Werror -fimplicit-none -fno-repack-arrays -fno-underscoring -Wno-missing-include-dirs"
+ AM_FCFLAGS="-I . -Wall -Werror -fimplicit-none -fno-repack-arrays -fno-underscoring"
## We like to use C11 and C99 routines when available. This makes
## sure that
## __STDC_VERSION__ is set such that libc includes make them available.
diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac
index a3550b4..a775098 100644
--- a/libgfortran/configure.ac
+++ b/libgfortran/configure.ac
@@ -146,7 +146,7 @@ AM_PROG_CC_C_O
# Add -Wall -fno-repack-arrays -fno-underscoring if we are using GCC.
if test "x$GCC" = "xyes"; then
- AM_FCFLAGS="-I . -Wall -Werror -fimplicit-none -fno-repack-arrays -fno-underscoring -Wno-missing-include-dirs"
+ AM_FCFLAGS="-I . -Wall -Werror -fimplicit-none -fno-repack-arrays -fno-underscoring"
## We like to use C11 and C99 routines when available. This makes
## sure that
## __STDC_VERSION__ is set such that libc includes make them available.
diff --git a/libgfortran/intrinsics/associated.c b/libgfortran/intrinsics/associated.c
index 943fc69..60c88ff 100644
--- a/libgfortran/intrinsics/associated.c
+++ b/libgfortran/intrinsics/associated.c
@@ -41,8 +41,9 @@ associated (const gfc_array_void *pointer, const gfc_array_void *target)
return 0;
if (GFC_DESCRIPTOR_DTYPE (pointer).type != GFC_DESCRIPTOR_DTYPE (target).type)
return 0;
-
rank = GFC_DESCRIPTOR_RANK (pointer);
+ if (rank != GFC_DESCRIPTOR_RANK (target))
+ return 0;
for (n = 0; n < rank; n++)
{
long extent;
diff --git a/libgfortran/intrinsics/size.c b/libgfortran/intrinsics/size.c
index e9d9386..f1a60ba 100644
--- a/libgfortran/intrinsics/size.c
+++ b/libgfortran/intrinsics/size.c
@@ -25,6 +25,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "libgfortran.h"
+/* Note: This function is only used internally in libgfortran and old FE code,
+ new code generates the code inline. */
index_type
size0 (const array_t * array)
{
@@ -47,6 +49,8 @@ iexport(size0);
extern index_type size1 (const array_t * array, index_type dim);
export_proto(size1);
+/* Note: This function it is unused in libgfortran itself and the FE no longer
+ call it; however, old code might still call it. */
index_type
size1 (const array_t * array, index_type dim)
{
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index d648771..64d3f03 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,131 @@
+2021-10-02 Tobias Burnus <tobias@codesourcery.com>
+
+ * testsuite/libgomp.fortran/order-reproducible-1.f90: New test
+ based on libgomp.c-c++-common/order-reproducible-1.c.
+ * testsuite/libgomp.fortran/order-reproducible-2.f90: Likewise.
+ * testsuite/libgomp.fortran/my-usleep.c: New test.
+
+2021-10-01 Tobias Burnus <tobias@codesourcery.com>
+
+ * testsuite/libgomp.fortran/alloc-10.f90: Fix alignment check.
+ * testsuite/libgomp.fortran/alloc-7.f90: Fix array access.
+ * testsuite/libgomp.fortran/alloc-8.f90: Likewise.
+ * testsuite/libgomp.fortran/alloc-11.f90: New test for omp_realloc,
+ based on libgomp.c-c++-common/alloc-9.c.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * testsuite/libgomp.c-c++-common/order-reproducible-1.c: New test.
+ * testsuite/libgomp.c-c++-common/order-reproducible-2.c: New test.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * affinity-fmt.c (omp_get_team_num, omp_get_num_teams): Add
+ ialias_redirect.
+ * env.c (handle_omp_display_env): Use ialias_call.
+ * icv-device.c: Move ialias right below each function.
+ (omp_get_device_num): Use ialias_call.
+ * fortran.c (omp_fulfill_event): Add ialias_redirect.
+ * icv.c (omp_get_active_level): Add ialias_redirect.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * omp.h.in (omp_aligned_alloc, omp_aligned_calloc): Add
+ __alloc_align__ (1) attribute.
+ * testsuite/libgomp.c-c++-common/alloc-9.c: New test.
+
+2021-09-30 Tobias Burnus <tobias@codesourcery.com>
+
+ * testsuite/libgomp.fortran/alloc-7.f90: Add dg-prune-output
+ for -fintrinsic-modules-path= warning of the C compiler.
+ * testsuite/libgomp.fortran/alloc-9.f90: Likewise.
+ * testsuite/libgomp.fortran/alloc-10.f90: Likewise.
+
+2021-09-30 Tobias Burnus <tobias@codesourcery.com>
+
+ * libgomp.texi (OpenMP 5.1): Set implementation status to Y for
+ omp_aligned_{,c}alloc and omp_{c,re}alloc routines.
+ * omp_lib.f90.in (omp_aligned_alloc, omp_aligned_calloc, omp_calloc,
+ omp_realloc): Add.
+ * omp_lib.h.in (omp_aligned_alloc, omp_aligned_calloc, omp_calloc,
+ omp_realloc): Add.
+ * testsuite/libgomp.fortran/alloc-10.f90: New test.
+ * testsuite/libgomp.fortran/alloc-6.f90: New test.
+ * testsuite/libgomp.fortran/alloc-7.c: New test.
+ * testsuite/libgomp.fortran/alloc-7.f90: New test.
+ * testsuite/libgomp.fortran/alloc-8.f90: New test.
+ * testsuite/libgomp.fortran/alloc-9.f90: New test.
+
+2021-09-30 Jakub Jelinek <jakub@redhat.com>
+
+ * omp.h.in (omp_aligned_alloc, omp_calloc, omp_aligned_calloc,
+ omp_realloc): New prototypes.
+ (omp_alloc): Move after omp_free prototype, add __malloc__ (omp_free)
+ attribute.
+ * allocator.c: Include string.h.
+ (omp_aligned_alloc): No longer static, add ialias. Add new_alignment
+ variable and use it instead of alignment so that when retrying the old
+ alignment is used again. Don't retry if new alignment is the same
+ as old alignment, unless allocator had pool size.
+ (omp_alloc, GOMP_alloc, GOMP_free): Use ialias_call.
+ (omp_aligned_calloc, omp_calloc, omp_realloc): New functions.
+ * libgomp.map (OMP_5.0.2): Export omp_aligned_alloc, omp_calloc,
+ omp_aligned_calloc and omp_realloc.
+ * testsuite/libgomp.c-c++-common/alloc-4.c (main): Add
+ omp_aligned_alloc, omp_calloc and omp_aligned_calloc tests.
+ * testsuite/libgomp.c-c++-common/alloc-5.c: New test.
+ * testsuite/libgomp.c-c++-common/alloc-6.c: New test.
+ * testsuite/libgomp.c-c++-common/alloc-7.c: New test.
+ * testsuite/libgomp.c-c++-common/alloc-8.c: New test.
+
+2021-09-28 Tobias Burnus <tobias@codesourcery.com>
+
+ PR libgomp/96661
+ * configure.ac: Only check for int-type = 2*size_t support when
+ building with Fortran support.
+ * configure: Regenerate.
+
+2021-09-28 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/libgomp.oacc-fortran/if-1.f90: Adjust.
+ * testsuite/libgomp.oacc-fortran/privatized-ref-2.f90: Likewise.
+
+2021-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * team.c: Initialize start_data.
+ * testsuite/libgomp.graphite/force-parallel-4.c: Adjust.
+ * testsuite/libgomp.graphite/force-parallel-8.c: Adjust.
+
+2021-09-27 Tobias Burnus <tobias@codesourcery.com>
+
+ * testsuite/libgomp.oacc-fortran/privatized-ref-2.f90: Change
+ dg-message back to dg-note.
+
+2021-09-27 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/94070
+ * testsuite/libgomp.oacc-fortran/privatized-ref-2.f90: Update
+ expected dg-note output.
+
+2021-09-22 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * testsuite/libgomp.fortran/fortran.exp (ALWAYS_CFLAGS): Revert
+ r12-3722 by removing -Wno-missing-include-dirs.
+ * testsuite/libgomp.oacc-fortran/fortran.exp (ALWAYS_CFLAGS): Likewise.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ * testsuite/libgomp.c-c++-common/allocate-2.c: New test.
+ * testsuite/libgomp.c-c++-common/allocate-3.c: New test.
+
+2021-09-21 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * testsuite/libgomp.fortran/fortran.exp: Add -Wno-missing-include-dirs
+ to ALWAYS_CFLAGS.
+ * testsuite/libgomp.oacc-fortran/fortran.exp: Likewise.
+
2021-09-18 Jakub Jelinek <jakub@redhat.com>
* testsuite/libgomp.c++/default-1.C: New test.
diff --git a/libgomp/affinity-fmt.c b/libgomp/affinity-fmt.c
index 9f40e37..75940b5 100644
--- a/libgomp/affinity-fmt.c
+++ b/libgomp/affinity-fmt.c
@@ -37,6 +37,9 @@
#include <sys/utsname.h>
#endif
+ialias_redirect (omp_get_team_num)
+ialias_redirect (omp_get_num_teams)
+
bool
gomp_print_string (const char *str, size_t len)
{
diff --git a/libgomp/allocator.c b/libgomp/allocator.c
index 9fcfc4e..dce600f 100644
--- a/libgomp/allocator.c
+++ b/libgomp/allocator.c
@@ -30,6 +30,7 @@
#define _GNU_SOURCE
#include "libgomp.h"
#include <stdlib.h>
+#include <string.h>
#define omp_max_predefined_alloc omp_thread_mem_alloc
@@ -205,18 +206,19 @@ omp_destroy_allocator (omp_allocator_handle_t allocator)
ialias (omp_init_allocator)
ialias (omp_destroy_allocator)
-static void *
+void *
omp_aligned_alloc (size_t alignment, size_t size,
omp_allocator_handle_t allocator)
{
struct omp_allocator_data *allocator_data;
- size_t new_size;
+ size_t new_size, new_alignment;
void *ptr, *ret;
if (__builtin_expect (size == 0, 0))
return NULL;
retry:
+ new_alignment = alignment;
if (allocator == omp_null_allocator)
{
struct gomp_thread *thr = gomp_thread ();
@@ -228,19 +230,19 @@ retry:
if (allocator > omp_max_predefined_alloc)
{
allocator_data = (struct omp_allocator_data *) allocator;
- if (alignment < allocator_data->alignment)
- alignment = allocator_data->alignment;
+ if (new_alignment < allocator_data->alignment)
+ new_alignment = allocator_data->alignment;
}
else
{
allocator_data = NULL;
- if (alignment < sizeof (void *))
- alignment = sizeof (void *);
+ if (new_alignment < sizeof (void *))
+ new_alignment = sizeof (void *);
}
new_size = sizeof (struct omp_mem_header);
- if (alignment > sizeof (void *))
- new_size += alignment - sizeof (void *);
+ if (new_alignment > sizeof (void *))
+ new_size += new_alignment - sizeof (void *);
if (__builtin_add_overflow (size, new_size, &new_size))
goto fail;
@@ -300,10 +302,11 @@ retry:
goto fail;
}
- if (alignment > sizeof (void *))
+ if (new_alignment > sizeof (void *))
ret = (void *) (((uintptr_t) ptr
+ sizeof (struct omp_mem_header)
- + alignment - sizeof (void *)) & ~(alignment - 1));
+ + new_alignment - sizeof (void *))
+ & ~(new_alignment - 1));
else
ret = (char *) ptr + sizeof (struct omp_mem_header);
((struct omp_mem_header *) ret)[-1].ptr = ptr;
@@ -317,7 +320,7 @@ fail:
switch (allocator_data->fallback)
{
case omp_atv_default_mem_fb:
- if (alignment > sizeof (void *)
+ if ((new_alignment > sizeof (void *) && new_alignment > alignment)
|| (allocator_data
&& allocator_data->pool_size < ~(uintptr_t) 0))
{
@@ -326,7 +329,7 @@ fail:
}
/* Otherwise, we've already performed default mem allocation
and if that failed, it won't succeed again (unless it was
- intermitent. Return NULL then, as that is the fallback. */
+ intermittent. Return NULL then, as that is the fallback. */
break;
case omp_atv_null_fb:
break;
@@ -342,10 +345,12 @@ fail:
return NULL;
}
+ialias (omp_aligned_alloc)
+
void *
omp_alloc (size_t size, omp_allocator_handle_t allocator)
{
- return omp_aligned_alloc (1, size, allocator);
+ return ialias_call (omp_aligned_alloc) (1, size, allocator);
}
/* Like omp_aligned_alloc, but apply on top of that:
@@ -355,8 +360,9 @@ omp_alloc (size_t size, omp_allocator_handle_t allocator)
void *
GOMP_alloc (size_t alignment, size_t size, uintptr_t allocator)
{
- void *ret = omp_aligned_alloc (alignment, size,
- (omp_allocator_handle_t) allocator);
+ void *ret
+ = ialias_call (omp_aligned_alloc) (alignment, size,
+ (omp_allocator_handle_t) allocator);
if (__builtin_expect (ret == NULL, 0) && size)
gomp_fatal ("Out of memory allocating %lu bytes",
(unsigned long) size);
@@ -396,5 +402,365 @@ ialias (omp_free)
void
GOMP_free (void *ptr, uintptr_t allocator)
{
- return omp_free (ptr, (omp_allocator_handle_t) allocator);
+ return ialias_call (omp_free) (ptr, (omp_allocator_handle_t) allocator);
+}
+
+void *
+omp_aligned_calloc (size_t alignment, size_t nmemb, size_t size,
+ omp_allocator_handle_t allocator)
+{
+ struct omp_allocator_data *allocator_data;
+ size_t new_size, size_temp, new_alignment;
+ void *ptr, *ret;
+
+ if (__builtin_expect (size == 0 || nmemb == 0, 0))
+ return NULL;
+
+retry:
+ new_alignment = alignment;
+ if (allocator == omp_null_allocator)
+ {
+ struct gomp_thread *thr = gomp_thread ();
+ if (thr->ts.def_allocator == omp_null_allocator)
+ thr->ts.def_allocator = gomp_def_allocator;
+ allocator = (omp_allocator_handle_t) thr->ts.def_allocator;
+ }
+
+ if (allocator > omp_max_predefined_alloc)
+ {
+ allocator_data = (struct omp_allocator_data *) allocator;
+ if (new_alignment < allocator_data->alignment)
+ new_alignment = allocator_data->alignment;
+ }
+ else
+ {
+ allocator_data = NULL;
+ if (new_alignment < sizeof (void *))
+ new_alignment = sizeof (void *);
+ }
+
+ new_size = sizeof (struct omp_mem_header);
+ if (new_alignment > sizeof (void *))
+ new_size += new_alignment - sizeof (void *);
+ if (__builtin_mul_overflow (size, nmemb, &size_temp))
+ goto fail;
+ if (__builtin_add_overflow (size_temp, new_size, &new_size))
+ goto fail;
+
+ if (__builtin_expect (allocator_data
+ && allocator_data->pool_size < ~(uintptr_t) 0, 0))
+ {
+ uintptr_t used_pool_size;
+ if (new_size > allocator_data->pool_size)
+ goto fail;
+#ifdef HAVE_SYNC_BUILTINS
+ used_pool_size = __atomic_load_n (&allocator_data->used_pool_size,
+ MEMMODEL_RELAXED);
+ do
+ {
+ uintptr_t new_pool_size;
+ if (__builtin_add_overflow (used_pool_size, new_size,
+ &new_pool_size)
+ || new_pool_size > allocator_data->pool_size)
+ goto fail;
+ if (__atomic_compare_exchange_n (&allocator_data->used_pool_size,
+ &used_pool_size, new_pool_size,
+ true, MEMMODEL_RELAXED,
+ MEMMODEL_RELAXED))
+ break;
+ }
+ while (1);
+#else
+ gomp_mutex_lock (&allocator_data->lock);
+ if (__builtin_add_overflow (allocator_data->used_pool_size, new_size,
+ &used_pool_size)
+ || used_pool_size > allocator_data->pool_size)
+ {
+ gomp_mutex_unlock (&allocator_data->lock);
+ goto fail;
+ }
+ allocator_data->used_pool_size = used_pool_size;
+ gomp_mutex_unlock (&allocator_data->lock);
+#endif
+ ptr = calloc (1, new_size);
+ if (ptr == NULL)
+ {
+#ifdef HAVE_SYNC_BUILTINS
+ __atomic_add_fetch (&allocator_data->used_pool_size, -new_size,
+ MEMMODEL_RELAXED);
+#else
+ gomp_mutex_lock (&allocator_data->lock);
+ allocator_data->used_pool_size -= new_size;
+ gomp_mutex_unlock (&allocator_data->lock);
+#endif
+ goto fail;
+ }
+ }
+ else
+ {
+ ptr = calloc (1, new_size);
+ if (ptr == NULL)
+ goto fail;
+ }
+
+ if (new_alignment > sizeof (void *))
+ ret = (void *) (((uintptr_t) ptr
+ + sizeof (struct omp_mem_header)
+ + new_alignment - sizeof (void *))
+ & ~(new_alignment - 1));
+ else
+ ret = (char *) ptr + sizeof (struct omp_mem_header);
+ ((struct omp_mem_header *) ret)[-1].ptr = ptr;
+ ((struct omp_mem_header *) ret)[-1].size = new_size;
+ ((struct omp_mem_header *) ret)[-1].allocator = allocator;
+ return ret;
+
+fail:
+ if (allocator_data)
+ {
+ switch (allocator_data->fallback)
+ {
+ case omp_atv_default_mem_fb:
+ if ((new_alignment > sizeof (void *) && new_alignment > alignment)
+ || (allocator_data
+ && allocator_data->pool_size < ~(uintptr_t) 0))
+ {
+ allocator = omp_default_mem_alloc;
+ goto retry;
+ }
+ /* Otherwise, we've already performed default mem allocation
+ and if that failed, it won't succeed again (unless it was
+ intermittent. Return NULL then, as that is the fallback. */
+ break;
+ case omp_atv_null_fb:
+ break;
+ default:
+ case omp_atv_abort_fb:
+ gomp_fatal ("Out of memory allocating %lu bytes",
+ (unsigned long) (size * nmemb));
+ case omp_atv_allocator_fb:
+ allocator = allocator_data->fb_data;
+ goto retry;
+ }
+ }
+ return NULL;
+}
+
+ialias (omp_aligned_calloc)
+
+void *
+omp_calloc (size_t nmemb, size_t size, omp_allocator_handle_t allocator)
+{
+ return ialias_call (omp_aligned_calloc) (1, nmemb, size, allocator);
+}
+
+void *
+omp_realloc (void *ptr, size_t size, omp_allocator_handle_t allocator,
+ omp_allocator_handle_t free_allocator)
+{
+ struct omp_allocator_data *allocator_data, *free_allocator_data;
+ size_t new_size, old_size, new_alignment, old_alignment;
+ void *new_ptr, *ret;
+ struct omp_mem_header *data;
+
+ if (__builtin_expect (ptr == NULL, 0))
+ return ialias_call (omp_aligned_alloc) (1, size, allocator);
+
+ if (__builtin_expect (size == 0, 0))
+ {
+ ialias_call (omp_free) (ptr, free_allocator);
+ return NULL;
+ }
+
+ data = &((struct omp_mem_header *) ptr)[-1];
+ free_allocator = data->allocator;
+
+retry:
+ new_alignment = sizeof (void *);
+ if (allocator == omp_null_allocator)
+ allocator = free_allocator;
+
+ if (allocator > omp_max_predefined_alloc)
+ {
+ allocator_data = (struct omp_allocator_data *) allocator;
+ if (new_alignment < allocator_data->alignment)
+ new_alignment = allocator_data->alignment;
+ }
+ else
+ allocator_data = NULL;
+ if (free_allocator > omp_max_predefined_alloc)
+ free_allocator_data = (struct omp_allocator_data *) free_allocator;
+ else
+ free_allocator_data = NULL;
+ old_alignment = (uintptr_t) ptr - (uintptr_t) (data->ptr);
+
+ new_size = sizeof (struct omp_mem_header);
+ if (new_alignment > sizeof (void *))
+ new_size += new_alignment - sizeof (void *);
+ if (__builtin_add_overflow (size, new_size, &new_size))
+ goto fail;
+ old_size = data->size;
+
+ if (__builtin_expect (allocator_data
+ && allocator_data->pool_size < ~(uintptr_t) 0, 0))
+ {
+ uintptr_t used_pool_size;
+ size_t prev_size = 0;
+ /* Check if we can use realloc. Don't use it if extra alignment
+ was used previously or newly, because realloc might return a pointer
+ with different alignment and then we'd need to memmove the data
+ again. */
+ if (free_allocator_data
+ && free_allocator_data == allocator_data
+ && new_alignment == sizeof (void *)
+ && old_alignment == sizeof (struct omp_mem_header))
+ prev_size = old_size;
+ if (new_size > prev_size
+ && new_size - prev_size > allocator_data->pool_size)
+ goto fail;
+#ifdef HAVE_SYNC_BUILTINS
+ used_pool_size = __atomic_load_n (&allocator_data->used_pool_size,
+ MEMMODEL_RELAXED);
+ do
+ {
+ uintptr_t new_pool_size;
+ if (new_size > prev_size)
+ {
+ if (__builtin_add_overflow (used_pool_size, new_size - prev_size,
+ &new_pool_size)
+ || new_pool_size > allocator_data->pool_size)
+ goto fail;
+ }
+ else
+ new_pool_size = used_pool_size + new_size - prev_size;
+ if (__atomic_compare_exchange_n (&allocator_data->used_pool_size,
+ &used_pool_size, new_pool_size,
+ true, MEMMODEL_RELAXED,
+ MEMMODEL_RELAXED))
+ break;
+ }
+ while (1);
+#else
+ gomp_mutex_lock (&allocator_data->lock);
+ if (new_size > prev_size)
+ {
+ if (__builtin_add_overflow (allocator_data->used_pool_size,
+ new_size - prev_size,
+ &used_pool_size)
+ || used_pool_size > allocator_data->pool_size)
+ {
+ gomp_mutex_unlock (&allocator_data->lock);
+ goto fail;
+ }
+ }
+ else
+ used_pool_size = (allocator_data->used_pool_size
+ + new_size - prev_size);
+ allocator_data->used_pool_size = used_pool_size;
+ gomp_mutex_unlock (&allocator_data->lock);
+#endif
+ if (prev_size)
+ new_ptr = realloc (data->ptr, new_size);
+ else
+ new_ptr = malloc (new_size);
+ if (new_ptr == NULL)
+ {
+#ifdef HAVE_SYNC_BUILTINS
+ __atomic_add_fetch (&allocator_data->used_pool_size,
+ prev_size - new_size,
+ MEMMODEL_RELAXED);
+#else
+ gomp_mutex_lock (&allocator_data->lock);
+ allocator_data->used_pool_size -= new_size - prev_size;
+ gomp_mutex_unlock (&allocator_data->lock);
+#endif
+ goto fail;
+ }
+ else if (prev_size)
+ {
+ ret = (char *) new_ptr + sizeof (struct omp_mem_header);
+ ((struct omp_mem_header *) ret)[-1].ptr = new_ptr;
+ ((struct omp_mem_header *) ret)[-1].size = new_size;
+ ((struct omp_mem_header *) ret)[-1].allocator = allocator;
+ return ret;
+ }
+ }
+ else if (new_alignment == sizeof (void *)
+ && old_alignment == sizeof (struct omp_mem_header)
+ && (free_allocator_data == NULL
+ || free_allocator_data->pool_size == ~(uintptr_t) 0))
+ {
+ new_ptr = realloc (data->ptr, new_size);
+ if (new_ptr == NULL)
+ goto fail;
+ ret = (char *) new_ptr + sizeof (struct omp_mem_header);
+ ((struct omp_mem_header *) ret)[-1].ptr = new_ptr;
+ ((struct omp_mem_header *) ret)[-1].size = new_size;
+ ((struct omp_mem_header *) ret)[-1].allocator = allocator;
+ return ret;
+ }
+ else
+ {
+ new_ptr = malloc (new_size);
+ if (new_ptr == NULL)
+ goto fail;
+ }
+
+ if (new_alignment > sizeof (void *))
+ ret = (void *) (((uintptr_t) new_ptr
+ + sizeof (struct omp_mem_header)
+ + new_alignment - sizeof (void *))
+ & ~(new_alignment - 1));
+ else
+ ret = (char *) new_ptr + sizeof (struct omp_mem_header);
+ ((struct omp_mem_header *) ret)[-1].ptr = new_ptr;
+ ((struct omp_mem_header *) ret)[-1].size = new_size;
+ ((struct omp_mem_header *) ret)[-1].allocator = allocator;
+ if (old_size - old_alignment < size)
+ size = old_size - old_alignment;
+ memcpy (ret, ptr, size);
+ if (__builtin_expect (free_allocator_data
+ && free_allocator_data->pool_size < ~(uintptr_t) 0, 0))
+ {
+#ifdef HAVE_SYNC_BUILTINS
+ __atomic_add_fetch (&free_allocator_data->used_pool_size, -data->size,
+ MEMMODEL_RELAXED);
+#else
+ gomp_mutex_lock (&free_allocator_data->lock);
+ free_allocator_data->used_pool_size -= data->size;
+ gomp_mutex_unlock (&free_allocator_data->lock);
+#endif
+ }
+ free (data->ptr);
+ return ret;
+
+fail:
+ if (allocator_data)
+ {
+ switch (allocator_data->fallback)
+ {
+ case omp_atv_default_mem_fb:
+ if (new_alignment > sizeof (void *)
+ || (allocator_data
+ && allocator_data->pool_size < ~(uintptr_t) 0))
+ {
+ allocator = omp_default_mem_alloc;
+ goto retry;
+ }
+ /* Otherwise, we've already performed default mem allocation
+ and if that failed, it won't succeed again (unless it was
+ intermittent. Return NULL then, as that is the fallback. */
+ break;
+ case omp_atv_null_fb:
+ break;
+ default:
+ case omp_atv_abort_fb:
+ gomp_fatal ("Out of memory allocating %lu bytes",
+ (unsigned long) size);
+ case omp_atv_allocator_fb:
+ allocator = allocator_data->fb_data;
+ goto retry;
+ }
+ }
+ return NULL;
}
diff --git a/libgomp/configure b/libgomp/configure
index 6161da5..4bc9b38 100755
--- a/libgomp/configure
+++ b/libgomp/configure
@@ -17007,13 +17007,15 @@ fi
if test $OMP_NEST_LOCK_25_SIZE -gt 8 || test $OMP_NEST_LOCK_25_ALIGN -gt $OMP_NEST_LOCK_25_SIZE; then
OMP_NEST_LOCK_25_KIND=8
fi
-if test $OMP_DEPEND_KIND -eq 16; then
- if test $OMP_INT128_SIZE -ne 16; then
- as_fn_error $? "unsupported system, cannot find Fortran int kind=16, needed for omp_depend_kind" "$LINENO" 5
- fi
-else
- if test $OMP_DEPEND_KIND -ne 8; then
- as_fn_error $? "unsupported system, cannot find Fortran integer kind for omp_depend_kind" "$LINENO" 5
+if test "$ac_cv_fc_compiler_gnu" = yes; then
+ if test $OMP_DEPEND_KIND -eq 16; then
+ if test $OMP_INT128_SIZE -ne 16; then
+ as_fn_error $? "unsupported system, cannot find Fortran int kind=16, needed for omp_depend_kind" "$LINENO" 5
+ fi
+ else
+ if test $OMP_DEPEND_KIND -ne 8; then
+ as_fn_error $? "unsupported system, cannot find Fortran integer kind for omp_depend_kind" "$LINENO" 5
+ fi
fi
fi
diff --git a/libgomp/configure.ac b/libgomp/configure.ac
index 7df80a3..bfb613b 100644
--- a/libgomp/configure.ac
+++ b/libgomp/configure.ac
@@ -438,13 +438,15 @@ fi
if test $OMP_NEST_LOCK_25_SIZE -gt 8 || test $OMP_NEST_LOCK_25_ALIGN -gt $OMP_NEST_LOCK_25_SIZE; then
OMP_NEST_LOCK_25_KIND=8
fi
-if test $OMP_DEPEND_KIND -eq 16; then
- if test $OMP_INT128_SIZE -ne 16; then
- AC_MSG_ERROR([unsupported system, cannot find Fortran int kind=16, needed for omp_depend_kind])
- fi
-else
- if test $OMP_DEPEND_KIND -ne 8; then
- AC_MSG_ERROR([unsupported system, cannot find Fortran integer kind for omp_depend_kind])
+if test "$ac_cv_fc_compiler_gnu" = yes; then
+ if test $OMP_DEPEND_KIND -eq 16; then
+ if test $OMP_INT128_SIZE -ne 16; then
+ AC_MSG_ERROR([unsupported system, cannot find Fortran int kind=16, needed for omp_depend_kind])
+ fi
+ else
+ if test $OMP_DEPEND_KIND -ne 8; then
+ AC_MSG_ERROR([unsupported system, cannot find Fortran integer kind for omp_depend_kind])
+ fi
fi
fi
diff --git a/libgomp/env.c b/libgomp/env.c
index 9216998..69ce1d2 100644
--- a/libgomp/env.c
+++ b/libgomp/env.c
@@ -1416,7 +1416,7 @@ handle_omp_display_env (void)
gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
if (display)
- omp_display_env (verbose);
+ ialias_call (omp_display_env) (verbose);
}
diff --git a/libgomp/fortran.c b/libgomp/fortran.c
index 07f9765..d171c79 100644
--- a/libgomp/fortran.c
+++ b/libgomp/fortran.c
@@ -96,6 +96,7 @@ ialias_redirect (omp_destroy_allocator)
ialias_redirect (omp_set_default_allocator)
ialias_redirect (omp_get_default_allocator)
ialias_redirect (omp_display_env)
+ialias_redirect (omp_fulfill_event)
#endif
#ifndef LIBGOMP_GNU_SYMBOL_VERSIONING
diff --git a/libgomp/icv-device.c b/libgomp/icv-device.c
index f11bdfa..709ceeb 100644
--- a/libgomp/icv-device.c
+++ b/libgomp/icv-device.c
@@ -35,6 +35,8 @@ omp_set_default_device (int device_num)
icv->default_device_var = device_num >= 0 ? device_num : 0;
}
+ialias (omp_set_default_device)
+
int
omp_get_default_device (void)
{
@@ -42,18 +44,24 @@ omp_get_default_device (void)
return icv->default_device_var;
}
+ialias (omp_get_default_device)
+
int
omp_get_initial_device (void)
{
return gomp_get_num_devices ();
}
+ialias (omp_get_initial_device)
+
int
omp_get_num_devices (void)
{
return gomp_get_num_devices ();
}
+ialias (omp_get_num_devices)
+
int
omp_is_initial_device (void)
{
@@ -61,17 +69,14 @@ omp_is_initial_device (void)
return 1;
}
+ialias (omp_is_initial_device)
+
int
omp_get_device_num (void)
{
/* By specification, this is equivalent to omp_get_initial_device
on the host. */
- return omp_get_initial_device ();
+ return ialias_call (omp_get_initial_device) ();
}
-ialias (omp_set_default_device)
-ialias (omp_get_default_device)
-ialias (omp_get_initial_device)
-ialias (omp_get_num_devices)
-ialias (omp_is_initial_device)
ialias (omp_get_device_num)
diff --git a/libgomp/icv.c b/libgomp/icv.c
index e32e5b2..4b4892f 100644
--- a/libgomp/icv.c
+++ b/libgomp/icv.c
@@ -30,6 +30,8 @@
#include "gomp-constants.h"
#include <limits.h>
+ialias_redirect (omp_get_active_level)
+
void
omp_set_num_threads (int n)
{
diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map
index e0c813c..460a7a4 100644
--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map
@@ -203,6 +203,10 @@ OMP_5.0.2 {
global:
omp_get_device_num;
omp_get_device_num_;
+ omp_aligned_alloc;
+ omp_calloc;
+ omp_aligned_calloc;
+ omp_realloc;
} OMP_5.0.1;
OMP_5.1 {
diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index b3bab8f..02160f8 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -315,7 +315,7 @@ The OpenMP 4.5 specification is fully supported.
runtime routines @tab N @tab
@item @code{omp_get_mapped_ptr} runtime routine @tab N @tab
@item @code{omp_calloc}, @code{omp_realloc}, @code{omp_aligned_alloc} and
- @code{omp_aligned_calloc} runtime routines @tab N @tab
+ @code{omp_aligned_calloc} runtime routines @tab Y @tab
@item @code{omp_alloctrait_key_t} enum: @code{omp_atv_serialized} added,
@code{omp_atv_default} changed @tab Y @tab
@item @code{omp_display_env} runtime routine @tab P
diff --git a/libgomp/omp.h.in b/libgomp/omp.h.in
index 314f964..d75ee13 100644
--- a/libgomp/omp.h.in
+++ b/libgomp/omp.h.in
@@ -295,12 +295,31 @@ extern omp_allocator_handle_t omp_init_allocator (omp_memspace_handle_t,
extern void omp_destroy_allocator (omp_allocator_handle_t) __GOMP_NOTHROW;
extern void omp_set_default_allocator (omp_allocator_handle_t) __GOMP_NOTHROW;
extern omp_allocator_handle_t omp_get_default_allocator (void) __GOMP_NOTHROW;
-extern void *omp_alloc (__SIZE_TYPE__,
- omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR)
- __GOMP_NOTHROW __attribute__((__malloc__, __alloc_size__ (1)));
extern void omp_free (void *,
omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR)
__GOMP_NOTHROW;
+extern void *omp_alloc (__SIZE_TYPE__,
+ omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR)
+ __GOMP_NOTHROW __attribute__((__malloc__, __malloc__ (omp_free),
+ __alloc_size__ (1)));
+extern void *omp_aligned_alloc (__SIZE_TYPE__, __SIZE_TYPE__,
+ omp_allocator_handle_t
+ __GOMP_DEFAULT_NULL_ALLOCATOR)
+ __GOMP_NOTHROW __attribute__((__malloc__, __malloc__ (omp_free),
+ __alloc_size__ (2), __alloc_align__ (1)));
+extern void *omp_calloc (__SIZE_TYPE__, __SIZE_TYPE__,
+ omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR)
+ __GOMP_NOTHROW __attribute__((__malloc__, __malloc__ (omp_free),
+ __alloc_size__ (1, 2)));
+extern void *omp_aligned_calloc (__SIZE_TYPE__, __SIZE_TYPE__, __SIZE_TYPE__,
+ omp_allocator_handle_t
+ __GOMP_DEFAULT_NULL_ALLOCATOR)
+ __GOMP_NOTHROW __attribute__((__malloc__, __malloc__ (omp_free),
+ __alloc_size__ (2, 3), __alloc_align__ (1)));
+extern void *omp_realloc (void *, __SIZE_TYPE__,
+ omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR,
+ omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR)
+ __GOMP_NOTHROW __attribute__((__malloc__ (omp_free), __alloc_size__ (2)));
extern void omp_display_env (int) __GOMP_NOTHROW;
diff --git a/libgomp/omp_lib.f90.in b/libgomp/omp_lib.f90.in
index a36a562..1063eee 100644
--- a/libgomp/omp_lib.f90.in
+++ b/libgomp/omp_lib.f90.in
@@ -681,12 +681,53 @@
end interface
interface
+ function omp_aligned_alloc (alignment, size, allocator) bind(c)
+ use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t
+ import :: omp_allocator_handle_kind
+ type(c_ptr) :: omp_aligned_alloc
+ integer(c_size_t), value :: alignment, size
+ integer(omp_allocator_handle_kind), value :: allocator
+ end function omp_aligned_alloc
+ end interface
+
+ interface
subroutine omp_free(ptr, allocator) bind(c)
use, intrinsic :: iso_c_binding, only : c_ptr
import :: omp_allocator_handle_kind
type(c_ptr), value :: ptr
integer(omp_allocator_handle_kind), value :: allocator
- end subroutine
+ end subroutine omp_free
+ end interface
+
+ interface
+ function omp_calloc (nmemb, size, allocator) bind(c)
+ use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t
+ import :: omp_allocator_handle_kind
+ type(c_ptr) :: omp_calloc
+ integer(c_size_t), value :: nmemb, size
+ integer(omp_allocator_handle_kind), value :: allocator
+ end function omp_calloc
+ end interface
+
+ interface
+ function omp_aligned_calloc (alignment, nmemb, size, allocator) bind(c)
+ use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t
+ import :: omp_allocator_handle_kind
+ type(c_ptr) :: omp_aligned_calloc
+ integer(c_size_t), value :: alignment, nmemb, size
+ integer(omp_allocator_handle_kind), value :: allocator
+ end function omp_aligned_calloc
+ end interface
+
+ interface
+ function omp_realloc (ptr, size, allocator, free_allocator) bind(c)
+ use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t
+ import :: omp_allocator_handle_kind
+ type(c_ptr) :: omp_realloc
+ type(c_ptr), value :: ptr
+ integer(c_size_t), value :: size
+ integer(omp_allocator_handle_kind), value :: allocator, free_allocator
+ end function omp_realloc
end interface
interface
diff --git a/libgomp/omp_lib.h.in b/libgomp/omp_lib.h.in
index 1c2eacb..f40321c 100644
--- a/libgomp/omp_lib.h.in
+++ b/libgomp/omp_lib.h.in
@@ -283,12 +283,56 @@
end interface
interface
+ function omp_aligned_alloc (alignment, size, allocator) bind(c)
+ use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t
+ use, intrinsic :: omp_lib_kinds
+ type(c_ptr) :: omp_aligned_alloc
+ integer(c_size_t), value :: alignment, size
+ integer(omp_allocator_handle_kind), value :: allocator
+ end function omp_aligned_alloc
+ end interface
+
+ interface
subroutine omp_free(ptr, allocator) bind(c)
use, intrinsic :: iso_c_binding, only : c_ptr
use, intrinsic :: omp_lib_kinds
type(c_ptr), value :: ptr
integer(omp_allocator_handle_kind), value :: allocator
- end subroutine
+ end subroutine omp_free
+ end interface
+
+ interface
+ function omp_calloc (nmemb, size, allocator) bind(c)
+ use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t
+ use, intrinsic :: omp_lib_kinds
+ type(c_ptr) :: omp_calloc
+ integer(c_size_t), value :: nmemb, size
+ integer(omp_allocator_handle_kind), value :: allocator
+ end function omp_calloc
+ end interface
+
+ interface
+ function omp_aligned_calloc (alignment, nmemb, size, allocator) &
+ & bind(c)
+ use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t
+ use, intrinsic :: omp_lib_kinds
+ type(c_ptr) :: omp_aligned_calloc
+ integer(c_size_t), value :: alignment, nmemb, size
+ integer(omp_allocator_handle_kind), value :: allocator
+ end function omp_aligned_calloc
+ end interface
+
+ interface
+ function omp_realloc (ptr, size, allocator, free_allocator) &
+ & bind(c)
+ use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t
+ use, intrinsic :: omp_lib_kinds
+ type(c_ptr) :: omp_realloc
+ type(c_ptr), value :: ptr
+ integer(c_size_t), value :: size
+ integer(omp_allocator_handle_kind), value :: allocator
+ integer(omp_allocator_handle_kind), value :: free_allocator
+ end function omp_realloc
end interface
interface
diff --git a/libgomp/team.c b/libgomp/team.c
index ba57152..11a2521 100644
--- a/libgomp/team.c
+++ b/libgomp/team.c
@@ -312,7 +312,7 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
unsigned flags, struct gomp_team *team,
struct gomp_taskgroup *taskgroup)
{
- struct gomp_thread_start_data *start_data;
+ struct gomp_thread_start_data *start_data = NULL;
struct gomp_thread *thr, *nthr;
struct gomp_task *task;
struct gomp_task_icv *icv;
diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-4.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-4.c
index 841e1bc..67ba1cd 100644
--- a/libgomp/testsuite/libgomp.c-c++-common/alloc-4.c
+++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-4.c
@@ -12,12 +12,30 @@ main ()
if (omp_alloc (0, omp_null_allocator) != NULL)
abort ();
+ if (omp_aligned_alloc (64, 0, omp_null_allocator) != NULL)
+ abort ();
+ if (omp_calloc (0, 0, omp_null_allocator) != NULL
+ || omp_calloc (32, 0, omp_null_allocator) != NULL
+ || omp_calloc (0, 64, omp_null_allocator) != NULL)
+ abort ();
+ if (omp_aligned_calloc (32, 0, 0, omp_null_allocator) != NULL
+ || omp_aligned_calloc (64, 32, 0, omp_null_allocator) != NULL
+ || omp_aligned_calloc (16, 0, 64, omp_null_allocator) != NULL)
+ abort ();
a = omp_init_allocator (omp_default_mem_space, 2, traits);
if (a != omp_null_allocator)
{
if (omp_alloc (0, a) != NULL
|| omp_alloc (0, a) != NULL
- || omp_alloc (0, a) != NULL)
+ || omp_alloc (0, a) != NULL
+ || omp_aligned_alloc (16, 0, a) != NULL
+ || omp_aligned_alloc (128, 0, a) != NULL
+ || omp_calloc (0, 0, a) != NULL
+ || omp_calloc (32, 0, a) != NULL
+ || omp_calloc (0, 64, a) != NULL
+ || omp_aligned_calloc (32, 0, 0, a) != NULL
+ || omp_aligned_calloc (64, 32, 0, a) != NULL
+ || omp_aligned_calloc (16, 0, 64, a) != NULL)
abort ();
omp_destroy_allocator (a);
}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-5.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-5.c
new file mode 100644
index 0000000..8b4a489
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-5.c
@@ -0,0 +1,159 @@
+#include <omp.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+const omp_alloctrait_t traits2[]
+= { { omp_atk_alignment, 16 },
+ { omp_atk_sync_hint, omp_atv_default },
+ { omp_atk_access, omp_atv_default },
+ { omp_atk_pool_size, 1024 },
+ { omp_atk_fallback, omp_atv_default_mem_fb },
+ { omp_atk_partition, omp_atv_environment } };
+omp_alloctrait_t traits3[]
+= { { omp_atk_sync_hint, omp_atv_uncontended },
+ { omp_atk_alignment, 32 },
+ { omp_atk_access, omp_atv_all },
+ { omp_atk_pool_size, 512 },
+ { omp_atk_fallback, omp_atv_allocator_fb },
+ { omp_atk_fb_data, 0 },
+ { omp_atk_partition, omp_atv_default } };
+const omp_alloctrait_t traits4[]
+= { { omp_atk_alignment, 128 },
+ { omp_atk_pool_size, 1024 },
+ { omp_atk_fallback, omp_atv_null_fb } };
+
+int
+main ()
+{
+ int *volatile p = (int *) omp_aligned_alloc (sizeof (int), 3 * sizeof (int), omp_default_mem_alloc);
+ int *volatile q;
+ int *volatile r;
+ omp_alloctrait_t traits[3]
+ = { { omp_atk_alignment, 64 },
+ { omp_atk_fallback, omp_atv_null_fb },
+ { omp_atk_pool_size, 4096 } };
+ omp_allocator_handle_t a, a2;
+
+ if ((((uintptr_t) p) % __alignof (int)) != 0)
+ abort ();
+ p[0] = 1;
+ p[1] = 2;
+ p[2] = 3;
+ omp_free (p, omp_default_mem_alloc);
+ p = (int *) omp_aligned_alloc (2 * sizeof (int), 2 * sizeof (int), omp_default_mem_alloc);
+ if ((((uintptr_t) p) % (2 * sizeof (int))) != 0)
+ abort ();
+ p[0] = 1;
+ p[1] = 2;
+ omp_free (p, omp_null_allocator);
+ omp_set_default_allocator (omp_default_mem_alloc);
+ p = (int *) omp_aligned_alloc (1, sizeof (int), omp_null_allocator);
+ if ((((uintptr_t) p) % __alignof (int)) != 0)
+ abort ();
+ p[0] = 3;
+ omp_free (p, omp_get_default_allocator ());
+
+ a = omp_init_allocator (omp_default_mem_space, 3, traits);
+ if (a == omp_null_allocator)
+ abort ();
+ p = (int *) omp_aligned_alloc (32, 3072, a);
+ if ((((uintptr_t) p) % 64) != 0)
+ abort ();
+ p[0] = 1;
+ p[3071 / sizeof (int)] = 2;
+ if (omp_aligned_alloc (8, 3072, a) != NULL)
+ abort ();
+ omp_free (p, a);
+ p = (int *) omp_aligned_alloc (128, 3072, a);
+ if ((((uintptr_t) p) % 128) != 0)
+ abort ();
+ p[0] = 3;
+ p[3071 / sizeof (int)] = 4;
+ omp_free (p, omp_null_allocator);
+ omp_set_default_allocator (a);
+ if (omp_get_default_allocator () != a)
+ abort ();
+ p = (int *) omp_aligned_alloc (64, 3072, omp_null_allocator);
+ if (omp_aligned_alloc (8, 3072, omp_null_allocator) != NULL)
+ abort ();
+ omp_free (p, a);
+ omp_destroy_allocator (a);
+
+ a = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits2) / sizeof (traits2[0]),
+ traits2);
+ if (a == omp_null_allocator)
+ abort ();
+ if (traits3[5].key != omp_atk_fb_data)
+ abort ();
+ traits3[5].value = (uintptr_t) a;
+ a2 = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits3) / sizeof (traits3[0]),
+ traits3);
+ if (a2 == omp_null_allocator)
+ abort ();
+ p = (int *) omp_aligned_alloc (4, 420, a2);
+ if ((((uintptr_t) p) % 32) != 0)
+ abort ();
+ p[0] = 5;
+ p[419 / sizeof (int)] = 6;
+ q = (int *) omp_aligned_alloc (8, 768, a2);
+ if ((((uintptr_t) q) % 16) != 0)
+ abort ();
+ q[0] = 7;
+ q[767 / sizeof (int)] = 8;
+ r = (int *) omp_aligned_alloc (8, 512, a2);
+ if ((((uintptr_t) r) % 8) != 0)
+ abort ();
+ r[0] = 9;
+ r[511 / sizeof (int)] = 10;
+ omp_free (p, omp_null_allocator);
+ omp_free (q, a2);
+ omp_free (r, omp_null_allocator);
+ omp_destroy_allocator (a2);
+ omp_destroy_allocator (a);
+
+ a = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits4) / sizeof (traits4[0]),
+ traits4);
+ if (a == omp_null_allocator)
+ abort ();
+ if (traits3[5].key != omp_atk_fb_data)
+ abort ();
+ traits3[5].value = (uintptr_t) a;
+ a2 = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits3) / sizeof (traits3[0]),
+ traits3);
+ if (a2 == omp_null_allocator)
+ abort ();
+ omp_set_default_allocator (a2);
+#ifdef __cplusplus
+ p = static_cast <int *> (omp_aligned_alloc (4, 420));
+#else
+ p = (int *) omp_aligned_alloc (4, 420, omp_null_allocator);
+#endif
+ if ((((uintptr_t) p) % 32) != 0)
+ abort ();
+ p[0] = 5;
+ p[419 / sizeof (int)] = 6;
+ q = (int *) omp_aligned_alloc (64, 768, omp_null_allocator);
+ if ((((uintptr_t) q) % 128) != 0)
+ abort ();
+ q[0] = 7;
+ q[767 / sizeof (int)] = 8;
+ if (omp_aligned_alloc (8, 768, omp_null_allocator) != NULL)
+ abort ();
+#ifdef __cplusplus
+ omp_free (p);
+ omp_free (q);
+ omp_free (NULL);
+#else
+ omp_free (p, omp_null_allocator);
+ omp_free (q, omp_null_allocator);
+ omp_free (NULL, omp_null_allocator);
+#endif
+ omp_free (NULL, omp_null_allocator);
+ omp_destroy_allocator (a2);
+ omp_destroy_allocator (a);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-6.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-6.c
new file mode 100644
index 0000000..be571b7e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-6.c
@@ -0,0 +1,58 @@
+#include <omp.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+const omp_alloctrait_t traits[]
+= { { omp_atk_alignment, 16 },
+ { omp_atk_sync_hint, omp_atv_default },
+ { omp_atk_access, omp_atv_default },
+ { omp_atk_fallback, omp_atv_default_mem_fb },
+ { omp_atk_partition, omp_atv_environment } };
+
+int
+main ()
+{
+ omp_allocator_handle_t a;
+ void *p, *q;
+ volatile size_t large_sz;
+
+ a = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits) / sizeof (traits[0]),
+ traits);
+ if (a == omp_null_allocator)
+ abort ();
+ p = omp_alloc (2048, a);
+ if ((((uintptr_t) p) % 16) != 0)
+ abort ();
+ large_sz = ~(size_t) 1023;
+ q = omp_alloc (large_sz, a);
+ if (q != NULL)
+ abort ();
+ q = omp_aligned_alloc (32, large_sz, a);
+ if (q != NULL)
+ abort ();
+ q = omp_calloc (large_sz / 4, 4, a);
+ if (q != NULL)
+ abort ();
+ q = omp_aligned_calloc (1, 2, large_sz / 2, a);
+ if (q != NULL)
+ abort ();
+ omp_free (p, a);
+ large_sz = ~(size_t) 0;
+ large_sz >>= 1;
+ large_sz += 1;
+ if (omp_calloc (2, large_sz, a) != NULL)
+ abort ();
+ if (omp_calloc (large_sz, 1024, a) != NULL)
+ abort ();
+ if (omp_calloc (large_sz, large_sz, a) != NULL)
+ abort ();
+ if (omp_aligned_calloc (16, 2, large_sz, a) != NULL)
+ abort ();
+ if (omp_aligned_calloc (32, large_sz, 1024, a) != NULL)
+ abort ();
+ if (omp_aligned_calloc (64, large_sz, large_sz, a) != NULL)
+ abort ();
+ omp_destroy_allocator (a);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-7.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-7.c
new file mode 100644
index 0000000..d66e25a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-7.c
@@ -0,0 +1,182 @@
+#include <omp.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+const omp_alloctrait_t traits2[]
+= { { omp_atk_alignment, 16 },
+ { omp_atk_sync_hint, omp_atv_default },
+ { omp_atk_access, omp_atv_default },
+ { omp_atk_pool_size, 1024 },
+ { omp_atk_fallback, omp_atv_default_mem_fb },
+ { omp_atk_partition, omp_atv_environment } };
+omp_alloctrait_t traits3[]
+= { { omp_atk_sync_hint, omp_atv_uncontended },
+ { omp_atk_alignment, 32 },
+ { omp_atk_access, omp_atv_all },
+ { omp_atk_pool_size, 512 },
+ { omp_atk_fallback, omp_atv_allocator_fb },
+ { omp_atk_fb_data, 0 },
+ { omp_atk_partition, omp_atv_default } };
+const omp_alloctrait_t traits4[]
+= { { omp_atk_alignment, 128 },
+ { omp_atk_pool_size, 1024 },
+ { omp_atk_fallback, omp_atv_null_fb } };
+
+int
+main ()
+{
+ int *volatile p = (int *) omp_calloc (3, sizeof (int), omp_default_mem_alloc);
+ int *volatile q;
+ int *volatile r;
+ int i;
+ omp_alloctrait_t traits[3]
+ = { { omp_atk_alignment, 64 },
+ { omp_atk_fallback, omp_atv_null_fb },
+ { omp_atk_pool_size, 4096 } };
+ omp_allocator_handle_t a, a2;
+
+ if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0] || p[1] || p[2])
+ abort ();
+ p[0] = 1;
+ p[1] = 2;
+ p[2] = 3;
+ omp_free (p, omp_default_mem_alloc);
+ p = (int *) omp_calloc (2, sizeof (int), omp_default_mem_alloc);
+ if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0] || p[1])
+ abort ();
+ p[0] = 1;
+ p[1] = 2;
+ omp_free (p, omp_null_allocator);
+ omp_set_default_allocator (omp_default_mem_alloc);
+ p = (int *) omp_calloc (1, sizeof (int), omp_null_allocator);
+ if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0])
+ abort ();
+ p[0] = 3;
+ omp_free (p, omp_get_default_allocator ());
+
+ a = omp_init_allocator (omp_default_mem_space, 3, traits);
+ if (a == omp_null_allocator)
+ abort ();
+ p = (int *) omp_calloc (3, 1024, a);
+ if ((((uintptr_t) p) % 64) != 0)
+ abort ();
+ for (i = 0; i < 3072 / sizeof (int); i++)
+ if (p[i])
+ abort ();
+ p[0] = 1;
+ p[3071 / sizeof (int)] = 2;
+ if (omp_calloc (1024, 3, a) != NULL)
+ abort ();
+ omp_free (p, a);
+ p = (int *) omp_calloc (512, 6, a);
+ for (i = 0; i < 3072 / sizeof (int); i++)
+ if (p[i])
+ abort ();
+ p[0] = 3;
+ p[3071 / sizeof (int)] = 4;
+ omp_free (p, omp_null_allocator);
+ omp_set_default_allocator (a);
+ if (omp_get_default_allocator () != a)
+ abort ();
+ p = (int *) omp_calloc (12, 256, omp_null_allocator);
+ for (i = 0; i < 3072 / sizeof (int); i++)
+ if (p[i])
+ abort ();
+ if (omp_calloc (128, 24, omp_null_allocator) != NULL)
+ abort ();
+ omp_free (p, a);
+ omp_destroy_allocator (a);
+
+ a = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits2) / sizeof (traits2[0]),
+ traits2);
+ if (a == omp_null_allocator)
+ abort ();
+ if (traits3[5].key != omp_atk_fb_data)
+ abort ();
+ traits3[5].value = (uintptr_t) a;
+ a2 = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits3) / sizeof (traits3[0]),
+ traits3);
+ if (a2 == omp_null_allocator)
+ abort ();
+ p = (int *) omp_calloc (10, 42, a2);
+ for (i = 0; i < 420 / sizeof (int); i++)
+ if (p[i])
+ abort ();
+ if ((((uintptr_t) p) % 32) != 0)
+ abort ();
+ p[0] = 5;
+ p[419 / sizeof (int)] = 6;
+ q = (int *) omp_calloc (24, 32, a2);
+ if ((((uintptr_t) q) % 16) != 0)
+ abort ();
+ for (i = 0; i < 768 / sizeof (int); i++)
+ if (q[i])
+ abort ();
+ q[0] = 7;
+ q[767 / sizeof (int)] = 8;
+ r = (int *) omp_calloc (128, 4, a2);
+ if ((((uintptr_t) r) % __alignof (int)) != 0)
+ abort ();
+ for (i = 0; i < 512 / sizeof (int); i++)
+ if (r[i])
+ abort ();
+ r[0] = 9;
+ r[511 / sizeof (int)] = 10;
+ omp_free (p, omp_null_allocator);
+ omp_free (q, a2);
+ omp_free (r, omp_null_allocator);
+ omp_destroy_allocator (a2);
+ omp_destroy_allocator (a);
+
+ a = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits4) / sizeof (traits4[0]),
+ traits4);
+ if (a == omp_null_allocator)
+ abort ();
+ if (traits3[5].key != omp_atk_fb_data)
+ abort ();
+ traits3[5].value = (uintptr_t) a;
+ a2 = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits3) / sizeof (traits3[0]),
+ traits3);
+ if (a2 == omp_null_allocator)
+ abort ();
+ omp_set_default_allocator (a2);
+#ifdef __cplusplus
+ p = static_cast <int *> (omp_calloc (42, 10));
+#else
+ p = (int *) omp_calloc (42, 10, omp_null_allocator);
+#endif
+ if ((((uintptr_t) p) % 32) != 0)
+ abort ();
+ for (i = 0; i < 420 / sizeof (int); i++)
+ if (p[i])
+ abort ();
+ p[0] = 5;
+ p[419 / sizeof (int)] = 6;
+ q = (int *) omp_calloc (32, 24, omp_null_allocator);
+ if ((((uintptr_t) q) % 128) != 0)
+ abort ();
+ for (i = 0; i < 768 / sizeof (int); i++)
+ if (q[i])
+ abort ();
+ q[0] = 7;
+ q[767 / sizeof (int)] = 8;
+ if (omp_calloc (24, 32, omp_null_allocator) != NULL)
+ abort ();
+#ifdef __cplusplus
+ omp_free (p);
+ omp_free (q);
+ omp_free (NULL);
+#else
+ omp_free (p, omp_null_allocator);
+ omp_free (q, omp_null_allocator);
+ omp_free (NULL, omp_null_allocator);
+#endif
+ omp_free (NULL, omp_null_allocator);
+ omp_destroy_allocator (a2);
+ omp_destroy_allocator (a);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-8.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-8.c
new file mode 100644
index 0000000..bd4e08a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-8.c
@@ -0,0 +1,184 @@
+#include <omp.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+const omp_alloctrait_t traits2[]
+= { { omp_atk_alignment, 16 },
+ { omp_atk_sync_hint, omp_atv_default },
+ { omp_atk_access, omp_atv_default },
+ { omp_atk_pool_size, 1024 },
+ { omp_atk_fallback, omp_atv_default_mem_fb },
+ { omp_atk_partition, omp_atv_environment } };
+omp_alloctrait_t traits3[]
+= { { omp_atk_sync_hint, omp_atv_uncontended },
+ { omp_atk_alignment, 32 },
+ { omp_atk_access, omp_atv_all },
+ { omp_atk_pool_size, 512 },
+ { omp_atk_fallback, omp_atv_allocator_fb },
+ { omp_atk_fb_data, 0 },
+ { omp_atk_partition, omp_atv_default } };
+const omp_alloctrait_t traits4[]
+= { { omp_atk_alignment, 128 },
+ { omp_atk_pool_size, 1024 },
+ { omp_atk_fallback, omp_atv_null_fb } };
+
+int
+main ()
+{
+ int *volatile p = (int *) omp_aligned_calloc (sizeof (int), 3, sizeof (int), omp_default_mem_alloc);
+ int *volatile q;
+ int *volatile r;
+ int i;
+ omp_alloctrait_t traits[3]
+ = { { omp_atk_alignment, 64 },
+ { omp_atk_fallback, omp_atv_null_fb },
+ { omp_atk_pool_size, 4096 } };
+ omp_allocator_handle_t a, a2;
+
+ if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0] || p[1] || p[2])
+ abort ();
+ p[0] = 1;
+ p[1] = 2;
+ p[2] = 3;
+ omp_free (p, omp_default_mem_alloc);
+ p = (int *) omp_aligned_calloc (2 * sizeof (int), 1, 2 * sizeof (int), omp_default_mem_alloc);
+ if ((((uintptr_t) p) % (2 * sizeof (int))) != 0 || p[0] || p[1])
+ abort ();
+ p[0] = 1;
+ p[1] = 2;
+ omp_free (p, omp_null_allocator);
+ omp_set_default_allocator (omp_default_mem_alloc);
+ p = (int *) omp_aligned_calloc (1, 1, sizeof (int), omp_null_allocator);
+ if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0])
+ abort ();
+ p[0] = 3;
+ omp_free (p, omp_get_default_allocator ());
+
+ a = omp_init_allocator (omp_default_mem_space, 3, traits);
+ if (a == omp_null_allocator)
+ abort ();
+ p = (int *) omp_aligned_calloc (32, 3, 1024, a);
+ if ((((uintptr_t) p) % 64) != 0)
+ abort ();
+ for (i = 0; i < 3072 / sizeof (int); i++)
+ if (p[i])
+ abort ();
+ p[0] = 1;
+ p[3071 / sizeof (int)] = 2;
+ if (omp_aligned_calloc (8, 192, 16, a) != NULL)
+ abort ();
+ omp_free (p, a);
+ p = (int *) omp_aligned_calloc (128, 6, 512, a);
+ if ((((uintptr_t) p) % 128) != 0)
+ abort ();
+ for (i = 0; i < 3072 / sizeof (int); i++)
+ if (p[i])
+ abort ();
+ p[0] = 3;
+ p[3071 / sizeof (int)] = 4;
+ omp_free (p, omp_null_allocator);
+ omp_set_default_allocator (a);
+ if (omp_get_default_allocator () != a)
+ abort ();
+ p = (int *) omp_aligned_calloc (64, 12, 256, omp_null_allocator);
+ for (i = 0; i < 3072 / sizeof (int); i++)
+ if (p[i])
+ abort ();
+ if (omp_aligned_calloc (8, 128, 24, omp_null_allocator) != NULL)
+ abort ();
+ omp_free (p, a);
+ omp_destroy_allocator (a);
+
+ a = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits2) / sizeof (traits2[0]),
+ traits2);
+ if (a == omp_null_allocator)
+ abort ();
+ if (traits3[5].key != omp_atk_fb_data)
+ abort ();
+ traits3[5].value = (uintptr_t) a;
+ a2 = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits3) / sizeof (traits3[0]),
+ traits3);
+ if (a2 == omp_null_allocator)
+ abort ();
+ p = (int *) omp_aligned_calloc (4, 5, 84, a2);
+ for (i = 0; i < 420 / sizeof (int); i++)
+ if (p[i])
+ abort ();
+ if ((((uintptr_t) p) % 32) != 0)
+ abort ();
+ p[0] = 5;
+ p[419 / sizeof (int)] = 6;
+ q = (int *) omp_aligned_calloc (8, 24, 32, a2);
+ if ((((uintptr_t) q) % 16) != 0)
+ abort ();
+ for (i = 0; i < 768 / sizeof (int); i++)
+ if (q[i])
+ abort ();
+ q[0] = 7;
+ q[767 / sizeof (int)] = 8;
+ r = (int *) omp_aligned_calloc (8, 64, 8, a2);
+ if ((((uintptr_t) r) % 8) != 0)
+ abort ();
+ for (i = 0; i < 512 / sizeof (int); i++)
+ if (r[i])
+ abort ();
+ r[0] = 9;
+ r[511 / sizeof (int)] = 10;
+ omp_free (p, omp_null_allocator);
+ omp_free (q, a2);
+ omp_free (r, omp_null_allocator);
+ omp_destroy_allocator (a2);
+ omp_destroy_allocator (a);
+
+ a = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits4) / sizeof (traits4[0]),
+ traits4);
+ if (a == omp_null_allocator)
+ abort ();
+ if (traits3[5].key != omp_atk_fb_data)
+ abort ();
+ traits3[5].value = (uintptr_t) a;
+ a2 = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits3) / sizeof (traits3[0]),
+ traits3);
+ if (a2 == omp_null_allocator)
+ abort ();
+ omp_set_default_allocator (a2);
+#ifdef __cplusplus
+ p = static_cast <int *> (omp_aligned_calloc (4, 21, 20));
+#else
+ p = (int *) omp_aligned_calloc (4, 21, 20, omp_null_allocator);
+#endif
+ if ((((uintptr_t) p) % 32) != 0)
+ abort ();
+ for (i = 0; i < 420 / sizeof (int); i++)
+ if (p[i])
+ abort ();
+ p[0] = 5;
+ p[419 / sizeof (int)] = 6;
+ q = (int *) omp_aligned_calloc (64, 12, 64, omp_null_allocator);
+ if ((((uintptr_t) q) % 128) != 0)
+ abort ();
+ for (i = 0; i < 768 / sizeof (int); i++)
+ if (q[i])
+ abort ();
+ q[0] = 7;
+ q[767 / sizeof (int)] = 8;
+ if (omp_aligned_calloc (8, 24, 32, omp_null_allocator) != NULL)
+ abort ();
+#ifdef __cplusplus
+ omp_free (p);
+ omp_free (q);
+ omp_free (NULL);
+#else
+ omp_free (p, omp_null_allocator);
+ omp_free (q, omp_null_allocator);
+ omp_free (NULL, omp_null_allocator);
+#endif
+ omp_free (NULL, omp_null_allocator);
+ omp_destroy_allocator (a2);
+ omp_destroy_allocator (a);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-9.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-9.c
new file mode 100644
index 0000000..e4b7baf
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-9.c
@@ -0,0 +1,271 @@
+#include <omp.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+const omp_alloctrait_t traits2[]
+= { { omp_atk_alignment, 16 },
+ { omp_atk_sync_hint, omp_atv_default },
+ { omp_atk_access, omp_atv_default },
+ { omp_atk_pool_size, 1024 },
+ { omp_atk_fallback, omp_atv_default_mem_fb },
+ { omp_atk_partition, omp_atv_environment } };
+omp_alloctrait_t traits3[]
+= { { omp_atk_sync_hint, omp_atv_uncontended },
+ { omp_atk_alignment, 32 },
+ { omp_atk_access, omp_atv_all },
+ { omp_atk_pool_size, 512 },
+ { omp_atk_fallback, omp_atv_allocator_fb },
+ { omp_atk_fb_data, 0 },
+ { omp_atk_partition, omp_atv_default } };
+const omp_alloctrait_t traits4[]
+= { { omp_atk_alignment, 128 },
+ { omp_atk_pool_size, 1024 },
+ { omp_atk_fallback, omp_atv_null_fb } };
+
+int
+main ()
+{
+ int *volatile p = (int *) omp_alloc (3 * sizeof (int), omp_default_mem_alloc);
+ int *volatile q;
+ int *volatile r;
+ omp_alloctrait_t traits[3]
+ = { { omp_atk_alignment, 64 },
+ { omp_atk_fallback, omp_atv_null_fb },
+ { omp_atk_pool_size, 4096 } };
+ omp_alloctrait_t traits5[2]
+ = { { omp_atk_fallback, omp_atv_null_fb },
+ { omp_atk_pool_size, 4096 } };
+ omp_allocator_handle_t a, a2;
+
+ if ((((uintptr_t) p) % __alignof (int)) != 0)
+ abort ();
+ p[0] = 1;
+ p[1] = 2;
+ p[2] = 3;
+ p = (int *) omp_realloc (p, 4 * sizeof (int), omp_default_mem_alloc, omp_default_mem_alloc);
+ if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0] != 1 || p[1] != 2 || p[2] != 3)
+ abort ();
+ p[0] = 4;
+ p[1] = 5;
+ p[2] = 6;
+ p[3] = 7;
+ p = (int *) omp_realloc (p, 2 * sizeof (int), omp_default_mem_alloc, omp_default_mem_alloc);
+ if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0] != 4 || p[1] != 5)
+ abort ();
+ p[0] = 8;
+ p[1] = 9;
+ if (omp_realloc (p, 0, omp_null_allocator, omp_default_mem_alloc) != NULL)
+ abort ();
+ p = (int *) omp_realloc (NULL, 2 * sizeof (int), omp_default_mem_alloc, omp_null_allocator);
+ if ((((uintptr_t) p) % __alignof (int)) != 0)
+ abort ();
+ p[0] = 1;
+ p[1] = 2;
+ p = (int *) omp_realloc (p, 5 * sizeof (int), omp_default_mem_alloc, omp_default_mem_alloc);
+ if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0] != 1 || p[1] != 2)
+ abort ();
+ p[0] = 3;
+ p[1] = 4;
+ p[2] = 5;
+ p[3] = 6;
+ p[4] = 7;
+ omp_free (p, omp_null_allocator);
+ omp_set_default_allocator (omp_default_mem_alloc);
+ if (omp_realloc (NULL, 0, omp_null_allocator, omp_null_allocator) != NULL)
+ abort ();
+ p = (int *) omp_alloc (sizeof (int), omp_null_allocator);
+ if ((((uintptr_t) p) % __alignof (int)) != 0)
+ abort ();
+ p[0] = 3;
+ p = (int *) omp_realloc (p, 3 * sizeof (int), omp_null_allocator, omp_null_allocator);
+ if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0] != 3)
+ abort ();
+ p[0] = 4;
+ p[1] = 5;
+ p[2] = 6;
+ if (omp_realloc (p, 0, omp_null_allocator, omp_get_default_allocator ()) != NULL)
+ abort ();
+ a = omp_init_allocator (omp_default_mem_space, 3, traits);
+ if (a == omp_null_allocator)
+ abort ();
+ p = (int *) omp_alloc (sizeof (int), a);
+ if ((((uintptr_t) p) % 64) != 0)
+ abort ();
+ p[0] = 7;
+ p = (int *) omp_realloc (p, 3072, a, a);
+ if ((((uintptr_t) p) % 64) != 0 || p[0] != 7)
+ abort ();
+ p[0] = 1;
+ p[3071 / sizeof (int)] = 2;
+ q = (int *) omp_alloc (sizeof (int), a);
+ if ((((uintptr_t) q) % 64) != 0)
+ abort ();
+ q[0] = 8;
+ if (omp_realloc (q, 3072, a, a) != NULL)
+ abort ();
+ omp_free (p, a);
+ omp_free (q, a);
+ p = (int *) omp_alloc (sizeof (int), a);
+ p[0] = 42;
+ p = (int *) omp_realloc (p, 3072, a, a);
+ if (p[0] != 42)
+ abort ();
+ p[0] = 3;
+ p[3071 / sizeof (int)] = 4;
+ omp_realloc (p, 0, omp_null_allocator, omp_null_allocator);
+ omp_set_default_allocator (a);
+ if (omp_get_default_allocator () != a)
+ abort ();
+ p = (int *) omp_alloc (31, omp_null_allocator);
+ if (p == NULL)
+ abort ();
+ p = (int *) omp_realloc (p, 3072, omp_null_allocator, omp_null_allocator);
+ if (p == NULL)
+ abort ();
+ q = (int *) omp_alloc (sizeof (int), omp_null_allocator);
+ if (q == NULL)
+ abort ();
+ if (omp_realloc (q, 3072, omp_null_allocator, omp_null_allocator) != NULL)
+ abort ();
+ omp_free (p, a);
+ omp_free (q, a);
+ omp_destroy_allocator (a);
+
+ a = omp_init_allocator (omp_default_mem_space, 2, traits5);
+ if (a == omp_null_allocator)
+ abort ();
+ omp_set_default_allocator (a);
+ if (omp_get_default_allocator () != a)
+ abort ();
+ p = (int *) omp_alloc (3071, omp_null_allocator);
+ if (p == NULL)
+ abort ();
+ p = (int *) omp_realloc (p, 3072, omp_null_allocator, omp_null_allocator);
+ if (p == NULL)
+ abort ();
+ q = (int *) omp_alloc (sizeof (int), omp_null_allocator);
+ if (q == NULL)
+ abort ();
+ if (omp_realloc (q, 3072, omp_null_allocator, omp_null_allocator) != NULL)
+ abort ();
+ omp_free (p, a);
+ omp_free (q, a);
+ omp_destroy_allocator (a);
+
+ a = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits2) / sizeof (traits2[0]),
+ traits2);
+ if (a == omp_null_allocator)
+ abort ();
+ if (traits3[5].key != omp_atk_fb_data)
+ abort ();
+ traits3[5].value = (uintptr_t) a;
+ a2 = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits3) / sizeof (traits3[0]),
+ traits3);
+ if (a2 == omp_null_allocator)
+ abort ();
+ p = (int *) omp_alloc (sizeof (int), a2);
+ if ((((uintptr_t) p) % 32) != 0)
+ abort ();
+ p[0] = 84;
+ p = (int *) omp_realloc (p, 380, a2, a2);
+ if ((((uintptr_t) p) % 32) != 0 || p[0] != 84)
+ abort ();
+ p[0] = 5;
+ p[379 / sizeof (int)] = 6;
+ q = (int *) omp_alloc (sizeof (int), a2);
+ if ((((uintptr_t) q) % 32) != 0)
+ abort ();
+ q[0] = 42;
+ q = (int *) omp_realloc (q, 768, a2, a2);
+ if ((((uintptr_t) q) % 16) != 0 || q[0] != 42)
+ abort ();
+ q[0] = 7;
+ q[767 / sizeof (int)] = 8;
+ r = (int *) omp_realloc (NULL, 512, a2, omp_null_allocator);
+ if ((((uintptr_t) r) % __alignof (int)) != 0)
+ abort ();
+ r[0] = 9;
+ r[511 / sizeof (int)] = 10;
+ omp_free (p, omp_null_allocator);
+ omp_free (q, a2);
+ omp_free (r, omp_null_allocator);
+ p = (int *) omp_alloc (sizeof (int), a2);
+ if ((((uintptr_t) p) % 32) != 0)
+ abort ();
+ p[0] = 85;
+ p = (int *) omp_realloc (p, 420, a, a2);
+ if ((((uintptr_t) p) % 16) != 0 || p[0] != 85)
+ abort ();
+ p[0] = 5;
+ p[419 / sizeof (int)] = 6;
+ q = (int *) omp_alloc (sizeof (int), a);
+ if ((((uintptr_t) q) % 16) != 0)
+ abort ();
+ q[0] = 43;
+ q = (int *) omp_realloc (q, 420, a2, a);
+ if ((((uintptr_t) q) % 32) != 0 || q[0] != 43)
+ abort ();
+ q[0] = 44;
+ q[419 / sizeof (int)] = 8;
+ q = (int *) omp_realloc (q, 768, a2, a2);
+ if ((((uintptr_t) q) % 16) != 0 || q[0] != 44)
+ abort ();
+ q[0] = 7;
+ q[767 / sizeof (int)] = 8;
+ omp_free (p, omp_null_allocator);
+ omp_free (q, a2);
+ omp_destroy_allocator (a2);
+ omp_destroy_allocator (a);
+
+ a = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits4) / sizeof (traits4[0]),
+ traits4);
+ if (a == omp_null_allocator)
+ abort ();
+ if (traits3[5].key != omp_atk_fb_data)
+ abort ();
+ traits3[5].value = (uintptr_t) a;
+ a2 = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits3) / sizeof (traits3[0]),
+ traits3);
+ if (a2 == omp_null_allocator)
+ abort ();
+ omp_set_default_allocator (a2);
+#ifdef __cplusplus
+ p = static_cast <int *> (omp_realloc (NULL, 420));
+#else
+ p = (int *) omp_realloc (NULL, 420, omp_null_allocator, omp_null_allocator);
+#endif
+ if ((((uintptr_t) p) % 32) != 0)
+ abort ();
+ p[0] = 5;
+ p[419 / sizeof (int)] = 6;
+ q = (int *) omp_realloc (NULL, sizeof (int), omp_null_allocator, omp_null_allocator);
+ if ((((uintptr_t) q) % 32) != 0)
+ abort ();
+ q[0] = 99;
+ q = (int *) omp_realloc (q, 700, omp_null_allocator, omp_null_allocator);
+ if ((((uintptr_t) q) % 128) != 0 || q[0] != 99)
+ abort ();
+ q[0] = 7;
+ q[699 / sizeof (int)] = 8;
+ if (omp_realloc (NULL, 768, omp_null_allocator, omp_null_allocator) != NULL)
+ abort ();
+#ifdef __cplusplus
+ omp_free (p);
+ if (omp_realloc (q, 0) != NULL)
+ abort ();
+ omp_free (NULL);
+#else
+ omp_free (p, omp_null_allocator);
+ if (omp_realloc (q, 0, omp_null_allocator, omp_null_allocator) != NULL)
+ abort ();
+ omp_free (NULL, omp_null_allocator);
+#endif
+ omp_free (NULL, omp_null_allocator);
+ omp_destroy_allocator (a2);
+ omp_destroy_allocator (a);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/allocate-2.c b/libgomp/testsuite/libgomp.c-c++-common/allocate-2.c
new file mode 100644
index 0000000..e4cd09a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/allocate-2.c
@@ -0,0 +1,37 @@
+#include <omp.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+int zero;
+
+omp_allocator_handle_t
+allocator (omp_allocator_handle_t h)
+{
+ if (zero)
+ return h;
+ else
+ abort ();
+}
+
+omp_allocator_handle_t
+align (int a)
+{
+ if (zero)
+ return omp_default_mem_alloc;
+ else
+ abort ();
+}
+
+int
+main ()
+{
+ int x = 1, y = 2;
+ #pragma omp parallel num_threads(2) firstprivate (x, y) allocate (allocator (omp_default_mem_alloc) : x) allocate (align (16) : y)
+ {
+ if (x != 1 || y != 2)
+ abort ();
+ if ((((uintptr_t) &y) & 15) != 0)
+ abort ();
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/allocate-3.c b/libgomp/testsuite/libgomp.c-c++-common/allocate-3.c
new file mode 100644
index 0000000..ce1a045
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/allocate-3.c
@@ -0,0 +1,405 @@
+#include <omp.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+struct S { int a, b; };
+
+void
+foo (int x, int *p, int *q, int px, omp_allocator_handle_t h, int fl)
+{
+ int y = 0, r = 0, i, i1, l, l2[4], l3, n = 8;
+ int i2, j2, n2 = 9, l4;
+ int i3, j3, n3 = 10, l5;
+ int i4, j4, n4 = 11, l6;
+ int i5;
+ int v[x], w[x];
+ int r2[4] = { 0, 0, 0, 0 };
+ int xo = x;
+ struct S s = { 27, 29 };
+ for (i = 0; i < 4; i++)
+ p[i] = 0;
+ for (i = 0; i < 3; i++)
+ q[i] = 0;
+ for (i = 0; i < x; i++)
+ w[i] = i;
+ #pragma omp parallel private (y, v) firstprivate (x) allocate (align (32) : x) allocate (align (128) : y) allocate (v)
+ {
+ int *volatile p1 = &x;
+ int *volatile p2 = &y;
+ if (x != 42)
+ abort ();
+ #pragma omp barrier
+ *p2 = 1;
+ p1[0]++;
+ v[0] = 7;
+ v[41] = 8;
+ #pragma omp barrier
+ if (x != 43 || y != 1)
+ abort ();
+ if (v[0] != 7 || v[41] != 8)
+ abort ();
+ if ((fl & 2) && (((uintptr_t) p1 | (uintptr_t) p2
+ | (uintptr_t) &v[0]) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) p1) & 31) != 0)
+ abort ();
+ if ((((uintptr_t) p2) & 127) != 0)
+ abort ();
+ }
+ x = xo;
+ #pragma omp teams
+ #pragma omp parallel private (y) firstprivate (x, w) allocate (allocator (h), align (32) : x) allocate (align (128), allocator (h):y) allocate(allocator(h):w)
+ {
+ int *volatile p1 = &x;
+ int *volatile p2 = &y;
+ if (x != 42 || w[17] != 17 || w[41] != 41)
+ abort ();
+ #pragma omp barrier
+ *p2 = 1;
+ p1[0]++;
+ w[19]++;
+ #pragma omp barrier
+ if (x != 43 || y != 1 || w[19] != 20)
+ abort ();
+ if ((fl & 1) && (((uintptr_t) p1 | (uintptr_t) p2
+ | (uintptr_t) &w[0]) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) p1) & 31) != 0)
+ abort ();
+ if ((((uintptr_t) p2) & 127) != 0)
+ abort ();
+ }
+ x = xo;
+ #pragma omp parallel for private (y) firstprivate (x) allocate (allocator (h), align (32) : x, y, r) allocate (align (128), allocator (h) : l, n) reduction(+: r) lastprivate (l) linear (n: 16)
+ for (i = 0; i < 64; i++)
+ {
+ if (x != 42)
+ abort ();
+ y = 1;
+ l = i;
+ n += y + 15;
+ r += i;
+ if ((fl & 1) && (((uintptr_t) &x | (uintptr_t) &y | (uintptr_t) &r
+ | (uintptr_t) &l | (uintptr_t) &n) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) &x | (uintptr_t) &y | (uintptr_t) &r) & 31) != 0)
+ abort ();
+ if ((((uintptr_t) &l | (uintptr_t) &n) & 127) != 0)
+ abort ();
+ }
+ x = xo;
+ #pragma omp parallel
+ {
+ #pragma omp for lastprivate (l2) private (i1) allocate (allocator (h): l2, l3) allocate (allocator (h),align(16): i1) lastprivate (conditional: l3)
+ for (i1 = 0; i1 < 64; i1++)
+ {
+ l2[0] = i1;
+ l2[1] = i1 + 1;
+ l2[2] = i1 + 2;
+ l2[3] = i1 + 3;
+ if (i1 < 37)
+ l3 = i1;
+ if ((fl & 1) && (((uintptr_t) &l2[0] | (uintptr_t) &l3 | (uintptr_t) &i1) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) &i1) & 15) != 0)
+ abort ();
+ }
+ #pragma omp for collapse(2) lastprivate(l4, i2, j2) linear (n2:17) allocate (allocator (h), align (8): n2, l4, i2, j2)
+ for (i2 = 3; i2 < 5; i2++)
+ for (j2 = 17; j2 < 22; j2 += 2)
+ {
+ n2 += 17;
+ l4 = i2 * 31 + j2;
+ if ((fl & 1) && (((uintptr_t) &l4 | (uintptr_t) &n2
+ | (uintptr_t) &i2 | (uintptr_t) &j2) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) &l4 | (uintptr_t) &n2 | (uintptr_t) &i2 | (uintptr_t) &j2) & 7) != 0)
+ abort ();
+ }
+ #pragma omp for collapse(2) lastprivate(l5, i3, j3) linear (n3:17) schedule (static, 3) allocate (align (16): n3, l5, i3, j3)
+ for (i3 = 3; i3 < 5; i3++)
+ for (j3 = 17; j3 < 23; j3 += 2)
+ {
+ n3 += 17;
+ l5 = i3 * 31 + j3;
+ if ((fl & 2) && (((uintptr_t) &l5 | (uintptr_t) &n3
+ | (uintptr_t) &i3 | (uintptr_t) &j3) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) &l5 | (uintptr_t) &n3 | (uintptr_t) &i3 | (uintptr_t) &j3) & 15) != 0)
+ abort ();
+ }
+ #pragma omp for collapse(2) lastprivate(l6, i4, j4) linear (n4:17) schedule (dynamic) allocate (align (16), allocator (h): n4, l6, i4, j4)
+ for (i4 = 3; i4 < 5; i4++)
+ for (j4 = 17; j4 < 22; j4 += 2)
+ {
+ n4 += 17;
+ l6 = i4 * 31 + j4;
+ if ((fl & 1) && (((uintptr_t) &l6 | (uintptr_t) &n4
+ | (uintptr_t) &i4 | (uintptr_t) &j4) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) &l6 | (uintptr_t) &n4 | (uintptr_t) &i4 | (uintptr_t) &j4) & 15) != 0)
+ abort ();
+ }
+ #pragma omp for lastprivate (i5) allocate (align (32): i5)
+ for (i5 = 1; i5 < 17; i5 += 3)
+ {
+ if ((fl & 2) && (((uintptr_t) &i5) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) &i5) & 31) != 0)
+ abort ();
+ }
+ #pragma omp for reduction(+:p[2:px], q[:3], r2) allocate(align (16), allocator (h): p, q, r2)
+ for (i = 0; i < 32; i++)
+ {
+ p[2] += i;
+ p[3] += 2 * i;
+ q[0] += 3 * i;
+ q[2] += 4 * i;
+ r2[0] += 5 * i;
+ r2[3] += 6 * i;
+ /* Can't really rely on alignment of &p[0], the implementation could
+ allocate the whole array or do what GCC does and allocate only part
+ of it. */
+ if ((fl & 1) && (((uintptr_t) &q[0] | (uintptr_t) &r2[0]) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) &q[0] | (uintptr_t) &r2[0]) & 15) != 0)
+ abort ();
+ }
+ #pragma omp task private(y) firstprivate(x) allocate(align (8) : x, y)
+ {
+ int *volatile p1 = &x;
+ int *volatile p2 = &y;
+ if (x != 42)
+ abort ();
+ p1[0]++;
+ p2[0] = 21;
+ if (x != 43 || y != 21)
+ abort ();
+ if ((fl & 2) && (((uintptr_t) p1 | (uintptr_t) p2) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) p1 | (uintptr_t) p2) & 7) != 0)
+ abort ();
+ }
+ #pragma omp task private(y) firstprivate(x) allocate(allocator (h),align(32): x, y)
+ {
+ int *volatile p1 = &x;
+ int *volatile p2 = &y;
+ if (x != 42)
+ abort ();
+ p1[0]++;
+ p2[0] = 21;
+ if (x != 43 || y != 21)
+ abort ();
+ if ((fl & 1) && (((uintptr_t) p1 | (uintptr_t) p2) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) p1 | (uintptr_t) p2) & 31) != 0)
+ abort ();
+ }
+ #pragma omp task private(y) firstprivate(s) allocate(align(16): s, y)
+ {
+ int *volatile p1 = &s.a;
+ int *volatile p2 = &s.b;
+ int *volatile p3 = &y;
+ if (s.a != 27 || s.b != 29)
+ abort ();
+ p1[0]++;
+ p2[0]++;
+ p3[0] = 21;
+ if (s.a != 28 || s.b != 30 || y != 21)
+ abort ();
+ if ((fl & 2) && (((uintptr_t) p1 | (uintptr_t) p3) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) p1 | (uintptr_t) p3) & 15) != 0)
+ abort ();
+ }
+ #pragma omp task private(y) firstprivate(s) allocate(allocator (h): s, y)
+ {
+ int *volatile p1 = &s.a;
+ int *volatile p2 = &s.b;
+ int *volatile p3 = &y;
+ if (s.a != 27 || s.b != 29)
+ abort ();
+ p1[0]++;
+ p2[0]++;
+ p3[0] = 21;
+ if (s.a != 28 || s.b != 30 || y != 21)
+ abort ();
+ if ((fl & 1) && (((uintptr_t) p1 | (uintptr_t) p3) & 63) != 0)
+ abort ();
+ }
+ }
+ if (r != 64 * 63 / 2 || l != 63 || n != 8 + 16 * 64)
+ abort ();
+ if (l2[0] != 63 || l2[1] != 63 + 1 || l2[2] != 63 + 2 || l2[3] != 63 + 3 || l3 != 36)
+ abort ();
+ if (i2 != 5 || j2 != 23 || n2 != 9 + 6 * 17 || l4 != 4 * 31 + 21)
+ abort ();
+ if (i3 != 5 || j3 != 23 || n3 != 10 + 6 * 17 || l5 != 4 * 31 + 21)
+ abort ();
+ if (i4 != 5 || j4 != 23 || n4 != 11 + 6 * 17 || l6 != 4 * 31 + 21)
+ abort ();
+ if (i5 != 19)
+ abort ();
+ if (p[2] != (32 * 31) / 2 || p[3] != 2 * (32 * 31) / 2
+ || q[0] != 3 * (32 * 31) / 2 || q[2] != 4 * (32 * 31) / 2
+ || r2[0] != 5 * (32 * 31) / 2 || r2[3] != 6 * (32 * 31) / 2)
+ abort ();
+}
+
+void
+bar (int x, omp_allocator_handle_t h)
+{
+ int y = 0, r = 0, i, i1, l, l2[4], l3, n = 8;
+ int i2, j2, n2 = 9, l4;
+ int i3, j3, n3 = 10, l5;
+ int i4, j4, n4 = 11, l6;
+ int i5;
+ struct S s = { 27, 29 };
+ int xo = x;
+ #pragma omp parallel private (y) firstprivate (x) allocate (x, y)
+ {
+ if (x != 42)
+ abort ();
+ #pragma omp barrier
+ y = 1;
+ x++;
+ #pragma omp barrier
+ if (x != 43 || y != 1)
+ abort ();
+ }
+ x = xo;
+ #pragma omp teams
+ #pragma omp parallel private (y) firstprivate (x) allocate (allocator (h): x, y)
+ {
+ if (x != 42)
+ abort ();
+ #pragma omp barrier
+ y = 1;
+ x++;
+ #pragma omp barrier
+ if (x != 43 || y != 1)
+ abort ();
+ }
+ x = xo;
+ #pragma omp parallel for private (y) firstprivate (x) allocate (allocator (h): x, y, r, l, n) reduction(+: r) lastprivate (l) linear (n: 16)
+ for (i = 0; i < 64; i++)
+ {
+ if (x != 42)
+ abort ();
+ y = 1;
+ l = i;
+ n += y + 15;
+ r += i;
+ }
+ x = xo;
+ #pragma omp parallel
+ {
+ #pragma omp for lastprivate (l2) private (i1) allocate (allocator (h): l2, l3, i1) lastprivate (conditional: l3)
+ for (i1 = 0; i1 < 64; i1++)
+ {
+ l2[0] = i1;
+ l2[1] = i1 + 1;
+ l2[2] = i1 + 2;
+ l2[3] = i1 + 3;
+ if (i1 < 37)
+ l3 = i1;
+ }
+ #pragma omp for collapse(2) lastprivate(l4, i2, j2) linear (n2:17) allocate (allocator (h): n2, l4, i2, j2)
+ for (i2 = 3; i2 < 5; i2++)
+ for (j2 = 17; j2 < 22; j2 += 2)
+ {
+ n2 += 17;
+ l4 = i2 * 31 + j2;
+ }
+ #pragma omp for collapse(2) lastprivate(l5, i3, j3) linear (n3:17) schedule (static, 3) allocate (n3, l5, i3, j3)
+ for (i3 = 3; i3 < 5; i3++)
+ for (j3 = 17; j3 < 23; j3 += 2)
+ {
+ n3 += 17;
+ l5 = i3 * 31 + j3;
+ }
+ #pragma omp for collapse(2) lastprivate(l6, i4, j4) linear (n4:17) schedule (dynamic) allocate (allocator (h): n4, l6, i4, j4)
+ for (i4 = 3; i4 < 5; i4++)
+ for (j4 = 17; j4 < 22; j4 += 2)
+ {
+ n4 += 17;
+ l6 = i4 * 31 + j4;
+ }
+ #pragma omp for lastprivate (i5) allocate (i5)
+ for (i5 = 1; i5 < 17; i5 += 3)
+ ;
+ #pragma omp task private(y) firstprivate(x) allocate(x, y)
+ {
+ if (x != 42)
+ abort ();
+ x++;
+ y = 21;
+ if (x != 43 || y != 21)
+ abort ();
+ }
+ #pragma omp task private(y) firstprivate(x) allocate(allocator (h): x, y)
+ {
+ if (x != 42)
+ abort ();
+ x++;
+ y = 21;
+ if (x != 43 || y != 21)
+ abort ();
+ }
+ #pragma omp task private(y) firstprivate(s) allocate(s, y)
+ {
+ if (s.a != 27 || s.b != 29)
+ abort ();
+ s.a++;
+ s.b++;
+ y = 21;
+ if (s.a != 28 || s.b != 30 || y != 21)
+ abort ();
+ }
+ #pragma omp task private(y) firstprivate(s) allocate(allocator (h), align (16): s, y)
+ {
+ if (s.a != 27 || s.b != 29)
+ abort ();
+ s.a++;
+ s.b++;
+ y = 21;
+ if (s.a != 28 || s.b != 30 || y != 21)
+ abort ();
+ }
+ }
+ if (r != 64 * 63 / 2 || l != 63 || n != 8 + 16 * 64)
+ abort ();
+ if (l2[0] != 63 || l2[1] != 63 + 1 || l2[2] != 63 + 2 || l2[3] != 63 + 3 || l3 != 36)
+ abort ();
+ if (i2 != 5 || j2 != 23 || n2 != 9 + 6 * 17 || l4 != 4 * 31 + 21)
+ abort ();
+ if (i3 != 5 || j3 != 23 || n3 != 10 + 6 * 17 || l5 != 4 * 31 + 21)
+ abort ();
+ if (i4 != 5 || j4 != 23 || n4 != 11 + 6 * 17 || l6 != 4 * 31 + 21)
+ abort ();
+ if (i5 != 19)
+ abort ();
+}
+
+int
+main ()
+{
+ omp_alloctrait_t traits[3]
+ = { { omp_atk_alignment, 64 },
+ { omp_atk_fallback, omp_atv_null_fb } };
+ omp_allocator_handle_t a
+ = omp_init_allocator (omp_default_mem_space, 2, traits);
+ int p[4], q[3];
+ if (a == omp_null_allocator)
+ abort ();
+ omp_set_default_allocator (omp_default_mem_alloc);
+ foo (42, p, q, 2, omp_null_allocator, 0);
+ foo (42, p, q, 2, omp_default_mem_alloc, 0);
+ foo (42, p, q, 2, a, 1);
+ omp_set_default_allocator (a);
+ foo (42, p, q, 2, omp_null_allocator, 3);
+ foo (42, p, q, 2, omp_default_mem_alloc, 2);
+ bar (42, a);
+ omp_destroy_allocator (a);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/order-reproducible-1.c b/libgomp/testsuite/libgomp.c-c++-common/order-reproducible-1.c
new file mode 100644
index 0000000..7e6968f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/order-reproducible-1.c
@@ -0,0 +1,63 @@
+#include <unistd.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ int a[128];
+ #pragma omp teams num_teams(5)
+ {
+ #pragma omp loop bind(teams)
+ for (int i = 0; i < 128; i++)
+ {
+ a[i] = i;
+ if (i == 0)
+ usleep (20);
+ else if (i == 17)
+ usleep (40);
+ }
+ #pragma omp loop bind(teams)
+ for (int i = 0; i < 128; i++)
+ a[i] += i;
+ }
+ for (int i = 0; i < 128; i++)
+ if (a[i] != 2 * i)
+ abort ();
+ #pragma omp teams num_teams(5)
+ {
+ #pragma omp loop bind(teams) order(concurrent)
+ for (int i = 0; i < 128; i++)
+ {
+ a[i] *= 2;
+ if (i == 1)
+ usleep (20);
+ else if (i == 13)
+ usleep (40);
+ }
+ #pragma omp loop bind(teams) order(concurrent)
+ for (int i = 0; i < 128; i++)
+ a[i] += i;
+ }
+ for (int i = 0; i < 128; i++)
+ if (a[i] != 5 * i)
+ abort ();
+ #pragma omp teams num_teams(5)
+ {
+ #pragma omp loop bind(teams) order(reproducible:concurrent)
+ for (int i = 0; i < 128; i++)
+ {
+ a[i] *= 2;
+ if (i == 2)
+ usleep (20);
+ else if (i == 105)
+ usleep (40);
+ }
+ #pragma omp loop bind(teams) order(reproducible:concurrent)
+ for (int i = 0; i < 128; i++)
+ a[i] += i;
+ }
+ for (int i = 0; i < 128; i++)
+ if (a[i] != 11 * i)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/order-reproducible-2.c b/libgomp/testsuite/libgomp.c-c++-common/order-reproducible-2.c
new file mode 100644
index 0000000..c8ba658
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/order-reproducible-2.c
@@ -0,0 +1,28 @@
+#include <unistd.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ int a[128];
+ #pragma omp parallel num_threads(8)
+ {
+ #pragma omp barrier
+ #pragma omp for nowait schedule (dynamic, 2) order(reproducible:concurrent)
+ for (int i = 0; i < 128; i++)
+ {
+ a[i] = i;
+ if (i == 0)
+ usleep (20);
+ else if (i == 17)
+ usleep (40);
+ }
+ #pragma omp for nowait schedule (dynamic, 2) order(reproducible:concurrent)
+ for (int i = 0; i < 128; i++)
+ a[i] += i;
+ }
+ for (int i = 0; i < 128; i++)
+ if (a[i] != 2 * i)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.fortran/alloc-10.f90 b/libgomp/testsuite/libgomp.fortran/alloc-10.f90
new file mode 100644
index 0000000..3eab859
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/alloc-10.f90
@@ -0,0 +1,199 @@
+! { dg-additional-sources alloc-7.c }
+! { dg-prune-output "command-line option '-fintrinsic-modules-path=.*' is valid for Fortran but not for C" }
+module m
+ use omp_lib
+ use iso_c_binding
+ implicit none
+
+ type (omp_alloctrait), parameter :: traits2(*) &
+ = [ omp_alloctrait (omp_atk_alignment, 16), &
+ omp_alloctrait (omp_atk_sync_hint, omp_atv_default), &
+ omp_alloctrait (omp_atk_access, omp_atv_default), &
+ omp_alloctrait (omp_atk_pool_size, 1024), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_default_mem_fb), &
+ omp_alloctrait (omp_atk_partition, omp_atv_environment)]
+ type (omp_alloctrait) :: traits3(7) &
+ = [ omp_alloctrait (omp_atk_sync_hint, omp_atv_uncontended), &
+ omp_alloctrait (omp_atk_alignment, 32), &
+ omp_alloctrait (omp_atk_access, omp_atv_all), &
+ omp_alloctrait (omp_atk_pool_size, 512), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_allocator_fb), &
+ omp_alloctrait (omp_atk_fb_data, 0), &
+ omp_alloctrait (omp_atk_partition, omp_atv_default)]
+ type (omp_alloctrait), parameter :: traits4(*) &
+ = [ omp_alloctrait (omp_atk_alignment, 128), &
+ omp_alloctrait (omp_atk_pool_size, 1024), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_null_fb)]
+
+ interface
+ integer(c_int) function get__alignof_int () bind(C)
+ import :: c_int
+ end
+ end interface
+end module m
+
+program main
+ use m
+ implicit none (external, type)
+ type(c_ptr) :: p, q, r
+ integer, pointer, contiguous :: ip(:), iq(:), ir(:)
+ type (omp_alloctrait) :: traits(3)
+ integer (omp_allocator_handle_kind) :: a, a2
+ integer (c_ptrdiff_t) :: iptr
+ integer :: i
+
+ traits = [ omp_alloctrait (omp_atk_alignment, 64), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_null_fb), &
+ omp_alloctrait (omp_atk_pool_size, 4096)]
+
+ p = omp_aligned_calloc (c_sizeof (0), 3_c_size_t, c_sizeof (0), omp_default_mem_alloc)
+ call c_f_pointer (p, ip, [3])
+ if (mod (TRANSFER (p, iptr), get__alignof_int ()) /= 0 &
+ .or. ip(1) /= 0 .or. ip(2) /= 0 .or. ip(3) /= 0) &
+ stop 1
+ ip(1) = 1
+ ip(2) = 2
+ ip(3) = 3
+ call omp_free (p, omp_default_mem_alloc)
+ p = omp_aligned_calloc (2 * c_sizeof (0), 1_c_size_t, 2 * c_sizeof (0), omp_default_mem_alloc)
+ call c_f_pointer (p, ip, [2])
+ if (mod (TRANSFER (p, iptr), 2 * c_sizeof (0)) /= 0 &
+ .or. ip(1) /= 0 .or. ip(2) /= 0) &
+ stop 2
+ ip(1) = 1
+ ip(2) = 2
+ call omp_free (p, omp_null_allocator)
+ call omp_set_default_allocator (omp_default_mem_alloc)
+ p = omp_aligned_calloc (1_c_size_t, 1_c_size_t, c_sizeof (0), omp_null_allocator)
+ call c_f_pointer (p, ip, [1])
+ if (mod (TRANSFER (p, iptr), get__alignof_int ()) /= 0 &
+ .or. ip(1) /= 0) &
+ stop 3
+ ip(1) = 3
+ call omp_free (p, omp_get_default_allocator ())
+
+ a = omp_init_allocator (omp_default_mem_space, 3, traits)
+ if (a == omp_null_allocator) &
+ stop 4
+ p = omp_aligned_calloc (32_c_size_t, 3_c_size_t, 1024_c_size_t, a)
+ call c_f_pointer (p, ip, [3072 / c_sizeof (0)])
+ if (mod (TRANSFER (p, iptr), 64) /= 0) &
+ stop 5
+ do i = 1, 3072 / c_sizeof (0)
+ if (ip(i) /= 0) &
+ stop 6
+ end do
+ ip(1) = 1
+ ip(3072 / c_sizeof (0)) = 2
+ if (c_associated (omp_aligned_calloc (8_c_size_t, 192_c_size_t, 16_c_size_t, a))) &
+ stop 7
+ call omp_free (p, a)
+ p = omp_aligned_calloc (128_c_size_t, 6_c_size_t, 512_c_size_t, a)
+ call c_f_pointer (p, ip, [3072 / c_sizeof (0)])
+ if (mod (TRANSFER (p, iptr), 128) /= 0) &
+ stop 8
+ do i = 1, 3072 / c_sizeof (0)
+ if (ip(i) /= 0) &
+ stop 9
+ end do
+ ip(1) = 3
+ ip(3072 / c_sizeof (0)) = 4
+ call omp_free (p, omp_null_allocator)
+ call omp_set_default_allocator (a)
+ if (omp_get_default_allocator () /= a) &
+ stop 10
+ p = omp_aligned_calloc (64_c_size_t, 12_c_size_t, 256_c_size_t, omp_null_allocator)
+ call c_f_pointer (p, ip, [3072 / c_sizeof (0)])
+ do i = 1, 3072 / c_sizeof (0)
+ if (ip(i) /= 0) &
+ stop 11
+ end do
+ if (c_associated (omp_aligned_calloc (8_c_size_t, 128_c_size_t, 24_c_size_t, omp_null_allocator))) &
+ stop 12
+ call omp_free (p, a)
+ call omp_destroy_allocator (a)
+
+ a = omp_init_allocator (omp_default_mem_space, size (traits2), traits2)
+ if (a == omp_null_allocator) &
+ stop 13
+ if (traits3(6)%key /= omp_atk_fb_data) &
+ stop 14
+ traits3(6)%value = a
+ a2 = omp_init_allocator (omp_default_mem_space, size (traits3), traits3)
+ if (a2 == omp_null_allocator) &
+ stop 15
+ p = omp_aligned_calloc (4_c_size_t, 5_c_size_t, 84_c_size_t, a2)
+ call c_f_pointer (p, ip, [420 / c_sizeof (0)])
+ do i = 1, 420 / c_sizeof (0)
+ if (ip(i) /= 0) &
+ stop 16
+ end do
+ if (mod (TRANSFER (p, iptr), 32) /= 0) &
+ stop 17
+ ip(1) = 5
+ ip(420 / c_sizeof (0)) = 6
+ q = omp_aligned_calloc (8_c_size_t, 24_c_size_t, 32_c_size_t, a2)
+ call c_f_pointer (q, iq, [768 / c_sizeof (0)])
+ if (mod (TRANSFER (q, iptr), 16) /= 0) &
+ stop 18
+ do i = 1, 768 / c_sizeof (0)
+ if (iq(i) /= 0) &
+ stop 19
+ end do
+ iq(1) = 7
+ iq(768 / c_sizeof (0)) = 8
+ r = omp_aligned_calloc (8_c_size_t, 64_c_size_t, 8_c_size_t, a2)
+ call c_f_pointer (r, ir, [512 / c_sizeof (0)])
+ if (mod (TRANSFER (r, iptr), 8) /= 0) &
+ stop 20
+ do i = 1, 512 / c_sizeof (0)
+ if (ir(i) /= 0) &
+ stop 21
+ end do
+ ir(1) = 9
+ ir(512 / c_sizeof (0)) = 10
+ call omp_free (p, omp_null_allocator)
+ call omp_free (q, a2)
+ call omp_free (r, omp_null_allocator)
+ call omp_destroy_allocator (a2)
+ call omp_destroy_allocator (a)
+
+ a = omp_init_allocator (omp_default_mem_space, size (traits4), traits4)
+ if (a == omp_null_allocator) &
+ stop 22
+ if (traits3(6)%key /= omp_atk_fb_data) &
+ stop 23
+ traits3(6)%value = a
+ a2 = omp_init_allocator (omp_default_mem_space, size (traits3), traits3)
+ if (a2 == omp_null_allocator) &
+ stop 24
+ call omp_set_default_allocator (a2)
+ p = omp_aligned_calloc (4_c_size_t, 21_c_size_t, 20_c_size_t, omp_null_allocator)
+ call c_f_pointer (p, ip, [420 / c_sizeof (0)])
+ if (mod (TRANSFER (p, iptr), 32) /= 0) &
+ stop 25
+ do i = 1, 420 / c_sizeof (0)
+ if (ip(i) /= 0) &
+ stop 26
+ end do
+ ip(1) = 5
+ ip(420 / c_sizeof (0)) = 6
+ q = omp_aligned_calloc (64_c_size_t, 12_c_size_t, 64_c_size_t, omp_null_allocator)
+ call c_f_pointer (q, iq, [768 / c_sizeof (0)])
+ if (mod (TRANSFER (q, iptr), 128) /= 0) &
+ stop 27
+ do i = 1, 768 / c_sizeof (0)
+ if (iq(i) /= 0) &
+ stop 28
+ end do
+ iq(1) = 7
+ iq(768 / c_sizeof (0)) = 8
+ if (c_associated (omp_aligned_calloc (8_c_size_t, 24_c_size_t, 32_c_size_t, omp_null_allocator))) &
+ stop 29
+ call omp_free (p, omp_null_allocator)
+ call omp_free (q, omp_null_allocator)
+ call omp_free (c_null_ptr, omp_null_allocator)
+ call omp_free (c_null_ptr, omp_null_allocator)
+ call omp_destroy_allocator (a2)
+ call omp_destroy_allocator (a)
+end program main
diff --git a/libgomp/testsuite/libgomp.fortran/alloc-11.f90 b/libgomp/testsuite/libgomp.fortran/alloc-11.f90
new file mode 100644
index 0000000..22b4f92
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/alloc-11.f90
@@ -0,0 +1,301 @@
+! { dg-additional-sources alloc-7.c }
+! { dg-prune-output "command-line option '-fintrinsic-modules-path=.*' is valid for Fortran but not for C" }
+module m
+ use omp_lib
+ use iso_c_binding
+ implicit none
+
+ type (omp_alloctrait), parameter :: traits2(*) &
+ = [ omp_alloctrait (omp_atk_alignment, 16), &
+ omp_alloctrait (omp_atk_sync_hint, omp_atv_default), &
+ omp_alloctrait (omp_atk_access, omp_atv_default), &
+ omp_alloctrait (omp_atk_pool_size, 1024), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_default_mem_fb), &
+ omp_alloctrait (omp_atk_partition, omp_atv_environment)]
+ type (omp_alloctrait) :: traits3(7) &
+ = [ omp_alloctrait (omp_atk_sync_hint, omp_atv_uncontended), &
+ omp_alloctrait (omp_atk_alignment, 32), &
+ omp_alloctrait (omp_atk_access, omp_atv_all), &
+ omp_alloctrait (omp_atk_pool_size, 512), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_allocator_fb), &
+ omp_alloctrait (omp_atk_fb_data, 0), &
+ omp_alloctrait (omp_atk_partition, omp_atv_default)]
+
+ type (omp_alloctrait), parameter :: traits4(*) &
+ = [ omp_alloctrait (omp_atk_alignment, 128), &
+ omp_alloctrait (omp_atk_pool_size, 1024), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_null_fb)]
+
+ interface
+ integer(c_int) function get__alignof_int () bind(C)
+ import :: c_int
+ end
+ end interface
+end module m
+
+program main
+ use m
+ implicit none (external, type)
+ type(c_ptr) :: p, q, r
+ integer, pointer, contiguous :: ip(:), iq(:), ir(:)
+ type (omp_alloctrait) :: traits(3)
+ type (omp_alloctrait) :: traits5(2)
+ integer (omp_allocator_handle_kind) :: a, a2
+ integer (c_ptrdiff_t) :: iptr
+
+ traits = [ omp_alloctrait (omp_atk_alignment, 64), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_null_fb), &
+ omp_alloctrait (omp_atk_pool_size, 4096)]
+ traits5 = [ omp_alloctrait (omp_atk_fallback, omp_atv_null_fb), &
+ omp_alloctrait (omp_atk_pool_size, 4096)]
+
+ p = omp_alloc (3 * c_sizeof (0), omp_default_mem_alloc)
+ call c_f_pointer (p, ip, [3])
+ if (mod (TRANSFER (p, iptr), get__alignof_int ()) /= 0) &
+ stop 1
+ ip(1) = 1
+ ip(2) = 2
+ ip(3) = 3
+ p = omp_realloc (p, 4 * c_sizeof (0), omp_default_mem_alloc, omp_default_mem_alloc)
+ call c_f_pointer (p, ip, [4])
+ if (mod (TRANSFER (p, iptr), get__alignof_int ()) /= 0 &
+ .or. ip(1) /= 1 .or. ip(2) /= 2 .or. ip(3) /= 3) &
+ stop 2
+ ip(1) = 4
+ ip(2) = 5
+ ip(3) = 6
+ ip(4) = 7
+ p = omp_realloc (p, 2 * c_sizeof (0), omp_default_mem_alloc, omp_default_mem_alloc)
+ call c_f_pointer (p, ip, [2])
+ if (mod (TRANSFER (p, iptr), get__alignof_int ()) /= 0 &
+ .or. ip(1) /= 4 .or. ip(2) /= 5) &
+ stop 3
+ ip(1) = 8
+ ip(2) = 9
+ if (c_associated (omp_realloc (p, 0_c_size_t, omp_null_allocator, omp_default_mem_alloc))) &
+ stop 4
+ p = omp_realloc (c_null_ptr, 2 * c_sizeof (0), omp_default_mem_alloc, omp_null_allocator)
+ call c_f_pointer (p, ip, [2])
+ if (mod (TRANSFER (p, iptr), get__alignof_int ()) /= 0) &
+ stop 5
+ ip(1) = 1
+ ip(2) = 2
+ p = omp_realloc (p, 5 * c_sizeof (0), omp_default_mem_alloc, omp_default_mem_alloc)
+ call c_f_pointer (p, ip, [5])
+ if (mod (TRANSFER (p, iptr), get__alignof_int ()) /= 0 &
+ .or. ip(1) /= 1 .or. ip(2) /= 2) &
+ stop 6
+ ip(1) = 3
+ ip(2) = 4
+ ip(3) = 5
+ ip(4) = 6
+ ip(5) = 7
+ call omp_free (p, omp_null_allocator)
+ call omp_set_default_allocator (omp_default_mem_alloc)
+ if (c_associated (omp_realloc (c_null_ptr, 0_c_size_t, omp_null_allocator, omp_null_allocator))) &
+ stop 7
+ p = omp_alloc (c_sizeof (0), omp_null_allocator)
+ call c_f_pointer (p, ip, [1])
+ if (mod (TRANSFER (p, iptr), get__alignof_int ()) /= 0) &
+ stop 8
+ ip(1) = 3
+ p = omp_realloc (p, 3 * c_sizeof (0), omp_null_allocator, omp_null_allocator)
+ call c_f_pointer (p, ip, [3])
+ if (mod (TRANSFER (p, iptr), get__alignof_int ()) /= 0 &
+ .or. ip(1) /= 3) &
+ stop 9
+ ip(1) = 4
+ ip(2) = 5
+ ip(3) = 6
+ if (c_associated (omp_realloc (p, 0_c_size_t, omp_null_allocator, omp_get_default_allocator ()))) &
+ stop 10
+ a = omp_init_allocator (omp_default_mem_space, 3, traits)
+ if (a == omp_null_allocator) &
+ stop 11
+ p = omp_alloc (c_sizeof (0), a)
+ call c_f_pointer (p, ip, [1])
+ if (mod (TRANSFER (p, iptr), 64) /= 0) &
+ stop 12
+ ip(1) = 7
+ p = omp_realloc (p, 3072_c_size_t, a, a)
+ call c_f_pointer (p, ip, [3072 / c_sizeof (0)])
+ if (mod (TRANSFER (p, iptr), 64) /= 0 &
+ .or. ip(1) /= 7) &
+ stop 13
+ ip(1) = 1
+ ip(3072 / c_sizeof (0)) = 2
+ q = omp_alloc (c_sizeof (0), a)
+ call c_f_pointer (q, iq, [1])
+ if (mod (TRANSFER (q, iptr), 64) /= 0) &
+ stop 14
+ iq(1) = 8
+ if (c_associated (omp_realloc (q, 3072_c_size_t, a, a))) &
+ stop 15
+ call omp_free (p, a)
+ call omp_free (q, a)
+ p = omp_alloc (c_sizeof (0), a)
+ call c_f_pointer (p, ip, [1])
+ ip(1) = 42
+ p = omp_realloc (p, 3072_c_size_t, a, a)
+ call c_f_pointer (p, ip, [3072 / c_sizeof (0)])
+ if (ip(1) /= 42) &
+ stop 16
+ ip(1) = 3
+ ip(3072 / c_sizeof (0)) = 4
+ ! ignore return value
+ r = omp_realloc (p, 0_c_size_t, omp_null_allocator, omp_null_allocator)
+ call omp_set_default_allocator (a)
+ if (omp_get_default_allocator () /= a) &
+ stop 17
+ p = omp_alloc (31_c_size_t, omp_null_allocator)
+ if (.not. c_associated (p)) &
+ stop 18
+ p = omp_realloc (p, 3072_c_size_t, omp_null_allocator, omp_null_allocator)
+ if (.not. c_associated (p)) &
+ stop 19
+ q = omp_alloc (c_sizeof (0), omp_null_allocator)
+ if (.not. c_associated (q)) &
+ stop 20
+ if (c_associated (omp_realloc (q, 3072_c_size_t, omp_null_allocator, omp_null_allocator))) &
+ stop 21
+ call omp_free (p, a)
+ call omp_free (q, a)
+ call omp_destroy_allocator (a)
+
+ a = omp_init_allocator (omp_default_mem_space, 2, traits5)
+ if (a == omp_null_allocator) &
+ stop 22
+ call omp_set_default_allocator (a)
+ if (omp_get_default_allocator () /= a) &
+ stop 23
+ p = omp_alloc (3071_c_size_t, omp_null_allocator)
+ if (.not. c_associated (p)) &
+ stop 24
+ p = omp_realloc (p, 3072_c_size_t, omp_null_allocator, omp_null_allocator)
+ if (.not. c_associated (p)) &
+ stop 25
+ q = omp_alloc (c_sizeof (0), omp_null_allocator)
+ if (.not. c_associated (q)) &
+ stop 26
+ if (c_associated (omp_realloc (q, 3072_c_size_t, omp_null_allocator, omp_null_allocator))) &
+ stop 27
+ call omp_free (p, a)
+ call omp_free (q, a)
+ call omp_destroy_allocator (a)
+
+ a = omp_init_allocator (omp_default_mem_space, size (traits2), traits2)
+ if (a == omp_null_allocator) &
+ stop 28
+ if (traits3(6)%key /= omp_atk_fb_data) &
+ stop 29
+ traits3(6)%value = a
+ a2 = omp_init_allocator (omp_default_mem_space, size (traits3), traits3)
+ if (a2 == omp_null_allocator) &
+ stop 30
+ p = omp_alloc (c_sizeof (0), a2)
+ call c_f_pointer (p, ip, [1])
+ if (mod (TRANSFER (p, iptr), 32) /= 0) &
+ stop 31
+ ip(1) = 84
+ p = omp_realloc (p, 380_c_size_t, a2, a2)
+ call c_f_pointer (p, ip, [380 / c_sizeof (0)])
+ if (mod (TRANSFER (p, iptr), 32) /= 0 &
+ .or. ip(1) /= 84) &
+ stop 32
+ ip(1) = 5
+ ip(380 / c_sizeof (0)) = 6
+ q = omp_alloc (c_sizeof (0), a2)
+ call c_f_pointer (q, iq, [1])
+ if (mod (TRANSFER (q, iptr), 32) /= 0) &
+ stop 33
+ iq(1) = 42
+ q = omp_realloc (q, 768_c_size_t, a2, a2)
+ call c_f_pointer (q, iq, [768 / c_sizeof (0)])
+ if (mod (TRANSFER (q, iptr), 16) /= 0 &
+ .or. iq(1) /= 42) &
+ stop 34
+ iq(1) = 7
+ iq(768 / c_sizeof (0)) = 8
+ r = omp_realloc (c_null_ptr, 512_c_size_t, a2, omp_null_allocator)
+ call c_f_pointer (r, ir, [512 / c_sizeof (0)])
+ if (mod (TRANSFER (r, iptr), get__alignof_int ()) /= 0) &
+ stop 35
+ ir(1) = 9
+ ir(512 / c_sizeof (0)) = 10
+ call omp_free (p, omp_null_allocator)
+ call omp_free (q, a2)
+ call omp_free (r, omp_null_allocator)
+ p = omp_alloc (c_sizeof (0), a2)
+ call c_f_pointer (p, ip, [1])
+ if (mod (TRANSFER (p, iptr), 32) /= 0) &
+ stop 36
+ ip(1) = 85
+ p = omp_realloc (p, 420_c_size_t, a, a2)
+ call c_f_pointer (p, ip, [420 / c_sizeof (0)])
+ if (mod (TRANSFER (p, iptr), 16) /= 0 &
+ .or. ip(1) /= 85) &
+ stop 37
+ ip(1) = 5
+ ip(420 / c_sizeof (0)) = 6
+ q = omp_alloc (c_sizeof (0), a)
+ call c_f_pointer (q, iq, [1])
+ if (mod (TRANSFER (q, iptr), 16) /= 0) &
+ stop 38
+ iq(1) = 43
+ q = omp_realloc (q, 420_c_size_t, a2, a)
+ call c_f_pointer (q, iq, [420 / c_sizeof (0)])
+ if (mod (TRANSFER (q, iptr), 32) /= 0 &
+ .or. iq(1) /= 43) &
+ stop 39
+ iq(1) = 44
+ iq(420 / c_sizeof (0)) = 8
+ q = omp_realloc (q, 768_c_size_t, a2, a2)
+ call c_f_pointer (q, iq, [768 / c_sizeof (0)])
+ if (mod (TRANSFER (q, iptr), 16) /= 0 &
+ .or. iq(1) /= 44) &
+ stop 40
+ iq(1) = 7
+ iq(768 / c_sizeof (0)) = 8
+ call omp_free (p, omp_null_allocator)
+ call omp_free (q, a2)
+ call omp_destroy_allocator (a2)
+ call omp_destroy_allocator (a)
+
+ a = omp_init_allocator (omp_default_mem_space, size (traits4), traits4)
+ if (a == omp_null_allocator) &
+ stop 41
+ if (traits3(6)%key /= omp_atk_fb_data) &
+ stop 1
+ traits3(6)%value = a
+ a2 = omp_init_allocator (omp_default_mem_space, size (traits3), traits3)
+ if (a2 == omp_null_allocator) &
+ stop 42
+ call omp_set_default_allocator (a2)
+ p = omp_realloc (c_null_ptr, 420_c_size_t, omp_null_allocator, omp_null_allocator)
+ call c_f_pointer (p, ip, [420 / c_sizeof (0)])
+ if (mod (TRANSFER (p, iptr), 32) /= 0) &
+ stop 43
+ ip(1) = 5
+ ip(420 / c_sizeof (0)) = 6
+ q = omp_realloc (c_null_ptr, c_sizeof (0), omp_null_allocator, omp_null_allocator)
+ call c_f_pointer (q, iq, [1])
+ if (mod (TRANSFER (q, iptr), 32) /= 0) &
+ stop 44
+ iq(1) = 99
+ q = omp_realloc (q, 700_c_size_t, omp_null_allocator, omp_null_allocator)
+ call c_f_pointer (q, iq, [700 / c_sizeof (0)])
+ if (mod (TRANSFER (q, iptr), 128) /= 0 &
+ .or. iq(1) /= 99) &
+ stop 45
+ iq(1) = 7
+ iq(700 / c_sizeof (0)) = 8
+ if (c_associated (omp_realloc (c_null_ptr, 768_c_size_t, omp_null_allocator, omp_null_allocator))) &
+ stop 46
+ call omp_free (p, omp_null_allocator)
+ if (c_associated (omp_realloc (q, 0_c_size_t, omp_null_allocator, omp_null_allocator))) &
+ stop 47
+ call omp_free (c_null_ptr, omp_null_allocator)
+ call omp_free (c_null_ptr, omp_null_allocator)
+ call omp_destroy_allocator (a2)
+ call omp_destroy_allocator (a)
+end program main
diff --git a/libgomp/testsuite/libgomp.fortran/alloc-6.f90 b/libgomp/testsuite/libgomp.fortran/alloc-6.f90
new file mode 100644
index 0000000..59fd14d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/alloc-6.f90
@@ -0,0 +1,45 @@
+module m
+ use omp_lib
+ implicit none
+
+ type (omp_alloctrait), parameter :: traits(*) &
+ = [ omp_alloctrait (omp_atk_pool_size, 1), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_abort_fb) ]
+end module m
+
+program main
+ use m
+ use iso_c_binding
+ implicit none (external, type)
+ integer (omp_allocator_handle_kind) :: a
+ integer(c_size_t), parameter :: zero = 0_c_size_t
+
+ if (c_associated (omp_alloc (zero, omp_null_allocator))) &
+ stop 1
+ if (c_associated (omp_aligned_alloc (64_c_size_t, zero, omp_null_allocator))) &
+ stop 2
+ if (c_associated (omp_calloc (zero, zero, omp_null_allocator)) &
+ .or. c_associated (omp_calloc (32_c_size_t, zero, omp_null_allocator)) &
+ .or. c_associated (omp_calloc (zero, 64_c_size_t, omp_null_allocator))) &
+ stop 3
+ if (c_associated (omp_aligned_calloc (32_c_size_t, zero, zero, omp_null_allocator)) &
+ .or. c_associated (omp_aligned_calloc (64_c_size_t, 32_c_size_t, zero, omp_null_allocator)) &
+ .or. c_associated (omp_aligned_calloc (16_c_size_t, zero, 64_c_size_t, omp_null_allocator))) &
+ stop 4
+ a = omp_init_allocator (omp_default_mem_space, 2, traits)
+ if (a /= omp_null_allocator) then
+ if (c_associated (omp_alloc (zero, a)) &
+ .or. c_associated (omp_alloc (zero, a)) &
+ .or. c_associated (omp_alloc (zero, a)) &
+ .or. c_associated (omp_aligned_alloc (16_c_size_t, zero, a)) &
+ .or. c_associated (omp_aligned_alloc (128_c_size_t, zero, a)) &
+ .or. c_associated (omp_calloc (zero, zero, a)) &
+ .or. c_associated (omp_calloc (32_c_size_t, zero, a)) &
+ .or. c_associated (omp_calloc (zero, 64_c_size_t, a)) &
+ .or. c_associated (omp_aligned_calloc (32_c_size_t, zero, zero, a)) &
+ .or. c_associated (omp_aligned_calloc (64_c_size_t, 32_c_size_t, zero, a)) &
+ .or. c_associated (omp_aligned_calloc (16_c_size_t, zero, 64_c_size_t, a))) &
+ stop 5
+ call omp_destroy_allocator (a)
+ end if
+end program main
diff --git a/libgomp/testsuite/libgomp.fortran/alloc-7.c b/libgomp/testsuite/libgomp.fortran/alloc-7.c
new file mode 100644
index 0000000..4d16d09
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/alloc-7.c
@@ -0,0 +1,5 @@
+int
+get__alignof_int ()
+{
+ return __alignof (int);
+}
diff --git a/libgomp/testsuite/libgomp.fortran/alloc-7.f90 b/libgomp/testsuite/libgomp.fortran/alloc-7.f90
new file mode 100644
index 0000000..57ecd83
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/alloc-7.f90
@@ -0,0 +1,175 @@
+! { dg-additional-sources alloc-7.c }
+! { dg-prune-output "command-line option '-fintrinsic-modules-path=.*' is valid for Fortran but not for C" }
+module m
+ use omp_lib
+ use iso_c_binding
+ implicit none
+
+ type (omp_alloctrait), parameter :: traits2(*) &
+ = [ omp_alloctrait (omp_atk_alignment, 16), &
+ omp_alloctrait (omp_atk_sync_hint, omp_atv_default), &
+ omp_alloctrait (omp_atk_access, omp_atv_default), &
+ omp_alloctrait (omp_atk_pool_size, 1024), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_default_mem_fb), &
+ omp_alloctrait (omp_atk_partition, omp_atv_environment)]
+
+ type (omp_alloctrait) :: traits3(7) &
+ = [ omp_alloctrait (omp_atk_sync_hint, omp_atv_uncontended), &
+ omp_alloctrait (omp_atk_alignment, 32), &
+ omp_alloctrait (omp_atk_access, omp_atv_all), &
+ omp_alloctrait (omp_atk_pool_size, 512), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_allocator_fb), &
+ omp_alloctrait (omp_atk_fb_data, 0), &
+ omp_alloctrait (omp_atk_partition, omp_atv_default)]
+
+ type (omp_alloctrait), parameter :: traits4(*) &
+ = [ omp_alloctrait (omp_atk_alignment, 128), &
+ omp_alloctrait (omp_atk_pool_size, 1024), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_null_fb)]
+
+ interface
+ integer(c_int) function get__alignof_int () bind(C)
+ import :: c_int
+ end
+ end interface
+end module m
+
+program main
+ use m
+ implicit none (external, type)
+ integer(c_ptrdiff_t) :: iptr
+ type (c_ptr), volatile :: p, q, r
+ integer, pointer, volatile, contiguous :: ip(:), iq(:), ir(:)
+ type (omp_alloctrait) :: traits(3)
+ integer (omp_allocator_handle_kind) :: a, a2
+ traits = [ omp_alloctrait (omp_atk_alignment, 64), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_null_fb), &
+ omp_alloctrait (omp_atk_pool_size, 4096)]
+
+ p = omp_aligned_alloc (c_sizeof (0), 3 * c_sizeof (0), omp_default_mem_alloc)
+ call c_f_pointer (p, ip, [3])
+ if (mod (TRANSFER (p, iptr), get__alignof_int ()) /= 0) &
+ stop 1
+ ip(1) = 1
+ ip(2) = 2
+ ip(3) = 3
+ call omp_free (p, omp_default_mem_alloc)
+
+ p = omp_aligned_alloc (2 * c_sizeof (0), 2 * c_sizeof (0), omp_default_mem_alloc)
+ call c_f_pointer (p, ip, [2])
+ if (mod (TRANSFER (p, iptr), 2 * c_sizeof (0)) /= 0) &
+ stop 2
+ ip(1) = 1
+ ip(2) = 2
+ call omp_free (p, omp_null_allocator)
+
+ call omp_set_default_allocator (omp_default_mem_alloc)
+ p = omp_aligned_alloc (1_c_size_t, 2 * c_sizeof (0), omp_null_allocator)
+ call c_f_pointer (p, ip, [2])
+ if (mod (TRANSFER (p, iptr), get__alignof_int ()) /= 0) &
+ stop 3
+ ip(1) = 3
+ call omp_free (p, omp_get_default_allocator ())
+
+ a = omp_init_allocator (omp_default_mem_space, 3, traits)
+ if (a == omp_null_allocator) &
+ stop 4
+ p = omp_aligned_alloc (32_c_size_t, 3072_c_size_t, a)
+ call c_f_pointer (p, ip, [3072/c_sizeof (0)])
+ if (mod (TRANSFER (p, iptr), 64) /= 0) &
+ stop 5
+ ip(1) = 1
+ ip(3072 / c_sizeof (0)) = 2
+
+ if (c_associated (omp_aligned_alloc (8_c_size_t, 3072_c_size_t, a))) &
+ stop 6
+
+ call omp_free (p, a)
+
+ p = omp_aligned_alloc (128_c_size_t, 3072_c_size_t, a)
+ call c_f_pointer (p, ip, [3072/c_sizeof (0)])
+ if (mod (TRANSFER (p, iptr), 128) /= 0) &
+ stop 7
+ ip(1) = 3
+ ip(3072 / c_sizeof (0)) = 4
+ call omp_free (p, omp_null_allocator)
+
+ call omp_set_default_allocator (a)
+ if (omp_get_default_allocator () /= a) &
+ stop 8
+ p = omp_aligned_alloc (64_c_size_t, 3072_c_size_t, omp_null_allocator)
+ call c_f_pointer (p, ip, [3072/c_sizeof (0)])
+ if (c_associated (omp_aligned_alloc (8_c_size_t, 3072_c_size_t, omp_null_allocator))) &
+ stop 9
+ call omp_free (p, a)
+ call omp_destroy_allocator (a)
+
+ a = omp_init_allocator (omp_default_mem_space, size (traits2), traits2)
+ if (a == omp_null_allocator) &
+ stop 9
+ if (traits3(6)%key /= omp_atk_fb_data) &
+ stop 10
+ traits3(6)%value = a
+ a2 = omp_init_allocator (omp_default_mem_space, size (traits3), traits3)
+ if (a2 == omp_null_allocator) &
+ stop 11
+
+ p = omp_aligned_alloc (4_c_size_t, 420_c_size_t, a2)
+ call c_f_pointer (p, ip, [420/c_sizeof (0)])
+ if (mod (TRANSFER (p, iptr), 32) /= 0) &
+ stop 12
+ ip(1) = 5
+ ip(420 / c_sizeof (0)) = 6
+
+ q = omp_aligned_alloc (8_c_size_t, 768_c_size_t, a2)
+ call c_f_pointer (q, iq, [768/c_sizeof (0)])
+ if (mod (TRANSFER (q, iptr), 16) /= 0) &
+ stop 13
+ iq(1) = 7
+ iq(768 / c_sizeof (0)) = 8
+
+ r = omp_aligned_alloc (8_c_size_t, 512_c_size_t, a2)
+ call c_f_pointer (r, ir, [512/c_sizeof (0)])
+ if (mod (TRANSFER (r, iptr), 8) /= 0) &
+ stop 14
+ ir(1) = 9
+ ir(512 / c_sizeof (0)) = 10
+ call omp_free (p, omp_null_allocator)
+ call omp_free (q, a2)
+ call omp_free (r, omp_null_allocator)
+ call omp_destroy_allocator (a2)
+ call omp_destroy_allocator (a)
+
+ a = omp_init_allocator (omp_default_mem_space, size (traits4), traits4)
+ if (a == omp_null_allocator) &
+ stop 15
+ if (traits3(6)%key /= omp_atk_fb_data) &
+ stop 16
+ traits3(6)%value = a
+ a2 = omp_init_allocator (omp_default_mem_space, size (traits3), traits3)
+ if (a2 == omp_null_allocator) &
+ stop 17
+ call omp_set_default_allocator (a2)
+
+ p = omp_aligned_alloc (4_c_size_t, 420_c_size_t, omp_null_allocator)
+ call c_f_pointer (p, ip, [420/c_sizeof (0)])
+ if (mod (TRANSFER (p, iptr), 32) /= 0) &
+ stop 18
+ ip(1) = 5
+ ip(420 / c_sizeof (0)) = 6
+
+ q = omp_aligned_alloc (64_c_size_t, 768_c_size_t, omp_null_allocator)
+ call c_f_pointer (q, iq, [768/c_sizeof (0)])
+ if (mod (TRANSFER (q, iptr), 128) /= 0) &
+ stop 19
+ iq(1) = 7
+ iq(768 / c_sizeof (0)) = 8
+ if (c_associated (omp_aligned_alloc (8_c_size_t, 768_c_size_t, omp_null_allocator))) &
+ stop 20
+ call omp_free (p, omp_null_allocator)
+ call omp_free (q, omp_null_allocator)
+ call omp_free (c_null_ptr, omp_null_allocator)
+ call omp_free (c_null_ptr, omp_null_allocator)
+ call omp_destroy_allocator (a2)
+ call omp_destroy_allocator (a)
+end program main
diff --git a/libgomp/testsuite/libgomp.fortran/alloc-8.f90 b/libgomp/testsuite/libgomp.fortran/alloc-8.f90
new file mode 100644
index 0000000..059c368
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/alloc-8.f90
@@ -0,0 +1,58 @@
+module m
+ use omp_lib
+ implicit none
+
+ type (omp_alloctrait), parameter :: traits(*) &
+ = [ omp_alloctrait (omp_atk_alignment, 16), &
+ omp_alloctrait (omp_atk_sync_hint, omp_atv_default), &
+ omp_alloctrait (omp_atk_access, omp_atv_default), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_default_mem_fb), &
+ omp_alloctrait (omp_atk_partition, omp_atv_environment)]
+end module m
+
+program main
+ use m
+ use iso_c_binding
+ implicit none (external, type)
+ integer (omp_allocator_handle_kind) :: a
+ type (c_ptr) :: p, q
+ integer (c_size_t), volatile :: large_sz
+ integer (c_ptrdiff_t) :: iptr
+
+ a = omp_init_allocator (omp_default_mem_space, size (traits), traits)
+ if (a == omp_null_allocator) &
+ stop 1
+ p = omp_alloc (2048_c_size_t, a)
+ if (mod (TRANSFER (p, iptr), 16) /= 0) &
+ stop 2
+ large_sz = NOT (1023_c_size_t)
+ q = omp_alloc (large_sz, a)
+ if (c_associated (q)) &
+ stop 3
+ q = omp_aligned_alloc (32_c_size_t, large_sz, a)
+ if (c_associated (q)) &
+ stop 4
+ q = omp_calloc (large_sz / 4_c_size_t, 4_c_size_t, a)
+ if (c_associated (q)) &
+ stop 5
+ q = omp_aligned_calloc (1_c_size_t, 2_c_size_t, large_sz / 2, a)
+ if (c_associated (q)) &
+ stop 6
+ call omp_free (p, a)
+ large_sz = NOT (0_c_size_t)
+ large_sz = ISHFT (large_sz, -1)
+ large_sz = large_sz + 1 ! signed integer overflow
+ if (c_associated (omp_calloc (2_c_size_t, large_sz, a))) &
+ stop 7
+ if (c_associated (omp_calloc (large_sz, 1024_c_size_t, a))) &
+ stop 8
+ if (c_associated (omp_calloc (large_sz, large_sz, a))) &
+ stop 9
+ if (c_associated (omp_aligned_calloc (16_c_size_t, 2_c_size_t, large_sz, a))) &
+ stop 10
+ if (c_associated (omp_aligned_calloc (32_c_size_t, large_sz, 1024_c_size_t, a))) &
+ stop 11
+ if (c_associated (omp_aligned_calloc (64_c_size_t, large_sz, large_sz, a))) &
+ stop 12
+ call omp_destroy_allocator (a)
+end program main
diff --git a/libgomp/testsuite/libgomp.fortran/alloc-9.f90 b/libgomp/testsuite/libgomp.fortran/alloc-9.f90
new file mode 100644
index 0000000..1da1416
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/alloc-9.f90
@@ -0,0 +1,197 @@
+! { dg-additional-sources alloc-7.c }
+! { dg-prune-output "command-line option '-fintrinsic-modules-path=.*' is valid for Fortran but not for C" }
+module m
+ use omp_lib
+ use iso_c_binding
+ implicit none
+
+ type (omp_alloctrait), parameter :: traits2(*) &
+ = [ omp_alloctrait (omp_atk_alignment, 16), &
+ omp_alloctrait (omp_atk_sync_hint, omp_atv_default), &
+ omp_alloctrait (omp_atk_access, omp_atv_default), &
+ omp_alloctrait (omp_atk_pool_size, 1024), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_default_mem_fb), &
+ omp_alloctrait (omp_atk_partition, omp_atv_environment)]
+ type (omp_alloctrait) :: traits3(7) &
+ = [ omp_alloctrait (omp_atk_sync_hint, omp_atv_uncontended), &
+ omp_alloctrait (omp_atk_alignment, 32), &
+ omp_alloctrait (omp_atk_access, omp_atv_all), &
+ omp_alloctrait (omp_atk_pool_size, 512), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_allocator_fb), &
+ omp_alloctrait (omp_atk_fb_data, 0), &
+ omp_alloctrait (omp_atk_partition, omp_atv_default)]
+ type (omp_alloctrait), parameter :: traits4(*) &
+ = [ omp_alloctrait (omp_atk_alignment, 128), &
+ omp_alloctrait (omp_atk_pool_size, 1024), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_null_fb)]
+
+ interface
+ integer(c_int) function get__alignof_int () bind(C)
+ import :: c_int
+ end
+ end interface
+end module m
+
+program main
+ use m
+ implicit none (external, type)
+ type(c_ptr), volatile :: p, q, r
+ integer, pointer, contiguous, volatile :: ip(:), iq(:), ir(:)
+ type (omp_alloctrait) :: traits(3)
+ integer (omp_allocator_handle_kind) :: a, a2
+ integer (c_ptrdiff_t) :: iptr
+ integer :: i
+
+ traits = [ omp_alloctrait (omp_atk_alignment, 64), &
+ omp_alloctrait (omp_atk_fallback, omp_atv_null_fb), &
+ omp_alloctrait (omp_atk_pool_size, 4096)]
+
+ p = omp_calloc (3_c_size_t, sizeof (0), omp_default_mem_alloc)
+ call c_f_pointer (p, ip, [3])
+ if (mod (TRANSFER (p, iptr), get__alignof_int ()) /= 0 &
+ .or. ip(1) /= 0 .or. ip(2) /= 0 .or. ip(3) /= 0) &
+ stop 1
+ ip(1) = 1
+ ip(2) = 2
+ ip(3) = 3
+ call omp_free (p, omp_default_mem_alloc)
+ p = omp_calloc (2_c_size_t, sizeof (0), omp_default_mem_alloc)
+ call c_f_pointer (p, ip, [2])
+ if (mod (TRANSFER (p, iptr), get__alignof_int ()) /= 0 &
+ .or. ip(1) /= 0 .or. ip(2) /= 0) &
+ stop 2
+ ip(1) = 1
+ ip(2) = 2
+ call omp_free (p, omp_null_allocator)
+ call omp_set_default_allocator (omp_default_mem_alloc)
+ p = omp_calloc (1_c_size_t, sizeof (0), omp_null_allocator)
+ call c_f_pointer (p, ip, [1])
+ if (mod (TRANSFER (p, iptr), get__alignof_int ()) /= 0 &
+ .or. ip(1) /= 0) &
+ stop 3
+ ip(1) = 3
+ call omp_free (p, omp_get_default_allocator ())
+
+ a = omp_init_allocator (omp_default_mem_space, 3, traits)
+ if (a == omp_null_allocator) &
+ stop 4
+ p = omp_calloc (3_c_size_t, 1024_c_size_t, a)
+ call c_f_pointer (p, ip, [3072 / c_sizeof (0)])
+ if (mod (TRANSFER (p, iptr), 64) /= 0) &
+ stop 5
+ do i = 1, 3072 / c_sizeof (0)
+ if (ip(i) /= 0) &
+ stop 6
+ end do
+ ip(1) = 1
+ ip(3072 / c_sizeof (0)) = 2
+ if (c_associated (omp_calloc (1024_c_size_t, 3_c_size_t, a))) &
+ stop 7
+ call omp_free (p, a)
+ p = omp_calloc (512_c_size_t, 6_c_size_t, a)
+ call c_f_pointer (p, ip, [3072 / c_sizeof (0)])
+ do i = 1, 3072 / c_sizeof (0)
+ if (ip(i) /= 0) &
+ stop 8
+ end do
+ ip(1) = 3
+ ip(3072 / c_sizeof (0)) = 4
+ call omp_free (p, omp_null_allocator)
+ call omp_set_default_allocator (a)
+ if (omp_get_default_allocator () /= a) &
+ stop 9
+ p = omp_calloc (12_c_size_t, 256_c_size_t, omp_null_allocator)
+ call c_f_pointer (p, ip, [3072 / c_sizeof (0)])
+ do i = 1, 3072 / c_sizeof (0)
+ if (ip(i) /= 0) &
+ stop 10
+ end do
+ if (c_associated (omp_calloc (128_c_size_t, 24_c_size_t, omp_null_allocator))) &
+ stop 11
+ call omp_free (p, a)
+ call omp_destroy_allocator (a)
+
+ a = omp_init_allocator (omp_default_mem_space, size (traits2), traits2)
+ if (a == omp_null_allocator) &
+ stop 12
+ if (traits3(6)%key /= omp_atk_fb_data) &
+ stop 13
+ traits3(6)%value = a
+ a2 = omp_init_allocator (omp_default_mem_space, size (traits3), traits3)
+ if (a2 == omp_null_allocator) &
+ stop 14
+ p = omp_calloc (10_c_size_t, 42_c_size_t, a2)
+ call c_f_pointer (p, ip, [420 / c_sizeof (0)])
+ do i = 1, 420 / c_sizeof (0)
+ if (ip(i) /= 0) &
+ stop 15
+ end do
+ if (mod (TRANSFER (p, iptr), 32) /= 0) &
+ stop 16
+ ip(1) = 5
+ ip(420 / c_sizeof (0)) = 6
+ q = omp_calloc (24_c_size_t, 32_c_size_t, a2)
+ call c_f_pointer (q, iq, [768 / c_sizeof (0)])
+ if (mod (TRANSFER (q, iptr), 16) /= 0) &
+ stop 17
+ do i = 1, 768 / c_sizeof (0)
+ if (iq(i) /= 0) &
+ stop 18
+ end do
+ iq(1) = 7
+ iq(768 / c_sizeof (0)) = 8
+ r = omp_calloc (128_c_size_t, 4_c_size_t, a2)
+ call c_f_pointer (r, ir, [512 / c_sizeof (0)])
+ if (mod (TRANSFER (r, iptr), get__alignof_int ()) /= 0) &
+ stop 19
+ do i = 1, 512 / c_sizeof (0)
+ if (ir(i) /= 0) &
+ stop 20
+ end do
+ ir(1) = 9
+ ir(512 / c_sizeof (0)) = 10
+ call omp_free (p, omp_null_allocator)
+ call omp_free (q, a2)
+ call omp_free (r, omp_null_allocator)
+ call omp_destroy_allocator (a2)
+ call omp_destroy_allocator (a)
+
+ a = omp_init_allocator (omp_default_mem_space, size (traits4), traits4)
+ if (a == omp_null_allocator) &
+ stop 21
+ if (traits3(6)%key /= omp_atk_fb_data) &
+ stop 22
+ traits3(6)%value = a
+ a2 = omp_init_allocator (omp_default_mem_space, size (traits3), traits3)
+ if (a2 == omp_null_allocator) &
+ stop 23
+ call omp_set_default_allocator (a2)
+ p = omp_calloc (42_c_size_t, 10_c_size_t, omp_null_allocator)
+ call c_f_pointer (p, ip, [420 / c_sizeof (0)])
+ if (mod (TRANSFER (p, iptr), 32) /= 0) &
+ stop 24
+ do i = 1, 420 / c_sizeof (0)
+ if (ip(i) /= 0) &
+ stop 25
+ end do
+ ip(1) = 5
+ ip(420 / c_sizeof (0)) = 6
+ q = omp_calloc (32_c_size_t, 24_c_size_t, omp_null_allocator)
+ call c_f_pointer (q, iq, [768 / c_sizeof (0)])
+ if (mod (TRANSFER (q, iptr), 128) /= 0) &
+ stop 26
+ do i = 1, 768 / c_sizeof (0)
+ if (iq(i) /= 0) &
+ stop 27
+ end do
+ iq(1) = 7
+ iq(768 / c_sizeof (0)) = 8
+ if (c_associated (omp_calloc (24_c_size_t, 32_c_size_t, omp_null_allocator))) &
+ stop 28
+ call omp_free (p, omp_null_allocator)
+ call omp_free (q, omp_null_allocator)
+ call omp_free (c_null_ptr, omp_null_allocator)
+ call omp_free (c_null_ptr, omp_null_allocator)
+ call omp_destroy_allocator (a2)
+ call omp_destroy_allocator (a)
+end program main
diff --git a/libgomp/testsuite/libgomp.fortran/fortran.exp b/libgomp/testsuite/libgomp.fortran/fortran.exp
index 912dd2a..eb70131 100644
--- a/libgomp/testsuite/libgomp.fortran/fortran.exp
+++ b/libgomp/testsuite/libgomp.fortran/fortran.exp
@@ -20,9 +20,6 @@ dg-init
# Turn on OpenMP.
lappend ALWAYS_CFLAGS "additional_flags=-fopenmp"
-# Silence warnings due to explicitly passed but nonexisting
-# -isystem <instdir>/target>/{sys-,}include (gfortran warns by default)
-lappend ALWAYS_CFLAGS "additional_flags=-Wno-missing-include-dirs"
if { $blddir != "" } {
set lang_source_re {^.*\.[fF](|90|95|03|08)$}
diff --git a/libgomp/testsuite/libgomp.fortran/my-usleep.c b/libgomp/testsuite/libgomp.fortran/my-usleep.c
new file mode 100644
index 0000000..1764db9
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/my-usleep.c
@@ -0,0 +1,9 @@
+/* Wrapper as usleep takes 'useconds_t', an unsigned integer type, as argument. */
+
+#include <unistd.h>
+
+void
+my_usleep (int t)
+{
+ usleep (t);
+}
diff --git a/libgomp/testsuite/libgomp.fortran/order-reproducible-1.f90 b/libgomp/testsuite/libgomp.fortran/order-reproducible-1.f90
new file mode 100644
index 0000000..ba416b9
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/order-reproducible-1.f90
@@ -0,0 +1,72 @@
+! { dg-additional-sources my-usleep.c }
+! { dg-prune-output "command-line option '-fintrinsic-modules-path=.*' is valid for Fortran but not for C" }
+program main
+ implicit none
+ interface
+ subroutine usleep(t) bind(C, name="my_usleep")
+ use iso_c_binding
+ integer(c_int), value :: t
+ end subroutine
+ end interface
+
+ integer :: a(128)
+ integer :: i
+
+ !$omp teams num_teams(5)
+ !$omp loop bind(teams)
+ do i = 1, 128
+ a(i) = i
+ if (i == 1) then
+ call usleep (20)
+ else if (i == 17) then
+ call usleep (40)
+ end if
+ end do
+ !$omp loop bind(teams)
+ do i = 1, 128
+ a(i) = a(i) + i
+ end do
+ !$omp end teams
+ do i = 1, 128
+ if (a(i) /= 2 * i) &
+ stop 1
+ end do
+ !$omp teams num_teams(5)
+ !$omp loop bind(teams) order(concurrent)
+ do i = 1, 128
+ a(i) = a(i) * 2
+ if (i == 1) then
+ call usleep (20)
+ else if (i == 13) then
+ call usleep (40)
+ end if
+ end do
+ !$omp loop bind(teams) order(concurrent)
+ do i = 1, 128
+ a(i) = a(i) + i
+ end do
+ !$omp end teams
+ do i = 1, 128
+ if (a(i) /= 5 * i) &
+ stop 2
+ end do
+ !$omp teams num_teams(5)
+ !$omp loop bind(teams) order(reproducible:concurrent)
+ do i = 1, 128
+ a(i) = a(i) * 2
+ if (i == 3) then
+ call usleep (20)
+ else if (i == 106) then
+ call usleep (40)
+ end if
+ end do
+ !$omp loop bind(teams) order(reproducible:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + i
+ end do
+ !$omp end teams
+ do i = 1, 128
+ if (a(i) /= 11 * i) &
+ stop 3
+ end do
+end program main
diff --git a/libgomp/testsuite/libgomp.fortran/order-reproducible-2.f90 b/libgomp/testsuite/libgomp.fortran/order-reproducible-2.f90
new file mode 100644
index 0000000..9d72020
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/order-reproducible-2.f90
@@ -0,0 +1,37 @@
+! { dg-additional-sources my-usleep.c }
+! { dg-prune-output "command-line option '-fintrinsic-modules-path=.*' is valid for Fortran but not for C" }
+program main
+ implicit none
+ interface
+ subroutine usleep(t) bind(C, name="my_usleep")
+ use iso_c_binding
+ integer(c_int), value :: t
+ end subroutine
+ end interface
+
+ integer :: a(128)
+ integer :: i
+
+ !$omp parallel num_threads(8)
+ !$omp barrier
+ !$omp do schedule (dynamic, 2) order(reproducible:concurrent)
+ do i = 1, 128
+ a(i) = i
+ if (i == 1) then
+ call usleep (20)
+ else if (i == 18) then
+ call usleep (40)
+ end if
+ end do
+ !$omp end do nowait
+ !$omp do schedule (dynamic, 2) order(reproducible:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + i
+ end do
+ !$omp end do nowait
+ !$omp end parallel
+ do i = 1, 128
+ if (a(i) /= 2 * i) &
+ stop
+ end do
+end program main
diff --git a/libgomp/testsuite/libgomp.graphite/force-parallel-4.c b/libgomp/testsuite/libgomp.graphite/force-parallel-4.c
index ef6f64d..6caa934 100644
--- a/libgomp/testsuite/libgomp.graphite/force-parallel-4.c
+++ b/libgomp/testsuite/libgomp.graphite/force-parallel-4.c
@@ -1,5 +1,5 @@
/* Autopar with IF conditions. */
-/* { dg-additional-options "-fdisable-tree-thread1" } */
+/* { dg-additional-options "-fdisable-tree-thread1 -fdisable-tree-vrp-thread1" } */
void abort();
diff --git a/libgomp/testsuite/libgomp.graphite/force-parallel-8.c b/libgomp/testsuite/libgomp.graphite/force-parallel-8.c
index a97eb97..f9e0703 100644
--- a/libgomp/testsuite/libgomp.graphite/force-parallel-8.c
+++ b/libgomp/testsuite/libgomp.graphite/force-parallel-8.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fdisable-tree-thread1" } */
+/* { dg-additional-options "-fdisable-tree-thread1 -fdisable-tree-vrp-thread1" } */
#define N 1500
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/fortran.exp b/libgomp/testsuite/libgomp.oacc-fortran/fortran.exp
index 22e91ec..7365b32 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/fortran.exp
+++ b/libgomp/testsuite/libgomp.oacc-fortran/fortran.exp
@@ -22,9 +22,6 @@ dg-init
# Turn on OpenACC.
lappend ALWAYS_CFLAGS "additional_flags=-fopenacc"
-# Silence warnings due to explicitly passed but nonexisting
-# -isystem <instdir>/target>/{sys-,}include (gfortran warns by default)
-lappend ALWAYS_CFLAGS "additional_flags=-Wno-missing-include-dirs"
if { $blddir != "" } {
set lang_source_re {^.*\.[fF](|90|95|03|08)$}
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/if-1.f90 b/libgomp/testsuite/libgomp.oacc-fortran/if-1.f90
index 3089d6a..9eadfcf 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/if-1.f90
+++ b/libgomp/testsuite/libgomp.oacc-fortran/if-1.f90
@@ -394,6 +394,7 @@ program main
!$acc data copyin (a(1:N)) copyout (b(1:N)) if (0 == 1)
! { dg-note {variable 'D\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} "" { target { ! openacc_host_selected } } .-1 }
+ ! { dg-note {variable 'parm\.[0-9]+' declared in block is candidate for adjusting OpenACC privatization level} "" { target { ! openacc_host_selected } } .-2 }
#if !ACC_MEM_SHARED
if (acc_is_present (a) .eqv. .TRUE.) STOP 21
@@ -408,6 +409,7 @@ program main
!$acc data copyin (a(1:N)) if (1 == 1)
! { dg-note {variable 'D\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} "" { target *-*-* } .-1 }
! { dg-note {variable 'parm\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} "" { target *-*-* } .-2 }
+ ! { dg-note {variable 'parm\.[0-9]+' declared in block is candidate for adjusting OpenACC privatization level} "" { target { ! openacc_host_selected } } .-3 }
#if !ACC_MEM_SHARED
if (acc_is_present (a) .eqv. .FALSE.) STOP 23
@@ -416,6 +418,7 @@ program main
!$acc data copyout (b(1:N)) if (0 == 1)
! { dg-note {variable 'D\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} "" { target *-*-* } .-1 }
! { dg-note {variable 'parm\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} "" { target *-*-* } .-2 }
+ ! { dg-note {variable 'parm\.[0-9]+' declared in block is candidate for adjusting OpenACC privatization level} "" { target { ! openacc_host_selected } } .-3 }
#if !ACC_MEM_SHARED
if (acc_is_present (b) .eqv. .TRUE.) STOP 24
#endif
@@ -864,6 +867,7 @@ program main
!$acc data copyin (a(1:N)) copyout (b(1:N)) if (0 == 1)
! { dg-note {variable 'D\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} "" { target { ! openacc_host_selected } } .-1 }
+ ! { dg-note {variable 'parm\.[0-9]+' declared in block is candidate for adjusting OpenACC privatization level} "" { target { ! openacc_host_selected } } .-2 }
#if !ACC_MEM_SHARED
if (acc_is_present (a) .eqv. .TRUE.) STOP 56
@@ -878,6 +882,7 @@ program main
!$acc data copyin (a(1:N)) if (1 == 1)
! { dg-note {variable 'D\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} "" { target *-*-* } .-1 }
! { dg-note {variable 'parm\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} "" { target *-*-* } .-2 }
+ ! { dg-note {variable 'parm\.[0-9]+' declared in block is candidate for adjusting OpenACC privatization level} "" { target { ! openacc_host_selected } } .-3 }
#if !ACC_MEM_SHARED
if (acc_is_present (a) .eqv. .FALSE.) STOP 58
@@ -886,6 +891,7 @@ program main
!$acc data copyout (b(1:N)) if (0 == 1)
! { dg-note {variable 'D\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} "" { target *-*-* } .-1 }
! { dg-note {variable 'parm\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} "" { target *-*-* } .-2 }
+ ! { dg-note {variable 'parm\.[0-9]+' declared in block is candidate for adjusting OpenACC privatization level} "" { target { ! openacc_host_selected } } .-3 }
#if !ACC_MEM_SHARED
if (acc_is_present (b) .eqv. .TRUE.) STOP 59
#endif
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/privatized-ref-2.f90 b/libgomp/testsuite/libgomp.oacc-fortran/privatized-ref-2.f90
index baaee02..3f3a1b5 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/privatized-ref-2.f90
+++ b/libgomp/testsuite/libgomp.oacc-fortran/privatized-ref-2.f90
@@ -71,9 +71,7 @@ contains
! { dg-note {variable 'offset\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} "" { target *-*-* } l_compute$c_compute }
! { dg-note {variable 'S\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} "" { target *-*-* } l_compute$c_compute }
! { dg-note {variable 'test\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} "" { target *-*-* } l_compute$c_compute }
- ! { dg-note {variable 'parm\.[0-9]+' declared in block is candidate for adjusting OpenACC privatization level} "" { target *-*-* } l_compute$c_compute }
- ! { dg-note {variable 'parm\.[0-9]+' ought to be adjusted for OpenACC privatization level: 'gang'} "" { target *-*-* } l_compute$c_compute }
- ! { dg-note {variable 'parm\.[0-9]+' adjusted for OpenACC privatization level: 'gang'} "" { target { ! { openacc_host_selected || openacc_nvidia_accel_selected } } } l_compute$c_compute }
+ ! { dg-note {variable 'parm\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} "" { target *-*-* } l_compute$c_compute }
! { dg-note {variable 'A\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: static} "" { target *-*-* } l_compute$c_compute }
array = [(-2*i, i = 1, size(array))]
!$acc loop gang private(array) ! { dg-line l_loop[incr c_loop] }
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 7c337c2..ff9c5d7 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,17 @@
+2021-10-01 Luís Ferreira <contact@lsferreira.net>
+
+ * testsuite/d-demangle-expected: Add missing format for new test
+
+2021-09-23 Luís Ferreira <contact@lsferreira.net>
+
+ * d-demangle.c (dlang_Type): Validate MANGLED is nonnull.
+ * testsuite/d-demangle-expected: New test.
+
+2021-09-23 Luís Ferreira <contact@lsferreira.net>
+
+ * d-demangle.c (dlang_symbol_backref): Ensure strlen of
+ string is less than length computed by dlang_number.
+
2021-09-01 Iain Sandoe <iain@sandoe.co.uk>
* configure: Regenerate.
diff --git a/libiberty/d-demangle.c b/libiberty/d-demangle.c
index a2152cc..3adf7b5 100644
--- a/libiberty/d-demangle.c
+++ b/libiberty/d-demangle.c
@@ -381,7 +381,7 @@ dlang_symbol_backref (string *decl, const char *mangled,
/* Must point to a simple identifier. */
backref = dlang_number (backref, &len);
- if (backref == NULL)
+ if (backref == NULL || strlen(backref) < len)
return NULL;
backref = dlang_lname (decl, backref, len);
@@ -875,7 +875,7 @@ dlang_type (string *decl, const char *mangled, struct dlang_info *info)
szmods = string_length (&mods);
/* Back referenced function type. */
- if (*mangled == 'Q')
+ if (mangled && *mangled == 'Q')
mangled = dlang_type_backref (decl, mangled, info, 1);
else
mangled = dlang_function_type (decl, mangled, info);
diff --git a/libiberty/testsuite/d-demangle-expected b/libiberty/testsuite/d-demangle-expected
index c35185c..44a3649 100644
--- a/libiberty/testsuite/d-demangle-expected
+++ b/libiberty/testsuite/d-demangle-expected
@@ -996,6 +996,10 @@ _D00
_D00
#
--format=dlang
+_D01_D
+_D01_D
+#
+--format=dlang
_D9223372036854775817
_D9223372036854775817
#
diff --git a/libphobos/ChangeLog b/libphobos/ChangeLog
index fa1aef7..0cc0b3d 100644
--- a/libphobos/ChangeLog
+++ b/libphobos/ChangeLog
@@ -1,3 +1,37 @@
+2021-09-30 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * libdruntime/gcc/deh.d (ExceptionHeader.getClassInfo): Move to...
+ (getClassInfo): ...here as free function. Add lsda parameter.
+ (scanLSDA): Pass lsda to actionTableLookup.
+ (actionTableLookup): Add lsda parameter, pass to getClassInfo.
+ (__gdc_personality): Remove currentCfa variable.
+
+2021-09-30 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * libdruntime/gcc/deh.d (_d_print_throwable): Declare.
+ (_d_throw): Print stacktrace before terminating program due to
+ uncaught exception.
+
+2021-09-30 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * libdruntime/core/runtime.d (runModuleUnitTests): Use scope to new
+ LibBacktrace on the stack.
+ * libdruntime/gcc/backtrace.d (FIRSTFRAME): Remove.
+ (LibBacktrace.MaxAlignment): Remove.
+ (LibBacktrace.this): Remove default initialization of firstFrame.
+ (UnwindBacktrace.this): Likewise.
+
+2021-09-30 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * libdruntime/gcc/unwind/generic.d (__aligned__): Define.
+ (_Unwind_Exception): Align struct to __aligned__.
+
+2021-09-30 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/102476
+ * libdruntime/__main.di: Define main function as extern(C) when
+ compiling without D runtime.
+
2021-09-01 Iain Buclaw <ibuclaw@gdcproject.org>
* m4/druntime/os.m4: Update comment for DRUNTIME_OS_SOURCES.
diff --git a/libphobos/libdruntime/__main.di b/libphobos/libdruntime/__main.di
index 8062bf4..ab1264b 100644
--- a/libphobos/libdruntime/__main.di
+++ b/libphobos/libdruntime/__main.di
@@ -20,7 +20,17 @@
module __main;
-int main(char[][])
+version (D_BetterC)
{
- return 0;
+ extern (C) int main(int, char**)
+ {
+ return 0;
+ }
+}
+else
+{
+ int main(char[][])
+ {
+ return 0;
+ }
}
diff --git a/libphobos/libdruntime/core/runtime.d b/libphobos/libdruntime/core/runtime.d
index 848b607..5fc9904 100644
--- a/libphobos/libdruntime/core/runtime.d
+++ b/libphobos/libdruntime/core/runtime.d
@@ -483,17 +483,9 @@ extern (C) bool runModuleUnitTests()
fprintf(stderr, "Segmentation fault while running unittests:\n");
fprintf(stderr, "----------------\n");
- enum alignment = LibBacktrace.MaxAlignment;
- enum classSize = __traits(classInstanceSize, LibBacktrace);
-
- void[classSize + alignment] bt_store = void;
- void* alignedAddress = cast(byte*)((cast(size_t)(bt_store.ptr + alignment - 1))
- & ~(alignment - 1));
-
- (alignedAddress[0 .. classSize]) = typeid(LibBacktrace).initializer[];
- auto bt = cast(LibBacktrace)(alignedAddress);
- // First frame is LibBacktrace ctor. Second is signal handler, but include that for now
- bt.__ctor(1);
+ // First frame is LibBacktrace ctor. Second is signal handler,
+ // but include that for now
+ scope bt = new LibBacktrace(1);
foreach (size_t i, const(char[]) msg; bt)
fprintf(stderr, "%s\n", msg.ptr ? msg.ptr : "???");
diff --git a/libphobos/libdruntime/gcc/backtrace.d b/libphobos/libdruntime/gcc/backtrace.d
index 8f5582d..3c4d65f 100644
--- a/libphobos/libdruntime/gcc/backtrace.d
+++ b/libphobos/libdruntime/gcc/backtrace.d
@@ -24,24 +24,6 @@ module gcc.backtrace;
import gcc.libbacktrace;
-version (Posix)
-{
- // NOTE: The first 5 frames with the current implementation are
- // inside core.runtime and the object code, so eliminate
- // these for readability. The alternative would be to
- // exclude the first N frames that are in a list of
- // mangled function names.
- private enum FIRSTFRAME = 5;
-}
-else
-{
- // NOTE: On Windows, the number of frames to exclude is based on
- // whether the exception is user or system-generated, so
- // it may be necessary to exclude a list of function names
- // instead.
- private enum FIRSTFRAME = 0;
-}
-
// Max size per line of the traceback.
private enum MAX_BUFSIZE = 1536;
@@ -205,8 +187,6 @@ static if (BACKTRACE_SUPPORTED && !BACKTRACE_USES_MALLOC)
// FIXME: state is never freed as libbacktrace doesn't provide a free function...
public class LibBacktrace : Throwable.TraceInfo
{
- enum MaxAlignment = (void*).alignof;
-
static void initLibBacktrace()
{
if (!initialized)
@@ -216,7 +196,7 @@ static if (BACKTRACE_SUPPORTED && !BACKTRACE_USES_MALLOC)
}
}
- this(int firstFrame = FIRSTFRAME)
+ this(int firstFrame)
{
_firstFrame = firstFrame;
@@ -365,7 +345,7 @@ else
*/
public class UnwindBacktrace : Throwable.TraceInfo
{
- this(int firstFrame = FIRSTFRAME)
+ this(int firstFrame)
{
_firstFrame = firstFrame;
_callstack = getBacktrace();
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index eb83751c..ba57fed 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -34,6 +34,7 @@ extern(C)
{
int _d_isbaseof(ClassInfo, ClassInfo);
void _d_createTrace(Object, void*);
+ void _d_print_throwable(Throwable t);
}
/**
@@ -279,26 +280,6 @@ struct ExceptionHeader
}
/**
- * Look at the chain of inflight exceptions and pick the class type that'll
- * be looked for in catch clauses.
- */
- static ClassInfo getClassInfo(_Unwind_Exception* unwindHeader) @nogc
- {
- ExceptionHeader* eh = toExceptionHeader(unwindHeader);
- // The first thrown Exception at the top of the stack takes precedence
- // over others that are inflight, unless an Error was thrown, in which
- // case, we search for error handlers instead.
- Throwable ehobject = eh.object;
- for (ExceptionHeader* ehn = eh.next; ehn; ehn = ehn.next)
- {
- Error e = cast(Error)ehobject;
- if (e is null || (cast(Error)ehn.object) !is null)
- ehobject = ehn.object;
- }
- return ehobject.classinfo;
- }
-
- /**
* Convert from pointer to unwindHeader to pointer to ExceptionHeader
* that it is embedded inside of.
*/
@@ -510,7 +491,11 @@ extern(C) void _d_throw(Throwable object)
// things, almost certainly we will have crashed before now, rather than
// actually being able to diagnose the problem.
if (r == _URC_END_OF_STACK)
+ {
+ __gdc_begin_catch(&eh.unwindHeader);
+ _d_print_throwable(object);
terminate("uncaught exception", __LINE__);
+ }
terminate("unwind error", __LINE__);
}
@@ -661,7 +646,7 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti
{
// Otherwise we have a catch handler or exception specification.
handler = actionTableLookup(actions, unwindHeader, actionRecord,
- exceptionClass, TTypeBase,
+ lsda, exceptionClass, TTypeBase,
TType, TTypeEncoding,
saw_handler, saw_cleanup);
}
@@ -689,7 +674,8 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti
* Look up and return the handler index of the classType in Action Table.
*/
int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader,
- const(ubyte)* actionRecord, _Unwind_Exception_Class exceptionClass,
+ const(ubyte)* actionRecord, const(ubyte)* lsda,
+ _Unwind_Exception_Class exceptionClass,
_Unwind_Ptr TTypeBase, const(ubyte)* TType,
ubyte TTypeEncoding,
out bool saw_handler, out bool saw_cleanup)
@@ -697,7 +683,7 @@ int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader,
ClassInfo thrownType;
if (isGdcExceptionClass(exceptionClass))
{
- thrownType = ExceptionHeader.getClassInfo(unwindHeader);
+ thrownType = getClassInfo(unwindHeader, lsda);
}
while (1)
@@ -774,6 +760,41 @@ int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader,
}
/**
+ * Look at the chain of inflight exceptions and pick the class type that'll
+ * be looked for in catch clauses.
+ */
+ClassInfo getClassInfo(_Unwind_Exception* unwindHeader,
+ const(ubyte)* currentLsd) @nogc
+{
+ ExceptionHeader* eh = ExceptionHeader.toExceptionHeader(unwindHeader);
+ // The first thrown Exception at the top of the stack takes precedence
+ // over others that are inflight, unless an Error was thrown, in which
+ // case, we search for error handlers instead.
+ Throwable ehobject = eh.object;
+ for (ExceptionHeader* ehn = eh.next; ehn; ehn = ehn.next)
+ {
+ const(ubyte)* nextLsd = void;
+ _Unwind_Ptr nextLandingPad = void;
+ _Unwind_Word nextCfa = void;
+ int nextHandler = void;
+
+ ExceptionHeader.restore(&ehn.unwindHeader, nextHandler, nextLsd, nextLandingPad, nextCfa);
+
+ // Don't combine when the exceptions are from different functions.
+ if (currentLsd != nextLsd)
+ break;
+
+ Error e = cast(Error)ehobject;
+ if (e is null || (cast(Error)ehn.object) !is null)
+ {
+ currentLsd = nextLsd;
+ ehobject = ehn.object;
+ }
+ }
+ return ehobject.classinfo;
+}
+
+/**
* Called when the personality function has found neither a cleanup or handler.
* To support ARM EABI personality routines, that must also unwind the stack.
*/
@@ -929,16 +950,15 @@ private _Unwind_Reason_Code __gdc_personality(_Unwind_Action actions,
// current object onto the end of the prevous object.
ExceptionHeader* eh = ExceptionHeader.toExceptionHeader(unwindHeader);
auto currentLsd = lsda;
- auto currentCfa = cfa;
bool bypassed = false;
while (eh.next)
{
ExceptionHeader* ehn = eh.next;
- const(ubyte)* nextLsd;
- _Unwind_Ptr nextLandingPad;
- _Unwind_Word nextCfa;
- int nextHandler;
+ const(ubyte)* nextLsd = void;
+ _Unwind_Ptr nextLandingPad = void;
+ _Unwind_Word nextCfa = void;
+ int nextHandler = void;
ExceptionHeader.restore(&ehn.unwindHeader, nextHandler, nextLsd, nextLandingPad, nextCfa);
@@ -947,14 +967,13 @@ private _Unwind_Reason_Code __gdc_personality(_Unwind_Action actions,
{
// We found an Error, bypass the exception chain.
currentLsd = nextLsd;
- currentCfa = nextCfa;
eh = ehn;
bypassed = true;
continue;
}
// Don't combine when the exceptions are from different functions.
- if (currentLsd != nextLsd && currentCfa != nextCfa)
+ if (currentLsd != nextLsd)
break;
// Add our object onto the end of the existing chain.
diff --git a/libphobos/libdruntime/gcc/unwind/generic.d b/libphobos/libdruntime/gcc/unwind/generic.d
index 592b3af..68ddd1d 100644
--- a/libphobos/libdruntime/gcc/unwind/generic.d
+++ b/libphobos/libdruntime/gcc/unwind/generic.d
@@ -123,7 +123,27 @@ enum : _Unwind_Reason_Code
// @@@ The IA-64 ABI says that this structure must be double-word aligned.
// Taking that literally does not make much sense generically. Instead we
// provide the maximum alignment required by any type for the machine.
-struct _Unwind_Exception
+ version (ARM) private enum __aligned__ = 8;
+else version (AArch64) private enum __aligned__ = 16;
+else version (HPPA) private enum __aligned__ = 8;
+else version (HPPA64) private enum __aligned__ = 16;
+else version (MIPS_N32) private enum __aligned__ = 16;
+else version (MIPS_N64) private enum __aligned__ = 16;
+else version (MIPS32) private enum __aligned__ = 8;
+else version (MIPS64) private enum __aligned__ = 8;
+else version (PPC) private enum __aligned__ = 16;
+else version (PPC64) private enum __aligned__ = 16;
+else version (RISCV32) private enum __aligned__ = 16;
+else version (RISCV64) private enum __aligned__ = 16;
+else version (S390) private enum __aligned__ = 8;
+else version (SPARC) private enum __aligned__ = 8;
+else version (SPARC64) private enum __aligned__ = 16;
+else version (SystemZ) private enum __aligned__ = 8;
+else version (X86) private enum __aligned__ = 16;
+else version (X86_64) private enum __aligned__ = 16;
+else static assert( false, "Platform not supported.");
+
+align(__aligned__) struct _Unwind_Exception
{
_Unwind_Exception_Class exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog
index bf7c4b4..e7a15fa 100644
--- a/libsanitizer/ChangeLog
+++ b/libsanitizer/ChangeLog
@@ -1,3 +1,11 @@
+2021-10-06 H.J. Lu <hjl.tools@gmail.com>
+
+ * LOCAL_PATCHES: Update to the corresponding revision.
+
+2021-10-01 H.J. Lu <hjl.tools@gmail.com>
+
+ * LOCAL_PATCHES: Update to the corresponding revision.
+
2021-08-11 Jakub Jelinek <jakub@redhat.com>
* sanitizer_common/sanitizer_common_interceptors.inc: Cherry-pick
diff --git a/libsanitizer/LOCAL_PATCHES b/libsanitizer/LOCAL_PATCHES
index d456553..2f1b4f8 100644
--- a/libsanitizer/LOCAL_PATCHES
+++ b/libsanitizer/LOCAL_PATCHES
@@ -1 +1 @@
-763479487980eefd1450c0c1cdeea651d70f2fdb
+bb8adf080ef03288bccd9f1316ae2a1122ebcd85
diff --git a/libsanitizer/MERGE b/libsanitizer/MERGE
index 81d00f2..5ea083a 100644
--- a/libsanitizer/MERGE
+++ b/libsanitizer/MERGE
@@ -1,4 +1,4 @@
-7704fedfff6ef5676adb6415f3be0ac927d1a746
+fdf4c035225de52f596899931b1f6100e5e3e928
The first line of this file holds the git revision number of the
last merge done from the master library sources.
diff --git a/libsanitizer/asan/asan_allocator.cpp b/libsanitizer/asan/asan_allocator.cpp
index 414fba3..268feac 100644
--- a/libsanitizer/asan/asan_allocator.cpp
+++ b/libsanitizer/asan/asan_allocator.cpp
@@ -908,13 +908,6 @@ AllocType AsanChunkView::GetAllocType() const {
return (AllocType)chunk_->alloc_type;
}
-static StackTrace GetStackTraceFromId(u32 id) {
- CHECK(id);
- StackTrace res = StackDepotGet(id);
- CHECK(res.trace);
- return res;
-}
-
u32 AsanChunkView::GetAllocStackId() const {
u32 tid = 0;
u32 stack = 0;
@@ -931,14 +924,6 @@ u32 AsanChunkView::GetFreeStackId() const {
return stack;
}
-StackTrace AsanChunkView::GetAllocStack() const {
- return GetStackTraceFromId(GetAllocStackId());
-}
-
-StackTrace AsanChunkView::GetFreeStack() const {
- return GetStackTraceFromId(GetFreeStackId());
-}
-
void InitializeAllocator(const AllocatorOptions &options) {
instance.InitLinkerInitialized(options);
}
diff --git a/libsanitizer/asan/asan_allocator.h b/libsanitizer/asan/asan_allocator.h
index 2963e97..27d826f 100644
--- a/libsanitizer/asan/asan_allocator.h
+++ b/libsanitizer/asan/asan_allocator.h
@@ -64,8 +64,6 @@ class AsanChunkView {
bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; }
u32 GetAllocStackId() const;
u32 GetFreeStackId() const;
- StackTrace GetAllocStack() const;
- StackTrace GetFreeStack() const;
AllocType GetAllocType() const;
bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) const {
if (addr >= Beg() && (addr + access_size) <= End()) {
diff --git a/libsanitizer/asan/asan_debugging.cpp b/libsanitizer/asan/asan_debugging.cpp
index c01360b..0b4bf52 100644
--- a/libsanitizer/asan/asan_debugging.cpp
+++ b/libsanitizer/asan/asan_debugging.cpp
@@ -19,6 +19,7 @@
#include "asan_mapping.h"
#include "asan_report.h"
#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
namespace {
using namespace __asan;
@@ -54,11 +55,11 @@ uptr AsanGetStack(uptr addr, uptr *trace, u32 size, u32 *thread_id,
StackTrace stack(nullptr, 0);
if (alloc_stack) {
if (chunk.AllocTid() == kInvalidTid) return 0;
- stack = chunk.GetAllocStack();
+ stack = StackDepotGet(chunk.GetAllocStackId());
if (thread_id) *thread_id = chunk.AllocTid();
} else {
if (chunk.FreeTid() == kInvalidTid) return 0;
- stack = chunk.GetFreeStack();
+ stack = StackDepotGet(chunk.GetFreeStackId());
if (thread_id) *thread_id = chunk.FreeTid();
}
diff --git a/libsanitizer/asan/asan_fuchsia.cpp b/libsanitizer/asan/asan_fuchsia.cpp
index b0c7255..b419019 100644
--- a/libsanitizer/asan/asan_fuchsia.cpp
+++ b/libsanitizer/asan/asan_fuchsia.cpp
@@ -31,7 +31,8 @@ namespace __asan {
// AsanInitInternal->InitializeHighMemEnd (asan_rtl.cpp).
// Just do some additional sanity checks here.
void InitializeShadowMemory() {
- if (Verbosity()) PrintAddressSpaceLayout();
+ if (Verbosity())
+ PrintAddressSpaceLayout();
// Make sure SHADOW_OFFSET doesn't use __asan_shadow_memory_dynamic_address.
__asan_shadow_memory_dynamic_address = kDefaultShadowSentinel;
@@ -62,7 +63,34 @@ void AsanOnDeadlySignal(int signo, void *siginfo, void *context) {
UNIMPLEMENTED();
}
-bool PlatformUnpoisonStacks() { return false; }
+bool PlatformUnpoisonStacks() {
+ // The current sp might not point to the default stack. This
+ // could be because we are in a crash stack from fuzzing for example.
+ // Unpoison the default stack and the current stack page.
+ AsanThread *curr_thread = GetCurrentThread();
+ CHECK(curr_thread != nullptr);
+ uptr top = curr_thread->stack_top();
+ uptr bottom = curr_thread->stack_bottom();
+ // The default stack grows from top to bottom. (bottom < top).
+
+ uptr local_stack = reinterpret_cast<uptr>(__builtin_frame_address(0));
+ if (local_stack >= bottom && local_stack <= top) {
+ // The current stack is the default stack.
+ // We only need to unpoison from where we are using until the end.
+ bottom = RoundDownTo(local_stack, GetPageSize());
+ UnpoisonStack(bottom, top, "default");
+ } else {
+ // The current stack is not the default stack.
+ // Unpoison the entire default stack and the current stack page.
+ UnpoisonStack(bottom, top, "default");
+ bottom = RoundDownTo(local_stack, GetPageSize());
+ top = bottom + GetPageSize();
+ UnpoisonStack(bottom, top, "unknown");
+ return true;
+ }
+
+ return false;
+}
// We can use a plain thread_local variable for TSD.
static thread_local void *per_thread;
@@ -148,7 +176,8 @@ static void *BeforeThreadCreateHook(uptr user_id, bool detached,
uptr stack_size) {
EnsureMainThreadIDIsCorrect();
// Strict init-order checking is thread-hostile.
- if (flags()->strict_init_order) StopInitOrderChecking();
+ if (flags()->strict_init_order)
+ StopInitOrderChecking();
GET_STACK_TRACE_THREAD;
u32 parent_tid = GetCurrentTidOrInvalid();
diff --git a/libsanitizer/asan/asan_globals.cpp b/libsanitizer/asan/asan_globals.cpp
index e045c31..763d3c6 100644
--- a/libsanitizer/asan/asan_globals.cpp
+++ b/libsanitizer/asan/asan_globals.cpp
@@ -35,7 +35,7 @@ struct ListOfGlobals {
ListOfGlobals *next;
};
-static BlockingMutex mu_for_globals(LINKER_INITIALIZED);
+static Mutex mu_for_globals;
static LowLevelAllocator allocator_for_globals;
static ListOfGlobals *list_of_all_globals;
@@ -108,7 +108,7 @@ static u32 FindRegistrationSite(const Global *g) {
int GetGlobalsForAddress(uptr addr, Global *globals, u32 *reg_sites,
int max_globals) {
if (!flags()->report_globals) return 0;
- BlockingMutexLock lock(&mu_for_globals);
+ Lock lock(&mu_for_globals);
int res = 0;
for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
const Global &g = *l->g;
@@ -238,7 +238,7 @@ static void UnregisterGlobal(const Global *g) {
}
void StopInitOrderChecking() {
- BlockingMutexLock lock(&mu_for_globals);
+ Lock lock(&mu_for_globals);
if (!flags()->check_initialization_order || !dynamic_init_globals)
return;
flags()->check_initialization_order = false;
@@ -340,7 +340,7 @@ void __asan_register_globals(__asan_global *globals, uptr n) {
if (!flags()->report_globals) return;
GET_STACK_TRACE_MALLOC;
u32 stack_id = StackDepotPut(stack);
- BlockingMutexLock lock(&mu_for_globals);
+ Lock lock(&mu_for_globals);
if (!global_registration_site_vector) {
global_registration_site_vector =
new (allocator_for_globals) GlobalRegistrationSiteVector;
@@ -379,7 +379,7 @@ void __asan_register_globals(__asan_global *globals, uptr n) {
// We must do this when a shared objects gets dlclosed.
void __asan_unregister_globals(__asan_global *globals, uptr n) {
if (!flags()->report_globals) return;
- BlockingMutexLock lock(&mu_for_globals);
+ Lock lock(&mu_for_globals);
for (uptr i = 0; i < n; i++) {
if (SANITIZER_WINDOWS && globals[i].beg == 0) {
// Skip globals that look like padding from the MSVC incremental linker.
@@ -405,7 +405,7 @@ void __asan_before_dynamic_init(const char *module_name) {
bool strict_init_order = flags()->strict_init_order;
CHECK(module_name);
CHECK(asan_inited);
- BlockingMutexLock lock(&mu_for_globals);
+ Lock lock(&mu_for_globals);
if (flags()->report_globals >= 3)
Printf("DynInitPoison module: %s\n", module_name);
for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
@@ -429,7 +429,7 @@ void __asan_after_dynamic_init() {
!dynamic_init_globals)
return;
CHECK(asan_inited);
- BlockingMutexLock lock(&mu_for_globals);
+ Lock lock(&mu_for_globals);
// FIXME: Optionally report that we're unpoisoning globals from a module.
for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
diff --git a/libsanitizer/asan/asan_interceptors.cpp b/libsanitizer/asan/asan_interceptors.cpp
index d0a6dd4..b289091 100644
--- a/libsanitizer/asan/asan_interceptors.cpp
+++ b/libsanitizer/asan/asan_interceptors.cpp
@@ -49,8 +49,8 @@ namespace __asan {
ASAN_READ_RANGE((ctx), (s), \
common_flags()->strict_string_checks ? (len) + 1 : (n))
-#define ASAN_READ_STRING(ctx, s, n) \
- ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
+# define ASAN_READ_STRING(ctx, s, n) \
+ ASAN_READ_STRING_OF_LEN((ctx), (s), internal_strlen(s), (n))
static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
#if SANITIZER_INTERCEPT_STRNLEN
@@ -370,9 +370,9 @@ DEFINE_REAL(char*, index, const char *string, int c)
ASAN_INTERCEPTOR_ENTER(ctx, strcat);
ENSURE_ASAN_INITED();
if (flags()->replace_str) {
- uptr from_length = REAL(strlen)(from);
+ uptr from_length = internal_strlen(from);
ASAN_READ_RANGE(ctx, from, from_length + 1);
- uptr to_length = REAL(strlen)(to);
+ uptr to_length = internal_strlen(to);
ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
// If the copying actually happens, the |from| string should not overlap
@@ -394,7 +394,7 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
uptr from_length = MaybeRealStrnlen(from, size);
uptr copy_length = Min(size, from_length + 1);
ASAN_READ_RANGE(ctx, from, copy_length);
- uptr to_length = REAL(strlen)(to);
+ uptr to_length = internal_strlen(to);
ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
if (from_length > 0) {
@@ -419,7 +419,7 @@ INTERCEPTOR(char *, strcpy, char *to, const char *from) {
}
ENSURE_ASAN_INITED();
if (flags()->replace_str) {
- uptr from_size = REAL(strlen)(from) + 1;
+ uptr from_size = internal_strlen(from) + 1;
CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
ASAN_READ_RANGE(ctx, from, from_size);
ASAN_WRITE_RANGE(ctx, to, from_size);
@@ -432,7 +432,7 @@ INTERCEPTOR(char*, strdup, const char *s) {
ASAN_INTERCEPTOR_ENTER(ctx, strdup);
if (UNLIKELY(!asan_inited)) return internal_strdup(s);
ENSURE_ASAN_INITED();
- uptr length = REAL(strlen)(s);
+ uptr length = internal_strlen(s);
if (flags()->replace_str) {
ASAN_READ_RANGE(ctx, s, length + 1);
}
@@ -448,7 +448,7 @@ INTERCEPTOR(char*, __strdup, const char *s) {
ASAN_INTERCEPTOR_ENTER(ctx, strdup);
if (UNLIKELY(!asan_inited)) return internal_strdup(s);
ENSURE_ASAN_INITED();
- uptr length = REAL(strlen)(s);
+ uptr length = internal_strlen(s);
if (flags()->replace_str) {
ASAN_READ_RANGE(ctx, s, length + 1);
}
@@ -581,7 +581,7 @@ INTERCEPTOR(int, atexit, void (*func)()) {
#if CAN_SANITIZE_LEAKS
__lsan::ScopedInterceptorDisabler disabler;
#endif
- // Avoid calling real atexit as it is unrechable on at least on Linux.
+ // Avoid calling real atexit as it is unreachable on at least on Linux.
int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr);
REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
return res;
diff --git a/libsanitizer/asan/asan_interceptors.h b/libsanitizer/asan/asan_interceptors.h
index 25e05e4..105c672 100644
--- a/libsanitizer/asan/asan_interceptors.h
+++ b/libsanitizer/asan/asan_interceptors.h
@@ -138,29 +138,30 @@ DECLARE_REAL(char*, strncpy, char *to, const char *from, uptr size)
DECLARE_REAL(uptr, strnlen, const char *s, uptr maxlen)
DECLARE_REAL(char*, strstr, const char *s1, const char *s2)
-#if !SANITIZER_MAC
-#define ASAN_INTERCEPT_FUNC(name) \
- do { \
- if (!INTERCEPT_FUNCTION(name)) \
- VReport(1, "AddressSanitizer: failed to intercept '%s'\n", #name); \
- } while (0)
-#define ASAN_INTERCEPT_FUNC_VER(name, ver) \
- do { \
- if (!INTERCEPT_FUNCTION_VER(name, ver)) \
- VReport(1, "AddressSanitizer: failed to intercept '%s@@%s'\n", #name, \
- #ver); \
- } while (0)
-#define ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \
- do { \
- if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \
- VReport(1, "AddressSanitizer: failed to intercept '%s@@%s' or '%s'\n", \
- #name, #ver, #name); \
- } while (0)
-
-#else
+# if !SANITIZER_MAC
+# define ASAN_INTERCEPT_FUNC(name) \
+ do { \
+ if (!INTERCEPT_FUNCTION(name)) \
+ VReport(1, "AddressSanitizer: failed to intercept '%s'\n", #name); \
+ } while (0)
+# define ASAN_INTERCEPT_FUNC_VER(name, ver) \
+ do { \
+ if (!INTERCEPT_FUNCTION_VER(name, ver)) \
+ VReport(1, "AddressSanitizer: failed to intercept '%s@@%s'\n", \
+ #name, ver); \
+ } while (0)
+# define ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \
+ do { \
+ if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \
+ VReport(1, \
+ "AddressSanitizer: failed to intercept '%s@@%s' or '%s'\n", \
+ #name, ver, #name); \
+ } while (0)
+
+# else
// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
-#define ASAN_INTERCEPT_FUNC(name)
-#endif // SANITIZER_MAC
+# define ASAN_INTERCEPT_FUNC(name)
+# endif // SANITIZER_MAC
#endif // !SANITIZER_FUCHSIA
diff --git a/libsanitizer/asan/asan_report.cpp b/libsanitizer/asan/asan_report.cpp
index 03f1ed2..271d896 100644
--- a/libsanitizer/asan/asan_report.cpp
+++ b/libsanitizer/asan/asan_report.cpp
@@ -32,12 +32,12 @@ namespace __asan {
static void (*error_report_callback)(const char*);
static char *error_message_buffer = nullptr;
static uptr error_message_buffer_pos = 0;
-static BlockingMutex error_message_buf_mutex(LINKER_INITIALIZED);
+static Mutex error_message_buf_mutex;
static const unsigned kAsanBuggyPcPoolSize = 25;
static __sanitizer::atomic_uintptr_t AsanBuggyPcPool[kAsanBuggyPcPoolSize];
void AppendToErrorMessageBuffer(const char *buffer) {
- BlockingMutexLock l(&error_message_buf_mutex);
+ Lock l(&error_message_buf_mutex);
if (!error_message_buffer) {
error_message_buffer =
(char*)MmapOrDieQuietly(kErrorMessageBufferSize, __func__);
@@ -155,10 +155,10 @@ class ScopedInErrorReport {
DumpProcessMap();
// Copy the message buffer so that we could start logging without holding a
- // lock that gets aquired during printing.
+ // lock that gets acquired during printing.
InternalMmapVector<char> buffer_copy(kErrorMessageBufferSize);
{
- BlockingMutexLock l(&error_message_buf_mutex);
+ Lock l(&error_message_buf_mutex);
internal_memcpy(buffer_copy.data(),
error_message_buffer, kErrorMessageBufferSize);
// Clear error_message_buffer so that if we find other errors
@@ -490,7 +490,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
}
void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
- BlockingMutexLock l(&error_message_buf_mutex);
+ Lock l(&error_message_buf_mutex);
error_report_callback = callback;
}
diff --git a/libsanitizer/asan/asan_rtl.cpp b/libsanitizer/asan/asan_rtl.cpp
index e06a111..bfaa3bc 100644
--- a/libsanitizer/asan/asan_rtl.cpp
+++ b/libsanitizer/asan/asan_rtl.cpp
@@ -82,6 +82,17 @@ void ShowStatsAndAbort() {
Die();
}
+NOINLINE
+static void ReportGenericErrorWrapper(uptr addr, bool is_write, int size,
+ int exp_arg, bool fatal) {
+ if (__asan_test_only_reported_buggy_pointer) {
+ *__asan_test_only_reported_buggy_pointer = addr;
+ } else {
+ GET_CALLER_PC_BP_SP;
+ ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, fatal);
+ }
+}
+
// --------------- LowLevelAllocateCallbac ---------- {{{1
static void OnLowLevelAllocate(uptr ptr, uptr size) {
PoisonShadow(ptr, size, kAsanInternalHeapMagic);
@@ -145,12 +156,7 @@ ASAN_REPORT_ERROR_N(store, true)
if (UNLIKELY(size >= SHADOW_GRANULARITY || \
((s8)((addr & (SHADOW_GRANULARITY - 1)) + size - 1)) >= \
(s8)s)) { \
- if (__asan_test_only_reported_buggy_pointer) { \
- *__asan_test_only_reported_buggy_pointer = addr; \
- } else { \
- GET_CALLER_PC_BP_SP; \
- ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, fatal); \
- } \
+ ReportGenericErrorWrapper(addr, is_write, size, exp_arg, fatal); \
} \
}
diff --git a/libsanitizer/asan/asan_stats.cpp b/libsanitizer/asan/asan_stats.cpp
index 00ded8f..9a715ea 100644
--- a/libsanitizer/asan/asan_stats.cpp
+++ b/libsanitizer/asan/asan_stats.cpp
@@ -62,11 +62,11 @@ void AsanStats::MergeFrom(const AsanStats *stats) {
dst_ptr[i] += src_ptr[i];
}
-static BlockingMutex print_lock(LINKER_INITIALIZED);
+static Mutex print_lock;
static AsanStats unknown_thread_stats(LINKER_INITIALIZED);
static AsanStats dead_threads_stats(LINKER_INITIALIZED);
-static BlockingMutex dead_threads_stats_lock(LINKER_INITIALIZED);
+static Mutex dead_threads_stats_lock;
// Required for malloc_zone_statistics() on OS X. This can't be stored in
// per-thread AsanStats.
static uptr max_malloced_memory;
@@ -87,7 +87,7 @@ static void GetAccumulatedStats(AsanStats *stats) {
}
stats->MergeFrom(&unknown_thread_stats);
{
- BlockingMutexLock lock(&dead_threads_stats_lock);
+ Lock lock(&dead_threads_stats_lock);
stats->MergeFrom(&dead_threads_stats);
}
// This is not very accurate: we may miss allocation peaks that happen
@@ -99,7 +99,7 @@ static void GetAccumulatedStats(AsanStats *stats) {
}
void FlushToDeadThreadStats(AsanStats *stats) {
- BlockingMutexLock lock(&dead_threads_stats_lock);
+ Lock lock(&dead_threads_stats_lock);
dead_threads_stats.MergeFrom(stats);
stats->Clear();
}
@@ -122,11 +122,11 @@ static void PrintAccumulatedStats() {
AsanStats stats;
GetAccumulatedStats(&stats);
// Use lock to keep reports from mixing up.
- BlockingMutexLock lock(&print_lock);
+ Lock lock(&print_lock);
stats.Print();
- StackDepotStats *stack_depot_stats = StackDepotGetStats();
+ StackDepotStats stack_depot_stats = StackDepotGetStats();
Printf("Stats: StackDepot: %zd ids; %zdM allocated\n",
- stack_depot_stats->n_uniq_ids, stack_depot_stats->allocated >> 20);
+ stack_depot_stats.n_uniq_ids, stack_depot_stats.allocated >> 20);
PrintInternalAllocatorStats();
}
diff --git a/libsanitizer/asan/asan_thread.cpp b/libsanitizer/asan/asan_thread.cpp
index 35d4467..d25e8ee 100644
--- a/libsanitizer/asan/asan_thread.cpp
+++ b/libsanitizer/asan/asan_thread.cpp
@@ -43,11 +43,11 @@ void AsanThreadContext::OnFinished() {
static ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)];
static ThreadRegistry *asan_thread_registry;
-static BlockingMutex mu_for_thread_context(LINKER_INITIALIZED);
+static Mutex mu_for_thread_context;
static LowLevelAllocator allocator_for_thread_context;
static ThreadContextBase *GetAsanThreadContext(u32 tid) {
- BlockingMutexLock lock(&mu_for_thread_context);
+ Lock lock(&mu_for_thread_context);
return new(allocator_for_thread_context) AsanThreadContext(tid);
}
diff --git a/libsanitizer/asan/libtool-version b/libsanitizer/asan/libtool-version
index 2cd4546..7a2a23f 100644
--- a/libsanitizer/asan/libtool-version
+++ b/libsanitizer/asan/libtool-version
@@ -3,4 +3,4 @@
# a separate file so that version updates don't involve re-running
# automake.
# CURRENT:REVISION:AGE
-7:0:0
+8:0:0
diff --git a/libsanitizer/hwasan/Makefile.am b/libsanitizer/hwasan/Makefile.am
index 5e3a0f1..cfc1bfe 100644
--- a/libsanitizer/hwasan/Makefile.am
+++ b/libsanitizer/hwasan/Makefile.am
@@ -28,7 +28,8 @@ hwasan_files = \
hwasan_new_delete.cpp \
hwasan_poisoning.cpp \
hwasan_report.cpp \
- hwasan_setjmp.S \
+ hwasan_setjmp_aarch64.S \
+ hwasan_setjmp_x86_64.S \
hwasan_tag_mismatch_aarch64.S \
hwasan_thread.cpp \
hwasan_thread_list.cpp \
diff --git a/libsanitizer/hwasan/Makefile.in b/libsanitizer/hwasan/Makefile.in
index 22c5266..f63670b 100644
--- a/libsanitizer/hwasan/Makefile.in
+++ b/libsanitizer/hwasan/Makefile.in
@@ -151,9 +151,9 @@ am__objects_1 = hwasan_allocation_functions.lo hwasan_allocator.lo \
hwasan_fuchsia.lo hwasan_globals.lo hwasan_interceptors.lo \
hwasan_interceptors_vfork.lo hwasan_linux.lo \
hwasan_memintrinsics.lo hwasan_new_delete.lo \
- hwasan_poisoning.lo hwasan_report.lo hwasan_setjmp.lo \
- hwasan_tag_mismatch_aarch64.lo hwasan_thread.lo \
- hwasan_thread_list.lo hwasan_type_test.lo
+ hwasan_poisoning.lo hwasan_report.lo hwasan_setjmp_aarch64.lo \
+ hwasan_setjmp_x86_64.lo hwasan_tag_mismatch_aarch64.lo \
+ hwasan_thread.lo hwasan_thread_list.lo hwasan_type_test.lo
am_libhwasan_la_OBJECTS = $(am__objects_1)
libhwasan_la_OBJECTS = $(am_libhwasan_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
@@ -427,7 +427,8 @@ hwasan_files = \
hwasan_new_delete.cpp \
hwasan_poisoning.cpp \
hwasan_report.cpp \
- hwasan_setjmp.S \
+ hwasan_setjmp_aarch64.S \
+ hwasan_setjmp_x86_64.S \
hwasan_tag_mismatch_aarch64.S \
hwasan_thread.cpp \
hwasan_thread_list.cpp \
@@ -570,7 +571,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hwasan_new_delete.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hwasan_poisoning.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hwasan_report.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hwasan_setjmp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hwasan_setjmp_aarch64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hwasan_setjmp_x86_64.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hwasan_tag_mismatch_aarch64.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hwasan_thread.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hwasan_thread_list.Plo@am__quote@
diff --git a/libsanitizer/hwasan/hwasan.cpp b/libsanitizer/hwasan/hwasan.cpp
index cbe0dee..e8ffbbd 100644
--- a/libsanitizer/hwasan/hwasan.cpp
+++ b/libsanitizer/hwasan/hwasan.cpp
@@ -141,7 +141,7 @@ static void CheckUnwind() {
static void HwasanFormatMemoryUsage(InternalScopedString &s) {
HwasanThreadList &thread_list = hwasanThreadList();
auto thread_stats = thread_list.GetThreadStats();
- auto *sds = StackDepotGetStats();
+ auto sds = StackDepotGetStats();
AllocatorStatCounters asc;
GetAllocatorStats(asc);
s.append(
@@ -151,7 +151,7 @@ static void HwasanFormatMemoryUsage(InternalScopedString &s) {
internal_getpid(), GetRSS(), thread_stats.n_live_threads,
thread_stats.total_stack_size,
thread_stats.n_live_threads * thread_list.MemoryUsedPerThread(),
- sds->allocated, sds->n_uniq_ids, asc[AllocatorStatMapped]);
+ sds.allocated, sds.n_uniq_ids, asc[AllocatorStatMapped]);
}
#if SANITIZER_ANDROID
@@ -319,7 +319,7 @@ void __hwasan_init_static() {
InitializeSingleGlobal(global);
}
-void __hwasan_init() {
+__attribute__((constructor(0))) void __hwasan_init() {
CHECK(!hwasan_init_is_running);
if (hwasan_inited) return;
hwasan_init_is_running = 1;
@@ -360,6 +360,7 @@ void __hwasan_init() {
HwasanTSDThreadInit();
HwasanAllocatorInit();
+ HwasanInstallAtForkHandler();
#if HWASAN_CONTAINS_UBSAN
__ubsan::InitAsPlugin();
diff --git a/libsanitizer/hwasan/hwasan.h b/libsanitizer/hwasan/hwasan.h
index 7338b69..371c43f3 100644
--- a/libsanitizer/hwasan/hwasan.h
+++ b/libsanitizer/hwasan/hwasan.h
@@ -107,6 +107,8 @@ void InitThreads();
void InitializeInterceptors();
void HwasanAllocatorInit();
+void HwasanAllocatorLock();
+void HwasanAllocatorUnlock();
void *hwasan_malloc(uptr size, StackTrace *stack);
void *hwasan_calloc(uptr nmemb, uptr size, StackTrace *stack);
@@ -140,6 +142,8 @@ void HwasanAtExit();
void HwasanOnDeadlySignal(int signo, void *info, void *context);
+void HwasanInstallAtForkHandler();
+
void UpdateMemoryUsage();
void AppendToErrorMessageBuffer(const char *buffer);
@@ -183,25 +187,34 @@ void HwasanTagMismatch(uptr addr, uptr access_info, uptr *registers_frame,
RunFreeHooks(ptr); \
} while (false)
-#if HWASAN_WITH_INTERCEPTORS && defined(__aarch64__)
+#if HWASAN_WITH_INTERCEPTORS
// For both bionic and glibc __sigset_t is an unsigned long.
typedef unsigned long __hw_sigset_t;
// Setjmp and longjmp implementations are platform specific, and hence the
-// interception code is platform specific too. As yet we've only implemented
-// the interception for AArch64.
-typedef unsigned long long __hw_register_buf[22];
+// interception code is platform specific too.
+# if defined(__aarch64__)
+constexpr size_t kHwRegisterBufSize = 22;
+# elif defined(__x86_64__)
+constexpr size_t kHwRegisterBufSize = 8;
+# endif
+typedef unsigned long long __hw_register_buf[kHwRegisterBufSize];
struct __hw_jmp_buf_struct {
// NOTE: The machine-dependent definition of `__sigsetjmp'
// assume that a `__hw_jmp_buf' begins with a `__hw_register_buf' and that
// `__mask_was_saved' follows it. Do not move these members or add others
// before it.
+ //
+ // We add a __magic field to our struct to catch cases where libc's setjmp
+ // populated the jmp_buf instead of our interceptor.
__hw_register_buf __jmpbuf; // Calling environment.
- int __mask_was_saved; // Saved the signal mask?
+ unsigned __mask_was_saved : 1; // Saved the signal mask?
+ unsigned __magic : 31; // Used to distinguish __hw_jmp_buf from jmp_buf.
__hw_sigset_t __saved_mask; // Saved signal mask.
};
typedef struct __hw_jmp_buf_struct __hw_jmp_buf[1];
typedef struct __hw_jmp_buf_struct __hw_sigjmp_buf[1];
-#endif // HWASAN_WITH_INTERCEPTORS && __aarch64__
+constexpr unsigned kHwJmpBufMagic = 0x248ACE77;
+#endif // HWASAN_WITH_INTERCEPTORS
#define ENSURE_HWASAN_INITED() \
do { \
diff --git a/libsanitizer/hwasan/hwasan_allocation_functions.cpp b/libsanitizer/hwasan/hwasan_allocation_functions.cpp
index 6c2a607..850daed 100644
--- a/libsanitizer/hwasan/hwasan_allocation_functions.cpp
+++ b/libsanitizer/hwasan/hwasan_allocation_functions.cpp
@@ -17,6 +17,8 @@
#include "sanitizer_common/sanitizer_allocator_interface.h"
#include "sanitizer_common/sanitizer_tls_get_addr.h"
+#if !SANITIZER_FUCHSIA
+
using namespace __hwasan;
static uptr allocated_for_dlsym;
@@ -36,6 +38,9 @@ static void *AllocateFromLocalPool(uptr size_in_bytes) {
return mem;
}
+extern "C" {
+
+SANITIZER_INTERFACE_ATTRIBUTE
int __sanitizer_posix_memalign(void **memptr, uptr alignment, uptr size) {
GET_MALLOC_STACK_TRACE;
CHECK_NE(memptr, 0);
@@ -43,16 +48,19 @@ int __sanitizer_posix_memalign(void **memptr, uptr alignment, uptr size) {
return res;
}
+SANITIZER_INTERFACE_ATTRIBUTE
void *__sanitizer_memalign(uptr alignment, uptr size) {
GET_MALLOC_STACK_TRACE;
return hwasan_memalign(alignment, size, &stack);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void *__sanitizer_aligned_alloc(uptr alignment, uptr size) {
GET_MALLOC_STACK_TRACE;
return hwasan_aligned_alloc(alignment, size, &stack);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void *__sanitizer___libc_memalign(uptr alignment, uptr size) {
GET_MALLOC_STACK_TRACE;
void *ptr = hwasan_memalign(alignment, size, &stack);
@@ -61,16 +69,19 @@ void *__sanitizer___libc_memalign(uptr alignment, uptr size) {
return ptr;
}
+SANITIZER_INTERFACE_ATTRIBUTE
void *__sanitizer_valloc(uptr size) {
GET_MALLOC_STACK_TRACE;
return hwasan_valloc(size, &stack);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void *__sanitizer_pvalloc(uptr size) {
GET_MALLOC_STACK_TRACE;
return hwasan_pvalloc(size, &stack);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void __sanitizer_free(void *ptr) {
GET_MALLOC_STACK_TRACE;
if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr)))
@@ -78,6 +89,7 @@ void __sanitizer_free(void *ptr) {
hwasan_free(ptr, &stack);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void __sanitizer_cfree(void *ptr) {
GET_MALLOC_STACK_TRACE;
if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr)))
@@ -85,22 +97,27 @@ void __sanitizer_cfree(void *ptr) {
hwasan_free(ptr, &stack);
}
+SANITIZER_INTERFACE_ATTRIBUTE
uptr __sanitizer_malloc_usable_size(const void *ptr) {
return __sanitizer_get_allocated_size(ptr);
}
+SANITIZER_INTERFACE_ATTRIBUTE
struct __sanitizer_struct_mallinfo __sanitizer_mallinfo() {
__sanitizer_struct_mallinfo sret;
internal_memset(&sret, 0, sizeof(sret));
return sret;
}
+SANITIZER_INTERFACE_ATTRIBUTE
int __sanitizer_mallopt(int cmd, int value) { return 0; }
+SANITIZER_INTERFACE_ATTRIBUTE
void __sanitizer_malloc_stats(void) {
// FIXME: implement, but don't call REAL(malloc_stats)!
}
+SANITIZER_INTERFACE_ATTRIBUTE
void *__sanitizer_calloc(uptr nmemb, uptr size) {
GET_MALLOC_STACK_TRACE;
if (UNLIKELY(!hwasan_inited))
@@ -109,6 +126,7 @@ void *__sanitizer_calloc(uptr nmemb, uptr size) {
return hwasan_calloc(nmemb, size, &stack);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void *__sanitizer_realloc(void *ptr, uptr size) {
GET_MALLOC_STACK_TRACE;
if (UNLIKELY(IsInDlsymAllocPool(ptr))) {
@@ -127,11 +145,13 @@ void *__sanitizer_realloc(void *ptr, uptr size) {
return hwasan_realloc(ptr, size, &stack);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void *__sanitizer_reallocarray(void *ptr, uptr nmemb, uptr size) {
GET_MALLOC_STACK_TRACE;
return hwasan_reallocarray(ptr, nmemb, size, &stack);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void *__sanitizer_malloc(uptr size) {
GET_MALLOC_STACK_TRACE;
if (UNLIKELY(!hwasan_init_is_running))
@@ -142,6 +162,8 @@ void *__sanitizer_malloc(uptr size) {
return hwasan_malloc(size, &stack);
}
+} // extern "C"
+
#if HWASAN_WITH_INTERCEPTORS
# define INTERCEPTOR_ALIAS(RET, FN, ARGS...) \
extern "C" SANITIZER_INTERFACE_ATTRIBUTE RET WRAP(FN)(ARGS) \
@@ -170,3 +192,5 @@ INTERCEPTOR_ALIAS(int, mallopt, int cmd, int value);
INTERCEPTOR_ALIAS(void, malloc_stats, void);
# endif
#endif // #if HWASAN_WITH_INTERCEPTORS
+
+#endif // SANITIZER_FUCHSIA
diff --git a/libsanitizer/hwasan/hwasan_allocator.cpp b/libsanitizer/hwasan/hwasan_allocator.cpp
index ef6d4d6..9e17299 100644
--- a/libsanitizer/hwasan/hwasan_allocator.cpp
+++ b/libsanitizer/hwasan/hwasan_allocator.cpp
@@ -107,6 +107,10 @@ void HwasanAllocatorInit() {
tail_magic[i] = GetCurrentThread()->GenerateRandomTag();
}
+void HwasanAllocatorLock() { allocator.ForceLock(); }
+
+void HwasanAllocatorUnlock() { allocator.ForceUnlock(); }
+
void AllocatorSwallowThreadLocalCache(AllocatorCache *cache) {
allocator.SwallowCache(cache);
}
@@ -158,8 +162,11 @@ static void *HwasanAllocate(StackTrace *stack, uptr orig_size, uptr alignment,
internal_memset(allocated, flags()->malloc_fill_byte, fill_size);
}
if (size != orig_size) {
- internal_memcpy(reinterpret_cast<u8 *>(allocated) + orig_size, tail_magic,
- size - orig_size - 1);
+ u8 *tail = reinterpret_cast<u8 *>(allocated) + orig_size;
+ uptr tail_length = size - orig_size;
+ internal_memcpy(tail, tail_magic, tail_length - 1);
+ // Short granule is excluded from magic tail, so we explicitly untag.
+ tail[tail_length - 1] = 0;
}
void *user_ptr = allocated;
@@ -201,21 +208,37 @@ static bool PointerAndMemoryTagsMatch(void *tagged_ptr) {
return PossiblyShortTagMatches(mem_tag, tagged_uptr, 1);
}
+static bool CheckInvalidFree(StackTrace *stack, void *untagged_ptr,
+ void *tagged_ptr) {
+ // This function can return true if halt_on_error is false.
+ if (!MemIsApp(reinterpret_cast<uptr>(untagged_ptr)) ||
+ !PointerAndMemoryTagsMatch(tagged_ptr)) {
+ ReportInvalidFree(stack, reinterpret_cast<uptr>(tagged_ptr));
+ return true;
+ }
+ return false;
+}
+
static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) {
CHECK(tagged_ptr);
HWASAN_FREE_HOOK(tagged_ptr);
- if (!PointerAndMemoryTagsMatch(tagged_ptr))
- ReportInvalidFree(stack, reinterpret_cast<uptr>(tagged_ptr));
+ bool in_taggable_region =
+ InTaggableRegion(reinterpret_cast<uptr>(tagged_ptr));
+ void *untagged_ptr = in_taggable_region ? UntagPtr(tagged_ptr) : tagged_ptr;
+
+ if (CheckInvalidFree(stack, untagged_ptr, tagged_ptr))
+ return;
- void *untagged_ptr = InTaggableRegion(reinterpret_cast<uptr>(tagged_ptr))
- ? UntagPtr(tagged_ptr)
- : tagged_ptr;
void *aligned_ptr = reinterpret_cast<void *>(
RoundDownTo(reinterpret_cast<uptr>(untagged_ptr), kShadowAlignment));
tag_t pointer_tag = GetTagFromPointer(reinterpret_cast<uptr>(tagged_ptr));
Metadata *meta =
reinterpret_cast<Metadata *>(allocator.GetMetaData(aligned_ptr));
+ if (!meta) {
+ ReportInvalidFree(stack, reinterpret_cast<uptr>(tagged_ptr));
+ return;
+ }
uptr orig_size = meta->get_requested_size();
u32 free_context_id = StackDepotPut(*stack);
u32 alloc_context_id = meta->alloc_context_id;
@@ -228,7 +251,11 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) {
CHECK_LT(tail_size, kShadowAlignment);
void *tail_beg = reinterpret_cast<void *>(
reinterpret_cast<uptr>(aligned_ptr) + orig_size);
- if (tail_size && internal_memcmp(tail_beg, tail_magic, tail_size))
+ tag_t short_granule_memtag = *(reinterpret_cast<tag_t *>(
+ reinterpret_cast<uptr>(tail_beg) + tail_size));
+ if (tail_size &&
+ (internal_memcmp(tail_beg, tail_magic, tail_size) ||
+ (in_taggable_region && pointer_tag != short_granule_memtag)))
ReportTailOverwritten(stack, reinterpret_cast<uptr>(tagged_ptr),
orig_size, tail_magic);
}
@@ -243,8 +270,7 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) {
Min(TaggedSize(orig_size), (uptr)flags()->max_free_fill_size);
internal_memset(aligned_ptr, flags()->free_fill_byte, fill_size);
}
- if (InTaggableRegion(reinterpret_cast<uptr>(tagged_ptr)) &&
- flags()->tag_in_free && malloc_bisect(stack, 0) &&
+ if (in_taggable_region && flags()->tag_in_free && malloc_bisect(stack, 0) &&
atomic_load_relaxed(&hwasan_allocator_tagging_enabled)) {
// Always store full 8-bit tags on free to maximize UAF detection.
tag_t tag;
@@ -278,13 +304,15 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) {
static void *HwasanReallocate(StackTrace *stack, void *tagged_ptr_old,
uptr new_size, uptr alignment) {
- if (!PointerAndMemoryTagsMatch(tagged_ptr_old))
- ReportInvalidFree(stack, reinterpret_cast<uptr>(tagged_ptr_old));
-
+ void *untagged_ptr_old =
+ InTaggableRegion(reinterpret_cast<uptr>(tagged_ptr_old))
+ ? UntagPtr(tagged_ptr_old)
+ : tagged_ptr_old;
+ if (CheckInvalidFree(stack, untagged_ptr_old, tagged_ptr_old))
+ return nullptr;
void *tagged_ptr_new =
HwasanAllocate(stack, new_size, alignment, false /*zeroise*/);
if (tagged_ptr_old && tagged_ptr_new) {
- void *untagged_ptr_old = UntagPtr(tagged_ptr_old);
Metadata *meta =
reinterpret_cast<Metadata *>(allocator.GetMetaData(untagged_ptr_old));
internal_memcpy(
@@ -305,6 +333,8 @@ static void *HwasanCalloc(StackTrace *stack, uptr nmemb, uptr size) {
}
HwasanChunkView FindHeapChunkByAddress(uptr address) {
+ if (!allocator.PointerIsMine(reinterpret_cast<void *>(address)))
+ return HwasanChunkView();
void *block = allocator.GetBlockBegin(reinterpret_cast<void*>(address));
if (!block)
return HwasanChunkView();
diff --git a/libsanitizer/hwasan/hwasan_dynamic_shadow.cpp b/libsanitizer/hwasan/hwasan_dynamic_shadow.cpp
index bde22df..7642ba6 100644
--- a/libsanitizer/hwasan/hwasan_dynamic_shadow.cpp
+++ b/libsanitizer/hwasan/hwasan_dynamic_shadow.cpp
@@ -113,6 +113,15 @@ uptr FindDynamicShadowStart(uptr shadow_size_bytes) {
}
} // namespace __hwasan
+
+#elif SANITIZER_FUCHSIA
+
+namespace __hwasan {
+
+void InitShadowGOT() {}
+
+} // namespace __hwasan
+
#else
namespace __hwasan {
diff --git a/libsanitizer/hwasan/hwasan_fuchsia.cpp b/libsanitizer/hwasan/hwasan_fuchsia.cpp
index e61f6ad..f51e148 100644
--- a/libsanitizer/hwasan/hwasan_fuchsia.cpp
+++ b/libsanitizer/hwasan/hwasan_fuchsia.cpp
@@ -34,6 +34,15 @@ bool InitShadow() {
__sanitizer::InitShadowBounds();
CHECK_NE(__sanitizer::ShadowBounds.shadow_limit, 0);
+ // These variables are used by MemIsShadow for asserting we have a correct
+ // shadow address. On Fuchsia, we only have one region of shadow, so the
+ // bounds of Low shadow can be zero while High shadow represents the true
+ // bounds. Note that these are inclusive ranges.
+ kLowShadowStart = 0;
+ kLowShadowEnd = 0;
+ kHighShadowStart = __sanitizer::ShadowBounds.shadow_base;
+ kHighShadowEnd = __sanitizer::ShadowBounds.shadow_limit - 1;
+
return true;
}
@@ -143,6 +152,14 @@ static void ThreadExitHook(void *hook, thrd_t self) {
hwasanThreadList().ReleaseThread(thread);
}
+uptr TagMemoryAligned(uptr p, uptr size, tag_t tag) {
+ CHECK(IsAligned(p, kShadowAlignment));
+ CHECK(IsAligned(size, kShadowAlignment));
+ __sanitizer_fill_shadow(p, size, tag,
+ common_flags()->clear_shadow_mmap_threshold);
+ return AddTagToPointer(p, tag);
+}
+
// Not implemented because Fuchsia does not use signal handlers.
void HwasanOnDeadlySignal(int signo, void *info, void *context) {}
@@ -163,6 +180,12 @@ void HwasanTSDThreadInit() {}
// function is unneeded.
void InstallAtExitHandler() {}
+void HwasanInstallAtForkHandler() {}
+
+// TODO(fxbug.dev/81499): Once we finalize the tagged pointer ABI in zircon, we should come back
+// here and implement the appropriate check that TBI is enabled.
+void InitializeOsSupport() {}
+
} // namespace __hwasan
extern "C" {
diff --git a/libsanitizer/hwasan/hwasan_interceptors.cpp b/libsanitizer/hwasan/hwasan_interceptors.cpp
index 68f8ade..f96ed88 100644
--- a/libsanitizer/hwasan/hwasan_interceptors.cpp
+++ b/libsanitizer/hwasan/hwasan_interceptors.cpp
@@ -49,15 +49,14 @@ INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
DEFINE_REAL(int, vfork)
DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
-#endif // HWASAN_WITH_INTERCEPTORS
-#if HWASAN_WITH_INTERCEPTORS && defined(__aarch64__)
// Get and/or change the set of blocked signals.
extern "C" int sigprocmask(int __how, const __hw_sigset_t *__restrict __set,
__hw_sigset_t *__restrict __oset);
#define SIG_BLOCK 0
#define SIG_SETMASK 2
extern "C" int __sigjmp_save(__hw_sigjmp_buf env, int savemask) {
+ env[0].__magic = kHwJmpBufMagic;
env[0].__mask_was_saved =
(savemask && sigprocmask(SIG_BLOCK, (__hw_sigset_t *)0,
&env[0].__saved_mask) == 0);
@@ -66,8 +65,14 @@ extern "C" int __sigjmp_save(__hw_sigjmp_buf env, int savemask) {
static void __attribute__((always_inline))
InternalLongjmp(__hw_register_buf env, int retval) {
+# if defined(__aarch64__)
+ constexpr size_t kSpIndex = 13;
+# elif defined(__x86_64__)
+ constexpr size_t kSpIndex = 6;
+# endif
+
// Clear all memory tags on the stack between here and where we're going.
- unsigned long long stack_pointer = env[13];
+ unsigned long long stack_pointer = env[kSpIndex];
// The stack pointer should never be tagged, so we don't need to clear the
// tag for this function call.
__hwasan_handle_longjmp((void *)stack_pointer);
@@ -78,6 +83,7 @@ InternalLongjmp(__hw_register_buf env, int retval) {
// Must implement this ourselves, since we don't know the order of registers
// in different libc implementations and many implementations mangle the
// stack pointer so we can't use it without knowing the demangling scheme.
+# if defined(__aarch64__)
register long int retval_tmp asm("x1") = retval;
register void *env_address asm("x0") = &env[0];
asm volatile("ldp x19, x20, [%0, #0<<3];"
@@ -100,9 +106,36 @@ InternalLongjmp(__hw_register_buf env, int retval) {
"br x30;"
: "+r"(env_address)
: "r"(retval_tmp));
+# elif defined(__x86_64__)
+ register long int retval_tmp asm("%rsi") = retval;
+ register void *env_address asm("%rdi") = &env[0];
+ asm volatile(
+ // Restore registers.
+ "mov (0*8)(%0),%%rbx;"
+ "mov (1*8)(%0),%%rbp;"
+ "mov (2*8)(%0),%%r12;"
+ "mov (3*8)(%0),%%r13;"
+ "mov (4*8)(%0),%%r14;"
+ "mov (5*8)(%0),%%r15;"
+ "mov (6*8)(%0),%%rsp;"
+ "mov (7*8)(%0),%%rdx;"
+ // Return 1 if retval is 0.
+ "mov $1,%%rax;"
+ "test %1,%1;"
+ "cmovnz %1,%%rax;"
+ "jmp *%%rdx;" ::"r"(env_address),
+ "r"(retval_tmp));
+# endif
}
INTERCEPTOR(void, siglongjmp, __hw_sigjmp_buf env, int val) {
+ if (env[0].__magic != kHwJmpBufMagic) {
+ Printf(
+ "WARNING: Unexpected bad jmp_buf. Either setjmp was not called or "
+ "there is a bug in HWASan.\n");
+ return REAL(siglongjmp)(env, val);
+ }
+
if (env[0].__mask_was_saved)
// Restore the saved signal mask.
(void)sigprocmask(SIG_SETMASK, &env[0].__saved_mask,
@@ -114,32 +147,24 @@ INTERCEPTOR(void, siglongjmp, __hw_sigjmp_buf env, int val) {
// _setjmp on start_thread. Hence we have to intercept the longjmp on
// pthread_exit so the __hw_jmp_buf order matches.
INTERCEPTOR(void, __libc_longjmp, __hw_jmp_buf env, int val) {
+ if (env[0].__magic != kHwJmpBufMagic)
+ return REAL(__libc_longjmp)(env, val);
InternalLongjmp(env[0].__jmpbuf, val);
}
INTERCEPTOR(void, longjmp, __hw_jmp_buf env, int val) {
+ if (env[0].__magic != kHwJmpBufMagic) {
+ Printf(
+ "WARNING: Unexpected bad jmp_buf. Either setjmp was not called or "
+ "there is a bug in HWASan.\n");
+ return REAL(longjmp)(env, val);
+ }
InternalLongjmp(env[0].__jmpbuf, val);
}
#undef SIG_BLOCK
#undef SIG_SETMASK
-#endif // HWASAN_WITH_INTERCEPTORS && __aarch64__
-
-static void BeforeFork() {
- StackDepotLockAll();
-}
-
-static void AfterFork() {
- StackDepotUnlockAll();
-}
-
-INTERCEPTOR(int, fork, void) {
- ENSURE_HWASAN_INITED();
- BeforeFork();
- int pid = REAL(fork)();
- AfterFork();
- return pid;
-}
+# endif // HWASAN_WITH_INTERCEPTORS
namespace __hwasan {
@@ -156,10 +181,11 @@ void InitializeInterceptors() {
static int inited = 0;
CHECK_EQ(inited, 0);
- INTERCEPT_FUNCTION(fork);
-
#if HWASAN_WITH_INTERCEPTORS
#if defined(__linux__)
+ INTERCEPT_FUNCTION(__libc_longjmp);
+ INTERCEPT_FUNCTION(longjmp);
+ INTERCEPT_FUNCTION(siglongjmp);
INTERCEPT_FUNCTION(vfork);
#endif // __linux__
INTERCEPT_FUNCTION(pthread_create);
diff --git a/libsanitizer/hwasan/hwasan_interface_internal.h b/libsanitizer/hwasan/hwasan_interface_internal.h
index 25c0f94..ef771ad 100644
--- a/libsanitizer/hwasan/hwasan_interface_internal.h
+++ b/libsanitizer/hwasan/hwasan_interface_internal.h
@@ -169,54 +169,6 @@ SANITIZER_INTERFACE_ATTRIBUTE
void __hwasan_print_memory_usage();
SANITIZER_INTERFACE_ATTRIBUTE
-int __sanitizer_posix_memalign(void **memptr, uptr alignment, uptr size);
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void * __sanitizer_memalign(uptr alignment, uptr size);
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void * __sanitizer_aligned_alloc(uptr alignment, uptr size);
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void * __sanitizer___libc_memalign(uptr alignment, uptr size);
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void * __sanitizer_valloc(uptr size);
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void * __sanitizer_pvalloc(uptr size);
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void __sanitizer_free(void *ptr);
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void __sanitizer_cfree(void *ptr);
-
-SANITIZER_INTERFACE_ATTRIBUTE
-uptr __sanitizer_malloc_usable_size(const void *ptr);
-
-SANITIZER_INTERFACE_ATTRIBUTE
-__hwasan::__sanitizer_struct_mallinfo __sanitizer_mallinfo();
-
-SANITIZER_INTERFACE_ATTRIBUTE
-int __sanitizer_mallopt(int cmd, int value);
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void __sanitizer_malloc_stats(void);
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void * __sanitizer_calloc(uptr nmemb, uptr size);
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void * __sanitizer_realloc(void *ptr, uptr size);
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void * __sanitizer_reallocarray(void *ptr, uptr nmemb, uptr size);
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void * __sanitizer_malloc(uptr size);
-
-SANITIZER_INTERFACE_ATTRIBUTE
void *__hwasan_memcpy(void *dst, const void *src, uptr size);
SANITIZER_INTERFACE_ATTRIBUTE
void *__hwasan_memset(void *s, int c, uptr n);
diff --git a/libsanitizer/hwasan/hwasan_linux.cpp b/libsanitizer/hwasan/hwasan_linux.cpp
index e227235..a86ec28 100644
--- a/libsanitizer/hwasan/hwasan_linux.cpp
+++ b/libsanitizer/hwasan/hwasan_linux.cpp
@@ -15,30 +15,30 @@
#include "sanitizer_common/sanitizer_platform.h"
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
-#include "hwasan.h"
-#include "hwasan_dynamic_shadow.h"
-#include "hwasan_interface_internal.h"
-#include "hwasan_mapping.h"
-#include "hwasan_report.h"
-#include "hwasan_thread.h"
-#include "hwasan_thread_list.h"
-
-#include <dlfcn.h>
-#include <elf.h>
-#include <link.h>
-#include <pthread.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/resource.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <unwind.h>
-#include <sys/prctl.h>
-#include <errno.h>
-
-#include "sanitizer_common/sanitizer_common.h"
-#include "sanitizer_common/sanitizer_procmaps.h"
+# include <dlfcn.h>
+# include <elf.h>
+# include <errno.h>
+# include <link.h>
+# include <pthread.h>
+# include <signal.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <sys/prctl.h>
+# include <sys/resource.h>
+# include <sys/time.h>
+# include <unistd.h>
+# include <unwind.h>
+
+# include "hwasan.h"
+# include "hwasan_dynamic_shadow.h"
+# include "hwasan_interface_internal.h"
+# include "hwasan_mapping.h"
+# include "hwasan_report.h"
+# include "hwasan_thread.h"
+# include "hwasan_thread_list.h"
+# include "sanitizer_common/sanitizer_common.h"
+# include "sanitizer_common/sanitizer_procmaps.h"
+# include "sanitizer_common/sanitizer_stackdepot.h"
// Configurations of HWASAN_WITH_INTERCEPTORS and SANITIZER_ANDROID.
//
@@ -50,10 +50,10 @@
// Tested with check-hwasan on x86_64-linux.
// HWASAN_WITH_INTERCEPTORS=ON, SANITIZER_ANDROID=ON
// Tested with check-hwasan on aarch64-linux-android.
-#if !SANITIZER_ANDROID
+# if !SANITIZER_ANDROID
SANITIZER_INTERFACE_ATTRIBUTE
THREADLOCAL uptr __hwasan_tls;
-#endif
+# endif
namespace __hwasan {
@@ -111,9 +111,9 @@ static void InitializeShadowBaseAddress(uptr shadow_size_bytes) {
}
void InitializeOsSupport() {
-#define PR_SET_TAGGED_ADDR_CTRL 55
-#define PR_GET_TAGGED_ADDR_CTRL 56
-#define PR_TAGGED_ADDR_ENABLE (1UL << 0)
+# define PR_SET_TAGGED_ADDR_CTRL 55
+# define PR_GET_TAGGED_ADDR_CTRL 56
+# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
// Check we're running on a kernel that can use the tagged address ABI.
int local_errno = 0;
if (internal_iserror(internal_prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0),
@@ -164,9 +164,9 @@ void InitializeOsSupport() {
Die();
}
}
-#undef PR_SET_TAGGED_ADDR_CTRL
-#undef PR_GET_TAGGED_ADDR_CTRL
-#undef PR_TAGGED_ADDR_ENABLE
+# undef PR_SET_TAGGED_ADDR_CTRL
+# undef PR_GET_TAGGED_ADDR_CTRL
+# undef PR_TAGGED_ADDR_ENABLE
}
bool InitShadow() {
@@ -241,12 +241,11 @@ bool MemIsApp(uptr p) {
CHECK(GetTagFromPointer(p) == 0);
# endif
- return p >= kHighMemStart || (p >= kLowMemStart && p <= kLowMemEnd);
+ return (p >= kHighMemStart && p <= kHighMemEnd) ||
+ (p >= kLowMemStart && p <= kLowMemEnd);
}
-void InstallAtExitHandler() {
- atexit(HwasanAtExit);
-}
+void InstallAtExitHandler() { atexit(HwasanAtExit); }
// ---------------------- TSD ---------------- {{{1
@@ -262,7 +261,7 @@ extern "C" void __hwasan_thread_exit() {
hwasanThreadList().ReleaseThread(t);
}
-#if HWASAN_WITH_INTERCEPTORS
+# if HWASAN_WITH_INTERCEPTORS
static pthread_key_t tsd_key;
static bool tsd_key_inited = false;
@@ -286,22 +285,18 @@ void HwasanTSDInit() {
tsd_key_inited = true;
CHECK_EQ(0, pthread_key_create(&tsd_key, HwasanTSDDtor));
}
-#else
+# else
void HwasanTSDInit() {}
void HwasanTSDThreadInit() {}
-#endif
+# endif
-#if SANITIZER_ANDROID
-uptr *GetCurrentThreadLongPtr() {
- return (uptr *)get_android_tls_ptr();
-}
-#else
-uptr *GetCurrentThreadLongPtr() {
- return &__hwasan_tls;
-}
-#endif
+# if SANITIZER_ANDROID
+uptr *GetCurrentThreadLongPtr() { return (uptr *)get_android_tls_ptr(); }
+# else
+uptr *GetCurrentThreadLongPtr() { return &__hwasan_tls; }
+# endif
-#if SANITIZER_ANDROID
+# if SANITIZER_ANDROID
void AndroidTestTlsSlot() {
uptr kMagicValue = 0x010203040A0B0C0D;
uptr *tls_ptr = GetCurrentThreadLongPtr();
@@ -316,9 +311,9 @@ void AndroidTestTlsSlot() {
}
*tls_ptr = old_value;
}
-#else
+# else
void AndroidTestTlsSlot() {}
-#endif
+# endif
static AccessInfo GetAccessInfo(siginfo_t *info, ucontext_t *uc) {
// Access type is passed in a platform dependent way (see below) and encoded
@@ -326,32 +321,32 @@ static AccessInfo GetAccessInfo(siginfo_t *info, ucontext_t *uc) {
// recoverable. Valid values of Y are 0 to 4, which are interpreted as
// log2(access_size), and 0xF, which means that access size is passed via
// platform dependent register (see below).
-#if defined(__aarch64__)
+# if defined(__aarch64__)
// Access type is encoded in BRK immediate as 0x900 + 0xXY. For Y == 0xF,
// access size is stored in X1 register. Access address is always in X0
// register.
uptr pc = (uptr)info->si_addr;
const unsigned code = ((*(u32 *)pc) >> 5) & 0xffff;
if ((code & 0xff00) != 0x900)
- return AccessInfo{}; // Not ours.
+ return AccessInfo{}; // Not ours.
const bool is_store = code & 0x10;
const bool recover = code & 0x20;
const uptr addr = uc->uc_mcontext.regs[0];
const unsigned size_log = code & 0xf;
if (size_log > 4 && size_log != 0xf)
- return AccessInfo{}; // Not ours.
+ return AccessInfo{}; // Not ours.
const uptr size = size_log == 0xf ? uc->uc_mcontext.regs[1] : 1U << size_log;
-#elif defined(__x86_64__)
+# elif defined(__x86_64__)
// Access type is encoded in the instruction following INT3 as
// NOP DWORD ptr [EAX + 0x40 + 0xXY]. For Y == 0xF, access size is stored in
// RSI register. Access address is always in RDI register.
uptr pc = (uptr)uc->uc_mcontext.gregs[REG_RIP];
- uint8_t *nop = (uint8_t*)pc;
- if (*nop != 0x0f || *(nop + 1) != 0x1f || *(nop + 2) != 0x40 ||
+ uint8_t *nop = (uint8_t *)pc;
+ if (*nop != 0x0f || *(nop + 1) != 0x1f || *(nop + 2) != 0x40 ||
*(nop + 3) < 0x40)
- return AccessInfo{}; // Not ours.
+ return AccessInfo{}; // Not ours.
const unsigned code = *(nop + 3);
const bool is_store = code & 0x10;
@@ -359,13 +354,13 @@ static AccessInfo GetAccessInfo(siginfo_t *info, ucontext_t *uc) {
const uptr addr = uc->uc_mcontext.gregs[REG_RDI];
const unsigned size_log = code & 0xf;
if (size_log > 4 && size_log != 0xf)
- return AccessInfo{}; // Not ours.
+ return AccessInfo{}; // Not ours.
const uptr size =
size_log == 0xf ? uc->uc_mcontext.gregs[REG_RSI] : 1U << size_log;
-#else
-# error Unsupported architecture
-#endif
+# else
+# error Unsupported architecture
+# endif
return AccessInfo{addr, size, is_store, !is_store, recover};
}
@@ -378,12 +373,12 @@ static bool HwasanOnSIGTRAP(int signo, siginfo_t *info, ucontext_t *uc) {
SignalContext sig{info, uc};
HandleTagMismatch(ai, StackTrace::GetNextInstructionPc(sig.pc), sig.bp, uc);
-#if defined(__aarch64__)
+# if defined(__aarch64__)
uc->uc_mcontext.pc += 4;
-#elif defined(__x86_64__)
-#else
-# error Unsupported architecture
-#endif
+# elif defined(__x86_64__)
+# else
+# error Unsupported architecture
+# endif
return true;
}
@@ -396,7 +391,7 @@ static void OnStackUnwind(const SignalContext &sig, const void *,
void HwasanOnDeadlySignal(int signo, void *info, void *context) {
// Probably a tag mismatch.
if (signo == SIGTRAP)
- if (HwasanOnSIGTRAP(signo, (siginfo_t *)info, (ucontext_t*)context))
+ if (HwasanOnSIGTRAP(signo, (siginfo_t *)info, (ucontext_t *)context))
return;
HandleDeadlySignal(info, context, GetTid(), &OnStackUnwind, nullptr);
@@ -435,6 +430,18 @@ uptr TagMemoryAligned(uptr p, uptr size, tag_t tag) {
return AddTagToPointer(p, tag);
}
-} // namespace __hwasan
+void HwasanInstallAtForkHandler() {
+ auto before = []() {
+ HwasanAllocatorLock();
+ StackDepotLockAll();
+ };
+ auto after = []() {
+ StackDepotUnlockAll();
+ HwasanAllocatorUnlock();
+ };
+ pthread_atfork(before, after, after);
+}
+
+} // namespace __hwasan
-#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
diff --git a/libsanitizer/hwasan/hwasan_report.cpp b/libsanitizer/hwasan/hwasan_report.cpp
index 44047c9..9b3b661 100644
--- a/libsanitizer/hwasan/hwasan_report.cpp
+++ b/libsanitizer/hwasan/hwasan_report.cpp
@@ -37,7 +37,7 @@ namespace __hwasan {
class ScopedReport {
public:
ScopedReport(bool fatal = false) : error_message_(1), fatal(fatal) {
- BlockingMutexLock lock(&error_message_lock_);
+ Lock lock(&error_message_lock_);
error_message_ptr_ = fatal ? &error_message_ : nullptr;
++hwasan_report_count;
}
@@ -45,7 +45,7 @@ class ScopedReport {
~ScopedReport() {
void (*report_cb)(const char *);
{
- BlockingMutexLock lock(&error_message_lock_);
+ Lock lock(&error_message_lock_);
report_cb = error_report_callback_;
error_message_ptr_ = nullptr;
}
@@ -61,7 +61,7 @@ class ScopedReport {
}
static void MaybeAppendToErrorMessage(const char *msg) {
- BlockingMutexLock lock(&error_message_lock_);
+ Lock lock(&error_message_lock_);
if (!error_message_ptr_)
return;
uptr len = internal_strlen(msg);
@@ -72,7 +72,7 @@ class ScopedReport {
}
static void SetErrorReportCallback(void (*callback)(const char *)) {
- BlockingMutexLock lock(&error_message_lock_);
+ Lock lock(&error_message_lock_);
error_report_callback_ = callback;
}
@@ -82,12 +82,12 @@ class ScopedReport {
bool fatal;
static InternalMmapVector<char> *error_message_ptr_;
- static BlockingMutex error_message_lock_;
+ static Mutex error_message_lock_;
static void (*error_report_callback_)(const char *);
};
InternalMmapVector<char> *ScopedReport::error_message_ptr_;
-BlockingMutex ScopedReport::error_message_lock_;
+Mutex ScopedReport::error_message_lock_;
void (*ScopedReport::error_report_callback_)(const char *);
// If there is an active ScopedReport, append to its error message.
@@ -351,14 +351,16 @@ static void ShowHeapOrGlobalCandidate(uptr untagged_addr, tag_t *candidate,
uptr size = GetGlobalSizeFromDescriptor(mem);
if (size == 0)
// We couldn't find the size of the global from the descriptors.
- Printf("%p is located to the %s of a global variable in (%s+0x%x)\n",
- untagged_addr, candidate == left ? "right" : "left", module_name,
- module_address);
+ Printf(
+ "%p is located to the %s of a global variable in "
+ "\n #0 0x%x (%s+0x%x)\n",
+ untagged_addr, candidate == left ? "right" : "left", mem,
+ module_name, module_address);
else
Printf(
"%p is located to the %s of a %zd-byte global variable in "
- "(%s+0x%x)\n",
- untagged_addr, candidate == left ? "right" : "left", size,
+ "\n #0 0x%x (%s+0x%x)\n",
+ untagged_addr, candidate == left ? "right" : "left", size, mem,
module_name, module_address);
}
Printf("%s", d.Default());
@@ -372,6 +374,12 @@ void PrintAddressDescription(
int num_descriptions_printed = 0;
uptr untagged_addr = UntagAddr(tagged_addr);
+ if (MemIsShadow(untagged_addr)) {
+ Printf("%s%p is HWAsan shadow memory.\n%s", d.Location(), untagged_addr,
+ d.Default());
+ return;
+ }
+
// Print some very basic information about the address, if it's a heap.
HwasanChunkView chunk = FindHeapChunkByAddress(untagged_addr);
if (uptr beg = chunk.Beg()) {
@@ -549,28 +557,48 @@ static void PrintTagsAroundAddr(tag_t *tag_ptr) {
"description of short granule tags\n");
}
+uptr GetTopPc(StackTrace *stack) {
+ return stack->size ? StackTrace::GetPreviousInstructionPc(stack->trace[0])
+ : 0;
+}
+
void ReportInvalidFree(StackTrace *stack, uptr tagged_addr) {
ScopedReport R(flags()->halt_on_error);
uptr untagged_addr = UntagAddr(tagged_addr);
tag_t ptr_tag = GetTagFromPointer(tagged_addr);
- tag_t *tag_ptr = reinterpret_cast<tag_t*>(MemToShadow(untagged_addr));
- tag_t mem_tag = *tag_ptr;
+ tag_t *tag_ptr = nullptr;
+ tag_t mem_tag = 0;
+ if (MemIsApp(untagged_addr)) {
+ tag_ptr = reinterpret_cast<tag_t *>(MemToShadow(untagged_addr));
+ if (MemIsShadow(reinterpret_cast<uptr>(tag_ptr)))
+ mem_tag = *tag_ptr;
+ else
+ tag_ptr = nullptr;
+ }
Decorator d;
Printf("%s", d.Error());
- uptr pc = stack->size ? stack->trace[0] : 0;
+ uptr pc = GetTopPc(stack);
const char *bug_type = "invalid-free";
- Report("ERROR: %s: %s on address %p at pc %p\n", SanitizerToolName, bug_type,
- untagged_addr, pc);
+ const Thread *thread = GetCurrentThread();
+ if (thread) {
+ Report("ERROR: %s: %s on address %p at pc %p on thread T%zd\n",
+ SanitizerToolName, bug_type, untagged_addr, pc, thread->unique_id());
+ } else {
+ Report("ERROR: %s: %s on address %p at pc %p on unknown thread\n",
+ SanitizerToolName, bug_type, untagged_addr, pc);
+ }
Printf("%s", d.Access());
- Printf("tags: %02x/%02x (ptr/mem)\n", ptr_tag, mem_tag);
+ if (tag_ptr)
+ Printf("tags: %02x/%02x (ptr/mem)\n", ptr_tag, mem_tag);
Printf("%s", d.Default());
stack->Print();
PrintAddressDescription(tagged_addr, 0, nullptr);
- PrintTagsAroundAddr(tag_ptr);
+ if (tag_ptr)
+ PrintTagsAroundAddr(tag_ptr);
ReportErrorSummary(bug_type, stack);
}
@@ -578,6 +606,15 @@ void ReportInvalidFree(StackTrace *stack, uptr tagged_addr) {
void ReportTailOverwritten(StackTrace *stack, uptr tagged_addr, uptr orig_size,
const u8 *expected) {
uptr tail_size = kShadowAlignment - (orig_size % kShadowAlignment);
+ u8 actual_expected[kShadowAlignment];
+ internal_memcpy(actual_expected, expected, tail_size);
+ tag_t ptr_tag = GetTagFromPointer(tagged_addr);
+ // Short granule is stashed in the last byte of the magic string. To avoid
+ // confusion, make the expected magic string contain the short granule tag.
+ if (orig_size % kShadowAlignment != 0) {
+ actual_expected[tail_size - 1] = ptr_tag;
+ }
+
ScopedReport R(flags()->halt_on_error);
Decorator d;
uptr untagged_addr = UntagAddr(tagged_addr);
@@ -614,14 +651,13 @@ void ReportTailOverwritten(StackTrace *stack, uptr tagged_addr, uptr orig_size,
s.append("Expected: ");
for (uptr i = 0; i < kShadowAlignment - tail_size; i++)
s.append(".. ");
- for (uptr i = 0; i < tail_size; i++)
- s.append("%02x ", expected[i]);
+ for (uptr i = 0; i < tail_size; i++) s.append("%02x ", actual_expected[i]);
s.append("\n");
s.append(" ");
for (uptr i = 0; i < kShadowAlignment - tail_size; i++)
s.append(" ");
for (uptr i = 0; i < tail_size; i++)
- s.append("%s ", expected[i] != tail[i] ? "^^" : " ");
+ s.append("%s ", actual_expected[i] != tail[i] ? "^^" : " ");
s.append("\nThis error occurs when a buffer overflow overwrites memory\n"
"to the right of a heap object, but within the %zd-byte granule, e.g.\n"
@@ -647,11 +683,11 @@ void ReportTagMismatch(StackTrace *stack, uptr tagged_addr, uptr access_size,
GetCurrentThread()->stack_allocations());
Decorator d;
- Printf("%s", d.Error());
uptr untagged_addr = UntagAddr(tagged_addr);
// TODO: when possible, try to print heap-use-after-free, etc.
const char *bug_type = "tag-mismatch";
- uptr pc = stack->size ? stack->trace[0] : 0;
+ uptr pc = GetTopPc(stack);
+ Printf("%s", d.Error());
Report("ERROR: %s: %s on address %p at pc %p\n", SanitizerToolName, bug_type,
untagged_addr, pc);
diff --git a/libsanitizer/hwasan/hwasan_setjmp.S b/libsanitizer/hwasan/hwasan_setjmp_aarch64.S
index 381af63..744748a 100644
--- a/libsanitizer/hwasan/hwasan_setjmp.S
+++ b/libsanitizer/hwasan/hwasan_setjmp_aarch64.S
@@ -1,4 +1,4 @@
-//===-- hwasan_setjmp.S --------------------------------------------------------===//
+//===-- hwasan_setjmp_aarch64.S -------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -29,7 +29,7 @@
// Hence we have to write this function in assembly.
.section .text
-.file "hwasan_setjmp.S"
+.file "hwasan_setjmp_aarch64.S"
.global __interceptor_setjmp
ASM_TYPE_FUNCTION(__interceptor_setjmp)
@@ -80,24 +80,19 @@ __interceptor_sigsetjmp:
ASM_SIZE(__interceptor_sigsetjmp)
-.macro ALIAS first second
- .globl \second
+.macro WEAK_ALIAS first second
+ .weak \second
.equ \second\(), \first
.endm
#if SANITIZER_ANDROID
-ALIAS __interceptor_sigsetjmp, sigsetjmp
-.weak sigsetjmp
-
-ALIAS __interceptor_setjmp_bionic, setjmp
-.weak setjmp
+WEAK_ALIAS __interceptor_sigsetjmp, sigsetjmp
+WEAK_ALIAS __interceptor_setjmp_bionic, setjmp
#else
-ALIAS __interceptor_sigsetjmp, __sigsetjmp
-.weak __sigsetjmp
+WEAK_ALIAS __interceptor_sigsetjmp, __sigsetjmp
#endif
-ALIAS __interceptor_setjmp, _setjmp
-.weak _setjmp
+WEAK_ALIAS __interceptor_setjmp, _setjmp
#endif
// We do not need executable stack.
diff --git a/libsanitizer/hwasan/hwasan_setjmp_x86_64.S b/libsanitizer/hwasan/hwasan_setjmp_x86_64.S
new file mode 100644
index 0000000..7566c1e
--- /dev/null
+++ b/libsanitizer/hwasan/hwasan_setjmp_x86_64.S
@@ -0,0 +1,82 @@
+//===-- hwasan_setjmp_x86_64.S --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// setjmp interceptor for x86_64.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_asm.h"
+
+#if HWASAN_WITH_INTERCEPTORS && defined(__x86_64__)
+#include "sanitizer_common/sanitizer_platform.h"
+
+// We want to save the context of the calling function.
+// That requires
+// 1) No modification of the return address by this function.
+// 2) No modification of the stack pointer by this function.
+// 3) (no modification of any other saved register, but that's not really going
+// to occur, and hence isn't as much of a worry).
+//
+// There's essentially no way to ensure that the compiler will not modify the
+// stack pointer when compiling a C function.
+// Hence we have to write this function in assembly.
+//
+// TODO: Handle Intel CET.
+
+.section .text
+.file "hwasan_setjmp_x86_64.S"
+
+.global __interceptor_setjmp
+ASM_TYPE_FUNCTION(__interceptor_setjmp)
+__interceptor_setjmp:
+ CFI_STARTPROC
+ _CET_ENDBR
+ xorl %esi, %esi
+ jmp __interceptor_sigsetjmp
+ CFI_ENDPROC
+ASM_SIZE(__interceptor_setjmp)
+
+.global __interceptor_sigsetjmp
+ASM_TYPE_FUNCTION(__interceptor_sigsetjmp)
+__interceptor_sigsetjmp:
+ CFI_STARTPROC
+ _CET_ENDBR
+
+ // Save callee save registers.
+ mov %rbx, (0*8)(%rdi)
+ mov %rbp, (1*8)(%rdi)
+ mov %r12, (2*8)(%rdi)
+ mov %r13, (3*8)(%rdi)
+ mov %r14, (4*8)(%rdi)
+ mov %r15, (5*8)(%rdi)
+
+ // Save SP as it was in caller's frame.
+ lea 8(%rsp), %rdx
+ mov %rdx, (6*8)(%rdi)
+
+ // Save return address.
+ mov (%rsp), %rax
+ mov %rax, (7*8)(%rdi)
+
+ jmp __sigjmp_save
+
+ CFI_ENDPROC
+ASM_SIZE(__interceptor_sigsetjmp)
+
+
+.macro WEAK_ALIAS first second
+ .weak \second
+ .equ \second\(), \first
+.endm
+
+WEAK_ALIAS __interceptor_sigsetjmp, __sigsetjmp
+WEAK_ALIAS __interceptor_setjmp, _setjmp
+#endif
+
+// We do not need executable stack.
+NO_EXEC_STACK_DIRECTIVE
diff --git a/libsanitizer/hwasan/hwasan_thread.cpp b/libsanitizer/hwasan/hwasan_thread.cpp
index ee747a3..5b65718 100644
--- a/libsanitizer/hwasan/hwasan_thread.cpp
+++ b/libsanitizer/hwasan/hwasan_thread.cpp
@@ -45,13 +45,13 @@ void Thread::Init(uptr stack_buffer_start, uptr stack_buffer_size,
if (auto sz = flags()->heap_history_size)
heap_allocations_ = HeapAllocationsRingBuffer::New(sz);
- InitStackAndTls(state);
#if !SANITIZER_FUCHSIA
// Do not initialize the stack ring buffer just yet on Fuchsia. Threads will
// be initialized before we enter the thread itself, so we will instead call
// this later.
InitStackRingBuffer(stack_buffer_start, stack_buffer_size);
#endif
+ InitStackAndTls(state);
}
void Thread::InitStackRingBuffer(uptr stack_buffer_start,
diff --git a/libsanitizer/hwasan/hwasan_type_test.cpp b/libsanitizer/hwasan/hwasan_type_test.cpp
index 8cff495..5307073 100644
--- a/libsanitizer/hwasan/hwasan_type_test.cpp
+++ b/libsanitizer/hwasan/hwasan_type_test.cpp
@@ -19,7 +19,7 @@
#define CHECK_TYPE_SIZE_FITS(TYPE) \
COMPILER_CHECK(sizeof(__hw_##TYPE) <= sizeof(TYPE))
-#if HWASAN_WITH_INTERCEPTORS && defined(__aarch64__)
+#if HWASAN_WITH_INTERCEPTORS
CHECK_TYPE_SIZE_FITS(jmp_buf);
CHECK_TYPE_SIZE_FITS(sigjmp_buf);
#endif
diff --git a/libsanitizer/include/sanitizer/asan_interface.h b/libsanitizer/include/sanitizer/asan_interface.h
index 792ef9c..9bff21c 100644
--- a/libsanitizer/include/sanitizer/asan_interface.h
+++ b/libsanitizer/include/sanitizer/asan_interface.h
@@ -316,7 +316,7 @@ void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg,
void __asan_handle_no_return(void);
/// Update allocation stack trace for the given allocation to the current stack
-/// trace. Returns 1 if successfull, 0 if not.
+/// trace. Returns 1 if successful, 0 if not.
int __asan_update_allocation_context(void* addr);
#ifdef __cplusplus
diff --git a/libsanitizer/include/sanitizer/common_interface_defs.h b/libsanitizer/include/sanitizer/common_interface_defs.h
index cd69285..692b8f7 100644
--- a/libsanitizer/include/sanitizer/common_interface_defs.h
+++ b/libsanitizer/include/sanitizer/common_interface_defs.h
@@ -28,7 +28,7 @@ typedef struct {
// Enable sandbox support in sanitizer coverage.
int coverage_sandboxed;
// File descriptor to write coverage data to. If -1 is passed, a file will
- // be pre-opened by __sanitizer_sandobx_on_notify(). This field has no
+ // be pre-opened by __sanitizer_sandbox_on_notify(). This field has no
// effect if coverage_sandboxed == 0.
intptr_t coverage_fd;
// If non-zero, split the coverage data into well-formed blocks. This is
diff --git a/libsanitizer/include/sanitizer/dfsan_interface.h b/libsanitizer/include/sanitizer/dfsan_interface.h
index cd3b6d6..d6209a3 100644
--- a/libsanitizer/include/sanitizer/dfsan_interface.h
+++ b/libsanitizer/include/sanitizer/dfsan_interface.h
@@ -150,8 +150,7 @@ int dfsan_get_track_origins(void);
#ifdef __cplusplus
} // extern "C"
-template <typename T>
-void dfsan_set_label(dfsan_label label, T &data) { // NOLINT
+template <typename T> void dfsan_set_label(dfsan_label label, T &data) {
dfsan_set_label(label, (void *)&data, sizeof(T));
}
diff --git a/libsanitizer/include/sanitizer/linux_syscall_hooks.h b/libsanitizer/include/sanitizer/linux_syscall_hooks.h
index 56eae3d4..3f3f1e7 100644
--- a/libsanitizer/include/sanitizer/linux_syscall_hooks.h
+++ b/libsanitizer/include/sanitizer/linux_syscall_hooks.h
@@ -20,1493 +20,1502 @@
#ifndef SANITIZER_LINUX_SYSCALL_HOOKS_H
#define SANITIZER_LINUX_SYSCALL_HOOKS_H
-#define __sanitizer_syscall_pre_time(tloc) \
+#define __sanitizer_syscall_pre_time(tloc) \
__sanitizer_syscall_pre_impl_time((long)(tloc))
-#define __sanitizer_syscall_post_time(res, tloc) \
+#define __sanitizer_syscall_post_time(res, tloc) \
__sanitizer_syscall_post_impl_time(res, (long)(tloc))
-#define __sanitizer_syscall_pre_stime(tptr) \
+#define __sanitizer_syscall_pre_stime(tptr) \
__sanitizer_syscall_pre_impl_stime((long)(tptr))
-#define __sanitizer_syscall_post_stime(res, tptr) \
+#define __sanitizer_syscall_post_stime(res, tptr) \
__sanitizer_syscall_post_impl_stime(res, (long)(tptr))
-#define __sanitizer_syscall_pre_gettimeofday(tv, tz) \
+#define __sanitizer_syscall_pre_gettimeofday(tv, tz) \
__sanitizer_syscall_pre_impl_gettimeofday((long)(tv), (long)(tz))
-#define __sanitizer_syscall_post_gettimeofday(res, tv, tz) \
+#define __sanitizer_syscall_post_gettimeofday(res, tv, tz) \
__sanitizer_syscall_post_impl_gettimeofday(res, (long)(tv), (long)(tz))
-#define __sanitizer_syscall_pre_settimeofday(tv, tz) \
+#define __sanitizer_syscall_pre_settimeofday(tv, tz) \
__sanitizer_syscall_pre_impl_settimeofday((long)(tv), (long)(tz))
-#define __sanitizer_syscall_post_settimeofday(res, tv, tz) \
+#define __sanitizer_syscall_post_settimeofday(res, tv, tz) \
__sanitizer_syscall_post_impl_settimeofday(res, (long)(tv), (long)(tz))
-#define __sanitizer_syscall_pre_adjtimex(txc_p) \
+#define __sanitizer_syscall_pre_adjtimex(txc_p) \
__sanitizer_syscall_pre_impl_adjtimex((long)(txc_p))
-#define __sanitizer_syscall_post_adjtimex(res, txc_p) \
+#define __sanitizer_syscall_post_adjtimex(res, txc_p) \
__sanitizer_syscall_post_impl_adjtimex(res, (long)(txc_p))
-#define __sanitizer_syscall_pre_times(tbuf) \
+#define __sanitizer_syscall_pre_times(tbuf) \
__sanitizer_syscall_pre_impl_times((long)(tbuf))
-#define __sanitizer_syscall_post_times(res, tbuf) \
+#define __sanitizer_syscall_post_times(res, tbuf) \
__sanitizer_syscall_post_impl_times(res, (long)(tbuf))
#define __sanitizer_syscall_pre_gettid() __sanitizer_syscall_pre_impl_gettid()
-#define __sanitizer_syscall_post_gettid(res) \
+#define __sanitizer_syscall_post_gettid(res) \
__sanitizer_syscall_post_impl_gettid(res)
-#define __sanitizer_syscall_pre_nanosleep(rqtp, rmtp) \
+#define __sanitizer_syscall_pre_nanosleep(rqtp, rmtp) \
__sanitizer_syscall_pre_impl_nanosleep((long)(rqtp), (long)(rmtp))
-#define __sanitizer_syscall_post_nanosleep(res, rqtp, rmtp) \
+#define __sanitizer_syscall_post_nanosleep(res, rqtp, rmtp) \
__sanitizer_syscall_post_impl_nanosleep(res, (long)(rqtp), (long)(rmtp))
-#define __sanitizer_syscall_pre_alarm(seconds) \
+#define __sanitizer_syscall_pre_alarm(seconds) \
__sanitizer_syscall_pre_impl_alarm((long)(seconds))
-#define __sanitizer_syscall_post_alarm(res, seconds) \
+#define __sanitizer_syscall_post_alarm(res, seconds) \
__sanitizer_syscall_post_impl_alarm(res, (long)(seconds))
#define __sanitizer_syscall_pre_getpid() __sanitizer_syscall_pre_impl_getpid()
-#define __sanitizer_syscall_post_getpid(res) \
+#define __sanitizer_syscall_post_getpid(res) \
__sanitizer_syscall_post_impl_getpid(res)
#define __sanitizer_syscall_pre_getppid() __sanitizer_syscall_pre_impl_getppid()
-#define __sanitizer_syscall_post_getppid(res) \
+#define __sanitizer_syscall_post_getppid(res) \
__sanitizer_syscall_post_impl_getppid(res)
#define __sanitizer_syscall_pre_getuid() __sanitizer_syscall_pre_impl_getuid()
-#define __sanitizer_syscall_post_getuid(res) \
+#define __sanitizer_syscall_post_getuid(res) \
__sanitizer_syscall_post_impl_getuid(res)
#define __sanitizer_syscall_pre_geteuid() __sanitizer_syscall_pre_impl_geteuid()
-#define __sanitizer_syscall_post_geteuid(res) \
+#define __sanitizer_syscall_post_geteuid(res) \
__sanitizer_syscall_post_impl_geteuid(res)
#define __sanitizer_syscall_pre_getgid() __sanitizer_syscall_pre_impl_getgid()
-#define __sanitizer_syscall_post_getgid(res) \
+#define __sanitizer_syscall_post_getgid(res) \
__sanitizer_syscall_post_impl_getgid(res)
#define __sanitizer_syscall_pre_getegid() __sanitizer_syscall_pre_impl_getegid()
-#define __sanitizer_syscall_post_getegid(res) \
+#define __sanitizer_syscall_post_getegid(res) \
__sanitizer_syscall_post_impl_getegid(res)
-#define __sanitizer_syscall_pre_getresuid(ruid, euid, suid) \
- __sanitizer_syscall_pre_impl_getresuid((long)(ruid), (long)(euid), \
+#define __sanitizer_syscall_pre_getresuid(ruid, euid, suid) \
+ __sanitizer_syscall_pre_impl_getresuid((long)(ruid), (long)(euid), \
(long)(suid))
-#define __sanitizer_syscall_post_getresuid(res, ruid, euid, suid) \
- __sanitizer_syscall_post_impl_getresuid(res, (long)(ruid), (long)(euid), \
+#define __sanitizer_syscall_post_getresuid(res, ruid, euid, suid) \
+ __sanitizer_syscall_post_impl_getresuid(res, (long)(ruid), (long)(euid), \
(long)(suid))
-#define __sanitizer_syscall_pre_getresgid(rgid, egid, sgid) \
- __sanitizer_syscall_pre_impl_getresgid((long)(rgid), (long)(egid), \
+#define __sanitizer_syscall_pre_getresgid(rgid, egid, sgid) \
+ __sanitizer_syscall_pre_impl_getresgid((long)(rgid), (long)(egid), \
(long)(sgid))
-#define __sanitizer_syscall_post_getresgid(res, rgid, egid, sgid) \
- __sanitizer_syscall_post_impl_getresgid(res, (long)(rgid), (long)(egid), \
+#define __sanitizer_syscall_post_getresgid(res, rgid, egid, sgid) \
+ __sanitizer_syscall_post_impl_getresgid(res, (long)(rgid), (long)(egid), \
(long)(sgid))
-#define __sanitizer_syscall_pre_getpgid(pid) \
+#define __sanitizer_syscall_pre_getpgid(pid) \
__sanitizer_syscall_pre_impl_getpgid((long)(pid))
-#define __sanitizer_syscall_post_getpgid(res, pid) \
+#define __sanitizer_syscall_post_getpgid(res, pid) \
__sanitizer_syscall_post_impl_getpgid(res, (long)(pid))
#define __sanitizer_syscall_pre_getpgrp() __sanitizer_syscall_pre_impl_getpgrp()
-#define __sanitizer_syscall_post_getpgrp(res) \
+#define __sanitizer_syscall_post_getpgrp(res) \
__sanitizer_syscall_post_impl_getpgrp(res)
-#define __sanitizer_syscall_pre_getsid(pid) \
+#define __sanitizer_syscall_pre_getsid(pid) \
__sanitizer_syscall_pre_impl_getsid((long)(pid))
-#define __sanitizer_syscall_post_getsid(res, pid) \
+#define __sanitizer_syscall_post_getsid(res, pid) \
__sanitizer_syscall_post_impl_getsid(res, (long)(pid))
-#define __sanitizer_syscall_pre_getgroups(gidsetsize, grouplist) \
+#define __sanitizer_syscall_pre_getgroups(gidsetsize, grouplist) \
__sanitizer_syscall_pre_impl_getgroups((long)(gidsetsize), (long)(grouplist))
-#define __sanitizer_syscall_post_getgroups(res, gidsetsize, grouplist) \
- __sanitizer_syscall_post_impl_getgroups(res, (long)(gidsetsize), \
+#define __sanitizer_syscall_post_getgroups(res, gidsetsize, grouplist) \
+ __sanitizer_syscall_post_impl_getgroups(res, (long)(gidsetsize), \
(long)(grouplist))
-#define __sanitizer_syscall_pre_setregid(rgid, egid) \
+#define __sanitizer_syscall_pre_setregid(rgid, egid) \
__sanitizer_syscall_pre_impl_setregid((long)(rgid), (long)(egid))
-#define __sanitizer_syscall_post_setregid(res, rgid, egid) \
+#define __sanitizer_syscall_post_setregid(res, rgid, egid) \
__sanitizer_syscall_post_impl_setregid(res, (long)(rgid), (long)(egid))
-#define __sanitizer_syscall_pre_setgid(gid) \
+#define __sanitizer_syscall_pre_setgid(gid) \
__sanitizer_syscall_pre_impl_setgid((long)(gid))
-#define __sanitizer_syscall_post_setgid(res, gid) \
+#define __sanitizer_syscall_post_setgid(res, gid) \
__sanitizer_syscall_post_impl_setgid(res, (long)(gid))
-#define __sanitizer_syscall_pre_setreuid(ruid, euid) \
+#define __sanitizer_syscall_pre_setreuid(ruid, euid) \
__sanitizer_syscall_pre_impl_setreuid((long)(ruid), (long)(euid))
-#define __sanitizer_syscall_post_setreuid(res, ruid, euid) \
+#define __sanitizer_syscall_post_setreuid(res, ruid, euid) \
__sanitizer_syscall_post_impl_setreuid(res, (long)(ruid), (long)(euid))
-#define __sanitizer_syscall_pre_setuid(uid) \
+#define __sanitizer_syscall_pre_setuid(uid) \
__sanitizer_syscall_pre_impl_setuid((long)(uid))
-#define __sanitizer_syscall_post_setuid(res, uid) \
+#define __sanitizer_syscall_post_setuid(res, uid) \
__sanitizer_syscall_post_impl_setuid(res, (long)(uid))
-#define __sanitizer_syscall_pre_setresuid(ruid, euid, suid) \
- __sanitizer_syscall_pre_impl_setresuid((long)(ruid), (long)(euid), \
+#define __sanitizer_syscall_pre_setresuid(ruid, euid, suid) \
+ __sanitizer_syscall_pre_impl_setresuid((long)(ruid), (long)(euid), \
(long)(suid))
-#define __sanitizer_syscall_post_setresuid(res, ruid, euid, suid) \
- __sanitizer_syscall_post_impl_setresuid(res, (long)(ruid), (long)(euid), \
+#define __sanitizer_syscall_post_setresuid(res, ruid, euid, suid) \
+ __sanitizer_syscall_post_impl_setresuid(res, (long)(ruid), (long)(euid), \
(long)(suid))
-#define __sanitizer_syscall_pre_setresgid(rgid, egid, sgid) \
- __sanitizer_syscall_pre_impl_setresgid((long)(rgid), (long)(egid), \
+#define __sanitizer_syscall_pre_setresgid(rgid, egid, sgid) \
+ __sanitizer_syscall_pre_impl_setresgid((long)(rgid), (long)(egid), \
(long)(sgid))
-#define __sanitizer_syscall_post_setresgid(res, rgid, egid, sgid) \
- __sanitizer_syscall_post_impl_setresgid(res, (long)(rgid), (long)(egid), \
+#define __sanitizer_syscall_post_setresgid(res, rgid, egid, sgid) \
+ __sanitizer_syscall_post_impl_setresgid(res, (long)(rgid), (long)(egid), \
(long)(sgid))
-#define __sanitizer_syscall_pre_setfsuid(uid) \
+#define __sanitizer_syscall_pre_setfsuid(uid) \
__sanitizer_syscall_pre_impl_setfsuid((long)(uid))
-#define __sanitizer_syscall_post_setfsuid(res, uid) \
+#define __sanitizer_syscall_post_setfsuid(res, uid) \
__sanitizer_syscall_post_impl_setfsuid(res, (long)(uid))
-#define __sanitizer_syscall_pre_setfsgid(gid) \
+#define __sanitizer_syscall_pre_setfsgid(gid) \
__sanitizer_syscall_pre_impl_setfsgid((long)(gid))
-#define __sanitizer_syscall_post_setfsgid(res, gid) \
+#define __sanitizer_syscall_post_setfsgid(res, gid) \
__sanitizer_syscall_post_impl_setfsgid(res, (long)(gid))
-#define __sanitizer_syscall_pre_setpgid(pid, pgid) \
+#define __sanitizer_syscall_pre_setpgid(pid, pgid) \
__sanitizer_syscall_pre_impl_setpgid((long)(pid), (long)(pgid))
-#define __sanitizer_syscall_post_setpgid(res, pid, pgid) \
+#define __sanitizer_syscall_post_setpgid(res, pid, pgid) \
__sanitizer_syscall_post_impl_setpgid(res, (long)(pid), (long)(pgid))
#define __sanitizer_syscall_pre_setsid() __sanitizer_syscall_pre_impl_setsid()
-#define __sanitizer_syscall_post_setsid(res) \
+#define __sanitizer_syscall_post_setsid(res) \
__sanitizer_syscall_post_impl_setsid(res)
-#define __sanitizer_syscall_pre_setgroups(gidsetsize, grouplist) \
+#define __sanitizer_syscall_pre_setgroups(gidsetsize, grouplist) \
__sanitizer_syscall_pre_impl_setgroups((long)(gidsetsize), (long)(grouplist))
-#define __sanitizer_syscall_post_setgroups(res, gidsetsize, grouplist) \
- __sanitizer_syscall_post_impl_setgroups(res, (long)(gidsetsize), \
+#define __sanitizer_syscall_post_setgroups(res, gidsetsize, grouplist) \
+ __sanitizer_syscall_post_impl_setgroups(res, (long)(gidsetsize), \
(long)(grouplist))
-#define __sanitizer_syscall_pre_acct(name) \
+#define __sanitizer_syscall_pre_acct(name) \
__sanitizer_syscall_pre_impl_acct((long)(name))
-#define __sanitizer_syscall_post_acct(res, name) \
+#define __sanitizer_syscall_post_acct(res, name) \
__sanitizer_syscall_post_impl_acct(res, (long)(name))
-#define __sanitizer_syscall_pre_capget(header, dataptr) \
+#define __sanitizer_syscall_pre_capget(header, dataptr) \
__sanitizer_syscall_pre_impl_capget((long)(header), (long)(dataptr))
-#define __sanitizer_syscall_post_capget(res, header, dataptr) \
+#define __sanitizer_syscall_post_capget(res, header, dataptr) \
__sanitizer_syscall_post_impl_capget(res, (long)(header), (long)(dataptr))
-#define __sanitizer_syscall_pre_capset(header, data) \
+#define __sanitizer_syscall_pre_capset(header, data) \
__sanitizer_syscall_pre_impl_capset((long)(header), (long)(data))
-#define __sanitizer_syscall_post_capset(res, header, data) \
+#define __sanitizer_syscall_post_capset(res, header, data) \
__sanitizer_syscall_post_impl_capset(res, (long)(header), (long)(data))
-#define __sanitizer_syscall_pre_personality(personality) \
+#define __sanitizer_syscall_pre_personality(personality) \
__sanitizer_syscall_pre_impl_personality((long)(personality))
-#define __sanitizer_syscall_post_personality(res, personality) \
+#define __sanitizer_syscall_post_personality(res, personality) \
__sanitizer_syscall_post_impl_personality(res, (long)(personality))
-#define __sanitizer_syscall_pre_sigpending(set) \
+#define __sanitizer_syscall_pre_sigpending(set) \
__sanitizer_syscall_pre_impl_sigpending((long)(set))
-#define __sanitizer_syscall_post_sigpending(res, set) \
+#define __sanitizer_syscall_post_sigpending(res, set) \
__sanitizer_syscall_post_impl_sigpending(res, (long)(set))
-#define __sanitizer_syscall_pre_sigprocmask(how, set, oset) \
- __sanitizer_syscall_pre_impl_sigprocmask((long)(how), (long)(set), \
+#define __sanitizer_syscall_pre_sigprocmask(how, set, oset) \
+ __sanitizer_syscall_pre_impl_sigprocmask((long)(how), (long)(set), \
(long)(oset))
-#define __sanitizer_syscall_post_sigprocmask(res, how, set, oset) \
- __sanitizer_syscall_post_impl_sigprocmask(res, (long)(how), (long)(set), \
+#define __sanitizer_syscall_post_sigprocmask(res, how, set, oset) \
+ __sanitizer_syscall_post_impl_sigprocmask(res, (long)(how), (long)(set), \
(long)(oset))
-#define __sanitizer_syscall_pre_getitimer(which, value) \
+#define __sanitizer_syscall_pre_getitimer(which, value) \
__sanitizer_syscall_pre_impl_getitimer((long)(which), (long)(value))
-#define __sanitizer_syscall_post_getitimer(res, which, value) \
+#define __sanitizer_syscall_post_getitimer(res, which, value) \
__sanitizer_syscall_post_impl_getitimer(res, (long)(which), (long)(value))
-#define __sanitizer_syscall_pre_setitimer(which, value, ovalue) \
- __sanitizer_syscall_pre_impl_setitimer((long)(which), (long)(value), \
+#define __sanitizer_syscall_pre_setitimer(which, value, ovalue) \
+ __sanitizer_syscall_pre_impl_setitimer((long)(which), (long)(value), \
(long)(ovalue))
-#define __sanitizer_syscall_post_setitimer(res, which, value, ovalue) \
- __sanitizer_syscall_post_impl_setitimer(res, (long)(which), (long)(value), \
+#define __sanitizer_syscall_post_setitimer(res, which, value, ovalue) \
+ __sanitizer_syscall_post_impl_setitimer(res, (long)(which), (long)(value), \
(long)(ovalue))
-#define __sanitizer_syscall_pre_timer_create(which_clock, timer_event_spec, \
- created_timer_id) \
- __sanitizer_syscall_pre_impl_timer_create( \
+#define __sanitizer_syscall_pre_timer_create(which_clock, timer_event_spec, \
+ created_timer_id) \
+ __sanitizer_syscall_pre_impl_timer_create( \
(long)(which_clock), (long)(timer_event_spec), (long)(created_timer_id))
-#define __sanitizer_syscall_post_timer_create( \
- res, which_clock, timer_event_spec, created_timer_id) \
- __sanitizer_syscall_post_impl_timer_create(res, (long)(which_clock), \
- (long)(timer_event_spec), \
+#define __sanitizer_syscall_post_timer_create( \
+ res, which_clock, timer_event_spec, created_timer_id) \
+ __sanitizer_syscall_post_impl_timer_create(res, (long)(which_clock), \
+ (long)(timer_event_spec), \
(long)(created_timer_id))
-#define __sanitizer_syscall_pre_timer_gettime(timer_id, setting) \
+#define __sanitizer_syscall_pre_timer_gettime(timer_id, setting) \
__sanitizer_syscall_pre_impl_timer_gettime((long)(timer_id), (long)(setting))
-#define __sanitizer_syscall_post_timer_gettime(res, timer_id, setting) \
- __sanitizer_syscall_post_impl_timer_gettime(res, (long)(timer_id), \
+#define __sanitizer_syscall_post_timer_gettime(res, timer_id, setting) \
+ __sanitizer_syscall_post_impl_timer_gettime(res, (long)(timer_id), \
(long)(setting))
-#define __sanitizer_syscall_pre_timer_getoverrun(timer_id) \
+#define __sanitizer_syscall_pre_timer_getoverrun(timer_id) \
__sanitizer_syscall_pre_impl_timer_getoverrun((long)(timer_id))
-#define __sanitizer_syscall_post_timer_getoverrun(res, timer_id) \
+#define __sanitizer_syscall_post_timer_getoverrun(res, timer_id) \
__sanitizer_syscall_post_impl_timer_getoverrun(res, (long)(timer_id))
-#define __sanitizer_syscall_pre_timer_settime(timer_id, flags, new_setting, \
- old_setting) \
- __sanitizer_syscall_pre_impl_timer_settime((long)(timer_id), (long)(flags), \
- (long)(new_setting), \
+#define __sanitizer_syscall_pre_timer_settime(timer_id, flags, new_setting, \
+ old_setting) \
+ __sanitizer_syscall_pre_impl_timer_settime((long)(timer_id), (long)(flags), \
+ (long)(new_setting), \
(long)(old_setting))
-#define __sanitizer_syscall_post_timer_settime(res, timer_id, flags, \
- new_setting, old_setting) \
- __sanitizer_syscall_post_impl_timer_settime( \
- res, (long)(timer_id), (long)(flags), (long)(new_setting), \
+#define __sanitizer_syscall_post_timer_settime(res, timer_id, flags, \
+ new_setting, old_setting) \
+ __sanitizer_syscall_post_impl_timer_settime( \
+ res, (long)(timer_id), (long)(flags), (long)(new_setting), \
(long)(old_setting))
-#define __sanitizer_syscall_pre_timer_delete(timer_id) \
+#define __sanitizer_syscall_pre_timer_delete(timer_id) \
__sanitizer_syscall_pre_impl_timer_delete((long)(timer_id))
-#define __sanitizer_syscall_post_timer_delete(res, timer_id) \
+#define __sanitizer_syscall_post_timer_delete(res, timer_id) \
__sanitizer_syscall_post_impl_timer_delete(res, (long)(timer_id))
-#define __sanitizer_syscall_pre_clock_settime(which_clock, tp) \
+#define __sanitizer_syscall_pre_clock_settime(which_clock, tp) \
__sanitizer_syscall_pre_impl_clock_settime((long)(which_clock), (long)(tp))
-#define __sanitizer_syscall_post_clock_settime(res, which_clock, tp) \
- __sanitizer_syscall_post_impl_clock_settime(res, (long)(which_clock), \
+#define __sanitizer_syscall_post_clock_settime(res, which_clock, tp) \
+ __sanitizer_syscall_post_impl_clock_settime(res, (long)(which_clock), \
(long)(tp))
-#define __sanitizer_syscall_pre_clock_gettime(which_clock, tp) \
+#define __sanitizer_syscall_pre_clock_gettime(which_clock, tp) \
__sanitizer_syscall_pre_impl_clock_gettime((long)(which_clock), (long)(tp))
-#define __sanitizer_syscall_post_clock_gettime(res, which_clock, tp) \
- __sanitizer_syscall_post_impl_clock_gettime(res, (long)(which_clock), \
+#define __sanitizer_syscall_post_clock_gettime(res, which_clock, tp) \
+ __sanitizer_syscall_post_impl_clock_gettime(res, (long)(which_clock), \
(long)(tp))
-#define __sanitizer_syscall_pre_clock_adjtime(which_clock, tx) \
+#define __sanitizer_syscall_pre_clock_adjtime(which_clock, tx) \
__sanitizer_syscall_pre_impl_clock_adjtime((long)(which_clock), (long)(tx))
-#define __sanitizer_syscall_post_clock_adjtime(res, which_clock, tx) \
- __sanitizer_syscall_post_impl_clock_adjtime(res, (long)(which_clock), \
+#define __sanitizer_syscall_post_clock_adjtime(res, which_clock, tx) \
+ __sanitizer_syscall_post_impl_clock_adjtime(res, (long)(which_clock), \
(long)(tx))
-#define __sanitizer_syscall_pre_clock_getres(which_clock, tp) \
+#define __sanitizer_syscall_pre_clock_getres(which_clock, tp) \
__sanitizer_syscall_pre_impl_clock_getres((long)(which_clock), (long)(tp))
-#define __sanitizer_syscall_post_clock_getres(res, which_clock, tp) \
- __sanitizer_syscall_post_impl_clock_getres(res, (long)(which_clock), \
+#define __sanitizer_syscall_post_clock_getres(res, which_clock, tp) \
+ __sanitizer_syscall_post_impl_clock_getres(res, (long)(which_clock), \
(long)(tp))
-#define __sanitizer_syscall_pre_clock_nanosleep(which_clock, flags, rqtp, \
- rmtp) \
- __sanitizer_syscall_pre_impl_clock_nanosleep( \
+#define __sanitizer_syscall_pre_clock_nanosleep(which_clock, flags, rqtp, \
+ rmtp) \
+ __sanitizer_syscall_pre_impl_clock_nanosleep( \
(long)(which_clock), (long)(flags), (long)(rqtp), (long)(rmtp))
-#define __sanitizer_syscall_post_clock_nanosleep(res, which_clock, flags, \
- rqtp, rmtp) \
- __sanitizer_syscall_post_impl_clock_nanosleep( \
+#define __sanitizer_syscall_post_clock_nanosleep(res, which_clock, flags, \
+ rqtp, rmtp) \
+ __sanitizer_syscall_post_impl_clock_nanosleep( \
res, (long)(which_clock), (long)(flags), (long)(rqtp), (long)(rmtp))
-#define __sanitizer_syscall_pre_nice(increment) \
+#define __sanitizer_syscall_pre_nice(increment) \
__sanitizer_syscall_pre_impl_nice((long)(increment))
-#define __sanitizer_syscall_post_nice(res, increment) \
+#define __sanitizer_syscall_post_nice(res, increment) \
__sanitizer_syscall_post_impl_nice(res, (long)(increment))
#define __sanitizer_syscall_pre_sched_setscheduler(pid, policy, param) \
__sanitizer_syscall_pre_impl_sched_setscheduler((long)(pid), (long)(policy), \
(long)(param))
-#define __sanitizer_syscall_post_sched_setscheduler(res, pid, policy, param) \
- __sanitizer_syscall_post_impl_sched_setscheduler( \
+#define __sanitizer_syscall_post_sched_setscheduler(res, pid, policy, param) \
+ __sanitizer_syscall_post_impl_sched_setscheduler( \
res, (long)(pid), (long)(policy), (long)(param))
-#define __sanitizer_syscall_pre_sched_setparam(pid, param) \
+#define __sanitizer_syscall_pre_sched_setparam(pid, param) \
__sanitizer_syscall_pre_impl_sched_setparam((long)(pid), (long)(param))
-#define __sanitizer_syscall_post_sched_setparam(res, pid, param) \
+#define __sanitizer_syscall_post_sched_setparam(res, pid, param) \
__sanitizer_syscall_post_impl_sched_setparam(res, (long)(pid), (long)(param))
-#define __sanitizer_syscall_pre_sched_getscheduler(pid) \
+#define __sanitizer_syscall_pre_sched_getscheduler(pid) \
__sanitizer_syscall_pre_impl_sched_getscheduler((long)(pid))
-#define __sanitizer_syscall_post_sched_getscheduler(res, pid) \
+#define __sanitizer_syscall_post_sched_getscheduler(res, pid) \
__sanitizer_syscall_post_impl_sched_getscheduler(res, (long)(pid))
-#define __sanitizer_syscall_pre_sched_getparam(pid, param) \
+#define __sanitizer_syscall_pre_sched_getparam(pid, param) \
__sanitizer_syscall_pre_impl_sched_getparam((long)(pid), (long)(param))
-#define __sanitizer_syscall_post_sched_getparam(res, pid, param) \
+#define __sanitizer_syscall_post_sched_getparam(res, pid, param) \
__sanitizer_syscall_post_impl_sched_getparam(res, (long)(pid), (long)(param))
-#define __sanitizer_syscall_pre_sched_setaffinity(pid, len, user_mask_ptr) \
- __sanitizer_syscall_pre_impl_sched_setaffinity((long)(pid), (long)(len), \
+#define __sanitizer_syscall_pre_sched_setaffinity(pid, len, user_mask_ptr) \
+ __sanitizer_syscall_pre_impl_sched_setaffinity((long)(pid), (long)(len), \
(long)(user_mask_ptr))
-#define __sanitizer_syscall_post_sched_setaffinity(res, pid, len, \
- user_mask_ptr) \
- __sanitizer_syscall_post_impl_sched_setaffinity( \
+#define __sanitizer_syscall_post_sched_setaffinity(res, pid, len, \
+ user_mask_ptr) \
+ __sanitizer_syscall_post_impl_sched_setaffinity( \
res, (long)(pid), (long)(len), (long)(user_mask_ptr))
-#define __sanitizer_syscall_pre_sched_getaffinity(pid, len, user_mask_ptr) \
- __sanitizer_syscall_pre_impl_sched_getaffinity((long)(pid), (long)(len), \
+#define __sanitizer_syscall_pre_sched_getaffinity(pid, len, user_mask_ptr) \
+ __sanitizer_syscall_pre_impl_sched_getaffinity((long)(pid), (long)(len), \
(long)(user_mask_ptr))
-#define __sanitizer_syscall_post_sched_getaffinity(res, pid, len, \
- user_mask_ptr) \
- __sanitizer_syscall_post_impl_sched_getaffinity( \
+#define __sanitizer_syscall_post_sched_getaffinity(res, pid, len, \
+ user_mask_ptr) \
+ __sanitizer_syscall_post_impl_sched_getaffinity( \
res, (long)(pid), (long)(len), (long)(user_mask_ptr))
-#define __sanitizer_syscall_pre_sched_yield() \
+#define __sanitizer_syscall_pre_sched_yield() \
__sanitizer_syscall_pre_impl_sched_yield()
-#define __sanitizer_syscall_post_sched_yield(res) \
+#define __sanitizer_syscall_post_sched_yield(res) \
__sanitizer_syscall_post_impl_sched_yield(res)
-#define __sanitizer_syscall_pre_sched_get_priority_max(policy) \
+#define __sanitizer_syscall_pre_sched_get_priority_max(policy) \
__sanitizer_syscall_pre_impl_sched_get_priority_max((long)(policy))
-#define __sanitizer_syscall_post_sched_get_priority_max(res, policy) \
+#define __sanitizer_syscall_post_sched_get_priority_max(res, policy) \
__sanitizer_syscall_post_impl_sched_get_priority_max(res, (long)(policy))
-#define __sanitizer_syscall_pre_sched_get_priority_min(policy) \
+#define __sanitizer_syscall_pre_sched_get_priority_min(policy) \
__sanitizer_syscall_pre_impl_sched_get_priority_min((long)(policy))
-#define __sanitizer_syscall_post_sched_get_priority_min(res, policy) \
+#define __sanitizer_syscall_post_sched_get_priority_min(res, policy) \
__sanitizer_syscall_post_impl_sched_get_priority_min(res, (long)(policy))
-#define __sanitizer_syscall_pre_sched_rr_get_interval(pid, interval) \
- __sanitizer_syscall_pre_impl_sched_rr_get_interval((long)(pid), \
+#define __sanitizer_syscall_pre_sched_rr_get_interval(pid, interval) \
+ __sanitizer_syscall_pre_impl_sched_rr_get_interval((long)(pid), \
(long)(interval))
-#define __sanitizer_syscall_post_sched_rr_get_interval(res, pid, interval) \
- __sanitizer_syscall_post_impl_sched_rr_get_interval(res, (long)(pid), \
+#define __sanitizer_syscall_post_sched_rr_get_interval(res, pid, interval) \
+ __sanitizer_syscall_post_impl_sched_rr_get_interval(res, (long)(pid), \
(long)(interval))
-#define __sanitizer_syscall_pre_setpriority(which, who, niceval) \
- __sanitizer_syscall_pre_impl_setpriority((long)(which), (long)(who), \
+#define __sanitizer_syscall_pre_setpriority(which, who, niceval) \
+ __sanitizer_syscall_pre_impl_setpriority((long)(which), (long)(who), \
(long)(niceval))
-#define __sanitizer_syscall_post_setpriority(res, which, who, niceval) \
- __sanitizer_syscall_post_impl_setpriority(res, (long)(which), (long)(who), \
+#define __sanitizer_syscall_post_setpriority(res, which, who, niceval) \
+ __sanitizer_syscall_post_impl_setpriority(res, (long)(which), (long)(who), \
(long)(niceval))
-#define __sanitizer_syscall_pre_getpriority(which, who) \
+#define __sanitizer_syscall_pre_getpriority(which, who) \
__sanitizer_syscall_pre_impl_getpriority((long)(which), (long)(who))
-#define __sanitizer_syscall_post_getpriority(res, which, who) \
+#define __sanitizer_syscall_post_getpriority(res, which, who) \
__sanitizer_syscall_post_impl_getpriority(res, (long)(which), (long)(who))
-#define __sanitizer_syscall_pre_shutdown(arg0, arg1) \
+#define __sanitizer_syscall_pre_shutdown(arg0, arg1) \
__sanitizer_syscall_pre_impl_shutdown((long)(arg0), (long)(arg1))
-#define __sanitizer_syscall_post_shutdown(res, arg0, arg1) \
+#define __sanitizer_syscall_post_shutdown(res, arg0, arg1) \
__sanitizer_syscall_post_impl_shutdown(res, (long)(arg0), (long)(arg1))
-#define __sanitizer_syscall_pre_reboot(magic1, magic2, cmd, arg) \
- __sanitizer_syscall_pre_impl_reboot((long)(magic1), (long)(magic2), \
+#define __sanitizer_syscall_pre_reboot(magic1, magic2, cmd, arg) \
+ __sanitizer_syscall_pre_impl_reboot((long)(magic1), (long)(magic2), \
(long)(cmd), (long)(arg))
-#define __sanitizer_syscall_post_reboot(res, magic1, magic2, cmd, arg) \
- __sanitizer_syscall_post_impl_reboot(res, (long)(magic1), (long)(magic2), \
+#define __sanitizer_syscall_post_reboot(res, magic1, magic2, cmd, arg) \
+ __sanitizer_syscall_post_impl_reboot(res, (long)(magic1), (long)(magic2), \
(long)(cmd), (long)(arg))
-#define __sanitizer_syscall_pre_restart_syscall() \
+#define __sanitizer_syscall_pre_restart_syscall() \
__sanitizer_syscall_pre_impl_restart_syscall()
-#define __sanitizer_syscall_post_restart_syscall(res) \
+#define __sanitizer_syscall_post_restart_syscall(res) \
__sanitizer_syscall_post_impl_restart_syscall(res)
-#define __sanitizer_syscall_pre_kexec_load(entry, nr_segments, segments, \
- flags) \
- __sanitizer_syscall_pre_impl_kexec_load((long)(entry), (long)(nr_segments), \
+#define __sanitizer_syscall_pre_kexec_load(entry, nr_segments, segments, \
+ flags) \
+ __sanitizer_syscall_pre_impl_kexec_load((long)(entry), (long)(nr_segments), \
(long)(segments), (long)(flags))
#define __sanitizer_syscall_post_kexec_load(res, entry, nr_segments, segments, \
flags) \
__sanitizer_syscall_post_impl_kexec_load(res, (long)(entry), \
(long)(nr_segments), \
(long)(segments), (long)(flags))
-#define __sanitizer_syscall_pre_exit(error_code) \
+#define __sanitizer_syscall_pre_exit(error_code) \
__sanitizer_syscall_pre_impl_exit((long)(error_code))
-#define __sanitizer_syscall_post_exit(res, error_code) \
+#define __sanitizer_syscall_post_exit(res, error_code) \
__sanitizer_syscall_post_impl_exit(res, (long)(error_code))
-#define __sanitizer_syscall_pre_exit_group(error_code) \
+#define __sanitizer_syscall_pre_exit_group(error_code) \
__sanitizer_syscall_pre_impl_exit_group((long)(error_code))
-#define __sanitizer_syscall_post_exit_group(res, error_code) \
+#define __sanitizer_syscall_post_exit_group(res, error_code) \
__sanitizer_syscall_post_impl_exit_group(res, (long)(error_code))
-#define __sanitizer_syscall_pre_wait4(pid, stat_addr, options, ru) \
- __sanitizer_syscall_pre_impl_wait4((long)(pid), (long)(stat_addr), \
+#define __sanitizer_syscall_pre_wait4(pid, stat_addr, options, ru) \
+ __sanitizer_syscall_pre_impl_wait4((long)(pid), (long)(stat_addr), \
(long)(options), (long)(ru))
-#define __sanitizer_syscall_post_wait4(res, pid, stat_addr, options, ru) \
- __sanitizer_syscall_post_impl_wait4(res, (long)(pid), (long)(stat_addr), \
+#define __sanitizer_syscall_post_wait4(res, pid, stat_addr, options, ru) \
+ __sanitizer_syscall_post_impl_wait4(res, (long)(pid), (long)(stat_addr), \
(long)(options), (long)(ru))
-#define __sanitizer_syscall_pre_waitid(which, pid, infop, options, ru) \
- __sanitizer_syscall_pre_impl_waitid( \
+#define __sanitizer_syscall_pre_waitid(which, pid, infop, options, ru) \
+ __sanitizer_syscall_pre_impl_waitid( \
(long)(which), (long)(pid), (long)(infop), (long)(options), (long)(ru))
-#define __sanitizer_syscall_post_waitid(res, which, pid, infop, options, ru) \
- __sanitizer_syscall_post_impl_waitid(res, (long)(which), (long)(pid), \
- (long)(infop), (long)(options), \
+#define __sanitizer_syscall_post_waitid(res, which, pid, infop, options, ru) \
+ __sanitizer_syscall_post_impl_waitid(res, (long)(which), (long)(pid), \
+ (long)(infop), (long)(options), \
(long)(ru))
-#define __sanitizer_syscall_pre_waitpid(pid, stat_addr, options) \
- __sanitizer_syscall_pre_impl_waitpid((long)(pid), (long)(stat_addr), \
+#define __sanitizer_syscall_pre_waitpid(pid, stat_addr, options) \
+ __sanitizer_syscall_pre_impl_waitpid((long)(pid), (long)(stat_addr), \
(long)(options))
-#define __sanitizer_syscall_post_waitpid(res, pid, stat_addr, options) \
- __sanitizer_syscall_post_impl_waitpid(res, (long)(pid), (long)(stat_addr), \
+#define __sanitizer_syscall_post_waitpid(res, pid, stat_addr, options) \
+ __sanitizer_syscall_post_impl_waitpid(res, (long)(pid), (long)(stat_addr), \
(long)(options))
-#define __sanitizer_syscall_pre_set_tid_address(tidptr) \
+#define __sanitizer_syscall_pre_set_tid_address(tidptr) \
__sanitizer_syscall_pre_impl_set_tid_address((long)(tidptr))
-#define __sanitizer_syscall_post_set_tid_address(res, tidptr) \
+#define __sanitizer_syscall_post_set_tid_address(res, tidptr) \
__sanitizer_syscall_post_impl_set_tid_address(res, (long)(tidptr))
-#define __sanitizer_syscall_pre_init_module(umod, len, uargs) \
- __sanitizer_syscall_pre_impl_init_module((long)(umod), (long)(len), \
+#define __sanitizer_syscall_pre_init_module(umod, len, uargs) \
+ __sanitizer_syscall_pre_impl_init_module((long)(umod), (long)(len), \
(long)(uargs))
-#define __sanitizer_syscall_post_init_module(res, umod, len, uargs) \
- __sanitizer_syscall_post_impl_init_module(res, (long)(umod), (long)(len), \
+#define __sanitizer_syscall_post_init_module(res, umod, len, uargs) \
+ __sanitizer_syscall_post_impl_init_module(res, (long)(umod), (long)(len), \
(long)(uargs))
-#define __sanitizer_syscall_pre_delete_module(name_user, flags) \
+#define __sanitizer_syscall_pre_delete_module(name_user, flags) \
__sanitizer_syscall_pre_impl_delete_module((long)(name_user), (long)(flags))
-#define __sanitizer_syscall_post_delete_module(res, name_user, flags) \
- __sanitizer_syscall_post_impl_delete_module(res, (long)(name_user), \
+#define __sanitizer_syscall_post_delete_module(res, name_user, flags) \
+ __sanitizer_syscall_post_impl_delete_module(res, (long)(name_user), \
(long)(flags))
-#define __sanitizer_syscall_pre_rt_sigprocmask(how, set, oset, sigsetsize) \
- __sanitizer_syscall_pre_impl_rt_sigprocmask( \
+#define __sanitizer_syscall_pre_rt_sigprocmask(how, set, oset, sigsetsize) \
+ __sanitizer_syscall_pre_impl_rt_sigprocmask( \
(long)(how), (long)(set), (long)(oset), (long)(sigsetsize))
-#define __sanitizer_syscall_post_rt_sigprocmask(res, how, set, oset, \
- sigsetsize) \
- __sanitizer_syscall_post_impl_rt_sigprocmask( \
+#define __sanitizer_syscall_post_rt_sigprocmask(res, how, set, oset, \
+ sigsetsize) \
+ __sanitizer_syscall_post_impl_rt_sigprocmask( \
res, (long)(how), (long)(set), (long)(oset), (long)(sigsetsize))
-#define __sanitizer_syscall_pre_rt_sigpending(set, sigsetsize) \
+#define __sanitizer_syscall_pre_rt_sigpending(set, sigsetsize) \
__sanitizer_syscall_pre_impl_rt_sigpending((long)(set), (long)(sigsetsize))
-#define __sanitizer_syscall_post_rt_sigpending(res, set, sigsetsize) \
- __sanitizer_syscall_post_impl_rt_sigpending(res, (long)(set), \
+#define __sanitizer_syscall_post_rt_sigpending(res, set, sigsetsize) \
+ __sanitizer_syscall_post_impl_rt_sigpending(res, (long)(set), \
(long)(sigsetsize))
-#define __sanitizer_syscall_pre_rt_sigtimedwait(uthese, uinfo, uts, \
- sigsetsize) \
- __sanitizer_syscall_pre_impl_rt_sigtimedwait( \
+#define __sanitizer_syscall_pre_rt_sigtimedwait(uthese, uinfo, uts, \
+ sigsetsize) \
+ __sanitizer_syscall_pre_impl_rt_sigtimedwait( \
(long)(uthese), (long)(uinfo), (long)(uts), (long)(sigsetsize))
-#define __sanitizer_syscall_post_rt_sigtimedwait(res, uthese, uinfo, uts, \
- sigsetsize) \
- __sanitizer_syscall_post_impl_rt_sigtimedwait( \
+#define __sanitizer_syscall_post_rt_sigtimedwait(res, uthese, uinfo, uts, \
+ sigsetsize) \
+ __sanitizer_syscall_post_impl_rt_sigtimedwait( \
res, (long)(uthese), (long)(uinfo), (long)(uts), (long)(sigsetsize))
-#define __sanitizer_syscall_pre_rt_tgsigqueueinfo(tgid, pid, sig, uinfo) \
- __sanitizer_syscall_pre_impl_rt_tgsigqueueinfo((long)(tgid), (long)(pid), \
+#define __sanitizer_syscall_pre_rt_tgsigqueueinfo(tgid, pid, sig, uinfo) \
+ __sanitizer_syscall_pre_impl_rt_tgsigqueueinfo((long)(tgid), (long)(pid), \
(long)(sig), (long)(uinfo))
#define __sanitizer_syscall_post_rt_tgsigqueueinfo(res, tgid, pid, sig, uinfo) \
__sanitizer_syscall_post_impl_rt_tgsigqueueinfo( \
res, (long)(tgid), (long)(pid), (long)(sig), (long)(uinfo))
-#define __sanitizer_syscall_pre_kill(pid, sig) \
+#define __sanitizer_syscall_pre_kill(pid, sig) \
__sanitizer_syscall_pre_impl_kill((long)(pid), (long)(sig))
-#define __sanitizer_syscall_post_kill(res, pid, sig) \
+#define __sanitizer_syscall_post_kill(res, pid, sig) \
__sanitizer_syscall_post_impl_kill(res, (long)(pid), (long)(sig))
-#define __sanitizer_syscall_pre_tgkill(tgid, pid, sig) \
+#define __sanitizer_syscall_pre_tgkill(tgid, pid, sig) \
__sanitizer_syscall_pre_impl_tgkill((long)(tgid), (long)(pid), (long)(sig))
-#define __sanitizer_syscall_post_tgkill(res, tgid, pid, sig) \
- __sanitizer_syscall_post_impl_tgkill(res, (long)(tgid), (long)(pid), \
+#define __sanitizer_syscall_post_tgkill(res, tgid, pid, sig) \
+ __sanitizer_syscall_post_impl_tgkill(res, (long)(tgid), (long)(pid), \
(long)(sig))
-#define __sanitizer_syscall_pre_tkill(pid, sig) \
+#define __sanitizer_syscall_pre_tkill(pid, sig) \
__sanitizer_syscall_pre_impl_tkill((long)(pid), (long)(sig))
-#define __sanitizer_syscall_post_tkill(res, pid, sig) \
+#define __sanitizer_syscall_post_tkill(res, pid, sig) \
__sanitizer_syscall_post_impl_tkill(res, (long)(pid), (long)(sig))
-#define __sanitizer_syscall_pre_rt_sigqueueinfo(pid, sig, uinfo) \
- __sanitizer_syscall_pre_impl_rt_sigqueueinfo((long)(pid), (long)(sig), \
+#define __sanitizer_syscall_pre_rt_sigqueueinfo(pid, sig, uinfo) \
+ __sanitizer_syscall_pre_impl_rt_sigqueueinfo((long)(pid), (long)(sig), \
(long)(uinfo))
#define __sanitizer_syscall_post_rt_sigqueueinfo(res, pid, sig, uinfo) \
__sanitizer_syscall_post_impl_rt_sigqueueinfo(res, (long)(pid), (long)(sig), \
(long)(uinfo))
-#define __sanitizer_syscall_pre_sgetmask() \
+#define __sanitizer_syscall_pre_sgetmask() \
__sanitizer_syscall_pre_impl_sgetmask()
-#define __sanitizer_syscall_post_sgetmask(res) \
+#define __sanitizer_syscall_post_sgetmask(res) \
__sanitizer_syscall_post_impl_sgetmask(res)
-#define __sanitizer_syscall_pre_ssetmask(newmask) \
+#define __sanitizer_syscall_pre_ssetmask(newmask) \
__sanitizer_syscall_pre_impl_ssetmask((long)(newmask))
-#define __sanitizer_syscall_post_ssetmask(res, newmask) \
+#define __sanitizer_syscall_post_ssetmask(res, newmask) \
__sanitizer_syscall_post_impl_ssetmask(res, (long)(newmask))
-#define __sanitizer_syscall_pre_signal(sig, handler) \
+#define __sanitizer_syscall_pre_signal(sig, handler) \
__sanitizer_syscall_pre_impl_signal((long)(sig), (long)(handler))
-#define __sanitizer_syscall_post_signal(res, sig, handler) \
+#define __sanitizer_syscall_post_signal(res, sig, handler) \
__sanitizer_syscall_post_impl_signal(res, (long)(sig), (long)(handler))
#define __sanitizer_syscall_pre_pause() __sanitizer_syscall_pre_impl_pause()
-#define __sanitizer_syscall_post_pause(res) \
+#define __sanitizer_syscall_post_pause(res) \
__sanitizer_syscall_post_impl_pause(res)
#define __sanitizer_syscall_pre_sync() __sanitizer_syscall_pre_impl_sync()
-#define __sanitizer_syscall_post_sync(res) \
+#define __sanitizer_syscall_post_sync(res) \
__sanitizer_syscall_post_impl_sync(res)
-#define __sanitizer_syscall_pre_fsync(fd) \
+#define __sanitizer_syscall_pre_fsync(fd) \
__sanitizer_syscall_pre_impl_fsync((long)(fd))
-#define __sanitizer_syscall_post_fsync(res, fd) \
+#define __sanitizer_syscall_post_fsync(res, fd) \
__sanitizer_syscall_post_impl_fsync(res, (long)(fd))
-#define __sanitizer_syscall_pre_fdatasync(fd) \
+#define __sanitizer_syscall_pre_fdatasync(fd) \
__sanitizer_syscall_pre_impl_fdatasync((long)(fd))
-#define __sanitizer_syscall_post_fdatasync(res, fd) \
+#define __sanitizer_syscall_post_fdatasync(res, fd) \
__sanitizer_syscall_post_impl_fdatasync(res, (long)(fd))
-#define __sanitizer_syscall_pre_bdflush(func, data) \
+#define __sanitizer_syscall_pre_bdflush(func, data) \
__sanitizer_syscall_pre_impl_bdflush((long)(func), (long)(data))
-#define __sanitizer_syscall_post_bdflush(res, func, data) \
+#define __sanitizer_syscall_post_bdflush(res, func, data) \
__sanitizer_syscall_post_impl_bdflush(res, (long)(func), (long)(data))
-#define __sanitizer_syscall_pre_mount(dev_name, dir_name, type, flags, data) \
- __sanitizer_syscall_pre_impl_mount((long)(dev_name), (long)(dir_name), \
- (long)(type), (long)(flags), \
+#define __sanitizer_syscall_pre_mount(dev_name, dir_name, type, flags, data) \
+ __sanitizer_syscall_pre_impl_mount((long)(dev_name), (long)(dir_name), \
+ (long)(type), (long)(flags), \
(long)(data))
#define __sanitizer_syscall_post_mount(res, dev_name, dir_name, type, flags, \
data) \
__sanitizer_syscall_post_impl_mount(res, (long)(dev_name), (long)(dir_name), \
(long)(type), (long)(flags), \
(long)(data))
-#define __sanitizer_syscall_pre_umount(name, flags) \
+#define __sanitizer_syscall_pre_umount(name, flags) \
__sanitizer_syscall_pre_impl_umount((long)(name), (long)(flags))
-#define __sanitizer_syscall_post_umount(res, name, flags) \
+#define __sanitizer_syscall_post_umount(res, name, flags) \
__sanitizer_syscall_post_impl_umount(res, (long)(name), (long)(flags))
-#define __sanitizer_syscall_pre_oldumount(name) \
+#define __sanitizer_syscall_pre_oldumount(name) \
__sanitizer_syscall_pre_impl_oldumount((long)(name))
-#define __sanitizer_syscall_post_oldumount(res, name) \
+#define __sanitizer_syscall_post_oldumount(res, name) \
__sanitizer_syscall_post_impl_oldumount(res, (long)(name))
-#define __sanitizer_syscall_pre_truncate(path, length) \
+#define __sanitizer_syscall_pre_truncate(path, length) \
__sanitizer_syscall_pre_impl_truncate((long)(path), (long)(length))
-#define __sanitizer_syscall_post_truncate(res, path, length) \
+#define __sanitizer_syscall_post_truncate(res, path, length) \
__sanitizer_syscall_post_impl_truncate(res, (long)(path), (long)(length))
-#define __sanitizer_syscall_pre_ftruncate(fd, length) \
+#define __sanitizer_syscall_pre_ftruncate(fd, length) \
__sanitizer_syscall_pre_impl_ftruncate((long)(fd), (long)(length))
-#define __sanitizer_syscall_post_ftruncate(res, fd, length) \
+#define __sanitizer_syscall_post_ftruncate(res, fd, length) \
__sanitizer_syscall_post_impl_ftruncate(res, (long)(fd), (long)(length))
-#define __sanitizer_syscall_pre_stat(filename, statbuf) \
+#define __sanitizer_syscall_pre_stat(filename, statbuf) \
__sanitizer_syscall_pre_impl_stat((long)(filename), (long)(statbuf))
-#define __sanitizer_syscall_post_stat(res, filename, statbuf) \
+#define __sanitizer_syscall_post_stat(res, filename, statbuf) \
__sanitizer_syscall_post_impl_stat(res, (long)(filename), (long)(statbuf))
-#define __sanitizer_syscall_pre_statfs(path, buf) \
+#define __sanitizer_syscall_pre_statfs(path, buf) \
__sanitizer_syscall_pre_impl_statfs((long)(path), (long)(buf))
-#define __sanitizer_syscall_post_statfs(res, path, buf) \
+#define __sanitizer_syscall_post_statfs(res, path, buf) \
__sanitizer_syscall_post_impl_statfs(res, (long)(path), (long)(buf))
-#define __sanitizer_syscall_pre_statfs64(path, sz, buf) \
+#define __sanitizer_syscall_pre_statfs64(path, sz, buf) \
__sanitizer_syscall_pre_impl_statfs64((long)(path), (long)(sz), (long)(buf))
-#define __sanitizer_syscall_post_statfs64(res, path, sz, buf) \
- __sanitizer_syscall_post_impl_statfs64(res, (long)(path), (long)(sz), \
+#define __sanitizer_syscall_post_statfs64(res, path, sz, buf) \
+ __sanitizer_syscall_post_impl_statfs64(res, (long)(path), (long)(sz), \
(long)(buf))
-#define __sanitizer_syscall_pre_fstatfs(fd, buf) \
+#define __sanitizer_syscall_pre_fstatfs(fd, buf) \
__sanitizer_syscall_pre_impl_fstatfs((long)(fd), (long)(buf))
-#define __sanitizer_syscall_post_fstatfs(res, fd, buf) \
+#define __sanitizer_syscall_post_fstatfs(res, fd, buf) \
__sanitizer_syscall_post_impl_fstatfs(res, (long)(fd), (long)(buf))
-#define __sanitizer_syscall_pre_fstatfs64(fd, sz, buf) \
+#define __sanitizer_syscall_pre_fstatfs64(fd, sz, buf) \
__sanitizer_syscall_pre_impl_fstatfs64((long)(fd), (long)(sz), (long)(buf))
-#define __sanitizer_syscall_post_fstatfs64(res, fd, sz, buf) \
- __sanitizer_syscall_post_impl_fstatfs64(res, (long)(fd), (long)(sz), \
+#define __sanitizer_syscall_post_fstatfs64(res, fd, sz, buf) \
+ __sanitizer_syscall_post_impl_fstatfs64(res, (long)(fd), (long)(sz), \
(long)(buf))
-#define __sanitizer_syscall_pre_lstat(filename, statbuf) \
+#define __sanitizer_syscall_pre_lstat(filename, statbuf) \
__sanitizer_syscall_pre_impl_lstat((long)(filename), (long)(statbuf))
-#define __sanitizer_syscall_post_lstat(res, filename, statbuf) \
+#define __sanitizer_syscall_post_lstat(res, filename, statbuf) \
__sanitizer_syscall_post_impl_lstat(res, (long)(filename), (long)(statbuf))
-#define __sanitizer_syscall_pre_fstat(fd, statbuf) \
+#define __sanitizer_syscall_pre_fstat(fd, statbuf) \
__sanitizer_syscall_pre_impl_fstat((long)(fd), (long)(statbuf))
-#define __sanitizer_syscall_post_fstat(res, fd, statbuf) \
+#define __sanitizer_syscall_post_fstat(res, fd, statbuf) \
__sanitizer_syscall_post_impl_fstat(res, (long)(fd), (long)(statbuf))
-#define __sanitizer_syscall_pre_newstat(filename, statbuf) \
+#define __sanitizer_syscall_pre_newstat(filename, statbuf) \
__sanitizer_syscall_pre_impl_newstat((long)(filename), (long)(statbuf))
-#define __sanitizer_syscall_post_newstat(res, filename, statbuf) \
+#define __sanitizer_syscall_post_newstat(res, filename, statbuf) \
__sanitizer_syscall_post_impl_newstat(res, (long)(filename), (long)(statbuf))
-#define __sanitizer_syscall_pre_newlstat(filename, statbuf) \
+#define __sanitizer_syscall_pre_newlstat(filename, statbuf) \
__sanitizer_syscall_pre_impl_newlstat((long)(filename), (long)(statbuf))
-#define __sanitizer_syscall_post_newlstat(res, filename, statbuf) \
+#define __sanitizer_syscall_post_newlstat(res, filename, statbuf) \
__sanitizer_syscall_post_impl_newlstat(res, (long)(filename), (long)(statbuf))
-#define __sanitizer_syscall_pre_newfstat(fd, statbuf) \
+#define __sanitizer_syscall_pre_newfstat(fd, statbuf) \
__sanitizer_syscall_pre_impl_newfstat((long)(fd), (long)(statbuf))
-#define __sanitizer_syscall_post_newfstat(res, fd, statbuf) \
+#define __sanitizer_syscall_post_newfstat(res, fd, statbuf) \
__sanitizer_syscall_post_impl_newfstat(res, (long)(fd), (long)(statbuf))
-#define __sanitizer_syscall_pre_ustat(dev, ubuf) \
+#define __sanitizer_syscall_pre_ustat(dev, ubuf) \
__sanitizer_syscall_pre_impl_ustat((long)(dev), (long)(ubuf))
-#define __sanitizer_syscall_post_ustat(res, dev, ubuf) \
+#define __sanitizer_syscall_post_ustat(res, dev, ubuf) \
__sanitizer_syscall_post_impl_ustat(res, (long)(dev), (long)(ubuf))
-#define __sanitizer_syscall_pre_stat64(filename, statbuf) \
+#define __sanitizer_syscall_pre_stat64(filename, statbuf) \
__sanitizer_syscall_pre_impl_stat64((long)(filename), (long)(statbuf))
-#define __sanitizer_syscall_post_stat64(res, filename, statbuf) \
+#define __sanitizer_syscall_post_stat64(res, filename, statbuf) \
__sanitizer_syscall_post_impl_stat64(res, (long)(filename), (long)(statbuf))
-#define __sanitizer_syscall_pre_fstat64(fd, statbuf) \
+#define __sanitizer_syscall_pre_fstat64(fd, statbuf) \
__sanitizer_syscall_pre_impl_fstat64((long)(fd), (long)(statbuf))
-#define __sanitizer_syscall_post_fstat64(res, fd, statbuf) \
+#define __sanitizer_syscall_post_fstat64(res, fd, statbuf) \
__sanitizer_syscall_post_impl_fstat64(res, (long)(fd), (long)(statbuf))
-#define __sanitizer_syscall_pre_lstat64(filename, statbuf) \
+#define __sanitizer_syscall_pre_lstat64(filename, statbuf) \
__sanitizer_syscall_pre_impl_lstat64((long)(filename), (long)(statbuf))
-#define __sanitizer_syscall_post_lstat64(res, filename, statbuf) \
+#define __sanitizer_syscall_post_lstat64(res, filename, statbuf) \
__sanitizer_syscall_post_impl_lstat64(res, (long)(filename), (long)(statbuf))
-#define __sanitizer_syscall_pre_setxattr(path, name, value, size, flags) \
- __sanitizer_syscall_pre_impl_setxattr( \
+#define __sanitizer_syscall_pre_setxattr(path, name, value, size, flags) \
+ __sanitizer_syscall_pre_impl_setxattr( \
(long)(path), (long)(name), (long)(value), (long)(size), (long)(flags))
#define __sanitizer_syscall_post_setxattr(res, path, name, value, size, flags) \
__sanitizer_syscall_post_impl_setxattr(res, (long)(path), (long)(name), \
(long)(value), (long)(size), \
(long)(flags))
-#define __sanitizer_syscall_pre_lsetxattr(path, name, value, size, flags) \
- __sanitizer_syscall_pre_impl_lsetxattr( \
+#define __sanitizer_syscall_pre_lsetxattr(path, name, value, size, flags) \
+ __sanitizer_syscall_pre_impl_lsetxattr( \
(long)(path), (long)(name), (long)(value), (long)(size), (long)(flags))
-#define __sanitizer_syscall_post_lsetxattr(res, path, name, value, size, \
- flags) \
- __sanitizer_syscall_post_impl_lsetxattr(res, (long)(path), (long)(name), \
- (long)(value), (long)(size), \
+#define __sanitizer_syscall_post_lsetxattr(res, path, name, value, size, \
+ flags) \
+ __sanitizer_syscall_post_impl_lsetxattr(res, (long)(path), (long)(name), \
+ (long)(value), (long)(size), \
(long)(flags))
-#define __sanitizer_syscall_pre_fsetxattr(fd, name, value, size, flags) \
- __sanitizer_syscall_pre_impl_fsetxattr( \
+#define __sanitizer_syscall_pre_fsetxattr(fd, name, value, size, flags) \
+ __sanitizer_syscall_pre_impl_fsetxattr( \
(long)(fd), (long)(name), (long)(value), (long)(size), (long)(flags))
-#define __sanitizer_syscall_post_fsetxattr(res, fd, name, value, size, flags) \
- __sanitizer_syscall_post_impl_fsetxattr(res, (long)(fd), (long)(name), \
- (long)(value), (long)(size), \
+#define __sanitizer_syscall_post_fsetxattr(res, fd, name, value, size, flags) \
+ __sanitizer_syscall_post_impl_fsetxattr(res, (long)(fd), (long)(name), \
+ (long)(value), (long)(size), \
(long)(flags))
-#define __sanitizer_syscall_pre_getxattr(path, name, value, size) \
- __sanitizer_syscall_pre_impl_getxattr((long)(path), (long)(name), \
+#define __sanitizer_syscall_pre_getxattr(path, name, value, size) \
+ __sanitizer_syscall_pre_impl_getxattr((long)(path), (long)(name), \
(long)(value), (long)(size))
-#define __sanitizer_syscall_post_getxattr(res, path, name, value, size) \
- __sanitizer_syscall_post_impl_getxattr(res, (long)(path), (long)(name), \
+#define __sanitizer_syscall_post_getxattr(res, path, name, value, size) \
+ __sanitizer_syscall_post_impl_getxattr(res, (long)(path), (long)(name), \
(long)(value), (long)(size))
-#define __sanitizer_syscall_pre_lgetxattr(path, name, value, size) \
- __sanitizer_syscall_pre_impl_lgetxattr((long)(path), (long)(name), \
+#define __sanitizer_syscall_pre_lgetxattr(path, name, value, size) \
+ __sanitizer_syscall_pre_impl_lgetxattr((long)(path), (long)(name), \
(long)(value), (long)(size))
-#define __sanitizer_syscall_post_lgetxattr(res, path, name, value, size) \
- __sanitizer_syscall_post_impl_lgetxattr(res, (long)(path), (long)(name), \
+#define __sanitizer_syscall_post_lgetxattr(res, path, name, value, size) \
+ __sanitizer_syscall_post_impl_lgetxattr(res, (long)(path), (long)(name), \
(long)(value), (long)(size))
-#define __sanitizer_syscall_pre_fgetxattr(fd, name, value, size) \
- __sanitizer_syscall_pre_impl_fgetxattr((long)(fd), (long)(name), \
+#define __sanitizer_syscall_pre_fgetxattr(fd, name, value, size) \
+ __sanitizer_syscall_pre_impl_fgetxattr((long)(fd), (long)(name), \
(long)(value), (long)(size))
-#define __sanitizer_syscall_post_fgetxattr(res, fd, name, value, size) \
- __sanitizer_syscall_post_impl_fgetxattr(res, (long)(fd), (long)(name), \
+#define __sanitizer_syscall_post_fgetxattr(res, fd, name, value, size) \
+ __sanitizer_syscall_post_impl_fgetxattr(res, (long)(fd), (long)(name), \
(long)(value), (long)(size))
-#define __sanitizer_syscall_pre_listxattr(path, list, size) \
- __sanitizer_syscall_pre_impl_listxattr((long)(path), (long)(list), \
+#define __sanitizer_syscall_pre_listxattr(path, list, size) \
+ __sanitizer_syscall_pre_impl_listxattr((long)(path), (long)(list), \
(long)(size))
-#define __sanitizer_syscall_post_listxattr(res, path, list, size) \
- __sanitizer_syscall_post_impl_listxattr(res, (long)(path), (long)(list), \
+#define __sanitizer_syscall_post_listxattr(res, path, list, size) \
+ __sanitizer_syscall_post_impl_listxattr(res, (long)(path), (long)(list), \
(long)(size))
-#define __sanitizer_syscall_pre_llistxattr(path, list, size) \
- __sanitizer_syscall_pre_impl_llistxattr((long)(path), (long)(list), \
+#define __sanitizer_syscall_pre_llistxattr(path, list, size) \
+ __sanitizer_syscall_pre_impl_llistxattr((long)(path), (long)(list), \
(long)(size))
-#define __sanitizer_syscall_post_llistxattr(res, path, list, size) \
- __sanitizer_syscall_post_impl_llistxattr(res, (long)(path), (long)(list), \
+#define __sanitizer_syscall_post_llistxattr(res, path, list, size) \
+ __sanitizer_syscall_post_impl_llistxattr(res, (long)(path), (long)(list), \
(long)(size))
-#define __sanitizer_syscall_pre_flistxattr(fd, list, size) \
- __sanitizer_syscall_pre_impl_flistxattr((long)(fd), (long)(list), \
+#define __sanitizer_syscall_pre_flistxattr(fd, list, size) \
+ __sanitizer_syscall_pre_impl_flistxattr((long)(fd), (long)(list), \
(long)(size))
-#define __sanitizer_syscall_post_flistxattr(res, fd, list, size) \
- __sanitizer_syscall_post_impl_flistxattr(res, (long)(fd), (long)(list), \
+#define __sanitizer_syscall_post_flistxattr(res, fd, list, size) \
+ __sanitizer_syscall_post_impl_flistxattr(res, (long)(fd), (long)(list), \
(long)(size))
-#define __sanitizer_syscall_pre_removexattr(path, name) \
+#define __sanitizer_syscall_pre_removexattr(path, name) \
__sanitizer_syscall_pre_impl_removexattr((long)(path), (long)(name))
-#define __sanitizer_syscall_post_removexattr(res, path, name) \
+#define __sanitizer_syscall_post_removexattr(res, path, name) \
__sanitizer_syscall_post_impl_removexattr(res, (long)(path), (long)(name))
-#define __sanitizer_syscall_pre_lremovexattr(path, name) \
+#define __sanitizer_syscall_pre_lremovexattr(path, name) \
__sanitizer_syscall_pre_impl_lremovexattr((long)(path), (long)(name))
-#define __sanitizer_syscall_post_lremovexattr(res, path, name) \
+#define __sanitizer_syscall_post_lremovexattr(res, path, name) \
__sanitizer_syscall_post_impl_lremovexattr(res, (long)(path), (long)(name))
-#define __sanitizer_syscall_pre_fremovexattr(fd, name) \
+#define __sanitizer_syscall_pre_fremovexattr(fd, name) \
__sanitizer_syscall_pre_impl_fremovexattr((long)(fd), (long)(name))
-#define __sanitizer_syscall_post_fremovexattr(res, fd, name) \
+#define __sanitizer_syscall_post_fremovexattr(res, fd, name) \
__sanitizer_syscall_post_impl_fremovexattr(res, (long)(fd), (long)(name))
-#define __sanitizer_syscall_pre_brk(brk) \
+#define __sanitizer_syscall_pre_brk(brk) \
__sanitizer_syscall_pre_impl_brk((long)(brk))
-#define __sanitizer_syscall_post_brk(res, brk) \
+#define __sanitizer_syscall_post_brk(res, brk) \
__sanitizer_syscall_post_impl_brk(res, (long)(brk))
-#define __sanitizer_syscall_pre_mprotect(start, len, prot) \
- __sanitizer_syscall_pre_impl_mprotect((long)(start), (long)(len), \
+#define __sanitizer_syscall_pre_mprotect(start, len, prot) \
+ __sanitizer_syscall_pre_impl_mprotect((long)(start), (long)(len), \
(long)(prot))
-#define __sanitizer_syscall_post_mprotect(res, start, len, prot) \
- __sanitizer_syscall_post_impl_mprotect(res, (long)(start), (long)(len), \
+#define __sanitizer_syscall_post_mprotect(res, start, len, prot) \
+ __sanitizer_syscall_post_impl_mprotect(res, (long)(start), (long)(len), \
(long)(prot))
-#define __sanitizer_syscall_pre_mremap(addr, old_len, new_len, flags, \
- new_addr) \
- __sanitizer_syscall_pre_impl_mremap((long)(addr), (long)(old_len), \
- (long)(new_len), (long)(flags), \
+#define __sanitizer_syscall_pre_mremap(addr, old_len, new_len, flags, \
+ new_addr) \
+ __sanitizer_syscall_pre_impl_mremap((long)(addr), (long)(old_len), \
+ (long)(new_len), (long)(flags), \
(long)(new_addr))
-#define __sanitizer_syscall_post_mremap(res, addr, old_len, new_len, flags, \
- new_addr) \
- __sanitizer_syscall_post_impl_mremap(res, (long)(addr), (long)(old_len), \
- (long)(new_len), (long)(flags), \
+#define __sanitizer_syscall_post_mremap(res, addr, old_len, new_len, flags, \
+ new_addr) \
+ __sanitizer_syscall_post_impl_mremap(res, (long)(addr), (long)(old_len), \
+ (long)(new_len), (long)(flags), \
(long)(new_addr))
-#define __sanitizer_syscall_pre_remap_file_pages(start, size, prot, pgoff, \
- flags) \
- __sanitizer_syscall_pre_impl_remap_file_pages( \
+#define __sanitizer_syscall_pre_remap_file_pages(start, size, prot, pgoff, \
+ flags) \
+ __sanitizer_syscall_pre_impl_remap_file_pages( \
(long)(start), (long)(size), (long)(prot), (long)(pgoff), (long)(flags))
-#define __sanitizer_syscall_post_remap_file_pages(res, start, size, prot, \
- pgoff, flags) \
- __sanitizer_syscall_post_impl_remap_file_pages(res, (long)(start), \
- (long)(size), (long)(prot), \
+#define __sanitizer_syscall_post_remap_file_pages(res, start, size, prot, \
+ pgoff, flags) \
+ __sanitizer_syscall_post_impl_remap_file_pages(res, (long)(start), \
+ (long)(size), (long)(prot), \
(long)(pgoff), (long)(flags))
-#define __sanitizer_syscall_pre_msync(start, len, flags) \
+#define __sanitizer_syscall_pre_msync(start, len, flags) \
__sanitizer_syscall_pre_impl_msync((long)(start), (long)(len), (long)(flags))
-#define __sanitizer_syscall_post_msync(res, start, len, flags) \
- __sanitizer_syscall_post_impl_msync(res, (long)(start), (long)(len), \
+#define __sanitizer_syscall_post_msync(res, start, len, flags) \
+ __sanitizer_syscall_post_impl_msync(res, (long)(start), (long)(len), \
(long)(flags))
-#define __sanitizer_syscall_pre_munmap(addr, len) \
+#define __sanitizer_syscall_pre_munmap(addr, len) \
__sanitizer_syscall_pre_impl_munmap((long)(addr), (long)(len))
-#define __sanitizer_syscall_post_munmap(res, addr, len) \
+#define __sanitizer_syscall_post_munmap(res, addr, len) \
__sanitizer_syscall_post_impl_munmap(res, (long)(addr), (long)(len))
-#define __sanitizer_syscall_pre_mlock(start, len) \
+#define __sanitizer_syscall_pre_mlock(start, len) \
__sanitizer_syscall_pre_impl_mlock((long)(start), (long)(len))
-#define __sanitizer_syscall_post_mlock(res, start, len) \
+#define __sanitizer_syscall_post_mlock(res, start, len) \
__sanitizer_syscall_post_impl_mlock(res, (long)(start), (long)(len))
-#define __sanitizer_syscall_pre_munlock(start, len) \
+#define __sanitizer_syscall_pre_munlock(start, len) \
__sanitizer_syscall_pre_impl_munlock((long)(start), (long)(len))
-#define __sanitizer_syscall_post_munlock(res, start, len) \
+#define __sanitizer_syscall_post_munlock(res, start, len) \
__sanitizer_syscall_post_impl_munlock(res, (long)(start), (long)(len))
-#define __sanitizer_syscall_pre_mlockall(flags) \
+#define __sanitizer_syscall_pre_mlockall(flags) \
__sanitizer_syscall_pre_impl_mlockall((long)(flags))
-#define __sanitizer_syscall_post_mlockall(res, flags) \
+#define __sanitizer_syscall_post_mlockall(res, flags) \
__sanitizer_syscall_post_impl_mlockall(res, (long)(flags))
-#define __sanitizer_syscall_pre_munlockall() \
+#define __sanitizer_syscall_pre_munlockall() \
__sanitizer_syscall_pre_impl_munlockall()
-#define __sanitizer_syscall_post_munlockall(res) \
+#define __sanitizer_syscall_post_munlockall(res) \
__sanitizer_syscall_post_impl_munlockall(res)
-#define __sanitizer_syscall_pre_madvise(start, len, behavior) \
- __sanitizer_syscall_pre_impl_madvise((long)(start), (long)(len), \
+#define __sanitizer_syscall_pre_madvise(start, len, behavior) \
+ __sanitizer_syscall_pre_impl_madvise((long)(start), (long)(len), \
(long)(behavior))
-#define __sanitizer_syscall_post_madvise(res, start, len, behavior) \
- __sanitizer_syscall_post_impl_madvise(res, (long)(start), (long)(len), \
+#define __sanitizer_syscall_post_madvise(res, start, len, behavior) \
+ __sanitizer_syscall_post_impl_madvise(res, (long)(start), (long)(len), \
(long)(behavior))
-#define __sanitizer_syscall_pre_mincore(start, len, vec) \
+#define __sanitizer_syscall_pre_mincore(start, len, vec) \
__sanitizer_syscall_pre_impl_mincore((long)(start), (long)(len), (long)(vec))
-#define __sanitizer_syscall_post_mincore(res, start, len, vec) \
- __sanitizer_syscall_post_impl_mincore(res, (long)(start), (long)(len), \
+#define __sanitizer_syscall_post_mincore(res, start, len, vec) \
+ __sanitizer_syscall_post_impl_mincore(res, (long)(start), (long)(len), \
(long)(vec))
-#define __sanitizer_syscall_pre_pivot_root(new_root, put_old) \
+#define __sanitizer_syscall_pre_pivot_root(new_root, put_old) \
__sanitizer_syscall_pre_impl_pivot_root((long)(new_root), (long)(put_old))
-#define __sanitizer_syscall_post_pivot_root(res, new_root, put_old) \
- __sanitizer_syscall_post_impl_pivot_root(res, (long)(new_root), \
+#define __sanitizer_syscall_post_pivot_root(res, new_root, put_old) \
+ __sanitizer_syscall_post_impl_pivot_root(res, (long)(new_root), \
(long)(put_old))
-#define __sanitizer_syscall_pre_chroot(filename) \
+#define __sanitizer_syscall_pre_chroot(filename) \
__sanitizer_syscall_pre_impl_chroot((long)(filename))
-#define __sanitizer_syscall_post_chroot(res, filename) \
+#define __sanitizer_syscall_post_chroot(res, filename) \
__sanitizer_syscall_post_impl_chroot(res, (long)(filename))
-#define __sanitizer_syscall_pre_mknod(filename, mode, dev) \
- __sanitizer_syscall_pre_impl_mknod((long)(filename), (long)(mode), \
+#define __sanitizer_syscall_pre_mknod(filename, mode, dev) \
+ __sanitizer_syscall_pre_impl_mknod((long)(filename), (long)(mode), \
(long)(dev))
-#define __sanitizer_syscall_post_mknod(res, filename, mode, dev) \
- __sanitizer_syscall_post_impl_mknod(res, (long)(filename), (long)(mode), \
+#define __sanitizer_syscall_post_mknod(res, filename, mode, dev) \
+ __sanitizer_syscall_post_impl_mknod(res, (long)(filename), (long)(mode), \
(long)(dev))
-#define __sanitizer_syscall_pre_link(oldname, newname) \
+#define __sanitizer_syscall_pre_link(oldname, newname) \
__sanitizer_syscall_pre_impl_link((long)(oldname), (long)(newname))
-#define __sanitizer_syscall_post_link(res, oldname, newname) \
+#define __sanitizer_syscall_post_link(res, oldname, newname) \
__sanitizer_syscall_post_impl_link(res, (long)(oldname), (long)(newname))
-#define __sanitizer_syscall_pre_symlink(old, new_) \
+#define __sanitizer_syscall_pre_symlink(old, new_) \
__sanitizer_syscall_pre_impl_symlink((long)(old), (long)(new_))
-#define __sanitizer_syscall_post_symlink(res, old, new_) \
+#define __sanitizer_syscall_post_symlink(res, old, new_) \
__sanitizer_syscall_post_impl_symlink(res, (long)(old), (long)(new_))
-#define __sanitizer_syscall_pre_unlink(pathname) \
+#define __sanitizer_syscall_pre_unlink(pathname) \
__sanitizer_syscall_pre_impl_unlink((long)(pathname))
-#define __sanitizer_syscall_post_unlink(res, pathname) \
+#define __sanitizer_syscall_post_unlink(res, pathname) \
__sanitizer_syscall_post_impl_unlink(res, (long)(pathname))
-#define __sanitizer_syscall_pre_rename(oldname, newname) \
+#define __sanitizer_syscall_pre_rename(oldname, newname) \
__sanitizer_syscall_pre_impl_rename((long)(oldname), (long)(newname))
-#define __sanitizer_syscall_post_rename(res, oldname, newname) \
+#define __sanitizer_syscall_post_rename(res, oldname, newname) \
__sanitizer_syscall_post_impl_rename(res, (long)(oldname), (long)(newname))
-#define __sanitizer_syscall_pre_chmod(filename, mode) \
+#define __sanitizer_syscall_pre_chmod(filename, mode) \
__sanitizer_syscall_pre_impl_chmod((long)(filename), (long)(mode))
-#define __sanitizer_syscall_post_chmod(res, filename, mode) \
+#define __sanitizer_syscall_post_chmod(res, filename, mode) \
__sanitizer_syscall_post_impl_chmod(res, (long)(filename), (long)(mode))
-#define __sanitizer_syscall_pre_fchmod(fd, mode) \
+#define __sanitizer_syscall_pre_fchmod(fd, mode) \
__sanitizer_syscall_pre_impl_fchmod((long)(fd), (long)(mode))
-#define __sanitizer_syscall_post_fchmod(res, fd, mode) \
+#define __sanitizer_syscall_post_fchmod(res, fd, mode) \
__sanitizer_syscall_post_impl_fchmod(res, (long)(fd), (long)(mode))
-#define __sanitizer_syscall_pre_fcntl(fd, cmd, arg) \
+#define __sanitizer_syscall_pre_fcntl(fd, cmd, arg) \
__sanitizer_syscall_pre_impl_fcntl((long)(fd), (long)(cmd), (long)(arg))
-#define __sanitizer_syscall_post_fcntl(res, fd, cmd, arg) \
+#define __sanitizer_syscall_post_fcntl(res, fd, cmd, arg) \
__sanitizer_syscall_post_impl_fcntl(res, (long)(fd), (long)(cmd), (long)(arg))
-#define __sanitizer_syscall_pre_fcntl64(fd, cmd, arg) \
+#define __sanitizer_syscall_pre_fcntl64(fd, cmd, arg) \
__sanitizer_syscall_pre_impl_fcntl64((long)(fd), (long)(cmd), (long)(arg))
-#define __sanitizer_syscall_post_fcntl64(res, fd, cmd, arg) \
- __sanitizer_syscall_post_impl_fcntl64(res, (long)(fd), (long)(cmd), \
+#define __sanitizer_syscall_post_fcntl64(res, fd, cmd, arg) \
+ __sanitizer_syscall_post_impl_fcntl64(res, (long)(fd), (long)(cmd), \
(long)(arg))
-#define __sanitizer_syscall_pre_pipe(fildes) \
+#define __sanitizer_syscall_pre_pipe(fildes) \
__sanitizer_syscall_pre_impl_pipe((long)(fildes))
-#define __sanitizer_syscall_post_pipe(res, fildes) \
+#define __sanitizer_syscall_post_pipe(res, fildes) \
__sanitizer_syscall_post_impl_pipe(res, (long)(fildes))
-#define __sanitizer_syscall_pre_pipe2(fildes, flags) \
+#define __sanitizer_syscall_pre_pipe2(fildes, flags) \
__sanitizer_syscall_pre_impl_pipe2((long)(fildes), (long)(flags))
-#define __sanitizer_syscall_post_pipe2(res, fildes, flags) \
+#define __sanitizer_syscall_post_pipe2(res, fildes, flags) \
__sanitizer_syscall_post_impl_pipe2(res, (long)(fildes), (long)(flags))
-#define __sanitizer_syscall_pre_dup(fildes) \
+#define __sanitizer_syscall_pre_dup(fildes) \
__sanitizer_syscall_pre_impl_dup((long)(fildes))
-#define __sanitizer_syscall_post_dup(res, fildes) \
+#define __sanitizer_syscall_post_dup(res, fildes) \
__sanitizer_syscall_post_impl_dup(res, (long)(fildes))
-#define __sanitizer_syscall_pre_dup2(oldfd, newfd) \
+#define __sanitizer_syscall_pre_dup2(oldfd, newfd) \
__sanitizer_syscall_pre_impl_dup2((long)(oldfd), (long)(newfd))
-#define __sanitizer_syscall_post_dup2(res, oldfd, newfd) \
+#define __sanitizer_syscall_post_dup2(res, oldfd, newfd) \
__sanitizer_syscall_post_impl_dup2(res, (long)(oldfd), (long)(newfd))
-#define __sanitizer_syscall_pre_dup3(oldfd, newfd, flags) \
+#define __sanitizer_syscall_pre_dup3(oldfd, newfd, flags) \
__sanitizer_syscall_pre_impl_dup3((long)(oldfd), (long)(newfd), (long)(flags))
-#define __sanitizer_syscall_post_dup3(res, oldfd, newfd, flags) \
- __sanitizer_syscall_post_impl_dup3(res, (long)(oldfd), (long)(newfd), \
+#define __sanitizer_syscall_post_dup3(res, oldfd, newfd, flags) \
+ __sanitizer_syscall_post_impl_dup3(res, (long)(oldfd), (long)(newfd), \
(long)(flags))
-#define __sanitizer_syscall_pre_ioperm(from, num, on) \
+#define __sanitizer_syscall_pre_ioperm(from, num, on) \
__sanitizer_syscall_pre_impl_ioperm((long)(from), (long)(num), (long)(on))
-#define __sanitizer_syscall_post_ioperm(res, from, num, on) \
- __sanitizer_syscall_post_impl_ioperm(res, (long)(from), (long)(num), \
+#define __sanitizer_syscall_post_ioperm(res, from, num, on) \
+ __sanitizer_syscall_post_impl_ioperm(res, (long)(from), (long)(num), \
(long)(on))
-#define __sanitizer_syscall_pre_ioctl(fd, cmd, arg) \
+#define __sanitizer_syscall_pre_ioctl(fd, cmd, arg) \
__sanitizer_syscall_pre_impl_ioctl((long)(fd), (long)(cmd), (long)(arg))
-#define __sanitizer_syscall_post_ioctl(res, fd, cmd, arg) \
+#define __sanitizer_syscall_post_ioctl(res, fd, cmd, arg) \
__sanitizer_syscall_post_impl_ioctl(res, (long)(fd), (long)(cmd), (long)(arg))
-#define __sanitizer_syscall_pre_flock(fd, cmd) \
+#define __sanitizer_syscall_pre_flock(fd, cmd) \
__sanitizer_syscall_pre_impl_flock((long)(fd), (long)(cmd))
-#define __sanitizer_syscall_post_flock(res, fd, cmd) \
+#define __sanitizer_syscall_post_flock(res, fd, cmd) \
__sanitizer_syscall_post_impl_flock(res, (long)(fd), (long)(cmd))
-#define __sanitizer_syscall_pre_io_setup(nr_reqs, ctx) \
+#define __sanitizer_syscall_pre_io_setup(nr_reqs, ctx) \
__sanitizer_syscall_pre_impl_io_setup((long)(nr_reqs), (long)(ctx))
-#define __sanitizer_syscall_post_io_setup(res, nr_reqs, ctx) \
+#define __sanitizer_syscall_post_io_setup(res, nr_reqs, ctx) \
__sanitizer_syscall_post_impl_io_setup(res, (long)(nr_reqs), (long)(ctx))
-#define __sanitizer_syscall_pre_io_destroy(ctx) \
+#define __sanitizer_syscall_pre_io_destroy(ctx) \
__sanitizer_syscall_pre_impl_io_destroy((long)(ctx))
-#define __sanitizer_syscall_post_io_destroy(res, ctx) \
+#define __sanitizer_syscall_post_io_destroy(res, ctx) \
__sanitizer_syscall_post_impl_io_destroy(res, (long)(ctx))
-#define __sanitizer_syscall_pre_io_getevents(ctx_id, min_nr, nr, events, \
- timeout) \
- __sanitizer_syscall_pre_impl_io_getevents((long)(ctx_id), (long)(min_nr), \
- (long)(nr), (long)(events), \
+#define __sanitizer_syscall_pre_io_getevents(ctx_id, min_nr, nr, events, \
+ timeout) \
+ __sanitizer_syscall_pre_impl_io_getevents((long)(ctx_id), (long)(min_nr), \
+ (long)(nr), (long)(events), \
(long)(timeout))
#define __sanitizer_syscall_post_io_getevents(res, ctx_id, min_nr, nr, events, \
timeout) \
__sanitizer_syscall_post_impl_io_getevents(res, (long)(ctx_id), \
(long)(min_nr), (long)(nr), \
(long)(events), (long)(timeout))
-#define __sanitizer_syscall_pre_io_submit(ctx_id, arg1, arg2) \
- __sanitizer_syscall_pre_impl_io_submit((long)(ctx_id), (long)(arg1), \
+#define __sanitizer_syscall_pre_io_submit(ctx_id, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_io_submit((long)(ctx_id), (long)(arg1), \
(long)(arg2))
-#define __sanitizer_syscall_post_io_submit(res, ctx_id, arg1, arg2) \
- __sanitizer_syscall_post_impl_io_submit(res, (long)(ctx_id), (long)(arg1), \
+#define __sanitizer_syscall_post_io_submit(res, ctx_id, arg1, arg2) \
+ __sanitizer_syscall_post_impl_io_submit(res, (long)(ctx_id), (long)(arg1), \
(long)(arg2))
-#define __sanitizer_syscall_pre_io_cancel(ctx_id, iocb, result) \
- __sanitizer_syscall_pre_impl_io_cancel((long)(ctx_id), (long)(iocb), \
+#define __sanitizer_syscall_pre_io_cancel(ctx_id, iocb, result) \
+ __sanitizer_syscall_pre_impl_io_cancel((long)(ctx_id), (long)(iocb), \
(long)(result))
-#define __sanitizer_syscall_post_io_cancel(res, ctx_id, iocb, result) \
- __sanitizer_syscall_post_impl_io_cancel(res, (long)(ctx_id), (long)(iocb), \
+#define __sanitizer_syscall_post_io_cancel(res, ctx_id, iocb, result) \
+ __sanitizer_syscall_post_impl_io_cancel(res, (long)(ctx_id), (long)(iocb), \
(long)(result))
-#define __sanitizer_syscall_pre_sendfile(out_fd, in_fd, offset, count) \
- __sanitizer_syscall_pre_impl_sendfile((long)(out_fd), (long)(in_fd), \
+#define __sanitizer_syscall_pre_sendfile(out_fd, in_fd, offset, count) \
+ __sanitizer_syscall_pre_impl_sendfile((long)(out_fd), (long)(in_fd), \
(long)(offset), (long)(count))
-#define __sanitizer_syscall_post_sendfile(res, out_fd, in_fd, offset, count) \
- __sanitizer_syscall_post_impl_sendfile(res, (long)(out_fd), (long)(in_fd), \
+#define __sanitizer_syscall_post_sendfile(res, out_fd, in_fd, offset, count) \
+ __sanitizer_syscall_post_impl_sendfile(res, (long)(out_fd), (long)(in_fd), \
(long)(offset), (long)(count))
-#define __sanitizer_syscall_pre_sendfile64(out_fd, in_fd, offset, count) \
- __sanitizer_syscall_pre_impl_sendfile64((long)(out_fd), (long)(in_fd), \
+#define __sanitizer_syscall_pre_sendfile64(out_fd, in_fd, offset, count) \
+ __sanitizer_syscall_pre_impl_sendfile64((long)(out_fd), (long)(in_fd), \
(long)(offset), (long)(count))
#define __sanitizer_syscall_post_sendfile64(res, out_fd, in_fd, offset, count) \
__sanitizer_syscall_post_impl_sendfile64(res, (long)(out_fd), (long)(in_fd), \
(long)(offset), (long)(count))
-#define __sanitizer_syscall_pre_readlink(path, buf, bufsiz) \
- __sanitizer_syscall_pre_impl_readlink((long)(path), (long)(buf), \
+#define __sanitizer_syscall_pre_readlink(path, buf, bufsiz) \
+ __sanitizer_syscall_pre_impl_readlink((long)(path), (long)(buf), \
(long)(bufsiz))
-#define __sanitizer_syscall_post_readlink(res, path, buf, bufsiz) \
- __sanitizer_syscall_post_impl_readlink(res, (long)(path), (long)(buf), \
+#define __sanitizer_syscall_post_readlink(res, path, buf, bufsiz) \
+ __sanitizer_syscall_post_impl_readlink(res, (long)(path), (long)(buf), \
(long)(bufsiz))
-#define __sanitizer_syscall_pre_creat(pathname, mode) \
+#define __sanitizer_syscall_pre_creat(pathname, mode) \
__sanitizer_syscall_pre_impl_creat((long)(pathname), (long)(mode))
-#define __sanitizer_syscall_post_creat(res, pathname, mode) \
+#define __sanitizer_syscall_post_creat(res, pathname, mode) \
__sanitizer_syscall_post_impl_creat(res, (long)(pathname), (long)(mode))
-#define __sanitizer_syscall_pre_open(filename, flags, mode) \
- __sanitizer_syscall_pre_impl_open((long)(filename), (long)(flags), \
+#define __sanitizer_syscall_pre_open(filename, flags, mode) \
+ __sanitizer_syscall_pre_impl_open((long)(filename), (long)(flags), \
(long)(mode))
-#define __sanitizer_syscall_post_open(res, filename, flags, mode) \
- __sanitizer_syscall_post_impl_open(res, (long)(filename), (long)(flags), \
+#define __sanitizer_syscall_post_open(res, filename, flags, mode) \
+ __sanitizer_syscall_post_impl_open(res, (long)(filename), (long)(flags), \
(long)(mode))
-#define __sanitizer_syscall_pre_close(fd) \
+#define __sanitizer_syscall_pre_close(fd) \
__sanitizer_syscall_pre_impl_close((long)(fd))
-#define __sanitizer_syscall_post_close(res, fd) \
+#define __sanitizer_syscall_post_close(res, fd) \
__sanitizer_syscall_post_impl_close(res, (long)(fd))
-#define __sanitizer_syscall_pre_access(filename, mode) \
+#define __sanitizer_syscall_pre_access(filename, mode) \
__sanitizer_syscall_pre_impl_access((long)(filename), (long)(mode))
-#define __sanitizer_syscall_post_access(res, filename, mode) \
+#define __sanitizer_syscall_post_access(res, filename, mode) \
__sanitizer_syscall_post_impl_access(res, (long)(filename), (long)(mode))
#define __sanitizer_syscall_pre_vhangup() __sanitizer_syscall_pre_impl_vhangup()
-#define __sanitizer_syscall_post_vhangup(res) \
+#define __sanitizer_syscall_post_vhangup(res) \
__sanitizer_syscall_post_impl_vhangup(res)
-#define __sanitizer_syscall_pre_chown(filename, user, group) \
- __sanitizer_syscall_pre_impl_chown((long)(filename), (long)(user), \
+#define __sanitizer_syscall_pre_chown(filename, user, group) \
+ __sanitizer_syscall_pre_impl_chown((long)(filename), (long)(user), \
(long)(group))
-#define __sanitizer_syscall_post_chown(res, filename, user, group) \
- __sanitizer_syscall_post_impl_chown(res, (long)(filename), (long)(user), \
+#define __sanitizer_syscall_post_chown(res, filename, user, group) \
+ __sanitizer_syscall_post_impl_chown(res, (long)(filename), (long)(user), \
(long)(group))
-#define __sanitizer_syscall_pre_lchown(filename, user, group) \
- __sanitizer_syscall_pre_impl_lchown((long)(filename), (long)(user), \
+#define __sanitizer_syscall_pre_lchown(filename, user, group) \
+ __sanitizer_syscall_pre_impl_lchown((long)(filename), (long)(user), \
(long)(group))
-#define __sanitizer_syscall_post_lchown(res, filename, user, group) \
- __sanitizer_syscall_post_impl_lchown(res, (long)(filename), (long)(user), \
+#define __sanitizer_syscall_post_lchown(res, filename, user, group) \
+ __sanitizer_syscall_post_impl_lchown(res, (long)(filename), (long)(user), \
(long)(group))
-#define __sanitizer_syscall_pre_fchown(fd, user, group) \
+#define __sanitizer_syscall_pre_fchown(fd, user, group) \
__sanitizer_syscall_pre_impl_fchown((long)(fd), (long)(user), (long)(group))
-#define __sanitizer_syscall_post_fchown(res, fd, user, group) \
- __sanitizer_syscall_post_impl_fchown(res, (long)(fd), (long)(user), \
+#define __sanitizer_syscall_post_fchown(res, fd, user, group) \
+ __sanitizer_syscall_post_impl_fchown(res, (long)(fd), (long)(user), \
(long)(group))
-#define __sanitizer_syscall_pre_chown16(filename, user, group) \
- __sanitizer_syscall_pre_impl_chown16((long)(filename), (long)user, \
+#define __sanitizer_syscall_pre_chown16(filename, user, group) \
+ __sanitizer_syscall_pre_impl_chown16((long)(filename), (long)user, \
(long)group)
-#define __sanitizer_syscall_post_chown16(res, filename, user, group) \
- __sanitizer_syscall_post_impl_chown16(res, (long)(filename), (long)user, \
+#define __sanitizer_syscall_post_chown16(res, filename, user, group) \
+ __sanitizer_syscall_post_impl_chown16(res, (long)(filename), (long)user, \
(long)group)
-#define __sanitizer_syscall_pre_lchown16(filename, user, group) \
- __sanitizer_syscall_pre_impl_lchown16((long)(filename), (long)user, \
+#define __sanitizer_syscall_pre_lchown16(filename, user, group) \
+ __sanitizer_syscall_pre_impl_lchown16((long)(filename), (long)user, \
(long)group)
-#define __sanitizer_syscall_post_lchown16(res, filename, user, group) \
- __sanitizer_syscall_post_impl_lchown16(res, (long)(filename), (long)user, \
+#define __sanitizer_syscall_post_lchown16(res, filename, user, group) \
+ __sanitizer_syscall_post_impl_lchown16(res, (long)(filename), (long)user, \
(long)group)
-#define __sanitizer_syscall_pre_fchown16(fd, user, group) \
+#define __sanitizer_syscall_pre_fchown16(fd, user, group) \
__sanitizer_syscall_pre_impl_fchown16((long)(fd), (long)user, (long)group)
-#define __sanitizer_syscall_post_fchown16(res, fd, user, group) \
- __sanitizer_syscall_post_impl_fchown16(res, (long)(fd), (long)user, \
+#define __sanitizer_syscall_post_fchown16(res, fd, user, group) \
+ __sanitizer_syscall_post_impl_fchown16(res, (long)(fd), (long)user, \
(long)group)
-#define __sanitizer_syscall_pre_setregid16(rgid, egid) \
+#define __sanitizer_syscall_pre_setregid16(rgid, egid) \
__sanitizer_syscall_pre_impl_setregid16((long)rgid, (long)egid)
-#define __sanitizer_syscall_post_setregid16(res, rgid, egid) \
+#define __sanitizer_syscall_post_setregid16(res, rgid, egid) \
__sanitizer_syscall_post_impl_setregid16(res, (long)rgid, (long)egid)
-#define __sanitizer_syscall_pre_setgid16(gid) \
+#define __sanitizer_syscall_pre_setgid16(gid) \
__sanitizer_syscall_pre_impl_setgid16((long)gid)
-#define __sanitizer_syscall_post_setgid16(res, gid) \
+#define __sanitizer_syscall_post_setgid16(res, gid) \
__sanitizer_syscall_post_impl_setgid16(res, (long)gid)
-#define __sanitizer_syscall_pre_setreuid16(ruid, euid) \
+#define __sanitizer_syscall_pre_setreuid16(ruid, euid) \
__sanitizer_syscall_pre_impl_setreuid16((long)ruid, (long)euid)
-#define __sanitizer_syscall_post_setreuid16(res, ruid, euid) \
+#define __sanitizer_syscall_post_setreuid16(res, ruid, euid) \
__sanitizer_syscall_post_impl_setreuid16(res, (long)ruid, (long)euid)
-#define __sanitizer_syscall_pre_setuid16(uid) \
+#define __sanitizer_syscall_pre_setuid16(uid) \
__sanitizer_syscall_pre_impl_setuid16((long)uid)
-#define __sanitizer_syscall_post_setuid16(res, uid) \
+#define __sanitizer_syscall_post_setuid16(res, uid) \
__sanitizer_syscall_post_impl_setuid16(res, (long)uid)
-#define __sanitizer_syscall_pre_setresuid16(ruid, euid, suid) \
+#define __sanitizer_syscall_pre_setresuid16(ruid, euid, suid) \
__sanitizer_syscall_pre_impl_setresuid16((long)ruid, (long)euid, (long)suid)
-#define __sanitizer_syscall_post_setresuid16(res, ruid, euid, suid) \
- __sanitizer_syscall_post_impl_setresuid16(res, (long)ruid, (long)euid, \
+#define __sanitizer_syscall_post_setresuid16(res, ruid, euid, suid) \
+ __sanitizer_syscall_post_impl_setresuid16(res, (long)ruid, (long)euid, \
(long)suid)
-#define __sanitizer_syscall_pre_getresuid16(ruid, euid, suid) \
- __sanitizer_syscall_pre_impl_getresuid16((long)(ruid), (long)(euid), \
+#define __sanitizer_syscall_pre_getresuid16(ruid, euid, suid) \
+ __sanitizer_syscall_pre_impl_getresuid16((long)(ruid), (long)(euid), \
(long)(suid))
-#define __sanitizer_syscall_post_getresuid16(res, ruid, euid, suid) \
- __sanitizer_syscall_post_impl_getresuid16(res, (long)(ruid), (long)(euid), \
+#define __sanitizer_syscall_post_getresuid16(res, ruid, euid, suid) \
+ __sanitizer_syscall_post_impl_getresuid16(res, (long)(ruid), (long)(euid), \
(long)(suid))
-#define __sanitizer_syscall_pre_setresgid16(rgid, egid, sgid) \
+#define __sanitizer_syscall_pre_setresgid16(rgid, egid, sgid) \
__sanitizer_syscall_pre_impl_setresgid16((long)rgid, (long)egid, (long)sgid)
-#define __sanitizer_syscall_post_setresgid16(res, rgid, egid, sgid) \
- __sanitizer_syscall_post_impl_setresgid16(res, (long)rgid, (long)egid, \
+#define __sanitizer_syscall_post_setresgid16(res, rgid, egid, sgid) \
+ __sanitizer_syscall_post_impl_setresgid16(res, (long)rgid, (long)egid, \
(long)sgid)
-#define __sanitizer_syscall_pre_getresgid16(rgid, egid, sgid) \
- __sanitizer_syscall_pre_impl_getresgid16((long)(rgid), (long)(egid), \
+#define __sanitizer_syscall_pre_getresgid16(rgid, egid, sgid) \
+ __sanitizer_syscall_pre_impl_getresgid16((long)(rgid), (long)(egid), \
(long)(sgid))
-#define __sanitizer_syscall_post_getresgid16(res, rgid, egid, sgid) \
- __sanitizer_syscall_post_impl_getresgid16(res, (long)(rgid), (long)(egid), \
+#define __sanitizer_syscall_post_getresgid16(res, rgid, egid, sgid) \
+ __sanitizer_syscall_post_impl_getresgid16(res, (long)(rgid), (long)(egid), \
(long)(sgid))
-#define __sanitizer_syscall_pre_setfsuid16(uid) \
+#define __sanitizer_syscall_pre_setfsuid16(uid) \
__sanitizer_syscall_pre_impl_setfsuid16((long)uid)
-#define __sanitizer_syscall_post_setfsuid16(res, uid) \
+#define __sanitizer_syscall_post_setfsuid16(res, uid) \
__sanitizer_syscall_post_impl_setfsuid16(res, (long)uid)
-#define __sanitizer_syscall_pre_setfsgid16(gid) \
+#define __sanitizer_syscall_pre_setfsgid16(gid) \
__sanitizer_syscall_pre_impl_setfsgid16((long)gid)
-#define __sanitizer_syscall_post_setfsgid16(res, gid) \
+#define __sanitizer_syscall_post_setfsgid16(res, gid) \
__sanitizer_syscall_post_impl_setfsgid16(res, (long)gid)
-#define __sanitizer_syscall_pre_getgroups16(gidsetsize, grouplist) \
- __sanitizer_syscall_pre_impl_getgroups16((long)(gidsetsize), \
+#define __sanitizer_syscall_pre_getgroups16(gidsetsize, grouplist) \
+ __sanitizer_syscall_pre_impl_getgroups16((long)(gidsetsize), \
(long)(grouplist))
-#define __sanitizer_syscall_post_getgroups16(res, gidsetsize, grouplist) \
- __sanitizer_syscall_post_impl_getgroups16(res, (long)(gidsetsize), \
+#define __sanitizer_syscall_post_getgroups16(res, gidsetsize, grouplist) \
+ __sanitizer_syscall_post_impl_getgroups16(res, (long)(gidsetsize), \
(long)(grouplist))
-#define __sanitizer_syscall_pre_setgroups16(gidsetsize, grouplist) \
- __sanitizer_syscall_pre_impl_setgroups16((long)(gidsetsize), \
+#define __sanitizer_syscall_pre_setgroups16(gidsetsize, grouplist) \
+ __sanitizer_syscall_pre_impl_setgroups16((long)(gidsetsize), \
(long)(grouplist))
-#define __sanitizer_syscall_post_setgroups16(res, gidsetsize, grouplist) \
- __sanitizer_syscall_post_impl_setgroups16(res, (long)(gidsetsize), \
+#define __sanitizer_syscall_post_setgroups16(res, gidsetsize, grouplist) \
+ __sanitizer_syscall_post_impl_setgroups16(res, (long)(gidsetsize), \
(long)(grouplist))
-#define __sanitizer_syscall_pre_getuid16() \
+#define __sanitizer_syscall_pre_getuid16() \
__sanitizer_syscall_pre_impl_getuid16()
-#define __sanitizer_syscall_post_getuid16(res) \
+#define __sanitizer_syscall_post_getuid16(res) \
__sanitizer_syscall_post_impl_getuid16(res)
-#define __sanitizer_syscall_pre_geteuid16() \
+#define __sanitizer_syscall_pre_geteuid16() \
__sanitizer_syscall_pre_impl_geteuid16()
-#define __sanitizer_syscall_post_geteuid16(res) \
+#define __sanitizer_syscall_post_geteuid16(res) \
__sanitizer_syscall_post_impl_geteuid16(res)
-#define __sanitizer_syscall_pre_getgid16() \
+#define __sanitizer_syscall_pre_getgid16() \
__sanitizer_syscall_pre_impl_getgid16()
-#define __sanitizer_syscall_post_getgid16(res) \
+#define __sanitizer_syscall_post_getgid16(res) \
__sanitizer_syscall_post_impl_getgid16(res)
-#define __sanitizer_syscall_pre_getegid16() \
+#define __sanitizer_syscall_pre_getegid16() \
__sanitizer_syscall_pre_impl_getegid16()
-#define __sanitizer_syscall_post_getegid16(res) \
+#define __sanitizer_syscall_post_getegid16(res) \
__sanitizer_syscall_post_impl_getegid16(res)
-#define __sanitizer_syscall_pre_utime(filename, times) \
+#define __sanitizer_syscall_pre_utime(filename, times) \
__sanitizer_syscall_pre_impl_utime((long)(filename), (long)(times))
-#define __sanitizer_syscall_post_utime(res, filename, times) \
+#define __sanitizer_syscall_post_utime(res, filename, times) \
__sanitizer_syscall_post_impl_utime(res, (long)(filename), (long)(times))
-#define __sanitizer_syscall_pre_utimes(filename, utimes) \
+#define __sanitizer_syscall_pre_utimes(filename, utimes) \
__sanitizer_syscall_pre_impl_utimes((long)(filename), (long)(utimes))
-#define __sanitizer_syscall_post_utimes(res, filename, utimes) \
+#define __sanitizer_syscall_post_utimes(res, filename, utimes) \
__sanitizer_syscall_post_impl_utimes(res, (long)(filename), (long)(utimes))
-#define __sanitizer_syscall_pre_lseek(fd, offset, origin) \
+#define __sanitizer_syscall_pre_lseek(fd, offset, origin) \
__sanitizer_syscall_pre_impl_lseek((long)(fd), (long)(offset), (long)(origin))
-#define __sanitizer_syscall_post_lseek(res, fd, offset, origin) \
- __sanitizer_syscall_post_impl_lseek(res, (long)(fd), (long)(offset), \
+#define __sanitizer_syscall_post_lseek(res, fd, offset, origin) \
+ __sanitizer_syscall_post_impl_lseek(res, (long)(fd), (long)(offset), \
(long)(origin))
-#define __sanitizer_syscall_pre_llseek(fd, offset_high, offset_low, result, \
- origin) \
- __sanitizer_syscall_pre_impl_llseek((long)(fd), (long)(offset_high), \
- (long)(offset_low), (long)(result), \
+#define __sanitizer_syscall_pre_llseek(fd, offset_high, offset_low, result, \
+ origin) \
+ __sanitizer_syscall_pre_impl_llseek((long)(fd), (long)(offset_high), \
+ (long)(offset_low), (long)(result), \
(long)(origin))
-#define __sanitizer_syscall_post_llseek(res, fd, offset_high, offset_low, \
- result, origin) \
- __sanitizer_syscall_post_impl_llseek(res, (long)(fd), (long)(offset_high), \
- (long)(offset_low), (long)(result), \
+#define __sanitizer_syscall_post_llseek(res, fd, offset_high, offset_low, \
+ result, origin) \
+ __sanitizer_syscall_post_impl_llseek(res, (long)(fd), (long)(offset_high), \
+ (long)(offset_low), (long)(result), \
(long)(origin))
-#define __sanitizer_syscall_pre_read(fd, buf, count) \
+#define __sanitizer_syscall_pre_read(fd, buf, count) \
__sanitizer_syscall_pre_impl_read((long)(fd), (long)(buf), (long)(count))
-#define __sanitizer_syscall_post_read(res, fd, buf, count) \
- __sanitizer_syscall_post_impl_read(res, (long)(fd), (long)(buf), \
+#define __sanitizer_syscall_post_read(res, fd, buf, count) \
+ __sanitizer_syscall_post_impl_read(res, (long)(fd), (long)(buf), \
(long)(count))
-#define __sanitizer_syscall_pre_readv(fd, vec, vlen) \
+#define __sanitizer_syscall_pre_readv(fd, vec, vlen) \
__sanitizer_syscall_pre_impl_readv((long)(fd), (long)(vec), (long)(vlen))
-#define __sanitizer_syscall_post_readv(res, fd, vec, vlen) \
- __sanitizer_syscall_post_impl_readv(res, (long)(fd), (long)(vec), \
+#define __sanitizer_syscall_post_readv(res, fd, vec, vlen) \
+ __sanitizer_syscall_post_impl_readv(res, (long)(fd), (long)(vec), \
(long)(vlen))
-#define __sanitizer_syscall_pre_write(fd, buf, count) \
+#define __sanitizer_syscall_pre_write(fd, buf, count) \
__sanitizer_syscall_pre_impl_write((long)(fd), (long)(buf), (long)(count))
-#define __sanitizer_syscall_post_write(res, fd, buf, count) \
- __sanitizer_syscall_post_impl_write(res, (long)(fd), (long)(buf), \
+#define __sanitizer_syscall_post_write(res, fd, buf, count) \
+ __sanitizer_syscall_post_impl_write(res, (long)(fd), (long)(buf), \
(long)(count))
-#define __sanitizer_syscall_pre_writev(fd, vec, vlen) \
+#define __sanitizer_syscall_pre_writev(fd, vec, vlen) \
__sanitizer_syscall_pre_impl_writev((long)(fd), (long)(vec), (long)(vlen))
-#define __sanitizer_syscall_post_writev(res, fd, vec, vlen) \
- __sanitizer_syscall_post_impl_writev(res, (long)(fd), (long)(vec), \
+#define __sanitizer_syscall_post_writev(res, fd, vec, vlen) \
+ __sanitizer_syscall_post_impl_writev(res, (long)(fd), (long)(vec), \
(long)(vlen))
#ifdef _LP64
#define __sanitizer_syscall_pre_pread64(fd, buf, count, pos) \
__sanitizer_syscall_pre_impl_pread64((long)(fd), (long)(buf), (long)(count), \
(long)(pos))
-#define __sanitizer_syscall_post_pread64(res, fd, buf, count, pos) \
- __sanitizer_syscall_post_impl_pread64(res, (long)(fd), (long)(buf), \
+#define __sanitizer_syscall_post_pread64(res, fd, buf, count, pos) \
+ __sanitizer_syscall_post_impl_pread64(res, (long)(fd), (long)(buf), \
(long)(count), (long)(pos))
-#define __sanitizer_syscall_pre_pwrite64(fd, buf, count, pos) \
- __sanitizer_syscall_pre_impl_pwrite64((long)(fd), (long)(buf), \
+#define __sanitizer_syscall_pre_pwrite64(fd, buf, count, pos) \
+ __sanitizer_syscall_pre_impl_pwrite64((long)(fd), (long)(buf), \
(long)(count), (long)(pos))
-#define __sanitizer_syscall_post_pwrite64(res, fd, buf, count, pos) \
- __sanitizer_syscall_post_impl_pwrite64(res, (long)(fd), (long)(buf), \
+#define __sanitizer_syscall_post_pwrite64(res, fd, buf, count, pos) \
+ __sanitizer_syscall_post_impl_pwrite64(res, (long)(fd), (long)(buf), \
(long)(count), (long)(pos))
#else
#define __sanitizer_syscall_pre_pread64(fd, buf, count, pos0, pos1) \
__sanitizer_syscall_pre_impl_pread64((long)(fd), (long)(buf), (long)(count), \
(long)(pos0), (long)(pos1))
-#define __sanitizer_syscall_post_pread64(res, fd, buf, count, pos0, pos1) \
- __sanitizer_syscall_post_impl_pread64(res, (long)(fd), (long)(buf), \
- (long)(count), (long)(pos0), \
- (long)(pos1))
-#define __sanitizer_syscall_pre_pwrite64(fd, buf, count, pos0, pos1) \
- __sanitizer_syscall_pre_impl_pwrite64( \
+#define __sanitizer_syscall_post_pread64(res, fd, buf, count, pos0, pos1) \
+ __sanitizer_syscall_post_impl_pread64( \
+ res, (long)(fd), (long)(buf), (long)(count), (long)(pos0), (long)(pos1))
+#define __sanitizer_syscall_pre_pwrite64(fd, buf, count, pos0, pos1) \
+ __sanitizer_syscall_pre_impl_pwrite64( \
(long)(fd), (long)(buf), (long)(count), (long)(pos0), (long)(pos1))
-#define __sanitizer_syscall_post_pwrite64(res, fd, buf, count, pos0, pos1) \
- __sanitizer_syscall_post_impl_pwrite64( \
+#define __sanitizer_syscall_post_pwrite64(res, fd, buf, count, pos0, pos1) \
+ __sanitizer_syscall_post_impl_pwrite64( \
res, (long)(fd), (long)(buf), (long)(count), (long)(pos0), (long)(pos1))
#endif
-#define __sanitizer_syscall_pre_preadv(fd, vec, vlen, pos_l, pos_h) \
- __sanitizer_syscall_pre_impl_preadv((long)(fd), (long)(vec), (long)(vlen), \
+#define __sanitizer_syscall_pre_preadv(fd, vec, vlen, pos_l, pos_h) \
+ __sanitizer_syscall_pre_impl_preadv((long)(fd), (long)(vec), (long)(vlen), \
(long)(pos_l), (long)(pos_h))
-#define __sanitizer_syscall_post_preadv(res, fd, vec, vlen, pos_l, pos_h) \
- __sanitizer_syscall_post_impl_preadv(res, (long)(fd), (long)(vec), \
- (long)(vlen), (long)(pos_l), \
+#define __sanitizer_syscall_post_preadv(res, fd, vec, vlen, pos_l, pos_h) \
+ __sanitizer_syscall_post_impl_preadv(res, (long)(fd), (long)(vec), \
+ (long)(vlen), (long)(pos_l), \
(long)(pos_h))
-#define __sanitizer_syscall_pre_pwritev(fd, vec, vlen, pos_l, pos_h) \
- __sanitizer_syscall_pre_impl_pwritev((long)(fd), (long)(vec), (long)(vlen), \
+#define __sanitizer_syscall_pre_pwritev(fd, vec, vlen, pos_l, pos_h) \
+ __sanitizer_syscall_pre_impl_pwritev((long)(fd), (long)(vec), (long)(vlen), \
(long)(pos_l), (long)(pos_h))
-#define __sanitizer_syscall_post_pwritev(res, fd, vec, vlen, pos_l, pos_h) \
- __sanitizer_syscall_post_impl_pwritev(res, (long)(fd), (long)(vec), \
- (long)(vlen), (long)(pos_l), \
+#define __sanitizer_syscall_post_pwritev(res, fd, vec, vlen, pos_l, pos_h) \
+ __sanitizer_syscall_post_impl_pwritev(res, (long)(fd), (long)(vec), \
+ (long)(vlen), (long)(pos_l), \
(long)(pos_h))
-#define __sanitizer_syscall_pre_getcwd(buf, size) \
+#define __sanitizer_syscall_pre_getcwd(buf, size) \
__sanitizer_syscall_pre_impl_getcwd((long)(buf), (long)(size))
-#define __sanitizer_syscall_post_getcwd(res, buf, size) \
+#define __sanitizer_syscall_post_getcwd(res, buf, size) \
__sanitizer_syscall_post_impl_getcwd(res, (long)(buf), (long)(size))
-#define __sanitizer_syscall_pre_mkdir(pathname, mode) \
+#define __sanitizer_syscall_pre_mkdir(pathname, mode) \
__sanitizer_syscall_pre_impl_mkdir((long)(pathname), (long)(mode))
-#define __sanitizer_syscall_post_mkdir(res, pathname, mode) \
+#define __sanitizer_syscall_post_mkdir(res, pathname, mode) \
__sanitizer_syscall_post_impl_mkdir(res, (long)(pathname), (long)(mode))
-#define __sanitizer_syscall_pre_chdir(filename) \
+#define __sanitizer_syscall_pre_chdir(filename) \
__sanitizer_syscall_pre_impl_chdir((long)(filename))
-#define __sanitizer_syscall_post_chdir(res, filename) \
+#define __sanitizer_syscall_post_chdir(res, filename) \
__sanitizer_syscall_post_impl_chdir(res, (long)(filename))
-#define __sanitizer_syscall_pre_fchdir(fd) \
+#define __sanitizer_syscall_pre_fchdir(fd) \
__sanitizer_syscall_pre_impl_fchdir((long)(fd))
-#define __sanitizer_syscall_post_fchdir(res, fd) \
+#define __sanitizer_syscall_post_fchdir(res, fd) \
__sanitizer_syscall_post_impl_fchdir(res, (long)(fd))
-#define __sanitizer_syscall_pre_rmdir(pathname) \
+#define __sanitizer_syscall_pre_rmdir(pathname) \
__sanitizer_syscall_pre_impl_rmdir((long)(pathname))
-#define __sanitizer_syscall_post_rmdir(res, pathname) \
+#define __sanitizer_syscall_post_rmdir(res, pathname) \
__sanitizer_syscall_post_impl_rmdir(res, (long)(pathname))
-#define __sanitizer_syscall_pre_lookup_dcookie(cookie64, buf, len) \
- __sanitizer_syscall_pre_impl_lookup_dcookie((long)(cookie64), (long)(buf), \
+#define __sanitizer_syscall_pre_lookup_dcookie(cookie64, buf, len) \
+ __sanitizer_syscall_pre_impl_lookup_dcookie((long)(cookie64), (long)(buf), \
(long)(len))
-#define __sanitizer_syscall_post_lookup_dcookie(res, cookie64, buf, len) \
- __sanitizer_syscall_post_impl_lookup_dcookie(res, (long)(cookie64), \
+#define __sanitizer_syscall_post_lookup_dcookie(res, cookie64, buf, len) \
+ __sanitizer_syscall_post_impl_lookup_dcookie(res, (long)(cookie64), \
(long)(buf), (long)(len))
-#define __sanitizer_syscall_pre_quotactl(cmd, special, id, addr) \
- __sanitizer_syscall_pre_impl_quotactl((long)(cmd), (long)(special), \
+#define __sanitizer_syscall_pre_quotactl(cmd, special, id, addr) \
+ __sanitizer_syscall_pre_impl_quotactl((long)(cmd), (long)(special), \
(long)(id), (long)(addr))
-#define __sanitizer_syscall_post_quotactl(res, cmd, special, id, addr) \
- __sanitizer_syscall_post_impl_quotactl(res, (long)(cmd), (long)(special), \
+#define __sanitizer_syscall_post_quotactl(res, cmd, special, id, addr) \
+ __sanitizer_syscall_post_impl_quotactl(res, (long)(cmd), (long)(special), \
(long)(id), (long)(addr))
-#define __sanitizer_syscall_pre_getdents(fd, dirent, count) \
- __sanitizer_syscall_pre_impl_getdents((long)(fd), (long)(dirent), \
+#define __sanitizer_syscall_pre_getdents(fd, dirent, count) \
+ __sanitizer_syscall_pre_impl_getdents((long)(fd), (long)(dirent), \
(long)(count))
-#define __sanitizer_syscall_post_getdents(res, fd, dirent, count) \
- __sanitizer_syscall_post_impl_getdents(res, (long)(fd), (long)(dirent), \
+#define __sanitizer_syscall_post_getdents(res, fd, dirent, count) \
+ __sanitizer_syscall_post_impl_getdents(res, (long)(fd), (long)(dirent), \
(long)(count))
-#define __sanitizer_syscall_pre_getdents64(fd, dirent, count) \
- __sanitizer_syscall_pre_impl_getdents64((long)(fd), (long)(dirent), \
+#define __sanitizer_syscall_pre_getdents64(fd, dirent, count) \
+ __sanitizer_syscall_pre_impl_getdents64((long)(fd), (long)(dirent), \
(long)(count))
-#define __sanitizer_syscall_post_getdents64(res, fd, dirent, count) \
- __sanitizer_syscall_post_impl_getdents64(res, (long)(fd), (long)(dirent), \
+#define __sanitizer_syscall_post_getdents64(res, fd, dirent, count) \
+ __sanitizer_syscall_post_impl_getdents64(res, (long)(fd), (long)(dirent), \
(long)(count))
#define __sanitizer_syscall_pre_setsockopt(fd, level, optname, optval, optlen) \
__sanitizer_syscall_pre_impl_setsockopt((long)(fd), (long)(level), \
(long)(optname), (long)(optval), \
(long)(optlen))
-#define __sanitizer_syscall_post_setsockopt(res, fd, level, optname, optval, \
- optlen) \
- __sanitizer_syscall_post_impl_setsockopt(res, (long)(fd), (long)(level), \
- (long)(optname), (long)(optval), \
+#define __sanitizer_syscall_post_setsockopt(res, fd, level, optname, optval, \
+ optlen) \
+ __sanitizer_syscall_post_impl_setsockopt(res, (long)(fd), (long)(level), \
+ (long)(optname), (long)(optval), \
(long)(optlen))
#define __sanitizer_syscall_pre_getsockopt(fd, level, optname, optval, optlen) \
__sanitizer_syscall_pre_impl_getsockopt((long)(fd), (long)(level), \
(long)(optname), (long)(optval), \
(long)(optlen))
-#define __sanitizer_syscall_post_getsockopt(res, fd, level, optname, optval, \
- optlen) \
- __sanitizer_syscall_post_impl_getsockopt(res, (long)(fd), (long)(level), \
- (long)(optname), (long)(optval), \
+#define __sanitizer_syscall_post_getsockopt(res, fd, level, optname, optval, \
+ optlen) \
+ __sanitizer_syscall_post_impl_getsockopt(res, (long)(fd), (long)(level), \
+ (long)(optname), (long)(optval), \
(long)(optlen))
-#define __sanitizer_syscall_pre_bind(arg0, arg1, arg2) \
+#define __sanitizer_syscall_pre_bind(arg0, arg1, arg2) \
__sanitizer_syscall_pre_impl_bind((long)(arg0), (long)(arg1), (long)(arg2))
-#define __sanitizer_syscall_post_bind(res, arg0, arg1, arg2) \
- __sanitizer_syscall_post_impl_bind(res, (long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_post_bind(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_bind(res, (long)(arg0), (long)(arg1), \
(long)(arg2))
-#define __sanitizer_syscall_pre_connect(arg0, arg1, arg2) \
+#define __sanitizer_syscall_pre_connect(arg0, arg1, arg2) \
__sanitizer_syscall_pre_impl_connect((long)(arg0), (long)(arg1), (long)(arg2))
-#define __sanitizer_syscall_post_connect(res, arg0, arg1, arg2) \
- __sanitizer_syscall_post_impl_connect(res, (long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_post_connect(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_connect(res, (long)(arg0), (long)(arg1), \
(long)(arg2))
-#define __sanitizer_syscall_pre_accept(arg0, arg1, arg2) \
+#define __sanitizer_syscall_pre_accept(arg0, arg1, arg2) \
__sanitizer_syscall_pre_impl_accept((long)(arg0), (long)(arg1), (long)(arg2))
-#define __sanitizer_syscall_post_accept(res, arg0, arg1, arg2) \
- __sanitizer_syscall_post_impl_accept(res, (long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_post_accept(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_accept(res, (long)(arg0), (long)(arg1), \
(long)(arg2))
-#define __sanitizer_syscall_pre_accept4(arg0, arg1, arg2, arg3) \
- __sanitizer_syscall_pre_impl_accept4((long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_pre_accept4(arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_pre_impl_accept4((long)(arg0), (long)(arg1), \
(long)(arg2), (long)(arg3))
-#define __sanitizer_syscall_post_accept4(res, arg0, arg1, arg2, arg3) \
- __sanitizer_syscall_post_impl_accept4(res, (long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_post_accept4(res, arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_post_impl_accept4(res, (long)(arg0), (long)(arg1), \
(long)(arg2), (long)(arg3))
-#define __sanitizer_syscall_pre_getsockname(arg0, arg1, arg2) \
- __sanitizer_syscall_pre_impl_getsockname((long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_pre_getsockname(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_getsockname((long)(arg0), (long)(arg1), \
(long)(arg2))
-#define __sanitizer_syscall_post_getsockname(res, arg0, arg1, arg2) \
- __sanitizer_syscall_post_impl_getsockname(res, (long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_post_getsockname(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_getsockname(res, (long)(arg0), (long)(arg1), \
(long)(arg2))
-#define __sanitizer_syscall_pre_getpeername(arg0, arg1, arg2) \
- __sanitizer_syscall_pre_impl_getpeername((long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_pre_getpeername(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_getpeername((long)(arg0), (long)(arg1), \
(long)(arg2))
-#define __sanitizer_syscall_post_getpeername(res, arg0, arg1, arg2) \
- __sanitizer_syscall_post_impl_getpeername(res, (long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_post_getpeername(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_getpeername(res, (long)(arg0), (long)(arg1), \
(long)(arg2))
-#define __sanitizer_syscall_pre_send(arg0, arg1, arg2, arg3) \
- __sanitizer_syscall_pre_impl_send((long)(arg0), (long)(arg1), (long)(arg2), \
+#define __sanitizer_syscall_pre_send(arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_pre_impl_send((long)(arg0), (long)(arg1), (long)(arg2), \
(long)(arg3))
-#define __sanitizer_syscall_post_send(res, arg0, arg1, arg2, arg3) \
- __sanitizer_syscall_post_impl_send(res, (long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_post_send(res, arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_post_impl_send(res, (long)(arg0), (long)(arg1), \
(long)(arg2), (long)(arg3))
-#define __sanitizer_syscall_pre_sendto(arg0, arg1, arg2, arg3, arg4, arg5) \
- __sanitizer_syscall_pre_impl_sendto((long)(arg0), (long)(arg1), \
- (long)(arg2), (long)(arg3), \
+#define __sanitizer_syscall_pre_sendto(arg0, arg1, arg2, arg3, arg4, arg5) \
+ __sanitizer_syscall_pre_impl_sendto((long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
(long)(arg4), (long)(arg5))
-#define __sanitizer_syscall_post_sendto(res, arg0, arg1, arg2, arg3, arg4, \
- arg5) \
- __sanitizer_syscall_post_impl_sendto(res, (long)(arg0), (long)(arg1), \
- (long)(arg2), (long)(arg3), \
+#define __sanitizer_syscall_post_sendto(res, arg0, arg1, arg2, arg3, arg4, \
+ arg5) \
+ __sanitizer_syscall_post_impl_sendto(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
(long)(arg4), (long)(arg5))
-#define __sanitizer_syscall_pre_sendmsg(fd, msg, flags) \
+#define __sanitizer_syscall_pre_sendmsg(fd, msg, flags) \
__sanitizer_syscall_pre_impl_sendmsg((long)(fd), (long)(msg), (long)(flags))
-#define __sanitizer_syscall_post_sendmsg(res, fd, msg, flags) \
- __sanitizer_syscall_post_impl_sendmsg(res, (long)(fd), (long)(msg), \
+#define __sanitizer_syscall_post_sendmsg(res, fd, msg, flags) \
+ __sanitizer_syscall_post_impl_sendmsg(res, (long)(fd), (long)(msg), \
(long)(flags))
#define __sanitizer_syscall_pre_sendmmsg(fd, msg, vlen, flags) \
__sanitizer_syscall_pre_impl_sendmmsg((long)(fd), (long)(msg), (long)(vlen), \
(long)(flags))
-#define __sanitizer_syscall_post_sendmmsg(res, fd, msg, vlen, flags) \
- __sanitizer_syscall_post_impl_sendmmsg(res, (long)(fd), (long)(msg), \
+#define __sanitizer_syscall_post_sendmmsg(res, fd, msg, vlen, flags) \
+ __sanitizer_syscall_post_impl_sendmmsg(res, (long)(fd), (long)(msg), \
(long)(vlen), (long)(flags))
-#define __sanitizer_syscall_pre_recv(arg0, arg1, arg2, arg3) \
- __sanitizer_syscall_pre_impl_recv((long)(arg0), (long)(arg1), (long)(arg2), \
+#define __sanitizer_syscall_pre_recv(arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_pre_impl_recv((long)(arg0), (long)(arg1), (long)(arg2), \
(long)(arg3))
-#define __sanitizer_syscall_post_recv(res, arg0, arg1, arg2, arg3) \
- __sanitizer_syscall_post_impl_recv(res, (long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_post_recv(res, arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_post_impl_recv(res, (long)(arg0), (long)(arg1), \
(long)(arg2), (long)(arg3))
-#define __sanitizer_syscall_pre_recvfrom(arg0, arg1, arg2, arg3, arg4, arg5) \
- __sanitizer_syscall_pre_impl_recvfrom((long)(arg0), (long)(arg1), \
- (long)(arg2), (long)(arg3), \
+#define __sanitizer_syscall_pre_recvfrom(arg0, arg1, arg2, arg3, arg4, arg5) \
+ __sanitizer_syscall_pre_impl_recvfrom((long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
(long)(arg4), (long)(arg5))
-#define __sanitizer_syscall_post_recvfrom(res, arg0, arg1, arg2, arg3, arg4, \
- arg5) \
- __sanitizer_syscall_post_impl_recvfrom(res, (long)(arg0), (long)(arg1), \
- (long)(arg2), (long)(arg3), \
+#define __sanitizer_syscall_post_recvfrom(res, arg0, arg1, arg2, arg3, arg4, \
+ arg5) \
+ __sanitizer_syscall_post_impl_recvfrom(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
(long)(arg4), (long)(arg5))
-#define __sanitizer_syscall_pre_recvmsg(fd, msg, flags) \
+#define __sanitizer_syscall_pre_recvmsg(fd, msg, flags) \
__sanitizer_syscall_pre_impl_recvmsg((long)(fd), (long)(msg), (long)(flags))
-#define __sanitizer_syscall_post_recvmsg(res, fd, msg, flags) \
- __sanitizer_syscall_post_impl_recvmsg(res, (long)(fd), (long)(msg), \
+#define __sanitizer_syscall_post_recvmsg(res, fd, msg, flags) \
+ __sanitizer_syscall_post_impl_recvmsg(res, (long)(fd), (long)(msg), \
(long)(flags))
#define __sanitizer_syscall_pre_recvmmsg(fd, msg, vlen, flags, timeout) \
__sanitizer_syscall_pre_impl_recvmmsg((long)(fd), (long)(msg), (long)(vlen), \
(long)(flags), (long)(timeout))
-#define __sanitizer_syscall_post_recvmmsg(res, fd, msg, vlen, flags, timeout) \
- __sanitizer_syscall_post_impl_recvmmsg(res, (long)(fd), (long)(msg), \
- (long)(vlen), (long)(flags), \
+#define __sanitizer_syscall_post_recvmmsg(res, fd, msg, vlen, flags, timeout) \
+ __sanitizer_syscall_post_impl_recvmmsg(res, (long)(fd), (long)(msg), \
+ (long)(vlen), (long)(flags), \
(long)(timeout))
-#define __sanitizer_syscall_pre_socket(arg0, arg1, arg2) \
+#define __sanitizer_syscall_pre_socket(arg0, arg1, arg2) \
__sanitizer_syscall_pre_impl_socket((long)(arg0), (long)(arg1), (long)(arg2))
-#define __sanitizer_syscall_post_socket(res, arg0, arg1, arg2) \
- __sanitizer_syscall_post_impl_socket(res, (long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_post_socket(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_socket(res, (long)(arg0), (long)(arg1), \
(long)(arg2))
-#define __sanitizer_syscall_pre_socketpair(arg0, arg1, arg2, arg3) \
- __sanitizer_syscall_pre_impl_socketpair((long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_pre_socketpair(arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_pre_impl_socketpair((long)(arg0), (long)(arg1), \
(long)(arg2), (long)(arg3))
-#define __sanitizer_syscall_post_socketpair(res, arg0, arg1, arg2, arg3) \
- __sanitizer_syscall_post_impl_socketpair(res, (long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_post_socketpair(res, arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_post_impl_socketpair(res, (long)(arg0), (long)(arg1), \
(long)(arg2), (long)(arg3))
-#define __sanitizer_syscall_pre_socketcall(call, args) \
+#define __sanitizer_syscall_pre_socketcall(call, args) \
__sanitizer_syscall_pre_impl_socketcall((long)(call), (long)(args))
-#define __sanitizer_syscall_post_socketcall(res, call, args) \
+#define __sanitizer_syscall_post_socketcall(res, call, args) \
__sanitizer_syscall_post_impl_socketcall(res, (long)(call), (long)(args))
-#define __sanitizer_syscall_pre_listen(arg0, arg1) \
+#define __sanitizer_syscall_pre_listen(arg0, arg1) \
__sanitizer_syscall_pre_impl_listen((long)(arg0), (long)(arg1))
-#define __sanitizer_syscall_post_listen(res, arg0, arg1) \
+#define __sanitizer_syscall_post_listen(res, arg0, arg1) \
__sanitizer_syscall_post_impl_listen(res, (long)(arg0), (long)(arg1))
-#define __sanitizer_syscall_pre_poll(ufds, nfds, timeout) \
+#define __sanitizer_syscall_pre_poll(ufds, nfds, timeout) \
__sanitizer_syscall_pre_impl_poll((long)(ufds), (long)(nfds), (long)(timeout))
-#define __sanitizer_syscall_post_poll(res, ufds, nfds, timeout) \
- __sanitizer_syscall_post_impl_poll(res, (long)(ufds), (long)(nfds), \
+#define __sanitizer_syscall_post_poll(res, ufds, nfds, timeout) \
+ __sanitizer_syscall_post_impl_poll(res, (long)(ufds), (long)(nfds), \
(long)(timeout))
-#define __sanitizer_syscall_pre_select(n, inp, outp, exp, tvp) \
- __sanitizer_syscall_pre_impl_select((long)(n), (long)(inp), (long)(outp), \
+#define __sanitizer_syscall_pre_select(n, inp, outp, exp, tvp) \
+ __sanitizer_syscall_pre_impl_select((long)(n), (long)(inp), (long)(outp), \
(long)(exp), (long)(tvp))
-#define __sanitizer_syscall_post_select(res, n, inp, outp, exp, tvp) \
- __sanitizer_syscall_post_impl_select(res, (long)(n), (long)(inp), \
+#define __sanitizer_syscall_post_select(res, n, inp, outp, exp, tvp) \
+ __sanitizer_syscall_post_impl_select(res, (long)(n), (long)(inp), \
(long)(outp), (long)(exp), (long)(tvp))
-#define __sanitizer_syscall_pre_old_select(arg) \
+#define __sanitizer_syscall_pre_old_select(arg) \
__sanitizer_syscall_pre_impl_old_select((long)(arg))
-#define __sanitizer_syscall_post_old_select(res, arg) \
+#define __sanitizer_syscall_post_old_select(res, arg) \
__sanitizer_syscall_post_impl_old_select(res, (long)(arg))
-#define __sanitizer_syscall_pre_epoll_create(size) \
+#define __sanitizer_syscall_pre_epoll_create(size) \
__sanitizer_syscall_pre_impl_epoll_create((long)(size))
-#define __sanitizer_syscall_post_epoll_create(res, size) \
+#define __sanitizer_syscall_post_epoll_create(res, size) \
__sanitizer_syscall_post_impl_epoll_create(res, (long)(size))
-#define __sanitizer_syscall_pre_epoll_create1(flags) \
+#define __sanitizer_syscall_pre_epoll_create1(flags) \
__sanitizer_syscall_pre_impl_epoll_create1((long)(flags))
-#define __sanitizer_syscall_post_epoll_create1(res, flags) \
+#define __sanitizer_syscall_post_epoll_create1(res, flags) \
__sanitizer_syscall_post_impl_epoll_create1(res, (long)(flags))
#define __sanitizer_syscall_pre_epoll_ctl(epfd, op, fd, event) \
__sanitizer_syscall_pre_impl_epoll_ctl((long)(epfd), (long)(op), (long)(fd), \
(long)(event))
-#define __sanitizer_syscall_post_epoll_ctl(res, epfd, op, fd, event) \
- __sanitizer_syscall_post_impl_epoll_ctl(res, (long)(epfd), (long)(op), \
+#define __sanitizer_syscall_post_epoll_ctl(res, epfd, op, fd, event) \
+ __sanitizer_syscall_post_impl_epoll_ctl(res, (long)(epfd), (long)(op), \
(long)(fd), (long)(event))
-#define __sanitizer_syscall_pre_epoll_wait(epfd, events, maxevents, timeout) \
- __sanitizer_syscall_pre_impl_epoll_wait((long)(epfd), (long)(events), \
+#define __sanitizer_syscall_pre_epoll_wait(epfd, events, maxevents, timeout) \
+ __sanitizer_syscall_pre_impl_epoll_wait((long)(epfd), (long)(events), \
(long)(maxevents), (long)(timeout))
-#define __sanitizer_syscall_post_epoll_wait(res, epfd, events, maxevents, \
- timeout) \
- __sanitizer_syscall_post_impl_epoll_wait(res, (long)(epfd), (long)(events), \
+#define __sanitizer_syscall_post_epoll_wait(res, epfd, events, maxevents, \
+ timeout) \
+ __sanitizer_syscall_post_impl_epoll_wait(res, (long)(epfd), (long)(events), \
(long)(maxevents), (long)(timeout))
-#define __sanitizer_syscall_pre_epoll_pwait(epfd, events, maxevents, timeout, \
- sigmask, sigsetsize) \
- __sanitizer_syscall_pre_impl_epoll_pwait( \
- (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \
+#define __sanitizer_syscall_pre_epoll_pwait(epfd, events, maxevents, timeout, \
+ sigmask, sigsetsize) \
+ __sanitizer_syscall_pre_impl_epoll_pwait( \
+ (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \
+ (long)(sigmask), (long)(sigsetsize))
+#define __sanitizer_syscall_post_epoll_pwait(res, epfd, events, maxevents, \
+ timeout, sigmask, sigsetsize) \
+ __sanitizer_syscall_post_impl_epoll_pwait( \
+ res, (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \
(long)(sigmask), (long)(sigsetsize))
-#define __sanitizer_syscall_post_epoll_pwait(res, epfd, events, maxevents, \
- timeout, sigmask, sigsetsize) \
- __sanitizer_syscall_post_impl_epoll_pwait( \
- res, (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \
+#define __sanitizer_syscall_pre_epoll_pwait2(epfd, events, maxevents, timeout, \
+ sigmask, sigsetsize) \
+ __sanitizer_syscall_pre_impl_epoll_pwait2( \
+ (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \
(long)(sigmask), (long)(sigsetsize))
-#define __sanitizer_syscall_pre_gethostname(name, len) \
+#define __sanitizer_syscall_post_epoll_pwait2(res, epfd, events, maxevents, \
+ timeout, sigmask, sigsetsize) \
+ __sanitizer_syscall_post_impl_epoll_pwait2( \
+ res, (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \
+ (long)(sigmask), (long)(sigsetsize))
+#define __sanitizer_syscall_pre_gethostname(name, len) \
__sanitizer_syscall_pre_impl_gethostname((long)(name), (long)(len))
-#define __sanitizer_syscall_post_gethostname(res, name, len) \
+#define __sanitizer_syscall_post_gethostname(res, name, len) \
__sanitizer_syscall_post_impl_gethostname(res, (long)(name), (long)(len))
-#define __sanitizer_syscall_pre_sethostname(name, len) \
+#define __sanitizer_syscall_pre_sethostname(name, len) \
__sanitizer_syscall_pre_impl_sethostname((long)(name), (long)(len))
-#define __sanitizer_syscall_post_sethostname(res, name, len) \
+#define __sanitizer_syscall_post_sethostname(res, name, len) \
__sanitizer_syscall_post_impl_sethostname(res, (long)(name), (long)(len))
-#define __sanitizer_syscall_pre_setdomainname(name, len) \
+#define __sanitizer_syscall_pre_setdomainname(name, len) \
__sanitizer_syscall_pre_impl_setdomainname((long)(name), (long)(len))
-#define __sanitizer_syscall_post_setdomainname(res, name, len) \
+#define __sanitizer_syscall_post_setdomainname(res, name, len) \
__sanitizer_syscall_post_impl_setdomainname(res, (long)(name), (long)(len))
-#define __sanitizer_syscall_pre_newuname(name) \
+#define __sanitizer_syscall_pre_newuname(name) \
__sanitizer_syscall_pre_impl_newuname((long)(name))
-#define __sanitizer_syscall_post_newuname(res, name) \
+#define __sanitizer_syscall_post_newuname(res, name) \
__sanitizer_syscall_post_impl_newuname(res, (long)(name))
-#define __sanitizer_syscall_pre_uname(arg0) \
+#define __sanitizer_syscall_pre_uname(arg0) \
__sanitizer_syscall_pre_impl_uname((long)(arg0))
-#define __sanitizer_syscall_post_uname(res, arg0) \
+#define __sanitizer_syscall_post_uname(res, arg0) \
__sanitizer_syscall_post_impl_uname(res, (long)(arg0))
-#define __sanitizer_syscall_pre_olduname(arg0) \
+#define __sanitizer_syscall_pre_olduname(arg0) \
__sanitizer_syscall_pre_impl_olduname((long)(arg0))
-#define __sanitizer_syscall_post_olduname(res, arg0) \
+#define __sanitizer_syscall_post_olduname(res, arg0) \
__sanitizer_syscall_post_impl_olduname(res, (long)(arg0))
-#define __sanitizer_syscall_pre_getrlimit(resource, rlim) \
+#define __sanitizer_syscall_pre_getrlimit(resource, rlim) \
__sanitizer_syscall_pre_impl_getrlimit((long)(resource), (long)(rlim))
-#define __sanitizer_syscall_post_getrlimit(res, resource, rlim) \
+#define __sanitizer_syscall_post_getrlimit(res, resource, rlim) \
__sanitizer_syscall_post_impl_getrlimit(res, (long)(resource), (long)(rlim))
-#define __sanitizer_syscall_pre_old_getrlimit(resource, rlim) \
+#define __sanitizer_syscall_pre_old_getrlimit(resource, rlim) \
__sanitizer_syscall_pre_impl_old_getrlimit((long)(resource), (long)(rlim))
-#define __sanitizer_syscall_post_old_getrlimit(res, resource, rlim) \
- __sanitizer_syscall_post_impl_old_getrlimit(res, (long)(resource), \
+#define __sanitizer_syscall_post_old_getrlimit(res, resource, rlim) \
+ __sanitizer_syscall_post_impl_old_getrlimit(res, (long)(resource), \
(long)(rlim))
-#define __sanitizer_syscall_pre_setrlimit(resource, rlim) \
+#define __sanitizer_syscall_pre_setrlimit(resource, rlim) \
__sanitizer_syscall_pre_impl_setrlimit((long)(resource), (long)(rlim))
-#define __sanitizer_syscall_post_setrlimit(res, resource, rlim) \
+#define __sanitizer_syscall_post_setrlimit(res, resource, rlim) \
__sanitizer_syscall_post_impl_setrlimit(res, (long)(resource), (long)(rlim))
-#define __sanitizer_syscall_pre_prlimit64(pid, resource, new_rlim, old_rlim) \
- __sanitizer_syscall_pre_impl_prlimit64((long)(pid), (long)(resource), \
+#define __sanitizer_syscall_pre_prlimit64(pid, resource, new_rlim, old_rlim) \
+ __sanitizer_syscall_pre_impl_prlimit64((long)(pid), (long)(resource), \
(long)(new_rlim), (long)(old_rlim))
-#define __sanitizer_syscall_post_prlimit64(res, pid, resource, new_rlim, \
- old_rlim) \
- __sanitizer_syscall_post_impl_prlimit64(res, (long)(pid), (long)(resource), \
+#define __sanitizer_syscall_post_prlimit64(res, pid, resource, new_rlim, \
+ old_rlim) \
+ __sanitizer_syscall_post_impl_prlimit64(res, (long)(pid), (long)(resource), \
(long)(new_rlim), (long)(old_rlim))
-#define __sanitizer_syscall_pre_getrusage(who, ru) \
+#define __sanitizer_syscall_pre_getrusage(who, ru) \
__sanitizer_syscall_pre_impl_getrusage((long)(who), (long)(ru))
-#define __sanitizer_syscall_post_getrusage(res, who, ru) \
+#define __sanitizer_syscall_post_getrusage(res, who, ru) \
__sanitizer_syscall_post_impl_getrusage(res, (long)(who), (long)(ru))
-#define __sanitizer_syscall_pre_umask(mask) \
+#define __sanitizer_syscall_pre_umask(mask) \
__sanitizer_syscall_pre_impl_umask((long)(mask))
-#define __sanitizer_syscall_post_umask(res, mask) \
+#define __sanitizer_syscall_post_umask(res, mask) \
__sanitizer_syscall_post_impl_umask(res, (long)(mask))
-#define __sanitizer_syscall_pre_msgget(key, msgflg) \
+#define __sanitizer_syscall_pre_msgget(key, msgflg) \
__sanitizer_syscall_pre_impl_msgget((long)(key), (long)(msgflg))
-#define __sanitizer_syscall_post_msgget(res, key, msgflg) \
+#define __sanitizer_syscall_post_msgget(res, key, msgflg) \
__sanitizer_syscall_post_impl_msgget(res, (long)(key), (long)(msgflg))
-#define __sanitizer_syscall_pre_msgsnd(msqid, msgp, msgsz, msgflg) \
- __sanitizer_syscall_pre_impl_msgsnd((long)(msqid), (long)(msgp), \
+#define __sanitizer_syscall_pre_msgsnd(msqid, msgp, msgsz, msgflg) \
+ __sanitizer_syscall_pre_impl_msgsnd((long)(msqid), (long)(msgp), \
(long)(msgsz), (long)(msgflg))
-#define __sanitizer_syscall_post_msgsnd(res, msqid, msgp, msgsz, msgflg) \
- __sanitizer_syscall_post_impl_msgsnd(res, (long)(msqid), (long)(msgp), \
+#define __sanitizer_syscall_post_msgsnd(res, msqid, msgp, msgsz, msgflg) \
+ __sanitizer_syscall_post_impl_msgsnd(res, (long)(msqid), (long)(msgp), \
(long)(msgsz), (long)(msgflg))
-#define __sanitizer_syscall_pre_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg) \
- __sanitizer_syscall_pre_impl_msgrcv((long)(msqid), (long)(msgp), \
- (long)(msgsz), (long)(msgtyp), \
+#define __sanitizer_syscall_pre_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg) \
+ __sanitizer_syscall_pre_impl_msgrcv((long)(msqid), (long)(msgp), \
+ (long)(msgsz), (long)(msgtyp), \
(long)(msgflg))
-#define __sanitizer_syscall_post_msgrcv(res, msqid, msgp, msgsz, msgtyp, \
- msgflg) \
- __sanitizer_syscall_post_impl_msgrcv(res, (long)(msqid), (long)(msgp), \
- (long)(msgsz), (long)(msgtyp), \
+#define __sanitizer_syscall_post_msgrcv(res, msqid, msgp, msgsz, msgtyp, \
+ msgflg) \
+ __sanitizer_syscall_post_impl_msgrcv(res, (long)(msqid), (long)(msgp), \
+ (long)(msgsz), (long)(msgtyp), \
(long)(msgflg))
-#define __sanitizer_syscall_pre_msgctl(msqid, cmd, buf) \
+#define __sanitizer_syscall_pre_msgctl(msqid, cmd, buf) \
__sanitizer_syscall_pre_impl_msgctl((long)(msqid), (long)(cmd), (long)(buf))
-#define __sanitizer_syscall_post_msgctl(res, msqid, cmd, buf) \
- __sanitizer_syscall_post_impl_msgctl(res, (long)(msqid), (long)(cmd), \
+#define __sanitizer_syscall_post_msgctl(res, msqid, cmd, buf) \
+ __sanitizer_syscall_post_impl_msgctl(res, (long)(msqid), (long)(cmd), \
(long)(buf))
-#define __sanitizer_syscall_pre_semget(key, nsems, semflg) \
- __sanitizer_syscall_pre_impl_semget((long)(key), (long)(nsems), \
+#define __sanitizer_syscall_pre_semget(key, nsems, semflg) \
+ __sanitizer_syscall_pre_impl_semget((long)(key), (long)(nsems), \
(long)(semflg))
-#define __sanitizer_syscall_post_semget(res, key, nsems, semflg) \
- __sanitizer_syscall_post_impl_semget(res, (long)(key), (long)(nsems), \
+#define __sanitizer_syscall_post_semget(res, key, nsems, semflg) \
+ __sanitizer_syscall_post_impl_semget(res, (long)(key), (long)(nsems), \
(long)(semflg))
-#define __sanitizer_syscall_pre_semop(semid, sops, nsops) \
+#define __sanitizer_syscall_pre_semop(semid, sops, nsops) \
__sanitizer_syscall_pre_impl_semop((long)(semid), (long)(sops), (long)(nsops))
-#define __sanitizer_syscall_post_semop(res, semid, sops, nsops) \
- __sanitizer_syscall_post_impl_semop(res, (long)(semid), (long)(sops), \
+#define __sanitizer_syscall_post_semop(res, semid, sops, nsops) \
+ __sanitizer_syscall_post_impl_semop(res, (long)(semid), (long)(sops), \
(long)(nsops))
-#define __sanitizer_syscall_pre_semctl(semid, semnum, cmd, arg) \
- __sanitizer_syscall_pre_impl_semctl((long)(semid), (long)(semnum), \
+#define __sanitizer_syscall_pre_semctl(semid, semnum, cmd, arg) \
+ __sanitizer_syscall_pre_impl_semctl((long)(semid), (long)(semnum), \
(long)(cmd), (long)(arg))
-#define __sanitizer_syscall_post_semctl(res, semid, semnum, cmd, arg) \
- __sanitizer_syscall_post_impl_semctl(res, (long)(semid), (long)(semnum), \
+#define __sanitizer_syscall_post_semctl(res, semid, semnum, cmd, arg) \
+ __sanitizer_syscall_post_impl_semctl(res, (long)(semid), (long)(semnum), \
(long)(cmd), (long)(arg))
-#define __sanitizer_syscall_pre_semtimedop(semid, sops, nsops, timeout) \
- __sanitizer_syscall_pre_impl_semtimedop((long)(semid), (long)(sops), \
+#define __sanitizer_syscall_pre_semtimedop(semid, sops, nsops, timeout) \
+ __sanitizer_syscall_pre_impl_semtimedop((long)(semid), (long)(sops), \
(long)(nsops), (long)(timeout))
-#define __sanitizer_syscall_post_semtimedop(res, semid, sops, nsops, timeout) \
- __sanitizer_syscall_post_impl_semtimedop(res, (long)(semid), (long)(sops), \
+#define __sanitizer_syscall_post_semtimedop(res, semid, sops, nsops, timeout) \
+ __sanitizer_syscall_post_impl_semtimedop(res, (long)(semid), (long)(sops), \
(long)(nsops), (long)(timeout))
-#define __sanitizer_syscall_pre_shmat(shmid, shmaddr, shmflg) \
- __sanitizer_syscall_pre_impl_shmat((long)(shmid), (long)(shmaddr), \
+#define __sanitizer_syscall_pre_shmat(shmid, shmaddr, shmflg) \
+ __sanitizer_syscall_pre_impl_shmat((long)(shmid), (long)(shmaddr), \
(long)(shmflg))
-#define __sanitizer_syscall_post_shmat(res, shmid, shmaddr, shmflg) \
- __sanitizer_syscall_post_impl_shmat(res, (long)(shmid), (long)(shmaddr), \
+#define __sanitizer_syscall_post_shmat(res, shmid, shmaddr, shmflg) \
+ __sanitizer_syscall_post_impl_shmat(res, (long)(shmid), (long)(shmaddr), \
(long)(shmflg))
-#define __sanitizer_syscall_pre_shmget(key, size, flag) \
+#define __sanitizer_syscall_pre_shmget(key, size, flag) \
__sanitizer_syscall_pre_impl_shmget((long)(key), (long)(size), (long)(flag))
-#define __sanitizer_syscall_post_shmget(res, key, size, flag) \
- __sanitizer_syscall_post_impl_shmget(res, (long)(key), (long)(size), \
+#define __sanitizer_syscall_post_shmget(res, key, size, flag) \
+ __sanitizer_syscall_post_impl_shmget(res, (long)(key), (long)(size), \
(long)(flag))
-#define __sanitizer_syscall_pre_shmdt(shmaddr) \
+#define __sanitizer_syscall_pre_shmdt(shmaddr) \
__sanitizer_syscall_pre_impl_shmdt((long)(shmaddr))
-#define __sanitizer_syscall_post_shmdt(res, shmaddr) \
+#define __sanitizer_syscall_post_shmdt(res, shmaddr) \
__sanitizer_syscall_post_impl_shmdt(res, (long)(shmaddr))
-#define __sanitizer_syscall_pre_shmctl(shmid, cmd, buf) \
+#define __sanitizer_syscall_pre_shmctl(shmid, cmd, buf) \
__sanitizer_syscall_pre_impl_shmctl((long)(shmid), (long)(cmd), (long)(buf))
-#define __sanitizer_syscall_post_shmctl(res, shmid, cmd, buf) \
- __sanitizer_syscall_post_impl_shmctl(res, (long)(shmid), (long)(cmd), \
+#define __sanitizer_syscall_post_shmctl(res, shmid, cmd, buf) \
+ __sanitizer_syscall_post_impl_shmctl(res, (long)(shmid), (long)(cmd), \
(long)(buf))
#define __sanitizer_syscall_pre_ipc(call, first, second, third, ptr, fifth) \
__sanitizer_syscall_pre_impl_ipc((long)(call), (long)(first), \
(long)(second), (long)(third), (long)(ptr), \
(long)(fifth))
-#define __sanitizer_syscall_post_ipc(res, call, first, second, third, ptr, \
- fifth) \
- __sanitizer_syscall_post_impl_ipc(res, (long)(call), (long)(first), \
- (long)(second), (long)(third), \
+#define __sanitizer_syscall_post_ipc(res, call, first, second, third, ptr, \
+ fifth) \
+ __sanitizer_syscall_post_impl_ipc(res, (long)(call), (long)(first), \
+ (long)(second), (long)(third), \
(long)(ptr), (long)(fifth))
-#define __sanitizer_syscall_pre_mq_open(name, oflag, mode, attr) \
- __sanitizer_syscall_pre_impl_mq_open((long)(name), (long)(oflag), \
+#define __sanitizer_syscall_pre_mq_open(name, oflag, mode, attr) \
+ __sanitizer_syscall_pre_impl_mq_open((long)(name), (long)(oflag), \
(long)(mode), (long)(attr))
-#define __sanitizer_syscall_post_mq_open(res, name, oflag, mode, attr) \
- __sanitizer_syscall_post_impl_mq_open(res, (long)(name), (long)(oflag), \
+#define __sanitizer_syscall_post_mq_open(res, name, oflag, mode, attr) \
+ __sanitizer_syscall_post_impl_mq_open(res, (long)(name), (long)(oflag), \
(long)(mode), (long)(attr))
-#define __sanitizer_syscall_pre_mq_unlink(name) \
+#define __sanitizer_syscall_pre_mq_unlink(name) \
__sanitizer_syscall_pre_impl_mq_unlink((long)(name))
-#define __sanitizer_syscall_post_mq_unlink(res, name) \
+#define __sanitizer_syscall_post_mq_unlink(res, name) \
__sanitizer_syscall_post_impl_mq_unlink(res, (long)(name))
#define __sanitizer_syscall_pre_mq_timedsend(mqdes, msg_ptr, msg_len, \
msg_prio, abs_timeout) \
__sanitizer_syscall_pre_impl_mq_timedsend((long)(mqdes), (long)(msg_ptr), \
(long)(msg_len), (long)(msg_prio), \
(long)(abs_timeout))
-#define __sanitizer_syscall_post_mq_timedsend(res, mqdes, msg_ptr, msg_len, \
- msg_prio, abs_timeout) \
- __sanitizer_syscall_post_impl_mq_timedsend( \
- res, (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \
+#define __sanitizer_syscall_post_mq_timedsend(res, mqdes, msg_ptr, msg_len, \
+ msg_prio, abs_timeout) \
+ __sanitizer_syscall_post_impl_mq_timedsend( \
+ res, (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \
(long)(abs_timeout))
-#define __sanitizer_syscall_pre_mq_timedreceive(mqdes, msg_ptr, msg_len, \
- msg_prio, abs_timeout) \
- __sanitizer_syscall_pre_impl_mq_timedreceive( \
- (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \
+#define __sanitizer_syscall_pre_mq_timedreceive(mqdes, msg_ptr, msg_len, \
+ msg_prio, abs_timeout) \
+ __sanitizer_syscall_pre_impl_mq_timedreceive( \
+ (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \
(long)(abs_timeout))
#define __sanitizer_syscall_post_mq_timedreceive(res, mqdes, msg_ptr, msg_len, \
msg_prio, abs_timeout) \
__sanitizer_syscall_post_impl_mq_timedreceive( \
res, (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \
(long)(abs_timeout))
-#define __sanitizer_syscall_pre_mq_notify(mqdes, notification) \
+#define __sanitizer_syscall_pre_mq_notify(mqdes, notification) \
__sanitizer_syscall_pre_impl_mq_notify((long)(mqdes), (long)(notification))
-#define __sanitizer_syscall_post_mq_notify(res, mqdes, notification) \
- __sanitizer_syscall_post_impl_mq_notify(res, (long)(mqdes), \
+#define __sanitizer_syscall_post_mq_notify(res, mqdes, notification) \
+ __sanitizer_syscall_post_impl_mq_notify(res, (long)(mqdes), \
(long)(notification))
-#define __sanitizer_syscall_pre_mq_getsetattr(mqdes, mqstat, omqstat) \
- __sanitizer_syscall_pre_impl_mq_getsetattr((long)(mqdes), (long)(mqstat), \
+#define __sanitizer_syscall_pre_mq_getsetattr(mqdes, mqstat, omqstat) \
+ __sanitizer_syscall_pre_impl_mq_getsetattr((long)(mqdes), (long)(mqstat), \
(long)(omqstat))
-#define __sanitizer_syscall_post_mq_getsetattr(res, mqdes, mqstat, omqstat) \
- __sanitizer_syscall_post_impl_mq_getsetattr(res, (long)(mqdes), \
+#define __sanitizer_syscall_post_mq_getsetattr(res, mqdes, mqstat, omqstat) \
+ __sanitizer_syscall_post_impl_mq_getsetattr(res, (long)(mqdes), \
(long)(mqstat), (long)(omqstat))
-#define __sanitizer_syscall_pre_pciconfig_iobase(which, bus, devfn) \
- __sanitizer_syscall_pre_impl_pciconfig_iobase((long)(which), (long)(bus), \
+#define __sanitizer_syscall_pre_pciconfig_iobase(which, bus, devfn) \
+ __sanitizer_syscall_pre_impl_pciconfig_iobase((long)(which), (long)(bus), \
(long)(devfn))
-#define __sanitizer_syscall_post_pciconfig_iobase(res, which, bus, devfn) \
- __sanitizer_syscall_post_impl_pciconfig_iobase(res, (long)(which), \
+#define __sanitizer_syscall_post_pciconfig_iobase(res, which, bus, devfn) \
+ __sanitizer_syscall_post_impl_pciconfig_iobase(res, (long)(which), \
(long)(bus), (long)(devfn))
-#define __sanitizer_syscall_pre_pciconfig_read(bus, dfn, off, len, buf) \
- __sanitizer_syscall_pre_impl_pciconfig_read( \
+#define __sanitizer_syscall_pre_pciconfig_read(bus, dfn, off, len, buf) \
+ __sanitizer_syscall_pre_impl_pciconfig_read( \
(long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf))
-#define __sanitizer_syscall_post_pciconfig_read(res, bus, dfn, off, len, buf) \
- __sanitizer_syscall_post_impl_pciconfig_read( \
+#define __sanitizer_syscall_post_pciconfig_read(res, bus, dfn, off, len, buf) \
+ __sanitizer_syscall_post_impl_pciconfig_read( \
res, (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf))
-#define __sanitizer_syscall_pre_pciconfig_write(bus, dfn, off, len, buf) \
- __sanitizer_syscall_pre_impl_pciconfig_write( \
+#define __sanitizer_syscall_pre_pciconfig_write(bus, dfn, off, len, buf) \
+ __sanitizer_syscall_pre_impl_pciconfig_write( \
(long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf))
#define __sanitizer_syscall_post_pciconfig_write(res, bus, dfn, off, len, buf) \
__sanitizer_syscall_post_impl_pciconfig_write( \
res, (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf))
-#define __sanitizer_syscall_pre_swapon(specialfile, swap_flags) \
+#define __sanitizer_syscall_pre_swapon(specialfile, swap_flags) \
__sanitizer_syscall_pre_impl_swapon((long)(specialfile), (long)(swap_flags))
-#define __sanitizer_syscall_post_swapon(res, specialfile, swap_flags) \
- __sanitizer_syscall_post_impl_swapon(res, (long)(specialfile), \
+#define __sanitizer_syscall_post_swapon(res, specialfile, swap_flags) \
+ __sanitizer_syscall_post_impl_swapon(res, (long)(specialfile), \
(long)(swap_flags))
-#define __sanitizer_syscall_pre_swapoff(specialfile) \
+#define __sanitizer_syscall_pre_swapoff(specialfile) \
__sanitizer_syscall_pre_impl_swapoff((long)(specialfile))
-#define __sanitizer_syscall_post_swapoff(res, specialfile) \
+#define __sanitizer_syscall_post_swapoff(res, specialfile) \
__sanitizer_syscall_post_impl_swapoff(res, (long)(specialfile))
-#define __sanitizer_syscall_pre_sysctl(args) \
+#define __sanitizer_syscall_pre_sysctl(args) \
__sanitizer_syscall_pre_impl_sysctl((long)(args))
-#define __sanitizer_syscall_post_sysctl(res, args) \
+#define __sanitizer_syscall_post_sysctl(res, args) \
__sanitizer_syscall_post_impl_sysctl(res, (long)(args))
-#define __sanitizer_syscall_pre_sysinfo(info) \
+#define __sanitizer_syscall_pre_sysinfo(info) \
__sanitizer_syscall_pre_impl_sysinfo((long)(info))
-#define __sanitizer_syscall_post_sysinfo(res, info) \
+#define __sanitizer_syscall_post_sysinfo(res, info) \
__sanitizer_syscall_post_impl_sysinfo(res, (long)(info))
-#define __sanitizer_syscall_pre_sysfs(option, arg1, arg2) \
+#define __sanitizer_syscall_pre_sysfs(option, arg1, arg2) \
__sanitizer_syscall_pre_impl_sysfs((long)(option), (long)(arg1), (long)(arg2))
-#define __sanitizer_syscall_post_sysfs(res, option, arg1, arg2) \
- __sanitizer_syscall_post_impl_sysfs(res, (long)(option), (long)(arg1), \
+#define __sanitizer_syscall_post_sysfs(res, option, arg1, arg2) \
+ __sanitizer_syscall_post_impl_sysfs(res, (long)(option), (long)(arg1), \
(long)(arg2))
-#define __sanitizer_syscall_pre_syslog(type, buf, len) \
+#define __sanitizer_syscall_pre_syslog(type, buf, len) \
__sanitizer_syscall_pre_impl_syslog((long)(type), (long)(buf), (long)(len))
-#define __sanitizer_syscall_post_syslog(res, type, buf, len) \
- __sanitizer_syscall_post_impl_syslog(res, (long)(type), (long)(buf), \
+#define __sanitizer_syscall_post_syslog(res, type, buf, len) \
+ __sanitizer_syscall_post_impl_syslog(res, (long)(type), (long)(buf), \
(long)(len))
-#define __sanitizer_syscall_pre_uselib(library) \
+#define __sanitizer_syscall_pre_uselib(library) \
__sanitizer_syscall_pre_impl_uselib((long)(library))
-#define __sanitizer_syscall_post_uselib(res, library) \
+#define __sanitizer_syscall_post_uselib(res, library) \
__sanitizer_syscall_post_impl_uselib(res, (long)(library))
-#define __sanitizer_syscall_pre_ni_syscall() \
+#define __sanitizer_syscall_pre_ni_syscall() \
__sanitizer_syscall_pre_impl_ni_syscall()
-#define __sanitizer_syscall_post_ni_syscall(res) \
+#define __sanitizer_syscall_post_ni_syscall(res) \
__sanitizer_syscall_post_impl_ni_syscall(res)
-#define __sanitizer_syscall_pre_ptrace(request, pid, addr, data) \
- __sanitizer_syscall_pre_impl_ptrace((long)(request), (long)(pid), \
+#define __sanitizer_syscall_pre_ptrace(request, pid, addr, data) \
+ __sanitizer_syscall_pre_impl_ptrace((long)(request), (long)(pid), \
(long)(addr), (long)(data))
-#define __sanitizer_syscall_post_ptrace(res, request, pid, addr, data) \
- __sanitizer_syscall_post_impl_ptrace(res, (long)(request), (long)(pid), \
+#define __sanitizer_syscall_post_ptrace(res, request, pid, addr, data) \
+ __sanitizer_syscall_post_impl_ptrace(res, (long)(request), (long)(pid), \
(long)(addr), (long)(data))
-#define __sanitizer_syscall_pre_add_key(_type, _description, _payload, plen, \
- destringid) \
- __sanitizer_syscall_pre_impl_add_key((long)(_type), (long)(_description), \
- (long)(_payload), (long)(plen), \
+#define __sanitizer_syscall_pre_add_key(_type, _description, _payload, plen, \
+ destringid) \
+ __sanitizer_syscall_pre_impl_add_key((long)(_type), (long)(_description), \
+ (long)(_payload), (long)(plen), \
(long)(destringid))
-#define __sanitizer_syscall_post_add_key(res, _type, _description, _payload, \
- plen, destringid) \
- __sanitizer_syscall_post_impl_add_key( \
- res, (long)(_type), (long)(_description), (long)(_payload), \
+#define __sanitizer_syscall_post_add_key(res, _type, _description, _payload, \
+ plen, destringid) \
+ __sanitizer_syscall_post_impl_add_key( \
+ res, (long)(_type), (long)(_description), (long)(_payload), \
(long)(plen), (long)(destringid))
-#define __sanitizer_syscall_pre_request_key(_type, _description, \
- _callout_info, destringid) \
- __sanitizer_syscall_pre_impl_request_key( \
- (long)(_type), (long)(_description), (long)(_callout_info), \
+#define __sanitizer_syscall_pre_request_key(_type, _description, \
+ _callout_info, destringid) \
+ __sanitizer_syscall_pre_impl_request_key( \
+ (long)(_type), (long)(_description), (long)(_callout_info), \
(long)(destringid))
-#define __sanitizer_syscall_post_request_key(res, _type, _description, \
- _callout_info, destringid) \
- __sanitizer_syscall_post_impl_request_key( \
- res, (long)(_type), (long)(_description), (long)(_callout_info), \
+#define __sanitizer_syscall_post_request_key(res, _type, _description, \
+ _callout_info, destringid) \
+ __sanitizer_syscall_post_impl_request_key( \
+ res, (long)(_type), (long)(_description), (long)(_callout_info), \
(long)(destringid))
#define __sanitizer_syscall_pre_keyctl(cmd, arg2, arg3, arg4, arg5) \
__sanitizer_syscall_pre_impl_keyctl((long)(cmd), (long)(arg2), (long)(arg3), \
(long)(arg4), (long)(arg5))
-#define __sanitizer_syscall_post_keyctl(res, cmd, arg2, arg3, arg4, arg5) \
- __sanitizer_syscall_post_impl_keyctl(res, (long)(cmd), (long)(arg2), \
- (long)(arg3), (long)(arg4), \
+#define __sanitizer_syscall_post_keyctl(res, cmd, arg2, arg3, arg4, arg5) \
+ __sanitizer_syscall_post_impl_keyctl(res, (long)(cmd), (long)(arg2), \
+ (long)(arg3), (long)(arg4), \
(long)(arg5))
-#define __sanitizer_syscall_pre_ioprio_set(which, who, ioprio) \
- __sanitizer_syscall_pre_impl_ioprio_set((long)(which), (long)(who), \
+#define __sanitizer_syscall_pre_ioprio_set(which, who, ioprio) \
+ __sanitizer_syscall_pre_impl_ioprio_set((long)(which), (long)(who), \
(long)(ioprio))
-#define __sanitizer_syscall_post_ioprio_set(res, which, who, ioprio) \
- __sanitizer_syscall_post_impl_ioprio_set(res, (long)(which), (long)(who), \
+#define __sanitizer_syscall_post_ioprio_set(res, which, who, ioprio) \
+ __sanitizer_syscall_post_impl_ioprio_set(res, (long)(which), (long)(who), \
(long)(ioprio))
-#define __sanitizer_syscall_pre_ioprio_get(which, who) \
+#define __sanitizer_syscall_pre_ioprio_get(which, who) \
__sanitizer_syscall_pre_impl_ioprio_get((long)(which), (long)(who))
-#define __sanitizer_syscall_post_ioprio_get(res, which, who) \
+#define __sanitizer_syscall_post_ioprio_get(res, which, who) \
__sanitizer_syscall_post_impl_ioprio_get(res, (long)(which), (long)(who))
-#define __sanitizer_syscall_pre_set_mempolicy(mode, nmask, maxnode) \
- __sanitizer_syscall_pre_impl_set_mempolicy((long)(mode), (long)(nmask), \
+#define __sanitizer_syscall_pre_set_mempolicy(mode, nmask, maxnode) \
+ __sanitizer_syscall_pre_impl_set_mempolicy((long)(mode), (long)(nmask), \
(long)(maxnode))
-#define __sanitizer_syscall_post_set_mempolicy(res, mode, nmask, maxnode) \
- __sanitizer_syscall_post_impl_set_mempolicy(res, (long)(mode), \
+#define __sanitizer_syscall_post_set_mempolicy(res, mode, nmask, maxnode) \
+ __sanitizer_syscall_post_impl_set_mempolicy(res, (long)(mode), \
(long)(nmask), (long)(maxnode))
-#define __sanitizer_syscall_pre_migrate_pages(pid, maxnode, from, to) \
- __sanitizer_syscall_pre_impl_migrate_pages((long)(pid), (long)(maxnode), \
+#define __sanitizer_syscall_pre_migrate_pages(pid, maxnode, from, to) \
+ __sanitizer_syscall_pre_impl_migrate_pages((long)(pid), (long)(maxnode), \
(long)(from), (long)(to))
-#define __sanitizer_syscall_post_migrate_pages(res, pid, maxnode, from, to) \
- __sanitizer_syscall_post_impl_migrate_pages( \
+#define __sanitizer_syscall_post_migrate_pages(res, pid, maxnode, from, to) \
+ __sanitizer_syscall_post_impl_migrate_pages( \
res, (long)(pid), (long)(maxnode), (long)(from), (long)(to))
-#define __sanitizer_syscall_pre_move_pages(pid, nr_pages, pages, nodes, \
- status, flags) \
- __sanitizer_syscall_pre_impl_move_pages((long)(pid), (long)(nr_pages), \
- (long)(pages), (long)(nodes), \
+#define __sanitizer_syscall_pre_move_pages(pid, nr_pages, pages, nodes, \
+ status, flags) \
+ __sanitizer_syscall_pre_impl_move_pages((long)(pid), (long)(nr_pages), \
+ (long)(pages), (long)(nodes), \
(long)(status), (long)(flags))
#define __sanitizer_syscall_post_move_pages(res, pid, nr_pages, pages, nodes, \
status, flags) \
@@ -1517,322 +1526,320 @@
__sanitizer_syscall_pre_impl_mbind((long)(start), (long)(len), (long)(mode), \
(long)(nmask), (long)(maxnode), \
(long)(flags))
-#define __sanitizer_syscall_post_mbind(res, start, len, mode, nmask, maxnode, \
- flags) \
- __sanitizer_syscall_post_impl_mbind(res, (long)(start), (long)(len), \
- (long)(mode), (long)(nmask), \
+#define __sanitizer_syscall_post_mbind(res, start, len, mode, nmask, maxnode, \
+ flags) \
+ __sanitizer_syscall_post_impl_mbind(res, (long)(start), (long)(len), \
+ (long)(mode), (long)(nmask), \
(long)(maxnode), (long)(flags))
-#define __sanitizer_syscall_pre_get_mempolicy(policy, nmask, maxnode, addr, \
- flags) \
- __sanitizer_syscall_pre_impl_get_mempolicy((long)(policy), (long)(nmask), \
- (long)(maxnode), (long)(addr), \
+#define __sanitizer_syscall_pre_get_mempolicy(policy, nmask, maxnode, addr, \
+ flags) \
+ __sanitizer_syscall_pre_impl_get_mempolicy((long)(policy), (long)(nmask), \
+ (long)(maxnode), (long)(addr), \
(long)(flags))
-#define __sanitizer_syscall_post_get_mempolicy(res, policy, nmask, maxnode, \
- addr, flags) \
- __sanitizer_syscall_post_impl_get_mempolicy(res, (long)(policy), \
- (long)(nmask), (long)(maxnode), \
+#define __sanitizer_syscall_post_get_mempolicy(res, policy, nmask, maxnode, \
+ addr, flags) \
+ __sanitizer_syscall_post_impl_get_mempolicy(res, (long)(policy), \
+ (long)(nmask), (long)(maxnode), \
(long)(addr), (long)(flags))
-#define __sanitizer_syscall_pre_inotify_init() \
+#define __sanitizer_syscall_pre_inotify_init() \
__sanitizer_syscall_pre_impl_inotify_init()
-#define __sanitizer_syscall_post_inotify_init(res) \
+#define __sanitizer_syscall_post_inotify_init(res) \
__sanitizer_syscall_post_impl_inotify_init(res)
-#define __sanitizer_syscall_pre_inotify_init1(flags) \
+#define __sanitizer_syscall_pre_inotify_init1(flags) \
__sanitizer_syscall_pre_impl_inotify_init1((long)(flags))
-#define __sanitizer_syscall_post_inotify_init1(res, flags) \
+#define __sanitizer_syscall_post_inotify_init1(res, flags) \
__sanitizer_syscall_post_impl_inotify_init1(res, (long)(flags))
-#define __sanitizer_syscall_pre_inotify_add_watch(fd, path, mask) \
- __sanitizer_syscall_pre_impl_inotify_add_watch((long)(fd), (long)(path), \
+#define __sanitizer_syscall_pre_inotify_add_watch(fd, path, mask) \
+ __sanitizer_syscall_pre_impl_inotify_add_watch((long)(fd), (long)(path), \
(long)(mask))
-#define __sanitizer_syscall_post_inotify_add_watch(res, fd, path, mask) \
- __sanitizer_syscall_post_impl_inotify_add_watch(res, (long)(fd), \
+#define __sanitizer_syscall_post_inotify_add_watch(res, fd, path, mask) \
+ __sanitizer_syscall_post_impl_inotify_add_watch(res, (long)(fd), \
(long)(path), (long)(mask))
-#define __sanitizer_syscall_pre_inotify_rm_watch(fd, wd) \
+#define __sanitizer_syscall_pre_inotify_rm_watch(fd, wd) \
__sanitizer_syscall_pre_impl_inotify_rm_watch((long)(fd), (long)(wd))
-#define __sanitizer_syscall_post_inotify_rm_watch(res, fd, wd) \
+#define __sanitizer_syscall_post_inotify_rm_watch(res, fd, wd) \
__sanitizer_syscall_post_impl_inotify_rm_watch(res, (long)(fd), (long)(wd))
-#define __sanitizer_syscall_pre_spu_run(fd, unpc, ustatus) \
- __sanitizer_syscall_pre_impl_spu_run((long)(fd), (long)(unpc), \
+#define __sanitizer_syscall_pre_spu_run(fd, unpc, ustatus) \
+ __sanitizer_syscall_pre_impl_spu_run((long)(fd), (long)(unpc), \
(long)(ustatus))
-#define __sanitizer_syscall_post_spu_run(res, fd, unpc, ustatus) \
- __sanitizer_syscall_post_impl_spu_run(res, (long)(fd), (long)(unpc), \
+#define __sanitizer_syscall_post_spu_run(res, fd, unpc, ustatus) \
+ __sanitizer_syscall_post_impl_spu_run(res, (long)(fd), (long)(unpc), \
(long)(ustatus))
-#define __sanitizer_syscall_pre_spu_create(name, flags, mode, fd) \
- __sanitizer_syscall_pre_impl_spu_create((long)(name), (long)(flags), \
+#define __sanitizer_syscall_pre_spu_create(name, flags, mode, fd) \
+ __sanitizer_syscall_pre_impl_spu_create((long)(name), (long)(flags), \
(long)(mode), (long)(fd))
-#define __sanitizer_syscall_post_spu_create(res, name, flags, mode, fd) \
- __sanitizer_syscall_post_impl_spu_create(res, (long)(name), (long)(flags), \
+#define __sanitizer_syscall_post_spu_create(res, name, flags, mode, fd) \
+ __sanitizer_syscall_post_impl_spu_create(res, (long)(name), (long)(flags), \
(long)(mode), (long)(fd))
-#define __sanitizer_syscall_pre_mknodat(dfd, filename, mode, dev) \
- __sanitizer_syscall_pre_impl_mknodat((long)(dfd), (long)(filename), \
+#define __sanitizer_syscall_pre_mknodat(dfd, filename, mode, dev) \
+ __sanitizer_syscall_pre_impl_mknodat((long)(dfd), (long)(filename), \
(long)(mode), (long)(dev))
-#define __sanitizer_syscall_post_mknodat(res, dfd, filename, mode, dev) \
- __sanitizer_syscall_post_impl_mknodat(res, (long)(dfd), (long)(filename), \
+#define __sanitizer_syscall_post_mknodat(res, dfd, filename, mode, dev) \
+ __sanitizer_syscall_post_impl_mknodat(res, (long)(dfd), (long)(filename), \
(long)(mode), (long)(dev))
-#define __sanitizer_syscall_pre_mkdirat(dfd, pathname, mode) \
- __sanitizer_syscall_pre_impl_mkdirat((long)(dfd), (long)(pathname), \
+#define __sanitizer_syscall_pre_mkdirat(dfd, pathname, mode) \
+ __sanitizer_syscall_pre_impl_mkdirat((long)(dfd), (long)(pathname), \
(long)(mode))
-#define __sanitizer_syscall_post_mkdirat(res, dfd, pathname, mode) \
- __sanitizer_syscall_post_impl_mkdirat(res, (long)(dfd), (long)(pathname), \
+#define __sanitizer_syscall_post_mkdirat(res, dfd, pathname, mode) \
+ __sanitizer_syscall_post_impl_mkdirat(res, (long)(dfd), (long)(pathname), \
(long)(mode))
-#define __sanitizer_syscall_pre_unlinkat(dfd, pathname, flag) \
- __sanitizer_syscall_pre_impl_unlinkat((long)(dfd), (long)(pathname), \
+#define __sanitizer_syscall_pre_unlinkat(dfd, pathname, flag) \
+ __sanitizer_syscall_pre_impl_unlinkat((long)(dfd), (long)(pathname), \
(long)(flag))
-#define __sanitizer_syscall_post_unlinkat(res, dfd, pathname, flag) \
- __sanitizer_syscall_post_impl_unlinkat(res, (long)(dfd), (long)(pathname), \
+#define __sanitizer_syscall_post_unlinkat(res, dfd, pathname, flag) \
+ __sanitizer_syscall_post_impl_unlinkat(res, (long)(dfd), (long)(pathname), \
(long)(flag))
-#define __sanitizer_syscall_pre_symlinkat(oldname, newdfd, newname) \
- __sanitizer_syscall_pre_impl_symlinkat((long)(oldname), (long)(newdfd), \
+#define __sanitizer_syscall_pre_symlinkat(oldname, newdfd, newname) \
+ __sanitizer_syscall_pre_impl_symlinkat((long)(oldname), (long)(newdfd), \
(long)(newname))
-#define __sanitizer_syscall_post_symlinkat(res, oldname, newdfd, newname) \
- __sanitizer_syscall_post_impl_symlinkat(res, (long)(oldname), \
+#define __sanitizer_syscall_post_symlinkat(res, oldname, newdfd, newname) \
+ __sanitizer_syscall_post_impl_symlinkat(res, (long)(oldname), \
(long)(newdfd), (long)(newname))
-#define __sanitizer_syscall_pre_linkat(olddfd, oldname, newdfd, newname, \
- flags) \
- __sanitizer_syscall_pre_impl_linkat((long)(olddfd), (long)(oldname), \
- (long)(newdfd), (long)(newname), \
+#define __sanitizer_syscall_pre_linkat(olddfd, oldname, newdfd, newname, \
+ flags) \
+ __sanitizer_syscall_pre_impl_linkat((long)(olddfd), (long)(oldname), \
+ (long)(newdfd), (long)(newname), \
(long)(flags))
#define __sanitizer_syscall_post_linkat(res, olddfd, oldname, newdfd, newname, \
flags) \
__sanitizer_syscall_post_impl_linkat(res, (long)(olddfd), (long)(oldname), \
(long)(newdfd), (long)(newname), \
(long)(flags))
-#define __sanitizer_syscall_pre_renameat(olddfd, oldname, newdfd, newname) \
- __sanitizer_syscall_pre_impl_renameat((long)(olddfd), (long)(oldname), \
+#define __sanitizer_syscall_pre_renameat(olddfd, oldname, newdfd, newname) \
+ __sanitizer_syscall_pre_impl_renameat((long)(olddfd), (long)(oldname), \
(long)(newdfd), (long)(newname))
#define __sanitizer_syscall_post_renameat(res, olddfd, oldname, newdfd, \
newname) \
__sanitizer_syscall_post_impl_renameat(res, (long)(olddfd), (long)(oldname), \
(long)(newdfd), (long)(newname))
-#define __sanitizer_syscall_pre_futimesat(dfd, filename, utimes) \
- __sanitizer_syscall_pre_impl_futimesat((long)(dfd), (long)(filename), \
+#define __sanitizer_syscall_pre_futimesat(dfd, filename, utimes) \
+ __sanitizer_syscall_pre_impl_futimesat((long)(dfd), (long)(filename), \
(long)(utimes))
-#define __sanitizer_syscall_post_futimesat(res, dfd, filename, utimes) \
- __sanitizer_syscall_post_impl_futimesat(res, (long)(dfd), (long)(filename), \
+#define __sanitizer_syscall_post_futimesat(res, dfd, filename, utimes) \
+ __sanitizer_syscall_post_impl_futimesat(res, (long)(dfd), (long)(filename), \
(long)(utimes))
-#define __sanitizer_syscall_pre_faccessat(dfd, filename, mode) \
- __sanitizer_syscall_pre_impl_faccessat((long)(dfd), (long)(filename), \
+#define __sanitizer_syscall_pre_faccessat(dfd, filename, mode) \
+ __sanitizer_syscall_pre_impl_faccessat((long)(dfd), (long)(filename), \
(long)(mode))
-#define __sanitizer_syscall_post_faccessat(res, dfd, filename, mode) \
- __sanitizer_syscall_post_impl_faccessat(res, (long)(dfd), (long)(filename), \
+#define __sanitizer_syscall_post_faccessat(res, dfd, filename, mode) \
+ __sanitizer_syscall_post_impl_faccessat(res, (long)(dfd), (long)(filename), \
(long)(mode))
-#define __sanitizer_syscall_pre_fchmodat(dfd, filename, mode) \
- __sanitizer_syscall_pre_impl_fchmodat((long)(dfd), (long)(filename), \
+#define __sanitizer_syscall_pre_fchmodat(dfd, filename, mode) \
+ __sanitizer_syscall_pre_impl_fchmodat((long)(dfd), (long)(filename), \
(long)(mode))
-#define __sanitizer_syscall_post_fchmodat(res, dfd, filename, mode) \
- __sanitizer_syscall_post_impl_fchmodat(res, (long)(dfd), (long)(filename), \
+#define __sanitizer_syscall_post_fchmodat(res, dfd, filename, mode) \
+ __sanitizer_syscall_post_impl_fchmodat(res, (long)(dfd), (long)(filename), \
(long)(mode))
-#define __sanitizer_syscall_pre_fchownat(dfd, filename, user, group, flag) \
- __sanitizer_syscall_pre_impl_fchownat((long)(dfd), (long)(filename), \
- (long)(user), (long)(group), \
+#define __sanitizer_syscall_pre_fchownat(dfd, filename, user, group, flag) \
+ __sanitizer_syscall_pre_impl_fchownat((long)(dfd), (long)(filename), \
+ (long)(user), (long)(group), \
(long)(flag))
-#define __sanitizer_syscall_post_fchownat(res, dfd, filename, user, group, \
- flag) \
- __sanitizer_syscall_post_impl_fchownat(res, (long)(dfd), (long)(filename), \
- (long)(user), (long)(group), \
+#define __sanitizer_syscall_post_fchownat(res, dfd, filename, user, group, \
+ flag) \
+ __sanitizer_syscall_post_impl_fchownat(res, (long)(dfd), (long)(filename), \
+ (long)(user), (long)(group), \
(long)(flag))
-#define __sanitizer_syscall_pre_openat(dfd, filename, flags, mode) \
- __sanitizer_syscall_pre_impl_openat((long)(dfd), (long)(filename), \
+#define __sanitizer_syscall_pre_openat(dfd, filename, flags, mode) \
+ __sanitizer_syscall_pre_impl_openat((long)(dfd), (long)(filename), \
(long)(flags), (long)(mode))
-#define __sanitizer_syscall_post_openat(res, dfd, filename, flags, mode) \
- __sanitizer_syscall_post_impl_openat(res, (long)(dfd), (long)(filename), \
+#define __sanitizer_syscall_post_openat(res, dfd, filename, flags, mode) \
+ __sanitizer_syscall_post_impl_openat(res, (long)(dfd), (long)(filename), \
(long)(flags), (long)(mode))
-#define __sanitizer_syscall_pre_newfstatat(dfd, filename, statbuf, flag) \
- __sanitizer_syscall_pre_impl_newfstatat((long)(dfd), (long)(filename), \
+#define __sanitizer_syscall_pre_newfstatat(dfd, filename, statbuf, flag) \
+ __sanitizer_syscall_pre_impl_newfstatat((long)(dfd), (long)(filename), \
(long)(statbuf), (long)(flag))
#define __sanitizer_syscall_post_newfstatat(res, dfd, filename, statbuf, flag) \
__sanitizer_syscall_post_impl_newfstatat(res, (long)(dfd), (long)(filename), \
(long)(statbuf), (long)(flag))
-#define __sanitizer_syscall_pre_fstatat64(dfd, filename, statbuf, flag) \
- __sanitizer_syscall_pre_impl_fstatat64((long)(dfd), (long)(filename), \
+#define __sanitizer_syscall_pre_fstatat64(dfd, filename, statbuf, flag) \
+ __sanitizer_syscall_pre_impl_fstatat64((long)(dfd), (long)(filename), \
(long)(statbuf), (long)(flag))
-#define __sanitizer_syscall_post_fstatat64(res, dfd, filename, statbuf, flag) \
- __sanitizer_syscall_post_impl_fstatat64(res, (long)(dfd), (long)(filename), \
+#define __sanitizer_syscall_post_fstatat64(res, dfd, filename, statbuf, flag) \
+ __sanitizer_syscall_post_impl_fstatat64(res, (long)(dfd), (long)(filename), \
(long)(statbuf), (long)(flag))
-#define __sanitizer_syscall_pre_readlinkat(dfd, path, buf, bufsiz) \
- __sanitizer_syscall_pre_impl_readlinkat((long)(dfd), (long)(path), \
+#define __sanitizer_syscall_pre_readlinkat(dfd, path, buf, bufsiz) \
+ __sanitizer_syscall_pre_impl_readlinkat((long)(dfd), (long)(path), \
(long)(buf), (long)(bufsiz))
-#define __sanitizer_syscall_post_readlinkat(res, dfd, path, buf, bufsiz) \
- __sanitizer_syscall_post_impl_readlinkat(res, (long)(dfd), (long)(path), \
+#define __sanitizer_syscall_post_readlinkat(res, dfd, path, buf, bufsiz) \
+ __sanitizer_syscall_post_impl_readlinkat(res, (long)(dfd), (long)(path), \
(long)(buf), (long)(bufsiz))
-#define __sanitizer_syscall_pre_utimensat(dfd, filename, utimes, flags) \
- __sanitizer_syscall_pre_impl_utimensat((long)(dfd), (long)(filename), \
+#define __sanitizer_syscall_pre_utimensat(dfd, filename, utimes, flags) \
+ __sanitizer_syscall_pre_impl_utimensat((long)(dfd), (long)(filename), \
(long)(utimes), (long)(flags))
-#define __sanitizer_syscall_post_utimensat(res, dfd, filename, utimes, flags) \
- __sanitizer_syscall_post_impl_utimensat(res, (long)(dfd), (long)(filename), \
+#define __sanitizer_syscall_post_utimensat(res, dfd, filename, utimes, flags) \
+ __sanitizer_syscall_post_impl_utimensat(res, (long)(dfd), (long)(filename), \
(long)(utimes), (long)(flags))
-#define __sanitizer_syscall_pre_unshare(unshare_flags) \
+#define __sanitizer_syscall_pre_unshare(unshare_flags) \
__sanitizer_syscall_pre_impl_unshare((long)(unshare_flags))
-#define __sanitizer_syscall_post_unshare(res, unshare_flags) \
+#define __sanitizer_syscall_post_unshare(res, unshare_flags) \
__sanitizer_syscall_post_impl_unshare(res, (long)(unshare_flags))
-#define __sanitizer_syscall_pre_splice(fd_in, off_in, fd_out, off_out, len, \
- flags) \
- __sanitizer_syscall_pre_impl_splice((long)(fd_in), (long)(off_in), \
- (long)(fd_out), (long)(off_out), \
+#define __sanitizer_syscall_pre_splice(fd_in, off_in, fd_out, off_out, len, \
+ flags) \
+ __sanitizer_syscall_pre_impl_splice((long)(fd_in), (long)(off_in), \
+ (long)(fd_out), (long)(off_out), \
(long)(len), (long)(flags))
-#define __sanitizer_syscall_post_splice(res, fd_in, off_in, fd_out, off_out, \
- len, flags) \
- __sanitizer_syscall_post_impl_splice(res, (long)(fd_in), (long)(off_in), \
- (long)(fd_out), (long)(off_out), \
+#define __sanitizer_syscall_post_splice(res, fd_in, off_in, fd_out, off_out, \
+ len, flags) \
+ __sanitizer_syscall_post_impl_splice(res, (long)(fd_in), (long)(off_in), \
+ (long)(fd_out), (long)(off_out), \
(long)(len), (long)(flags))
-#define __sanitizer_syscall_pre_vmsplice(fd, iov, nr_segs, flags) \
- __sanitizer_syscall_pre_impl_vmsplice((long)(fd), (long)(iov), \
+#define __sanitizer_syscall_pre_vmsplice(fd, iov, nr_segs, flags) \
+ __sanitizer_syscall_pre_impl_vmsplice((long)(fd), (long)(iov), \
(long)(nr_segs), (long)(flags))
-#define __sanitizer_syscall_post_vmsplice(res, fd, iov, nr_segs, flags) \
- __sanitizer_syscall_post_impl_vmsplice(res, (long)(fd), (long)(iov), \
+#define __sanitizer_syscall_post_vmsplice(res, fd, iov, nr_segs, flags) \
+ __sanitizer_syscall_post_impl_vmsplice(res, (long)(fd), (long)(iov), \
(long)(nr_segs), (long)(flags))
-#define __sanitizer_syscall_pre_tee(fdin, fdout, len, flags) \
- __sanitizer_syscall_pre_impl_tee((long)(fdin), (long)(fdout), (long)(len), \
+#define __sanitizer_syscall_pre_tee(fdin, fdout, len, flags) \
+ __sanitizer_syscall_pre_impl_tee((long)(fdin), (long)(fdout), (long)(len), \
(long)(flags))
-#define __sanitizer_syscall_post_tee(res, fdin, fdout, len, flags) \
- __sanitizer_syscall_post_impl_tee(res, (long)(fdin), (long)(fdout), \
+#define __sanitizer_syscall_post_tee(res, fdin, fdout, len, flags) \
+ __sanitizer_syscall_post_impl_tee(res, (long)(fdin), (long)(fdout), \
(long)(len), (long)(flags))
-#define __sanitizer_syscall_pre_get_robust_list(pid, head_ptr, len_ptr) \
- __sanitizer_syscall_pre_impl_get_robust_list((long)(pid), (long)(head_ptr), \
+#define __sanitizer_syscall_pre_get_robust_list(pid, head_ptr, len_ptr) \
+ __sanitizer_syscall_pre_impl_get_robust_list((long)(pid), (long)(head_ptr), \
(long)(len_ptr))
-#define __sanitizer_syscall_post_get_robust_list(res, pid, head_ptr, len_ptr) \
- __sanitizer_syscall_post_impl_get_robust_list( \
+#define __sanitizer_syscall_post_get_robust_list(res, pid, head_ptr, len_ptr) \
+ __sanitizer_syscall_post_impl_get_robust_list( \
res, (long)(pid), (long)(head_ptr), (long)(len_ptr))
-#define __sanitizer_syscall_pre_set_robust_list(head, len) \
+#define __sanitizer_syscall_pre_set_robust_list(head, len) \
__sanitizer_syscall_pre_impl_set_robust_list((long)(head), (long)(len))
-#define __sanitizer_syscall_post_set_robust_list(res, head, len) \
+#define __sanitizer_syscall_post_set_robust_list(res, head, len) \
__sanitizer_syscall_post_impl_set_robust_list(res, (long)(head), (long)(len))
-#define __sanitizer_syscall_pre_getcpu(cpu, node, cache) \
+#define __sanitizer_syscall_pre_getcpu(cpu, node, cache) \
__sanitizer_syscall_pre_impl_getcpu((long)(cpu), (long)(node), (long)(cache))
-#define __sanitizer_syscall_post_getcpu(res, cpu, node, cache) \
- __sanitizer_syscall_post_impl_getcpu(res, (long)(cpu), (long)(node), \
+#define __sanitizer_syscall_post_getcpu(res, cpu, node, cache) \
+ __sanitizer_syscall_post_impl_getcpu(res, (long)(cpu), (long)(node), \
(long)(cache))
-#define __sanitizer_syscall_pre_signalfd(ufd, user_mask, sizemask) \
- __sanitizer_syscall_pre_impl_signalfd((long)(ufd), (long)(user_mask), \
+#define __sanitizer_syscall_pre_signalfd(ufd, user_mask, sizemask) \
+ __sanitizer_syscall_pre_impl_signalfd((long)(ufd), (long)(user_mask), \
(long)(sizemask))
-#define __sanitizer_syscall_post_signalfd(res, ufd, user_mask, sizemask) \
- __sanitizer_syscall_post_impl_signalfd(res, (long)(ufd), (long)(user_mask), \
+#define __sanitizer_syscall_post_signalfd(res, ufd, user_mask, sizemask) \
+ __sanitizer_syscall_post_impl_signalfd(res, (long)(ufd), (long)(user_mask), \
(long)(sizemask))
-#define __sanitizer_syscall_pre_signalfd4(ufd, user_mask, sizemask, flags) \
- __sanitizer_syscall_pre_impl_signalfd4((long)(ufd), (long)(user_mask), \
+#define __sanitizer_syscall_pre_signalfd4(ufd, user_mask, sizemask, flags) \
+ __sanitizer_syscall_pre_impl_signalfd4((long)(ufd), (long)(user_mask), \
(long)(sizemask), (long)(flags))
#define __sanitizer_syscall_post_signalfd4(res, ufd, user_mask, sizemask, \
flags) \
__sanitizer_syscall_post_impl_signalfd4(res, (long)(ufd), (long)(user_mask), \
(long)(sizemask), (long)(flags))
-#define __sanitizer_syscall_pre_timerfd_create(clockid, flags) \
+#define __sanitizer_syscall_pre_timerfd_create(clockid, flags) \
__sanitizer_syscall_pre_impl_timerfd_create((long)(clockid), (long)(flags))
-#define __sanitizer_syscall_post_timerfd_create(res, clockid, flags) \
- __sanitizer_syscall_post_impl_timerfd_create(res, (long)(clockid), \
+#define __sanitizer_syscall_post_timerfd_create(res, clockid, flags) \
+ __sanitizer_syscall_post_impl_timerfd_create(res, (long)(clockid), \
(long)(flags))
-#define __sanitizer_syscall_pre_timerfd_settime(ufd, flags, utmr, otmr) \
- __sanitizer_syscall_pre_impl_timerfd_settime((long)(ufd), (long)(flags), \
+#define __sanitizer_syscall_pre_timerfd_settime(ufd, flags, utmr, otmr) \
+ __sanitizer_syscall_pre_impl_timerfd_settime((long)(ufd), (long)(flags), \
(long)(utmr), (long)(otmr))
-#define __sanitizer_syscall_post_timerfd_settime(res, ufd, flags, utmr, otmr) \
- __sanitizer_syscall_post_impl_timerfd_settime( \
+#define __sanitizer_syscall_post_timerfd_settime(res, ufd, flags, utmr, otmr) \
+ __sanitizer_syscall_post_impl_timerfd_settime( \
res, (long)(ufd), (long)(flags), (long)(utmr), (long)(otmr))
-#define __sanitizer_syscall_pre_timerfd_gettime(ufd, otmr) \
+#define __sanitizer_syscall_pre_timerfd_gettime(ufd, otmr) \
__sanitizer_syscall_pre_impl_timerfd_gettime((long)(ufd), (long)(otmr))
-#define __sanitizer_syscall_post_timerfd_gettime(res, ufd, otmr) \
+#define __sanitizer_syscall_post_timerfd_gettime(res, ufd, otmr) \
__sanitizer_syscall_post_impl_timerfd_gettime(res, (long)(ufd), (long)(otmr))
-#define __sanitizer_syscall_pre_eventfd(count) \
+#define __sanitizer_syscall_pre_eventfd(count) \
__sanitizer_syscall_pre_impl_eventfd((long)(count))
-#define __sanitizer_syscall_post_eventfd(res, count) \
+#define __sanitizer_syscall_post_eventfd(res, count) \
__sanitizer_syscall_post_impl_eventfd(res, (long)(count))
-#define __sanitizer_syscall_pre_eventfd2(count, flags) \
+#define __sanitizer_syscall_pre_eventfd2(count, flags) \
__sanitizer_syscall_pre_impl_eventfd2((long)(count), (long)(flags))
-#define __sanitizer_syscall_post_eventfd2(res, count, flags) \
+#define __sanitizer_syscall_post_eventfd2(res, count, flags) \
__sanitizer_syscall_post_impl_eventfd2(res, (long)(count), (long)(flags))
-#define __sanitizer_syscall_pre_old_readdir(arg0, arg1, arg2) \
- __sanitizer_syscall_pre_impl_old_readdir((long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_pre_old_readdir(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_old_readdir((long)(arg0), (long)(arg1), \
(long)(arg2))
-#define __sanitizer_syscall_post_old_readdir(res, arg0, arg1, arg2) \
- __sanitizer_syscall_post_impl_old_readdir(res, (long)(arg0), (long)(arg1), \
+#define __sanitizer_syscall_post_old_readdir(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_old_readdir(res, (long)(arg0), (long)(arg1), \
(long)(arg2))
-#define __sanitizer_syscall_pre_pselect6(arg0, arg1, arg2, arg3, arg4, arg5) \
- __sanitizer_syscall_pre_impl_pselect6((long)(arg0), (long)(arg1), \
- (long)(arg2), (long)(arg3), \
+#define __sanitizer_syscall_pre_pselect6(arg0, arg1, arg2, arg3, arg4, arg5) \
+ __sanitizer_syscall_pre_impl_pselect6((long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
(long)(arg4), (long)(arg5))
-#define __sanitizer_syscall_post_pselect6(res, arg0, arg1, arg2, arg3, arg4, \
- arg5) \
- __sanitizer_syscall_post_impl_pselect6(res, (long)(arg0), (long)(arg1), \
- (long)(arg2), (long)(arg3), \
+#define __sanitizer_syscall_post_pselect6(res, arg0, arg1, arg2, arg3, arg4, \
+ arg5) \
+ __sanitizer_syscall_post_impl_pselect6(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
(long)(arg4), (long)(arg5))
#define __sanitizer_syscall_pre_ppoll(arg0, arg1, arg2, arg3, arg4) \
__sanitizer_syscall_pre_impl_ppoll((long)(arg0), (long)(arg1), (long)(arg2), \
(long)(arg3), (long)(arg4))
-#define __sanitizer_syscall_post_ppoll(res, arg0, arg1, arg2, arg3, arg4) \
- __sanitizer_syscall_post_impl_ppoll(res, (long)(arg0), (long)(arg1), \
- (long)(arg2), (long)(arg3), \
+#define __sanitizer_syscall_post_ppoll(res, arg0, arg1, arg2, arg3, arg4) \
+ __sanitizer_syscall_post_impl_ppoll(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
(long)(arg4))
-#define __sanitizer_syscall_pre_syncfs(fd) \
+#define __sanitizer_syscall_pre_syncfs(fd) \
__sanitizer_syscall_pre_impl_syncfs((long)(fd))
-#define __sanitizer_syscall_post_syncfs(res, fd) \
+#define __sanitizer_syscall_post_syncfs(res, fd) \
__sanitizer_syscall_post_impl_syncfs(res, (long)(fd))
#define __sanitizer_syscall_pre_perf_event_open(attr_uptr, pid, cpu, group_fd, \
flags) \
__sanitizer_syscall_pre_impl_perf_event_open((long)(attr_uptr), (long)(pid), \
(long)(cpu), (long)(group_fd), \
(long)(flags))
-#define __sanitizer_syscall_post_perf_event_open(res, attr_uptr, pid, cpu, \
- group_fd, flags) \
- __sanitizer_syscall_post_impl_perf_event_open( \
- res, (long)(attr_uptr), (long)(pid), (long)(cpu), (long)(group_fd), \
+#define __sanitizer_syscall_post_perf_event_open(res, attr_uptr, pid, cpu, \
+ group_fd, flags) \
+ __sanitizer_syscall_post_impl_perf_event_open( \
+ res, (long)(attr_uptr), (long)(pid), (long)(cpu), (long)(group_fd), \
(long)(flags))
-#define __sanitizer_syscall_pre_mmap_pgoff(addr, len, prot, flags, fd, pgoff) \
- __sanitizer_syscall_pre_impl_mmap_pgoff((long)(addr), (long)(len), \
- (long)(prot), (long)(flags), \
+#define __sanitizer_syscall_pre_mmap_pgoff(addr, len, prot, flags, fd, pgoff) \
+ __sanitizer_syscall_pre_impl_mmap_pgoff((long)(addr), (long)(len), \
+ (long)(prot), (long)(flags), \
(long)(fd), (long)(pgoff))
-#define __sanitizer_syscall_post_mmap_pgoff(res, addr, len, prot, flags, fd, \
- pgoff) \
- __sanitizer_syscall_post_impl_mmap_pgoff(res, (long)(addr), (long)(len), \
- (long)(prot), (long)(flags), \
+#define __sanitizer_syscall_post_mmap_pgoff(res, addr, len, prot, flags, fd, \
+ pgoff) \
+ __sanitizer_syscall_post_impl_mmap_pgoff(res, (long)(addr), (long)(len), \
+ (long)(prot), (long)(flags), \
(long)(fd), (long)(pgoff))
-#define __sanitizer_syscall_pre_old_mmap(arg) \
+#define __sanitizer_syscall_pre_old_mmap(arg) \
__sanitizer_syscall_pre_impl_old_mmap((long)(arg))
-#define __sanitizer_syscall_post_old_mmap(res, arg) \
+#define __sanitizer_syscall_post_old_mmap(res, arg) \
__sanitizer_syscall_post_impl_old_mmap(res, (long)(arg))
-#define __sanitizer_syscall_pre_name_to_handle_at(dfd, name, handle, mnt_id, \
- flag) \
- __sanitizer_syscall_pre_impl_name_to_handle_at( \
+#define __sanitizer_syscall_pre_name_to_handle_at(dfd, name, handle, mnt_id, \
+ flag) \
+ __sanitizer_syscall_pre_impl_name_to_handle_at( \
(long)(dfd), (long)(name), (long)(handle), (long)(mnt_id), (long)(flag))
-#define __sanitizer_syscall_post_name_to_handle_at(res, dfd, name, handle, \
- mnt_id, flag) \
- __sanitizer_syscall_post_impl_name_to_handle_at( \
- res, (long)(dfd), (long)(name), (long)(handle), (long)(mnt_id), \
+#define __sanitizer_syscall_post_name_to_handle_at(res, dfd, name, handle, \
+ mnt_id, flag) \
+ __sanitizer_syscall_post_impl_name_to_handle_at( \
+ res, (long)(dfd), (long)(name), (long)(handle), (long)(mnt_id), \
(long)(flag))
-#define __sanitizer_syscall_pre_open_by_handle_at(mountdirfd, handle, flags) \
- __sanitizer_syscall_pre_impl_open_by_handle_at( \
+#define __sanitizer_syscall_pre_open_by_handle_at(mountdirfd, handle, flags) \
+ __sanitizer_syscall_pre_impl_open_by_handle_at( \
(long)(mountdirfd), (long)(handle), (long)(flags))
-#define __sanitizer_syscall_post_open_by_handle_at(res, mountdirfd, handle, \
- flags) \
- __sanitizer_syscall_post_impl_open_by_handle_at( \
+#define __sanitizer_syscall_post_open_by_handle_at(res, mountdirfd, handle, \
+ flags) \
+ __sanitizer_syscall_post_impl_open_by_handle_at( \
res, (long)(mountdirfd), (long)(handle), (long)(flags))
-#define __sanitizer_syscall_pre_setns(fd, nstype) \
+#define __sanitizer_syscall_pre_setns(fd, nstype) \
__sanitizer_syscall_pre_impl_setns((long)(fd), (long)(nstype))
-#define __sanitizer_syscall_post_setns(res, fd, nstype) \
+#define __sanitizer_syscall_post_setns(res, fd, nstype) \
__sanitizer_syscall_post_impl_setns(res, (long)(fd), (long)(nstype))
-#define __sanitizer_syscall_pre_process_vm_readv(pid, lvec, liovcnt, rvec, \
- riovcnt, flags) \
- __sanitizer_syscall_pre_impl_process_vm_readv( \
- (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
+#define __sanitizer_syscall_pre_process_vm_readv(pid, lvec, liovcnt, rvec, \
+ riovcnt, flags) \
+ __sanitizer_syscall_pre_impl_process_vm_readv( \
+ (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
(long)(riovcnt), (long)(flags))
-#define __sanitizer_syscall_post_process_vm_readv(res, pid, lvec, liovcnt, \
- rvec, riovcnt, flags) \
- __sanitizer_syscall_post_impl_process_vm_readv( \
- res, (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
+#define __sanitizer_syscall_post_process_vm_readv(res, pid, lvec, liovcnt, \
+ rvec, riovcnt, flags) \
+ __sanitizer_syscall_post_impl_process_vm_readv( \
+ res, (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
(long)(riovcnt), (long)(flags))
-#define __sanitizer_syscall_pre_process_vm_writev(pid, lvec, liovcnt, rvec, \
- riovcnt, flags) \
- __sanitizer_syscall_pre_impl_process_vm_writev( \
- (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
+#define __sanitizer_syscall_pre_process_vm_writev(pid, lvec, liovcnt, rvec, \
+ riovcnt, flags) \
+ __sanitizer_syscall_pre_impl_process_vm_writev( \
+ (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
(long)(riovcnt), (long)(flags))
-#define __sanitizer_syscall_post_process_vm_writev(res, pid, lvec, liovcnt, \
- rvec, riovcnt, flags) \
- __sanitizer_syscall_post_impl_process_vm_writev( \
- res, (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
+#define __sanitizer_syscall_post_process_vm_writev(res, pid, lvec, liovcnt, \
+ rvec, riovcnt, flags) \
+ __sanitizer_syscall_post_impl_process_vm_writev( \
+ res, (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
(long)(riovcnt), (long)(flags))
-#define __sanitizer_syscall_pre_fork() \
- __sanitizer_syscall_pre_impl_fork()
-#define __sanitizer_syscall_post_fork(res) \
+#define __sanitizer_syscall_pre_fork() __sanitizer_syscall_pre_impl_fork()
+#define __sanitizer_syscall_post_fork(res) \
__sanitizer_syscall_post_impl_fork(res)
-#define __sanitizer_syscall_pre_vfork() \
- __sanitizer_syscall_pre_impl_vfork()
-#define __sanitizer_syscall_post_vfork(res) \
+#define __sanitizer_syscall_pre_vfork() __sanitizer_syscall_pre_impl_vfork()
+#define __sanitizer_syscall_post_vfork(res) \
__sanitizer_syscall_post_impl_vfork(res)
#define __sanitizer_syscall_pre_sigaction(signum, act, oldact) \
__sanitizer_syscall_pre_impl_sigaction((long)signum, (long)act, (long)oldact)
@@ -2699,6 +2706,13 @@ void __sanitizer_syscall_pre_impl_epoll_pwait(long epfd, long events,
void __sanitizer_syscall_post_impl_epoll_pwait(long res, long epfd, long events,
long maxevents, long timeout,
long sigmask, long sigsetsize);
+void __sanitizer_syscall_pre_impl_epoll_pwait2(long epfd, long events,
+ long maxevents, long timeout,
+ long sigmask, long sigsetsize);
+void __sanitizer_syscall_post_impl_epoll_pwait2(long res, long epfd,
+ long events, long maxevents,
+ long timeout, long sigmask,
+ long sigsetsize);
void __sanitizer_syscall_pre_impl_gethostname(long name, long len);
void __sanitizer_syscall_post_impl_gethostname(long res, long name, long len);
void __sanitizer_syscall_pre_impl_sethostname(long name, long len);
@@ -3080,7 +3094,7 @@ void __sanitizer_syscall_post_impl_rt_sigaction(long res, long signum, long act,
void __sanitizer_syscall_pre_impl_sigaltstack(long ss, long oss);
void __sanitizer_syscall_post_impl_sigaltstack(long res, long ss, long oss);
#ifdef __cplusplus
-} // extern "C"
+} // extern "C"
#endif
-#endif // SANITIZER_LINUX_SYSCALL_HOOKS_H
+#endif // SANITIZER_LINUX_SYSCALL_HOOKS_H
diff --git a/libsanitizer/include/sanitizer/tsan_interface.h b/libsanitizer/include/sanitizer/tsan_interface.h
index 565aa39..2782e61 100644
--- a/libsanitizer/include/sanitizer/tsan_interface.h
+++ b/libsanitizer/include/sanitizer/tsan_interface.h
@@ -169,6 +169,9 @@ void __tsan_on_initialize();
// if TSan should exit as if issues were detected.
int __tsan_on_finalize(int failed);
+// Release TSan internal memory in a best-effort manner.
+void __tsan_flush_memory();
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/libsanitizer/interception/interception_win.cpp b/libsanitizer/interception/interception_win.cpp
index 98bc756..38b8c05 100644
--- a/libsanitizer/interception/interception_win.cpp
+++ b/libsanitizer/interception/interception_win.cpp
@@ -56,7 +56,7 @@
// tramp: jmp QWORD [addr]
// addr: .bytes <hook>
//
-// Note: <real> is equilavent to <label>.
+// Note: <real> is equivalent to <label>.
//
// 3) HotPatch
//
@@ -398,8 +398,42 @@ static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) {
return allocated_space;
}
+// The following prologues cannot be patched because of the short jump
+// jumping to the patching region.
+
+// ntdll!wcslen in Win11
+// 488bc1 mov rax,rcx
+// 0fb710 movzx edx,word ptr [rax]
+// 4883c002 add rax,2
+// 6685d2 test dx,dx
+// 75f4 jne -12
+static const u8 kPrologueWithShortJump1[] = {
+ 0x48, 0x8b, 0xc1, 0x0f, 0xb7, 0x10, 0x48, 0x83,
+ 0xc0, 0x02, 0x66, 0x85, 0xd2, 0x75, 0xf4,
+};
+
+// ntdll!strrchr in Win11
+// 4c8bc1 mov r8,rcx
+// 8a01 mov al,byte ptr [rcx]
+// 48ffc1 inc rcx
+// 84c0 test al,al
+// 75f7 jne -9
+static const u8 kPrologueWithShortJump2[] = {
+ 0x4c, 0x8b, 0xc1, 0x8a, 0x01, 0x48, 0xff, 0xc1,
+ 0x84, 0xc0, 0x75, 0xf7,
+};
+
// Returns 0 on error.
static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
+#if SANITIZER_WINDOWS64
+ if (memcmp((u8*)address, kPrologueWithShortJump1,
+ sizeof(kPrologueWithShortJump1)) == 0 ||
+ memcmp((u8*)address, kPrologueWithShortJump2,
+ sizeof(kPrologueWithShortJump2)) == 0) {
+ return 0;
+ }
+#endif
+
switch (*(u64*)address) {
case 0x90909090909006EB: // stub: jmp over 6 x nop.
return 8;
@@ -477,6 +511,14 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
case 0xA1: // A1 XX XX XX XX XX XX XX XX :
// movabs eax, dword ptr ds:[XXXXXXXX]
return 9;
+
+ case 0x83:
+ const u8 next_byte = *(u8*)(address + 1);
+ const u8 mod = next_byte >> 6;
+ const u8 rm = next_byte & 7;
+ if (mod == 1 && rm == 4)
+ return 5; // 83 ModR/M SIB Disp8 Imm8
+ // add|or|adc|sbb|and|sub|xor|cmp [r+disp8], imm8
}
switch (*(u16*)address) {
@@ -493,6 +535,8 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
case 0x5641: // push r14
case 0x5741: // push r15
case 0x9066: // Two-byte NOP
+ case 0xc084: // test al, al
+ case 0x018a: // mov al, byte ptr [rcx]
return 2;
case 0x058B: // 8B 05 XX XX XX XX : mov eax, dword ptr [XX XX XX XX]
@@ -509,6 +553,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
case 0xd12b48: // 48 2b d1 : sub rdx, rcx
case 0x07c1f6: // f6 c1 07 : test cl, 0x7
case 0xc98548: // 48 85 C9 : test rcx, rcx
+ case 0xd28548: // 48 85 d2 : test rdx, rdx
case 0xc0854d: // 4d 85 c0 : test r8, r8
case 0xc2b60f: // 0f b6 c2 : movzx eax, dl
case 0xc03345: // 45 33 c0 : xor r8d, r8d
@@ -522,6 +567,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
case 0xca2b48: // 48 2b ca : sub rcx, rdx
case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax]
case 0xc00b4d: // 3d 0b c0 : or r8, r8
+ case 0xc08b41: // 41 8b c0 : mov eax, r8d
case 0xd18b48: // 48 8b d1 : mov rdx, rcx
case 0xdc8b4c: // 4c 8b dc : mov r11, rsp
case 0xd18b4c: // 4c 8b d1 : mov r10, rcx
diff --git a/libsanitizer/lsan/lsan_allocator.h b/libsanitizer/lsan/lsan_allocator.h
index 9d76378..45c6ac4 100644
--- a/libsanitizer/lsan/lsan_allocator.h
+++ b/libsanitizer/lsan/lsan_allocator.h
@@ -50,7 +50,7 @@ struct ChunkMetadata {
};
#if defined(__mips64) || defined(__aarch64__) || defined(__i386__) || \
- defined(__arm__) || SANITIZER_RISCV64
+ defined(__arm__) || SANITIZER_RISCV64 || defined(__hexagon__)
template <typename AddressSpaceViewTy>
struct AP32 {
static const uptr kSpaceBeg = 0;
diff --git a/libsanitizer/lsan/lsan_common.cpp b/libsanitizer/lsan/lsan_common.cpp
index 74400d2..5f8fc5b 100644
--- a/libsanitizer/lsan/lsan_common.cpp
+++ b/libsanitizer/lsan/lsan_common.cpp
@@ -30,7 +30,7 @@ namespace __lsan {
// This mutex is used to prevent races between DoLeakCheck and IgnoreObject, and
// also to protect the global list of root regions.
-BlockingMutex global_mutex(LINKER_INITIALIZED);
+Mutex global_mutex;
Flags lsan_flags;
@@ -79,7 +79,8 @@ class LeakSuppressionContext {
int suppression_types_num)
: context(supprression_types, suppression_types_num) {}
- Suppression *GetSuppressionForStack(u32 stack_trace_id);
+ Suppression *GetSuppressionForStack(u32 stack_trace_id,
+ const StackTrace &stack);
const InternalMmapVector<u32> &GetSortedSuppressedStacks() {
if (!suppressed_stacks_sorted) {
@@ -477,9 +478,7 @@ static void CollectIgnoredCb(uptr chunk, void *arg) {
}
}
-static uptr GetCallerPC(u32 stack_id, StackDepotReverseMap *map) {
- CHECK(stack_id);
- StackTrace stack = map->Get(stack_id);
+static uptr GetCallerPC(const StackTrace &stack) {
// The top frame is our malloc/calloc/etc. The next frame is the caller.
if (stack.size >= 2)
return stack.trace[1];
@@ -488,7 +487,7 @@ static uptr GetCallerPC(u32 stack_id, StackDepotReverseMap *map) {
struct InvalidPCParam {
Frontier *frontier;
- StackDepotReverseMap *stack_depot_reverse_map;
+ const StackDepotReverseMap *stack_depot;
bool skip_linker_allocations;
};
@@ -503,7 +502,7 @@ static void MarkInvalidPCCb(uptr chunk, void *arg) {
u32 stack_id = m.stack_trace_id();
uptr caller_pc = 0;
if (stack_id > 0)
- caller_pc = GetCallerPC(stack_id, param->stack_depot_reverse_map);
+ caller_pc = GetCallerPC(param->stack_depot->Get(stack_id));
// If caller_pc is unknown, this chunk may be allocated in a coroutine. Mark
// it as reachable, as we can't properly report its allocation stack anyway.
if (caller_pc == 0 || (param->skip_linker_allocations &&
@@ -534,11 +533,11 @@ static void MarkInvalidPCCb(uptr chunk, void *arg) {
// which we don't care about).
// On all other platforms, this simply checks to ensure that the caller pc is
// valid before reporting chunks as leaked.
-void ProcessPC(Frontier *frontier) {
- StackDepotReverseMap stack_depot_reverse_map;
+static void ProcessPC(Frontier *frontier,
+ const StackDepotReverseMap &stack_depot) {
InvalidPCParam arg;
arg.frontier = frontier;
- arg.stack_depot_reverse_map = &stack_depot_reverse_map;
+ arg.stack_depot = &stack_depot;
arg.skip_linker_allocations =
flags()->use_tls && flags()->use_ld_allocations && GetLinker() != nullptr;
ForEachChunk(MarkInvalidPCCb, &arg);
@@ -546,6 +545,7 @@ void ProcessPC(Frontier *frontier) {
// Sets the appropriate tag on each chunk.
static void ClassifyAllChunks(SuspendedThreadsList const &suspended_threads,
+ const StackDepotReverseMap &stack_depot,
Frontier *frontier) {
const InternalMmapVector<u32> &suppressed_stacks =
GetSuppressionContext()->GetSortedSuppressedStacks();
@@ -560,7 +560,7 @@ static void ClassifyAllChunks(SuspendedThreadsList const &suspended_threads,
FloodFillTag(frontier, kReachable);
CHECK_EQ(0, frontier->size());
- ProcessPC(frontier);
+ ProcessPC(frontier, stack_depot);
// The check here is relatively expensive, so we do this in a separate flood
// fill. That way we can skip the check for chunks that are reachable
@@ -584,11 +584,6 @@ static void ResetTagsCb(uptr chunk, void *arg) {
m.set_tag(kDirectlyLeaked);
}
-static void PrintStackTraceById(u32 stack_trace_id) {
- CHECK(stack_trace_id);
- StackDepotGet(stack_trace_id).Print();
-}
-
// ForEachChunk callback. Aggregates information about unreachable chunks into
// a LeakReport.
static void CollectLeaksCb(uptr chunk, void *arg) {
@@ -598,16 +593,7 @@ static void CollectLeaksCb(uptr chunk, void *arg) {
LsanMetadata m(chunk);
if (!m.allocated()) return;
if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked) {
- u32 resolution = flags()->resolution;
- u32 stack_trace_id = 0;
- if (resolution > 0) {
- StackTrace stack = StackDepotGet(m.stack_trace_id());
- stack.size = Min(stack.size, resolution);
- stack_trace_id = StackDepotPut(stack);
- } else {
- stack_trace_id = m.stack_trace_id();
- }
- leak_report->AddLeakedChunk(chunk, stack_trace_id, m.requested_size(),
+ leak_report->AddLeakedChunk(chunk, m.stack_trace_id(), m.requested_size(),
m.tag());
}
}
@@ -668,7 +654,8 @@ static void CheckForLeaksCallback(const SuspendedThreadsList &suspended_threads,
CHECK(param);
CHECK(!param->success);
ReportUnsuspendedThreads(suspended_threads);
- ClassifyAllChunks(suspended_threads, &param->frontier);
+ ClassifyAllChunks(suspended_threads, param->leak_report.stack_depot(),
+ &param->frontier);
ForEachChunk(CollectLeaksCb, &param->leak_report);
// Clean up for subsequent leak checks. This assumes we did not overwrite any
// kIgnored tags.
@@ -742,7 +729,7 @@ static bool has_reported_leaks = false;
bool HasReportedLeaks() { return has_reported_leaks; }
void DoLeakCheck() {
- BlockingMutexLock l(&global_mutex);
+ Lock l(&global_mutex);
static bool already_done;
if (already_done) return;
already_done = true;
@@ -751,7 +738,7 @@ void DoLeakCheck() {
}
static int DoRecoverableLeakCheck() {
- BlockingMutexLock l(&global_mutex);
+ Lock l(&global_mutex);
bool have_leaks = CheckForLeaks();
return have_leaks ? 1 : 0;
}
@@ -780,9 +767,8 @@ Suppression *LeakSuppressionContext::GetSuppressionForAddr(uptr addr) {
}
Suppression *LeakSuppressionContext::GetSuppressionForStack(
- u32 stack_trace_id) {
+ u32 stack_trace_id, const StackTrace &stack) {
LazyInit();
- StackTrace stack = StackDepotGet(stack_trace_id);
for (uptr i = 0; i < stack.size; i++) {
Suppression *s = GetSuppressionForAddr(
StackTrace::GetPreviousInstructionPc(stack.trace[i]));
@@ -807,6 +793,13 @@ const uptr kMaxLeaksConsidered = 5000;
void LeakReport::AddLeakedChunk(uptr chunk, u32 stack_trace_id,
uptr leaked_size, ChunkTag tag) {
CHECK(tag == kDirectlyLeaked || tag == kIndirectlyLeaked);
+
+ if (u32 resolution = flags()->resolution) {
+ StackTrace stack = stack_depot_.Get(stack_trace_id);
+ stack.size = Min(stack.size, resolution);
+ stack_trace_id = StackDepotPut(stack);
+ }
+
bool is_directly_leaked = (tag == kDirectlyLeaked);
uptr i;
for (i = 0; i < leaks_.size(); i++) {
@@ -869,7 +862,8 @@ void LeakReport::PrintReportForLeak(uptr index) {
leaks_[index].total_size, leaks_[index].hit_count);
Printf("%s", d.Default());
- PrintStackTraceById(leaks_[index].stack_trace_id);
+ CHECK(leaks_[index].stack_trace_id);
+ stack_depot_.Get(leaks_[index].stack_trace_id).Print();
if (flags()->report_objects) {
Printf("Objects leaked above:\n");
@@ -905,8 +899,8 @@ uptr LeakReport::ApplySuppressions() {
LeakSuppressionContext *suppressions = GetSuppressionContext();
uptr new_suppressions = false;
for (uptr i = 0; i < leaks_.size(); i++) {
- Suppression *s =
- suppressions->GetSuppressionForStack(leaks_[i].stack_trace_id);
+ Suppression *s = suppressions->GetSuppressionForStack(
+ leaks_[i].stack_trace_id, stack_depot_.Get(leaks_[i].stack_trace_id));
if (s) {
s->weight += leaks_[i].total_size;
atomic_store_relaxed(&s->hit_count, atomic_load_relaxed(&s->hit_count) +
@@ -954,7 +948,7 @@ void __lsan_ignore_object(const void *p) {
return;
// Cannot use PointsIntoChunk or LsanMetadata here, since the allocator is not
// locked.
- BlockingMutexLock l(&global_mutex);
+ Lock l(&global_mutex);
IgnoreObjectResult res = IgnoreObjectLocked(p);
if (res == kIgnoreObjectInvalid)
VReport(1, "__lsan_ignore_object(): no heap object found at %p", p);
@@ -969,7 +963,7 @@ void __lsan_ignore_object(const void *p) {
SANITIZER_INTERFACE_ATTRIBUTE
void __lsan_register_root_region(const void *begin, uptr size) {
#if CAN_SANITIZE_LEAKS
- BlockingMutexLock l(&global_mutex);
+ Lock l(&global_mutex);
CHECK(root_regions);
RootRegion region = {reinterpret_cast<uptr>(begin), size};
root_regions->push_back(region);
@@ -980,7 +974,7 @@ void __lsan_register_root_region(const void *begin, uptr size) {
SANITIZER_INTERFACE_ATTRIBUTE
void __lsan_unregister_root_region(const void *begin, uptr size) {
#if CAN_SANITIZE_LEAKS
- BlockingMutexLock l(&global_mutex);
+ Lock l(&global_mutex);
CHECK(root_regions);
bool removed = false;
for (uptr i = 0; i < root_regions->size(); i++) {
diff --git a/libsanitizer/lsan/lsan_common.h b/libsanitizer/lsan/lsan_common.h
index 776ca60..c15df1b 100644
--- a/libsanitizer/lsan/lsan_common.h
+++ b/libsanitizer/lsan/lsan_common.h
@@ -18,6 +18,7 @@
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_platform.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_stoptheworld.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
@@ -107,12 +108,14 @@ class LeakReport {
uptr ApplySuppressions();
uptr UnsuppressedLeakCount();
uptr IndirectUnsuppressedLeakCount();
+ const StackDepotReverseMap &stack_depot() { return stack_depot_; }
private:
void PrintReportForLeak(uptr index);
void PrintLeakedObjectsForLeak(uptr index);
u32 next_id_ = 0;
+ StackDepotReverseMap stack_depot_;
InternalMmapVector<Leak> leaks_;
InternalMmapVector<LeakedObject> leaked_objects_;
};
diff --git a/libsanitizer/sanitizer_common/sancov_flags.inc b/libsanitizer/sanitizer_common/sancov_flags.inc
index cca33fc..de9ede2 100644
--- a/libsanitizer/sanitizer_common/sancov_flags.inc
+++ b/libsanitizer/sanitizer_common/sancov_flags.inc
@@ -14,7 +14,7 @@
#endif
SANCOV_FLAG(bool, symbolize, true,
- "If set, converage information will be symbolized by sancov tool "
+ "If set, coverage information will be symbolized by sancov tool "
"after dumping.")
SANCOV_FLAG(bool, help, false, "Print flags help.")
diff --git a/libsanitizer/sanitizer_common/sanitizer_addrhashmap.h b/libsanitizer/sanitizer_common/sanitizer_addrhashmap.h
index 15f81a0..73b48cb 100644
--- a/libsanitizer/sanitizer_common/sanitizer_addrhashmap.h
+++ b/libsanitizer/sanitizer_common/sanitizer_addrhashmap.h
@@ -56,7 +56,7 @@ class AddrHashMap {
static const uptr kBucketSize = 3;
struct Bucket {
- RWMutex mtx;
+ Mutex mtx;
atomic_uintptr_t add;
Cell cells[kBucketSize];
};
diff --git a/libsanitizer/sanitizer_common/sanitizer_allocator_primary64.h b/libsanitizer/sanitizer_common/sanitizer_allocator_primary64.h
index b142ee0..3710947 100644
--- a/libsanitizer/sanitizer_common/sanitizer_allocator_primary64.h
+++ b/libsanitizer/sanitizer_common/sanitizer_allocator_primary64.h
@@ -161,7 +161,7 @@ class SizeClassAllocator64 {
void ForceReleaseToOS() {
MemoryMapperT memory_mapper(*this);
for (uptr class_id = 1; class_id < kNumClasses; class_id++) {
- BlockingMutexLock l(&GetRegionInfo(class_id)->mutex);
+ Lock l(&GetRegionInfo(class_id)->mutex);
MaybeReleaseToOS(&memory_mapper, class_id, true /*force*/);
}
}
@@ -178,7 +178,7 @@ class SizeClassAllocator64 {
uptr region_beg = GetRegionBeginBySizeClass(class_id);
CompactPtrT *free_array = GetFreeArray(region_beg);
- BlockingMutexLock l(&region->mutex);
+ Lock l(&region->mutex);
uptr old_num_chunks = region->num_freed_chunks;
uptr new_num_freed_chunks = old_num_chunks + n_chunks;
// Failure to allocate free array space while releasing memory is non
@@ -204,7 +204,7 @@ class SizeClassAllocator64 {
uptr region_beg = GetRegionBeginBySizeClass(class_id);
CompactPtrT *free_array = GetFreeArray(region_beg);
- BlockingMutexLock l(&region->mutex);
+ Lock l(&region->mutex);
#if SANITIZER_WINDOWS
/* On Windows unmapping of memory during __sanitizer_purge_allocator is
explicit and immediate, so unmapped regions must be explicitly mapped back
@@ -282,6 +282,8 @@ class SizeClassAllocator64 {
CHECK(kMetadataSize);
uptr class_id = GetSizeClass(p);
uptr size = ClassIdToSize(class_id);
+ if (!size)
+ return nullptr;
uptr chunk_idx = GetChunkIdx(reinterpret_cast<uptr>(p), size);
uptr region_beg = GetRegionBeginBySizeClass(class_id);
return reinterpret_cast<void *>(GetMetadataEnd(region_beg) -
@@ -315,7 +317,7 @@ class SizeClassAllocator64 {
Printf(
"%s %02zd (%6zd): mapped: %6zdK allocs: %7zd frees: %7zd inuse: %6zd "
"num_freed_chunks %7zd avail: %6zd rss: %6zdK releases: %6zd "
- "last released: %6zdK region: 0x%zx\n",
+ "last released: %6lldK region: 0x%zx\n",
region->exhausted ? "F" : " ", class_id, ClassIdToSize(class_id),
region->mapped_user >> 10, region->stats.n_allocated,
region->stats.n_freed, in_use, region->num_freed_chunks, avail_chunks,
@@ -623,7 +625,7 @@ class SizeClassAllocator64 {
static const uptr kRegionSize = kSpaceSize / kNumClassesRounded;
// FreeArray is the array of free-d chunks (stored as 4-byte offsets).
- // In the worst case it may reguire kRegionSize/SizeClassMap::kMinSize
+ // In the worst case it may require kRegionSize/SizeClassMap::kMinSize
// elements, but in reality this will not happen. For simplicity we
// dedicate 1/8 of the region's virtual space to FreeArray.
static const uptr kFreeArraySize = kRegionSize / 8;
@@ -665,7 +667,7 @@ class SizeClassAllocator64 {
};
struct ALIGNED(SANITIZER_CACHE_LINE_SIZE) RegionInfo {
- BlockingMutex mutex;
+ Mutex mutex;
uptr num_freed_chunks; // Number of elements in the freearray.
uptr mapped_free_array; // Bytes mapped for freearray.
uptr allocated_user; // Bytes allocated for user memory.
diff --git a/libsanitizer/sanitizer_common/sanitizer_allocator_size_class_map.h b/libsanitizer/sanitizer_common/sanitizer_allocator_size_class_map.h
index c50d133..361793f 100644
--- a/libsanitizer/sanitizer_common/sanitizer_allocator_size_class_map.h
+++ b/libsanitizer/sanitizer_common/sanitizer_allocator_size_class_map.h
@@ -193,13 +193,13 @@ class SizeClassMap {
uptr cached = MaxCachedHint(s) * s;
if (i == kBatchClassID)
d = p = l = 0;
- Printf("c%02zd => s: %zd diff: +%zd %02zd%% l %zd "
- "cached: %zd %zd; id %zd\n",
- i, Size(i), d, p, l, MaxCachedHint(s), cached, ClassID(s));
+ Printf(
+ "c%02zu => s: %zu diff: +%zu %02zu%% l %zu cached: %zu %zu; id %zu\n",
+ i, Size(i), d, p, l, MaxCachedHint(s), cached, ClassID(s));
total_cached += cached;
prev_s = s;
}
- Printf("Total cached: %zd\n", total_cached);
+ Printf("Total cached: %zu\n", total_cached);
}
static void Validate() {
diff --git a/libsanitizer/sanitizer_common/sanitizer_asm.h b/libsanitizer/sanitizer_common/sanitizer_asm.h
index 803af32..6b86120 100644
--- a/libsanitizer/sanitizer_common/sanitizer_asm.h
+++ b/libsanitizer/sanitizer_common/sanitizer_asm.h
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
-// Various support for assemebler.
+// Various support for assembler.
//
//===----------------------------------------------------------------------===//
@@ -61,8 +61,12 @@
#if defined(__ELF__) && (defined(__GNU__) || defined(__FreeBSD__) || \
defined(__Fuchsia__) || defined(__linux__))
// clang-format off
-#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits // NOLINT
+#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
// clang-format on
#else
#define NO_EXEC_STACK_DIRECTIVE
#endif
+
+#if defined(__x86_64__) || defined(__i386__)
+#include <cet.h>
+#endif
diff --git a/libsanitizer/sanitizer_common/sanitizer_atomic_clang_mips.h b/libsanitizer/sanitizer_common/sanitizer_atomic_clang_mips.h
index 2b39097..f3d3052 100644
--- a/libsanitizer/sanitizer_common/sanitizer_atomic_clang_mips.h
+++ b/libsanitizer/sanitizer_common/sanitizer_atomic_clang_mips.h
@@ -18,7 +18,7 @@ namespace __sanitizer {
// MIPS32 does not support atomics > 4 bytes. To address this lack of
// functionality, the sanitizer library provides helper methods which use an
-// internal spin lock mechanism to emulate atomic oprations when the size is
+// internal spin lock mechanism to emulate atomic operations when the size is
// 8 bytes.
static void __spin_lock(volatile int *lock) {
while (__sync_lock_test_and_set(lock, 1))
diff --git a/libsanitizer/sanitizer_common/sanitizer_chained_origin_depot.cpp b/libsanitizer/sanitizer_common/sanitizer_chained_origin_depot.cpp
index 250ac39..7fe9cd7 100644
--- a/libsanitizer/sanitizer_common/sanitizer_chained_origin_depot.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_chained_origin_depot.cpp
@@ -14,7 +14,7 @@
namespace __sanitizer {
bool ChainedOriginDepot::ChainedOriginDepotNode::eq(
- u32 hash, const args_type &args) const {
+ hash_type hash, const args_type &args) const {
return here_id == args.here_id && prev_id == args.prev_id;
}
@@ -36,7 +36,8 @@ uptr ChainedOriginDepot::ChainedOriginDepotNode::storage_size(
split, or one of two reserved values (-1) or (-2). Either case can
dominate depending on the workload.
*/
-u32 ChainedOriginDepot::ChainedOriginDepotNode::hash(const args_type &args) {
+ChainedOriginDepot::ChainedOriginDepotNode::hash_type
+ChainedOriginDepot::ChainedOriginDepotNode::hash(const args_type &args) {
const u32 m = 0x5bd1e995;
const u32 seed = 0x9747b28c;
const u32 r = 24;
@@ -67,7 +68,7 @@ bool ChainedOriginDepot::ChainedOriginDepotNode::is_valid(
}
void ChainedOriginDepot::ChainedOriginDepotNode::store(const args_type &args,
- u32 other_hash) {
+ hash_type other_hash) {
here_id = args.here_id;
prev_id = args.prev_id;
}
@@ -85,7 +86,9 @@ ChainedOriginDepot::ChainedOriginDepotNode::get_handle() {
ChainedOriginDepot::ChainedOriginDepot() {}
-StackDepotStats *ChainedOriginDepot::GetStats() { return depot.GetStats(); }
+StackDepotStats ChainedOriginDepot::GetStats() const {
+ return depot.GetStats();
+}
bool ChainedOriginDepot::Put(u32 here_id, u32 prev_id, u32 *new_id) {
ChainedOriginDepotDesc desc = {here_id, prev_id};
diff --git a/libsanitizer/sanitizer_common/sanitizer_chained_origin_depot.h b/libsanitizer/sanitizer_common/sanitizer_chained_origin_depot.h
index 453cdf6..73a10e1 100644
--- a/libsanitizer/sanitizer_common/sanitizer_chained_origin_depot.h
+++ b/libsanitizer/sanitizer_common/sanitizer_chained_origin_depot.h
@@ -22,7 +22,7 @@ class ChainedOriginDepot {
ChainedOriginDepot();
// Gets the statistic of the origin chain storage.
- StackDepotStats *GetStats();
+ StackDepotStats GetStats() const;
// Stores a chain with StackDepot ID here_id and previous chain ID prev_id.
// If successful, returns true and the new chain id new_id.
@@ -43,6 +43,7 @@ class ChainedOriginDepot {
};
struct ChainedOriginDepotNode {
+ using hash_type = u32;
ChainedOriginDepotNode *link;
u32 id;
u32 here_id;
@@ -50,15 +51,15 @@ class ChainedOriginDepot {
typedef ChainedOriginDepotDesc args_type;
- bool eq(u32 hash, const args_type &args) const;
+ bool eq(hash_type hash, const args_type &args) const;
static uptr storage_size(const args_type &args);
- static u32 hash(const args_type &args);
+ static hash_type hash(const args_type &args);
static bool is_valid(const args_type &args);
- void store(const args_type &args, u32 other_hash);
+ void store(const args_type &args, hash_type other_hash);
args_type load() const;
diff --git a/libsanitizer/sanitizer_common/sanitizer_common.h b/libsanitizer/sanitizer_common/sanitizer_common.h
index cbdbb0c..17c29c7 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common.h
+++ b/libsanitizer/sanitizer_common/sanitizer_common.h
@@ -222,8 +222,8 @@ void CatastrophicErrorWrite(const char *buffer, uptr length);
void RawWrite(const char *buffer);
bool ColorizeReports();
void RemoveANSIEscapeSequencesFromString(char *buffer);
-void Printf(const char *format, ...);
-void Report(const char *format, ...);
+void Printf(const char *format, ...) FORMAT(1, 2);
+void Report(const char *format, ...) FORMAT(1, 2);
void SetPrintfAndReportCallback(void (*callback)(const char *));
#define VReport(level, ...) \
do { \
@@ -618,7 +618,7 @@ class InternalScopedString {
buffer_.resize(1);
buffer_[0] = '\0';
}
- void append(const char *format, ...);
+ void append(const char *format, ...) FORMAT(2, 3);
const char *data() const { return buffer_.data(); }
char *data() { return buffer_.data(); }
@@ -697,7 +697,8 @@ enum ModuleArch {
kModuleArchARMV7S,
kModuleArchARMV7K,
kModuleArchARM64,
- kModuleArchRISCV64
+ kModuleArchRISCV64,
+ kModuleArchHexagon
};
// Sorts and removes duplicates from the container.
@@ -764,6 +765,8 @@ inline const char *ModuleArchToString(ModuleArch arch) {
return "arm64";
case kModuleArchRISCV64:
return "riscv64";
+ case kModuleArchHexagon:
+ return "hexagon";
}
CHECK(0 && "Invalid module arch");
return "";
@@ -1063,17 +1066,10 @@ class ArrayRef {
T *end_ = nullptr;
};
-#define PRINTF_128(v) \
- (*((u8 *)&v + 0)), (*((u8 *)&v + 1)), (*((u8 *)&v + 2)), (*((u8 *)&v + 3)), \
- (*((u8 *)&v + 4)), (*((u8 *)&v + 5)), (*((u8 *)&v + 6)), \
- (*((u8 *)&v + 7)), (*((u8 *)&v + 8)), (*((u8 *)&v + 9)), \
- (*((u8 *)&v + 10)), (*((u8 *)&v + 11)), (*((u8 *)&v + 12)), \
- (*((u8 *)&v + 13)), (*((u8 *)&v + 14)), (*((u8 *)&v + 15))
-
} // namespace __sanitizer
inline void *operator new(__sanitizer::operator_new_size_type size,
- __sanitizer::LowLevelAllocator &alloc) { // NOLINT
+ __sanitizer::LowLevelAllocator &alloc) {
return alloc.Allocate(size);
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
index 5ac6cf4..9511a3b 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
@@ -204,7 +204,7 @@ extern const short *_tolower_tab_;
#define COMMON_INTERCEPTOR_READ_STRING(ctx, s, n) \
COMMON_INTERCEPTOR_READ_RANGE((ctx), (s), \
- common_flags()->strict_string_checks ? (REAL(strlen)(s)) + 1 : (n) )
+ common_flags()->strict_string_checks ? (internal_strlen(s)) + 1 : (n) )
#ifndef COMMON_INTERCEPTOR_ON_DLOPEN
#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
@@ -435,7 +435,7 @@ INTERCEPTOR(char*, textdomain, const char *domainname) {
if (domainname) COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0);
char *domain = REAL(textdomain)(domainname);
if (domain) {
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, REAL(strlen)(domain) + 1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, internal_strlen(domain) + 1);
}
return domain;
}
@@ -575,8 +575,8 @@ INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T size) {
#if SANITIZER_INTERCEPT_STRSTR || SANITIZER_INTERCEPT_STRCASESTR
static inline void StrstrCheck(void *ctx, char *r, const char *s1,
const char *s2) {
- uptr len1 = REAL(strlen)(s1);
- uptr len2 = REAL(strlen)(s2);
+ uptr len1 = internal_strlen(s1);
+ uptr len2 = internal_strlen(s2);
COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r ? r - s1 + len2 : len1 + 1);
COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2 + 1);
}
@@ -640,10 +640,10 @@ INTERCEPTOR(char*, strtok, char *str, const char *delimiters) {
// for subsequent calls). We do not need to check strtok's result.
// As the delimiters can change, we check them every call.
if (str != nullptr) {
- COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
}
COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters,
- REAL(strlen)(delimiters) + 1);
+ internal_strlen(delimiters) + 1);
return REAL(strtok)(str, delimiters);
} else {
// However, when strict_string_checks is disabled we cannot check the
@@ -657,11 +657,11 @@ INTERCEPTOR(char*, strtok, char *str, const char *delimiters) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters, 1);
char *result = REAL(strtok)(str, delimiters);
if (result != nullptr) {
- COMMON_INTERCEPTOR_READ_RANGE(ctx, result, REAL(strlen)(result) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, result, internal_strlen(result) + 1);
} else if (str != nullptr) {
// No delimiter were found, it's safe to assume that the entire str was
// scanned.
- COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
}
return result;
}
@@ -706,7 +706,7 @@ INTERCEPTOR(char*, strchr, const char *s, int c) {
if (common_flags()->intercept_strchr) {
// Keep strlen as macro argument, as macro may ignore it.
COMMON_INTERCEPTOR_READ_STRING(ctx, s,
- (result ? result - s : REAL(strlen)(s)) + 1);
+ (result ? result - s : internal_strlen(s)) + 1);
}
return result;
}
@@ -737,7 +737,7 @@ INTERCEPTOR(char*, strrchr, const char *s, int c) {
return internal_strrchr(s, c);
COMMON_INTERCEPTOR_ENTER(ctx, strrchr, s, c);
if (common_flags()->intercept_strchr)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
return REAL(strrchr)(s, c);
}
#define INIT_STRRCHR COMMON_INTERCEPT_FUNCTION(strrchr)
@@ -751,7 +751,7 @@ INTERCEPTOR(SIZE_T, strspn, const char *s1, const char *s2) {
COMMON_INTERCEPTOR_ENTER(ctx, strspn, s1, s2);
SIZE_T r = REAL(strspn)(s1, s2);
if (common_flags()->intercept_strspn) {
- COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
}
return r;
@@ -762,7 +762,7 @@ INTERCEPTOR(SIZE_T, strcspn, const char *s1, const char *s2) {
COMMON_INTERCEPTOR_ENTER(ctx, strcspn, s1, s2);
SIZE_T r = REAL(strcspn)(s1, s2);
if (common_flags()->intercept_strspn) {
- COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
}
return r;
@@ -781,9 +781,9 @@ INTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) {
COMMON_INTERCEPTOR_ENTER(ctx, strpbrk, s1, s2);
char *r = REAL(strpbrk)(s1, s2);
if (common_flags()->intercept_strpbrk) {
- COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
COMMON_INTERCEPTOR_READ_STRING(ctx, s1,
- r ? r - s1 + 1 : REAL(strlen)(s1) + 1);
+ r ? r - s1 + 1 : internal_strlen(s1) + 1);
}
return r;
}
@@ -1251,7 +1251,7 @@ INTERCEPTOR(char *, fgets, char *s, SIZE_T size, void *file) {
// https://github.com/google/sanitizers/issues/321.
char *res = REAL(fgets)(s, size, file);
if (res)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
return res;
}
#define INIT_FGETS COMMON_INTERCEPT_FUNCTION(fgets)
@@ -1265,7 +1265,7 @@ INTERCEPTOR_WITH_SUFFIX(int, fputs, char *s, void *file) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, fputs, s, file);
if (!SANITIZER_MAC || s) { // `fputs(NULL, file)` is supported on Darwin.
- COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
}
return REAL(fputs)(s, file);
}
@@ -1280,7 +1280,7 @@ INTERCEPTOR(int, puts, char *s) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, puts, s);
if (!SANITIZER_MAC || s) { // `puts(NULL)` is supported on Darwin.
- COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
}
return REAL(puts)(s);
}
@@ -1334,7 +1334,7 @@ static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
// Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because tm->tm_zone
// can point to shared memory and tsan would report a data race.
COMMON_INTERCEPTOR_INITIALIZE_RANGE(tm->tm_zone,
- REAL(strlen(tm->tm_zone)) + 1);
+ internal_strlen(tm->tm_zone) + 1);
}
#endif
}
@@ -1387,7 +1387,7 @@ INTERCEPTOR(char *, ctime, unsigned long *timep) {
char *res = REAL(ctime)(timep);
if (res) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
}
return res;
}
@@ -1400,7 +1400,7 @@ INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
char *res = REAL(ctime_r)(timep, result);
if (res) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
}
return res;
}
@@ -1413,7 +1413,7 @@ INTERCEPTOR(char *, asctime, __sanitizer_tm *tm) {
char *res = REAL(asctime)(tm);
if (res) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
}
return res;
}
@@ -1426,7 +1426,7 @@ INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) {
char *res = REAL(asctime_r)(tm, result);
if (res) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
}
return res;
}
@@ -1463,7 +1463,7 @@ INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strptime, s, format, tm);
if (format)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, format, REAL(strlen)(format) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, format, internal_strlen(format) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -1843,9 +1843,9 @@ INTERCEPTOR(int, ioctl, int d, unsigned long request, ...) {
const ioctl_desc *desc = ioctl_lookup(request);
ioctl_desc decoded_desc;
if (!desc) {
- VPrintf(2, "Decoding unknown ioctl 0x%x\n", request);
+ VPrintf(2, "Decoding unknown ioctl 0x%lx\n", request);
if (!ioctl_decode(request, &decoded_desc))
- Printf("WARNING: failed decoding unknown ioctl 0x%x\n", request);
+ Printf("WARNING: failed decoding unknown ioctl 0x%lx\n", request);
else
desc = &decoded_desc;
}
@@ -1869,26 +1869,26 @@ UNUSED static void unpoison_passwd(void *ctx, __sanitizer_passwd *pwd) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, sizeof(*pwd));
if (pwd->pw_name)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_name,
- REAL(strlen)(pwd->pw_name) + 1);
+ internal_strlen(pwd->pw_name) + 1);
if (pwd->pw_passwd)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_passwd,
- REAL(strlen)(pwd->pw_passwd) + 1);
+ internal_strlen(pwd->pw_passwd) + 1);
#if !SANITIZER_ANDROID
if (pwd->pw_gecos)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_gecos,
- REAL(strlen)(pwd->pw_gecos) + 1);
+ internal_strlen(pwd->pw_gecos) + 1);
#endif
#if SANITIZER_MAC || SANITIZER_FREEBSD || SANITIZER_NETBSD
if (pwd->pw_class)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_class,
- REAL(strlen)(pwd->pw_class) + 1);
+ internal_strlen(pwd->pw_class) + 1);
#endif
if (pwd->pw_dir)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_dir,
- REAL(strlen)(pwd->pw_dir) + 1);
+ internal_strlen(pwd->pw_dir) + 1);
if (pwd->pw_shell)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_shell,
- REAL(strlen)(pwd->pw_shell) + 1);
+ internal_strlen(pwd->pw_shell) + 1);
}
}
@@ -1897,13 +1897,13 @@ UNUSED static void unpoison_group(void *ctx, __sanitizer_group *grp) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, sizeof(*grp));
if (grp->gr_name)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_name,
- REAL(strlen)(grp->gr_name) + 1);
+ internal_strlen(grp->gr_name) + 1);
if (grp->gr_passwd)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_passwd,
- REAL(strlen)(grp->gr_passwd) + 1);
+ internal_strlen(grp->gr_passwd) + 1);
char **p = grp->gr_mem;
for (; *p; ++p) {
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
}
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_mem,
(p - grp->gr_mem + 1) * sizeof(*p));
@@ -1916,7 +1916,7 @@ INTERCEPTOR(__sanitizer_passwd *, getpwnam, const char *name) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
if (name)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
__sanitizer_passwd *res = REAL(getpwnam)(name);
unpoison_passwd(ctx, res);
return res;
@@ -1931,7 +1931,7 @@ INTERCEPTOR(__sanitizer_passwd *, getpwuid, u32 uid) {
INTERCEPTOR(__sanitizer_group *, getgrnam, const char *name) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
__sanitizer_group *res = REAL(getgrnam)(name);
unpoison_group(ctx, res);
return res;
@@ -1957,7 +1957,7 @@ INTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd,
char *buf, SIZE_T buflen, __sanitizer_passwd **result) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -1984,7 +1984,7 @@ INTERCEPTOR(int, getgrnam_r, const char *name, __sanitizer_group *grp,
char *buf, SIZE_T buflen, __sanitizer_group **result) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -2229,8 +2229,20 @@ INTERCEPTOR(int, clock_getcpuclockid, pid_t pid,
return res;
}
-#define INIT_CLOCK_GETCPUCLOCKID \
- COMMON_INTERCEPT_FUNCTION(clock_getcpuclockid);
+INTERCEPTOR(int, pthread_getcpuclockid, uptr thread,
+ __sanitizer_clockid_t *clockid) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pthread_getcpuclockid, thread, clockid);
+ int res = REAL(pthread_getcpuclockid)(thread, clockid);
+ if (!res && clockid) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, clockid, sizeof *clockid);
+ }
+ return res;
+}
+
+#define INIT_CLOCK_GETCPUCLOCKID \
+ COMMON_INTERCEPT_FUNCTION(clock_getcpuclockid); \
+ COMMON_INTERCEPT_FUNCTION(pthread_getcpuclockid);
#else
#define INIT_CLOCK_GETCPUCLOCKID
#endif
@@ -2289,7 +2301,7 @@ static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
char *p = pglob->gl_pathv[i];
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, REAL(strlen)(p) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, internal_strlen(p) + 1);
}
}
@@ -2319,19 +2331,19 @@ static void *wrapped_gl_readdir(void *dir) {
static void *wrapped_gl_opendir(const char *s) {
COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
return pglob_copy->gl_opendir(s);
}
static int wrapped_gl_lstat(const char *s, void *st) {
COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
return pglob_copy->gl_lstat(s, st);
}
static int wrapped_gl_stat(const char *s, void *st) {
COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
return pglob_copy->gl_stat(s, st);
}
@@ -2519,7 +2531,7 @@ INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
char *res = REAL(inet_ntop)(af, src, dst, size);
- if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
return res;
}
INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
@@ -2548,7 +2560,7 @@ INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
- if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1);
+ if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, internal_strlen(cp) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -2590,9 +2602,9 @@ INTERCEPTOR(int, getaddrinfo, char *node, char *service,
struct __sanitizer_addrinfo **out) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
- if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
+ if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, internal_strlen(node) + 1);
if (service)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, service, internal_strlen(service) + 1);
if (hints)
COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
// FIXME: under ASan the call below may write to freed memory and corrupt
@@ -2608,7 +2620,7 @@ INTERCEPTOR(int, getaddrinfo, char *node, char *service,
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
if (p->ai_canonname)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
- REAL(strlen)(p->ai_canonname) + 1);
+ internal_strlen(p->ai_canonname) + 1);
p = p->ai_next;
}
}
@@ -2634,9 +2646,9 @@ INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags);
if (res == 0) {
if (host && hostlen)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, REAL(strlen)(host) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, internal_strlen(host) + 1);
if (serv && servlen)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, REAL(strlen)(serv) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, internal_strlen(serv) + 1);
}
return res;
}
@@ -2669,10 +2681,10 @@ INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
if (h->h_name)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, internal_strlen(h->h_name) + 1);
char **p = h->h_aliases;
while (*p) {
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
++p;
}
COMMON_INTERCEPTOR_WRITE_RANGE(
@@ -3196,7 +3208,7 @@ INTERCEPTOR(int, sysinfo, void *info) {
INTERCEPTOR(__sanitizer_dirent *, opendir, const char *path) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, opendir, path);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
__sanitizer_dirent *res = REAL(opendir)(path);
if (res)
COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path);
@@ -3351,10 +3363,10 @@ INTERCEPTOR(char *, setlocale, int category, char *locale) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
if (locale)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, internal_strlen(locale) + 1);
char *res = REAL(setlocale)(category, locale);
if (res) {
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
unpoison_ctype_arrays(ctx);
}
return res;
@@ -3373,7 +3385,7 @@ INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
char *res = REAL(getcwd)(buf, size);
- if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
return res;
}
#define INIT_GETCWD COMMON_INTERCEPT_FUNCTION(getcwd);
@@ -3389,7 +3401,7 @@ INTERCEPTOR(char *, get_current_dir_name, int fake) {
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
char *res = REAL(get_current_dir_name)(fake);
- if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
return res;
}
@@ -3663,12 +3675,23 @@ INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+
+ // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
+ // version of a versioned symbol. For realpath(), this gives us something
+ // (called __old_realpath) that does not handle NULL in the second argument.
+ // Handle it as part of the interceptor.
+ char *allocated_path = nullptr;
+ if (!resolved_path)
+ allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);
+
char *res = REAL(realpath)(path, resolved_path);
- if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ if (allocated_path && !res)
+ WRAP(free)(allocated_path);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
return res;
}
-#define INIT_REALPATH COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(realpath, "GLIBC_2.3");
+# define INIT_REALPATH COMMON_INTERCEPT_FUNCTION(realpath);
#else
#define INIT_REALPATH
#endif
@@ -3677,9 +3700,9 @@ INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
char *res = REAL(canonicalize_file_name)(path);
- if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
return res;
}
#define INIT_CANONICALIZE_FILE_NAME \
@@ -3740,7 +3763,7 @@ INTERCEPTOR(char *, strerror, int errnum) {
COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
COMMON_INTERCEPTOR_STRERROR();
char *res = REAL(strerror)(errnum);
- if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
+ if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
return res;
}
#define INIT_STRERROR COMMON_INTERCEPT_FUNCTION(strerror);
@@ -3782,9 +3805,9 @@ INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) {
// https://github.com/google/sanitizers/issues/321.
char *res = REAL(strerror_r)(errnum, buf, buflen);
if (res == buf)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
else
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
return res;
}
#endif //(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE ||
@@ -3804,7 +3827,7 @@ INTERCEPTOR(int, __xpg_strerror_r, int errnum, char *buf, SIZE_T buflen) {
int res = REAL(__xpg_strerror_r)(errnum, buf, buflen);
// This version always returns a null-terminated string.
if (buf && buflen)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
return res;
}
#define INIT_XPG_STRERROR_R COMMON_INTERCEPT_FUNCTION(__xpg_strerror_r);
@@ -3840,7 +3863,7 @@ INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
scandir_filter_f filter, scandir_compar_f compar) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, scandir, dirp, namelist, filter, compar);
- if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
+ if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, internal_strlen(dirp) + 1);
scandir_filter = filter;
scandir_compar = compar;
// FIXME: under ASan the call below may write to freed memory and corrupt
@@ -3893,7 +3916,7 @@ INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
scandir64_filter_f filter, scandir64_compar_f compar) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, scandir64, dirp, namelist, filter, compar);
- if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
+ if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, internal_strlen(dirp) + 1);
scandir64_filter = filter;
scandir64_compar = compar;
// FIXME: under ASan the call below may write to freed memory and corrupt
@@ -3989,19 +4012,20 @@ INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, wordexp, s, p, flags);
- if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
+ if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
int res = REAL(wordexp)(s, p, flags);
if (!res && p) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
- if (p->we_wordc)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
- sizeof(*p->we_wordv) * p->we_wordc);
- for (uptr i = 0; i < p->we_wordc; ++i) {
+ uptr we_wordc =
+ ((flags & wordexp_wrde_dooffs) ? p->we_offs : 0) + p->we_wordc;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
+ sizeof(*p->we_wordv) * (we_wordc + 1));
+ for (uptr i = 0; i < we_wordc; ++i) {
char *w = p->we_wordv[i];
- if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, REAL(strlen)(w) + 1);
+ if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, internal_strlen(w) + 1);
}
}
return res;
@@ -4207,7 +4231,7 @@ INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) {
if (res && size) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, size * sizeof(*res));
for (int i = 0; i < size; ++i)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], REAL(strlen(res[i])) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], internal_strlen(res[i]) + 1);
}
return res;
}
@@ -4325,16 +4349,16 @@ static void write_mntent(void *ctx, __sanitizer_mntent *mnt) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt, sizeof(*mnt));
if (mnt->mnt_fsname)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_fsname,
- REAL(strlen)(mnt->mnt_fsname) + 1);
+ internal_strlen(mnt->mnt_fsname) + 1);
if (mnt->mnt_dir)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_dir,
- REAL(strlen)(mnt->mnt_dir) + 1);
+ internal_strlen(mnt->mnt_dir) + 1);
if (mnt->mnt_type)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_type,
- REAL(strlen)(mnt->mnt_type) + 1);
+ internal_strlen(mnt->mnt_type) + 1);
if (mnt->mnt_opts)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_opts,
- REAL(strlen)(mnt->mnt_opts) + 1);
+ internal_strlen(mnt->mnt_opts) + 1);
}
#endif
@@ -4369,7 +4393,7 @@ INTERCEPTOR(__sanitizer_mntent *, getmntent_r, void *fp,
INTERCEPTOR(int, statfs, char *path, void *buf) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, statfs, path, buf);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -4398,7 +4422,7 @@ INTERCEPTOR(int, fstatfs, int fd, void *buf) {
INTERCEPTOR(int, statfs64, char *path, void *buf) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, statfs64, path, buf);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -4427,7 +4451,7 @@ INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
INTERCEPTOR(int, statvfs, char *path, void *buf) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -4461,7 +4485,7 @@ INTERCEPTOR(int, fstatvfs, int fd, void *buf) {
INTERCEPTOR(int, statvfs64, char *path, void *buf) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, statvfs64, path, buf);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -4490,7 +4514,7 @@ INTERCEPTOR(int, fstatvfs64, int fd, void *buf) {
INTERCEPTOR(int, initgroups, char *user, u32 group) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, initgroups, user, group);
- if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, REAL(strlen)(user) + 1);
+ if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, internal_strlen(user) + 1);
int res = REAL(initgroups)(user, group);
return res;
}
@@ -4505,13 +4529,13 @@ INTERCEPTOR(char *, ether_ntoa, __sanitizer_ether_addr *addr) {
COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa, addr);
if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
char *res = REAL(ether_ntoa)(addr);
- if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
+ if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
return res;
}
INTERCEPTOR(__sanitizer_ether_addr *, ether_aton, char *buf) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, ether_aton, buf);
- if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
+ if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, internal_strlen(buf) + 1);
__sanitizer_ether_addr *res = REAL(ether_aton)(buf);
if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, sizeof(*res));
return res;
@@ -4533,14 +4557,14 @@ INTERCEPTOR(int, ether_ntohost, char *hostname, __sanitizer_ether_addr *addr) {
// https://github.com/google/sanitizers/issues/321.
int res = REAL(ether_ntohost)(hostname, addr);
if (!res && hostname)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
return res;
}
INTERCEPTOR(int, ether_hostton, char *hostname, __sanitizer_ether_addr *addr) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, ether_hostton, hostname, addr);
if (hostname)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -4552,7 +4576,7 @@ INTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr,
char *hostname) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, ether_line, line, addr, hostname);
- if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, REAL(strlen)(line) + 1);
+ if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, internal_strlen(line) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -4560,7 +4584,7 @@ INTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr,
if (!res) {
if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
if (hostname)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
}
return res;
}
@@ -4581,14 +4605,14 @@ INTERCEPTOR(char *, ether_ntoa_r, __sanitizer_ether_addr *addr, char *buf) {
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
char *res = REAL(ether_ntoa_r)(addr, buf);
- if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
return res;
}
INTERCEPTOR(__sanitizer_ether_addr *, ether_aton_r, char *buf,
__sanitizer_ether_addr *addr) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, ether_aton_r, buf, addr);
- if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
+ if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, internal_strlen(buf) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -4854,9 +4878,9 @@ INTERCEPTOR(char *, tmpnam, char *s) {
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
else
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
}
return res;
}
@@ -4873,7 +4897,7 @@ INTERCEPTOR(char *, tmpnam_r, char *s) {
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
char *res = REAL(tmpnam_r)(s);
- if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
+ if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
return res;
}
#define INIT_TMPNAM_R COMMON_INTERCEPT_FUNCTION(tmpnam_r);
@@ -4887,7 +4911,7 @@ INTERCEPTOR(char *, ptsname, int fd) {
COMMON_INTERCEPTOR_ENTER(ctx, ptsname, fd);
char *res = REAL(ptsname)(fd);
if (res != nullptr)
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
return res;
}
#define INIT_PTSNAME COMMON_INTERCEPT_FUNCTION(ptsname);
@@ -4901,7 +4925,7 @@ INTERCEPTOR(int, ptsname_r, int fd, char *name, SIZE_T namesize) {
COMMON_INTERCEPTOR_ENTER(ctx, ptsname_r, fd, name, namesize);
int res = REAL(ptsname_r)(fd, name, namesize);
if (res == 0)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
return res;
}
#define INIT_PTSNAME_R COMMON_INTERCEPT_FUNCTION(ptsname_r);
@@ -4915,7 +4939,7 @@ INTERCEPTOR(char *, ttyname, int fd) {
COMMON_INTERCEPTOR_ENTER(ctx, ttyname, fd);
char *res = REAL(ttyname)(fd);
if (res != nullptr)
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
return res;
}
#define INIT_TTYNAME COMMON_INTERCEPT_FUNCTION(ttyname);
@@ -4929,7 +4953,7 @@ INTERCEPTOR(int, ttyname_r, int fd, char *name, SIZE_T namesize) {
COMMON_INTERCEPTOR_ENTER(ctx, ttyname_r, fd, name, namesize);
int res = REAL(ttyname_r)(fd, name, namesize);
if (res == 0)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
return res;
}
#define INIT_TTYNAME_R COMMON_INTERCEPT_FUNCTION(ttyname_r);
@@ -4941,10 +4965,10 @@ INTERCEPTOR(int, ttyname_r, int fd, char *name, SIZE_T namesize) {
INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, tempnam, dir, pfx);
- if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, REAL(strlen)(dir) + 1);
- if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, REAL(strlen)(pfx) + 1);
+ if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, internal_strlen(dir) + 1);
+ if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, internal_strlen(pfx) + 1);
char *res = REAL(tempnam)(dir, pfx);
- if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
+ if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
return res;
}
#define INIT_TEMPNAM COMMON_INTERCEPT_FUNCTION(tempnam);
@@ -5404,7 +5428,7 @@ asm(
INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, listxattr, path, list, size);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -5417,7 +5441,7 @@ INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) {
INTERCEPTOR(SSIZE_T, llistxattr, const char *path, char *list, SIZE_T size) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, llistxattr, path, list, size);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -5448,8 +5472,8 @@ INTERCEPTOR(SSIZE_T, getxattr, const char *path, const char *name, char *value,
SIZE_T size) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getxattr, path, name, value, size);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
- if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -5461,8 +5485,8 @@ INTERCEPTOR(SSIZE_T, lgetxattr, const char *path, const char *name, char *value,
SIZE_T size) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, lgetxattr, path, name, value, size);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
- if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -5474,7 +5498,7 @@ INTERCEPTOR(SSIZE_T, fgetxattr, int fd, const char *name, char *value,
SIZE_T size) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, fgetxattr, fd, name, value, size);
- if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -5544,7 +5568,7 @@ INTERCEPTOR(int, getifaddrs, __sanitizer_ifaddrs **ifap) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(__sanitizer_ifaddrs));
if (p->ifa_name)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_name,
- REAL(strlen)(p->ifa_name) + 1);
+ internal_strlen(p->ifa_name) + 1);
if (p->ifa_addr)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_addr, struct_sockaddr_sz);
if (p->ifa_netmask)
@@ -5574,14 +5598,14 @@ INTERCEPTOR(char *, if_indextoname, unsigned int ifindex, char* ifname) {
// https://github.com/google/sanitizers/issues/321.
char *res = REAL(if_indextoname)(ifindex, ifname);
if (res && ifname)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, internal_strlen(ifname) + 1);
return res;
}
INTERCEPTOR(unsigned int, if_nametoindex, const char* ifname) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, if_nametoindex, ifname);
if (ifname)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, internal_strlen(ifname) + 1);
return REAL(if_nametoindex)(ifname);
}
#define INIT_IF_INDEXTONAME \
@@ -5839,7 +5863,7 @@ INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p,
COMMON_INTERCEPTOR_ENTER(ctx, xdr_string, xdrs, p, maxsize);
if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
- COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, internal_strlen(*p) + 1);
}
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
@@ -5848,7 +5872,7 @@ INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p,
if (p && xdrs->x_op == __sanitizer_XDR_DECODE) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
if (res && *p)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
}
return res;
}
@@ -6059,8 +6083,8 @@ INTERCEPTOR(int, __woverflow, __sanitizer_FILE *fp, int ch) {
INTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, fopen, path, mode);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
__sanitizer_FILE *res = REAL(fopen)(path, mode);
COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
if (res) unpoison_file(res);
@@ -6069,7 +6093,7 @@ INTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) {
INTERCEPTOR(__sanitizer_FILE *, fdopen, int fd, const char *mode) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, fdopen, fd, mode);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
__sanitizer_FILE *res = REAL(fdopen)(fd, mode);
if (res) unpoison_file(res);
return res;
@@ -6078,8 +6102,8 @@ INTERCEPTOR(__sanitizer_FILE *, freopen, const char *path, const char *mode,
__sanitizer_FILE *fp) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, freopen, path, mode, fp);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
__sanitizer_FILE *res = REAL(freopen)(path, mode, fp);
COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
@@ -6103,7 +6127,7 @@ INTERCEPTOR(int, flopen, const char *path, int flags, ...) {
va_end(ap);
COMMON_INTERCEPTOR_ENTER(ctx, flopen, path, flags, mode);
if (path) {
- COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
}
return REAL(flopen)(path, flags, mode);
}
@@ -6116,7 +6140,7 @@ INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) {
va_end(ap);
COMMON_INTERCEPTOR_ENTER(ctx, flopen, path, flags, mode);
if (path) {
- COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
}
return REAL(flopenat)(dirfd, path, flags, mode);
}
@@ -6132,8 +6156,8 @@ INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) {
INTERCEPTOR(__sanitizer_FILE *, fopen64, const char *path, const char *mode) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, fopen64, path, mode);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
__sanitizer_FILE *res = REAL(fopen64)(path, mode);
COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
if (res) unpoison_file(res);
@@ -6143,8 +6167,8 @@ INTERCEPTOR(__sanitizer_FILE *, freopen64, const char *path, const char *mode,
__sanitizer_FILE *fp) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, freopen64, path, mode, fp);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
__sanitizer_FILE *res = REAL(freopen64)(path, mode, fp);
COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
@@ -6322,9 +6346,9 @@ INTERCEPTOR(char *, getpass, const char *prompt) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getpass, prompt);
if (prompt)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, prompt, REAL(strlen)(prompt)+1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, prompt, internal_strlen(prompt)+1);
char *res = REAL(getpass)(prompt);
- if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res)+1);
+ if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res)+1);
return res;
}
@@ -6528,17 +6552,42 @@ INTERCEPTOR(int, sem_getvalue, __sanitizer_sem_t *s, int *sval) {
}
return res;
}
-#define INIT_SEM \
- COMMON_INTERCEPT_FUNCTION(sem_init); \
- COMMON_INTERCEPT_FUNCTION(sem_destroy); \
- COMMON_INTERCEPT_FUNCTION(sem_wait); \
- COMMON_INTERCEPT_FUNCTION(sem_trywait); \
- COMMON_INTERCEPT_FUNCTION(sem_timedwait); \
- COMMON_INTERCEPT_FUNCTION(sem_post); \
- COMMON_INTERCEPT_FUNCTION(sem_getvalue);
+
+INTERCEPTOR(__sanitizer_sem_t *, sem_open, const char *name, int oflag, ...) {
+ void *ctx;
+ va_list ap;
+ va_start(ap, oflag);
+ u32 mode = va_arg(ap, u32);
+ u32 value = va_arg(ap, u32);
+ COMMON_INTERCEPTOR_ENTER(ctx, sem_open, name, oflag, mode, value);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ __sanitizer_sem_t *s = REAL(sem_open)(name, oflag, mode, value);
+ if (s)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, sizeof(*s));
+ va_end(ap);
+ return s;
+}
+
+INTERCEPTOR(int, sem_unlink, const char *name) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sem_unlink, name);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ return REAL(sem_unlink)(name);
+}
+
+# define INIT_SEM \
+ COMMON_INTERCEPT_FUNCTION(sem_init); \
+ COMMON_INTERCEPT_FUNCTION(sem_destroy); \
+ COMMON_INTERCEPT_FUNCTION(sem_wait); \
+ COMMON_INTERCEPT_FUNCTION(sem_trywait); \
+ COMMON_INTERCEPT_FUNCTION(sem_timedwait); \
+ COMMON_INTERCEPT_FUNCTION(sem_post); \
+ COMMON_INTERCEPT_FUNCTION(sem_getvalue); \
+ COMMON_INTERCEPT_FUNCTION(sem_open); \
+ COMMON_INTERCEPT_FUNCTION(sem_unlink);
#else
-#define INIT_SEM
-#endif // SANITIZER_INTERCEPT_SEM
+# define INIT_SEM
+#endif // SANITIZER_INTERCEPT_SEM
#if SANITIZER_INTERCEPT_PTHREAD_SETCANCEL
INTERCEPTOR(int, pthread_setcancelstate, int state, int *oldstate) {
@@ -6621,7 +6670,7 @@ INTERCEPTOR(char *, ctermid, char *s) {
COMMON_INTERCEPTOR_ENTER(ctx, ctermid, s);
char *res = REAL(ctermid)(s);
if (res) {
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
}
return res;
}
@@ -6636,7 +6685,7 @@ INTERCEPTOR(char *, ctermid_r, char *s) {
COMMON_INTERCEPTOR_ENTER(ctx, ctermid_r, s);
char *res = REAL(ctermid_r)(s);
if (res) {
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
}
return res;
}
@@ -6973,8 +7022,8 @@ INTERCEPTOR(SIZE_T, wcsnlen, const wchar_t *s, SIZE_T n) {
INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, wcscat, dst, src);
- SIZE_T src_size = REAL(wcslen)(src);
- SIZE_T dst_size = REAL(wcslen)(dst);
+ SIZE_T src_size = internal_wcslen(src);
+ SIZE_T dst_size = internal_wcslen(dst);
COMMON_INTERCEPTOR_READ_RANGE(ctx, src, (src_size + 1) * sizeof(wchar_t));
COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
@@ -6985,8 +7034,8 @@ INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, wcsncat, dst, src, n);
- SIZE_T src_size = REAL(wcsnlen)(src, n);
- SIZE_T dst_size = REAL(wcslen)(dst);
+ SIZE_T src_size = internal_wcsnlen(src, n);
+ SIZE_T dst_size = internal_wcslen(dst);
COMMON_INTERCEPTOR_READ_RANGE(ctx, src,
Min(src_size + 1, n) * sizeof(wchar_t));
COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
@@ -7005,7 +7054,7 @@ INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
INTERCEPTOR(wchar_t *, wcsdup, wchar_t *s) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, wcsdup, s);
- SIZE_T len = REAL(wcslen)(s);
+ SIZE_T len = internal_wcslen(s);
COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (len + 1));
wchar_t *result = REAL(wcsdup)(s);
if (result)
@@ -7019,9 +7068,9 @@ INTERCEPTOR(wchar_t *, wcsdup, wchar_t *s) {
#endif
#if SANITIZER_INTERCEPT_STRXFRM
-static SIZE_T RealStrLen(const char *str) { return REAL(strlen)(str); }
+static SIZE_T RealStrLen(const char *str) { return internal_strlen(str); }
-static SIZE_T RealStrLen(const wchar_t *str) { return REAL(wcslen)(str); }
+static SIZE_T RealStrLen(const wchar_t *str) { return internal_wcslen(str); }
#define STRXFRM_INTERCEPTOR_IMPL(strxfrm, dest, src, len, ...) \
{ \
@@ -7095,7 +7144,7 @@ INTERCEPTOR(int, acct, const char *file) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, acct, file);
if (file)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, file, REAL(strlen)(file) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, file, internal_strlen(file) + 1);
return REAL(acct)(file);
}
#define INIT_ACCT COMMON_INTERCEPT_FUNCTION(acct)
@@ -7110,7 +7159,7 @@ INTERCEPTOR(const char *, user_from_uid, u32 uid, int nouser) {
COMMON_INTERCEPTOR_ENTER(ctx, user_from_uid, uid, nouser);
user = REAL(user_from_uid)(uid, nouser);
if (user)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, user, REAL(strlen)(user) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, user, internal_strlen(user) + 1);
return user;
}
#define INIT_USER_FROM_UID COMMON_INTERCEPT_FUNCTION(user_from_uid)
@@ -7124,7 +7173,7 @@ INTERCEPTOR(int, uid_from_user, const char *name, u32 *uid) {
int res;
COMMON_INTERCEPTOR_ENTER(ctx, uid_from_user, name, uid);
if (name)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
res = REAL(uid_from_user)(name, uid);
if (uid)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, uid, sizeof(*uid));
@@ -7142,7 +7191,7 @@ INTERCEPTOR(const char *, group_from_gid, u32 gid, int nogroup) {
COMMON_INTERCEPTOR_ENTER(ctx, group_from_gid, gid, nogroup);
group = REAL(group_from_gid)(gid, nogroup);
if (group)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, group, REAL(strlen)(group) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, group, internal_strlen(group) + 1);
return group;
}
#define INIT_GROUP_FROM_GID COMMON_INTERCEPT_FUNCTION(group_from_gid)
@@ -7156,7 +7205,7 @@ INTERCEPTOR(int, gid_from_group, const char *group, u32 *gid) {
int res;
COMMON_INTERCEPTOR_ENTER(ctx, gid_from_group, group, gid);
if (group)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, group, REAL(strlen)(group) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, group, internal_strlen(group) + 1);
res = REAL(gid_from_group)(group, gid);
if (gid)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, gid, sizeof(*gid));
@@ -7172,7 +7221,7 @@ INTERCEPTOR(int, access, const char *path, int mode) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, access, path, mode);
if (path)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
return REAL(access)(path, mode);
}
#define INIT_ACCESS COMMON_INTERCEPT_FUNCTION(access)
@@ -7185,7 +7234,7 @@ INTERCEPTOR(int, faccessat, int fd, const char *path, int mode, int flags) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, faccessat, fd, path, mode, flags);
if (path)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
return REAL(faccessat)(fd, path, mode, flags);
}
#define INIT_FACCESSAT COMMON_INTERCEPT_FUNCTION(faccessat)
@@ -7200,7 +7249,7 @@ INTERCEPTOR(int, getgrouplist, const char *name, u32 basegid, u32 *groups,
int res;
COMMON_INTERCEPTOR_ENTER(ctx, getgrouplist, name, basegid, groups, ngroups);
if (name)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
if (ngroups)
COMMON_INTERCEPTOR_READ_RANGE(ctx, ngroups, sizeof(*ngroups));
res = REAL(getgrouplist)(name, basegid, groups, ngroups);
@@ -7224,7 +7273,7 @@ INTERCEPTOR(int, getgroupmembership, const char *name, u32 basegid, u32 *groups,
COMMON_INTERCEPTOR_ENTER(ctx, getgroupmembership, name, basegid, groups,
maxgrp, ngroups);
if (name)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
res = REAL(getgroupmembership)(name, basegid, groups, maxgrp, ngroups);
if (!res && groups && ngroups) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, groups, sizeof(*groups) * (*ngroups));
@@ -7242,7 +7291,7 @@ INTERCEPTOR(int, getgroupmembership, const char *name, u32 basegid, u32 *groups,
INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) {
void* ctx;
COMMON_INTERCEPTOR_ENTER(ctx, readlink, path, buf, bufsiz);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
SSIZE_T res = REAL(readlink)(path, buf, bufsiz);
if (res > 0)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
@@ -7259,7 +7308,7 @@ INTERCEPTOR(SSIZE_T, readlinkat, int dirfd, const char *path, char *buf,
SIZE_T bufsiz) {
void* ctx;
COMMON_INTERCEPTOR_ENTER(ctx, readlinkat, dirfd, path, buf, bufsiz);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
SSIZE_T res = REAL(readlinkat)(dirfd, path, buf, bufsiz);
if (res > 0)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
@@ -7277,7 +7326,7 @@ INTERCEPTOR(int, name_to_handle_at, int dirfd, const char *pathname,
void* ctx;
COMMON_INTERCEPTOR_ENTER(ctx, name_to_handle_at, dirfd, pathname, handle,
mount_id, flags);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, pathname, REAL(strlen)(pathname) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, pathname, internal_strlen(pathname) + 1);
__sanitizer_file_handle *sanitizer_handle =
reinterpret_cast<__sanitizer_file_handle*>(handle);
@@ -7341,7 +7390,7 @@ INTERCEPTOR(SIZE_T, strlcpy, char *dst, char *src, SIZE_T size) {
ctx, src, Min(internal_strnlen(src, size), size - 1) + 1);
}
res = REAL(strlcpy)(dst, src, size);
- COMMON_INTERCEPTOR_COPY_STRING(ctx, dst, src, REAL(strlen)(dst) + 1);
+ COMMON_INTERCEPTOR_COPY_STRING(ctx, dst, src, internal_strlen(dst) + 1);
return res;
}
@@ -7416,7 +7465,7 @@ INTERCEPTOR(char *, devname, u64 dev, u32 type) {
COMMON_INTERCEPTOR_ENTER(ctx, devname, dev, type);
name = REAL(devname)(dev, type);
if (name)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
return name;
}
#define INIT_DEVNAME COMMON_INTERCEPT_FUNCTION(devname);
@@ -7438,7 +7487,7 @@ INTERCEPTOR(DEVNAME_R_RETTYPE, devname_r, u64 dev, u32 type, char *path,
COMMON_INTERCEPTOR_ENTER(ctx, devname_r, dev, type, path, len);
DEVNAME_R_RETTYPE res = REAL(devname_r)(dev, type, path, len);
if (DEVNAME_R_SUCCESS(res))
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, path, internal_strlen(path) + 1);
return res;
}
#define INIT_DEVNAME_R COMMON_INTERCEPT_FUNCTION(devname_r);
@@ -7468,7 +7517,7 @@ INTERCEPTOR(void, strmode, u32 mode, char *bp) {
COMMON_INTERCEPTOR_ENTER(ctx, strmode, mode, bp);
REAL(strmode)(mode, bp);
if (bp)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, bp, REAL(strlen)(bp) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, bp, internal_strlen(bp) + 1);
}
#define INIT_STRMODE COMMON_INTERCEPT_FUNCTION(strmode)
#else
@@ -7488,37 +7537,42 @@ INTERCEPTOR(struct __sanitizer_ttyent *, getttynam, char *name) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getttynam, name);
if (name)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
struct __sanitizer_ttyent *ttyent = REAL(getttynam)(name);
if (ttyent)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ttyent, struct_ttyent_sz);
return ttyent;
}
+#define INIT_TTYENT \
+ COMMON_INTERCEPT_FUNCTION(getttyent); \
+ COMMON_INTERCEPT_FUNCTION(getttynam);
+#else
+#define INIT_TTYENT
+#endif
+
+#if SANITIZER_INTERCEPT_TTYENTPATH
INTERCEPTOR(int, setttyentpath, char *path) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, setttyentpath, path);
if (path)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
return REAL(setttyentpath)(path);
}
-#define INIT_TTYENT \
- COMMON_INTERCEPT_FUNCTION(getttyent); \
- COMMON_INTERCEPT_FUNCTION(getttynam); \
- COMMON_INTERCEPT_FUNCTION(setttyentpath)
+#define INIT_TTYENTPATH COMMON_INTERCEPT_FUNCTION(setttyentpath);
#else
-#define INIT_TTYENT
+#define INIT_TTYENTPATH
#endif
#if SANITIZER_INTERCEPT_PROTOENT
static void write_protoent(void *ctx, struct __sanitizer_protoent *p) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, REAL(strlen)(p->p_name) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, internal_strlen(p->p_name) + 1);
SIZE_T pp_size = 1; // One handles the trailing \0
for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, REAL(strlen)(*pp) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, internal_strlen(*pp) + 1);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases,
pp_size * sizeof(char **));
@@ -7537,7 +7591,7 @@ INTERCEPTOR(struct __sanitizer_protoent *, getprotobyname, const char *name) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getprotobyname, name);
if (name)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
struct __sanitizer_protoent *p = REAL(getprotobyname)(name);
if (p)
write_protoent(ctx, p);
@@ -7581,7 +7635,7 @@ INTERCEPTOR(int, getprotobyname_r, const char *name,
COMMON_INTERCEPTOR_ENTER(ctx, getprotobyname_r, name, result_buf, buf,
buflen, result);
if (name)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
int res = REAL(getprotobyname_r)(name, result_buf, buf, buflen, result);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
@@ -7620,12 +7674,12 @@ INTERCEPTOR(struct __sanitizer_netent *, getnetent) {
if (n) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);
SIZE_T nn_size = 1; // One handles the trailing \0
for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
nn_size * sizeof(char **));
@@ -7637,17 +7691,17 @@ INTERCEPTOR(struct __sanitizer_netent *, getnetbyname, const char *name) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getnetbyname, name);
if (name)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
struct __sanitizer_netent *n = REAL(getnetbyname)(name);
if (n) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);
SIZE_T nn_size = 1; // One handles the trailing \0
for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
nn_size * sizeof(char **));
@@ -7662,12 +7716,12 @@ INTERCEPTOR(struct __sanitizer_netent *, getnetbyaddr, u32 net, int type) {
if (n) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);
SIZE_T nn_size = 1; // One handles the trailing \0
for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
nn_size * sizeof(char **));
@@ -7788,7 +7842,7 @@ INTERCEPTOR(int, regcomp, void *preg, const char *pattern, int cflags) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, regcomp, preg, pattern, cflags);
if (pattern)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, pattern, REAL(strlen)(pattern) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, pattern, internal_strlen(pattern) + 1);
int res = REAL(regcomp)(preg, pattern, cflags);
if (!res)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, preg, struct_regex_sz);
@@ -7801,7 +7855,7 @@ INTERCEPTOR(int, regexec, const void *preg, const char *string, SIZE_T nmatch,
if (preg)
COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
if (string)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, string, REAL(strlen)(string) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, string, internal_strlen(string) + 1);
int res = REAL(regexec)(preg, string, nmatch, pmatch, eflags);
if (!res && pmatch)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pmatch, nmatch * struct_regmatch_sz);
@@ -7815,7 +7869,7 @@ INTERCEPTOR(SIZE_T, regerror, int errcode, const void *preg, char *errbuf,
COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
SIZE_T res = REAL(regerror)(errcode, preg, errbuf, errbuf_size);
if (errbuf)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errbuf, REAL(strlen)(errbuf) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errbuf, internal_strlen(errbuf) + 1);
return res;
}
INTERCEPTOR(void, regfree, const void *preg) {
@@ -7840,15 +7894,15 @@ INTERCEPTOR(SSIZE_T, regnsub, char *buf, SIZE_T bufsiz, const char *sub,
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, regnsub, buf, bufsiz, sub, rm, str);
if (sub)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, REAL(strlen)(sub) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, internal_strlen(sub) + 1);
// The implementation demands and hardcodes 10 elements
if (rm)
COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
if (str)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
SSIZE_T res = REAL(regnsub)(buf, bufsiz, sub, rm, str);
if (res > 0 && buf)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
return res;
}
INTERCEPTOR(SSIZE_T, regasub, char **buf, const char *sub,
@@ -7856,16 +7910,16 @@ INTERCEPTOR(SSIZE_T, regasub, char **buf, const char *sub,
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, regasub, buf, sub, rm, sstr);
if (sub)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, REAL(strlen)(sub) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, internal_strlen(sub) + 1);
// Hardcode 10 elements as this is hardcoded size
if (rm)
COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
if (sstr)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, sstr, REAL(strlen)(sstr) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sstr, internal_strlen(sstr) + 1);
SSIZE_T res = REAL(regasub)(buf, sub, rm, sstr);
if (res > 0 && buf) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sizeof(char *));
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *buf, REAL(strlen)(*buf) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *buf, internal_strlen(*buf) + 1);
}
return res;
}
@@ -7887,7 +7941,7 @@ INTERCEPTOR(void *, fts_open, char *const *path_argv, int options,
COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
if (!*pa)
break;
- COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
}
}
// TODO(kamil): handle compar callback
@@ -7979,7 +8033,7 @@ INTERCEPTOR(int, sysctlbyname, char *sname, void *oldp, SIZE_T *oldlenp,
COMMON_INTERCEPTOR_ENTER(ctx, sysctlbyname, sname, oldp, oldlenp, newp,
newlen);
if (sname)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
if (oldlenp)
COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
if (newp && newlen)
@@ -8000,7 +8054,7 @@ INTERCEPTOR(int, sysctlnametomib, const char *sname, int *name,
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, sysctlnametomib, sname, name, namelenp);
if (sname)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
if (namelenp)
COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
int res = REAL(sysctlnametomib)(sname, name, namelenp);
@@ -8040,7 +8094,7 @@ INTERCEPTOR(void *, asysctlbyname, const char *sname, SIZE_T *len) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, asysctlbyname, sname, len);
if (sname)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
void *res = REAL(asysctlbyname)(sname, len);
if (res && len) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
@@ -8063,7 +8117,7 @@ INTERCEPTOR(int, sysctlgetmibinfo, char *sname, int *name,
COMMON_INTERCEPTOR_ENTER(ctx, sysctlgetmibinfo, sname, name, namelenp, cname,
csz, rnode, v);
if (sname)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
if (namelenp)
COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
if (csz)
@@ -8097,7 +8151,7 @@ INTERCEPTOR(char *, nl_langinfo, long item) {
COMMON_INTERCEPTOR_ENTER(ctx, nl_langinfo, item);
char *ret = REAL(nl_langinfo)(item);
if (ret)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, REAL(strlen)(ret) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, internal_strlen(ret) + 1);
return ret;
}
#define INIT_NL_LANGINFO COMMON_INTERCEPT_FUNCTION(nl_langinfo)
@@ -8117,7 +8171,7 @@ INTERCEPTOR(int, modctl, int operation, void *argp) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, ml, sizeof(*ml));
if (ml->ml_filename)
COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_filename,
- REAL(strlen)(ml->ml_filename) + 1);
+ internal_strlen(ml->ml_filename) + 1);
if (ml->ml_props)
COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_props, ml->ml_propslen);
}
@@ -8125,7 +8179,7 @@ INTERCEPTOR(int, modctl, int operation, void *argp) {
} else if (operation == modctl_unload) {
if (argp) {
const char *name = (const char *)argp;
- COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
}
ret = REAL(modctl)(operation, argp);
} else if (operation == modctl_stat) {
@@ -8167,7 +8221,7 @@ INTERCEPTOR(long long, strtonum, const char *nptr, long long minval,
if (errstr) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errstr, sizeof(const char *));
if (*errstr)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *errstr, REAL(strlen)(*errstr) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *errstr, internal_strlen(*errstr) + 1);
}
return ret;
}
@@ -8187,7 +8241,7 @@ INTERCEPTOR(char *, fparseln, __sanitizer_FILE *stream, SIZE_T *len,
COMMON_INTERCEPTOR_READ_RANGE(ctx, delim, sizeof(delim[0]) * 3);
char *ret = REAL(fparseln)(stream, len, lineno, delim, flags);
if (ret) {
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, REAL(strlen)(ret) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, internal_strlen(ret) + 1);
if (len)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
if (lineno)
@@ -8204,7 +8258,7 @@ INTERCEPTOR(char *, fparseln, __sanitizer_FILE *stream, SIZE_T *len,
INTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
int res = REAL(statvfs1)(path, buf, flags);
if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
return res;
@@ -8485,7 +8539,7 @@ INTERCEPTOR(char *, SHA1File, char *filename, char *buf) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, SHA1File, filename, buf);
if (filename)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
char *ret = REAL(SHA1File)(filename, buf);
if (ret)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
@@ -8496,7 +8550,7 @@ INTERCEPTOR(char *, SHA1FileChunk, char *filename, char *buf, OFF_T offset,
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, SHA1FileChunk, filename, buf, offset, length);
if (filename)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
char *ret = REAL(SHA1FileChunk)(filename, buf, offset, length);
if (ret)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
@@ -8572,7 +8626,7 @@ INTERCEPTOR(char *, MD4File, const char *filename, char *buf) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, MD4File, filename, buf);
if (filename)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
char *ret = REAL(MD4File)(filename, buf);
if (ret)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
@@ -8655,7 +8709,7 @@ INTERCEPTOR(char *, RMD160File, char *filename, char *buf) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, RMD160File, filename, buf);
if (filename)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
char *ret = REAL(RMD160File)(filename, buf);
if (ret)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
@@ -8666,7 +8720,7 @@ INTERCEPTOR(char *, RMD160FileChunk, char *filename, char *buf, OFF_T offset,
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, RMD160FileChunk, filename, buf, offset, length);
if (filename)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
char *ret = REAL(RMD160FileChunk)(filename, buf, offset, length);
if (ret)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
@@ -8742,7 +8796,7 @@ INTERCEPTOR(char *, MD5File, const char *filename, char *buf) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, MD5File, filename, buf);
if (filename)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
char *ret = REAL(MD5File)(filename, buf);
if (ret)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
@@ -8872,7 +8926,7 @@ INTERCEPTOR(char *, MD2File, const char *filename, char *buf) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, MD2File, filename, buf);
if (filename)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
char *ret = REAL(MD2File)(filename, buf);
if (ret)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
@@ -8950,7 +9004,7 @@ INTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len,
void *ctx; \
COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_File, filename, buf); \
if (filename) \
- COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);\
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);\
char *ret = REAL(SHA##LEN##_File)(filename, buf); \
if (ret) \
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
@@ -8962,7 +9016,7 @@ INTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len,
COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_FileChunk, filename, buf, offset, \
length); \
if (filename) \
- COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);\
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);\
char *ret = REAL(SHA##LEN##_FileChunk)(filename, buf, offset, length); \
if (ret) \
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
@@ -9026,7 +9080,7 @@ INTERCEPTOR(int, strvis, char *dst, const char *src, int flag) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strvis, dst, src, flag);
if (src)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
int len = REAL(strvis)(dst, src, flag);
if (dst)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
@@ -9036,7 +9090,7 @@ INTERCEPTOR(int, stravis, char **dst, const char *src, int flag) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, stravis, dst, src, flag);
if (src)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
int len = REAL(stravis)(dst, src, flag);
if (dst) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(char *));
@@ -9049,7 +9103,7 @@ INTERCEPTOR(int, strnvis, char *dst, SIZE_T dlen, const char *src, int flag) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strnvis, dst, dlen, src, flag);
if (src)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
int len = REAL(strnvis)(dst, dlen, src, flag);
// The interface will be valid even if there is no space for NULL char
if (dst && len > 0)
@@ -9099,7 +9153,7 @@ INTERCEPTOR(char *, svis, char *dst, int c, int flag, int nextc,
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, svis, dst, c, flag, nextc, extra);
if (extra)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
char *end = REAL(svis)(dst, c, flag, nextc, extra);
if (dst && end)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
@@ -9110,7 +9164,7 @@ INTERCEPTOR(char *, snvis, char *dst, SIZE_T dlen, int c, int flag, int nextc,
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, snvis, dst, dlen, c, flag, nextc, extra);
if (extra)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
char *end = REAL(snvis)(dst, dlen, c, flag, nextc, extra);
if (dst && end)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst,
@@ -9122,9 +9176,9 @@ INTERCEPTOR(int, strsvis, char *dst, const char *src, int flag,
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strsvis, dst, src, flag, extra);
if (src)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
if (extra)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
int len = REAL(strsvis)(dst, src, flag, extra);
if (dst)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
@@ -9135,9 +9189,9 @@ INTERCEPTOR(int, strsnvis, char *dst, SIZE_T dlen, const char *src, int flag,
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strsnvis, dst, dlen, src, flag, extra);
if (src)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
if (extra)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
int len = REAL(strsnvis)(dst, dlen, src, flag, extra);
// The interface will be valid even if there is no space for NULL char
if (dst && len >= 0)
@@ -9151,7 +9205,7 @@ INTERCEPTOR(int, strsvisx, char *dst, const char *src, SIZE_T len, int flag,
if (src)
COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
if (extra)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
int ret = REAL(strsvisx)(dst, src, len, flag, extra);
if (dst)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
@@ -9164,7 +9218,7 @@ INTERCEPTOR(int, strsnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
if (src)
COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
if (extra)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
int ret = REAL(strsnvisx)(dst, dlen, src, len, flag, extra);
if (dst && ret >= 0)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
@@ -9178,7 +9232,7 @@ INTERCEPTOR(int, strsenvisx, char *dst, SIZE_T dlen, const char *src,
if (src)
COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
if (extra)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
// FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
// according to the implementation
if (cerr_ptr)
@@ -9205,7 +9259,7 @@ INTERCEPTOR(int, strunvis, char *dst, const char *src) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strunvis, dst, src);
if (src)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
int ret = REAL(strunvis)(dst, src);
if (ret != -1)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
@@ -9215,7 +9269,7 @@ INTERCEPTOR(int, strnunvis, char *dst, SIZE_T dlen, const char *src) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strnunvis, dst, dlen, src);
if (src)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
int ret = REAL(strnunvis)(dst, dlen, src);
if (ret != -1)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
@@ -9225,7 +9279,7 @@ INTERCEPTOR(int, strunvisx, char *dst, const char *src, int flag) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strunvisx, dst, src, flag);
if (src)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
int ret = REAL(strunvisx)(dst, src, flag);
if (ret != -1)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
@@ -9236,7 +9290,7 @@ INTERCEPTOR(int, strnunvisx, char *dst, SIZE_T dlen, const char *src,
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strnunvisx, dst, dlen, src, flag);
if (src)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
int ret = REAL(strnunvisx)(dst, dlen, src, flag);
if (ret != -1)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
@@ -9272,7 +9326,7 @@ INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open, const char *path, int flags) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open, path, flags);
if (path)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
struct __sanitizer_cdbr *cdbr = REAL(cdbr_open)(path, flags);
if (cdbr)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
@@ -9464,7 +9518,7 @@ INTERCEPTOR(void *, getfsspec, const char *spec) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getfsspec, spec);
if (spec)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, spec, REAL(strlen)(spec) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, spec, internal_strlen(spec) + 1);
void *ret = REAL(getfsspec)(spec);
if (ret)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
@@ -9475,7 +9529,7 @@ INTERCEPTOR(void *, getfsfile, const char *file) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getfsfile, file);
if (file)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, file, REAL(strlen)(file) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, file, internal_strlen(file) + 1);
void *ret = REAL(getfsfile)(file);
if (ret)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
@@ -9519,9 +9573,9 @@ INTERCEPTOR(__sanitizer_FILE *, popen, const char *command, const char *type) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, popen, command, type);
if (command)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, command, REAL(strlen)(command) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, command, internal_strlen(command) + 1);
if (type)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, type, internal_strlen(type) + 1);
__sanitizer_FILE *res = REAL(popen)(command, type);
COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
if (res) unpoison_file(res);
@@ -9538,13 +9592,13 @@ INTERCEPTOR(__sanitizer_FILE *, popenve, const char *path,
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, popenve, path, argv, envp, type);
if (path)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
if (argv) {
for (char *const *pa = argv; ; ++pa) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
if (!*pa)
break;
- COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
}
}
if (envp) {
@@ -9552,11 +9606,11 @@ INTERCEPTOR(__sanitizer_FILE *, popenve, const char *path,
COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
if (!*pa)
break;
- COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
}
}
if (type)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, type, internal_strlen(type) + 1);
__sanitizer_FILE *res = REAL(popenve)(path, argv, envp, type);
COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
if (res) unpoison_file(res);
@@ -9752,7 +9806,7 @@ INTERCEPTOR(char *, fdevname, int fd) {
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
char *name = REAL(fdevname)(fd);
if (name) {
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
if (fd > 0)
COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
}
@@ -9765,7 +9819,7 @@ INTERCEPTOR(char *, fdevname_r, int fd, char *buf, SIZE_T len) {
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
char *name = REAL(fdevname_r)(fd, buf, len);
if (name && buf && len > 0) {
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
if (fd > 0)
COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
}
@@ -9785,7 +9839,7 @@ INTERCEPTOR(char *, getusershell) {
COMMON_INTERCEPTOR_ENTER(ctx, getusershell);
char *res = REAL(getusershell)();
if (res)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
return res;
}
@@ -9810,7 +9864,7 @@ INTERCEPTOR(int, sl_add, void *sl, char *item) {
if (sl)
COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
if (item)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, item, internal_strlen(item) + 1);
int res = REAL(sl_add)(sl, item);
if (!res)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
@@ -9823,10 +9877,10 @@ INTERCEPTOR(char *, sl_find, void *sl, const char *item) {
if (sl)
COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
if (item)
- COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, item, internal_strlen(item) + 1);
char *res = REAL(sl_find)(sl, item);
if (res)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
return res;
}
@@ -9912,7 +9966,52 @@ INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
#define INIT_GETENTROPY
#endif
-#if SANITIZER_INTERCEPT_QSORT
+#if SANITIZER_INTERCEPT_QSORT_R
+typedef int (*qsort_r_compar_f)(const void *, const void *, void *);
+struct qsort_r_compar_params {
+ SIZE_T size;
+ qsort_r_compar_f compar;
+ void *arg;
+};
+static int wrapped_qsort_r_compar(const void *a, const void *b, void *arg) {
+ qsort_r_compar_params *params = (qsort_r_compar_params *)arg;
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, params->size);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, params->size);
+ return params->compar(a, b, params->arg);
+}
+
+INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
+ qsort_r_compar_f compar, void *arg) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, qsort_r, base, nmemb, size, compar, arg);
+ // Run the comparator over all array elements to detect any memory issues.
+ if (nmemb > 1) {
+ for (SIZE_T i = 0; i < nmemb - 1; ++i) {
+ void *p = (void *)((char *)base + i * size);
+ void *q = (void *)((char *)base + (i + 1) * size);
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
+ compar(p, q, arg);
+ }
+ }
+ qsort_r_compar_params params = {size, compar, arg};
+ REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, &params);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
+}
+# define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION(qsort_r)
+#else
+# define INIT_QSORT_R
+#endif
+
+#if SANITIZER_INTERCEPT_QSORT && SANITIZER_INTERCEPT_QSORT_R
+INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
+ qsort_r_compar_f compar) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, qsort, base, nmemb, size, compar);
+ WRAP(qsort_r)(base, nmemb, size, compar, nullptr);
+}
+# define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
+#elif SANITIZER_INTERCEPT_QSORT && !SANITIZER_INTERCEPT_QSORT_R
// Glibc qsort uses a temporary buffer allocated either on stack or on heap.
// Poisoned memory from there may get copied into the comparator arguments,
// where it needs to be dealt with. But even that is not enough - the results of
@@ -9927,7 +10026,7 @@ INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
typedef int (*qsort_compar_f)(const void *, const void *);
static THREADLOCAL qsort_compar_f qsort_compar;
static THREADLOCAL SIZE_T qsort_size;
-int wrapped_qsort_compar(const void *a, const void *b) {
+static int wrapped_qsort_compar(const void *a, const void *b) {
COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_size);
COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_size);
@@ -9969,60 +10068,34 @@ INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
}
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
}
-#define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
+# define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
#else
-#define INIT_QSORT
+# define INIT_QSORT
#endif
-#if SANITIZER_INTERCEPT_QSORT_R
-typedef int (*qsort_r_compar_f)(const void *, const void *, void *);
-static THREADLOCAL qsort_r_compar_f qsort_r_compar;
-static THREADLOCAL SIZE_T qsort_r_size;
-int wrapped_qsort_r_compar(const void *a, const void *b, void *arg) {
- COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_r_size);
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_r_size);
- return qsort_r_compar(a, b, arg);
+#if SANITIZER_INTERCEPT_BSEARCH
+typedef int (*bsearch_compar_f)(const void *, const void *);
+struct bsearch_compar_params {
+ const void *key;
+ bsearch_compar_f compar;
+};
+
+static int wrapped_bsearch_compar(const void *key, const void *b) {
+ const bsearch_compar_params *params = (const bsearch_compar_params *)key;
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
+ return params->compar(params->key, b);
}
-INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
- qsort_r_compar_f compar, void *arg) {
+INTERCEPTOR(void *, bsearch, const void *key, const void *base, SIZE_T nmemb,
+ SIZE_T size, bsearch_compar_f compar) {
void *ctx;
- COMMON_INTERCEPTOR_ENTER(ctx, qsort_r, base, nmemb, size, compar, arg);
- // Run the comparator over all array elements to detect any memory issues.
- if (nmemb > 1) {
- for (SIZE_T i = 0; i < nmemb - 1; ++i) {
- void *p = (void *)((char *)base + i * size);
- void *q = (void *)((char *)base + (i + 1) * size);
- COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
- compar(p, q, arg);
- }
- }
- qsort_r_compar_f old_compar = qsort_r_compar;
- SIZE_T old_size = qsort_r_size;
- // Handle qsort_r() implementations that recurse using an
- // interposable function call:
- bool already_wrapped = compar == wrapped_qsort_r_compar;
- if (already_wrapped) {
- // This case should only happen if the qsort() implementation calls itself
- // using a preemptible function call (e.g. the FreeBSD libc version).
- // Check that the size and comparator arguments are as expected.
- CHECK_NE(compar, qsort_r_compar);
- CHECK_EQ(qsort_r_size, size);
- } else {
- qsort_r_compar = compar;
- qsort_r_size = size;
- }
- REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, arg);
- if (!already_wrapped) {
- qsort_r_compar = old_compar;
- qsort_r_size = old_size;
- }
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
+ COMMON_INTERCEPTOR_ENTER(ctx, bsearch, key, base, nmemb, size, compar);
+ bsearch_compar_params params = {key, compar};
+ return REAL(bsearch)(&params, base, nmemb, size, wrapped_bsearch_compar);
}
-#define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION(qsort_r)
+# define INIT_BSEARCH COMMON_INTERCEPT_FUNCTION(bsearch)
#else
-#define INIT_QSORT_R
+# define INIT_BSEARCH
#endif
#if SANITIZER_INTERCEPT_SIGALTSTACK
@@ -10391,6 +10464,7 @@ static void InitializeCommonInterceptors() {
INIT_GETENTROPY;
INIT_QSORT;
INIT_QSORT_R;
+ INIT_BSEARCH;
INIT_SIGALTSTACK;
INIT_UNAME;
INIT___XUNAME;
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_format.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_format.inc
index 082398b..220abb8 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_format.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_format.inc
@@ -324,8 +324,8 @@ static void scanf_common(void *ctx, int n_inputs, bool allowGnuMalloc,
continue;
int size = scanf_get_value_size(&dir);
if (size == FSS_INVALID) {
- Report("%s: WARNING: unexpected format specifier in scanf interceptor: ",
- SanitizerToolName, "%.*s\n", dir.end - dir.begin, dir.begin);
+ Report("%s: WARNING: unexpected format specifier in scanf interceptor: %.*s\n",
+ SanitizerToolName, static_cast<int>(dir.end - dir.begin), dir.begin);
break;
}
void *argp = va_arg(aq, void *);
@@ -469,7 +469,7 @@ static int printf_get_value_size(PrintfDirective *dir) {
break; \
default: \
Report("WARNING: unexpected floating-point arg size" \
- " in printf interceptor: %d\n", size); \
+ " in printf interceptor: %zu\n", static_cast<uptr>(size)); \
return; \
} \
} else { \
@@ -484,7 +484,7 @@ static int printf_get_value_size(PrintfDirective *dir) {
break; \
default: \
Report("WARNING: unexpected arg size" \
- " in printf interceptor: %d\n", size); \
+ " in printf interceptor: %zu\n", static_cast<uptr>(size)); \
return; \
} \
} \
@@ -530,7 +530,7 @@ static void printf_common(void *ctx, const char *format, va_list aq) {
Report(
"%s: WARNING: unexpected format specifier in printf "
"interceptor: %.*s (reported once per process)\n",
- SanitizerToolName, dir.end - dir.begin, dir.begin);
+ SanitizerToolName, static_cast<int>(dir.end - dir.begin), dir.begin);
break;
}
if (dir.convSpecifier == 'n') {
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_netbsd_compat.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_netbsd_compat.inc
index 6aa73ec..f6ac3fa 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_netbsd_compat.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_netbsd_compat.inc
@@ -33,7 +33,7 @@
INTERCEPTOR(int, statvfs, char *path, void *buf) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
@@ -99,7 +99,7 @@ INTERCEPTOR(int, getvfsstat, void *buf, SIZE_T bufsize, int flags) {
INTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags);
- if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
int res = REAL(statvfs1)(path, buf, flags);
if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
return res;
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S
index ed69381..f60b05d 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S
@@ -6,6 +6,7 @@
.globl ASM_WRAPPER_NAME(vfork)
ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
ASM_WRAPPER_NAME(vfork):
+ _CET_ENDBR
// Store return address in the spill area and tear down the stack frame.
sub $12, %esp
call COMMON_INTERCEPTOR_SPILL_AREA
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S
index 8147cdd..8fd18ea 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S
@@ -6,6 +6,7 @@
.globl ASM_WRAPPER_NAME(vfork)
ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
ASM_WRAPPER_NAME(vfork):
+ _CET_ENDBR
// Store return address in the spill area and tear down the stack frame.
push %rcx
call COMMON_INTERCEPTOR_SPILL_AREA
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_libcdep.cpp b/libsanitizer/sanitizer_common/sanitizer_common_libcdep.cpp
index 01ccacc..bc4b477 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_libcdep.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_common_libcdep.cpp
@@ -26,9 +26,7 @@ void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded)) {
#if (SANITIZER_LINUX || SANITIZER_NETBSD) && !SANITIZER_GO
// Weak default implementation for when sanitizer_stackdepot is not linked in.
-SANITIZER_WEAK_ATTRIBUTE StackDepotStats *StackDepotGetStats() {
- return nullptr;
-}
+SANITIZER_WEAK_ATTRIBUTE StackDepotStats StackDepotGetStats() { return {}; }
void *BackgroundThread(void *arg) {
const uptr hard_rss_limit_mb = common_flags()->hard_rss_limit_mb;
@@ -48,16 +46,12 @@ void *BackgroundThread(void *arg) {
prev_reported_rss = current_rss_mb;
}
// If stack depot has grown 10% since last time, print it too.
- StackDepotStats *stack_depot_stats = StackDepotGetStats();
- if (stack_depot_stats) {
- if (prev_reported_stack_depot_size * 11 / 10 <
- stack_depot_stats->allocated) {
- Printf("%s: StackDepot: %zd ids; %zdM allocated\n",
- SanitizerToolName,
- stack_depot_stats->n_uniq_ids,
- stack_depot_stats->allocated >> 20);
- prev_reported_stack_depot_size = stack_depot_stats->allocated;
- }
+ StackDepotStats stack_depot_stats = StackDepotGetStats();
+ if (prev_reported_stack_depot_size * 11 / 10 <
+ stack_depot_stats.allocated) {
+ Printf("%s: StackDepot: %zd ids; %zdM allocated\n", SanitizerToolName,
+ stack_depot_stats.n_uniq_ids, stack_depot_stats.allocated >> 20);
+ prev_reported_stack_depot_size = stack_depot_stats.allocated;
}
}
// Check RSS against the limit.
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_nolibc.cpp b/libsanitizer/sanitizer_common/sanitizer_common_nolibc.cpp
index 9a4e538..a20602d 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_nolibc.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_common_nolibc.cpp
@@ -25,6 +25,7 @@ void LogMessageOnPrintf(const char *str) {}
#endif
void WriteToSyslog(const char *buffer) {}
void Abort() { internal__exit(1); }
+bool CreateDir(const char *pathname) { return false; }
#endif // !SANITIZER_WINDOWS
#if !SANITIZER_WINDOWS && !SANITIZER_MAC
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc b/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc
index 1b89d6e..a38b134 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc
@@ -43,45 +43,47 @@
#include "sanitizer_platform.h"
#if SANITIZER_LINUX
-#include "sanitizer_libc.h"
+# include "sanitizer_libc.h"
-#define PRE_SYSCALL(name) \
- SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_pre_impl_##name
-#define PRE_READ(p, s) COMMON_SYSCALL_PRE_READ_RANGE(p, s)
-#define PRE_WRITE(p, s) COMMON_SYSCALL_PRE_WRITE_RANGE(p, s)
+# define PRE_SYSCALL(name) \
+ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_pre_impl_##name
+# define PRE_READ(p, s) COMMON_SYSCALL_PRE_READ_RANGE(p, s)
+# define PRE_WRITE(p, s) COMMON_SYSCALL_PRE_WRITE_RANGE(p, s)
-#define POST_SYSCALL(name) \
- SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_post_impl_##name
-#define POST_READ(p, s) COMMON_SYSCALL_POST_READ_RANGE(p, s)
-#define POST_WRITE(p, s) COMMON_SYSCALL_POST_WRITE_RANGE(p, s)
+# define POST_SYSCALL(name) \
+ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_post_impl_##name
+# define POST_READ(p, s) COMMON_SYSCALL_POST_READ_RANGE(p, s)
+# define POST_WRITE(p, s) COMMON_SYSCALL_POST_WRITE_RANGE(p, s)
-#ifndef COMMON_SYSCALL_ACQUIRE
-# define COMMON_SYSCALL_ACQUIRE(addr) ((void)(addr))
-#endif
+# ifndef COMMON_SYSCALL_ACQUIRE
+# define COMMON_SYSCALL_ACQUIRE(addr) ((void)(addr))
+# endif
-#ifndef COMMON_SYSCALL_RELEASE
-# define COMMON_SYSCALL_RELEASE(addr) ((void)(addr))
-#endif
+# ifndef COMMON_SYSCALL_RELEASE
+# define COMMON_SYSCALL_RELEASE(addr) ((void)(addr))
+# endif
-#ifndef COMMON_SYSCALL_FD_CLOSE
-# define COMMON_SYSCALL_FD_CLOSE(fd) ((void)(fd))
-#endif
+# ifndef COMMON_SYSCALL_FD_CLOSE
+# define COMMON_SYSCALL_FD_CLOSE(fd) ((void)(fd))
+# endif
-#ifndef COMMON_SYSCALL_FD_ACQUIRE
-# define COMMON_SYSCALL_FD_ACQUIRE(fd) ((void)(fd))
-#endif
+# ifndef COMMON_SYSCALL_FD_ACQUIRE
+# define COMMON_SYSCALL_FD_ACQUIRE(fd) ((void)(fd))
+# endif
-#ifndef COMMON_SYSCALL_FD_RELEASE
-# define COMMON_SYSCALL_FD_RELEASE(fd) ((void)(fd))
-#endif
+# ifndef COMMON_SYSCALL_FD_RELEASE
+# define COMMON_SYSCALL_FD_RELEASE(fd) ((void)(fd))
+# endif
-#ifndef COMMON_SYSCALL_PRE_FORK
-# define COMMON_SYSCALL_PRE_FORK() {}
-#endif
+# ifndef COMMON_SYSCALL_PRE_FORK
+# define COMMON_SYSCALL_PRE_FORK() \
+ {}
+# endif
-#ifndef COMMON_SYSCALL_POST_FORK
-# define COMMON_SYSCALL_POST_FORK(res) {}
-#endif
+# ifndef COMMON_SYSCALL_POST_FORK
+# define COMMON_SYSCALL_POST_FORK(res) \
+ {}
+# endif
// FIXME: do some kind of PRE_READ for all syscall arguments (int(s) and such).
@@ -130,8 +132,8 @@ struct sanitizer_kernel_sockaddr {
// Declare it "void" to catch sizeof(kernel_sigset_t).
typedef void kernel_sigset_t;
-static void kernel_write_iovec(const __sanitizer_iovec *iovec,
- SIZE_T iovlen, SIZE_T maxlen) {
+static void kernel_write_iovec(const __sanitizer_iovec *iovec, SIZE_T iovlen,
+ SIZE_T maxlen) {
for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
POST_WRITE(iovec[i].iov_base, sz);
@@ -141,8 +143,8 @@ static void kernel_write_iovec(const __sanitizer_iovec *iovec,
// This functions uses POST_READ, because it needs to run after syscall to know
// the real read range.
-static void kernel_read_iovec(const __sanitizer_iovec *iovec,
- SIZE_T iovlen, SIZE_T maxlen) {
+static void kernel_read_iovec(const __sanitizer_iovec *iovec, SIZE_T iovlen,
+ SIZE_T maxlen) {
POST_READ(iovec, sizeof(*iovec) * iovlen);
for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
@@ -155,8 +157,8 @@ PRE_SYSCALL(recvmsg)(long sockfd, sanitizer_kernel_msghdr *msg, long flags) {
PRE_READ(msg, sizeof(*msg));
}
-POST_SYSCALL(recvmsg)(long res, long sockfd, sanitizer_kernel_msghdr *msg,
- long flags) {
+POST_SYSCALL(recvmsg)
+(long res, long sockfd, sanitizer_kernel_msghdr *msg, long flags) {
if (res >= 0) {
if (msg) {
for (unsigned long i = 0; i < msg->msg_iovlen; ++i) {
@@ -167,13 +169,14 @@ POST_SYSCALL(recvmsg)(long res, long sockfd, sanitizer_kernel_msghdr *msg,
}
}
-PRE_SYSCALL(recvmmsg)(long fd, sanitizer_kernel_mmsghdr *msg, long vlen,
- long flags, void *timeout) {
+PRE_SYSCALL(recvmmsg)
+(long fd, sanitizer_kernel_mmsghdr *msg, long vlen, long flags, void *timeout) {
PRE_READ(msg, vlen * sizeof(*msg));
}
-POST_SYSCALL(recvmmsg)(long res, long fd, sanitizer_kernel_mmsghdr *msg,
- long vlen, long flags, void *timeout) {
+POST_SYSCALL(recvmmsg)
+(long res, long fd, sanitizer_kernel_mmsghdr *msg, long vlen, long flags,
+ void *timeout) {
if (res >= 0) {
if (msg) {
for (unsigned long i = 0; i < msg->msg_hdr.msg_iovlen; ++i) {
@@ -183,7 +186,8 @@ POST_SYSCALL(recvmmsg)(long res, long fd, sanitizer_kernel_mmsghdr *msg,
POST_WRITE(msg->msg_hdr.msg_control, msg->msg_hdr.msg_controllen);
POST_WRITE(&msg->msg_len, sizeof(msg->msg_len));
}
- if (timeout) POST_WRITE(timeout, struct_timespec_sz);
+ if (timeout)
+ POST_WRITE(timeout, struct_timespec_sz);
}
}
@@ -203,7 +207,8 @@ PRE_SYSCALL(time)(void *tloc) {}
POST_SYSCALL(time)(long res, void *tloc) {
if (res >= 0) {
- if (tloc) POST_WRITE(tloc, sizeof(long));
+ if (tloc)
+ POST_WRITE(tloc, sizeof(long));
}
}
@@ -211,7 +216,8 @@ PRE_SYSCALL(stime)(void *tptr) {}
POST_SYSCALL(stime)(long res, void *tptr) {
if (res >= 0) {
- if (tptr) POST_WRITE(tptr, sizeof(long));
+ if (tptr)
+ POST_WRITE(tptr, sizeof(long));
}
}
@@ -219,8 +225,10 @@ PRE_SYSCALL(gettimeofday)(void *tv, void *tz) {}
POST_SYSCALL(gettimeofday)(long res, void *tv, void *tz) {
if (res >= 0) {
- if (tv) POST_WRITE(tv, timeval_sz);
- if (tz) POST_WRITE(tz, struct_timezone_sz);
+ if (tv)
+ POST_WRITE(tv, timeval_sz);
+ if (tz)
+ POST_WRITE(tz, struct_timezone_sz);
}
}
@@ -228,26 +236,30 @@ PRE_SYSCALL(settimeofday)(void *tv, void *tz) {}
POST_SYSCALL(settimeofday)(long res, void *tv, void *tz) {
if (res >= 0) {
- if (tv) POST_WRITE(tv, timeval_sz);
- if (tz) POST_WRITE(tz, struct_timezone_sz);
+ if (tv)
+ POST_WRITE(tv, timeval_sz);
+ if (tz)
+ POST_WRITE(tz, struct_timezone_sz);
}
}
-#if !SANITIZER_ANDROID
+# if !SANITIZER_ANDROID
PRE_SYSCALL(adjtimex)(void *txc_p) {}
POST_SYSCALL(adjtimex)(long res, void *txc_p) {
if (res >= 0) {
- if (txc_p) POST_WRITE(txc_p, struct_timex_sz);
+ if (txc_p)
+ POST_WRITE(txc_p, struct_timex_sz);
}
}
-#endif
+# endif
PRE_SYSCALL(times)(void *tbuf) {}
POST_SYSCALL(times)(long res, void *tbuf) {
if (res >= 0) {
- if (tbuf) POST_WRITE(tbuf, struct_tms_sz);
+ if (tbuf)
+ POST_WRITE(tbuf, struct_tms_sz);
}
}
@@ -259,8 +271,10 @@ PRE_SYSCALL(nanosleep)(void *rqtp, void *rmtp) {}
POST_SYSCALL(nanosleep)(long res, void *rqtp, void *rmtp) {
if (res >= 0) {
- if (rqtp) POST_WRITE(rqtp, struct_timespec_sz);
- if (rmtp) POST_WRITE(rmtp, struct_timespec_sz);
+ if (rqtp)
+ POST_WRITE(rqtp, struct_timespec_sz);
+ if (rmtp)
+ POST_WRITE(rmtp, struct_timespec_sz);
}
}
@@ -296,9 +310,12 @@ PRE_SYSCALL(getresuid)(void *ruid, void *euid, void *suid) {}
POST_SYSCALL(getresuid)(long res, void *ruid, void *euid, void *suid) {
if (res >= 0) {
- if (ruid) POST_WRITE(ruid, sizeof(unsigned));
- if (euid) POST_WRITE(euid, sizeof(unsigned));
- if (suid) POST_WRITE(suid, sizeof(unsigned));
+ if (ruid)
+ POST_WRITE(ruid, sizeof(unsigned));
+ if (euid)
+ POST_WRITE(euid, sizeof(unsigned));
+ if (suid)
+ POST_WRITE(suid, sizeof(unsigned));
}
}
@@ -306,9 +323,12 @@ PRE_SYSCALL(getresgid)(void *rgid, void *egid, void *sgid) {}
POST_SYSCALL(getresgid)(long res, void *rgid, void *egid, void *sgid) {
if (res >= 0) {
- if (rgid) POST_WRITE(rgid, sizeof(unsigned));
- if (egid) POST_WRITE(egid, sizeof(unsigned));
- if (sgid) POST_WRITE(sgid, sizeof(unsigned));
+ if (rgid)
+ POST_WRITE(rgid, sizeof(unsigned));
+ if (egid)
+ POST_WRITE(egid, sizeof(unsigned));
+ if (sgid)
+ POST_WRITE(sgid, sizeof(unsigned));
}
}
@@ -326,10 +346,11 @@ POST_SYSCALL(getsid)(long res, long pid) {}
PRE_SYSCALL(getgroups)(long gidsetsize, void *grouplist) {}
-POST_SYSCALL(getgroups)(long res, long gidsetsize,
- __sanitizer___kernel_gid_t *grouplist) {
+POST_SYSCALL(getgroups)
+(long res, long gidsetsize, __sanitizer___kernel_gid_t *grouplist) {
if (res >= 0) {
- if (grouplist) POST_WRITE(grouplist, res * sizeof(*grouplist));
+ if (grouplist)
+ POST_WRITE(grouplist, res * sizeof(*grouplist));
}
}
@@ -374,11 +395,12 @@ PRE_SYSCALL(setsid)() {}
POST_SYSCALL(setsid)(long res) {}
PRE_SYSCALL(setgroups)(long gidsetsize, __sanitizer___kernel_gid_t *grouplist) {
- if (grouplist) POST_WRITE(grouplist, gidsetsize * sizeof(*grouplist));
+ if (grouplist)
+ POST_WRITE(grouplist, gidsetsize * sizeof(*grouplist));
}
-POST_SYSCALL(setgroups)(long res, long gidsetsize,
- __sanitizer___kernel_gid_t *grouplist) {}
+POST_SYSCALL(setgroups)
+(long res, long gidsetsize, __sanitizer___kernel_gid_t *grouplist) {}
PRE_SYSCALL(acct)(const void *name) {
if (name)
@@ -388,17 +410,21 @@ PRE_SYSCALL(acct)(const void *name) {
POST_SYSCALL(acct)(long res, const void *name) {}
PRE_SYSCALL(capget)(void *header, void *dataptr) {
- if (header) PRE_READ(header, __user_cap_header_struct_sz);
+ if (header)
+ PRE_READ(header, __user_cap_header_struct_sz);
}
POST_SYSCALL(capget)(long res, void *header, void *dataptr) {
if (res >= 0)
- if (dataptr) POST_WRITE(dataptr, __user_cap_data_struct_sz);
+ if (dataptr)
+ POST_WRITE(dataptr, __user_cap_data_struct_sz);
}
PRE_SYSCALL(capset)(void *header, const void *data) {
- if (header) PRE_READ(header, __user_cap_header_struct_sz);
- if (data) PRE_READ(data, __user_cap_data_struct_sz);
+ if (header)
+ PRE_READ(header, __user_cap_header_struct_sz);
+ if (data)
+ PRE_READ(data, __user_cap_data_struct_sz);
}
POST_SYSCALL(capset)(long res, void *header, const void *data) {}
@@ -411,7 +437,8 @@ PRE_SYSCALL(sigpending)(void *set) {}
POST_SYSCALL(sigpending)(long res, void *set) {
if (res >= 0) {
- if (set) POST_WRITE(set, old_sigset_t_sz);
+ if (set)
+ POST_WRITE(set, old_sigset_t_sz);
}
}
@@ -419,8 +446,10 @@ PRE_SYSCALL(sigprocmask)(long how, void *set, void *oset) {}
POST_SYSCALL(sigprocmask)(long res, long how, void *set, void *oset) {
if (res >= 0) {
- if (set) POST_WRITE(set, old_sigset_t_sz);
- if (oset) POST_WRITE(oset, old_sigset_t_sz);
+ if (set)
+ POST_WRITE(set, old_sigset_t_sz);
+ if (oset)
+ POST_WRITE(oset, old_sigset_t_sz);
}
}
@@ -428,7 +457,8 @@ PRE_SYSCALL(getitimer)(long which, void *value) {}
POST_SYSCALL(getitimer)(long res, long which, void *value) {
if (res >= 0) {
- if (value) POST_WRITE(value, struct_itimerval_sz);
+ if (value)
+ POST_WRITE(value, struct_itimerval_sz);
}
}
@@ -436,19 +466,23 @@ PRE_SYSCALL(setitimer)(long which, void *value, void *ovalue) {}
POST_SYSCALL(setitimer)(long res, long which, void *value, void *ovalue) {
if (res >= 0) {
- if (value) POST_WRITE(value, struct_itimerval_sz);
- if (ovalue) POST_WRITE(ovalue, struct_itimerval_sz);
+ if (value)
+ POST_WRITE(value, struct_itimerval_sz);
+ if (ovalue)
+ POST_WRITE(ovalue, struct_itimerval_sz);
}
}
-PRE_SYSCALL(timer_create)(long which_clock, void *timer_event_spec,
- void *created_timer_id) {}
+PRE_SYSCALL(timer_create)
+(long which_clock, void *timer_event_spec, void *created_timer_id) {}
-POST_SYSCALL(timer_create)(long res, long which_clock, void *timer_event_spec,
- void *created_timer_id) {
+POST_SYSCALL(timer_create)
+(long res, long which_clock, void *timer_event_spec, void *created_timer_id) {
if (res >= 0) {
- if (timer_event_spec) POST_WRITE(timer_event_spec, struct_sigevent_sz);
- if (created_timer_id) POST_WRITE(created_timer_id, sizeof(long));
+ if (timer_event_spec)
+ POST_WRITE(timer_event_spec, struct_sigevent_sz);
+ if (created_timer_id)
+ POST_WRITE(created_timer_id, sizeof(long));
}
}
@@ -456,7 +490,8 @@ PRE_SYSCALL(timer_gettime)(long timer_id, void *setting) {}
POST_SYSCALL(timer_gettime)(long res, long timer_id, void *setting) {
if (res >= 0) {
- if (setting) POST_WRITE(setting, struct_itimerspec_sz);
+ if (setting)
+ POST_WRITE(setting, struct_itimerspec_sz);
}
}
@@ -464,15 +499,18 @@ PRE_SYSCALL(timer_getoverrun)(long timer_id) {}
POST_SYSCALL(timer_getoverrun)(long res, long timer_id) {}
-PRE_SYSCALL(timer_settime)(long timer_id, long flags, const void *new_setting,
- void *old_setting) {
- if (new_setting) PRE_READ(new_setting, struct_itimerspec_sz);
+PRE_SYSCALL(timer_settime)
+(long timer_id, long flags, const void *new_setting, void *old_setting) {
+ if (new_setting)
+ PRE_READ(new_setting, struct_itimerspec_sz);
}
-POST_SYSCALL(timer_settime)(long res, long timer_id, long flags,
- const void *new_setting, void *old_setting) {
+POST_SYSCALL(timer_settime)
+(long res, long timer_id, long flags, const void *new_setting,
+ void *old_setting) {
if (res >= 0) {
- if (old_setting) POST_WRITE(old_setting, struct_itimerspec_sz);
+ if (old_setting)
+ POST_WRITE(old_setting, struct_itimerspec_sz);
}
}
@@ -481,7 +519,8 @@ PRE_SYSCALL(timer_delete)(long timer_id) {}
POST_SYSCALL(timer_delete)(long res, long timer_id) {}
PRE_SYSCALL(clock_settime)(long which_clock, const void *tp) {
- if (tp) PRE_READ(tp, struct_timespec_sz);
+ if (tp)
+ PRE_READ(tp, struct_timespec_sz);
}
POST_SYSCALL(clock_settime)(long res, long which_clock, const void *tp) {}
@@ -490,37 +529,42 @@ PRE_SYSCALL(clock_gettime)(long which_clock, void *tp) {}
POST_SYSCALL(clock_gettime)(long res, long which_clock, void *tp) {
if (res >= 0) {
- if (tp) POST_WRITE(tp, struct_timespec_sz);
+ if (tp)
+ POST_WRITE(tp, struct_timespec_sz);
}
}
-#if !SANITIZER_ANDROID
+# if !SANITIZER_ANDROID
PRE_SYSCALL(clock_adjtime)(long which_clock, void *tx) {}
POST_SYSCALL(clock_adjtime)(long res, long which_clock, void *tx) {
if (res >= 0) {
- if (tx) POST_WRITE(tx, struct_timex_sz);
+ if (tx)
+ POST_WRITE(tx, struct_timex_sz);
}
}
-#endif
+# endif
PRE_SYSCALL(clock_getres)(long which_clock, void *tp) {}
POST_SYSCALL(clock_getres)(long res, long which_clock, void *tp) {
if (res >= 0) {
- if (tp) POST_WRITE(tp, struct_timespec_sz);
+ if (tp)
+ POST_WRITE(tp, struct_timespec_sz);
}
}
-PRE_SYSCALL(clock_nanosleep)(long which_clock, long flags, const void *rqtp,
- void *rmtp) {
- if (rqtp) PRE_READ(rqtp, struct_timespec_sz);
+PRE_SYSCALL(clock_nanosleep)
+(long which_clock, long flags, const void *rqtp, void *rmtp) {
+ if (rqtp)
+ PRE_READ(rqtp, struct_timespec_sz);
}
-POST_SYSCALL(clock_nanosleep)(long res, long which_clock, long flags,
- const void *rqtp, void *rmtp) {
+POST_SYSCALL(clock_nanosleep)
+(long res, long which_clock, long flags, const void *rqtp, void *rmtp) {
if (res >= 0) {
- if (rmtp) POST_WRITE(rmtp, struct_timespec_sz);
+ if (rmtp)
+ POST_WRITE(rmtp, struct_timespec_sz);
}
}
@@ -532,12 +576,14 @@ PRE_SYSCALL(sched_setscheduler)(long pid, long policy, void *param) {}
POST_SYSCALL(sched_setscheduler)(long res, long pid, long policy, void *param) {
if (res >= 0) {
- if (param) POST_WRITE(param, struct_sched_param_sz);
+ if (param)
+ POST_WRITE(param, struct_sched_param_sz);
}
}
PRE_SYSCALL(sched_setparam)(long pid, void *param) {
- if (param) PRE_READ(param, struct_sched_param_sz);
+ if (param)
+ PRE_READ(param, struct_sched_param_sz);
}
POST_SYSCALL(sched_setparam)(long res, long pid, void *param) {}
@@ -550,23 +596,26 @@ PRE_SYSCALL(sched_getparam)(long pid, void *param) {}
POST_SYSCALL(sched_getparam)(long res, long pid, void *param) {
if (res >= 0) {
- if (param) POST_WRITE(param, struct_sched_param_sz);
+ if (param)
+ POST_WRITE(param, struct_sched_param_sz);
}
}
PRE_SYSCALL(sched_setaffinity)(long pid, long len, void *user_mask_ptr) {
- if (user_mask_ptr) PRE_READ(user_mask_ptr, len);
+ if (user_mask_ptr)
+ PRE_READ(user_mask_ptr, len);
}
-POST_SYSCALL(sched_setaffinity)(long res, long pid, long len,
- void *user_mask_ptr) {}
+POST_SYSCALL(sched_setaffinity)
+(long res, long pid, long len, void *user_mask_ptr) {}
PRE_SYSCALL(sched_getaffinity)(long pid, long len, void *user_mask_ptr) {}
-POST_SYSCALL(sched_getaffinity)(long res, long pid, long len,
- void *user_mask_ptr) {
+POST_SYSCALL(sched_getaffinity)
+(long res, long pid, long len, void *user_mask_ptr) {
if (res >= 0) {
- if (user_mask_ptr) POST_WRITE(user_mask_ptr, len);
+ if (user_mask_ptr)
+ POST_WRITE(user_mask_ptr, len);
}
}
@@ -586,7 +635,8 @@ PRE_SYSCALL(sched_rr_get_interval)(long pid, void *interval) {}
POST_SYSCALL(sched_rr_get_interval)(long res, long pid, void *interval) {
if (res >= 0) {
- if (interval) POST_WRITE(interval, struct_timespec_sz);
+ if (interval)
+ POST_WRITE(interval, struct_timespec_sz);
}
}
@@ -610,13 +660,14 @@ PRE_SYSCALL(restart_syscall)() {}
POST_SYSCALL(restart_syscall)(long res) {}
-PRE_SYSCALL(kexec_load)(long entry, long nr_segments, void *segments,
- long flags) {}
+PRE_SYSCALL(kexec_load)
+(long entry, long nr_segments, void *segments, long flags) {}
-POST_SYSCALL(kexec_load)(long res, long entry, long nr_segments, void *segments,
- long flags) {
+POST_SYSCALL(kexec_load)
+(long res, long entry, long nr_segments, void *segments, long flags) {
if (res >= 0) {
- if (segments) POST_WRITE(segments, struct_kexec_segment_sz);
+ if (segments)
+ POST_WRITE(segments, struct_kexec_segment_sz);
}
}
@@ -630,22 +681,26 @@ POST_SYSCALL(exit_group)(long res, long error_code) {}
PRE_SYSCALL(wait4)(long pid, void *stat_addr, long options, void *ru) {}
-POST_SYSCALL(wait4)(long res, long pid, void *stat_addr, long options,
- void *ru) {
+POST_SYSCALL(wait4)
+(long res, long pid, void *stat_addr, long options, void *ru) {
if (res >= 0) {
- if (stat_addr) POST_WRITE(stat_addr, sizeof(int));
- if (ru) POST_WRITE(ru, struct_rusage_sz);
+ if (stat_addr)
+ POST_WRITE(stat_addr, sizeof(int));
+ if (ru)
+ POST_WRITE(ru, struct_rusage_sz);
}
}
-PRE_SYSCALL(waitid)(long which, long pid, void *infop, long options, void *ru) {
-}
+PRE_SYSCALL(waitid)
+(long which, long pid, void *infop, long options, void *ru) {}
-POST_SYSCALL(waitid)(long res, long which, long pid, void *infop, long options,
- void *ru) {
+POST_SYSCALL(waitid)
+(long res, long which, long pid, void *infop, long options, void *ru) {
if (res >= 0) {
- if (infop) POST_WRITE(infop, siginfo_t_sz);
- if (ru) POST_WRITE(ru, struct_rusage_sz);
+ if (infop)
+ POST_WRITE(infop, siginfo_t_sz);
+ if (ru)
+ POST_WRITE(ru, struct_rusage_sz);
}
}
@@ -653,7 +708,8 @@ PRE_SYSCALL(waitpid)(long pid, void *stat_addr, long options) {}
POST_SYSCALL(waitpid)(long res, long pid, void *stat_addr, long options) {
if (res >= 0) {
- if (stat_addr) POST_WRITE(stat_addr, sizeof(int));
+ if (stat_addr)
+ POST_WRITE(stat_addr, sizeof(int));
}
}
@@ -661,7 +717,8 @@ PRE_SYSCALL(set_tid_address)(void *tidptr) {}
POST_SYSCALL(set_tid_address)(long res, void *tidptr) {
if (res >= 0) {
- if (tidptr) POST_WRITE(tidptr, sizeof(int));
+ if (tidptr)
+ POST_WRITE(tidptr, sizeof(int));
}
}
@@ -682,11 +739,14 @@ POST_SYSCALL(delete_module)(long res, const void *name_user, long flags) {}
PRE_SYSCALL(rt_sigprocmask)(long how, void *set, void *oset, long sigsetsize) {}
-POST_SYSCALL(rt_sigprocmask)(long res, long how, kernel_sigset_t *set,
- kernel_sigset_t *oset, long sigsetsize) {
+POST_SYSCALL(rt_sigprocmask)
+(long res, long how, kernel_sigset_t *set, kernel_sigset_t *oset,
+ long sigsetsize) {
if (res >= 0) {
- if (set) POST_WRITE(set, sigsetsize);
- if (oset) POST_WRITE(oset, sigsetsize);
+ if (set)
+ POST_WRITE(set, sigsetsize);
+ if (oset)
+ POST_WRITE(oset, sigsetsize);
}
}
@@ -694,29 +754,34 @@ PRE_SYSCALL(rt_sigpending)(void *set, long sigsetsize) {}
POST_SYSCALL(rt_sigpending)(long res, kernel_sigset_t *set, long sigsetsize) {
if (res >= 0) {
- if (set) POST_WRITE(set, sigsetsize);
+ if (set)
+ POST_WRITE(set, sigsetsize);
}
}
-PRE_SYSCALL(rt_sigtimedwait)(const kernel_sigset_t *uthese, void *uinfo,
- const void *uts, long sigsetsize) {
- if (uthese) PRE_READ(uthese, sigsetsize);
- if (uts) PRE_READ(uts, struct_timespec_sz);
+PRE_SYSCALL(rt_sigtimedwait)
+(const kernel_sigset_t *uthese, void *uinfo, const void *uts, long sigsetsize) {
+ if (uthese)
+ PRE_READ(uthese, sigsetsize);
+ if (uts)
+ PRE_READ(uts, struct_timespec_sz);
}
-POST_SYSCALL(rt_sigtimedwait)(long res, const void *uthese, void *uinfo,
- const void *uts, long sigsetsize) {
+POST_SYSCALL(rt_sigtimedwait)
+(long res, const void *uthese, void *uinfo, const void *uts, long sigsetsize) {
if (res >= 0) {
- if (uinfo) POST_WRITE(uinfo, siginfo_t_sz);
+ if (uinfo)
+ POST_WRITE(uinfo, siginfo_t_sz);
}
}
PRE_SYSCALL(rt_tgsigqueueinfo)(long tgid, long pid, long sig, void *uinfo) {}
-POST_SYSCALL(rt_tgsigqueueinfo)(long res, long tgid, long pid, long sig,
- void *uinfo) {
+POST_SYSCALL(rt_tgsigqueueinfo)
+(long res, long tgid, long pid, long sig, void *uinfo) {
if (res >= 0) {
- if (uinfo) POST_WRITE(uinfo, siginfo_t_sz);
+ if (uinfo)
+ POST_WRITE(uinfo, siginfo_t_sz);
}
}
@@ -736,7 +801,8 @@ PRE_SYSCALL(rt_sigqueueinfo)(long pid, long sig, void *uinfo) {}
POST_SYSCALL(rt_sigqueueinfo)(long res, long pid, long sig, void *uinfo) {
if (res >= 0) {
- if (uinfo) POST_WRITE(uinfo, siginfo_t_sz);
+ if (uinfo)
+ POST_WRITE(uinfo, siginfo_t_sz);
}
}
@@ -772,11 +838,11 @@ PRE_SYSCALL(bdflush)(long func, long data) {}
POST_SYSCALL(bdflush)(long res, long func, long data) {}
-PRE_SYSCALL(mount)(void *dev_name, void *dir_name, void *type, long flags,
- void *data) {}
+PRE_SYSCALL(mount)
+(void *dev_name, void *dir_name, void *type, long flags, void *data) {}
-POST_SYSCALL(mount)(long res, void *dev_name, void *dir_name, void *type,
- long flags, void *data) {
+POST_SYSCALL(mount)
+(long res, void *dev_name, void *dir_name, void *type, long flags, void *data) {
if (res >= 0) {
if (dev_name)
POST_WRITE(dev_name,
@@ -826,11 +892,12 @@ PRE_SYSCALL(stat)(const void *filename, void *statbuf) {
POST_SYSCALL(stat)(long res, const void *filename, void *statbuf) {
if (res >= 0) {
- if (statbuf) POST_WRITE(statbuf, struct___old_kernel_stat_sz);
+ if (statbuf)
+ POST_WRITE(statbuf, struct___old_kernel_stat_sz);
}
}
-#if !SANITIZER_ANDROID
+# if !SANITIZER_ANDROID
PRE_SYSCALL(statfs)(const void *path, void *buf) {
if (path)
PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
@@ -838,7 +905,8 @@ PRE_SYSCALL(statfs)(const void *path, void *buf) {
POST_SYSCALL(statfs)(long res, const void *path, void *buf) {
if (res >= 0) {
- if (buf) POST_WRITE(buf, struct_statfs_sz);
+ if (buf)
+ POST_WRITE(buf, struct_statfs_sz);
}
}
@@ -849,7 +917,8 @@ PRE_SYSCALL(statfs64)(const void *path, long sz, void *buf) {
POST_SYSCALL(statfs64)(long res, const void *path, long sz, void *buf) {
if (res >= 0) {
- if (buf) POST_WRITE(buf, struct_statfs64_sz);
+ if (buf)
+ POST_WRITE(buf, struct_statfs64_sz);
}
}
@@ -857,7 +926,8 @@ PRE_SYSCALL(fstatfs)(long fd, void *buf) {}
POST_SYSCALL(fstatfs)(long res, long fd, void *buf) {
if (res >= 0) {
- if (buf) POST_WRITE(buf, struct_statfs_sz);
+ if (buf)
+ POST_WRITE(buf, struct_statfs_sz);
}
}
@@ -865,10 +935,11 @@ PRE_SYSCALL(fstatfs64)(long fd, long sz, void *buf) {}
POST_SYSCALL(fstatfs64)(long res, long fd, long sz, void *buf) {
if (res >= 0) {
- if (buf) POST_WRITE(buf, struct_statfs64_sz);
+ if (buf)
+ POST_WRITE(buf, struct_statfs64_sz);
}
}
-#endif // !SANITIZER_ANDROID
+# endif // !SANITIZER_ANDROID
PRE_SYSCALL(lstat)(const void *filename, void *statbuf) {
if (filename)
@@ -878,7 +949,8 @@ PRE_SYSCALL(lstat)(const void *filename, void *statbuf) {
POST_SYSCALL(lstat)(long res, const void *filename, void *statbuf) {
if (res >= 0) {
- if (statbuf) POST_WRITE(statbuf, struct___old_kernel_stat_sz);
+ if (statbuf)
+ POST_WRITE(statbuf, struct___old_kernel_stat_sz);
}
}
@@ -886,7 +958,8 @@ PRE_SYSCALL(fstat)(long fd, void *statbuf) {}
POST_SYSCALL(fstat)(long res, long fd, void *statbuf) {
if (res >= 0) {
- if (statbuf) POST_WRITE(statbuf, struct___old_kernel_stat_sz);
+ if (statbuf)
+ POST_WRITE(statbuf, struct___old_kernel_stat_sz);
}
}
@@ -898,7 +971,8 @@ PRE_SYSCALL(newstat)(const void *filename, void *statbuf) {
POST_SYSCALL(newstat)(long res, const void *filename, void *statbuf) {
if (res >= 0) {
- if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat_sz);
}
}
@@ -910,7 +984,8 @@ PRE_SYSCALL(newlstat)(const void *filename, void *statbuf) {
POST_SYSCALL(newlstat)(long res, const void *filename, void *statbuf) {
if (res >= 0) {
- if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat_sz);
}
}
@@ -918,19 +993,21 @@ PRE_SYSCALL(newfstat)(long fd, void *statbuf) {}
POST_SYSCALL(newfstat)(long res, long fd, void *statbuf) {
if (res >= 0) {
- if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat_sz);
}
}
-#if !SANITIZER_ANDROID
+# if !SANITIZER_ANDROID
PRE_SYSCALL(ustat)(long dev, void *ubuf) {}
POST_SYSCALL(ustat)(long res, long dev, void *ubuf) {
if (res >= 0) {
- if (ubuf) POST_WRITE(ubuf, struct_ustat_sz);
+ if (ubuf)
+ POST_WRITE(ubuf, struct_ustat_sz);
}
}
-#endif // !SANITIZER_ANDROID
+# endif // !SANITIZER_ANDROID
PRE_SYSCALL(stat64)(const void *filename, void *statbuf) {
if (filename)
@@ -940,7 +1017,8 @@ PRE_SYSCALL(stat64)(const void *filename, void *statbuf) {
POST_SYSCALL(stat64)(long res, const void *filename, void *statbuf) {
if (res >= 0) {
- if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat64_sz);
}
}
@@ -948,7 +1026,8 @@ PRE_SYSCALL(fstat64)(long fd, void *statbuf) {}
POST_SYSCALL(fstat64)(long res, long fd, void *statbuf) {
if (res >= 0) {
- if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat64_sz);
}
}
@@ -960,71 +1039,80 @@ PRE_SYSCALL(lstat64)(const void *filename, void *statbuf) {
POST_SYSCALL(lstat64)(long res, const void *filename, void *statbuf) {
if (res >= 0) {
- if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat64_sz);
}
}
-PRE_SYSCALL(setxattr)(const void *path, const void *name, const void *value,
- long size, long flags) {
+PRE_SYSCALL(setxattr)
+(const void *path, const void *name, const void *value, long size, long flags) {
if (path)
PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
if (name)
PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
- if (value) PRE_READ(value, size);
+ if (value)
+ PRE_READ(value, size);
}
-POST_SYSCALL(setxattr)(long res, const void *path, const void *name,
- const void *value, long size, long flags) {}
+POST_SYSCALL(setxattr)
+(long res, const void *path, const void *name, const void *value, long size,
+ long flags) {}
-PRE_SYSCALL(lsetxattr)(const void *path, const void *name, const void *value,
- long size, long flags) {
+PRE_SYSCALL(lsetxattr)
+(const void *path, const void *name, const void *value, long size, long flags) {
if (path)
PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
if (name)
PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
- if (value) PRE_READ(value, size);
+ if (value)
+ PRE_READ(value, size);
}
-POST_SYSCALL(lsetxattr)(long res, const void *path, const void *name,
- const void *value, long size, long flags) {}
+POST_SYSCALL(lsetxattr)
+(long res, const void *path, const void *name, const void *value, long size,
+ long flags) {}
-PRE_SYSCALL(fsetxattr)(long fd, const void *name, const void *value, long size,
- long flags) {
+PRE_SYSCALL(fsetxattr)
+(long fd, const void *name, const void *value, long size, long flags) {
if (name)
PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
- if (value) PRE_READ(value, size);
+ if (value)
+ PRE_READ(value, size);
}
-POST_SYSCALL(fsetxattr)(long res, long fd, const void *name, const void *value,
- long size, long flags) {}
+POST_SYSCALL(fsetxattr)
+(long res, long fd, const void *name, const void *value, long size,
+ long flags) {}
-PRE_SYSCALL(getxattr)(const void *path, const void *name, void *value,
- long size) {
+PRE_SYSCALL(getxattr)
+(const void *path, const void *name, void *value, long size) {
if (path)
PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
if (name)
PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
}
-POST_SYSCALL(getxattr)(long res, const void *path, const void *name,
- void *value, long size) {
+POST_SYSCALL(getxattr)
+(long res, const void *path, const void *name, void *value, long size) {
if (size && res > 0) {
- if (value) POST_WRITE(value, res);
+ if (value)
+ POST_WRITE(value, res);
}
}
-PRE_SYSCALL(lgetxattr)(const void *path, const void *name, void *value,
- long size) {
+PRE_SYSCALL(lgetxattr)
+(const void *path, const void *name, void *value, long size) {
if (path)
PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
if (name)
PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
}
-POST_SYSCALL(lgetxattr)(long res, const void *path, const void *name,
- void *value, long size) {
+POST_SYSCALL(lgetxattr)
+(long res, const void *path, const void *name, void *value, long size) {
if (size && res > 0) {
- if (value) POST_WRITE(value, res);
+ if (value)
+ POST_WRITE(value, res);
}
}
@@ -1033,10 +1121,11 @@ PRE_SYSCALL(fgetxattr)(long fd, const void *name, void *value, long size) {
PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
}
-POST_SYSCALL(fgetxattr)(long res, long fd, const void *name, void *value,
- long size) {
+POST_SYSCALL(fgetxattr)
+(long res, long fd, const void *name, void *value, long size) {
if (size && res > 0) {
- if (value) POST_WRITE(value, res);
+ if (value)
+ POST_WRITE(value, res);
}
}
@@ -1047,7 +1136,8 @@ PRE_SYSCALL(listxattr)(const void *path, void *list, long size) {
POST_SYSCALL(listxattr)(long res, const void *path, void *list, long size) {
if (size && res > 0) {
- if (list) POST_WRITE(list, res);
+ if (list)
+ POST_WRITE(list, res);
}
}
@@ -1058,7 +1148,8 @@ PRE_SYSCALL(llistxattr)(const void *path, void *list, long size) {
POST_SYSCALL(llistxattr)(long res, const void *path, void *list, long size) {
if (size && res > 0) {
- if (list) POST_WRITE(list, res);
+ if (list)
+ POST_WRITE(list, res);
}
}
@@ -1066,7 +1157,8 @@ PRE_SYSCALL(flistxattr)(long fd, void *list, long size) {}
POST_SYSCALL(flistxattr)(long res, long fd, void *list, long size) {
if (size && res > 0) {
- if (list) POST_WRITE(list, res);
+ if (list)
+ POST_WRITE(list, res);
}
}
@@ -1103,17 +1195,17 @@ PRE_SYSCALL(mprotect)(long start, long len, long prot) {}
POST_SYSCALL(mprotect)(long res, long start, long len, long prot) {}
-PRE_SYSCALL(mremap)(long addr, long old_len, long new_len, long flags,
- long new_addr) {}
+PRE_SYSCALL(mremap)
+(long addr, long old_len, long new_len, long flags, long new_addr) {}
-POST_SYSCALL(mremap)(long res, long addr, long old_len, long new_len,
- long flags, long new_addr) {}
+POST_SYSCALL(mremap)
+(long res, long addr, long old_len, long new_len, long flags, long new_addr) {}
-PRE_SYSCALL(remap_file_pages)(long start, long size, long prot, long pgoff,
- long flags) {}
+PRE_SYSCALL(remap_file_pages)
+(long start, long size, long prot, long pgoff, long flags) {}
-POST_SYSCALL(remap_file_pages)(long res, long start, long size, long prot,
- long pgoff, long flags) {}
+POST_SYSCALL(remap_file_pages)
+(long res, long start, long size, long prot, long pgoff, long flags) {}
PRE_SYSCALL(msync)(long start, long len, long flags) {}
@@ -1189,7 +1281,8 @@ PRE_SYSCALL(link)(const void *oldname, const void *newname) {
POST_SYSCALL(link)(long res, const void *oldname, const void *newname) {}
PRE_SYSCALL(symlink)(const void *old, const void *new_) {
- if (old) PRE_READ(old, __sanitizer::internal_strlen((const char *)old) + 1);
+ if (old)
+ PRE_READ(old, __sanitizer::internal_strlen((const char *)old) + 1);
if (new_)
PRE_READ(new_, __sanitizer::internal_strlen((const char *)new_) + 1);
}
@@ -1237,14 +1330,16 @@ PRE_SYSCALL(pipe)(void *fildes) {}
POST_SYSCALL(pipe)(long res, void *fildes) {
if (res >= 0)
- if (fildes) POST_WRITE(fildes, sizeof(int) * 2);
+ if (fildes)
+ POST_WRITE(fildes, sizeof(int) * 2);
}
PRE_SYSCALL(pipe2)(void *fildes, long flags) {}
POST_SYSCALL(pipe2)(long res, void *fildes, long flags) {
if (res >= 0)
- if (fildes) POST_WRITE(fildes, sizeof(int) * 2);
+ if (fildes)
+ POST_WRITE(fildes, sizeof(int) * 2);
}
PRE_SYSCALL(dup)(long fildes) {}
@@ -1272,16 +1367,19 @@ PRE_SYSCALL(flock)(long fd, long cmd) {}
POST_SYSCALL(flock)(long res, long fd, long cmd) {}
PRE_SYSCALL(io_setup)(long nr_reqs, void **ctx) {
- if (ctx) PRE_WRITE(ctx, sizeof(*ctx));
+ if (ctx)
+ PRE_WRITE(ctx, sizeof(*ctx));
}
POST_SYSCALL(io_setup)(long res, long nr_reqs, void **ctx) {
if (res >= 0) {
- if (ctx) POST_WRITE(ctx, sizeof(*ctx));
+ if (ctx)
+ POST_WRITE(ctx, sizeof(*ctx));
// (*ctx) is actually a pointer to a kernel mapped page, and there are
// people out there who are crazy enough to peek into that page's 32-byte
// header.
- if (*ctx) POST_WRITE(*ctx, 32);
+ if (*ctx)
+ POST_WRITE(*ctx, 32);
}
}
@@ -1289,16 +1387,21 @@ PRE_SYSCALL(io_destroy)(long ctx) {}
POST_SYSCALL(io_destroy)(long res, long ctx) {}
-PRE_SYSCALL(io_getevents)(long ctx_id, long min_nr, long nr,
- __sanitizer_io_event *ioevpp, void *timeout) {
- if (timeout) PRE_READ(timeout, struct_timespec_sz);
+PRE_SYSCALL(io_getevents)
+(long ctx_id, long min_nr, long nr, __sanitizer_io_event *ioevpp,
+ void *timeout) {
+ if (timeout)
+ PRE_READ(timeout, struct_timespec_sz);
}
-POST_SYSCALL(io_getevents)(long res, long ctx_id, long min_nr, long nr,
- __sanitizer_io_event *ioevpp, void *timeout) {
+POST_SYSCALL(io_getevents)
+(long res, long ctx_id, long min_nr, long nr, __sanitizer_io_event *ioevpp,
+ void *timeout) {
if (res >= 0) {
- if (ioevpp) POST_WRITE(ioevpp, res * sizeof(*ioevpp));
- if (timeout) POST_WRITE(timeout, struct_timespec_sz);
+ if (ioevpp)
+ POST_WRITE(ioevpp, res * sizeof(*ioevpp));
+ if (timeout)
+ POST_WRITE(timeout, struct_timespec_sz);
}
for (long i = 0; i < res; i++) {
// We synchronize io_submit -> io_getevents/io_cancel using the
@@ -1308,26 +1411,26 @@ POST_SYSCALL(io_getevents)(long res, long ctx_id, long min_nr, long nr,
// synchronize on 0. But there does not seem to be a better solution
// (except wrapping all operations in own context, which is unreliable).
// We can not reliably extract fildes in io_getevents.
- COMMON_SYSCALL_ACQUIRE((void*)ioevpp[i].data);
+ COMMON_SYSCALL_ACQUIRE((void *)ioevpp[i].data);
}
}
PRE_SYSCALL(io_submit)(long ctx_id, long nr, __sanitizer_iocb **iocbpp) {
for (long i = 0; i < nr; ++i) {
uptr op = iocbpp[i]->aio_lio_opcode;
- void *data = (void*)iocbpp[i]->aio_data;
- void *buf = (void*)iocbpp[i]->aio_buf;
+ void *data = (void *)iocbpp[i]->aio_data;
+ void *buf = (void *)iocbpp[i]->aio_buf;
uptr len = (uptr)iocbpp[i]->aio_nbytes;
if (op == iocb_cmd_pwrite && buf && len) {
PRE_READ(buf, len);
} else if (op == iocb_cmd_pread && buf && len) {
POST_WRITE(buf, len);
} else if (op == iocb_cmd_pwritev) {
- __sanitizer_iovec *iovec = (__sanitizer_iovec*)buf;
+ __sanitizer_iovec *iovec = (__sanitizer_iovec *)buf;
for (uptr v = 0; v < len; v++)
PRE_READ(iovec[v].iov_base, iovec[v].iov_len);
} else if (op == iocb_cmd_preadv) {
- __sanitizer_iovec *iovec = (__sanitizer_iovec*)buf;
+ __sanitizer_iovec *iovec = (__sanitizer_iovec *)buf;
for (uptr v = 0; v < len; v++)
POST_WRITE(iovec[v].iov_base, iovec[v].iov_len);
}
@@ -1336,19 +1439,18 @@ PRE_SYSCALL(io_submit)(long ctx_id, long nr, __sanitizer_iocb **iocbpp) {
}
}
-POST_SYSCALL(io_submit)(long res, long ctx_id, long nr,
- __sanitizer_iocb **iocbpp) {}
+POST_SYSCALL(io_submit)
+(long res, long ctx_id, long nr, __sanitizer_iocb **iocbpp) {}
-PRE_SYSCALL(io_cancel)(long ctx_id, __sanitizer_iocb *iocb,
- __sanitizer_io_event *result) {
-}
+PRE_SYSCALL(io_cancel)
+(long ctx_id, __sanitizer_iocb *iocb, __sanitizer_io_event *result) {}
-POST_SYSCALL(io_cancel)(long res, long ctx_id, __sanitizer_iocb *iocb,
- __sanitizer_io_event *result) {
+POST_SYSCALL(io_cancel)
+(long res, long ctx_id, __sanitizer_iocb *iocb, __sanitizer_io_event *result) {
if (res == 0) {
if (result) {
// See comment in io_getevents.
- COMMON_SYSCALL_ACQUIRE((void*)result->data);
+ COMMON_SYSCALL_ACQUIRE((void *)result->data);
POST_WRITE(result, sizeof(*result));
}
if (iocb)
@@ -1358,19 +1460,23 @@ POST_SYSCALL(io_cancel)(long res, long ctx_id, __sanitizer_iocb *iocb,
PRE_SYSCALL(sendfile)(long out_fd, long in_fd, void *offset, long count) {}
-POST_SYSCALL(sendfile)(long res, long out_fd, long in_fd,
- __sanitizer___kernel_off_t *offset, long count) {
+POST_SYSCALL(sendfile)
+(long res, long out_fd, long in_fd, __sanitizer___kernel_off_t *offset,
+ long count) {
if (res >= 0) {
- if (offset) POST_WRITE(offset, sizeof(*offset));
+ if (offset)
+ POST_WRITE(offset, sizeof(*offset));
}
}
PRE_SYSCALL(sendfile64)(long out_fd, long in_fd, void *offset, long count) {}
-POST_SYSCALL(sendfile64)(long res, long out_fd, long in_fd,
- __sanitizer___kernel_loff_t *offset, long count) {
+POST_SYSCALL(sendfile64)
+(long res, long out_fd, long in_fd, __sanitizer___kernel_loff_t *offset,
+ long count) {
if (res >= 0) {
- if (offset) POST_WRITE(offset, sizeof(*offset));
+ if (offset)
+ POST_WRITE(offset, sizeof(*offset));
}
}
@@ -1402,9 +1508,7 @@ PRE_SYSCALL(open)(const void *filename, long flags, long mode) {
POST_SYSCALL(open)(long res, const void *filename, long flags, long mode) {}
-PRE_SYSCALL(close)(long fd) {
- COMMON_SYSCALL_FD_CLOSE((int)fd);
-}
+PRE_SYSCALL(close)(long fd) { COMMON_SYSCALL_FD_CLOSE((int)fd); }
POST_SYSCALL(close)(long res, long fd) {}
@@ -1440,7 +1544,7 @@ PRE_SYSCALL(fchown)(long fd, long user, long group) {}
POST_SYSCALL(fchown)(long res, long fd, long user, long group) {}
-#if SANITIZER_USES_UID16_SYSCALLS
+# if SANITIZER_USES_UID16_SYSCALLS
PRE_SYSCALL(chown16)(const void *filename, long user, long group) {
if (filename)
PRE_READ(filename,
@@ -1483,13 +1587,16 @@ POST_SYSCALL(setresuid16)(long res, long ruid, long euid, long suid) {}
PRE_SYSCALL(getresuid16)(void *ruid, void *euid, void *suid) {}
-POST_SYSCALL(getresuid16)(long res, __sanitizer___kernel_old_uid_t *ruid,
- __sanitizer___kernel_old_uid_t *euid,
- __sanitizer___kernel_old_uid_t *suid) {
+POST_SYSCALL(getresuid16)
+(long res, __sanitizer___kernel_old_uid_t *ruid,
+ __sanitizer___kernel_old_uid_t *euid, __sanitizer___kernel_old_uid_t *suid) {
if (res >= 0) {
- if (ruid) POST_WRITE(ruid, sizeof(*ruid));
- if (euid) POST_WRITE(euid, sizeof(*euid));
- if (suid) POST_WRITE(suid, sizeof(*suid));
+ if (ruid)
+ POST_WRITE(ruid, sizeof(*ruid));
+ if (euid)
+ POST_WRITE(euid, sizeof(*euid));
+ if (suid)
+ POST_WRITE(suid, sizeof(*suid));
}
}
@@ -1499,13 +1606,16 @@ POST_SYSCALL(setresgid16)(long res, long rgid, long egid, long sgid) {}
PRE_SYSCALL(getresgid16)(void *rgid, void *egid, void *sgid) {}
-POST_SYSCALL(getresgid16)(long res, __sanitizer___kernel_old_gid_t *rgid,
- __sanitizer___kernel_old_gid_t *egid,
- __sanitizer___kernel_old_gid_t *sgid) {
+POST_SYSCALL(getresgid16)
+(long res, __sanitizer___kernel_old_gid_t *rgid,
+ __sanitizer___kernel_old_gid_t *egid, __sanitizer___kernel_old_gid_t *sgid) {
if (res >= 0) {
- if (rgid) POST_WRITE(rgid, sizeof(*rgid));
- if (egid) POST_WRITE(egid, sizeof(*egid));
- if (sgid) POST_WRITE(sgid, sizeof(*sgid));
+ if (rgid)
+ POST_WRITE(rgid, sizeof(*rgid));
+ if (egid)
+ POST_WRITE(egid, sizeof(*egid));
+ if (sgid)
+ POST_WRITE(sgid, sizeof(*sgid));
}
}
@@ -1517,23 +1627,25 @@ PRE_SYSCALL(setfsgid16)(long gid) {}
POST_SYSCALL(setfsgid16)(long res, long gid) {}
-PRE_SYSCALL(getgroups16)(long gidsetsize,
- __sanitizer___kernel_old_gid_t *grouplist) {}
+PRE_SYSCALL(getgroups16)
+(long gidsetsize, __sanitizer___kernel_old_gid_t *grouplist) {}
-POST_SYSCALL(getgroups16)(long res, long gidsetsize,
- __sanitizer___kernel_old_gid_t *grouplist) {
+POST_SYSCALL(getgroups16)
+(long res, long gidsetsize, __sanitizer___kernel_old_gid_t *grouplist) {
if (res >= 0) {
- if (grouplist) POST_WRITE(grouplist, res * sizeof(*grouplist));
+ if (grouplist)
+ POST_WRITE(grouplist, res * sizeof(*grouplist));
}
}
-PRE_SYSCALL(setgroups16)(long gidsetsize,
- __sanitizer___kernel_old_gid_t *grouplist) {
- if (grouplist) POST_WRITE(grouplist, gidsetsize * sizeof(*grouplist));
+PRE_SYSCALL(setgroups16)
+(long gidsetsize, __sanitizer___kernel_old_gid_t *grouplist) {
+ if (grouplist)
+ POST_WRITE(grouplist, gidsetsize * sizeof(*grouplist));
}
-POST_SYSCALL(setgroups16)(long res, long gidsetsize,
- __sanitizer___kernel_old_gid_t *grouplist) {}
+POST_SYSCALL(setgroups16)
+(long res, long gidsetsize, __sanitizer___kernel_old_gid_t *grouplist) {}
PRE_SYSCALL(getuid16)() {}
@@ -1550,7 +1662,7 @@ POST_SYSCALL(getgid16)(long res) {}
PRE_SYSCALL(getegid16)() {}
POST_SYSCALL(getegid16)(long res) {}
-#endif // SANITIZER_USES_UID16_SYSCALLS
+# endif // SANITIZER_USES_UID16_SYSCALLS
PRE_SYSCALL(utime)(void *filename, void *times) {}
@@ -1559,7 +1671,8 @@ POST_SYSCALL(utime)(long res, void *filename, void *times) {
if (filename)
POST_WRITE(filename,
__sanitizer::internal_strlen((const char *)filename) + 1);
- if (times) POST_WRITE(times, struct_utimbuf_sz);
+ if (times)
+ POST_WRITE(times, struct_utimbuf_sz);
}
}
@@ -1570,7 +1683,8 @@ POST_SYSCALL(utimes)(long res, void *filename, void *utimes) {
if (filename)
POST_WRITE(filename,
__sanitizer::internal_strlen((const char *)filename) + 1);
- if (utimes) POST_WRITE(utimes, timeval_sz);
+ if (utimes)
+ POST_WRITE(utimes, timeval_sz);
}
}
@@ -1578,91 +1692,104 @@ PRE_SYSCALL(lseek)(long fd, long offset, long origin) {}
POST_SYSCALL(lseek)(long res, long fd, long offset, long origin) {}
-PRE_SYSCALL(llseek)(long fd, long offset_high, long offset_low, void *result,
- long origin) {}
+PRE_SYSCALL(llseek)
+(long fd, long offset_high, long offset_low, void *result, long origin) {}
-POST_SYSCALL(llseek)(long res, long fd, long offset_high, long offset_low,
- void *result, long origin) {
+POST_SYSCALL(llseek)
+(long res, long fd, long offset_high, long offset_low, void *result,
+ long origin) {
if (res >= 0) {
- if (result) POST_WRITE(result, sizeof(long long));
+ if (result)
+ POST_WRITE(result, sizeof(long long));
}
}
PRE_SYSCALL(readv)(long fd, const __sanitizer_iovec *vec, long vlen) {}
-POST_SYSCALL(readv)(long res, long fd, const __sanitizer_iovec *vec,
- long vlen) {
+POST_SYSCALL(readv)
+(long res, long fd, const __sanitizer_iovec *vec, long vlen) {
if (res >= 0) {
- if (vec) kernel_write_iovec(vec, vlen, res);
+ if (vec)
+ kernel_write_iovec(vec, vlen, res);
}
}
PRE_SYSCALL(write)(long fd, const void *buf, long count) {
- if (buf) PRE_READ(buf, count);
+ if (buf)
+ PRE_READ(buf, count);
}
POST_SYSCALL(write)(long res, long fd, const void *buf, long count) {}
PRE_SYSCALL(writev)(long fd, const __sanitizer_iovec *vec, long vlen) {}
-POST_SYSCALL(writev)(long res, long fd, const __sanitizer_iovec *vec,
- long vlen) {
+POST_SYSCALL(writev)
+(long res, long fd, const __sanitizer_iovec *vec, long vlen) {
if (res >= 0) {
- if (vec) kernel_read_iovec(vec, vlen, res);
+ if (vec)
+ kernel_read_iovec(vec, vlen, res);
}
}
-#ifdef _LP64
+# ifdef _LP64
PRE_SYSCALL(pread64)(long fd, void *buf, long count, long pos) {}
POST_SYSCALL(pread64)(long res, long fd, void *buf, long count, long pos) {
if (res >= 0) {
- if (buf) POST_WRITE(buf, res);
+ if (buf)
+ POST_WRITE(buf, res);
}
}
PRE_SYSCALL(pwrite64)(long fd, const void *buf, long count, long pos) {
- if (buf) PRE_READ(buf, count);
+ if (buf)
+ PRE_READ(buf, count);
}
-POST_SYSCALL(pwrite64)(long res, long fd, const void *buf, long count,
- long pos) {}
-#else
+POST_SYSCALL(pwrite64)
+(long res, long fd, const void *buf, long count, long pos) {}
+# else
PRE_SYSCALL(pread64)(long fd, void *buf, long count, long pos0, long pos1) {}
-POST_SYSCALL(pread64)(long res, long fd, void *buf, long count, long pos0,
- long pos1) {
+POST_SYSCALL(pread64)
+(long res, long fd, void *buf, long count, long pos0, long pos1) {
if (res >= 0) {
- if (buf) POST_WRITE(buf, res);
+ if (buf)
+ POST_WRITE(buf, res);
}
}
-PRE_SYSCALL(pwrite64)(long fd, const void *buf, long count, long pos0,
- long pos1) {
- if (buf) PRE_READ(buf, count);
+PRE_SYSCALL(pwrite64)
+(long fd, const void *buf, long count, long pos0, long pos1) {
+ if (buf)
+ PRE_READ(buf, count);
}
-POST_SYSCALL(pwrite64)(long res, long fd, const void *buf, long count,
- long pos0, long pos1) {}
-#endif
+POST_SYSCALL(pwrite64)
+(long res, long fd, const void *buf, long count, long pos0, long pos1) {}
+# endif
-PRE_SYSCALL(preadv)(long fd, const __sanitizer_iovec *vec, long vlen,
- long pos_l, long pos_h) {}
+PRE_SYSCALL(preadv)
+(long fd, const __sanitizer_iovec *vec, long vlen, long pos_l, long pos_h) {}
-POST_SYSCALL(preadv)(long res, long fd, const __sanitizer_iovec *vec, long vlen,
- long pos_l, long pos_h) {
+POST_SYSCALL(preadv)
+(long res, long fd, const __sanitizer_iovec *vec, long vlen, long pos_l,
+ long pos_h) {
if (res >= 0) {
- if (vec) kernel_write_iovec(vec, vlen, res);
+ if (vec)
+ kernel_write_iovec(vec, vlen, res);
}
}
-PRE_SYSCALL(pwritev)(long fd, const __sanitizer_iovec *vec, long vlen,
- long pos_l, long pos_h) {}
+PRE_SYSCALL(pwritev)
+(long fd, const __sanitizer_iovec *vec, long vlen, long pos_l, long pos_h) {}
-POST_SYSCALL(pwritev)(long res, long fd, const __sanitizer_iovec *vec,
- long vlen, long pos_l, long pos_h) {
+POST_SYSCALL(pwritev)
+(long res, long fd, const __sanitizer_iovec *vec, long vlen, long pos_l,
+ long pos_h) {
if (res >= 0) {
- if (vec) kernel_read_iovec(vec, vlen, res);
+ if (vec)
+ kernel_read_iovec(vec, vlen, res);
}
}
@@ -1717,14 +1844,15 @@ PRE_SYSCALL(quotactl)(long cmd, const void *special, long id, void *addr) {
PRE_READ(special, __sanitizer::internal_strlen((const char *)special) + 1);
}
-POST_SYSCALL(quotactl)(long res, long cmd, const void *special, long id,
- void *addr) {}
+POST_SYSCALL(quotactl)
+(long res, long cmd, const void *special, long id, void *addr) {}
PRE_SYSCALL(getdents)(long fd, void *dirent, long count) {}
POST_SYSCALL(getdents)(long res, long fd, void *dirent, long count) {
if (res >= 0) {
- if (dirent) POST_WRITE(dirent, res);
+ if (dirent)
+ POST_WRITE(dirent, res);
}
}
@@ -1732,15 +1860,16 @@ PRE_SYSCALL(getdents64)(long fd, void *dirent, long count) {}
POST_SYSCALL(getdents64)(long res, long fd, void *dirent, long count) {
if (res >= 0) {
- if (dirent) POST_WRITE(dirent, res);
+ if (dirent)
+ POST_WRITE(dirent, res);
}
}
-PRE_SYSCALL(setsockopt)(long fd, long level, long optname, void *optval,
- long optlen) {}
+PRE_SYSCALL(setsockopt)
+(long fd, long level, long optname, void *optval, long optlen) {}
-POST_SYSCALL(setsockopt)(long res, long fd, long level, long optname,
- void *optval, long optlen) {
+POST_SYSCALL(setsockopt)
+(long res, long fd, long level, long optname, void *optval, long optlen) {
if (res >= 0) {
if (optval)
POST_WRITE(optval,
@@ -1748,77 +1877,88 @@ POST_SYSCALL(setsockopt)(long res, long fd, long level, long optname,
}
}
-PRE_SYSCALL(getsockopt)(long fd, long level, long optname, void *optval,
- void *optlen) {}
+PRE_SYSCALL(getsockopt)
+(long fd, long level, long optname, void *optval, void *optlen) {}
-POST_SYSCALL(getsockopt)(long res, long fd, long level, long optname,
- void *optval, void *optlen) {
+POST_SYSCALL(getsockopt)
+(long res, long fd, long level, long optname, void *optval, void *optlen) {
if (res >= 0) {
if (optval)
POST_WRITE(optval,
__sanitizer::internal_strlen((const char *)optval) + 1);
- if (optlen) POST_WRITE(optlen, sizeof(int));
+ if (optlen)
+ POST_WRITE(optlen, sizeof(int));
}
}
PRE_SYSCALL(bind)(long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {}
-POST_SYSCALL(bind)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
- long arg2) {
+POST_SYSCALL(bind)
+(long res, long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {
if (res >= 0) {
- if (arg1) POST_WRITE(arg1, sizeof(*arg1));
+ if (arg1)
+ POST_WRITE(arg1, sizeof(*arg1));
}
}
PRE_SYSCALL(connect)(long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {}
-POST_SYSCALL(connect)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
- long arg2) {
+POST_SYSCALL(connect)
+(long res, long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {
if (res >= 0) {
- if (arg1) POST_WRITE(arg1, sizeof(*arg1));
+ if (arg1)
+ POST_WRITE(arg1, sizeof(*arg1));
}
}
PRE_SYSCALL(accept)(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {}
-POST_SYSCALL(accept)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
- void *arg2) {
+POST_SYSCALL(accept)
+(long res, long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {
if (res >= 0) {
- if (arg1) POST_WRITE(arg1, sizeof(*arg1));
- if (arg2) POST_WRITE(arg2, sizeof(unsigned));
+ if (arg1)
+ POST_WRITE(arg1, sizeof(*arg1));
+ if (arg2)
+ POST_WRITE(arg2, sizeof(unsigned));
}
}
-PRE_SYSCALL(accept4)(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2,
- long arg3) {}
+PRE_SYSCALL(accept4)
+(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2, long arg3) {}
-POST_SYSCALL(accept4)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
- void *arg2, long arg3) {
+POST_SYSCALL(accept4)
+(long res, long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2, long arg3) {
if (res >= 0) {
- if (arg1) POST_WRITE(arg1, sizeof(*arg1));
- if (arg2) POST_WRITE(arg2, sizeof(unsigned));
+ if (arg1)
+ POST_WRITE(arg1, sizeof(*arg1));
+ if (arg2)
+ POST_WRITE(arg2, sizeof(unsigned));
}
}
-PRE_SYSCALL(getsockname)(long arg0, sanitizer_kernel_sockaddr *arg1,
- void *arg2) {}
+PRE_SYSCALL(getsockname)
+(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {}
-POST_SYSCALL(getsockname)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
- void *arg2) {
+POST_SYSCALL(getsockname)
+(long res, long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {
if (res >= 0) {
- if (arg1) POST_WRITE(arg1, sizeof(*arg1));
- if (arg2) POST_WRITE(arg2, sizeof(unsigned));
+ if (arg1)
+ POST_WRITE(arg1, sizeof(*arg1));
+ if (arg2)
+ POST_WRITE(arg2, sizeof(unsigned));
}
}
-PRE_SYSCALL(getpeername)(long arg0, sanitizer_kernel_sockaddr *arg1,
- void *arg2) {}
+PRE_SYSCALL(getpeername)
+(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {}
-POST_SYSCALL(getpeername)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
- void *arg2) {
+POST_SYSCALL(getpeername)
+(long res, long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {
if (res >= 0) {
- if (arg1) POST_WRITE(arg1, sizeof(*arg1));
- if (arg2) POST_WRITE(arg2, sizeof(unsigned));
+ if (arg1)
+ POST_WRITE(arg1, sizeof(*arg1));
+ if (arg2)
+ POST_WRITE(arg2, sizeof(unsigned));
}
}
@@ -1826,18 +1966,23 @@ PRE_SYSCALL(send)(long arg0, void *arg1, long arg2, long arg3) {}
POST_SYSCALL(send)(long res, long arg0, void *arg1, long arg2, long arg3) {
if (res) {
- if (arg1) POST_READ(arg1, res);
+ if (arg1)
+ POST_READ(arg1, res);
}
}
-PRE_SYSCALL(sendto)(long arg0, void *arg1, long arg2, long arg3,
- sanitizer_kernel_sockaddr *arg4, long arg5) {}
+PRE_SYSCALL(sendto)
+(long arg0, void *arg1, long arg2, long arg3, sanitizer_kernel_sockaddr *arg4,
+ long arg5) {}
-POST_SYSCALL(sendto)(long res, long arg0, void *arg1, long arg2, long arg3,
- sanitizer_kernel_sockaddr *arg4, long arg5) {
+POST_SYSCALL(sendto)
+(long res, long arg0, void *arg1, long arg2, long arg3,
+ sanitizer_kernel_sockaddr *arg4, long arg5) {
if (res >= 0) {
- if (arg1) POST_READ(arg1, res);
- if (arg4) POST_WRITE(arg4, sizeof(*arg4));
+ if (arg1)
+ POST_READ(arg1, res);
+ if (arg4)
+ POST_WRITE(arg4, sizeof(*arg4));
}
}
@@ -1857,19 +2002,25 @@ PRE_SYSCALL(recv)(long arg0, void *buf, long len, long flags) {}
POST_SYSCALL(recv)(long res, void *buf, long len, long flags) {
if (res >= 0) {
- if (buf) POST_WRITE(buf, res);
+ if (buf)
+ POST_WRITE(buf, res);
}
}
-PRE_SYSCALL(recvfrom)(long arg0, void *buf, long len, long flags,
- sanitizer_kernel_sockaddr *arg4, void *arg5) {}
+PRE_SYSCALL(recvfrom)
+(long arg0, void *buf, long len, long flags, sanitizer_kernel_sockaddr *arg4,
+ void *arg5) {}
-POST_SYSCALL(recvfrom)(long res, long arg0, void *buf, long len, long flags,
- sanitizer_kernel_sockaddr *arg4, void *arg5) {
+POST_SYSCALL(recvfrom)
+(long res, long arg0, void *buf, long len, long flags,
+ sanitizer_kernel_sockaddr *arg4, void *arg5) {
if (res >= 0) {
- if (buf) POST_WRITE(buf, res);
- if (arg4) POST_WRITE(arg4, sizeof(*arg4));
- if (arg5) POST_WRITE(arg5, sizeof(int));
+ if (buf)
+ POST_WRITE(buf, res);
+ if (arg4)
+ POST_WRITE(arg4, sizeof(*arg4));
+ if (arg5)
+ POST_WRITE(arg5, sizeof(int));
}
}
@@ -1881,14 +2032,16 @@ PRE_SYSCALL(socketpair)(long arg0, long arg1, long arg2, int *sv) {}
POST_SYSCALL(socketpair)(long res, long arg0, long arg1, long arg2, int *sv) {
if (res >= 0)
- if (sv) POST_WRITE(sv, sizeof(int) * 2);
+ if (sv)
+ POST_WRITE(sv, sizeof(int) * 2);
}
PRE_SYSCALL(socketcall)(long call, void *args) {}
POST_SYSCALL(socketcall)(long res, long call, void *args) {
if (res >= 0) {
- if (args) POST_WRITE(args, sizeof(long));
+ if (args)
+ POST_WRITE(args, sizeof(long));
}
}
@@ -1898,25 +2051,31 @@ POST_SYSCALL(listen)(long res, long arg0, long arg1) {}
PRE_SYSCALL(poll)(void *ufds, long nfds, long timeout) {}
-POST_SYSCALL(poll)(long res, __sanitizer_pollfd *ufds, long nfds,
- long timeout) {
+POST_SYSCALL(poll)
+(long res, __sanitizer_pollfd *ufds, long nfds, long timeout) {
if (res >= 0) {
- if (ufds) POST_WRITE(ufds, nfds * sizeof(*ufds));
+ if (ufds)
+ POST_WRITE(ufds, nfds * sizeof(*ufds));
}
}
-PRE_SYSCALL(select)(long n, __sanitizer___kernel_fd_set *inp,
- __sanitizer___kernel_fd_set *outp,
- __sanitizer___kernel_fd_set *exp, void *tvp) {}
+PRE_SYSCALL(select)
+(long n, __sanitizer___kernel_fd_set *inp, __sanitizer___kernel_fd_set *outp,
+ __sanitizer___kernel_fd_set *exp, void *tvp) {}
-POST_SYSCALL(select)(long res, long n, __sanitizer___kernel_fd_set *inp,
- __sanitizer___kernel_fd_set *outp,
- __sanitizer___kernel_fd_set *exp, void *tvp) {
+POST_SYSCALL(select)
+(long res, long n, __sanitizer___kernel_fd_set *inp,
+ __sanitizer___kernel_fd_set *outp, __sanitizer___kernel_fd_set *exp,
+ void *tvp) {
if (res >= 0) {
- if (inp) POST_WRITE(inp, sizeof(*inp));
- if (outp) POST_WRITE(outp, sizeof(*outp));
- if (exp) POST_WRITE(exp, sizeof(*exp));
- if (tvp) POST_WRITE(tvp, timeval_sz);
+ if (inp)
+ POST_WRITE(inp, sizeof(*inp));
+ if (outp)
+ POST_WRITE(outp, sizeof(*outp));
+ if (exp)
+ POST_WRITE(exp, sizeof(*exp));
+ if (tvp)
+ POST_WRITE(tvp, timeval_sz);
}
}
@@ -1936,29 +2095,55 @@ PRE_SYSCALL(epoll_ctl)(long epfd, long op, long fd, void *event) {}
POST_SYSCALL(epoll_ctl)(long res, long epfd, long op, long fd, void *event) {
if (res >= 0) {
- if (event) POST_WRITE(event, struct_epoll_event_sz);
+ if (event)
+ POST_WRITE(event, struct_epoll_event_sz);
}
}
-PRE_SYSCALL(epoll_wait)(long epfd, void *events, long maxevents, long timeout) {
+PRE_SYSCALL(epoll_wait)
+(long epfd, void *events, long maxevents, long timeout) {}
+
+POST_SYSCALL(epoll_wait)
+(long res, long epfd, void *events, long maxevents, long timeout) {
+ if (res >= 0) {
+ if (events)
+ POST_WRITE(events, res * struct_epoll_event_sz);
+ }
+}
+
+PRE_SYSCALL(epoll_pwait)
+(long epfd, void *events, long maxevents, long timeout,
+ const kernel_sigset_t *sigmask, long sigsetsize) {
+ if (sigmask)
+ PRE_READ(sigmask, sigsetsize);
}
-POST_SYSCALL(epoll_wait)(long res, long epfd, void *events, long maxevents,
- long timeout) {
+POST_SYSCALL(epoll_pwait)
+(long res, long epfd, void *events, long maxevents, long timeout,
+ const void *sigmask, long sigsetsize) {
if (res >= 0) {
- if (events) POST_WRITE(events, struct_epoll_event_sz);
+ if (events)
+ POST_WRITE(events, res * struct_epoll_event_sz);
}
}
-PRE_SYSCALL(epoll_pwait)(long epfd, void *events, long maxevents, long timeout,
- const kernel_sigset_t *sigmask, long sigsetsize) {
- if (sigmask) PRE_READ(sigmask, sigsetsize);
+PRE_SYSCALL(epoll_pwait2)
+(long epfd, void *events, long maxevents,
+ const sanitizer_kernel_timespec *timeout, const kernel_sigset_t *sigmask,
+ long sigsetsize) {
+ if (timeout)
+ PRE_READ(timeout, sizeof(timeout));
+ if (sigmask)
+ PRE_READ(sigmask, sigsetsize);
}
-POST_SYSCALL(epoll_pwait)(long res, long epfd, void *events, long maxevents,
- long timeout, const void *sigmask, long sigsetsize) {
+POST_SYSCALL(epoll_pwait2)
+(long res, long epfd, void *events, long maxevents,
+ const sanitizer_kernel_timespec *timeout, const void *sigmask,
+ long sigsetsize) {
if (res >= 0) {
- if (events) POST_WRITE(events, struct_epoll_event_sz);
+ if (events)
+ POST_WRITE(events, res * struct_epoll_event_sz);
}
}
@@ -1993,7 +2178,8 @@ PRE_SYSCALL(newuname)(void *name) {}
POST_SYSCALL(newuname)(long res, void *name) {
if (res >= 0) {
- if (name) POST_WRITE(name, struct_new_utsname_sz);
+ if (name)
+ POST_WRITE(name, struct_new_utsname_sz);
}
}
@@ -2001,7 +2187,8 @@ PRE_SYSCALL(uname)(void *arg0) {}
POST_SYSCALL(uname)(long res, void *arg0) {
if (res >= 0) {
- if (arg0) POST_WRITE(arg0, struct_old_utsname_sz);
+ if (arg0)
+ POST_WRITE(arg0, struct_old_utsname_sz);
}
}
@@ -2009,7 +2196,8 @@ PRE_SYSCALL(olduname)(void *arg0) {}
POST_SYSCALL(olduname)(long res, void *arg0) {
if (res >= 0) {
- if (arg0) POST_WRITE(arg0, struct_oldold_utsname_sz);
+ if (arg0)
+ POST_WRITE(arg0, struct_oldold_utsname_sz);
}
}
@@ -2017,7 +2205,8 @@ PRE_SYSCALL(getrlimit)(long resource, void *rlim) {}
POST_SYSCALL(getrlimit)(long res, long resource, void *rlim) {
if (res >= 0) {
- if (rlim) POST_WRITE(rlim, struct_rlimit_sz);
+ if (rlim)
+ POST_WRITE(rlim, struct_rlimit_sz);
}
}
@@ -2025,7 +2214,8 @@ PRE_SYSCALL(old_getrlimit)(long resource, void *rlim) {}
POST_SYSCALL(old_getrlimit)(long res, long resource, void *rlim) {
if (res >= 0) {
- if (rlim) POST_WRITE(rlim, struct_rlimit_sz);
+ if (rlim)
+ POST_WRITE(rlim, struct_rlimit_sz);
}
}
@@ -2033,29 +2223,33 @@ PRE_SYSCALL(setrlimit)(long resource, void *rlim) {}
POST_SYSCALL(setrlimit)(long res, long resource, void *rlim) {
if (res >= 0) {
- if (rlim) POST_WRITE(rlim, struct_rlimit_sz);
+ if (rlim)
+ POST_WRITE(rlim, struct_rlimit_sz);
}
}
-#if !SANITIZER_ANDROID
-PRE_SYSCALL(prlimit64)(long pid, long resource, const void *new_rlim,
- void *old_rlim) {
- if (new_rlim) PRE_READ(new_rlim, struct_rlimit64_sz);
+# if !SANITIZER_ANDROID
+PRE_SYSCALL(prlimit64)
+(long pid, long resource, const void *new_rlim, void *old_rlim) {
+ if (new_rlim)
+ PRE_READ(new_rlim, struct_rlimit64_sz);
}
-POST_SYSCALL(prlimit64)(long res, long pid, long resource, const void *new_rlim,
- void *old_rlim) {
+POST_SYSCALL(prlimit64)
+(long res, long pid, long resource, const void *new_rlim, void *old_rlim) {
if (res >= 0) {
- if (old_rlim) POST_WRITE(old_rlim, struct_rlimit64_sz);
+ if (old_rlim)
+ POST_WRITE(old_rlim, struct_rlimit64_sz);
}
}
-#endif
+# endif
PRE_SYSCALL(getrusage)(long who, void *ru) {}
POST_SYSCALL(getrusage)(long res, long who, void *ru) {
if (res >= 0) {
- if (ru) POST_WRITE(ru, struct_rusage_sz);
+ if (ru)
+ POST_WRITE(ru, struct_rusage_sz);
}
}
@@ -2068,31 +2262,34 @@ PRE_SYSCALL(msgget)(long key, long msgflg) {}
POST_SYSCALL(msgget)(long res, long key, long msgflg) {}
PRE_SYSCALL(msgsnd)(long msqid, void *msgp, long msgsz, long msgflg) {
- if (msgp) PRE_READ(msgp, msgsz);
+ if (msgp)
+ PRE_READ(msgp, msgsz);
}
-POST_SYSCALL(msgsnd)(long res, long msqid, void *msgp, long msgsz,
- long msgflg) {}
+POST_SYSCALL(msgsnd)
+(long res, long msqid, void *msgp, long msgsz, long msgflg) {}
-PRE_SYSCALL(msgrcv)(long msqid, void *msgp, long msgsz, long msgtyp,
- long msgflg) {}
+PRE_SYSCALL(msgrcv)
+(long msqid, void *msgp, long msgsz, long msgtyp, long msgflg) {}
-POST_SYSCALL(msgrcv)(long res, long msqid, void *msgp, long msgsz, long msgtyp,
- long msgflg) {
+POST_SYSCALL(msgrcv)
+(long res, long msqid, void *msgp, long msgsz, long msgtyp, long msgflg) {
if (res >= 0) {
- if (msgp) POST_WRITE(msgp, res);
+ if (msgp)
+ POST_WRITE(msgp, res);
}
}
-#if !SANITIZER_ANDROID
+# if !SANITIZER_ANDROID
PRE_SYSCALL(msgctl)(long msqid, long cmd, void *buf) {}
POST_SYSCALL(msgctl)(long res, long msqid, long cmd, void *buf) {
if (res >= 0) {
- if (buf) POST_WRITE(buf, struct_msqid_ds_sz);
+ if (buf)
+ POST_WRITE(buf, struct_msqid_ds_sz);
}
}
-#endif
+# endif
PRE_SYSCALL(semget)(long key, long nsems, long semflg) {}
@@ -2106,13 +2303,14 @@ PRE_SYSCALL(semctl)(long semid, long semnum, long cmd, void *arg) {}
POST_SYSCALL(semctl)(long res, long semid, long semnum, long cmd, void *arg) {}
-PRE_SYSCALL(semtimedop)(long semid, void *sops, long nsops,
- const void *timeout) {
- if (timeout) PRE_READ(timeout, struct_timespec_sz);
+PRE_SYSCALL(semtimedop)
+(long semid, void *sops, long nsops, const void *timeout) {
+ if (timeout)
+ PRE_READ(timeout, struct_timespec_sz);
}
-POST_SYSCALL(semtimedop)(long res, long semid, void *sops, long nsops,
- const void *timeout) {}
+POST_SYSCALL(semtimedop)
+(long res, long semid, void *sops, long nsops, const void *timeout) {}
PRE_SYSCALL(shmat)(long shmid, void *shmaddr, long shmflg) {}
@@ -2138,18 +2336,20 @@ POST_SYSCALL(shmdt)(long res, void *shmaddr) {
}
}
-PRE_SYSCALL(ipc)(long call, long first, long second, long third, void *ptr,
- long fifth) {}
+PRE_SYSCALL(ipc)
+(long call, long first, long second, long third, void *ptr, long fifth) {}
-POST_SYSCALL(ipc)(long res, long call, long first, long second, long third,
- void *ptr, long fifth) {}
+POST_SYSCALL(ipc)
+(long res, long call, long first, long second, long third, void *ptr,
+ long fifth) {}
-#if !SANITIZER_ANDROID
+# if !SANITIZER_ANDROID
PRE_SYSCALL(shmctl)(long shmid, long cmd, void *buf) {}
POST_SYSCALL(shmctl)(long res, long shmid, long cmd, void *buf) {
if (res >= 0) {
- if (buf) POST_WRITE(buf, sizeof(__sanitizer_shmid_ds));
+ if (buf)
+ POST_WRITE(buf, sizeof(__sanitizer_shmid_ds));
}
}
@@ -2158,10 +2358,11 @@ PRE_SYSCALL(mq_open)(const void *name, long oflag, long mode, void *attr) {
PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
}
-POST_SYSCALL(mq_open)(long res, const void *name, long oflag, long mode,
- void *attr) {
+POST_SYSCALL(mq_open)
+(long res, const void *name, long oflag, long mode, void *attr) {
if (res >= 0) {
- if (attr) POST_WRITE(attr, struct_mq_attr_sz);
+ if (attr)
+ POST_WRITE(attr, struct_mq_attr_sz);
}
}
@@ -2172,62 +2373,73 @@ PRE_SYSCALL(mq_unlink)(const void *name) {
POST_SYSCALL(mq_unlink)(long res, const void *name) {}
-PRE_SYSCALL(mq_timedsend)(long mqdes, const void *msg_ptr, long msg_len,
- long msg_prio, const void *abs_timeout) {
- if (msg_ptr) PRE_READ(msg_ptr, msg_len);
- if (abs_timeout) PRE_READ(abs_timeout, struct_timespec_sz);
+PRE_SYSCALL(mq_timedsend)
+(long mqdes, const void *msg_ptr, long msg_len, long msg_prio,
+ const void *abs_timeout) {
+ if (msg_ptr)
+ PRE_READ(msg_ptr, msg_len);
+ if (abs_timeout)
+ PRE_READ(abs_timeout, struct_timespec_sz);
}
-POST_SYSCALL(mq_timedsend)(long res, long mqdes, const void *msg_ptr,
- long msg_len, long msg_prio,
- const void *abs_timeout) {}
+POST_SYSCALL(mq_timedsend)
+(long res, long mqdes, const void *msg_ptr, long msg_len, long msg_prio,
+ const void *abs_timeout) {}
-PRE_SYSCALL(mq_timedreceive)(long mqdes, void *msg_ptr, long msg_len,
- void *msg_prio, const void *abs_timeout) {
- if (abs_timeout) PRE_READ(abs_timeout, struct_timespec_sz);
+PRE_SYSCALL(mq_timedreceive)
+(long mqdes, void *msg_ptr, long msg_len, void *msg_prio,
+ const void *abs_timeout) {
+ if (abs_timeout)
+ PRE_READ(abs_timeout, struct_timespec_sz);
}
-POST_SYSCALL(mq_timedreceive)(long res, long mqdes, void *msg_ptr, long msg_len,
- int *msg_prio, const void *abs_timeout) {
+POST_SYSCALL(mq_timedreceive)
+(long res, long mqdes, void *msg_ptr, long msg_len, int *msg_prio,
+ const void *abs_timeout) {
if (res >= 0) {
- if (msg_ptr) POST_WRITE(msg_ptr, res);
- if (msg_prio) POST_WRITE(msg_prio, sizeof(*msg_prio));
+ if (msg_ptr)
+ POST_WRITE(msg_ptr, res);
+ if (msg_prio)
+ POST_WRITE(msg_prio, sizeof(*msg_prio));
}
}
PRE_SYSCALL(mq_notify)(long mqdes, const void *notification) {
- if (notification) PRE_READ(notification, struct_sigevent_sz);
+ if (notification)
+ PRE_READ(notification, struct_sigevent_sz);
}
POST_SYSCALL(mq_notify)(long res, long mqdes, const void *notification) {}
PRE_SYSCALL(mq_getsetattr)(long mqdes, const void *mqstat, void *omqstat) {
- if (mqstat) PRE_READ(mqstat, struct_mq_attr_sz);
+ if (mqstat)
+ PRE_READ(mqstat, struct_mq_attr_sz);
}
-POST_SYSCALL(mq_getsetattr)(long res, long mqdes, const void *mqstat,
- void *omqstat) {
+POST_SYSCALL(mq_getsetattr)
+(long res, long mqdes, const void *mqstat, void *omqstat) {
if (res >= 0) {
- if (omqstat) POST_WRITE(omqstat, struct_mq_attr_sz);
+ if (omqstat)
+ POST_WRITE(omqstat, struct_mq_attr_sz);
}
}
-#endif // SANITIZER_ANDROID
+# endif // SANITIZER_ANDROID
PRE_SYSCALL(pciconfig_iobase)(long which, long bus, long devfn) {}
POST_SYSCALL(pciconfig_iobase)(long res, long which, long bus, long devfn) {}
-PRE_SYSCALL(pciconfig_read)(long bus, long dfn, long off, long len, void *buf) {
-}
+PRE_SYSCALL(pciconfig_read)
+(long bus, long dfn, long off, long len, void *buf) {}
-POST_SYSCALL(pciconfig_read)(long res, long bus, long dfn, long off, long len,
- void *buf) {}
+POST_SYSCALL(pciconfig_read)
+(long res, long bus, long dfn, long off, long len, void *buf) {}
-PRE_SYSCALL(pciconfig_write)(long bus, long dfn, long off, long len,
- void *buf) {}
+PRE_SYSCALL(pciconfig_write)
+(long bus, long dfn, long off, long len, void *buf) {}
-POST_SYSCALL(pciconfig_write)(long res, long bus, long dfn, long off, long len,
- void *buf) {}
+POST_SYSCALL(pciconfig_write)
+(long res, long bus, long dfn, long off, long len, void *buf) {}
PRE_SYSCALL(swapon)(const void *specialfile, long swap_flags) {
if (specialfile)
@@ -2247,8 +2459,10 @@ POST_SYSCALL(swapoff)(long res, const void *specialfile) {}
PRE_SYSCALL(sysctl)(__sanitizer___sysctl_args *args) {
if (args) {
- if (args->name) PRE_READ(args->name, args->nlen * sizeof(*args->name));
- if (args->newval) PRE_READ(args->name, args->newlen);
+ if (args->name)
+ PRE_READ(args->name, args->nlen * sizeof(*args->name));
+ if (args->newval)
+ PRE_READ(args->name, args->newlen);
}
}
@@ -2265,7 +2479,8 @@ PRE_SYSCALL(sysinfo)(void *info) {}
POST_SYSCALL(sysinfo)(long res, void *info) {
if (res >= 0) {
- if (info) POST_WRITE(info, struct_sysinfo_sz);
+ if (info)
+ POST_WRITE(info, struct_sysinfo_sz);
}
}
@@ -2294,10 +2509,10 @@ PRE_SYSCALL(ni_syscall)() {}
POST_SYSCALL(ni_syscall)(long res) {}
PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) {
-#if !SANITIZER_ANDROID && \
- (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
- defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
- SANITIZER_RISCV64)
+# if !SANITIZER_ANDROID && \
+ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
+ defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
+ SANITIZER_RISCV64)
if (data) {
if (request == ptrace_setregs) {
PRE_READ((void *)data, struct_user_regs_struct_sz);
@@ -2312,14 +2527,14 @@ PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) {
PRE_READ(iov->iov_base, iov->iov_len);
}
}
-#endif
+# endif
}
POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) {
-#if !SANITIZER_ANDROID && \
- (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
- defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
- SANITIZER_RISCV64)
+# if !SANITIZER_ANDROID && \
+ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
+ defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
+ SANITIZER_RISCV64)
if (res >= 0 && data) {
// Note that this is different from the interceptor in
// sanitizer_common_interceptors.inc.
@@ -2340,11 +2555,12 @@ POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) {
POST_WRITE((void *)data, sizeof(void *));
}
}
-#endif
+# endif
}
-PRE_SYSCALL(add_key)(const void *_type, const void *_description,
- const void *_payload, long plen, long destringid) {
+PRE_SYSCALL(add_key)
+(const void *_type, const void *_description, const void *_payload, long plen,
+ long destringid) {
if (_type)
PRE_READ(_type, __sanitizer::internal_strlen((const char *)_type) + 1);
if (_description)
@@ -2352,11 +2568,13 @@ PRE_SYSCALL(add_key)(const void *_type, const void *_description,
__sanitizer::internal_strlen((const char *)_description) + 1);
}
-POST_SYSCALL(add_key)(long res, const void *_type, const void *_description,
- const void *_payload, long plen, long destringid) {}
+POST_SYSCALL(add_key)
+(long res, const void *_type, const void *_description, const void *_payload,
+ long plen, long destringid) {}
-PRE_SYSCALL(request_key)(const void *_type, const void *_description,
- const void *_callout_info, long destringid) {
+PRE_SYSCALL(request_key)
+(const void *_type, const void *_description, const void *_callout_info,
+ long destringid) {
if (_type)
PRE_READ(_type, __sanitizer::internal_strlen((const char *)_type) + 1);
if (_description)
@@ -2367,13 +2585,14 @@ PRE_SYSCALL(request_key)(const void *_type, const void *_description,
__sanitizer::internal_strlen((const char *)_callout_info) + 1);
}
-POST_SYSCALL(request_key)(long res, const void *_type, const void *_description,
- const void *_callout_info, long destringid) {}
+POST_SYSCALL(request_key)
+(long res, const void *_type, const void *_description,
+ const void *_callout_info, long destringid) {}
PRE_SYSCALL(keyctl)(long cmd, long arg2, long arg3, long arg4, long arg5) {}
-POST_SYSCALL(keyctl)(long res, long cmd, long arg2, long arg3, long arg4,
- long arg5) {}
+POST_SYSCALL(keyctl)
+(long res, long cmd, long arg2, long arg3, long arg4, long arg5) {}
PRE_SYSCALL(ioprio_set)(long which, long who, long ioprio) {}
@@ -2387,50 +2606,62 @@ PRE_SYSCALL(set_mempolicy)(long mode, void *nmask, long maxnode) {}
POST_SYSCALL(set_mempolicy)(long res, long mode, void *nmask, long maxnode) {
if (res >= 0) {
- if (nmask) POST_WRITE(nmask, sizeof(long));
+ if (nmask)
+ POST_WRITE(nmask, sizeof(long));
}
}
-PRE_SYSCALL(migrate_pages)(long pid, long maxnode, const void *from,
- const void *to) {
- if (from) PRE_READ(from, sizeof(long));
- if (to) PRE_READ(to, sizeof(long));
+PRE_SYSCALL(migrate_pages)
+(long pid, long maxnode, const void *from, const void *to) {
+ if (from)
+ PRE_READ(from, sizeof(long));
+ if (to)
+ PRE_READ(to, sizeof(long));
}
-POST_SYSCALL(migrate_pages)(long res, long pid, long maxnode, const void *from,
- const void *to) {}
+POST_SYSCALL(migrate_pages)
+(long res, long pid, long maxnode, const void *from, const void *to) {}
-PRE_SYSCALL(move_pages)(long pid, long nr_pages, const void **pages,
- const int *nodes, int *status, long flags) {
- if (pages) PRE_READ(pages, nr_pages * sizeof(*pages));
- if (nodes) PRE_READ(nodes, nr_pages * sizeof(*nodes));
+PRE_SYSCALL(move_pages)
+(long pid, long nr_pages, const void **pages, const int *nodes, int *status,
+ long flags) {
+ if (pages)
+ PRE_READ(pages, nr_pages * sizeof(*pages));
+ if (nodes)
+ PRE_READ(nodes, nr_pages * sizeof(*nodes));
}
-POST_SYSCALL(move_pages)(long res, long pid, long nr_pages, const void **pages,
- const int *nodes, int *status, long flags) {
+POST_SYSCALL(move_pages)
+(long res, long pid, long nr_pages, const void **pages, const int *nodes,
+ int *status, long flags) {
if (res >= 0) {
- if (status) POST_WRITE(status, nr_pages * sizeof(*status));
+ if (status)
+ POST_WRITE(status, nr_pages * sizeof(*status));
}
}
-PRE_SYSCALL(mbind)(long start, long len, long mode, void *nmask, long maxnode,
- long flags) {}
+PRE_SYSCALL(mbind)
+(long start, long len, long mode, void *nmask, long maxnode, long flags) {}
-POST_SYSCALL(mbind)(long res, long start, long len, long mode, void *nmask,
- long maxnode, long flags) {
+POST_SYSCALL(mbind)
+(long res, long start, long len, long mode, void *nmask, long maxnode,
+ long flags) {
if (res >= 0) {
- if (nmask) POST_WRITE(nmask, sizeof(long));
+ if (nmask)
+ POST_WRITE(nmask, sizeof(long));
}
}
-PRE_SYSCALL(get_mempolicy)(void *policy, void *nmask, long maxnode, long addr,
- long flags) {}
+PRE_SYSCALL(get_mempolicy)
+(void *policy, void *nmask, long maxnode, long addr, long flags) {}
-POST_SYSCALL(get_mempolicy)(long res, void *policy, void *nmask, long maxnode,
- long addr, long flags) {
+POST_SYSCALL(get_mempolicy)
+(long res, void *policy, void *nmask, long maxnode, long addr, long flags) {
if (res >= 0) {
- if (policy) POST_WRITE(policy, sizeof(int));
- if (nmask) POST_WRITE(nmask, sizeof(long));
+ if (policy)
+ POST_WRITE(policy, sizeof(int));
+ if (nmask)
+ POST_WRITE(nmask, sizeof(long));
}
}
@@ -2447,8 +2678,8 @@ PRE_SYSCALL(inotify_add_watch)(long fd, const void *path, long mask) {
PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
}
-POST_SYSCALL(inotify_add_watch)(long res, long fd, const void *path,
- long mask) {}
+POST_SYSCALL(inotify_add_watch)
+(long res, long fd, const void *path, long mask) {}
PRE_SYSCALL(inotify_rm_watch)(long fd, long wd) {}
@@ -2458,8 +2689,10 @@ PRE_SYSCALL(spu_run)(long fd, void *unpc, void *ustatus) {}
POST_SYSCALL(spu_run)(long res, long fd, unsigned *unpc, unsigned *ustatus) {
if (res >= 0) {
- if (unpc) POST_WRITE(unpc, sizeof(*unpc));
- if (ustatus) POST_WRITE(ustatus, sizeof(*ustatus));
+ if (unpc)
+ POST_WRITE(unpc, sizeof(*unpc));
+ if (ustatus)
+ POST_WRITE(ustatus, sizeof(*ustatus));
}
}
@@ -2468,8 +2701,8 @@ PRE_SYSCALL(spu_create)(const void *name, long flags, long mode, long fd) {
PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
}
-POST_SYSCALL(spu_create)(long res, const void *name, long flags, long mode,
- long fd) {}
+POST_SYSCALL(spu_create)
+(long res, const void *name, long flags, long mode, long fd) {}
PRE_SYSCALL(mknodat)(long dfd, const void *filename, long mode, long dev) {
if (filename)
@@ -2477,8 +2710,8 @@ PRE_SYSCALL(mknodat)(long dfd, const void *filename, long mode, long dev) {
__sanitizer::internal_strlen((const char *)filename) + 1);
}
-POST_SYSCALL(mknodat)(long res, long dfd, const void *filename, long mode,
- long dev) {}
+POST_SYSCALL(mknodat)
+(long res, long dfd, const void *filename, long mode, long dev) {}
PRE_SYSCALL(mkdirat)(long dfd, const void *pathname, long mode) {
if (pathname)
@@ -2503,30 +2736,33 @@ PRE_SYSCALL(symlinkat)(const void *oldname, long newdfd, const void *newname) {
PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
}
-POST_SYSCALL(symlinkat)(long res, const void *oldname, long newdfd,
- const void *newname) {}
+POST_SYSCALL(symlinkat)
+(long res, const void *oldname, long newdfd, const void *newname) {}
-PRE_SYSCALL(linkat)(long olddfd, const void *oldname, long newdfd,
- const void *newname, long flags) {
+PRE_SYSCALL(linkat)
+(long olddfd, const void *oldname, long newdfd, const void *newname,
+ long flags) {
if (oldname)
PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
if (newname)
PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
}
-POST_SYSCALL(linkat)(long res, long olddfd, const void *oldname, long newdfd,
- const void *newname, long flags) {}
+POST_SYSCALL(linkat)
+(long res, long olddfd, const void *oldname, long newdfd, const void *newname,
+ long flags) {}
-PRE_SYSCALL(renameat)(long olddfd, const void *oldname, long newdfd,
- const void *newname) {
+PRE_SYSCALL(renameat)
+(long olddfd, const void *oldname, long newdfd, const void *newname) {
if (oldname)
PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
if (newname)
PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
}
-POST_SYSCALL(renameat)(long res, long olddfd, const void *oldname, long newdfd,
- const void *newname) {}
+POST_SYSCALL(renameat)
+(long res, long olddfd, const void *oldname, long newdfd, const void *newname) {
+}
PRE_SYSCALL(futimesat)(long dfd, const void *filename, void *utimes) {
if (filename)
@@ -2534,10 +2770,11 @@ PRE_SYSCALL(futimesat)(long dfd, const void *filename, void *utimes) {
__sanitizer::internal_strlen((const char *)filename) + 1);
}
-POST_SYSCALL(futimesat)(long res, long dfd, const void *filename,
- void *utimes) {
+POST_SYSCALL(futimesat)
+(long res, long dfd, const void *filename, void *utimes) {
if (res >= 0) {
- if (utimes) POST_WRITE(utimes, timeval_sz);
+ if (utimes)
+ POST_WRITE(utimes, timeval_sz);
}
}
@@ -2557,15 +2794,15 @@ PRE_SYSCALL(fchmodat)(long dfd, const void *filename, long mode) {
POST_SYSCALL(fchmodat)(long res, long dfd, const void *filename, long mode) {}
-PRE_SYSCALL(fchownat)(long dfd, const void *filename, long user, long group,
- long flag) {
+PRE_SYSCALL(fchownat)
+(long dfd, const void *filename, long user, long group, long flag) {
if (filename)
PRE_READ(filename,
__sanitizer::internal_strlen((const char *)filename) + 1);
}
-POST_SYSCALL(fchownat)(long res, long dfd, const void *filename, long user,
- long group, long flag) {}
+POST_SYSCALL(fchownat)
+(long res, long dfd, const void *filename, long user, long group, long flag) {}
PRE_SYSCALL(openat)(long dfd, const void *filename, long flags, long mode) {
if (filename)
@@ -2573,34 +2810,36 @@ PRE_SYSCALL(openat)(long dfd, const void *filename, long flags, long mode) {
__sanitizer::internal_strlen((const char *)filename) + 1);
}
-POST_SYSCALL(openat)(long res, long dfd, const void *filename, long flags,
- long mode) {}
+POST_SYSCALL(openat)
+(long res, long dfd, const void *filename, long flags, long mode) {}
-PRE_SYSCALL(newfstatat)(long dfd, const void *filename, void *statbuf,
- long flag) {
+PRE_SYSCALL(newfstatat)
+(long dfd, const void *filename, void *statbuf, long flag) {
if (filename)
PRE_READ(filename,
__sanitizer::internal_strlen((const char *)filename) + 1);
}
-POST_SYSCALL(newfstatat)(long res, long dfd, const void *filename,
- void *statbuf, long flag) {
+POST_SYSCALL(newfstatat)
+(long res, long dfd, const void *filename, void *statbuf, long flag) {
if (res >= 0) {
- if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat_sz);
}
}
-PRE_SYSCALL(fstatat64)(long dfd, const void *filename, void *statbuf,
- long flag) {
+PRE_SYSCALL(fstatat64)
+(long dfd, const void *filename, void *statbuf, long flag) {
if (filename)
PRE_READ(filename,
__sanitizer::internal_strlen((const char *)filename) + 1);
}
-POST_SYSCALL(fstatat64)(long res, long dfd, const void *filename, void *statbuf,
- long flag) {
+POST_SYSCALL(fstatat64)
+(long res, long dfd, const void *filename, void *statbuf, long flag) {
if (res >= 0) {
- if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat64_sz);
}
}
@@ -2609,25 +2848,26 @@ PRE_SYSCALL(readlinkat)(long dfd, const void *path, void *buf, long bufsiz) {
PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
}
-POST_SYSCALL(readlinkat)(long res, long dfd, const void *path, void *buf,
- long bufsiz) {
+POST_SYSCALL(readlinkat)
+(long res, long dfd, const void *path, void *buf, long bufsiz) {
if (res >= 0) {
if (buf)
POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
}
}
-PRE_SYSCALL(utimensat)(long dfd, const void *filename, void *utimes,
- long flags) {
+PRE_SYSCALL(utimensat)
+(long dfd, const void *filename, void *utimes, long flags) {
if (filename)
PRE_READ(filename,
__sanitizer::internal_strlen((const char *)filename) + 1);
}
-POST_SYSCALL(utimensat)(long res, long dfd, const void *filename, void *utimes,
- long flags) {
+POST_SYSCALL(utimensat)
+(long res, long dfd, const void *filename, void *utimes, long flags) {
if (res >= 0) {
- if (utimes) POST_WRITE(utimes, struct_timespec_sz);
+ if (utimes)
+ POST_WRITE(utimes, struct_timespec_sz);
}
}
@@ -2635,24 +2875,28 @@ PRE_SYSCALL(unshare)(long unshare_flags) {}
POST_SYSCALL(unshare)(long res, long unshare_flags) {}
-PRE_SYSCALL(splice)(long fd_in, void *off_in, long fd_out, void *off_out,
- long len, long flags) {}
+PRE_SYSCALL(splice)
+(long fd_in, void *off_in, long fd_out, void *off_out, long len, long flags) {}
-POST_SYSCALL(splice)(long res, long fd_in, void *off_in, long fd_out,
- void *off_out, long len, long flags) {
+POST_SYSCALL(splice)
+(long res, long fd_in, void *off_in, long fd_out, void *off_out, long len,
+ long flags) {
if (res >= 0) {
- if (off_in) POST_WRITE(off_in, sizeof(long long));
- if (off_out) POST_WRITE(off_out, sizeof(long long));
+ if (off_in)
+ POST_WRITE(off_in, sizeof(long long));
+ if (off_out)
+ POST_WRITE(off_out, sizeof(long long));
}
}
-PRE_SYSCALL(vmsplice)(long fd, const __sanitizer_iovec *iov, long nr_segs,
- long flags) {}
+PRE_SYSCALL(vmsplice)
+(long fd, const __sanitizer_iovec *iov, long nr_segs, long flags) {}
-POST_SYSCALL(vmsplice)(long res, long fd, const __sanitizer_iovec *iov,
- long nr_segs, long flags) {
+POST_SYSCALL(vmsplice)
+(long res, long fd, const __sanitizer_iovec *iov, long nr_segs, long flags) {
if (res >= 0) {
- if (iov) kernel_read_iovec(iov, nr_segs, res);
+ if (iov)
+ kernel_read_iovec(iov, nr_segs, res);
}
}
@@ -2662,8 +2906,8 @@ POST_SYSCALL(tee)(long res, long fdin, long fdout, long len, long flags) {}
PRE_SYSCALL(get_robust_list)(long pid, void *head_ptr, void *len_ptr) {}
-POST_SYSCALL(get_robust_list)(long res, long pid, void *head_ptr,
- void *len_ptr) {}
+POST_SYSCALL(get_robust_list)
+(long res, long pid, void *head_ptr, void *len_ptr) {}
PRE_SYSCALL(set_robust_list)(void *head, long len) {}
@@ -2673,27 +2917,31 @@ PRE_SYSCALL(getcpu)(void *cpu, void *node, void *cache) {}
POST_SYSCALL(getcpu)(long res, void *cpu, void *node, void *cache) {
if (res >= 0) {
- if (cpu) POST_WRITE(cpu, sizeof(unsigned));
- if (node) POST_WRITE(node, sizeof(unsigned));
+ if (cpu)
+ POST_WRITE(cpu, sizeof(unsigned));
+ if (node)
+ POST_WRITE(node, sizeof(unsigned));
// The third argument to this system call is nowadays unused.
}
}
PRE_SYSCALL(signalfd)(long ufd, void *user_mask, long sizemask) {}
-POST_SYSCALL(signalfd)(long res, long ufd, kernel_sigset_t *user_mask,
- long sizemask) {
+POST_SYSCALL(signalfd)
+(long res, long ufd, kernel_sigset_t *user_mask, long sizemask) {
if (res >= 0) {
- if (user_mask) POST_WRITE(user_mask, sizemask);
+ if (user_mask)
+ POST_WRITE(user_mask, sizemask);
}
}
PRE_SYSCALL(signalfd4)(long ufd, void *user_mask, long sizemask, long flags) {}
-POST_SYSCALL(signalfd4)(long res, long ufd, kernel_sigset_t *user_mask,
- long sizemask, long flags) {
+POST_SYSCALL(signalfd4)
+(long res, long ufd, kernel_sigset_t *user_mask, long sizemask, long flags) {
if (res >= 0) {
- if (user_mask) POST_WRITE(user_mask, sizemask);
+ if (user_mask)
+ POST_WRITE(user_mask, sizemask);
}
}
@@ -2701,15 +2949,17 @@ PRE_SYSCALL(timerfd_create)(long clockid, long flags) {}
POST_SYSCALL(timerfd_create)(long res, long clockid, long flags) {}
-PRE_SYSCALL(timerfd_settime)(long ufd, long flags, const void *utmr,
- void *otmr) {
- if (utmr) PRE_READ(utmr, struct_itimerspec_sz);
+PRE_SYSCALL(timerfd_settime)
+(long ufd, long flags, const void *utmr, void *otmr) {
+ if (utmr)
+ PRE_READ(utmr, struct_itimerspec_sz);
}
-POST_SYSCALL(timerfd_settime)(long res, long ufd, long flags, const void *utmr,
- void *otmr) {
+POST_SYSCALL(timerfd_settime)
+(long res, long ufd, long flags, const void *utmr, void *otmr) {
if (res >= 0) {
- if (otmr) POST_WRITE(otmr, struct_itimerspec_sz);
+ if (otmr)
+ POST_WRITE(otmr, struct_itimerspec_sz);
}
}
@@ -2717,7 +2967,8 @@ PRE_SYSCALL(timerfd_gettime)(long ufd, void *otmr) {}
POST_SYSCALL(timerfd_gettime)(long res, long ufd, void *otmr) {
if (res >= 0) {
- if (otmr) POST_WRITE(otmr, struct_itimerspec_sz);
+ if (otmr)
+ POST_WRITE(otmr, struct_itimerspec_sz);
}
}
@@ -2735,33 +2986,42 @@ POST_SYSCALL(old_readdir)(long res, long arg0, void *arg1, long arg2) {
// Missing definition of 'struct old_linux_dirent'.
}
-PRE_SYSCALL(pselect6)(long arg0, __sanitizer___kernel_fd_set *arg1,
- __sanitizer___kernel_fd_set *arg2,
- __sanitizer___kernel_fd_set *arg3, void *arg4,
- void *arg5) {}
+PRE_SYSCALL(pselect6)
+(long arg0, __sanitizer___kernel_fd_set *arg1,
+ __sanitizer___kernel_fd_set *arg2, __sanitizer___kernel_fd_set *arg3,
+ void *arg4, void *arg5) {}
-POST_SYSCALL(pselect6)(long res, long arg0, __sanitizer___kernel_fd_set *arg1,
- __sanitizer___kernel_fd_set *arg2,
- __sanitizer___kernel_fd_set *arg3, void *arg4,
- void *arg5) {
+POST_SYSCALL(pselect6)
+(long res, long arg0, __sanitizer___kernel_fd_set *arg1,
+ __sanitizer___kernel_fd_set *arg2, __sanitizer___kernel_fd_set *arg3,
+ void *arg4, void *arg5) {
if (res >= 0) {
- if (arg1) POST_WRITE(arg1, sizeof(*arg1));
- if (arg2) POST_WRITE(arg2, sizeof(*arg2));
- if (arg3) POST_WRITE(arg3, sizeof(*arg3));
- if (arg4) POST_WRITE(arg4, struct_timespec_sz);
+ if (arg1)
+ POST_WRITE(arg1, sizeof(*arg1));
+ if (arg2)
+ POST_WRITE(arg2, sizeof(*arg2));
+ if (arg3)
+ POST_WRITE(arg3, sizeof(*arg3));
+ if (arg4)
+ POST_WRITE(arg4, struct_timespec_sz);
}
}
-PRE_SYSCALL(ppoll)(__sanitizer_pollfd *arg0, long arg1, void *arg2,
- const kernel_sigset_t *arg3, long arg4) {
- if (arg3) PRE_READ(arg3, arg4);
+PRE_SYSCALL(ppoll)
+(__sanitizer_pollfd *arg0, long arg1, void *arg2, const kernel_sigset_t *arg3,
+ long arg4) {
+ if (arg3)
+ PRE_READ(arg3, arg4);
}
-POST_SYSCALL(ppoll)(long res, __sanitizer_pollfd *arg0, long arg1, void *arg2,
- const void *arg3, long arg4) {
+POST_SYSCALL(ppoll)
+(long res, __sanitizer_pollfd *arg0, long arg1, void *arg2, const void *arg3,
+ long arg4) {
if (res >= 0) {
- if (arg0) POST_WRITE(arg0, sizeof(*arg0));
- if (arg2) POST_WRITE(arg2, struct_timespec_sz);
+ if (arg0)
+ POST_WRITE(arg0, sizeof(*arg0));
+ if (arg2)
+ POST_WRITE(arg2, struct_timespec_sz);
}
}
@@ -2769,81 +3029,79 @@ PRE_SYSCALL(syncfs)(long fd) {}
POST_SYSCALL(syncfs)(long res, long fd) {}
-PRE_SYSCALL(perf_event_open)(__sanitizer_perf_event_attr *attr_uptr, long pid,
- long cpu, long group_fd, long flags) {
- if (attr_uptr) PRE_READ(attr_uptr, attr_uptr->size);
+PRE_SYSCALL(perf_event_open)
+(__sanitizer_perf_event_attr *attr_uptr, long pid, long cpu, long group_fd,
+ long flags) {
+ if (attr_uptr)
+ PRE_READ(attr_uptr, attr_uptr->size);
}
-POST_SYSCALL(perf_event_open)(long res, __sanitizer_perf_event_attr *attr_uptr,
- long pid, long cpu, long group_fd, long flags) {}
+POST_SYSCALL(perf_event_open)
+(long res, __sanitizer_perf_event_attr *attr_uptr, long pid, long cpu,
+ long group_fd, long flags) {}
-PRE_SYSCALL(mmap_pgoff)(long addr, long len, long prot, long flags, long fd,
- long pgoff) {}
+PRE_SYSCALL(mmap_pgoff)
+(long addr, long len, long prot, long flags, long fd, long pgoff) {}
-POST_SYSCALL(mmap_pgoff)(long res, long addr, long len, long prot, long flags,
- long fd, long pgoff) {}
+POST_SYSCALL(mmap_pgoff)
+(long res, long addr, long len, long prot, long flags, long fd, long pgoff) {}
PRE_SYSCALL(old_mmap)(void *arg) {}
POST_SYSCALL(old_mmap)(long res, void *arg) {}
-PRE_SYSCALL(name_to_handle_at)(long dfd, const void *name, void *handle,
- void *mnt_id, long flag) {}
+PRE_SYSCALL(name_to_handle_at)
+(long dfd, const void *name, void *handle, void *mnt_id, long flag) {}
-POST_SYSCALL(name_to_handle_at)(long res, long dfd, const void *name,
- void *handle, void *mnt_id, long flag) {}
+POST_SYSCALL(name_to_handle_at)
+(long res, long dfd, const void *name, void *handle, void *mnt_id, long flag) {}
PRE_SYSCALL(open_by_handle_at)(long mountdirfd, void *handle, long flags) {}
-POST_SYSCALL(open_by_handle_at)(long res, long mountdirfd, void *handle,
- long flags) {}
+POST_SYSCALL(open_by_handle_at)
+(long res, long mountdirfd, void *handle, long flags) {}
PRE_SYSCALL(setns)(long fd, long nstype) {}
POST_SYSCALL(setns)(long res, long fd, long nstype) {}
-PRE_SYSCALL(process_vm_readv)(long pid, const __sanitizer_iovec *lvec,
- long liovcnt, const void *rvec, long riovcnt,
- long flags) {}
+PRE_SYSCALL(process_vm_readv)
+(long pid, const __sanitizer_iovec *lvec, long liovcnt, const void *rvec,
+ long riovcnt, long flags) {}
-POST_SYSCALL(process_vm_readv)(long res, long pid,
- const __sanitizer_iovec *lvec, long liovcnt,
- const void *rvec, long riovcnt, long flags) {
+POST_SYSCALL(process_vm_readv)
+(long res, long pid, const __sanitizer_iovec *lvec, long liovcnt,
+ const void *rvec, long riovcnt, long flags) {
if (res >= 0) {
- if (lvec) kernel_write_iovec(lvec, liovcnt, res);
+ if (lvec)
+ kernel_write_iovec(lvec, liovcnt, res);
}
}
-PRE_SYSCALL(process_vm_writev)(long pid, const __sanitizer_iovec *lvec,
- long liovcnt, const void *rvec, long riovcnt,
- long flags) {}
+PRE_SYSCALL(process_vm_writev)
+(long pid, const __sanitizer_iovec *lvec, long liovcnt, const void *rvec,
+ long riovcnt, long flags) {}
-POST_SYSCALL(process_vm_writev)(long res, long pid,
- const __sanitizer_iovec *lvec, long liovcnt,
- const void *rvec, long riovcnt, long flags) {
+POST_SYSCALL(process_vm_writev)
+(long res, long pid, const __sanitizer_iovec *lvec, long liovcnt,
+ const void *rvec, long riovcnt, long flags) {
if (res >= 0) {
- if (lvec) kernel_read_iovec(lvec, liovcnt, res);
+ if (lvec)
+ kernel_read_iovec(lvec, liovcnt, res);
}
}
-PRE_SYSCALL(fork)() {
- COMMON_SYSCALL_PRE_FORK();
-}
+PRE_SYSCALL(fork)() { COMMON_SYSCALL_PRE_FORK(); }
-POST_SYSCALL(fork)(long res) {
- COMMON_SYSCALL_POST_FORK(res);
-}
+POST_SYSCALL(fork)(long res) { COMMON_SYSCALL_POST_FORK(res); }
-PRE_SYSCALL(vfork)() {
- COMMON_SYSCALL_PRE_FORK();
-}
+PRE_SYSCALL(vfork)() { COMMON_SYSCALL_PRE_FORK(); }
-POST_SYSCALL(vfork)(long res) {
- COMMON_SYSCALL_POST_FORK(res);
-}
+POST_SYSCALL(vfork)(long res) { COMMON_SYSCALL_POST_FORK(res); }
-PRE_SYSCALL(sigaction)(long signum, const __sanitizer_kernel_sigaction_t *act,
- __sanitizer_kernel_sigaction_t *oldact) {
+PRE_SYSCALL(sigaction)
+(long signum, const __sanitizer_kernel_sigaction_t *act,
+ __sanitizer_kernel_sigaction_t *oldact) {
if (act) {
PRE_READ(&act->sigaction, sizeof(act->sigaction));
PRE_READ(&act->sa_flags, sizeof(act->sa_flags));
@@ -2851,15 +3109,16 @@ PRE_SYSCALL(sigaction)(long signum, const __sanitizer_kernel_sigaction_t *act,
}
}
-POST_SYSCALL(sigaction)(long res, long signum,
- const __sanitizer_kernel_sigaction_t *act,
- __sanitizer_kernel_sigaction_t *oldact) {
- if (res >= 0 && oldact) POST_WRITE(oldact, sizeof(*oldact));
+POST_SYSCALL(sigaction)
+(long res, long signum, const __sanitizer_kernel_sigaction_t *act,
+ __sanitizer_kernel_sigaction_t *oldact) {
+ if (res >= 0 && oldact)
+ POST_WRITE(oldact, sizeof(*oldact));
}
-PRE_SYSCALL(rt_sigaction)(long signum,
- const __sanitizer_kernel_sigaction_t *act,
- __sanitizer_kernel_sigaction_t *oldact, SIZE_T sz) {
+PRE_SYSCALL(rt_sigaction)
+(long signum, const __sanitizer_kernel_sigaction_t *act,
+ __sanitizer_kernel_sigaction_t *oldact, SIZE_T sz) {
if (act) {
PRE_READ(&act->sigaction, sizeof(act->sigaction));
PRE_READ(&act->sa_flags, sizeof(act->sa_flags));
@@ -2867,9 +3126,9 @@ PRE_SYSCALL(rt_sigaction)(long signum,
}
}
-POST_SYSCALL(rt_sigaction)(long res, long signum,
- const __sanitizer_kernel_sigaction_t *act,
- __sanitizer_kernel_sigaction_t *oldact, SIZE_T sz) {
+POST_SYSCALL(rt_sigaction)
+(long res, long signum, const __sanitizer_kernel_sigaction_t *act,
+ __sanitizer_kernel_sigaction_t *oldact, SIZE_T sz) {
if (res >= 0 && oldact) {
SIZE_T oldact_sz = ((char *)&oldact->sa_mask) - ((char *)oldact) + sz;
POST_WRITE(oldact, oldact_sz);
@@ -2906,11 +3165,11 @@ POST_SYSCALL(sigaltstack)(long res, void *ss, void *oss) {
}
} // extern "C"
-#undef PRE_SYSCALL
-#undef PRE_READ
-#undef PRE_WRITE
-#undef POST_SYSCALL
-#undef POST_READ
-#undef POST_WRITE
+# undef PRE_SYSCALL
+# undef PRE_READ
+# undef PRE_WRITE
+# undef POST_SYSCALL
+# undef POST_READ
+# undef POST_WRITE
#endif // SANITIZER_LINUX
diff --git a/libsanitizer/sanitizer_common/sanitizer_coverage_fuchsia.cpp b/libsanitizer/sanitizer_common/sanitizer_coverage_fuchsia.cpp
index a52db08..1d0dbe5 100644
--- a/libsanitizer/sanitizer_common/sanitizer_coverage_fuchsia.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_coverage_fuchsia.cpp
@@ -51,6 +51,8 @@ constexpr const char kSancovSinkName[] = "sancov";
// This class relies on zero-initialization.
class TracePcGuardController final {
public:
+ constexpr TracePcGuardController() {}
+
// For each PC location being tracked, there is a u32 reserved in global
// data called the "guard". At startup, we assign each guard slot a
// unique index into the big results array. Later during runtime, the
@@ -87,7 +89,7 @@ class TracePcGuardController final {
}
void Dump() {
- BlockingMutexLock locked(&setup_lock_);
+ Lock locked(&setup_lock_);
if (array_) {
CHECK_NE(vmo_, ZX_HANDLE_INVALID);
@@ -114,7 +116,7 @@ class TracePcGuardController final {
// We can always spare the 32G of address space.
static constexpr size_t MappingSize = sizeof(uptr) << 32;
- BlockingMutex setup_lock_ = BlockingMutex(LINKER_INITIALIZED);
+ Mutex setup_lock_;
uptr *array_ = nullptr;
u32 next_index_ = 0;
zx_handle_t vmo_ = {};
@@ -123,7 +125,7 @@ class TracePcGuardController final {
size_t DataSize() const { return next_index_ * sizeof(uintptr_t); }
u32 Setup(u32 num_guards) {
- BlockingMutexLock locked(&setup_lock_);
+ Lock locked(&setup_lock_);
DCHECK(common_flags()->coverage);
if (next_index_ == 0) {
diff --git a/libsanitizer/sanitizer_common/sanitizer_coverage_libcdep_new.cpp b/libsanitizer/sanitizer_common/sanitizer_coverage_libcdep_new.cpp
index 73ebeb5..56220df 100644
--- a/libsanitizer/sanitizer_common/sanitizer_coverage_libcdep_new.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_coverage_libcdep_new.cpp
@@ -73,7 +73,7 @@ static void SanitizerDumpCoverage(const uptr* unsorted_pcs, uptr len) {
if (!pc) continue;
if (!__sanitizer_get_module_and_offset_for_pc(pc, nullptr, 0, &pcs[i])) {
- Printf("ERROR: unknown pc 0x%x (may happen if dlclose is used)\n", pc);
+ Printf("ERROR: unknown pc 0x%zx (may happen if dlclose is used)\n", pc);
continue;
}
uptr module_base = pc - pcs[i];
@@ -151,6 +151,55 @@ class TracePcGuardController {
static TracePcGuardController pc_guard_controller;
+// A basic default implementation of callbacks for
+// -fsanitize-coverage=inline-8bit-counters,pc-table.
+// Use TOOL_OPTIONS (UBSAN_OPTIONS, etc) to dump the coverage data:
+// * cov_8bit_counters_out=PATH to dump the 8bit counters.
+// * cov_pcs_out=PATH to dump the pc table.
+//
+// Most users will still need to define their own callbacks for greater
+// flexibility.
+namespace SingletonCounterCoverage {
+
+static char *counters_beg, *counters_end;
+static const uptr *pcs_beg, *pcs_end;
+
+static void DumpCoverage() {
+ const char* file_path = common_flags()->cov_8bit_counters_out;
+ if (file_path && internal_strlen(file_path)) {
+ fd_t fd = OpenFile(file_path);
+ FileCloser file_closer(fd);
+ uptr size = counters_end - counters_beg;
+ WriteToFile(fd, counters_beg, size);
+ if (common_flags()->verbosity)
+ __sanitizer::Printf("cov_8bit_counters_out: written %zd bytes to %s\n",
+ size, file_path);
+ }
+ file_path = common_flags()->cov_pcs_out;
+ if (file_path && internal_strlen(file_path)) {
+ fd_t fd = OpenFile(file_path);
+ FileCloser file_closer(fd);
+ uptr size = (pcs_end - pcs_beg) * sizeof(uptr);
+ WriteToFile(fd, pcs_beg, size);
+ if (common_flags()->verbosity)
+ __sanitizer::Printf("cov_pcs_out: written %zd bytes to %s\n", size,
+ file_path);
+ }
+}
+
+static void Cov8bitCountersInit(char* beg, char* end) {
+ counters_beg = beg;
+ counters_end = end;
+ Atexit(DumpCoverage);
+}
+
+static void CovPcsInit(const uptr* beg, const uptr* end) {
+ pcs_beg = beg;
+ pcs_end = end;
+}
+
+} // namespace SingletonCounterCoverage
+
} // namespace
} // namespace __sancov
@@ -191,7 +240,9 @@ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() {
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_reset() {
__sancov::pc_guard_controller.Reset();
}
-// Default empty implementations (weak). Users should redefine them.
+// Default implementations (weak).
+// Either empty or very simple.
+// Most users should redefine them.
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp, void) {}
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp1, void) {}
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp2, void) {}
@@ -206,9 +257,15 @@ SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div4, void) {}
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div8, void) {}
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_gep, void) {}
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {}
-SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_8bit_counters_init, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_8bit_counters_init,
+ char* start, char* end) {
+ __sancov::SingletonCounterCoverage::Cov8bitCountersInit(start, end);
+}
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_bool_flag_init, void) {}
-SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, const uptr* beg,
+ const uptr* end) {
+ __sancov::SingletonCounterCoverage::CovPcsInit(beg, end);
+}
} // extern "C"
// Weak definition for code instrumented with -fsanitize-coverage=stack-depth
// and later linked with code containing a strong definition.
diff --git a/libsanitizer/sanitizer_common/sanitizer_file.cpp b/libsanitizer/sanitizer_common/sanitizer_file.cpp
index 0b92dcc..5492560 100644
--- a/libsanitizer/sanitizer_common/sanitizer_file.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_file.cpp
@@ -75,6 +75,20 @@ void ReportFile::ReopenIfNecessary() {
fd_pid = pid;
}
+static void RecursiveCreateParentDirs(char *path) {
+ if (path[0] == '\0')
+ return;
+ for (int i = 1; path[i] != '\0'; ++i) {
+ char save = path[i];
+ if (!IsPathSeparator(path[i]))
+ continue;
+ path[i] = '\0';
+ /* Some of these will fail, because the directory exists, ignore it. */
+ CreateDir(path);
+ path[i] = save;
+ }
+}
+
void ReportFile::SetReportPath(const char *path) {
if (path) {
uptr len = internal_strlen(path);
@@ -95,6 +109,7 @@ void ReportFile::SetReportPath(const char *path) {
fd = kStdoutFd;
} else {
internal_snprintf(path_prefix, kMaxPathLength, "%s", path);
+ RecursiveCreateParentDirs(path_prefix);
}
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_file.h b/libsanitizer/sanitizer_common/sanitizer_file.h
index 08671ab..3d79161 100644
--- a/libsanitizer/sanitizer_common/sanitizer_file.h
+++ b/libsanitizer/sanitizer_common/sanitizer_file.h
@@ -81,6 +81,8 @@ bool FileExists(const char *filename);
char *FindPathToBinary(const char *name);
bool IsPathSeparator(const char c);
bool IsAbsolutePath(const char *path);
+// Returns true on success, false on failure.
+bool CreateDir(const char *pathname);
// Starts a subprocess and returs its pid.
// If *_fd parameters are not kInvalidFd their corresponding input/output
// streams will be redirect to the file. The files will always be closed
diff --git a/libsanitizer/sanitizer_common/sanitizer_flag_parser.h b/libsanitizer/sanitizer_common/sanitizer_flag_parser.h
index acc71cc..3ccc6a6 100644
--- a/libsanitizer/sanitizer_common/sanitizer_flag_parser.h
+++ b/libsanitizer/sanitizer_common/sanitizer_flag_parser.h
@@ -138,7 +138,7 @@ inline bool FlagHandler<uptr>::Parse(const char *value) {
template <>
inline bool FlagHandler<uptr>::Format(char *buffer, uptr size) {
- uptr num_symbols_should_write = internal_snprintf(buffer, size, "%p", *t_);
+ uptr num_symbols_should_write = internal_snprintf(buffer, size, "0x%zx", *t_);
return num_symbols_should_write < size;
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_flags.inc b/libsanitizer/sanitizer_common/sanitizer_flags.inc
index 3bc44c6..95da82b 100644
--- a/libsanitizer/sanitizer_common/sanitizer_flags.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_flags.inc
@@ -160,6 +160,10 @@ COMMON_FLAG(
COMMON_FLAG(const char *, coverage_dir, ".",
"Target directory for coverage dumps. Defaults to the current "
"directory.")
+COMMON_FLAG(const char *, cov_8bit_counters_out, "",
+ "If non-empty, write 8bit counters to this file. ")
+COMMON_FLAG(const char *, cov_pcs_out, "",
+ "If non-empty, write the coverage pc table to this file. ")
COMMON_FLAG(bool, full_address_space, false,
"Sanitize complete address space; "
"by default kernel area on 32-bit platforms will not be sanitized")
diff --git a/libsanitizer/sanitizer_common/sanitizer_fuchsia.cpp b/libsanitizer/sanitizer_common/sanitizer_fuchsia.cpp
index 65bc398..de4c985 100644
--- a/libsanitizer/sanitizer_common/sanitizer_fuchsia.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_fuchsia.cpp
@@ -112,47 +112,6 @@ void FutexWake(atomic_uint32_t *p, u32 count) {
CHECK_EQ(status, ZX_OK);
}
-enum MutexState : int { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 };
-
-BlockingMutex::BlockingMutex() {
- // NOTE! It's important that this use internal_memset, because plain
- // memset might be intercepted (e.g., actually be __asan_memset).
- // Defining this so the compiler initializes each field, e.g.:
- // BlockingMutex::BlockingMutex() : BlockingMutex(LINKER_INITIALIZED) {}
- // might result in the compiler generating a call to memset, which would
- // have the same problem.
- internal_memset(this, 0, sizeof(*this));
-}
-
-void BlockingMutex::Lock() {
- CHECK_EQ(owner_, 0);
- atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
- if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
- return;
- while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
- zx_status_t status =
- _zx_futex_wait(reinterpret_cast<zx_futex_t *>(m), MtxSleeping,
- ZX_HANDLE_INVALID, ZX_TIME_INFINITE);
- if (status != ZX_ERR_BAD_STATE) // Normal race.
- CHECK_EQ(status, ZX_OK);
- }
-}
-
-void BlockingMutex::Unlock() {
- atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
- u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release);
- CHECK_NE(v, MtxUnlocked);
- if (v == MtxSleeping) {
- zx_status_t status = _zx_futex_wake(reinterpret_cast<zx_futex_t *>(m), 1);
- CHECK_EQ(status, ZX_OK);
- }
-}
-
-void BlockingMutex::CheckLocked() const {
- auto m = reinterpret_cast<atomic_uint32_t const *>(&opaque_storage_);
- CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
-}
-
uptr GetPageSize() { return _zx_system_get_page_size(); }
uptr GetMmapGranularity() { return _zx_system_get_page_size(); }
diff --git a/libsanitizer/sanitizer_common/sanitizer_hash.h b/libsanitizer/sanitizer_common/sanitizer_hash.h
index 3d97dcc..f7cf9f2 100644
--- a/libsanitizer/sanitizer_common/sanitizer_hash.h
+++ b/libsanitizer/sanitizer_common/sanitizer_hash.h
@@ -38,6 +38,30 @@ class MurMur2HashBuilder {
return x;
}
};
+
+class MurMur2Hash64Builder {
+ static const u64 m = 0xc6a4a7935bd1e995ull;
+ static const u64 seed = 0x9747b28c9747b28cull;
+ static const u64 r = 47;
+ u64 h;
+
+ public:
+ explicit MurMur2Hash64Builder(u64 init = 0) { h = seed ^ (init * m); }
+ void add(u64 k) {
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+ h ^= k;
+ h *= m;
+ }
+ u64 get() {
+ u64 x = h;
+ x ^= x >> r;
+ x *= m;
+ x ^= x >> r;
+ return x;
+ }
+};
} //namespace __sanitizer
#endif // SANITIZER_HASH_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc b/libsanitizer/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc
index 576807e..9683b97 100644
--- a/libsanitizer/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc
@@ -1406,7 +1406,7 @@ static void ioctl_table_fill() {
_(URIO_SEND_COMMAND, READWRITE, struct_urio_command_sz);
_(URIO_RECV_COMMAND, READWRITE, struct_urio_command_sz);
#undef _
-} // NOLINT
+}
static bool ioctl_initialized = false;
diff --git a/libsanitizer/sanitizer_common/sanitizer_interface_internal.h b/libsanitizer/sanitizer_common/sanitizer_interface_internal.h
index 0b001c1..1600d31 100644
--- a/libsanitizer/sanitizer_common/sanitizer_interface_internal.h
+++ b/libsanitizer/sanitizer_common/sanitizer_interface_internal.h
@@ -111,12 +111,13 @@ extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
void __sanitizer_cov_trace_pc_guard_init(__sanitizer::u32*,
__sanitizer::u32*);
- SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
- void __sanitizer_cov_8bit_counters_init();
+ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+ __sanitizer_cov_8bit_counters_init(char *, char *);
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
__sanitizer_cov_bool_flag_init();
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
- __sanitizer_cov_pcs_init();
+ __sanitizer_cov_pcs_init(const __sanitizer::uptr *,
+ const __sanitizer::uptr *);
} // extern "C"
#endif // SANITIZER_INTERFACE_INTERNAL_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
index 84053fe..e97cc9a 100644
--- a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
+++ b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
@@ -125,6 +125,10 @@
# define __has_attribute(x) 0
#endif
+#if !defined(__has_cpp_attribute)
+# define __has_cpp_attribute(x) 0
+#endif
+
// For portability reasons we do not include stddef.h, stdint.h or any other
// system header, but we do need some basic types that are not defined
// in a portable way by the language itself.
@@ -135,8 +139,13 @@ namespace __sanitizer {
typedef unsigned long long uptr;
typedef signed long long sptr;
#else
+# if (SANITIZER_WORDSIZE == 64) || SANITIZER_MAC || SANITIZER_WINDOWS
typedef unsigned long uptr;
typedef signed long sptr;
+# else
+typedef unsigned int uptr;
+typedef signed int sptr;
+# endif
#endif // defined(_WIN64)
#if defined(__x86_64__)
// Since x32 uses ILP32 data model in 64-bit hardware mode, we must use
@@ -168,10 +177,9 @@ typedef long pid_t;
typedef int pid_t;
#endif
-#if SANITIZER_FREEBSD || SANITIZER_NETBSD || \
- SANITIZER_MAC || \
+#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_MAC || \
(SANITIZER_SOLARIS && (defined(_LP64) || _FILE_OFFSET_BITS == 64)) || \
- (SANITIZER_LINUX && defined(__x86_64__))
+ (SANITIZER_LINUX && (defined(__x86_64__) || defined(__hexagon__)))
typedef u64 OFF_T;
#else
typedef uptr OFF_T;
@@ -250,6 +258,12 @@ typedef u64 tid_t;
# define NOEXCEPT throw()
#endif
+#if __has_cpp_attribute(clang::fallthrough)
+# define FALLTHROUGH [[clang::fallthrough]]
+#else
+# define FALLTHROUGH
+#endif
+
// Unaligned versions of basic types.
typedef ALIGNED(1) u16 uu16;
typedef ALIGNED(1) u32 uu32;
@@ -277,14 +291,16 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
u64 v1, u64 v2);
// Check macro
-#define RAW_CHECK_MSG(expr, msg) do { \
- if (UNLIKELY(!(expr))) { \
- RawWrite(msg); \
- Die(); \
- } \
-} while (0)
+#define RAW_CHECK_MSG(expr, msg, ...) \
+ do { \
+ if (UNLIKELY(!(expr))) { \
+ const char* msgs[] = {msg, __VA_ARGS__}; \
+ for (const char* m : msgs) RawWrite(m); \
+ Die(); \
+ } \
+ } while (0)
-#define RAW_CHECK(expr) RAW_CHECK_MSG(expr, #expr)
+#define RAW_CHECK(expr, ...) RAW_CHECK_MSG(expr, #expr "\n", __VA_ARGS__)
#define CHECK_IMPL(c1, op, c2) \
do { \
@@ -409,8 +425,14 @@ inline void Trap() {
(void)enable_fp; \
} while (0)
-constexpr u32 kInvalidTid = -1;
-constexpr u32 kMainTid = 0;
+// Internal thread identifier allocated by ThreadRegistry.
+typedef u32 Tid;
+constexpr Tid kInvalidTid = -1;
+constexpr Tid kMainTid = 0;
+
+// Stack depot stack identifier.
+typedef u32 StackID;
+const StackID kInvalidStackID = 0;
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_libc.cpp b/libsanitizer/sanitizer_common/sanitizer_libc.cpp
index 4bc04b4..d3076f0 100644
--- a/libsanitizer/sanitizer_common/sanitizer_libc.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_libc.cpp
@@ -258,6 +258,18 @@ s64 internal_simple_strtoll(const char *nptr, const char **endptr, int base) {
}
}
+uptr internal_wcslen(const wchar_t *s) {
+ uptr i = 0;
+ while (s[i]) i++;
+ return i;
+}
+
+uptr internal_wcsnlen(const wchar_t *s, uptr maxlen) {
+ uptr i = 0;
+ while (i < maxlen && s[i]) i++;
+ return i;
+}
+
bool mem_is_zero(const char *beg, uptr size) {
CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check.
const char *end = beg + size;
diff --git a/libsanitizer/sanitizer_common/sanitizer_libc.h b/libsanitizer/sanitizer_common/sanitizer_libc.h
index bcb81eb..39a2126 100644
--- a/libsanitizer/sanitizer_common/sanitizer_libc.h
+++ b/libsanitizer/sanitizer_common/sanitizer_libc.h
@@ -49,7 +49,10 @@ char *internal_strrchr(const char *s, int c);
char *internal_strstr(const char *haystack, const char *needle);
// Works only for base=10 and doesn't set errno.
s64 internal_simple_strtoll(const char *nptr, const char **endptr, int base);
-int internal_snprintf(char *buffer, uptr length, const char *format, ...);
+int internal_snprintf(char *buffer, uptr length, const char *format, ...)
+ FORMAT(3, 4);
+uptr internal_wcslen(const wchar_t *s);
+uptr internal_wcsnlen(const wchar_t *s, uptr maxlen);
// Return true if all bytes in [mem, mem+size) are zero.
// Optimized for the case when the result is true.
diff --git a/libsanitizer/sanitizer_common/sanitizer_libignore.cpp b/libsanitizer/sanitizer_common/sanitizer_libignore.cpp
index 431efc5..caaba31 100644
--- a/libsanitizer/sanitizer_common/sanitizer_libignore.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_libignore.cpp
@@ -22,9 +22,9 @@ LibIgnore::LibIgnore(LinkerInitialized) {
}
void LibIgnore::AddIgnoredLibrary(const char *name_templ) {
- BlockingMutexLock lock(&mutex_);
+ Lock lock(&mutex_);
if (count_ >= kMaxLibs) {
- Report("%s: too many ignored libraries (max: %d)\n", SanitizerToolName,
+ Report("%s: too many ignored libraries (max: %zu)\n", SanitizerToolName,
kMaxLibs);
Die();
}
@@ -36,7 +36,7 @@ void LibIgnore::AddIgnoredLibrary(const char *name_templ) {
}
void LibIgnore::OnLibraryLoaded(const char *name) {
- BlockingMutexLock lock(&mutex_);
+ Lock lock(&mutex_);
// Try to match suppressions with symlink target.
InternalMmapVector<char> buf(kMaxPathLength);
if (name && internal_readlink(name, buf.data(), buf.size() - 1) > 0 &&
@@ -84,7 +84,6 @@ void LibIgnore::OnLibraryLoaded(const char *name) {
ignored_code_ranges_[idx].begin = range.beg;
ignored_code_ranges_[idx].end = range.end;
atomic_store(&ignored_ranges_count_, idx + 1, memory_order_release);
- atomic_store(&enabled_, 1, memory_order_release);
break;
}
}
@@ -106,7 +105,7 @@ void LibIgnore::OnLibraryLoaded(const char *name) {
continue;
if (IsPcInstrumented(range.beg) && IsPcInstrumented(range.end - 1))
continue;
- VReport(1, "Adding instrumented range %p-%p from library '%s'\n",
+ VReport(1, "Adding instrumented range 0x%zx-0x%zx from library '%s'\n",
range.beg, range.end, mod.full_name());
const uptr idx =
atomic_load(&instrumented_ranges_count_, memory_order_relaxed);
@@ -115,7 +114,6 @@ void LibIgnore::OnLibraryLoaded(const char *name) {
instrumented_code_ranges_[idx].end = range.end;
atomic_store(&instrumented_ranges_count_, idx + 1,
memory_order_release);
- atomic_store(&enabled_, 1, memory_order_release);
}
}
}
@@ -125,29 +123,6 @@ void LibIgnore::OnLibraryUnloaded() {
OnLibraryLoaded(nullptr);
}
-bool LibIgnore::IsIgnoredSlow(uptr pc, bool *pc_in_ignored_lib) const {
- const uptr n = atomic_load(&ignored_ranges_count_, memory_order_acquire);
- for (uptr i = 0; i < n; i++) {
- if (IsInRange(pc, ignored_code_ranges_[i])) {
- *pc_in_ignored_lib = true;
- return true;
- }
- }
- *pc_in_ignored_lib = false;
- if (track_instrumented_libs_ && !IsPcInstrumented(pc))
- return true;
- return false;
-}
-
-bool LibIgnore::IsPcInstrumented(uptr pc) const {
- const uptr n = atomic_load(&instrumented_ranges_count_, memory_order_acquire);
- for (uptr i = 0; i < n; i++) {
- if (IsInRange(pc, instrumented_code_ranges_[i]))
- return true;
- }
- return false;
-}
-
} // namespace __sanitizer
#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC ||
diff --git a/libsanitizer/sanitizer_common/sanitizer_libignore.h b/libsanitizer/sanitizer_common/sanitizer_libignore.h
index 85452e5..18e4d83 100644
--- a/libsanitizer/sanitizer_common/sanitizer_libignore.h
+++ b/libsanitizer/sanitizer_common/sanitizer_libignore.h
@@ -45,6 +45,9 @@ class LibIgnore {
// "pc_in_ignored_lib" if the PC is in an ignored library, false otherwise.
bool IsIgnored(uptr pc, bool *pc_in_ignored_lib) const;
+ // Checks whether the provided PC belongs to an instrumented module.
+ bool IsPcInstrumented(uptr pc) const;
+
private:
struct Lib {
char *templ;
@@ -58,10 +61,6 @@ class LibIgnore {
uptr end;
};
- // Checks whether the provided PC belongs to an instrumented module.
- bool IsPcInstrumented(uptr pc) const;
- bool IsIgnoredSlow(uptr pc, bool *pc_in_ignored_lib) const;
-
inline bool IsInRange(uptr pc, const LibCodeRange &range) const {
return (pc >= range.begin && pc < range.end);
}
@@ -71,8 +70,6 @@ class LibIgnore {
static const uptr kMaxLibs = 1024;
// Hot part:
- atomic_uintptr_t enabled_;
-
atomic_uintptr_t ignored_ranges_count_;
LibCodeRange ignored_code_ranges_[kMaxIgnoredRanges];
@@ -80,7 +77,7 @@ class LibIgnore {
LibCodeRange instrumented_code_ranges_[kMaxInstrumentedRanges];
// Cold part:
- BlockingMutex mutex_;
+ Mutex mutex_;
uptr count_;
Lib libs_[kMaxLibs];
bool track_instrumented_libs_;
@@ -90,11 +87,27 @@ class LibIgnore {
void operator = (const LibIgnore&); // not implemented
};
-ALWAYS_INLINE
-bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const {
- if (LIKELY(atomic_load(&enabled_, memory_order_acquire) == 0))
- return false;
- return IsIgnoredSlow(pc, pc_in_ignored_lib);
+inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const {
+ const uptr n = atomic_load(&ignored_ranges_count_, memory_order_acquire);
+ for (uptr i = 0; i < n; i++) {
+ if (IsInRange(pc, ignored_code_ranges_[i])) {
+ *pc_in_ignored_lib = true;
+ return true;
+ }
+ }
+ *pc_in_ignored_lib = false;
+ if (track_instrumented_libs_ && !IsPcInstrumented(pc))
+ return true;
+ return false;
+}
+
+inline bool LibIgnore::IsPcInstrumented(uptr pc) const {
+ const uptr n = atomic_load(&instrumented_ranges_count_, memory_order_acquire);
+ for (uptr i = 0; i < n; i++) {
+ if (IsInRange(pc, instrumented_code_ranges_[i]))
+ return true;
+ }
+ return false;
}
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.cpp b/libsanitizer/sanitizer_common/sanitizer_linux.cpp
index 9b7d87e..ea3e5bd 100644
--- a/libsanitizer/sanitizer_common/sanitizer_linux.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_linux.cpp
@@ -158,9 +158,11 @@ namespace __sanitizer {
#include "sanitizer_syscall_linux_aarch64.inc"
#elif SANITIZER_LINUX && defined(__arm__)
#include "sanitizer_syscall_linux_arm.inc"
-#else
-#include "sanitizer_syscall_generic.inc"
-#endif
+# elif SANITIZER_LINUX && defined(__hexagon__)
+# include "sanitizer_syscall_linux_hexagon.inc"
+# else
+# include "sanitizer_syscall_generic.inc"
+# endif
// --------------- sanitizer_libc.h
#if !SANITIZER_SOLARIS && !SANITIZER_NETBSD
@@ -415,7 +417,7 @@ uptr internal_unlink(const char *path) {
}
uptr internal_rename(const char *oldpath, const char *newpath) {
-#if defined(__riscv)
+#if defined(__riscv) && defined(__linux__)
return internal_syscall(SYSCALL(renameat2), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
(uptr)newpath, 0);
#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
@@ -659,48 +661,6 @@ void FutexWake(atomic_uint32_t *p, u32 count) {
# endif
}
-enum { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 };
-
-BlockingMutex::BlockingMutex() {
- internal_memset(this, 0, sizeof(*this));
-}
-
-void BlockingMutex::Lock() {
- CHECK_EQ(owner_, 0);
- atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
- if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
- return;
- while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
-#if SANITIZER_FREEBSD
- _umtx_op(m, UMTX_OP_WAIT_UINT, MtxSleeping, 0, 0);
-#elif SANITIZER_NETBSD
- sched_yield(); /* No userspace futex-like synchronization */
-#else
- internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAIT_PRIVATE, MtxSleeping,
- 0, 0, 0);
-#endif
- }
-}
-
-void BlockingMutex::Unlock() {
- atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
- u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release);
- CHECK_NE(v, MtxUnlocked);
- if (v == MtxSleeping) {
-#if SANITIZER_FREEBSD
- _umtx_op(m, UMTX_OP_WAKE, 1, 0, 0);
-#elif SANITIZER_NETBSD
- /* No userspace futex-like synchronization */
-#else
- internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAKE_PRIVATE, 1, 0, 0, 0);
-#endif
- }
-}
-
-void BlockingMutex::CheckLocked() const {
- auto m = reinterpret_cast<atomic_uint32_t const *>(&opaque_storage_);
- CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
-}
# endif // !SANITIZER_SOLARIS
// ----------------- sanitizer_linux.h
@@ -1217,7 +1177,8 @@ void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
}
#endif
-#if defined(__x86_64__) && SANITIZER_LINUX
+#if SANITIZER_LINUX
+#if defined(__x86_64__)
// We cannot use glibc's clone wrapper, because it messes with the child
// task's TLS. It writes the PID and TID of the child task to its thread
// descriptor, but in our case the child task shares the thread descriptor with
@@ -1556,7 +1517,7 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
: "cr0", "cr1", "memory", "ctr", "r0", "r27", "r28", "r29");
return res;
}
-#elif defined(__i386__) && SANITIZER_LINUX
+#elif defined(__i386__)
uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
int *parent_tidptr, void *newtls, int *child_tidptr) {
int res;
@@ -1621,7 +1582,7 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
: "memory");
return res;
}
-#elif defined(__arm__) && SANITIZER_LINUX
+#elif defined(__arm__)
uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
int *parent_tidptr, void *newtls, int *child_tidptr) {
unsigned int res;
@@ -1687,7 +1648,8 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
: "memory");
return res;
}
-#endif // defined(__x86_64__) && SANITIZER_LINUX
+#endif
+#endif // SANITIZER_LINUX
#if SANITIZER_LINUX
int internal_uname(struct utsname *buf) {
@@ -1917,7 +1879,11 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
u32 instr = *(u32 *)pc;
return (instr >> 21) & 1 ? WRITE: READ;
#elif defined(__riscv)
+#if SANITIZER_FREEBSD
+ unsigned long pc = ucontext->uc_mcontext.mc_gpregs.gp_sepc;
+#else
unsigned long pc = ucontext->uc_mcontext.__gregs[REG_PC];
+#endif
unsigned faulty_instruction = *(uint16_t *)pc;
#if defined(__riscv_compressed)
@@ -2136,12 +2102,23 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
*sp = ucontext->uc_mcontext.gregs[15];
#elif defined(__riscv)
ucontext_t *ucontext = (ucontext_t*)context;
+# if SANITIZER_FREEBSD
+ *pc = ucontext->uc_mcontext.mc_gpregs.gp_sepc;
+ *bp = ucontext->uc_mcontext.mc_gpregs.gp_s[0];
+ *sp = ucontext->uc_mcontext.mc_gpregs.gp_sp;
+# else
*pc = ucontext->uc_mcontext.__gregs[REG_PC];
*bp = ucontext->uc_mcontext.__gregs[REG_S0];
*sp = ucontext->uc_mcontext.__gregs[REG_SP];
-#else
-# error "Unsupported arch"
-#endif
+# endif
+# elif defined(__hexagon__)
+ ucontext_t *ucontext = (ucontext_t *)context;
+ *pc = ucontext->uc_mcontext.pc;
+ *bp = ucontext->uc_mcontext.r30;
+ *sp = ucontext->uc_mcontext.r29;
+# else
+# error "Unsupported arch"
+# endif
}
void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); }
diff --git a/libsanitizer/sanitizer_common/sanitizer_local_address_space_view.h b/libsanitizer/sanitizer_common/sanitizer_local_address_space_view.h
index 0e19c4d..a47cfc9 100644
--- a/libsanitizer/sanitizer_common/sanitizer_local_address_space_view.h
+++ b/libsanitizer/sanitizer_common/sanitizer_local_address_space_view.h
@@ -17,7 +17,7 @@
// instantiated with the `LocalAddressSpaceView` type. This type is used to
// load any pointers in instance methods. This implementation is effectively
// a no-op. When an object is to be used in an out-of-process manner it is
-// instansiated with the `RemoteAddressSpaceView` type.
+// instantiated with the `RemoteAddressSpaceView` type.
//
// By making `AddressSpaceView` a template parameter of an object, it can
// change its implementation at compile time which has no run time overhead.
diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.cpp b/libsanitizer/sanitizer_common/sanitizer_mac.cpp
index 0aafbdb..fa077a1 100644
--- a/libsanitizer/sanitizer_common/sanitizer_mac.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_mac.cpp
@@ -524,25 +524,6 @@ void FutexWait(atomic_uint32_t *p, u32 cmp) {
void FutexWake(atomic_uint32_t *p, u32 count) {}
-BlockingMutex::BlockingMutex() {
- internal_memset(this, 0, sizeof(*this));
-}
-
-void BlockingMutex::Lock() {
- CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_));
- CHECK_EQ(OS_SPINLOCK_INIT, 0);
- CHECK_EQ(owner_, 0);
- OSSpinLockLock((OSSpinLock*)&opaque_storage_);
-}
-
-void BlockingMutex::Unlock() {
- OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
-}
-
-void BlockingMutex::CheckLocked() const {
- CHECK_NE(*(OSSpinLock*)&opaque_storage_, 0);
-}
-
u64 NanoTime() {
timeval tv;
internal_memset(&tv, 0, sizeof(tv));
@@ -792,8 +773,8 @@ void *internal_start_thread(void *(*func)(void *arg), void *arg) {
void internal_join_thread(void *th) { pthread_join((pthread_t)th, 0); }
#if !SANITIZER_GO
-static BlockingMutex syslog_lock(LINKER_INITIALIZED);
-#endif
+static Mutex syslog_lock;
+# endif
void WriteOneLineToSyslog(const char *s) {
#if !SANITIZER_GO
@@ -808,7 +789,7 @@ void WriteOneLineToSyslog(const char *s) {
// buffer to store crash report application information
static char crashreporter_info_buff[__sanitizer::kErrorMessageBufferSize] = {};
-static BlockingMutex crashreporter_info_mutex(LINKER_INITIALIZED);
+static Mutex crashreporter_info_mutex;
extern "C" {
// Integrate with crash reporter libraries.
@@ -838,7 +819,7 @@ asm(".desc ___crashreporter_info__, 0x10");
} // extern "C"
static void CRAppendCrashLogMessage(const char *msg) {
- BlockingMutexLock l(&crashreporter_info_mutex);
+ Lock l(&crashreporter_info_mutex);
internal_strlcat(crashreporter_info_buff, msg,
sizeof(crashreporter_info_buff));
#if HAVE_CRASHREPORTERCLIENT_H
@@ -882,7 +863,7 @@ void LogFullErrorReport(const char *buffer) {
// the reporting thread holds the thread registry mutex, and asl_log waits
// for GCD to dispatch a new thread, the process will deadlock, because the
// pthread_create wrapper needs to acquire the lock as well.
- BlockingMutexLock l(&syslog_lock);
+ Lock l(&syslog_lock);
if (common_flags()->log_to_syslog)
WriteToSyslog(buffer);
diff --git a/libsanitizer/sanitizer_common/sanitizer_mutex.cpp b/libsanitizer/sanitizer_common/sanitizer_mutex.cpp
index bc2d83c..1c177d8 100644
--- a/libsanitizer/sanitizer_common/sanitizer_mutex.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_mutex.cpp
@@ -16,6 +16,18 @@
namespace __sanitizer {
+void StaticSpinMutex::LockSlow() {
+ for (int i = 0;; i++) {
+ if (i < 100)
+ proc_yield(1);
+ else
+ internal_sched_yield();
+ if (atomic_load(&state_, memory_order_relaxed) == 0 &&
+ atomic_exchange(&state_, 1, memory_order_acquire) == 0)
+ return;
+ }
+}
+
void Semaphore::Wait() {
u32 count = atomic_load(&state_, memory_order_relaxed);
for (;;) {
@@ -36,4 +48,178 @@ void Semaphore::Post(u32 count) {
FutexWake(&state_, count);
}
+#if SANITIZER_CHECK_DEADLOCKS
+// An empty mutex meta table, it effectively disables deadlock detection.
+// Each tool can override the table to define own mutex hierarchy and
+// enable deadlock detection.
+// The table defines a static mutex type hierarchy (what mutex types can be locked
+// under what mutex types). This table is checked to be acyclic and then
+// actual mutex lock/unlock operations are checked to adhere to this hierarchy.
+// The checking happens on mutex types rather than on individual mutex instances
+// because doing it on mutex instances will both significantly complicate
+// the implementation, worsen performance and memory overhead and is mostly
+// unnecessary (we almost never lock multiple mutexes of the same type recursively).
+static constexpr int kMutexTypeMax = 20;
+SANITIZER_WEAK_ATTRIBUTE MutexMeta mutex_meta[kMutexTypeMax] = {};
+SANITIZER_WEAK_ATTRIBUTE void PrintMutexPC(uptr pc) {}
+static StaticSpinMutex mutex_meta_mtx;
+static int mutex_type_count = -1;
+// Adjacency matrix of what mutexes can be locked under what mutexes.
+static bool mutex_can_lock[kMutexTypeMax][kMutexTypeMax];
+// Mutex types with MutexMulti mark.
+static bool mutex_multi[kMutexTypeMax];
+
+void DebugMutexInit() {
+ // Build adjacency matrix.
+ bool leaf[kMutexTypeMax];
+ internal_memset(&leaf, 0, sizeof(leaf));
+ int cnt[kMutexTypeMax];
+ internal_memset(&cnt, 0, sizeof(cnt));
+ for (int t = 0; t < kMutexTypeMax; t++) {
+ mutex_type_count = t;
+ if (!mutex_meta[t].name)
+ break;
+ CHECK_EQ(t, mutex_meta[t].type);
+ for (uptr j = 0; j < ARRAY_SIZE(mutex_meta[t].can_lock); j++) {
+ MutexType z = mutex_meta[t].can_lock[j];
+ if (z == MutexInvalid)
+ break;
+ if (z == MutexLeaf) {
+ CHECK(!leaf[t]);
+ leaf[t] = true;
+ continue;
+ }
+ if (z == MutexMulti) {
+ mutex_multi[t] = true;
+ continue;
+ }
+ CHECK_LT(z, kMutexTypeMax);
+ CHECK(!mutex_can_lock[t][z]);
+ mutex_can_lock[t][z] = true;
+ cnt[t]++;
+ }
+ }
+ // Indicates the array is not properly terminated.
+ CHECK_LT(mutex_type_count, kMutexTypeMax);
+ // Add leaf mutexes.
+ for (int t = 0; t < mutex_type_count; t++) {
+ if (!leaf[t])
+ continue;
+ CHECK_EQ(cnt[t], 0);
+ for (int z = 0; z < mutex_type_count; z++) {
+ if (z == MutexInvalid || t == z || leaf[z])
+ continue;
+ CHECK(!mutex_can_lock[z][t]);
+ mutex_can_lock[z][t] = true;
+ }
+ }
+ // Build the transitive closure and check that the graphs is acyclic.
+ u32 trans[kMutexTypeMax];
+ static_assert(sizeof(trans[0]) * 8 >= kMutexTypeMax,
+ "kMutexTypeMax does not fit into u32, switch to u64");
+ internal_memset(&trans, 0, sizeof(trans));
+ for (int i = 0; i < mutex_type_count; i++) {
+ for (int j = 0; j < mutex_type_count; j++)
+ if (mutex_can_lock[i][j])
+ trans[i] |= 1 << j;
+ }
+ for (int k = 0; k < mutex_type_count; k++) {
+ for (int i = 0; i < mutex_type_count; i++) {
+ if (trans[i] & (1 << k))
+ trans[i] |= trans[k];
+ }
+ }
+ for (int i = 0; i < mutex_type_count; i++) {
+ if (trans[i] & (1 << i)) {
+ Printf("Mutex %s participates in a cycle\n", mutex_meta[i].name);
+ Die();
+ }
+ }
+}
+
+struct InternalDeadlockDetector {
+ struct LockDesc {
+ u64 seq;
+ uptr pc;
+ int recursion;
+ };
+ int initialized;
+ u64 sequence;
+ LockDesc locked[kMutexTypeMax];
+
+ void Lock(MutexType type, uptr pc) {
+ if (!Initialize(type))
+ return;
+ CHECK_LT(type, mutex_type_count);
+ // Find the last locked mutex type.
+ // This is the type we will use for hierarchy checks.
+ u64 max_seq = 0;
+ MutexType max_idx = MutexInvalid;
+ for (int i = 0; i != mutex_type_count; i++) {
+ if (locked[i].seq == 0)
+ continue;
+ CHECK_NE(locked[i].seq, max_seq);
+ if (max_seq < locked[i].seq) {
+ max_seq = locked[i].seq;
+ max_idx = (MutexType)i;
+ }
+ }
+ if (max_idx == type && mutex_multi[type]) {
+ // Recursive lock of the same type.
+ CHECK_EQ(locked[type].seq, max_seq);
+ CHECK(locked[type].pc);
+ locked[type].recursion++;
+ return;
+ }
+ if (max_idx != MutexInvalid && !mutex_can_lock[max_idx][type]) {
+ Printf("%s: internal deadlock: can't lock %s under %s mutex\n", SanitizerToolName,
+ mutex_meta[type].name, mutex_meta[max_idx].name);
+ PrintMutexPC(pc);
+ CHECK(0);
+ }
+ locked[type].seq = ++sequence;
+ locked[type].pc = pc;
+ locked[type].recursion = 1;
+ }
+
+ void Unlock(MutexType type) {
+ if (!Initialize(type))
+ return;
+ CHECK_LT(type, mutex_type_count);
+ CHECK(locked[type].seq);
+ CHECK_GT(locked[type].recursion, 0);
+ if (--locked[type].recursion)
+ return;
+ locked[type].seq = 0;
+ locked[type].pc = 0;
+ }
+
+ void CheckNoLocks() {
+ for (int i = 0; i < mutex_type_count; i++) CHECK_EQ(locked[i].recursion, 0);
+ }
+
+ bool Initialize(MutexType type) {
+ if (type == MutexUnchecked || type == MutexInvalid)
+ return false;
+ CHECK_GT(type, MutexInvalid);
+ if (initialized != 0)
+ return initialized > 0;
+ initialized = -1;
+ SpinMutexLock lock(&mutex_meta_mtx);
+ if (mutex_type_count < 0)
+ DebugMutexInit();
+ initialized = mutex_type_count ? 1 : -1;
+ return initialized > 0;
+ }
+};
+
+static THREADLOCAL InternalDeadlockDetector deadlock_detector;
+
+void CheckedMutex::LockImpl(uptr pc) { deadlock_detector.Lock(type_, pc); }
+
+void CheckedMutex::UnlockImpl() { deadlock_detector.Unlock(type_); }
+
+void CheckedMutex::CheckNoLocksImpl() { deadlock_detector.CheckNoLocks(); }
+#endif
+
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_mutex.h b/libsanitizer/sanitizer_common/sanitizer_mutex.h
index e3ff650..7479d35 100644
--- a/libsanitizer/sanitizer_common/sanitizer_mutex.h
+++ b/libsanitizer/sanitizer_common/sanitizer_mutex.h
@@ -27,7 +27,7 @@ class MUTEX StaticSpinMutex {
}
void Lock() ACQUIRE() {
- if (TryLock())
+ if (LIKELY(TryLock()))
return;
LockSlow();
}
@@ -45,17 +45,7 @@ class MUTEX StaticSpinMutex {
private:
atomic_uint8_t state_;
- void NOINLINE LockSlow() {
- for (int i = 0;; i++) {
- if (i < 10)
- proc_yield(10);
- else
- internal_sched_yield();
- if (atomic_load(&state_, memory_order_relaxed) == 0
- && atomic_exchange(&state_, 1, memory_order_acquire) == 0)
- return;
- }
- }
+ void LockSlow();
};
class MUTEX SpinMutex : public StaticSpinMutex {
@@ -64,7 +54,6 @@ class MUTEX SpinMutex : public StaticSpinMutex {
Init();
}
- private:
SpinMutex(const SpinMutex &) = delete;
void operator=(const SpinMutex &) = delete;
};
@@ -85,15 +74,94 @@ class Semaphore {
atomic_uint32_t state_ = {0};
};
+typedef int MutexType;
+
+enum {
+ // Used as sentinel and to catch unassigned types
+ // (should not be used as real Mutex type).
+ MutexInvalid = 0,
+ MutexThreadRegistry,
+ // Each tool own mutexes must start at this number.
+ MutexLastCommon,
+ // Type for legacy mutexes that are not checked for deadlocks.
+ MutexUnchecked = -1,
+ // Special marks that can be used in MutexMeta::can_lock table.
+ // The leaf mutexes can be locked under any other non-leaf mutex,
+ // but no other mutex can be locked while under a leaf mutex.
+ MutexLeaf = -1,
+ // Multiple mutexes of this type can be locked at the same time.
+ MutexMulti = -3,
+};
+
+// Go linker does not support THREADLOCAL variables,
+// so we can't use per-thread state.
+#define SANITIZER_CHECK_DEADLOCKS \
+ (SANITIZER_DEBUG && !SANITIZER_GO && SANITIZER_SUPPORTS_THREADLOCAL)
+
+#if SANITIZER_CHECK_DEADLOCKS
+struct MutexMeta {
+ MutexType type;
+ const char *name;
+ // The table fixes what mutexes can be locked under what mutexes.
+ // If the entry for MutexTypeFoo contains MutexTypeBar,
+ // then Bar mutex can be locked while under Foo mutex.
+ // Can also contain the special MutexLeaf/MutexMulti marks.
+ MutexType can_lock[10];
+};
+#endif
+
+class CheckedMutex {
+ public:
+ explicit constexpr CheckedMutex(MutexType type)
+#if SANITIZER_CHECK_DEADLOCKS
+ : type_(type)
+#endif
+ {
+ }
+
+ ALWAYS_INLINE void Lock() {
+#if SANITIZER_CHECK_DEADLOCKS
+ LockImpl(GET_CALLER_PC());
+#endif
+ }
+
+ ALWAYS_INLINE void Unlock() {
+#if SANITIZER_CHECK_DEADLOCKS
+ UnlockImpl();
+#endif
+ }
+
+ // Checks that the current thread does not hold any mutexes
+ // (e.g. when returning from a runtime function to user code).
+ static void CheckNoLocks() {
+#if SANITIZER_CHECK_DEADLOCKS
+ CheckNoLocksImpl();
+#endif
+ }
+
+ private:
+#if SANITIZER_CHECK_DEADLOCKS
+ const MutexType type_;
+
+ void LockImpl(uptr pc);
+ void UnlockImpl();
+ static void CheckNoLocksImpl();
+#endif
+};
+
// Reader-writer mutex.
-class MUTEX Mutex2 {
+// Derive from CheckedMutex for the purposes of EBO.
+// We could make it a field marked with [[no_unique_address]],
+// but this attribute is not supported by some older compilers.
+class MUTEX Mutex : CheckedMutex {
public:
- constexpr Mutex2() {}
+ explicit constexpr Mutex(MutexType type = MutexUnchecked)
+ : CheckedMutex(type) {}
void Lock() ACQUIRE() {
+ CheckedMutex::Lock();
u64 reset_mask = ~0ull;
u64 state = atomic_load_relaxed(&state_);
- const uptr kMaxSpinIters = 1500;
for (uptr spin_iters = 0;; spin_iters++) {
u64 new_state;
bool locked = (state & (kWriterLock | kReaderLockMask)) != 0;
@@ -122,8 +190,6 @@ class MUTEX Mutex2 {
// We've incremented waiting writers, so now block.
writers_.Wait();
spin_iters = 0;
- state = atomic_load(&state_, memory_order_relaxed);
- DCHECK_NE(state & kWriterSpinWait, 0);
} else {
// We've set kWriterSpinWait, but we are still in active spinning.
}
@@ -132,10 +198,13 @@ class MUTEX Mutex2 {
// Either way we need to reset kWriterSpinWait
// next time we take the lock or block again.
reset_mask = ~kWriterSpinWait;
+ state = atomic_load(&state_, memory_order_relaxed);
+ DCHECK_NE(state & kWriterSpinWait, 0);
}
}
void Unlock() RELEASE() {
+ CheckedMutex::Unlock();
bool wake_writer;
u64 wake_readers;
u64 new_state;
@@ -144,17 +213,16 @@ class MUTEX Mutex2 {
DCHECK_NE(state & kWriterLock, 0);
DCHECK_EQ(state & kReaderLockMask, 0);
new_state = state & ~kWriterLock;
- wake_writer =
- (state & kWriterSpinWait) == 0 && (state & kWaitingWriterMask) != 0;
+ wake_writer = (state & (kWriterSpinWait | kReaderSpinWait)) == 0 &&
+ (state & kWaitingWriterMask) != 0;
if (wake_writer)
new_state = (new_state - kWaitingWriterInc) | kWriterSpinWait;
wake_readers =
- (state & (kWriterSpinWait | kWaitingWriterMask)) != 0
+ wake_writer || (state & kWriterSpinWait) != 0
? 0
: ((state & kWaitingReaderMask) >> kWaitingReaderShift);
if (wake_readers)
- new_state = (new_state & ~kWaitingReaderMask) +
- (wake_readers << kReaderLockShift);
+ new_state = (new_state & ~kWaitingReaderMask) | kReaderSpinWait;
} while (UNLIKELY(!atomic_compare_exchange_weak(&state_, &state, new_state,
memory_order_release)));
if (UNLIKELY(wake_writer))
@@ -164,34 +232,53 @@ class MUTEX Mutex2 {
}
void ReadLock() ACQUIRE_SHARED() {
- bool locked;
- u64 new_state;
+ CheckedMutex::Lock();
+ u64 reset_mask = ~0ull;
u64 state = atomic_load_relaxed(&state_);
- do {
- locked =
- (state & kReaderLockMask) == 0 &&
- (state & (kWriterLock | kWriterSpinWait | kWaitingWriterMask)) != 0;
+ for (uptr spin_iters = 0;; spin_iters++) {
+ bool locked = (state & kWriterLock) != 0;
+ u64 new_state;
+ if (LIKELY(!locked)) {
+ new_state = (state + kReaderLockInc) & reset_mask;
+ } else if (spin_iters > kMaxSpinIters) {
+ new_state = (state + kWaitingReaderInc) & reset_mask;
+ } else if ((state & kReaderSpinWait) == 0) {
+ // Active spinning, but denote our presence so that unlocking
+ // thread does not wake up other threads.
+ new_state = state | kReaderSpinWait;
+ } else {
+ // Active spinning.
+ state = atomic_load(&state_, memory_order_relaxed);
+ continue;
+ }
+ if (UNLIKELY(!atomic_compare_exchange_weak(&state_, &state, new_state,
+ memory_order_acquire)))
+ continue;
if (LIKELY(!locked))
- new_state = state + kReaderLockInc;
- else
- new_state = state + kWaitingReaderInc;
- } while (UNLIKELY(!atomic_compare_exchange_weak(&state_, &state, new_state,
- memory_order_acquire)));
- if (UNLIKELY(locked))
- readers_.Wait();
- DCHECK_EQ(atomic_load_relaxed(&state_) & kWriterLock, 0);
- DCHECK_NE(atomic_load_relaxed(&state_) & kReaderLockMask, 0);
+ return; // We've locked the mutex.
+ if (spin_iters > kMaxSpinIters) {
+ // We've incremented waiting readers, so now block.
+ readers_.Wait();
+ spin_iters = 0;
+ } else {
+ // We've set kReaderSpinWait, but we are still in active spinning.
+ }
+ reset_mask = ~kReaderSpinWait;
+ state = atomic_load(&state_, memory_order_relaxed);
+ }
}
void ReadUnlock() RELEASE_SHARED() {
+ CheckedMutex::Unlock();
bool wake;
u64 new_state;
u64 state = atomic_load_relaxed(&state_);
do {
DCHECK_NE(state & kReaderLockMask, 0);
- DCHECK_EQ(state & (kWaitingReaderMask | kWriterLock), 0);
+ DCHECK_EQ(state & kWriterLock, 0);
new_state = state - kReaderLockInc;
- wake = (new_state & (kReaderLockMask | kWriterSpinWait)) == 0 &&
+ wake = (new_state &
+ (kReaderLockMask | kWriterSpinWait | kReaderSpinWait)) == 0 &&
(new_state & kWaitingWriterMask) != 0;
if (wake)
new_state = (new_state - kWaitingWriterInc) | kWriterSpinWait;
@@ -235,16 +322,14 @@ class MUTEX Mutex2 {
// - a writer is awake and spin-waiting
// the flag is used to prevent thundering herd problem
// (new writers are not woken if this flag is set)
+ // - a reader is awake and spin-waiting
//
- // Writer support active spinning, readers does not.
+ // Both writers and readers use active spinning before blocking.
// But readers are more aggressive and always take the mutex
// if there are any other readers.
- // Writers hand off the mutex to readers: after wake up readers
- // already assume ownership of the mutex (don't need to do any
- // state updates). But the mutex is not handed off to writers,
- // after wake up writers compete to lock the mutex again.
- // This is needed to allow repeated write locks even in presence
- // of other blocked writers.
+ // After wake up both writers and readers compete to lock the
+ // mutex again. This is needed to allow repeated locks even in presence
+ // of other blocked threads.
static constexpr u64 kCounterWidth = 20;
static constexpr u64 kReaderLockShift = 0;
static constexpr u64 kReaderLockInc = 1ull << kReaderLockShift;
@@ -260,119 +345,18 @@ class MUTEX Mutex2 {
<< kWaitingWriterShift;
static constexpr u64 kWriterLock = 1ull << (3 * kCounterWidth);
static constexpr u64 kWriterSpinWait = 1ull << (3 * kCounterWidth + 1);
+ static constexpr u64 kReaderSpinWait = 1ull << (3 * kCounterWidth + 2);
+
+ static constexpr uptr kMaxSpinIters = 1500;
- Mutex2(const Mutex2 &) = delete;
- void operator=(const Mutex2 &) = delete;
+ Mutex(LinkerInitialized) = delete;
+ Mutex(const Mutex &) = delete;
+ void operator=(const Mutex &) = delete;
};
void FutexWait(atomic_uint32_t *p, u32 cmp);
void FutexWake(atomic_uint32_t *p, u32 count);
-class MUTEX BlockingMutex {
- public:
- explicit constexpr BlockingMutex(LinkerInitialized)
- : opaque_storage_ {0, }, owner_ {0} {}
- BlockingMutex();
- void Lock() ACQUIRE();
- void Unlock() RELEASE();
-
- // This function does not guarantee an explicit check that the calling thread
- // is the thread which owns the mutex. This behavior, while more strictly
- // correct, causes problems in cases like StopTheWorld, where a parent thread
- // owns the mutex but a child checks that it is locked. Rather than
- // maintaining complex state to work around those situations, the check only
- // checks that the mutex is owned, and assumes callers to be generally
- // well-behaved.
- void CheckLocked() const CHECK_LOCKED();
-
- private:
- // Solaris mutex_t has a member that requires 64-bit alignment.
- ALIGNED(8) uptr opaque_storage_[10];
- uptr owner_; // for debugging
-};
-
-// Reader-writer spin mutex.
-class MUTEX RWMutex {
- public:
- RWMutex() {
- atomic_store(&state_, kUnlocked, memory_order_relaxed);
- }
-
- ~RWMutex() {
- CHECK_EQ(atomic_load(&state_, memory_order_relaxed), kUnlocked);
- }
-
- void Lock() ACQUIRE() {
- u32 cmp = kUnlocked;
- if (atomic_compare_exchange_strong(&state_, &cmp, kWriteLock,
- memory_order_acquire))
- return;
- LockSlow();
- }
-
- void Unlock() RELEASE() {
- u32 prev = atomic_fetch_sub(&state_, kWriteLock, memory_order_release);
- DCHECK_NE(prev & kWriteLock, 0);
- (void)prev;
- }
-
- void ReadLock() ACQUIRE_SHARED() {
- u32 prev = atomic_fetch_add(&state_, kReadLock, memory_order_acquire);
- if ((prev & kWriteLock) == 0)
- return;
- ReadLockSlow();
- }
-
- void ReadUnlock() RELEASE_SHARED() {
- u32 prev = atomic_fetch_sub(&state_, kReadLock, memory_order_release);
- DCHECK_EQ(prev & kWriteLock, 0);
- DCHECK_GT(prev & ~kWriteLock, 0);
- (void)prev;
- }
-
- void CheckLocked() const CHECK_LOCKED() {
- CHECK_NE(atomic_load(&state_, memory_order_relaxed), kUnlocked);
- }
-
- private:
- atomic_uint32_t state_;
-
- enum {
- kUnlocked = 0,
- kWriteLock = 1,
- kReadLock = 2
- };
-
- void NOINLINE LockSlow() {
- for (int i = 0;; i++) {
- if (i < 10)
- proc_yield(10);
- else
- internal_sched_yield();
- u32 cmp = atomic_load(&state_, memory_order_relaxed);
- if (cmp == kUnlocked &&
- atomic_compare_exchange_weak(&state_, &cmp, kWriteLock,
- memory_order_acquire))
- return;
- }
- }
-
- void NOINLINE ReadLockSlow() {
- for (int i = 0;; i++) {
- if (i < 10)
- proc_yield(10);
- else
- internal_sched_yield();
- u32 prev = atomic_load(&state_, memory_order_acquire);
- if ((prev & kWriteLock) == 0)
- return;
- }
- }
-
- RWMutex(const RWMutex &) = delete;
- void operator=(const RWMutex &) = delete;
-};
-
template <typename MutexType>
class SCOPED_LOCK GenericScopedLock {
public:
@@ -405,10 +389,37 @@ class SCOPED_LOCK GenericScopedReadLock {
void operator=(const GenericScopedReadLock &) = delete;
};
+template <typename MutexType>
+class SCOPED_LOCK GenericScopedRWLock {
+ public:
+ ALWAYS_INLINE explicit GenericScopedRWLock(MutexType *mu, bool write)
+ ACQUIRE(mu)
+ : mu_(mu), write_(write) {
+ if (write_)
+ mu_->Lock();
+ else
+ mu_->ReadLock();
+ }
+
+ ALWAYS_INLINE ~GenericScopedRWLock() RELEASE() {
+ if (write_)
+ mu_->Unlock();
+ else
+ mu_->ReadUnlock();
+ }
+
+ private:
+ MutexType *mu_;
+ bool write_;
+
+ GenericScopedRWLock(const GenericScopedRWLock &) = delete;
+ void operator=(const GenericScopedRWLock &) = delete;
+};
+
typedef GenericScopedLock<StaticSpinMutex> SpinMutexLock;
-typedef GenericScopedLock<BlockingMutex> BlockingMutexLock;
-typedef GenericScopedLock<RWMutex> RWMutexLock;
-typedef GenericScopedReadLock<RWMutex> RWMutexReadLock;
+typedef GenericScopedLock<Mutex> Lock;
+typedef GenericScopedReadLock<Mutex> ReadLock;
+typedef GenericScopedRWLock<Mutex> RWLock;
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform.h b/libsanitizer/sanitizer_common/sanitizer_platform.h
index 4d3c088..3153de3 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform.h
@@ -281,11 +281,12 @@
// mandated by the upstream linux community for all new ports. Other ports
// may still use legacy syscalls.
#ifndef SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
-# if (defined(__aarch64__) || defined(__riscv)) && SANITIZER_LINUX
-# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1
-# else
-# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0
-# endif
+# if (defined(__aarch64__) || defined(__riscv) || defined(__hexagon__)) && \
+ SANITIZER_LINUX
+# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1
+# else
+# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0
+# endif
#endif
// udi16 syscalls can only be used when the following conditions are
@@ -377,4 +378,18 @@
#define SANITIZER_SUPPORTS_INIT_FOR_DLOPEN 0
#endif
+// SANITIZER_SUPPORTS_THREADLOCAL
+// 1 - THREADLOCAL macro is supported by target
+// 0 - THREADLOCAL macro is not supported by target
+#ifndef __has_feature
+// TODO: Support other compilers here
+# define SANITIZER_SUPPORTS_THREADLOCAL 1
+#else
+# if __has_feature(tls)
+# define SANITIZER_SUPPORTS_THREADLOCAL 1
+# else
+# define SANITIZER_SUPPORTS_THREADLOCAL 0
+# endif
+#endif
+
#endif // SANITIZER_PLATFORM_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
index 5b710c2..4e6efca 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
@@ -229,7 +229,8 @@
(SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
#define SANITIZER_INTERCEPT_CLOCK_GETTIME \
(SI_FREEBSD || SI_NETBSD || SI_LINUX || SI_SOLARIS)
-#define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID SI_LINUX
+#define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID \
+ (SI_LINUX || SI_FREEBSD || SI_NETBSD)
#define SANITIZER_INTERCEPT_GETITIMER SI_POSIX
#define SANITIZER_INTERCEPT_TIME SI_POSIX
#define SANITIZER_INTERCEPT_GLOB (SI_GLIBC || SI_SOLARIS)
@@ -251,7 +252,8 @@
#define SANITIZER_INTERCEPT_GETHOSTENT_R (SI_FREEBSD || SI_GLIBC || SI_SOLARIS)
#define SANITIZER_INTERCEPT_GETSOCKOPT SI_POSIX
#define SANITIZER_INTERCEPT_ACCEPT SI_POSIX
-#define SANITIZER_INTERCEPT_ACCEPT4 (SI_LINUX_NOT_ANDROID || SI_NETBSD)
+#define SANITIZER_INTERCEPT_ACCEPT4 \
+ (SI_LINUX_NOT_ANDROID || SI_NETBSD || SI_FREEBSD)
#define SANITIZER_INTERCEPT_PACCEPT SI_NETBSD
#define SANITIZER_INTERCEPT_MODF SI_POSIX
#define SANITIZER_INTERCEPT_RECVMSG SI_POSIX
@@ -309,7 +311,7 @@
#define SANITIZER_INTERCEPT_PPOLL SI_LINUX_NOT_ANDROID || SI_SOLARIS
#define SANITIZER_INTERCEPT_WORDEXP \
(SI_FREEBSD || SI_NETBSD || (SI_MAC && !SI_IOS) || SI_LINUX_NOT_ANDROID || \
- SI_SOLARIS) // NOLINT
+ SI_SOLARIS)
#define SANITIZER_INTERCEPT_SIGWAIT SI_POSIX
#define SANITIZER_INTERCEPT_SIGWAITINFO SI_LINUX_NOT_ANDROID || SI_SOLARIS
#define SANITIZER_INTERCEPT_SIGTIMEDWAIT SI_LINUX_NOT_ANDROID || SI_SOLARIS
@@ -337,7 +339,7 @@
#define SANITIZER_INTERCEPT_ETHER_R (SI_FREEBSD || SI_LINUX_NOT_ANDROID)
#define SANITIZER_INTERCEPT_SHMCTL \
(((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && SANITIZER_WORDSIZE == 64) || \
- SI_NETBSD || SI_SOLARIS) // NOLINT
+ SI_NETBSD || SI_SOLARIS)
#define SANITIZER_INTERCEPT_RANDOM_R SI_GLIBC
#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET SI_POSIX
#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED \
@@ -445,7 +447,8 @@
#define SANITIZER_INTERCEPT_SEM \
(SI_LINUX || SI_FREEBSD || SI_NETBSD || SI_SOLARIS)
#define SANITIZER_INTERCEPT_PTHREAD_SETCANCEL SI_POSIX
-#define SANITIZER_INTERCEPT_MINCORE (SI_LINUX || SI_NETBSD || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_MINCORE \
+ (SI_LINUX || SI_NETBSD || SI_FREEBSD || SI_SOLARIS)
#define SANITIZER_INTERCEPT_PROCESS_VM_READV SI_LINUX
#define SANITIZER_INTERCEPT_CTERMID \
(SI_LINUX || SI_MAC || SI_FREEBSD || SI_NETBSD || SI_SOLARIS)
@@ -496,7 +499,8 @@
#define SANITIZER_INTERCEPT_GID_FROM_GROUP SI_NETBSD
#define SANITIZER_INTERCEPT_ACCESS (SI_NETBSD || SI_FREEBSD)
#define SANITIZER_INTERCEPT_FACCESSAT (SI_NETBSD || SI_FREEBSD)
-#define SANITIZER_INTERCEPT_GETGROUPLIST SI_NETBSD
+#define SANITIZER_INTERCEPT_GETGROUPLIST \
+ (SI_NETBSD || SI_FREEBSD || SI_LINUX)
#define SANITIZER_INTERCEPT_STRLCPY \
(SI_NETBSD || SI_FREEBSD || SI_MAC || SI_ANDROID)
@@ -517,10 +521,11 @@
#define SANITIZER_INTERCEPT_DEVNAME_R (SI_NETBSD || SI_FREEBSD)
#define SANITIZER_INTERCEPT_FGETLN (SI_NETBSD || SI_FREEBSD)
#define SANITIZER_INTERCEPT_STRMODE (SI_NETBSD || SI_FREEBSD)
-#define SANITIZER_INTERCEPT_TTYENT SI_NETBSD
-#define SANITIZER_INTERCEPT_PROTOENT (SI_NETBSD || SI_LINUX)
+#define SANITIZER_INTERCEPT_TTYENT (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_TTYENTPATH SI_NETBSD
+#define SANITIZER_INTERCEPT_PROTOENT (SI_LINUX || SI_NETBSD || SI_FREEBSD)
#define SANITIZER_INTERCEPT_PROTOENT_R SI_GLIBC
-#define SANITIZER_INTERCEPT_NETENT SI_NETBSD
+#define SANITIZER_INTERCEPT_NETENT (SI_LINUX || SI_NETBSD || SI_FREEBSD)
#define SANITIZER_INTERCEPT_SETVBUF \
(SI_NETBSD || SI_FREEBSD || SI_LINUX || SI_MAC)
#define SANITIZER_INTERCEPT_GETMNTINFO (SI_NETBSD || SI_FREEBSD || SI_MAC)
@@ -536,17 +541,17 @@
#define SANITIZER_INTERCEPT_MODCTL SI_NETBSD
#define SANITIZER_INTERCEPT_CAPSICUM SI_FREEBSD
#define SANITIZER_INTERCEPT_STRTONUM (SI_NETBSD || SI_FREEBSD)
-#define SANITIZER_INTERCEPT_FPARSELN SI_NETBSD
+#define SANITIZER_INTERCEPT_FPARSELN (SI_NETBSD || SI_FREEBSD)
#define SANITIZER_INTERCEPT_STATVFS1 SI_NETBSD
#define SANITIZER_INTERCEPT_STRTOI SI_NETBSD
#define SANITIZER_INTERCEPT_CAPSICUM SI_FREEBSD
#define SANITIZER_INTERCEPT_SHA1 SI_NETBSD
#define SANITIZER_INTERCEPT_MD4 SI_NETBSD
#define SANITIZER_INTERCEPT_RMD160 SI_NETBSD
-#define SANITIZER_INTERCEPT_MD5 SI_NETBSD
+#define SANITIZER_INTERCEPT_MD5 (SI_NETBSD || SI_FREEBSD)
#define SANITIZER_INTERCEPT_FSEEK (SI_NETBSD || SI_FREEBSD)
#define SANITIZER_INTERCEPT_MD2 SI_NETBSD
-#define SANITIZER_INTERCEPT_SHA2 SI_NETBSD
+#define SANITIZER_INTERCEPT_SHA2 (SI_NETBSD || SI_FREEBSD)
#define SANITIZER_INTERCEPT_CDB SI_NETBSD
#define SANITIZER_INTERCEPT_VIS (SI_NETBSD || SI_FREEBSD)
#define SANITIZER_INTERCEPT_POPEN SI_POSIX
@@ -571,6 +576,8 @@
#define SANITIZER_INTERCEPT_QSORT \
(SI_POSIX && !SI_IOSSIM && !SI_WATCHOS && !SI_TVOS && !SI_ANDROID)
#define SANITIZER_INTERCEPT_QSORT_R SI_GLIBC
+#define SANITIZER_INTERCEPT_BSEARCH \
+ (SI_POSIX && !SI_IOSSIM && !SI_WATCHOS && !SI_TVOS && !SI_ANDROID)
// sigaltstack on i386 macOS cannot be intercepted due to setjmp()
// calling it and assuming that it does not clobber registers.
#define SANITIZER_INTERCEPT_SIGALTSTACK \
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.cpp b/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.cpp
index b5a45ae..6453580 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.cpp
@@ -69,11 +69,17 @@
#include <semaphore.h>
#include <signal.h>
#include <stddef.h>
+#include <md5.h>
+#include <sha224.h>
+#include <sha256.h>
+#include <sha384.h>
+#include <sha512.h>
#include <stdio.h>
#include <stringlist.h>
#include <term.h>
#include <termios.h>
#include <time.h>
+#include <ttyent.h>
#include <utime.h>
#include <utmpx.h>
#include <vis.h>
@@ -170,9 +176,12 @@ uptr __sanitizer_in_addr_sz(int af) {
unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
int glob_nomatch = GLOB_NOMATCH;
int glob_altdirfunc = GLOB_ALTDIRFUNC;
+const int wordexp_wrde_dooffs = WRDE_DOOFFS;
unsigned path_max = PATH_MAX;
+int struct_ttyent_sz = sizeof(struct ttyent);
+
// ioctl arguments
unsigned struct_ifreq_sz = sizeof(struct ifreq);
unsigned struct_termios_sz = sizeof(struct termios);
@@ -357,6 +366,22 @@ const int si_SEGV_MAPERR = SEGV_MAPERR;
const int si_SEGV_ACCERR = SEGV_ACCERR;
const int unvis_valid = UNVIS_VALID;
const int unvis_validpush = UNVIS_VALIDPUSH;
+
+const unsigned MD5_CTX_sz = sizeof(MD5_CTX);
+const unsigned MD5_return_length = MD5_DIGEST_STRING_LENGTH;
+
+#define SHA2_CONST(LEN) \
+ const unsigned SHA##LEN##_CTX_sz = sizeof(SHA##LEN##_CTX); \
+ const unsigned SHA##LEN##_return_length = SHA##LEN##_DIGEST_STRING_LENGTH; \
+ const unsigned SHA##LEN##_block_length = SHA##LEN##_BLOCK_LENGTH; \
+ const unsigned SHA##LEN##_digest_length = SHA##LEN##_DIGEST_LENGTH
+
+SHA2_CONST(224);
+SHA2_CONST(256);
+SHA2_CONST(384);
+SHA2_CONST(512);
+
+#undef SHA2_CONST
} // namespace __sanitizer
using namespace __sanitizer;
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.h b/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.h
index 5e0ca9c..649e64f 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.h
@@ -16,26 +16,26 @@
#if SANITIZER_FREEBSD
-#include "sanitizer_internal_defs.h"
-#include "sanitizer_platform.h"
-#include "sanitizer_platform_limits_posix.h"
+# include "sanitizer_internal_defs.h"
+# include "sanitizer_platform.h"
+# include "sanitizer_platform_limits_posix.h"
// Get sys/_types.h, because that tells us whether 64-bit inodes are
// used in struct dirent below.
-#include <sys/_types.h>
+# include <sys/_types.h>
namespace __sanitizer {
void *__sanitizer_get_link_map_by_dlopen_handle(void *handle);
-#define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \
- (link_map *)__sanitizer_get_link_map_by_dlopen_handle(handle)
+# define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \
+ (link_map *)__sanitizer_get_link_map_by_dlopen_handle(handle)
extern unsigned struct_utsname_sz;
extern unsigned struct_stat_sz;
-#if defined(__powerpc64__)
+# if defined(__powerpc64__)
const unsigned struct___old_kernel_stat_sz = 0;
-#else
+# else
const unsigned struct___old_kernel_stat_sz = 32;
-#endif
+# endif
extern unsigned struct_rusage_sz;
extern unsigned siginfo_t_sz;
extern unsigned struct_itimerval_sz;
@@ -114,11 +114,24 @@ struct __sanitizer_ipc_perm {
long key;
};
-#if !defined(__i386__)
+struct __sanitizer_protoent {
+ char *p_name;
+ char **p_aliases;
+ int p_proto;
+};
+
+struct __sanitizer_netent {
+ char *n_name;
+ char **n_aliases;
+ int n_addrtype;
+ u32 n_net;
+};
+
+# if !defined(__i386__)
typedef long long __sanitizer_time_t;
-#else
+# else
typedef long __sanitizer_time_t;
-#endif
+# endif
struct __sanitizer_shmid_ds {
__sanitizer_ipc_perm shm_perm;
@@ -147,7 +160,7 @@ struct __sanitizer_ifaddrs {
unsigned int ifa_flags;
void *ifa_addr; // (struct sockaddr *)
void *ifa_netmask; // (struct sockaddr *)
-#undef ifa_dstaddr
+# undef ifa_dstaddr
void *ifa_dstaddr; // (struct sockaddr *)
void *ifa_data;
};
@@ -229,12 +242,12 @@ struct __sanitizer_cmsghdr {
};
struct __sanitizer_dirent {
-#if defined(__INO64)
+# if defined(__INO64)
unsigned long long d_fileno;
unsigned long long d_off;
-#else
+# else
unsigned int d_fileno;
-#endif
+# endif
unsigned short d_reclen;
// more fields that we don't care about
};
@@ -243,23 +256,23 @@ struct __sanitizer_dirent {
typedef int __sanitizer_clock_t;
typedef int __sanitizer_clockid_t;
-#if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
- defined(__mips__)
+# if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
+ defined(__mips__)
typedef unsigned __sanitizer___kernel_uid_t;
typedef unsigned __sanitizer___kernel_gid_t;
-#else
+# else
typedef unsigned short __sanitizer___kernel_uid_t;
typedef unsigned short __sanitizer___kernel_gid_t;
-#endif
+# endif
typedef long long __sanitizer___kernel_off_t;
-#if defined(__powerpc__) || defined(__mips__)
+# if defined(__powerpc__) || defined(__mips__)
typedef unsigned int __sanitizer___kernel_old_uid_t;
typedef unsigned int __sanitizer___kernel_old_gid_t;
-#else
+# else
typedef unsigned short __sanitizer___kernel_old_uid_t;
typedef unsigned short __sanitizer___kernel_old_gid_t;
-#endif
+# endif
typedef long long __sanitizer___kernel_loff_t;
typedef struct {
@@ -366,9 +379,12 @@ struct __sanitizer_glob_t {
extern int glob_nomatch;
extern int glob_altdirfunc;
+extern const int wordexp_wrde_dooffs;
extern unsigned path_max;
+extern int struct_ttyent_sz;
+
struct __sanitizer_wordexp_t {
uptr we_wordc;
char **we_wordv;
@@ -398,39 +414,49 @@ struct __sanitizer_ifconf {
} ifc_ifcu;
};
-#define IOC_NRBITS 8
-#define IOC_TYPEBITS 8
-#if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__)
-#define IOC_SIZEBITS 13
-#define IOC_DIRBITS 3
-#define IOC_NONE 1U
-#define IOC_WRITE 4U
-#define IOC_READ 2U
-#else
-#define IOC_SIZEBITS 14
-#define IOC_DIRBITS 2
-#define IOC_NONE 0U
-#define IOC_WRITE 1U
-#define IOC_READ 2U
-#endif
-#define IOC_NRMASK ((1 << IOC_NRBITS) - 1)
-#define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1)
-#define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1)
-#if defined(IOC_DIRMASK)
-#undef IOC_DIRMASK
-#endif
-#define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1)
-#define IOC_NRSHIFT 0
-#define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS)
-#define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS)
-#define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS)
-#define EVIOC_EV_MAX 0x1f
-#define EVIOC_ABS_MAX 0x3f
-
-#define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
-#define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
-#define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
-#define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
+struct __sanitizer__ttyent {
+ char *ty_name;
+ char *ty_getty;
+ char *ty_type;
+ int ty_status;
+ char *ty_window;
+ char *ty_comment;
+ char *ty_group;
+};
+
+# define IOC_NRBITS 8
+# define IOC_TYPEBITS 8
+# if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__)
+# define IOC_SIZEBITS 13
+# define IOC_DIRBITS 3
+# define IOC_NONE 1U
+# define IOC_WRITE 4U
+# define IOC_READ 2U
+# else
+# define IOC_SIZEBITS 14
+# define IOC_DIRBITS 2
+# define IOC_NONE 0U
+# define IOC_WRITE 1U
+# define IOC_READ 2U
+# endif
+# define IOC_NRMASK ((1 << IOC_NRBITS) - 1)
+# define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1)
+# define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1)
+# if defined(IOC_DIRMASK)
+# undef IOC_DIRMASK
+# endif
+# define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1)
+# define IOC_NRSHIFT 0
+# define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS)
+# define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS)
+# define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS)
+# define EVIOC_EV_MAX 0x1f
+# define EVIOC_ABS_MAX 0x3f
+
+# define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
+# define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
+# define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
+# define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
extern unsigned struct_ifreq_sz;
extern unsigned struct_termios_sz;
@@ -621,6 +647,22 @@ extern unsigned IOCTL_KDSKBMODE;
extern const int si_SEGV_MAPERR;
extern const int si_SEGV_ACCERR;
+extern const unsigned MD5_CTX_sz;
+extern const unsigned MD5_return_length;
+
+#define SHA2_EXTERN(LEN) \
+ extern const unsigned SHA##LEN##_CTX_sz; \
+ extern const unsigned SHA##LEN##_return_length; \
+ extern const unsigned SHA##LEN##_block_length; \
+ extern const unsigned SHA##LEN##_digest_length
+
+SHA2_EXTERN(224);
+SHA2_EXTERN(256);
+SHA2_EXTERN(384);
+SHA2_EXTERN(512);
+
+#undef SHA2_EXTERN
+
struct __sanitizer_cap_rights {
u64 cr_rights[2];
};
@@ -632,24 +674,24 @@ extern unsigned struct_fstab_sz;
extern unsigned struct_StringList_sz;
} // namespace __sanitizer
-#define CHECK_TYPE_SIZE(TYPE) \
- COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE))
+# define CHECK_TYPE_SIZE(TYPE) \
+ COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE))
-#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \
- COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *)NULL)->MEMBER) == \
- sizeof(((CLASS *)NULL)->MEMBER)); \
- COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \
- offsetof(CLASS, MEMBER))
+# define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \
+ COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *)NULL)->MEMBER) == \
+ sizeof(((CLASS *)NULL)->MEMBER)); \
+ COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \
+ offsetof(CLASS, MEMBER))
// For sigaction, which is a function and struct at the same time,
// and thus requires explicit "struct" in sizeof() expression.
-#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \
- COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *)NULL)->MEMBER) == \
- sizeof(((struct CLASS *)NULL)->MEMBER)); \
- COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \
- offsetof(struct CLASS, MEMBER))
+# define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \
+ COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *)NULL)->MEMBER) == \
+ sizeof(((struct CLASS *)NULL)->MEMBER)); \
+ COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \
+ offsetof(struct CLASS, MEMBER))
-#define SIGACTION_SYMNAME sigaction
+# define SIGACTION_SYMNAME sigaction
#endif
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp
index f22f503..2b1a2f7 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp
@@ -31,32 +31,32 @@
// Also, for some platforms (e.g. mips) there are additional members in the
// <sys/stat.h> struct stat:s.
#include <linux/posix_types.h>
-#if defined(__x86_64__)
-#include <sys/stat.h>
-#else
-#define ino_t __kernel_ino_t
-#define mode_t __kernel_mode_t
-#define nlink_t __kernel_nlink_t
-#define uid_t __kernel_uid_t
-#define gid_t __kernel_gid_t
-#define off_t __kernel_off_t
-#define time_t __kernel_time_t
+# if defined(__x86_64__) || defined(__mips__) || defined(__hexagon__)
+# include <sys/stat.h>
+# else
+# define ino_t __kernel_ino_t
+# define mode_t __kernel_mode_t
+# define nlink_t __kernel_nlink_t
+# define uid_t __kernel_uid_t
+# define gid_t __kernel_gid_t
+# define off_t __kernel_off_t
+# define time_t __kernel_time_t
// This header seems to contain the definitions of _kernel_ stat* structs.
-#include <asm/stat.h>
-#undef ino_t
-#undef mode_t
-#undef nlink_t
-#undef uid_t
-#undef gid_t
-#undef off_t
-#endif
-
-#include <linux/aio_abi.h>
-
-#if !SANITIZER_ANDROID
-#include <sys/statfs.h>
-#include <linux/perf_event.h>
-#endif
+# include <asm/stat.h>
+# undef ino_t
+# undef mode_t
+# undef nlink_t
+# undef uid_t
+# undef gid_t
+# undef off_t
+# endif
+
+# include <linux/aio_abi.h>
+
+# if !SANITIZER_ANDROID
+# include <sys/statfs.h>
+# include <linux/perf_event.h>
+# endif
using namespace __sanitizer;
@@ -66,9 +66,9 @@ namespace __sanitizer {
#endif
} // namespace __sanitizer
-#if !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__aarch64__)\
- && !defined(__mips__) && !defined(__s390__)\
- && !defined(__sparc__) && !defined(__riscv)
+# if !defined(__powerpc64__) && !defined(__x86_64__) && \
+ !defined(__aarch64__) && !defined(__mips__) && !defined(__s390__) && \
+ !defined(__sparc__) && !defined(__riscv) && !defined(__hexagon__)
COMPILER_CHECK(struct___old_kernel_stat_sz == sizeof(struct __old_kernel_stat));
#endif
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.cpp b/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.cpp
index c8f2aa5..531e07f 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.cpp
@@ -666,6 +666,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
int glob_nomatch = GLOB_NOMATCH;
int glob_altdirfunc = GLOB_ALTDIRFUNC;
+const int wordexp_wrde_dooffs = WRDE_DOOFFS;
unsigned path_max = PATH_MAX;
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.h b/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.h
index 9e28dcf..9407803 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.h
@@ -394,6 +394,7 @@ struct __sanitizer_glob_t {
extern int glob_nomatch;
extern int glob_altdirfunc;
+extern const int wordexp_wrde_dooffs;
extern unsigned path_max;
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp
index 6e5c330..a1c4528 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp
@@ -91,10 +91,10 @@
#if SANITIZER_LINUX
# include <utime.h>
# include <sys/ptrace.h>
-#if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \
- SANITIZER_RISCV64
-# include <asm/ptrace.h>
-# ifdef __arm__
+# if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \
+ defined(__hexagon__) || SANITIZER_RISCV64
+# include <asm/ptrace.h>
+# ifdef __arm__
typedef struct user_fpregs elf_fpregset_t;
# define ARM_VFPREGS_SIZE_ASAN (32 * 8 /*fpregs*/ + 4 /*fpscr*/)
# if !defined(ARM_VFPREGS_SIZE)
@@ -242,12 +242,13 @@ namespace __sanitizer {
defined(__powerpc64__) || defined(__arch64__) || defined(__sparcv9) || \
defined(__x86_64__) || SANITIZER_RISCV64
#define SIZEOF_STRUCT_USTAT 32
-#elif defined(__arm__) || defined(__i386__) || defined(__mips__) \
- || defined(__powerpc__) || defined(__s390__) || defined(__sparc__)
-#define SIZEOF_STRUCT_USTAT 20
-#else
-#error Unknown size of struct ustat
-#endif
+# elif defined(__arm__) || defined(__i386__) || defined(__mips__) || \
+ defined(__powerpc__) || defined(__s390__) || defined(__sparc__) || \
+ defined(__hexagon__)
+# define SIZEOF_STRUCT_USTAT 20
+# else
+# error Unknown size of struct ustat
+# endif
unsigned struct_ustat_sz = SIZEOF_STRUCT_USTAT;
unsigned struct_rlimit64_sz = sizeof(struct rlimit64);
unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
@@ -312,6 +313,10 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
int glob_altdirfunc = GLOB_ALTDIRFUNC;
#endif
+# if !SANITIZER_ANDROID
+ const int wordexp_wrde_dooffs = WRDE_DOOFFS;
+# endif // !SANITIZER_ANDROID
+
#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
(defined(__i386) || defined(__x86_64) || defined(__mips64) || \
defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
index 07c7a93..da53b5a 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -102,7 +102,10 @@ const unsigned struct_kernel_stat64_sz = 104;
#elif SANITIZER_RISCV64
const unsigned struct_kernel_stat_sz = 128;
const unsigned struct_kernel_stat64_sz = 0; // RISCV64 does not use stat64
-#endif
+# elif defined(__hexagon__)
+const unsigned struct_kernel_stat_sz = 128;
+const unsigned struct_kernel_stat64_sz = 0;
+# endif
struct __sanitizer_perf_event_attr {
unsigned type;
unsigned size;
@@ -367,7 +370,7 @@ struct __sanitizer_group {
char **gr_mem;
};
-#if defined(__x86_64__) && !defined(_LP64)
+# if (defined(__x86_64__) && !defined(_LP64)) || defined(__hexagon__)
typedef long long __sanitizer_time_t;
#else
typedef long __sanitizer_time_t;
@@ -475,23 +478,23 @@ struct __sanitizer_dirent {
unsigned short d_reclen;
// more fields that we don't care about
};
-#elif SANITIZER_ANDROID || defined(__x86_64__)
+# elif SANITIZER_ANDROID || defined(__x86_64__) || defined(__hexagon__)
struct __sanitizer_dirent {
unsigned long long d_ino;
unsigned long long d_off;
unsigned short d_reclen;
// more fields that we don't care about
};
-#else
+# else
struct __sanitizer_dirent {
uptr d_ino;
uptr d_off;
unsigned short d_reclen;
// more fields that we don't care about
};
-#endif
+# endif
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+# if SANITIZER_LINUX && !SANITIZER_ANDROID
struct __sanitizer_dirent64 {
unsigned long long d_ino;
unsigned long long d_off;
@@ -511,8 +514,8 @@ typedef int __sanitizer_clockid_t;
#endif
#if SANITIZER_LINUX
-#if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
- defined(__mips__)
+# if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
+ defined(__mips__) || defined(__hexagon__)
typedef unsigned __sanitizer___kernel_uid_t;
typedef unsigned __sanitizer___kernel_gid_t;
#else
@@ -712,6 +715,13 @@ struct __sanitizer_protoent {
int p_proto;
};
+struct __sanitizer_netent {
+ char *n_name;
+ char **n_aliases;
+ int n_addrtype;
+ u32 n_net;
+};
+
struct __sanitizer_addrinfo {
int ai_flags;
int ai_family;
@@ -773,6 +783,10 @@ extern int glob_altdirfunc;
extern unsigned path_max;
+# if !SANITIZER_ANDROID
+extern const int wordexp_wrde_dooffs;
+# endif // !SANITIZER_ANDROID
+
struct __sanitizer_wordexp_t {
uptr we_wordc;
char **we_wordv;
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.cpp b/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.cpp
index 565b31f..a113cb0 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.cpp
@@ -123,6 +123,7 @@ namespace __sanitizer {
unsigned struct_ElfW_Phdr_sz = sizeof(ElfW(Phdr));
int glob_nomatch = GLOB_NOMATCH;
+ const int wordexp_wrde_dooffs = WRDE_DOOFFS;
unsigned path_max = PATH_MAX;
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.h b/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.h
index 85995e7..cbab577 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.h
@@ -341,6 +341,7 @@ struct __sanitizer_glob_t {
extern int glob_nomatch;
extern int glob_altdirfunc;
+extern const int wordexp_wrde_dooffs;
extern unsigned path_max;
diff --git a/libsanitizer/sanitizer_common/sanitizer_posix.h b/libsanitizer/sanitizer_common/sanitizer_posix.h
index b65dae6..f91e26e 100644
--- a/libsanitizer/sanitizer_common/sanitizer_posix.h
+++ b/libsanitizer/sanitizer_common/sanitizer_posix.h
@@ -20,10 +20,7 @@
#include "sanitizer_platform_limits_posix.h"
#include "sanitizer_platform_limits_solaris.h"
-#if !SANITIZER_POSIX
-// Make it hard to accidentally use any of functions declared in this file:
-#error This file should only be included on POSIX
-#endif
+#if SANITIZER_POSIX
namespace __sanitizer {
@@ -126,4 +123,6 @@ void DecorateMapping(uptr addr, uptr size, const char *name);
} // namespace __sanitizer
+#endif // SANITIZER_POSIX
+
#endif // SANITIZER_POSIX_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp
index ddf6844..eed02ce 100644
--- a/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp
@@ -151,6 +151,8 @@ int Atexit(void (*function)(void)) {
#endif
}
+bool CreateDir(const char *pathname) { return mkdir(pathname, 0755) == 0; }
+
bool SupportsColoredOutput(fd_t fd) {
return isatty(fd) != 0;
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_printf.cpp b/libsanitizer/sanitizer_common/sanitizer_printf.cpp
index b913c92..79aee8b 100644
--- a/libsanitizer/sanitizer_common/sanitizer_printf.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_printf.cpp
@@ -20,10 +20,6 @@
#include <stdio.h>
#include <stdarg.h>
-#if defined(__x86_64__)
-# include <emmintrin.h>
-#endif
-
#if SANITIZER_WINDOWS && defined(_MSC_VER) && _MSC_VER < 1800 && \
!defined(va_copy)
# define va_copy(dst, src) ((dst) = (src))
@@ -132,8 +128,8 @@ static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) {
int VSNPrintf(char *buff, int buff_length,
const char *format, va_list args) {
static const char *kPrintfFormatsHelp =
- "Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x,X,V}; %p; "
- "%[-]([0-9]*)?(\\.\\*)?s; %c\n";
+ "Supported Printf formats: %([0-9]*)?(z|l|ll)?{d,u,x,X}; %p; "
+ "%[-]([0-9]*)?(\\.\\*)?s; %c\nProvided format: ";
RAW_CHECK(format);
RAW_CHECK(buff_length > 0);
const char *buff_end = &buff[buff_length - 1];
@@ -164,9 +160,11 @@ int VSNPrintf(char *buff, int buff_length,
}
bool have_z = (*cur == 'z');
cur += have_z;
- bool have_ll = !have_z && (cur[0] == 'l' && cur[1] == 'l');
+ bool have_l = cur[0] == 'l' && cur[1] != 'l';
+ cur += have_l;
+ bool have_ll = cur[0] == 'l' && cur[1] == 'l';
cur += have_ll * 2;
- const bool have_length = have_z || have_ll;
+ const bool have_length = have_z || have_l || have_ll;
const bool have_flags = have_width || have_length;
// At the moment only %s supports precision and left-justification.
CHECK(!((precision >= 0 || left_justified) && *cur != 's'));
@@ -174,6 +172,7 @@ int VSNPrintf(char *buff, int buff_length,
case 'd': {
s64 dval = have_ll ? va_arg(args, s64)
: have_z ? va_arg(args, sptr)
+ : have_l ? va_arg(args, long)
: va_arg(args, int);
result += AppendSignedDecimal(&buff, buff_end, dval, width,
pad_with_zero);
@@ -184,26 +183,20 @@ int VSNPrintf(char *buff, int buff_length,
case 'X': {
u64 uval = have_ll ? va_arg(args, u64)
: have_z ? va_arg(args, uptr)
+ : have_l ? va_arg(args, unsigned long)
: va_arg(args, unsigned);
bool uppercase = (*cur == 'X');
result += AppendUnsigned(&buff, buff_end, uval, (*cur == 'u') ? 10 : 16,
width, pad_with_zero, uppercase);
break;
}
- case 'V': {
- for (uptr i = 0; i < 16; i++) {
- unsigned x = va_arg(args, unsigned);
- result += AppendUnsigned(&buff, buff_end, x, 16, 2, true, false);
- }
- break;
- }
case 'p': {
- RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
+ RAW_CHECK(!have_flags, kPrintfFormatsHelp, format);
result += AppendPointer(&buff, buff_end, va_arg(args, uptr));
break;
}
case 's': {
- RAW_CHECK_MSG(!have_length, kPrintfFormatsHelp);
+ RAW_CHECK(!have_length, kPrintfFormatsHelp, format);
// Only left-justified width is supported.
CHECK(!have_width || left_justified);
result += AppendString(&buff, buff_end, left_justified ? -width : width,
@@ -211,17 +204,17 @@ int VSNPrintf(char *buff, int buff_length,
break;
}
case 'c': {
- RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
+ RAW_CHECK(!have_flags, kPrintfFormatsHelp, format);
result += AppendChar(&buff, buff_end, va_arg(args, int));
break;
}
case '%' : {
- RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
+ RAW_CHECK(!have_flags, kPrintfFormatsHelp, format);
result += AppendChar(&buff, buff_end, '%');
break;
}
default: {
- RAW_CHECK_MSG(false, kPrintfFormatsHelp);
+ RAW_CHECK(false, kPrintfFormatsHelp, format);
}
}
}
@@ -317,7 +310,6 @@ static void NOINLINE SharedPrintfCode(bool append_pid, const char *format,
format, args);
}
-FORMAT(1, 2)
void Printf(const char *format, ...) {
va_list args;
va_start(args, format);
@@ -326,7 +318,6 @@ void Printf(const char *format, ...) {
}
// Like Printf, but prints the current PID before the output string.
-FORMAT(1, 2)
void Report(const char *format, ...) {
va_list args;
va_start(args, format);
@@ -338,7 +329,6 @@ void Report(const char *format, ...) {
// Returns the number of symbols that should have been written to buffer
// (not including trailing '\0'). Thus, the string is truncated
// iff return value is not less than "length".
-FORMAT(3, 4)
int internal_snprintf(char *buffer, uptr length, const char *format, ...) {
va_list args;
va_start(args, format);
@@ -347,7 +337,6 @@ int internal_snprintf(char *buffer, uptr length, const char *format, ...) {
return needed_length;
}
-FORMAT(2, 3)
void InternalScopedString::append(const char *format, ...) {
uptr prev_len = length();
diff --git a/libsanitizer/sanitizer_common/sanitizer_signal_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_signal_interceptors.inc
index cefb870..475e577 100644
--- a/libsanitizer/sanitizer_common/sanitizer_signal_interceptors.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_signal_interceptors.inc
@@ -29,8 +29,16 @@ using namespace __sanitizer;
#endif
#ifndef SIGNAL_INTERCEPTOR_SIGACTION_IMPL
-#define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact) \
- { return REAL(sigaction_symname)(signum, act, oldact); }
+# define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact) \
+ { \
+ if (!REAL(sigaction_symname)) { \
+ Printf( \
+ "Warning: REAL(sigaction_symname) == nullptr. This may happen " \
+ "if you link with ubsan statically. Sigaction will not work.\n"); \
+ return -1; \
+ } \
+ return REAL(sigaction_symname)(signum, act, oldact); \
+ }
#endif
#if SANITIZER_INTERCEPT_BSD_SIGNAL
diff --git a/libsanitizer/sanitizer_common/sanitizer_solaris.cpp b/libsanitizer/sanitizer_common/sanitizer_solaris.cpp
index cb53eab..62c40af 100644
--- a/libsanitizer/sanitizer_common/sanitizer_solaris.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_solaris.cpp
@@ -225,28 +225,6 @@ void FutexWait(atomic_uint32_t *p, u32 cmp) {
void FutexWake(atomic_uint32_t *p, u32 count) {}
-BlockingMutex::BlockingMutex() {
- CHECK(sizeof(mutex_t) <= sizeof(opaque_storage_));
- internal_memset(this, 0, sizeof(*this));
- CHECK_EQ(mutex_init((mutex_t *)&opaque_storage_, USYNC_THREAD, NULL), 0);
-}
-
-void BlockingMutex::Lock() {
- CHECK(sizeof(mutex_t) <= sizeof(opaque_storage_));
- CHECK_NE(owner_, (uptr)thr_self());
- CHECK_EQ(mutex_lock((mutex_t *)&opaque_storage_), 0);
- CHECK(!owner_);
- owner_ = (uptr)thr_self();
-}
-
-void BlockingMutex::Unlock() {
- CHECK(owner_ == (uptr)thr_self());
- owner_ = 0;
- CHECK_EQ(mutex_unlock((mutex_t *)&opaque_storage_), 0);
-}
-
-void BlockingMutex::CheckLocked() const { CHECK_EQ((uptr)thr_self(), owner_); }
-
} // namespace __sanitizer
#endif // SANITIZER_SOLARIS
diff --git a/libsanitizer/sanitizer_common/sanitizer_stackdepot.cpp b/libsanitizer/sanitizer_common/sanitizer_stackdepot.cpp
index 44a9521..fc2ea2f 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stackdepot.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_stackdepot.cpp
@@ -19,26 +19,24 @@
namespace __sanitizer {
struct StackDepotNode {
+ using hash_type = u32;
StackDepotNode *link;
u32 id;
- atomic_uint32_t hash_and_use_count; // hash_bits : 12; use_count : 20;
+ hash_type stack_hash;
u32 size;
- u32 tag;
+ atomic_uint32_t tag_and_use_count; // tag : 12 high bits; use_count : 20;
uptr stack[1]; // [size]
static const u32 kTabSizeLog = SANITIZER_ANDROID ? 16 : 20;
- // Lower kTabSizeLog bits are equal for all items in one bucket.
- // We use these bits to store the per-stack use counter.
- static const u32 kUseCountBits = kTabSizeLog;
+ static const u32 kUseCountBits = 20;
static const u32 kMaxUseCount = 1 << kUseCountBits;
static const u32 kUseCountMask = (1 << kUseCountBits) - 1;
- static const u32 kHashMask = ~kUseCountMask;
typedef StackTrace args_type;
- bool eq(u32 hash, const args_type &args) const {
- u32 hash_bits =
- atomic_load(&hash_and_use_count, memory_order_relaxed) & kHashMask;
- if ((hash & kHashMask) != hash_bits || args.size != size || args.tag != tag)
+ bool eq(hash_type hash, const args_type &args) const {
+ u32 tag =
+ atomic_load(&tag_and_use_count, memory_order_relaxed) >> kUseCountBits;
+ if (stack_hash != hash || args.size != size || args.tag != tag)
return false;
uptr i = 0;
for (; i < size; i++) {
@@ -49,7 +47,7 @@ struct StackDepotNode {
static uptr storage_size(const args_type &args) {
return sizeof(StackDepotNode) + (args.size - 1) * sizeof(uptr);
}
- static u32 hash(const args_type &args) {
+ static hash_type hash(const args_type &args) {
MurMur2HashBuilder H(args.size * sizeof(uptr));
for (uptr i = 0; i < args.size; i++) H.add(args.trace[i]);
return H.get();
@@ -57,13 +55,17 @@ struct StackDepotNode {
static bool is_valid(const args_type &args) {
return args.size > 0 && args.trace;
}
- void store(const args_type &args, u32 hash) {
- atomic_store(&hash_and_use_count, hash & kHashMask, memory_order_relaxed);
+ void store(const args_type &args, hash_type hash) {
+ CHECK_EQ(args.tag & (~kUseCountMask >> kUseCountBits), args.tag);
+ atomic_store(&tag_and_use_count, args.tag << kUseCountBits,
+ memory_order_relaxed);
+ stack_hash = hash;
size = args.size;
- tag = args.tag;
internal_memcpy(stack, args.trace, size * sizeof(uptr));
}
args_type load() const {
+ u32 tag =
+ atomic_load(&tag_and_use_count, memory_order_relaxed) >> kUseCountBits;
return args_type(&stack[0], size, tag);
}
StackDepotHandle get_handle() { return StackDepotHandle(this); }
@@ -71,16 +73,16 @@ struct StackDepotNode {
typedef StackDepotHandle handle_type;
};
-COMPILER_CHECK(StackDepotNode::kMaxUseCount == (u32)kStackDepotMaxUseCount);
+COMPILER_CHECK(StackDepotNode::kMaxUseCount >= (u32)kStackDepotMaxUseCount);
u32 StackDepotHandle::id() { return node_->id; }
int StackDepotHandle::use_count() {
- return atomic_load(&node_->hash_and_use_count, memory_order_relaxed) &
+ return atomic_load(&node_->tag_and_use_count, memory_order_relaxed) &
StackDepotNode::kUseCountMask;
}
void StackDepotHandle::inc_use_count_unsafe() {
u32 prev =
- atomic_fetch_add(&node_->hash_and_use_count, 1, memory_order_relaxed) &
+ atomic_fetch_add(&node_->tag_and_use_count, 1, memory_order_relaxed) &
StackDepotNode::kUseCountMask;
CHECK_LT(prev + 1, StackDepotNode::kMaxUseCount);
}
@@ -90,9 +92,7 @@ typedef StackDepotBase<StackDepotNode, 1, StackDepotNode::kTabSizeLog>
StackDepot;
static StackDepot theDepot;
-StackDepotStats *StackDepotGetStats() {
- return theDepot.GetStats();
-}
+StackDepotStats StackDepotGetStats() { return theDepot.GetStats(); }
u32 StackDepotPut(StackTrace stack) {
StackDepotHandle h = theDepot.Put(stack);
@@ -127,8 +127,10 @@ bool StackDepotReverseMap::IdDescPair::IdComparator(
return a.id < b.id;
}
-StackDepotReverseMap::StackDepotReverseMap() {
- map_.reserve(StackDepotGetStats()->n_uniq_ids + 100);
+void StackDepotReverseMap::Init() const {
+ if (LIKELY(map_.capacity()))
+ return;
+ map_.reserve(StackDepotGetStats().n_uniq_ids + 100);
for (int idx = 0; idx < StackDepot::kTabSize; idx++) {
atomic_uintptr_t *p = &theDepot.tab[idx];
uptr v = atomic_load(p, memory_order_consume);
@@ -141,7 +143,8 @@ StackDepotReverseMap::StackDepotReverseMap() {
Sort(map_.data(), map_.size(), &IdDescPair::IdComparator);
}
-StackTrace StackDepotReverseMap::Get(u32 id) {
+StackTrace StackDepotReverseMap::Get(u32 id) const {
+ Init();
if (!map_.size())
return StackTrace();
IdDescPair pair = {id, nullptr};
diff --git a/libsanitizer/sanitizer_common/sanitizer_stackdepot.h b/libsanitizer/sanitizer_common/sanitizer_stackdepot.h
index 0e26c1f..6f79fff 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stackdepot.h
+++ b/libsanitizer/sanitizer_common/sanitizer_stackdepot.h
@@ -33,7 +33,7 @@ struct StackDepotHandle {
const int kStackDepotMaxUseCount = 1U << (SANITIZER_ANDROID ? 16 : 20);
-StackDepotStats *StackDepotGetStats();
+StackDepotStats StackDepotGetStats();
u32 StackDepotPut(StackTrace stack);
StackDepotHandle StackDepotPut_WithHandle(StackTrace stack);
// Retrieves a stored stack trace by the id.
@@ -49,8 +49,8 @@ void StackDepotPrintAll();
// which were stored before it was instantiated.
class StackDepotReverseMap {
public:
- StackDepotReverseMap();
- StackTrace Get(u32 id);
+ StackDepotReverseMap() = default;
+ StackTrace Get(u32 id) const;
private:
struct IdDescPair {
@@ -60,7 +60,9 @@ class StackDepotReverseMap {
static bool IdComparator(const IdDescPair &a, const IdDescPair &b);
};
- InternalMmapVector<IdDescPair> map_;
+ void Init() const;
+
+ mutable InternalMmapVector<IdDescPair> map_;
// Disallow evil constructors.
StackDepotReverseMap(const StackDepotReverseMap&);
diff --git a/libsanitizer/sanitizer_common/sanitizer_stackdepotbase.h b/libsanitizer/sanitizer_common/sanitizer_stackdepotbase.h
index 1af2c18..435f634 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stackdepotbase.h
+++ b/libsanitizer/sanitizer_common/sanitizer_stackdepotbase.h
@@ -27,19 +27,20 @@ class StackDepotBase {
public:
typedef typename Node::args_type args_type;
typedef typename Node::handle_type handle_type;
+ typedef typename Node::hash_type hash_type;
// Maps stack trace to an unique id.
handle_type Put(args_type args, bool *inserted = nullptr);
// Retrieves a stored stack trace by the id.
args_type Get(u32 id);
- StackDepotStats *GetStats() { return &stats; }
+ StackDepotStats GetStats() const { return stats; }
void LockAll();
void UnlockAll();
void PrintAll();
private:
- static Node *find(Node *s, args_type args, u32 hash);
+ static Node *find(Node *s, args_type args, hash_type hash);
static Node *lock(atomic_uintptr_t *p);
static void unlock(atomic_uintptr_t *p, Node *s);
@@ -62,7 +63,7 @@ class StackDepotBase {
template <class Node, int kReservedBits, int kTabSizeLog>
Node *StackDepotBase<Node, kReservedBits, kTabSizeLog>::find(Node *s,
args_type args,
- u32 hash) {
+ hash_type hash) {
// Searches linked list s for the stack, returns its id.
for (; s; s = s->link) {
if (s->eq(hash, args)) {
@@ -101,7 +102,7 @@ StackDepotBase<Node, kReservedBits, kTabSizeLog>::Put(args_type args,
bool *inserted) {
if (inserted) *inserted = false;
if (!Node::is_valid(args)) return handle_type();
- uptr h = Node::hash(args);
+ hash_type h = Node::hash(args);
atomic_uintptr_t *p = &tab[h % kTabSize];
uptr v = atomic_load(p, memory_order_consume);
Node *s = (Node *)(v & ~1);
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cpp b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cpp
index 515dedd..15ea495 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cpp
@@ -22,7 +22,8 @@ namespace __sanitizer {
uptr StackTrace::GetNextInstructionPc(uptr pc) {
#if defined(__sparc__) || defined(__mips__)
return pc + 8;
-#elif defined(__powerpc__) || defined(__arm__) || defined(__aarch64__)
+#elif defined(__powerpc__) || defined(__arm__) || defined(__aarch64__) || \
+ defined(__hexagon__)
return pc + 4;
#elif SANITIZER_RISCV64
// Current check order is 4 -> 2 -> 6 -> 8
@@ -64,7 +65,7 @@ void BufferedStackTrace::Init(const uptr *pcs, uptr cnt, uptr extra_top_pc) {
top_frame_bp = 0;
}
-// Sparc implemention is in its own file.
+// Sparc implementation is in its own file.
#if !defined(__sparc__)
// In GCC on ARM bp points to saved lr, not fp, so we should check the next
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cpp b/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cpp
index f60ea77..2d1c03f 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cpp
@@ -64,7 +64,7 @@ class StackTraceTextPrinter {
if (dedup_token_->length())
dedup_token_->append("--");
if (stack->info.function != nullptr)
- dedup_token_->append(stack->info.function);
+ dedup_token_->append("%s", stack->info.function);
}
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace_printer.cpp b/libsanitizer/sanitizer_common/sanitizer_stacktrace_printer.cpp
index c998322..ad638a8 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace_printer.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace_printer.cpp
@@ -129,7 +129,7 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
break;
// Frame number and all fields of AddressInfo structure.
case 'n':
- buffer->append("%zu", frame_no);
+ buffer->append("%u", frame_no);
break;
case 'p':
buffer->append("0x%zx", address);
@@ -198,8 +198,7 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
}
break;
default:
- Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p,
- *p);
+ Report("Unsupported specifier in stack frame format: %c (%p)!\n", *p, p);
Die();
}
}
@@ -244,14 +243,14 @@ void RenderData(InternalScopedString *buffer, const char *format,
buffer->append("%s", StripPathPrefix(DI->file, strip_path_prefix));
break;
case 'l':
- buffer->append("%d", DI->line);
+ buffer->append("%zu", DI->line);
break;
case 'g':
buffer->append("%s", DI->name);
break;
default:
- Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p,
- *p);
+ Report("Unsupported specifier in stack frame format: %c (%p)!\n", *p,
+ p);
Die();
}
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace_sparc.cpp b/libsanitizer/sanitizer_common/sanitizer_stacktrace_sparc.cpp
index 34190fb..1e635a6 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace_sparc.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace_sparc.cpp
@@ -9,7 +9,7 @@
// This file is shared between AddressSanitizer and ThreadSanitizer
// run-time libraries.
//
-// Implemention of fast stack unwinding for Sparc.
+// Implementation of fast stack unwinding for Sparc.
//===----------------------------------------------------------------------===//
#if defined(__sparc__)
diff --git a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
index 53cfddc..403bda1 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
@@ -108,7 +108,7 @@ struct TracerThreadArgument {
void *callback_argument;
// The tracer thread waits on this mutex while the parent finishes its
// preparations.
- BlockingMutex mutex;
+ Mutex mutex;
// Tracer thread signals its completion by setting done.
atomic_uintptr_t done;
uptr parent_pid;
diff --git a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
index 9c7cd64..701db72 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
@@ -68,7 +68,7 @@ class SuspendedThreadsListNetBSD final : public SuspendedThreadsList {
struct TracerThreadArgument {
StopTheWorldCallback callback;
void *callback_argument;
- BlockingMutex mutex;
+ Mutex mutex;
atomic_uintptr_t done;
uptr parent_pid;
};
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer.h b/libsanitizer/sanitizer_common/sanitizer_symbolizer.h
index 2476b0e..42bd157 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer.h
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer.h
@@ -158,7 +158,7 @@ class Symbolizer final {
// its method should be protected by |mu_|.
class ModuleNameOwner {
public:
- explicit ModuleNameOwner(BlockingMutex *synchronized_by)
+ explicit ModuleNameOwner(Mutex *synchronized_by)
: last_match_(nullptr), mu_(synchronized_by) {
storage_.reserve(kInitialCapacity);
}
@@ -169,7 +169,7 @@ class Symbolizer final {
InternalMmapVector<const char*> storage_;
const char *last_match_;
- BlockingMutex *mu_;
+ Mutex *mu_;
} module_names_;
/// Platform-specific function for creating a Symbolizer object.
@@ -192,7 +192,7 @@ class Symbolizer final {
// Mutex locked from public methods of |Symbolizer|, so that the internals
// (including individual symbolizer tools and platform-specific methods) are
// always synchronized.
- BlockingMutex mu_;
+ Mutex mu_;
IntrusiveList<SymbolizerTool> tools_;
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_internal.h b/libsanitizer/sanitizer_common/sanitizer_symbolizer_internal.h
index 71de175..b867094 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_internal.h
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_internal.h
@@ -21,7 +21,7 @@ namespace __sanitizer {
// Parsing helpers, 'str' is searched for delimiter(s) and a string or uptr
// is extracted. When extracting a string, a newly allocated (using
-// InternalAlloc) and null-terminataed buffer is returned. They return a pointer
+// InternalAlloc) and null-terminated buffer is returned. They return a pointer
// to the next characted after the found delimiter.
const char *ExtractToken(const char *str, const char *delims, char **result);
const char *ExtractInt(const char *str, const char *delims, int *result);
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_libcdep.cpp b/libsanitizer/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
index 98418b4..3fc994f 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
@@ -83,7 +83,7 @@ const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
}
SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) {
- BlockingMutexLock l(&mu_);
+ Lock l(&mu_);
const char *module_name = nullptr;
uptr module_offset;
ModuleArch arch;
@@ -103,7 +103,7 @@ SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) {
}
bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
- BlockingMutexLock l(&mu_);
+ Lock l(&mu_);
const char *module_name = nullptr;
uptr module_offset;
ModuleArch arch;
@@ -124,7 +124,7 @@ bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
}
bool Symbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) {
- BlockingMutexLock l(&mu_);
+ Lock l(&mu_);
const char *module_name = nullptr;
if (!FindModuleNameAndOffsetForAddress(
addr, &module_name, &info->module_offset, &info->module_arch))
@@ -141,7 +141,7 @@ bool Symbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) {
bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
uptr *module_address) {
- BlockingMutexLock l(&mu_);
+ Lock l(&mu_);
const char *internal_module_name = nullptr;
ModuleArch arch;
if (!FindModuleNameAndOffsetForAddress(pc, &internal_module_name,
@@ -154,7 +154,7 @@ bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
}
void Symbolizer::Flush() {
- BlockingMutexLock l(&mu_);
+ Lock l(&mu_);
for (auto &tool : tools_) {
SymbolizerScope sym_scope(this);
tool.Flush();
@@ -162,7 +162,7 @@ void Symbolizer::Flush() {
}
const char *Symbolizer::Demangle(const char *name) {
- BlockingMutexLock l(&mu_);
+ Lock l(&mu_);
for (auto &tool : tools_) {
SymbolizerScope sym_scope(this);
if (const char *demangled = tool.Demangle(name))
diff --git a/libsanitizer/sanitizer_common/sanitizer_syscall_linux_hexagon.inc b/libsanitizer/sanitizer_common/sanitizer_syscall_linux_hexagon.inc
new file mode 100644
index 0000000..553bff7
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_syscall_linux_hexagon.inc
@@ -0,0 +1,131 @@
+//===-- sanitizer_syscall_linux_hexagon.inc ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementations of internal_syscall and internal_iserror for Linux/hexagon.
+//
+//===----------------------------------------------------------------------===//
+
+#define SYSCALL(name) __NR_##name
+
+#define __internal_syscall_LL_E(x) \
+ ((union { \
+ long long ll; \
+ long l[2]; \
+ }){.ll = x}) \
+ .l[0], \
+ ((union { \
+ long long ll; \
+ long l[2]; \
+ }){.ll = x}) \
+ .l[1]
+#define __internal_syscall_LL_O(x) 0, __SYSCALL_LL_E((x))
+
+#define __asm_syscall(...) \
+ do { \
+ __asm__ __volatile__("trap0(#1)" : "=r"(r0) : __VA_ARGS__ : "memory"); \
+ return r0; \
+ } while (0)
+
+#define __internal_syscall0(n) (__internal_syscall)(n)
+
+static uptr __internal_syscall(long n) {
+ register u32 r6 __asm__("r6") = n;
+ register u32 r0 __asm__("r0");
+ __asm_syscall("r"(r6));
+}
+
+#define __internal_syscall1(n, a1) (__internal_syscall)(n, (long)(a1))
+
+static uptr __internal_syscall(long n, long a) {
+ register u32 r6 __asm__("r6") = n;
+ register u32 r0 __asm__("r0") = a;
+ __asm_syscall("r"(r6), "0"(r0));
+}
+
+#define __internal_syscall2(n, a1, a2) \
+ (__internal_syscall)(n, (long)(a1), (long)(a2))
+
+static uptr __internal_syscall(long n, long a, long b) {
+ register u32 r6 __asm__("r6") = n;
+ register u32 r0 __asm__("r0") = a;
+ register u32 r1 __asm__("r1") = b;
+ __asm_syscall("r"(r6), "0"(r0), "r"(r1));
+}
+
+#define __internal_syscall3(n, a1, a2, a3) \
+ (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3))
+
+static uptr __internal_syscall(long n, long a, long b, long c) {
+ register u32 r6 __asm__("r6") = n;
+ register u32 r0 __asm__("r0") = a;
+ register u32 r1 __asm__("r1") = b;
+ register u32 r2 __asm__("r2") = c;
+ __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2));
+}
+
+#define __internal_syscall4(n, a1, a2, a3, a4) \
+ (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3), (long)(a4))
+
+static uptr __internal_syscall(long n, long a, long b, long c, long d) {
+ register u32 r6 __asm__("r6") = n;
+ register u32 r0 __asm__("r0") = a;
+ register u32 r1 __asm__("r1") = b;
+ register u32 r2 __asm__("r2") = c;
+ register u32 r3 __asm__("r3") = d;
+ __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2), "r"(r3));
+}
+
+#define __internal_syscall5(n, a1, a2, a3, a4, a5) \
+ (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (long)(a5))
+
+static uptr __internal_syscall(long n, long a, long b, long c, long d, long e) {
+ register u32 r6 __asm__("r6") = n;
+ register u32 r0 __asm__("r0") = a;
+ register u32 r1 __asm__("r1") = b;
+ register u32 r2 __asm__("r2") = c;
+ register u32 r3 __asm__("r3") = d;
+ register u32 r4 __asm__("r4") = e;
+ __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4));
+}
+
+#define __internal_syscall6(n, a1, a2, a3, a4, a5, a6) \
+ (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (long)(a5), (long)(a6))
+
+static uptr __internal_syscall(long n, long a, long b, long c, long d, long e,
+ long f) {
+ register u32 r6 __asm__("r6") = n;
+ register u32 r0 __asm__("r0") = a;
+ register u32 r1 __asm__("r1") = b;
+ register u32 r2 __asm__("r2") = c;
+ register u32 r3 __asm__("r3") = d;
+ register u32 r4 __asm__("r4") = e;
+ register u32 r5 __asm__("r5") = f;
+ __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5));
+}
+
+#define __SYSCALL_NARGS_X(a1, a2, a3, a4, a5, a6, a7, a8, n, ...) n
+#define __SYSCALL_NARGS(...) \
+ __SYSCALL_NARGS_X(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0, )
+#define __SYSCALL_CONCAT_X(a, b) a##b
+#define __SYSCALL_CONCAT(a, b) __SYSCALL_CONCAT_X(a, b)
+#define __SYSCALL_DISP(b, ...) \
+ __SYSCALL_CONCAT(b, __SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
+
+#define internal_syscall(...) __SYSCALL_DISP(__internal_syscall, __VA_ARGS__)
+
+// Helper function used to avoid clobbering of errno.
+bool internal_iserror(uptr retval, int *rverrno) {
+ if (retval >= (uptr)-4095) {
+ if (rverrno)
+ *rverrno = -retval;
+ return true;
+ }
+ return false;
+}
diff --git a/libsanitizer/sanitizer_common/sanitizer_thread_registry.cpp b/libsanitizer/sanitizer_common/sanitizer_thread_registry.cpp
index 745fbf7..a34b8c1 100644
--- a/libsanitizer/sanitizer_common/sanitizer_thread_registry.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_thread_registry.cpp
@@ -119,7 +119,7 @@ ThreadRegistry::ThreadRegistry(ThreadContextFactory factory, u32 max_threads,
void ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running,
uptr *alive) {
- BlockingMutexLock l(&mtx_);
+ ThreadRegistryLock l(this);
if (total)
*total = threads_.size();
if (running) *running = running_threads_;
@@ -127,13 +127,13 @@ void ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running,
}
uptr ThreadRegistry::GetMaxAliveThreads() {
- BlockingMutexLock l(&mtx_);
+ ThreadRegistryLock l(this);
return max_alive_threads_;
}
u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,
void *arg) {
- BlockingMutexLock l(&mtx_);
+ ThreadRegistryLock l(this);
u32 tid = kInvalidTid;
ThreadContextBase *tctx = QuarantinePop();
if (tctx) {
@@ -179,7 +179,7 @@ void ThreadRegistry::RunCallbackForEachThreadLocked(ThreadCallback cb,
}
u32 ThreadRegistry::FindThread(FindThreadCallback cb, void *arg) {
- BlockingMutexLock l(&mtx_);
+ ThreadRegistryLock l(this);
for (u32 tid = 0; tid < threads_.size(); tid++) {
ThreadContextBase *tctx = threads_[tid];
if (tctx != 0 && cb(tctx, arg))
@@ -211,7 +211,7 @@ ThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(tid_t os_id) {
}
void ThreadRegistry::SetThreadName(u32 tid, const char *name) {
- BlockingMutexLock l(&mtx_);
+ ThreadRegistryLock l(this);
ThreadContextBase *tctx = threads_[tid];
CHECK_NE(tctx, 0);
CHECK_EQ(SANITIZER_FUCHSIA ? ThreadStatusCreated : ThreadStatusRunning,
@@ -220,7 +220,7 @@ void ThreadRegistry::SetThreadName(u32 tid, const char *name) {
}
void ThreadRegistry::SetThreadNameByUserId(uptr user_id, const char *name) {
- BlockingMutexLock l(&mtx_);
+ ThreadRegistryLock l(this);
for (u32 tid = 0; tid < threads_.size(); tid++) {
ThreadContextBase *tctx = threads_[tid];
if (tctx != 0 && tctx->user_id == user_id &&
@@ -232,7 +232,7 @@ void ThreadRegistry::SetThreadNameByUserId(uptr user_id, const char *name) {
}
void ThreadRegistry::DetachThread(u32 tid, void *arg) {
- BlockingMutexLock l(&mtx_);
+ ThreadRegistryLock l(this);
ThreadContextBase *tctx = threads_[tid];
CHECK_NE(tctx, 0);
if (tctx->status == ThreadStatusInvalid) {
@@ -252,7 +252,7 @@ void ThreadRegistry::JoinThread(u32 tid, void *arg) {
bool destroyed = false;
do {
{
- BlockingMutexLock l(&mtx_);
+ ThreadRegistryLock l(this);
ThreadContextBase *tctx = threads_[tid];
CHECK_NE(tctx, 0);
if (tctx->status == ThreadStatusInvalid) {
@@ -275,7 +275,7 @@ void ThreadRegistry::JoinThread(u32 tid, void *arg) {
// thread before trying to create it, and then failed to actually
// create it, and so never called StartThread.
ThreadStatus ThreadRegistry::FinishThread(u32 tid) {
- BlockingMutexLock l(&mtx_);
+ ThreadRegistryLock l(this);
CHECK_GT(alive_threads_, 0);
alive_threads_--;
ThreadContextBase *tctx = threads_[tid];
@@ -301,7 +301,7 @@ ThreadStatus ThreadRegistry::FinishThread(u32 tid) {
void ThreadRegistry::StartThread(u32 tid, tid_t os_id, ThreadType thread_type,
void *arg) {
- BlockingMutexLock l(&mtx_);
+ ThreadRegistryLock l(this);
running_threads_++;
ThreadContextBase *tctx = threads_[tid];
CHECK_NE(tctx, 0);
@@ -334,7 +334,7 @@ ThreadContextBase *ThreadRegistry::QuarantinePop() {
}
void ThreadRegistry::SetThreadUserId(u32 tid, uptr user_id) {
- BlockingMutexLock l(&mtx_);
+ ThreadRegistryLock l(this);
ThreadContextBase *tctx = threads_[tid];
CHECK_NE(tctx, 0);
CHECK_NE(tctx->status, ThreadStatusInvalid);
diff --git a/libsanitizer/sanitizer_common/sanitizer_thread_registry.h b/libsanitizer/sanitizer_common/sanitizer_thread_registry.h
index 0b28bbe..a8a4d4d 100644
--- a/libsanitizer/sanitizer_common/sanitizer_thread_registry.h
+++ b/libsanitizer/sanitizer_common/sanitizer_thread_registry.h
@@ -135,7 +135,7 @@ class MUTEX ThreadRegistry {
const u32 thread_quarantine_size_;
const u32 max_reuse_;
- BlockingMutex mtx_;
+ Mutex mtx_;
u64 total_threads_; // Total number of created threads. May be greater than
// max_threads_ if contexts were reused.
diff --git a/libsanitizer/sanitizer_common/sanitizer_tls_get_addr.cpp b/libsanitizer/sanitizer_common/sanitizer_tls_get_addr.cpp
index 1f664b6..ce5e85d 100644
--- a/libsanitizer/sanitizer_common/sanitizer_tls_get_addr.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_tls_get_addr.cpp
@@ -44,7 +44,7 @@ static atomic_uintptr_t number_of_live_dtls;
static const uptr kDestroyedThread = -1;
static void DTLS_Deallocate(DTLS::DTVBlock *block) {
- VReport(2, "__tls_get_addr: DTLS_Deallocate %p %zd\n", block);
+ VReport(2, "__tls_get_addr: DTLS_Deallocate %p\n", block);
UnmapOrDie(block, sizeof(DTLS::DTVBlock));
atomic_fetch_sub(&number_of_live_dtls, 1, memory_order_relaxed);
}
@@ -117,26 +117,27 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
return 0;
uptr tls_size = 0;
uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset - kDtvOffset;
- VReport(2, "__tls_get_addr: %p {%p,%p} => %p; tls_beg: %p; sp: %p "
- "num_live_dtls %zd\n",
+ VReport(2,
+ "__tls_get_addr: %p {0x%zx,0x%zx} => %p; tls_beg: 0x%zx; sp: %p "
+ "num_live_dtls %zd\n",
arg, arg->dso_id, arg->offset, res, tls_beg, &tls_beg,
atomic_load(&number_of_live_dtls, memory_order_relaxed));
if (dtls.last_memalign_ptr == tls_beg) {
tls_size = dtls.last_memalign_size;
- VReport(2, "__tls_get_addr: glibc <=2.18 suspected; tls={%p,%p}\n",
- tls_beg, tls_size);
+ VReport(2, "__tls_get_addr: glibc <=2.18 suspected; tls={0x%zx,0x%zx}\n",
+ tls_beg, tls_size);
} else if (tls_beg >= static_tls_begin && tls_beg < static_tls_end) {
// This is the static TLS block which was initialized / unpoisoned at thread
// creation.
- VReport(2, "__tls_get_addr: static tls: %p\n", tls_beg);
+ VReport(2, "__tls_get_addr: static tls: 0x%zx\n", tls_beg);
tls_size = 0;
} else if ((tls_beg % 4096) == sizeof(Glibc_2_19_tls_header)) {
// We may want to check gnu_get_libc_version().
Glibc_2_19_tls_header *header = (Glibc_2_19_tls_header *)tls_beg - 1;
tls_size = header->size;
tls_beg = header->start;
- VReport(2, "__tls_get_addr: glibc >=2.19 suspected; tls={%p %p}\n",
- tls_beg, tls_size);
+ VReport(2, "__tls_get_addr: glibc >=2.19 suspected; tls={0x%zx 0x%zx}\n",
+ tls_beg, tls_size);
} else {
VReport(2, "__tls_get_addr: Can't guess glibc version\n");
// This may happen inside the DTOR of main thread, so just ignore it.
@@ -149,7 +150,7 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
void DTLS_on_libc_memalign(void *ptr, uptr size) {
if (!common_flags()->intercept_tls_get_addr) return;
- VReport(2, "DTLS_on_libc_memalign: %p %p\n", ptr, size);
+ VReport(2, "DTLS_on_libc_memalign: %p 0x%zx\n", ptr, size);
dtls.last_memalign_ptr = reinterpret_cast<uptr>(ptr);
dtls.last_memalign_size = size;
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_win.cpp b/libsanitizer/sanitizer_common/sanitizer_win.cpp
index dddd885..811aa49 100644
--- a/libsanitizer/sanitizer_common/sanitizer_win.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_win.cpp
@@ -16,6 +16,7 @@
#define WIN32_LEAN_AND_MEAN
#define NOGDI
+#include <direct.h>
#include <windows.h>
#include <io.h>
#include <psapi.h>
@@ -565,6 +566,8 @@ void Abort() {
internal__exit(3);
}
+bool CreateDir(const char *pathname) { return _mkdir(pathname) == 0; }
+
#if !SANITIZER_GO
// Read the file to extract the ImageBase field from the PE header. If ASLR is
// disabled and this virtual address is available, the loader will typically
@@ -827,27 +830,6 @@ void FutexWake(atomic_uint32_t *p, u32 count) {
WakeByAddressAll(p);
}
-// ---------------------- BlockingMutex ---------------- {{{1
-
-BlockingMutex::BlockingMutex() {
- CHECK(sizeof(SRWLOCK) <= sizeof(opaque_storage_));
- internal_memset(this, 0, sizeof(*this));
-}
-
-void BlockingMutex::Lock() {
- AcquireSRWLockExclusive((PSRWLOCK)opaque_storage_);
- CHECK_EQ(owner_, 0);
- owner_ = GetThreadSelf();
-}
-
-void BlockingMutex::Unlock() {
- CheckLocked();
- owner_ = 0;
- ReleaseSRWLockExclusive((PSRWLOCK)opaque_storage_);
-}
-
-void BlockingMutex::CheckLocked() const { CHECK_EQ(owner_, GetThreadSelf()); }
-
uptr GetTlsSize() {
return 0;
}
diff --git a/libsanitizer/tsan/Makefile.am b/libsanitizer/tsan/Makefile.am
index dcb247e..9dc11f7 100644
--- a/libsanitizer/tsan/Makefile.am
+++ b/libsanitizer/tsan/Makefile.am
@@ -29,7 +29,6 @@ tsan_files = \
tsan_malloc_mac.cpp \
tsan_md5.cpp \
tsan_mman.cpp \
- tsan_mutex.cpp \
tsan_mutexset.cpp \
tsan_new_delete.cpp \
tsan_platform_linux.cpp \
@@ -45,7 +44,8 @@ tsan_files = \
tsan_stack_trace.cpp \
tsan_suppressions.cpp \
tsan_symbolize.cpp \
- tsan_sync.cpp
+ tsan_sync.cpp \
+ tsan_vector_clock.cpp
libtsan_la_SOURCES = $(tsan_files)
EXTRA_libtsan_la_SOURCES = tsan_rtl_amd64.S tsan_rtl_aarch64.S tsan_rtl_mips64.S tsan_rtl_ppc64.S tsan_rtl_s390x.S
diff --git a/libsanitizer/tsan/Makefile.in b/libsanitizer/tsan/Makefile.in
index 83617cf..921a78c 100644
--- a/libsanitizer/tsan/Makefile.in
+++ b/libsanitizer/tsan/Makefile.in
@@ -150,12 +150,13 @@ am__objects_1 = tsan_clock.lo tsan_debugging.lo tsan_external.lo \
tsan_interceptors_posix.lo tsan_interceptors_mac.lo \
tsan_interface_ann.lo tsan_interface_atomic.lo \
tsan_interface.lo tsan_interface_java.lo tsan_malloc_mac.lo \
- tsan_md5.lo tsan_mman.lo tsan_mutex.lo tsan_mutexset.lo \
- tsan_new_delete.lo tsan_platform_linux.lo tsan_platform_mac.lo \
+ tsan_md5.lo tsan_mman.lo tsan_mutexset.lo tsan_new_delete.lo \
+ tsan_platform_linux.lo tsan_platform_mac.lo \
tsan_platform_posix.lo tsan_platform_windows.lo tsan_report.lo \
tsan_rtl.lo tsan_rtl_mutex.lo tsan_rtl_proc.lo \
tsan_rtl_report.lo tsan_rtl_thread.lo tsan_stack_trace.lo \
- tsan_suppressions.lo tsan_symbolize.lo tsan_sync.lo
+ tsan_suppressions.lo tsan_symbolize.lo tsan_sync.lo \
+ tsan_vector_clock.lo
am_libtsan_la_OBJECTS = $(am__objects_1)
libtsan_la_OBJECTS = $(am_libtsan_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
@@ -431,7 +432,6 @@ tsan_files = \
tsan_malloc_mac.cpp \
tsan_md5.cpp \
tsan_mman.cpp \
- tsan_mutex.cpp \
tsan_mutexset.cpp \
tsan_new_delete.cpp \
tsan_platform_linux.cpp \
@@ -447,7 +447,8 @@ tsan_files = \
tsan_stack_trace.cpp \
tsan_suppressions.cpp \
tsan_symbolize.cpp \
- tsan_sync.cpp
+ tsan_sync.cpp \
+ tsan_vector_clock.cpp
libtsan_la_SOURCES = $(tsan_files)
EXTRA_libtsan_la_SOURCES = tsan_rtl_amd64.S tsan_rtl_aarch64.S tsan_rtl_mips64.S tsan_rtl_ppc64.S tsan_rtl_s390x.S
@@ -594,7 +595,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_malloc_mac.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_md5.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_mman.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_mutex.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_mutexset.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_new_delete.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_platform_linux.Plo@am__quote@
@@ -616,6 +616,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_suppressions.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_symbolize.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_sync.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_vector_clock.Plo@am__quote@
.S.o:
@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/libsanitizer/tsan/libtool-version b/libsanitizer/tsan/libtool-version
index 79dfeee..6fa8162 100644
--- a/libsanitizer/tsan/libtool-version
+++ b/libsanitizer/tsan/libtool-version
@@ -3,4 +3,4 @@
# a separate file so that version updates don't involve re-running
# automake.
# CURRENT:REVISION:AGE
-1:0:0
+2:0:0
diff --git a/libsanitizer/tsan/tsan_clock.cpp b/libsanitizer/tsan/tsan_clock.cpp
index 61848c2..d122b67 100644
--- a/libsanitizer/tsan/tsan_clock.cpp
+++ b/libsanitizer/tsan/tsan_clock.cpp
@@ -72,9 +72,9 @@
// clk_ - variable size vector clock, low kClkBits hold timestamp,
// the remaining bits hold "acquired" flag (the actual value is thread's
// reused counter);
-// if acquried == thr->reused_, then the respective thread has already
+// if acquired == thr->reused_, then the respective thread has already
// acquired this clock (except possibly for dirty elements).
-// dirty_ - holds up to two indeces in the vector clock that other threads
+// dirty_ - holds up to two indices in the vector clock that other threads
// need to acquire regardless of "acquired" flag value;
// release_store_tid_ - denotes that the clock state is a result of
// release-store operation by the thread with release_store_tid_ index.
@@ -272,7 +272,7 @@ void ThreadClock::ReleaseStore(ClockCache *c, SyncClock *dst) {
// we could update the existing clock and cache it, or replace it with the
// currently cached clock and release the old one. And for a shared
// existing clock, we could replace it with the currently cached;
- // or unshare, update and cache. But, for simplicity, we currnetly reuse
+ // or unshare, update and cache. But, for simplicity, we currently reuse
// cached clock only when the target clock is empty.
dst->tab_ = ctx->clock_alloc.Map(cached_idx_);
dst->tab_idx_ = cached_idx_;
@@ -285,7 +285,7 @@ void ThreadClock::ReleaseStore(ClockCache *c, SyncClock *dst) {
dst->dirty_[0].epoch = clk_[tid_];
dst->release_store_tid_ = tid_;
dst->release_store_reused_ = reused_;
- // Rememeber that we don't need to acquire it in future.
+ // Remember that we don't need to acquire it in future.
dst->elem(tid_).reused = reused_;
// Grab a reference.
atomic_fetch_add(ref_ptr(dst->tab_), 1, memory_order_relaxed);
@@ -316,7 +316,7 @@ void ThreadClock::ReleaseStore(ClockCache *c, SyncClock *dst) {
for (uptr i = 0; i < kDirtyTids; i++) dst->dirty_[i].set_tid(kInvalidTid);
dst->release_store_tid_ = tid_;
dst->release_store_reused_ = reused_;
- // Rememeber that we don't need to acquire it in future.
+ // Remember that we don't need to acquire it in future.
dst->elem(tid_).reused = reused_;
// If the resulting clock is cachable, cache it for future release operations.
diff --git a/libsanitizer/tsan/tsan_clock.h b/libsanitizer/tsan/tsan_clock.h
index 31376a1..11cbc0c 100644
--- a/libsanitizer/tsan/tsan_clock.h
+++ b/libsanitizer/tsan/tsan_clock.h
@@ -213,7 +213,7 @@ class ThreadClock {
// We reuse it for subsequent store-release operations without intervening
// acquire operations. Since it is shared (and thus constant), clock value
// for the current thread is then stored in dirty entries in the SyncClock.
- // We host a refernece to the table while it is cached here.
+ // We host a reference to the table while it is cached here.
u32 cached_idx_;
u16 cached_size_;
u16 cached_blocks_;
diff --git a/libsanitizer/tsan/tsan_debugging.cpp b/libsanitizer/tsan/tsan_debugging.cpp
index d3d6255..1d3c384 100644
--- a/libsanitizer/tsan/tsan_debugging.cpp
+++ b/libsanitizer/tsan/tsan_debugging.cpp
@@ -195,9 +195,9 @@ const char *__tsan_locate_address(uptr addr, char *name, uptr name_size,
const char *region_kind = nullptr;
if (name && name_size > 0) name[0] = 0;
- if (IsMetaMem(addr)) {
+ if (IsMetaMem(reinterpret_cast<u32 *>(addr))) {
region_kind = "meta shadow";
- } else if (IsShadowMem(addr)) {
+ } else if (IsShadowMem(reinterpret_cast<RawShadow *>(addr))) {
region_kind = "shadow";
} else {
bool is_stack = false;
@@ -215,9 +215,9 @@ const char *__tsan_locate_address(uptr addr, char *name, uptr name_size,
} else {
// TODO(kuba.brecka): We should not lock. This is supposed to be called
// from within the debugger when other threads are stopped.
- ctx->thread_registry->Lock();
+ ctx->thread_registry.Lock();
ThreadContext *tctx = IsThreadStackOrTls(addr, &is_stack);
- ctx->thread_registry->Unlock();
+ ctx->thread_registry.Unlock();
if (tctx) {
region_kind = is_stack ? "stack" : "tls";
} else {
@@ -252,7 +252,7 @@ int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id,
*thread_id = b->tid;
// No locking. This is supposed to be called from within the debugger when
// other threads are stopped.
- ThreadContextBase *tctx = ctx->thread_registry->GetThreadLocked(b->tid);
+ ThreadContextBase *tctx = ctx->thread_registry.GetThreadLocked(b->tid);
*os_id = tctx->os_id;
StackTrace stack = StackDepotGet(b->stk);
diff --git a/libsanitizer/tsan/tsan_defs.h b/libsanitizer/tsan/tsan_defs.h
index 5c8f280..fe0c1da 100644
--- a/libsanitizer/tsan/tsan_defs.h
+++ b/libsanitizer/tsan/tsan_defs.h
@@ -15,8 +15,27 @@
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_mutex.h"
#include "ubsan/ubsan_platform.h"
+#ifndef TSAN_VECTORIZE
+# define TSAN_VECTORIZE __SSE4_2__
+#endif
+
+#if TSAN_VECTORIZE
+// <emmintrin.h> transitively includes <stdlib.h>,
+// and it's prohibited to include std headers into tsan runtime.
+// So we do this dirty trick.
+# define _MM_MALLOC_H_INCLUDED
+# define __MM_MALLOC_H
+# include <emmintrin.h>
+# include <smmintrin.h>
+# define VECTOR_ALIGNED ALIGNED(16)
+typedef __m128i m128;
+#else
+# define VECTOR_ALIGNED
+#endif
+
// Setup defaults for compile definitions.
#ifndef TSAN_NO_HISTORY
# define TSAN_NO_HISTORY 0
@@ -32,6 +51,19 @@
namespace __tsan {
+constexpr uptr kByteBits = 8;
+
+// Thread slot ID.
+enum class Sid : u8 {};
+constexpr uptr kThreadSlotCount = 256;
+constexpr Sid kFreeSid = static_cast<Sid>(255);
+
+// Abstract time unit, vector clock element.
+enum class Epoch : u16 {};
+constexpr uptr kEpochBits = 14;
+constexpr Epoch kEpochZero = static_cast<Epoch>(0);
+constexpr Epoch kEpochOver = static_cast<Epoch>(1 << kEpochBits);
+
const int kClkBits = 42;
const unsigned kMaxTidReuse = (1 << (64 - kClkBits)) - 1;
@@ -74,8 +106,9 @@ const uptr kShadowCnt = 4;
// That many user bytes are mapped onto a single shadow cell.
const uptr kShadowCell = 8;
-// Size of a single shadow value (u64).
-const uptr kShadowSize = 8;
+// Single shadow value.
+typedef u64 RawShadow;
+const uptr kShadowSize = sizeof(RawShadow);
// Shadow memory is kShadowMultiplier times larger than user memory.
const uptr kShadowMultiplier = kShadowSize * kShadowCnt / kShadowCell;
@@ -87,6 +120,9 @@ const uptr kMetaShadowCell = 8;
// Size of a single meta shadow value (u32).
const uptr kMetaShadowSize = 4;
+// All addresses and PCs are assumed to be compressable to that many bits.
+const uptr kCompressedAddrBits = 44;
+
#if TSAN_NO_HISTORY
const bool kCollectHistory = false;
#else
@@ -153,12 +189,23 @@ struct ReportStack;
class ReportDesc;
class RegionAlloc;
+typedef uptr AccessType;
+
+enum : AccessType {
+ kAccessWrite = 0,
+ kAccessRead = 1 << 0,
+ kAccessAtomic = 1 << 1,
+ kAccessVptr = 1 << 2, // read or write of an object virtual table pointer
+ kAccessFree = 1 << 3, // synthetic memory access during memory freeing
+ kAccessExternalPC = 1 << 4, // access PC can have kExternalPCBit set
+};
+
// Descriptor of user's memory block.
struct MBlock {
u64 siz : 48;
u64 tag : 16;
- u32 stk;
- u16 tid;
+ StackID stk;
+ Tid tid;
};
COMPILER_CHECK(sizeof(MBlock) == 16);
@@ -172,6 +219,17 @@ enum ExternalTag : uptr {
// as 16-bit values, see tsan_defs.h.
};
+enum MutexType {
+ MutexTypeTrace = MutexLastCommon,
+ MutexTypeReport,
+ MutexTypeSyncVar,
+ MutexTypeAnnotations,
+ MutexTypeAtExit,
+ MutexTypeFired,
+ MutexTypeRacy,
+ MutexTypeGlobalProc,
+};
+
} // namespace __tsan
#endif // TSAN_DEFS_H
diff --git a/libsanitizer/tsan/tsan_dense_alloc.h b/libsanitizer/tsan/tsan_dense_alloc.h
index 6c89e40..9e15f74 100644
--- a/libsanitizer/tsan/tsan_dense_alloc.h
+++ b/libsanitizer/tsan/tsan_dense_alloc.h
@@ -20,7 +20,6 @@
#include "sanitizer_common/sanitizer_common.h"
#include "tsan_defs.h"
-#include "tsan_mutex.h"
namespace __tsan {
@@ -50,11 +49,7 @@ class DenseSlabAlloc {
static_assert(sizeof(T) > sizeof(IndexT),
"it doesn't make sense to use dense alloc");
- explicit DenseSlabAlloc(LinkerInitialized, const char *name) {
- freelist_ = 0;
- fillpos_ = 0;
- name_ = name;
- }
+ DenseSlabAlloc(LinkerInitialized, const char *name) : name_(name) {}
explicit DenseSlabAlloc(const char *name)
: DenseSlabAlloc(LINKER_INITIALIZED, name) {
@@ -90,6 +85,8 @@ class DenseSlabAlloc {
}
void FlushCache(Cache *c) {
+ if (!c->pos)
+ return;
SpinMutexLock lock(&mtx_);
while (c->pos) {
IndexT idx = c->cache[--c->pos];
@@ -103,33 +100,39 @@ class DenseSlabAlloc {
internal_memset(c->cache, 0, sizeof(c->cache));
}
+ uptr AllocatedMemory() const {
+ return atomic_load_relaxed(&fillpos_) * kL2Size * sizeof(T);
+ }
+
private:
T *map_[kL1Size];
SpinMutex mtx_;
- IndexT freelist_;
- uptr fillpos_;
- const char *name_;
+ IndexT freelist_ = {0};
+ atomic_uintptr_t fillpos_ = {0};
+ const char *const name_;
void Refill(Cache *c) {
SpinMutexLock lock(&mtx_);
if (freelist_ == 0) {
- if (fillpos_ == kL1Size) {
+ uptr fillpos = atomic_load_relaxed(&fillpos_);
+ if (fillpos == kL1Size) {
Printf("ThreadSanitizer: %s overflow (%zu*%zu). Dying.\n",
name_, kL1Size, kL2Size);
Die();
}
- VPrintf(2, "ThreadSanitizer: growing %s: %zu out of %zu*%zu\n",
- name_, fillpos_, kL1Size, kL2Size);
+ VPrintf(2, "ThreadSanitizer: growing %s: %zu out of %zu*%zu\n", name_,
+ fillpos, kL1Size, kL2Size);
T *batch = (T*)MmapOrDie(kL2Size * sizeof(T), name_);
// Reserve 0 as invalid index.
- IndexT start = fillpos_ == 0 ? 1 : 0;
+ IndexT start = fillpos == 0 ? 1 : 0;
for (IndexT i = start; i < kL2Size; i++) {
new(batch + i) T;
- *(IndexT*)(batch + i) = i + 1 + fillpos_ * kL2Size;
+ *(IndexT *)(batch + i) = i + 1 + fillpos * kL2Size;
}
*(IndexT*)(batch + kL2Size - 1) = 0;
- freelist_ = fillpos_ * kL2Size + start;
- map_[fillpos_++] = batch;
+ freelist_ = fillpos * kL2Size + start;
+ map_[fillpos] = batch;
+ atomic_store_relaxed(&fillpos_, fillpos + 1);
}
for (uptr i = 0; i < Cache::kSize / 2 && freelist_ != 0; i++) {
IndexT idx = freelist_;
diff --git a/libsanitizer/tsan/tsan_external.cpp b/libsanitizer/tsan/tsan_external.cpp
index a87e12f..19ae174 100644
--- a/libsanitizer/tsan/tsan_external.cpp
+++ b/libsanitizer/tsan/tsan_external.cpp
@@ -10,9 +10,12 @@
//
//===----------------------------------------------------------------------===//
#include "tsan_rtl.h"
-#include "tsan_interceptors.h"
#include "sanitizer_common/sanitizer_ptrauth.h"
+#if !SANITIZER_GO
+# include "tsan_interceptors.h"
+#endif
+
namespace __tsan {
#define CALLERPC ((uptr)__builtin_return_address(0))
@@ -57,16 +60,14 @@ uptr TagFromShadowStackFrame(uptr pc) {
#if !SANITIZER_GO
-typedef void(*AccessFunc)(ThreadState *, uptr, uptr, int);
-void ExternalAccess(void *addr, uptr caller_pc, void *tag, AccessFunc access) {
+void ExternalAccess(void *addr, uptr caller_pc, void *tag, AccessType typ) {
CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed));
ThreadState *thr = cur_thread();
if (caller_pc) FuncEntry(thr, caller_pc);
InsertShadowStackFrameForTag(thr, (uptr)tag);
bool in_ignored_lib;
- if (!caller_pc || !libignore()->IsIgnored(caller_pc, &in_ignored_lib)) {
- access(thr, CALLERPC, (uptr)addr, kSizeLog1);
- }
+ if (!caller_pc || !libignore()->IsIgnored(caller_pc, &in_ignored_lib))
+ MemoryAccess(thr, CALLERPC, (uptr)addr, 1, typ);
FuncExit(thr);
if (caller_pc) FuncExit(thr);
}
@@ -92,7 +93,7 @@ void __tsan_external_register_header(void *tag, const char *header) {
header = internal_strdup(header);
char *old_header =
(char *)atomic_exchange(header_ptr, (uptr)header, memory_order_seq_cst);
- if (old_header) internal_free(old_header);
+ Free(old_header);
}
SANITIZER_INTERFACE_ATTRIBUTE
@@ -111,12 +112,12 @@ void __tsan_external_assign_tag(void *addr, void *tag) {
SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_external_read(void *addr, void *caller_pc, void *tag) {
- ExternalAccess(addr, STRIP_PAC_PC(caller_pc), tag, MemoryRead);
+ ExternalAccess(addr, STRIP_PAC_PC(caller_pc), tag, kAccessRead);
}
SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_external_write(void *addr, void *caller_pc, void *tag) {
- ExternalAccess(addr, STRIP_PAC_PC(caller_pc), tag, MemoryWrite);
+ ExternalAccess(addr, STRIP_PAC_PC(caller_pc), tag, kAccessWrite);
}
} // extern "C"
diff --git a/libsanitizer/tsan/tsan_fd.cpp b/libsanitizer/tsan/tsan_fd.cpp
index 50a6b56..255ffa8 100644
--- a/libsanitizer/tsan/tsan_fd.cpp
+++ b/libsanitizer/tsan/tsan_fd.cpp
@@ -26,8 +26,8 @@ struct FdSync {
struct FdDesc {
FdSync *sync;
- int creation_tid;
- u32 creation_stack;
+ Tid creation_tid;
+ StackID creation_stack;
};
struct FdContext {
@@ -115,7 +115,7 @@ static void init(ThreadState *thr, uptr pc, int fd, FdSync *s,
MemoryRangeImitateWrite(thr, pc, (uptr)d, 8);
} else {
// See the dup-related comment in FdClose.
- MemoryRead(thr, pc, (uptr)d, kSizeLog8);
+ MemoryAccess(thr, pc, (uptr)d, 8, kAccessRead);
}
}
@@ -140,7 +140,7 @@ void FdOnFork(ThreadState *thr, uptr pc) {
}
}
-bool FdLocation(uptr addr, int *fd, int *tid, u32 *stack) {
+bool FdLocation(uptr addr, int *fd, Tid *tid, StackID *stack) {
for (int l1 = 0; l1 < kTableSizeL1; l1++) {
FdDesc *tab = (FdDesc*)atomic_load(&fdctx.tab[l1], memory_order_relaxed);
if (tab == 0)
@@ -163,7 +163,7 @@ void FdAcquire(ThreadState *thr, uptr pc, int fd) {
FdDesc *d = fddesc(thr, pc, fd);
FdSync *s = d->sync;
DPrintf("#%d: FdAcquire(%d) -> %p\n", thr->tid, fd, s);
- MemoryRead(thr, pc, (uptr)d, kSizeLog8);
+ MemoryAccess(thr, pc, (uptr)d, 8, kAccessRead);
if (s)
Acquire(thr, pc, (uptr)s);
}
@@ -174,7 +174,7 @@ void FdRelease(ThreadState *thr, uptr pc, int fd) {
FdDesc *d = fddesc(thr, pc, fd);
FdSync *s = d->sync;
DPrintf("#%d: FdRelease(%d) -> %p\n", thr->tid, fd, s);
- MemoryRead(thr, pc, (uptr)d, kSizeLog8);
+ MemoryAccess(thr, pc, (uptr)d, 8, kAccessRead);
if (s)
Release(thr, pc, (uptr)s);
}
@@ -184,7 +184,7 @@ void FdAccess(ThreadState *thr, uptr pc, int fd) {
if (bogusfd(fd))
return;
FdDesc *d = fddesc(thr, pc, fd);
- MemoryRead(thr, pc, (uptr)d, kSizeLog8);
+ MemoryAccess(thr, pc, (uptr)d, 8, kAccessRead);
}
void FdClose(ThreadState *thr, uptr pc, int fd, bool write) {
@@ -194,7 +194,7 @@ void FdClose(ThreadState *thr, uptr pc, int fd, bool write) {
FdDesc *d = fddesc(thr, pc, fd);
if (write) {
// To catch races between fd usage and close.
- MemoryWrite(thr, pc, (uptr)d, kSizeLog8);
+ MemoryAccess(thr, pc, (uptr)d, 8, kAccessWrite);
} else {
// This path is used only by dup2/dup3 calls.
// We do read instead of write because there is a number of legitimate
@@ -204,15 +204,15 @@ void FdClose(ThreadState *thr, uptr pc, int fd, bool write) {
// 2. Some daemons dup /dev/null in place of stdin/stdout.
// On the other hand we have not seen cases when write here catches real
// bugs.
- MemoryRead(thr, pc, (uptr)d, kSizeLog8);
+ MemoryAccess(thr, pc, (uptr)d, 8, kAccessRead);
}
// We need to clear it, because if we do not intercept any call out there
// that creates fd, we will hit false postives.
MemoryResetRange(thr, pc, (uptr)d, 8);
unref(thr, pc, d->sync);
d->sync = 0;
- d->creation_tid = 0;
- d->creation_stack = 0;
+ d->creation_tid = kInvalidTid;
+ d->creation_stack = kInvalidStackID;
}
void FdFileCreate(ThreadState *thr, uptr pc, int fd) {
@@ -228,7 +228,7 @@ void FdDup(ThreadState *thr, uptr pc, int oldfd, int newfd, bool write) {
return;
// Ignore the case when user dups not yet connected socket.
FdDesc *od = fddesc(thr, pc, oldfd);
- MemoryRead(thr, pc, (uptr)od, kSizeLog8);
+ MemoryAccess(thr, pc, (uptr)od, 8, kAccessRead);
FdClose(thr, pc, newfd, write);
init(thr, pc, newfd, ref(od->sync), write);
}
diff --git a/libsanitizer/tsan/tsan_fd.h b/libsanitizer/tsan/tsan_fd.h
index ce4f2f7..d964817 100644
--- a/libsanitizer/tsan/tsan_fd.h
+++ b/libsanitizer/tsan/tsan_fd.h
@@ -53,7 +53,7 @@ void FdSocketCreate(ThreadState *thr, uptr pc, int fd);
void FdSocketAccept(ThreadState *thr, uptr pc, int fd, int newfd);
void FdSocketConnecting(ThreadState *thr, uptr pc, int fd);
void FdSocketConnect(ThreadState *thr, uptr pc, int fd);
-bool FdLocation(uptr addr, int *fd, int *tid, u32 *stack);
+bool FdLocation(uptr addr, int *fd, Tid *tid, StackID *stack);
void FdOnFork(ThreadState *thr, uptr pc);
uptr File2addr(const char *path);
diff --git a/libsanitizer/tsan/tsan_flags.cpp b/libsanitizer/tsan/tsan_flags.cpp
index 49e4a9c..ee89862 100644
--- a/libsanitizer/tsan/tsan_flags.cpp
+++ b/libsanitizer/tsan/tsan_flags.cpp
@@ -55,6 +55,7 @@ void InitializeFlags(Flags *f, const char *env, const char *env_option_name) {
// Override some common flags defaults.
CommonFlags cf;
cf.CopyFrom(*common_flags());
+ cf.external_symbolizer_path = GetEnv("TSAN_SYMBOLIZER_PATH");
cf.allow_addr2line = true;
if (SANITIZER_GO) {
// Does not work as expected for Go: runtime handles SIGABRT and crashes.
diff --git a/libsanitizer/tsan/tsan_flags.inc b/libsanitizer/tsan/tsan_flags.inc
index 2105c75..7954a430 100644
--- a/libsanitizer/tsan/tsan_flags.inc
+++ b/libsanitizer/tsan/tsan_flags.inc
@@ -43,7 +43,6 @@ TSAN_FLAG(
bool, force_seq_cst_atomics, false,
"If set, all atomics are effectively sequentially consistent (seq_cst), "
"regardless of what user actually specified.")
-TSAN_FLAG(bool, print_benign, false, "Print matched \"benign\" races at exit.")
TSAN_FLAG(bool, halt_on_error, false, "Exit after first reported error.")
TSAN_FLAG(int, atexit_sleep_ms, 1000,
"Sleep in main thread before exiting for that many ms "
diff --git a/libsanitizer/tsan/tsan_ignoreset.cpp b/libsanitizer/tsan/tsan_ignoreset.cpp
index f6e41f6..1fca1cf 100644
--- a/libsanitizer/tsan/tsan_ignoreset.cpp
+++ b/libsanitizer/tsan/tsan_ignoreset.cpp
@@ -19,7 +19,7 @@ IgnoreSet::IgnoreSet()
: size_() {
}
-void IgnoreSet::Add(u32 stack_id) {
+void IgnoreSet::Add(StackID stack_id) {
if (size_ == kMaxSize)
return;
for (uptr i = 0; i < size_; i++) {
@@ -29,15 +29,7 @@ void IgnoreSet::Add(u32 stack_id) {
stacks_[size_++] = stack_id;
}
-void IgnoreSet::Reset() {
- size_ = 0;
-}
-
-uptr IgnoreSet::Size() const {
- return size_;
-}
-
-u32 IgnoreSet::At(uptr i) const {
+StackID IgnoreSet::At(uptr i) const {
CHECK_LT(i, size_);
CHECK_LE(size_, kMaxSize);
return stacks_[i];
diff --git a/libsanitizer/tsan/tsan_ignoreset.h b/libsanitizer/tsan/tsan_ignoreset.h
index 3e318bd..4e25112 100644
--- a/libsanitizer/tsan/tsan_ignoreset.h
+++ b/libsanitizer/tsan/tsan_ignoreset.h
@@ -19,17 +19,16 @@ namespace __tsan {
class IgnoreSet {
public:
- static const uptr kMaxSize = 16;
-
IgnoreSet();
- void Add(u32 stack_id);
- void Reset();
- uptr Size() const;
- u32 At(uptr i) const;
+ void Add(StackID stack_id);
+ void Reset() { size_ = 0; }
+ uptr Size() const { return size_; }
+ StackID At(uptr i) const;
private:
+ static constexpr uptr kMaxSize = 16;
uptr size_;
- u32 stacks_[kMaxSize];
+ StackID stacks_[kMaxSize];
};
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_ilist.h b/libsanitizer/tsan/tsan_ilist.h
new file mode 100644
index 0000000..d7d8be2
--- /dev/null
+++ b/libsanitizer/tsan/tsan_ilist.h
@@ -0,0 +1,189 @@
+//===-- tsan_ilist.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_ILIST_H
+#define TSAN_ILIST_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+namespace __tsan {
+
+class INode {
+ public:
+ INode() = default;
+
+ private:
+ INode* next_ = nullptr;
+ INode* prev_ = nullptr;
+
+ template <typename Base, INode Base::*Node, typename Elem>
+ friend class IList;
+ INode(const INode&) = delete;
+ void operator=(const INode&) = delete;
+};
+
+// Intrusive doubly-linked list.
+//
+// The node class (MyNode) needs to include "INode foo" field,
+// then the list can be declared as IList<MyNode, &MyNode::foo>.
+// This design allows to link MyNode into multiple lists using
+// different INode fields.
+// The optional Elem template argument allows to specify node MDT
+// (most derived type) if it's different from MyNode.
+template <typename Base, INode Base::*Node, typename Elem = Base>
+class IList {
+ public:
+ IList();
+
+ void PushFront(Elem* e);
+ void PushBack(Elem* e);
+ void Remove(Elem* e);
+
+ Elem* PopFront();
+ Elem* PopBack();
+ Elem* Front();
+ Elem* Back();
+
+ // Prev links point towards front of the queue.
+ Elem* Prev(Elem* e);
+ // Next links point towards back of the queue.
+ Elem* Next(Elem* e);
+
+ uptr Size() const;
+ bool Empty() const;
+ bool Queued(Elem* e) const;
+
+ private:
+ INode node_;
+ uptr size_ = 0;
+
+ void Push(Elem* e, INode* after);
+ static INode* ToNode(Elem* e);
+ static Elem* ToElem(INode* n);
+
+ IList(const IList&) = delete;
+ void operator=(const IList&) = delete;
+};
+
+template <typename Base, INode Base::*Node, typename Elem>
+IList<Base, Node, Elem>::IList() {
+ node_.next_ = node_.prev_ = &node_;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+void IList<Base, Node, Elem>::PushFront(Elem* e) {
+ Push(e, &node_);
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+void IList<Base, Node, Elem>::PushBack(Elem* e) {
+ Push(e, node_.prev_);
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+void IList<Base, Node, Elem>::Push(Elem* e, INode* after) {
+ INode* n = ToNode(e);
+ DCHECK_EQ(n->next_, nullptr);
+ DCHECK_EQ(n->prev_, nullptr);
+ INode* next = after->next_;
+ n->next_ = next;
+ n->prev_ = after;
+ next->prev_ = n;
+ after->next_ = n;
+ size_++;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+void IList<Base, Node, Elem>::Remove(Elem* e) {
+ INode* n = ToNode(e);
+ INode* next = n->next_;
+ INode* prev = n->prev_;
+ DCHECK(next);
+ DCHECK(prev);
+ DCHECK(size_);
+ next->prev_ = prev;
+ prev->next_ = next;
+ n->prev_ = n->next_ = nullptr;
+ size_--;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+Elem* IList<Base, Node, Elem>::PopFront() {
+ Elem* e = Front();
+ if (e)
+ Remove(e);
+ return e;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+Elem* IList<Base, Node, Elem>::PopBack() {
+ Elem* e = Back();
+ if (e)
+ Remove(e);
+ return e;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+Elem* IList<Base, Node, Elem>::Front() {
+ return size_ ? ToElem(node_.next_) : nullptr;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+Elem* IList<Base, Node, Elem>::Back() {
+ return size_ ? ToElem(node_.prev_) : nullptr;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+Elem* IList<Base, Node, Elem>::Prev(Elem* e) {
+ INode* n = ToNode(e);
+ DCHECK(n->prev_);
+ return n->prev_ != &node_ ? ToElem(n->prev_) : nullptr;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+Elem* IList<Base, Node, Elem>::Next(Elem* e) {
+ INode* n = ToNode(e);
+ DCHECK(n->next_);
+ return n->next_ != &node_ ? ToElem(n->next_) : nullptr;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+uptr IList<Base, Node, Elem>::Size() const {
+ return size_;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+bool IList<Base, Node, Elem>::Empty() const {
+ return size_ == 0;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+bool IList<Base, Node, Elem>::Queued(Elem* e) const {
+ INode* n = ToNode(e);
+ DCHECK_EQ(!n->next_, !n->prev_);
+ return n->next_;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+INode* IList<Base, Node, Elem>::ToNode(Elem* e) {
+ return &(e->*Node);
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+Elem* IList<Base, Node, Elem>::ToElem(INode* n) {
+ return static_cast<Elem*>(reinterpret_cast<Base*>(
+ reinterpret_cast<uptr>(n) -
+ reinterpret_cast<uptr>(&(reinterpret_cast<Elem*>(0)->*Node))));
+}
+
+} // namespace __tsan
+
+#endif
diff --git a/libsanitizer/tsan/tsan_interceptors.h b/libsanitizer/tsan/tsan_interceptors.h
index c5716f5..89b2f99 100644
--- a/libsanitizer/tsan/tsan_interceptors.h
+++ b/libsanitizer/tsan/tsan_interceptors.h
@@ -10,44 +10,49 @@ class ScopedInterceptor {
public:
ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc);
~ScopedInterceptor();
- void DisableIgnores();
- void EnableIgnores();
+ void DisableIgnores() {
+ if (UNLIKELY(ignoring_))
+ DisableIgnoresImpl();
+ }
+ void EnableIgnores() {
+ if (UNLIKELY(ignoring_))
+ EnableIgnoresImpl();
+ }
+
private:
ThreadState *const thr_;
- const uptr pc_;
bool in_ignored_lib_;
bool ignoring_;
+
+ void DisableIgnoresImpl();
+ void EnableIgnoresImpl();
};
LibIgnore *libignore();
#if !SANITIZER_GO
inline bool in_symbolizer() {
- cur_thread_init();
- return UNLIKELY(cur_thread()->in_symbolizer);
+ return UNLIKELY(cur_thread_init()->in_symbolizer);
}
#endif
} // namespace __tsan
#define SCOPED_INTERCEPTOR_RAW(func, ...) \
- cur_thread_init(); \
- ThreadState *thr = cur_thread(); \
+ ThreadState *thr = cur_thread_init(); \
const uptr caller_pc = GET_CALLER_PC(); \
ScopedInterceptor si(thr, #func, caller_pc); \
const uptr pc = GET_CURRENT_PC(); \
- (void)pc; \
- /**/
+ (void)pc;
-#define SCOPED_TSAN_INTERCEPTOR(func, ...) \
- SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
- if (REAL(func) == 0) { \
- Report("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \
- Die(); \
- } \
- if (!thr->is_inited || thr->ignore_interceptors || thr->in_ignored_lib) \
- return REAL(func)(__VA_ARGS__); \
-/**/
+#define SCOPED_TSAN_INTERCEPTOR(func, ...) \
+ SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
+ if (REAL(func) == 0) { \
+ Report("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \
+ Die(); \
+ } \
+ if (!thr->is_inited || thr->ignore_interceptors || thr->in_ignored_lib) \
+ return REAL(func)(__VA_ARGS__);
#define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START() \
si.DisableIgnores();
diff --git a/libsanitizer/tsan/tsan_interceptors_mac.cpp b/libsanitizer/tsan/tsan_interceptors_mac.cpp
index 2d400c7..ed06415 100644
--- a/libsanitizer/tsan/tsan_interceptors_mac.cpp
+++ b/libsanitizer/tsan/tsan_interceptors_mac.cpp
@@ -365,7 +365,7 @@ static uptr GetOrCreateSyncAddress(uptr addr, ThreadState *thr, uptr pc) {
if (h.created()) {
ThreadIgnoreBegin(thr, pc);
*h = (uptr) user_alloc(thr, pc, /*size=*/1);
- ThreadIgnoreEnd(thr, pc);
+ ThreadIgnoreEnd(thr);
}
return *h;
}
@@ -405,8 +405,8 @@ TSAN_INTERCEPTOR(int, swapcontext, ucontext_t *oucp, const ucontext_t *ucp) {
{
SCOPED_INTERCEPTOR_RAW(swapcontext, oucp, ucp);
}
- // Bacause of swapcontext() semantics we have no option but to copy its
- // impementation here
+ // Because of swapcontext() semantics we have no option but to copy its
+ // implementation here
if (!oucp || !ucp) {
errno = EINVAL;
return -1;
diff --git a/libsanitizer/tsan/tsan_interceptors_posix.cpp b/libsanitizer/tsan/tsan_interceptors_posix.cpp
index 6808f2e..617eda6 100644
--- a/libsanitizer/tsan/tsan_interceptors_posix.cpp
+++ b/libsanitizer/tsan/tsan_interceptors_posix.cpp
@@ -96,9 +96,6 @@ extern "C" void _exit(int status);
extern "C" int fileno_unlocked(void *stream);
extern "C" int dirfd(void *dirp);
#endif
-#if SANITIZER_GLIBC
-extern "C" int mallopt(int param, int value);
-#endif
#if SANITIZER_NETBSD
extern __sanitizer_FILE __sF[];
#else
@@ -156,12 +153,11 @@ const int SIG_SETMASK = 2;
#endif
#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED \
- (cur_thread_init(), !cur_thread()->is_inited)
+ (!cur_thread_init()->is_inited)
namespace __tsan {
struct SignalDesc {
bool armed;
- bool sigaction;
__sanitizer_siginfo siginfo;
ucontext_t ctx;
};
@@ -169,7 +165,6 @@ struct SignalDesc {
struct ThreadSignalContext {
int int_signal_send;
atomic_uintptr_t in_blocking_func;
- atomic_uintptr_t have_pending_signals;
SignalDesc pending_signals[kSigCount];
// emptyset and oldset are too big for stack.
__sanitizer_sigset_t emptyset;
@@ -196,12 +191,10 @@ struct InterceptorContext {
unsigned finalize_key;
#endif
- BlockingMutex atexit_mu;
+ Mutex atexit_mu;
Vector<struct AtExitCtx *> AtExitStack;
- InterceptorContext()
- : libignore(LINKER_INITIALIZED), AtExitStack() {
- }
+ InterceptorContext() : libignore(LINKER_INITIALIZED), atexit_mu(MutexTypeAtExit), AtExitStack() {}
};
static ALIGNED(64) char interceptor_placeholder[sizeof(InterceptorContext)];
@@ -250,8 +243,8 @@ static ThreadSignalContext *SigCtx(ThreadState *thr) {
ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
uptr pc)
- : thr_(thr), pc_(pc), in_ignored_lib_(false), ignoring_(false) {
- Initialize(thr);
+ : thr_(thr), in_ignored_lib_(false), ignoring_(false) {
+ LazyInitialize(thr);
if (!thr_->is_inited) return;
if (!thr_->ignore_interceptors) FuncEntry(thr, pc);
DPrintf("#%d: intercept %s()\n", thr_->tid, fname);
@@ -267,29 +260,29 @@ ScopedInterceptor::~ScopedInterceptor() {
if (!thr_->ignore_interceptors) {
ProcessPendingSignals(thr_);
FuncExit(thr_);
- CheckNoLocks(thr_);
+ CheckedMutex::CheckNoLocks();
}
}
-void ScopedInterceptor::EnableIgnores() {
- if (ignoring_) {
- ThreadIgnoreBegin(thr_, pc_, /*save_stack=*/false);
- if (flags()->ignore_noninstrumented_modules) thr_->suppress_reports++;
- if (in_ignored_lib_) {
- DCHECK(!thr_->in_ignored_lib);
- thr_->in_ignored_lib = true;
- }
+NOINLINE
+void ScopedInterceptor::EnableIgnoresImpl() {
+ ThreadIgnoreBegin(thr_, 0);
+ if (flags()->ignore_noninstrumented_modules)
+ thr_->suppress_reports++;
+ if (in_ignored_lib_) {
+ DCHECK(!thr_->in_ignored_lib);
+ thr_->in_ignored_lib = true;
}
}
-void ScopedInterceptor::DisableIgnores() {
- if (ignoring_) {
- ThreadIgnoreEnd(thr_, pc_);
- if (flags()->ignore_noninstrumented_modules) thr_->suppress_reports--;
- if (in_ignored_lib_) {
- DCHECK(thr_->in_ignored_lib);
- thr_->in_ignored_lib = false;
- }
+NOINLINE
+void ScopedInterceptor::DisableIgnoresImpl() {
+ ThreadIgnoreEnd(thr_);
+ if (flags()->ignore_noninstrumented_modules)
+ thr_->suppress_reports--;
+ if (in_ignored_lib_) {
+ DCHECK(thr_->in_ignored_lib);
+ thr_->in_ignored_lib = false;
}
}
@@ -325,7 +318,7 @@ struct BlockingCall {
, ctx(SigCtx(thr)) {
for (;;) {
atomic_store(&ctx->in_blocking_func, 1, memory_order_relaxed);
- if (atomic_load(&ctx->have_pending_signals, memory_order_relaxed) == 0)
+ if (atomic_load(&thr->pending_signals, memory_order_relaxed) == 0)
break;
atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed);
ProcessPendingSignals(thr);
@@ -377,7 +370,7 @@ static void at_exit_wrapper() {
AtExitCtx *ctx;
{
// Ensure thread-safety.
- BlockingMutexLock l(&interceptor_ctx()->atexit_mu);
+ Lock l(&interceptor_ctx()->atexit_mu);
// Pop AtExitCtx from the top of the stack of callback functions
uptr element = interceptor_ctx()->AtExitStack.Size() - 1;
@@ -387,14 +380,14 @@ static void at_exit_wrapper() {
Acquire(cur_thread(), (uptr)0, (uptr)ctx);
((void(*)())ctx->f)();
- InternalFree(ctx);
+ Free(ctx);
}
static void cxa_at_exit_wrapper(void *arg) {
Acquire(cur_thread(), 0, (uptr)arg);
AtExitCtx *ctx = (AtExitCtx*)arg;
((void(*)(void *arg))ctx->f)(ctx->arg);
- InternalFree(ctx);
+ Free(ctx);
}
static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
@@ -420,7 +413,7 @@ TSAN_INTERCEPTOR(int, __cxa_atexit, void (*f)(void *a), void *arg, void *dso) {
static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
void *arg, void *dso) {
- AtExitCtx *ctx = (AtExitCtx*)InternalAlloc(sizeof(AtExitCtx));
+ auto *ctx = New<AtExitCtx>();
ctx->f = f;
ctx->arg = arg;
Release(thr, pc, (uptr)ctx);
@@ -433,7 +426,10 @@ static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
// Store ctx in a local stack-like structure
// Ensure thread-safety.
- BlockingMutexLock l(&interceptor_ctx()->atexit_mu);
+ Lock l(&interceptor_ctx()->atexit_mu);
+ // __cxa_atexit calls calloc. If we don't ignore interceptors, we will fail
+ // due to atexit_mu held on exit from the calloc interceptor.
+ ScopedIgnoreInterceptors ignore;
res = REAL(__cxa_atexit)((void (*)(void *a))at_exit_wrapper, 0, 0);
// Push AtExitCtx on the top of the stack of callback functions
@@ -443,7 +439,7 @@ static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
} else {
res = REAL(__cxa_atexit)(cxa_at_exit_wrapper, ctx, dso);
}
- ThreadIgnoreEnd(thr, pc);
+ ThreadIgnoreEnd(thr);
return res;
}
@@ -454,14 +450,14 @@ static void on_exit_wrapper(int status, void *arg) {
Acquire(thr, pc, (uptr)arg);
AtExitCtx *ctx = (AtExitCtx*)arg;
((void(*)(int status, void *arg))ctx->f)(status, ctx->arg);
- InternalFree(ctx);
+ Free(ctx);
}
TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) {
if (in_symbolizer())
return 0;
SCOPED_TSAN_INTERCEPTOR(on_exit, f, arg);
- AtExitCtx *ctx = (AtExitCtx*)InternalAlloc(sizeof(AtExitCtx));
+ auto *ctx = New<AtExitCtx>();
ctx->f = (void(*)())f;
ctx->arg = arg;
Release(thr, pc, (uptr)ctx);
@@ -469,7 +465,7 @@ TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) {
// because we do not see synchronization around atexit callback list.
ThreadIgnoreBegin(thr, pc);
int res = REAL(on_exit)(on_exit_wrapper, ctx);
- ThreadIgnoreEnd(thr, pc);
+ ThreadIgnoreEnd(thr);
return res;
}
#define TSAN_MAYBE_INTERCEPT_ON_EXIT TSAN_INTERCEPT(on_exit)
@@ -535,10 +531,7 @@ static void LongJmp(ThreadState *thr, uptr *env) {
}
// FIXME: put everything below into a common extern "C" block?
-extern "C" void __tsan_setjmp(uptr sp) {
- cur_thread_init();
- SetJmp(cur_thread(), sp);
-}
+extern "C" void __tsan_setjmp(uptr sp) { SetJmp(cur_thread_init(), sp); }
#if SANITIZER_MAC
TSAN_INTERCEPTOR(int, setjmp, void *env);
@@ -848,6 +841,53 @@ TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
}
#endif
+// Both __cxa_guard_acquire and pthread_once 0-initialize
+// the object initially. pthread_once does not have any
+// other ABI requirements. __cxa_guard_acquire assumes
+// that any non-0 value in the first byte means that
+// initialization is completed. Contents of the remaining
+// bytes are up to us.
+constexpr u32 kGuardInit = 0;
+constexpr u32 kGuardDone = 1;
+constexpr u32 kGuardRunning = 1 << 16;
+constexpr u32 kGuardWaiter = 1 << 17;
+
+static int guard_acquire(ThreadState *thr, uptr pc, atomic_uint32_t *g,
+ bool blocking_hooks = true) {
+ if (blocking_hooks)
+ OnPotentiallyBlockingRegionBegin();
+ auto on_exit = at_scope_exit([blocking_hooks] {
+ if (blocking_hooks)
+ OnPotentiallyBlockingRegionEnd();
+ });
+
+ for (;;) {
+ u32 cmp = atomic_load(g, memory_order_acquire);
+ if (cmp == kGuardInit) {
+ if (atomic_compare_exchange_strong(g, &cmp, kGuardRunning,
+ memory_order_relaxed))
+ return 1;
+ } else if (cmp == kGuardDone) {
+ if (!thr->in_ignored_lib)
+ Acquire(thr, pc, (uptr)g);
+ return 0;
+ } else {
+ if ((cmp & kGuardWaiter) ||
+ atomic_compare_exchange_strong(g, &cmp, cmp | kGuardWaiter,
+ memory_order_relaxed))
+ FutexWait(g, cmp | kGuardWaiter);
+ }
+ }
+}
+
+static void guard_release(ThreadState *thr, uptr pc, atomic_uint32_t *g) {
+ if (!thr->in_ignored_lib)
+ Release(thr, pc, (uptr)g);
+ u32 old = atomic_exchange(g, kGuardDone, memory_order_release);
+ if (old & kGuardWaiter)
+ FutexWake(g, 1 << 30);
+}
+
// __cxa_guard_acquire and friends need to be intercepted in a special way -
// regular interceptors will break statically-linked libstdc++. Linux
// interceptors are especially defined as weak functions (so that they don't
@@ -868,31 +908,17 @@ TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
// Used in thread-safe function static initialization.
STDCXX_INTERCEPTOR(int, __cxa_guard_acquire, atomic_uint32_t *g) {
SCOPED_INTERCEPTOR_RAW(__cxa_guard_acquire, g);
- OnPotentiallyBlockingRegionBegin();
- auto on_exit = at_scope_exit(&OnPotentiallyBlockingRegionEnd);
- for (;;) {
- u32 cmp = atomic_load(g, memory_order_acquire);
- if (cmp == 0) {
- if (atomic_compare_exchange_strong(g, &cmp, 1<<16, memory_order_relaxed))
- return 1;
- } else if (cmp == 1) {
- Acquire(thr, pc, (uptr)g);
- return 0;
- } else {
- internal_sched_yield();
- }
- }
+ return guard_acquire(thr, pc, g);
}
STDCXX_INTERCEPTOR(void, __cxa_guard_release, atomic_uint32_t *g) {
SCOPED_INTERCEPTOR_RAW(__cxa_guard_release, g);
- Release(thr, pc, (uptr)g);
- atomic_store(g, 1, memory_order_release);
+ guard_release(thr, pc, g);
}
STDCXX_INTERCEPTOR(void, __cxa_guard_abort, atomic_uint32_t *g) {
SCOPED_INTERCEPTOR_RAW(__cxa_guard_abort, g);
- atomic_store(g, 0, memory_order_relaxed);
+ atomic_store(g, kGuardInit, memory_order_relaxed);
}
namespace __tsan {
@@ -934,17 +960,17 @@ static void thread_finalize(void *v) {
struct ThreadParam {
void* (*callback)(void *arg);
void *param;
- atomic_uintptr_t tid;
+ Tid tid;
+ Semaphore created;
+ Semaphore started;
};
extern "C" void *__tsan_thread_start_func(void *arg) {
ThreadParam *p = (ThreadParam*)arg;
void* (*callback)(void *arg) = p->callback;
void *param = p->param;
- int tid = 0;
{
- cur_thread_init();
- ThreadState *thr = cur_thread();
+ ThreadState *thr = cur_thread_init();
// Thread-local state is not initialized yet.
ScopedIgnoreInterceptors ignore;
#if !SANITIZER_MAC && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
@@ -954,14 +980,13 @@ extern "C" void *__tsan_thread_start_func(void *arg) {
Printf("ThreadSanitizer: failed to set thread key\n");
Die();
}
- ThreadIgnoreEnd(thr, 0);
+ ThreadIgnoreEnd(thr);
#endif
- while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
- internal_sched_yield();
+ p->created.Wait();
Processor *proc = ProcCreate();
ProcWire(proc, thr);
- ThreadStart(thr, tid, GetTid(), ThreadType::Regular);
- atomic_store(&p->tid, 0, memory_order_release);
+ ThreadStart(thr, p->tid, GetTid(), ThreadType::Regular);
+ p->started.Post();
}
void *res = callback(param);
// Prevent the callback from being tail called,
@@ -983,9 +1008,11 @@ TSAN_INTERCEPTOR(int, pthread_create,
"fork is not supported. Dying (set die_after_fork=0 to override)\n");
Die();
} else {
- VPrintf(1, "ThreadSanitizer: starting new threads after multi-threaded "
- "fork is not supported (pid %d). Continuing because of "
- "die_after_fork=0, but you are on your own\n", internal_getpid());
+ VPrintf(1,
+ "ThreadSanitizer: starting new threads after multi-threaded "
+ "fork is not supported (pid %lu). Continuing because of "
+ "die_after_fork=0, but you are on your own\n",
+ internal_getpid());
}
}
__sanitizer_pthread_attr_t myattr;
@@ -1000,18 +1027,18 @@ TSAN_INTERCEPTOR(int, pthread_create,
ThreadParam p;
p.callback = callback;
p.param = param;
- atomic_store(&p.tid, 0, memory_order_relaxed);
+ p.tid = kMainTid;
int res = -1;
{
// Otherwise we see false positives in pthread stack manipulation.
ScopedIgnoreInterceptors ignore;
ThreadIgnoreBegin(thr, pc);
res = REAL(pthread_create)(th, attr, __tsan_thread_start_func, &p);
- ThreadIgnoreEnd(thr, pc);
+ ThreadIgnoreEnd(thr);
}
if (res == 0) {
- int tid = ThreadCreate(thr, pc, *(uptr*)th, IsStateDetached(detached));
- CHECK_NE(tid, 0);
+ p.tid = ThreadCreate(thr, pc, *(uptr *)th, IsStateDetached(detached));
+ CHECK_NE(p.tid, kMainTid);
// Synchronization on p.tid serves two purposes:
// 1. ThreadCreate must finish before the new thread starts.
// Otherwise the new thread can call pthread_detach, but the pthread_t
@@ -1019,9 +1046,8 @@ TSAN_INTERCEPTOR(int, pthread_create,
// 2. ThreadStart must finish before this thread continues.
// Otherwise, this thread can call pthread_detach and reset thr->sync
// before the new thread got a chance to acquire from it in ThreadStart.
- atomic_store(&p.tid, tid, memory_order_release);
- while (atomic_load(&p.tid, memory_order_acquire) != 0)
- internal_sched_yield();
+ p.created.Post();
+ p.started.Wait();
}
if (attr == &myattr)
pthread_attr_destroy(&myattr);
@@ -1030,10 +1056,10 @@ TSAN_INTERCEPTOR(int, pthread_create,
TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
SCOPED_INTERCEPTOR_RAW(pthread_join, th, ret);
- int tid = ThreadConsumeTid(thr, pc, (uptr)th);
+ Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
ThreadIgnoreBegin(thr, pc);
int res = BLOCK_REAL(pthread_join)(th, ret);
- ThreadIgnoreEnd(thr, pc);
+ ThreadIgnoreEnd(thr);
if (res == 0) {
ThreadJoin(thr, pc, tid);
}
@@ -1044,7 +1070,7 @@ DEFINE_REAL_PTHREAD_FUNCTIONS
TSAN_INTERCEPTOR(int, pthread_detach, void *th) {
SCOPED_INTERCEPTOR_RAW(pthread_detach, th);
- int tid = ThreadConsumeTid(thr, pc, (uptr)th);
+ Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
int res = REAL(pthread_detach)(th);
if (res == 0) {
ThreadDetach(thr, pc, tid);
@@ -1065,10 +1091,10 @@ TSAN_INTERCEPTOR(void, pthread_exit, void *retval) {
#if SANITIZER_LINUX
TSAN_INTERCEPTOR(int, pthread_tryjoin_np, void *th, void **ret) {
SCOPED_INTERCEPTOR_RAW(pthread_tryjoin_np, th, ret);
- int tid = ThreadConsumeTid(thr, pc, (uptr)th);
+ Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
ThreadIgnoreBegin(thr, pc);
int res = REAL(pthread_tryjoin_np)(th, ret);
- ThreadIgnoreEnd(thr, pc);
+ ThreadIgnoreEnd(thr);
if (res == 0)
ThreadJoin(thr, pc, tid);
else
@@ -1079,10 +1105,10 @@ TSAN_INTERCEPTOR(int, pthread_tryjoin_np, void *th, void **ret) {
TSAN_INTERCEPTOR(int, pthread_timedjoin_np, void *th, void **ret,
const struct timespec *abstime) {
SCOPED_INTERCEPTOR_RAW(pthread_timedjoin_np, th, ret, abstime);
- int tid = ThreadConsumeTid(thr, pc, (uptr)th);
+ Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
ThreadIgnoreBegin(thr, pc);
int res = BLOCK_REAL(pthread_timedjoin_np)(th, ret, abstime);
- ThreadIgnoreEnd(thr, pc);
+ ThreadIgnoreEnd(thr);
if (res == 0)
ThreadJoin(thr, pc, tid);
else
@@ -1446,14 +1472,14 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) {
#if !SANITIZER_MAC
TSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) {
SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count);
- MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
+ MemoryAccess(thr, pc, (uptr)b, 1, kAccessWrite);
int res = REAL(pthread_barrier_init)(b, a, count);
return res;
}
TSAN_INTERCEPTOR(int, pthread_barrier_destroy, void *b) {
SCOPED_TSAN_INTERCEPTOR(pthread_barrier_destroy, b);
- MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
+ MemoryAccess(thr, pc, (uptr)b, 1, kAccessWrite);
int res = REAL(pthread_barrier_destroy)(b);
return res;
}
@@ -1461,9 +1487,9 @@ TSAN_INTERCEPTOR(int, pthread_barrier_destroy, void *b) {
TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) {
SCOPED_TSAN_INTERCEPTOR(pthread_barrier_wait, b);
Release(thr, pc, (uptr)b);
- MemoryRead(thr, pc, (uptr)b, kSizeLog1);
+ MemoryAccess(thr, pc, (uptr)b, 1, kAccessRead);
int res = REAL(pthread_barrier_wait)(b);
- MemoryRead(thr, pc, (uptr)b, kSizeLog1);
+ MemoryAccess(thr, pc, (uptr)b, 1, kAccessRead);
if (res == 0 || res == PTHREAD_BARRIER_SERIAL_THREAD) {
Acquire(thr, pc, (uptr)b);
}
@@ -1485,20 +1511,11 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {
else
a = static_cast<atomic_uint32_t*>(o);
- u32 v = atomic_load(a, memory_order_acquire);
- if (v == 0 && atomic_compare_exchange_strong(a, &v, 1,
- memory_order_relaxed)) {
+ // Mac OS X appears to use pthread_once() where calling BlockingRegion hooks
+ // result in crashes due to too little stack space.
+ if (guard_acquire(thr, pc, a, !SANITIZER_MAC)) {
(*f)();
- if (!thr->in_ignored_lib)
- Release(thr, pc, (uptr)o);
- atomic_store(a, 2, memory_order_release);
- } else {
- while (v != 2) {
- internal_sched_yield();
- v = atomic_load(a, memory_order_acquire);
- }
- if (!thr->in_ignored_lib)
- Acquire(thr, pc, (uptr)o);
+ guard_release(thr, pc, a);
}
return 0;
}
@@ -1932,24 +1949,45 @@ TSAN_INTERCEPTOR(int, pthread_sigmask, int how, const __sanitizer_sigset_t *set,
namespace __tsan {
+static void ReportErrnoSpoiling(ThreadState *thr, uptr pc) {
+ VarSizeStackTrace stack;
+ // StackTrace::GetNestInstructionPc(pc) is used because return address is
+ // expected, OutputReport() will undo this.
+ ObtainCurrentStack(thr, StackTrace::GetNextInstructionPc(pc), &stack);
+ ThreadRegistryLock l(&ctx->thread_registry);
+ ScopedReport rep(ReportTypeErrnoInSignal);
+ if (!IsFiredSuppression(ctx, ReportTypeErrnoInSignal, stack)) {
+ rep.AddStack(stack, true);
+ OutputReport(thr, rep);
+ }
+}
+
static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
- bool sigact, int sig,
- __sanitizer_siginfo *info, void *uctx) {
+ int sig, __sanitizer_siginfo *info,
+ void *uctx) {
__sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
if (acquire)
Acquire(thr, 0, (uptr)&sigactions[sig]);
// Signals are generally asynchronous, so if we receive a signals when
// ignores are enabled we should disable ignores. This is critical for sync
- // and interceptors, because otherwise we can miss syncronization and report
+ // and interceptors, because otherwise we can miss synchronization and report
// false races.
int ignore_reads_and_writes = thr->ignore_reads_and_writes;
int ignore_interceptors = thr->ignore_interceptors;
int ignore_sync = thr->ignore_sync;
+ // For symbolizer we only process SIGSEGVs synchronously
+ // (bug in symbolizer or in tsan). But we want to reset
+ // in_symbolizer to fail gracefully. Symbolizer and user code
+ // use different memory allocators, so if we don't reset
+ // in_symbolizer we can get memory allocated with one being
+ // feed with another, which can cause more crashes.
+ int in_symbolizer = thr->in_symbolizer;
if (!ctx->after_multithreaded_fork) {
thr->ignore_reads_and_writes = 0;
thr->fast_state.ClearIgnoreBit();
thr->ignore_interceptors = 0;
thr->ignore_sync = 0;
+ thr->in_symbolizer = 0;
}
// Ensure that the handler does not spoil errno.
const int saved_errno = errno;
@@ -1957,13 +1995,14 @@ static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
// This code races with sigaction. Be careful to not read sa_sigaction twice.
// Also need to remember pc for reporting before the call,
// because the handler can reset it.
- volatile uptr pc =
- sigact ? (uptr)sigactions[sig].sigaction : (uptr)sigactions[sig].handler;
+ volatile uptr pc = (sigactions[sig].sa_flags & SA_SIGINFO)
+ ? (uptr)sigactions[sig].sigaction
+ : (uptr)sigactions[sig].handler;
if (pc != sig_dfl && pc != sig_ign) {
- if (sigact)
- ((__sanitizer_sigactionhandler_ptr)pc)(sig, info, uctx);
- else
- ((__sanitizer_sighandler_ptr)pc)(sig);
+ // The callback can be either sa_handler or sa_sigaction.
+ // They have different signatures, but we assume that passing
+ // additional arguments to sa_handler works and is harmless.
+ ((__sanitizer_sigactionhandler_ptr)pc)(sig, info, uctx);
}
if (!ctx->after_multithreaded_fork) {
thr->ignore_reads_and_writes = ignore_reads_and_writes;
@@ -1971,6 +2010,7 @@ static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
thr->fast_state.SetIgnoreBit();
thr->ignore_interceptors = ignore_interceptors;
thr->ignore_sync = ignore_sync;
+ thr->in_symbolizer = in_symbolizer;
}
// We do not detect errno spoiling for SIGTERM,
// because some SIGTERM handlers do spoil errno but reraise SIGTERM,
@@ -1980,27 +2020,16 @@ static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
// from rtl_generic_sighandler) we have not yet received the reraised
// signal; and it looks too fragile to intercept all ways to reraise a signal.
if (ShouldReport(thr, ReportTypeErrnoInSignal) && !sync && sig != SIGTERM &&
- errno != 99) {
- VarSizeStackTrace stack;
- // StackTrace::GetNestInstructionPc(pc) is used because return address is
- // expected, OutputReport() will undo this.
- ObtainCurrentStack(thr, StackTrace::GetNextInstructionPc(pc), &stack);
- ThreadRegistryLock l(ctx->thread_registry);
- ScopedReport rep(ReportTypeErrnoInSignal);
- if (!IsFiredSuppression(ctx, ReportTypeErrnoInSignal, stack)) {
- rep.AddStack(stack, true);
- OutputReport(thr, rep);
- }
- }
+ errno != 99)
+ ReportErrnoSpoiling(thr, pc);
errno = saved_errno;
}
-void ProcessPendingSignals(ThreadState *thr) {
+void ProcessPendingSignalsImpl(ThreadState *thr) {
+ atomic_store(&thr->pending_signals, 0, memory_order_relaxed);
ThreadSignalContext *sctx = SigCtx(thr);
- if (sctx == 0 ||
- atomic_load(&sctx->have_pending_signals, memory_order_relaxed) == 0)
+ if (sctx == 0)
return;
- atomic_store(&sctx->have_pending_signals, 0, memory_order_relaxed);
atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
internal_sigfillset(&sctx->emptyset);
int res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->emptyset, &sctx->oldset);
@@ -2009,8 +2038,8 @@ void ProcessPendingSignals(ThreadState *thr) {
SignalDesc *signal = &sctx->pending_signals[sig];
if (signal->armed) {
signal->armed = false;
- CallUserSignalHandler(thr, false, true, signal->sigaction, sig,
- &signal->siginfo, &signal->ctx);
+ CallUserSignalHandler(thr, false, true, sig, &signal->siginfo,
+ &signal->ctx);
}
}
res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->oldset, 0);
@@ -2027,11 +2056,8 @@ static bool is_sync_signal(ThreadSignalContext *sctx, int sig) {
(sctx && sig == sctx->int_signal_send);
}
-void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
- __sanitizer_siginfo *info,
- void *ctx) {
- cur_thread_init();
- ThreadState *thr = cur_thread();
+void sighandler(int sig, __sanitizer_siginfo *info, void *ctx) {
+ ThreadState *thr = cur_thread_init();
ThreadSignalContext *sctx = SigCtx(thr);
if (sig < 0 || sig >= kSigCount) {
VPrintf(1, "ThreadSanitizer: ignoring signal %d\n", sig);
@@ -2047,7 +2073,7 @@ void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
if (sctx && atomic_load(&sctx->in_blocking_func, memory_order_relaxed)) {
atomic_store(&sctx->in_blocking_func, 0, memory_order_relaxed);
- CallUserSignalHandler(thr, sync, true, sigact, sig, info, ctx);
+ CallUserSignalHandler(thr, sync, true, sig, info, ctx);
atomic_store(&sctx->in_blocking_func, 1, memory_order_relaxed);
} else {
// Be very conservative with when we do acquire in this case.
@@ -2056,7 +2082,7 @@ void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
// SIGSYS looks relatively safe -- it's synchronous and can actually
// need some global state.
bool acq = (sig == SIGSYS);
- CallUserSignalHandler(thr, sync, acq, sigact, sig, info, ctx);
+ CallUserSignalHandler(thr, sync, acq, sig, info, ctx);
}
atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
return;
@@ -2067,23 +2093,12 @@ void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
SignalDesc *signal = &sctx->pending_signals[sig];
if (signal->armed == false) {
signal->armed = true;
- signal->sigaction = sigact;
- if (info)
- internal_memcpy(&signal->siginfo, info, sizeof(*info));
- if (ctx)
- internal_memcpy(&signal->ctx, ctx, sizeof(signal->ctx));
- atomic_store(&sctx->have_pending_signals, 1, memory_order_relaxed);
+ internal_memcpy(&signal->siginfo, info, sizeof(*info));
+ internal_memcpy(&signal->ctx, ctx, sizeof(signal->ctx));
+ atomic_store(&thr->pending_signals, 1, memory_order_relaxed);
}
}
-static void rtl_sighandler(int sig) {
- rtl_generic_sighandler(false, sig, 0, 0);
-}
-
-static void rtl_sigaction(int sig, __sanitizer_siginfo *info, void *ctx) {
- rtl_generic_sighandler(true, sig, info, ctx);
-}
-
TSAN_INTERCEPTOR(int, raise, int sig) {
SCOPED_TSAN_INTERCEPTOR(raise, sig);
ThreadSignalContext *sctx = SigCtx(thr);
@@ -2142,7 +2157,7 @@ TSAN_INTERCEPTOR(int, getaddrinfo, void *node, void *service,
// inside of getaddrinfo. So ignore memory accesses.
ThreadIgnoreBegin(thr, pc);
int res = REAL(getaddrinfo)(node, service, hints, rv);
- ThreadIgnoreEnd(thr, pc);
+ ThreadIgnoreEnd(thr);
return res;
}
@@ -2206,7 +2221,7 @@ struct dl_iterate_phdr_data {
};
static bool IsAppNotRodata(uptr addr) {
- return IsAppMem(addr) && *(u64*)MemToShadow(addr) != kShadowRodata;
+ return IsAppMem(addr) && *MemToShadow(addr) != kShadowRodata;
}
static int dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
@@ -2249,7 +2264,6 @@ static int OnExit(ThreadState *thr) {
struct TsanInterceptorContext {
ThreadState *thr;
- const uptr caller_pc;
const uptr pc;
};
@@ -2290,17 +2304,17 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
((TsanInterceptorContext *) ctx)->pc, (uptr) ptr, size, \
false)
-#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
- SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__); \
- TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \
- ctx = (void *)&_ctx; \
- (void) ctx;
+#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
+ SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__); \
+ TsanInterceptorContext _ctx = {thr, pc}; \
+ ctx = (void *)&_ctx; \
+ (void)ctx;
#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, func, ...) \
SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
- TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \
+ TsanInterceptorContext _ctx = {thr, pc}; \
ctx = (void *)&_ctx; \
- (void) ctx;
+ (void)ctx;
#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) \
if (path) \
@@ -2347,7 +2361,7 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
ThreadSetName(((TsanInterceptorContext *) ctx)->thr, name)
#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
- __tsan::ctx->thread_registry->SetThreadNameByUserId(thread, name)
+ __tsan::ctx->thread_registry.SetThreadNameByUserId(thread, name)
#define COMMON_INTERCEPTOR_BLOCK_REAL(name) BLOCK_REAL(name)
@@ -2419,9 +2433,13 @@ static __sanitizer_sighandler_ptr signal_impl(int sig,
int sigaction_impl(int sig, const __sanitizer_sigaction *act,
__sanitizer_sigaction *old) {
// Note: if we call REAL(sigaction) directly for any reason without proxying
- // the signal handler through rtl_sigaction, very bad things will happen.
+ // the signal handler through sighandler, very bad things will happen.
// The handler will run synchronously and corrupt tsan per-thread state.
SCOPED_INTERCEPTOR_RAW(sigaction, sig, act, old);
+ if (sig <= 0 || sig >= kSigCount) {
+ errno = errno_EINVAL;
+ return -1;
+ }
__sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
__sanitizer_sigaction old_stored;
if (old) internal_memcpy(&old_stored, &sigactions[sig], sizeof(old_stored));
@@ -2443,22 +2461,17 @@ int sigaction_impl(int sig, const __sanitizer_sigaction *act,
#endif
internal_memcpy(&newact, act, sizeof(newact));
internal_sigfillset(&newact.sa_mask);
- if ((uptr)act->handler != sig_ign && (uptr)act->handler != sig_dfl) {
- if (newact.sa_flags & SA_SIGINFO)
- newact.sigaction = rtl_sigaction;
- else
- newact.handler = rtl_sighandler;
+ if ((act->sa_flags & SA_SIGINFO) ||
+ ((uptr)act->handler != sig_ign && (uptr)act->handler != sig_dfl)) {
+ newact.sa_flags |= SA_SIGINFO;
+ newact.sigaction = sighandler;
}
ReleaseStore(thr, pc, (uptr)&sigactions[sig]);
act = &newact;
}
int res = REAL(sigaction)(sig, act, old);
- if (res == 0 && old) {
- uptr cb = (uptr)old->sigaction;
- if (cb == (uptr)rtl_sigaction || cb == (uptr)rtl_sighandler) {
- internal_memcpy(old, &old_stored, sizeof(*old));
- }
- }
+ if (res == 0 && old && old->sigaction == sighandler)
+ internal_memcpy(old, &old_stored, sizeof(*old));
return res;
}
@@ -2474,20 +2487,16 @@ static __sanitizer_sighandler_ptr signal_impl(int sig,
return old.handler;
}
-#define TSAN_SYSCALL() \
+#define TSAN_SYSCALL() \
ThreadState *thr = cur_thread(); \
- if (thr->ignore_interceptors) \
- return; \
- ScopedSyscall scoped_syscall(thr) \
-/**/
+ if (thr->ignore_interceptors) \
+ return; \
+ ScopedSyscall scoped_syscall(thr)
struct ScopedSyscall {
ThreadState *thr;
- explicit ScopedSyscall(ThreadState *thr)
- : thr(thr) {
- Initialize(thr);
- }
+ explicit ScopedSyscall(ThreadState *thr) : thr(thr) { LazyInitialize(thr); }
~ScopedSyscall() {
ProcessPendingSignals(thr);
@@ -2503,12 +2512,12 @@ static void syscall_access_range(uptr pc, uptr p, uptr s, bool write) {
static USED void syscall_acquire(uptr pc, uptr addr) {
TSAN_SYSCALL();
Acquire(thr, pc, addr);
- DPrintf("syscall_acquire(%p)\n", addr);
+ DPrintf("syscall_acquire(0x%zx))\n", addr);
}
static USED void syscall_release(uptr pc, uptr addr) {
TSAN_SYSCALL();
- DPrintf("syscall_release(%p)\n", addr);
+ DPrintf("syscall_release(0x%zx)\n", addr);
Release(thr, pc, addr);
}
@@ -2520,12 +2529,12 @@ static void syscall_fd_close(uptr pc, int fd) {
static USED void syscall_fd_acquire(uptr pc, int fd) {
TSAN_SYSCALL();
FdAcquire(thr, pc, fd);
- DPrintf("syscall_fd_acquire(%p)\n", fd);
+ DPrintf("syscall_fd_acquire(%d)\n", fd);
}
static USED void syscall_fd_release(uptr pc, int fd) {
TSAN_SYSCALL();
- DPrintf("syscall_fd_release(%p)\n", fd);
+ DPrintf("syscall_fd_release(%d)\n", fd);
FdRelease(thr, pc, fd);
}
@@ -2695,12 +2704,6 @@ void InitializeInterceptors() {
REAL(memcpy) = internal_memcpy;
#endif
- // Instruct libc malloc to consume less memory.
-#if SANITIZER_GLIBC
- mallopt(1, 0); // M_MXFAST
- mallopt(-3, 32*1024); // M_MMAP_THRESHOLD
-#endif
-
new(interceptor_ctx()) InterceptorContext();
InitializeCommonInterceptors();
@@ -2915,25 +2918,36 @@ void InitializeInterceptors() {
// Note that no_sanitize_thread attribute does not turn off atomic interception
// so attaching it to the function defined in user code does not help.
// That's why we now have what we have.
-extern "C" SANITIZER_INTERFACE_ATTRIBUTE
-void __tsan_testonly_barrier_init(u64 *barrier, u32 count) {
- if (count >= (1 << 8)) {
- Printf("barrier_init: count is too large (%d)\n", count);
- Die();
+constexpr u32 kBarrierThreadBits = 10;
+constexpr u32 kBarrierThreads = 1 << kBarrierThreadBits;
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __tsan_testonly_barrier_init(
+ atomic_uint32_t *barrier, u32 num_threads) {
+ if (num_threads >= kBarrierThreads) {
+ Printf("barrier_init: count is too large (%d)\n", num_threads);
+ Die();
}
- // 8 lsb is thread count, the remaining are count of entered threads.
- *barrier = count;
+ // kBarrierThreadBits lsb is thread count,
+ // the remaining are count of entered threads.
+ atomic_store(barrier, num_threads, memory_order_relaxed);
}
-extern "C" SANITIZER_INTERFACE_ATTRIBUTE
-void __tsan_testonly_barrier_wait(u64 *barrier) {
- unsigned old = __atomic_fetch_add(barrier, 1 << 8, __ATOMIC_RELAXED);
- unsigned old_epoch = (old >> 8) / (old & 0xff);
+static u32 barrier_epoch(u32 value) {
+ return (value >> kBarrierThreadBits) / (value & (kBarrierThreads - 1));
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __tsan_testonly_barrier_wait(
+ atomic_uint32_t *barrier) {
+ u32 old = atomic_fetch_add(barrier, kBarrierThreads, memory_order_relaxed);
+ u32 old_epoch = barrier_epoch(old);
+ if (barrier_epoch(old + kBarrierThreads) != old_epoch) {
+ FutexWake(barrier, (1 << 30));
+ return;
+ }
for (;;) {
- unsigned cur = __atomic_load_n(barrier, __ATOMIC_RELAXED);
- unsigned cur_epoch = (cur >> 8) / (cur & 0xff);
- if (cur_epoch != old_epoch)
+ u32 cur = atomic_load(barrier, memory_order_relaxed);
+ if (barrier_epoch(cur) != old_epoch)
return;
- internal_sched_yield();
+ FutexWait(barrier, cur);
}
}
diff --git a/libsanitizer/tsan/tsan_interface.cpp b/libsanitizer/tsan/tsan_interface.cpp
index 9bd0e85..0487151 100644
--- a/libsanitizer/tsan/tsan_interface.cpp
+++ b/libsanitizer/tsan/tsan_interface.cpp
@@ -20,109 +20,58 @@
using namespace __tsan;
-void __tsan_init() {
- cur_thread_init();
- Initialize(cur_thread());
-}
+void __tsan_init() { Initialize(cur_thread_init()); }
void __tsan_flush_memory() {
FlushShadowMemory();
}
void __tsan_read16(void *addr) {
- MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
- MemoryRead(cur_thread(), CALLERPC, (uptr)addr + 8, kSizeLog8);
+ uptr pc = CALLERPC;
+ ThreadState *thr = cur_thread();
+ MemoryAccess(thr, pc, (uptr)addr, 8, kAccessRead);
+ MemoryAccess(thr, pc, (uptr)addr + 8, 8, kAccessRead);
}
void __tsan_write16(void *addr) {
- MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
- MemoryWrite(cur_thread(), CALLERPC, (uptr)addr + 8, kSizeLog8);
+ uptr pc = CALLERPC;
+ ThreadState *thr = cur_thread();
+ MemoryAccess(thr, pc, (uptr)addr, 8, kAccessWrite);
+ MemoryAccess(thr, pc, (uptr)addr + 8, 8, kAccessWrite);
}
void __tsan_read16_pc(void *addr, void *pc) {
- MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog8);
- MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr + 8, kSizeLog8);
+ uptr pc_no_pac = STRIP_PAC_PC(pc);
+ ThreadState *thr = cur_thread();
+ MemoryAccess(thr, pc_no_pac, (uptr)addr, 8, kAccessRead);
+ MemoryAccess(thr, pc_no_pac, (uptr)addr + 8, 8, kAccessRead);
}
void __tsan_write16_pc(void *addr, void *pc) {
- MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog8);
- MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr + 8, kSizeLog8);
+ uptr pc_no_pac = STRIP_PAC_PC(pc);
+ ThreadState *thr = cur_thread();
+ MemoryAccess(thr, pc_no_pac, (uptr)addr, 8, kAccessWrite);
+ MemoryAccess(thr, pc_no_pac, (uptr)addr + 8, 8, kAccessWrite);
}
// __tsan_unaligned_read/write calls are emitted by compiler.
-void __tsan_unaligned_read2(const void *addr) {
- UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, false, false);
-}
-
-void __tsan_unaligned_read4(const void *addr) {
- UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, false, false);
-}
-
-void __tsan_unaligned_read8(const void *addr) {
- UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, false, false);
-}
-
void __tsan_unaligned_read16(const void *addr) {
- UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 16, false, false);
-}
-
-void __tsan_unaligned_write2(void *addr) {
- UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, true, false);
-}
-
-void __tsan_unaligned_write4(void *addr) {
- UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, true, false);
-}
-
-void __tsan_unaligned_write8(void *addr) {
- UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, true, false);
+ uptr pc = CALLERPC;
+ ThreadState *thr = cur_thread();
+ UnalignedMemoryAccess(thr, pc, (uptr)addr, 8, kAccessRead);
+ UnalignedMemoryAccess(thr, pc, (uptr)addr + 8, 8, kAccessRead);
}
void __tsan_unaligned_write16(void *addr) {
- UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 16, true, false);
+ uptr pc = CALLERPC;
+ ThreadState *thr = cur_thread();
+ UnalignedMemoryAccess(thr, pc, (uptr)addr, 8, kAccessWrite);
+ UnalignedMemoryAccess(thr, pc, (uptr)addr + 8, 8, kAccessWrite);
}
-// __sanitizer_unaligned_load/store are for user instrumentation.
-
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
-u16 __sanitizer_unaligned_load16(const uu16 *addr) {
- __tsan_unaligned_read2(addr);
- return *addr;
-}
-
-SANITIZER_INTERFACE_ATTRIBUTE
-u32 __sanitizer_unaligned_load32(const uu32 *addr) {
- __tsan_unaligned_read4(addr);
- return *addr;
-}
-
-SANITIZER_INTERFACE_ATTRIBUTE
-u64 __sanitizer_unaligned_load64(const uu64 *addr) {
- __tsan_unaligned_read8(addr);
- return *addr;
-}
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void __sanitizer_unaligned_store16(uu16 *addr, u16 v) {
- __tsan_unaligned_write2(addr);
- *addr = v;
-}
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void __sanitizer_unaligned_store32(uu32 *addr, u32 v) {
- __tsan_unaligned_write4(addr);
- *addr = v;
-}
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void __sanitizer_unaligned_store64(uu64 *addr, u64 v) {
- __tsan_unaligned_write8(addr);
- *addr = v;
-}
-
-SANITIZER_INTERFACE_ATTRIBUTE
void *__tsan_get_current_fiber() {
return cur_thread();
}
diff --git a/libsanitizer/tsan/tsan_interface.h b/libsanitizer/tsan/tsan_interface.h
index 124aa2f..711f064 100644
--- a/libsanitizer/tsan/tsan_interface.h
+++ b/libsanitizer/tsan/tsan_interface.h
@@ -95,9 +95,9 @@ SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_write_range(void *addr, unsigned long size);
SANITIZER_INTERFACE_ATTRIBUTE
-void __tsan_read_range_pc(void *addr, unsigned long size, void *pc); // NOLINT
+void __tsan_read_range_pc(void *addr, unsigned long size, void *pc);
SANITIZER_INTERFACE_ATTRIBUTE
-void __tsan_write_range_pc(void *addr, unsigned long size, void *pc); // NOLINT
+void __tsan_write_range_pc(void *addr, unsigned long size, void *pc);
// User may provide function that would be called right when TSan detects
// an error. The argument 'report' is an opaque pointer that can be used to
@@ -417,12 +417,6 @@ SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_go_atomic64_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
u8 *a);
-SANITIZER_INTERFACE_ATTRIBUTE
-void __tsan_on_initialize();
-
-SANITIZER_INTERFACE_ATTRIBUTE
-int __tsan_on_finalize(int failed);
-
} // extern "C"
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_interface.inc b/libsanitizer/tsan/tsan_interface.inc
new file mode 100644
index 0000000..0031800
--- /dev/null
+++ b/libsanitizer/tsan/tsan_interface.inc
@@ -0,0 +1,182 @@
+//===-- tsan_interface.inc --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_ptrauth.h"
+#include "tsan_interface.h"
+#include "tsan_rtl.h"
+
+#define CALLERPC ((uptr)__builtin_return_address(0))
+
+using namespace __tsan;
+
+void __tsan_read1(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 1, kAccessRead);
+}
+
+void __tsan_read2(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessRead);
+}
+
+void __tsan_read4(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessRead);
+}
+
+void __tsan_read8(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessRead);
+}
+
+void __tsan_write1(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 1, kAccessWrite);
+}
+
+void __tsan_write2(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessWrite);
+}
+
+void __tsan_write4(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessWrite);
+}
+
+void __tsan_write8(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessWrite);
+}
+
+void __tsan_read1_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 1, kAccessRead | kAccessExternalPC);
+}
+
+void __tsan_read2_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 2, kAccessRead | kAccessExternalPC);
+}
+
+void __tsan_read4_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 4, kAccessRead | kAccessExternalPC);
+}
+
+void __tsan_read8_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 8, kAccessRead | kAccessExternalPC);
+}
+
+void __tsan_write1_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 1, kAccessWrite | kAccessExternalPC);
+}
+
+void __tsan_write2_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 2, kAccessWrite | kAccessExternalPC);
+}
+
+void __tsan_write4_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 4, kAccessWrite | kAccessExternalPC);
+}
+
+void __tsan_write8_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 8, kAccessWrite | kAccessExternalPC);
+}
+
+ALWAYS_INLINE USED void __tsan_unaligned_read2(const void *addr) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessRead);
+}
+
+ALWAYS_INLINE USED void __tsan_unaligned_read4(const void *addr) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessRead);
+}
+
+ALWAYS_INLINE USED void __tsan_unaligned_read8(const void *addr) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessRead);
+}
+
+ALWAYS_INLINE USED void __tsan_unaligned_write2(void *addr) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessWrite);
+}
+
+ALWAYS_INLINE USED void __tsan_unaligned_write4(void *addr) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessWrite);
+}
+
+ALWAYS_INLINE USED void __tsan_unaligned_write8(void *addr) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessWrite);
+}
+
+extern "C" {
+// __sanitizer_unaligned_load/store are for user instrumentation.
+SANITIZER_INTERFACE_ATTRIBUTE
+u16 __sanitizer_unaligned_load16(const uu16 *addr) {
+ __tsan_unaligned_read2(addr);
+ return *addr;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+u32 __sanitizer_unaligned_load32(const uu32 *addr) {
+ __tsan_unaligned_read4(addr);
+ return *addr;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+u64 __sanitizer_unaligned_load64(const uu64 *addr) {
+ __tsan_unaligned_read8(addr);
+ return *addr;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store16(uu16 *addr, u16 v) {
+ *addr = v;
+ __tsan_unaligned_write2(addr);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store32(uu32 *addr, u32 v) {
+ *addr = v;
+ __tsan_unaligned_write4(addr);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store64(uu64 *addr, u64 v) {
+ *addr = v;
+ __tsan_unaligned_write8(addr);
+}
+}
+
+void __tsan_vptr_update(void **vptr_p, void *new_val) {
+ if (*vptr_p == new_val)
+ return;
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)vptr_p, sizeof(*vptr_p),
+ kAccessWrite | kAccessVptr);
+}
+
+void __tsan_vptr_read(void **vptr_p) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)vptr_p, sizeof(*vptr_p),
+ kAccessRead | kAccessVptr);
+}
+
+void __tsan_func_entry(void *pc) { FuncEntry(cur_thread(), STRIP_PAC_PC(pc)); }
+
+void __tsan_func_exit() { FuncExit(cur_thread()); }
+
+void __tsan_ignore_thread_begin() { ThreadIgnoreBegin(cur_thread(), CALLERPC); }
+
+void __tsan_ignore_thread_end() { ThreadIgnoreEnd(cur_thread()); }
+
+void __tsan_read_range(void *addr, uptr size) {
+ MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, false);
+}
+
+void __tsan_write_range(void *addr, uptr size) {
+ MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, true);
+}
+
+void __tsan_read_range_pc(void *addr, uptr size, void *pc) {
+ MemoryAccessRange(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, size, false);
+}
+
+void __tsan_write_range_pc(void *addr, uptr size, void *pc) {
+ MemoryAccessRange(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, size, true);
+}
diff --git a/libsanitizer/tsan/tsan_interface_ann.cpp b/libsanitizer/tsan/tsan_interface_ann.cpp
index 175855f..6bd72e1 100644
--- a/libsanitizer/tsan/tsan_interface_ann.cpp
+++ b/libsanitizer/tsan/tsan_interface_ann.cpp
@@ -15,7 +15,6 @@
#include "sanitizer_common/sanitizer_stacktrace.h"
#include "sanitizer_common/sanitizer_vector.h"
#include "tsan_interface_ann.h"
-#include "tsan_mutex.h"
#include "tsan_report.h"
#include "tsan_rtl.h"
#include "tsan_mman.h"
@@ -38,21 +37,20 @@ class ScopedAnnotation {
~ScopedAnnotation() {
FuncExit(thr_);
- CheckNoLocks(thr_);
+ CheckedMutex::CheckNoLocks();
}
private:
ThreadState *const thr_;
};
-#define SCOPED_ANNOTATION_RET(typ, ret) \
- if (!flags()->enable_annotations) \
- return ret; \
- ThreadState *thr = cur_thread(); \
- const uptr caller_pc = (uptr)__builtin_return_address(0); \
- ScopedAnnotation sa(thr, __func__, caller_pc); \
- const uptr pc = StackTrace::GetCurrentPc(); \
- (void)pc; \
-/**/
+#define SCOPED_ANNOTATION_RET(typ, ret) \
+ if (!flags()->enable_annotations) \
+ return ret; \
+ ThreadState *thr = cur_thread(); \
+ const uptr caller_pc = (uptr)__builtin_return_address(0); \
+ ScopedAnnotation sa(thr, __func__, caller_pc); \
+ const uptr pc = StackTrace::GetCurrentPc(); \
+ (void)pc;
#define SCOPED_ANNOTATION(typ) SCOPED_ANNOTATION_RET(typ, )
@@ -72,7 +70,6 @@ struct ExpectRace {
struct DynamicAnnContext {
Mutex mtx;
- ExpectRace expect;
ExpectRace benign;
DynamicAnnContext() : mtx(MutexTypeAnnotations) {}
@@ -91,7 +88,7 @@ static void AddExpectRace(ExpectRace *list,
return;
}
}
- race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace));
+ race = static_cast<ExpectRace *>(Alloc(sizeof(ExpectRace)));
race->addr = addr;
race->size = size;
race->file = f;
@@ -138,81 +135,12 @@ static void InitList(ExpectRace *list) {
void InitializeDynamicAnnotations() {
dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
- InitList(&dyn_ann_ctx->expect);
InitList(&dyn_ann_ctx->benign);
}
bool IsExpectedReport(uptr addr, uptr size) {
ReadLock lock(&dyn_ann_ctx->mtx);
- if (CheckContains(&dyn_ann_ctx->expect, addr, size))
- return true;
- if (CheckContains(&dyn_ann_ctx->benign, addr, size))
- return true;
- return false;
-}
-
-static void CollectMatchedBenignRaces(Vector<ExpectRace> *matched,
- int *unique_count, int *hit_count, atomic_uintptr_t ExpectRace::*counter) {
- ExpectRace *list = &dyn_ann_ctx->benign;
- for (ExpectRace *race = list->next; race != list; race = race->next) {
- (*unique_count)++;
- const uptr cnt = atomic_load_relaxed(&(race->*counter));
- if (cnt == 0)
- continue;
- *hit_count += cnt;
- uptr i = 0;
- for (; i < matched->Size(); i++) {
- ExpectRace *race0 = &(*matched)[i];
- if (race->line == race0->line
- && internal_strcmp(race->file, race0->file) == 0
- && internal_strcmp(race->desc, race0->desc) == 0) {
- atomic_fetch_add(&(race0->*counter), cnt, memory_order_relaxed);
- break;
- }
- }
- if (i == matched->Size())
- matched->PushBack(*race);
- }
-}
-
-void PrintMatchedBenignRaces() {
- Lock lock(&dyn_ann_ctx->mtx);
- int unique_count = 0;
- int hit_count = 0;
- int add_count = 0;
- Vector<ExpectRace> hit_matched;
- CollectMatchedBenignRaces(&hit_matched, &unique_count, &hit_count,
- &ExpectRace::hitcount);
- Vector<ExpectRace> add_matched;
- CollectMatchedBenignRaces(&add_matched, &unique_count, &add_count,
- &ExpectRace::addcount);
- if (hit_matched.Size()) {
- Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n",
- hit_count, (int)internal_getpid());
- for (uptr i = 0; i < hit_matched.Size(); i++) {
- Printf("%d %s:%d %s\n",
- atomic_load_relaxed(&hit_matched[i].hitcount),
- hit_matched[i].file, hit_matched[i].line, hit_matched[i].desc);
- }
- }
- if (hit_matched.Size()) {
- Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique"
- " (pid=%d):\n",
- add_count, unique_count, (int)internal_getpid());
- for (uptr i = 0; i < add_matched.Size(); i++) {
- Printf("%d %s:%d %s\n",
- atomic_load_relaxed(&add_matched[i].addcount),
- add_matched[i].file, add_matched[i].line, add_matched[i].desc);
- }
- }
-}
-
-static void ReportMissedExpectedRace(ExpectRace *race) {
- Printf("==================\n");
- Printf("WARNING: ThreadSanitizer: missed expected data race\n");
- Printf(" %s addr=%zx %s:%d\n",
- race->desc, race->addr, race->file, race->line);
- Printf("==================\n");
+ return CheckContains(&dyn_ann_ctx->benign, addr, size);
}
} // namespace __tsan
@@ -230,20 +158,16 @@ void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
}
void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
- SCOPED_ANNOTATION(AnnotateCondVarSignal);
}
void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
- SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
}
void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
- SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
}
void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
uptr lock) {
- SCOPED_ANNOTATION(AnnotateCondVarWait);
}
void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {
@@ -280,86 +204,56 @@ void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,
}
void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
- SCOPED_ANNOTATION(AnnotateTraceMemory);
}
void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
- SCOPED_ANNOTATION(AnnotateFlushState);
}
void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
uptr size) {
- SCOPED_ANNOTATION(AnnotateNewMemory);
}
void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
- SCOPED_ANNOTATION(AnnotateNoOp);
}
void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
- SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
- Lock lock(&dyn_ann_ctx->mtx);
- while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
- ExpectRace *race = dyn_ann_ctx->expect.next;
- if (atomic_load_relaxed(&race->hitcount) == 0) {
- ctx->nmissed_expected++;
- ReportMissedExpectedRace(race);
- }
- race->prev->next = race->next;
- race->next->prev = race->prev;
- internal_free(race);
- }
}
void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
char *f, int l, int enable) {
- SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
- // FIXME: Reconsider this functionality later. It may be irrelevant.
}
void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
char *f, int l, uptr mu) {
- SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
}
void INTERFACE_ATTRIBUTE AnnotatePCQGet(
char *f, int l, uptr pcq) {
- SCOPED_ANNOTATION(AnnotatePCQGet);
}
void INTERFACE_ATTRIBUTE AnnotatePCQPut(
char *f, int l, uptr pcq) {
- SCOPED_ANNOTATION(AnnotatePCQPut);
}
void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
char *f, int l, uptr pcq) {
- SCOPED_ANNOTATION(AnnotatePCQDestroy);
}
void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
char *f, int l, uptr pcq) {
- SCOPED_ANNOTATION(AnnotatePCQCreate);
}
void INTERFACE_ATTRIBUTE AnnotateExpectRace(
char *f, int l, uptr mem, char *desc) {
- SCOPED_ANNOTATION(AnnotateExpectRace);
- Lock lock(&dyn_ann_ctx->mtx);
- AddExpectRace(&dyn_ann_ctx->expect,
- f, l, mem, 1, desc);
- DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
}
-static void BenignRaceImpl(
- char *f, int l, uptr mem, uptr size, char *desc) {
+static void BenignRaceImpl(char *f, int l, uptr mem, uptr size, char *desc) {
Lock lock(&dyn_ann_ctx->mtx);
AddExpectRace(&dyn_ann_ctx->benign,
f, l, mem, size, desc);
DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
}
-// FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(
char *f, int l, uptr mem, uptr size, char *desc) {
SCOPED_ANNOTATION(AnnotateBenignRaceSized);
@@ -379,7 +273,7 @@ void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
- ThreadIgnoreEnd(thr, pc);
+ ThreadIgnoreEnd(thr);
}
void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
@@ -389,7 +283,7 @@ void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
- ThreadIgnoreEnd(thr, pc);
+ ThreadIgnoreEnd(thr);
}
void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
@@ -399,17 +293,15 @@ void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) {
SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd);
- ThreadIgnoreSyncEnd(thr, pc);
+ ThreadIgnoreSyncEnd(thr);
}
void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
char *f, int l, uptr addr, uptr size) {
- SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
}
void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
char *f, int l, uptr addr, uptr size) {
- SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
}
void INTERFACE_ATTRIBUTE AnnotateThreadName(
@@ -422,11 +314,9 @@ void INTERFACE_ATTRIBUTE AnnotateThreadName(
// WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
// atomic operations, which should be handled by ThreadSanitizer correctly.
void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
- SCOPED_ANNOTATION(AnnotateHappensBefore);
}
void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
- SCOPED_ANNOTATION(AnnotateHappensAfter);
}
void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
@@ -478,15 +368,15 @@ void __tsan_mutex_pre_lock(void *m, unsigned flagz) {
else
MutexPreLock(thr, pc, (uptr)m);
}
- ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
- ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
+ ThreadIgnoreBegin(thr, 0);
+ ThreadIgnoreSyncBegin(thr, 0);
}
INTERFACE_ATTRIBUTE
void __tsan_mutex_post_lock(void *m, unsigned flagz, int rec) {
SCOPED_ANNOTATION(__tsan_mutex_post_lock);
- ThreadIgnoreSyncEnd(thr, pc);
- ThreadIgnoreEnd(thr, pc);
+ ThreadIgnoreSyncEnd(thr);
+ ThreadIgnoreEnd(thr);
if (!(flagz & MutexFlagTryLockFailed)) {
if (flagz & MutexFlagReadLock)
MutexPostReadLock(thr, pc, (uptr)m, flagz);
@@ -505,44 +395,44 @@ int __tsan_mutex_pre_unlock(void *m, unsigned flagz) {
} else {
ret = MutexUnlock(thr, pc, (uptr)m, flagz);
}
- ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
- ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
+ ThreadIgnoreBegin(thr, 0);
+ ThreadIgnoreSyncBegin(thr, 0);
return ret;
}
INTERFACE_ATTRIBUTE
void __tsan_mutex_post_unlock(void *m, unsigned flagz) {
SCOPED_ANNOTATION(__tsan_mutex_post_unlock);
- ThreadIgnoreSyncEnd(thr, pc);
- ThreadIgnoreEnd(thr, pc);
+ ThreadIgnoreSyncEnd(thr);
+ ThreadIgnoreEnd(thr);
}
INTERFACE_ATTRIBUTE
void __tsan_mutex_pre_signal(void *addr, unsigned flagz) {
SCOPED_ANNOTATION(__tsan_mutex_pre_signal);
- ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
- ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
+ ThreadIgnoreBegin(thr, 0);
+ ThreadIgnoreSyncBegin(thr, 0);
}
INTERFACE_ATTRIBUTE
void __tsan_mutex_post_signal(void *addr, unsigned flagz) {
SCOPED_ANNOTATION(__tsan_mutex_post_signal);
- ThreadIgnoreSyncEnd(thr, pc);
- ThreadIgnoreEnd(thr, pc);
+ ThreadIgnoreSyncEnd(thr);
+ ThreadIgnoreEnd(thr);
}
INTERFACE_ATTRIBUTE
void __tsan_mutex_pre_divert(void *addr, unsigned flagz) {
SCOPED_ANNOTATION(__tsan_mutex_pre_divert);
// Exit from ignore region started in __tsan_mutex_pre_lock/unlock/signal.
- ThreadIgnoreSyncEnd(thr, pc);
- ThreadIgnoreEnd(thr, pc);
+ ThreadIgnoreSyncEnd(thr);
+ ThreadIgnoreEnd(thr);
}
INTERFACE_ATTRIBUTE
void __tsan_mutex_post_divert(void *addr, unsigned flagz) {
SCOPED_ANNOTATION(__tsan_mutex_post_divert);
- ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
- ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
+ ThreadIgnoreBegin(thr, 0);
+ ThreadIgnoreSyncBegin(thr, 0);
}
} // extern "C"
diff --git a/libsanitizer/tsan/tsan_interface_atomic.cpp b/libsanitizer/tsan/tsan_interface_atomic.cpp
index 21fe4a1..24ba3bb 100644
--- a/libsanitizer/tsan/tsan_interface_atomic.cpp
+++ b/libsanitizer/tsan/tsan_interface_atomic.cpp
@@ -32,6 +32,7 @@ using namespace __tsan;
static StaticSpinMutex mutex128;
#endif
+#if SANITIZER_DEBUG
static bool IsLoadOrder(morder mo) {
return mo == mo_relaxed || mo == mo_consume
|| mo == mo_acquire || mo == mo_seq_cst;
@@ -40,6 +41,7 @@ static bool IsLoadOrder(morder mo) {
static bool IsStoreOrder(morder mo) {
return mo == mo_relaxed || mo == mo_release || mo == mo_seq_cst;
}
+#endif
static bool IsReleaseOrder(morder mo) {
return mo == mo_release || mo == mo_acq_rel || mo == mo_seq_cst;
@@ -161,16 +163,16 @@ a128 func_cas(volatile a128 *v, a128 cmp, a128 xch) {
}
#endif
-template<typename T>
-static int SizeLog() {
+template <typename T>
+static int AccessSize() {
if (sizeof(T) <= 1)
- return kSizeLog1;
+ return 1;
else if (sizeof(T) <= 2)
- return kSizeLog2;
+ return 2;
else if (sizeof(T) <= 4)
- return kSizeLog4;
+ return 4;
else
- return kSizeLog8;
+ return 8;
// For 16-byte atomics we also use 8-byte memory access,
// this leads to false negatives only in very obscure cases.
}
@@ -202,7 +204,7 @@ static memory_order to_mo(morder mo) {
case mo_acq_rel: return memory_order_acq_rel;
case mo_seq_cst: return memory_order_seq_cst;
}
- CHECK(0);
+ DCHECK(0);
return memory_order_seq_cst;
}
@@ -218,27 +220,28 @@ static a128 NoTsanAtomicLoad(const volatile a128 *a, morder mo) {
}
#endif
-template<typename T>
+template <typename T>
static T AtomicLoad(ThreadState *thr, uptr pc, const volatile T *a, morder mo) {
- CHECK(IsLoadOrder(mo));
+ DCHECK(IsLoadOrder(mo));
// This fast-path is critical for performance.
// Assume the access is atomic.
if (!IsAcquireOrder(mo)) {
- MemoryReadAtomic(thr, pc, (uptr)a, SizeLog<T>());
+ MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(),
+ kAccessRead | kAccessAtomic);
return NoTsanAtomicLoad(a, mo);
}
// Don't create sync object if it does not exist yet. For example, an atomic
// pointer is initialized to nullptr and then periodically acquire-loaded.
T v = NoTsanAtomicLoad(a, mo);
- SyncVar *s = ctx->metamap.GetIfExistsAndLock((uptr)a, false);
+ SyncVar *s = ctx->metamap.GetSyncIfExists((uptr)a);
if (s) {
+ ReadLock l(&s->mtx);
AcquireImpl(thr, pc, &s->clock);
// Re-read under sync mutex because we need a consistent snapshot
// of the value and the clock we acquire.
v = NoTsanAtomicLoad(a, mo);
- s->mtx.ReadUnlock();
}
- MemoryReadAtomic(thr, pc, (uptr)a, SizeLog<T>());
+ MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessRead | kAccessAtomic);
return v;
}
@@ -254,11 +257,11 @@ static void NoTsanAtomicStore(volatile a128 *a, a128 v, morder mo) {
}
#endif
-template<typename T>
+template <typename T>
static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v,
- morder mo) {
- CHECK(IsStoreOrder(mo));
- MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
+ morder mo) {
+ DCHECK(IsStoreOrder(mo));
+ MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessWrite | kAccessAtomic);
// This fast-path is critical for performance.
// Assume the access is atomic.
// Strictly saying even relaxed store cuts off release sequence,
@@ -268,35 +271,32 @@ static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v,
return;
}
__sync_synchronize();
- SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, true);
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
+ Lock l(&s->mtx);
thr->fast_state.IncrementEpoch();
// Can't increment epoch w/o writing to the trace as well.
TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
ReleaseStoreImpl(thr, pc, &s->clock);
NoTsanAtomicStore(a, v, mo);
- s->mtx.Unlock();
}
-template<typename T, T (*F)(volatile T *v, T op)>
+template <typename T, T (*F)(volatile T *v, T op)>
static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) {
- MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
- SyncVar *s = 0;
- if (mo != mo_relaxed) {
- s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, true);
- thr->fast_state.IncrementEpoch();
- // Can't increment epoch w/o writing to the trace as well.
- TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
- if (IsAcqRelOrder(mo))
- AcquireReleaseImpl(thr, pc, &s->clock);
- else if (IsReleaseOrder(mo))
- ReleaseImpl(thr, pc, &s->clock);
- else if (IsAcquireOrder(mo))
- AcquireImpl(thr, pc, &s->clock);
- }
- v = F(a, v);
- if (s)
- s->mtx.Unlock();
- return v;
+ MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessWrite | kAccessAtomic);
+ if (LIKELY(mo == mo_relaxed))
+ return F(a, v);
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
+ Lock l(&s->mtx);
+ thr->fast_state.IncrementEpoch();
+ // Can't increment epoch w/o writing to the trace as well.
+ TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
+ if (IsAcqRelOrder(mo))
+ AcquireReleaseImpl(thr, pc, &s->clock);
+ else if (IsReleaseOrder(mo))
+ ReleaseImpl(thr, pc, &s->clock);
+ else if (IsAcquireOrder(mo))
+ AcquireImpl(thr, pc, &s->clock);
+ return F(a, v);
}
template<typename T>
@@ -399,21 +399,27 @@ static T NoTsanAtomicCAS(volatile T *a, T c, T v, morder mo, morder fmo) {
return c;
}
-template<typename T>
-static bool AtomicCAS(ThreadState *thr, uptr pc,
- volatile T *a, T *c, T v, morder mo, morder fmo) {
+template <typename T>
+static bool AtomicCAS(ThreadState *thr, uptr pc, volatile T *a, T *c, T v,
+ morder mo, morder fmo) {
// 31.7.2.18: "The failure argument shall not be memory_order_release
// nor memory_order_acq_rel". LLVM (2021-05) fallbacks to Monotonic
// (mo_relaxed) when those are used.
- CHECK(IsLoadOrder(fmo));
-
- MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
- SyncVar *s = 0;
- bool write_lock = IsReleaseOrder(mo);
-
- if (mo != mo_relaxed || fmo != mo_relaxed)
- s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, write_lock);
+ DCHECK(IsLoadOrder(fmo));
+
+ MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessWrite | kAccessAtomic);
+ if (LIKELY(mo == mo_relaxed && fmo == mo_relaxed)) {
+ T cc = *c;
+ T pr = func_cas(a, cc, v);
+ if (pr == cc)
+ return true;
+ *c = pr;
+ return false;
+ }
+ bool release = IsReleaseOrder(mo);
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
+ RWLock l(&s->mtx, release);
T cc = *c;
T pr = func_cas(a, cc, v);
bool success = pr == cc;
@@ -421,25 +427,16 @@ static bool AtomicCAS(ThreadState *thr, uptr pc,
*c = pr;
mo = fmo;
}
+ thr->fast_state.IncrementEpoch();
+ // Can't increment epoch w/o writing to the trace as well.
+ TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
- if (s) {
- thr->fast_state.IncrementEpoch();
- // Can't increment epoch w/o writing to the trace as well.
- TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
-
- if (success && IsAcqRelOrder(mo))
- AcquireReleaseImpl(thr, pc, &s->clock);
- else if (success && IsReleaseOrder(mo))
- ReleaseImpl(thr, pc, &s->clock);
- else if (IsAcquireOrder(mo))
- AcquireImpl(thr, pc, &s->clock);
-
- if (write_lock)
- s->mtx.Unlock();
- else
- s->mtx.ReadUnlock();
- }
-
+ if (success && IsAcqRelOrder(mo))
+ AcquireReleaseImpl(thr, pc, &s->clock);
+ else if (success && IsReleaseOrder(mo))
+ ReleaseImpl(thr, pc, &s->clock);
+ else if (IsAcquireOrder(mo))
+ AcquireImpl(thr, pc, &s->clock);
return success;
}
@@ -483,380 +480,356 @@ static morder convert_morder(morder mo) {
return (morder)(mo & 0x7fff);
}
-#define SCOPED_ATOMIC(func, ...) \
- ThreadState *const thr = cur_thread(); \
- if (UNLIKELY(thr->ignore_sync || thr->ignore_interceptors)) { \
- ProcessPendingSignals(thr); \
- return NoTsanAtomic##func(__VA_ARGS__); \
- } \
- const uptr callpc = (uptr)__builtin_return_address(0); \
- uptr pc = StackTrace::GetCurrentPc(); \
- mo = convert_morder(mo); \
- ScopedAtomic sa(thr, callpc, a, mo, __func__); \
- return Atomic##func(thr, pc, __VA_ARGS__); \
-/**/
-
-class ScopedAtomic {
- public:
- ScopedAtomic(ThreadState *thr, uptr pc, const volatile void *a,
- morder mo, const char *func)
- : thr_(thr) {
- FuncEntry(thr_, pc);
- DPrintf("#%d: %s(%p, %d)\n", thr_->tid, func, a, mo);
- }
- ~ScopedAtomic() {
- ProcessPendingSignals(thr_);
- FuncExit(thr_);
- }
- private:
- ThreadState *thr_;
-};
+# define ATOMIC_IMPL(func, ...) \
+ ThreadState *const thr = cur_thread(); \
+ ProcessPendingSignals(thr); \
+ if (UNLIKELY(thr->ignore_sync || thr->ignore_interceptors)) \
+ return NoTsanAtomic##func(__VA_ARGS__); \
+ mo = convert_morder(mo); \
+ return Atomic##func(thr, GET_CALLER_PC(), __VA_ARGS__);
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_load(const volatile a8 *a, morder mo) {
- SCOPED_ATOMIC(Load, a, mo);
+ ATOMIC_IMPL(Load, a, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_load(const volatile a16 *a, morder mo) {
- SCOPED_ATOMIC(Load, a, mo);
+ ATOMIC_IMPL(Load, a, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_load(const volatile a32 *a, morder mo) {
- SCOPED_ATOMIC(Load, a, mo);
+ ATOMIC_IMPL(Load, a, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_load(const volatile a64 *a, morder mo) {
- SCOPED_ATOMIC(Load, a, mo);
+ ATOMIC_IMPL(Load, a, mo);
}
#if __TSAN_HAS_INT128
SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_load(const volatile a128 *a, morder mo) {
- SCOPED_ATOMIC(Load, a, mo);
+ ATOMIC_IMPL(Load, a, mo);
}
#endif
SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_atomic8_store(volatile a8 *a, a8 v, morder mo) {
- SCOPED_ATOMIC(Store, a, v, mo);
+ ATOMIC_IMPL(Store, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_atomic16_store(volatile a16 *a, a16 v, morder mo) {
- SCOPED_ATOMIC(Store, a, v, mo);
+ ATOMIC_IMPL(Store, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_atomic32_store(volatile a32 *a, a32 v, morder mo) {
- SCOPED_ATOMIC(Store, a, v, mo);
+ ATOMIC_IMPL(Store, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_atomic64_store(volatile a64 *a, a64 v, morder mo) {
- SCOPED_ATOMIC(Store, a, v, mo);
+ ATOMIC_IMPL(Store, a, v, mo);
}
#if __TSAN_HAS_INT128
SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_atomic128_store(volatile a128 *a, a128 v, morder mo) {
- SCOPED_ATOMIC(Store, a, v, mo);
+ ATOMIC_IMPL(Store, a, v, mo);
}
#endif
SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, morder mo) {
- SCOPED_ATOMIC(Exchange, a, v, mo);
+ ATOMIC_IMPL(Exchange, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, morder mo) {
- SCOPED_ATOMIC(Exchange, a, v, mo);
+ ATOMIC_IMPL(Exchange, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, morder mo) {
- SCOPED_ATOMIC(Exchange, a, v, mo);
+ ATOMIC_IMPL(Exchange, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, morder mo) {
- SCOPED_ATOMIC(Exchange, a, v, mo);
+ ATOMIC_IMPL(Exchange, a, v, mo);
}
#if __TSAN_HAS_INT128
SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, morder mo) {
- SCOPED_ATOMIC(Exchange, a, v, mo);
+ ATOMIC_IMPL(Exchange, a, v, mo);
}
#endif
SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_fetch_add(volatile a8 *a, a8 v, morder mo) {
- SCOPED_ATOMIC(FetchAdd, a, v, mo);
+ ATOMIC_IMPL(FetchAdd, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_fetch_add(volatile a16 *a, a16 v, morder mo) {
- SCOPED_ATOMIC(FetchAdd, a, v, mo);
+ ATOMIC_IMPL(FetchAdd, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_fetch_add(volatile a32 *a, a32 v, morder mo) {
- SCOPED_ATOMIC(FetchAdd, a, v, mo);
+ ATOMIC_IMPL(FetchAdd, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_fetch_add(volatile a64 *a, a64 v, morder mo) {
- SCOPED_ATOMIC(FetchAdd, a, v, mo);
+ ATOMIC_IMPL(FetchAdd, a, v, mo);
}
#if __TSAN_HAS_INT128
SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_fetch_add(volatile a128 *a, a128 v, morder mo) {
- SCOPED_ATOMIC(FetchAdd, a, v, mo);
+ ATOMIC_IMPL(FetchAdd, a, v, mo);
}
#endif
SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_fetch_sub(volatile a8 *a, a8 v, morder mo) {
- SCOPED_ATOMIC(FetchSub, a, v, mo);
+ ATOMIC_IMPL(FetchSub, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_fetch_sub(volatile a16 *a, a16 v, morder mo) {
- SCOPED_ATOMIC(FetchSub, a, v, mo);
+ ATOMIC_IMPL(FetchSub, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_fetch_sub(volatile a32 *a, a32 v, morder mo) {
- SCOPED_ATOMIC(FetchSub, a, v, mo);
+ ATOMIC_IMPL(FetchSub, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_fetch_sub(volatile a64 *a, a64 v, morder mo) {
- SCOPED_ATOMIC(FetchSub, a, v, mo);
+ ATOMIC_IMPL(FetchSub, a, v, mo);
}
#if __TSAN_HAS_INT128
SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_fetch_sub(volatile a128 *a, a128 v, morder mo) {
- SCOPED_ATOMIC(FetchSub, a, v, mo);
+ ATOMIC_IMPL(FetchSub, a, v, mo);
}
#endif
SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_fetch_and(volatile a8 *a, a8 v, morder mo) {
- SCOPED_ATOMIC(FetchAnd, a, v, mo);
+ ATOMIC_IMPL(FetchAnd, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_fetch_and(volatile a16 *a, a16 v, morder mo) {
- SCOPED_ATOMIC(FetchAnd, a, v, mo);
+ ATOMIC_IMPL(FetchAnd, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_fetch_and(volatile a32 *a, a32 v, morder mo) {
- SCOPED_ATOMIC(FetchAnd, a, v, mo);
+ ATOMIC_IMPL(FetchAnd, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_fetch_and(volatile a64 *a, a64 v, morder mo) {
- SCOPED_ATOMIC(FetchAnd, a, v, mo);
+ ATOMIC_IMPL(FetchAnd, a, v, mo);
}
#if __TSAN_HAS_INT128
SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_fetch_and(volatile a128 *a, a128 v, morder mo) {
- SCOPED_ATOMIC(FetchAnd, a, v, mo);
+ ATOMIC_IMPL(FetchAnd, a, v, mo);
}
#endif
SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_fetch_or(volatile a8 *a, a8 v, morder mo) {
- SCOPED_ATOMIC(FetchOr, a, v, mo);
+ ATOMIC_IMPL(FetchOr, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_fetch_or(volatile a16 *a, a16 v, morder mo) {
- SCOPED_ATOMIC(FetchOr, a, v, mo);
+ ATOMIC_IMPL(FetchOr, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_fetch_or(volatile a32 *a, a32 v, morder mo) {
- SCOPED_ATOMIC(FetchOr, a, v, mo);
+ ATOMIC_IMPL(FetchOr, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_fetch_or(volatile a64 *a, a64 v, morder mo) {
- SCOPED_ATOMIC(FetchOr, a, v, mo);
+ ATOMIC_IMPL(FetchOr, a, v, mo);
}
#if __TSAN_HAS_INT128
SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_fetch_or(volatile a128 *a, a128 v, morder mo) {
- SCOPED_ATOMIC(FetchOr, a, v, mo);
+ ATOMIC_IMPL(FetchOr, a, v, mo);
}
#endif
SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_fetch_xor(volatile a8 *a, a8 v, morder mo) {
- SCOPED_ATOMIC(FetchXor, a, v, mo);
+ ATOMIC_IMPL(FetchXor, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_fetch_xor(volatile a16 *a, a16 v, morder mo) {
- SCOPED_ATOMIC(FetchXor, a, v, mo);
+ ATOMIC_IMPL(FetchXor, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_fetch_xor(volatile a32 *a, a32 v, morder mo) {
- SCOPED_ATOMIC(FetchXor, a, v, mo);
+ ATOMIC_IMPL(FetchXor, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_fetch_xor(volatile a64 *a, a64 v, morder mo) {
- SCOPED_ATOMIC(FetchXor, a, v, mo);
+ ATOMIC_IMPL(FetchXor, a, v, mo);
}
#if __TSAN_HAS_INT128
SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_fetch_xor(volatile a128 *a, a128 v, morder mo) {
- SCOPED_ATOMIC(FetchXor, a, v, mo);
+ ATOMIC_IMPL(FetchXor, a, v, mo);
}
#endif
SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_fetch_nand(volatile a8 *a, a8 v, morder mo) {
- SCOPED_ATOMIC(FetchNand, a, v, mo);
+ ATOMIC_IMPL(FetchNand, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_fetch_nand(volatile a16 *a, a16 v, morder mo) {
- SCOPED_ATOMIC(FetchNand, a, v, mo);
+ ATOMIC_IMPL(FetchNand, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_fetch_nand(volatile a32 *a, a32 v, morder mo) {
- SCOPED_ATOMIC(FetchNand, a, v, mo);
+ ATOMIC_IMPL(FetchNand, a, v, mo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_fetch_nand(volatile a64 *a, a64 v, morder mo) {
- SCOPED_ATOMIC(FetchNand, a, v, mo);
+ ATOMIC_IMPL(FetchNand, a, v, mo);
}
#if __TSAN_HAS_INT128
SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_fetch_nand(volatile a128 *a, a128 v, morder mo) {
- SCOPED_ATOMIC(FetchNand, a, v, mo);
+ ATOMIC_IMPL(FetchNand, a, v, mo);
}
#endif
SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v,
morder mo, morder fmo) {
- SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
}
SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic16_compare_exchange_strong(volatile a16 *a, a16 *c, a16 v,
morder mo, morder fmo) {
- SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
}
SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic32_compare_exchange_strong(volatile a32 *a, a32 *c, a32 v,
morder mo, morder fmo) {
- SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
}
SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic64_compare_exchange_strong(volatile a64 *a, a64 *c, a64 v,
morder mo, morder fmo) {
- SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
}
#if __TSAN_HAS_INT128
SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic128_compare_exchange_strong(volatile a128 *a, a128 *c, a128 v,
morder mo, morder fmo) {
- SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
}
#endif
SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v,
morder mo, morder fmo) {
- SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
}
SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic16_compare_exchange_weak(volatile a16 *a, a16 *c, a16 v,
morder mo, morder fmo) {
- SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
}
SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic32_compare_exchange_weak(volatile a32 *a, a32 *c, a32 v,
morder mo, morder fmo) {
- SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
}
SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,
morder mo, morder fmo) {
- SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
}
#if __TSAN_HAS_INT128
SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic128_compare_exchange_weak(volatile a128 *a, a128 *c, a128 v,
morder mo, morder fmo) {
- SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
}
#endif
SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v,
morder mo, morder fmo) {
- SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v,
morder mo, morder fmo) {
- SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v,
morder mo, morder fmo) {
- SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
}
SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v,
morder mo, morder fmo) {
- SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
}
#if __TSAN_HAS_INT128
SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v,
morder mo, morder fmo) {
- SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
}
#endif
SANITIZER_INTERFACE_ATTRIBUTE
-void __tsan_atomic_thread_fence(morder mo) {
- char* a = 0;
- SCOPED_ATOMIC(Fence, mo);
-}
+void __tsan_atomic_thread_fence(morder mo) { ATOMIC_IMPL(Fence, mo); }
SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_atomic_signal_fence(morder mo) {
@@ -867,25 +840,23 @@ void __tsan_atomic_signal_fence(morder mo) {
// Go
-#define ATOMIC(func, ...) \
- if (thr->ignore_sync) { \
- NoTsanAtomic##func(__VA_ARGS__); \
- } else { \
- FuncEntry(thr, cpc); \
+# define ATOMIC(func, ...) \
+ if (thr->ignore_sync) { \
+ NoTsanAtomic##func(__VA_ARGS__); \
+ } else { \
+ FuncEntry(thr, cpc); \
Atomic##func(thr, pc, __VA_ARGS__); \
- FuncExit(thr); \
- } \
-/**/
-
-#define ATOMIC_RET(func, ret, ...) \
- if (thr->ignore_sync) { \
- (ret) = NoTsanAtomic##func(__VA_ARGS__); \
- } else { \
- FuncEntry(thr, cpc); \
+ FuncExit(thr); \
+ }
+
+# define ATOMIC_RET(func, ret, ...) \
+ if (thr->ignore_sync) { \
+ (ret) = NoTsanAtomic##func(__VA_ARGS__); \
+ } else { \
+ FuncEntry(thr, cpc); \
(ret) = Atomic##func(thr, pc, __VA_ARGS__); \
- FuncExit(thr); \
- } \
-/**/
+ FuncExit(thr); \
+ }
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
diff --git a/libsanitizer/tsan/tsan_interface_inl.h b/libsanitizer/tsan/tsan_interface_inl.h
deleted file mode 100644
index 5e77d4d..0000000
--- a/libsanitizer/tsan/tsan_interface_inl.h
+++ /dev/null
@@ -1,133 +0,0 @@
-//===-- tsan_interface_inl.h ------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of ThreadSanitizer (TSan), a race detector.
-//
-//===----------------------------------------------------------------------===//
-
-#include "tsan_interface.h"
-#include "tsan_rtl.h"
-#include "sanitizer_common/sanitizer_ptrauth.h"
-
-#define CALLERPC ((uptr)__builtin_return_address(0))
-
-using namespace __tsan;
-
-void __tsan_read1(void *addr) {
- MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog1);
-}
-
-void __tsan_read2(void *addr) {
- MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog2);
-}
-
-void __tsan_read4(void *addr) {
- MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog4);
-}
-
-void __tsan_read8(void *addr) {
- MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
-}
-
-void __tsan_write1(void *addr) {
- MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog1);
-}
-
-void __tsan_write2(void *addr) {
- MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog2);
-}
-
-void __tsan_write4(void *addr) {
- MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog4);
-}
-
-void __tsan_write8(void *addr) {
- MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
-}
-
-void __tsan_read1_pc(void *addr, void *pc) {
- MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog1);
-}
-
-void __tsan_read2_pc(void *addr, void *pc) {
- MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog2);
-}
-
-void __tsan_read4_pc(void *addr, void *pc) {
- MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog4);
-}
-
-void __tsan_read8_pc(void *addr, void *pc) {
- MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog8);
-}
-
-void __tsan_write1_pc(void *addr, void *pc) {
- MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog1);
-}
-
-void __tsan_write2_pc(void *addr, void *pc) {
- MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog2);
-}
-
-void __tsan_write4_pc(void *addr, void *pc) {
- MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog4);
-}
-
-void __tsan_write8_pc(void *addr, void *pc) {
- MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog8);
-}
-
-void __tsan_vptr_update(void **vptr_p, void *new_val) {
- CHECK_EQ(sizeof(vptr_p), 8);
- if (*vptr_p != new_val) {
- ThreadState *thr = cur_thread();
- thr->is_vptr_access = true;
- MemoryWrite(thr, CALLERPC, (uptr)vptr_p, kSizeLog8);
- thr->is_vptr_access = false;
- }
-}
-
-void __tsan_vptr_read(void **vptr_p) {
- CHECK_EQ(sizeof(vptr_p), 8);
- ThreadState *thr = cur_thread();
- thr->is_vptr_access = true;
- MemoryRead(thr, CALLERPC, (uptr)vptr_p, kSizeLog8);
- thr->is_vptr_access = false;
-}
-
-void __tsan_func_entry(void *pc) {
- FuncEntry(cur_thread(), STRIP_PAC_PC(pc));
-}
-
-void __tsan_func_exit() {
- FuncExit(cur_thread());
-}
-
-void __tsan_ignore_thread_begin() {
- ThreadIgnoreBegin(cur_thread(), CALLERPC);
-}
-
-void __tsan_ignore_thread_end() {
- ThreadIgnoreEnd(cur_thread(), CALLERPC);
-}
-
-void __tsan_read_range(void *addr, uptr size) {
- MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, false);
-}
-
-void __tsan_write_range(void *addr, uptr size) {
- MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, true);
-}
-
-void __tsan_read_range_pc(void *addr, uptr size, void *pc) {
- MemoryAccessRange(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, size, false);
-}
-
-void __tsan_write_range_pc(void *addr, uptr size, void *pc) {
- MemoryAccessRange(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, size, true);
-}
diff --git a/libsanitizer/tsan/tsan_interface_java.cpp b/libsanitizer/tsan/tsan_interface_java.cpp
index 081c6ff..c090c1f 100644
--- a/libsanitizer/tsan/tsan_interface_java.cpp
+++ b/libsanitizer/tsan/tsan_interface_java.cpp
@@ -12,7 +12,6 @@
#include "tsan_interface_java.h"
#include "tsan_rtl.h"
-#include "tsan_mutex.h"
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_placement_new.h"
@@ -35,52 +34,49 @@ struct JavaContext {
}
};
-class ScopedJavaFunc {
- public:
- ScopedJavaFunc(ThreadState *thr, uptr pc)
- : thr_(thr) {
- Initialize(thr_);
- FuncEntry(thr, pc);
- }
-
- ~ScopedJavaFunc() {
- FuncExit(thr_);
- // FIXME(dvyukov): process pending signals.
- }
-
- private:
- ThreadState *thr_;
-};
-
static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
static JavaContext *jctx;
+MBlock *JavaHeapBlock(uptr addr, uptr *start) {
+ if (!jctx || addr < jctx->heap_begin ||
+ addr >= jctx->heap_begin + jctx->heap_size)
+ return nullptr;
+ for (uptr p = RoundDown(addr, kMetaShadowCell); p >= jctx->heap_begin;
+ p -= kMetaShadowCell) {
+ MBlock *b = ctx->metamap.GetBlock(p);
+ if (!b)
+ continue;
+ if (p + b->siz <= addr)
+ return nullptr;
+ *start = p;
+ return b;
+ }
+ return nullptr;
+}
+
} // namespace __tsan
-#define SCOPED_JAVA_FUNC(func) \
+#define JAVA_FUNC_ENTER(func) \
ThreadState *thr = cur_thread(); \
- const uptr caller_pc = GET_CALLER_PC(); \
- const uptr pc = StackTrace::GetCurrentPc(); \
- (void)pc; \
- ScopedJavaFunc scoped(thr, caller_pc); \
-/**/
+ (void)thr;
void __tsan_java_init(jptr heap_begin, jptr heap_size) {
- SCOPED_JAVA_FUNC(__tsan_java_init);
- DPrintf("#%d: java_init(%p, %p)\n", thr->tid, heap_begin, heap_size);
- CHECK_EQ(jctx, 0);
- CHECK_GT(heap_begin, 0);
- CHECK_GT(heap_size, 0);
- CHECK_EQ(heap_begin % kHeapAlignment, 0);
- CHECK_EQ(heap_size % kHeapAlignment, 0);
- CHECK_LT(heap_begin, heap_begin + heap_size);
+ JAVA_FUNC_ENTER(__tsan_java_init);
+ Initialize(thr);
+ DPrintf("#%d: java_init(0x%zx, 0x%zx)\n", thr->tid, heap_begin, heap_size);
+ DCHECK_EQ(jctx, 0);
+ DCHECK_GT(heap_begin, 0);
+ DCHECK_GT(heap_size, 0);
+ DCHECK_EQ(heap_begin % kHeapAlignment, 0);
+ DCHECK_EQ(heap_size % kHeapAlignment, 0);
+ DCHECK_LT(heap_begin, heap_begin + heap_size);
jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
}
int __tsan_java_fini() {
- SCOPED_JAVA_FUNC(__tsan_java_fini);
+ JAVA_FUNC_ENTER(__tsan_java_fini);
DPrintf("#%d: java_fini()\n", thr->tid);
- CHECK_NE(jctx, 0);
+ DCHECK_NE(jctx, 0);
// FIXME(dvyukov): this does not call atexit() callbacks.
int status = Finalize(thr);
DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
@@ -88,74 +84,65 @@ int __tsan_java_fini() {
}
void __tsan_java_alloc(jptr ptr, jptr size) {
- SCOPED_JAVA_FUNC(__tsan_java_alloc);
- DPrintf("#%d: java_alloc(%p, %p)\n", thr->tid, ptr, size);
- CHECK_NE(jctx, 0);
- CHECK_NE(size, 0);
- CHECK_EQ(ptr % kHeapAlignment, 0);
- CHECK_EQ(size % kHeapAlignment, 0);
- CHECK_GE(ptr, jctx->heap_begin);
- CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
-
- OnUserAlloc(thr, pc, ptr, size, false);
+ JAVA_FUNC_ENTER(__tsan_java_alloc);
+ DPrintf("#%d: java_alloc(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
+ DCHECK_NE(jctx, 0);
+ DCHECK_NE(size, 0);
+ DCHECK_EQ(ptr % kHeapAlignment, 0);
+ DCHECK_EQ(size % kHeapAlignment, 0);
+ DCHECK_GE(ptr, jctx->heap_begin);
+ DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
+
+ OnUserAlloc(thr, 0, ptr, size, false);
}
void __tsan_java_free(jptr ptr, jptr size) {
- SCOPED_JAVA_FUNC(__tsan_java_free);
- DPrintf("#%d: java_free(%p, %p)\n", thr->tid, ptr, size);
- CHECK_NE(jctx, 0);
- CHECK_NE(size, 0);
- CHECK_EQ(ptr % kHeapAlignment, 0);
- CHECK_EQ(size % kHeapAlignment, 0);
- CHECK_GE(ptr, jctx->heap_begin);
- CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
+ JAVA_FUNC_ENTER(__tsan_java_free);
+ DPrintf("#%d: java_free(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
+ DCHECK_NE(jctx, 0);
+ DCHECK_NE(size, 0);
+ DCHECK_EQ(ptr % kHeapAlignment, 0);
+ DCHECK_EQ(size % kHeapAlignment, 0);
+ DCHECK_GE(ptr, jctx->heap_begin);
+ DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
ctx->metamap.FreeRange(thr->proc(), ptr, size);
}
void __tsan_java_move(jptr src, jptr dst, jptr size) {
- SCOPED_JAVA_FUNC(__tsan_java_move);
- DPrintf("#%d: java_move(%p, %p, %p)\n", thr->tid, src, dst, size);
- CHECK_NE(jctx, 0);
- CHECK_NE(size, 0);
- CHECK_EQ(src % kHeapAlignment, 0);
- CHECK_EQ(dst % kHeapAlignment, 0);
- CHECK_EQ(size % kHeapAlignment, 0);
- CHECK_GE(src, jctx->heap_begin);
- CHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
- CHECK_GE(dst, jctx->heap_begin);
- CHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
- CHECK_NE(dst, src);
- CHECK_NE(size, 0);
+ JAVA_FUNC_ENTER(__tsan_java_move);
+ DPrintf("#%d: java_move(0x%zx, 0x%zx, 0x%zx)\n", thr->tid, src, dst, size);
+ DCHECK_NE(jctx, 0);
+ DCHECK_NE(size, 0);
+ DCHECK_EQ(src % kHeapAlignment, 0);
+ DCHECK_EQ(dst % kHeapAlignment, 0);
+ DCHECK_EQ(size % kHeapAlignment, 0);
+ DCHECK_GE(src, jctx->heap_begin);
+ DCHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
+ DCHECK_GE(dst, jctx->heap_begin);
+ DCHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
+ DCHECK_NE(dst, src);
+ DCHECK_NE(size, 0);
// Assuming it's not running concurrently with threads that do
// memory accesses and mutex operations (stop-the-world phase).
ctx->metamap.MoveMemory(src, dst, size);
- // Move shadow.
- u64 *s = (u64*)MemToShadow(src);
- u64 *d = (u64*)MemToShadow(dst);
- u64 *send = (u64*)MemToShadow(src + size);
- uptr inc = 1;
- if (dst > src) {
- s = (u64*)MemToShadow(src + size) - 1;
- d = (u64*)MemToShadow(dst + size) - 1;
- send = (u64*)MemToShadow(src) - 1;
- inc = -1;
- }
- for (; s != send; s += inc, d += inc) {
- *d = *s;
- *s = 0;
- }
+ // Clear the destination shadow range.
+ // We used to move shadow from src to dst, but the trace format does not
+ // support that anymore as it contains addresses of accesses.
+ RawShadow *d = MemToShadow(dst);
+ RawShadow *dend = MemToShadow(dst + size);
+ internal_memset(d, 0, (dend - d) * sizeof(*d));
}
jptr __tsan_java_find(jptr *from_ptr, jptr to) {
- SCOPED_JAVA_FUNC(__tsan_java_find);
- DPrintf("#%d: java_find(&%p, %p)\n", *from_ptr, to);
- CHECK_EQ((*from_ptr) % kHeapAlignment, 0);
- CHECK_EQ(to % kHeapAlignment, 0);
- CHECK_GE(*from_ptr, jctx->heap_begin);
- CHECK_LE(to, jctx->heap_begin + jctx->heap_size);
+ JAVA_FUNC_ENTER(__tsan_java_find);
+ DPrintf("#%d: java_find(&0x%zx, 0x%zx)\n", thr->tid, *from_ptr, to);
+ DCHECK_EQ((*from_ptr) % kHeapAlignment, 0);
+ DCHECK_EQ(to % kHeapAlignment, 0);
+ DCHECK_GE(*from_ptr, jctx->heap_begin);
+ DCHECK_LE(to, jctx->heap_begin + jctx->heap_size);
for (uptr from = *from_ptr; from < to; from += kHeapAlignment) {
MBlock *b = ctx->metamap.GetBlock(from);
if (b) {
@@ -167,101 +154,105 @@ jptr __tsan_java_find(jptr *from_ptr, jptr to) {
}
void __tsan_java_finalize() {
- SCOPED_JAVA_FUNC(__tsan_java_finalize);
- DPrintf("#%d: java_mutex_finalize()\n", thr->tid);
- AcquireGlobal(thr, 0);
+ JAVA_FUNC_ENTER(__tsan_java_finalize);
+ DPrintf("#%d: java_finalize()\n", thr->tid);
+ AcquireGlobal(thr);
}
void __tsan_java_mutex_lock(jptr addr) {
- SCOPED_JAVA_FUNC(__tsan_java_mutex_lock);
- DPrintf("#%d: java_mutex_lock(%p)\n", thr->tid, addr);
- CHECK_NE(jctx, 0);
- CHECK_GE(addr, jctx->heap_begin);
- CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
-
- MutexPostLock(thr, pc, addr, MutexFlagLinkerInit | MutexFlagWriteReentrant |
- MutexFlagDoPreLockOnPostLock);
+ JAVA_FUNC_ENTER(__tsan_java_mutex_lock);
+ DPrintf("#%d: java_mutex_lock(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+
+ MutexPostLock(thr, 0, addr,
+ MutexFlagLinkerInit | MutexFlagWriteReentrant |
+ MutexFlagDoPreLockOnPostLock);
}
void __tsan_java_mutex_unlock(jptr addr) {
- SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock);
- DPrintf("#%d: java_mutex_unlock(%p)\n", thr->tid, addr);
- CHECK_NE(jctx, 0);
- CHECK_GE(addr, jctx->heap_begin);
- CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+ JAVA_FUNC_ENTER(__tsan_java_mutex_unlock);
+ DPrintf("#%d: java_mutex_unlock(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
- MutexUnlock(thr, pc, addr);
+ MutexUnlock(thr, 0, addr);
}
void __tsan_java_mutex_read_lock(jptr addr) {
- SCOPED_JAVA_FUNC(__tsan_java_mutex_read_lock);
- DPrintf("#%d: java_mutex_read_lock(%p)\n", thr->tid, addr);
- CHECK_NE(jctx, 0);
- CHECK_GE(addr, jctx->heap_begin);
- CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
-
- MutexPostReadLock(thr, pc, addr, MutexFlagLinkerInit |
- MutexFlagWriteReentrant | MutexFlagDoPreLockOnPostLock);
+ JAVA_FUNC_ENTER(__tsan_java_mutex_read_lock);
+ DPrintf("#%d: java_mutex_read_lock(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+
+ MutexPostReadLock(thr, 0, addr,
+ MutexFlagLinkerInit | MutexFlagWriteReentrant |
+ MutexFlagDoPreLockOnPostLock);
}
void __tsan_java_mutex_read_unlock(jptr addr) {
- SCOPED_JAVA_FUNC(__tsan_java_mutex_read_unlock);
- DPrintf("#%d: java_mutex_read_unlock(%p)\n", thr->tid, addr);
- CHECK_NE(jctx, 0);
- CHECK_GE(addr, jctx->heap_begin);
- CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+ JAVA_FUNC_ENTER(__tsan_java_mutex_read_unlock);
+ DPrintf("#%d: java_mutex_read_unlock(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
- MutexReadUnlock(thr, pc, addr);
+ MutexReadUnlock(thr, 0, addr);
}
void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
- SCOPED_JAVA_FUNC(__tsan_java_mutex_lock_rec);
- DPrintf("#%d: java_mutex_lock_rec(%p, %d)\n", thr->tid, addr, rec);
- CHECK_NE(jctx, 0);
- CHECK_GE(addr, jctx->heap_begin);
- CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
- CHECK_GT(rec, 0);
-
- MutexPostLock(thr, pc, addr, MutexFlagLinkerInit | MutexFlagWriteReentrant |
- MutexFlagDoPreLockOnPostLock | MutexFlagRecursiveLock, rec);
+ JAVA_FUNC_ENTER(__tsan_java_mutex_lock_rec);
+ DPrintf("#%d: java_mutex_lock_rec(0x%zx, %d)\n", thr->tid, addr, rec);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+ DCHECK_GT(rec, 0);
+
+ MutexPostLock(thr, 0, addr,
+ MutexFlagLinkerInit | MutexFlagWriteReentrant |
+ MutexFlagDoPreLockOnPostLock | MutexFlagRecursiveLock,
+ rec);
}
int __tsan_java_mutex_unlock_rec(jptr addr) {
- SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock_rec);
- DPrintf("#%d: java_mutex_unlock_rec(%p)\n", thr->tid, addr);
- CHECK_NE(jctx, 0);
- CHECK_GE(addr, jctx->heap_begin);
- CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+ JAVA_FUNC_ENTER(__tsan_java_mutex_unlock_rec);
+ DPrintf("#%d: java_mutex_unlock_rec(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
- return MutexUnlock(thr, pc, addr, MutexFlagRecursiveUnlock);
+ return MutexUnlock(thr, 0, addr, MutexFlagRecursiveUnlock);
}
void __tsan_java_acquire(jptr addr) {
- SCOPED_JAVA_FUNC(__tsan_java_acquire);
- DPrintf("#%d: java_acquire(%p)\n", thr->tid, addr);
- CHECK_NE(jctx, 0);
- CHECK_GE(addr, jctx->heap_begin);
- CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+ JAVA_FUNC_ENTER(__tsan_java_acquire);
+ DPrintf("#%d: java_acquire(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
- Acquire(thr, caller_pc, addr);
+ Acquire(thr, 0, addr);
}
void __tsan_java_release(jptr addr) {
- SCOPED_JAVA_FUNC(__tsan_java_release);
- DPrintf("#%d: java_release(%p)\n", thr->tid, addr);
- CHECK_NE(jctx, 0);
- CHECK_GE(addr, jctx->heap_begin);
- CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+ JAVA_FUNC_ENTER(__tsan_java_release);
+ DPrintf("#%d: java_release(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
- Release(thr, caller_pc, addr);
+ Release(thr, 0, addr);
}
void __tsan_java_release_store(jptr addr) {
- SCOPED_JAVA_FUNC(__tsan_java_release);
- DPrintf("#%d: java_release_store(%p)\n", thr->tid, addr);
- CHECK_NE(jctx, 0);
- CHECK_GE(addr, jctx->heap_begin);
- CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+ JAVA_FUNC_ENTER(__tsan_java_release);
+ DPrintf("#%d: java_release_store(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
- ReleaseStore(thr, caller_pc, addr);
+ ReleaseStore(thr, 0, addr);
}
diff --git a/libsanitizer/tsan/tsan_mman.cpp b/libsanitizer/tsan/tsan_mman.cpp
index 7765bc0..f1b6768 100644
--- a/libsanitizer/tsan/tsan_mman.cpp
+++ b/libsanitizer/tsan/tsan_mman.cpp
@@ -148,7 +148,7 @@ static void SignalUnsafeCall(ThreadState *thr, uptr pc) {
ObtainCurrentStack(thr, pc, &stack);
if (IsFiredSuppression(ctx, ReportTypeSignalUnsafe, stack))
return;
- ThreadRegistryLock l(ctx->thread_registry);
+ ThreadRegistryLock l(&ctx->thread_registry);
ScopedReport rep(ReportTypeSignalUnsafe);
rep.AddStack(stack, true);
OutputReport(thr, rep);
@@ -218,7 +218,7 @@ void *user_reallocarray(ThreadState *thr, uptr pc, void *p, uptr size, uptr n) {
}
void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write) {
- DPrintf("#%d: alloc(%zu) = %p\n", thr->tid, sz, p);
+ DPrintf("#%d: alloc(%zu) = 0x%zx\n", thr->tid, sz, p);
ctx->metamap.AllocBlock(thr, pc, p, sz);
if (write && thr->ignore_reads_and_writes == 0)
MemoryRangeImitateWrite(thr, pc, (uptr)p, sz);
@@ -229,7 +229,7 @@ void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write) {
void OnUserFree(ThreadState *thr, uptr pc, uptr p, bool write) {
CHECK_NE(p, (void*)0);
uptr sz = ctx->metamap.FreeBlock(thr->proc(), p);
- DPrintf("#%d: free(%p, %zu)\n", thr->tid, p, sz);
+ DPrintf("#%d: free(0x%zx, %zu)\n", thr->tid, p, sz);
if (write && thr->ignore_reads_and_writes == 0)
MemoryRangeFreed(thr, pc, (uptr)p, sz);
}
@@ -336,7 +336,7 @@ void invoke_free_hook(void *ptr) {
RunFreeHooks(ptr);
}
-void *internal_alloc(MBlockType typ, uptr sz) {
+void *Alloc(uptr sz) {
ThreadState *thr = cur_thread();
if (thr->nomalloc) {
thr->nomalloc = 0; // CHECK calls internal_malloc().
@@ -345,7 +345,7 @@ void *internal_alloc(MBlockType typ, uptr sz) {
return InternalAlloc(sz, &thr->proc()->internal_alloc_cache);
}
-void internal_free(void *p) {
+void FreeImpl(void *p) {
ThreadState *thr = cur_thread();
if (thr->nomalloc) {
thr->nomalloc = 0; // CHECK calls internal_malloc().
diff --git a/libsanitizer/tsan/tsan_mman.h b/libsanitizer/tsan/tsan_mman.h
index a5280d4..efea5e5 100644
--- a/libsanitizer/tsan/tsan_mman.h
+++ b/libsanitizer/tsan/tsan_mman.h
@@ -47,42 +47,29 @@ uptr user_alloc_usable_size(const void *p);
void invoke_malloc_hook(void *ptr, uptr size);
void invoke_free_hook(void *ptr);
-enum MBlockType {
- MBlockScopedBuf,
- MBlockString,
- MBlockStackTrace,
- MBlockShadowStack,
- MBlockSync,
- MBlockClock,
- MBlockThreadContex,
- MBlockDeadInfo,
- MBlockRacyStacks,
- MBlockRacyAddresses,
- MBlockAtExit,
- MBlockFlag,
- MBlockReport,
- MBlockReportMop,
- MBlockReportThread,
- MBlockReportMutex,
- MBlockReportLoc,
- MBlockReportStack,
- MBlockSuppression,
- MBlockExpectRace,
- MBlockSignal,
- MBlockJmpBuf,
+// For internal data structures.
+void *Alloc(uptr sz);
+void FreeImpl(void *p);
- // This must be the last.
- MBlockTypeCount
-};
+template <typename T, typename... Args>
+T *New(Args &&...args) {
+ return new (Alloc(sizeof(T))) T(static_cast<Args &&>(args)...);
+}
-// For internal data structures.
-void *internal_alloc(MBlockType typ, uptr sz);
-void internal_free(void *p);
+template <typename T>
+void Free(T *&p) {
+ if (p == nullptr)
+ return;
+ FreeImpl(p);
+ p = nullptr;
+}
template <typename T>
-void DestroyAndFree(T *p) {
+void DestroyAndFree(T *&p) {
+ if (p == nullptr)
+ return;
p->~T();
- internal_free(p);
+ Free(p);
}
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_mutex.cpp b/libsanitizer/tsan/tsan_mutex.cpp
deleted file mode 100644
index d8b1826..0000000
--- a/libsanitizer/tsan/tsan_mutex.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-//===-- tsan_mutex.cpp ----------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of ThreadSanitizer (TSan), a race detector.
-//
-//===----------------------------------------------------------------------===//
-#include "sanitizer_common/sanitizer_libc.h"
-#include "tsan_mutex.h"
-#include "tsan_platform.h"
-#include "tsan_rtl.h"
-
-namespace __tsan {
-
-// Simple reader-writer spin-mutex. Optimized for not-so-contended case.
-// Readers have preference, can possibly starvate writers.
-
-// The table fixes what mutexes can be locked under what mutexes.
-// E.g. if the row for MutexTypeThreads contains MutexTypeReport,
-// then Report mutex can be locked while under Threads mutex.
-// The leaf mutexes can be locked under any other mutexes.
-// Recursive locking is not supported.
-#if SANITIZER_DEBUG && !SANITIZER_GO
-const MutexType MutexTypeLeaf = (MutexType)-1;
-static MutexType CanLockTab[MutexTypeCount][MutexTypeCount] = {
- /*0 MutexTypeInvalid*/ {},
- /*1 MutexTypeTrace*/ {MutexTypeLeaf},
- /*2 MutexTypeThreads*/ {MutexTypeReport},
- /*3 MutexTypeReport*/ {MutexTypeSyncVar,
- MutexTypeMBlock, MutexTypeJavaMBlock},
- /*4 MutexTypeSyncVar*/ {MutexTypeDDetector},
- /*5 MutexTypeSyncTab*/ {}, // unused
- /*6 MutexTypeSlab*/ {MutexTypeLeaf},
- /*7 MutexTypeAnnotations*/ {},
- /*8 MutexTypeAtExit*/ {MutexTypeSyncVar},
- /*9 MutexTypeMBlock*/ {MutexTypeSyncVar},
- /*10 MutexTypeJavaMBlock*/ {MutexTypeSyncVar},
- /*11 MutexTypeDDetector*/ {},
- /*12 MutexTypeFired*/ {MutexTypeLeaf},
- /*13 MutexTypeRacy*/ {MutexTypeLeaf},
- /*14 MutexTypeGlobalProc*/ {},
-};
-
-static bool CanLockAdj[MutexTypeCount][MutexTypeCount];
-#endif
-
-void InitializeMutex() {
-#if SANITIZER_DEBUG && !SANITIZER_GO
- // Build the "can lock" adjacency matrix.
- // If [i][j]==true, then one can lock mutex j while under mutex i.
- const int N = MutexTypeCount;
- int cnt[N] = {};
- bool leaf[N] = {};
- for (int i = 1; i < N; i++) {
- for (int j = 0; j < N; j++) {
- MutexType z = CanLockTab[i][j];
- if (z == MutexTypeInvalid)
- continue;
- if (z == MutexTypeLeaf) {
- CHECK(!leaf[i]);
- leaf[i] = true;
- continue;
- }
- CHECK(!CanLockAdj[i][(int)z]);
- CanLockAdj[i][(int)z] = true;
- cnt[i]++;
- }
- }
- for (int i = 0; i < N; i++) {
- CHECK(!leaf[i] || cnt[i] == 0);
- }
- // Add leaf mutexes.
- for (int i = 0; i < N; i++) {
- if (!leaf[i])
- continue;
- for (int j = 0; j < N; j++) {
- if (i == j || leaf[j] || j == MutexTypeInvalid)
- continue;
- CHECK(!CanLockAdj[j][i]);
- CanLockAdj[j][i] = true;
- }
- }
- // Build the transitive closure.
- bool CanLockAdj2[MutexTypeCount][MutexTypeCount];
- for (int i = 0; i < N; i++) {
- for (int j = 0; j < N; j++) {
- CanLockAdj2[i][j] = CanLockAdj[i][j];
- }
- }
- for (int k = 0; k < N; k++) {
- for (int i = 0; i < N; i++) {
- for (int j = 0; j < N; j++) {
- if (CanLockAdj2[i][k] && CanLockAdj2[k][j]) {
- CanLockAdj2[i][j] = true;
- }
- }
- }
- }
-#if 0
- Printf("Can lock graph:\n");
- for (int i = 0; i < N; i++) {
- for (int j = 0; j < N; j++) {
- Printf("%d ", CanLockAdj[i][j]);
- }
- Printf("\n");
- }
- Printf("Can lock graph closure:\n");
- for (int i = 0; i < N; i++) {
- for (int j = 0; j < N; j++) {
- Printf("%d ", CanLockAdj2[i][j]);
- }
- Printf("\n");
- }
-#endif
- // Verify that the graph is acyclic.
- for (int i = 0; i < N; i++) {
- if (CanLockAdj2[i][i]) {
- Printf("Mutex %d participates in a cycle\n", i);
- Die();
- }
- }
-#endif
-}
-
-InternalDeadlockDetector::InternalDeadlockDetector() {
- // Rely on zero initialization because some mutexes can be locked before ctor.
-}
-
-#if SANITIZER_DEBUG && !SANITIZER_GO
-void InternalDeadlockDetector::Lock(MutexType t) {
- // Printf("LOCK %d @%zu\n", t, seq_ + 1);
- CHECK_GT(t, MutexTypeInvalid);
- CHECK_LT(t, MutexTypeCount);
- u64 max_seq = 0;
- u64 max_idx = MutexTypeInvalid;
- for (int i = 0; i != MutexTypeCount; i++) {
- if (locked_[i] == 0)
- continue;
- CHECK_NE(locked_[i], max_seq);
- if (max_seq < locked_[i]) {
- max_seq = locked_[i];
- max_idx = i;
- }
- }
- locked_[t] = ++seq_;
- if (max_idx == MutexTypeInvalid)
- return;
- // Printf(" last %d @%zu\n", max_idx, max_seq);
- if (!CanLockAdj[max_idx][t]) {
- Printf("ThreadSanitizer: internal deadlock detected\n");
- Printf("ThreadSanitizer: can't lock %d while under %zu\n",
- t, (uptr)max_idx);
- CHECK(0);
- }
-}
-
-void InternalDeadlockDetector::Unlock(MutexType t) {
- // Printf("UNLO %d @%zu #%zu\n", t, seq_, locked_[t]);
- CHECK(locked_[t]);
- locked_[t] = 0;
-}
-
-void InternalDeadlockDetector::CheckNoLocks() {
- for (int i = 0; i != MutexTypeCount; i++) {
- CHECK_EQ(locked_[i], 0);
- }
-}
-#endif
-
-void CheckNoLocks(ThreadState *thr) {
-#if SANITIZER_DEBUG && !SANITIZER_GO
- thr->internal_deadlock_detector.CheckNoLocks();
-#endif
-}
-
-const uptr kUnlocked = 0;
-const uptr kWriteLock = 1;
-const uptr kReadLock = 2;
-
-class Backoff {
- public:
- Backoff()
- : iter_() {
- }
-
- bool Do() {
- if (iter_++ < kActiveSpinIters)
- proc_yield(kActiveSpinCnt);
- else
- internal_sched_yield();
- return true;
- }
-
- u64 Contention() const {
- u64 active = iter_ % kActiveSpinIters;
- u64 passive = iter_ - active;
- return active + 10 * passive;
- }
-
- private:
- int iter_;
- static const int kActiveSpinIters = 10;
- static const int kActiveSpinCnt = 20;
-};
-
-Mutex::Mutex(MutexType type) {
- CHECK_GT(type, MutexTypeInvalid);
- CHECK_LT(type, MutexTypeCount);
-#if SANITIZER_DEBUG
- type_ = type;
-#endif
- atomic_store(&state_, kUnlocked, memory_order_relaxed);
-}
-
-Mutex::~Mutex() {
- CHECK_EQ(atomic_load(&state_, memory_order_relaxed), kUnlocked);
-}
-
-void Mutex::Lock() {
-#if SANITIZER_DEBUG && !SANITIZER_GO
- cur_thread()->internal_deadlock_detector.Lock(type_);
-#endif
- uptr cmp = kUnlocked;
- if (atomic_compare_exchange_strong(&state_, &cmp, kWriteLock,
- memory_order_acquire))
- return;
- for (Backoff backoff; backoff.Do();) {
- if (atomic_load(&state_, memory_order_relaxed) == kUnlocked) {
- cmp = kUnlocked;
- if (atomic_compare_exchange_weak(&state_, &cmp, kWriteLock,
- memory_order_acquire)) {
- return;
- }
- }
- }
-}
-
-void Mutex::Unlock() {
- uptr prev = atomic_fetch_sub(&state_, kWriteLock, memory_order_release);
- (void)prev;
- DCHECK_NE(prev & kWriteLock, 0);
-#if SANITIZER_DEBUG && !SANITIZER_GO
- cur_thread()->internal_deadlock_detector.Unlock(type_);
-#endif
-}
-
-void Mutex::ReadLock() {
-#if SANITIZER_DEBUG && !SANITIZER_GO
- cur_thread()->internal_deadlock_detector.Lock(type_);
-#endif
- uptr prev = atomic_fetch_add(&state_, kReadLock, memory_order_acquire);
- if ((prev & kWriteLock) == 0)
- return;
- for (Backoff backoff; backoff.Do();) {
- prev = atomic_load(&state_, memory_order_acquire);
- if ((prev & kWriteLock) == 0) {
- return;
- }
- }
-}
-
-void Mutex::ReadUnlock() {
- uptr prev = atomic_fetch_sub(&state_, kReadLock, memory_order_release);
- (void)prev;
- DCHECK_EQ(prev & kWriteLock, 0);
- DCHECK_GT(prev & ~kWriteLock, 0);
-#if SANITIZER_DEBUG && !SANITIZER_GO
- cur_thread()->internal_deadlock_detector.Unlock(type_);
-#endif
-}
-
-void Mutex::CheckLocked() {
- CHECK_NE(atomic_load(&state_, memory_order_relaxed), 0);
-}
-
-} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_mutex.h b/libsanitizer/tsan/tsan_mutex.h
deleted file mode 100644
index 9a579ea..0000000
--- a/libsanitizer/tsan/tsan_mutex.h
+++ /dev/null
@@ -1,87 +0,0 @@
-//===-- tsan_mutex.h --------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of ThreadSanitizer (TSan), a race detector.
-//
-//===----------------------------------------------------------------------===//
-#ifndef TSAN_MUTEX_H
-#define TSAN_MUTEX_H
-
-#include "sanitizer_common/sanitizer_atomic.h"
-#include "sanitizer_common/sanitizer_mutex.h"
-#include "tsan_defs.h"
-
-namespace __tsan {
-
-enum MutexType {
- MutexTypeInvalid,
- MutexTypeTrace,
- MutexTypeThreads,
- MutexTypeReport,
- MutexTypeSyncVar,
- MutexTypeSyncTab,
- MutexTypeSlab,
- MutexTypeAnnotations,
- MutexTypeAtExit,
- MutexTypeMBlock,
- MutexTypeJavaMBlock,
- MutexTypeDDetector,
- MutexTypeFired,
- MutexTypeRacy,
- MutexTypeGlobalProc,
-
- // This must be the last.
- MutexTypeCount
-};
-
-class Mutex {
- public:
- explicit Mutex(MutexType type);
- ~Mutex();
-
- void Lock();
- void Unlock();
-
- void ReadLock();
- void ReadUnlock();
-
- void CheckLocked();
-
- private:
- atomic_uintptr_t state_;
-#if SANITIZER_DEBUG
- MutexType type_;
-#endif
-
- Mutex(const Mutex&);
- void operator = (const Mutex&);
-};
-
-typedef GenericScopedLock<Mutex> Lock;
-typedef GenericScopedReadLock<Mutex> ReadLock;
-
-class InternalDeadlockDetector {
- public:
- InternalDeadlockDetector();
- void Lock(MutexType t);
- void Unlock(MutexType t);
- void CheckNoLocks();
- private:
- u64 seq_;
- u64 locked_[MutexTypeCount];
-};
-
-void InitializeMutex();
-
-// Checks that the current thread does not hold any runtime locks
-// (e.g. when returning from an interceptor).
-void CheckNoLocks(ThreadState *thr);
-
-} // namespace __tsan
-
-#endif // TSAN_MUTEX_H
diff --git a/libsanitizer/tsan/tsan_mutexset.cpp b/libsanitizer/tsan/tsan_mutexset.cpp
index 813fa3b..efc0e41 100644
--- a/libsanitizer/tsan/tsan_mutexset.cpp
+++ b/libsanitizer/tsan/tsan_mutexset.cpp
@@ -14,11 +14,7 @@
namespace __tsan {
-const uptr MutexSet::kMaxSize;
-
MutexSet::MutexSet() {
- size_ = 0;
- internal_memset(&descs_, 0, sizeof(descs_));
}
void MutexSet::Add(u64 id, bool write, u64 epoch) {
@@ -44,9 +40,12 @@ void MutexSet::Add(u64 id, bool write, u64 epoch) {
CHECK_EQ(size_, kMaxSize - 1);
}
// Add new mutex descriptor.
+ descs_[size_].addr = 0;
+ descs_[size_].stack_id = kInvalidStackID;
descs_[size_].id = id;
descs_[size_].write = write;
descs_[size_].epoch = epoch;
+ descs_[size_].seq = seq_++;
descs_[size_].count = 1;
size_++;
}
@@ -70,6 +69,46 @@ void MutexSet::Remove(u64 id) {
}
}
+void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {
+ // Look up existing mutex with the same id.
+ for (uptr i = 0; i < size_; i++) {
+ if (descs_[i].addr == addr) {
+ descs_[i].count++;
+ descs_[i].seq = seq_++;
+ return;
+ }
+ }
+ // On overflow, find the oldest mutex and drop it.
+ if (size_ == kMaxSize) {
+ uptr min = 0;
+ for (uptr i = 0; i < size_; i++) {
+ if (descs_[i].seq < descs_[min].seq)
+ min = i;
+ }
+ RemovePos(min);
+ CHECK_EQ(size_, kMaxSize - 1);
+ }
+ // Add new mutex descriptor.
+ descs_[size_].addr = addr;
+ descs_[size_].stack_id = stack_id;
+ descs_[size_].id = 0;
+ descs_[size_].write = write;
+ descs_[size_].epoch = 0;
+ descs_[size_].seq = seq_++;
+ descs_[size_].count = 1;
+ size_++;
+}
+
+void MutexSet::DelAddr(uptr addr, bool destroy) {
+ for (uptr i = 0; i < size_; i++) {
+ if (descs_[i].addr == addr) {
+ if (destroy || --descs_[i].count == 0)
+ RemovePos(i);
+ return;
+ }
+ }
+}
+
void MutexSet::RemovePos(uptr i) {
CHECK_LT(i, size_);
descs_[i] = descs_[size_ - 1];
diff --git a/libsanitizer/tsan/tsan_mutexset.h b/libsanitizer/tsan/tsan_mutexset.h
index d63881f..a448cee 100644
--- a/libsanitizer/tsan/tsan_mutexset.h
+++ b/libsanitizer/tsan/tsan_mutexset.h
@@ -21,12 +21,22 @@ class MutexSet {
public:
// Holds limited number of mutexes.
// The oldest mutexes are discarded on overflow.
- static const uptr kMaxSize = 16;
+ static constexpr uptr kMaxSize = 16;
struct Desc {
+ uptr addr;
+ StackID stack_id;
u64 id;
u64 epoch;
- int count;
+ u32 seq;
+ u32 count;
bool write;
+
+ Desc() { internal_memset(this, 0, sizeof(*this)); }
+ Desc(const Desc& other) { *this = other; }
+ Desc& operator=(const MutexSet::Desc& other) {
+ internal_memcpy(this, &other, sizeof(*this));
+ return *this;
+ }
};
MutexSet();
@@ -34,21 +44,19 @@ class MutexSet {
void Add(u64 id, bool write, u64 epoch);
void Del(u64 id, bool write);
void Remove(u64 id); // Removes the mutex completely (if it's destroyed).
+ void AddAddr(uptr addr, StackID stack_id, bool write);
+ void DelAddr(uptr addr, bool destroy = false);
uptr Size() const;
Desc Get(uptr i) const;
- void operator=(const MutexSet &other) {
- internal_memcpy(this, &other, sizeof(*this));
- }
-
private:
#if !SANITIZER_GO
- uptr size_;
+ u32 seq_ = 0;
+ uptr size_ = 0;
Desc descs_[kMaxSize];
-#endif
void RemovePos(uptr i);
- MutexSet(const MutexSet&);
+#endif
};
// Go does not have mutexes, so do not spend memory and time.
@@ -59,7 +67,8 @@ MutexSet::MutexSet() {}
void MutexSet::Add(u64 id, bool write, u64 epoch) {}
void MutexSet::Del(u64 id, bool write) {}
void MutexSet::Remove(u64 id) {}
-void MutexSet::RemovePos(uptr i) {}
+void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {}
+void MutexSet::DelAddr(uptr addr, bool destroy) {}
uptr MutexSet::Size() const { return 0; }
MutexSet::Desc MutexSet::Get(uptr i) const { return Desc(); }
#endif
diff --git a/libsanitizer/tsan/tsan_platform.h b/libsanitizer/tsan/tsan_platform.h
index 8bd218e..fc27a56 100644
--- a/libsanitizer/tsan/tsan_platform.h
+++ b/libsanitizer/tsan/tsan_platform.h
@@ -23,21 +23,19 @@
namespace __tsan {
-#if defined(__x86_64__)
-#define HAS_48_BIT_ADDRESS_SPACE 1
-#elif SANITIZER_IOSSIM // arm64 iOS simulators (order of #if matters)
-#define HAS_48_BIT_ADDRESS_SPACE 1
-#elif SANITIZER_IOS // arm64 iOS devices (order of #if matters)
-#define HAS_48_BIT_ADDRESS_SPACE 0
-#elif SANITIZER_MAC // arm64 macOS (order of #if matters)
-#define HAS_48_BIT_ADDRESS_SPACE 1
-#else
-#define HAS_48_BIT_ADDRESS_SPACE 0
-#endif
-
-#if !SANITIZER_GO
+enum {
+ // App memory is not mapped onto shadow memory range.
+ kBrokenMapping = 1 << 0,
+ // Mapping app memory and back does not produce the same address,
+ // this can lead to wrong addresses in reports and potentially
+ // other bad consequences.
+ kBrokenReverseMapping = 1 << 1,
+ // Mapping is non-linear for linear user range.
+ // This is bad and can lead to unpredictable memory corruptions, etc
+ // because range access functions assume linearity.
+ kBrokenLinearity = 1 << 2,
+};
-#if HAS_48_BIT_ADDRESS_SPACE
/*
C/C++ on linux/x86_64 and freebsd/x86_64
0000 0000 1000 - 0080 0000 0000: main binary and/or MAP_32BIT mappings (512GB)
@@ -65,9 +63,8 @@ C/C++ on netbsd/amd64 can reuse the same mapping:
* Stack on NetBSD/amd64 has prereserved 128MB.
* Heap grows downwards (top-down).
* ASLR must be disabled per-process or globally.
-
*/
-struct Mapping {
+struct Mapping48AddressSpace {
static const uptr kMetaShadowBeg = 0x300000000000ull;
static const uptr kMetaShadowEnd = 0x340000000000ull;
static const uptr kTraceMemBeg = 0x600000000000ull;
@@ -82,13 +79,12 @@ struct Mapping {
static const uptr kMidAppMemEnd = 0x568000000000ull;
static const uptr kHiAppMemBeg = 0x7e8000000000ull;
static const uptr kHiAppMemEnd = 0x800000000000ull;
- static const uptr kAppMemMsk = 0x780000000000ull;
- static const uptr kAppMemXor = 0x040000000000ull;
+ static const uptr kShadowMsk = 0x780000000000ull;
+ static const uptr kShadowXor = 0x040000000000ull;
+ static const uptr kShadowAdd = 0x000000000000ull;
static const uptr kVdsoBeg = 0xf000000000000000ull;
};
-#define TSAN_MID_APP_RANGE 1
-#elif defined(__mips64)
/*
C/C++ on linux/mips64 (40-bit VMA)
0000 0000 00 - 0100 0000 00: - (4 GB)
@@ -105,7 +101,7 @@ fe00 0000 00 - ff00 0000 00: heap (4 GB)
ff00 0000 00 - ff80 0000 00: - (2 GB)
ff80 0000 00 - ffff ffff ff: modules and main thread stack (<2 GB)
*/
-struct Mapping40 {
+struct MappingMips64_40 {
static const uptr kMetaShadowBeg = 0x4000000000ull;
static const uptr kMetaShadowEnd = 0x5000000000ull;
static const uptr kTraceMemBeg = 0xb000000000ull;
@@ -120,14 +116,12 @@ struct Mapping40 {
static const uptr kMidAppMemEnd = 0xab00000000ull;
static const uptr kHiAppMemBeg = 0xff80000000ull;
static const uptr kHiAppMemEnd = 0xffffffffffull;
- static const uptr kAppMemMsk = 0xf800000000ull;
- static const uptr kAppMemXor = 0x0800000000ull;
+ static const uptr kShadowMsk = 0xf800000000ull;
+ static const uptr kShadowXor = 0x0800000000ull;
+ static const uptr kShadowAdd = 0x0000000000ull;
static const uptr kVdsoBeg = 0xfffff00000ull;
};
-#define TSAN_MID_APP_RANGE 1
-#define TSAN_RUNTIME_VMA 1
-#elif defined(__aarch64__) && defined(__APPLE__)
/*
C/C++ on Darwin/iOS/ARM64 (36-bit VMA, 64 GB VM)
0000 0000 00 - 0100 0000 00: - (4 GB)
@@ -141,7 +135,7 @@ C/C++ on Darwin/iOS/ARM64 (36-bit VMA, 64 GB VM)
0f00 0000 00 - 0fc0 0000 00: traces (3 GB)
0fc0 0000 00 - 1000 0000 00: -
*/
-struct Mapping {
+struct MappingAppleAarch64 {
static const uptr kLoAppMemBeg = 0x0100000000ull;
static const uptr kLoAppMemEnd = 0x0200000000ull;
static const uptr kHeapMemBeg = 0x0200000000ull;
@@ -154,18 +148,14 @@ struct Mapping {
static const uptr kTraceMemEnd = 0x0fc0000000ull;
static const uptr kHiAppMemBeg = 0x0fc0000000ull;
static const uptr kHiAppMemEnd = 0x0fc0000000ull;
- static const uptr kAppMemMsk = 0x0ull;
- static const uptr kAppMemXor = 0x0ull;
+ static const uptr kShadowMsk = 0x0ull;
+ static const uptr kShadowXor = 0x0ull;
+ static const uptr kShadowAdd = 0x0ull;
static const uptr kVdsoBeg = 0x7000000000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
};
-#elif defined(__aarch64__) && !defined(__APPLE__)
-// AArch64 supports multiple VMA which leads to multiple address transformation
-// functions. To support these multiple VMAS transformations and mappings TSAN
-// runtime for AArch64 uses an external memory read (vmaSize) to select which
-// mapping to use. Although slower, it make a same instrumented binary run on
-// multiple kernels.
-
/*
C/C++ on linux/aarch64 (39-bit VMA)
0000 0010 00 - 0100 0000 00: main binary
@@ -181,7 +171,7 @@ C/C++ on linux/aarch64 (39-bit VMA)
7c00 0000 00 - 7d00 0000 00: heap
7d00 0000 00 - 7fff ffff ff: modules and main thread stack
*/
-struct Mapping39 {
+struct MappingAarch64_39 {
static const uptr kLoAppMemBeg = 0x0000001000ull;
static const uptr kLoAppMemEnd = 0x0100000000ull;
static const uptr kShadowBeg = 0x0800000000ull;
@@ -196,8 +186,9 @@ struct Mapping39 {
static const uptr kHeapMemEnd = 0x7d00000000ull;
static const uptr kHiAppMemBeg = 0x7e00000000ull;
static const uptr kHiAppMemEnd = 0x7fffffffffull;
- static const uptr kAppMemMsk = 0x7800000000ull;
- static const uptr kAppMemXor = 0x0200000000ull;
+ static const uptr kShadowMsk = 0x7800000000ull;
+ static const uptr kShadowXor = 0x0200000000ull;
+ static const uptr kShadowAdd = 0x0000000000ull;
static const uptr kVdsoBeg = 0x7f00000000ull;
};
@@ -216,7 +207,8 @@ C/C++ on linux/aarch64 (42-bit VMA)
3e000 0000 00 - 3f000 0000 00: heap
3f000 0000 00 - 3ffff ffff ff: modules and main thread stack
*/
-struct Mapping42 {
+struct MappingAarch64_42 {
+ static const uptr kBroken = kBrokenReverseMapping;
static const uptr kLoAppMemBeg = 0x00000001000ull;
static const uptr kLoAppMemEnd = 0x01000000000ull;
static const uptr kShadowBeg = 0x10000000000ull;
@@ -231,12 +223,13 @@ struct Mapping42 {
static const uptr kHeapMemEnd = 0x3f000000000ull;
static const uptr kHiAppMemBeg = 0x3f000000000ull;
static const uptr kHiAppMemEnd = 0x3ffffffffffull;
- static const uptr kAppMemMsk = 0x3c000000000ull;
- static const uptr kAppMemXor = 0x04000000000ull;
+ static const uptr kShadowMsk = 0x3c000000000ull;
+ static const uptr kShadowXor = 0x04000000000ull;
+ static const uptr kShadowAdd = 0x00000000000ull;
static const uptr kVdsoBeg = 0x37f00000000ull;
};
-struct Mapping48 {
+struct MappingAarch64_48 {
static const uptr kLoAppMemBeg = 0x0000000001000ull;
static const uptr kLoAppMemEnd = 0x0000200000000ull;
static const uptr kShadowBeg = 0x0002000000000ull;
@@ -251,22 +244,12 @@ struct Mapping48 {
static const uptr kHeapMemEnd = 0x0ffff00000000ull;
static const uptr kHiAppMemBeg = 0x0ffff00000000ull;
static const uptr kHiAppMemEnd = 0x1000000000000ull;
- static const uptr kAppMemMsk = 0x0fff800000000ull;
- static const uptr kAppMemXor = 0x0000800000000ull;
+ static const uptr kShadowMsk = 0x0fff800000000ull;
+ static const uptr kShadowXor = 0x0000800000000ull;
+ static const uptr kShadowAdd = 0x0000000000000ull;
static const uptr kVdsoBeg = 0xffff000000000ull;
};
-// Indicates the runtime will define the memory regions at runtime.
-#define TSAN_RUNTIME_VMA 1
-// Indicates that mapping defines a mid range memory segment.
-#define TSAN_MID_APP_RANGE 1
-#elif defined(__powerpc64__)
-// PPC64 supports multiple VMA which leads to multiple address transformation
-// functions. To support these multiple VMAS transformations and mappings TSAN
-// runtime for PPC64 uses an external memory read (vmaSize) to select which
-// mapping to use. Although slower, it make a same instrumented binary run on
-// multiple kernels.
-
/*
C/C++ on linux/powerpc64 (44-bit VMA)
0000 0000 0100 - 0001 0000 0000: main binary
@@ -281,7 +264,9 @@ C/C++ on linux/powerpc64 (44-bit VMA)
0f50 0000 0000 - 0f60 0000 0000: -
0f60 0000 0000 - 1000 0000 0000: modules and main thread stack
*/
-struct Mapping44 {
+struct MappingPPC64_44 {
+ static const uptr kBroken =
+ kBrokenMapping | kBrokenReverseMapping | kBrokenLinearity;
static const uptr kMetaShadowBeg = 0x0b0000000000ull;
static const uptr kMetaShadowEnd = 0x0d0000000000ull;
static const uptr kTraceMemBeg = 0x0d0000000000ull;
@@ -294,9 +279,12 @@ struct Mapping44 {
static const uptr kHeapMemEnd = 0x0f5000000000ull;
static const uptr kHiAppMemBeg = 0x0f6000000000ull;
static const uptr kHiAppMemEnd = 0x100000000000ull; // 44 bits
- static const uptr kAppMemMsk = 0x0f0000000000ull;
- static const uptr kAppMemXor = 0x002100000000ull;
+ static const uptr kShadowMsk = 0x0f0000000000ull;
+ static const uptr kShadowXor = 0x002100000000ull;
+ static const uptr kShadowAdd = 0x000000000000ull;
static const uptr kVdsoBeg = 0x3c0000000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
};
/*
@@ -313,7 +301,7 @@ C/C++ on linux/powerpc64 (46-bit VMA)
3e00 0000 0000 - 3e80 0000 0000: -
3e80 0000 0000 - 4000 0000 0000: modules and main thread stack
*/
-struct Mapping46 {
+struct MappingPPC64_46 {
static const uptr kMetaShadowBeg = 0x100000000000ull;
static const uptr kMetaShadowEnd = 0x200000000000ull;
static const uptr kTraceMemBeg = 0x200000000000ull;
@@ -326,9 +314,12 @@ struct Mapping46 {
static const uptr kLoAppMemEnd = 0x010000000000ull;
static const uptr kHiAppMemBeg = 0x3e8000000000ull;
static const uptr kHiAppMemEnd = 0x400000000000ull; // 46 bits
- static const uptr kAppMemMsk = 0x3c0000000000ull;
- static const uptr kAppMemXor = 0x020000000000ull;
+ static const uptr kShadowMsk = 0x3c0000000000ull;
+ static const uptr kShadowXor = 0x020000000000ull;
+ static const uptr kShadowAdd = 0x000000000000ull;
static const uptr kVdsoBeg = 0x7800000000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
};
/*
@@ -345,7 +336,7 @@ C/C++ on linux/powerpc64 (47-bit VMA)
7e00 0000 0000 - 7e80 0000 0000: -
7e80 0000 0000 - 8000 0000 0000: modules and main thread stack
*/
-struct Mapping47 {
+struct MappingPPC64_47 {
static const uptr kMetaShadowBeg = 0x100000000000ull;
static const uptr kMetaShadowEnd = 0x200000000000ull;
static const uptr kTraceMemBeg = 0x200000000000ull;
@@ -358,14 +349,14 @@ struct Mapping47 {
static const uptr kLoAppMemEnd = 0x010000000000ull;
static const uptr kHiAppMemBeg = 0x7e8000000000ull;
static const uptr kHiAppMemEnd = 0x800000000000ull; // 47 bits
- static const uptr kAppMemMsk = 0x7c0000000000ull;
- static const uptr kAppMemXor = 0x020000000000ull;
+ static const uptr kShadowMsk = 0x7c0000000000ull;
+ static const uptr kShadowXor = 0x020000000000ull;
+ static const uptr kShadowAdd = 0x000000000000ull;
static const uptr kVdsoBeg = 0x7800000000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
};
-// Indicates the runtime will define the memory regions at runtime.
-#define TSAN_RUNTIME_VMA 1
-#elif defined(__s390x__)
/*
C/C++ on linux/s390x
While the kernel provides a 64-bit address space, we have to restrict ourselves
@@ -380,7 +371,7 @@ a000 0000 0000 - b000 0000 0000: traces - 16TiB (max history * 128k threads)
b000 0000 0000 - be00 0000 0000: -
be00 0000 0000 - c000 0000 0000: heap - 2TiB (max supported by the allocator)
*/
-struct Mapping {
+struct MappingS390x {
static const uptr kMetaShadowBeg = 0x900000000000ull;
static const uptr kMetaShadowEnd = 0x980000000000ull;
static const uptr kTraceMemBeg = 0xa00000000000ull;
@@ -393,13 +384,13 @@ struct Mapping {
static const uptr kLoAppMemEnd = 0x0e0000000000ull;
static const uptr kHiAppMemBeg = 0xc00000004000ull;
static const uptr kHiAppMemEnd = 0xc00000004000ull;
- static const uptr kAppMemMsk = 0xb00000000000ull;
- static const uptr kAppMemXor = 0x100000000000ull;
+ static const uptr kShadowMsk = 0xb00000000000ull;
+ static const uptr kShadowXor = 0x100000000000ull;
+ static const uptr kShadowAdd = 0x000000000000ull;
static const uptr kVdsoBeg = 0xfffffffff000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
};
-#endif
-
-#elif SANITIZER_GO && !SANITIZER_WINDOWS && HAS_48_BIT_ADDRESS_SPACE
/* Go on linux, darwin and freebsd on x86_64
0000 0000 1000 - 0000 1000 0000: executable
@@ -414,46 +405,59 @@ struct Mapping {
6200 0000 0000 - 8000 0000 0000: -
*/
-struct Mapping {
+struct MappingGo48 {
static const uptr kMetaShadowBeg = 0x300000000000ull;
static const uptr kMetaShadowEnd = 0x400000000000ull;
static const uptr kTraceMemBeg = 0x600000000000ull;
static const uptr kTraceMemEnd = 0x620000000000ull;
static const uptr kShadowBeg = 0x200000000000ull;
static const uptr kShadowEnd = 0x238000000000ull;
- static const uptr kAppMemBeg = 0x000000001000ull;
- static const uptr kAppMemEnd = 0x00e000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x00e000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+ static const uptr kHiAppMemBeg = 0;
+ static const uptr kHiAppMemEnd = 0;
+ static const uptr kHeapMemBeg = 0;
+ static const uptr kHeapMemEnd = 0;
+ static const uptr kVdsoBeg = 0;
+ static const uptr kShadowMsk = 0;
+ static const uptr kShadowXor = 0;
+ static const uptr kShadowAdd = 0x200000000000ull;
};
-#elif SANITIZER_GO && SANITIZER_WINDOWS
-
/* Go on windows
0000 0000 1000 - 0000 1000 0000: executable
0000 1000 0000 - 00f8 0000 0000: -
00c0 0000 0000 - 00e0 0000 0000: heap
00e0 0000 0000 - 0100 0000 0000: -
0100 0000 0000 - 0500 0000 0000: shadow
-0500 0000 0000 - 0560 0000 0000: -
-0560 0000 0000 - 0760 0000 0000: traces
-0760 0000 0000 - 07d0 0000 0000: metainfo (memory blocks and sync objects)
+0500 0000 0000 - 0700 0000 0000: traces
+0700 0000 0000 - 0770 0000 0000: metainfo (memory blocks and sync objects)
07d0 0000 0000 - 8000 0000 0000: -
*/
-struct Mapping {
- static const uptr kMetaShadowBeg = 0x076000000000ull;
- static const uptr kMetaShadowEnd = 0x07d000000000ull;
- static const uptr kTraceMemBeg = 0x056000000000ull;
- static const uptr kTraceMemEnd = 0x076000000000ull;
+struct MappingGoWindows {
+ static const uptr kMetaShadowBeg = 0x070000000000ull;
+ static const uptr kMetaShadowEnd = 0x077000000000ull;
+ static const uptr kTraceMemBeg = 0x050000000000ull;
+ static const uptr kTraceMemEnd = 0x070000000000ull;
static const uptr kShadowBeg = 0x010000000000ull;
static const uptr kShadowEnd = 0x050000000000ull;
- static const uptr kAppMemBeg = 0x000000001000ull;
- static const uptr kAppMemEnd = 0x00e000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x00e000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+ static const uptr kHiAppMemBeg = 0;
+ static const uptr kHiAppMemEnd = 0;
+ static const uptr kHeapMemBeg = 0;
+ static const uptr kHeapMemEnd = 0;
+ static const uptr kVdsoBeg = 0;
+ static const uptr kShadowMsk = 0;
+ static const uptr kShadowXor = 0;
+ static const uptr kShadowAdd = 0x010000000000ull;
};
-#elif SANITIZER_GO && defined(__powerpc64__)
-
-/* Only Mapping46 and Mapping47 are currently supported for powercp64 on Go. */
-
/* Go on linux/powerpc64 (46-bit VMA)
0000 0000 1000 - 0000 1000 0000: executable
0000 1000 0000 - 00c0 0000 0000: -
@@ -467,15 +471,25 @@ struct Mapping {
3800 0000 0000 - 4000 0000 0000: -
*/
-struct Mapping46 {
+struct MappingGoPPC64_46 {
static const uptr kMetaShadowBeg = 0x240000000000ull;
static const uptr kMetaShadowEnd = 0x340000000000ull;
static const uptr kTraceMemBeg = 0x360000000000ull;
static const uptr kTraceMemEnd = 0x380000000000ull;
static const uptr kShadowBeg = 0x200000000000ull;
static const uptr kShadowEnd = 0x238000000000ull;
- static const uptr kAppMemBeg = 0x000000001000ull;
- static const uptr kAppMemEnd = 0x00e000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x00e000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+ static const uptr kHiAppMemBeg = 0;
+ static const uptr kHiAppMemEnd = 0;
+ static const uptr kHeapMemBeg = 0;
+ static const uptr kHeapMemEnd = 0;
+ static const uptr kVdsoBeg = 0;
+ static const uptr kShadowMsk = 0;
+ static const uptr kShadowXor = 0;
+ static const uptr kShadowAdd = 0x200000000000ull;
};
/* Go on linux/powerpc64 (47-bit VMA)
@@ -491,21 +505,27 @@ struct Mapping46 {
6200 0000 0000 - 8000 0000 0000: -
*/
-struct Mapping47 {
+struct MappingGoPPC64_47 {
static const uptr kMetaShadowBeg = 0x300000000000ull;
static const uptr kMetaShadowEnd = 0x400000000000ull;
static const uptr kTraceMemBeg = 0x600000000000ull;
static const uptr kTraceMemEnd = 0x620000000000ull;
static const uptr kShadowBeg = 0x200000000000ull;
static const uptr kShadowEnd = 0x300000000000ull;
- static const uptr kAppMemBeg = 0x000000001000ull;
- static const uptr kAppMemEnd = 0x00e000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x00e000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+ static const uptr kHiAppMemBeg = 0;
+ static const uptr kHiAppMemEnd = 0;
+ static const uptr kHeapMemBeg = 0;
+ static const uptr kHeapMemEnd = 0;
+ static const uptr kVdsoBeg = 0;
+ static const uptr kShadowMsk = 0;
+ static const uptr kShadowXor = 0;
+ static const uptr kShadowAdd = 0x200000000000ull;
};
-#define TSAN_RUNTIME_VMA 1
-
-#elif SANITIZER_GO && defined(__aarch64__)
-
/* Go on linux/aarch64 (48-bit VMA) and darwin/aarch64 (47-bit VMA)
0000 0000 1000 - 0000 1000 0000: executable
0000 1000 0000 - 00c0 0000 0000: -
@@ -518,22 +538,27 @@ struct Mapping47 {
6000 0000 0000 - 6200 0000 0000: traces
6200 0000 0000 - 8000 0000 0000: -
*/
-
-struct Mapping {
+struct MappingGoAarch64 {
static const uptr kMetaShadowBeg = 0x300000000000ull;
static const uptr kMetaShadowEnd = 0x400000000000ull;
static const uptr kTraceMemBeg = 0x600000000000ull;
static const uptr kTraceMemEnd = 0x620000000000ull;
static const uptr kShadowBeg = 0x200000000000ull;
static const uptr kShadowEnd = 0x300000000000ull;
- static const uptr kAppMemBeg = 0x000000001000ull;
- static const uptr kAppMemEnd = 0x00e000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x00e000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+ static const uptr kHiAppMemBeg = 0;
+ static const uptr kHiAppMemEnd = 0;
+ static const uptr kHeapMemBeg = 0;
+ static const uptr kHeapMemEnd = 0;
+ static const uptr kVdsoBeg = 0;
+ static const uptr kShadowMsk = 0;
+ static const uptr kShadowXor = 0;
+ static const uptr kShadowAdd = 0x200000000000ull;
};
-// Indicates the runtime will define the memory regions at runtime.
-#define TSAN_RUNTIME_VMA 1
-
-#elif SANITIZER_GO && defined(__mips64)
/*
Go on linux/mips64 (47-bit VMA)
0000 0000 1000 - 0000 1000 0000: executable
@@ -547,20 +572,27 @@ Go on linux/mips64 (47-bit VMA)
6000 0000 0000 - 6200 0000 0000: traces
6200 0000 0000 - 8000 0000 0000: -
*/
-struct Mapping47 {
+struct MappingGoMips64_47 {
static const uptr kMetaShadowBeg = 0x300000000000ull;
static const uptr kMetaShadowEnd = 0x400000000000ull;
static const uptr kTraceMemBeg = 0x600000000000ull;
static const uptr kTraceMemEnd = 0x620000000000ull;
static const uptr kShadowBeg = 0x200000000000ull;
static const uptr kShadowEnd = 0x300000000000ull;
- static const uptr kAppMemBeg = 0x000000001000ull;
- static const uptr kAppMemEnd = 0x00e000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x00e000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+ static const uptr kHiAppMemBeg = 0;
+ static const uptr kHiAppMemEnd = 0;
+ static const uptr kHeapMemBeg = 0;
+ static const uptr kHeapMemEnd = 0;
+ static const uptr kVdsoBeg = 0;
+ static const uptr kShadowMsk = 0;
+ static const uptr kShadowXor = 0;
+ static const uptr kShadowAdd = 0x200000000000ull;
};
-#define TSAN_RUNTIME_VMA 1
-
-#elif SANITIZER_GO && defined(__s390x__)
/*
Go on linux/s390x
0000 0000 1000 - 1000 0000 0000: executable and heap - 16 TiB
@@ -571,622 +603,367 @@ Go on linux/s390x
9800 0000 0000 - a000 0000 0000: -
a000 0000 0000 - b000 0000 0000: traces - 16TiB (max history * 128k threads)
*/
-struct Mapping {
+struct MappingGoS390x {
static const uptr kMetaShadowBeg = 0x900000000000ull;
static const uptr kMetaShadowEnd = 0x980000000000ull;
static const uptr kTraceMemBeg = 0xa00000000000ull;
static const uptr kTraceMemEnd = 0xb00000000000ull;
static const uptr kShadowBeg = 0x400000000000ull;
static const uptr kShadowEnd = 0x800000000000ull;
- static const uptr kAppMemBeg = 0x000000001000ull;
- static const uptr kAppMemEnd = 0x100000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x100000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+ static const uptr kHiAppMemBeg = 0;
+ static const uptr kHiAppMemEnd = 0;
+ static const uptr kHeapMemBeg = 0;
+ static const uptr kHeapMemEnd = 0;
+ static const uptr kVdsoBeg = 0;
+ static const uptr kShadowMsk = 0;
+ static const uptr kShadowXor = 0;
+ static const uptr kShadowAdd = 0x400000000000ull;
};
-#else
-# error "Unknown platform"
-#endif
-
-
-#ifdef TSAN_RUNTIME_VMA
extern uptr vmaSize;
-#endif
-
-
-enum MappingType {
- MAPPING_LO_APP_BEG,
- MAPPING_LO_APP_END,
- MAPPING_HI_APP_BEG,
- MAPPING_HI_APP_END,
-#ifdef TSAN_MID_APP_RANGE
- MAPPING_MID_APP_BEG,
- MAPPING_MID_APP_END,
-#endif
- MAPPING_HEAP_BEG,
- MAPPING_HEAP_END,
- MAPPING_APP_BEG,
- MAPPING_APP_END,
- MAPPING_SHADOW_BEG,
- MAPPING_SHADOW_END,
- MAPPING_META_SHADOW_BEG,
- MAPPING_META_SHADOW_END,
- MAPPING_TRACE_BEG,
- MAPPING_TRACE_END,
- MAPPING_VDSO_BEG,
-};
-
-template<typename Mapping, int Type>
-uptr MappingImpl(void) {
- switch (Type) {
-#if !SANITIZER_GO
- case MAPPING_LO_APP_BEG: return Mapping::kLoAppMemBeg;
- case MAPPING_LO_APP_END: return Mapping::kLoAppMemEnd;
-# ifdef TSAN_MID_APP_RANGE
- case MAPPING_MID_APP_BEG: return Mapping::kMidAppMemBeg;
- case MAPPING_MID_APP_END: return Mapping::kMidAppMemEnd;
-# endif
- case MAPPING_HI_APP_BEG: return Mapping::kHiAppMemBeg;
- case MAPPING_HI_APP_END: return Mapping::kHiAppMemEnd;
- case MAPPING_HEAP_BEG: return Mapping::kHeapMemBeg;
- case MAPPING_HEAP_END: return Mapping::kHeapMemEnd;
- case MAPPING_VDSO_BEG: return Mapping::kVdsoBeg;
-#else
- case MAPPING_APP_BEG: return Mapping::kAppMemBeg;
- case MAPPING_APP_END: return Mapping::kAppMemEnd;
-#endif
- case MAPPING_SHADOW_BEG: return Mapping::kShadowBeg;
- case MAPPING_SHADOW_END: return Mapping::kShadowEnd;
- case MAPPING_META_SHADOW_BEG: return Mapping::kMetaShadowBeg;
- case MAPPING_META_SHADOW_END: return Mapping::kMetaShadowEnd;
- case MAPPING_TRACE_BEG: return Mapping::kTraceMemBeg;
- case MAPPING_TRACE_END: return Mapping::kTraceMemEnd;
- }
-}
-template<int Type>
-uptr MappingArchImpl(void) {
-#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
+template <typename Func, typename Arg>
+ALWAYS_INLINE auto SelectMapping(Arg arg) {
+#if SANITIZER_GO
+# if defined(__powerpc64__)
switch (vmaSize) {
- case 39: return MappingImpl<Mapping39, Type>();
- case 42: return MappingImpl<Mapping42, Type>();
- case 48: return MappingImpl<Mapping48, Type>();
+ case 46:
+ return Func::template Apply<MappingGoPPC64_46>(arg);
+ case 47:
+ return Func::template Apply<MappingGoPPC64_47>(arg);
}
- DCHECK(0);
- return 0;
-#elif defined(__powerpc64__)
+# elif defined(__mips64)
+ return Func::template Apply<MappingGoMips64_47>(arg);
+# elif defined(__s390x__)
+ return Func::template Apply<MappingGoS390x>(arg);
+# elif defined(__aarch64__)
+ return Func::template Apply<MappingGoAarch64>(arg);
+# elif SANITIZER_WINDOWS
+ return Func::template Apply<MappingGoWindows>(arg);
+# else
+ return Func::template Apply<MappingGo48>(arg);
+# endif
+#else // SANITIZER_GO
+# if defined(__x86_64__) || SANITIZER_IOSSIM || SANITIZER_MAC && !SANITIZER_IOS
+ return Func::template Apply<Mapping48AddressSpace>(arg);
+# elif defined(__aarch64__) && defined(__APPLE__)
+ return Func::template Apply<MappingAppleAarch64>(arg);
+# elif defined(__aarch64__) && !defined(__APPLE__)
switch (vmaSize) {
-#if !SANITIZER_GO
- case 44: return MappingImpl<Mapping44, Type>();
-#endif
- case 46: return MappingImpl<Mapping46, Type>();
- case 47: return MappingImpl<Mapping47, Type>();
+ case 39:
+ return Func::template Apply<MappingAarch64_39>(arg);
+ case 42:
+ return Func::template Apply<MappingAarch64_42>(arg);
+ case 48:
+ return Func::template Apply<MappingAarch64_48>(arg);
}
- DCHECK(0);
- return 0;
-#elif defined(__mips64)
+# elif defined(__powerpc64__)
switch (vmaSize) {
-#if !SANITIZER_GO
- case 40: return MappingImpl<Mapping40, Type>();
-#else
- case 47: return MappingImpl<Mapping47, Type>();
-#endif
+ case 44:
+ return Func::template Apply<MappingPPC64_44>(arg);
+ case 46:
+ return Func::template Apply<MappingPPC64_46>(arg);
+ case 47:
+ return Func::template Apply<MappingPPC64_47>(arg);
}
- DCHECK(0);
- return 0;
-#else
- return MappingImpl<Mapping, Type>();
-#endif
+# elif defined(__mips64)
+ return Func::template Apply<MappingMips64_40>(arg);
+# elif defined(__s390x__)
+ return Func::template Apply<MappingS390x>(arg);
+# else
+# error "unsupported platform"
+# endif
+#endif
+ Die();
+}
+
+template <typename Func>
+void ForEachMapping() {
+ Func::template Apply<Mapping48AddressSpace>();
+ Func::template Apply<MappingMips64_40>();
+ Func::template Apply<MappingAppleAarch64>();
+ Func::template Apply<MappingAarch64_39>();
+ Func::template Apply<MappingAarch64_42>();
+ Func::template Apply<MappingAarch64_48>();
+ Func::template Apply<MappingPPC64_44>();
+ Func::template Apply<MappingPPC64_46>();
+ Func::template Apply<MappingPPC64_47>();
+ Func::template Apply<MappingS390x>();
+ Func::template Apply<MappingGo48>();
+ Func::template Apply<MappingGoWindows>();
+ Func::template Apply<MappingGoPPC64_46>();
+ Func::template Apply<MappingGoPPC64_47>();
+ Func::template Apply<MappingGoAarch64>();
+ Func::template Apply<MappingGoMips64_47>();
+ Func::template Apply<MappingGoS390x>();
}
-#if !SANITIZER_GO
-ALWAYS_INLINE
-uptr LoAppMemBeg(void) {
- return MappingArchImpl<MAPPING_LO_APP_BEG>();
-}
-ALWAYS_INLINE
-uptr LoAppMemEnd(void) {
- return MappingArchImpl<MAPPING_LO_APP_END>();
-}
+enum MappingType {
+ kLoAppMemBeg,
+ kLoAppMemEnd,
+ kHiAppMemBeg,
+ kHiAppMemEnd,
+ kMidAppMemBeg,
+ kMidAppMemEnd,
+ kHeapMemBeg,
+ kHeapMemEnd,
+ kShadowBeg,
+ kShadowEnd,
+ kMetaShadowBeg,
+ kMetaShadowEnd,
+ kTraceMemBeg,
+ kTraceMemEnd,
+ kVdsoBeg,
+};
-#ifdef TSAN_MID_APP_RANGE
-ALWAYS_INLINE
-uptr MidAppMemBeg(void) {
- return MappingArchImpl<MAPPING_MID_APP_BEG>();
-}
-ALWAYS_INLINE
-uptr MidAppMemEnd(void) {
- return MappingArchImpl<MAPPING_MID_APP_END>();
-}
-#endif
+struct MappingField {
+ template <typename Mapping>
+ static uptr Apply(MappingType type) {
+ switch (type) {
+ case kLoAppMemBeg:
+ return Mapping::kLoAppMemBeg;
+ case kLoAppMemEnd:
+ return Mapping::kLoAppMemEnd;
+ case kMidAppMemBeg:
+ return Mapping::kMidAppMemBeg;
+ case kMidAppMemEnd:
+ return Mapping::kMidAppMemEnd;
+ case kHiAppMemBeg:
+ return Mapping::kHiAppMemBeg;
+ case kHiAppMemEnd:
+ return Mapping::kHiAppMemEnd;
+ case kHeapMemBeg:
+ return Mapping::kHeapMemBeg;
+ case kHeapMemEnd:
+ return Mapping::kHeapMemEnd;
+ case kVdsoBeg:
+ return Mapping::kVdsoBeg;
+ case kShadowBeg:
+ return Mapping::kShadowBeg;
+ case kShadowEnd:
+ return Mapping::kShadowEnd;
+ case kMetaShadowBeg:
+ return Mapping::kMetaShadowBeg;
+ case kMetaShadowEnd:
+ return Mapping::kMetaShadowEnd;
+ case kTraceMemBeg:
+ return Mapping::kTraceMemBeg;
+ case kTraceMemEnd:
+ return Mapping::kTraceMemEnd;
+ }
+ Die();
+ }
+};
ALWAYS_INLINE
-uptr HeapMemBeg(void) {
- return MappingArchImpl<MAPPING_HEAP_BEG>();
-}
+uptr LoAppMemBeg(void) { return SelectMapping<MappingField>(kLoAppMemBeg); }
ALWAYS_INLINE
-uptr HeapMemEnd(void) {
- return MappingArchImpl<MAPPING_HEAP_END>();
-}
+uptr LoAppMemEnd(void) { return SelectMapping<MappingField>(kLoAppMemEnd); }
ALWAYS_INLINE
-uptr HiAppMemBeg(void) {
- return MappingArchImpl<MAPPING_HI_APP_BEG>();
-}
+uptr MidAppMemBeg(void) { return SelectMapping<MappingField>(kMidAppMemBeg); }
ALWAYS_INLINE
-uptr HiAppMemEnd(void) {
- return MappingArchImpl<MAPPING_HI_APP_END>();
-}
+uptr MidAppMemEnd(void) { return SelectMapping<MappingField>(kMidAppMemEnd); }
ALWAYS_INLINE
-uptr VdsoBeg(void) {
- return MappingArchImpl<MAPPING_VDSO_BEG>();
-}
-
-#else
+uptr HeapMemBeg(void) { return SelectMapping<MappingField>(kHeapMemBeg); }
+ALWAYS_INLINE
+uptr HeapMemEnd(void) { return SelectMapping<MappingField>(kHeapMemEnd); }
ALWAYS_INLINE
-uptr AppMemBeg(void) {
- return MappingArchImpl<MAPPING_APP_BEG>();
-}
+uptr HiAppMemBeg(void) { return SelectMapping<MappingField>(kHiAppMemBeg); }
ALWAYS_INLINE
-uptr AppMemEnd(void) {
- return MappingArchImpl<MAPPING_APP_END>();
-}
-
-#endif
+uptr HiAppMemEnd(void) { return SelectMapping<MappingField>(kHiAppMemEnd); }
-static inline
-bool GetUserRegion(int i, uptr *start, uptr *end) {
- switch (i) {
- default:
- return false;
-#if !SANITIZER_GO
- case 0:
- *start = LoAppMemBeg();
- *end = LoAppMemEnd();
- return true;
- case 1:
- *start = HiAppMemBeg();
- *end = HiAppMemEnd();
- return true;
- case 2:
- *start = HeapMemBeg();
- *end = HeapMemEnd();
- return true;
-# ifdef TSAN_MID_APP_RANGE
- case 3:
- *start = MidAppMemBeg();
- *end = MidAppMemEnd();
- return true;
-# endif
-#else
- case 0:
- *start = AppMemBeg();
- *end = AppMemEnd();
- return true;
-#endif
- }
-}
+ALWAYS_INLINE
+uptr VdsoBeg(void) { return SelectMapping<MappingField>(kVdsoBeg); }
ALWAYS_INLINE
-uptr ShadowBeg(void) {
- return MappingArchImpl<MAPPING_SHADOW_BEG>();
-}
+uptr ShadowBeg(void) { return SelectMapping<MappingField>(kShadowBeg); }
ALWAYS_INLINE
-uptr ShadowEnd(void) {
- return MappingArchImpl<MAPPING_SHADOW_END>();
-}
+uptr ShadowEnd(void) { return SelectMapping<MappingField>(kShadowEnd); }
ALWAYS_INLINE
-uptr MetaShadowBeg(void) {
- return MappingArchImpl<MAPPING_META_SHADOW_BEG>();
-}
+uptr MetaShadowBeg(void) { return SelectMapping<MappingField>(kMetaShadowBeg); }
ALWAYS_INLINE
-uptr MetaShadowEnd(void) {
- return MappingArchImpl<MAPPING_META_SHADOW_END>();
-}
+uptr MetaShadowEnd(void) { return SelectMapping<MappingField>(kMetaShadowEnd); }
ALWAYS_INLINE
-uptr TraceMemBeg(void) {
- return MappingArchImpl<MAPPING_TRACE_BEG>();
-}
+uptr TraceMemBeg(void) { return SelectMapping<MappingField>(kTraceMemBeg); }
ALWAYS_INLINE
-uptr TraceMemEnd(void) {
- return MappingArchImpl<MAPPING_TRACE_END>();
-}
-
+uptr TraceMemEnd(void) { return SelectMapping<MappingField>(kTraceMemEnd); }
-template<typename Mapping>
-bool IsAppMemImpl(uptr mem) {
-#if !SANITIZER_GO
+struct IsAppMemImpl {
+ template <typename Mapping>
+ static bool Apply(uptr mem) {
return (mem >= Mapping::kHeapMemBeg && mem < Mapping::kHeapMemEnd) ||
-# ifdef TSAN_MID_APP_RANGE
(mem >= Mapping::kMidAppMemBeg && mem < Mapping::kMidAppMemEnd) ||
-# endif
(mem >= Mapping::kLoAppMemBeg && mem < Mapping::kLoAppMemEnd) ||
(mem >= Mapping::kHiAppMemBeg && mem < Mapping::kHiAppMemEnd);
-#else
- return mem >= Mapping::kAppMemBeg && mem < Mapping::kAppMemEnd;
-#endif
-}
-
-ALWAYS_INLINE
-bool IsAppMem(uptr mem) {
-#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
- switch (vmaSize) {
- case 39: return IsAppMemImpl<Mapping39>(mem);
- case 42: return IsAppMemImpl<Mapping42>(mem);
- case 48: return IsAppMemImpl<Mapping48>(mem);
- }
- DCHECK(0);
- return false;
-#elif defined(__powerpc64__)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 44: return IsAppMemImpl<Mapping44>(mem);
-#endif
- case 46: return IsAppMemImpl<Mapping46>(mem);
- case 47: return IsAppMemImpl<Mapping47>(mem);
}
- DCHECK(0);
- return false;
-#elif defined(__mips64)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 40: return IsAppMemImpl<Mapping40>(mem);
-#else
- case 47: return IsAppMemImpl<Mapping47>(mem);
-#endif
- }
- DCHECK(0);
- return false;
-#else
- return IsAppMemImpl<Mapping>(mem);
-#endif
-}
+};
+ALWAYS_INLINE
+bool IsAppMem(uptr mem) { return SelectMapping<IsAppMemImpl>(mem); }
-template<typename Mapping>
-bool IsShadowMemImpl(uptr mem) {
- return mem >= Mapping::kShadowBeg && mem <= Mapping::kShadowEnd;
-}
+struct IsShadowMemImpl {
+ template <typename Mapping>
+ static bool Apply(uptr mem) {
+ return mem >= Mapping::kShadowBeg && mem <= Mapping::kShadowEnd;
+ }
+};
ALWAYS_INLINE
-bool IsShadowMem(uptr mem) {
-#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
- switch (vmaSize) {
- case 39: return IsShadowMemImpl<Mapping39>(mem);
- case 42: return IsShadowMemImpl<Mapping42>(mem);
- case 48: return IsShadowMemImpl<Mapping48>(mem);
- }
- DCHECK(0);
- return false;
-#elif defined(__powerpc64__)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 44: return IsShadowMemImpl<Mapping44>(mem);
-#endif
- case 46: return IsShadowMemImpl<Mapping46>(mem);
- case 47: return IsShadowMemImpl<Mapping47>(mem);
- }
- DCHECK(0);
- return false;
-#elif defined(__mips64)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 40: return IsShadowMemImpl<Mapping40>(mem);
-#else
- case 47: return IsShadowMemImpl<Mapping47>(mem);
-#endif
- }
- DCHECK(0);
- return false;
-#else
- return IsShadowMemImpl<Mapping>(mem);
-#endif
+bool IsShadowMem(RawShadow *p) {
+ return SelectMapping<IsShadowMemImpl>(reinterpret_cast<uptr>(p));
}
-
-template<typename Mapping>
-bool IsMetaMemImpl(uptr mem) {
- return mem >= Mapping::kMetaShadowBeg && mem <= Mapping::kMetaShadowEnd;
-}
+struct IsMetaMemImpl {
+ template <typename Mapping>
+ static bool Apply(uptr mem) {
+ return mem >= Mapping::kMetaShadowBeg && mem <= Mapping::kMetaShadowEnd;
+ }
+};
ALWAYS_INLINE
-bool IsMetaMem(uptr mem) {
-#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
- switch (vmaSize) {
- case 39: return IsMetaMemImpl<Mapping39>(mem);
- case 42: return IsMetaMemImpl<Mapping42>(mem);
- case 48: return IsMetaMemImpl<Mapping48>(mem);
- }
- DCHECK(0);
- return false;
-#elif defined(__powerpc64__)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 44: return IsMetaMemImpl<Mapping44>(mem);
-#endif
- case 46: return IsMetaMemImpl<Mapping46>(mem);
- case 47: return IsMetaMemImpl<Mapping47>(mem);
+bool IsMetaMem(const u32 *p) {
+ return SelectMapping<IsMetaMemImpl>(reinterpret_cast<uptr>(p));
+}
+
+struct MemToShadowImpl {
+ template <typename Mapping>
+ static uptr Apply(uptr x) {
+ DCHECK(IsAppMemImpl::Apply<Mapping>(x));
+ return (((x) & ~(Mapping::kShadowMsk | (kShadowCell - 1))) ^
+ Mapping::kShadowXor) *
+ kShadowMultiplier +
+ Mapping::kShadowAdd;
}
- DCHECK(0);
- return false;
-#elif defined(__mips64)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 40: return IsMetaMemImpl<Mapping40>(mem);
-#else
- case 47: return IsMetaMemImpl<Mapping47>(mem);
-#endif
- }
- DCHECK(0);
- return false;
-#else
- return IsMetaMemImpl<Mapping>(mem);
-#endif
-}
-
-
-template<typename Mapping>
-uptr MemToShadowImpl(uptr x) {
- DCHECK(IsAppMem(x));
-#if !SANITIZER_GO
- return (((x) & ~(Mapping::kAppMemMsk | (kShadowCell - 1)))
- ^ Mapping::kAppMemXor) * kShadowCnt;
-#else
-# ifndef SANITIZER_WINDOWS
- return ((x & ~(kShadowCell - 1)) * kShadowCnt) | Mapping::kShadowBeg;
-# else
- return ((x & ~(kShadowCell - 1)) * kShadowCnt) + Mapping::kShadowBeg;
-# endif
-#endif
-}
+};
ALWAYS_INLINE
-uptr MemToShadow(uptr x) {
-#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
- switch (vmaSize) {
- case 39: return MemToShadowImpl<Mapping39>(x);
- case 42: return MemToShadowImpl<Mapping42>(x);
- case 48: return MemToShadowImpl<Mapping48>(x);
- }
- DCHECK(0);
- return 0;
-#elif defined(__powerpc64__)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 44: return MemToShadowImpl<Mapping44>(x);
-#endif
- case 46: return MemToShadowImpl<Mapping46>(x);
- case 47: return MemToShadowImpl<Mapping47>(x);
- }
- DCHECK(0);
- return 0;
-#elif defined(__mips64)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 40: return MemToShadowImpl<Mapping40>(x);
-#else
- case 47: return MemToShadowImpl<Mapping47>(x);
-#endif
- }
- DCHECK(0);
- return 0;
-#else
- return MemToShadowImpl<Mapping>(x);
-#endif
+RawShadow *MemToShadow(uptr x) {
+ return reinterpret_cast<RawShadow *>(SelectMapping<MemToShadowImpl>(x));
}
-
-template<typename Mapping>
-u32 *MemToMetaImpl(uptr x) {
- DCHECK(IsAppMem(x));
-#if !SANITIZER_GO
- return (u32*)(((((x) & ~(Mapping::kAppMemMsk | (kMetaShadowCell - 1)))) /
- kMetaShadowCell * kMetaShadowSize) | Mapping::kMetaShadowBeg);
-#else
-# ifndef SANITIZER_WINDOWS
- return (u32*)(((x & ~(kMetaShadowCell - 1)) / \
- kMetaShadowCell * kMetaShadowSize) | Mapping::kMetaShadowBeg);
-# else
- return (u32*)(((x & ~(kMetaShadowCell - 1)) / \
- kMetaShadowCell * kMetaShadowSize) + Mapping::kMetaShadowBeg);
-# endif
-#endif
-}
+struct MemToMetaImpl {
+ template <typename Mapping>
+ static u32 *Apply(uptr x) {
+ DCHECK(IsAppMemImpl::Apply<Mapping>(x));
+ return (u32 *)(((((x) & ~(Mapping::kShadowMsk | (kMetaShadowCell - 1)))) /
+ kMetaShadowCell * kMetaShadowSize) |
+ Mapping::kMetaShadowBeg);
+ }
+};
ALWAYS_INLINE
-u32 *MemToMeta(uptr x) {
-#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
- switch (vmaSize) {
- case 39: return MemToMetaImpl<Mapping39>(x);
- case 42: return MemToMetaImpl<Mapping42>(x);
- case 48: return MemToMetaImpl<Mapping48>(x);
- }
- DCHECK(0);
- return 0;
-#elif defined(__powerpc64__)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 44: return MemToMetaImpl<Mapping44>(x);
-#endif
- case 46: return MemToMetaImpl<Mapping46>(x);
- case 47: return MemToMetaImpl<Mapping47>(x);
+u32 *MemToMeta(uptr x) { return SelectMapping<MemToMetaImpl>(x); }
+
+struct ShadowToMemImpl {
+ template <typename Mapping>
+ static uptr Apply(uptr sp) {
+ if (!IsShadowMemImpl::Apply<Mapping>(sp))
+ return 0;
+ // The shadow mapping is non-linear and we've lost some bits, so we don't
+ // have an easy way to restore the original app address. But the mapping is
+ // a bijection, so we try to restore the address as belonging to
+ // low/mid/high range consecutively and see if shadow->app->shadow mapping
+ // gives us the same address.
+ uptr p =
+ ((sp - Mapping::kShadowAdd) / kShadowMultiplier) ^ Mapping::kShadowXor;
+ if (p >= Mapping::kLoAppMemBeg && p < Mapping::kLoAppMemEnd &&
+ MemToShadowImpl::Apply<Mapping>(p) == sp)
+ return p;
+ if (Mapping::kMidAppMemBeg) {
+ uptr p_mid = p + (Mapping::kMidAppMemBeg & Mapping::kShadowMsk);
+ if (p_mid >= Mapping::kMidAppMemBeg && p_mid < Mapping::kMidAppMemEnd &&
+ MemToShadowImpl::Apply<Mapping>(p_mid) == sp)
+ return p_mid;
+ }
+ return p | Mapping::kShadowMsk;
}
- DCHECK(0);
- return 0;
-#elif defined(__mips64)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 40: return MemToMetaImpl<Mapping40>(x);
-#else
- case 47: return MemToMetaImpl<Mapping47>(x);
-#endif
- }
- DCHECK(0);
- return 0;
-#else
- return MemToMetaImpl<Mapping>(x);
-#endif
-}
-
-
-template<typename Mapping>
-uptr ShadowToMemImpl(uptr s) {
- DCHECK(IsShadowMem(s));
-#if !SANITIZER_GO
- // The shadow mapping is non-linear and we've lost some bits, so we don't have
- // an easy way to restore the original app address. But the mapping is a
- // bijection, so we try to restore the address as belonging to low/mid/high
- // range consecutively and see if shadow->app->shadow mapping gives us the
- // same address.
- uptr p = (s / kShadowCnt) ^ Mapping::kAppMemXor;
- if (p >= Mapping::kLoAppMemBeg && p < Mapping::kLoAppMemEnd &&
- MemToShadow(p) == s)
- return p;
-# ifdef TSAN_MID_APP_RANGE
- p = ((s / kShadowCnt) ^ Mapping::kAppMemXor) +
- (Mapping::kMidAppMemBeg & Mapping::kAppMemMsk);
- if (p >= Mapping::kMidAppMemBeg && p < Mapping::kMidAppMemEnd &&
- MemToShadow(p) == s)
- return p;
-# endif
- return ((s / kShadowCnt) ^ Mapping::kAppMemXor) | Mapping::kAppMemMsk;
-#else // #if !SANITIZER_GO
-# ifndef SANITIZER_WINDOWS
- return (s & ~Mapping::kShadowBeg) / kShadowCnt;
-# else
- return (s - Mapping::kShadowBeg) / kShadowCnt;
-# endif // SANITIZER_WINDOWS
-#endif
-}
+};
ALWAYS_INLINE
-uptr ShadowToMem(uptr s) {
-#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
- switch (vmaSize) {
- case 39: return ShadowToMemImpl<Mapping39>(s);
- case 42: return ShadowToMemImpl<Mapping42>(s);
- case 48: return ShadowToMemImpl<Mapping48>(s);
- }
- DCHECK(0);
- return 0;
-#elif defined(__powerpc64__)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 44: return ShadowToMemImpl<Mapping44>(s);
-#endif
- case 46: return ShadowToMemImpl<Mapping46>(s);
- case 47: return ShadowToMemImpl<Mapping47>(s);
+uptr ShadowToMem(RawShadow *s) {
+ return SelectMapping<ShadowToMemImpl>(reinterpret_cast<uptr>(s));
+}
+
+// Compresses addr to kCompressedAddrBits stored in least significant bits.
+ALWAYS_INLINE uptr CompressAddr(uptr addr) {
+ return addr & ((1ull << kCompressedAddrBits) - 1);
+}
+
+struct RestoreAddrImpl {
+ typedef uptr Result;
+ template <typename Mapping>
+ static Result Apply(uptr addr) {
+ // To restore the address we go over all app memory ranges and check if top
+ // 3 bits of the compressed addr match that of the app range. If yes, we
+ // assume that the compressed address come from that range and restore the
+ // missing top bits to match the app range address.
+ static constexpr uptr ranges[] = {
+ Mapping::kLoAppMemBeg, Mapping::kLoAppMemEnd, Mapping::kMidAppMemBeg,
+ Mapping::kMidAppMemEnd, Mapping::kHiAppMemBeg, Mapping::kHiAppMemEnd,
+ Mapping::kHeapMemBeg, Mapping::kHeapMemEnd,
+ };
+ const uptr indicator = 0x0e0000000000ull;
+ const uptr ind_lsb = 1ull << LeastSignificantSetBitIndex(indicator);
+ for (uptr i = 0; i < ARRAY_SIZE(ranges); i += 2) {
+ uptr beg = ranges[i];
+ uptr end = ranges[i + 1];
+ if (beg == end)
+ continue;
+ for (uptr p = beg; p < end; p = RoundDown(p + ind_lsb, ind_lsb)) {
+ if ((addr & indicator) == (p & indicator))
+ return addr | (p & ~(ind_lsb - 1));
+ }
+ }
+ Printf("ThreadSanitizer: failed to restore address 0x%zx\n", addr);
+ Die();
}
- DCHECK(0);
- return 0;
-#elif defined(__mips64)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 40: return ShadowToMemImpl<Mapping40>(s);
-#else
- case 47: return ShadowToMemImpl<Mapping47>(s);
-#endif
- }
- DCHECK(0);
- return 0;
-#else
- return ShadowToMemImpl<Mapping>(s);
-#endif
-}
-
+};
+// Restores compressed addr from kCompressedAddrBits to full representation.
+// This is called only during reporting and is not performance-critical.
+inline uptr RestoreAddr(uptr addr) {
+ return SelectMapping<RestoreAddrImpl>(addr);
+}
// The additional page is to catch shadow stack overflow as paging fault.
// Windows wants 64K alignment for mmaps.
const uptr kTotalTraceSize = (kTraceSize * sizeof(Event) + sizeof(Trace)
+ (64 << 10) + (64 << 10) - 1) & ~((64 << 10) - 1);
-template<typename Mapping>
-uptr GetThreadTraceImpl(int tid) {
- uptr p = Mapping::kTraceMemBeg + (uptr)tid * kTotalTraceSize;
- DCHECK_LT(p, Mapping::kTraceMemEnd);
- return p;
-}
+struct GetThreadTraceImpl {
+ template <typename Mapping>
+ static uptr Apply(uptr tid) {
+ uptr p = Mapping::kTraceMemBeg + tid * kTotalTraceSize;
+ DCHECK_LT(p, Mapping::kTraceMemEnd);
+ return p;
+ }
+};
ALWAYS_INLINE
-uptr GetThreadTrace(int tid) {
-#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
- switch (vmaSize) {
- case 39: return GetThreadTraceImpl<Mapping39>(tid);
- case 42: return GetThreadTraceImpl<Mapping42>(tid);
- case 48: return GetThreadTraceImpl<Mapping48>(tid);
- }
- DCHECK(0);
- return 0;
-#elif defined(__powerpc64__)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 44: return GetThreadTraceImpl<Mapping44>(tid);
-#endif
- case 46: return GetThreadTraceImpl<Mapping46>(tid);
- case 47: return GetThreadTraceImpl<Mapping47>(tid);
- }
- DCHECK(0);
- return 0;
-#elif defined(__mips64)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 40: return GetThreadTraceImpl<Mapping40>(tid);
-#else
- case 47: return GetThreadTraceImpl<Mapping47>(tid);
-#endif
+uptr GetThreadTrace(int tid) { return SelectMapping<GetThreadTraceImpl>(tid); }
+
+struct GetThreadTraceHeaderImpl {
+ template <typename Mapping>
+ static uptr Apply(uptr tid) {
+ uptr p = Mapping::kTraceMemBeg + tid * kTotalTraceSize +
+ kTraceSize * sizeof(Event);
+ DCHECK_LT(p, Mapping::kTraceMemEnd);
+ return p;
}
- DCHECK(0);
- return 0;
-#else
- return GetThreadTraceImpl<Mapping>(tid);
-#endif
-}
-
-
-template<typename Mapping>
-uptr GetThreadTraceHeaderImpl(int tid) {
- uptr p = Mapping::kTraceMemBeg + (uptr)tid * kTotalTraceSize
- + kTraceSize * sizeof(Event);
- DCHECK_LT(p, Mapping::kTraceMemEnd);
- return p;
-}
+};
ALWAYS_INLINE
uptr GetThreadTraceHeader(int tid) {
-#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
- switch (vmaSize) {
- case 39: return GetThreadTraceHeaderImpl<Mapping39>(tid);
- case 42: return GetThreadTraceHeaderImpl<Mapping42>(tid);
- case 48: return GetThreadTraceHeaderImpl<Mapping48>(tid);
- }
- DCHECK(0);
- return 0;
-#elif defined(__powerpc64__)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 44: return GetThreadTraceHeaderImpl<Mapping44>(tid);
-#endif
- case 46: return GetThreadTraceHeaderImpl<Mapping46>(tid);
- case 47: return GetThreadTraceHeaderImpl<Mapping47>(tid);
- }
- DCHECK(0);
- return 0;
-#elif defined(__mips64)
- switch (vmaSize) {
-#if !SANITIZER_GO
- case 40: return GetThreadTraceHeaderImpl<Mapping40>(tid);
-#else
- case 47: return GetThreadTraceHeaderImpl<Mapping47>(tid);
-#endif
- }
- DCHECK(0);
- return 0;
-#else
- return GetThreadTraceHeaderImpl<Mapping>(tid);
-#endif
+ return SelectMapping<GetThreadTraceHeaderImpl>(tid);
}
void InitializePlatform();
@@ -1194,7 +971,7 @@ void InitializePlatformEarly();
void CheckAndProtect();
void InitializeShadowMemoryPlatform();
void FlushShadowMemory();
-void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive);
+void WriteMemoryProfile(char *buf, uptr buf_size, u64 uptime_ns);
int ExtractResolvFDs(void *state, int *fds, int nfd);
int ExtractRecvmsgFDs(void *msg, int *fds, int nfd);
uptr ExtractLongJmpSp(uptr *env);
diff --git a/libsanitizer/tsan/tsan_platform_linux.cpp b/libsanitizer/tsan/tsan_platform_linux.cpp
index cfe597e..2fb753d 100644
--- a/libsanitizer/tsan/tsan_platform_linux.cpp
+++ b/libsanitizer/tsan/tsan_platform_linux.cpp
@@ -85,21 +85,19 @@ static void InitializeLongjmpXorKey();
static uptr longjmp_xor_key;
#endif
-#ifdef TSAN_RUNTIME_VMA
// Runtime detected VMA size.
uptr vmaSize;
-#endif
enum {
- MemTotal = 0,
- MemShadow = 1,
- MemMeta = 2,
- MemFile = 3,
- MemMmap = 4,
- MemTrace = 5,
- MemHeap = 6,
- MemOther = 7,
- MemCount = 8,
+ MemTotal,
+ MemShadow,
+ MemMeta,
+ MemFile,
+ MemMmap,
+ MemTrace,
+ MemHeap,
+ MemOther,
+ MemCount,
};
void FillProfileCallback(uptr p, uptr rss, bool file,
@@ -109,39 +107,47 @@ void FillProfileCallback(uptr p, uptr rss, bool file,
mem[MemShadow] += rss;
else if (p >= MetaShadowBeg() && p < MetaShadowEnd())
mem[MemMeta] += rss;
-#if !SANITIZER_GO
+ else if ((p >= LoAppMemBeg() && p < LoAppMemEnd()) ||
+ (p >= MidAppMemBeg() && p < MidAppMemEnd()) ||
+ (p >= HiAppMemBeg() && p < HiAppMemEnd()))
+ mem[file ? MemFile : MemMmap] += rss;
else if (p >= HeapMemBeg() && p < HeapMemEnd())
mem[MemHeap] += rss;
- else if (p >= LoAppMemBeg() && p < LoAppMemEnd())
- mem[file ? MemFile : MemMmap] += rss;
- else if (p >= HiAppMemBeg() && p < HiAppMemEnd())
- mem[file ? MemFile : MemMmap] += rss;
-#else
- else if (p >= AppMemBeg() && p < AppMemEnd())
- mem[file ? MemFile : MemMmap] += rss;
-#endif
else if (p >= TraceMemBeg() && p < TraceMemEnd())
mem[MemTrace] += rss;
else
mem[MemOther] += rss;
}
-void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) {
+void WriteMemoryProfile(char *buf, uptr buf_size, u64 uptime_ns) {
uptr mem[MemCount];
- internal_memset(mem, 0, sizeof(mem[0]) * MemCount);
- __sanitizer::GetMemoryProfile(FillProfileCallback, mem, 7);
- StackDepotStats *stacks = StackDepotGetStats();
- internal_snprintf(buf, buf_size,
- "RSS %zd MB: shadow:%zd meta:%zd file:%zd mmap:%zd"
- " trace:%zd heap:%zd other:%zd stacks=%zd[%zd] nthr=%zd/%zd\n",
- mem[MemTotal] >> 20, mem[MemShadow] >> 20, mem[MemMeta] >> 20,
- mem[MemFile] >> 20, mem[MemMmap] >> 20, mem[MemTrace] >> 20,
- mem[MemHeap] >> 20, mem[MemOther] >> 20,
- stacks->allocated >> 20, stacks->n_uniq_ids,
- nlive, nthread);
+ internal_memset(mem, 0, sizeof(mem));
+ GetMemoryProfile(FillProfileCallback, mem, MemCount);
+ auto meta = ctx->metamap.GetMemoryStats();
+ StackDepotStats stacks = StackDepotGetStats();
+ uptr nthread, nlive;
+ ctx->thread_registry.GetNumberOfThreads(&nthread, &nlive);
+ uptr internal_stats[AllocatorStatCount];
+ internal_allocator()->GetStats(internal_stats);
+ // All these are allocated from the common mmap region.
+ mem[MemMmap] -= meta.mem_block + meta.sync_obj + stacks.allocated +
+ internal_stats[AllocatorStatMapped];
+ if (s64(mem[MemMmap]) < 0)
+ mem[MemMmap] = 0;
+ internal_snprintf(
+ buf, buf_size,
+ "%llus: RSS %zd MB: shadow:%zd meta:%zd file:%zd mmap:%zd"
+ " trace:%zd heap:%zd other:%zd intalloc:%zd memblocks:%zd syncobj:%zu"
+ " stacks=%zd[%zd] nthr=%zd/%zd\n",
+ uptime_ns / (1000 * 1000 * 1000), mem[MemTotal] >> 20,
+ mem[MemShadow] >> 20, mem[MemMeta] >> 20, mem[MemFile] >> 20,
+ mem[MemMmap] >> 20, mem[MemTrace] >> 20, mem[MemHeap] >> 20,
+ mem[MemOther] >> 20, internal_stats[AllocatorStatMapped] >> 20,
+ meta.mem_block >> 20, meta.sync_obj >> 20, stacks.allocated >> 20,
+ stacks.n_uniq_ids, nlive, nthread);
}
-#if SANITIZER_LINUX
+# if SANITIZER_LINUX
void FlushShadowMemoryCallback(
const SuspendedThreadsList &suspended_threads_list,
void *argument) {
@@ -178,12 +184,13 @@ static void MapRodata() {
internal_unlink(name); // Unlink it now, so that we can reuse the buffer.
fd_t fd = openrv;
// Fill the file with kShadowRodata.
- const uptr kMarkerSize = 512 * 1024 / sizeof(u64);
- InternalMmapVector<u64> marker(kMarkerSize);
+ const uptr kMarkerSize = 512 * 1024 / sizeof(RawShadow);
+ InternalMmapVector<RawShadow> marker(kMarkerSize);
// volatile to prevent insertion of memset
- for (volatile u64 *p = marker.data(); p < marker.data() + kMarkerSize; p++)
+ for (volatile RawShadow *p = marker.data(); p < marker.data() + kMarkerSize;
+ p++)
*p = kShadowRodata;
- internal_write(fd, marker.data(), marker.size() * sizeof(u64));
+ internal_write(fd, marker.data(), marker.size() * sizeof(RawShadow));
// Map the file into memory.
uptr page = internal_mmap(0, GetPageSizeCached(), PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, fd, 0);
@@ -203,9 +210,10 @@ static void MapRodata() {
char *shadow_start = (char *)MemToShadow(segment.start);
char *shadow_end = (char *)MemToShadow(segment.end);
for (char *p = shadow_start; p < shadow_end;
- p += marker.size() * sizeof(u64)) {
- internal_mmap(p, Min<uptr>(marker.size() * sizeof(u64), shadow_end - p),
- PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, 0);
+ p += marker.size() * sizeof(RawShadow)) {
+ internal_mmap(
+ p, Min<uptr>(marker.size() * sizeof(RawShadow), shadow_end - p),
+ PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, 0);
}
}
}
@@ -219,7 +227,6 @@ void InitializeShadowMemoryPlatform() {
#endif // #if !SANITIZER_GO
void InitializePlatformEarly() {
-#ifdef TSAN_RUNTIME_VMA
vmaSize =
(MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1);
#if defined(__aarch64__)
@@ -265,7 +272,6 @@ void InitializePlatformEarly() {
}
# endif
#endif
-#endif
}
void InitializePlatform() {
@@ -341,7 +347,7 @@ int ExtractResolvFDs(void *state, int *fds, int nfd) {
}
// Extract file descriptors passed via UNIX domain sockets.
-// This is requried to properly handle "open" of these fds.
+// This is required to properly handle "open" of these fds.
// see 'man recvmsg' and 'man 3 cmsg'.
int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) {
int res = 0;
@@ -447,6 +453,8 @@ static void InitializeLongjmpXorKey() {
}
#endif
+extern "C" void __tsan_tls_initialization() {}
+
void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) {
// Check that the thr object is in tls;
const uptr thr_beg = (uptr)thr;
@@ -456,9 +464,10 @@ void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) {
CHECK_GE(thr_end, tls_addr);
CHECK_LE(thr_end, tls_addr + tls_size);
// Since the thr object is huge, skip it.
- MemoryRangeImitateWrite(thr, /*pc=*/2, tls_addr, thr_beg - tls_addr);
- MemoryRangeImitateWrite(thr, /*pc=*/2, thr_end,
- tls_addr + tls_size - thr_end);
+ const uptr pc = StackTrace::GetNextInstructionPc(
+ reinterpret_cast<uptr>(__tsan_tls_initialization));
+ MemoryRangeImitateWrite(thr, pc, tls_addr, thr_beg - tls_addr);
+ MemoryRangeImitateWrite(thr, pc, thr_end, tls_addr + tls_size - thr_end);
}
// Note: this function runs with async signals enabled,
diff --git a/libsanitizer/tsan/tsan_platform_mac.cpp b/libsanitizer/tsan/tsan_platform_mac.cpp
index d9719a1..388b383 100644
--- a/libsanitizer/tsan/tsan_platform_mac.cpp
+++ b/libsanitizer/tsan/tsan_platform_mac.cpp
@@ -139,7 +139,7 @@ static void RegionMemUsage(uptr start, uptr end, uptr *res, uptr *dirty) {
*dirty = dirty_pages * GetPageSizeCached();
}
-void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) {
+void WriteMemoryProfile(char *buf, uptr buf_size, u64 uptime_ns) {
uptr shadow_res, shadow_dirty;
uptr meta_res, meta_dirty;
uptr trace_res, trace_dirty;
@@ -156,39 +156,41 @@ void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) {
RegionMemUsage(HeapMemBeg(), HeapMemEnd(), &heap_res, &heap_dirty);
#else // !SANITIZER_GO
uptr app_res, app_dirty;
- RegionMemUsage(AppMemBeg(), AppMemEnd(), &app_res, &app_dirty);
+ RegionMemUsage(LoAppMemBeg(), LoAppMemEnd(), &app_res, &app_dirty);
#endif
- StackDepotStats *stacks = StackDepotGetStats();
- internal_snprintf(buf, buf_size,
- "shadow (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
- "meta (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
- "traces (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
-#if !SANITIZER_GO
- "low app (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
- "high app (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
- "heap (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
-#else // !SANITIZER_GO
- "app (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
-#endif
- "stacks: %zd unique IDs, %zd kB allocated\n"
- "threads: %zd total, %zd live\n"
- "------------------------------\n",
- ShadowBeg(), ShadowEnd(), shadow_res / 1024, shadow_dirty / 1024,
- MetaShadowBeg(), MetaShadowEnd(), meta_res / 1024, meta_dirty / 1024,
- TraceMemBeg(), TraceMemEnd(), trace_res / 1024, trace_dirty / 1024,
-#if !SANITIZER_GO
- LoAppMemBeg(), LoAppMemEnd(), low_res / 1024, low_dirty / 1024,
- HiAppMemBeg(), HiAppMemEnd(), high_res / 1024, high_dirty / 1024,
- HeapMemBeg(), HeapMemEnd(), heap_res / 1024, heap_dirty / 1024,
-#else // !SANITIZER_GO
- AppMemBeg(), AppMemEnd(), app_res / 1024, app_dirty / 1024,
-#endif
- stacks->n_uniq_ids, stacks->allocated / 1024,
- nthread, nlive);
+ StackDepotStats stacks = StackDepotGetStats();
+ uptr nthread, nlive;
+ ctx->thread_registry.GetNumberOfThreads(&nthread, &nlive);
+ internal_snprintf(
+ buf, buf_size,
+ "shadow (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
+ "meta (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
+ "traces (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
+# if !SANITIZER_GO
+ "low app (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
+ "high app (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
+ "heap (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
+# else // !SANITIZER_GO
+ "app (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
+# endif
+ "stacks: %zd unique IDs, %zd kB allocated\n"
+ "threads: %zd total, %zd live\n"
+ "------------------------------\n",
+ ShadowBeg(), ShadowEnd(), shadow_res / 1024, shadow_dirty / 1024,
+ MetaShadowBeg(), MetaShadowEnd(), meta_res / 1024, meta_dirty / 1024,
+ TraceMemBeg(), TraceMemEnd(), trace_res / 1024, trace_dirty / 1024,
+# if !SANITIZER_GO
+ LoAppMemBeg(), LoAppMemEnd(), low_res / 1024, low_dirty / 1024,
+ HiAppMemBeg(), HiAppMemEnd(), high_res / 1024, high_dirty / 1024,
+ HeapMemBeg(), HeapMemEnd(), heap_res / 1024, heap_dirty / 1024,
+# else // !SANITIZER_GO
+ LoAppMemBeg(), LoAppMemEnd(), app_res / 1024, app_dirty / 1024,
+# endif
+ stacks.n_uniq_ids, stacks.allocated / 1024, nthread, nlive);
}
-#if !SANITIZER_GO
+# if !SANITIZER_GO
void InitializeShadowMemoryPlatform() { }
// On OS X, GCD worker threads are created without a call to pthread_create. We
@@ -215,8 +217,8 @@ static void my_pthread_introspection_hook(unsigned int event, pthread_t thread,
Processor *proc = ProcCreate();
ProcWire(proc, thr);
ThreadState *parent_thread_state = nullptr; // No parent.
- int tid = ThreadCreate(parent_thread_state, 0, (uptr)thread, true);
- CHECK_NE(tid, 0);
+ Tid tid = ThreadCreate(parent_thread_state, 0, (uptr)thread, true);
+ CHECK_NE(tid, kMainTid);
ThreadStart(thr, tid, GetTid(), ThreadType::Worker);
}
} else if (event == PTHREAD_INTROSPECTION_THREAD_TERMINATE) {
@@ -234,11 +236,11 @@ static void my_pthread_introspection_hook(unsigned int event, pthread_t thread,
#endif
void InitializePlatformEarly() {
-#if !SANITIZER_GO && !HAS_48_BIT_ADDRESS_SPACE
+# if !SANITIZER_GO && SANITIZER_IOS
uptr max_vm = GetMaxUserVirtualAddress() + 1;
- if (max_vm != Mapping::kHiAppMemEnd) {
+ if (max_vm != HiAppMemEnd()) {
Printf("ThreadSanitizer: unsupported vm address limit %p, expected %p.\n",
- max_vm, Mapping::kHiAppMemEnd);
+ max_vm, HiAppMemEnd());
Die();
}
#endif
@@ -281,13 +283,17 @@ uptr ExtractLongJmpSp(uptr *env) {
}
#if !SANITIZER_GO
+extern "C" void __tsan_tls_initialization() {}
+
void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) {
// The pointer to the ThreadState object is stored in the shadow memory
// of the tls.
uptr tls_end = tls_addr + tls_size;
uptr thread_identity = (uptr)pthread_self();
+ const uptr pc = StackTrace::GetNextInstructionPc(
+ reinterpret_cast<uptr>(__tsan_tls_initialization));
if (thread_identity == main_thread_identity) {
- MemoryRangeImitateWrite(thr, /*pc=*/2, tls_addr, tls_size);
+ MemoryRangeImitateWrite(thr, pc, tls_addr, tls_size);
} else {
uptr thr_state_start = thread_identity;
uptr thr_state_end = thr_state_start + sizeof(uptr);
@@ -295,10 +301,8 @@ void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) {
CHECK_LE(thr_state_start, tls_addr + tls_size);
CHECK_GE(thr_state_end, tls_addr);
CHECK_LE(thr_state_end, tls_addr + tls_size);
- MemoryRangeImitateWrite(thr, /*pc=*/2, tls_addr,
- thr_state_start - tls_addr);
- MemoryRangeImitateWrite(thr, /*pc=*/2, thr_state_end,
- tls_end - thr_state_end);
+ MemoryRangeImitateWrite(thr, pc, tls_addr, thr_state_start - tls_addr);
+ MemoryRangeImitateWrite(thr, pc, thr_state_end, tls_end - thr_state_end);
}
}
#endif
diff --git a/libsanitizer/tsan/tsan_platform_posix.cpp b/libsanitizer/tsan/tsan_platform_posix.cpp
index 1c6198c..763ac44 100644
--- a/libsanitizer/tsan/tsan_platform_posix.cpp
+++ b/libsanitizer/tsan/tsan_platform_posix.cpp
@@ -14,12 +14,14 @@
#include "sanitizer_common/sanitizer_platform.h"
#if SANITIZER_POSIX
-#include "sanitizer_common/sanitizer_common.h"
-#include "sanitizer_common/sanitizer_errno.h"
-#include "sanitizer_common/sanitizer_libc.h"
-#include "sanitizer_common/sanitizer_procmaps.h"
-#include "tsan_platform.h"
-#include "tsan_rtl.h"
+# include <dlfcn.h>
+
+# include "sanitizer_common/sanitizer_common.h"
+# include "sanitizer_common/sanitizer_errno.h"
+# include "sanitizer_common/sanitizer_libc.h"
+# include "sanitizer_common/sanitizer_procmaps.h"
+# include "tsan_platform.h"
+# include "tsan_rtl.h"
namespace __tsan {
@@ -29,6 +31,7 @@ static const char kShadowMemoryMappingHint[] =
"HINT: if %s is not supported in your environment, you may set "
"TSAN_OPTIONS=%s=0\n";
+# if !SANITIZER_GO
static void DontDumpShadow(uptr addr, uptr size) {
if (common_flags()->use_madv_dontdump)
if (!DontDumpShadowMemory(addr, size)) {
@@ -39,7 +42,6 @@ static void DontDumpShadow(uptr addr, uptr size) {
}
}
-#if !SANITIZER_GO
void InitializeShadowMemory() {
// Map memory shadow.
if (!MmapFixedSuperNoReserve(ShadowBeg(), ShadowEnd() - ShadowBeg(),
@@ -70,6 +72,11 @@ void InitializeShadowMemory() {
meta, meta + meta_size, meta_size >> 30);
InitializeShadowMemoryPlatform();
+
+ on_initialize = reinterpret_cast<void (*)(void)>(
+ dlsym(RTLD_DEFAULT, "__tsan_on_initialize"));
+ on_finalize =
+ reinterpret_cast<int (*)(int)>(dlsym(RTLD_DEFAULT, "__tsan_on_finalize"));
}
static bool TryProtectRange(uptr beg, uptr end) {
@@ -98,24 +105,24 @@ void CheckAndProtect() {
continue;
if (segment.start >= VdsoBeg()) // vdso
break;
- Printf("FATAL: ThreadSanitizer: unexpected memory mapping %p-%p\n",
+ Printf("FATAL: ThreadSanitizer: unexpected memory mapping 0x%zx-0x%zx\n",
segment.start, segment.end);
Die();
}
-#if defined(__aarch64__) && defined(__APPLE__) && !HAS_48_BIT_ADDRESS_SPACE
+# if defined(__aarch64__) && defined(__APPLE__) && SANITIZER_IOS
ProtectRange(HeapMemEnd(), ShadowBeg());
ProtectRange(ShadowEnd(), MetaShadowBeg());
ProtectRange(MetaShadowEnd(), TraceMemBeg());
#else
ProtectRange(LoAppMemEnd(), ShadowBeg());
ProtectRange(ShadowEnd(), MetaShadowBeg());
-#ifdef TSAN_MID_APP_RANGE
- ProtectRange(MetaShadowEnd(), MidAppMemBeg());
- ProtectRange(MidAppMemEnd(), TraceMemBeg());
-#else
- ProtectRange(MetaShadowEnd(), TraceMemBeg());
-#endif
+ if (MidAppMemBeg()) {
+ ProtectRange(MetaShadowEnd(), MidAppMemBeg());
+ ProtectRange(MidAppMemEnd(), TraceMemBeg());
+ } else {
+ ProtectRange(MetaShadowEnd(), TraceMemBeg());
+ }
// Memory for traces is mapped lazily in MapThreadTrace.
// Protect the whole range for now, so that user does not map something here.
ProtectRange(TraceMemBeg(), TraceMemEnd());
diff --git a/libsanitizer/tsan/tsan_platform_windows.cpp b/libsanitizer/tsan/tsan_platform_windows.cpp
index 1943787..fea8937 100644
--- a/libsanitizer/tsan/tsan_platform_windows.cpp
+++ b/libsanitizer/tsan/tsan_platform_windows.cpp
@@ -23,8 +23,7 @@ namespace __tsan {
void FlushShadowMemory() {
}
-void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) {
-}
+void WriteMemoryProfile(char *buf, uptr buf_size, u64 uptime_ns) {}
void InitializePlatformEarly() {
}
diff --git a/libsanitizer/tsan/tsan_report.cpp b/libsanitizer/tsan/tsan_report.cpp
index 8ef9f0c..a926c37 100644
--- a/libsanitizer/tsan/tsan_report.cpp
+++ b/libsanitizer/tsan/tsan_report.cpp
@@ -19,22 +19,6 @@
namespace __tsan {
-ReportStack::ReportStack() : frames(nullptr), suppressable(false) {}
-
-ReportStack *ReportStack::New() {
- void *mem = internal_alloc(MBlockReportStack, sizeof(ReportStack));
- return new(mem) ReportStack();
-}
-
-ReportLocation::ReportLocation(ReportLocationType type)
- : type(type), global(), heap_chunk_start(0), heap_chunk_size(0), tid(0),
- fd(0), suppressable(false), stack(nullptr) {}
-
-ReportLocation *ReportLocation::New(ReportLocationType type) {
- void *mem = internal_alloc(MBlockReportStack, sizeof(ReportLocation));
- return new(mem) ReportLocation(type);
-}
-
class Decorator: public __sanitizer::SanitizerCommonDecorator {
public:
Decorator() : SanitizerCommonDecorator() { }
@@ -68,7 +52,7 @@ ReportDesc::~ReportDesc() {
#if !SANITIZER_GO
const int kThreadBufSize = 32;
-const char *thread_name(char *buf, int tid) {
+const char *thread_name(char *buf, Tid tid) {
if (tid == kMainTid)
return "main thread";
internal_snprintf(buf, kThreadBufSize, "thread T%d", tid);
@@ -189,23 +173,25 @@ static void PrintLocation(const ReportLocation *loc) {
if (loc->type == ReportLocationGlobal) {
const DataInfo &global = loc->global;
if (global.size != 0)
- Printf(" Location is global '%s' of size %zu at %p (%s+%p)\n\n",
- global.name, global.size, global.start,
+ Printf(" Location is global '%s' of size %zu at %p (%s+0x%zx)\n\n",
+ global.name, global.size, reinterpret_cast<void *>(global.start),
StripModuleName(global.module), global.module_offset);
else
- Printf(" Location is global '%s' at %p (%s+%p)\n\n", global.name,
- global.start, StripModuleName(global.module),
- global.module_offset);
+ Printf(" Location is global '%s' at %p (%s+0x%zx)\n\n", global.name,
+ reinterpret_cast<void *>(global.start),
+ StripModuleName(global.module), global.module_offset);
} else if (loc->type == ReportLocationHeap) {
char thrbuf[kThreadBufSize];
const char *object_type = GetObjectTypeFromTag(loc->external_tag);
if (!object_type) {
Printf(" Location is heap block of size %zu at %p allocated by %s:\n",
- loc->heap_chunk_size, loc->heap_chunk_start,
+ loc->heap_chunk_size,
+ reinterpret_cast<void *>(loc->heap_chunk_start),
thread_name(thrbuf, loc->tid));
} else {
Printf(" Location is %s of size %zu at %p allocated by %s:\n",
- object_type, loc->heap_chunk_size, loc->heap_chunk_start,
+ object_type, loc->heap_chunk_size,
+ reinterpret_cast<void *>(loc->heap_chunk_start),
thread_name(thrbuf, loc->tid));
}
print_stack = true;
@@ -225,13 +211,14 @@ static void PrintLocation(const ReportLocation *loc) {
static void PrintMutexShort(const ReportMutex *rm, const char *after) {
Decorator d;
- Printf("%sM%zd%s%s", d.Mutex(), rm->id, d.Default(), after);
+ Printf("%sM%lld%s%s", d.Mutex(), rm->id, d.Default(), after);
}
static void PrintMutexShortWithAddress(const ReportMutex *rm,
const char *after) {
Decorator d;
- Printf("%sM%zd (%p)%s%s", d.Mutex(), rm->id, rm->addr, d.Default(), after);
+ Printf("%sM%lld (%p)%s%s", d.Mutex(), rm->id,
+ reinterpret_cast<void *>(rm->addr), d.Default(), after);
}
static void PrintMutex(const ReportMutex *rm) {
@@ -242,7 +229,8 @@ static void PrintMutex(const ReportMutex *rm) {
Printf("%s", d.Default());
} else {
Printf("%s", d.Mutex());
- Printf(" Mutex M%llu (%p) created at:\n", rm->id, rm->addr);
+ Printf(" Mutex M%llu (%p) created at:\n", rm->id,
+ reinterpret_cast<void *>(rm->addr));
Printf("%s", d.Default());
PrintStack(rm->stack);
}
@@ -259,12 +247,13 @@ static void PrintThread(const ReportThread *rt) {
char thrbuf[kThreadBufSize];
const char *thread_status = rt->running ? "running" : "finished";
if (rt->thread_type == ThreadType::Worker) {
- Printf(" (tid=%zu, %s) is a GCD worker thread\n", rt->os_id, thread_status);
+ Printf(" (tid=%llu, %s) is a GCD worker thread\n", rt->os_id,
+ thread_status);
Printf("\n");
Printf("%s", d.Default());
return;
}
- Printf(" (tid=%zu, %s) created by %s", rt->os_id, thread_status,
+ Printf(" (tid=%llu, %s) created by %s", rt->os_id, thread_status,
thread_name(thrbuf, rt->parent_tid));
if (rt->stack)
Printf(" at:");
@@ -394,7 +383,7 @@ void PrintReport(const ReportDesc *rep) {
#else // #if !SANITIZER_GO
-const u32 kMainGoroutineId = 1;
+const Tid kMainGoroutineId = 1;
void PrintStack(const ReportStack *ent) {
if (ent == 0 || ent->frames == 0) {
@@ -405,16 +394,17 @@ void PrintStack(const ReportStack *ent) {
for (int i = 0; frame; frame = frame->next, i++) {
const AddressInfo &info = frame->info;
Printf(" %s()\n %s:%d +0x%zx\n", info.function,
- StripPathPrefix(info.file, common_flags()->strip_path_prefix),
- info.line, (void *)info.module_offset);
+ StripPathPrefix(info.file, common_flags()->strip_path_prefix),
+ info.line, info.module_offset);
}
}
static void PrintMop(const ReportMop *mop, bool first) {
Printf("\n");
Printf("%s at %p by ",
- (first ? (mop->write ? "Write" : "Read")
- : (mop->write ? "Previous write" : "Previous read")), mop->addr);
+ (first ? (mop->write ? "Write" : "Read")
+ : (mop->write ? "Previous write" : "Previous read")),
+ reinterpret_cast<void *>(mop->addr));
if (mop->tid == kMainGoroutineId)
Printf("main goroutine:\n");
else
@@ -426,8 +416,8 @@ static void PrintLocation(const ReportLocation *loc) {
switch (loc->type) {
case ReportLocationHeap: {
Printf("\n");
- Printf("Heap block of size %zu at %p allocated by ",
- loc->heap_chunk_size, loc->heap_chunk_start);
+ Printf("Heap block of size %zu at %p allocated by ", loc->heap_chunk_size,
+ reinterpret_cast<void *>(loc->heap_chunk_start));
if (loc->tid == kMainGoroutineId)
Printf("main goroutine:\n");
else
@@ -438,8 +428,9 @@ static void PrintLocation(const ReportLocation *loc) {
case ReportLocationGlobal: {
Printf("\n");
Printf("Global var %s of size %zu at %p declared at %s:%zu\n",
- loc->global.name, loc->global.size, loc->global.start,
- loc->global.file, loc->global.line);
+ loc->global.name, loc->global.size,
+ reinterpret_cast<void *>(loc->global.start), loc->global.file,
+ loc->global.line);
break;
}
default:
@@ -469,13 +460,13 @@ void PrintReport(const ReportDesc *rep) {
} else if (rep->typ == ReportTypeDeadlock) {
Printf("WARNING: DEADLOCK\n");
for (uptr i = 0; i < rep->mutexes.Size(); i++) {
- Printf("Goroutine %d lock mutex %d while holding mutex %d:\n",
- 999, rep->mutexes[i]->id,
- rep->mutexes[(i+1) % rep->mutexes.Size()]->id);
+ Printf("Goroutine %d lock mutex %llu while holding mutex %llu:\n", 999,
+ rep->mutexes[i]->id,
+ rep->mutexes[(i + 1) % rep->mutexes.Size()]->id);
PrintStack(rep->stacks[2*i]);
Printf("\n");
- Printf("Mutex %d was previously locked here:\n",
- rep->mutexes[(i+1) % rep->mutexes.Size()]->id);
+ Printf("Mutex %llu was previously locked here:\n",
+ rep->mutexes[(i + 1) % rep->mutexes.Size()]->id);
PrintStack(rep->stacks[2*i + 1]);
Printf("\n");
}
diff --git a/libsanitizer/tsan/tsan_report.h b/libsanitizer/tsan/tsan_report.h
index b4e4d89..d68c2db 100644
--- a/libsanitizer/tsan/tsan_report.h
+++ b/libsanitizer/tsan/tsan_report.h
@@ -38,12 +38,8 @@ enum ReportType {
};
struct ReportStack {
- SymbolizedStack *frames;
- bool suppressable;
- static ReportStack *New();
-
- private:
- ReportStack();
+ SymbolizedStack *frames = nullptr;
+ bool suppressable = false;
};
struct ReportMopMutex {
@@ -73,28 +69,24 @@ enum ReportLocationType {
};
struct ReportLocation {
- ReportLocationType type;
- DataInfo global;
- uptr heap_chunk_start;
- uptr heap_chunk_size;
- uptr external_tag;
- int tid;
- int fd;
- bool suppressable;
- ReportStack *stack;
-
- static ReportLocation *New(ReportLocationType type);
- private:
- explicit ReportLocation(ReportLocationType type);
+ ReportLocationType type = ReportLocationGlobal;
+ DataInfo global = {};
+ uptr heap_chunk_start = 0;
+ uptr heap_chunk_size = 0;
+ uptr external_tag = 0;
+ Tid tid = kInvalidTid;
+ int fd = 0;
+ bool suppressable = false;
+ ReportStack *stack = nullptr;
};
struct ReportThread {
- int id;
+ Tid id;
tid_t os_id;
bool running;
ThreadType thread_type;
char *name;
- u32 parent_tid;
+ Tid parent_tid;
ReportStack *stack;
};
@@ -114,7 +106,7 @@ class ReportDesc {
Vector<ReportLocation*> locs;
Vector<ReportMutex*> mutexes;
Vector<ReportThread*> threads;
- Vector<int> unique_tids;
+ Vector<Tid> unique_tids;
ReportStack *sleep;
int count;
diff --git a/libsanitizer/tsan/tsan_rtl.cpp b/libsanitizer/tsan/tsan_rtl.cpp
index bcf489a..1c53f95 100644
--- a/libsanitizer/tsan/tsan_rtl.cpp
+++ b/libsanitizer/tsan/tsan_rtl.cpp
@@ -28,16 +28,6 @@
#include "tsan_symbolize.h"
#include "ubsan/ubsan_init.h"
-#ifdef __SSE3__
-// <emmintrin.h> transitively includes <stdlib.h>,
-// and it's prohibited to include std headers into tsan runtime.
-// So we do this dirty trick.
-#define _MM_MALLOC_H_INCLUDED
-#define __MM_MALLOC_H
-#include <emmintrin.h>
-typedef __m128i m128;
-#endif
-
volatile int __tsan_resumed = 0;
extern "C" void __tsan_resume() {
@@ -46,11 +36,17 @@ extern "C" void __tsan_resume() {
namespace __tsan {
+#if !SANITIZER_GO
+void (*on_initialize)(void);
+int (*on_finalize)(int);
+#endif
+
#if !SANITIZER_GO && !SANITIZER_MAC
__attribute__((tls_model("initial-exec")))
-THREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64);
+THREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(
+ SANITIZER_CACHE_LINE_SIZE);
#endif
-static char ctx_placeholder[sizeof(Context)] ALIGNED(64);
+static char ctx_placeholder[sizeof(Context)] ALIGNED(SANITIZER_CACHE_LINE_SIZE);
Context *ctx;
// Can be overriden by a front-end.
@@ -62,24 +58,21 @@ void OnInitialize();
SANITIZER_WEAK_CXX_DEFAULT_IMPL
bool OnFinalize(bool failed) {
#if !SANITIZER_GO
- if (auto *ptr = dlsym(RTLD_DEFAULT, "__tsan_on_finalize"))
- return reinterpret_cast<decltype(&__tsan_on_finalize)>(ptr)(failed);
+ if (on_finalize)
+ return on_finalize(failed);
#endif
return failed;
}
SANITIZER_WEAK_CXX_DEFAULT_IMPL
void OnInitialize() {
#if !SANITIZER_GO
- if (auto *ptr = dlsym(RTLD_DEFAULT, "__tsan_on_initialize")) {
- return reinterpret_cast<decltype(&__tsan_on_initialize)>(ptr)();
- }
+ if (on_initialize)
+ on_initialize();
#endif
}
#endif
-static ALIGNED(64) char thread_registry_placeholder[sizeof(ThreadRegistry)];
-
-static ThreadContextBase *CreateThreadContext(u32 tid) {
+static ThreadContextBase *CreateThreadContext(Tid tid) {
// Map thread trace when context is created.
char name[50];
internal_snprintf(name, sizeof(name), "trace %u", tid);
@@ -98,13 +91,12 @@ static ThreadContextBase *CreateThreadContext(u32 tid) {
ReleaseMemoryPagesToOS(hdr_end, hdr + sizeof(Trace));
uptr unused = hdr + sizeof(Trace) - hdr_end;
if (hdr_end != (uptr)MmapFixedNoAccess(hdr_end, unused)) {
- Report("ThreadSanitizer: failed to mprotect(%p, %p)\n",
- hdr_end, unused);
+ Report("ThreadSanitizer: failed to mprotect [0x%zx-0x%zx) \n", hdr_end,
+ unused);
CHECK("unable to mprotect" && 0);
}
}
- void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadContext));
- return new(mem) ThreadContext(tid);
+ return New<ThreadContext>(tid);
}
#if !SANITIZER_GO
@@ -117,9 +109,8 @@ Context::Context()
: initialized(),
report_mtx(MutexTypeReport),
nreported(),
- nmissed_expected(),
- thread_registry(new (thread_registry_placeholder) ThreadRegistry(
- CreateThreadContext, kMaxTid, kThreadQuarantineSize, kMaxTidReuse)),
+ thread_registry(CreateThreadContext, kMaxTid, kThreadQuarantineSize,
+ kMaxTidReuse),
racy_mtx(MutexTypeRacy),
racy_stacks(),
racy_addresses(),
@@ -129,7 +120,7 @@ Context::Context()
}
// The objects are allocated in TLS, so one may rely on zero-initialization.
-ThreadState::ThreadState(Context *ctx, u32 tid, int unique_id, u64 epoch,
+ThreadState::ThreadState(Context *ctx, Tid tid, int unique_id, u64 epoch,
unsigned reuse_count, uptr stk_addr, uptr stk_size,
uptr tls_addr, uptr tls_size)
: fast_state(tid, epoch)
@@ -155,16 +146,49 @@ ThreadState::ThreadState(Context *ctx, u32 tid, int unique_id, u64 epoch,
last_sleep_clock(tid)
#endif
{
+ CHECK_EQ(reinterpret_cast<uptr>(this) % SANITIZER_CACHE_LINE_SIZE, 0);
+#if !SANITIZER_GO
+ shadow_stack_pos = shadow_stack;
+ shadow_stack_end = shadow_stack + kShadowStackSize;
+#else
+ // Setup dynamic shadow stack.
+ const int kInitStackSize = 8;
+ shadow_stack = (uptr *)Alloc(kInitStackSize * sizeof(uptr));
+ shadow_stack_pos = shadow_stack;
+ shadow_stack_end = shadow_stack + kInitStackSize;
+#endif
}
#if !SANITIZER_GO
-static void MemoryProfiler(Context *ctx, fd_t fd, int i) {
- uptr n_threads;
- uptr n_running_threads;
- ctx->thread_registry->GetNumberOfThreads(&n_threads, &n_running_threads);
+void MemoryProfiler(u64 uptime) {
+ if (ctx->memprof_fd == kInvalidFd)
+ return;
InternalMmapVector<char> buf(4096);
- WriteMemoryProfile(buf.data(), buf.size(), n_threads, n_running_threads);
- WriteToFile(fd, buf.data(), internal_strlen(buf.data()));
+ WriteMemoryProfile(buf.data(), buf.size(), uptime);
+ WriteToFile(ctx->memprof_fd, buf.data(), internal_strlen(buf.data()));
+}
+
+void InitializeMemoryProfiler() {
+ ctx->memprof_fd = kInvalidFd;
+ const char *fname = flags()->profile_memory;
+ if (!fname || !fname[0])
+ return;
+ if (internal_strcmp(fname, "stdout") == 0) {
+ ctx->memprof_fd = 1;
+ } else if (internal_strcmp(fname, "stderr") == 0) {
+ ctx->memprof_fd = 2;
+ } else {
+ InternalScopedString filename;
+ filename.append("%s.%d", fname, (int)internal_getpid());
+ ctx->memprof_fd = OpenFile(filename.data(), WrOnly);
+ if (ctx->memprof_fd == kInvalidFd) {
+ Printf("ThreadSanitizer: failed to open memory profile file '%s'\n",
+ filename.data());
+ return;
+ }
+ }
+ MemoryProfiler(0);
+ MaybeSpawnBackgroundThread();
}
static void *BackgroundThread(void *arg) {
@@ -172,28 +196,9 @@ static void *BackgroundThread(void *arg) {
// We don't use ScopedIgnoreInterceptors, because we want ignores to be
// enabled even when the thread function exits (e.g. during pthread thread
// shutdown code).
- cur_thread_init();
- cur_thread()->ignore_interceptors++;
+ cur_thread_init()->ignore_interceptors++;
const u64 kMs2Ns = 1000 * 1000;
-
- fd_t mprof_fd = kInvalidFd;
- if (flags()->profile_memory && flags()->profile_memory[0]) {
- if (internal_strcmp(flags()->profile_memory, "stdout") == 0) {
- mprof_fd = 1;
- } else if (internal_strcmp(flags()->profile_memory, "stderr") == 0) {
- mprof_fd = 2;
- } else {
- InternalScopedString filename;
- filename.append("%s.%d", flags()->profile_memory, (int)internal_getpid());
- fd_t fd = OpenFile(filename.data(), WrOnly);
- if (fd == kInvalidFd) {
- Printf("ThreadSanitizer: failed to open memory profile file '%s'\n",
- filename.data());
- } else {
- mprof_fd = fd;
- }
- }
- }
+ const u64 start = NanoTime();
u64 last_flush = NanoTime();
uptr last_rss = 0;
@@ -211,7 +216,6 @@ static void *BackgroundThread(void *arg) {
last_flush = NanoTime();
}
}
- // GetRSS can be expensive on huge programs, so don't do it every 100ms.
if (flags()->memory_limit_mb > 0) {
uptr rss = GetRSS();
uptr limit = uptr(flags()->memory_limit_mb) << 20;
@@ -227,9 +231,7 @@ static void *BackgroundThread(void *arg) {
last_rss = rss;
}
- // Write memory profile if requested.
- if (mprof_fd != kInvalidFd)
- MemoryProfiler(ctx, mprof_fd, i);
+ MemoryProfiler(now - start);
// Flush symbolizer cache if requested.
if (flags()->flush_symbolizer_ms > 0) {
@@ -260,7 +262,8 @@ static void StopBackgroundThread() {
#endif
void DontNeedShadowFor(uptr addr, uptr size) {
- ReleaseMemoryPagesToOS(MemToShadow(addr), MemToShadow(addr + size));
+ ReleaseMemoryPagesToOS(reinterpret_cast<uptr>(MemToShadow(addr)),
+ reinterpret_cast<uptr>(MemToShadow(addr + size)));
}
#if !SANITIZER_GO
@@ -297,7 +300,7 @@ void MapShadow(uptr addr, uptr size) {
"meta shadow"))
Die();
} else {
- // Mapping continous heap.
+ // Mapping continuous heap.
// Windows wants 64K alignment.
meta_begin = RoundDownTo(meta_begin, 64 << 10);
meta_end = RoundUpTo(meta_end, 64 << 10);
@@ -310,58 +313,22 @@ void MapShadow(uptr addr, uptr size) {
Die();
mapped_meta_end = meta_end;
}
- VPrintf(2, "mapped meta shadow for (%p-%p) at (%p-%p)\n",
- addr, addr+size, meta_begin, meta_end);
+ VPrintf(2, "mapped meta shadow for (0x%zx-0x%zx) at (0x%zx-0x%zx)\n", addr,
+ addr + size, meta_begin, meta_end);
}
void MapThreadTrace(uptr addr, uptr size, const char *name) {
- DPrintf("#0: Mapping trace at %p-%p(0x%zx)\n", addr, addr + size, size);
+ DPrintf("#0: Mapping trace at 0x%zx-0x%zx(0x%zx)\n", addr, addr + size, size);
CHECK_GE(addr, TraceMemBeg());
CHECK_LE(addr + size, TraceMemEnd());
CHECK_EQ(addr, addr & ~((64 << 10) - 1)); // windows wants 64K alignment
if (!MmapFixedSuperNoReserve(addr, size, name)) {
- Printf("FATAL: ThreadSanitizer can not mmap thread trace (%p/%p)\n",
- addr, size);
+ Printf("FATAL: ThreadSanitizer can not mmap thread trace (0x%zx/0x%zx)\n",
+ addr, size);
Die();
}
}
-static void CheckShadowMapping() {
- uptr beg, end;
- for (int i = 0; GetUserRegion(i, &beg, &end); i++) {
- // Skip cases for empty regions (heap definition for architectures that
- // do not use 64-bit allocator).
- if (beg == end)
- continue;
- VPrintf(3, "checking shadow region %p-%p\n", beg, end);
- uptr prev = 0;
- for (uptr p0 = beg; p0 <= end; p0 += (end - beg) / 4) {
- for (int x = -(int)kShadowCell; x <= (int)kShadowCell; x += kShadowCell) {
- const uptr p = RoundDown(p0 + x, kShadowCell);
- if (p < beg || p >= end)
- continue;
- const uptr s = MemToShadow(p);
- const uptr m = (uptr)MemToMeta(p);
- VPrintf(3, " checking pointer %p: shadow=%p meta=%p\n", p, s, m);
- CHECK(IsAppMem(p));
- CHECK(IsShadowMem(s));
- CHECK_EQ(p, ShadowToMem(s));
- CHECK(IsMetaMem(m));
- if (prev) {
- // Ensure that shadow and meta mappings are linear within a single
- // user range. Lots of code that processes memory ranges assumes it.
- const uptr prev_s = MemToShadow(prev);
- const uptr prev_m = (uptr)MemToMeta(prev);
- CHECK_EQ(s - prev_s, (p - prev) * kShadowMultiplier);
- CHECK_EQ((m - prev_m) / kMetaShadowSize,
- (p - prev) / kMetaShadowCell);
- }
- prev = p;
- }
- }
- }
-}
-
#if !SANITIZER_GO
static void OnStackUnwind(const SignalContext &sig, const void *,
BufferedStackTrace *stack) {
@@ -386,9 +353,10 @@ void CheckUnwind() {
PrintCurrentStackSlow(StackTrace::GetCurrentPc());
}
+bool is_initialized;
+
void Initialize(ThreadState *thr) {
// Thread safe because done before all threads exist.
- static bool is_initialized = false;
if (is_initialized)
return;
is_initialized = true;
@@ -420,9 +388,7 @@ void Initialize(ThreadState *thr) {
Processor *proc = ProcCreate();
ProcWire(proc, thr);
InitializeInterceptors();
- CheckShadowMapping();
InitializePlatform();
- InitializeMutex();
InitializeDynamicAnnotations();
#if !SANITIZER_GO
InitializeShadowMemory();
@@ -441,8 +407,8 @@ void Initialize(ThreadState *thr) {
(int)internal_getpid());
// Initialize thread 0.
- int tid = ThreadCreate(thr, 0, 0, true);
- CHECK_EQ(tid, 0);
+ Tid tid = ThreadCreate(thr, 0, 0, true);
+ CHECK_EQ(tid, kMainTid);
ThreadStart(thr, tid, GetTid(), ThreadType::Regular);
#if TSAN_CONTAINS_UBSAN
__ubsan::InitAsPlugin();
@@ -451,6 +417,7 @@ void Initialize(ThreadState *thr) {
#if !SANITIZER_GO
Symbolizer::LateInitialize();
+ InitializeMemoryProfiler();
#endif
if (flags()->stop_on_start) {
@@ -507,18 +474,8 @@ int Finalize(ThreadState *thr) {
#endif
}
- if (ctx->nmissed_expected) {
- failed = true;
- Printf("ThreadSanitizer: missed %d expected races\n",
- ctx->nmissed_expected);
- }
-
if (common_flags()->print_suppressions)
PrintMatchedSuppressions();
-#if !SANITIZER_GO
- if (flags()->print_benign)
- PrintMatchedBenignRaces();
-#endif
failed = OnFinalize(failed);
@@ -527,7 +484,7 @@ int Finalize(ThreadState *thr) {
#if !SANITIZER_GO
void ForkBefore(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS {
- ctx->thread_registry->Lock();
+ ctx->thread_registry.Lock();
ctx->report_mtx.Lock();
ScopedErrorReportLock::Lock();
// Suppress all reports in the pthread_atfork callbacks.
@@ -546,7 +503,7 @@ void ForkParentAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS {
thr->ignore_interceptors--;
ScopedErrorReportLock::Unlock();
ctx->report_mtx.Unlock();
- ctx->thread_registry->Unlock();
+ ctx->thread_registry.Unlock();
}
void ForkChildAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS {
@@ -554,10 +511,10 @@ void ForkChildAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS {
thr->ignore_interceptors--;
ScopedErrorReportLock::Unlock();
ctx->report_mtx.Unlock();
- ctx->thread_registry->Unlock();
+ ctx->thread_registry.Unlock();
uptr nthread = 0;
- ctx->thread_registry->GetNumberOfThreads(0, 0, &nthread /* alive threads */);
+ ctx->thread_registry.GetNumberOfThreads(0, 0, &nthread /* alive threads */);
VPrintf(1, "ThreadSanitizer: forked new process with pid %d,"
" parent had %d threads\n", (int)internal_getpid(), (int)nthread);
if (nthread == 1) {
@@ -579,19 +536,18 @@ NOINLINE
void GrowShadowStack(ThreadState *thr) {
const int sz = thr->shadow_stack_end - thr->shadow_stack;
const int newsz = 2 * sz;
- uptr *newstack = (uptr*)internal_alloc(MBlockShadowStack,
- newsz * sizeof(uptr));
+ auto *newstack = (uptr *)Alloc(newsz * sizeof(uptr));
internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr));
- internal_free(thr->shadow_stack);
+ Free(thr->shadow_stack);
thr->shadow_stack = newstack;
thr->shadow_stack_pos = newstack + sz;
thr->shadow_stack_end = newstack + newsz;
}
#endif
-u32 CurrentStackId(ThreadState *thr, uptr pc) {
+StackID CurrentStackId(ThreadState *thr, uptr pc) {
if (!thr->is_inited) // May happen during bootstrap.
- return 0;
+ return kInvalidStackID;
if (pc != 0) {
#if !SANITIZER_GO
DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
@@ -602,13 +558,195 @@ u32 CurrentStackId(ThreadState *thr, uptr pc) {
thr->shadow_stack_pos[0] = pc;
thr->shadow_stack_pos++;
}
- u32 id = StackDepotPut(
+ StackID id = StackDepotPut(
StackTrace(thr->shadow_stack, thr->shadow_stack_pos - thr->shadow_stack));
if (pc != 0)
thr->shadow_stack_pos--;
return id;
}
+namespace v3 {
+
+ALWAYS_INLINE USED bool TryTraceMemoryAccess(ThreadState *thr, uptr pc,
+ uptr addr, uptr size,
+ AccessType typ) {
+ DCHECK(size == 1 || size == 2 || size == 4 || size == 8);
+ if (!kCollectHistory)
+ return true;
+ EventAccess *ev;
+ if (UNLIKELY(!TraceAcquire(thr, &ev)))
+ return false;
+ u64 size_log = size == 1 ? 0 : size == 2 ? 1 : size == 4 ? 2 : 3;
+ uptr pc_delta = pc - thr->trace_prev_pc + (1 << (EventAccess::kPCBits - 1));
+ thr->trace_prev_pc = pc;
+ if (LIKELY(pc_delta < (1 << EventAccess::kPCBits))) {
+ ev->is_access = 1;
+ ev->is_read = !!(typ & kAccessRead);
+ ev->is_atomic = !!(typ & kAccessAtomic);
+ ev->size_log = size_log;
+ ev->pc_delta = pc_delta;
+ DCHECK_EQ(ev->pc_delta, pc_delta);
+ ev->addr = CompressAddr(addr);
+ TraceRelease(thr, ev);
+ return true;
+ }
+ auto *evex = reinterpret_cast<EventAccessExt *>(ev);
+ evex->is_access = 0;
+ evex->is_func = 0;
+ evex->type = EventType::kAccessExt;
+ evex->is_read = !!(typ & kAccessRead);
+ evex->is_atomic = !!(typ & kAccessAtomic);
+ evex->size_log = size_log;
+ evex->addr = CompressAddr(addr);
+ evex->pc = pc;
+ TraceRelease(thr, evex);
+ return true;
+}
+
+ALWAYS_INLINE USED bool TryTraceMemoryAccessRange(ThreadState *thr, uptr pc,
+ uptr addr, uptr size,
+ AccessType typ) {
+ if (!kCollectHistory)
+ return true;
+ EventAccessRange *ev;
+ if (UNLIKELY(!TraceAcquire(thr, &ev)))
+ return false;
+ thr->trace_prev_pc = pc;
+ ev->is_access = 0;
+ ev->is_func = 0;
+ ev->type = EventType::kAccessRange;
+ ev->is_read = !!(typ & kAccessRead);
+ ev->is_free = !!(typ & kAccessFree);
+ ev->size_lo = size;
+ ev->pc = CompressAddr(pc);
+ ev->addr = CompressAddr(addr);
+ ev->size_hi = size >> EventAccessRange::kSizeLoBits;
+ TraceRelease(thr, ev);
+ return true;
+}
+
+void TraceMemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, uptr size,
+ AccessType typ) {
+ if (LIKELY(TryTraceMemoryAccessRange(thr, pc, addr, size, typ)))
+ return;
+ TraceSwitchPart(thr);
+ UNUSED bool res = TryTraceMemoryAccessRange(thr, pc, addr, size, typ);
+ DCHECK(res);
+}
+
+void TraceFunc(ThreadState *thr, uptr pc) {
+ if (LIKELY(TryTraceFunc(thr, pc)))
+ return;
+ TraceSwitchPart(thr);
+ UNUSED bool res = TryTraceFunc(thr, pc);
+ DCHECK(res);
+}
+
+void TraceMutexLock(ThreadState *thr, EventType type, uptr pc, uptr addr,
+ StackID stk) {
+ DCHECK(type == EventType::kLock || type == EventType::kRLock);
+ if (!kCollectHistory)
+ return;
+ EventLock ev;
+ ev.is_access = 0;
+ ev.is_func = 0;
+ ev.type = type;
+ ev.pc = CompressAddr(pc);
+ ev.stack_lo = stk;
+ ev.stack_hi = stk >> EventLock::kStackIDLoBits;
+ ev._ = 0;
+ ev.addr = CompressAddr(addr);
+ TraceEvent(thr, ev);
+}
+
+void TraceMutexUnlock(ThreadState *thr, uptr addr) {
+ if (!kCollectHistory)
+ return;
+ EventUnlock ev;
+ ev.is_access = 0;
+ ev.is_func = 0;
+ ev.type = EventType::kUnlock;
+ ev._ = 0;
+ ev.addr = CompressAddr(addr);
+ TraceEvent(thr, ev);
+}
+
+void TraceTime(ThreadState *thr) {
+ if (!kCollectHistory)
+ return;
+ EventTime ev;
+ ev.is_access = 0;
+ ev.is_func = 0;
+ ev.type = EventType::kTime;
+ ev.sid = static_cast<u64>(thr->sid);
+ ev.epoch = static_cast<u64>(thr->epoch);
+ ev._ = 0;
+ TraceEvent(thr, ev);
+}
+
+NOINLINE
+void TraceSwitchPart(ThreadState *thr) {
+ Trace *trace = &thr->tctx->trace;
+ Event *pos = reinterpret_cast<Event *>(atomic_load_relaxed(&thr->trace_pos));
+ DCHECK_EQ(reinterpret_cast<uptr>(pos + 1) & TracePart::kAlignment, 0);
+ auto *part = trace->parts.Back();
+ DPrintf("TraceSwitchPart part=%p pos=%p\n", part, pos);
+ if (part) {
+ // We can get here when we still have space in the current trace part.
+ // The fast-path check in TraceAcquire has false positives in the middle of
+ // the part. Check if we are indeed at the end of the current part or not,
+ // and fill any gaps with NopEvent's.
+ Event *end = &part->events[TracePart::kSize];
+ DCHECK_GE(pos, &part->events[0]);
+ DCHECK_LE(pos, end);
+ if (pos + 1 < end) {
+ if ((reinterpret_cast<uptr>(pos) & TracePart::kAlignment) ==
+ TracePart::kAlignment)
+ *pos++ = NopEvent;
+ *pos++ = NopEvent;
+ DCHECK_LE(pos + 2, end);
+ atomic_store_relaxed(&thr->trace_pos, reinterpret_cast<uptr>(pos));
+ // Ensure we setup trace so that the next TraceAcquire
+ // won't detect trace part end.
+ Event *ev;
+ CHECK(TraceAcquire(thr, &ev));
+ return;
+ }
+ // We are indeed at the end.
+ for (; pos < end; pos++) *pos = NopEvent;
+ }
+#if !SANITIZER_GO
+ if (ctx->after_multithreaded_fork) {
+ // We just need to survive till exec.
+ CHECK(part);
+ atomic_store_relaxed(&thr->trace_pos,
+ reinterpret_cast<uptr>(&part->events[0]));
+ return;
+ }
+#endif
+ part = new (MmapOrDie(sizeof(TracePart), "TracePart")) TracePart();
+ part->trace = trace;
+ thr->trace_prev_pc = 0;
+ {
+ Lock lock(&trace->mtx);
+ trace->parts.PushBack(part);
+ atomic_store_relaxed(&thr->trace_pos,
+ reinterpret_cast<uptr>(&part->events[0]));
+ }
+ // Make this part self-sufficient by restoring the current stack
+ // and mutex set in the beginning of the trace.
+ TraceTime(thr);
+ for (uptr *pos = &thr->shadow_stack[0]; pos < thr->shadow_stack_pos; pos++)
+ CHECK(TryTraceFunc(thr, *pos));
+ for (uptr i = 0; i < thr->mset.Size(); i++) {
+ MutexSet::Desc d = thr->mset.Get(i);
+ TraceMutexLock(thr, d.write ? EventType::kLock : EventType::kRLock, 0,
+ d.addr, d.stack_id);
+ }
+}
+
+} // namespace v3
+
void TraceSwitch(ThreadState *thr) {
#if !SANITIZER_GO
if (ctx->after_multithreaded_fork)
@@ -625,9 +763,7 @@ void TraceSwitch(ThreadState *thr) {
thr->nomalloc--;
}
-Trace *ThreadTrace(int tid) {
- return (Trace*)GetThreadTraceHeader(tid);
-}
+Trace *ThreadTrace(Tid tid) { return (Trace *)GetThreadTraceHeader(tid); }
uptr TraceTopPC(ThreadState *thr) {
Event *events = (Event*)GetThreadTrace(thr->tid);
@@ -716,28 +852,28 @@ void MemoryAccessImpl1(ThreadState *thr, uptr addr,
// threads, which is not enough for the unrolled loop.
#if SANITIZER_DEBUG
for (int idx = 0; idx < 4; idx++) {
-#include "tsan_update_shadow_word_inl.h"
+# include "tsan_update_shadow_word.inc"
}
#else
int idx = 0;
-#include "tsan_update_shadow_word_inl.h"
+# include "tsan_update_shadow_word.inc"
idx = 1;
if (stored) {
-#include "tsan_update_shadow_word_inl.h"
+# include "tsan_update_shadow_word.inc"
} else {
-#include "tsan_update_shadow_word_inl.h"
+# include "tsan_update_shadow_word.inc"
}
idx = 2;
if (stored) {
-#include "tsan_update_shadow_word_inl.h"
+# include "tsan_update_shadow_word.inc"
} else {
-#include "tsan_update_shadow_word_inl.h"
+# include "tsan_update_shadow_word.inc"
}
idx = 3;
if (stored) {
-#include "tsan_update_shadow_word_inl.h"
+# include "tsan_update_shadow_word.inc"
} else {
-#include "tsan_update_shadow_word_inl.h"
+# include "tsan_update_shadow_word.inc"
}
#endif
@@ -753,8 +889,11 @@ void MemoryAccessImpl1(ThreadState *thr, uptr addr,
return;
}
-void UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr,
- int size, bool kAccessIsWrite, bool kIsAtomic) {
+void UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr, uptr size,
+ AccessType typ) {
+ DCHECK(!(typ & kAccessAtomic));
+ const bool kAccessIsWrite = !(typ & kAccessRead);
+ const bool kIsAtomic = false;
while (size) {
int size1 = 1;
int kAccessSizeLog = kSizeLog1;
@@ -789,10 +928,11 @@ bool ContainsSameAccessSlow(u64 *s, u64 a, u64 sync_epoch, bool is_write) {
return false;
}
-#if defined(__SSE3__)
-#define SHUF(v0, v1, i0, i1, i2, i3) _mm_castps_si128(_mm_shuffle_ps( \
- _mm_castsi128_ps(v0), _mm_castsi128_ps(v1), \
- (i0)*1 + (i1)*4 + (i2)*16 + (i3)*64))
+#if TSAN_VECTORIZE
+# define SHUF(v0, v1, i0, i1, i2, i3) \
+ _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(v0), \
+ _mm_castsi128_ps(v1), \
+ (i0)*1 + (i1)*4 + (i2)*16 + (i3)*64))
ALWAYS_INLINE
bool ContainsSameAccessFast(u64 *s, u64 a, u64 sync_epoch, bool is_write) {
// This is an optimized version of ContainsSameAccessSlow.
@@ -849,7 +989,7 @@ bool ContainsSameAccessFast(u64 *s, u64 a, u64 sync_epoch, bool is_write) {
ALWAYS_INLINE
bool ContainsSameAccess(u64 *s, u64 a, u64 sync_epoch, bool is_write) {
-#if defined(__SSE3__)
+#if TSAN_VECTORIZE
bool res = ContainsSameAccessFast(s, a, sync_epoch, is_write);
// NOTE: this check can fail if the shadow is concurrently mutated
// by other threads. But it still can be useful if you modify
@@ -864,7 +1004,7 @@ bool ContainsSameAccess(u64 *s, u64 a, u64 sync_epoch, bool is_write) {
ALWAYS_INLINE USED
void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic) {
- u64 *shadow_mem = (u64*)MemToShadow(addr);
+ RawShadow *shadow_mem = MemToShadow(addr);
DPrintf2("#%d: MemoryAccess: @%p %p size=%d"
" is_write=%d shadow_mem=%p {%zx, %zx, %zx, %zx}\n",
(int)thr->fast_state.tid(), (void*)pc, (void*)addr,
@@ -876,9 +1016,9 @@ void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
Printf("Access to non app mem %zx\n", addr);
DCHECK(IsAppMem(addr));
}
- if (!IsShadowMem((uptr)shadow_mem)) {
+ if (!IsShadowMem(shadow_mem)) {
Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
- DCHECK(IsShadowMem((uptr)shadow_mem));
+ DCHECK(IsShadowMem(shadow_mem));
}
#endif
@@ -953,9 +1093,9 @@ static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
size = (size + (kShadowCell - 1)) & ~(kShadowCell - 1);
// UnmapOrDie/MmapFixedNoReserve does not work on Windows.
if (SANITIZER_WINDOWS || size < common_flags()->clear_shadow_mmap_threshold) {
- u64 *p = (u64*)MemToShadow(addr);
- CHECK(IsShadowMem((uptr)p));
- CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1)));
+ RawShadow *p = MemToShadow(addr);
+ CHECK(IsShadowMem(p));
+ CHECK(IsShadowMem(p + size * kShadowCnt / kShadowCell - 1));
// FIXME: may overwrite a part outside the region
for (uptr i = 0; i < size / kShadowCell * kShadowCnt;) {
p[i++] = val;
@@ -965,9 +1105,9 @@ static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
} else {
// The region is big, reset only beginning and end.
const uptr kPageSize = GetPageSizeCached();
- u64 *begin = (u64*)MemToShadow(addr);
- u64 *end = begin + size / kShadowCell * kShadowCnt;
- u64 *p = begin;
+ RawShadow *begin = MemToShadow(addr);
+ RawShadow *end = begin + size / kShadowCell * kShadowCnt;
+ RawShadow *p = begin;
// Set at least first kPageSize/2 to page boundary.
while ((p < begin + kPageSize / kShadowSize / 2) || ((uptr)p % kPageSize)) {
*p++ = val;
@@ -975,7 +1115,7 @@ static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
*p++ = 0;
}
// Reset middle part.
- u64 *p1 = p;
+ RawShadow *p1 = p;
p = RoundDown(end, kPageSize);
if (!MmapFixedSuperNoReserve((uptr)p1, (uptr)p - (uptr)p1))
Die();
@@ -1070,18 +1210,18 @@ void FuncExit(ThreadState *thr) {
thr->shadow_stack_pos--;
}
-void ThreadIgnoreBegin(ThreadState *thr, uptr pc, bool save_stack) {
+void ThreadIgnoreBegin(ThreadState *thr, uptr pc) {
DPrintf("#%d: ThreadIgnoreBegin\n", thr->tid);
thr->ignore_reads_and_writes++;
CHECK_GT(thr->ignore_reads_and_writes, 0);
thr->fast_state.SetIgnoreBit();
#if !SANITIZER_GO
- if (save_stack && !ctx->after_multithreaded_fork)
+ if (pc && !ctx->after_multithreaded_fork)
thr->mop_ignore_set.Add(CurrentStackId(thr, pc));
#endif
}
-void ThreadIgnoreEnd(ThreadState *thr, uptr pc) {
+void ThreadIgnoreEnd(ThreadState *thr) {
DPrintf("#%d: ThreadIgnoreEnd\n", thr->tid);
CHECK_GT(thr->ignore_reads_and_writes, 0);
thr->ignore_reads_and_writes--;
@@ -1101,17 +1241,17 @@ uptr __tsan_testonly_shadow_stack_current_size() {
}
#endif
-void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc, bool save_stack) {
+void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc) {
DPrintf("#%d: ThreadIgnoreSyncBegin\n", thr->tid);
thr->ignore_sync++;
CHECK_GT(thr->ignore_sync, 0);
#if !SANITIZER_GO
- if (save_stack && !ctx->after_multithreaded_fork)
+ if (pc && !ctx->after_multithreaded_fork)
thr->sync_ignore_set.Add(CurrentStackId(thr, pc));
#endif
}
-void ThreadIgnoreSyncEnd(ThreadState *thr, uptr pc) {
+void ThreadIgnoreSyncEnd(ThreadState *thr) {
DPrintf("#%d: ThreadIgnoreSyncEnd\n", thr->tid);
CHECK_GT(thr->ignore_sync, 0);
thr->ignore_sync--;
@@ -1133,7 +1273,28 @@ void build_consistency_release() {}
} // namespace __tsan
+#if SANITIZER_CHECK_DEADLOCKS
+namespace __sanitizer {
+using namespace __tsan;
+MutexMeta mutex_meta[] = {
+ {MutexInvalid, "Invalid", {}},
+ {MutexThreadRegistry, "ThreadRegistry", {}},
+ {MutexTypeTrace, "Trace", {MutexLeaf}},
+ {MutexTypeReport, "Report", {MutexTypeSyncVar}},
+ {MutexTypeSyncVar, "SyncVar", {}},
+ {MutexTypeAnnotations, "Annotations", {}},
+ {MutexTypeAtExit, "AtExit", {MutexTypeSyncVar}},
+ {MutexTypeFired, "Fired", {MutexLeaf}},
+ {MutexTypeRacy, "Racy", {MutexLeaf}},
+ {MutexTypeGlobalProc, "GlobalProc", {}},
+ {},
+};
+
+void PrintMutexPC(uptr pc) { StackTrace(&pc, 1).Print(); }
+} // namespace __sanitizer
+#endif
+
#if !SANITIZER_GO
// Must be included in this file to make sure everything is inlined.
-#include "tsan_interface_inl.h"
+# include "tsan_interface.inc"
#endif
diff --git a/libsanitizer/tsan/tsan_rtl.h b/libsanitizer/tsan/tsan_rtl.h
index 6576d40..669c4ac 100644
--- a/libsanitizer/tsan/tsan_rtl.h
+++ b/libsanitizer/tsan/tsan_rtl.h
@@ -37,14 +37,15 @@
#include "tsan_clock.h"
#include "tsan_defs.h"
#include "tsan_flags.h"
+#include "tsan_ignoreset.h"
#include "tsan_mman.h"
-#include "tsan_sync.h"
-#include "tsan_trace.h"
-#include "tsan_report.h"
-#include "tsan_platform.h"
#include "tsan_mutexset.h"
-#include "tsan_ignoreset.h"
+#include "tsan_platform.h"
+#include "tsan_report.h"
+#include "tsan_shadow.h"
#include "tsan_stack_trace.h"
+#include "tsan_sync.h"
+#include "tsan_trace.h"
#if SANITIZER_WORDSIZE != 64
# error "ThreadSanitizer is supported only on 64-bit platforms"
@@ -69,6 +70,11 @@ struct AP32 {
typedef SizeClassAllocator32<AP32> PrimaryAllocator;
#else
struct AP64 { // Allocator64 parameters. Deliberately using a short name.
+# if defined(__s390x__)
+ typedef MappingS390x Mapping;
+# else
+ typedef Mapping48AddressSpace Mapping;
+# endif
static const uptr kSpaceBeg = Mapping::kHeapMemBeg;
static const uptr kSpaceSize = Mapping::kHeapMemEnd - Mapping::kHeapMemBeg;
static const uptr kMetadataSize = 0;
@@ -84,240 +90,6 @@ typedef Allocator::AllocatorCache AllocatorCache;
Allocator *allocator();
#endif
-const u64 kShadowRodata = (u64)-1; // .rodata shadow marker
-
-// FastState (from most significant bit):
-// ignore : 1
-// tid : kTidBits
-// unused : -
-// history_size : 3
-// epoch : kClkBits
-class FastState {
- public:
- FastState(u64 tid, u64 epoch) {
- x_ = tid << kTidShift;
- x_ |= epoch;
- DCHECK_EQ(tid, this->tid());
- DCHECK_EQ(epoch, this->epoch());
- DCHECK_EQ(GetIgnoreBit(), false);
- }
-
- explicit FastState(u64 x)
- : x_(x) {
- }
-
- u64 raw() const {
- return x_;
- }
-
- u64 tid() const {
- u64 res = (x_ & ~kIgnoreBit) >> kTidShift;
- return res;
- }
-
- u64 TidWithIgnore() const {
- u64 res = x_ >> kTidShift;
- return res;
- }
-
- u64 epoch() const {
- u64 res = x_ & ((1ull << kClkBits) - 1);
- return res;
- }
-
- void IncrementEpoch() {
- u64 old_epoch = epoch();
- x_ += 1;
- DCHECK_EQ(old_epoch + 1, epoch());
- (void)old_epoch;
- }
-
- void SetIgnoreBit() { x_ |= kIgnoreBit; }
- void ClearIgnoreBit() { x_ &= ~kIgnoreBit; }
- bool GetIgnoreBit() const { return (s64)x_ < 0; }
-
- void SetHistorySize(int hs) {
- CHECK_GE(hs, 0);
- CHECK_LE(hs, 7);
- x_ = (x_ & ~(kHistoryMask << kHistoryShift)) | (u64(hs) << kHistoryShift);
- }
-
- ALWAYS_INLINE
- int GetHistorySize() const {
- return (int)((x_ >> kHistoryShift) & kHistoryMask);
- }
-
- void ClearHistorySize() {
- SetHistorySize(0);
- }
-
- ALWAYS_INLINE
- u64 GetTracePos() const {
- const int hs = GetHistorySize();
- // When hs == 0, the trace consists of 2 parts.
- const u64 mask = (1ull << (kTracePartSizeBits + hs + 1)) - 1;
- return epoch() & mask;
- }
-
- private:
- friend class Shadow;
- static const int kTidShift = 64 - kTidBits - 1;
- static const u64 kIgnoreBit = 1ull << 63;
- static const u64 kFreedBit = 1ull << 63;
- static const u64 kHistoryShift = kClkBits;
- static const u64 kHistoryMask = 7;
- u64 x_;
-};
-
-// Shadow (from most significant bit):
-// freed : 1
-// tid : kTidBits
-// is_atomic : 1
-// is_read : 1
-// size_log : 2
-// addr0 : 3
-// epoch : kClkBits
-class Shadow : public FastState {
- public:
- explicit Shadow(u64 x)
- : FastState(x) {
- }
-
- explicit Shadow(const FastState &s)
- : FastState(s.x_) {
- ClearHistorySize();
- }
-
- void SetAddr0AndSizeLog(u64 addr0, unsigned kAccessSizeLog) {
- DCHECK_EQ((x_ >> kClkBits) & 31, 0);
- DCHECK_LE(addr0, 7);
- DCHECK_LE(kAccessSizeLog, 3);
- x_ |= ((kAccessSizeLog << 3) | addr0) << kClkBits;
- DCHECK_EQ(kAccessSizeLog, size_log());
- DCHECK_EQ(addr0, this->addr0());
- }
-
- void SetWrite(unsigned kAccessIsWrite) {
- DCHECK_EQ(x_ & kReadBit, 0);
- if (!kAccessIsWrite)
- x_ |= kReadBit;
- DCHECK_EQ(kAccessIsWrite, IsWrite());
- }
-
- void SetAtomic(bool kIsAtomic) {
- DCHECK(!IsAtomic());
- if (kIsAtomic)
- x_ |= kAtomicBit;
- DCHECK_EQ(IsAtomic(), kIsAtomic);
- }
-
- bool IsAtomic() const {
- return x_ & kAtomicBit;
- }
-
- bool IsZero() const {
- return x_ == 0;
- }
-
- static inline bool TidsAreEqual(const Shadow s1, const Shadow s2) {
- u64 shifted_xor = (s1.x_ ^ s2.x_) >> kTidShift;
- DCHECK_EQ(shifted_xor == 0, s1.TidWithIgnore() == s2.TidWithIgnore());
- return shifted_xor == 0;
- }
-
- static ALWAYS_INLINE
- bool Addr0AndSizeAreEqual(const Shadow s1, const Shadow s2) {
- u64 masked_xor = ((s1.x_ ^ s2.x_) >> kClkBits) & 31;
- return masked_xor == 0;
- }
-
- static ALWAYS_INLINE bool TwoRangesIntersect(Shadow s1, Shadow s2,
- unsigned kS2AccessSize) {
- bool res = false;
- u64 diff = s1.addr0() - s2.addr0();
- if ((s64)diff < 0) { // s1.addr0 < s2.addr0
- // if (s1.addr0() + size1) > s2.addr0()) return true;
- if (s1.size() > -diff)
- res = true;
- } else {
- // if (s2.addr0() + kS2AccessSize > s1.addr0()) return true;
- if (kS2AccessSize > diff)
- res = true;
- }
- DCHECK_EQ(res, TwoRangesIntersectSlow(s1, s2));
- DCHECK_EQ(res, TwoRangesIntersectSlow(s2, s1));
- return res;
- }
-
- u64 ALWAYS_INLINE addr0() const { return (x_ >> kClkBits) & 7; }
- u64 ALWAYS_INLINE size() const { return 1ull << size_log(); }
- bool ALWAYS_INLINE IsWrite() const { return !IsRead(); }
- bool ALWAYS_INLINE IsRead() const { return x_ & kReadBit; }
-
- // The idea behind the freed bit is as follows.
- // When the memory is freed (or otherwise unaccessible) we write to the shadow
- // values with tid/epoch related to the free and the freed bit set.
- // During memory accesses processing the freed bit is considered
- // as msb of tid. So any access races with shadow with freed bit set
- // (it is as if write from a thread with which we never synchronized before).
- // This allows us to detect accesses to freed memory w/o additional
- // overheads in memory access processing and at the same time restore
- // tid/epoch of free.
- void MarkAsFreed() {
- x_ |= kFreedBit;
- }
-
- bool IsFreed() const {
- return x_ & kFreedBit;
- }
-
- bool GetFreedAndReset() {
- bool res = x_ & kFreedBit;
- x_ &= ~kFreedBit;
- return res;
- }
-
- bool ALWAYS_INLINE IsBothReadsOrAtomic(bool kIsWrite, bool kIsAtomic) const {
- bool v = x_ & ((u64(kIsWrite ^ 1) << kReadShift)
- | (u64(kIsAtomic) << kAtomicShift));
- DCHECK_EQ(v, (!IsWrite() && !kIsWrite) || (IsAtomic() && kIsAtomic));
- return v;
- }
-
- bool ALWAYS_INLINE IsRWNotWeaker(bool kIsWrite, bool kIsAtomic) const {
- bool v = ((x_ >> kReadShift) & 3)
- <= u64((kIsWrite ^ 1) | (kIsAtomic << 1));
- DCHECK_EQ(v, (IsAtomic() < kIsAtomic) ||
- (IsAtomic() == kIsAtomic && !IsWrite() <= !kIsWrite));
- return v;
- }
-
- bool ALWAYS_INLINE IsRWWeakerOrEqual(bool kIsWrite, bool kIsAtomic) const {
- bool v = ((x_ >> kReadShift) & 3)
- >= u64((kIsWrite ^ 1) | (kIsAtomic << 1));
- DCHECK_EQ(v, (IsAtomic() > kIsAtomic) ||
- (IsAtomic() == kIsAtomic && !IsWrite() >= !kIsWrite));
- return v;
- }
-
- private:
- static const u64 kReadShift = 5 + kClkBits;
- static const u64 kReadBit = 1ull << kReadShift;
- static const u64 kAtomicShift = 6 + kClkBits;
- static const u64 kAtomicBit = 1ull << kAtomicShift;
-
- u64 size_log() const { return (x_ >> (3 + kClkBits)) & 3; }
-
- static bool TwoRangesIntersectSlow(const Shadow s1, const Shadow s2) {
- if (s1.addr0() == s2.addr0()) return true;
- if (s1.addr0() < s2.addr0() && s1.addr0() + s1.size() > s2.addr0())
- return true;
- if (s2.addr0() < s1.addr0() && s2.addr0() + s2.size() > s1.addr0())
- return true;
- return false;
- }
-};
-
struct ThreadSignalContext;
struct JmpBuf {
@@ -380,27 +152,30 @@ struct ThreadState {
// We do not distinguish beteween ignoring reads and writes
// for better performance.
int ignore_reads_and_writes;
+ atomic_sint32_t pending_signals;
int ignore_sync;
int suppress_reports;
// Go does not support ignores.
#if !SANITIZER_GO
IgnoreSet mop_ignore_set;
IgnoreSet sync_ignore_set;
-#endif
- // C/C++ uses fixed size shadow stack embed into Trace.
+ // C/C++ uses fixed size shadow stack.
+ uptr shadow_stack[kShadowStackSize];
+#else
// Go uses malloc-allocated shadow stack with dynamic size.
uptr *shadow_stack;
+#endif
uptr *shadow_stack_end;
uptr *shadow_stack_pos;
- u64 *racy_shadow_addr;
- u64 racy_state[2];
+ RawShadow *racy_shadow_addr;
+ RawShadow racy_state[2];
MutexSet mset;
ThreadClock clock;
#if !SANITIZER_GO
Vector<JmpBuf> jmp_bufs;
int ignore_interceptors;
#endif
- const u32 tid;
+ const Tid tid;
const int unique_id;
bool in_symbolizer;
bool in_ignored_lib;
@@ -414,9 +189,6 @@ struct ThreadState {
const uptr tls_size;
ThreadContext *tctx;
-#if SANITIZER_DEBUG && !SANITIZER_GO
- InternalDeadlockDetector internal_deadlock_detector;
-#endif
DDLogicalThread *dd_lt;
// Current wired Processor, or nullptr. Required to handle any events.
@@ -431,7 +203,7 @@ struct ThreadState {
ThreadSignalContext *signal_ctx;
#if !SANITIZER_GO
- u32 last_sleep_stack_id;
+ StackID last_sleep_stack_id;
ThreadClock last_sleep_clock;
#endif
@@ -441,41 +213,49 @@ struct ThreadState {
const ReportDesc *current_report;
- explicit ThreadState(Context *ctx, u32 tid, int unique_id, u64 epoch,
+ // Current position in tctx->trace.Back()->events (Event*).
+ atomic_uintptr_t trace_pos;
+ // PC of the last memory access, used to compute PC deltas in the trace.
+ uptr trace_prev_pc;
+ Sid sid;
+ Epoch epoch;
+
+ explicit ThreadState(Context *ctx, Tid tid, int unique_id, u64 epoch,
unsigned reuse_count, uptr stk_addr, uptr stk_size,
uptr tls_addr, uptr tls_size);
-};
+} ALIGNED(SANITIZER_CACHE_LINE_SIZE);
#if !SANITIZER_GO
#if SANITIZER_MAC || SANITIZER_ANDROID
ThreadState *cur_thread();
void set_cur_thread(ThreadState *thr);
void cur_thread_finalize();
-inline void cur_thread_init() { }
-#else
+inline ThreadState *cur_thread_init() { return cur_thread(); }
+# else
__attribute__((tls_model("initial-exec")))
extern THREADLOCAL char cur_thread_placeholder[];
inline ThreadState *cur_thread() {
return reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current;
}
-inline void cur_thread_init() {
+inline ThreadState *cur_thread_init() {
ThreadState *thr = reinterpret_cast<ThreadState *>(cur_thread_placeholder);
if (UNLIKELY(!thr->current))
thr->current = thr;
+ return thr->current;
}
inline void set_cur_thread(ThreadState *thr) {
reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current = thr;
}
inline void cur_thread_finalize() { }
-#endif // SANITIZER_MAC || SANITIZER_ANDROID
+# endif // SANITIZER_MAC || SANITIZER_ANDROID
#endif // SANITIZER_GO
class ThreadContext final : public ThreadContextBase {
public:
- explicit ThreadContext(int tid);
+ explicit ThreadContext(Tid tid);
~ThreadContext();
ThreadState *thr;
- u32 creation_stack_id;
+ StackID creation_stack_id;
SyncClock sync;
// Epoch at which the thread had started.
// If we see an event from the thread stamped by an older epoch,
@@ -483,6 +263,8 @@ class ThreadContext final : public ThreadContextBase {
u64 epoch0;
u64 epoch1;
+ v3::Trace trace;
+
// Override superclass callbacks.
void OnDead() override;
void OnJoined(void *arg) override;
@@ -495,13 +277,7 @@ class ThreadContext final : public ThreadContextBase {
struct RacyStacks {
MD5Hash hash[2];
- bool operator==(const RacyStacks &other) const {
- if (hash[0] == other.hash[0] && hash[1] == other.hash[1])
- return true;
- if (hash[0] == other.hash[1] && hash[1] == other.hash[0])
- return true;
- return false;
- }
+ bool operator==(const RacyStacks &other) const;
};
struct RacyAddress {
@@ -527,13 +303,12 @@ struct Context {
Mutex report_mtx;
int nreported;
- int nmissed_expected;
atomic_uint64_t last_symbolize_time_ns;
void *background_thread;
atomic_uint32_t stop_background_thread;
- ThreadRegistry *thread_registry;
+ ThreadRegistry thread_registry;
Mutex racy_mtx;
Vector<RacyStacks> racy_stacks;
@@ -546,9 +321,9 @@ struct Context {
ClockAlloc clock_alloc;
Flags flags;
+ fd_t memprof_fd;
- u64 int_alloc_cnt[MBlockTypeCount];
- u64 int_alloc_siz[MBlockTypeCount];
+ Mutex slot_mtx;
};
extern Context *ctx; // The one and the only global runtime context.
@@ -581,12 +356,12 @@ class ScopedReportBase {
const MutexSet *mset);
void AddStack(StackTrace stack, bool suppressable = false);
void AddThread(const ThreadContext *tctx, bool suppressable = false);
- void AddThread(int unique_tid, bool suppressable = false);
- void AddUniqueTid(int unique_tid);
+ void AddThread(Tid unique_tid, bool suppressable = false);
+ void AddUniqueTid(Tid unique_tid);
void AddMutex(const SyncVar *s);
u64 AddMutex(u64 id);
void AddLocation(uptr addr, uptr size);
- void AddSleep(u32 stack_id);
+ void AddSleep(StackID stack_id);
void SetCount(int count);
const ReportDesc *GetReport() const;
@@ -618,7 +393,7 @@ class ScopedReport : public ScopedReportBase {
bool ShouldReport(ThreadState *thr, ReportType typ);
ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack);
-void RestoreStack(int tid, const u64 epoch, VarSizeStackTrace *stk,
+void RestoreStack(Tid tid, const u64 epoch, VarSizeStackTrace *stk,
MutexSet *mset, uptr *tag = nullptr);
// The stack could look like:
@@ -671,7 +446,6 @@ void ReportRace(ThreadState *thr);
bool OutputReport(ThreadState *thr, const ScopedReport &srep);
bool IsFiredSuppression(Context *ctx, ReportType type, StackTrace trace);
bool IsExpectedReport(uptr addr, uptr size);
-void PrintMatchedBenignRaces();
#if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 1
# define DPrintf Printf
@@ -685,10 +459,11 @@ void PrintMatchedBenignRaces();
# define DPrintf2(...)
#endif
-u32 CurrentStackId(ThreadState *thr, uptr pc);
-ReportStack *SymbolizeStackId(u32 stack_id);
+StackID CurrentStackId(ThreadState *thr, uptr pc);
+ReportStack *SymbolizeStackId(StackID stack_id);
void PrintCurrentStack(ThreadState *thr, uptr pc);
void PrintCurrentStackSlow(uptr pc); // uses libunwind
+MBlock *JavaHeapBlock(uptr addr, uptr *start);
void Initialize(ThreadState *thr);
void MaybeSpawnBackgroundThread();
@@ -704,34 +479,44 @@ void MemoryAccessImpl(ThreadState *thr, uptr addr,
u64 *shadow_mem, Shadow cur);
void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
uptr size, bool is_write);
-void MemoryAccessRangeStep(ThreadState *thr, uptr pc, uptr addr,
- uptr size, uptr step, bool is_write);
-void UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr,
- int size, bool kAccessIsWrite, bool kIsAtomic);
+void UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr, uptr size,
+ AccessType typ);
const int kSizeLog1 = 0;
const int kSizeLog2 = 1;
const int kSizeLog4 = 2;
const int kSizeLog8 = 3;
-void ALWAYS_INLINE MemoryRead(ThreadState *thr, uptr pc,
- uptr addr, int kAccessSizeLog) {
- MemoryAccess(thr, pc, addr, kAccessSizeLog, false, false);
-}
-
-void ALWAYS_INLINE MemoryWrite(ThreadState *thr, uptr pc,
- uptr addr, int kAccessSizeLog) {
- MemoryAccess(thr, pc, addr, kAccessSizeLog, true, false);
-}
-
-void ALWAYS_INLINE MemoryReadAtomic(ThreadState *thr, uptr pc,
- uptr addr, int kAccessSizeLog) {
- MemoryAccess(thr, pc, addr, kAccessSizeLog, false, true);
-}
-
-void ALWAYS_INLINE MemoryWriteAtomic(ThreadState *thr, uptr pc,
- uptr addr, int kAccessSizeLog) {
- MemoryAccess(thr, pc, addr, kAccessSizeLog, true, true);
+ALWAYS_INLINE
+void MemoryAccess(ThreadState *thr, uptr pc, uptr addr, uptr size,
+ AccessType typ) {
+ int size_log;
+ switch (size) {
+ case 1:
+ size_log = kSizeLog1;
+ break;
+ case 2:
+ size_log = kSizeLog2;
+ break;
+ case 4:
+ size_log = kSizeLog4;
+ break;
+ default:
+ DCHECK_EQ(size, 8);
+ size_log = kSizeLog8;
+ break;
+ }
+ bool is_write = !(typ & kAccessRead);
+ bool is_atomic = typ & kAccessAtomic;
+ if (typ & kAccessVptr)
+ thr->is_vptr_access = true;
+ if (typ & kAccessFree)
+ thr->is_freeing = true;
+ MemoryAccess(thr, pc, addr, size_log, is_write, is_atomic);
+ if (typ & kAccessVptr)
+ thr->is_vptr_access = false;
+ if (typ & kAccessFree)
+ thr->is_freeing = false;
}
void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size);
@@ -740,26 +525,26 @@ void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size);
void MemoryRangeImitateWriteOrResetRange(ThreadState *thr, uptr pc, uptr addr,
uptr size);
-void ThreadIgnoreBegin(ThreadState *thr, uptr pc, bool save_stack = true);
-void ThreadIgnoreEnd(ThreadState *thr, uptr pc);
-void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc, bool save_stack = true);
-void ThreadIgnoreSyncEnd(ThreadState *thr, uptr pc);
+void ThreadIgnoreBegin(ThreadState *thr, uptr pc);
+void ThreadIgnoreEnd(ThreadState *thr);
+void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc);
+void ThreadIgnoreSyncEnd(ThreadState *thr);
void FuncEntry(ThreadState *thr, uptr pc);
void FuncExit(ThreadState *thr);
-int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached);
-void ThreadStart(ThreadState *thr, int tid, tid_t os_id,
+Tid ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached);
+void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
ThreadType thread_type);
void ThreadFinish(ThreadState *thr);
-int ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid);
-void ThreadJoin(ThreadState *thr, uptr pc, int tid);
-void ThreadDetach(ThreadState *thr, uptr pc, int tid);
+Tid ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid);
+void ThreadJoin(ThreadState *thr, uptr pc, Tid tid);
+void ThreadDetach(ThreadState *thr, uptr pc, Tid tid);
void ThreadFinalize(ThreadState *thr);
void ThreadSetName(ThreadState *thr, const char *name);
int ThreadCount(ThreadState *thr);
-void ProcessPendingSignals(ThreadState *thr);
-void ThreadNotJoined(ThreadState *thr, uptr pc, int tid, uptr uid);
+void ProcessPendingSignalsImpl(ThreadState *thr);
+void ThreadNotJoined(ThreadState *thr, uptr pc, Tid tid, uptr uid);
Processor *ProcCreate();
void ProcDestroy(Processor *proc);
@@ -788,7 +573,7 @@ void Acquire(ThreadState *thr, uptr pc, uptr addr);
// handle Go finalizers. Namely, finalizer goroutine executes AcquireGlobal
// right before executing finalizers. This provides a coarse, but simple
// approximation of the actual required synchronization.
-void AcquireGlobal(ThreadState *thr, uptr pc);
+void AcquireGlobal(ThreadState *thr);
void Release(ThreadState *thr, uptr pc, uptr addr);
void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr);
void ReleaseStore(ThreadState *thr, uptr pc, uptr addr);
@@ -824,7 +609,7 @@ void TraceSwitch(ThreadState *thr);
uptr TraceTopPC(ThreadState *thr);
uptr TraceSize();
uptr TraceParts();
-Trace *ThreadTrace(int tid);
+Trace *ThreadTrace(Tid tid);
extern "C" void __tsan_trace_switch();
void ALWAYS_INLINE TraceAddEvent(ThreadState *thr, FastState fs,
@@ -864,6 +649,111 @@ enum FiberSwitchFlags {
FiberSwitchFlagNoSync = 1 << 0, // __tsan_switch_to_fiber_no_sync
};
+ALWAYS_INLINE void ProcessPendingSignals(ThreadState *thr) {
+ if (UNLIKELY(atomic_load_relaxed(&thr->pending_signals)))
+ ProcessPendingSignalsImpl(thr);
+}
+
+extern bool is_initialized;
+
+ALWAYS_INLINE
+void LazyInitialize(ThreadState *thr) {
+ // If we can use .preinit_array, assume that __tsan_init
+ // called from .preinit_array initializes runtime before
+ // any instrumented code.
+#if !SANITIZER_CAN_USE_PREINIT_ARRAY
+ if (UNLIKELY(!is_initialized))
+ Initialize(thr);
+#endif
+}
+
+namespace v3 {
+
+void TraceSwitchPart(ThreadState *thr);
+bool RestoreStack(Tid tid, EventType type, Sid sid, Epoch epoch, uptr addr,
+ uptr size, AccessType typ, VarSizeStackTrace *pstk,
+ MutexSet *pmset, uptr *ptag);
+
+template <typename EventT>
+ALWAYS_INLINE WARN_UNUSED_RESULT bool TraceAcquire(ThreadState *thr,
+ EventT **ev) {
+ Event *pos = reinterpret_cast<Event *>(atomic_load_relaxed(&thr->trace_pos));
+#if SANITIZER_DEBUG
+ // TraceSwitch acquires these mutexes,
+ // so we lock them here to detect deadlocks more reliably.
+ { Lock lock(&ctx->slot_mtx); }
+ { Lock lock(&thr->tctx->trace.mtx); }
+ TracePart *current = thr->tctx->trace.parts.Back();
+ if (current) {
+ DCHECK_GE(pos, &current->events[0]);
+ DCHECK_LE(pos, &current->events[TracePart::kSize]);
+ } else {
+ DCHECK_EQ(pos, nullptr);
+ }
+#endif
+ // TracePart is allocated with mmap and is at least 4K aligned.
+ // So the following check is a faster way to check for part end.
+ // It may have false positives in the middle of the trace,
+ // they are filtered out in TraceSwitch.
+ if (UNLIKELY(((uptr)(pos + 1) & TracePart::kAlignment) == 0))
+ return false;
+ *ev = reinterpret_cast<EventT *>(pos);
+ return true;
+}
+
+template <typename EventT>
+ALWAYS_INLINE void TraceRelease(ThreadState *thr, EventT *evp) {
+ DCHECK_LE(evp + 1, &thr->tctx->trace.parts.Back()->events[TracePart::kSize]);
+ atomic_store_relaxed(&thr->trace_pos, (uptr)(evp + 1));
+}
+
+template <typename EventT>
+void TraceEvent(ThreadState *thr, EventT ev) {
+ EventT *evp;
+ if (!TraceAcquire(thr, &evp)) {
+ TraceSwitchPart(thr);
+ UNUSED bool res = TraceAcquire(thr, &evp);
+ DCHECK(res);
+ }
+ *evp = ev;
+ TraceRelease(thr, evp);
+}
+
+ALWAYS_INLINE WARN_UNUSED_RESULT bool TryTraceFunc(ThreadState *thr,
+ uptr pc = 0) {
+ if (!kCollectHistory)
+ return true;
+ EventFunc *ev;
+ if (UNLIKELY(!TraceAcquire(thr, &ev)))
+ return false;
+ ev->is_access = 0;
+ ev->is_func = 1;
+ ev->pc = pc;
+ TraceRelease(thr, ev);
+ return true;
+}
+
+WARN_UNUSED_RESULT
+bool TryTraceMemoryAccess(ThreadState *thr, uptr pc, uptr addr, uptr size,
+ AccessType typ);
+WARN_UNUSED_RESULT
+bool TryTraceMemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, uptr size,
+ AccessType typ);
+void TraceMemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, uptr size,
+ AccessType typ);
+void TraceFunc(ThreadState *thr, uptr pc = 0);
+void TraceMutexLock(ThreadState *thr, EventType type, uptr pc, uptr addr,
+ StackID stk);
+void TraceMutexUnlock(ThreadState *thr, uptr addr);
+void TraceTime(ThreadState *thr);
+
+} // namespace v3
+
+#if !SANITIZER_GO
+extern void (*on_initialize)(void);
+extern int (*on_finalize)(int);
+#endif
+
} // namespace __tsan
#endif // TSAN_RTL_H
diff --git a/libsanitizer/tsan/tsan_rtl_amd64.S b/libsanitizer/tsan/tsan_rtl_amd64.S
index 5913aa3..10c0122 100644
--- a/libsanitizer/tsan/tsan_rtl_amd64.S
+++ b/libsanitizer/tsan/tsan_rtl_amd64.S
@@ -13,6 +13,7 @@ ASM_HIDDEN(__tsan_trace_switch)
.globl ASM_SYMBOL(__tsan_trace_switch_thunk)
ASM_SYMBOL(__tsan_trace_switch_thunk):
CFI_STARTPROC
+ _CET_ENDBR
# Save scratch registers.
push %rax
CFI_ADJUST_CFA_OFFSET(8)
@@ -93,6 +94,7 @@ ASM_HIDDEN(__tsan_report_race)
.globl ASM_SYMBOL(__tsan_report_race_thunk)
ASM_SYMBOL(__tsan_report_race_thunk):
CFI_STARTPROC
+ _CET_ENDBR
# Save scratch registers.
push %rax
CFI_ADJUST_CFA_OFFSET(8)
@@ -185,6 +187,7 @@ ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(setjmp))
ASM_SYMBOL_INTERCEPTOR(setjmp):
#endif
CFI_STARTPROC
+ _CET_ENDBR
// save env parameter
push %rdi
CFI_ADJUST_CFA_OFFSET(8)
@@ -226,6 +229,7 @@ ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(setjmp))
ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(_setjmp))
ASM_SYMBOL_INTERCEPTOR(_setjmp):
CFI_STARTPROC
+ _CET_ENDBR
// save env parameter
push %rdi
CFI_ADJUST_CFA_OFFSET(8)
@@ -267,6 +271,7 @@ ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
ASM_SYMBOL_INTERCEPTOR(sigsetjmp):
#endif
CFI_STARTPROC
+ _CET_ENDBR
// save env parameter
push %rdi
CFI_ADJUST_CFA_OFFSET(8)
@@ -323,6 +328,7 @@ ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
ASM_SYMBOL_INTERCEPTOR(__sigsetjmp):
CFI_STARTPROC
+ _CET_ENDBR
// save env parameter
push %rdi
CFI_ADJUST_CFA_OFFSET(8)
diff --git a/libsanitizer/tsan/tsan_rtl_mutex.cpp b/libsanitizer/tsan/tsan_rtl_mutex.cpp
index a214a33..7d6b411 100644
--- a/libsanitizer/tsan/tsan_rtl_mutex.cpp
+++ b/libsanitizer/tsan/tsan_rtl_mutex.cpp
@@ -35,7 +35,7 @@ struct Callback final : public DDCallback {
DDCallback::lt = thr->dd_lt;
}
- u32 Unwind() override { return CurrentStackId(thr, pc); }
+ StackID Unwind() override { return CurrentStackId(thr, pc); }
int UniqueTid() override { return thr->unique_id; }
};
@@ -53,7 +53,7 @@ static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ,
return;
if (!ShouldReport(thr, typ))
return;
- ThreadRegistryLock l(ctx->thread_registry);
+ ThreadRegistryLock l(&ctx->thread_registry);
ScopedReport rep(typ);
rep.AddMutex(mid);
VarSizeStackTrace trace;
@@ -68,46 +68,49 @@ void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
if (!(flagz & MutexFlagLinkerInit) && IsAppMem(addr)) {
CHECK(!thr->is_freeing);
thr->is_freeing = true;
- MemoryWrite(thr, pc, addr, kSizeLog1);
+ MemoryAccess(thr, pc, addr, 1, kAccessWrite);
thr->is_freeing = false;
}
- SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ Lock l(&s->mtx);
s->SetFlags(flagz & MutexCreationFlagMask);
+ // Save stack in the case the sync object was created before as atomic.
if (!SANITIZER_GO && s->creation_stack_id == 0)
s->creation_stack_id = CurrentStackId(thr, pc);
- s->mtx.Unlock();
}
void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
DPrintf("#%d: MutexDestroy %zx\n", thr->tid, addr);
- SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr, true);
- if (s == 0)
- return;
- if ((flagz & MutexFlagLinkerInit)
- || s->IsFlagSet(MutexFlagLinkerInit)
- || ((flagz & MutexFlagNotStatic) && !s->IsFlagSet(MutexFlagNotStatic))) {
- // Destroy is no-op for linker-initialized mutexes.
- s->mtx.Unlock();
- return;
- }
- if (common_flags()->detect_deadlocks) {
- Callback cb(thr, pc);
- ctx->dd->MutexDestroy(&cb, &s->dd);
- ctx->dd->MutexInit(&cb, &s->dd);
- }
bool unlock_locked = false;
- if (flags()->report_destroy_locked && s->owner_tid != kInvalidTid &&
- !s->IsFlagSet(MutexFlagBroken)) {
- s->SetFlags(MutexFlagBroken);
- unlock_locked = true;
+ u64 mid = 0;
+ u64 last_lock = 0;
+ {
+ SyncVar *s = ctx->metamap.GetSyncIfExists(addr);
+ if (s == 0)
+ return;
+ Lock l(&s->mtx);
+ if ((flagz & MutexFlagLinkerInit) || s->IsFlagSet(MutexFlagLinkerInit) ||
+ ((flagz & MutexFlagNotStatic) && !s->IsFlagSet(MutexFlagNotStatic))) {
+ // Destroy is no-op for linker-initialized mutexes.
+ return;
+ }
+ if (common_flags()->detect_deadlocks) {
+ Callback cb(thr, pc);
+ ctx->dd->MutexDestroy(&cb, &s->dd);
+ ctx->dd->MutexInit(&cb, &s->dd);
+ }
+ if (flags()->report_destroy_locked && s->owner_tid != kInvalidTid &&
+ !s->IsFlagSet(MutexFlagBroken)) {
+ s->SetFlags(MutexFlagBroken);
+ unlock_locked = true;
+ }
+ mid = s->GetId();
+ last_lock = s->last_lock;
+ if (!unlock_locked)
+ s->Reset(thr->proc()); // must not reset it before the report is printed
}
- u64 mid = s->GetId();
- u64 last_lock = s->last_lock;
- if (!unlock_locked)
- s->Reset(thr->proc()); // must not reset it before the report is printed
- s->mtx.Unlock();
if (unlock_locked && ShouldReport(thr, ReportTypeMutexDestroyLocked)) {
- ThreadRegistryLock l(ctx->thread_registry);
+ ThreadRegistryLock l(&ctx->thread_registry);
ScopedReport rep(ReportTypeMutexDestroyLocked);
rep.AddMutex(mid);
VarSizeStackTrace trace;
@@ -119,38 +122,35 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
rep.AddLocation(addr, 1);
OutputReport(thr, rep);
- SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr, true);
+ SyncVar *s = ctx->metamap.GetSyncIfExists(addr);
if (s != 0) {
+ Lock l(&s->mtx);
s->Reset(thr->proc());
- s->mtx.Unlock();
}
}
thr->mset.Remove(mid);
// Imitate a memory write to catch unlock-destroy races.
// Do this outside of sync mutex, because it can report a race which locks
// sync mutexes.
- if (IsAppMem(addr)) {
- CHECK(!thr->is_freeing);
- thr->is_freeing = true;
- MemoryWrite(thr, pc, addr, kSizeLog1);
- thr->is_freeing = false;
- }
+ if (IsAppMem(addr))
+ MemoryAccess(thr, pc, addr, 1, kAccessWrite | kAccessFree);
// s will be destroyed and freed in MetaMap::FreeBlock.
}
void MutexPreLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
DPrintf("#%d: MutexPreLock %zx flagz=0x%x\n", thr->tid, addr, flagz);
if (!(flagz & MutexFlagTryLock) && common_flags()->detect_deadlocks) {
- SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, false);
- s->UpdateFlags(flagz);
- if (s->owner_tid != thr->tid) {
- Callback cb(thr, pc);
- ctx->dd->MutexBeforeLock(&cb, &s->dd, true);
- s->mtx.ReadUnlock();
- ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
- } else {
- s->mtx.ReadUnlock();
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ {
+ ReadLock l(&s->mtx);
+ s->UpdateFlags(flagz);
+ if (s->owner_tid != thr->tid) {
+ Callback cb(thr, pc);
+ ctx->dd->MutexBeforeLock(&cb, &s->dd, true);
+ }
}
+ Callback cb(thr, pc);
+ ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
}
}
@@ -162,43 +162,45 @@ void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz, int rec) {
else
rec = 1;
if (IsAppMem(addr))
- MemoryReadAtomic(thr, pc, addr, kSizeLog1);
- SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
- s->UpdateFlags(flagz);
- thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeLock, s->GetId());
- bool report_double_lock = false;
- if (s->owner_tid == kInvalidTid) {
- CHECK_EQ(s->recursion, 0);
- s->owner_tid = thr->tid;
- s->last_lock = thr->fast_state.raw();
- } else if (s->owner_tid == thr->tid) {
- CHECK_GT(s->recursion, 0);
- } else if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
- s->SetFlags(MutexFlagBroken);
- report_double_lock = true;
- }
- const bool first = s->recursion == 0;
- s->recursion += rec;
- if (first) {
- AcquireImpl(thr, pc, &s->clock);
- AcquireImpl(thr, pc, &s->read_clock);
- } else if (!s->IsFlagSet(MutexFlagWriteReentrant)) {
- }
- thr->mset.Add(s->GetId(), true, thr->fast_state.epoch());
+ MemoryAccess(thr, pc, addr, 1, kAccessRead | kAccessAtomic);
+ u64 mid = 0;
bool pre_lock = false;
- if (first && common_flags()->detect_deadlocks) {
- pre_lock = (flagz & MutexFlagDoPreLockOnPostLock) &&
- !(flagz & MutexFlagTryLock);
- Callback cb(thr, pc);
- if (pre_lock)
- ctx->dd->MutexBeforeLock(&cb, &s->dd, true);
- ctx->dd->MutexAfterLock(&cb, &s->dd, true, flagz & MutexFlagTryLock);
+ bool first = false;
+ bool report_double_lock = false;
+ {
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ Lock l(&s->mtx);
+ s->UpdateFlags(flagz);
+ thr->fast_state.IncrementEpoch();
+ TraceAddEvent(thr, thr->fast_state, EventTypeLock, s->GetId());
+ if (s->owner_tid == kInvalidTid) {
+ CHECK_EQ(s->recursion, 0);
+ s->owner_tid = thr->tid;
+ s->last_lock = thr->fast_state.raw();
+ } else if (s->owner_tid == thr->tid) {
+ CHECK_GT(s->recursion, 0);
+ } else if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
+ s->SetFlags(MutexFlagBroken);
+ report_double_lock = true;
+ }
+ first = s->recursion == 0;
+ s->recursion += rec;
+ if (first) {
+ AcquireImpl(thr, pc, &s->clock);
+ AcquireImpl(thr, pc, &s->read_clock);
+ } else if (!s->IsFlagSet(MutexFlagWriteReentrant)) {
+ }
+ thr->mset.Add(s->GetId(), true, thr->fast_state.epoch());
+ if (first && common_flags()->detect_deadlocks) {
+ pre_lock =
+ (flagz & MutexFlagDoPreLockOnPostLock) && !(flagz & MutexFlagTryLock);
+ Callback cb(thr, pc);
+ if (pre_lock)
+ ctx->dd->MutexBeforeLock(&cb, &s->dd, true);
+ ctx->dd->MutexAfterLock(&cb, &s->dd, true, flagz & MutexFlagTryLock);
+ }
+ mid = s->GetId();
}
- u64 mid = s->GetId();
- s->mtx.Unlock();
- // Can't touch s after this point.
- s = 0;
if (report_double_lock)
ReportMutexMisuse(thr, pc, ReportTypeMutexDoubleLock, addr, mid);
if (first && pre_lock && common_flags()->detect_deadlocks) {
@@ -210,35 +212,37 @@ void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz, int rec) {
int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
DPrintf("#%d: MutexUnlock %zx flagz=0x%x\n", thr->tid, addr, flagz);
if (IsAppMem(addr))
- MemoryReadAtomic(thr, pc, addr, kSizeLog1);
- SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
- thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, s->GetId());
- int rec = 0;
+ MemoryAccess(thr, pc, addr, 1, kAccessRead | kAccessAtomic);
+ u64 mid = 0;
bool report_bad_unlock = false;
- if (!SANITIZER_GO && (s->recursion == 0 || s->owner_tid != thr->tid)) {
- if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
- s->SetFlags(MutexFlagBroken);
- report_bad_unlock = true;
- }
- } else {
- rec = (flagz & MutexFlagRecursiveUnlock) ? s->recursion : 1;
- s->recursion -= rec;
- if (s->recursion == 0) {
- s->owner_tid = kInvalidTid;
- ReleaseStoreImpl(thr, pc, &s->clock);
+ int rec = 0;
+ {
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ Lock l(&s->mtx);
+ thr->fast_state.IncrementEpoch();
+ TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, s->GetId());
+ if (!SANITIZER_GO && (s->recursion == 0 || s->owner_tid != thr->tid)) {
+ if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
+ s->SetFlags(MutexFlagBroken);
+ report_bad_unlock = true;
+ }
} else {
+ rec = (flagz & MutexFlagRecursiveUnlock) ? s->recursion : 1;
+ s->recursion -= rec;
+ if (s->recursion == 0) {
+ s->owner_tid = kInvalidTid;
+ ReleaseStoreImpl(thr, pc, &s->clock);
+ } else {
+ }
}
+ thr->mset.Del(s->GetId(), true);
+ if (common_flags()->detect_deadlocks && s->recursion == 0 &&
+ !report_bad_unlock) {
+ Callback cb(thr, pc);
+ ctx->dd->MutexBeforeUnlock(&cb, &s->dd, true);
+ }
+ mid = s->GetId();
}
- thr->mset.Del(s->GetId(), true);
- if (common_flags()->detect_deadlocks && s->recursion == 0 &&
- !report_bad_unlock) {
- Callback cb(thr, pc);
- ctx->dd->MutexBeforeUnlock(&cb, &s->dd, true);
- }
- u64 mid = s->GetId();
- s->mtx.Unlock();
- // Can't touch s after this point.
if (report_bad_unlock)
ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr, mid);
if (common_flags()->detect_deadlocks && !report_bad_unlock) {
@@ -251,11 +255,14 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
void MutexPreReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
DPrintf("#%d: MutexPreReadLock %zx flagz=0x%x\n", thr->tid, addr, flagz);
if (!(flagz & MutexFlagTryLock) && common_flags()->detect_deadlocks) {
- SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, false);
- s->UpdateFlags(flagz);
+ {
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ ReadLock l(&s->mtx);
+ s->UpdateFlags(flagz);
+ Callback cb(thr, pc);
+ ctx->dd->MutexBeforeLock(&cb, &s->dd, false);
+ }
Callback cb(thr, pc);
- ctx->dd->MutexBeforeLock(&cb, &s->dd, false);
- s->mtx.ReadUnlock();
ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
}
}
@@ -263,34 +270,35 @@ void MutexPreReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
DPrintf("#%d: MutexPostReadLock %zx flagz=0x%x\n", thr->tid, addr, flagz);
if (IsAppMem(addr))
- MemoryReadAtomic(thr, pc, addr, kSizeLog1);
- SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, false);
- s->UpdateFlags(flagz);
- thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeRLock, s->GetId());
+ MemoryAccess(thr, pc, addr, 1, kAccessRead | kAccessAtomic);
+ u64 mid = 0;
bool report_bad_lock = false;
- if (s->owner_tid != kInvalidTid) {
- if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
- s->SetFlags(MutexFlagBroken);
- report_bad_lock = true;
- }
- }
- AcquireImpl(thr, pc, &s->clock);
- s->last_lock = thr->fast_state.raw();
- thr->mset.Add(s->GetId(), false, thr->fast_state.epoch());
bool pre_lock = false;
- if (common_flags()->detect_deadlocks) {
- pre_lock = (flagz & MutexFlagDoPreLockOnPostLock) &&
- !(flagz & MutexFlagTryLock);
- Callback cb(thr, pc);
- if (pre_lock)
- ctx->dd->MutexBeforeLock(&cb, &s->dd, false);
- ctx->dd->MutexAfterLock(&cb, &s->dd, false, flagz & MutexFlagTryLock);
+ {
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ ReadLock l(&s->mtx);
+ s->UpdateFlags(flagz);
+ thr->fast_state.IncrementEpoch();
+ TraceAddEvent(thr, thr->fast_state, EventTypeRLock, s->GetId());
+ if (s->owner_tid != kInvalidTid) {
+ if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
+ s->SetFlags(MutexFlagBroken);
+ report_bad_lock = true;
+ }
+ }
+ AcquireImpl(thr, pc, &s->clock);
+ s->last_lock = thr->fast_state.raw();
+ thr->mset.Add(s->GetId(), false, thr->fast_state.epoch());
+ if (common_flags()->detect_deadlocks) {
+ pre_lock =
+ (flagz & MutexFlagDoPreLockOnPostLock) && !(flagz & MutexFlagTryLock);
+ Callback cb(thr, pc);
+ if (pre_lock)
+ ctx->dd->MutexBeforeLock(&cb, &s->dd, false);
+ ctx->dd->MutexAfterLock(&cb, &s->dd, false, flagz & MutexFlagTryLock);
+ }
+ mid = s->GetId();
}
- u64 mid = s->GetId();
- s->mtx.ReadUnlock();
- // Can't touch s after this point.
- s = 0;
if (report_bad_lock)
ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadLock, addr, mid);
if (pre_lock && common_flags()->detect_deadlocks) {
@@ -302,25 +310,27 @@ void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
DPrintf("#%d: MutexReadUnlock %zx\n", thr->tid, addr);
if (IsAppMem(addr))
- MemoryReadAtomic(thr, pc, addr, kSizeLog1);
- SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
- thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
+ MemoryAccess(thr, pc, addr, 1, kAccessRead | kAccessAtomic);
+ u64 mid = 0;
bool report_bad_unlock = false;
- if (s->owner_tid != kInvalidTid) {
- if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
- s->SetFlags(MutexFlagBroken);
- report_bad_unlock = true;
+ {
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ Lock l(&s->mtx);
+ thr->fast_state.IncrementEpoch();
+ TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
+ if (s->owner_tid != kInvalidTid) {
+ if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
+ s->SetFlags(MutexFlagBroken);
+ report_bad_unlock = true;
+ }
}
+ ReleaseImpl(thr, pc, &s->read_clock);
+ if (common_flags()->detect_deadlocks && s->recursion == 0) {
+ Callback cb(thr, pc);
+ ctx->dd->MutexBeforeUnlock(&cb, &s->dd, false);
+ }
+ mid = s->GetId();
}
- ReleaseImpl(thr, pc, &s->read_clock);
- if (common_flags()->detect_deadlocks && s->recursion == 0) {
- Callback cb(thr, pc);
- ctx->dd->MutexBeforeUnlock(&cb, &s->dd, false);
- }
- u64 mid = s->GetId();
- s->mtx.Unlock();
- // Can't touch s after this point.
thr->mset.Del(mid, false);
if (report_bad_unlock)
ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadUnlock, addr, mid);
@@ -333,39 +343,41 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
DPrintf("#%d: MutexReadOrWriteUnlock %zx\n", thr->tid, addr);
if (IsAppMem(addr))
- MemoryReadAtomic(thr, pc, addr, kSizeLog1);
- SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
- bool write = true;
+ MemoryAccess(thr, pc, addr, 1, kAccessRead | kAccessAtomic);
+ u64 mid = 0;
bool report_bad_unlock = false;
- if (s->owner_tid == kInvalidTid) {
- // Seems to be read unlock.
- write = false;
- thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
- ReleaseImpl(thr, pc, &s->read_clock);
- } else if (s->owner_tid == thr->tid) {
- // Seems to be write unlock.
- thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, s->GetId());
- CHECK_GT(s->recursion, 0);
- s->recursion--;
- if (s->recursion == 0) {
- s->owner_tid = kInvalidTid;
- ReleaseStoreImpl(thr, pc, &s->clock);
- } else {
+ {
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ Lock l(&s->mtx);
+ bool write = true;
+ if (s->owner_tid == kInvalidTid) {
+ // Seems to be read unlock.
+ write = false;
+ thr->fast_state.IncrementEpoch();
+ TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
+ ReleaseImpl(thr, pc, &s->read_clock);
+ } else if (s->owner_tid == thr->tid) {
+ // Seems to be write unlock.
+ thr->fast_state.IncrementEpoch();
+ TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, s->GetId());
+ CHECK_GT(s->recursion, 0);
+ s->recursion--;
+ if (s->recursion == 0) {
+ s->owner_tid = kInvalidTid;
+ ReleaseStoreImpl(thr, pc, &s->clock);
+ } else {
+ }
+ } else if (!s->IsFlagSet(MutexFlagBroken)) {
+ s->SetFlags(MutexFlagBroken);
+ report_bad_unlock = true;
}
- } else if (!s->IsFlagSet(MutexFlagBroken)) {
- s->SetFlags(MutexFlagBroken);
- report_bad_unlock = true;
- }
- thr->mset.Del(s->GetId(), write);
- if (common_flags()->detect_deadlocks && s->recursion == 0) {
- Callback cb(thr, pc);
- ctx->dd->MutexBeforeUnlock(&cb, &s->dd, write);
+ thr->mset.Del(s->GetId(), write);
+ if (common_flags()->detect_deadlocks && s->recursion == 0) {
+ Callback cb(thr, pc);
+ ctx->dd->MutexBeforeUnlock(&cb, &s->dd, write);
+ }
+ mid = s->GetId();
}
- u64 mid = s->GetId();
- s->mtx.Unlock();
- // Can't touch s after this point.
if (report_bad_unlock)
ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr, mid);
if (common_flags()->detect_deadlocks) {
@@ -376,29 +388,27 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
void MutexRepair(ThreadState *thr, uptr pc, uptr addr) {
DPrintf("#%d: MutexRepair %zx\n", thr->tid, addr);
- SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ Lock l(&s->mtx);
s->owner_tid = kInvalidTid;
s->recursion = 0;
- s->mtx.Unlock();
}
void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr) {
DPrintf("#%d: MutexInvalidAccess %zx\n", thr->tid, addr);
- SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
- u64 mid = s->GetId();
- s->mtx.Unlock();
- ReportMutexMisuse(thr, pc, ReportTypeMutexInvalidAccess, addr, mid);
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ ReportMutexMisuse(thr, pc, ReportTypeMutexInvalidAccess, addr, s->GetId());
}
void Acquire(ThreadState *thr, uptr pc, uptr addr) {
DPrintf("#%d: Acquire %zx\n", thr->tid, addr);
if (thr->ignore_sync)
return;
- SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr, false);
+ SyncVar *s = ctx->metamap.GetSyncIfExists(addr);
if (!s)
return;
+ ReadLock l(&s->mtx);
AcquireImpl(thr, pc, &s->clock);
- s->mtx.ReadUnlock();
}
static void UpdateClockCallback(ThreadContextBase *tctx_base, void *arg) {
@@ -412,49 +422,48 @@ static void UpdateClockCallback(ThreadContextBase *tctx_base, void *arg) {
thr->clock.set(&thr->proc()->clock_cache, tctx->tid, epoch);
}
-void AcquireGlobal(ThreadState *thr, uptr pc) {
+void AcquireGlobal(ThreadState *thr) {
DPrintf("#%d: AcquireGlobal\n", thr->tid);
if (thr->ignore_sync)
return;
- ThreadRegistryLock l(ctx->thread_registry);
- ctx->thread_registry->RunCallbackForEachThreadLocked(
- UpdateClockCallback, thr);
+ ThreadRegistryLock l(&ctx->thread_registry);
+ ctx->thread_registry.RunCallbackForEachThreadLocked(UpdateClockCallback, thr);
}
void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr) {
DPrintf("#%d: ReleaseStoreAcquire %zx\n", thr->tid, addr);
if (thr->ignore_sync)
return;
- SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, false);
+ Lock l(&s->mtx);
thr->fast_state.IncrementEpoch();
// Can't increment epoch w/o writing to the trace as well.
TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
ReleaseStoreAcquireImpl(thr, pc, &s->clock);
- s->mtx.Unlock();
}
void Release(ThreadState *thr, uptr pc, uptr addr) {
DPrintf("#%d: Release %zx\n", thr->tid, addr);
if (thr->ignore_sync)
return;
- SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, false);
+ Lock l(&s->mtx);
thr->fast_state.IncrementEpoch();
// Can't increment epoch w/o writing to the trace as well.
TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
ReleaseImpl(thr, pc, &s->clock);
- s->mtx.Unlock();
}
void ReleaseStore(ThreadState *thr, uptr pc, uptr addr) {
DPrintf("#%d: ReleaseStore %zx\n", thr->tid, addr);
if (thr->ignore_sync)
return;
- SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, false);
+ Lock l(&s->mtx);
thr->fast_state.IncrementEpoch();
// Can't increment epoch w/o writing to the trace as well.
TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
ReleaseStoreImpl(thr, pc, &s->clock);
- s->mtx.Unlock();
}
#if !SANITIZER_GO
@@ -468,13 +477,13 @@ static void UpdateSleepClockCallback(ThreadContextBase *tctx_base, void *arg) {
}
void AfterSleep(ThreadState *thr, uptr pc) {
- DPrintf("#%d: AfterSleep %zx\n", thr->tid);
+ DPrintf("#%d: AfterSleep\n", thr->tid);
if (thr->ignore_sync)
return;
thr->last_sleep_stack_id = CurrentStackId(thr, pc);
- ThreadRegistryLock l(ctx->thread_registry);
- ctx->thread_registry->RunCallbackForEachThreadLocked(
- UpdateSleepClockCallback, thr);
+ ThreadRegistryLock l(&ctx->thread_registry);
+ ctx->thread_registry.RunCallbackForEachThreadLocked(UpdateSleepClockCallback,
+ thr);
}
#endif
@@ -520,7 +529,7 @@ void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) {
void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
if (r == 0 || !ShouldReport(thr, ReportTypeDeadlock))
return;
- ThreadRegistryLock l(ctx->thread_registry);
+ ThreadRegistryLock l(&ctx->thread_registry);
ScopedReport rep(ReportTypeDeadlock);
for (int i = 0; i < r->n; i++) {
rep.AddMutex(r->loop[i].mtx_ctx0);
diff --git a/libsanitizer/tsan/tsan_rtl_report.cpp b/libsanitizer/tsan/tsan_rtl_report.cpp
index 706794f..1f0bcb3 100644
--- a/libsanitizer/tsan/tsan_rtl_report.cpp
+++ b/libsanitizer/tsan/tsan_rtl_report.cpp
@@ -68,8 +68,10 @@ static void StackStripMain(SymbolizedStack *frames) {
} else if (last && 0 == internal_strcmp(last, "__tsan_thread_start_func")) {
last_frame->ClearAll();
last_frame2->next = nullptr;
- // Strip global ctors init.
- } else if (last && 0 == internal_strcmp(last, "__do_global_ctors_aux")) {
+ // Strip global ctors init, .preinit_array and main caller.
+ } else if (last && (0 == internal_strcmp(last, "__do_global_ctors_aux") ||
+ 0 == internal_strcmp(last, "__libc_csu_init") ||
+ 0 == internal_strcmp(last, "__libc_start_main"))) {
last_frame->ClearAll();
last_frame2->next = nullptr;
// If both are 0, then we probably just failed to symbolize.
@@ -120,7 +122,7 @@ static ReportStack *SymbolizeStack(StackTrace trace) {
}
StackStripMain(top);
- ReportStack *stack = ReportStack::New();
+ auto *stack = New<ReportStack>();
stack->frames = top;
return stack;
}
@@ -129,10 +131,10 @@ bool ShouldReport(ThreadState *thr, ReportType typ) {
// We set thr->suppress_reports in the fork context.
// Taking any locking in the fork context can lead to deadlocks.
// If any locks are already taken, it's too late to do this check.
- CheckNoLocks(thr);
+ CheckedMutex::CheckNoLocks();
// For the same reason check we didn't lock thread_registry yet.
if (SANITIZER_DEBUG)
- ThreadRegistryLock l(ctx->thread_registry);
+ ThreadRegistryLock l(&ctx->thread_registry);
if (!flags()->report_bugs || thr->suppress_reports)
return false;
switch (typ) {
@@ -154,9 +156,8 @@ bool ShouldReport(ThreadState *thr, ReportType typ) {
}
ScopedReportBase::ScopedReportBase(ReportType typ, uptr tag) {
- ctx->thread_registry->CheckLocked();
- void *mem = internal_alloc(MBlockReport, sizeof(ReportDesc));
- rep_ = new(mem) ReportDesc;
+ ctx->thread_registry.CheckLocked();
+ rep_ = New<ReportDesc>();
rep_->typ = typ;
rep_->tag = tag;
ctx->report_mtx.Lock();
@@ -165,7 +166,6 @@ ScopedReportBase::ScopedReportBase(ReportType typ, uptr tag) {
ScopedReportBase::~ScopedReportBase() {
ctx->report_mtx.Unlock();
DestroyAndFree(rep_);
- rep_ = nullptr;
}
void ScopedReportBase::AddStack(StackTrace stack, bool suppressable) {
@@ -176,8 +176,7 @@ void ScopedReportBase::AddStack(StackTrace stack, bool suppressable) {
void ScopedReportBase::AddMemoryAccess(uptr addr, uptr external_tag, Shadow s,
StackTrace stack, const MutexSet *mset) {
- void *mem = internal_alloc(MBlockReportMop, sizeof(ReportMop));
- ReportMop *mop = new(mem) ReportMop;
+ auto *mop = New<ReportMop>();
rep_->mops.PushBack(mop);
mop->tid = s.tid();
mop->addr = addr + s.addr0();
@@ -196,7 +195,7 @@ void ScopedReportBase::AddMemoryAccess(uptr addr, uptr external_tag, Shadow s,
}
}
-void ScopedReportBase::AddUniqueTid(int unique_tid) {
+void ScopedReportBase::AddUniqueTid(Tid unique_tid) {
rep_->unique_tids.PushBack(unique_tid);
}
@@ -205,8 +204,7 @@ void ScopedReportBase::AddThread(const ThreadContext *tctx, bool suppressable) {
if ((u32)rep_->threads[i]->id == tctx->tid)
return;
}
- void *mem = internal_alloc(MBlockReportThread, sizeof(ReportThread));
- ReportThread *rt = new(mem) ReportThread;
+ auto *rt = New<ReportThread>();
rep_->threads.PushBack(rt);
rt->id = tctx->tid;
rt->os_id = tctx->os_id;
@@ -226,17 +224,17 @@ static bool FindThreadByUidLockedCallback(ThreadContextBase *tctx, void *arg) {
return tctx->unique_id == (u32)unique_id;
}
-static ThreadContext *FindThreadByUidLocked(int unique_id) {
- ctx->thread_registry->CheckLocked();
+static ThreadContext *FindThreadByUidLocked(Tid unique_id) {
+ ctx->thread_registry.CheckLocked();
return static_cast<ThreadContext *>(
- ctx->thread_registry->FindThreadContextLocked(
+ ctx->thread_registry.FindThreadContextLocked(
FindThreadByUidLockedCallback, &unique_id));
}
-static ThreadContext *FindThreadByTidLocked(int tid) {
- ctx->thread_registry->CheckLocked();
- return static_cast<ThreadContext*>(
- ctx->thread_registry->GetThreadLocked(tid));
+static ThreadContext *FindThreadByTidLocked(Tid tid) {
+ ctx->thread_registry.CheckLocked();
+ return static_cast<ThreadContext *>(
+ ctx->thread_registry.GetThreadLocked(tid));
}
static bool IsInStackOrTls(ThreadContextBase *tctx_base, void *arg) {
@@ -251,10 +249,10 @@ static bool IsInStackOrTls(ThreadContextBase *tctx_base, void *arg) {
}
ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack) {
- ctx->thread_registry->CheckLocked();
- ThreadContext *tctx = static_cast<ThreadContext*>(
- ctx->thread_registry->FindThreadContextLocked(IsInStackOrTls,
- (void*)addr));
+ ctx->thread_registry.CheckLocked();
+ ThreadContext *tctx =
+ static_cast<ThreadContext *>(ctx->thread_registry.FindThreadContextLocked(
+ IsInStackOrTls, (void *)addr));
if (!tctx)
return 0;
ThreadState *thr = tctx->thr;
@@ -264,7 +262,7 @@ ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack) {
}
#endif
-void ScopedReportBase::AddThread(int unique_tid, bool suppressable) {
+void ScopedReportBase::AddThread(Tid unique_tid, bool suppressable) {
#if !SANITIZER_GO
if (const ThreadContext *tctx = FindThreadByUidLocked(unique_tid))
AddThread(tctx, suppressable);
@@ -276,8 +274,7 @@ void ScopedReportBase::AddMutex(const SyncVar *s) {
if (rep_->mutexes[i]->id == s->uid)
return;
}
- void *mem = internal_alloc(MBlockReportMutex, sizeof(ReportMutex));
- ReportMutex *rm = new(mem) ReportMutex;
+ auto *rm = New<ReportMutex>();
rep_->mutexes.PushBack(rm);
rm->id = s->uid;
rm->addr = s->addr;
@@ -289,18 +286,17 @@ u64 ScopedReportBase::AddMutex(u64 id) {
u64 uid = 0;
u64 mid = id;
uptr addr = SyncVar::SplitId(id, &uid);
- SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr, true);
+ SyncVar *s = ctx->metamap.GetSyncIfExists(addr);
// Check that the mutex is still alive.
// Another mutex can be created at the same address,
// so check uid as well.
if (s && s->CheckId(uid)) {
+ Lock l(&s->mtx);
mid = s->uid;
AddMutex(s);
} else {
AddDeadMutex(id);
}
- if (s)
- s->mtx.Unlock();
return mid;
}
@@ -309,8 +305,7 @@ void ScopedReportBase::AddDeadMutex(u64 id) {
if (rep_->mutexes[i]->id == id)
return;
}
- void *mem = internal_alloc(MBlockReportMutex, sizeof(ReportMutex));
- ReportMutex *rm = new(mem) ReportMutex;
+ auto *rm = New<ReportMutex>();
rep_->mutexes.PushBack(rm);
rm->id = id;
rm->addr = 0;
@@ -323,10 +318,11 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {
return;
#if !SANITIZER_GO
int fd = -1;
- int creat_tid = kInvalidTid;
- u32 creat_stack = 0;
+ Tid creat_tid = kInvalidTid;
+ StackID creat_stack = 0;
if (FdLocation(addr, &fd, &creat_tid, &creat_stack)) {
- ReportLocation *loc = ReportLocation::New(ReportLocationFD);
+ auto *loc = New<ReportLocation>();
+ loc->type = ReportLocationFD;
loc->fd = fd;
loc->tid = creat_tid;
loc->stack = SymbolizeStackId(creat_stack);
@@ -337,15 +333,19 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {
return;
}
MBlock *b = 0;
+ uptr block_begin = 0;
Allocator *a = allocator();
if (a->PointerIsMine((void*)addr)) {
- void *block_begin = a->GetBlockBegin((void*)addr);
+ block_begin = (uptr)a->GetBlockBegin((void *)addr);
if (block_begin)
- b = ctx->metamap.GetBlock((uptr)block_begin);
+ b = ctx->metamap.GetBlock(block_begin);
}
+ if (!b)
+ b = JavaHeapBlock(addr, &block_begin);
if (b != 0) {
ThreadContext *tctx = FindThreadByTidLocked(b->tid);
- ReportLocation *loc = ReportLocation::New(ReportLocationHeap);
+ auto *loc = New<ReportLocation>();
+ loc->type = ReportLocationHeap;
loc->heap_chunk_start = (uptr)allocator()->GetBlockBegin((void *)addr);
loc->heap_chunk_size = b->siz;
loc->external_tag = b->tag;
@@ -358,8 +358,8 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {
}
bool is_stack = false;
if (ThreadContext *tctx = IsThreadStackOrTls(addr, &is_stack)) {
- ReportLocation *loc =
- ReportLocation::New(is_stack ? ReportLocationStack : ReportLocationTLS);
+ auto *loc = New<ReportLocation>();
+ loc->type = is_stack ? ReportLocationStack : ReportLocationTLS;
loc->tid = tctx->tid;
rep_->locs.PushBack(loc);
AddThread(tctx);
@@ -373,7 +373,7 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {
}
#if !SANITIZER_GO
-void ScopedReportBase::AddSleep(u32 stack_id) {
+void ScopedReportBase::AddSleep(StackID stack_id) {
rep_->sleep = SymbolizeStackId(stack_id);
}
#endif
@@ -387,7 +387,7 @@ ScopedReport::ScopedReport(ReportType typ, uptr tag)
ScopedReport::~ScopedReport() {}
-void RestoreStack(int tid, const u64 epoch, VarSizeStackTrace *stk,
+void RestoreStack(Tid tid, const u64 epoch, VarSizeStackTrace *stk,
MutexSet *mset, uptr *tag) {
// This function restores stack trace and mutex set for the thread/epoch.
// It does so by getting stack trace and mutex set at the beginning of
@@ -450,6 +450,234 @@ void RestoreStack(int tid, const u64 epoch, VarSizeStackTrace *stk,
ExtractTagFromStack(stk, tag);
}
+namespace v3 {
+
+// Replays the trace up to last_pos position in the last part
+// or up to the provided epoch/sid (whichever is earlier)
+// and calls the provided function f for each event.
+template <typename Func>
+void TraceReplay(Trace *trace, TracePart *last, Event *last_pos, Sid sid,
+ Epoch epoch, Func f) {
+ TracePart *part = trace->parts.Front();
+ Sid ev_sid = kFreeSid;
+ Epoch ev_epoch = kEpochOver;
+ for (;;) {
+ DCHECK_EQ(part->trace, trace);
+ // Note: an event can't start in the last element.
+ // Since an event can take up to 2 elements,
+ // we ensure we have at least 2 before adding an event.
+ Event *end = &part->events[TracePart::kSize - 1];
+ if (part == last)
+ end = last_pos;
+ for (Event *evp = &part->events[0]; evp < end; evp++) {
+ Event *evp0 = evp;
+ if (!evp->is_access && !evp->is_func) {
+ switch (evp->type) {
+ case EventType::kTime: {
+ auto *ev = reinterpret_cast<EventTime *>(evp);
+ ev_sid = static_cast<Sid>(ev->sid);
+ ev_epoch = static_cast<Epoch>(ev->epoch);
+ if (ev_sid == sid && ev_epoch > epoch)
+ return;
+ break;
+ }
+ case EventType::kAccessExt:
+ FALLTHROUGH;
+ case EventType::kAccessRange:
+ FALLTHROUGH;
+ case EventType::kLock:
+ FALLTHROUGH;
+ case EventType::kRLock:
+ // These take 2 Event elements.
+ evp++;
+ break;
+ case EventType::kUnlock:
+ // This takes 1 Event element.
+ break;
+ }
+ }
+ CHECK_NE(ev_sid, kFreeSid);
+ CHECK_NE(ev_epoch, kEpochOver);
+ f(ev_sid, ev_epoch, evp0);
+ }
+ if (part == last)
+ return;
+ part = trace->parts.Next(part);
+ CHECK(part);
+ }
+ CHECK(0);
+}
+
+static void RestoreStackMatch(VarSizeStackTrace *pstk, MutexSet *pmset,
+ Vector<uptr> *stack, MutexSet *mset, uptr pc,
+ bool *found) {
+ DPrintf2(" MATCHED\n");
+ *pmset = *mset;
+ stack->PushBack(pc);
+ pstk->Init(&(*stack)[0], stack->Size());
+ stack->PopBack();
+ *found = true;
+}
+
+// Checks if addr1|size1 is fully contained in addr2|size2.
+// We check for fully contained instread of just overlapping
+// because a memory access is always traced once, but can be
+// split into multiple accesses in the shadow.
+static constexpr bool IsWithinAccess(uptr addr1, uptr size1, uptr addr2,
+ uptr size2) {
+ return addr1 >= addr2 && addr1 + size1 <= addr2 + size2;
+}
+
+// Replays the trace of thread tid up to the target event identified
+// by sid/epoch/addr/size/typ and restores and returns stack, mutex set
+// and tag for that event. If there are multiple such events, it returns
+// the last one. Returns false if the event is not present in the trace.
+bool RestoreStack(Tid tid, EventType type, Sid sid, Epoch epoch, uptr addr,
+ uptr size, AccessType typ, VarSizeStackTrace *pstk,
+ MutexSet *pmset, uptr *ptag) {
+ // This function restores stack trace and mutex set for the thread/epoch.
+ // It does so by getting stack trace and mutex set at the beginning of
+ // trace part, and then replaying the trace till the given epoch.
+ DPrintf2("RestoreStack: tid=%u sid=%u@%u addr=0x%zx/%zu typ=%x\n", tid,
+ static_cast<int>(sid), static_cast<int>(epoch), addr, size,
+ static_cast<int>(typ));
+ ctx->slot_mtx.CheckLocked(); // needed to prevent trace part recycling
+ ctx->thread_registry.CheckLocked();
+ ThreadContext *tctx =
+ static_cast<ThreadContext *>(ctx->thread_registry.GetThreadLocked(tid));
+ Trace *trace = &tctx->trace;
+ // Snapshot first/last parts and the current position in the last part.
+ TracePart *first_part;
+ TracePart *last_part;
+ Event *last_pos;
+ {
+ Lock lock(&trace->mtx);
+ first_part = trace->parts.Front();
+ if (!first_part)
+ return false;
+ last_part = trace->parts.Back();
+ last_pos = trace->final_pos;
+ if (tctx->thr)
+ last_pos = (Event *)atomic_load_relaxed(&tctx->thr->trace_pos);
+ }
+ // Too large for stack.
+ alignas(MutexSet) static char mset_storage[sizeof(MutexSet)];
+ MutexSet &mset = *new (mset_storage) MutexSet();
+ Vector<uptr> stack;
+ uptr prev_pc = 0;
+ bool found = false;
+ bool is_read = typ & kAccessRead;
+ bool is_atomic = typ & kAccessAtomic;
+ bool is_free = typ & kAccessFree;
+ TraceReplay(
+ trace, last_part, last_pos, sid, epoch,
+ [&](Sid ev_sid, Epoch ev_epoch, Event *evp) {
+ bool match = ev_sid == sid && ev_epoch == epoch;
+ if (evp->is_access) {
+ if (evp->is_func == 0 && evp->type == EventType::kAccessExt &&
+ evp->_ == 0) // NopEvent
+ return;
+ auto *ev = reinterpret_cast<EventAccess *>(evp);
+ uptr ev_addr = RestoreAddr(ev->addr);
+ uptr ev_size = 1 << ev->size_log;
+ uptr ev_pc =
+ prev_pc + ev->pc_delta - (1 << (EventAccess::kPCBits - 1));
+ prev_pc = ev_pc;
+ DPrintf2(" Access: pc=0x%zx addr=0x%zx/%zu type=%u/%u\n", ev_pc,
+ ev_addr, ev_size, ev->is_read, ev->is_atomic);
+ if (match && type == EventType::kAccessExt &&
+ IsWithinAccess(addr, size, ev_addr, ev_size) &&
+ is_read == ev->is_read && is_atomic == ev->is_atomic && !is_free)
+ RestoreStackMatch(pstk, pmset, &stack, &mset, ev_pc, &found);
+ return;
+ }
+ if (evp->is_func) {
+ auto *ev = reinterpret_cast<EventFunc *>(evp);
+ if (ev->pc) {
+ DPrintf2(" FuncEnter: pc=0x%llx\n", ev->pc);
+ stack.PushBack(ev->pc);
+ } else {
+ DPrintf2(" FuncExit\n");
+ CHECK(stack.Size());
+ stack.PopBack();
+ }
+ return;
+ }
+ switch (evp->type) {
+ case EventType::kAccessExt: {
+ auto *ev = reinterpret_cast<EventAccessExt *>(evp);
+ uptr ev_addr = RestoreAddr(ev->addr);
+ uptr ev_size = 1 << ev->size_log;
+ prev_pc = ev->pc;
+ DPrintf2(" AccessExt: pc=0x%llx addr=0x%zx/%zu type=%u/%u\n",
+ ev->pc, ev_addr, ev_size, ev->is_read, ev->is_atomic);
+ if (match && type == EventType::kAccessExt &&
+ IsWithinAccess(addr, size, ev_addr, ev_size) &&
+ is_read == ev->is_read && is_atomic == ev->is_atomic &&
+ !is_free)
+ RestoreStackMatch(pstk, pmset, &stack, &mset, ev->pc, &found);
+ break;
+ }
+ case EventType::kAccessRange: {
+ auto *ev = reinterpret_cast<EventAccessRange *>(evp);
+ uptr ev_addr = RestoreAddr(ev->addr);
+ uptr ev_size =
+ (ev->size_hi << EventAccessRange::kSizeLoBits) + ev->size_lo;
+ uptr ev_pc = RestoreAddr(ev->pc);
+ prev_pc = ev_pc;
+ DPrintf2(" Range: pc=0x%zx addr=0x%zx/%zu type=%u/%u\n", ev_pc,
+ ev_addr, ev_size, ev->is_read, ev->is_free);
+ if (match && type == EventType::kAccessExt &&
+ IsWithinAccess(addr, size, ev_addr, ev_size) &&
+ is_read == ev->is_read && !is_atomic && is_free == ev->is_free)
+ RestoreStackMatch(pstk, pmset, &stack, &mset, ev_pc, &found);
+ break;
+ }
+ case EventType::kLock:
+ FALLTHROUGH;
+ case EventType::kRLock: {
+ auto *ev = reinterpret_cast<EventLock *>(evp);
+ bool is_write = ev->type == EventType::kLock;
+ uptr ev_addr = RestoreAddr(ev->addr);
+ uptr ev_pc = RestoreAddr(ev->pc);
+ StackID stack_id =
+ (ev->stack_hi << EventLock::kStackIDLoBits) + ev->stack_lo;
+ DPrintf2(" Lock: pc=0x%zx addr=0x%zx stack=%u write=%d\n", ev_pc,
+ ev_addr, stack_id, is_write);
+ mset.AddAddr(ev_addr, stack_id, is_write);
+ // Events with ev_pc == 0 are written to the beginning of trace
+ // part as initial mutex set (are not real).
+ if (match && type == EventType::kLock && addr == ev_addr && ev_pc)
+ RestoreStackMatch(pstk, pmset, &stack, &mset, ev_pc, &found);
+ break;
+ }
+ case EventType::kUnlock: {
+ auto *ev = reinterpret_cast<EventUnlock *>(evp);
+ uptr ev_addr = RestoreAddr(ev->addr);
+ DPrintf2(" Unlock: addr=0x%zx\n", ev_addr);
+ mset.DelAddr(ev_addr);
+ break;
+ }
+ case EventType::kTime:
+ // TraceReplay already extracted sid/epoch from it,
+ // nothing else to do here.
+ break;
+ }
+ });
+ ExtractTagFromStack(pstk, ptag);
+ return found;
+}
+
+} // namespace v3
+
+bool RacyStacks::operator==(const RacyStacks &other) const {
+ if (hash[0] == other.hash[0] && hash[1] == other.hash[1])
+ return true;
+ if (hash[0] == other.hash[1] && hash[1] == other.hash[0])
+ return true;
+ return false;
+}
+
static bool FindRacyStacks(const RacyStacks &hash) {
for (uptr i = 0; i < ctx->racy_stacks.Size(); i++) {
if (hash == ctx->racy_stacks[i]) {
@@ -596,7 +824,7 @@ static bool RaceBetweenAtomicAndFree(ThreadState *thr) {
}
void ReportRace(ThreadState *thr) {
- CheckNoLocks(thr);
+ CheckedMutex::CheckNoLocks();
// Symbolizer makes lots of intercepted calls. If we try to process them,
// at best it will cause deadlocks on internal mutexes.
@@ -614,7 +842,7 @@ void ReportRace(ThreadState *thr) {
thr->racy_state[1] = s.raw();
}
- uptr addr = ShadowToMem((uptr)thr->racy_shadow_addr);
+ uptr addr = ShadowToMem(thr->racy_shadow_addr);
uptr addr_min = 0;
uptr addr_max = 0;
{
@@ -692,7 +920,7 @@ void ReportRace(ThreadState *thr) {
}
}
- ThreadRegistryLock l0(ctx->thread_registry);
+ ThreadRegistryLock l0(&ctx->thread_registry);
ScopedReport rep(typ, tag);
for (uptr i = 0; i < kMop; i++) {
Shadow s(thr->racy_state[i]);
@@ -702,8 +930,8 @@ void ReportRace(ThreadState *thr) {
for (uptr i = 0; i < kMop; i++) {
FastState s(thr->racy_state[i]);
- ThreadContext *tctx = static_cast<ThreadContext*>(
- ctx->thread_registry->GetThreadLocked(s.tid()));
+ ThreadContext *tctx = static_cast<ThreadContext *>(
+ ctx->thread_registry.GetThreadLocked(s.tid()));
if (s.epoch() < tctx->epoch0 || s.epoch() > tctx->epoch1)
continue;
rep.AddThread(tctx);
@@ -738,9 +966,7 @@ void PrintCurrentStack(ThreadState *thr, uptr pc) {
ALWAYS_INLINE USED void PrintCurrentStackSlow(uptr pc) {
#if !SANITIZER_GO
uptr bp = GET_CURRENT_FRAME();
- BufferedStackTrace *ptrace =
- new(internal_alloc(MBlockStackTrace, sizeof(BufferedStackTrace)))
- BufferedStackTrace();
+ auto *ptrace = New<BufferedStackTrace>();
ptrace->Unwind(pc, bp, nullptr, false);
for (uptr i = 0; i < ptrace->size / 2; i++) {
diff --git a/libsanitizer/tsan/tsan_rtl_thread.cpp b/libsanitizer/tsan/tsan_rtl_thread.cpp
index cdb6e60..61133a4 100644
--- a/libsanitizer/tsan/tsan_rtl_thread.cpp
+++ b/libsanitizer/tsan/tsan_rtl_thread.cpp
@@ -21,48 +21,14 @@ namespace __tsan {
// ThreadContext implementation.
-ThreadContext::ThreadContext(int tid)
- : ThreadContextBase(tid)
- , thr()
- , sync()
- , epoch0()
- , epoch1() {
-}
+ThreadContext::ThreadContext(Tid tid)
+ : ThreadContextBase(tid), thr(), sync(), epoch0(), epoch1() {}
#if !SANITIZER_GO
ThreadContext::~ThreadContext() {
}
#endif
-void ThreadContext::OnDead() {
- CHECK_EQ(sync.size(), 0);
-}
-
-void ThreadContext::OnJoined(void *arg) {
- ThreadState *caller_thr = static_cast<ThreadState *>(arg);
- AcquireImpl(caller_thr, 0, &sync);
- sync.Reset(&caller_thr->proc()->clock_cache);
-}
-
-struct OnCreatedArgs {
- ThreadState *thr;
- uptr pc;
-};
-
-void ThreadContext::OnCreated(void *arg) {
- thr = 0;
- if (tid == kMainTid)
- return;
- OnCreatedArgs *args = static_cast<OnCreatedArgs *>(arg);
- if (!args->thr) // GCD workers don't have a parent thread.
- return;
- args->thr->fast_state.IncrementEpoch();
- // Can't increment epoch w/o writing to the trace as well.
- TraceAddEvent(args->thr, args->thr->fast_state, EventTypeMop, 0);
- ReleaseImpl(args->thr, 0, &sync);
- creation_stack_id = CurrentStackId(args->thr, args->pc);
-}
-
void ThreadContext::OnReset() {
CHECK_EQ(sync.size(), 0);
uptr trace_p = GetThreadTrace(tid);
@@ -70,94 +36,15 @@ void ThreadContext::OnReset() {
//!!! ReleaseMemoryToOS(GetThreadTraceHeader(tid), sizeof(Trace));
}
-void ThreadContext::OnDetached(void *arg) {
- ThreadState *thr1 = static_cast<ThreadState*>(arg);
- sync.Reset(&thr1->proc()->clock_cache);
-}
-
-struct OnStartedArgs {
- ThreadState *thr;
- uptr stk_addr;
- uptr stk_size;
- uptr tls_addr;
- uptr tls_size;
-};
-
-void ThreadContext::OnStarted(void *arg) {
- OnStartedArgs *args = static_cast<OnStartedArgs*>(arg);
- thr = args->thr;
- // RoundUp so that one trace part does not contain events
- // from different threads.
- epoch0 = RoundUp(epoch1 + 1, kTracePartSize);
- epoch1 = (u64)-1;
- new(thr) ThreadState(ctx, tid, unique_id, epoch0, reuse_count,
- args->stk_addr, args->stk_size, args->tls_addr, args->tls_size);
-#if !SANITIZER_GO
- thr->shadow_stack = &ThreadTrace(thr->tid)->shadow_stack[0];
- thr->shadow_stack_pos = thr->shadow_stack;
- thr->shadow_stack_end = thr->shadow_stack + kShadowStackSize;
-#else
- // Setup dynamic shadow stack.
- const int kInitStackSize = 8;
- thr->shadow_stack = (uptr*)internal_alloc(MBlockShadowStack,
- kInitStackSize * sizeof(uptr));
- thr->shadow_stack_pos = thr->shadow_stack;
- thr->shadow_stack_end = thr->shadow_stack + kInitStackSize;
-#endif
- if (common_flags()->detect_deadlocks)
- thr->dd_lt = ctx->dd->CreateLogicalThread(unique_id);
- thr->fast_state.SetHistorySize(flags()->history_size);
- // Commit switch to the new part of the trace.
- // TraceAddEvent will reset stack0/mset0 in the new part for us.
- TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
-
- thr->fast_synch_epoch = epoch0;
- AcquireImpl(thr, 0, &sync);
- sync.Reset(&thr->proc()->clock_cache);
- thr->is_inited = true;
- DPrintf("#%d: ThreadStart epoch=%zu stk_addr=%zx stk_size=%zx "
- "tls_addr=%zx tls_size=%zx\n",
- tid, (uptr)epoch0, args->stk_addr, args->stk_size,
- args->tls_addr, args->tls_size);
-}
-
-void ThreadContext::OnFinished() {
-#if SANITIZER_GO
- internal_free(thr->shadow_stack);
- thr->shadow_stack = nullptr;
- thr->shadow_stack_pos = nullptr;
- thr->shadow_stack_end = nullptr;
-#endif
- if (!detached) {
- thr->fast_state.IncrementEpoch();
- // Can't increment epoch w/o writing to the trace as well.
- TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
- ReleaseImpl(thr, 0, &sync);
- }
- epoch1 = thr->fast_state.epoch();
-
- if (common_flags()->detect_deadlocks)
- ctx->dd->DestroyLogicalThread(thr->dd_lt);
- thr->clock.ResetCached(&thr->proc()->clock_cache);
-#if !SANITIZER_GO
- thr->last_sleep_clock.ResetCached(&thr->proc()->clock_cache);
-#endif
-#if !SANITIZER_GO
- PlatformCleanUpThreadState(thr);
-#endif
- thr->~ThreadState();
- thr = 0;
-}
-
#if !SANITIZER_GO
struct ThreadLeak {
ThreadContext *tctx;
int count;
};
-static void MaybeReportThreadLeak(ThreadContextBase *tctx_base, void *arg) {
- Vector<ThreadLeak> &leaks = *(Vector<ThreadLeak>*)arg;
- ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base);
+static void CollectThreadLeaks(ThreadContextBase *tctx_base, void *arg) {
+ auto &leaks = *static_cast<Vector<ThreadLeak> *>(arg);
+ auto *tctx = static_cast<ThreadContext *>(tctx_base);
if (tctx->detached || tctx->status != ThreadStatusFinished)
return;
for (uptr i = 0; i < leaks.Size(); i++) {
@@ -166,8 +53,7 @@ static void MaybeReportThreadLeak(ThreadContextBase *tctx_base, void *arg) {
return;
}
}
- ThreadLeak leak = {tctx, 1};
- leaks.PushBack(leak);
+ leaks.PushBack({tctx, 1});
}
#endif
@@ -206,10 +92,10 @@ void ThreadFinalize(ThreadState *thr) {
#if !SANITIZER_GO
if (!ShouldReport(thr, ReportTypeThreadLeak))
return;
- ThreadRegistryLock l(ctx->thread_registry);
+ ThreadRegistryLock l(&ctx->thread_registry);
Vector<ThreadLeak> leaks;
- ctx->thread_registry->RunCallbackForEachThreadLocked(
- MaybeReportThreadLeak, &leaks);
+ ctx->thread_registry.RunCallbackForEachThreadLocked(CollectThreadLeaks,
+ &leaks);
for (uptr i = 0; i < leaks.Size(); i++) {
ScopedReport rep(ReportTypeThreadLeak);
rep.AddThread(leaks[i].tctx, true);
@@ -221,20 +107,48 @@ void ThreadFinalize(ThreadState *thr) {
int ThreadCount(ThreadState *thr) {
uptr result;
- ctx->thread_registry->GetNumberOfThreads(0, 0, &result);
+ ctx->thread_registry.GetNumberOfThreads(0, 0, &result);
return (int)result;
}
-int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {
+struct OnCreatedArgs {
+ ThreadState *thr;
+ uptr pc;
+};
+
+Tid ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {
OnCreatedArgs args = { thr, pc };
u32 parent_tid = thr ? thr->tid : kInvalidTid; // No parent for GCD workers.
- int tid =
- ctx->thread_registry->CreateThread(uid, detached, parent_tid, &args);
+ Tid tid = ctx->thread_registry.CreateThread(uid, detached, parent_tid, &args);
DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", parent_tid, tid, uid);
return tid;
}
-void ThreadStart(ThreadState *thr, int tid, tid_t os_id,
+void ThreadContext::OnCreated(void *arg) {
+ thr = 0;
+ if (tid == kMainTid)
+ return;
+ OnCreatedArgs *args = static_cast<OnCreatedArgs *>(arg);
+ if (!args->thr) // GCD workers don't have a parent thread.
+ return;
+ args->thr->fast_state.IncrementEpoch();
+ // Can't increment epoch w/o writing to the trace as well.
+ TraceAddEvent(args->thr, args->thr->fast_state, EventTypeMop, 0);
+ ReleaseImpl(args->thr, 0, &sync);
+ creation_stack_id = CurrentStackId(args->thr, args->pc);
+}
+
+extern "C" void __tsan_stack_initialization() {}
+
+struct OnStartedArgs {
+ ThreadState *thr;
+ uptr stk_addr;
+ uptr stk_size;
+ uptr tls_addr;
+ uptr tls_size;
+};
+
+void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
ThreadType thread_type) {
uptr stk_addr = 0;
uptr stk_size = 0;
@@ -244,22 +158,13 @@ void ThreadStart(ThreadState *thr, int tid, tid_t os_id,
if (thread_type != ThreadType::Fiber)
GetThreadStackAndTls(tid == kMainTid, &stk_addr, &stk_size, &tls_addr,
&tls_size);
-
- if (tid != kMainTid) {
- if (stk_addr && stk_size)
- MemoryRangeImitateWrite(thr, /*pc=*/ 1, stk_addr, stk_size);
-
- if (tls_addr && tls_size) ImitateTlsWrite(thr, tls_addr, tls_size);
- }
#endif
- ThreadRegistry *tr = ctx->thread_registry;
+ ThreadRegistry *tr = &ctx->thread_registry;
OnStartedArgs args = { thr, stk_addr, stk_size, tls_addr, tls_size };
tr->StartThread(tid, os_id, thread_type, &args);
- tr->Lock();
- thr->tctx = (ThreadContext*)tr->GetThreadLocked(tid);
- tr->Unlock();
+ while (!thr->tctx->trace.parts.Empty()) thr->tctx->trace.parts.PopBack();
#if !SANITIZER_GO
if (ctx->after_multithreaded_fork) {
@@ -268,6 +173,51 @@ void ThreadStart(ThreadState *thr, int tid, tid_t os_id,
ThreadIgnoreSyncBegin(thr, 0);
}
#endif
+
+#if !SANITIZER_GO
+ // Don't imitate stack/TLS writes for the main thread,
+ // because its initialization is synchronized with all
+ // subsequent threads anyway.
+ if (tid != kMainTid) {
+ if (stk_addr && stk_size) {
+ const uptr pc = StackTrace::GetNextInstructionPc(
+ reinterpret_cast<uptr>(__tsan_stack_initialization));
+ MemoryRangeImitateWrite(thr, pc, stk_addr, stk_size);
+ }
+
+ if (tls_addr && tls_size)
+ ImitateTlsWrite(thr, tls_addr, tls_size);
+ }
+#endif
+}
+
+void ThreadContext::OnStarted(void *arg) {
+ OnStartedArgs *args = static_cast<OnStartedArgs *>(arg);
+ thr = args->thr;
+ // RoundUp so that one trace part does not contain events
+ // from different threads.
+ epoch0 = RoundUp(epoch1 + 1, kTracePartSize);
+ epoch1 = (u64)-1;
+ new (thr)
+ ThreadState(ctx, tid, unique_id, epoch0, reuse_count, args->stk_addr,
+ args->stk_size, args->tls_addr, args->tls_size);
+ if (common_flags()->detect_deadlocks)
+ thr->dd_lt = ctx->dd->CreateLogicalThread(unique_id);
+ thr->fast_state.SetHistorySize(flags()->history_size);
+ // Commit switch to the new part of the trace.
+ // TraceAddEvent will reset stack0/mset0 in the new part for us.
+ TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
+
+ thr->fast_synch_epoch = epoch0;
+ AcquireImpl(thr, 0, &sync);
+ sync.Reset(&thr->proc()->clock_cache);
+ thr->tctx = this;
+ thr->is_inited = true;
+ DPrintf(
+ "#%d: ThreadStart epoch=%zu stk_addr=%zx stk_size=%zx "
+ "tls_addr=%zx tls_size=%zx\n",
+ tid, (uptr)epoch0, args->stk_addr, args->stk_size, args->tls_addr,
+ args->tls_size);
}
void ThreadFinish(ThreadState *thr) {
@@ -277,7 +227,34 @@ void ThreadFinish(ThreadState *thr) {
if (thr->tls_addr && thr->tls_size)
DontNeedShadowFor(thr->tls_addr, thr->tls_size);
thr->is_dead = true;
- ctx->thread_registry->FinishThread(thr->tid);
+ ctx->thread_registry.FinishThread(thr->tid);
+}
+
+void ThreadContext::OnFinished() {
+#if SANITIZER_GO
+ Free(thr->shadow_stack);
+ thr->shadow_stack_pos = nullptr;
+ thr->shadow_stack_end = nullptr;
+#endif
+ if (!detached) {
+ thr->fast_state.IncrementEpoch();
+ // Can't increment epoch w/o writing to the trace as well.
+ TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
+ ReleaseImpl(thr, 0, &sync);
+ }
+ epoch1 = thr->fast_state.epoch();
+
+ if (common_flags()->detect_deadlocks)
+ ctx->dd->DestroyLogicalThread(thr->dd_lt);
+ thr->clock.ResetCached(&thr->proc()->clock_cache);
+#if !SANITIZER_GO
+ thr->last_sleep_clock.ResetCached(&thr->proc()->clock_cache);
+#endif
+#if !SANITIZER_GO
+ PlatformCleanUpThreadState(thr);
+#endif
+ thr->~ThreadState();
+ thr = 0;
}
struct ConsumeThreadContext {
@@ -302,35 +279,48 @@ static bool ConsumeThreadByUid(ThreadContextBase *tctx, void *arg) {
return false;
}
-int ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid) {
+Tid ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid) {
ConsumeThreadContext findCtx = {uid, nullptr};
- ctx->thread_registry->FindThread(ConsumeThreadByUid, &findCtx);
- int tid = findCtx.tctx ? findCtx.tctx->tid : kInvalidTid;
+ ctx->thread_registry.FindThread(ConsumeThreadByUid, &findCtx);
+ Tid tid = findCtx.tctx ? findCtx.tctx->tid : kInvalidTid;
DPrintf("#%d: ThreadTid uid=%zu tid=%d\n", thr->tid, uid, tid);
return tid;
}
-void ThreadJoin(ThreadState *thr, uptr pc, int tid) {
+void ThreadJoin(ThreadState *thr, uptr pc, Tid tid) {
CHECK_GT(tid, 0);
CHECK_LT(tid, kMaxTid);
DPrintf("#%d: ThreadJoin tid=%d\n", thr->tid, tid);
- ctx->thread_registry->JoinThread(tid, thr);
+ ctx->thread_registry.JoinThread(tid, thr);
}
-void ThreadDetach(ThreadState *thr, uptr pc, int tid) {
+void ThreadContext::OnJoined(void *arg) {
+ ThreadState *caller_thr = static_cast<ThreadState *>(arg);
+ AcquireImpl(caller_thr, 0, &sync);
+ sync.Reset(&caller_thr->proc()->clock_cache);
+}
+
+void ThreadContext::OnDead() { CHECK_EQ(sync.size(), 0); }
+
+void ThreadDetach(ThreadState *thr, uptr pc, Tid tid) {
CHECK_GT(tid, 0);
CHECK_LT(tid, kMaxTid);
- ctx->thread_registry->DetachThread(tid, thr);
+ ctx->thread_registry.DetachThread(tid, thr);
+}
+
+void ThreadContext::OnDetached(void *arg) {
+ ThreadState *thr1 = static_cast<ThreadState *>(arg);
+ sync.Reset(&thr1->proc()->clock_cache);
}
-void ThreadNotJoined(ThreadState *thr, uptr pc, int tid, uptr uid) {
+void ThreadNotJoined(ThreadState *thr, uptr pc, Tid tid, uptr uid) {
CHECK_GT(tid, 0);
CHECK_LT(tid, kMaxTid);
- ctx->thread_registry->SetThreadUserId(tid, uid);
+ ctx->thread_registry.SetThreadUserId(tid, uid);
}
void ThreadSetName(ThreadState *thr, const char *name) {
- ctx->thread_registry->SetThreadName(thr->tid, name);
+ ctx->thread_registry.SetThreadName(thr->tid, name);
}
void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
@@ -338,7 +328,7 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
if (size == 0)
return;
- u64 *shadow_mem = (u64*)MemToShadow(addr);
+ RawShadow *shadow_mem = MemToShadow(addr);
DPrintf2("#%d: MemoryAccessRange: @%p %p size=%d is_write=%d\n",
thr->tid, (void*)pc, (void*)addr,
(int)size, is_write);
@@ -352,14 +342,14 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
Printf("Access to non app mem %zx\n", addr + size - 1);
DCHECK(IsAppMem(addr + size - 1));
}
- if (!IsShadowMem((uptr)shadow_mem)) {
+ if (!IsShadowMem(shadow_mem)) {
Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
- DCHECK(IsShadowMem((uptr)shadow_mem));
+ DCHECK(IsShadowMem(shadow_mem));
}
- if (!IsShadowMem((uptr)(shadow_mem + size * kShadowCnt / 8 - 1))) {
+ if (!IsShadowMem(shadow_mem + size * kShadowCnt / 8 - 1)) {
Printf("Bad shadow addr %p (%zx)\n",
shadow_mem + size * kShadowCnt / 8 - 1, addr + size - 1);
- DCHECK(IsShadowMem((uptr)(shadow_mem + size * kShadowCnt / 8 - 1)));
+ DCHECK(IsShadowMem(shadow_mem + size * kShadowCnt / 8 - 1));
}
#endif
@@ -421,10 +411,10 @@ void FiberSwitchImpl(ThreadState *from, ThreadState *to) {
}
ThreadState *FiberCreate(ThreadState *thr, uptr pc, unsigned flags) {
- void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadState));
+ void *mem = Alloc(sizeof(ThreadState));
ThreadState *fiber = static_cast<ThreadState *>(mem);
internal_memset(fiber, 0, sizeof(*fiber));
- int tid = ThreadCreate(thr, pc, 0, true);
+ Tid tid = ThreadCreate(thr, pc, 0, true);
FiberSwitchImpl(thr, fiber);
ThreadStart(fiber, tid, 0, ThreadType::Fiber);
FiberSwitchImpl(fiber, thr);
@@ -435,7 +425,7 @@ void FiberDestroy(ThreadState *thr, uptr pc, ThreadState *fiber) {
FiberSwitchImpl(thr, fiber);
ThreadFinish(fiber);
FiberSwitchImpl(fiber, thr);
- internal_free(fiber);
+ Free(fiber);
}
void FiberSwitch(ThreadState *thr, uptr pc,
diff --git a/libsanitizer/tsan/tsan_shadow.h b/libsanitizer/tsan/tsan_shadow.h
new file mode 100644
index 0000000..8b7bc34
--- /dev/null
+++ b/libsanitizer/tsan/tsan_shadow.h
@@ -0,0 +1,233 @@
+//===-- tsan_shadow.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TSAN_SHADOW_H
+#define TSAN_SHADOW_H
+
+#include "tsan_defs.h"
+#include "tsan_trace.h"
+
+namespace __tsan {
+
+// FastState (from most significant bit):
+// ignore : 1
+// tid : kTidBits
+// unused : -
+// history_size : 3
+// epoch : kClkBits
+class FastState {
+ public:
+ FastState(u64 tid, u64 epoch) {
+ x_ = tid << kTidShift;
+ x_ |= epoch;
+ DCHECK_EQ(tid, this->tid());
+ DCHECK_EQ(epoch, this->epoch());
+ DCHECK_EQ(GetIgnoreBit(), false);
+ }
+
+ explicit FastState(u64 x) : x_(x) {}
+
+ u64 raw() const { return x_; }
+
+ u64 tid() const {
+ u64 res = (x_ & ~kIgnoreBit) >> kTidShift;
+ return res;
+ }
+
+ u64 TidWithIgnore() const {
+ u64 res = x_ >> kTidShift;
+ return res;
+ }
+
+ u64 epoch() const {
+ u64 res = x_ & ((1ull << kClkBits) - 1);
+ return res;
+ }
+
+ void IncrementEpoch() {
+ u64 old_epoch = epoch();
+ x_ += 1;
+ DCHECK_EQ(old_epoch + 1, epoch());
+ (void)old_epoch;
+ }
+
+ void SetIgnoreBit() { x_ |= kIgnoreBit; }
+ void ClearIgnoreBit() { x_ &= ~kIgnoreBit; }
+ bool GetIgnoreBit() const { return (s64)x_ < 0; }
+
+ void SetHistorySize(int hs) {
+ CHECK_GE(hs, 0);
+ CHECK_LE(hs, 7);
+ x_ = (x_ & ~(kHistoryMask << kHistoryShift)) | (u64(hs) << kHistoryShift);
+ }
+
+ ALWAYS_INLINE
+ int GetHistorySize() const {
+ return (int)((x_ >> kHistoryShift) & kHistoryMask);
+ }
+
+ void ClearHistorySize() { SetHistorySize(0); }
+
+ ALWAYS_INLINE
+ u64 GetTracePos() const {
+ const int hs = GetHistorySize();
+ // When hs == 0, the trace consists of 2 parts.
+ const u64 mask = (1ull << (kTracePartSizeBits + hs + 1)) - 1;
+ return epoch() & mask;
+ }
+
+ private:
+ friend class Shadow;
+ static const int kTidShift = 64 - kTidBits - 1;
+ static const u64 kIgnoreBit = 1ull << 63;
+ static const u64 kFreedBit = 1ull << 63;
+ static const u64 kHistoryShift = kClkBits;
+ static const u64 kHistoryMask = 7;
+ u64 x_;
+};
+
+// Shadow (from most significant bit):
+// freed : 1
+// tid : kTidBits
+// is_atomic : 1
+// is_read : 1
+// size_log : 2
+// addr0 : 3
+// epoch : kClkBits
+class Shadow : public FastState {
+ public:
+ explicit Shadow(u64 x) : FastState(x) {}
+
+ explicit Shadow(const FastState &s) : FastState(s.x_) { ClearHistorySize(); }
+
+ void SetAddr0AndSizeLog(u64 addr0, unsigned kAccessSizeLog) {
+ DCHECK_EQ((x_ >> kClkBits) & 31, 0);
+ DCHECK_LE(addr0, 7);
+ DCHECK_LE(kAccessSizeLog, 3);
+ x_ |= ((kAccessSizeLog << 3) | addr0) << kClkBits;
+ DCHECK_EQ(kAccessSizeLog, size_log());
+ DCHECK_EQ(addr0, this->addr0());
+ }
+
+ void SetWrite(unsigned kAccessIsWrite) {
+ DCHECK_EQ(x_ & kReadBit, 0);
+ if (!kAccessIsWrite)
+ x_ |= kReadBit;
+ DCHECK_EQ(kAccessIsWrite, IsWrite());
+ }
+
+ void SetAtomic(bool kIsAtomic) {
+ DCHECK(!IsAtomic());
+ if (kIsAtomic)
+ x_ |= kAtomicBit;
+ DCHECK_EQ(IsAtomic(), kIsAtomic);
+ }
+
+ bool IsAtomic() const { return x_ & kAtomicBit; }
+
+ bool IsZero() const { return x_ == 0; }
+
+ static inline bool TidsAreEqual(const Shadow s1, const Shadow s2) {
+ u64 shifted_xor = (s1.x_ ^ s2.x_) >> kTidShift;
+ DCHECK_EQ(shifted_xor == 0, s1.TidWithIgnore() == s2.TidWithIgnore());
+ return shifted_xor == 0;
+ }
+
+ static ALWAYS_INLINE bool Addr0AndSizeAreEqual(const Shadow s1,
+ const Shadow s2) {
+ u64 masked_xor = ((s1.x_ ^ s2.x_) >> kClkBits) & 31;
+ return masked_xor == 0;
+ }
+
+ static ALWAYS_INLINE bool TwoRangesIntersect(Shadow s1, Shadow s2,
+ unsigned kS2AccessSize) {
+ bool res = false;
+ u64 diff = s1.addr0() - s2.addr0();
+ if ((s64)diff < 0) { // s1.addr0 < s2.addr0
+ // if (s1.addr0() + size1) > s2.addr0()) return true;
+ if (s1.size() > -diff)
+ res = true;
+ } else {
+ // if (s2.addr0() + kS2AccessSize > s1.addr0()) return true;
+ if (kS2AccessSize > diff)
+ res = true;
+ }
+ DCHECK_EQ(res, TwoRangesIntersectSlow(s1, s2));
+ DCHECK_EQ(res, TwoRangesIntersectSlow(s2, s1));
+ return res;
+ }
+
+ u64 ALWAYS_INLINE addr0() const { return (x_ >> kClkBits) & 7; }
+ u64 ALWAYS_INLINE size() const { return 1ull << size_log(); }
+ bool ALWAYS_INLINE IsWrite() const { return !IsRead(); }
+ bool ALWAYS_INLINE IsRead() const { return x_ & kReadBit; }
+
+ // The idea behind the freed bit is as follows.
+ // When the memory is freed (or otherwise unaccessible) we write to the shadow
+ // values with tid/epoch related to the free and the freed bit set.
+ // During memory accesses processing the freed bit is considered
+ // as msb of tid. So any access races with shadow with freed bit set
+ // (it is as if write from a thread with which we never synchronized before).
+ // This allows us to detect accesses to freed memory w/o additional
+ // overheads in memory access processing and at the same time restore
+ // tid/epoch of free.
+ void MarkAsFreed() { x_ |= kFreedBit; }
+
+ bool IsFreed() const { return x_ & kFreedBit; }
+
+ bool GetFreedAndReset() {
+ bool res = x_ & kFreedBit;
+ x_ &= ~kFreedBit;
+ return res;
+ }
+
+ bool ALWAYS_INLINE IsBothReadsOrAtomic(bool kIsWrite, bool kIsAtomic) const {
+ bool v = x_ & ((u64(kIsWrite ^ 1) << kReadShift) |
+ (u64(kIsAtomic) << kAtomicShift));
+ DCHECK_EQ(v, (!IsWrite() && !kIsWrite) || (IsAtomic() && kIsAtomic));
+ return v;
+ }
+
+ bool ALWAYS_INLINE IsRWNotWeaker(bool kIsWrite, bool kIsAtomic) const {
+ bool v = ((x_ >> kReadShift) & 3) <= u64((kIsWrite ^ 1) | (kIsAtomic << 1));
+ DCHECK_EQ(v, (IsAtomic() < kIsAtomic) ||
+ (IsAtomic() == kIsAtomic && !IsWrite() <= !kIsWrite));
+ return v;
+ }
+
+ bool ALWAYS_INLINE IsRWWeakerOrEqual(bool kIsWrite, bool kIsAtomic) const {
+ bool v = ((x_ >> kReadShift) & 3) >= u64((kIsWrite ^ 1) | (kIsAtomic << 1));
+ DCHECK_EQ(v, (IsAtomic() > kIsAtomic) ||
+ (IsAtomic() == kIsAtomic && !IsWrite() >= !kIsWrite));
+ return v;
+ }
+
+ private:
+ static const u64 kReadShift = 5 + kClkBits;
+ static const u64 kReadBit = 1ull << kReadShift;
+ static const u64 kAtomicShift = 6 + kClkBits;
+ static const u64 kAtomicBit = 1ull << kAtomicShift;
+
+ u64 size_log() const { return (x_ >> (3 + kClkBits)) & 3; }
+
+ static bool TwoRangesIntersectSlow(const Shadow s1, const Shadow s2) {
+ if (s1.addr0() == s2.addr0())
+ return true;
+ if (s1.addr0() < s2.addr0() && s1.addr0() + s1.size() > s2.addr0())
+ return true;
+ if (s2.addr0() < s1.addr0() && s2.addr0() + s2.size() > s1.addr0())
+ return true;
+ return false;
+ }
+};
+
+const RawShadow kShadowRodata = (RawShadow)-1; // .rodata shadow marker
+
+} // namespace __tsan
+
+#endif
diff --git a/libsanitizer/tsan/tsan_stack_trace.cpp b/libsanitizer/tsan/tsan_stack_trace.cpp
index 6c703d7..9bbaafb 100644
--- a/libsanitizer/tsan/tsan_stack_trace.cpp
+++ b/libsanitizer/tsan/tsan_stack_trace.cpp
@@ -23,14 +23,10 @@ VarSizeStackTrace::~VarSizeStackTrace() {
}
void VarSizeStackTrace::ResizeBuffer(uptr new_size) {
- if (trace_buffer) {
- internal_free(trace_buffer);
- }
- trace_buffer =
- (new_size > 0)
- ? (uptr *)internal_alloc(MBlockStackTrace,
- new_size * sizeof(trace_buffer[0]))
- : nullptr;
+ Free(trace_buffer);
+ trace_buffer = (new_size > 0)
+ ? (uptr *)Alloc(new_size * sizeof(trace_buffer[0]))
+ : nullptr;
trace = trace_buffer;
size = new_size;
}
diff --git a/libsanitizer/tsan/tsan_symbolize.cpp b/libsanitizer/tsan/tsan_symbolize.cpp
index 6478f3a..2e2744d 100644
--- a/libsanitizer/tsan/tsan_symbolize.cpp
+++ b/libsanitizer/tsan/tsan_symbolize.cpp
@@ -110,7 +110,8 @@ ReportLocation *SymbolizeData(uptr addr) {
DataInfo info;
if (!Symbolizer::GetOrInit()->SymbolizeData(addr, &info))
return 0;
- ReportLocation *ent = ReportLocation::New(ReportLocationGlobal);
+ auto *ent = New<ReportLocation>();
+ ent->type = ReportLocationGlobal;
internal_memcpy(&ent->global, &info, sizeof(info));
return ent;
}
diff --git a/libsanitizer/tsan/tsan_sync.cpp b/libsanitizer/tsan/tsan_sync.cpp
index d25434a..f042aba 100644
--- a/libsanitizer/tsan/tsan_sync.cpp
+++ b/libsanitizer/tsan/tsan_sync.cpp
@@ -20,13 +20,14 @@ void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s);
SyncVar::SyncVar() : mtx(MutexTypeSyncVar) { Reset(0); }
-void SyncVar::Init(ThreadState *thr, uptr pc, uptr addr, u64 uid) {
+void SyncVar::Init(ThreadState *thr, uptr pc, uptr addr, u64 uid,
+ bool save_stack) {
this->addr = addr;
this->uid = uid;
this->next = 0;
- creation_stack_id = 0;
- if (!SANITIZER_GO) // Go does not use them
+ creation_stack_id = kInvalidStackID;
+ if (save_stack && !SANITIZER_GO) // Go does not use them
creation_stack_id = CurrentStackId(thr, pc);
if (common_flags()->detect_deadlocks)
DDMutexInit(thr, pc, this);
@@ -34,7 +35,7 @@ void SyncVar::Init(ThreadState *thr, uptr pc, uptr addr, u64 uid) {
void SyncVar::Reset(Processor *proc) {
uid = 0;
- creation_stack_id = 0;
+ creation_stack_id = kInvalidStackID;
owner_tid = kInvalidTid;
last_lock = 0;
recursion = 0;
@@ -190,63 +191,41 @@ MBlock* MetaMap::GetBlock(uptr p) {
}
}
-SyncVar* MetaMap::GetOrCreateAndLock(ThreadState *thr, uptr pc,
- uptr addr, bool write_lock) {
- return GetAndLock(thr, pc, addr, write_lock, true);
-}
-
-SyncVar* MetaMap::GetIfExistsAndLock(uptr addr, bool write_lock) {
- return GetAndLock(0, 0, addr, write_lock, false);
-}
-
-SyncVar* MetaMap::GetAndLock(ThreadState *thr, uptr pc,
- uptr addr, bool write_lock, bool create) {
+SyncVar *MetaMap::GetSync(ThreadState *thr, uptr pc, uptr addr, bool create,
+ bool save_stack) {
u32 *meta = MemToMeta(addr);
u32 idx0 = *meta;
u32 myidx = 0;
- SyncVar *mys = 0;
+ SyncVar *mys = nullptr;
for (;;) {
- u32 idx = idx0;
- for (;;) {
- if (idx == 0)
- break;
- if (idx & kFlagBlock)
- break;
+ for (u32 idx = idx0; idx && !(idx & kFlagBlock);) {
DCHECK(idx & kFlagSync);
SyncVar * s = sync_alloc_.Map(idx & ~kFlagMask);
- if (s->addr == addr) {
- if (myidx != 0) {
+ if (LIKELY(s->addr == addr)) {
+ if (UNLIKELY(myidx != 0)) {
mys->Reset(thr->proc());
sync_alloc_.Free(&thr->proc()->sync_cache, myidx);
}
- if (write_lock)
- s->mtx.Lock();
- else
- s->mtx.ReadLock();
return s;
}
idx = s->next;
}
if (!create)
- return 0;
- if (*meta != idx0) {
+ return nullptr;
+ if (UNLIKELY(*meta != idx0)) {
idx0 = *meta;
continue;
}
- if (myidx == 0) {
+ if (LIKELY(myidx == 0)) {
const u64 uid = atomic_fetch_add(&uid_gen_, 1, memory_order_relaxed);
myidx = sync_alloc_.Alloc(&thr->proc()->sync_cache);
mys = sync_alloc_.Map(myidx);
- mys->Init(thr, pc, addr, uid);
+ mys->Init(thr, pc, addr, uid, save_stack);
}
mys->next = idx0;
if (atomic_compare_exchange_strong((atomic_uint32_t*)meta, &idx0,
myidx | kFlagSync, memory_order_release)) {
- if (write_lock)
- mys->mtx.Lock();
- else
- mys->mtx.ReadLock();
return mys;
}
}
@@ -290,4 +269,11 @@ void MetaMap::OnProcIdle(Processor *proc) {
sync_alloc_.FlushCache(&proc->sync_cache);
}
+MetaMap::MemoryStats MetaMap::GetMemoryStats() const {
+ MemoryStats stats;
+ stats.mem_block = block_alloc_.AllocatedMemory();
+ stats.sync_obj = sync_alloc_.AllocatedMemory();
+ return stats;
+}
+
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_sync.h b/libsanitizer/tsan/tsan_sync.h
index c4056f6..fc8fa28 100644
--- a/libsanitizer/tsan/tsan_sync.h
+++ b/libsanitizer/tsan/tsan_sync.h
@@ -17,7 +17,6 @@
#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
#include "tsan_defs.h"
#include "tsan_clock.h"
-#include "tsan_mutex.h"
#include "tsan_dense_alloc.h"
namespace __tsan {
@@ -47,14 +46,16 @@ enum MutexFlags {
MutexFlagNotStatic,
};
+// SyncVar is a descriptor of a user synchronization object
+// (mutex or an atomic variable).
struct SyncVar {
SyncVar();
uptr addr; // overwritten by DenseSlabAlloc freelist
Mutex mtx;
u64 uid; // Globally unique id.
- u32 creation_stack_id;
- u32 owner_tid; // Set only by exclusive owners.
+ StackID creation_stack_id;
+ Tid owner_tid; // Set only by exclusive owners.
u64 last_lock;
int recursion;
atomic_uint32_t flags;
@@ -65,7 +66,7 @@ struct SyncVar {
// with the mtx. This reduces contention for hot sync objects.
SyncClock clock;
- void Init(ThreadState *thr, uptr pc, uptr addr, u64 uid);
+ void Init(ThreadState *thr, uptr pc, uptr addr, u64 uid, bool save_stack);
void Reset(Processor *proc);
u64 GetId() const {
@@ -102,10 +103,8 @@ struct SyncVar {
}
};
-/* MetaMap allows to map arbitrary user pointers onto various descriptors.
- Currently it maps pointers to heap block descriptors and sync var descs.
- It uses 1/2 direct shadow, see tsan_platform.h.
-*/
+// MetaMap maps app addresses to heap block (MBlock) and sync var (SyncVar)
+// descriptors. It uses 1/2 direct shadow, see tsan_platform.h for the mapping.
class MetaMap {
public:
MetaMap();
@@ -116,14 +115,25 @@ class MetaMap {
void ResetRange(Processor *proc, uptr p, uptr sz);
MBlock* GetBlock(uptr p);
- SyncVar* GetOrCreateAndLock(ThreadState *thr, uptr pc,
- uptr addr, bool write_lock);
- SyncVar* GetIfExistsAndLock(uptr addr, bool write_lock);
+ SyncVar *GetSyncOrCreate(ThreadState *thr, uptr pc, uptr addr,
+ bool save_stack) {
+ return GetSync(thr, pc, addr, true, save_stack);
+ }
+ SyncVar *GetSyncIfExists(uptr addr) {
+ return GetSync(nullptr, 0, addr, false, false);
+ }
void MoveMemory(uptr src, uptr dst, uptr sz);
void OnProcIdle(Processor *proc);
+ struct MemoryStats {
+ uptr mem_block;
+ uptr sync_obj;
+ };
+
+ MemoryStats GetMemoryStats() const;
+
private:
static const u32 kFlagMask = 3u << 30;
static const u32 kFlagBlock = 1u << 30;
@@ -134,8 +144,8 @@ class MetaMap {
SyncAlloc sync_alloc_;
atomic_uint64_t uid_gen_;
- SyncVar* GetAndLock(ThreadState *thr, uptr pc, uptr addr, bool write_lock,
- bool create);
+ SyncVar *GetSync(ThreadState *thr, uptr pc, uptr addr, bool create,
+ bool save_stack);
};
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_trace.h b/libsanitizer/tsan/tsan_trace.h
index 9f2677b..a771ad9 100644
--- a/libsanitizer/tsan/tsan_trace.h
+++ b/libsanitizer/tsan/tsan_trace.h
@@ -13,9 +13,9 @@
#define TSAN_TRACE_H
#include "tsan_defs.h"
-#include "tsan_mutex.h"
-#include "tsan_stack_trace.h"
+#include "tsan_ilist.h"
#include "tsan_mutexset.h"
+#include "tsan_stack_trace.h"
namespace __tsan {
@@ -68,6 +68,155 @@ struct Trace {
Trace() : mtx(MutexTypeTrace) {}
};
+namespace v3 {
+
+enum class EventType : u64 {
+ kAccessExt,
+ kAccessRange,
+ kLock,
+ kRLock,
+ kUnlock,
+ kTime,
+};
+
+// "Base" type for all events for type dispatch.
+struct Event {
+ // We use variable-length type encoding to give more bits to some event
+ // types that need them. If is_access is set, this is EventAccess.
+ // Otherwise, if is_func is set, this is EventFunc.
+ // Otherwise type denotes the type.
+ u64 is_access : 1;
+ u64 is_func : 1;
+ EventType type : 3;
+ u64 _ : 59;
+};
+static_assert(sizeof(Event) == 8, "bad Event size");
+
+// Nop event used as padding and does not affect state during replay.
+static constexpr Event NopEvent = {1, 0, EventType::kAccessExt, 0};
+
+// Compressed memory access can represent only some events with PCs
+// close enough to each other. Otherwise we fall back to EventAccessExt.
+struct EventAccess {
+ static constexpr uptr kPCBits = 15;
+
+ u64 is_access : 1; // = 1
+ u64 is_read : 1;
+ u64 is_atomic : 1;
+ u64 size_log : 2;
+ u64 pc_delta : kPCBits; // signed delta from the previous memory access PC
+ u64 addr : kCompressedAddrBits;
+};
+static_assert(sizeof(EventAccess) == 8, "bad EventAccess size");
+
+// Function entry (pc != 0) or exit (pc == 0).
+struct EventFunc {
+ u64 is_access : 1; // = 0
+ u64 is_func : 1; // = 1
+ u64 pc : 62;
+};
+static_assert(sizeof(EventFunc) == 8, "bad EventFunc size");
+
+// Extended memory access with full PC.
+struct EventAccessExt {
+ u64 is_access : 1; // = 0
+ u64 is_func : 1; // = 0
+ EventType type : 3; // = EventType::kAccessExt
+ u64 is_read : 1;
+ u64 is_atomic : 1;
+ u64 size_log : 2;
+ u64 _ : 11;
+ u64 addr : kCompressedAddrBits;
+ u64 pc;
+};
+static_assert(sizeof(EventAccessExt) == 16, "bad EventAccessExt size");
+
+// Access to a memory range.
+struct EventAccessRange {
+ static constexpr uptr kSizeLoBits = 13;
+
+ u64 is_access : 1; // = 0
+ u64 is_func : 1; // = 0
+ EventType type : 3; // = EventType::kAccessRange
+ u64 is_read : 1;
+ u64 is_free : 1;
+ u64 size_lo : kSizeLoBits;
+ u64 pc : kCompressedAddrBits;
+ u64 addr : kCompressedAddrBits;
+ u64 size_hi : 64 - kCompressedAddrBits;
+};
+static_assert(sizeof(EventAccessRange) == 16, "bad EventAccessRange size");
+
+// Mutex lock.
+struct EventLock {
+ static constexpr uptr kStackIDLoBits = 15;
+
+ u64 is_access : 1; // = 0
+ u64 is_func : 1; // = 0
+ EventType type : 3; // = EventType::kLock or EventType::kRLock
+ u64 pc : kCompressedAddrBits;
+ u64 stack_lo : kStackIDLoBits;
+ u64 stack_hi : sizeof(StackID) * kByteBits - kStackIDLoBits;
+ u64 _ : 3;
+ u64 addr : kCompressedAddrBits;
+};
+static_assert(sizeof(EventLock) == 16, "bad EventLock size");
+
+// Mutex unlock.
+struct EventUnlock {
+ u64 is_access : 1; // = 0
+ u64 is_func : 1; // = 0
+ EventType type : 3; // = EventType::kUnlock
+ u64 _ : 15;
+ u64 addr : kCompressedAddrBits;
+};
+static_assert(sizeof(EventUnlock) == 8, "bad EventUnlock size");
+
+// Time change event.
+struct EventTime {
+ u64 is_access : 1; // = 0
+ u64 is_func : 1; // = 0
+ EventType type : 3; // = EventType::kTime
+ u64 sid : sizeof(Sid) * kByteBits;
+ u64 epoch : kEpochBits;
+ u64 _ : 64 - 5 - sizeof(Sid) * kByteBits - kEpochBits;
+};
+static_assert(sizeof(EventTime) == 8, "bad EventTime size");
+
+struct Trace;
+
+struct TraceHeader {
+ Trace* trace = nullptr; // back-pointer to Trace containing this part
+ INode trace_parts; // in Trace::parts
+};
+
+struct TracePart : TraceHeader {
+ static constexpr uptr kByteSize = 256 << 10;
+ static constexpr uptr kSize =
+ (kByteSize - sizeof(TraceHeader)) / sizeof(Event);
+ // TraceAcquire does a fast event pointer overflow check by comparing
+ // pointer into TracePart::events with kAlignment mask. Since TracePart's
+ // are allocated page-aligned, this check detects end of the array
+ // (it also have false positives in the middle that are filtered separately).
+ // This also requires events to be the last field.
+ static constexpr uptr kAlignment = 0xff0;
+ Event events[kSize];
+
+ TracePart() {}
+};
+static_assert(sizeof(TracePart) == TracePart::kByteSize, "bad TracePart size");
+
+struct Trace {
+ Mutex mtx;
+ IList<TraceHeader, &TraceHeader::trace_parts, TracePart> parts;
+ Event* final_pos =
+ nullptr; // final position in the last part for finished threads
+
+ Trace() : mtx(MutexTypeTrace) {}
+};
+
+} // namespace v3
+
} // namespace __tsan
#endif // TSAN_TRACE_H
diff --git a/libsanitizer/tsan/tsan_update_shadow_word_inl.h b/libsanitizer/tsan/tsan_update_shadow_word.inc
index d23dfb0..a58ef0f 100644
--- a/libsanitizer/tsan/tsan_update_shadow_word_inl.h
+++ b/libsanitizer/tsan/tsan_update_shadow_word.inc
@@ -1,4 +1,4 @@
-//===-- tsan_update_shadow_word_inl.h ---------------------------*- C++ -*-===//
+//===-- tsan_update_shadow_word.inc -----------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/libsanitizer/tsan/tsan_vector_clock.cpp b/libsanitizer/tsan/tsan_vector_clock.cpp
new file mode 100644
index 0000000..2782985
--- /dev/null
+++ b/libsanitizer/tsan/tsan_vector_clock.cpp
@@ -0,0 +1,126 @@
+//===-- tsan_vector_clock.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_vector_clock.h"
+
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "tsan_mman.h"
+
+namespace __tsan {
+
+#if TSAN_VECTORIZE
+const uptr kVectorClockSize = kThreadSlotCount * sizeof(Epoch) / sizeof(m128);
+#endif
+
+VectorClock::VectorClock() { Reset(); }
+
+void VectorClock::Reset() {
+#if !TSAN_VECTORIZE
+ for (uptr i = 0; i < kThreadSlotCount; i++)
+ clk_[i] = kEpochZero;
+#else
+ m128 z = _mm_setzero_si128();
+ m128* vclk = reinterpret_cast<m128*>(clk_);
+ for (uptr i = 0; i < kVectorClockSize; i++) _mm_store_si128(&vclk[i], z);
+#endif
+}
+
+void VectorClock::Acquire(const VectorClock* src) {
+ if (!src)
+ return;
+#if !TSAN_VECTORIZE
+ for (uptr i = 0; i < kThreadSlotCount; i++)
+ clk_[i] = max(clk_[i], src->clk_[i]);
+#else
+ m128* __restrict vdst = reinterpret_cast<m128*>(clk_);
+ m128 const* __restrict vsrc = reinterpret_cast<m128 const*>(src->clk_);
+ for (uptr i = 0; i < kVectorClockSize; i++) {
+ m128 s = _mm_load_si128(&vsrc[i]);
+ m128 d = _mm_load_si128(&vdst[i]);
+ m128 m = _mm_max_epu16(s, d);
+ _mm_store_si128(&vdst[i], m);
+ }
+#endif
+}
+
+static VectorClock* AllocClock(VectorClock** dstp) {
+ if (UNLIKELY(!*dstp))
+ *dstp = New<VectorClock>();
+ return *dstp;
+}
+
+void VectorClock::Release(VectorClock** dstp) const {
+ VectorClock* dst = AllocClock(dstp);
+ dst->Acquire(this);
+}
+
+void VectorClock::ReleaseStore(VectorClock** dstp) const {
+ VectorClock* dst = AllocClock(dstp);
+ *dst = *this;
+}
+
+VectorClock& VectorClock::operator=(const VectorClock& other) {
+#if !TSAN_VECTORIZE
+ for (uptr i = 0; i < kThreadSlotCount; i++)
+ clk_[i] = other.clk_[i];
+#else
+ m128* __restrict vdst = reinterpret_cast<m128*>(clk_);
+ m128 const* __restrict vsrc = reinterpret_cast<m128 const*>(other.clk_);
+ for (uptr i = 0; i < kVectorClockSize; i++) {
+ m128 s = _mm_load_si128(&vsrc[i]);
+ _mm_store_si128(&vdst[i], s);
+ }
+#endif
+ return *this;
+}
+
+void VectorClock::ReleaseStoreAcquire(VectorClock** dstp) {
+ VectorClock* dst = AllocClock(dstp);
+#if !TSAN_VECTORIZE
+ for (uptr i = 0; i < kThreadSlotCount; i++) {
+ Epoch tmp = dst->clk_[i];
+ dst->clk_[i] = clk_[i];
+ clk_[i] = max(clk_[i], tmp);
+ }
+#else
+ m128* __restrict vdst = reinterpret_cast<m128*>(dst->clk_);
+ m128* __restrict vclk = reinterpret_cast<m128*>(clk_);
+ for (uptr i = 0; i < kVectorClockSize; i++) {
+ m128 t = _mm_load_si128(&vdst[i]);
+ m128 c = _mm_load_si128(&vclk[i]);
+ m128 m = _mm_max_epu16(c, t);
+ _mm_store_si128(&vdst[i], c);
+ _mm_store_si128(&vclk[i], m);
+ }
+#endif
+}
+
+void VectorClock::ReleaseAcquire(VectorClock** dstp) {
+ VectorClock* dst = AllocClock(dstp);
+#if !TSAN_VECTORIZE
+ for (uptr i = 0; i < kThreadSlotCount; i++) {
+ dst->clk_[i] = max(dst->clk_[i], clk_[i]);
+ clk_[i] = dst->clk_[i];
+ }
+#else
+ m128* __restrict vdst = reinterpret_cast<m128*>(dst->clk_);
+ m128* __restrict vclk = reinterpret_cast<m128*>(clk_);
+ for (uptr i = 0; i < kVectorClockSize; i++) {
+ m128 c = _mm_load_si128(&vclk[i]);
+ m128 d = _mm_load_si128(&vdst[i]);
+ m128 m = _mm_max_epu16(c, d);
+ _mm_store_si128(&vdst[i], m);
+ _mm_store_si128(&vclk[i], m);
+ }
+#endif
+}
+
+} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_vector_clock.h b/libsanitizer/tsan/tsan_vector_clock.h
new file mode 100644
index 0000000..63b2063
--- /dev/null
+++ b/libsanitizer/tsan/tsan_vector_clock.h
@@ -0,0 +1,51 @@
+//===-- tsan_vector_clock.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_VECTOR_CLOCK_H
+#define TSAN_VECTOR_CLOCK_H
+
+#include "tsan_defs.h"
+
+namespace __tsan {
+
+// Fixed-size vector clock, used both for threads and sync objects.
+class VectorClock {
+ public:
+ VectorClock();
+
+ Epoch Get(Sid sid) const;
+ void Set(Sid sid, Epoch v);
+
+ void Reset();
+ void Acquire(const VectorClock* src);
+ void Release(VectorClock** dstp) const;
+ void ReleaseStore(VectorClock** dstp) const;
+ void ReleaseStoreAcquire(VectorClock** dstp);
+ void ReleaseAcquire(VectorClock** dstp);
+
+ VectorClock& operator=(const VectorClock& other);
+
+ private:
+ Epoch clk_[kThreadSlotCount] VECTOR_ALIGNED;
+};
+
+ALWAYS_INLINE Epoch VectorClock::Get(Sid sid) const {
+ return clk_[static_cast<u8>(sid)];
+}
+
+ALWAYS_INLINE void VectorClock::Set(Sid sid, Epoch v) {
+ DCHECK_GE(v, clk_[static_cast<u8>(sid)]);
+ clk_[static_cast<u8>(sid)] = v;
+}
+
+} // namespace __tsan
+
+#endif // TSAN_VECTOR_CLOCK_H
diff --git a/libsanitizer/ubsan/ubsan_diag.cpp b/libsanitizer/ubsan/ubsan_diag.cpp
index ef2e495..8de51bc 100644
--- a/libsanitizer/ubsan/ubsan_diag.cpp
+++ b/libsanitizer/ubsan/ubsan_diag.cpp
@@ -157,7 +157,7 @@ static void RenderLocation(InternalScopedString *Buffer, Location Loc) {
return;
}
case Location::LK_Memory:
- Buffer->append("%p", Loc.getMemoryLocation());
+ Buffer->append("%p", reinterpret_cast<void *>(Loc.getMemoryLocation()));
return;
case Location::LK_Symbolized: {
const AddressInfo &Info = Loc.getSymbolizedStack()->info;
@@ -169,7 +169,7 @@ static void RenderLocation(InternalScopedString *Buffer, Location Loc) {
RenderModuleLocation(Buffer, Info.module, Info.module_offset,
Info.module_arch, common_flags()->strip_path_prefix);
else
- Buffer->append("%p", Info.address);
+ Buffer->append("%p", reinterpret_cast<void *>(Info.address));
return;
}
case Location::LK_Null:
@@ -286,7 +286,7 @@ static void PrintMemorySnippet(const Decorator &Decor, MemoryLocation Loc,
Buffer.append("\n");
// Emit highlights.
- Buffer.append(Decor.Highlight());
+ Buffer.append("%s", Decor.Highlight());
Range *InRange = upperBound(Min, Ranges, NumRanges);
for (uptr P = Min; P != Max; ++P) {
char Pad = ' ', Byte = ' ';
@@ -355,7 +355,7 @@ Diag::~Diag() {
Buffer.clear();
}
- Buffer.append(Decor.Bold());
+ Buffer.append("%s", Decor.Bold());
RenderLocation(&Buffer, Loc);
Buffer.append(":");
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 22f78a3..daafc57 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,706 @@
+2021-10-06 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/Makefile.am: Add new headers.
+ * include/Makefile.in: Regenerate.
+ * include/std/functional: Include <bits/move_only_function.h>.
+ * include/std/version (__cpp_lib_move_only_function): Define.
+ * include/bits/mofunc_impl.h: New file.
+ * include/bits/move_only_function.h: New file.
+ * testsuite/20_util/move_only_function/call.cc: New test.
+ * testsuite/20_util/move_only_function/cons.cc: New test.
+ * testsuite/20_util/move_only_function/move.cc: New test.
+ * testsuite/20_util/move_only_function/version.cc: New test.
+
+2021-10-05 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/21_strings/basic_string_view/requirements/trivially_copyable.cc:
+ New test.
+ * testsuite/23_containers/span/trivially_copyable.cc: New test.
+
+2021-10-05 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/utility.h (__is_in_place_type_v): Define
+ variable template to detect in_place_type_t specializations.
+ (__is_in_place_type): Replace class template with alias
+ template using __is_in_place_type_v.
+ * include/std/any (any(T&&)): Check __is_in_place_type first and
+ avoid instantiating is_copy_constructible unnecessarily.
+
+2021-10-05 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/20_util/integer_comparisons/greater.cc: New test.
+
+2021-10-05 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/27_io/basic_ostream/inserters_other/char/volatile_ptr.cc:
+ Check result matches non-volatile pointer.
+
+2021-10-05 Jonathan Wakely <jwakely@redhat.com>
+
+ PR c++/102535
+ * testsuite/20_util/is_trivially_constructible/value.cc: Adjust
+ expected value for C++20.
+
+2021-10-05 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/std_function.h (_Any_data::_M_access): Add
+ noexcept.
+ (_Function_base::_Base_manager::_M_get_pointer): Likewise.
+ (_Function_base::_Base_manager::_M_not_empty_function):
+ Likewise.
+
+2021-10-05 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/ostream (operator<<(const volatile void*)):
+ Add new overload, as per P1147R1.
+ * testsuite/27_io/basic_ostream/inserters_other/char/volatile_ptr.cc:
+ New test.
+
+2021-10-05 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/stl_queue.h
+ (__cpp_lib_adaptor_iterator_pair_constructor): Set to correct
+ value.
+ * include/bits/stl_stack.h
+ (__cpp_lib_adaptor_iterator_pair_constructor): Likewise.
+ * include/std/version
+ (__cpp_lib_adaptor_iterator_pair_constructor): Likewise.
+ * testsuite/23_containers/queue/cons_from_iters.cc: Update
+ expected value.
+ * testsuite/23_containers/stack/cons_from_iters.cc: Likewise.
+
+2021-10-04 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/forward_list.h (forward_list): Use non-deduced
+ context for allocator parameter of allocator-extended copy and
+ move constructors.
+ * include/bits/stl_bvector.h (vector<bool>): Likewise.
+ * include/bits/stl_deque.h (deque): Likewise.
+ * include/bits/stl_list.h (list): Likewise.
+ * include/bits/stl_map.h (map): Likewise.
+ * include/bits/stl_multimap.h (multimap): Likewise.
+ * include/bits/stl_multiset.h (multiset): Likewise.
+ * include/bits/stl_set.h (set): Likewise.
+ * include/bits/stl_vector.h (vector): Likewise.
+ * include/bits/stl_queue.h (queue, priority_queue): Do not
+ constrain Allocator template parameter of deduction guides that
+ have a Container parameter.
+ * include/bits/stl_stack.h (stack): Likewise.
+ * include/debug/deque (__gnu_debug::deque): Use non-deduced
+ context for allocator parameter of allocator-extended copy and
+ move constructors.
+ * include/debug/list (__gnu_debug::list): Likewise.
+ * include/debug/map.h (__gnu_debug::map): Likewise.
+ * include/debug/multimap.h (__gnu_debug::multimap): Likewise.
+ * include/debug/multiset.h (__gnu_debug::multiset): Likewise.
+ * include/debug/set.h (__gnu_debug::set): Likewise.
+ * include/debug/vector (__gnu_debug::vector): Likewise.
+ * testsuite/23_containers/deque/cons/deduction.cc: Test class
+ template argument deduction with non-deduced allocator
+ arguments.
+ * testsuite/23_containers/forward_list/cons/deduction.cc:
+ Likewise.
+ * testsuite/23_containers/list/cons/deduction.cc: Likewise.
+ * testsuite/23_containers/map/cons/deduction.cc: Likewise.
+ * testsuite/23_containers/multimap/cons/deduction.cc: Likewise.
+ * testsuite/23_containers/multiset/cons/deduction.cc: Likewise.
+ * testsuite/23_containers/priority_queue/deduction.cc: Likewise.
+ * testsuite/23_containers/queue/deduction.cc: Likewise.
+ * testsuite/23_containers/set/cons/deduction.cc: Likewise.
+ * testsuite/23_containers/stack/deduction.cc: Likewise.
+ * testsuite/23_containers/unordered_map/cons/deduction.cc:
+ Likewise.
+ * testsuite/23_containers/unordered_multimap/cons/deduction.cc:
+ Likewise.
+ * testsuite/23_containers/unordered_multiset/cons/deduction.cc:
+ Likewise.
+ * testsuite/23_containers/unordered_set/cons/deduction.cc:
+ Likewise.
+ * testsuite/23_containers/vector/cons/deduction.cc: Likewise.
+
+2021-10-04 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/variant (__detail::__variant::__as): Add missing
+ noexcept to first overload.
+
+2021-10-04 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/basic_string.h (basic_string(nullptr_t)): Define
+ as deleted.
+ (operator=(nullptr_t)): Likewise.
+ * include/bits/cow_string.h (basic_string(nullptr_t)): Likewise.
+ (operator=(nullptr_t)): Likewise.
+ * include/std/string_view (basic_string_view(nullptr_t)):
+ Likewise.
+ * testsuite/21_strings/basic_string/cons/char/nullptr.cc: New test.
+ * testsuite/21_strings/basic_string_view/cons/char/nonnull.cc:
+ Change dg-warning to dg-error.
+ * testsuite/21_strings/basic_string_view/cons/wchar_t/nonnull.cc:
+ Likewise.
+
+2021-10-02 Jonathan Wakely <jwakely@redhat.com>
+
+ * src/c++17/fs_ops.cc (create_directory): Fix typo in enum name.
+ * src/filesystem/ops-common.h (__last_system_error): Add
+ explicit cast to avoid narrowing conversion.
+ (do_space): Fix type in function name.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/102100
+ * include/Makefile.am (c++config.h): Define
+ _GLIBCXX_VERBOSE_ASSERT based on configure output.
+ * include/Makefile.in: Regenerate.
+ * include/bits/c++config: Fix condition for verbose assertions.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/92546
+ * include/bits/erase_if.h (__erase_nodes_if): Use __niter_base to
+ unwrap debug iterators.
+ * include/bits/refwrap.h: Do not error if included in C++03.
+ * include/bits/stl_algo.h (__remove_if): Move to ...
+ * include/bits/stl_algobase.h (__remove_if): ... here.
+ * include/std/deque (erase, erase_if): Use __remove_if instead of
+ remove and remove_if.
+ * include/std/string (erase, erase_if): Likewise.
+ * include/std/vector (erase, erase_if): Likewise.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/66742
+ * include/bits/list.tcc (list::sort()): Use _Scratch_list
+ objects for splicing and merging.
+ (list::sort(StrictWeakOrdering)): Likewise.
+ * include/bits/stl_list.h (__detail::_Scratch_list): New type.
+ * src/c++98/list.cc (_List_node_base::_M_transfer): Add
+ assertion for --enable-libstdcxx-debug library.
+ * testsuite/23_containers/list/operations/66742.cc: New test.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/100612
+ * include/std/thread (__pmf_expects_stop_token): New variable
+ template to detect a pointer to member function that needs a
+ stop_token to be added to the arguments.
+ (jthread::__S_create): Use __pmf_expects_stop_token.
+ (jthread::__S_create_pmf): New function.
+ * testsuite/30_threads/jthread/100612.cc: New test.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/stl_queue.h
+ (__cpp_lib_adaptor_iterator_pair_constructor): Define for C++23, as
+ per P1425R4.
+ (queue(InputIterator, InputIterator)): Likewise.
+ (queue(InputIterator, InputIterator, const Alloc&)): Likewise.
+ * include/bits/stl_stack.h
+ (__cpp_lib_adaptor_iterator_pair_constructor): Likewise.
+ (stack(InputIterator, InputIterator)): Likewise.
+ (stack(InputIterator, InputIterator, const Alloc&)): Likewise.
+ * include/std/version (__cpp_lib_adaptor_iterator_pair_constructor):
+ Define.
+ * testsuite/23_containers/queue/cons_from_iters.cc: New test.
+ * testsuite/23_containers/stack/cons_from_iters.cc: New test.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/stl_queue.h (priority_queue): Add
+ allocator-extended overloads for constructors taking iterator.
+ * testsuite/23_containers/priority_queue/lwg3506.cc: New test.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/stl_queue.h (priority_queue): Construct sequence
+ from iterators when no sequence argument is present (LWG 3529).
+ * testsuite/23_containers/priority_queue/lwg3529.cc: New test.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/stl_queue.h (priority_queue): Constrain
+ constructors with InputIterator parameters (LWG 3522).
+ * testsuite/23_containers/priority_queue/lwg3522.cc: New test.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/ranges_base.h (ranges::distance): Split overload
+ into two (LWG 3392).
+ * testsuite/24_iterators/range_operations/lwg3392.cc: New test.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/30_threads/thread/cons/3.cc: Remove derivation from
+ std::unary_function.
+ * testsuite/30_threads/thread/cons/4.cc: Likewise.
+ * testsuite/30_threads/thread/cons/5.cc: Likewise.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/ext/pb_ds/example/basic_multimap.cc: Remove
+ unnecesary derivation from std::unary_function.
+ * testsuite/ext/pb_ds/example/erase_if.cc: Likewise.
+ * testsuite/ext/pb_ds/example/hash_illegal_resize.cc: Likewise.
+ * testsuite/ext/pb_ds/example/hash_initial_size.cc: Likewise.
+ * testsuite/ext/pb_ds/example/hash_load_set_change.cc: Likewise.
+ * testsuite/ext/pb_ds/example/hash_mod.cc: Likewise.
+ * testsuite/ext/pb_ds/example/hash_resize.cc: Likewise.
+ * testsuite/ext/pb_ds/example/hash_shift_mask.cc: Likewise.
+ * testsuite/ext/pb_ds/example/priority_queue_dijkstra.cc:
+ Likewise.
+ * testsuite/ext/pb_ds/example/ranged_hash.cc: Likewise.
+ * testsuite/ext/pb_ds/example/store_hash.cc: Likewise.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * src/c++11/functexcept.cc (__throw_out_of_range_fmt): Do not
+ expand the format string for freestanding, or non-vebose, or if
+ we're just going to abort anyway.
+ * src/c++11/snprintf_lite.cc: Remove unused header and
+ declaration.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/variant (__do_visit): Use variant_npos instead of
+ literal -1 that requires a narrowing conversion.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/99327
+ * src/filesystem/ops-common.h (__unsupported): New function to
+ return a suitable error code for missing functionality.
+ (posix::off_t): New typedef.
+ (posix::*): Set errno to ENOSYS instead of ENOTSUP for no-op
+ fallback implementations.
+ (do_copy_file): Replace uses of errc::not_supported.
+ * src/c++17/fs_ops.cc (fs::copy, fs::copy_file, create_dir)
+ (fs::create_directory, fs::create_directory_symlink)
+ (fs::create_hard_link, fs::create_symlink, fs::current_path)
+ (fs::equivalent, do_stat, fs::file_size, fs::hard_link_count)
+ (fs::last_write_time, fs::permissions, fs::read_symlink):
+ Replace uses of errc::not_supported.
+ (fs::resize_file): Qualify off_t.
+ * src/filesystem/ops.cc (fs::copy, fs::copy_file, create_dir)
+ (fs::create_directory, fs::create_directory_symlink)
+ (fs::create_hard_link, fs::create_symlink, fs::current_path)
+ (fs::equivalent, do_stat, fs::file_size, fs::last_write_time)
+ (fs::permissions, fs::read_symlink, fs::system_complete):
+ Replace uses of errc::not_supported.
+ (fs::resize_file): Qualify off_t and enable unconditionally.
+ * testsuite/19_diagnostics/system_error/cons-1.cc: Likewise.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * src/filesystem/ops-common.h (last_error): New helper function.
+ (filesystem::do_space): Use last_error().
+ * src/c++17/fs_ops.cc (fs::absolute, fs::create_hard_link)
+ (fs::equivalent, fs::remove, fs::temp_directory_path): Use
+ last_error().
+ * src/filesystem/ops.cc (fs::create_hard_link)
+ (fs::remove, fs::temp_directory_path): Likewise.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/type_traits (__conditional): New class template
+ for internal uses of std::conditional.
+ (__conditional_t): New alias template to replace conditional_t.
+ (__and_, __or_, __result_of_memfun, __result_of_memobj): Use
+ __conditional_t instead of conditional::type.
+ * include/bits/atomic_base.h (__atomic_impl::_Diff): Likewise.
+ * include/bits/hashtable.h (_Hashtable): Likewise.
+ * include/bits/hashtable_policy.h (_Node_iterator, _Insert_base)
+ (_Local_iterator): Likewise. Replace typedefs with
+ using-declarations.
+ * include/bits/move.h (move_if_noexcept): Use __conditional_t.
+ * include/bits/parse_numbers.h (_Select_int_base): Likewise.
+ * include/bits/ptr_traits.h (__make_not_void): Likewise.
+ * include/bits/ranges_algobase.h (__copy_or_move_backward)
+ (__copy_or_move): Likewise.
+ * include/bits/ranges_base.h (borrowed_iterator_t): Likewise.
+ * include/bits/ranges_util.h (borrowed_subrange_t): Likewise.
+ * include/bits/regex_compiler.h (_BracketMatcher): Use
+ __conditional_t. Replace typedefs with using-declarations.
+ * include/bits/shared_ptr_base.h (__shared_count): Use
+ __conditional_t.
+ * include/bits/stl_algobase.h (__copy_move, __copy_move_backward):
+ Likewise.
+ * include/bits/stl_iterator.h (__detail::__clamp_iter_cat)
+ (reverse_iterator::iterator_concept)
+ (__make_move_if_noexcept_iterator)
+ (iterator_traits<common_iterator<_It, _Sent>>)
+ (iterator_traits<counted_iterator<_It>>): Likewise.
+ * include/bits/stl_pair.h (_PCC, pair::operator=): Likewise.
+ * include/bits/stl_tree.h (_Rb_tree::insert_return_type)
+ (_Rb_tree::_M_clone_node): Likewise.
+ * include/bits/unique_ptr.h (unique_ptr(unique_ptr<U,E>&&)):
+ Likewise.
+ * include/bits/uses_allocator.h (__uses_alloc): Likewise.
+ (__is_uses_allocator_predicate): Likewise.
+ * include/debug/functions.h (__foreign_iterator_aux2): Likewise.
+ * include/experimental/any (any::_Manager, __any_caster):
+ Likewise.
+ * include/experimental/executor (async_completion): Likewise.
+ * include/experimental/functional (__boyer_moore_base_t):
+ Likewise.
+ * include/std/any (any::_Manager): Likewise.
+ * include/std/functional (__boyer_moore_base_t): Likewise.
+ * include/std/ranges (borrowed_iterator_t)
+ (borrowed_subrange_t, __detail::__maybe_present_t)
+ (__detail::__maybe_const_t, split_view): Likewise.
+ * include/std/tuple (__empty_not_final, tuple::operator=):
+ Likewise.
+ * include/std/variant (__detail::__variant::__get_t): Likewise.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/78113
+ * include/std/variant (__do_visit): Use a switch when we have a
+ single variant with a small number of alternatives.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/90943
+ * include/std/variant (__cpp_lib_variant): Update value.
+ (__detail::__variant::__as): New helpers implementing the
+ as-variant exposition-only function templates.
+ (visit, visit<R>): Use __as to upcast the variant parameters.
+ * include/std/version (__cpp_lib_variant): Update value.
+ * testsuite/20_util/variant/visit_inherited.cc: New test.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/stl_iterator.h (__normal_iterator): Simplify
+ converting constructor and do not require _Container::pointer.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/cow_string.h [_GLIBCXX_FULLY_DYNAMIC_STRING]
+ (basic_string(basic_string&&)): Add noexcept and avoid
+ allocation, by sharing rep with the rvalue string.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/stl_iterator.h (common_iterator::__arrow_proxy)
+ (common_iterator::__postfix_proxy): Add noexcept.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/94418
+ * include/bits/stl_iterator.h (reverse_iterator): Use
+ conditional noexcept on constructors and assignment operators.
+ * testsuite/24_iterators/reverse_iterator/noexcept.cc: New test.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/100153
+ * include/bits/vector.tcc (vector<bool>::_M_shrink_to_fit()):
+ When size() is zero just deallocate and reset.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/96733
+ * include/bits/stl_algo.h (clamp): Use std::min and std::max.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/regex.h (basic_regex::multiline): Define for
+ non-strict C++11 and C++14 modes.
+ * include/bits/regex_constants.h (regex_constants::multiline):
+ Add _GLIBCXX_RESOLVE_LIB_DEFECTS comment.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/25_algorithms/is_permutation/2.cc: Include <iterator>.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/stream_iterator.h (istream_iterator): Add
+ noexcept to constructors and non-throwing member functions and
+ friend functions.
+ (ostream_iterator): Likewise.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/boost_concept_check.h (_Is_vector_bool_iterator):
+ New trait to identify vector<bool> iterators, including debug
+ ones.
+ (_ForwardIteratorReferenceConcept): Add default template
+ argument using _Is_vector_bool_iterator and use it in partial
+ specialization for the vector<bool> cases.
+ (_Mutable_ForwardIteratorReferenceConcept): Likewise.
+ * testsuite/24_iterators/operations/prev_neg.cc: Adjust dg-error
+ line number.
+
+2021-10-01 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/list.tcc (list::merge): Remove call to size() and
+ try-catch block. Use _Finalize_merge instead.
+ * include/bits/stl_list.h (list::_Finalize_merge): New
+ scope guard type to update _M_size members after a merge.
+
+2021-09-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/regex.h (basic_regex::multiline): Fix #if
+ condition.
+
+2021-09-29 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/regex.h (basic_regex::multiline): Define constant
+ for C++17.
+ * include/bits/regex_constants.h (regex_constants::multiline):
+ Define constant for C++17.
+ (regex_constants::__multiline): Define duplicate constant for
+ internal use in C++11 and C++14.
+ * include/bits/regex_executor.h (_Executor::_M_match_multiline()):
+ New member function.
+ (_Executor::_M_is_line_terminator(_CharT)): New member function.
+ (_Executor::_M_at_begin(), _Executor::_M_at_end()): Use new
+ member functions to support multiline matches.
+ * testsuite/28_regex/algorithms/regex_match/multiline.cc: New test.
+
+2021-09-29 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/regex_compiler.h (_Compiler::_S_validate): New
+ function.
+ * include/bits/regex_compiler.tcc (_Compiler::_Compiler): Use
+ _S_validate to check flags.
+ * include/bits/regex_error.h (_S_grammar): New error code for
+ internal use.
+ * testsuite/28_regex/basic_regex/ctors/grammar.cc: New test.
+
+2021-09-29 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/84110
+ * include/bits/regex_error.h (regex_constants::_S_null): New
+ error code for internal use.
+ * include/bits/regex_scanner.tcc (_Scanner::_M_scan_normal()):
+ Check for null character.
+ * testsuite/28_regex/basic_regex/84110.cc: New test.
+
+2021-09-29 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/regex.h (__detail::__is_contiguous_iter): Move
+ here from <bits/regex_compiler.h>.
+ (basic_regex::_M_compile): New function to compile an NFA from
+ a regular expression string.
+ (basic_regex::basic_regex): Use _M_compile instead of delegating
+ to other constructors.
+ (basic_regex::operator=(const basic_regex&)): Define as
+ defaulted.
+ (basic_regex::operator=(initializer_list<C>)): Use _M_compile.
+ (basic_regex::assign(const basic_regex&)): Use copy assignment.
+ (basic_regex::assign(basic_regex&&)): Use move assignment.
+ (basic_regex::assign(const C*, flag_type)): Use _M_compile
+ instead of constructing a temporary string.
+ (basic_regex::assign(const C*, size_t, flag_type)): Likewise.
+ (basic_regex::assign(const basic_string<C,T,A>&, flag_type)):
+ Use _M_compile instead of constructing a temporary basic_regex.
+ (basic_regex::assign(InputIter, InputIter, flag_type)): Avoid
+ constructing a temporary string for contiguous iterators of the
+ right value type.
+ * include/bits/regex_compiler.h (__is_contiguous_iter): Move to
+ <bits/regex.h>.
+ (__enable_if_contiguous_iter, __disable_if_contiguous_iter)
+ (__compile_nfa): Remove.
+ * testsuite/28_regex/basic_regex/assign/exception_safety.cc: New
+ test.
+ * testsuite/28_regex/basic_regex/ctors/char/other.cc: New test.
+
+2021-09-28 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/atomic_timed_wait.h (__platform_wait_until_impl):
+ Return false for ETIMEDOUT and true otherwise.
+
+2021-09-28 François Dumont <fdumont@gcc.gnu.org>
+
+ * testsuite/20_util/default_delete/48631_neg.cc: Adapt dg-prune-output message
+ to also match message with '__8' in it.
+
+2021-09-28 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/regex_automaton.h (_NFA_base::_SizeT): Remove.
+ * include/bits/regex_compiler.h (_Compiler::_IterT): Remove.
+ * include/bits/regex_compiler.tcc: Likewise.
+ * include/bits/regex_scanner.h (_Scanner::_IterT): Remove.
+ * include/bits/regex_scanner.tcc: Likewise.
+
+2021-09-28 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/regex_compiler.tcc: Add line break in empty while
+ statement.
+ * include/bits/regex_executor.tcc: Avoid unused parameter
+ warning.
+
+2021-09-28 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/regex.h (basic_regex, swap): Add noexcept to
+ non-throwing functions.
+ * include/bits/regex_automaton.h (_State_base, _State)
+ (_NFA_base): Likewise.
+ * include/bits/regex_compiler.h (_Compiler): Likewise.
+ * include/bits/regex_error.h (regex_error::code()): Likewise.
+ * include/bits/regex_scanner.h (_Scanner): Likewise.
+
+2021-09-28 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/atomic_wait.h (_GLIBCXX_HAVE_PLATFORM_WAIT):
+ Define before first attempt to check it.
+
+2021-09-28 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1.cc:
+ Do not check non-default constructible sequences when
+ _GLIBCXX_CONCEPT_CHECKS is defined.
+ * testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1_c++98.cc:
+ Likewise.
+ * testsuite/23_containers/queue/requirements/explicit_instantiation/1.cc:
+ Likewise.
+ * testsuite/23_containers/queue/requirements/explicit_instantiation/1_c++98.cc:
+ Likewise.
+ * testsuite/23_containers/stack/requirements/explicit_instantiation/1.cc:
+ Likewise.
+ * testsuite/23_containers/stack/requirements/explicit_instantiation/1_c++98.cc:
+ Likewise.
+
+2021-09-28 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/23_containers/deque/requirements/explicit_instantiation/3.cc:
+ Do not test implicit allocator rebinding when _GLIBCXX_CONCEPT_CHECKS
+ is defined.
+ * testsuite/23_containers/forward_list/requirements/explicit_instantiation/3.cc:
+ Likewise.
+ * testsuite/23_containers/list/requirements/explicit_instantiation/3.cc:
+ Likewise.
+ * testsuite/23_containers/list/requirements/explicit_instantiation/5.cc:
+ Likewise.
+ * testsuite/23_containers/map/requirements/explicit_instantiation/3.cc:
+ Likewise.
+ * testsuite/23_containers/map/requirements/explicit_instantiation/5.cc:
+ Likewise.
+ * testsuite/23_containers/multimap/requirements/explicit_instantiation/3.cc:
+ Likewise.
+ * testsuite/23_containers/multimap/requirements/explicit_instantiation/5.cc:
+ Likewise.
+ * testsuite/23_containers/multiset/requirements/explicit_instantiation/3.cc:
+ Likewise.
+ * testsuite/23_containers/multiset/requirements/explicit_instantiation/5.cc:
+ Likewise.
+ * testsuite/23_containers/set/requirements/explicit_instantiation/3.cc:
+ Likewise.
+ * testsuite/23_containers/set/requirements/explicit_instantiation/5.cc:
+ Likewise.
+ * testsuite/23_containers/unordered_map/requirements/explicit_instantiation/3.cc:
+ Likewise.
+ * testsuite/23_containers/unordered_multimap/requirements/explicit_instantiation/3.cc:
+ Likewise.
+ * testsuite/23_containers/unordered_multiset/requirements/explicit_instantiation/3.cc:
+ Likewise.
+ * testsuite/23_containers/unordered_set/requirements/explicit_instantiation/3.cc:
+ Likewise.
+ * testsuite/23_containers/vector/ext_pointer/explicit_instantiation/3.cc:
+ Likewise.
+ * testsuite/23_containers/vector/requirements/explicit_instantiation/3.cc:
+ Likewise.
+
+2021-09-28 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/boost_concept_check.h (_ForwardIteratorConcept)
+ (_BidirectionalIteratorConcept, _RandomAccessIteratorConcept):
+ Check result types of iterator operations.
+ (_Mutable_ForwardIteratorConcept): Check that iterator's
+ reference type is a reference to its value type.
+ (_Mutable_BidirectionalIteratorConcept): Do not require the
+ value type to be assignable.
+ (_Mutable_RandomAccessIteratorConcept): Likewise.
+ * testsuite/24_iterators/operations/prev_neg.cc: Adjust dg-error
+ line number.
+
+2021-09-28 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/25_algorithms/copy/34595.cc: Add missing operation
+ for type used as an iterator.
+ * testsuite/25_algorithms/unique_copy/check_type.cc: Likewise.
+
+2021-09-28 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/20_util/is_nothrow_swappable/value.h: Use custom
+ comparison function for priority_queue of type with no
+ relational operators.
+ * testsuite/20_util/is_swappable/value.h: Likewise.
+ * testsuite/24_iterators/output/concept.cc: Add operator< to
+ type used in set.
+
+2021-09-28 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/boost_concept_check.h (_OutputIteratorConcept):
+ Use a function to preserve value category of the type.
+ * include/bits/stl_algobase.h (copy, move, fill_n): Use a
+ reference as the second argument for _OutputIteratorConcept.
+ (copy_backward, move_backward): Use _OutputIteratorConcept
+ instead of _ConvertibleConcept.
+
+2021-09-28 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/stl_iterator.h (pointer_traits): Define partial
+ specialization for __normal_iterator.
+ * testsuite/24_iterators/normal_iterator/to_address.cc: New test.
+
+2021-09-28 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/move.h (forward(remove_reference_t<T>&&)):
+ Improve text of static_assert.
+ * testsuite/20_util/forward/c_neg.cc: Adjust dg-error.
+ * testsuite/20_util/forward/f_neg.cc: Likewise.
+
+2021-09-28 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/102499
+ * include/bits/fs_path.h (path::begin, path::end): Add noexcept
+ to declarations, to match definitions.
+
+2021-09-24 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/range_access.h (cbegin, cend): Remove redundant
+ 'inline' specifier.
+
+2021-09-23 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/20_util/specialized_algorithms/memory_management_tools/destroy_neg.cc:
+ Remove dg-error lines for C++20-only errors.
+
+2021-09-23 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/19_diagnostics/headers/system_error/93151.cc:
+ Disable PCH.
+
+2021-09-23 Jonathan Wakely <jwakely@redhat.com>
+
+ * src/c++11/system_error.cc (system_error_category) [_WIN32]:
+ Map Windows error codes to generic POSIX error numbers. Use
+ FormatMessage instead of strerror.
+ * testsuite/19_diagnostics/error_category/system_category.cc:
+ Adjust for new behaviour on Windows.
+
+2021-09-23 Jonathan Wakely <jwakely@redhat.com>
+
+ * src/c++11/system_error.cc (generic_error_category): Define
+ class and virtual functions as 'final'.
+ (generic_error_category::equivalent(int, const error_condition&)):
+ Override.
+ (system_error_category): Define class and virtual functions as
+ 'final'.
+ (system_error_category::equivalent(int, const error_condition&)):
+ Override.
+ (generic_category_instance, system_category_instance): Use
+ constinit union to make the objects immortal.
+
+2021-09-23 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/102425
+ * src/c++11/system_error.cc
+ (system_error_category::default_error_condition): Add 0 to
+ switch.
+ * testsuite/19_diagnostics/error_category/102425.cc: New test.
+
2021-09-17 Jonathan Wakely <jwakely@redhat.com>
* include/bits/fs_path.h (path::iterator): Add noexcept to all
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 15c0ad8..0e43f14 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -117,6 +117,7 @@ bits_headers = \
${bits_srcdir}/c++0x_warning.h \
${bits_srcdir}/char_traits.h \
${bits_srcdir}/charconv.h \
+ ${bits_srcdir}/chrono.h \
${bits_srcdir}/codecvt.h \
${bits_srcdir}/concept_check.h \
${bits_srcdir}/cow_string.h \
@@ -154,7 +155,9 @@ bits_headers = \
${bits_srcdir}/mask_array.h \
${bits_srcdir}/max_size_type.h \
${bits_srcdir}/memoryfwd.h \
+ ${bits_srcdir}/mofunc_impl.h \
${bits_srcdir}/move.h \
+ ${bits_srcdir}/move_only_function.h \
${bits_srcdir}/node_handle.h \
${bits_srcdir}/ostream.tcc \
${bits_srcdir}/ostream_insert.h \
@@ -1315,6 +1318,12 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
grep "^[ ]*#[ ]*define[ ][ ]*_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT[ ][ ]*1[ ]*$$" \
${CONFIG_HEADER} > /dev/null 2>&1 \
&& ldbl_alt128_compat='s,^#undef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT$$,#define _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT 1,' ;\
+ verbose_assert='s,g,g,' ; \
+ grep "^[ ]*#[ ]*define[ ][ ]*_GLIBCXX_HOSTED[ ][ ]*1[ ]*$$" \
+ ${CONFIG_HEADER} > /dev/null 2>&1 \
+ && grep "^[ ]*#[ ]*define[ ][ ]*_GLIBCXX_VERBOSE[ ][ ]*1[ ]*$$" \
+ ${CONFIG_HEADER} > /dev/null 2>&1 \
+ && verbose_assert='s,^#undef _GLIBCXX_VERBOSE_ASSERT$$,#define _GLIBCXX_VERBOSE_ASSERT 1,' ;\
sed -e "s,define __GLIBCXX__,define __GLIBCXX__ $$date," \
-e "s,define _GLIBCXX_RELEASE,define _GLIBCXX_RELEASE $$release," \
-e "s,define _GLIBCXX_INLINE_VERSION, define _GLIBCXX_INLINE_VERSION $$ns_version," \
@@ -1326,6 +1335,7 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
-e "s,define _GLIBCXX_USE_FLOAT128,$$float128," \
-e "$$ldbl_compat" \
-e "$$ldbl_alt128_compat" \
+ -e "$$verbose_assert" \
< ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
sed -e 's/HAVE_/_GLIBCXX_HAVE_/g' \
-e 's/PACKAGE/_GLIBCXX_PACKAGE/g' \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 9d559e2..0571a63 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -467,6 +467,7 @@ bits_headers = \
${bits_srcdir}/c++0x_warning.h \
${bits_srcdir}/char_traits.h \
${bits_srcdir}/charconv.h \
+ ${bits_srcdir}/chrono.h \
${bits_srcdir}/codecvt.h \
${bits_srcdir}/concept_check.h \
${bits_srcdir}/cow_string.h \
@@ -504,7 +505,9 @@ bits_headers = \
${bits_srcdir}/mask_array.h \
${bits_srcdir}/max_size_type.h \
${bits_srcdir}/memoryfwd.h \
+ ${bits_srcdir}/mofunc_impl.h \
${bits_srcdir}/move.h \
+ ${bits_srcdir}/move_only_function.h \
${bits_srcdir}/node_handle.h \
${bits_srcdir}/ostream.tcc \
${bits_srcdir}/ostream_insert.h \
@@ -1801,6 +1804,12 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
grep "^[ ]*#[ ]*define[ ][ ]*_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT[ ][ ]*1[ ]*$$" \
${CONFIG_HEADER} > /dev/null 2>&1 \
&& ldbl_alt128_compat='s,^#undef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT$$,#define _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT 1,' ;\
+ verbose_assert='s,g,g,' ; \
+ grep "^[ ]*#[ ]*define[ ][ ]*_GLIBCXX_HOSTED[ ][ ]*1[ ]*$$" \
+ ${CONFIG_HEADER} > /dev/null 2>&1 \
+ && grep "^[ ]*#[ ]*define[ ][ ]*_GLIBCXX_VERBOSE[ ][ ]*1[ ]*$$" \
+ ${CONFIG_HEADER} > /dev/null 2>&1 \
+ && verbose_assert='s,^#undef _GLIBCXX_VERBOSE_ASSERT$$,#define _GLIBCXX_VERBOSE_ASSERT 1,' ;\
sed -e "s,define __GLIBCXX__,define __GLIBCXX__ $$date," \
-e "s,define _GLIBCXX_RELEASE,define _GLIBCXX_RELEASE $$release," \
-e "s,define _GLIBCXX_INLINE_VERSION, define _GLIBCXX_INLINE_VERSION $$ns_version," \
@@ -1812,6 +1821,7 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
-e "s,define _GLIBCXX_USE_FLOAT128,$$float128," \
-e "$$ldbl_compat" \
-e "$$ldbl_alt128_compat" \
+ -e "$$verbose_assert" \
< ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
sed -e 's/HAVE_/_GLIBCXX_HAVE_/g' \
-e 's/PACKAGE/_GLIBCXX_PACKAGE/g' \
diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h
index 71e1de0..9e18aad 100644
--- a/libstdc++-v3/include/bits/atomic_base.h
+++ b/libstdc++-v3/include/bits/atomic_base.h
@@ -946,7 +946,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// As above, but for difference_type arguments.
template<typename _Tp>
- using _Diff = conditional_t<is_pointer_v<_Tp>, ptrdiff_t, _Val<_Tp>>;
+ using _Diff = __conditional_t<is_pointer_v<_Tp>, ptrdiff_t, _Val<_Tp>>;
template<size_t _Size, size_t _Align>
_GLIBCXX_ALWAYS_INLINE bool
diff --git a/libstdc++-v3/include/bits/atomic_futex.h b/libstdc++-v3/include/bits/atomic_futex.h
index d4bb32c..41c59c4 100644
--- a/libstdc++-v3/include/bits/atomic_futex.h
+++ b/libstdc++-v3/include/bits/atomic_futex.h
@@ -32,13 +32,12 @@
#pragma GCC system_header
-#include <bits/c++config.h>
#include <atomic>
-#include <chrono>
#if ! (defined(_GLIBCXX_HAVE_LINUX_FUTEX) && ATOMIC_INT_LOCK_FREE > 1)
#include <mutex>
#include <condition_variable>
#endif
+#include <bits/chrono.h>
#ifndef _GLIBCXX_ALWAYS_INLINE
#define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h b/libstdc++-v3/include/bits/atomic_timed_wait.h
index 3db08f8..64c1ba6 100644
--- a/libstdc++-v3/include/bits/atomic_timed_wait.h
+++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
@@ -37,8 +37,7 @@
#if __cpp_lib_atomic_wait
#include <bits/functional_hash.h>
#include <bits/this_thread_sleep.h>
-
-#include <chrono>
+#include <bits/chrono.h>
#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
#include <exception> // std::terminate
@@ -101,12 +100,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__e)
{
- if ((errno != ETIMEDOUT) && (errno != EINTR)
- && (errno != EAGAIN))
+ if (errno == ETIMEDOUT)
+ return false;
+ if (errno != EINTR && errno != EAGAIN)
__throw_system_error(errno);
- return true;
}
- return false;
+ return true;
}
// returns true if wait ended before timeout
diff --git a/libstdc++-v3/include/bits/atomic_wait.h b/libstdc++-v3/include/bits/atomic_wait.h
index 07bb744..2ac07cc 100644
--- a/libstdc++-v3/include/bits/atomic_wait.h
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -56,9 +56,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace __detail
{
#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
+#define _GLIBCXX_HAVE_PLATFORM_WAIT 1
using __platform_wait_t = int;
static constexpr size_t __platform_wait_alignment = 4;
#else
+// define _GLIBCX_HAVE_PLATFORM_WAIT and implement __platform_wait()
+// and __platform_notify() if there is a more efficient primitive supported
+// by the platform (e.g. __ulock_wait()/__ulock_wake()) which is better than
+// a mutex/condvar based wait.
using __platform_wait_t = uint64_t;
static constexpr size_t __platform_wait_alignment
= __alignof__(__platform_wait_t);
@@ -70,7 +75,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#ifdef _GLIBCXX_HAVE_PLATFORM_WAIT
= is_scalar_v<_Tp>
&& ((sizeof(_Tp) == sizeof(__detail::__platform_wait_t))
- && (alignof(_Tp*) >= __platform_wait_alignment));
+ && (alignof(_Tp*) >= __detail::__platform_wait_alignment));
#else
= false;
#endif
@@ -78,7 +83,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace __detail
{
#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
-#define _GLIBCXX_HAVE_PLATFORM_WAIT 1
enum class __futex_wait_flags : int
{
#ifdef _GLIBCXX_HAVE_LINUX_FUTEX_PRIVATE
@@ -118,11 +122,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_cast<int>(__futex_wait_flags::__wake_private),
__all ? INT_MAX : 1);
}
-#else
-// define _GLIBCX_HAVE_PLATFORM_WAIT and implement __platform_wait()
-// and __platform_notify() if there is a more efficient primitive supported
-// by the platform (e.g. __ulock_wait()/__ulock_wake()) which is better than
-// a mutex/condvar based wait
#endif
inline void
@@ -191,11 +190,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __waiter_pool_base
{
-#ifdef __cpp_lib_hardware_interference_size
- static constexpr auto _S_align = hardware_destructive_interference_size;
-#else
- static constexpr auto _S_align = 64;
-#endif
+ // Don't use std::hardware_destructive_interference_size here because we
+ // don't want the layout of library types to depend on compiler options.
+ static constexpr auto _S_align = 64;
alignas(_S_align) __platform_wait_t _M_wait = 0;
@@ -331,7 +328,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if constexpr (__platform_wait_uses_type<_Up>)
{
- __val == __old;
+ __builtin_memcpy(&__val, &__old, sizeof(__val));
}
else
{
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 24c454d..68c3884 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -623,6 +623,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_M_construct(__str.begin(), __str.end());
}
+ basic_string(nullptr_t) = delete;
+ basic_string& operator=(nullptr_t) = delete;
#endif // C++11
/**
diff --git a/libstdc++-v3/include/bits/boost_concept_check.h b/libstdc++-v3/include/bits/boost_concept_check.h
index 5c87e32..8135251 100644
--- a/libstdc++-v3/include/bits/boost_concept_check.h
+++ b/libstdc++-v3/include/bits/boost_concept_check.h
@@ -44,6 +44,22 @@
#include <bits/c++config.h>
#include <bits/stl_iterator_base_types.h> // for traits and tags
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
+ struct _Bit_iterator;
+ struct _Bit_const_iterator;
+_GLIBCXX_END_NAMESPACE_CONTAINER
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+
+namespace __gnu_debug
+{
+ template<typename _Iterator, typename _Sequence, typename _Category>
+ class _Safe_iterator;
+}
+
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -464,12 +480,76 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; };
__function_requires< _AssignableConcept<_Tp> >();
++__i; // require preincrement operator
__i++; // require postincrement operator
- *__i++ = __t; // require postincrement and assignment
+ *__i++ = __val(); // require postincrement and assignment
}
_Tp __i;
- _ValueT __t;
+ _ValueT __val() const;
+ };
+
+ template<typename _Tp>
+ struct _Is_vector_bool_iterator
+ { static const bool __value = false; };
+
+#ifdef _GLIBCXX_DEBUG
+ namespace __cont = ::std::_GLIBCXX_STD_C;
+#else
+ namespace __cont = ::std;
+#endif
+
+ // Trait to identify vector<bool>::iterator
+ template <>
+ struct _Is_vector_bool_iterator<__cont::_Bit_iterator>
+ { static const bool __value = true; };
+
+ // And for vector<bool>::const_iterator.
+ template <>
+ struct _Is_vector_bool_iterator<__cont::_Bit_const_iterator>
+ { static const bool __value = true; };
+
+ // And for __gnu_debug::vector<bool> iterators too.
+ template <typename _It, typename _Seq, typename _Tag>
+ struct _Is_vector_bool_iterator<__gnu_debug::_Safe_iterator<_It, _Seq, _Tag> >
+ : _Is_vector_bool_iterator<_It> { };
+
+ template <class _Tp, bool = _Is_vector_bool_iterator<_Tp>::__value>
+ struct _ForwardIteratorReferenceConcept
+ {
+ void __constraints() {
+#if __cplusplus >= 201103L
+ typedef typename std::iterator_traits<_Tp>::reference _Ref;
+ static_assert(std::is_reference<_Ref>::value,
+ "reference type of a forward iterator must be a real reference");
+#endif
+ }
};
+ template <class _Tp, bool = _Is_vector_bool_iterator<_Tp>::__value>
+ struct _Mutable_ForwardIteratorReferenceConcept
+ {
+ void __constraints() {
+ typedef typename std::iterator_traits<_Tp>::reference _Ref;
+ typedef typename std::iterator_traits<_Tp>::value_type _Val;
+ __function_requires< _SameTypeConcept<_Ref, _Val&> >();
+ }
+ };
+
+ // vector<bool> iterators are not real forward iterators, but we ignore that.
+ template <class _Tp>
+ struct _ForwardIteratorReferenceConcept<_Tp, true>
+ {
+ void __constraints() { }
+ };
+
+ // vector<bool> iterators are not real forward iterators, but we ignore that.
+ template <class _Tp>
+ struct _Mutable_ForwardIteratorReferenceConcept<_Tp, true>
+ {
+ void __constraints() { }
+ };
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-variable"
+
template <class _Tp>
struct _ForwardIteratorConcept
{
@@ -479,8 +559,12 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; };
__function_requires< _ConvertibleConcept<
typename std::iterator_traits<_Tp>::iterator_category,
std::forward_iterator_tag> >();
+ __function_requires< _ForwardIteratorReferenceConcept<_Tp> >();
+ _Tp& __j = ++__i;
+ const _Tp& __k = __i++;
typedef typename std::iterator_traits<_Tp>::reference _Ref;
- _Ref __r _IsUnused = *__i;
+ _Ref __r = *__k;
+ _Ref __r2 = *__i++;
}
_Tp __i;
};
@@ -490,7 +574,9 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; };
{
void __constraints() {
__function_requires< _ForwardIteratorConcept<_Tp> >();
- *__i++ = *__i; // require postincrement and assignment
+ typedef typename std::iterator_traits<_Tp>::reference _Ref;
+ typedef typename std::iterator_traits<_Tp>::value_type _Val;
+ __function_requires< _Mutable_ForwardIteratorReferenceConcept<_Tp> >();
}
_Tp __i;
};
@@ -503,8 +589,10 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; };
__function_requires< _ConvertibleConcept<
typename std::iterator_traits<_Tp>::iterator_category,
std::bidirectional_iterator_tag> >();
- --__i; // require predecrement operator
- __i--; // require postdecrement operator
+ _Tp& __j = --__i; // require predecrement operator
+ const _Tp& __k = __i--; // require postdecrement operator
+ typedef typename std::iterator_traits<_Tp>::reference _Ref;
+ _Ref __r = *__j--;
}
_Tp __i;
};
@@ -515,7 +603,6 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; };
void __constraints() {
__function_requires< _BidirectionalIteratorConcept<_Tp> >();
__function_requires< _Mutable_ForwardIteratorConcept<_Tp> >();
- *__i-- = *__i; // require postdecrement and assignment
}
_Tp __i;
};
@@ -530,16 +617,15 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; };
__function_requires< _ConvertibleConcept<
typename std::iterator_traits<_Tp>::iterator_category,
std::random_access_iterator_tag> >();
- // ??? We don't use _Ref, are we just checking for "referenceability"?
typedef typename std::iterator_traits<_Tp>::reference _Ref;
- __i += __n; // require assignment addition operator
+ _Tp& __j = __i += __n; // require assignment addition operator
__i = __i + __n; __i = __n + __i; // require addition with difference type
- __i -= __n; // require assignment subtraction op
+ _Tp& __k = __i -= __n; // require assignment subtraction op
__i = __i - __n; // require subtraction with
// difference type
__n = __i - __j; // require difference operator
- (void)__i[__n]; // require element access operator
+ _Ref __r = __i[__n]; // require element access operator
}
_Tp __a, __b;
_Tp __i, __j;
@@ -552,12 +638,13 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; };
void __constraints() {
__function_requires< _RandomAccessIteratorConcept<_Tp> >();
__function_requires< _Mutable_BidirectionalIteratorConcept<_Tp> >();
- __i[__n] = *__i; // require element access and assignment
}
_Tp __i;
typename std::iterator_traits<_Tp>::difference_type __n;
};
+#pragma GCC diagnostic pop
+
//===========================================================================
// Container Concepts
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index 32b8957..69343a2 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -506,11 +506,12 @@ namespace std
# define __glibcxx_constexpr_assert(unevaluated)
#endif
+#undef _GLIBCXX_VERBOSE_ASSERT
// Assert.
#if defined(_GLIBCXX_ASSERTIONS) \
|| defined(_GLIBCXX_PARALLEL) || defined(_GLIBCXX_PARALLEL_ASSERTIONS)
-# if _GLIBCXX_HOSTED && _GLIBCXX_VERBOSE
+# ifdef _GLIBCXX_VERBOSE_ASSERT
namespace std
{
// Avoid the use of assert, because we're trying to keep the <cassert>
@@ -533,7 +534,7 @@ namespace std
std::__replacement_assert(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
#_Condition); \
}
-# else // ! VERBOSE
+# else // ! VERBOSE_ASSERT
# define __glibcxx_assert_impl(_Condition) \
if (__builtin_expect(!bool(_Condition), false)) \
{ \
diff --git a/libstdc++-v3/include/bits/chrono.h b/libstdc++-v3/include/bits/chrono.h
new file mode 100644
index 0000000..956af05
--- /dev/null
+++ b/libstdc++-v3/include/bits/chrono.h
@@ -0,0 +1,1392 @@
+// chrono::duration and chrono::time_point -*- C++ -*-
+
+// Copyright (C) 2008-2021 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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/>.
+
+/** @file include/bits/chrono.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{chrono}
+ */
+
+#ifndef _GLIBCXX_CHRONO_H
+#define _GLIBCXX_CHRONO_H 1
+
+#pragma GCC system_header
+
+#if __cplusplus >= 201103L
+
+#include <ratio>
+#include <type_traits>
+#include <limits>
+#include <ctime>
+#include <bits/parse_numbers.h> // for literals support.
+#if __cplusplus >= 202002L
+# include <concepts>
+# include <compare>
+#endif
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+#if __cplusplus >= 201703L
+ namespace filesystem { struct __file_clock; };
+#endif
+
+ namespace chrono
+ {
+ /// @addtogroup chrono
+ /// @{
+
+ /// `chrono::duration` represents a distance between two points in time
+ template<typename _Rep, typename _Period = ratio<1>>
+ struct duration;
+
+ /// `chrono::time_point` represents a point in time as measured by a clock
+ template<typename _Clock, typename _Dur = typename _Clock::duration>
+ struct time_point;
+ /// @}
+ }
+
+ /// @addtogroup chrono
+ /// @{
+
+ // 20.11.4.3 specialization of common_type (for duration, sfinae-friendly)
+
+ /// @cond undocumented
+
+ template<typename _CT, typename _Period1, typename _Period2, typename = void>
+ struct __duration_common_type
+ { };
+
+ template<typename _CT, typename _Period1, typename _Period2>
+ struct __duration_common_type<_CT, _Period1, _Period2,
+ __void_t<typename _CT::type>>
+ {
+ private:
+ using __gcd_num = __static_gcd<_Period1::num, _Period2::num>;
+ using __gcd_den = __static_gcd<_Period1::den, _Period2::den>;
+ using __cr = typename _CT::type;
+ using __r = ratio<__gcd_num::value,
+ (_Period1::den / __gcd_den::value) * _Period2::den>;
+
+ public:
+ using type = chrono::duration<__cr, typename __r::type>;
+ };
+
+ /// @endcond
+
+ /// @{
+ /// @relates chrono::duration
+
+ /// Specialization of common_type for chrono::duration types.
+ template<typename _Rep1, typename _Period1, typename _Rep2, typename _Period2>
+ struct common_type<chrono::duration<_Rep1, _Period1>,
+ chrono::duration<_Rep2, _Period2>>
+ : __duration_common_type<common_type<_Rep1, _Rep2>,
+ typename _Period1::type,
+ typename _Period2::type>
+ { };
+
+ /// Specialization of common_type for two identical chrono::duration types.
+ template<typename _Rep, typename _Period>
+ struct common_type<chrono::duration<_Rep, _Period>,
+ chrono::duration<_Rep, _Period>>
+ {
+ using type = chrono::duration<typename common_type<_Rep>::type,
+ typename _Period::type>;
+ };
+
+ /// Specialization of common_type for one chrono::duration type.
+ template<typename _Rep, typename _Period>
+ struct common_type<chrono::duration<_Rep, _Period>>
+ {
+ using type = chrono::duration<typename common_type<_Rep>::type,
+ typename _Period::type>;
+ };
+ /// @}
+
+ // 20.11.4.3 specialization of common_type (for time_point, sfinae-friendly)
+
+ /// @cond undocumented
+
+ template<typename _CT, typename _Clock, typename = void>
+ struct __timepoint_common_type
+ { };
+
+ template<typename _CT, typename _Clock>
+ struct __timepoint_common_type<_CT, _Clock, __void_t<typename _CT::type>>
+ {
+ using type = chrono::time_point<_Clock, typename _CT::type>;
+ };
+
+ /// @endcond
+
+ /// @{
+ /// @relates chrono::time_point
+
+ /// Specialization of common_type for chrono::time_point types.
+ template<typename _Clock, typename _Duration1, typename _Duration2>
+ struct common_type<chrono::time_point<_Clock, _Duration1>,
+ chrono::time_point<_Clock, _Duration2>>
+ : __timepoint_common_type<common_type<_Duration1, _Duration2>, _Clock>
+ { };
+
+ /// Specialization of common_type for two identical chrono::time_point types.
+ template<typename _Clock, typename _Duration>
+ struct common_type<chrono::time_point<_Clock, _Duration>,
+ chrono::time_point<_Clock, _Duration>>
+ { using type = chrono::time_point<_Clock, _Duration>; };
+
+ /// Specialization of common_type for one chrono::time_point type.
+ template<typename _Clock, typename _Duration>
+ struct common_type<chrono::time_point<_Clock, _Duration>>
+ { using type = chrono::time_point<_Clock, _Duration>; };
+ /// @}
+
+ /// @} group chrono
+
+ namespace chrono
+ {
+ /// @addtogroup chrono
+ /// @{
+
+ /// @cond undocumented
+
+ // Primary template for duration_cast impl.
+ template<typename _ToDur, typename _CF, typename _CR,
+ bool _NumIsOne = false, bool _DenIsOne = false>
+ struct __duration_cast_impl
+ {
+ template<typename _Rep, typename _Period>
+ static constexpr _ToDur
+ __cast(const duration<_Rep, _Period>& __d)
+ {
+ typedef typename _ToDur::rep __to_rep;
+ return _ToDur(static_cast<__to_rep>(static_cast<_CR>(__d.count())
+ * static_cast<_CR>(_CF::num)
+ / static_cast<_CR>(_CF::den)));
+ }
+ };
+
+ template<typename _ToDur, typename _CF, typename _CR>
+ struct __duration_cast_impl<_ToDur, _CF, _CR, true, true>
+ {
+ template<typename _Rep, typename _Period>
+ static constexpr _ToDur
+ __cast(const duration<_Rep, _Period>& __d)
+ {
+ typedef typename _ToDur::rep __to_rep;
+ return _ToDur(static_cast<__to_rep>(__d.count()));
+ }
+ };
+
+ template<typename _ToDur, typename _CF, typename _CR>
+ struct __duration_cast_impl<_ToDur, _CF, _CR, true, false>
+ {
+ template<typename _Rep, typename _Period>
+ static constexpr _ToDur
+ __cast(const duration<_Rep, _Period>& __d)
+ {
+ typedef typename _ToDur::rep __to_rep;
+ return _ToDur(static_cast<__to_rep>(
+ static_cast<_CR>(__d.count()) / static_cast<_CR>(_CF::den)));
+ }
+ };
+
+ template<typename _ToDur, typename _CF, typename _CR>
+ struct __duration_cast_impl<_ToDur, _CF, _CR, false, true>
+ {
+ template<typename _Rep, typename _Period>
+ static constexpr _ToDur
+ __cast(const duration<_Rep, _Period>& __d)
+ {
+ typedef typename _ToDur::rep __to_rep;
+ return _ToDur(static_cast<__to_rep>(
+ static_cast<_CR>(__d.count()) * static_cast<_CR>(_CF::num)));
+ }
+ };
+
+ template<typename _Tp>
+ struct __is_duration
+ : std::false_type
+ { };
+
+ template<typename _Rep, typename _Period>
+ struct __is_duration<duration<_Rep, _Period>>
+ : std::true_type
+ { };
+
+ template<typename _Tp>
+ using __enable_if_is_duration
+ = typename enable_if<__is_duration<_Tp>::value, _Tp>::type;
+
+ template<typename _Tp>
+ using __disable_if_is_duration
+ = typename enable_if<!__is_duration<_Tp>::value, _Tp>::type;
+
+ /// @endcond
+
+ /// duration_cast
+ template<typename _ToDur, typename _Rep, typename _Period>
+ constexpr __enable_if_is_duration<_ToDur>
+ duration_cast(const duration<_Rep, _Period>& __d)
+ {
+ typedef typename _ToDur::period __to_period;
+ typedef typename _ToDur::rep __to_rep;
+ typedef ratio_divide<_Period, __to_period> __cf;
+ typedef typename common_type<__to_rep, _Rep, intmax_t>::type __cr;
+ typedef __duration_cast_impl<_ToDur, __cf, __cr,
+ __cf::num == 1, __cf::den == 1> __dc;
+ return __dc::__cast(__d);
+ }
+
+ /// treat_as_floating_point
+ template<typename _Rep>
+ struct treat_as_floating_point
+ : is_floating_point<_Rep>
+ { };
+
+#if __cplusplus > 201402L
+ template <typename _Rep>
+ inline constexpr bool treat_as_floating_point_v =
+ treat_as_floating_point<_Rep>::value;
+#endif // C++17
+
+#if __cplusplus > 201703L
+ template<typename _Tp>
+ struct is_clock;
+
+ template<typename _Tp>
+ inline constexpr bool is_clock_v = is_clock<_Tp>::value;
+
+#if __cpp_lib_concepts
+ template<typename _Tp>
+ struct is_clock : false_type
+ { };
+
+ template<typename _Tp>
+ requires requires {
+ typename _Tp::rep;
+ typename _Tp::period;
+ typename _Tp::duration;
+ typename _Tp::time_point::clock;
+ typename _Tp::time_point::duration;
+ { &_Tp::is_steady } -> same_as<const bool*>;
+ { _Tp::now() } -> same_as<typename _Tp::time_point>;
+ requires same_as<typename _Tp::duration,
+ duration<typename _Tp::rep, typename _Tp::period>>;
+ requires same_as<typename _Tp::time_point::duration,
+ typename _Tp::duration>;
+ }
+ struct is_clock<_Tp> : true_type
+ { };
+#else
+ template<typename _Tp, typename = void>
+ struct __is_clock_impl : false_type
+ { };
+
+ template<typename _Tp>
+ struct __is_clock_impl<_Tp,
+ void_t<typename _Tp::rep, typename _Tp::period,
+ typename _Tp::duration,
+ typename _Tp::time_point::duration,
+ decltype(_Tp::is_steady),
+ decltype(_Tp::now())>>
+ : __and_<is_same<typename _Tp::duration,
+ duration<typename _Tp::rep, typename _Tp::period>>,
+ is_same<typename _Tp::time_point::duration,
+ typename _Tp::duration>,
+ is_same<decltype(&_Tp::is_steady), const bool*>,
+ is_same<decltype(_Tp::now()), typename _Tp::time_point>>::type
+ { };
+
+ template<typename _Tp>
+ struct is_clock : __is_clock_impl<_Tp>::type
+ { };
+#endif
+#endif // C++20
+
+#if __cplusplus >= 201703L
+# define __cpp_lib_chrono 201611
+
+ template<typename _ToDur, typename _Rep, typename _Period>
+ constexpr __enable_if_is_duration<_ToDur>
+ floor(const duration<_Rep, _Period>& __d)
+ {
+ auto __to = chrono::duration_cast<_ToDur>(__d);
+ if (__to > __d)
+ return __to - _ToDur{1};
+ return __to;
+ }
+
+ template<typename _ToDur, typename _Rep, typename _Period>
+ constexpr __enable_if_is_duration<_ToDur>
+ ceil(const duration<_Rep, _Period>& __d)
+ {
+ auto __to = chrono::duration_cast<_ToDur>(__d);
+ if (__to < __d)
+ return __to + _ToDur{1};
+ return __to;
+ }
+
+ template <typename _ToDur, typename _Rep, typename _Period>
+ constexpr enable_if_t<
+ __and_<__is_duration<_ToDur>,
+ __not_<treat_as_floating_point<typename _ToDur::rep>>>::value,
+ _ToDur>
+ round(const duration<_Rep, _Period>& __d)
+ {
+ _ToDur __t0 = chrono::floor<_ToDur>(__d);
+ _ToDur __t1 = __t0 + _ToDur{1};
+ auto __diff0 = __d - __t0;
+ auto __diff1 = __t1 - __d;
+ if (__diff0 == __diff1)
+ {
+ if (__t0.count() & 1)
+ return __t1;
+ return __t0;
+ }
+ else if (__diff0 < __diff1)
+ return __t0;
+ return __t1;
+ }
+
+ template<typename _Rep, typename _Period>
+ constexpr
+ enable_if_t<numeric_limits<_Rep>::is_signed, duration<_Rep, _Period>>
+ abs(duration<_Rep, _Period> __d)
+ {
+ if (__d >= __d.zero())
+ return __d;
+ return -__d;
+ }
+
+ // Make chrono::ceil<D> also usable as chrono::__detail::ceil<D>.
+ namespace __detail { using chrono::ceil; }
+
+#else // ! C++17
+
+ // We want to use ceil even when compiling for earlier standards versions.
+ // C++11 only allows a single statement in a constexpr function, so we
+ // need to move the comparison into a separate function, __ceil_impl.
+ namespace __detail
+ {
+ template<typename _Tp, typename _Up>
+ constexpr _Tp
+ __ceil_impl(const _Tp& __t, const _Up& __u)
+ {
+ return (__t < __u) ? (__t + _Tp{1}) : __t;
+ }
+
+ // C++11-friendly version of std::chrono::ceil<D> for internal use.
+ template<typename _ToDur, typename _Rep, typename _Period>
+ constexpr _ToDur
+ ceil(const duration<_Rep, _Period>& __d)
+ {
+ return __detail::__ceil_impl(chrono::duration_cast<_ToDur>(__d), __d);
+ }
+ }
+#endif // C++17
+
+ /// duration_values
+ template<typename _Rep>
+ struct duration_values
+ {
+ static constexpr _Rep
+ zero() noexcept
+ { return _Rep(0); }
+
+ static constexpr _Rep
+ max() noexcept
+ { return numeric_limits<_Rep>::max(); }
+
+ static constexpr _Rep
+ min() noexcept
+ { return numeric_limits<_Rep>::lowest(); }
+ };
+
+ /// @cond undocumented
+
+ template<typename _Tp>
+ struct __is_ratio
+ : std::false_type
+ { };
+
+ template<intmax_t _Num, intmax_t _Den>
+ struct __is_ratio<ratio<_Num, _Den>>
+ : std::true_type
+ { };
+
+ /// @endcond
+
+ template<typename _Rep, typename _Period>
+ struct duration
+ {
+ private:
+ template<typename _Rep2>
+ using __is_float = treat_as_floating_point<_Rep2>;
+
+ static constexpr intmax_t
+ _S_gcd(intmax_t __m, intmax_t __n) noexcept
+ {
+ // Duration only allows positive periods so we don't need to
+ // handle negative values here (unlike __static_gcd and std::gcd).
+#if __cplusplus >= 201402L
+ do
+ {
+ intmax_t __rem = __m % __n;
+ __m = __n;
+ __n = __rem;
+ }
+ while (__n != 0);
+ return __m;
+#else
+ // C++11 doesn't allow loops in constexpr functions, but this
+ // recursive version can be more expensive to evaluate.
+ return (__n == 0) ? __m : _S_gcd(__n, __m % __n);
+#endif
+ }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2094. overflow shouldn't participate in overload resolution
+ // 3090. What is [2094] intended to mean?
+ // This only produces a valid type if no overflow occurs.
+ template<typename _R1, typename _R2,
+ intmax_t __gcd1 = _S_gcd(_R1::num, _R2::num),
+ intmax_t __gcd2 = _S_gcd(_R1::den, _R2::den)>
+ using __divide = ratio<(_R1::num / __gcd1) * (_R2::den / __gcd2),
+ (_R1::den / __gcd2) * (_R2::num / __gcd1)>;
+
+ // _Period2 is an exact multiple of _Period
+ template<typename _Period2>
+ using __is_harmonic
+ = __bool_constant<__divide<_Period2, _Period>::den == 1>;
+
+ public:
+
+ using rep = _Rep;
+ using period = typename _Period::type;
+
+ static_assert(!__is_duration<_Rep>::value, "rep cannot be a duration");
+ static_assert(__is_ratio<_Period>::value,
+ "period must be a specialization of ratio");
+ static_assert(_Period::num > 0, "period must be positive");
+
+ // 20.11.5.1 construction / copy / destroy
+ constexpr duration() = default;
+
+ duration(const duration&) = default;
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3050. Conversion specification problem in chrono::duration
+ template<typename _Rep2, typename = _Require<
+ is_convertible<const _Rep2&, rep>,
+ __or_<__is_float<rep>, __not_<__is_float<_Rep2>>>>>
+ constexpr explicit duration(const _Rep2& __rep)
+ : __r(static_cast<rep>(__rep)) { }
+
+ template<typename _Rep2, typename _Period2, typename = _Require<
+ is_convertible<const _Rep2&, rep>,
+ __or_<__is_float<rep>,
+ __and_<__is_harmonic<_Period2>,
+ __not_<__is_float<_Rep2>>>>>>
+ constexpr duration(const duration<_Rep2, _Period2>& __d)
+ : __r(duration_cast<duration>(__d).count()) { }
+
+ ~duration() = default;
+ duration& operator=(const duration&) = default;
+
+ // 20.11.5.2 observer
+ constexpr rep
+ count() const
+ { return __r; }
+
+ // 20.11.5.3 arithmetic
+
+ constexpr duration<typename common_type<rep>::type, period>
+ operator+() const
+ { return duration<typename common_type<rep>::type, period>(__r); }
+
+ constexpr duration<typename common_type<rep>::type, period>
+ operator-() const
+ { return duration<typename common_type<rep>::type, period>(-__r); }
+
+ _GLIBCXX17_CONSTEXPR duration&
+ operator++()
+ {
+ ++__r;
+ return *this;
+ }
+
+ _GLIBCXX17_CONSTEXPR duration
+ operator++(int)
+ { return duration(__r++); }
+
+ _GLIBCXX17_CONSTEXPR duration&
+ operator--()
+ {
+ --__r;
+ return *this;
+ }
+
+ _GLIBCXX17_CONSTEXPR duration
+ operator--(int)
+ { return duration(__r--); }
+
+ _GLIBCXX17_CONSTEXPR duration&
+ operator+=(const duration& __d)
+ {
+ __r += __d.count();
+ return *this;
+ }
+
+ _GLIBCXX17_CONSTEXPR duration&
+ operator-=(const duration& __d)
+ {
+ __r -= __d.count();
+ return *this;
+ }
+
+ _GLIBCXX17_CONSTEXPR duration&
+ operator*=(const rep& __rhs)
+ {
+ __r *= __rhs;
+ return *this;
+ }
+
+ _GLIBCXX17_CONSTEXPR duration&
+ operator/=(const rep& __rhs)
+ {
+ __r /= __rhs;
+ return *this;
+ }
+
+ // DR 934.
+ template<typename _Rep2 = rep>
+ _GLIBCXX17_CONSTEXPR
+ typename enable_if<!treat_as_floating_point<_Rep2>::value,
+ duration&>::type
+ operator%=(const rep& __rhs)
+ {
+ __r %= __rhs;
+ return *this;
+ }
+
+ template<typename _Rep2 = rep>
+ _GLIBCXX17_CONSTEXPR
+ typename enable_if<!treat_as_floating_point<_Rep2>::value,
+ duration&>::type
+ operator%=(const duration& __d)
+ {
+ __r %= __d.count();
+ return *this;
+ }
+
+ // 20.11.5.4 special values
+ static constexpr duration
+ zero() noexcept
+ { return duration(duration_values<rep>::zero()); }
+
+ static constexpr duration
+ min() noexcept
+ { return duration(duration_values<rep>::min()); }
+
+ static constexpr duration
+ max() noexcept
+ { return duration(duration_values<rep>::max()); }
+
+ private:
+ rep __r;
+ };
+
+ /// @{
+ /// @relates std::chrono::duration
+
+ /// The sum of two durations.
+ template<typename _Rep1, typename _Period1,
+ typename _Rep2, typename _Period2>
+ constexpr typename common_type<duration<_Rep1, _Period1>,
+ duration<_Rep2, _Period2>>::type
+ operator+(const duration<_Rep1, _Period1>& __lhs,
+ const duration<_Rep2, _Period2>& __rhs)
+ {
+ typedef duration<_Rep1, _Period1> __dur1;
+ typedef duration<_Rep2, _Period2> __dur2;
+ typedef typename common_type<__dur1,__dur2>::type __cd;
+ return __cd(__cd(__lhs).count() + __cd(__rhs).count());
+ }
+
+ /// The difference between two durations.
+ template<typename _Rep1, typename _Period1,
+ typename _Rep2, typename _Period2>
+ constexpr typename common_type<duration<_Rep1, _Period1>,
+ duration<_Rep2, _Period2>>::type
+ operator-(const duration<_Rep1, _Period1>& __lhs,
+ const duration<_Rep2, _Period2>& __rhs)
+ {
+ typedef duration<_Rep1, _Period1> __dur1;
+ typedef duration<_Rep2, _Period2> __dur2;
+ typedef typename common_type<__dur1,__dur2>::type __cd;
+ return __cd(__cd(__lhs).count() - __cd(__rhs).count());
+ }
+
+ /// @}
+
+ /// @cond undocumented
+
+ // SFINAE helper to obtain common_type<_Rep1, _Rep2> only if _Rep2
+ // is implicitly convertible to it.
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3050. Conversion specification problem in chrono::duration constructor
+ template<typename _Rep1, typename _Rep2,
+ typename _CRep = typename common_type<_Rep1, _Rep2>::type>
+ using __common_rep_t = typename
+ enable_if<is_convertible<const _Rep2&, _CRep>::value, _CRep>::type;
+
+ /// @endcond
+
+ /** @{
+ * Arithmetic operators for chrono::duration
+ * @relates std::chrono::duration
+ */
+
+ template<typename _Rep1, typename _Period, typename _Rep2>
+ constexpr duration<__common_rep_t<_Rep1, _Rep2>, _Period>
+ operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
+ {
+ typedef duration<typename common_type<_Rep1, _Rep2>::type, _Period>
+ __cd;
+ return __cd(__cd(__d).count() * __s);
+ }
+
+ template<typename _Rep1, typename _Rep2, typename _Period>
+ constexpr duration<__common_rep_t<_Rep2, _Rep1>, _Period>
+ operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d)
+ { return __d * __s; }
+
+ template<typename _Rep1, typename _Period, typename _Rep2>
+ constexpr
+ duration<__common_rep_t<_Rep1, __disable_if_is_duration<_Rep2>>, _Period>
+ operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
+ {
+ typedef duration<typename common_type<_Rep1, _Rep2>::type, _Period>
+ __cd;
+ return __cd(__cd(__d).count() / __s);
+ }
+
+ template<typename _Rep1, typename _Period1,
+ typename _Rep2, typename _Period2>
+ constexpr typename common_type<_Rep1, _Rep2>::type
+ operator/(const duration<_Rep1, _Period1>& __lhs,
+ const duration<_Rep2, _Period2>& __rhs)
+ {
+ typedef duration<_Rep1, _Period1> __dur1;
+ typedef duration<_Rep2, _Period2> __dur2;
+ typedef typename common_type<__dur1,__dur2>::type __cd;
+ return __cd(__lhs).count() / __cd(__rhs).count();
+ }
+
+ // DR 934.
+ template<typename _Rep1, typename _Period, typename _Rep2>
+ constexpr
+ duration<__common_rep_t<_Rep1, __disable_if_is_duration<_Rep2>>, _Period>
+ operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
+ {
+ typedef duration<typename common_type<_Rep1, _Rep2>::type, _Period>
+ __cd;
+ return __cd(__cd(__d).count() % __s);
+ }
+
+ template<typename _Rep1, typename _Period1,
+ typename _Rep2, typename _Period2>
+ constexpr typename common_type<duration<_Rep1, _Period1>,
+ duration<_Rep2, _Period2>>::type
+ operator%(const duration<_Rep1, _Period1>& __lhs,
+ const duration<_Rep2, _Period2>& __rhs)
+ {
+ typedef duration<_Rep1, _Period1> __dur1;
+ typedef duration<_Rep2, _Period2> __dur2;
+ typedef typename common_type<__dur1,__dur2>::type __cd;
+ return __cd(__cd(__lhs).count() % __cd(__rhs).count());
+ }
+ /// @}
+
+ // comparisons
+
+ /** @{
+ * Comparisons for chrono::duration
+ * @relates std::chrono::duration
+ */
+
+ template<typename _Rep1, typename _Period1,
+ typename _Rep2, typename _Period2>
+ constexpr bool
+ operator==(const duration<_Rep1, _Period1>& __lhs,
+ const duration<_Rep2, _Period2>& __rhs)
+ {
+ typedef duration<_Rep1, _Period1> __dur1;
+ typedef duration<_Rep2, _Period2> __dur2;
+ typedef typename common_type<__dur1,__dur2>::type __ct;
+ return __ct(__lhs).count() == __ct(__rhs).count();
+ }
+
+ template<typename _Rep1, typename _Period1,
+ typename _Rep2, typename _Period2>
+ constexpr bool
+ operator<(const duration<_Rep1, _Period1>& __lhs,
+ const duration<_Rep2, _Period2>& __rhs)
+ {
+ typedef duration<_Rep1, _Period1> __dur1;
+ typedef duration<_Rep2, _Period2> __dur2;
+ typedef typename common_type<__dur1,__dur2>::type __ct;
+ return __ct(__lhs).count() < __ct(__rhs).count();
+ }
+
+#if __cpp_lib_three_way_comparison
+ template<typename _Rep1, typename _Period1,
+ typename _Rep2, typename _Period2>
+ requires three_way_comparable<common_type_t<_Rep1, _Rep2>>
+ constexpr auto
+ operator<=>(const duration<_Rep1, _Period1>& __lhs,
+ const duration<_Rep2, _Period2>& __rhs)
+ {
+ using __ct = common_type_t<duration<_Rep1, _Period1>,
+ duration<_Rep2, _Period2>>;
+ return __ct(__lhs).count() <=> __ct(__rhs).count();
+ }
+#else
+ template<typename _Rep1, typename _Period1,
+ typename _Rep2, typename _Period2>
+ constexpr bool
+ operator!=(const duration<_Rep1, _Period1>& __lhs,
+ const duration<_Rep2, _Period2>& __rhs)
+ { return !(__lhs == __rhs); }
+#endif
+
+ template<typename _Rep1, typename _Period1,
+ typename _Rep2, typename _Period2>
+ constexpr bool
+ operator<=(const duration<_Rep1, _Period1>& __lhs,
+ const duration<_Rep2, _Period2>& __rhs)
+ { return !(__rhs < __lhs); }
+
+ template<typename _Rep1, typename _Period1,
+ typename _Rep2, typename _Period2>
+ constexpr bool
+ operator>(const duration<_Rep1, _Period1>& __lhs,
+ const duration<_Rep2, _Period2>& __rhs)
+ { return __rhs < __lhs; }
+
+ template<typename _Rep1, typename _Period1,
+ typename _Rep2, typename _Period2>
+ constexpr bool
+ operator>=(const duration<_Rep1, _Period1>& __lhs,
+ const duration<_Rep2, _Period2>& __rhs)
+ { return !(__lhs < __rhs); }
+
+ /// @}
+
+ /// @cond undocumented
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+# define _GLIBCXX_CHRONO_INT64_T int64_t
+#elif defined __INT64_TYPE__
+# define _GLIBCXX_CHRONO_INT64_T __INT64_TYPE__
+#else
+ static_assert(std::numeric_limits<unsigned long long>::digits >= 64,
+ "Representation type for nanoseconds must have at least 64 bits");
+# define _GLIBCXX_CHRONO_INT64_T long long
+#endif
+ /// @endcond
+
+ /// nanoseconds
+ using nanoseconds = duration<_GLIBCXX_CHRONO_INT64_T, nano>;
+
+ /// microseconds
+ using microseconds = duration<_GLIBCXX_CHRONO_INT64_T, micro>;
+
+ /// milliseconds
+ using milliseconds = duration<_GLIBCXX_CHRONO_INT64_T, milli>;
+
+ /// seconds
+ using seconds = duration<_GLIBCXX_CHRONO_INT64_T>;
+
+ /// minutes
+ using minutes = duration<_GLIBCXX_CHRONO_INT64_T, ratio< 60>>;
+
+ /// hours
+ using hours = duration<_GLIBCXX_CHRONO_INT64_T, ratio<3600>>;
+
+#if __cplusplus > 201703L
+ /// days
+ using days = duration<_GLIBCXX_CHRONO_INT64_T, ratio<86400>>;
+
+ /// weeks
+ using weeks = duration<_GLIBCXX_CHRONO_INT64_T, ratio<604800>>;
+
+ /// years
+ using years = duration<_GLIBCXX_CHRONO_INT64_T, ratio<31556952>>;
+
+ /// months
+ using months = duration<_GLIBCXX_CHRONO_INT64_T, ratio<2629746>>;
+#endif // C++20
+
+#undef _GLIBCXX_CHRONO_INT64_T
+
+ template<typename _Clock, typename _Dur>
+ struct time_point
+ {
+ static_assert(__is_duration<_Dur>::value,
+ "duration must be a specialization of std::chrono::duration");
+
+ typedef _Clock clock;
+ typedef _Dur duration;
+ typedef typename duration::rep rep;
+ typedef typename duration::period period;
+
+ constexpr time_point() : __d(duration::zero())
+ { }
+
+ constexpr explicit time_point(const duration& __dur)
+ : __d(__dur)
+ { }
+
+ // conversions
+ template<typename _Dur2,
+ typename = _Require<is_convertible<_Dur2, _Dur>>>
+ constexpr time_point(const time_point<clock, _Dur2>& __t)
+ : __d(__t.time_since_epoch())
+ { }
+
+ // observer
+ constexpr duration
+ time_since_epoch() const
+ { return __d; }
+
+#if __cplusplus > 201703L
+ constexpr time_point&
+ operator++()
+ {
+ ++__d;
+ return *this;
+ }
+
+ constexpr time_point
+ operator++(int)
+ { return time_point{__d++}; }
+
+ constexpr time_point&
+ operator--()
+ {
+ --__d;
+ return *this;
+ }
+
+ constexpr time_point
+ operator--(int)
+ { return time_point{__d--}; }
+#endif
+
+ // arithmetic
+ _GLIBCXX17_CONSTEXPR time_point&
+ operator+=(const duration& __dur)
+ {
+ __d += __dur;
+ return *this;
+ }
+
+ _GLIBCXX17_CONSTEXPR time_point&
+ operator-=(const duration& __dur)
+ {
+ __d -= __dur;
+ return *this;
+ }
+
+ // special values
+ static constexpr time_point
+ min() noexcept
+ { return time_point(duration::min()); }
+
+ static constexpr time_point
+ max() noexcept
+ { return time_point(duration::max()); }
+
+ private:
+ duration __d;
+ };
+
+ /// time_point_cast
+ template<typename _ToDur, typename _Clock, typename _Dur>
+ constexpr typename enable_if<__is_duration<_ToDur>::value,
+ time_point<_Clock, _ToDur>>::type
+ time_point_cast(const time_point<_Clock, _Dur>& __t)
+ {
+ typedef time_point<_Clock, _ToDur> __time_point;
+ return __time_point(duration_cast<_ToDur>(__t.time_since_epoch()));
+ }
+
+#if __cplusplus > 201402L
+ template<typename _ToDur, typename _Clock, typename _Dur>
+ constexpr
+ enable_if_t<__is_duration<_ToDur>::value, time_point<_Clock, _ToDur>>
+ floor(const time_point<_Clock, _Dur>& __tp)
+ {
+ return time_point<_Clock, _ToDur>{
+ chrono::floor<_ToDur>(__tp.time_since_epoch())};
+ }
+
+ template<typename _ToDur, typename _Clock, typename _Dur>
+ constexpr
+ enable_if_t<__is_duration<_ToDur>::value, time_point<_Clock, _ToDur>>
+ ceil(const time_point<_Clock, _Dur>& __tp)
+ {
+ return time_point<_Clock, _ToDur>{
+ chrono::ceil<_ToDur>(__tp.time_since_epoch())};
+ }
+
+ template<typename _ToDur, typename _Clock, typename _Dur>
+ constexpr enable_if_t<
+ __and_<__is_duration<_ToDur>,
+ __not_<treat_as_floating_point<typename _ToDur::rep>>>::value,
+ time_point<_Clock, _ToDur>>
+ round(const time_point<_Clock, _Dur>& __tp)
+ {
+ return time_point<_Clock, _ToDur>{
+ chrono::round<_ToDur>(__tp.time_since_epoch())};
+ }
+#endif // C++17
+
+ /// @{
+ /// @relates time_point
+
+ /// Adjust a time point forwards by the given duration.
+ template<typename _Clock, typename _Dur1,
+ typename _Rep2, typename _Period2>
+ constexpr time_point<_Clock,
+ typename common_type<_Dur1, duration<_Rep2, _Period2>>::type>
+ operator+(const time_point<_Clock, _Dur1>& __lhs,
+ const duration<_Rep2, _Period2>& __rhs)
+ {
+ typedef duration<_Rep2, _Period2> __dur2;
+ typedef typename common_type<_Dur1,__dur2>::type __ct;
+ typedef time_point<_Clock, __ct> __time_point;
+ return __time_point(__lhs.time_since_epoch() + __rhs);
+ }
+
+ /// Adjust a time point forwards by the given duration.
+ template<typename _Rep1, typename _Period1,
+ typename _Clock, typename _Dur2>
+ constexpr time_point<_Clock,
+ typename common_type<duration<_Rep1, _Period1>, _Dur2>::type>
+ operator+(const duration<_Rep1, _Period1>& __lhs,
+ const time_point<_Clock, _Dur2>& __rhs)
+ {
+ typedef duration<_Rep1, _Period1> __dur1;
+ typedef typename common_type<__dur1,_Dur2>::type __ct;
+ typedef time_point<_Clock, __ct> __time_point;
+ return __time_point(__rhs.time_since_epoch() + __lhs);
+ }
+
+ /// Adjust a time point backwards by the given duration.
+ template<typename _Clock, typename _Dur1,
+ typename _Rep2, typename _Period2>
+ constexpr time_point<_Clock,
+ typename common_type<_Dur1, duration<_Rep2, _Period2>>::type>
+ operator-(const time_point<_Clock, _Dur1>& __lhs,
+ const duration<_Rep2, _Period2>& __rhs)
+ {
+ typedef duration<_Rep2, _Period2> __dur2;
+ typedef typename common_type<_Dur1,__dur2>::type __ct;
+ typedef time_point<_Clock, __ct> __time_point;
+ return __time_point(__lhs.time_since_epoch() -__rhs);
+ }
+
+ /// The difference between two time points (as a duration)
+ template<typename _Clock, typename _Dur1, typename _Dur2>
+ constexpr typename common_type<_Dur1, _Dur2>::type
+ operator-(const time_point<_Clock, _Dur1>& __lhs,
+ const time_point<_Clock, _Dur2>& __rhs)
+ { return __lhs.time_since_epoch() - __rhs.time_since_epoch(); }
+ /// @}
+
+ /** @{
+ * Comparisons for time_point
+ * @relates chrono::time_point
+ */
+
+ template<typename _Clock, typename _Dur1, typename _Dur2>
+ constexpr bool
+ operator==(const time_point<_Clock, _Dur1>& __lhs,
+ const time_point<_Clock, _Dur2>& __rhs)
+ { return __lhs.time_since_epoch() == __rhs.time_since_epoch(); }
+
+#if __cpp_lib_three_way_comparison
+ template<typename _Clock, typename _Dur1,
+ three_way_comparable_with<_Dur1> _Dur2>
+ constexpr auto
+ operator<=>(const time_point<_Clock, _Dur1>& __lhs,
+ const time_point<_Clock, _Dur2>& __rhs)
+ { return __lhs.time_since_epoch() <=> __rhs.time_since_epoch(); }
+#else
+ template<typename _Clock, typename _Dur1, typename _Dur2>
+ constexpr bool
+ operator!=(const time_point<_Clock, _Dur1>& __lhs,
+ const time_point<_Clock, _Dur2>& __rhs)
+ { return !(__lhs == __rhs); }
+#endif
+
+ template<typename _Clock, typename _Dur1, typename _Dur2>
+ constexpr bool
+ operator<(const time_point<_Clock, _Dur1>& __lhs,
+ const time_point<_Clock, _Dur2>& __rhs)
+ { return __lhs.time_since_epoch() < __rhs.time_since_epoch(); }
+
+ template<typename _Clock, typename _Dur1, typename _Dur2>
+ constexpr bool
+ operator<=(const time_point<_Clock, _Dur1>& __lhs,
+ const time_point<_Clock, _Dur2>& __rhs)
+ { return !(__rhs < __lhs); }
+
+ template<typename _Clock, typename _Dur1, typename _Dur2>
+ constexpr bool
+ operator>(const time_point<_Clock, _Dur1>& __lhs,
+ const time_point<_Clock, _Dur2>& __rhs)
+ { return __rhs < __lhs; }
+
+ template<typename _Clock, typename _Dur1, typename _Dur2>
+ constexpr bool
+ operator>=(const time_point<_Clock, _Dur1>& __lhs,
+ const time_point<_Clock, _Dur2>& __rhs)
+ { return !(__lhs < __rhs); }
+
+ /// @}
+ /// @} group chrono
+
+ // Clocks.
+
+ // Why nanosecond resolution as the default?
+ // Why have std::system_clock always count in the highest
+ // resolution (ie nanoseconds), even if on some OSes the low 3
+ // or 9 decimal digits will be always zero? This allows later
+ // implementations to change the system_clock::now()
+ // implementation any time to provide better resolution without
+ // changing function signature or units.
+
+ // To support the (forward) evolution of the library's defined
+ // clocks, wrap inside inline namespace so that the current
+ // defintions of system_clock, steady_clock, and
+ // high_resolution_clock types are uniquely mangled. This way, new
+ // code can use the latests clocks, while the library can contain
+ // compatibility definitions for previous versions. At some
+ // point, when these clocks settle down, the inlined namespaces
+ // can be removed. XXX GLIBCXX_ABI Deprecated
+ inline namespace _V2 {
+
+ /**
+ * @brief System clock.
+ *
+ * Time returned represents wall time from the system-wide clock.
+ * @ingroup chrono
+ */
+ struct system_clock
+ {
+ typedef chrono::nanoseconds duration;
+ typedef duration::rep rep;
+ typedef duration::period period;
+ typedef chrono::time_point<system_clock, duration> time_point;
+
+ static_assert(system_clock::duration::min()
+ < system_clock::duration::zero(),
+ "a clock's minimum duration cannot be less than its epoch");
+
+ static constexpr bool is_steady = false;
+
+ static time_point
+ now() noexcept;
+
+ // Map to C API
+ static std::time_t
+ to_time_t(const time_point& __t) noexcept
+ {
+ return std::time_t(duration_cast<chrono::seconds>
+ (__t.time_since_epoch()).count());
+ }
+
+ static time_point
+ from_time_t(std::time_t __t) noexcept
+ {
+ typedef chrono::time_point<system_clock, seconds> __from;
+ return time_point_cast<system_clock::duration>
+ (__from(chrono::seconds(__t)));
+ }
+ };
+
+
+ /**
+ * @brief Monotonic clock
+ *
+ * Time returned has the property of only increasing at a uniform rate.
+ * @ingroup chrono
+ */
+ struct steady_clock
+ {
+ typedef chrono::nanoseconds duration;
+ typedef duration::rep rep;
+ typedef duration::period period;
+ typedef chrono::time_point<steady_clock, duration> time_point;
+
+ static constexpr bool is_steady = true;
+
+ static time_point
+ now() noexcept;
+ };
+
+
+ /**
+ * @brief Highest-resolution clock
+ *
+ * This is the clock "with the shortest tick period." Alias to
+ * std::system_clock until higher-than-nanosecond definitions
+ * become feasible.
+ * @ingroup chrono
+ */
+ using high_resolution_clock = system_clock;
+
+ } // end inline namespace _V2
+
+#if __cplusplus >= 202002L
+ /// @addtogroup chrono
+ /// @{
+ template<typename _Duration>
+ using sys_time = time_point<system_clock, _Duration>;
+ using sys_seconds = sys_time<seconds>;
+ using sys_days = sys_time<days>;
+
+ using file_clock = ::std::filesystem::__file_clock;
+
+ template<typename _Duration>
+ using file_time = time_point<file_clock, _Duration>;
+
+ template<> struct is_clock<system_clock> : true_type { };
+ template<> struct is_clock<steady_clock> : true_type { };
+ template<> struct is_clock<file_clock> : true_type { };
+
+ template<> inline constexpr bool is_clock_v<system_clock> = true;
+ template<> inline constexpr bool is_clock_v<steady_clock> = true;
+ template<> inline constexpr bool is_clock_v<file_clock> = true;
+ /// @}
+#endif // C++20
+ } // namespace chrono
+
+#if __cplusplus >= 201402L
+ #define __cpp_lib_chrono_udls 201304
+
+ inline namespace literals
+ {
+ /** ISO C++ 2014 namespace for suffixes for duration literals.
+ *
+ * These suffixes can be used to create `chrono::duration` values with
+ * tick periods of hours, minutes, seconds, milliseconds, microseconds
+ * or nanoseconds. For example, `std::chrono::seconds(5)` can be written
+ * as `5s` after making the suffix visible in the current scope.
+ * The suffixes can be made visible by a using-directive or
+ * using-declaration such as:
+ * - `using namespace std::chrono_literals;`
+ * - `using namespace std::literals;`
+ * - `using namespace std::chrono;`
+ * - `using namespace std;`
+ * - `using std::chrono_literals::operator""s;`
+ *
+ * The result of these suffixes on an integer literal is one of the
+ * standard typedefs such as `std::chrono::hours`.
+ * The result on a floating-point literal is a duration type with the
+ * specified tick period and an unspecified floating-point representation,
+ * for example `1.5e2ms` might be equivalent to
+ * `chrono::duration<long double, chrono::milli>(1.5e2)`.
+ *
+ * @since C+14
+ * @ingroup chrono
+ */
+ inline namespace chrono_literals
+ {
+ /// @addtogroup chrono
+ /// @{
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wliteral-suffix"
+ /// @cond undocumented
+ template<typename _Dur, char... _Digits>
+ constexpr _Dur __check_overflow()
+ {
+ using _Val = __parse_int::_Parse_int<_Digits...>;
+ constexpr typename _Dur::rep __repval = _Val::value;
+ static_assert(__repval >= 0 && __repval == _Val::value,
+ "literal value cannot be represented by duration type");
+ return _Dur(__repval);
+ }
+ /// @endcond
+
+ /// Literal suffix for durations representing non-integer hours
+ constexpr chrono::duration<long double, ratio<3600,1>>
+ operator""h(long double __hours)
+ { return chrono::duration<long double, ratio<3600,1>>{__hours}; }
+
+ /// Literal suffix for durations of type `std::chrono::hours`
+ template <char... _Digits>
+ constexpr chrono::hours
+ operator""h()
+ { return __check_overflow<chrono::hours, _Digits...>(); }
+
+ /// Literal suffix for durations representing non-integer minutes
+ constexpr chrono::duration<long double, ratio<60,1>>
+ operator""min(long double __mins)
+ { return chrono::duration<long double, ratio<60,1>>{__mins}; }
+
+ /// Literal suffix for durations of type `std::chrono::minutes`
+ template <char... _Digits>
+ constexpr chrono::minutes
+ operator""min()
+ { return __check_overflow<chrono::minutes, _Digits...>(); }
+
+ /// Literal suffix for durations representing non-integer seconds
+ constexpr chrono::duration<long double>
+ operator""s(long double __secs)
+ { return chrono::duration<long double>{__secs}; }
+
+ /// Literal suffix for durations of type `std::chrono::seconds`
+ template <char... _Digits>
+ constexpr chrono::seconds
+ operator""s()
+ { return __check_overflow<chrono::seconds, _Digits...>(); }
+
+ /// Literal suffix for durations representing non-integer milliseconds
+ constexpr chrono::duration<long double, milli>
+ operator""ms(long double __msecs)
+ { return chrono::duration<long double, milli>{__msecs}; }
+
+ /// Literal suffix for durations of type `std::chrono::milliseconds`
+ template <char... _Digits>
+ constexpr chrono::milliseconds
+ operator""ms()
+ { return __check_overflow<chrono::milliseconds, _Digits...>(); }
+
+ /// Literal suffix for durations representing non-integer microseconds
+ constexpr chrono::duration<long double, micro>
+ operator""us(long double __usecs)
+ { return chrono::duration<long double, micro>{__usecs}; }
+
+ /// Literal suffix for durations of type `std::chrono::microseconds`
+ template <char... _Digits>
+ constexpr chrono::microseconds
+ operator""us()
+ { return __check_overflow<chrono::microseconds, _Digits...>(); }
+
+ /// Literal suffix for durations representing non-integer nanoseconds
+ constexpr chrono::duration<long double, nano>
+ operator""ns(long double __nsecs)
+ { return chrono::duration<long double, nano>{__nsecs}; }
+
+ /// Literal suffix for durations of type `std::chrono::nanoseconds`
+ template <char... _Digits>
+ constexpr chrono::nanoseconds
+ operator""ns()
+ { return __check_overflow<chrono::nanoseconds, _Digits...>(); }
+
+#pragma GCC diagnostic pop
+ /// @}
+ } // inline namespace chrono_literals
+ } // inline namespace literals
+
+ namespace chrono
+ {
+ using namespace literals::chrono_literals;
+ } // namespace chrono
+#endif // C++14
+
+#if __cplusplus >= 201703L
+ namespace filesystem
+ {
+ struct __file_clock
+ {
+ using duration = chrono::nanoseconds;
+ using rep = duration::rep;
+ using period = duration::period;
+ using time_point = chrono::time_point<__file_clock>;
+ static constexpr bool is_steady = false;
+
+ static time_point
+ now() noexcept
+ { return _S_from_sys(chrono::system_clock::now()); }
+
+#if __cplusplus > 201703L
+ template<typename _Dur>
+ static
+ chrono::file_time<_Dur>
+ from_sys(const chrono::sys_time<_Dur>& __t) noexcept
+ { return _S_from_sys(__t); }
+
+ // For internal use only
+ template<typename _Dur>
+ static
+ chrono::sys_time<_Dur>
+ to_sys(const chrono::file_time<_Dur>& __t) noexcept
+ { return _S_to_sys(__t); }
+#endif // C++20
+
+ private:
+ using __sys_clock = chrono::system_clock;
+
+ // This clock's (unspecified) epoch is 2174-01-01 00:00:00 UTC.
+ // A signed 64-bit duration with nanosecond resolution gives roughly
+ // +/- 292 years, which covers the 1901-2446 date range for ext4.
+ static constexpr chrono::seconds _S_epoch_diff{6437664000};
+
+ protected:
+ // For internal use only
+ template<typename _Dur>
+ static
+ chrono::time_point<__file_clock, _Dur>
+ _S_from_sys(const chrono::time_point<__sys_clock, _Dur>& __t) noexcept
+ {
+ using __file_time = chrono::time_point<__file_clock, _Dur>;
+ return __file_time{__t.time_since_epoch()} - _S_epoch_diff;
+ }
+
+ // For internal use only
+ template<typename _Dur>
+ static
+ chrono::time_point<__sys_clock, _Dur>
+ _S_to_sys(const chrono::time_point<__file_clock, _Dur>& __t) noexcept
+ {
+ using __sys_time = chrono::time_point<__sys_clock, _Dur>;
+ return __sys_time{__t.time_since_epoch()} + _S_epoch_diff;
+ }
+ };
+ } // namespace filesystem
+#endif // C++17
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // C++11
+
+#endif //_GLIBCXX_CHRONO_H
diff --git a/libstdc++-v3/include/bits/cow_string.h b/libstdc++-v3/include/bits/cow_string.h
index 61edaa8..f054012 100644
--- a/libstdc++-v3/include/bits/cow_string.h
+++ b/libstdc++-v3/include/bits/cow_string.h
@@ -620,18 +620,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* The newly-created string contains the exact contents of @a __str.
* @a __str is a valid, but unspecified string.
*/
- basic_string(basic_string&& __str)
+ basic_string(basic_string&& __str) noexcept
#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
- noexcept // FIXME C++11: should always be noexcept.
-#endif
: _M_dataplus(std::move(__str._M_dataplus))
{
-#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
__str._M_data(_S_empty_rep()._M_refdata());
+ }
#else
- __str._M_data(_S_construct(size_type(), _CharT(), get_allocator()));
-#endif
+ : _M_dataplus(__str._M_rep())
+ {
+ // Rather than allocate an empty string for the rvalue string,
+ // just share ownership with it by incrementing the reference count.
+ // If the rvalue string was "leaked" then it was the unique owner,
+ // so need an extra increment to indicate shared ownership.
+ if (_M_rep()->_M_is_leaked())
+ __gnu_cxx::__atomic_add_dispatch(&_M_rep()->_M_refcount, 2);
+ else
+ __gnu_cxx::__atomic_add_dispatch(&_M_rep()->_M_refcount, 1);
}
+#endif
/**
* @brief Construct string from an initializer %list.
@@ -660,6 +667,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
else
_M_dataplus._M_p = _S_construct(__str.begin(), __str.end(), __a);
}
+
+ basic_string(nullptr_t) = delete;
+ basic_string& operator=(nullptr_t) = delete;
#endif // C++11
/**
diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h
index ab6d938..aa8623b 100644
--- a/libstdc++-v3/include/bits/forward_list.h
+++ b/libstdc++-v3/include/bits/forward_list.h
@@ -480,7 +480,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* @param __list Input list to copy.
* @param __al An allocator object.
*/
- forward_list(const forward_list& __list, const _Alloc& __al)
+ forward_list(const forward_list& __list,
+ const __type_identity_t<_Alloc>& __al)
: _Base(_Node_alloc_type(__al))
{ _M_range_initialize(__list.begin(), __list.end()); }
@@ -508,7 +509,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* @param __list Input list to move.
* @param __al An allocator object.
*/
- forward_list(forward_list&& __list, const _Alloc& __al)
+ forward_list(forward_list&& __list,
+ const __type_identity_t<_Alloc>& __al)
noexcept(_Node_alloc_traits::_S_always_equal())
: forward_list(std::move(__list), _Node_alloc_type(__al),
typename _Node_alloc_traits::is_always_equal{})
diff --git a/libstdc++-v3/include/bits/fs_fwd.h b/libstdc++-v3/include/bits/fs_fwd.h
index a7f5a377..51f351e 100644
--- a/libstdc++-v3/include/bits/fs_fwd.h
+++ b/libstdc++-v3/include/bits/fs_fwd.h
@@ -34,7 +34,7 @@
#include <system_error>
#include <cstdint>
-#include <chrono>
+#include <bits/chrono.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/bits/fs_path.h b/libstdc++-v3/include/bits/fs_path.h
index 92f7cbb..1918c24 100644
--- a/libstdc++-v3/include/bits/fs_path.h
+++ b/libstdc++-v3/include/bits/fs_path.h
@@ -489,8 +489,8 @@ namespace __detail
class iterator;
using const_iterator = iterator;
- iterator begin() const;
- iterator end() const;
+ iterator begin() const noexcept;
+ iterator end() const noexcept;
/// Write a path to a stream
template<typename _CharT, typename _Traits>
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index 92516b8..79a3096 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -317,8 +317,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Ht>
static constexpr
- typename conditional<std::is_lvalue_reference<_Ht>::value,
- const value_type&, value_type&&>::type
+ __conditional_t<std::is_lvalue_reference<_Ht>::value,
+ const value_type&, value_type&&>
__fwd_value_for(value_type& __val) noexcept
{ return std::move(__val); }
@@ -875,10 +875,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_insert_unique(_Kt&&, _Arg&&, const _NodeGenerator&);
template<typename _Kt>
- static typename conditional<
+ static __conditional_t<
__and_<__is_nothrow_invocable<_Hash&, const key_type&>,
__not_<__is_nothrow_invocable<_Hash&, _Kt>>>::value,
- key_type, _Kt&&>::type
+ key_type, _Kt&&>
_S_forward_key(_Kt&& __k)
{ return std::forward<_Kt>(__k); }
@@ -1540,9 +1540,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
__alloc_node_gen_t __alloc_gen(*this);
- using _Fwd_Ht = typename
- conditional<__move_if_noexcept_cond<value_type>::value,
- const _Hashtable&, _Hashtable&&>::type;
+ using _Fwd_Ht = __conditional_t<
+ __move_if_noexcept_cond<value_type>::value,
+ const _Hashtable&, _Hashtable&&>;
_M_assign(std::forward<_Fwd_Ht>(__ht), __alloc_gen);
__ht.clear();
}
diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h
index 2130c95..2f85025 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -360,15 +360,15 @@ namespace __detail
using __node_type = typename __base_type::__node_type;
public:
- typedef _Value value_type;
- typedef std::ptrdiff_t difference_type;
- typedef std::forward_iterator_tag iterator_category;
+ using value_type = _Value;
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::forward_iterator_tag;
- using pointer = typename std::conditional<__constant_iterators,
- const value_type*, value_type*>::type;
+ using pointer = __conditional_t<__constant_iterators,
+ const value_type*, value_type*>;
- using reference = typename std::conditional<__constant_iterators,
- const value_type&, value_type&>::type;
+ using reference = __conditional_t<__constant_iterators,
+ const value_type&, value_type&>;
_Node_iterator() = default;
@@ -867,12 +867,13 @@ namespace __detail
using iterator = _Node_iterator<_Value, __constant_iterators::value,
__hash_cached::value>;
- using const_iterator = _Node_const_iterator<_Value, __constant_iterators::value,
+ using const_iterator = _Node_const_iterator<_Value,
+ __constant_iterators::value,
__hash_cached::value>;
- using __ireturn_type = typename std::conditional<__unique_keys::value,
- std::pair<iterator, bool>,
- iterator>::type;
+ using __ireturn_type = __conditional_t<__unique_keys::value,
+ std::pair<iterator, bool>,
+ iterator>;
__ireturn_type
insert(const value_type& __v)
@@ -1482,15 +1483,13 @@ namespace __detail
using __hash_code_base = typename __base_type::__hash_code_base;
public:
- typedef _Value value_type;
- typedef typename std::conditional<__constant_iterators,
- const value_type*, value_type*>::type
- pointer;
- typedef typename std::conditional<__constant_iterators,
- const value_type&, value_type&>::type
- reference;
- typedef std::ptrdiff_t difference_type;
- typedef std::forward_iterator_tag iterator_category;
+ using value_type = _Value;
+ using pointer = __conditional_t<__constant_iterators,
+ const value_type*, value_type*>;
+ using reference = __conditional_t<__constant_iterators,
+ const value_type&, value_type&>;
+ using difference_type = ptrdiff_t;
+ using iterator_category = forward_iterator_tag;
_Local_iterator() = default;
diff --git a/libstdc++-v3/include/bits/list.tcc b/libstdc++-v3/include/bits/list.tcc
index 0ce4c47..7f4e156 100644
--- a/libstdc++-v3/include/bits/list.tcc
+++ b/libstdc++-v3/include/bits/list.tcc
@@ -416,29 +416,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
iterator __last1 = end();
iterator __first2 = __x.begin();
iterator __last2 = __x.end();
- const size_t __orig_size = __x.size();
- __try {
- while (__first1 != __last1 && __first2 != __last2)
- if (*__first2 < *__first1)
- {
- iterator __next = __first2;
- _M_transfer(__first1, __first2, ++__next);
- __first2 = __next;
- }
- else
- ++__first1;
- if (__first2 != __last2)
- _M_transfer(__last1, __first2, __last2);
- this->_M_inc_size(__x._M_get_size());
- __x._M_set_size(0);
- }
- __catch(...)
+ const _Finalize_merge __fin(*this, __x, __first2);
+
+ while (__first1 != __last1 && __first2 != __last2)
+ if (*__first2 < *__first1)
+ {
+ iterator __next = __first2;
+ _M_transfer(__first1, __first2, ++__next);
+ __first2 = __next;
+ }
+ else
+ ++__first1;
+ if (__first2 != __last2)
{
- const size_t __dist = std::distance(__first2, __last2);
- this->_M_inc_size(__orig_size - __dist);
- __x._M_set_size(__dist);
- __throw_exception_again;
+ _M_transfer(__last1, __first2, __last2);
+ __first2 = __last2;
}
}
}
@@ -463,30 +456,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
iterator __last1 = end();
iterator __first2 = __x.begin();
iterator __last2 = __x.end();
- const size_t __orig_size = __x.size();
- __try
- {
- while (__first1 != __last1 && __first2 != __last2)
- if (__comp(*__first2, *__first1))
- {
- iterator __next = __first2;
- _M_transfer(__first1, __first2, ++__next);
- __first2 = __next;
- }
- else
- ++__first1;
- if (__first2 != __last2)
- _M_transfer(__last1, __first2, __last2);
- this->_M_inc_size(__x._M_get_size());
- __x._M_set_size(0);
- }
- __catch(...)
+ const _Finalize_merge __fin(*this, __x, __first2);
+
+ while (__first1 != __last1 && __first2 != __last2)
+ if (__comp(*__first2, *__first1))
+ {
+ iterator __next = __first2;
+ _M_transfer(__first1, __first2, ++__next);
+ __first2 = __next;
+ }
+ else
+ ++__first1;
+ if (__first2 != __last2)
{
- const size_t __dist = std::distance(__first2, __last2);
- this->_M_inc_size(__orig_size - __dist);
- __x._M_set_size(__dist);
- __throw_exception_again;
+ _M_transfer(__last1, __first2, __last2);
+ __first2 = __last2;
}
}
}
@@ -500,21 +485,34 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (this->_M_impl._M_node._M_next != &this->_M_impl._M_node
&& this->_M_impl._M_node._M_next->_M_next != &this->_M_impl._M_node)
{
- list __carry;
- list __tmp[64];
- list * __fill = __tmp;
- list * __counter;
+ using __detail::_Scratch_list;
+ // The algorithm used here is largely unchanged from the SGI STL
+ // and is described in The C++ Standard Template Library by Plauger,
+ // Stepanov, Lee, Musser.
+ // Each element of *this is spliced out and merged into one of the
+ // sorted lists in __tmp, then all the lists in __tmp are merged
+ // together and then swapped back into *this.
+ // Because all nodes end up back in *this we do not need to update
+ // this->size() while nodes are temporarily moved out.
+ _Scratch_list __carry;
+ _Scratch_list __tmp[64];
+ _Scratch_list* __fill = __tmp;
+ _Scratch_list* __counter;
+
+ _Scratch_list::_Ptr_cmp<const_iterator, void> __ptr_comp;
+
__try
{
do
{
- __carry.splice(__carry.begin(), *this, begin());
+ __carry._M_take_one(begin()._M_node);
for(__counter = __tmp;
__counter != __fill && !__counter->empty();
++__counter)
{
- __counter->merge(__carry);
+
+ __counter->merge(__carry, __ptr_comp);
__carry.swap(*__counter);
}
__carry.swap(*__counter);
@@ -524,14 +522,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
while ( !empty() );
for (__counter = __tmp + 1; __counter != __fill; ++__counter)
- __counter->merge(*(__counter - 1));
- swap( *(__fill - 1) );
+ __counter->merge(__counter[-1], __ptr_comp);
+ __fill[-1].swap(this->_M_impl._M_node);
}
__catch(...)
{
- this->splice(this->end(), __carry);
+ // Move all nodes back into *this.
+ __carry._M_put_all(end()._M_node);
for (int __i = 0; __i < sizeof(__tmp)/sizeof(__tmp[0]); ++__i)
- this->splice(this->end(), __tmp[__i]);
+ __tmp[__i]._M_put_all(end()._M_node);
__throw_exception_again;
}
}
@@ -617,42 +616,49 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Do nothing if the list has length 0 or 1.
if (this->_M_impl._M_node._M_next != &this->_M_impl._M_node
&& this->_M_impl._M_node._M_next->_M_next != &this->_M_impl._M_node)
- {
- list __carry;
- list __tmp[64];
- list * __fill = __tmp;
- list * __counter;
- __try
- {
- do
- {
- __carry.splice(__carry.begin(), *this, begin());
-
- for(__counter = __tmp;
- __counter != __fill && !__counter->empty();
- ++__counter)
- {
- __counter->merge(__carry, __comp);
- __carry.swap(*__counter);
- }
- __carry.swap(*__counter);
- if (__counter == __fill)
- ++__fill;
- }
- while ( !empty() );
+ {
+ using __detail::_Scratch_list;
+ _Scratch_list __carry;
+ _Scratch_list __tmp[64];
+ _Scratch_list* __fill = __tmp;
+ _Scratch_list* __counter;
- for (__counter = __tmp + 1; __counter != __fill; ++__counter)
- __counter->merge(*(__counter - 1), __comp);
- swap(*(__fill - 1));
- }
- __catch(...)
- {
- this->splice(this->end(), __carry);
- for (int __i = 0; __i < sizeof(__tmp)/sizeof(__tmp[0]); ++__i)
- this->splice(this->end(), __tmp[__i]);
- __throw_exception_again;
- }
- }
+ _Scratch_list::_Ptr_cmp<const_iterator, _StrictWeakOrdering> __ptr_comp
+ = { __comp };
+
+ __try
+ {
+ do
+ {
+ __carry._M_take_one(begin()._M_node);
+
+ for(__counter = __tmp;
+ __counter != __fill && !__counter->empty();
+ ++__counter)
+ {
+
+ __counter->merge(__carry, __ptr_comp);
+ __carry.swap(*__counter);
+ }
+ __carry.swap(*__counter);
+ if (__counter == __fill)
+ ++__fill;
+ }
+ while ( !empty() );
+
+ for (__counter = __tmp + 1; __counter != __fill; ++__counter)
+ __counter->merge(__counter[-1], __ptr_comp);
+ __fill[-1].swap(this->_M_impl._M_node);
+ }
+ __catch(...)
+ {
+ // Move all nodes back into *this.
+ __carry._M_put_all(end()._M_node);
+ for (int __i = 0; __i < sizeof(__tmp)/sizeof(__tmp[0]); ++__i)
+ __tmp[__i]._M_put_all(end()._M_node);
+ __throw_exception_again;
+ }
+ }
}
_GLIBCXX_END_NAMESPACE_CONTAINER
diff --git a/libstdc++-v3/include/bits/mofunc_impl.h b/libstdc++-v3/include/bits/mofunc_impl.h
new file mode 100644
index 0000000..543c6f5
--- /dev/null
+++ b/libstdc++-v3/include/bits/mofunc_impl.h
@@ -0,0 +1,200 @@
+// Implementation of std::move_only_function -*- C++ -*-
+
+// Copyright The GNU Toolchain Authors.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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/>.
+
+/** @file include/bits/mofunc_impl.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{functional}
+ */
+
+#ifndef _GLIBCXX_MOF_CV
+# define _GLIBCXX_MOF_CV
+#endif
+
+#ifdef _GLIBCXX_MOF_REF
+# define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF
+#else
+# define _GLIBCXX_MOF_REF
+# define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV &
+#endif
+
+#define _GLIBCXX_MOF_CV_REF _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ template<typename _Res, typename... _ArgTypes, bool _Noex>
+ class move_only_function<_Res(_ArgTypes...) _GLIBCXX_MOF_CV
+ _GLIBCXX_MOF_REF noexcept(_Noex)>
+ : _Mofunc_base
+ {
+ template<typename _Tp>
+ using __callable
+ = __conditional_t<_Noex,
+ is_nothrow_invocable_r<_Res, _Tp, _ArgTypes...>,
+ is_invocable_r<_Res, _Tp, _ArgTypes...>>;
+
+ // [func.wrap.mov.con]/1 is-callable-from<VT>
+ template<typename _Vt>
+ static constexpr bool __is_callable_from
+ = __and_v<__callable<_Vt _GLIBCXX_MOF_CV_REF>,
+ __callable<_Vt _GLIBCXX_MOF_INV_QUALS>>;
+
+ public:
+ using result_type = _Res;
+
+ move_only_function() noexcept { }
+
+ move_only_function(nullptr_t) noexcept { }
+
+ move_only_function(move_only_function&& __x) noexcept
+ : _Mofunc_base(static_cast<_Mofunc_base&&>(__x)),
+ _M_invoke(std::__exchange(__x._M_invoke, nullptr))
+ { }
+
+ template<typename _Fn, typename _Vt = decay_t<_Fn>>
+ requires (!is_same_v<_Vt, move_only_function>)
+ && (!__is_in_place_type_v<_Vt>) && __is_callable_from<_Vt>
+ move_only_function(_Fn&& __f) noexcept(_S_nothrow_init<_Vt, _Fn>())
+ {
+ if constexpr (is_function_v<remove_pointer_t<_Vt>>
+ || is_member_pointer_v<_Vt>
+ || __is_move_only_function_v<_Vt>)
+ {
+ if (__f == nullptr)
+ return;
+ }
+ _M_init<_Vt>(std::forward<_Fn>(__f));
+ _M_invoke = &_S_invoke<_Vt>;
+ }
+
+ template<typename _Tp, typename... _Args>
+ requires is_constructible_v<_Tp, _Args...>
+ && __is_callable_from<_Tp>
+ explicit
+ move_only_function(in_place_type_t<_Tp>, _Args&&... __args)
+ noexcept(_S_nothrow_init<_Tp, _Args...>())
+ : _M_invoke(&_S_invoke<_Tp>)
+ {
+ static_assert(is_same_v<decay_t<_Tp>, _Tp>);
+ _M_init<_Tp>(std::forward<_Args>(__args)...);
+ }
+
+ template<typename _Tp, typename _Up, typename... _Args>
+ requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
+ && __is_callable_from<_Tp>
+ explicit
+ move_only_function(in_place_type_t<_Tp>, initializer_list<_Up> __il,
+ _Args&&... __args)
+ noexcept(_S_nothrow_init<_Tp, initializer_list<_Up>&, _Args...>())
+ : _Mofunc_base(nullptr), _M_invoke(&_S_invoke<_Tp>)
+ {
+ static_assert(is_same_v<decay_t<_Tp>, _Tp>);
+ _M_init<_Tp>(__il, std::forward<_Args>(__args)...);
+ }
+
+ move_only_function&
+ operator=(move_only_function&& __x) noexcept
+ {
+ _Mofunc_base::operator=(static_cast<_Mofunc_base&&>(__x));
+ _M_invoke = std::__exchange(__x._M_invoke, nullptr);
+ return *this;
+ }
+
+ move_only_function&
+ operator=(nullptr_t) noexcept
+ {
+ _Mofunc_base::operator=(nullptr);
+ _M_invoke = nullptr;
+ return *this;
+ }
+
+ template<typename _Fn>
+ requires is_constructible_v<move_only_function, _Fn>
+ move_only_function&
+ operator=(_Fn&& __f)
+ noexcept(is_nothrow_constructible_v<move_only_function, _Fn>)
+ {
+ move_only_function(std::forward<_Fn>(__f)).swap(*this);
+ return *this;
+ }
+
+ ~move_only_function() = default;
+
+ explicit operator bool() const noexcept { return _M_invoke != nullptr; }
+
+ _Res
+ operator()(_ArgTypes... __args) _GLIBCXX_MOF_CV_REF noexcept(_Noex)
+ {
+ __glibcxx_assert(*this != nullptr);
+ return _M_invoke(this, std::forward<_ArgTypes>(__args)...);
+ }
+
+ void
+ swap(move_only_function& __x) noexcept
+ {
+ _Mofunc_base::swap(__x);
+ std::swap(_M_invoke, __x._M_invoke);
+ }
+
+ friend void
+ swap(move_only_function& __x, move_only_function& __y) noexcept
+ { __x.swap(__y); }
+
+ friend bool
+ operator==(const move_only_function& __x, nullptr_t) noexcept
+ { return __x._M_invoke == nullptr; }
+
+ private:
+ template<typename _Tp>
+ using __param_t
+ = __conditional_t<is_trivially_copyable_v<_Tp>
+ && sizeof(_Tp) <= sizeof(long),
+ _Tp, _Tp&&>;
+
+ using _Invoker = _Res (*)(_Mofunc_base _GLIBCXX_MOF_CV*,
+ __param_t<_ArgTypes>...) noexcept(_Noex);
+
+ template<typename _Tp>
+ static _Res
+ _S_invoke(_Mofunc_base _GLIBCXX_MOF_CV* __self,
+ __param_t<_ArgTypes>... __args) noexcept(_Noex)
+ {
+ using _TpCv = _Tp _GLIBCXX_MOF_CV;
+ using _TpInv = _Tp _GLIBCXX_MOF_INV_QUALS;
+ return std::__invoke_r<_Res>(
+ std::forward<_TpInv>(*_S_access<_TpCv>(__self)),
+ std::forward<__param_t<_ArgTypes>>(__args)...);
+ }
+
+ _Invoker _M_invoke = nullptr;
+ };
+
+#undef _GLIBCXX_MOF_CV_REF
+#undef _GLIBCXX_MOF_CV
+#undef _GLIBCXX_MOF_REF
+#undef _GLIBCXX_MOF_INV_QUALS
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h
index 3abbb37..1c13abc 100644
--- a/libstdc++-v3/include/bits/move.h
+++ b/libstdc++-v3/include/bits/move.h
@@ -88,8 +88,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
{
- static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
- " substituting _Tp must not be an lvalue reference type");
+ static_assert(!std::is_lvalue_reference<_Tp>::value,
+ "std::forward must not be used to convert an rvalue to an lvalue");
return static_cast<_Tp&&>(__t);
}
@@ -120,8 +120,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
template<typename _Tp>
_GLIBCXX_NODISCARD
- constexpr typename
- conditional<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>::type
+ constexpr
+ __conditional_t<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>
move_if_noexcept(_Tp& __x) noexcept
{ return std::move(__x); }
diff --git a/libstdc++-v3/include/bits/move_only_function.h b/libstdc++-v3/include/bits/move_only_function.h
new file mode 100644
index 0000000..f96552a
--- /dev/null
+++ b/libstdc++-v3/include/bits/move_only_function.h
@@ -0,0 +1,204 @@
+// Implementation of std::move_only_function -*- C++ -*-
+
+// Copyright The GNU Toolchain Authors.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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/>.
+
+/** @file include/bits/move_only_function.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{functional}
+ */
+
+#ifndef _GLIBCXX_MOVE_ONLY_FUNCTION_H
+#define _GLIBCXX_MOVE_ONLY_FUNCTION_H 1
+
+#pragma GCC system_header
+
+#if __cplusplus > 202002L
+
+#include <bits/invoke.h>
+#include <bits/utility.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+#define __cpp_lib_move_only_function 202110L
+
+ template<typename... _Signature>
+ class move_only_function; // not defined
+
+ /// @cond undocumented
+ class _Mofunc_base
+ {
+ protected:
+ _Mofunc_base() noexcept
+ : _M_manage(_S_empty)
+ { }
+
+ _Mofunc_base(_Mofunc_base&& __x) noexcept
+ {
+ _M_manage = std::__exchange(__x._M_manage, _S_empty);
+ _M_manage(_M_storage, &__x._M_storage);
+ }
+
+ template<typename _Tp, typename... _Args>
+ static constexpr bool
+ _S_nothrow_init() noexcept
+ {
+ if constexpr (__stored_locally<_Tp>)
+ return is_nothrow_constructible_v<_Tp, _Args...>;
+ return false;
+ }
+
+ template<typename _Tp, typename... _Args>
+ void
+ _M_init(_Args&&... __args) noexcept(_S_nothrow_init<_Tp, _Args...>())
+ {
+ if constexpr (__stored_locally<_Tp>)
+ ::new (_M_storage._M_addr()) _Tp(std::forward<_Args>(__args)...);
+ else
+ _M_storage._M_p = new _Tp(std::forward<_Args>(__args)...);
+
+ _M_manage = &_S_manage<_Tp>;
+ }
+
+ _Mofunc_base&
+ operator=(_Mofunc_base&& __x) noexcept
+ {
+ _M_manage(_M_storage, nullptr);
+ _M_manage = std::__exchange(__x._M_manage, _S_empty);
+ _M_manage(_M_storage, &__x._M_storage);
+ return *this;
+ }
+
+ _Mofunc_base&
+ operator=(nullptr_t) noexcept
+ {
+ _M_manage(_M_storage, nullptr);
+ _M_manage = _S_empty;
+ return *this;
+ }
+
+ ~_Mofunc_base() { _M_manage(_M_storage, nullptr); }
+
+ void
+ swap(_Mofunc_base& __x) noexcept
+ {
+ // Order of operations here is more efficient if __x is empty.
+ _Storage __s;
+ __x._M_manage(__s, &__x._M_storage);
+ _M_manage(__x._M_storage, &_M_storage);
+ __x._M_manage(_M_storage, &__s);
+ std::swap(_M_manage, __x._M_manage);
+ }
+
+ template<typename _Tp, typename _Self>
+ static _Tp*
+ _S_access(_Self* __self) noexcept
+ {
+ if constexpr (__stored_locally<remove_const_t<_Tp>>)
+ return static_cast<_Tp*>(__self->_M_storage._M_addr());
+ else
+ return static_cast<_Tp*>(__self->_M_storage._M_p);
+ }
+
+ private:
+ struct _Storage
+ {
+ void* _M_addr() noexcept { return &_M_bytes[0]; }
+ const void* _M_addr() const noexcept { return &_M_bytes[0]; }
+
+ // We want to have enough space to store a simple delegate type.
+ struct _Delegate { void (_Storage::*__pfm)(); _Storage* __obj; };
+ union {
+ void* _M_p;
+ alignas(_Delegate) alignas(void(*)())
+ unsigned char _M_bytes[sizeof(_Delegate)];
+ };
+ };
+
+ template<typename _Tp>
+ static constexpr bool __stored_locally
+ = sizeof(_Tp) <= sizeof(_Storage) && alignof(_Tp) <= alignof(_Storage)
+ && is_nothrow_move_constructible_v<_Tp>;
+
+ // A function that either destroys the target object stored in __target,
+ // or moves the target object from *__src to __target.
+ using _Manager = void (*)(_Storage& __target, _Storage* __src) noexcept;
+
+ // The no-op manager function for objects with no target.
+ static void _S_empty(_Storage&, _Storage*) noexcept { }
+
+ // The real manager function for a target object of type _Tp.
+ template<typename _Tp>
+ static void
+ _S_manage(_Storage& __target, _Storage* __src) noexcept
+ {
+ if constexpr (__stored_locally<_Tp>)
+ {
+ if (__src)
+ {
+ _Tp* __rval = static_cast<_Tp*>(__src->_M_addr());
+ ::new (__target._M_addr()) _Tp(std::move(*__rval));
+ __rval->~_Tp();
+ }
+ else
+ static_cast<_Tp*>(__target._M_addr())->~_Tp();
+ }
+ else
+ {
+ if (__src)
+ __target._M_p = __src->_M_p;
+ else
+ delete static_cast<_Tp*>(__target._M_p);
+ }
+ }
+
+ _Storage _M_storage;
+ _Manager _M_manage;
+ };
+
+ template<typename _Tp>
+ inline constexpr bool __is_move_only_function_v = false;
+ template<typename _Tp>
+ constexpr bool __is_move_only_function_v<move_only_function<_Tp>> = true;
+ /// @endcond
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#include "mofunc_impl.h"
+#define _GLIBCXX_MOF_CV const
+#include "mofunc_impl.h"
+#define _GLIBCXX_MOF_REF &
+#include "mofunc_impl.h"
+#define _GLIBCXX_MOF_REF &&
+#include "mofunc_impl.h"
+#define _GLIBCXX_MOF_CV const
+#define _GLIBCXX_MOF_REF &
+#include "mofunc_impl.h"
+#define _GLIBCXX_MOF_CV const
+#define _GLIBCXX_MOF_REF &&
+#include "mofunc_impl.h"
+
+#endif // C++23
+#endif // _GLIBCXX_MOVE_ONLY_FUNCTION_H
diff --git a/libstdc++-v3/include/bits/parse_numbers.h b/libstdc++-v3/include/bits/parse_numbers.h
index 5618661..54b63c0 100644
--- a/libstdc++-v3/include/bits/parse_numbers.h
+++ b/libstdc++-v3/include/bits/parse_numbers.h
@@ -266,9 +266,9 @@ namespace __select_int
template<unsigned long long _Val, typename _IntType, typename... _Ints>
struct _Select_int_base<_Val, _IntType, _Ints...>
- : conditional_t<(_Val <= __gnu_cxx::__int_traits<_IntType>::__max),
- integral_constant<_IntType, (_IntType)_Val>,
- _Select_int_base<_Val, _Ints...>>
+ : __conditional_t<(_Val <= __gnu_cxx::__int_traits<_IntType>::__max),
+ integral_constant<_IntType, (_IntType)_Val>,
+ _Select_int_base<_Val, _Ints...>>
{ };
template<unsigned long long _Val>
diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h
index 653a358..115b86d 100644
--- a/libstdc++-v3/include/bits/ptr_traits.h
+++ b/libstdc++-v3/include/bits/ptr_traits.h
@@ -73,7 +73,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
using __make_not_void
- = typename conditional<is_void<_Tp>::value, __undefined, _Tp>::type;
+ = __conditional_t<is_void<_Tp>::value, __undefined, _Tp>;
/**
* @brief Uniform interface to all pointer-like types
diff --git a/libstdc++-v3/include/bits/range_access.h b/libstdc++-v3/include/bits/range_access.h
index ab2d4f8..3dec687 100644
--- a/libstdc++-v3/include/bits/range_access.h
+++ b/libstdc++-v3/include/bits/range_access.h
@@ -122,7 +122,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
template<typename _Container>
[[__nodiscard__]]
- inline constexpr auto
+ constexpr auto
cbegin(const _Container& __cont) noexcept(noexcept(std::begin(__cont)))
-> decltype(std::begin(__cont))
{ return std::begin(__cont); }
@@ -134,7 +134,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
template<typename _Container>
[[__nodiscard__]]
- inline constexpr auto
+ constexpr auto
cend(const _Container& __cont) noexcept(noexcept(std::end(__cont)))
-> decltype(std::end(__cont))
{ return std::end(__cont); }
diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h
index 78c2959..cfbac83 100644
--- a/libstdc++-v3/include/bits/ranges_algobase.h
+++ b/libstdc++-v3/include/bits/ranges_algobase.h
@@ -195,9 +195,9 @@ namespace ranges
requires (_IsMove
? indirectly_movable<_Iter, _Out>
: indirectly_copyable<_Iter, _Out>)
- constexpr conditional_t<_IsMove,
- move_backward_result<_Iter, _Out>,
- copy_backward_result<_Iter, _Out>>
+ constexpr __conditional_t<_IsMove,
+ move_backward_result<_Iter, _Out>,
+ copy_backward_result<_Iter, _Out>>
__copy_or_move_backward(_Iter __first, _Sent __last, _Out __result);
template<bool _IsMove,
@@ -206,9 +206,9 @@ namespace ranges
requires (_IsMove
? indirectly_movable<_Iter, _Out>
: indirectly_copyable<_Iter, _Out>)
- constexpr conditional_t<_IsMove,
- move_result<_Iter, _Out>,
- copy_result<_Iter, _Out>>
+ constexpr __conditional_t<_IsMove,
+ move_result<_Iter, _Out>,
+ copy_result<_Iter, _Out>>
__copy_or_move(_Iter __first, _Sent __last, _Out __result)
{
// TODO: implement more specializations to be at least on par with
@@ -349,9 +349,9 @@ namespace ranges
requires (_IsMove
? indirectly_movable<_Iter, _Out>
: indirectly_copyable<_Iter, _Out>)
- constexpr conditional_t<_IsMove,
- move_backward_result<_Iter, _Out>,
- copy_backward_result<_Iter, _Out>>
+ constexpr __conditional_t<_IsMove,
+ move_backward_result<_Iter, _Out>,
+ copy_backward_result<_Iter, _Out>>
__copy_or_move_backward(_Iter __first, _Sent __last, _Out __result)
{
// TODO: implement more specializations to be at least on par with
diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h
index 49c7d9c..01d0c35 100644
--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -787,22 +787,25 @@ namespace ranges
struct __distance_fn final
{
template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
- [[nodiscard]]
+ requires (!sized_sentinel_for<_Sent, _It>)
constexpr iter_difference_t<_It>
- operator()(_It __first, _Sent __last) const
+ operator()[[nodiscard]](_It __first, _Sent __last) const
{
- if constexpr (sized_sentinel_for<_Sent, _It>)
- return __last - __first;
- else
+ iter_difference_t<_It> __n = 0;
+ while (__first != __last)
{
- iter_difference_t<_It> __n = 0;
- while (__first != __last)
- {
- ++__first;
- ++__n;
- }
- return __n;
+ ++__first;
+ ++__n;
}
+ return __n;
+ }
+
+ template<input_or_output_iterator _It, sized_sentinel_for<_It> _Sent>
+ [[nodiscard]]
+ constexpr iter_difference_t<_It>
+ operator()(const _It& __first, const _Sent& __last) const
+ {
+ return __last - __first;
}
template<range _Range>
@@ -907,9 +910,9 @@ namespace ranges
};
template<range _Range>
- using borrowed_iterator_t = conditional_t<borrowed_range<_Range>,
- iterator_t<_Range>,
- dangling>;
+ using borrowed_iterator_t = __conditional_t<borrowed_range<_Range>,
+ iterator_t<_Range>,
+ dangling>;
} // namespace ranges
_GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h
index 4e87cfc..7e7b958 100644
--- a/libstdc++-v3/include/bits/ranges_util.h
+++ b/libstdc++-v3/include/bits/ranges_util.h
@@ -418,9 +418,9 @@ namespace ranges
enable_borrowed_range<subrange<_It, _Sent, _Kind>> = true;
template<range _Range>
- using borrowed_subrange_t = conditional_t<borrowed_range<_Range>,
- subrange<iterator_t<_Range>>,
- dangling>;
+ using borrowed_subrange_t = __conditional_t<borrowed_range<_Range>,
+ subrange<iterator_t<_Range>>,
+ dangling>;
} // namespace ranges
// The following ranges algorithms are used by <ranges>, and are defined here
diff --git a/libstdc++-v3/include/bits/refwrap.h b/libstdc++-v3/include/bits/refwrap.h
index adfbe21..a549efb 100644
--- a/libstdc++-v3/include/bits/refwrap.h
+++ b/libstdc++-v3/include/bits/refwrap.h
@@ -32,9 +32,7 @@
#pragma GCC system_header
-#if __cplusplus < 201103L
-# include <bits/c++0x_warning.h>
-#else
+#if __cplusplus >= 201103L
#include <bits/move.h>
#include <bits/invoke.h>
diff --git a/libstdc++-v3/include/bits/regex.h b/libstdc++-v3/include/bits/regex.h
index b8a0ad2..ff908da 100644
--- a/libstdc++-v3/include/bits/regex.h
+++ b/libstdc++-v3/include/bits/regex.h
@@ -57,6 +57,16 @@ namespace __detail
template<typename, typename, typename, bool>
class _Executor;
+
+ template<typename _Tp>
+ struct __is_contiguous_iter : false_type { };
+
+ template<typename _Tp>
+ struct __is_contiguous_iter<_Tp*> : true_type { };
+
+ template<typename _Tp, typename _Cont>
+ struct __is_contiguous_iter<__gnu_cxx::__normal_iterator<_Tp*, _Cont>>
+ : true_type { };
}
_GLIBCXX_BEGIN_NAMESPACE_CXX11
@@ -414,6 +424,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
static constexpr flag_type awk = regex_constants::awk;
static constexpr flag_type grep = regex_constants::grep;
static constexpr flag_type egrep = regex_constants::egrep;
+#if __cplusplus >= 201703L || !defined __STRICT_ANSI__
+ static constexpr flag_type multiline = regex_constants::multiline;
+#endif
///@}
// [7.8.2] construct/copy/destroy
@@ -421,7 +434,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
* Constructs a basic regular expression that does not match any
* character sequence.
*/
- basic_regex()
+ basic_regex() noexcept
: _M_flags(ECMAScript), _M_loc(), _M_automaton(nullptr)
{ }
@@ -438,8 +451,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
*/
explicit
basic_regex(const _Ch_type* __p, flag_type __f = ECMAScript)
- : basic_regex(__p, __p + char_traits<_Ch_type>::length(__p), __f)
- { }
+ { _M_compile(__p, __p + _Rx_traits::length(__p), __f); }
/**
* @brief Constructs a basic regular expression from the sequence
@@ -455,8 +467,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
*/
basic_regex(const _Ch_type* __p, std::size_t __len,
flag_type __f = ECMAScript)
- : basic_regex(__p, __p + __len, __f)
- { }
+ { _M_compile(__p, __p + __len, __f); }
/**
* @brief Copy-constructs a basic regular expression.
@@ -486,8 +497,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
basic_regex(const std::basic_string<_Ch_type, _Ch_traits,
_Ch_alloc>& __s,
flag_type __f = ECMAScript)
- : basic_regex(__s.data(), __s.data() + __s.size(), __f)
- { }
+ { _M_compile(__s.data(), __s.data() + __s.size(), __f); }
/**
* @brief Constructs a basic regular expression from the range
@@ -505,8 +515,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
template<typename _FwdIter>
basic_regex(_FwdIter __first, _FwdIter __last,
flag_type __f = ECMAScript)
- : basic_regex(std::move(__first), std::move(__last), locale_type(), __f)
- { }
+ { this->assign(__first, __last, __f); }
/**
* @brief Constructs a basic regular expression from an initializer list.
@@ -517,8 +526,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
* @throws regex_error if @p __l is not a valid regular expression.
*/
basic_regex(initializer_list<_Ch_type> __l, flag_type __f = ECMAScript)
- : basic_regex(__l.begin(), __l.end(), __f)
- { }
+ { _M_compile(__l.begin(), __l.end(), __f); }
/**
* @brief Destroys a basic regular expression.
@@ -530,15 +538,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
* @brief Assigns one regular expression to another.
*/
basic_regex&
- operator=(const basic_regex& __rhs)
- { return this->assign(__rhs); }
+ operator=(const basic_regex&) = default;
/**
* @brief Move-assigns one regular expression to another.
*/
basic_regex&
- operator=(basic_regex&& __rhs) noexcept
- { return this->assign(std::move(__rhs)); }
+ operator=(basic_regex&&) = default;
/**
* @brief Replaces a regular expression with a new one constructed from
@@ -561,7 +567,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
*/
basic_regex&
operator=(initializer_list<_Ch_type> __l)
- { return this->assign(__l.begin(), __l.end()); }
+ { return this->assign(__l); }
/**
* @brief Replaces a regular expression with a new one constructed from
@@ -576,30 +582,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
// [7.8.3] assign
/**
- * @brief the real assignment operator.
+ * @brief Assigns one regular expression to another.
*
* @param __rhs Another regular expression object.
*/
basic_regex&
- assign(const basic_regex& __rhs)
- {
- basic_regex __tmp(__rhs);
- this->swap(__tmp);
- return *this;
- }
+ assign(const basic_regex& __rhs) noexcept
+ { return *this = __rhs; }
/**
- * @brief The move-assignment operator.
+ * @brief Move-assigns one regular expression to another.
*
* @param __rhs Another regular expression object.
*/
basic_regex&
assign(basic_regex&& __rhs) noexcept
- {
- basic_regex __tmp(std::move(__rhs));
- this->swap(__tmp);
- return *this;
- }
+ { return *this = std::move(__rhs); }
/**
* @brief Assigns a new regular expression to a regex object from a
@@ -616,7 +614,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
*/
basic_regex&
assign(const _Ch_type* __p, flag_type __flags = ECMAScript)
- { return this->assign(string_type(__p), __flags); }
+ {
+ _M_compile(__p, __p + _Rx_traits::length(__p), __flags);
+ return *this;
+ }
/**
* @brief Assigns a new regular expression to a regex object from a
@@ -635,7 +636,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
// 3296. Inconsistent default argument for basic_regex<>::assign
basic_regex&
assign(const _Ch_type* __p, size_t __len, flag_type __flags = ECMAScript)
- { return this->assign(string_type(__p, __len), __flags); }
+ {
+ _M_compile(__p, __p + __len, __flags);
+ return *this;
+ }
/**
* @brief Assigns a new regular expression to a regex object from a
@@ -653,8 +657,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
assign(const basic_string<_Ch_type, _Ch_traits, _Alloc>& __s,
flag_type __flags = ECMAScript)
{
- return this->assign(basic_regex(__s.data(), __s.data() + __s.size(),
- _M_loc, __flags));
+ _M_compile(__s.data(), __s.data() + __s.size(), __flags);
+ return *this;
}
/**
@@ -674,7 +678,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
basic_regex&
assign(_InputIterator __first, _InputIterator __last,
flag_type __flags = ECMAScript)
- { return this->assign(string_type(__first, __last), __flags); }
+ {
+#if __cplusplus >= 201703L
+ using _ValT = typename iterator_traits<_InputIterator>::value_type;
+ if constexpr (__detail::__is_contiguous_iter<_InputIterator>::value
+ && is_same_v<_ValT, value_type>)
+ {
+ const auto __len = __last - __first;
+ const _Ch_type* __p = std::__to_address(__first);
+ _M_compile(__p, __p + __len, __flags);
+ }
+ else
+#endif
+ this->assign(string_type(__first, __last), __flags);
+ return *this;
+ }
/**
* @brief Assigns a new regular expression to a regex object.
@@ -689,7 +707,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
*/
basic_regex&
assign(initializer_list<_Ch_type> __l, flag_type __flags = ECMAScript)
- { return this->assign(__l.begin(), __l.end(), __flags); }
+ {
+ _M_compile(__l.begin(), __l.end(), __flags);
+ return *this;
+ }
// [7.8.4] const operations
/**
@@ -697,7 +718,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
* expression.
*/
unsigned int
- mark_count() const
+ mark_count() const noexcept
{
if (_M_automaton)
return _M_automaton->_M_sub_count() - 1;
@@ -709,7 +730,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
* or in the last call to assign().
*/
flag_type
- flags() const
+ flags() const noexcept
{ return _M_flags; }
// [7.8.5] locale
@@ -731,7 +752,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
* object.
*/
locale_type
- getloc() const
+ getloc() const noexcept
{ return _M_loc; }
// [7.8.6] swap
@@ -741,7 +762,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
* @param __rhs Another regular expression object.
*/
void
- swap(basic_regex& __rhs)
+ swap(basic_regex& __rhs) noexcept
{
std::swap(_M_flags, __rhs._M_flags);
std::swap(_M_loc, __rhs._M_loc);
@@ -757,13 +778,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
private:
typedef std::shared_ptr<const __detail::_NFA<_Rx_traits>> _AutomatonPtr;
- template<typename _FwdIter>
- basic_regex(_FwdIter __first, _FwdIter __last, locale_type __loc,
- flag_type __f)
- : _M_flags(__f), _M_loc(std::move(__loc)),
- _M_automaton(__detail::__compile_nfa<_Rx_traits>(
- std::move(__first), std::move(__last), _M_loc, _M_flags))
- { }
+ void
+ _M_compile(const _Ch_type* __first, const _Ch_type* __last,
+ flag_type __f)
+ {
+ __detail::_Compiler<_Rx_traits> __c(__first, __last, _M_loc, __f);
+ _M_automaton = __c._M_get_nfa();
+ _M_flags = __f;
+ }
template<typename _Bp, typename _Ap, typename _Cp, typename _Rp,
__detail::_RegexExecutorPolicy, bool>
@@ -848,7 +870,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
template<typename _Ch_type, typename _Rx_traits>
inline void
swap(basic_regex<_Ch_type, _Rx_traits>& __lhs,
- basic_regex<_Ch_type, _Rx_traits>& __rhs)
+ basic_regex<_Ch_type, _Rx_traits>& __rhs) noexcept
{ __lhs.swap(__rhs); }
diff --git a/libstdc++-v3/include/bits/regex_automaton.h b/libstdc++-v3/include/bits/regex_automaton.h
index 872a17f..f108675 100644
--- a/libstdc++-v3/include/bits/regex_automaton.h
+++ b/libstdc++-v3/include/bits/regex_automaton.h
@@ -95,13 +95,13 @@ namespace __detail
};
protected:
- explicit _State_base(_Opcode __opcode)
+ explicit _State_base(_Opcode __opcode) noexcept
: _M_opcode(__opcode), _M_next(_S_invalid_state_id)
{ }
public:
bool
- _M_has_alt()
+ _M_has_alt() const noexcept
{
return _M_opcode == _S_opcode_alternative
|| _M_opcode == _S_opcode_repeat
@@ -130,7 +130,7 @@ namespace __detail
"std::function<bool(char)>");
explicit
- _State(_Opcode __opcode) : _State_base(__opcode)
+ _State(_Opcode __opcode) noexcept : _State_base(__opcode)
{
if (_M_opcode() == _S_opcode_match)
new (this->_M_matcher_storage._M_addr()) _MatcherT();
@@ -143,7 +143,7 @@ namespace __detail
_MatcherT(__rhs._M_get_matcher());
}
- _State(_State&& __rhs) : _State_base(__rhs)
+ _State(_State&& __rhs) noexcept : _State_base(__rhs)
{
if (__rhs._M_opcode() == _S_opcode_match)
new (this->_M_matcher_storage._M_addr())
@@ -162,7 +162,7 @@ namespace __detail
// Since correct ctor and dtor rely on _M_opcode, it's better not to
// change it over time.
_Opcode
- _M_opcode() const
+ _M_opcode() const noexcept
{ return _State_base::_M_opcode; }
bool
@@ -170,11 +170,11 @@ namespace __detail
{ return _M_get_matcher()(__char); }
_MatcherT&
- _M_get_matcher()
+ _M_get_matcher() noexcept
{ return *static_cast<_MatcherT*>(this->_M_matcher_storage._M_addr()); }
const _MatcherT&
- _M_get_matcher() const
+ _M_get_matcher() const noexcept
{
return *static_cast<const _MatcherT*>(
this->_M_matcher_storage._M_addr());
@@ -183,11 +183,10 @@ namespace __detail
struct _NFA_base
{
- typedef size_t _SizeT;
typedef regex_constants::syntax_option_type _FlagT;
explicit
- _NFA_base(_FlagT __f)
+ _NFA_base(_FlagT __f) noexcept
: _M_flags(__f), _M_start_state(0), _M_subexpr_count(0),
_M_has_backref(false)
{ }
@@ -199,21 +198,21 @@ namespace __detail
public:
_FlagT
- _M_options() const
+ _M_options() const noexcept
{ return _M_flags; }
_StateIdT
- _M_start() const
+ _M_start() const noexcept
{ return _M_start_state; }
- _SizeT
- _M_sub_count() const
+ size_t
+ _M_sub_count() const noexcept
{ return _M_subexpr_count; }
_GLIBCXX_STD_C::vector<size_t> _M_paren_stack;
_FlagT _M_flags;
_StateIdT _M_start_state;
- _SizeT _M_subexpr_count;
+ size_t _M_subexpr_count;
bool _M_has_backref;
};
diff --git a/libstdc++-v3/include/bits/regex_compiler.h b/libstdc++-v3/include/bits/regex_compiler.h
index 5b4f2ae..88c60c2 100644
--- a/libstdc++-v3/include/bits/regex_compiler.h
+++ b/libstdc++-v3/include/bits/regex_compiler.h
@@ -58,15 +58,14 @@ namespace __detail
{
public:
typedef typename _TraitsT::char_type _CharT;
- typedef const _CharT* _IterT;
typedef _NFA<_TraitsT> _RegexT;
typedef regex_constants::syntax_option_type _FlagT;
- _Compiler(_IterT __b, _IterT __e,
+ _Compiler(const _CharT* __b, const _CharT* __e,
const typename _TraitsT::locale_type& __traits, _FlagT __flags);
shared_ptr<const _RegexT>
- _M_get_nfa()
+ _M_get_nfa() noexcept
{ return std::move(_M_nfa); }
private:
@@ -144,6 +143,26 @@ namespace __detail
return ret;
}
+ static _FlagT
+ _S_validate(_FlagT __f)
+ {
+ using namespace regex_constants;
+ switch (__f & (ECMAScript|basic|extended|awk|grep|egrep))
+ {
+ case ECMAScript:
+ case basic:
+ case extended:
+ case awk:
+ case grep:
+ case egrep:
+ return __f;
+ case _FlagT(0):
+ return __f | ECMAScript;
+ default:
+ std::__throw_regex_error(_S_grammar, "conflicting grammar options");
+ }
+ }
+
_FlagT _M_flags;
_ScannerT _M_scanner;
shared_ptr<_RegexT> _M_nfa;
@@ -153,47 +172,6 @@ namespace __detail
const _CtypeT& _M_ctype;
};
- template<typename _Tp>
- struct __is_contiguous_iter : is_pointer<_Tp>::type { };
-
- template<typename _Tp, typename _Cont>
- struct
- __is_contiguous_iter<__gnu_cxx::__normal_iterator<_Tp*, _Cont>>
- : true_type { };
-
- template<typename _Iter, typename _TraitsT>
- using __enable_if_contiguous_iter
- = __enable_if_t< __is_contiguous_iter<_Iter>::value,
- std::shared_ptr<const _NFA<_TraitsT>> >;
-
- template<typename _Iter, typename _TraitsT>
- using __disable_if_contiguous_iter
- = __enable_if_t< !__is_contiguous_iter<_Iter>::value,
- std::shared_ptr<const _NFA<_TraitsT>> >;
-
- template<typename _TraitsT, typename _FwdIter>
- inline __enable_if_contiguous_iter<_FwdIter, _TraitsT>
- __compile_nfa(_FwdIter __first, _FwdIter __last,
- const typename _TraitsT::locale_type& __loc,
- regex_constants::syntax_option_type __flags)
- {
- size_t __len = __last - __first;
- const auto* __cfirst = __len ? std::__addressof(*__first) : nullptr;
- using _Cmplr = _Compiler<_TraitsT>;
- return _Cmplr(__cfirst, __cfirst + __len, __loc, __flags)._M_get_nfa();
- }
-
- template<typename _TraitsT, typename _FwdIter>
- inline __disable_if_contiguous_iter<_FwdIter, _TraitsT>
- __compile_nfa(_FwdIter __first, _FwdIter __last,
- const typename _TraitsT::locale_type& __loc,
- regex_constants::syntax_option_type __flags)
- {
- const basic_string<typename _TraitsT::char_type> __str(__first, __last);
- return __compile_nfa<_TraitsT>(__str.data(), __str.data() + __str.size(),
- __loc, __flags);
- }
-
// [28.13.14]
template<typename _TraitsT, bool __icase, bool __collate>
class _RegexTranslatorBase
@@ -507,17 +485,17 @@ namespace __detail
private:
// Currently we only use the cache for char
- typedef typename std::is_same<_CharT, char>::type _UseCache;
+ using _UseCache = typename std::is_same<_CharT, char>::type;
static constexpr size_t
_S_cache_size =
1ul << (sizeof(_CharT) * __CHAR_BIT__ * int(_UseCache::value));
struct _Dummy { };
- typedef typename std::conditional<_UseCache::value,
- std::bitset<_S_cache_size>,
- _Dummy>::type _CacheT;
- typedef typename std::make_unsigned<_CharT>::type _UnsignedCharT;
+ using _CacheT = std::__conditional_t<_UseCache::value,
+ std::bitset<_S_cache_size>,
+ _Dummy>;
+ using _UnsignedCharT = typename std::make_unsigned<_CharT>::type;
bool
_M_apply(_CharT __ch, false_type) const;
diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc
index 440669d..956262a 100644
--- a/libstdc++-v3/include/bits/regex_compiler.tcc
+++ b/libstdc++-v3/include/bits/regex_compiler.tcc
@@ -63,17 +63,9 @@ namespace __detail
{
template<typename _TraitsT>
_Compiler<_TraitsT>::
- _Compiler(_IterT __b, _IterT __e,
+ _Compiler(const _CharT* __b, const _CharT* __e,
const typename _TraitsT::locale_type& __loc, _FlagT __flags)
- : _M_flags((__flags
- & (regex_constants::ECMAScript
- | regex_constants::basic
- | regex_constants::extended
- | regex_constants::grep
- | regex_constants::egrep
- | regex_constants::awk))
- ? __flags
- : __flags | regex_constants::ECMAScript),
+ : _M_flags(_S_validate(__flags)),
_M_scanner(__b, __e, _M_flags, __loc),
_M_nfa(make_shared<_RegexT>(__loc, _M_flags)),
_M_traits(_M_nfa->_M_traits),
@@ -140,7 +132,8 @@ namespace __detail
return true;
if (this->_M_atom())
{
- while (this->_M_quantifier());
+ while (this->_M_quantifier())
+ ;
return true;
}
return false;
@@ -440,7 +433,8 @@ namespace __detail
__last_char.second = '-';
}
}
- while (_M_expression_term(__last_char, __matcher));
+ while (_M_expression_term(__last_char, __matcher))
+ ;
if (__last_char.first)
__matcher._M_add_char(__last_char.second);
__matcher._M_ready();
diff --git a/libstdc++-v3/include/bits/regex_constants.h b/libstdc++-v3/include/bits/regex_constants.h
index 1c3dd36..0fd2879 100644
--- a/libstdc++-v3/include/bits/regex_constants.h
+++ b/libstdc++-v3/include/bits/regex_constants.h
@@ -64,7 +64,7 @@ namespace regex_constants
_S_grep,
_S_egrep,
_S_polynomial,
- _S_syntax_last
+ _S_multiline
};
/**
@@ -170,6 +170,24 @@ namespace regex_constants
_GLIBCXX17_INLINE constexpr syntax_option_type egrep =
static_cast<syntax_option_type>(1 << _S_egrep);
+#if __cplusplus >= 201703L || !defined __STRICT_ANSI__
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2503. multiline option should be added to syntax_option_type
+ /**
+ * Specifies that the `^` anchor matches at the beginning of a line,
+ * and the `$` anchor matches at the end of a line, not only at the
+ * beginning/end of the input.
+ * Valid for the ECMAScript syntax, ignored otherwise.
+ * @since C++17
+ */
+ _GLIBCXX17_INLINE constexpr syntax_option_type multiline =
+ static_cast<syntax_option_type>(1 << _S_multiline);
+#endif
+
+ /// Extension: Equivalent to regex_constants::multiline for C++11 and C++14.
+ _GLIBCXX17_INLINE constexpr syntax_option_type __multiline =
+ static_cast<syntax_option_type>(1 << _S_multiline);
+
/**
* Extension: Ensure both space complexity of compiled regex and
* time complexity execution are not exponential.
@@ -310,9 +328,10 @@ namespace regex_constants
static_cast<match_flag_type>(1 << _S_continuous);
/**
- * --first is a valid iterator position. When this flag is set then the
- * flags match_not_bol and match_not_bow are ignored by the regular
- * expression algorithms 28.11 and iterators 28.12.
+ * `--first` is a valid iterator position. When this flag is set then the
+ * flags `match_not_bol` and `match_not_bow` are ignored by the algorithms
+ * `regex_match`, `regex_search`, and `regex_replace`, and by the iterators
+ * `regex_iterator` and `regex_token_iterator`.
*/
_GLIBCXX17_INLINE constexpr match_flag_type match_prev_avail =
static_cast<match_flag_type>(1 << _S_prev_avail);
diff --git a/libstdc++-v3/include/bits/regex_error.h b/libstdc++-v3/include/bits/regex_error.h
index 2759383..e7b7b42 100644
--- a/libstdc++-v3/include/bits/regex_error.h
+++ b/libstdc++-v3/include/bits/regex_error.h
@@ -61,6 +61,8 @@ namespace regex_constants
_S_error_badrepeat,
_S_error_complexity,
_S_error_stack,
+ _S_null,
+ _S_grammar
};
/** The expression contained an invalid collating element name. */
@@ -150,7 +152,7 @@ namespace regex_constants
* @returns the regex error code.
*/
regex_constants::error_type
- code() const
+ code() const noexcept
{ return _M_code; }
private:
diff --git a/libstdc++-v3/include/bits/regex_executor.h b/libstdc++-v3/include/bits/regex_executor.h
index 3422893..167d406 100644
--- a/libstdc++-v3/include/bits/regex_executor.h
+++ b/libstdc++-v3/include/bits/regex_executor.h
@@ -78,12 +78,12 @@ namespace __detail
_M_results(__results),
_M_rep_count(_M_nfa.size()),
_M_states(_M_nfa._M_start(), _M_nfa.size()),
- _M_flags((__flags & regex_constants::match_prev_avail)
- ? (__flags
- & ~regex_constants::match_not_bol
- & ~regex_constants::match_not_bow)
- : __flags)
- { }
+ _M_flags(__flags)
+ {
+ using namespace regex_constants;
+ if (__flags & match_prev_avail) // ignore not_bol and not_bow
+ _M_flags &= ~(match_not_bol | match_not_bow);
+ }
// Set matched when string exactly matches the pattern.
bool
@@ -165,16 +165,39 @@ namespace __detail
bool
_M_at_begin() const
{
- return _M_current == _M_begin
- && !(_M_flags & (regex_constants::match_not_bol
- | regex_constants::match_prev_avail));
+ if (_M_current == _M_begin)
+ {
+ // match_not_bol means ^ does not match [_M_begin,_M_begin)
+ if (_M_flags & regex_constants::match_not_bol)
+ return false;
+ // match_prev_avail means _M_begin is not the start of the input.
+ if (_M_flags & regex_constants::match_prev_avail)
+ {
+ // For ECMAScript multiline matches, check if the previous
+ // character is a line terminator.
+ if (_M_match_multiline())
+ return _M_is_line_terminator(*std::prev(_M_current));
+ else
+ return false;
+ }
+ else // ^ matches at _M_begin
+ return true;
+ }
+ else if (_M_match_multiline())
+ return _M_is_line_terminator(*std::prev(_M_current));
+ else
+ return false;
}
bool
_M_at_end() const
{
- return _M_current == _M_end
- && !(_M_flags & regex_constants::match_not_eol);
+ if (_M_current == _M_end)
+ return !(_M_flags & regex_constants::match_not_eol);
+ else if (_M_match_multiline())
+ return _M_is_line_terminator(*_M_current);
+ else
+ return false;
}
bool
@@ -183,6 +206,31 @@ namespace __detail
bool
_M_lookahead(_StateIdT __next);
+ bool
+ _M_is_line_terminator(_CharT __c) const
+ {
+ const auto& __traits = _M_re._M_automaton->_M_traits;
+ const auto& __ct = use_facet<ctype<_CharT>>(__traits.getloc());
+ const char __n{ __ct.narrow(__c, ' ') };
+ if (__n == '\n')
+ return true;
+ if (_M_re._M_automaton->_M_options() & regex_constants::ECMAScript)
+ {
+ if (__n == '\r')
+ return true;
+ // FIXME: U+2028 (line separator) and U+2029 (paragraph separator)
+ }
+ return false;
+ }
+
+ bool
+ _M_match_multiline() const noexcept
+ {
+ constexpr auto __m
+ = regex_constants::ECMAScript | regex_constants::__multiline;
+ return (_M_re._M_automaton->_M_options() & __m) == __m;
+ }
+
// Holds additional information used in BFS-mode.
template<typename _SearchMode, typename _ResultsVec>
struct _State_info;
diff --git a/libstdc++-v3/include/bits/regex_executor.tcc b/libstdc++-v3/include/bits/regex_executor.tcc
index 3cefeda..2577265 100644
--- a/libstdc++-v3/include/bits/regex_executor.tcc
+++ b/libstdc++-v3/include/bits/regex_executor.tcc
@@ -423,7 +423,7 @@ namespace __detail
template<typename _BiIter, typename _Alloc, typename _TraitsT,
bool __dfs_mode>
void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
- _M_handle_accept(_Match_mode __match_mode, _StateIdT __i)
+ _M_handle_accept(_Match_mode __match_mode, _StateIdT)
{
if (__dfs_mode)
{
diff --git a/libstdc++-v3/include/bits/regex_scanner.h b/libstdc++-v3/include/bits/regex_scanner.h
index e810fa7..4e7d5ef 100644
--- a/libstdc++-v3/include/bits/regex_scanner.h
+++ b/libstdc++-v3/include/bits/regex_scanner.h
@@ -211,23 +211,22 @@ namespace __detail
: public _ScannerBase
{
public:
- typedef const _CharT* _IterT;
typedef std::basic_string<_CharT> _StringT;
typedef regex_constants::syntax_option_type _FlagT;
typedef const std::ctype<_CharT> _CtypeT;
- _Scanner(_IterT __begin, _IterT __end,
+ _Scanner(const _CharT* __begin, const _CharT* __end,
_FlagT __flags, std::locale __loc);
void
_M_advance();
_TokenT
- _M_get_token() const
+ _M_get_token() const noexcept
{ return _M_token; }
const _StringT&
- _M_get_value() const
+ _M_get_value() const noexcept
{ return _M_value; }
#ifdef _GLIBCXX_DEBUG
@@ -257,8 +256,8 @@ namespace __detail
void
_M_eat_class(char);
- _IterT _M_current;
- _IterT _M_end;
+ const _CharT* _M_current;
+ const _CharT* _M_end;
_CtypeT& _M_ctype;
_StringT _M_value;
void (_Scanner::* _M_eat_escape)();
diff --git a/libstdc++-v3/include/bits/regex_scanner.tcc b/libstdc++-v3/include/bits/regex_scanner.tcc
index a9d6a61..d81627d 100644
--- a/libstdc++-v3/include/bits/regex_scanner.tcc
+++ b/libstdc++-v3/include/bits/regex_scanner.tcc
@@ -54,8 +54,7 @@ namespace __detail
{
template<typename _CharT>
_Scanner<_CharT>::
- _Scanner(typename _Scanner::_IterT __begin,
- typename _Scanner::_IterT __end,
+ _Scanner(const _CharT* __begin, const _CharT* __end,
_FlagT __flags, std::locale __loc)
: _ScannerBase(__flags),
_M_current(__begin), _M_end(__end),
@@ -176,6 +175,16 @@ namespace __detail
_M_state = _S_state_in_brace;
_M_token = _S_token_interval_begin;
}
+ else if (__builtin_expect(__c == _CharT(0), false))
+ {
+ if (!_M_is_ecma())
+ {
+ __throw_regex_error(regex_constants::_S_null,
+ "Unexpected null character in regular expression");
+ }
+ _M_token = _S_token_ord_char;
+ _M_value.assign(1, __c);
+ }
else if (__c != ']' && __c != '}')
{
auto __it = _M_token_tbl;
diff --git a/libstdc++-v3/include/bits/semaphore_base.h b/libstdc++-v3/include/bits/semaphore_base.h
index c4565d7..2c8d757 100644
--- a/libstdc++-v3/include/bits/semaphore_base.h
+++ b/libstdc++-v3/include/bits/semaphore_base.h
@@ -33,6 +33,7 @@
#pragma GCC system_header
#include <bits/atomic_base.h>
+#include <bits/chrono.h>
#if __cpp_lib_atomic_wait
#include <bits/atomic_timed_wait.h>
#include <ext/numeric_traits.h>
@@ -45,9 +46,6 @@
# include <semaphore.h> // sem_t, sem_init, sem_wait, sem_post etc.
#endif
-#include <chrono>
-#include <type_traits>
-
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
index 5be935d..3473a74 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -675,9 +675,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return;
using _Ptr = typename unique_ptr<_Tp, _Del>::pointer;
- using _Del2 = typename conditional<is_reference<_Del>::value,
+ using _Del2 = __conditional_t<is_reference<_Del>::value,
reference_wrapper<typename remove_reference<_Del>::type>,
- _Del>::type;
+ _Del>;
using _Sp_cd_type
= _Sp_counted_deleter<_Ptr, _Del2, allocator<void>, _Lp>;
using _Alloc = allocator<_Sp_cd_type>;
diff --git a/libstdc++-v3/include/bits/std_function.h b/libstdc++-v3/include/bits/std_function.h
index 3dda820..5573844 100644
--- a/libstdc++-v3/include/bits/std_function.h
+++ b/libstdc++-v3/include/bits/std_function.h
@@ -82,17 +82,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
union [[gnu::may_alias]] _Any_data
{
- void* _M_access() { return &_M_pod_data[0]; }
- const void* _M_access() const { return &_M_pod_data[0]; }
+ void* _M_access() noexcept { return &_M_pod_data[0]; }
+ const void* _M_access() const noexcept { return &_M_pod_data[0]; }
template<typename _Tp>
_Tp&
- _M_access()
+ _M_access() noexcept
{ return *static_cast<_Tp*>(_M_access()); }
template<typename _Tp>
const _Tp&
- _M_access() const
+ _M_access() const noexcept
{ return *static_cast<const _Tp*>(_M_access()); }
_Nocopy_types _M_unused;
@@ -131,7 +131,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Retrieve a pointer to the function object
static _Functor*
- _M_get_pointer(const _Any_data& __source)
+ _M_get_pointer(const _Any_data& __source) noexcept
{
if _GLIBCXX17_CONSTEXPR (__stored_locally)
{
@@ -217,22 +217,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Signature>
static bool
- _M_not_empty_function(const function<_Signature>& __f)
+ _M_not_empty_function(const function<_Signature>& __f) noexcept
{ return static_cast<bool>(__f); }
template<typename _Tp>
static bool
- _M_not_empty_function(_Tp* __fp)
+ _M_not_empty_function(_Tp* __fp) noexcept
{ return __fp != nullptr; }
template<typename _Class, typename _Tp>
static bool
- _M_not_empty_function(_Tp _Class::* __mp)
+ _M_not_empty_function(_Tp _Class::* __mp) noexcept
{ return __mp != nullptr; }
template<typename _Tp>
static bool
- _M_not_empty_function(const _Tp&)
+ _M_not_empty_function(const _Tp&) noexcept
{ return true; }
};
diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index 5d12972..bc611a9 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -810,26 +810,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
#endif // C++11
- template<typename _ForwardIterator, typename _Predicate>
- _GLIBCXX20_CONSTEXPR
- _ForwardIterator
- __remove_if(_ForwardIterator __first, _ForwardIterator __last,
- _Predicate __pred)
- {
- __first = std::__find_if(__first, __last, __pred);
- if (__first == __last)
- return __first;
- _ForwardIterator __result = __first;
- ++__first;
- for (; __first != __last; ++__first)
- if (!__pred(__first))
- {
- *__result = _GLIBCXX_MOVE(*__first);
- ++__result;
- }
- return __result;
- }
-
/**
* @brief Remove elements from a sequence.
* @ingroup mutating_algorithms
@@ -3621,7 +3601,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__gnu_cxx::__ops::__iter_comp_iter(__pred));
}
-#if __cplusplus > 201402L
+#if __cplusplus >= 201703L
#define __cpp_lib_clamp 201603
@@ -3631,14 +3611,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @param __val A value of arbitrary type.
* @param __lo A lower limit of arbitrary type.
* @param __hi An upper limit of arbitrary type.
- * @return max(__val, __lo) if __val < __hi or min(__val, __hi) otherwise.
+ * @retval `__lo` if `__val < __lo`
+ * @retval `__hi` if `__hi < __val`
+ * @retval `__val` otherwise.
+ * @pre `_Tp` is LessThanComparable and `(__hi < __lo)` is false.
*/
template<typename _Tp>
constexpr const _Tp&
clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi)
{
__glibcxx_assert(!(__hi < __lo));
- return (__val < __lo) ? __lo : (__hi < __val) ? __hi : __val;
+ return std::min(std::max(__val, __lo), __hi);
}
/**
@@ -3648,15 +3631,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @param __lo A lower limit of arbitrary type.
* @param __hi An upper limit of arbitrary type.
* @param __comp A comparison functor.
- * @return max(__val, __lo, __comp) if __comp(__val, __hi)
- * or min(__val, __hi, __comp) otherwise.
+ * @retval `__lo` if `__comp(__val, __lo)`
+ * @retval `__hi` if `__comp(__hi, __val)`
+ * @retval `__val` otherwise.
+ * @pre `__comp(__hi, __lo)` is false.
*/
template<typename _Tp, typename _Compare>
constexpr const _Tp&
clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi, _Compare __comp)
{
__glibcxx_assert(!__comp(__hi, __lo));
- return __comp(__val, __lo) ? __lo : __comp(__hi, __val) ? __hi : __val;
+ return std::min(std::max(__val, __lo, __comp), __hi, __comp);
}
#endif // C++17
#endif // C++14
diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h
index d0c4962..0e05868 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -420,11 +420,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result)
{
#if __cplusplus >= 201103L
- using __assignable = conditional<_IsMove,
- is_move_assignable<_Tp>,
- is_copy_assignable<_Tp>>;
+ using __assignable = __conditional_t<_IsMove,
+ is_move_assignable<_Tp>,
+ is_copy_assignable<_Tp>>;
// trivial types can have deleted assignment
- static_assert( __assignable::type::value, "type must be assignable" );
+ static_assert( __assignable::value, "type must be assignable" );
#endif
const ptrdiff_t _Num = __last - __first;
if (_Num)
@@ -613,7 +613,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_II>)
__glibcxx_function_requires(_OutputIteratorConcept<_OI,
- typename iterator_traits<_II>::value_type>)
+ typename iterator_traits<_II>::reference>)
__glibcxx_requires_can_increment_range(__first, __last, __result);
return std::__copy_move_a<__is_move_iterator<_II>::__value>
@@ -646,7 +646,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_II>)
__glibcxx_function_requires(_OutputIteratorConcept<_OI,
- typename iterator_traits<_II>::value_type>)
+ typename iterator_traits<_II>::value_type&&>)
__glibcxx_requires_can_increment_range(__first, __last, __result);
return std::__copy_move_a<true>(std::__miter_base(__first),
@@ -731,11 +731,11 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
__copy_move_b(const _Tp* __first, const _Tp* __last, _Tp* __result)
{
#if __cplusplus >= 201103L
- using __assignable = conditional<_IsMove,
- is_move_assignable<_Tp>,
- is_copy_assignable<_Tp>>;
+ using __assignable = __conditional_t<_IsMove,
+ is_move_assignable<_Tp>,
+ is_copy_assignable<_Tp>>;
// trivial types can have deleted assignment
- static_assert( __assignable::type::value, "type must be assignable" );
+ static_assert( __assignable::value, "type must be assignable" );
#endif
const ptrdiff_t _Num = __last - __first;
if (_Num)
@@ -850,9 +850,8 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
// concept requirements
__glibcxx_function_requires(_BidirectionalIteratorConcept<_BI1>)
__glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<_BI2>)
- __glibcxx_function_requires(_ConvertibleConcept<
- typename iterator_traits<_BI1>::value_type,
- typename iterator_traits<_BI2>::value_type>)
+ __glibcxx_function_requires(_OutputIteratorConcept<_BI2,
+ typename iterator_traits<_BI1>::reference>)
__glibcxx_requires_can_decrement_range(__first, __last, __result);
return std::__copy_move_backward_a<__is_move_iterator<_BI1>::__value>
@@ -886,9 +885,8 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
// concept requirements
__glibcxx_function_requires(_BidirectionalIteratorConcept<_BI1>)
__glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<_BI2>)
- __glibcxx_function_requires(_ConvertibleConcept<
- typename iterator_traits<_BI1>::value_type,
- typename iterator_traits<_BI2>::value_type>)
+ __glibcxx_function_requires(_OutputIteratorConcept<_BI2,
+ typename iterator_traits<_BI1>::value_type&&>)
__glibcxx_requires_can_decrement_range(__first, __last, __result);
return std::__copy_move_backward_a<true>(std::__miter_base(__first),
@@ -1144,7 +1142,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
fill_n(_OI __first, _Size __n, const _Tp& __value)
{
// concept requirements
- __glibcxx_function_requires(_OutputIteratorConcept<_OI, _Tp>)
+ __glibcxx_function_requires(_OutputIteratorConcept<_OI, const _Tp&>)
return std::__fill_n_a(__first, std::__size_to_integer(__n), __value,
std::__iterator_category(__first));
@@ -2127,6 +2125,26 @@ _GLIBCXX_END_NAMESPACE_ALGO
return __n;
}
+ template<typename _ForwardIterator, typename _Predicate>
+ _GLIBCXX20_CONSTEXPR
+ _ForwardIterator
+ __remove_if(_ForwardIterator __first, _ForwardIterator __last,
+ _Predicate __pred)
+ {
+ __first = std::__find_if(__first, __last, __pred);
+ if (__first == __last)
+ return __first;
+ _ForwardIterator __result = __first;
+ ++__first;
+ for (; __first != __last; ++__first)
+ if (!__pred(__first))
+ {
+ *__result = _GLIBCXX_MOVE(*__first);
+ ++__result;
+ }
+ return __result;
+ }
+
#if __cplusplus >= 201103L
template<typename _ForwardIterator1, typename _ForwardIterator2,
typename _BinaryPredicate>
diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h
index a954890..3778d5a 100644
--- a/libstdc++-v3/include/bits/stl_bvector.h
+++ b/libstdc++-v3/include/bits/stl_bvector.h
@@ -706,13 +706,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
public:
- vector(vector&& __x, const allocator_type& __a)
+ vector(vector&& __x, const __type_identity_t<allocator_type>& __a)
noexcept(_Bit_alloc_traits::_S_always_equal())
: vector(std::move(__x), __a,
typename _Bit_alloc_traits::is_always_equal{})
{ }
- vector(const vector& __x, const allocator_type& __a)
+ vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
: _Base(__a)
{
_M_initialize(__x.size());
diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h
index 6095498..268fb9e 100644
--- a/libstdc++-v3/include/bits/stl_deque.h
+++ b/libstdc++-v3/include/bits/stl_deque.h
@@ -932,14 +932,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
deque(deque&&) = default;
/// Copy constructor with alternative allocator
- deque(const deque& __x, const allocator_type& __a)
+ deque(const deque& __x, const __type_identity_t<allocator_type>& __a)
: _Base(__a, __x.size())
{ std::__uninitialized_copy_a(__x.begin(), __x.end(),
this->_M_impl._M_start,
_M_get_Tp_allocator()); }
/// Move constructor with alternative allocator
- deque(deque&& __x, const allocator_type& __a)
+ deque(deque&& __x, const __type_identity_t<allocator_type>& __a)
: deque(std::move(__x), __a, typename _Alloc_traits::is_always_equal{})
{ }
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index c5b0240..8afd675 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -100,7 +100,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// otherwise use _Otherwise.
template<typename _Cat, typename _Limit, typename _Otherwise = _Cat>
using __clamp_iter_cat
- = conditional_t<derived_from<_Cat, _Limit>, _Limit, _Otherwise>;
+ = __conditional_t<derived_from<_Cat, _Limit>, _Limit, _Otherwise>;
}
#endif
@@ -155,9 +155,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef typename __traits_type::reference reference;
#else
using iterator_concept
- = conditional_t<random_access_iterator<_Iterator>,
- random_access_iterator_tag,
- bidirectional_iterator_tag>;
+ = __conditional_t<random_access_iterator<_Iterator>,
+ random_access_iterator_tag,
+ bidirectional_iterator_tag>;
using iterator_category
= __detail::__clamp_iter_cat<typename __traits_type::iterator_category,
random_access_iterator_tag>;
@@ -174,20 +174,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// 235 No specification of default ctor for reverse_iterator
// 1012. reverse_iterator default ctor should value initialize
_GLIBCXX17_CONSTEXPR
- reverse_iterator() : current() { }
+ reverse_iterator()
+ _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator()))
+ : current()
+ { }
/**
* This %iterator will move in the opposite direction that @p x does.
*/
explicit _GLIBCXX17_CONSTEXPR
- reverse_iterator(iterator_type __x) : current(__x) { }
+ reverse_iterator(iterator_type __x)
+ _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator(__x)))
+ : current(__x)
+ { }
/**
* The copy constructor is normal.
*/
_GLIBCXX17_CONSTEXPR
reverse_iterator(const reverse_iterator& __x)
- : current(__x.current) { }
+ _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator(__x.current)))
+ : current(__x.current)
+ { }
#if __cplusplus >= 201103L
reverse_iterator& operator=(const reverse_iterator&) = default;
@@ -203,7 +211,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
_GLIBCXX17_CONSTEXPR
reverse_iterator(const reverse_iterator<_Iter>& __x)
- : current(__x.current) { }
+ _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator(__x.current)))
+ : current(__x.current)
+ { }
#if __cplusplus >= 201103L
template<typename _Iter>
@@ -214,6 +224,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX17_CONSTEXPR
reverse_iterator&
operator=(const reverse_iterator<_Iter>& __x)
+ _GLIBCXX_NOEXCEPT_IF(noexcept(current = __x.current))
{
current = __x.current;
return *this;
@@ -226,6 +237,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_NODISCARD
_GLIBCXX17_CONSTEXPR iterator_type
base() const
+ _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator(current)))
{ return current; }
/**
@@ -1010,6 +1022,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef std::iterator_traits<_Iterator> __traits_type;
+#if __cplusplus >= 201103L
+ template<typename _Iter>
+ using __convertible_from
+ = std::__enable_if_t<std::is_convertible<_Iter, _Iterator>::value>;
+#endif
+
public:
typedef _Iterator iterator_type;
typedef typename __traits_type::iterator_category iterator_category;
@@ -1030,12 +1048,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: _M_current(__i) { }
// Allow iterator to const_iterator conversion
+#if __cplusplus >= 201103L
+ template<typename _Iter, typename = __convertible_from<_Iter>>
+ _GLIBCXX20_CONSTEXPR
+ __normal_iterator(const __normal_iterator<_Iter, _Container>& __i)
+ noexcept
+#else
+ // N.B. _Container::pointer is not actually in container requirements,
+ // but is present in std::vector and std::basic_string.
template<typename _Iter>
- _GLIBCXX20_CONSTEXPR
__normal_iterator(const __normal_iterator<_Iter,
typename __enable_if<
- (std::__are_same<_Iter, typename _Container::pointer>::__value),
- _Container>::__type>& __i) _GLIBCXX_NOEXCEPT
+ (std::__are_same<_Iter, typename _Container::pointer>::__value),
+ _Container>::__type>& __i)
+#endif
: _M_current(__i.base()) { }
// Forward iterator requirements
@@ -1285,6 +1311,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __it.base(); }
#if __cplusplus >= 201103L
+
+ // Need to specialize pointer_traits because the primary template will
+ // deduce element_type of __normal_iterator<T*, C> as T* rather than T.
+ template<typename _Iterator, typename _Container>
+ struct pointer_traits<__gnu_cxx::__normal_iterator<_Iterator, _Container>>
+ {
+ private:
+ using _Base = pointer_traits<_Iterator>;
+
+ public:
+ using element_type = typename _Base::element_type;
+ using pointer = __gnu_cxx::__normal_iterator<_Iterator, _Container>;
+ using difference_type = typename _Base::difference_type;
+
+ template<typename _Tp>
+ using rebind = __gnu_cxx::__normal_iterator<_Tp, _Container>;
+
+ static pointer
+ pointer_to(element_type& __e) noexcept
+ { return pointer(_Base::pointer_to(__e)); }
+
+#if __cplusplus >= 202002L
+ static element_type*
+ to_address(pointer __p) noexcept
+ { return __p.base(); }
+#endif
+ };
+
/**
* @addtogroup iterators
* @{
@@ -1401,9 +1455,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef _Iterator pointer;
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2106. move_iterator wrapping iterators returning prvalues
- typedef typename conditional<is_reference<__base_ref>::value,
- typename remove_reference<__base_ref>::type&&,
- __base_ref>::type reference;
+ using reference
+ = __conditional_t<is_reference<__base_ref>::value,
+ typename remove_reference<__base_ref>::type&&,
+ __base_ref>;
#endif
_GLIBCXX17_CONSTEXPR
@@ -1708,9 +1763,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return move_iterator<_Iterator>(std::move(__i)); }
template<typename _Iterator, typename _ReturnType
- = typename conditional<__move_if_noexcept_cond
+ = __conditional_t<__move_if_noexcept_cond
<typename iterator_traits<_Iterator>::value_type>::value,
- _Iterator, move_iterator<_Iterator>>::type>
+ _Iterator, move_iterator<_Iterator>>>
inline _GLIBCXX17_CONSTEXPR _ReturnType
__make_move_if_noexcept_iterator(_Iterator __i)
{ return _ReturnType(__i); }
@@ -1718,8 +1773,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Overload for pointers that matches std::move_if_noexcept more closely,
// returning a constant iterator when we don't want to move.
template<typename _Tp, typename _ReturnType
- = typename conditional<__move_if_noexcept_cond<_Tp>::value,
- const _Tp*, move_iterator<_Tp*>>::type>
+ = __conditional_t<__move_if_noexcept_cond<_Tp>::value,
+ const _Tp*, move_iterator<_Tp*>>>
inline _GLIBCXX17_CONSTEXPR _ReturnType
__make_move_if_noexcept_iterator(_Tp* __i)
{ return _ReturnType(__i); }
@@ -1773,7 +1828,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
public:
const iter_value_t<_It>*
- operator->() const
+ operator->() const noexcept
{ return std::__addressof(_M_keep); }
};
@@ -1788,7 +1843,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
public:
const iter_value_t<_It>&
- operator*() const
+ operator*() const noexcept
{ return _M_keep; }
};
@@ -2124,8 +2179,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
public:
- using iterator_concept = conditional_t<forward_iterator<_It>,
- forward_iterator_tag, input_iterator_tag>;
+ using iterator_concept = __conditional_t<forward_iterator<_It>,
+ forward_iterator_tag,
+ input_iterator_tag>;
using iterator_category = decltype(_S_iter_cat());
using value_type = iter_value_t<_It>;
using difference_type = iter_difference_t<_It>;
@@ -2405,9 +2461,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
requires same_as<__detail::__iter_traits<_It>, iterator_traits<_It>>
struct iterator_traits<counted_iterator<_It>> : iterator_traits<_It>
{
- using pointer = conditional_t<contiguous_iterator<_It>,
- add_pointer_t<iter_reference_t<_It>>,
- void>;
+ using pointer = __conditional_t<contiguous_iterator<_It>,
+ add_pointer_t<iter_reference_t<_It>>,
+ void>;
};
#endif // C++20
diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h
index 9ae640e..96d2a2f 100644
--- a/libstdc++-v3/include/bits/stl_list.h
+++ b/libstdc++-v3/include/bits/stl_list.h
@@ -1,6 +1,7 @@
// List implementation -*- C++ -*-
// Copyright (C) 2001-2021 Free Software Foundation, Inc.
+// Copyright The GNU Toolchain Authors.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -157,6 +158,73 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
private:
_List_node_base* _M_base() { return this; }
};
+
+ // Used by list::sort to hold nodes being sorted.
+ struct _Scratch_list : _List_node_base
+ {
+ _Scratch_list() { _M_next = _M_prev = this; }
+
+ bool empty() const { return _M_next == this; }
+
+ void swap(_List_node_base& __l) { _List_node_base::swap(*this, __l); }
+
+ template<typename _Iter, typename _Cmp>
+ struct _Ptr_cmp
+ {
+ _Cmp _M_cmp;
+
+ bool
+ operator()(const __detail::_List_node_base* __lhs,
+ const __detail::_List_node_base* __rhs) /* not const */
+ { return _M_cmp(*_Iter(__lhs), *_Iter(__rhs)); }
+ };
+
+ template<typename _Iter>
+ struct _Ptr_cmp<_Iter, void>
+ {
+ bool
+ operator()(const __detail::_List_node_base* __lhs,
+ const __detail::_List_node_base* __rhs) const
+ { return *_Iter(__lhs) < *_Iter(__rhs); }
+ };
+
+ // Merge nodes from __x into *this. Both lists must be sorted wrt _Cmp.
+ template<typename _Cmp>
+ void
+ merge(_List_node_base& __x, _Cmp __comp)
+ {
+ _List_node_base* __first1 = _M_next;
+ _List_node_base* const __last1 = this;
+ _List_node_base* __first2 = __x._M_next;
+ _List_node_base* const __last2 = std::__addressof(__x);
+
+ while (__first1 != __last1 && __first2 != __last2)
+ {
+ if (__comp(__first2, __first1))
+ {
+ _List_node_base* __next = __first2->_M_next;
+ __first1->_M_transfer(__first2, __next);
+ __first2 = __next;
+ }
+ else
+ __first1 = __first1->_M_next;
+ }
+ if (__first2 != __last2)
+ this->_M_transfer(__first2, __last2);
+ }
+
+ // Splice the node at __i into *this.
+ void _M_take_one(_List_node_base* __i)
+ { this->_M_transfer(__i, __i->_M_next); }
+
+ // Splice all nodes from *this after __i.
+ void _M_put_all(_List_node_base* __i)
+ {
+ if (!empty())
+ __i->_M_transfer(_M_next, this);
+ }
+ };
+
} // namespace detail
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
@@ -768,7 +836,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
: _Base(_Node_alloc_type(__a))
{ _M_initialize_dispatch(__l.begin(), __l.end(), __false_type()); }
- list(const list& __x, const allocator_type& __a)
+ list(const list& __x, const __type_identity_t<allocator_type>& __a)
: _Base(_Node_alloc_type(__a))
{ _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); }
@@ -788,7 +856,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
}
public:
- list(list&& __x, const allocator_type& __a)
+ list(list&& __x, const __type_identity_t<allocator_type>& __a)
noexcept(_Node_alloc_traits::_S_always_equal())
: list(std::move(__x), __a,
typename _Node_alloc_traits::is_always_equal{})
@@ -1992,6 +2060,40 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
__false_type{});
}
#endif
+
+#if _GLIBCXX_USE_CXX11_ABI
+ // Update _M_size members after merging (some of) __src into __dest.
+ struct _Finalize_merge
+ {
+ explicit
+ _Finalize_merge(list& __dest, list& __src, const iterator& __src_next)
+ : _M_dest(__dest), _M_src(__src), _M_next(__src_next)
+ { }
+
+ ~_Finalize_merge()
+ {
+ // For the common case, _M_next == _M_sec.end() and the std::distance
+ // call is fast. But if any *iter1 < *iter2 comparison throws then we
+ // have to count how many elements remain in _M_src.
+ const size_t __num_unmerged = std::distance(_M_next, _M_src.end());
+ const size_t __orig_size = _M_src._M_get_size();
+ _M_dest._M_inc_size(__orig_size - __num_unmerged);
+ _M_src._M_set_size(__num_unmerged);
+ }
+
+ list& _M_dest;
+ list& _M_src;
+ const iterator& _M_next;
+
+#if __cplusplus >= 201103L
+ _Finalize_merge(const _Finalize_merge&) = delete;
+#endif
+ };
+#else
+ struct _Finalize_merge
+ { explicit _Finalize_merge(list&, list&, const iterator&) { } };
+#endif
+
};
#if __cpp_deduction_guides >= 201606
diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h
index 535dbeb..cc87f11 100644
--- a/libstdc++-v3/include/bits/stl_map.h
+++ b/libstdc++-v3/include/bits/stl_map.h
@@ -237,11 +237,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: _M_t(_Pair_alloc_type(__a)) { }
/// Allocator-extended copy constructor.
- map(const map& __m, const allocator_type& __a)
+ map(const map& __m, const __type_identity_t<allocator_type>& __a)
: _M_t(__m._M_t, _Pair_alloc_type(__a)) { }
/// Allocator-extended move constructor.
- map(map&& __m, const allocator_type& __a)
+ map(map&& __m, const __type_identity_t<allocator_type>& __a)
noexcept(is_nothrow_copy_constructible<_Compare>::value
&& _Alloc_traits::_S_always_equal())
: _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { }
diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h
index 8157981..1b9648e 100644
--- a/libstdc++-v3/include/bits/stl_multimap.h
+++ b/libstdc++-v3/include/bits/stl_multimap.h
@@ -234,11 +234,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: _M_t(_Pair_alloc_type(__a)) { }
/// Allocator-extended copy constructor.
- multimap(const multimap& __m, const allocator_type& __a)
+ multimap(const multimap& __m,
+ const __type_identity_t<allocator_type>& __a)
: _M_t(__m._M_t, _Pair_alloc_type(__a)) { }
/// Allocator-extended move constructor.
- multimap(multimap&& __m, const allocator_type& __a)
+ multimap(multimap&& __m, const __type_identity_t<allocator_type>& __a)
noexcept(is_nothrow_copy_constructible<_Compare>::value
&& _Alloc_traits::_S_always_equal())
: _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { }
diff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h
index ef98760..5d9d619 100644
--- a/libstdc++-v3/include/bits/stl_multiset.h
+++ b/libstdc++-v3/include/bits/stl_multiset.h
@@ -248,11 +248,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: _M_t(_Key_alloc_type(__a)) { }
/// Allocator-extended copy constructor.
- multiset(const multiset& __m, const allocator_type& __a)
+ multiset(const multiset& __m,
+ const __type_identity_t<allocator_type>& __a)
: _M_t(__m._M_t, _Key_alloc_type(__a)) { }
/// Allocator-extended move constructor.
- multiset(multiset&& __m, const allocator_type& __a)
+ multiset(multiset&& __m, const __type_identity_t<allocator_type>& __a)
noexcept(is_nothrow_copy_constructible<_Compare>::value
&& _Alloc_traits::_S_always_equal())
: _M_t(std::move(__m._M_t), _Key_alloc_type(__a)) { }
diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h
index 329485c..5b400da 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -129,15 +129,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
is_convertible<_U2&&, _T2>>::value;
}
-
template <bool __implicit, typename _U1, typename _U2>
static constexpr bool _DeprConsPair()
{
using __do_converts = __and_<is_convertible<_U1&&, _T1>,
is_convertible<_U2&&, _T2>>;
- using __converts = typename conditional<__implicit,
- __do_converts,
- __not_<__do_converts>>::type;
+ using __converts = __conditional_t<__implicit,
+ __do_converts,
+ __not_<__do_converts>>;
return __and_<is_constructible<_T1, _U1&&>,
is_constructible<_T2, _U2&&>,
__converts
@@ -561,10 +560,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
second(std::forward<_U2>(__p.second)) { }
pair&
- operator=(typename conditional<
- __and_<is_copy_assignable<_T1>,
- is_copy_assignable<_T2>>::value,
- const pair&, const __nonesuch&>::type __p)
+ operator=(__conditional_t<__and_<is_copy_assignable<_T1>,
+ is_copy_assignable<_T2>>::value,
+ const pair&, const __nonesuch&> __p)
{
first = __p.first;
second = __p.second;
@@ -572,10 +570,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
pair&
- operator=(typename conditional<
- __and_<is_move_assignable<_T1>,
- is_move_assignable<_T2>>::value,
- pair&&, __nonesuch&&>::type __p)
+ operator=(__conditional_t<__and_<is_move_assignable<_T1>,
+ is_move_assignable<_T2>>::value,
+ pair&&, __nonesuch&&> __p)
noexcept(__and_<is_nothrow_move_assignable<_T1>,
is_nothrow_move_assignable<_T2>>::value)
{
diff --git a/libstdc++-v3/include/bits/stl_queue.h b/libstdc++-v3/include/bits/stl_queue.h
index 41ffc50..68cfe86 100644
--- a/libstdc++-v3/include/bits/stl_queue.h
+++ b/libstdc++-v3/include/bits/stl_queue.h
@@ -194,6 +194,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
queue(queue&& __q, const _Alloc& __a)
: c(std::move(__q.c), __a) { }
+
+#if __cplusplus > 202002L
+#define __cpp_lib_adaptor_iterator_pair_constructor 202106L
+
+ template<typename _InputIterator,
+ typename = _RequireInputIter<_InputIterator>>
+ queue(_InputIterator __first, _InputIterator __last)
+ : c(__first, __last) { }
+
+ template<typename _InputIterator, typename _Alloc,
+ typename = _RequireInputIter<_InputIterator>,
+ typename = _Uses<_Alloc>>
+ queue(_InputIterator __first, _InputIterator __last, const _Alloc& __a)
+ : c(__first, __last, __a) { }
+#endif
#endif
/**
@@ -327,10 +342,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
queue(_Container) -> queue<typename _Container::value_type, _Container>;
template<typename _Container, typename _Allocator,
- typename = _RequireNotAllocator<_Container>,
- typename = _RequireAllocator<_Allocator>>
+ typename = _RequireNotAllocator<_Container>>
queue(_Container, _Allocator)
-> queue<typename _Container::value_type, _Container>;
+
+#ifdef __cpp_lib_adaptor_iterator_pair_constructor
+ template<typename _InputIterator,
+ typename _ValT
+ = typename iterator_traits<_InputIterator>::value_type,
+ typename = _RequireInputIter<_InputIterator>>
+ queue(_InputIterator, _InputIterator) -> queue<_ValT>;
+
+ template<typename _InputIterator, typename _Allocator,
+ typename _ValT
+ = typename iterator_traits<_InputIterator>::value_type,
+ typename = _RequireInputIter<_InputIterator>,
+ typename = _RequireAllocator<_Allocator>>
+ queue(_InputIterator, _InputIterator, _Allocator)
+ -> queue<_ValT, deque<_ValT, _Allocator>>;
+#endif
#endif
/**
@@ -594,10 +624,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::make_heap(c.begin(), c.end(), comp);
}
#else
- template<typename _InputIterator>
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3529. priority_queue(first, last) should construct c with (first, last)
+ template<typename _InputIterator,
+ typename = std::_RequireInputIter<_InputIterator>>
+ priority_queue(_InputIterator __first, _InputIterator __last,
+ const _Compare& __x = _Compare())
+ : c(__first, __last), comp(__x)
+ { std::make_heap(c.begin(), c.end(), comp); }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3522. Missing requirement on InputIterator template parameter
+ template<typename _InputIterator,
+ typename = std::_RequireInputIter<_InputIterator>>
priority_queue(_InputIterator __first, _InputIterator __last,
- const _Compare& __x,
- const _Sequence& __s)
+ const _Compare& __x, const _Sequence& __s)
: c(__s), comp(__x)
{
__glibcxx_requires_valid_range(__first, __last);
@@ -605,16 +646,59 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::make_heap(c.begin(), c.end(), comp);
}
- template<typename _InputIterator>
+ template<typename _InputIterator,
+ typename = std::_RequireInputIter<_InputIterator>>
priority_queue(_InputIterator __first, _InputIterator __last,
- const _Compare& __x = _Compare(),
- _Sequence&& __s = _Sequence())
+ const _Compare& __x, _Sequence&& __s)
: c(std::move(__s)), comp(__x)
{
__glibcxx_requires_valid_range(__first, __last);
c.insert(c.end(), __first, __last);
std::make_heap(c.begin(), c.end(), comp);
}
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3506. Missing allocator-extended constructors for priority_queue
+ template<typename _InputIterator, typename _Alloc,
+ typename = std::_RequireInputIter<_InputIterator>,
+ typename _Requires = _Uses<_Alloc>>
+ priority_queue(_InputIterator __first, _InputIterator __last,
+ const _Alloc& __alloc)
+ : c(__first, __last, __alloc), comp()
+ { std::make_heap(c.begin(), c.end(), comp); }
+
+ template<typename _InputIterator, typename _Alloc,
+ typename = std::_RequireInputIter<_InputIterator>,
+ typename _Requires = _Uses<_Alloc>>
+ priority_queue(_InputIterator __first, _InputIterator __last,
+ const _Compare& __x, const _Alloc& __alloc)
+ : c(__first, __last, __alloc), comp(__x)
+ { std::make_heap(c.begin(), c.end(), comp); }
+
+ template<typename _InputIterator, typename _Alloc,
+ typename = std::_RequireInputIter<_InputIterator>,
+ typename _Requires = _Uses<_Alloc>>
+ priority_queue(_InputIterator __first, _InputIterator __last,
+ const _Compare& __x, const _Sequence& __s,
+ const _Alloc& __alloc)
+ : c(__s, __alloc), comp(__x)
+ {
+ __glibcxx_requires_valid_range(__first, __last);
+ c.insert(c.end(), __first, __last);
+ std::make_heap(c.begin(), c.end(), comp);
+ }
+
+ template<typename _InputIterator, typename _Alloc,
+ typename _Requires = _Uses<_Alloc>>
+ priority_queue(_InputIterator __first, _InputIterator __last,
+ const _Compare& __x, _Sequence&& __s,
+ const _Alloc& __alloc)
+ : c(std::move(__s), __alloc), comp(__x)
+ {
+ __glibcxx_requires_valid_range(__first, __last);
+ c.insert(c.end(), __first, __last);
+ std::make_heap(c.begin(), c.end(), comp);
+ }
#endif
/**
@@ -732,8 +816,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Compare, typename _Container, typename _Allocator,
typename = _RequireNotAllocator<_Compare>,
- typename = _RequireNotAllocator<_Container>,
- typename = _RequireAllocator<_Allocator>>
+ typename = _RequireNotAllocator<_Container>>
priority_queue(_Compare, _Container, _Allocator)
-> priority_queue<typename _Container::value_type, _Container, _Compare>;
#endif
diff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h
index a9b9695..f0dfa05 100644
--- a/libstdc++-v3/include/bits/stl_set.h
+++ b/libstdc++-v3/include/bits/stl_set.h
@@ -252,11 +252,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: _M_t(_Key_alloc_type(__a)) { }
/// Allocator-extended copy constructor.
- set(const set& __x, const allocator_type& __a)
+ set(const set& __x, const __type_identity_t<allocator_type>& __a)
: _M_t(__x._M_t, _Key_alloc_type(__a)) { }
/// Allocator-extended move constructor.
- set(set&& __x, const allocator_type& __a)
+ set(set&& __x, const __type_identity_t<allocator_type>& __a)
noexcept(is_nothrow_copy_constructible<_Compare>::value
&& _Alloc_traits::_S_always_equal())
: _M_t(std::move(__x._M_t), _Key_alloc_type(__a)) { }
diff --git a/libstdc++-v3/include/bits/stl_stack.h b/libstdc++-v3/include/bits/stl_stack.h
index 85137b9..429743f 100644
--- a/libstdc++-v3/include/bits/stl_stack.h
+++ b/libstdc++-v3/include/bits/stl_stack.h
@@ -170,6 +170,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
stack(_Sequence&& __c)
: c(std::move(__c)) { }
+#if __cplusplus > 202002L
+#define __cpp_lib_adaptor_iterator_pair_constructor 202106L
+
+ template<typename _InputIterator,
+ typename = _RequireInputIter<_InputIterator>>
+ stack(_InputIterator __first, _InputIterator __last)
+ : c(__first, __last) { }
+#endif
+
+
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
explicit
stack(const _Alloc& __a)
@@ -190,6 +200,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
stack(stack&& __q, const _Alloc& __a)
: c(std::move(__q.c), __a) { }
+
+#if __cplusplus > 202002L
+ template<typename _InputIterator, typename _Alloc,
+ typename = _RequireInputIter<_InputIterator>,
+ typename = _Uses<_Alloc>>
+ stack(_InputIterator __first, _InputIterator __last, const _Alloc& __a)
+ : c(__first, __last, __a) { }
+#endif
#endif
/**
@@ -299,10 +317,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
stack(_Container) -> stack<typename _Container::value_type, _Container>;
template<typename _Container, typename _Allocator,
- typename = _RequireNotAllocator<_Container>,
- typename = _RequireAllocator<_Allocator>>
+ typename = _RequireNotAllocator<_Container>>
stack(_Container, _Allocator)
-> stack<typename _Container::value_type, _Container>;
+
+#ifdef __cpp_lib_adaptor_iterator_pair_constructor
+ template<typename _InputIterator, typename _Allocator,
+ typename _ValT
+ = typename iterator_traits<_InputIterator>::value_type,
+ typename = _RequireInputIter<_InputIterator>>
+ stack(_InputIterator, _InputIterator) -> stack<_ValT>;
+
+ template<typename _InputIterator, typename _Allocator,
+ typename _ValT
+ = typename iterator_traits<_InputIterator>::value_type,
+ typename = _RequireInputIter<_InputIterator>,
+ typename = _RequireAllocator<_Allocator>>
+ stack(_InputIterator, _InputIterator, _Allocator)
+ -> stack<_ValT, deque<_ValT, _Allocator>>;
+#endif
#endif
/**
diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h
index e4e3e0b..0692525 100644
--- a/libstdc++-v3/include/bits/stl_tree.h
+++ b/libstdc++-v3/include/bits/stl_tree.h
@@ -637,9 +637,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_clone_node(_Link_type __x, _NodeGen& __node_gen)
{
#if __cplusplus >= 201103L
- using _Vp = typename conditional<_MoveValue,
- value_type&&,
- const value_type&>::type;
+ using _Vp = __conditional_t<_MoveValue,
+ value_type&&,
+ const value_type&>;
#endif
_Link_type __tmp
= __node_gen(_GLIBCXX_FORWARD(_Vp, *__x->_M_valptr()));
@@ -821,7 +821,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus > 201402L
using node_type = _Node_handle<_Key, _Val, _Node_allocator>;
using insert_return_type = _Node_insert_return<
- conditional_t<is_same_v<_Key, _Val>, const_iterator, iterator>,
+ __conditional_t<is_same_v<_Key, _Val>, const_iterator, iterator>,
node_type>;
#endif
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index 296da43..2023581 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -572,7 +572,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
vector(vector&&) noexcept = default;
/// Copy constructor with alternative allocator
- vector(const vector& __x, const allocator_type& __a)
+ vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
: _Base(__x.size(), __a)
{
this->_M_impl._M_finish =
@@ -604,7 +604,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
public:
/// Move constructor with alternative allocator
- vector(vector&& __rv, const allocator_type& __m)
+ vector(vector&& __rv, const __type_identity_t<allocator_type>& __m)
noexcept( noexcept(
vector(std::declval<vector&&>(), std::declval<const allocator_type&>(),
std::declval<typename _Alloc_traits::is_always_equal>())) )
diff --git a/libstdc++-v3/include/bits/stream_iterator.h b/libstdc++-v3/include/bits/stream_iterator.h
index d74c158..5a13231 100644
--- a/libstdc++-v3/include/bits/stream_iterator.h
+++ b/libstdc++-v3/include/bits/stream_iterator.h
@@ -65,6 +65,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
public:
/// Construct end of input stream iterator.
_GLIBCXX_CONSTEXPR istream_iterator()
+ _GLIBCXX_NOEXCEPT_IF(is_nothrow_default_constructible<_Tp>::value)
: _M_stream(0), _M_value(), _M_ok(false) {}
/// Construct start of input stream iterator.
@@ -73,6 +74,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ _M_read(); }
istream_iterator(const istream_iterator& __obj)
+ _GLIBCXX_NOEXCEPT_IF(is_nothrow_copy_constructible<_Tp>::value)
: _M_stream(__obj._M_stream), _M_value(__obj._M_value),
_M_ok(__obj._M_ok)
{ }
@@ -91,7 +93,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_NODISCARD
const _Tp&
- operator*() const
+ operator*() const _GLIBCXX_NOEXCEPT
{
__glibcxx_requires_cond(_M_ok,
_M_message(__gnu_debug::__msg_deref_istream)
@@ -101,7 +103,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_NODISCARD
const _Tp*
- operator->() const { return std::__addressof((operator*())); }
+ operator->() const _GLIBCXX_NOEXCEPT
+ { return std::__addressof((operator*())); }
istream_iterator&
operator++()
@@ -126,7 +129,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
private:
bool
- _M_equal(const istream_iterator& __x) const
+ _M_equal(const istream_iterator& __x) const _GLIBCXX_NOEXCEPT
{
// Ideally this would just return _M_stream == __x._M_stream,
// but code compiled with old versions never sets _M_stream to null.
@@ -148,6 +151,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_NODISCARD
friend bool
operator==(const istream_iterator& __x, const istream_iterator& __y)
+ _GLIBCXX_NOEXCEPT
{ return __x._M_equal(__y); }
#if __cpp_impl_three_way_comparison < 201907L
@@ -156,13 +160,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_NODISCARD
friend bool
operator!=(const istream_iterator& __x, const istream_iterator& __y)
+ _GLIBCXX_NOEXCEPT
{ return !__x._M_equal(__y); }
#endif
#if __cplusplus > 201703L && __cpp_lib_concepts
[[nodiscard]]
friend bool
- operator==(const istream_iterator& __i, default_sentinel_t)
+ operator==(const istream_iterator& __i, default_sentinel_t) noexcept
{ return !__i._M_stream; }
#endif
};
@@ -200,7 +205,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
public:
/// Construct from an ostream.
- ostream_iterator(ostream_type& __s)
+ ostream_iterator(ostream_type& __s) _GLIBCXX_NOEXCEPT
: _M_stream(std::__addressof(__s)), _M_string(0) {}
/**
@@ -213,11 +218,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @param __s Underlying ostream to write to.
* @param __c CharT delimiter string to insert.
*/
- ostream_iterator(ostream_type& __s, const _CharT* __c)
+ ostream_iterator(ostream_type& __s, const _CharT* __c) _GLIBCXX_NOEXCEPT
: _M_stream(std::__addressof(__s)), _M_string(__c) { }
/// Copy constructor.
- ostream_iterator(const ostream_iterator& __obj)
+ ostream_iterator(const ostream_iterator& __obj) _GLIBCXX_NOEXCEPT
: _M_stream(__obj._M_stream), _M_string(__obj._M_string) { }
#if __cplusplus >= 201103L
@@ -240,15 +245,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_NODISCARD
ostream_iterator&
- operator*()
+ operator*() _GLIBCXX_NOEXCEPT
{ return *this; }
ostream_iterator&
- operator++()
+ operator++() _GLIBCXX_NOEXCEPT
{ return *this; }
ostream_iterator&
- operator++(int)
+ operator++(int) _GLIBCXX_NOEXCEPT
{ return *this; }
};
diff --git a/libstdc++-v3/include/bits/this_thread_sleep.h b/libstdc++-v3/include/bits/this_thread_sleep.h
index bdcd0cd..0b95f51 100644
--- a/libstdc++-v3/include/bits/this_thread_sleep.h
+++ b/libstdc++-v3/include/bits/this_thread_sleep.h
@@ -33,9 +33,7 @@
#pragma GCC system_header
#if __cplusplus >= 201103L
-#include <bits/c++config.h>
-
-#include <chrono> // std::chrono::*
+#include <bits/chrono.h> // std::chrono::*
#ifdef _GLIBCXX_USE_NANOSLEEP
# include <cerrno> // errno, EINTR
diff --git a/libstdc++-v3/include/bits/unique_lock.h b/libstdc++-v3/include/bits/unique_lock.h
index 07edfbb..048bc27 100644
--- a/libstdc++-v3/include/bits/unique_lock.h
+++ b/libstdc++-v3/include/bits/unique_lock.h
@@ -36,7 +36,7 @@
# include <bits/c++0x_warning.h>
#else
-#include <chrono>
+#include <bits/chrono.h>
#include <bits/move.h> // for std::swap
#include <bits/std_mutex.h> // for std::defer_lock_t
diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h
index da58217..c257e95 100644
--- a/libstdc++-v3/include/bits/unique_ptr.h
+++ b/libstdc++-v3/include/bits/unique_ptr.h
@@ -338,9 +338,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
template<typename _Up, typename _Ep, typename = _Require<
__safe_conversion_up<_Up, _Ep>,
- typename conditional<is_reference<_Dp>::value,
- is_same<_Ep, _Dp>,
- is_convertible<_Ep, _Dp>>::type>>
+ __conditional_t<is_reference<_Dp>::value,
+ is_same<_Ep, _Dp>,
+ is_convertible<_Ep, _Dp>>>>
unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
{ }
@@ -605,9 +605,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Up, typename _Ep, typename = _Require<
__safe_conversion_up<_Up, _Ep>,
- typename conditional<is_reference<_Dp>::value,
- is_same<_Ep, _Dp>,
- is_convertible<_Ep, _Dp>>::type>>
+ __conditional_t<is_reference<_Dp>::value,
+ is_same<_Ep, _Dp>,
+ is_convertible<_Ep, _Dp>>>>
unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
{ }
diff --git a/libstdc++-v3/include/bits/uses_allocator.h b/libstdc++-v3/include/bits/uses_allocator.h
index 36b219c..358c571 100644
--- a/libstdc++-v3/include/bits/uses_allocator.h
+++ b/libstdc++-v3/include/bits/uses_allocator.h
@@ -86,10 +86,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Alloc, typename... _Args>
struct __uses_alloc<true, _Tp, _Alloc, _Args...>
- : conditional<
+ : __conditional_t<
is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>::value,
__uses_alloc1<_Alloc>,
- __uses_alloc2<_Alloc>>::type
+ __uses_alloc2<_Alloc>>
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2586. Wrong value category used in scoped_allocator_adaptor::construct
@@ -131,10 +131,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<template<typename...> class _Predicate,
typename _Tp, typename _Alloc, typename... _Args>
struct __is_uses_allocator_predicate
- : conditional<uses_allocator<_Tp, _Alloc>::value,
+ : __conditional_t<uses_allocator<_Tp, _Alloc>::value,
__or_<_Predicate<_Tp, allocator_arg_t, _Alloc, _Args...>,
_Predicate<_Tp, _Args..., _Alloc>>,
- _Predicate<_Tp, _Args...>>::type { };
+ _Predicate<_Tp, _Args...>> { };
template<typename _Tp, typename _Alloc, typename... _Args>
struct __is_uses_allocator_constructible
diff --git a/libstdc++-v3/include/bits/utility.h b/libstdc++-v3/include/bits/utility.h
index 96d3508..fce52a4 100644
--- a/libstdc++-v3/include/bits/utility.h
+++ b/libstdc++-v3/include/bits/utility.h
@@ -184,17 +184,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline constexpr in_place_index_t<_Idx> in_place_index{};
template<typename>
- struct __is_in_place_type_impl : false_type
- { };
+ inline constexpr bool __is_in_place_type_v = false;
template<typename _Tp>
- struct __is_in_place_type_impl<in_place_type_t<_Tp>> : true_type
- { };
+ inline constexpr bool __is_in_place_type_v<in_place_type_t<_Tp>> = true;
template<typename _Tp>
- struct __is_in_place_type
- : public __is_in_place_type_impl<_Tp>
- { };
+ using __is_in_place_type = bool_constant<__is_in_place_type_v<_Tp>>;
+
#endif // C++17
#endif // C++14
diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc
index caee5cb..16366e0 100644
--- a/libstdc++-v3/include/bits/vector.tcc
+++ b/libstdc++-v3/include/bits/vector.tcc
@@ -944,7 +944,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return false;
__try
{
- _M_reallocate(size());
+ if (size_type __n = size())
+ _M_reallocate(__n);
+ else
+ {
+ this->_M_deallocate();
+ this->_M_impl._M_reset();
+ }
return true;
}
__catch(...)
diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque
index 574cab1..8e48111 100644
--- a/libstdc++-v3/include/debug/deque
+++ b/libstdc++-v3/include/debug/deque
@@ -108,10 +108,10 @@ namespace __debug
deque(const deque&) = default;
deque(deque&&) = default;
- deque(const deque& __d, const _Allocator& __a)
+ deque(const deque& __d, const __type_identity_t<_Allocator>& __a)
: _Base(__d, __a) { }
- deque(deque&& __d, const _Allocator& __a)
+ deque(deque&& __d, const __type_identity_t<_Allocator>& __a)
: _Safe(std::move(__d)), _Base(std::move(__d), __a) { }
deque(initializer_list<value_type> __l,
diff --git a/libstdc++-v3/include/debug/functions.h b/libstdc++-v3/include/debug/functions.h
index 6cac11f..5d53544 100644
--- a/libstdc++-v3/include/debug/functions.h
+++ b/libstdc++-v3/include/debug/functions.h
@@ -33,7 +33,7 @@
#if __cplusplus >= 201103L
# include <bits/stl_iterator.h> // for __miter_base
-# include <type_traits> // for is_lvalue_reference and conditional.
+# include <type_traits> // for is_lvalue_reference and __conditional_t.
#endif
#include <debug/helper_functions.h>
@@ -158,8 +158,8 @@ namespace __gnu_debug
using __lvalref = std::is_lvalue_reference<
typename std::iterator_traits<_InputIterator>::reference>;
using __contiguous = _Is_contiguous_sequence<_Sequence>;
- using __tag = typename std::conditional<__lvalref::value, __contiguous,
- std::__false_type>::type;
+ using __tag = std::__conditional_t<__lvalref::value, __contiguous,
+ std::__false_type>;
#endif
return __foreign_iterator_aux3(__it, __other, __other_end, __tag());
}
diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list
index b599e93..de30edb 100644
--- a/libstdc++-v3/include/debug/list
+++ b/libstdc++-v3/include/debug/list
@@ -115,10 +115,10 @@ namespace __debug
~list() = default;
- list(const list& __x, const allocator_type& __a)
+ list(const list& __x, const __type_identity_t<allocator_type>& __a)
: _Base(__x, __a) { }
- list(list&& __x, const allocator_type& __a)
+ list(list&& __x, const __type_identity_t<allocator_type>& __a)
noexcept(
std::is_nothrow_constructible<_Base,
_Base, const allocator_type&>::value )
diff --git a/libstdc++-v3/include/debug/map.h b/libstdc++-v3/include/debug/map.h
index c0153d0..9e142cf 100644
--- a/libstdc++-v3/include/debug/map.h
+++ b/libstdc++-v3/include/debug/map.h
@@ -114,10 +114,10 @@ namespace __debug
map(const allocator_type& __a)
: _Base(__a) { }
- map(const map& __m, const allocator_type& __a)
+ map(const map& __m, const __type_identity_t<allocator_type>& __a)
: _Base(__m, __a) { }
- map(map&& __m, const allocator_type& __a)
+ map(map&& __m, const __type_identity_t<allocator_type>& __a)
noexcept( noexcept(_Base(std::move(__m._M_base()), __a)) )
: _Safe(std::move(__m._M_safe()), __a),
_Base(std::move(__m._M_base()), __a) { }
diff --git a/libstdc++-v3/include/debug/multimap.h b/libstdc++-v3/include/debug/multimap.h
index 9492934..a05b8a8 100644
--- a/libstdc++-v3/include/debug/multimap.h
+++ b/libstdc++-v3/include/debug/multimap.h
@@ -114,10 +114,11 @@ namespace __debug
multimap(const allocator_type& __a)
: _Base(__a) { }
- multimap(const multimap& __m, const allocator_type& __a)
+ multimap(const multimap& __m,
+ const __type_identity_t<allocator_type>& __a)
: _Base(__m, __a) { }
- multimap(multimap&& __m, const allocator_type& __a)
+ multimap(multimap&& __m, const __type_identity_t<allocator_type>& __a)
noexcept( noexcept(_Base(std::move(__m._M_base()), __a)) )
: _Safe(std::move(__m._M_safe()), __a),
_Base(std::move(__m._M_base()), __a) { }
diff --git a/libstdc++-v3/include/debug/multiset.h b/libstdc++-v3/include/debug/multiset.h
index bb68d8c..a312ccf 100644
--- a/libstdc++-v3/include/debug/multiset.h
+++ b/libstdc++-v3/include/debug/multiset.h
@@ -113,10 +113,11 @@ namespace __debug
multiset(const allocator_type& __a)
: _Base(__a) { }
- multiset(const multiset& __m, const allocator_type& __a)
+ multiset(const multiset& __m,
+ const __type_identity_t<allocator_type>& __a)
: _Base(__m, __a) { }
- multiset(multiset&& __m, const allocator_type& __a)
+ multiset(multiset&& __m, const __type_identity_t<allocator_type>& __a)
noexcept( noexcept(_Base(std::move(__m._M_base()), __a)) )
: _Safe(std::move(__m._M_safe()), __a),
_Base(std::move(__m._M_base()), __a) { }
diff --git a/libstdc++-v3/include/debug/set.h b/libstdc++-v3/include/debug/set.h
index cdf35ea..01da942 100644
--- a/libstdc++-v3/include/debug/set.h
+++ b/libstdc++-v3/include/debug/set.h
@@ -113,10 +113,10 @@ namespace __debug
set(const allocator_type& __a)
: _Base(__a) { }
- set(const set& __x, const allocator_type& __a)
+ set(const set& __x, const __type_identity_t<allocator_type>& __a)
: _Base(__x, __a) { }
- set(set&& __x, const allocator_type& __a)
+ set(set&& __x, const __type_identity_t<allocator_type>& __a)
noexcept( noexcept(_Base(std::move(__x._M_base()), __a)) )
: _Safe(std::move(__x._M_safe()), __a),
_Base(std::move(__x._M_base()), __a) { }
diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector
index d30d750..03fd940 100644
--- a/libstdc++-v3/include/debug/vector
+++ b/libstdc++-v3/include/debug/vector
@@ -212,10 +212,10 @@ namespace __debug
vector(const vector&) = default;
vector(vector&&) = default;
- vector(const vector& __x, const allocator_type& __a)
+ vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
: _Base(__x, __a) { }
- vector(vector&& __x, const allocator_type& __a)
+ vector(vector&& __x, const __type_identity_t<allocator_type>& __a)
noexcept(
std::is_nothrow_constructible<_Base,
_Base, const allocator_type&>::value )
diff --git a/libstdc++-v3/include/experimental/any b/libstdc++-v3/include/experimental/any
index 7d18f26..44f5db0 100644
--- a/libstdc++-v3/include/experimental/any
+++ b/libstdc++-v3/include/experimental/any
@@ -115,9 +115,9 @@ inline namespace fundamentals_v1
struct _Manager_external; // creates contained object on the heap
template<typename _Tp>
- using _Manager = conditional_t<_Internal<_Tp>::value,
- _Manager_internal<_Tp>,
- _Manager_external<_Tp>>;
+ using _Manager = __conditional_t<_Internal<_Tp>::value,
+ _Manager_internal<_Tp>,
+ _Manager_external<_Tp>>;
template<typename _Tp, typename _Decayed = decay_t<_Tp>>
using _Decay = enable_if_t<!is_same<_Decayed, any>::value, _Decayed>;
@@ -430,8 +430,8 @@ inline namespace fundamentals_v1
// If the type _Tp could never be stored in an any we don't want to
// instantiate _Manager<_Tp>, so use _Manager<any::_Op> instead, which
// is explicitly specialized and has a no-op _S_manage function.
- using _Vp = conditional_t<__and_<__does_not_decay, __is_copyable>::value,
- _Up, any::_Op>;
+ using _Vp = __conditional_t<__and_<__does_not_decay, __is_copyable>{},
+ _Up, any::_Op>;
// First try comparing function addresses, which works without RTTI
if (__any->_M_manager == &any::_Manager<_Vp>::_S_manage
#if __cpp_rtti
diff --git a/libstdc++-v3/include/experimental/bits/fs_fwd.h b/libstdc++-v3/include/experimental/bits/fs_fwd.h
index 8d63e09..243e571 100644
--- a/libstdc++-v3/include/experimental/bits/fs_fwd.h
+++ b/libstdc++-v3/include/experimental/bits/fs_fwd.h
@@ -36,7 +36,7 @@
#include <system_error>
#include <cstdint>
-#include <chrono>
+#include <bits/chrono.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/experimental/chrono b/libstdc++-v3/include/experimental/chrono
index a38cb52..8d66174 100644
--- a/libstdc++-v3/include/experimental/chrono
+++ b/libstdc++-v3/include/experimental/chrono
@@ -38,7 +38,7 @@
#if __cplusplus >= 201402L
-#include <chrono>
+#include <bits/chrono.h> // Only the C++14 parts of <chrono>
#include <experimental/bits/lfts_config.h>
namespace std _GLIBCXX_VISIBILITY(default)
diff --git a/libstdc++-v3/include/experimental/deque b/libstdc++-v3/include/experimental/deque
index a76fb65..710833e 100644
--- a/libstdc++-v3/include/experimental/deque
+++ b/libstdc++-v3/include/experimental/deque
@@ -50,16 +50,16 @@ inline namespace fundamentals_v2
inline void
erase_if(deque<_Tp, _Alloc>& __cont, _Predicate __pred)
{
- __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred),
- __cont.end());
+ _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __c = __cont;
+ __c.erase(std::remove_if(__c.begin(), __c.end(), __pred), __c.end());
}
template<typename _Tp, typename _Alloc, typename _Up>
inline void
erase(deque<_Tp, _Alloc>& __cont, const _Up& __value)
{
- __cont.erase(std::remove(__cont.begin(), __cont.end(), __value),
- __cont.end());
+ _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __c = __cont;
+ __c.erase(std::remove(__c.begin(), __c.end(), __value), __c.end());
}
namespace pmr {
diff --git a/libstdc++-v3/include/experimental/executor b/libstdc++-v3/include/experimental/executor
index 4322a7f..e7a0c6e 100644
--- a/libstdc++-v3/include/experimental/executor
+++ b/libstdc++-v3/include/experimental/executor
@@ -389,7 +389,7 @@ inline namespace v1
= typename __result_type::completion_handler_type;
private:
- using __handler_type = conditional_t<
+ using __handler_type = __conditional_t<
is_same<_CompletionToken, completion_handler_type>::value,
completion_handler_type&,
completion_handler_type>;
diff --git a/libstdc++-v3/include/experimental/functional b/libstdc++-v3/include/experimental/functional
index 0a2b938..8be2fab 100644
--- a/libstdc++-v3/include/experimental/functional
+++ b/libstdc++-v3/include/experimental/functional
@@ -164,9 +164,9 @@ inline namespace fundamentals_v1
typename _Val = typename iterator_traits<_RAIter>::value_type,
typename _Diff = typename iterator_traits<_RAIter>::difference_type>
using __boyer_moore_base_t
- = std::conditional_t<std::__is_byte_like<_Val, _Pred>::value,
- __boyer_moore_array_base<_Diff, 256, _Pred>,
- __boyer_moore_map_base<_Val, _Diff, _Hash, _Pred>>;
+ = std::__conditional_t<std::__is_byte_like<_Val, _Pred>::value,
+ __boyer_moore_array_base<_Diff, 256, _Pred>,
+ __boyer_moore_map_base<_Val, _Diff, _Hash, _Pred>>;
template<typename _RAIter, typename _Hash
= std::hash<typename std::iterator_traits<_RAIter>::value_type>,
diff --git a/libstdc++-v3/include/experimental/io_context b/libstdc++-v3/include/experimental/io_context
index 63d7db5..f0e2e32 100644
--- a/libstdc++-v3/include/experimental/io_context
+++ b/libstdc++-v3/include/experimental/io_context
@@ -35,7 +35,6 @@
#if __cplusplus >= 201402L
#include <atomic>
-#include <chrono>
#include <forward_list>
#include <functional>
#include <system_error>
@@ -43,6 +42,7 @@
#include <vector>
#include <experimental/netfwd>
#include <experimental/executor>
+#include <bits/chrono.h>
#if _GLIBCXX_HAVE_UNISTD_H
# include <unistd.h>
#endif
diff --git a/libstdc++-v3/include/experimental/map b/libstdc++-v3/include/experimental/map
index 0c0f422..ef69fad 100644
--- a/libstdc++-v3/include/experimental/map
+++ b/libstdc++-v3/include/experimental/map
@@ -50,13 +50,19 @@ inline namespace fundamentals_v2
typename _Predicate>
inline void
erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& __c = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Tp, typename _Compare, typename _Alloc,
typename _Predicate>
inline void
erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& __c = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
namespace pmr {
template<typename _Key, typename _Tp, typename _Compare = less<_Key>>
diff --git a/libstdc++-v3/include/experimental/netfwd b/libstdc++-v3/include/experimental/netfwd
index b331598..31b938c 100644
--- a/libstdc++-v3/include/experimental/netfwd
+++ b/libstdc++-v3/include/experimental/netfwd
@@ -37,7 +37,7 @@
// #define __cpp_lib_experimental_net 201803
// #define __cpp_lib_experimental_net_extensible 201803
-#include <chrono>
+#include <bits/chrono.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/experimental/set b/libstdc++-v3/include/experimental/set
index c3f5433..7a5986a 100644
--- a/libstdc++-v3/include/experimental/set
+++ b/libstdc++-v3/include/experimental/set
@@ -50,13 +50,19 @@ inline namespace fundamentals_v2
typename _Predicate>
inline void
erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __c = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Compare, typename _Alloc,
typename _Predicate>
inline void
erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __c = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
namespace pmr {
template<typename _Key, typename _Compare = less<_Key>>
diff --git a/libstdc++-v3/include/experimental/timer b/libstdc++-v3/include/experimental/timer
index e28efa3f..d947a58 100644
--- a/libstdc++-v3/include/experimental/timer
+++ b/libstdc++-v3/include/experimental/timer
@@ -34,7 +34,7 @@
#if __cplusplus >= 201402L
-#include <chrono>
+#include <bits/chrono.h>
#include <system_error>
#include <thread>
#include <experimental/netfwd>
diff --git a/libstdc++-v3/include/experimental/unordered_map b/libstdc++-v3/include/experimental/unordered_map
index 0b915ab..eba9897 100644
--- a/libstdc++-v3/include/experimental/unordered_map
+++ b/libstdc++-v3/include/experimental/unordered_map
@@ -51,14 +51,22 @@ inline namespace fundamentals_v2
inline void
erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __c
+ = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Tp, typename _Hash, typename _CPred,
typename _Alloc, typename _Predicate>
inline void
erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __c
+ = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
namespace pmr {
template<typename _Key, typename _Tp, typename _Hash = hash<_Key>,
diff --git a/libstdc++-v3/include/experimental/unordered_set b/libstdc++-v3/include/experimental/unordered_set
index 87db446..bc5cc11 100644
--- a/libstdc++-v3/include/experimental/unordered_set
+++ b/libstdc++-v3/include/experimental/unordered_set
@@ -51,14 +51,21 @@ inline namespace fundamentals_v2
inline void
erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>& __c = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Hash, typename _CPred, typename _Alloc,
typename _Predicate>
inline void
erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __c
+ = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
namespace pmr {
template<typename _Key, typename _Hash = hash<_Key>,
diff --git a/libstdc++-v3/include/experimental/vector b/libstdc++-v3/include/experimental/vector
index a14aedf..c45a500 100644
--- a/libstdc++-v3/include/experimental/vector
+++ b/libstdc++-v3/include/experimental/vector
@@ -52,16 +52,16 @@ inline namespace fundamentals_v2
inline void
erase_if(vector<_Tp, _Alloc>& __cont, _Predicate __pred)
{
- __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred),
- __cont.end());
+ _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __c = __cont;
+ __c.erase(std::remove_if(__c.begin(), __c.end(), __pred), __c.end());
}
template<typename _Tp, typename _Alloc, typename _Up>
inline void
erase(vector<_Tp, _Alloc>& __cont, const _Up& __value)
{
- __cont.erase(std::remove(__cont.begin(), __cont.end(), __value),
- __cont.end());
+ _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __c = __cont;
+ __c.erase(std::remove(__c.begin(), __c.end(), __value), __c.end());
}
namespace pmr {
diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any
index 1fce957..e3d9d77 100644
--- a/libstdc++-v3/include/std/any
+++ b/libstdc++-v3/include/std/any
@@ -102,9 +102,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct _Manager_external; // creates contained object on the heap
template<typename _Tp>
- using _Manager = conditional_t<_Internal<_Tp>::value,
- _Manager_internal<_Tp>,
- _Manager_external<_Tp>>;
+ using _Manager = __conditional_t<_Internal<_Tp>::value,
+ _Manager_internal<_Tp>,
+ _Manager_external<_Tp>>;
template<typename _Tp, typename _VTp = decay_t<_Tp>>
using _Decay_if_not_any = enable_if_t<!is_same_v<_VTp, any>, _VTp>;
@@ -183,8 +183,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Construct with a copy of @p __value as the contained object.
template <typename _Tp, typename _VTp = _Decay_if_not_any<_Tp>,
typename _Mgr = _Manager<_VTp>,
- enable_if_t<is_copy_constructible<_VTp>::value
- && !__is_in_place_type<_VTp>::value, bool> = true>
+ typename = _Require<__not_<__is_in_place_type<_VTp>>,
+ is_copy_constructible<_VTp>>>
any(_Tp&& __value)
: _M_manager(&_Mgr::_S_manage)
{
diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
index a329054..c8060d7 100644
--- a/libstdc++-v3/include/std/chrono
+++ b/libstdc++-v3/include/std/chrono
@@ -36,24 +36,12 @@
# include <bits/c++0x_warning.h>
#else
-#include <ratio>
-#include <type_traits>
-#include <limits>
-#include <ctime>
-#include <bits/parse_numbers.h> // for literals support.
-#if __cplusplus > 201703L
-# include <concepts>
-# include <compare>
-#endif
+#include <bits/chrono.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
-#if __cplusplus >= 201703L
- namespace filesystem { struct __file_clock; };
-#endif
-
/**
* @defgroup chrono Time
* @ingroup utilities
@@ -69,1144 +57,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
namespace chrono
{
+#if __cplusplus >= 202002L
/// @addtogroup chrono
/// @{
-
- /// `chrono::duration` represents a distance between two points in time
- template<typename _Rep, typename _Period = ratio<1>>
- struct duration;
-
- /// `chrono::time_point` represents a point in time as measured by a clock
- template<typename _Clock, typename _Dur = typename _Clock::duration>
- struct time_point;
- /// @}
- }
-
- /// @addtogroup chrono
- /// @{
-
- // 20.11.4.3 specialization of common_type (for duration, sfinae-friendly)
-
- /// @cond undocumented
-
- template<typename _CT, typename _Period1, typename _Period2, typename = void>
- struct __duration_common_type
- { };
-
- template<typename _CT, typename _Period1, typename _Period2>
- struct __duration_common_type<_CT, _Period1, _Period2,
- __void_t<typename _CT::type>>
- {
- private:
- using __gcd_num = __static_gcd<_Period1::num, _Period2::num>;
- using __gcd_den = __static_gcd<_Period1::den, _Period2::den>;
- using __cr = typename _CT::type;
- using __r = ratio<__gcd_num::value,
- (_Period1::den / __gcd_den::value) * _Period2::den>;
-
- public:
- using type = chrono::duration<__cr, typename __r::type>;
- };
-
- /// @endcond
-
- /// @{
- /// @relates chrono::duration
-
- /// Specialization of common_type for chrono::duration types.
- template<typename _Rep1, typename _Period1, typename _Rep2, typename _Period2>
- struct common_type<chrono::duration<_Rep1, _Period1>,
- chrono::duration<_Rep2, _Period2>>
- : __duration_common_type<common_type<_Rep1, _Rep2>,
- typename _Period1::type,
- typename _Period2::type>
- { };
-
- /// Specialization of common_type for two identical chrono::duration types.
- template<typename _Rep, typename _Period>
- struct common_type<chrono::duration<_Rep, _Period>,
- chrono::duration<_Rep, _Period>>
- {
- using type = chrono::duration<typename common_type<_Rep>::type,
- typename _Period::type>;
- };
-
- /// Specialization of common_type for one chrono::duration type.
- template<typename _Rep, typename _Period>
- struct common_type<chrono::duration<_Rep, _Period>>
- {
- using type = chrono::duration<typename common_type<_Rep>::type,
- typename _Period::type>;
- };
- /// @}
-
- // 20.11.4.3 specialization of common_type (for time_point, sfinae-friendly)
-
- /// @cond undocumented
-
- template<typename _CT, typename _Clock, typename = void>
- struct __timepoint_common_type
- { };
-
- template<typename _CT, typename _Clock>
- struct __timepoint_common_type<_CT, _Clock, __void_t<typename _CT::type>>
- {
- using type = chrono::time_point<_Clock, typename _CT::type>;
- };
-
- /// @endcond
-
- /// @{
- /// @relates chrono::time_point
-
- /// Specialization of common_type for chrono::time_point types.
- template<typename _Clock, typename _Duration1, typename _Duration2>
- struct common_type<chrono::time_point<_Clock, _Duration1>,
- chrono::time_point<_Clock, _Duration2>>
- : __timepoint_common_type<common_type<_Duration1, _Duration2>, _Clock>
- { };
-
- /// Specialization of common_type for two identical chrono::time_point types.
- template<typename _Clock, typename _Duration>
- struct common_type<chrono::time_point<_Clock, _Duration>,
- chrono::time_point<_Clock, _Duration>>
- { using type = chrono::time_point<_Clock, _Duration>; };
-
- /// Specialization of common_type for one chrono::time_point type.
- template<typename _Clock, typename _Duration>
- struct common_type<chrono::time_point<_Clock, _Duration>>
- { using type = chrono::time_point<_Clock, _Duration>; };
- /// @}
-
- /// @} group chrono
-
- namespace chrono
- {
- /// @addtogroup chrono
- /// @{
-
- /// @cond undocumented
-
- // Primary template for duration_cast impl.
- template<typename _ToDur, typename _CF, typename _CR,
- bool _NumIsOne = false, bool _DenIsOne = false>
- struct __duration_cast_impl
- {
- template<typename _Rep, typename _Period>
- static constexpr _ToDur
- __cast(const duration<_Rep, _Period>& __d)
- {
- typedef typename _ToDur::rep __to_rep;
- return _ToDur(static_cast<__to_rep>(static_cast<_CR>(__d.count())
- * static_cast<_CR>(_CF::num)
- / static_cast<_CR>(_CF::den)));
- }
- };
-
- template<typename _ToDur, typename _CF, typename _CR>
- struct __duration_cast_impl<_ToDur, _CF, _CR, true, true>
- {
- template<typename _Rep, typename _Period>
- static constexpr _ToDur
- __cast(const duration<_Rep, _Period>& __d)
- {
- typedef typename _ToDur::rep __to_rep;
- return _ToDur(static_cast<__to_rep>(__d.count()));
- }
- };
-
- template<typename _ToDur, typename _CF, typename _CR>
- struct __duration_cast_impl<_ToDur, _CF, _CR, true, false>
- {
- template<typename _Rep, typename _Period>
- static constexpr _ToDur
- __cast(const duration<_Rep, _Period>& __d)
- {
- typedef typename _ToDur::rep __to_rep;
- return _ToDur(static_cast<__to_rep>(
- static_cast<_CR>(__d.count()) / static_cast<_CR>(_CF::den)));
- }
- };
-
- template<typename _ToDur, typename _CF, typename _CR>
- struct __duration_cast_impl<_ToDur, _CF, _CR, false, true>
- {
- template<typename _Rep, typename _Period>
- static constexpr _ToDur
- __cast(const duration<_Rep, _Period>& __d)
- {
- typedef typename _ToDur::rep __to_rep;
- return _ToDur(static_cast<__to_rep>(
- static_cast<_CR>(__d.count()) * static_cast<_CR>(_CF::num)));
- }
- };
-
- template<typename _Tp>
- struct __is_duration
- : std::false_type
- { };
-
- template<typename _Rep, typename _Period>
- struct __is_duration<duration<_Rep, _Period>>
- : std::true_type
- { };
-
- template<typename _Tp>
- using __enable_if_is_duration
- = typename enable_if<__is_duration<_Tp>::value, _Tp>::type;
-
- template<typename _Tp>
- using __disable_if_is_duration
- = typename enable_if<!__is_duration<_Tp>::value, _Tp>::type;
-
- /// @endcond
-
- /// duration_cast
- template<typename _ToDur, typename _Rep, typename _Period>
- constexpr __enable_if_is_duration<_ToDur>
- duration_cast(const duration<_Rep, _Period>& __d)
- {
- typedef typename _ToDur::period __to_period;
- typedef typename _ToDur::rep __to_rep;
- typedef ratio_divide<_Period, __to_period> __cf;
- typedef typename common_type<__to_rep, _Rep, intmax_t>::type
- __cr;
- typedef __duration_cast_impl<_ToDur, __cf, __cr,
- __cf::num == 1, __cf::den == 1> __dc;
- return __dc::__cast(__d);
- }
-
- /// treat_as_floating_point
- template<typename _Rep>
- struct treat_as_floating_point
- : is_floating_point<_Rep>
- { };
-
-#if __cplusplus > 201402L
- template <typename _Rep>
- inline constexpr bool treat_as_floating_point_v =
- treat_as_floating_point<_Rep>::value;
-#endif // C++17
-
-#if __cplusplus > 201703L
- template<typename _Tp>
- struct is_clock;
-
- template<typename _Tp>
- inline constexpr bool is_clock_v = is_clock<_Tp>::value;
-
-#if __cpp_lib_concepts
- template<typename _Tp>
- struct is_clock : false_type
- { };
-
- template<typename _Tp>
- requires requires {
- typename _Tp::rep;
- typename _Tp::period;
- typename _Tp::duration;
- typename _Tp::time_point::clock;
- typename _Tp::time_point::duration;
- { &_Tp::is_steady } -> same_as<const bool*>;
- { _Tp::now() } -> same_as<typename _Tp::time_point>;
- requires same_as<typename _Tp::duration,
- duration<typename _Tp::rep, typename _Tp::period>>;
- requires same_as<typename _Tp::time_point::duration,
- typename _Tp::duration>;
- }
- struct is_clock<_Tp> : true_type
- { };
-#else
- template<typename _Tp, typename = void>
- struct __is_clock_impl : false_type
- { };
-
- template<typename _Tp>
- struct __is_clock_impl<_Tp,
- void_t<typename _Tp::rep, typename _Tp::period,
- typename _Tp::duration,
- typename _Tp::time_point::duration,
- decltype(_Tp::is_steady),
- decltype(_Tp::now())>>
- : __and_<is_same<typename _Tp::duration,
- duration<typename _Tp::rep, typename _Tp::period>>,
- is_same<typename _Tp::time_point::duration,
- typename _Tp::duration>,
- is_same<decltype(&_Tp::is_steady), const bool*>,
- is_same<decltype(_Tp::now()), typename _Tp::time_point>>::type
- { };
-
- template<typename _Tp>
- struct is_clock : __is_clock_impl<_Tp>::type
- { };
-#endif
-#endif // C++20
-
-#if __cplusplus >= 201703L
-# define __cpp_lib_chrono 201611
-
- template<typename _ToDur, typename _Rep, typename _Period>
- constexpr __enable_if_is_duration<_ToDur>
- floor(const duration<_Rep, _Period>& __d)
- {
- auto __to = chrono::duration_cast<_ToDur>(__d);
- if (__to > __d)
- return __to - _ToDur{1};
- return __to;
- }
-
- template<typename _ToDur, typename _Rep, typename _Period>
- constexpr __enable_if_is_duration<_ToDur>
- ceil(const duration<_Rep, _Period>& __d)
- {
- auto __to = chrono::duration_cast<_ToDur>(__d);
- if (__to < __d)
- return __to + _ToDur{1};
- return __to;
- }
-
- template <typename _ToDur, typename _Rep, typename _Period>
- constexpr enable_if_t<
- __and_<__is_duration<_ToDur>,
- __not_<treat_as_floating_point<typename _ToDur::rep>>>::value,
- _ToDur>
- round(const duration<_Rep, _Period>& __d)
- {
- _ToDur __t0 = chrono::floor<_ToDur>(__d);
- _ToDur __t1 = __t0 + _ToDur{1};
- auto __diff0 = __d - __t0;
- auto __diff1 = __t1 - __d;
- if (__diff0 == __diff1)
- {
- if (__t0.count() & 1)
- return __t1;
- return __t0;
- }
- else if (__diff0 < __diff1)
- return __t0;
- return __t1;
- }
-
- template<typename _Rep, typename _Period>
- constexpr
- enable_if_t<numeric_limits<_Rep>::is_signed, duration<_Rep, _Period>>
- abs(duration<_Rep, _Period> __d)
- {
- if (__d >= __d.zero())
- return __d;
- return -__d;
- }
-
- // Make chrono::ceil<D> also usable as chrono::__detail::ceil<D>.
- namespace __detail { using chrono::ceil; }
-
-#else // ! C++17
-
- // We want to use ceil even when compiling for earlier standards versions.
- // C++11 only allows a single statement in a constexpr function, so we
- // need to move the comparison into a separate function, __ceil_impl.
- namespace __detail
- {
- template<typename _Tp, typename _Up>
- constexpr _Tp
- __ceil_impl(const _Tp& __t, const _Up& __u)
- {
- return (__t < __u) ? (__t + _Tp{1}) : __t;
- }
-
- // C++11-friendly version of std::chrono::ceil<D> for internal use.
- template<typename _ToDur, typename _Rep, typename _Period>
- constexpr _ToDur
- ceil(const duration<_Rep, _Period>& __d)
- {
- return __detail::__ceil_impl(chrono::duration_cast<_ToDur>(__d), __d);
- }
- }
-#endif // C++17
-
- /// duration_values
- template<typename _Rep>
- struct duration_values
- {
- static constexpr _Rep
- zero() noexcept
- { return _Rep(0); }
-
- static constexpr _Rep
- max() noexcept
- { return numeric_limits<_Rep>::max(); }
-
- static constexpr _Rep
- min() noexcept
- { return numeric_limits<_Rep>::lowest(); }
- };
-
- /// @cond undocumented
-
- template<typename _Tp>
- struct __is_ratio
- : std::false_type
- { };
-
- template<intmax_t _Num, intmax_t _Den>
- struct __is_ratio<ratio<_Num, _Den>>
- : std::true_type
- { };
-
- /// @endcond
-
- template<typename _Rep, typename _Period>
- struct duration
- {
- private:
- template<typename _Rep2>
- using __is_float = treat_as_floating_point<_Rep2>;
-
- static constexpr intmax_t
- _S_gcd(intmax_t __m, intmax_t __n) noexcept
- {
- // Duration only allows positive periods so we don't need to
- // handle negative values here (unlike __static_gcd and std::gcd).
-#if __cplusplus >= 201402L
- do
- {
- intmax_t __rem = __m % __n;
- __m = __n;
- __n = __rem;
- }
- while (__n != 0);
- return __m;
-#else
- // C++11 doesn't allow loops in constexpr functions, but this
- // recursive version can be more expensive to evaluate.
- return (__n == 0) ? __m : _S_gcd(__n, __m % __n);
-#endif
- }
-
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 2094. overflow shouldn't participate in overload resolution
- // 3090. What is [2094] intended to mean?
- // This only produces a valid type if no overflow occurs.
- template<typename _R1, typename _R2,
- intmax_t __gcd1 = _S_gcd(_R1::num, _R2::num),
- intmax_t __gcd2 = _S_gcd(_R1::den, _R2::den)>
- using __divide = ratio<(_R1::num / __gcd1) * (_R2::den / __gcd2),
- (_R1::den / __gcd2) * (_R2::num / __gcd1)>;
-
- // _Period2 is an exact multiple of _Period
- template<typename _Period2>
- using __is_harmonic
- = __bool_constant<__divide<_Period2, _Period>::den == 1>;
-
- public:
-
- using rep = _Rep;
- using period = typename _Period::type;
-
- static_assert(!__is_duration<_Rep>::value, "rep cannot be a duration");
- static_assert(__is_ratio<_Period>::value,
- "period must be a specialization of ratio");
- static_assert(_Period::num > 0, "period must be positive");
-
- // 20.11.5.1 construction / copy / destroy
- constexpr duration() = default;
-
- duration(const duration&) = default;
-
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 3050. Conversion specification problem in chrono::duration
- template<typename _Rep2, typename = _Require<
- is_convertible<const _Rep2&, rep>,
- __or_<__is_float<rep>, __not_<__is_float<_Rep2>>>>>
- constexpr explicit duration(const _Rep2& __rep)
- : __r(static_cast<rep>(__rep)) { }
-
- template<typename _Rep2, typename _Period2, typename = _Require<
- is_convertible<const _Rep2&, rep>,
- __or_<__is_float<rep>,
- __and_<__is_harmonic<_Period2>,
- __not_<__is_float<_Rep2>>>>>>
- constexpr duration(const duration<_Rep2, _Period2>& __d)
- : __r(duration_cast<duration>(__d).count()) { }
-
- ~duration() = default;
- duration& operator=(const duration&) = default;
-
- // 20.11.5.2 observer
- constexpr rep
- count() const
- { return __r; }
-
- // 20.11.5.3 arithmetic
-
- constexpr duration<typename common_type<rep>::type, period>
- operator+() const
- { return duration<typename common_type<rep>::type, period>(__r); }
-
- constexpr duration<typename common_type<rep>::type, period>
- operator-() const
- { return duration<typename common_type<rep>::type, period>(-__r); }
-
- _GLIBCXX17_CONSTEXPR duration&
- operator++()
- {
- ++__r;
- return *this;
- }
-
- _GLIBCXX17_CONSTEXPR duration
- operator++(int)
- { return duration(__r++); }
-
- _GLIBCXX17_CONSTEXPR duration&
- operator--()
- {
- --__r;
- return *this;
- }
-
- _GLIBCXX17_CONSTEXPR duration
- operator--(int)
- { return duration(__r--); }
-
- _GLIBCXX17_CONSTEXPR duration&
- operator+=(const duration& __d)
- {
- __r += __d.count();
- return *this;
- }
-
- _GLIBCXX17_CONSTEXPR duration&
- operator-=(const duration& __d)
- {
- __r -= __d.count();
- return *this;
- }
-
- _GLIBCXX17_CONSTEXPR duration&
- operator*=(const rep& __rhs)
- {
- __r *= __rhs;
- return *this;
- }
-
- _GLIBCXX17_CONSTEXPR duration&
- operator/=(const rep& __rhs)
- {
- __r /= __rhs;
- return *this;
- }
-
- // DR 934.
- template<typename _Rep2 = rep>
- _GLIBCXX17_CONSTEXPR
- typename enable_if<!treat_as_floating_point<_Rep2>::value,
- duration&>::type
- operator%=(const rep& __rhs)
- {
- __r %= __rhs;
- return *this;
- }
-
- template<typename _Rep2 = rep>
- _GLIBCXX17_CONSTEXPR
- typename enable_if<!treat_as_floating_point<_Rep2>::value,
- duration&>::type
- operator%=(const duration& __d)
- {
- __r %= __d.count();
- return *this;
- }
-
- // 20.11.5.4 special values
- static constexpr duration
- zero() noexcept
- { return duration(duration_values<rep>::zero()); }
-
- static constexpr duration
- min() noexcept
- { return duration(duration_values<rep>::min()); }
-
- static constexpr duration
- max() noexcept
- { return duration(duration_values<rep>::max()); }
-
- private:
- rep __r;
- };
-
- /// @{
- /// @relates std::chrono::duration
-
- /// The sum of two durations.
- template<typename _Rep1, typename _Period1,
- typename _Rep2, typename _Period2>
- constexpr typename common_type<duration<_Rep1, _Period1>,
- duration<_Rep2, _Period2>>::type
- operator+(const duration<_Rep1, _Period1>& __lhs,
- const duration<_Rep2, _Period2>& __rhs)
- {
- typedef duration<_Rep1, _Period1> __dur1;
- typedef duration<_Rep2, _Period2> __dur2;
- typedef typename common_type<__dur1,__dur2>::type __cd;
- return __cd(__cd(__lhs).count() + __cd(__rhs).count());
- }
-
- /// The difference between two durations.
- template<typename _Rep1, typename _Period1,
- typename _Rep2, typename _Period2>
- constexpr typename common_type<duration<_Rep1, _Period1>,
- duration<_Rep2, _Period2>>::type
- operator-(const duration<_Rep1, _Period1>& __lhs,
- const duration<_Rep2, _Period2>& __rhs)
- {
- typedef duration<_Rep1, _Period1> __dur1;
- typedef duration<_Rep2, _Period2> __dur2;
- typedef typename common_type<__dur1,__dur2>::type __cd;
- return __cd(__cd(__lhs).count() - __cd(__rhs).count());
- }
-
- /// @}
-
- /// @cond undocumented
-
- // SFINAE helper to obtain common_type<_Rep1, _Rep2> only if _Rep2
- // is implicitly convertible to it.
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 3050. Conversion specification problem in chrono::duration constructor
- template<typename _Rep1, typename _Rep2,
- typename _CRep = typename common_type<_Rep1, _Rep2>::type>
- using __common_rep_t = typename
- enable_if<is_convertible<const _Rep2&, _CRep>::value, _CRep>::type;
-
- /// @endcond
-
- /** @{
- * Arithmetic operators for chrono::duration
- * @relates std::chrono::duration
- */
-
- template<typename _Rep1, typename _Period, typename _Rep2>
- constexpr duration<__common_rep_t<_Rep1, _Rep2>, _Period>
- operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
- {
- typedef duration<typename common_type<_Rep1, _Rep2>::type, _Period>
- __cd;
- return __cd(__cd(__d).count() * __s);
- }
-
- template<typename _Rep1, typename _Rep2, typename _Period>
- constexpr duration<__common_rep_t<_Rep2, _Rep1>, _Period>
- operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d)
- { return __d * __s; }
-
- template<typename _Rep1, typename _Period, typename _Rep2>
- constexpr
- duration<__common_rep_t<_Rep1, __disable_if_is_duration<_Rep2>>, _Period>
- operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
- {
- typedef duration<typename common_type<_Rep1, _Rep2>::type, _Period>
- __cd;
- return __cd(__cd(__d).count() / __s);
- }
-
- template<typename _Rep1, typename _Period1,
- typename _Rep2, typename _Period2>
- constexpr typename common_type<_Rep1, _Rep2>::type
- operator/(const duration<_Rep1, _Period1>& __lhs,
- const duration<_Rep2, _Period2>& __rhs)
- {
- typedef duration<_Rep1, _Period1> __dur1;
- typedef duration<_Rep2, _Period2> __dur2;
- typedef typename common_type<__dur1,__dur2>::type __cd;
- return __cd(__lhs).count() / __cd(__rhs).count();
- }
-
- // DR 934.
- template<typename _Rep1, typename _Period, typename _Rep2>
- constexpr
- duration<__common_rep_t<_Rep1, __disable_if_is_duration<_Rep2>>, _Period>
- operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
- {
- typedef duration<typename common_type<_Rep1, _Rep2>::type, _Period>
- __cd;
- return __cd(__cd(__d).count() % __s);
- }
-
- template<typename _Rep1, typename _Period1,
- typename _Rep2, typename _Period2>
- constexpr typename common_type<duration<_Rep1, _Period1>,
- duration<_Rep2, _Period2>>::type
- operator%(const duration<_Rep1, _Period1>& __lhs,
- const duration<_Rep2, _Period2>& __rhs)
- {
- typedef duration<_Rep1, _Period1> __dur1;
- typedef duration<_Rep2, _Period2> __dur2;
- typedef typename common_type<__dur1,__dur2>::type __cd;
- return __cd(__cd(__lhs).count() % __cd(__rhs).count());
- }
- /// @}
-
- // comparisons
-
- /** @{
- * Comparisons for chrono::duration
- * @relates std::chrono::duration
- */
-
- template<typename _Rep1, typename _Period1,
- typename _Rep2, typename _Period2>
- constexpr bool
- operator==(const duration<_Rep1, _Period1>& __lhs,
- const duration<_Rep2, _Period2>& __rhs)
- {
- typedef duration<_Rep1, _Period1> __dur1;
- typedef duration<_Rep2, _Period2> __dur2;
- typedef typename common_type<__dur1,__dur2>::type __ct;
- return __ct(__lhs).count() == __ct(__rhs).count();
- }
-
- template<typename _Rep1, typename _Period1,
- typename _Rep2, typename _Period2>
- constexpr bool
- operator<(const duration<_Rep1, _Period1>& __lhs,
- const duration<_Rep2, _Period2>& __rhs)
- {
- typedef duration<_Rep1, _Period1> __dur1;
- typedef duration<_Rep2, _Period2> __dur2;
- typedef typename common_type<__dur1,__dur2>::type __ct;
- return __ct(__lhs).count() < __ct(__rhs).count();
- }
-
-#if __cpp_lib_three_way_comparison
- template<typename _Rep1, typename _Period1,
- typename _Rep2, typename _Period2>
- requires three_way_comparable<common_type_t<_Rep1, _Rep2>>
- constexpr auto
- operator<=>(const duration<_Rep1, _Period1>& __lhs,
- const duration<_Rep2, _Period2>& __rhs)
- {
- using __ct = common_type_t<duration<_Rep1, _Period1>,
- duration<_Rep2, _Period2>>;
- return __ct(__lhs).count() <=> __ct(__rhs).count();
- }
-#else
- template<typename _Rep1, typename _Period1,
- typename _Rep2, typename _Period2>
- constexpr bool
- operator!=(const duration<_Rep1, _Period1>& __lhs,
- const duration<_Rep2, _Period2>& __rhs)
- { return !(__lhs == __rhs); }
-#endif
-
- template<typename _Rep1, typename _Period1,
- typename _Rep2, typename _Period2>
- constexpr bool
- operator<=(const duration<_Rep1, _Period1>& __lhs,
- const duration<_Rep2, _Period2>& __rhs)
- { return !(__rhs < __lhs); }
-
- template<typename _Rep1, typename _Period1,
- typename _Rep2, typename _Period2>
- constexpr bool
- operator>(const duration<_Rep1, _Period1>& __lhs,
- const duration<_Rep2, _Period2>& __rhs)
- { return __rhs < __lhs; }
-
- template<typename _Rep1, typename _Period1,
- typename _Rep2, typename _Period2>
- constexpr bool
- operator>=(const duration<_Rep1, _Period1>& __lhs,
- const duration<_Rep2, _Period2>& __rhs)
- { return !(__lhs < __rhs); }
-
- /// @}
-
- /// @cond undocumented
-#ifdef _GLIBCXX_USE_C99_STDINT_TR1
-# define _GLIBCXX_CHRONO_INT64_T int64_t
-#elif defined __INT64_TYPE__
-# define _GLIBCXX_CHRONO_INT64_T __INT64_TYPE__
-#else
- static_assert(std::numeric_limits<unsigned long long>::digits >= 64,
- "Representation type for nanoseconds must have at least 64 bits");
-# define _GLIBCXX_CHRONO_INT64_T long long
-#endif
- /// @endcond
-
- /// nanoseconds
- using nanoseconds = duration<_GLIBCXX_CHRONO_INT64_T, nano>;
-
- /// microseconds
- using microseconds = duration<_GLIBCXX_CHRONO_INT64_T, micro>;
-
- /// milliseconds
- using milliseconds = duration<_GLIBCXX_CHRONO_INT64_T, milli>;
-
- /// seconds
- using seconds = duration<_GLIBCXX_CHRONO_INT64_T>;
-
- /// minutes
- using minutes = duration<_GLIBCXX_CHRONO_INT64_T, ratio< 60>>;
-
- /// hours
- using hours = duration<_GLIBCXX_CHRONO_INT64_T, ratio<3600>>;
-
-#if __cplusplus > 201703L
- /// days
- using days = duration<_GLIBCXX_CHRONO_INT64_T, ratio<86400>>;
-
- /// weeks
- using weeks = duration<_GLIBCXX_CHRONO_INT64_T, ratio<604800>>;
-
- /// years
- using years = duration<_GLIBCXX_CHRONO_INT64_T, ratio<31556952>>;
-
- /// months
- using months = duration<_GLIBCXX_CHRONO_INT64_T, ratio<2629746>>;
-#endif // C++20
-
-#undef _GLIBCXX_CHRONO_INT64_T
-
- template<typename _Clock, typename _Dur>
- struct time_point
- {
- static_assert(__is_duration<_Dur>::value,
- "duration must be a specialization of std::chrono::duration");
-
- typedef _Clock clock;
- typedef _Dur duration;
- typedef typename duration::rep rep;
- typedef typename duration::period period;
-
- constexpr time_point() : __d(duration::zero())
- { }
-
- constexpr explicit time_point(const duration& __dur)
- : __d(__dur)
- { }
-
- // conversions
- template<typename _Dur2,
- typename = _Require<is_convertible<_Dur2, _Dur>>>
- constexpr time_point(const time_point<clock, _Dur2>& __t)
- : __d(__t.time_since_epoch())
- { }
-
- // observer
- constexpr duration
- time_since_epoch() const
- { return __d; }
-
-#if __cplusplus > 201703L
- constexpr time_point&
- operator++()
- {
- ++__d;
- return *this;
- }
-
- constexpr time_point
- operator++(int)
- { return time_point{__d++}; }
-
- constexpr time_point&
- operator--()
- {
- --__d;
- return *this;
- }
-
- constexpr time_point
- operator--(int)
- { return time_point{__d--}; }
-#endif
-
- // arithmetic
- _GLIBCXX17_CONSTEXPR time_point&
- operator+=(const duration& __dur)
- {
- __d += __dur;
- return *this;
- }
-
- _GLIBCXX17_CONSTEXPR time_point&
- operator-=(const duration& __dur)
- {
- __d -= __dur;
- return *this;
- }
-
- // special values
- static constexpr time_point
- min() noexcept
- { return time_point(duration::min()); }
-
- static constexpr time_point
- max() noexcept
- { return time_point(duration::max()); }
-
- private:
- duration __d;
- };
-
- /// time_point_cast
- template<typename _ToDur, typename _Clock, typename _Dur>
- constexpr typename enable_if<__is_duration<_ToDur>::value,
- time_point<_Clock, _ToDur>>::type
- time_point_cast(const time_point<_Clock, _Dur>& __t)
- {
- typedef time_point<_Clock, _ToDur> __time_point;
- return __time_point(duration_cast<_ToDur>(__t.time_since_epoch()));
- }
-
-#if __cplusplus > 201402L
- template<typename _ToDur, typename _Clock, typename _Dur>
- constexpr
- enable_if_t<__is_duration<_ToDur>::value, time_point<_Clock, _ToDur>>
- floor(const time_point<_Clock, _Dur>& __tp)
- {
- return time_point<_Clock, _ToDur>{
- chrono::floor<_ToDur>(__tp.time_since_epoch())};
- }
-
- template<typename _ToDur, typename _Clock, typename _Dur>
- constexpr
- enable_if_t<__is_duration<_ToDur>::value, time_point<_Clock, _ToDur>>
- ceil(const time_point<_Clock, _Dur>& __tp)
- {
- return time_point<_Clock, _ToDur>{
- chrono::ceil<_ToDur>(__tp.time_since_epoch())};
- }
-
- template<typename _ToDur, typename _Clock, typename _Dur>
- constexpr enable_if_t<
- __and_<__is_duration<_ToDur>,
- __not_<treat_as_floating_point<typename _ToDur::rep>>>::value,
- time_point<_Clock, _ToDur>>
- round(const time_point<_Clock, _Dur>& __tp)
- {
- return time_point<_Clock, _ToDur>{
- chrono::round<_ToDur>(__tp.time_since_epoch())};
- }
-#endif // C++17
-
- /// @{
- /// @relates time_point
-
- /// Adjust a time point forwards by the given duration.
- template<typename _Clock, typename _Dur1,
- typename _Rep2, typename _Period2>
- constexpr time_point<_Clock,
- typename common_type<_Dur1, duration<_Rep2, _Period2>>::type>
- operator+(const time_point<_Clock, _Dur1>& __lhs,
- const duration<_Rep2, _Period2>& __rhs)
- {
- typedef duration<_Rep2, _Period2> __dur2;
- typedef typename common_type<_Dur1,__dur2>::type __ct;
- typedef time_point<_Clock, __ct> __time_point;
- return __time_point(__lhs.time_since_epoch() + __rhs);
- }
-
- /// Adjust a time point forwards by the given duration.
- template<typename _Rep1, typename _Period1,
- typename _Clock, typename _Dur2>
- constexpr time_point<_Clock,
- typename common_type<duration<_Rep1, _Period1>, _Dur2>::type>
- operator+(const duration<_Rep1, _Period1>& __lhs,
- const time_point<_Clock, _Dur2>& __rhs)
- {
- typedef duration<_Rep1, _Period1> __dur1;
- typedef typename common_type<__dur1,_Dur2>::type __ct;
- typedef time_point<_Clock, __ct> __time_point;
- return __time_point(__rhs.time_since_epoch() + __lhs);
- }
-
- /// Adjust a time point backwards by the given duration.
- template<typename _Clock, typename _Dur1,
- typename _Rep2, typename _Period2>
- constexpr time_point<_Clock,
- typename common_type<_Dur1, duration<_Rep2, _Period2>>::type>
- operator-(const time_point<_Clock, _Dur1>& __lhs,
- const duration<_Rep2, _Period2>& __rhs)
- {
- typedef duration<_Rep2, _Period2> __dur2;
- typedef typename common_type<_Dur1,__dur2>::type __ct;
- typedef time_point<_Clock, __ct> __time_point;
- return __time_point(__lhs.time_since_epoch() -__rhs);
- }
-
- /// The difference between two time points (as a duration)
- template<typename _Clock, typename _Dur1, typename _Dur2>
- constexpr typename common_type<_Dur1, _Dur2>::type
- operator-(const time_point<_Clock, _Dur1>& __lhs,
- const time_point<_Clock, _Dur2>& __rhs)
- { return __lhs.time_since_epoch() - __rhs.time_since_epoch(); }
- /// @}
-
- /** @{
- * Comparisons for time_point
- * @relates chrono::time_point
- */
-
- template<typename _Clock, typename _Dur1, typename _Dur2>
- constexpr bool
- operator==(const time_point<_Clock, _Dur1>& __lhs,
- const time_point<_Clock, _Dur2>& __rhs)
- { return __lhs.time_since_epoch() == __rhs.time_since_epoch(); }
-
-#if __cpp_lib_three_way_comparison
- template<typename _Clock, typename _Dur1,
- three_way_comparable_with<_Dur1> _Dur2>
- constexpr auto
- operator<=>(const time_point<_Clock, _Dur1>& __lhs,
- const time_point<_Clock, _Dur2>& __rhs)
- { return __lhs.time_since_epoch() <=> __rhs.time_since_epoch(); }
-#else
- template<typename _Clock, typename _Dur1, typename _Dur2>
- constexpr bool
- operator!=(const time_point<_Clock, _Dur1>& __lhs,
- const time_point<_Clock, _Dur2>& __rhs)
- { return !(__lhs == __rhs); }
-#endif
-
- template<typename _Clock, typename _Dur1, typename _Dur2>
- constexpr bool
- operator<(const time_point<_Clock, _Dur1>& __lhs,
- const time_point<_Clock, _Dur2>& __rhs)
- { return __lhs.time_since_epoch() < __rhs.time_since_epoch(); }
-
- template<typename _Clock, typename _Dur1, typename _Dur2>
- constexpr bool
- operator<=(const time_point<_Clock, _Dur1>& __lhs,
- const time_point<_Clock, _Dur2>& __rhs)
- { return !(__rhs < __lhs); }
-
- template<typename _Clock, typename _Dur1, typename _Dur2>
- constexpr bool
- operator>(const time_point<_Clock, _Dur1>& __lhs,
- const time_point<_Clock, _Dur2>& __rhs)
- { return __rhs < __lhs; }
-
- template<typename _Clock, typename _Dur1, typename _Dur2>
- constexpr bool
- operator>=(const time_point<_Clock, _Dur1>& __lhs,
- const time_point<_Clock, _Dur2>& __rhs)
- { return !(__lhs < __rhs); }
-
- /// @}
-
- // Clocks.
-
- // Why nanosecond resolution as the default?
- // Why have std::system_clock always count in the highest
- // resolution (ie nanoseconds), even if on some OSes the low 3
- // or 9 decimal digits will be always zero? This allows later
- // implementations to change the system_clock::now()
- // implementation any time to provide better resolution without
- // changing function signature or units.
-
- // To support the (forward) evolution of the library's defined
- // clocks, wrap inside inline namespace so that the current
- // defintions of system_clock, steady_clock, and
- // high_resolution_clock types are uniquely mangled. This way, new
- // code can use the latests clocks, while the library can contain
- // compatibility definitions for previous versions. At some
- // point, when these clocks settle down, the inlined namespaces
- // can be removed. XXX GLIBCXX_ABI Deprecated
- inline namespace _V2 {
-
- /**
- * @brief System clock.
- *
- * Time returned represents wall time from the system-wide clock.
- * @ingroup chrono
- */
- struct system_clock
- {
- typedef chrono::nanoseconds duration;
- typedef duration::rep rep;
- typedef duration::period period;
- typedef chrono::time_point<system_clock, duration> time_point;
-
- static_assert(system_clock::duration::min()
- < system_clock::duration::zero(),
- "a clock's minimum duration cannot be less than its epoch");
-
- static constexpr bool is_steady = false;
-
- static time_point
- now() noexcept;
-
- // Map to C API
- static std::time_t
- to_time_t(const time_point& __t) noexcept
- {
- return std::time_t(duration_cast<chrono::seconds>
- (__t.time_since_epoch()).count());
- }
-
- static time_point
- from_time_t(std::time_t __t) noexcept
- {
- typedef chrono::time_point<system_clock, seconds> __from;
- return time_point_cast<system_clock::duration>
- (__from(chrono::seconds(__t)));
- }
- };
-
-
- /**
- * @brief Monotonic clock
- *
- * Time returned has the property of only increasing at a uniform rate.
- * @ingroup chrono
- */
- struct steady_clock
- {
- typedef chrono::nanoseconds duration;
- typedef duration::rep rep;
- typedef duration::period period;
- typedef chrono::time_point<steady_clock, duration> time_point;
-
- static constexpr bool is_steady = true;
-
- static time_point
- now() noexcept;
- };
-
-
- /**
- * @brief Highest-resolution clock
- *
- * This is the clock "with the shortest tick period." Alias to
- * std::system_clock until higher-than-nanosecond definitions
- * become feasible.
- * @ingroup chrono
- */
- using high_resolution_clock = system_clock;
-
- } // end inline namespace _V2
-
-#if __cplusplus > 201703L
- template<typename _Duration>
- using sys_time = time_point<system_clock, _Duration>;
- using sys_seconds = sys_time<seconds>;
- using sys_days = sys_time<days>;
-
- using file_clock = ::std::filesystem::__file_clock;
-
- template<typename _Duration>
- using file_time = time_point<file_clock, _Duration>;
-
- template<> struct is_clock<system_clock> : true_type { };
- template<> struct is_clock<steady_clock> : true_type { };
- template<> struct is_clock<file_clock> : true_type { };
-
- template<> inline constexpr bool is_clock_v<system_clock> = true;
- template<> inline constexpr bool is_clock_v<steady_clock> = true;
- template<> inline constexpr bool is_clock_v<file_clock> = true;
-
struct local_t { };
template<typename _Duration>
using local_time = time_point<local_t, _Duration>;
@@ -3157,150 +2010,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
chrono::seconds _M_s;
precision _M_ss;
};
-#endif // C++20
-
- /// @} group chrono
- } // namespace chrono
-
-#if __cplusplus > 201103L
-
-#define __cpp_lib_chrono_udls 201304
-
- inline namespace literals
- {
- /** ISO C++ 2014 namespace for suffixes for duration literals.
- *
- * These suffixes can be used to create `chrono::duration` values with
- * tick periods of hours, minutes, seconds, milliseconds, microseconds
- * or nanoseconds. For example, `std::chrono::seconds(5)` can be written
- * as `5s` after making the suffix visible in the current scope.
- * The suffixes can be made visible by a using-directive or
- * using-declaration such as:
- * - `using namespace std::chrono_literals;`
- * - `using namespace std::literals;`
- * - `using namespace std::chrono;`
- * - `using namespace std;`
- * - `using std::chrono_literals::operator""s;`
- *
- * The result of these suffixes on an integer literal is one of the
- * standard typedefs such as `std::chrono::hours`.
- * The result on a floating-point literal is a duration type with the
- * specified tick period and an unspecified floating-point representation,
- * for example `1.5e2ms` might be equivalent to
- * `chrono::duration<long double, chrono::milli>(1.5e2)`.
- *
- * @ingroup chrono
- */
- inline namespace chrono_literals
- {
- /// @addtogroup chrono
- /// @{
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wliteral-suffix"
- /// @cond undocumented
- template<typename _Dur, char... _Digits>
- constexpr _Dur __check_overflow()
- {
- using _Val = __parse_int::_Parse_int<_Digits...>;
- constexpr typename _Dur::rep __repval = _Val::value;
- static_assert(__repval >= 0 && __repval == _Val::value,
- "literal value cannot be represented by duration type");
- return _Dur(__repval);
- }
- /// @endcond
-
- /// Literal suffix for durations representing non-integer hours
- constexpr chrono::duration<long double, ratio<3600,1>>
- operator""h(long double __hours)
- { return chrono::duration<long double, ratio<3600,1>>{__hours}; }
-
- /// Literal suffix for durations of type `std::chrono::hours`
- template <char... _Digits>
- constexpr chrono::hours
- operator""h()
- { return __check_overflow<chrono::hours, _Digits...>(); }
-
- /// Literal suffix for durations representing non-integer minutes
- constexpr chrono::duration<long double, ratio<60,1>>
- operator""min(long double __mins)
- { return chrono::duration<long double, ratio<60,1>>{__mins}; }
-
- /// Literal suffix for durations of type `std::chrono::minutes`
- template <char... _Digits>
- constexpr chrono::minutes
- operator""min()
- { return __check_overflow<chrono::minutes, _Digits...>(); }
-
- /// Literal suffix for durations representing non-integer seconds
- constexpr chrono::duration<long double>
- operator""s(long double __secs)
- { return chrono::duration<long double>{__secs}; }
-
- /// Literal suffix for durations of type `std::chrono::seconds`
- template <char... _Digits>
- constexpr chrono::seconds
- operator""s()
- { return __check_overflow<chrono::seconds, _Digits...>(); }
-
- /// Literal suffix for durations representing non-integer milliseconds
- constexpr chrono::duration<long double, milli>
- operator""ms(long double __msecs)
- { return chrono::duration<long double, milli>{__msecs}; }
-
- /// Literal suffix for durations of type `std::chrono::milliseconds`
- template <char... _Digits>
- constexpr chrono::milliseconds
- operator""ms()
- { return __check_overflow<chrono::milliseconds, _Digits...>(); }
-
- /// Literal suffix for durations representing non-integer microseconds
- constexpr chrono::duration<long double, micro>
- operator""us(long double __usecs)
- { return chrono::duration<long double, micro>{__usecs}; }
-
- /// Literal suffix for durations of type `std::chrono::microseconds`
- template <char... _Digits>
- constexpr chrono::microseconds
- operator""us()
- { return __check_overflow<chrono::microseconds, _Digits...>(); }
-
- /// Literal suffix for durations representing non-integer nanoseconds
- constexpr chrono::duration<long double, nano>
- operator""ns(long double __nsecs)
- { return chrono::duration<long double, nano>{__nsecs}; }
-
- /// Literal suffix for durations of type `std::chrono::nanoseconds`
- template <char... _Digits>
- constexpr chrono::nanoseconds
- operator""ns()
- { return __check_overflow<chrono::nanoseconds, _Digits...>(); }
-
-#if __cplusplus > 201703L
- constexpr chrono::day
- operator""d(unsigned long long __d) noexcept
- { return chrono::day{static_cast<unsigned>(__d)}; }
-
- constexpr chrono::year
- operator""y(unsigned long long __y) noexcept
- { return chrono::year{static_cast<int>(__y)}; }
-#endif // C++20
-
-#pragma GCC diagnostic pop
- /// @}
- } // inline namespace chrono_literals
- } // inline namespace literals
-
- namespace chrono
- {
- using namespace literals::chrono_literals;
- } // namespace chrono
-
-#if __cplusplus > 201703L
- namespace chrono
- {
- /// @addtogroup chrono
- /// @{
// 12/24 HOURS FUNCTIONS
@@ -3341,71 +2050,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
/// @} group chrono
+#endif // C++20
} // namespace chrono
-#endif
-#if __cplusplus >= 201703L
- namespace filesystem
+#if __cplusplus >= 202002L
+ inline namespace literals
{
- struct __file_clock
- {
- using duration = chrono::nanoseconds;
- using rep = duration::rep;
- using period = duration::period;
- using time_point = chrono::time_point<__file_clock>;
- static constexpr bool is_steady = false;
-
- static time_point
- now() noexcept
- { return _S_from_sys(chrono::system_clock::now()); }
-
-#if __cplusplus > 201703L
- template<typename _Dur>
- static
- chrono::file_time<_Dur>
- from_sys(const chrono::sys_time<_Dur>& __t) noexcept
- { return _S_from_sys(__t); }
-
- // For internal use only
- template<typename _Dur>
- static
- chrono::sys_time<_Dur>
- to_sys(const chrono::file_time<_Dur>& __t) noexcept
- { return _S_to_sys(__t); }
-#endif // C++20
-
- private:
- using __sys_clock = chrono::system_clock;
-
- // This clock's (unspecified) epoch is 2174-01-01 00:00:00 UTC.
- // A signed 64-bit duration with nanosecond resolution gives roughly
- // +/- 292 years, which covers the 1901-2446 date range for ext4.
- static constexpr chrono::seconds _S_epoch_diff{6437664000};
-
- protected:
- // For internal use only
- template<typename _Dur>
- static
- chrono::time_point<__file_clock, _Dur>
- _S_from_sys(const chrono::time_point<__sys_clock, _Dur>& __t) noexcept
- {
- using __file_time = chrono::time_point<__file_clock, _Dur>;
- return __file_time{__t.time_since_epoch()} - _S_epoch_diff;
- }
+ inline namespace chrono_literals
+ {
+ /// @addtogroup chrono
+ /// @{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wliteral-suffix"
+ /// Literal suffix for creating chrono::day objects.
+ /// @since C++20
+ constexpr chrono::day
+ operator""d(unsigned long long __d) noexcept
+ { return chrono::day{static_cast<unsigned>(__d)}; }
- // For internal use only
- template<typename _Dur>
- static
- chrono::time_point<__sys_clock, _Dur>
- _S_to_sys(const chrono::time_point<__file_clock, _Dur>& __t) noexcept
- {
- using __sys_time = chrono::time_point<__sys_clock, _Dur>;
- return __sys_time{__t.time_since_epoch()} + _S_epoch_diff;
- }
- };
- } // namespace filesystem
-#endif // C++17
-#endif // C++14
+ /// Literal suffix for creating chrono::year objects.
+ /// @since C++20
+ constexpr chrono::year
+ operator""y(unsigned long long __y) noexcept
+ { return chrono::year{static_cast<int>(__y)}; }
+#pragma GCC diagnostic pop
+ /// @}
+ } // inline namespace chrono_literals
+ } // inline namespace literals
+#endif // C++20
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/std/condition_variable b/libstdc++-v3/include/std/condition_variable
index fb9b7d3..4fcec6a 100644
--- a/libstdc++-v3/include/std/condition_variable
+++ b/libstdc++-v3/include/std/condition_variable
@@ -35,8 +35,7 @@
# include <bits/c++0x_warning.h>
#else
-#include <chrono>
-
+#include <bits/chrono.h>
#include <bits/std_mutex.h>
#include <bits/unique_lock.h>
#include <bits/alloc_traits.h>
diff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque
index c9a8211..71993e7 100644
--- a/libstdc++-v3/include/std/deque
+++ b/libstdc++-v3/include/std/deque
@@ -58,13 +58,11 @@
#pragma GCC system_header
#include <bits/stl_algobase.h>
-#if __cplusplus > 201703L
-# include <bits/stl_algo.h> // For remove and remove_if
-#endif // C++20
#include <bits/allocator.h>
#include <bits/stl_construct.h>
#include <bits/stl_uninitialized.h>
#include <bits/stl_deque.h>
+#include <bits/refwrap.h>
#include <bits/range_access.h>
#include <bits/deque.tcc>
@@ -97,20 +95,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline typename deque<_Tp, _Alloc>::size_type
erase_if(deque<_Tp, _Alloc>& __cont, _Predicate __pred)
{
- const auto __osz = __cont.size();
- __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred),
- __cont.end());
- return __osz - __cont.size();
+ _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __c = __cont;
+ using namespace __gnu_cxx;
+ const auto __osz = __c.size();
+ const auto __end = __c.end();
+ auto __removed = std::__remove_if(__c.begin(), __end,
+ __ops::__pred_iter(std::ref(__pred)));
+ __c.erase(__removed, __end);
+ return __osz - __c.size();
}
template<typename _Tp, typename _Alloc, typename _Up>
inline typename deque<_Tp, _Alloc>::size_type
erase(deque<_Tp, _Alloc>& __cont, const _Up& __value)
{
- const auto __osz = __cont.size();
- __cont.erase(std::remove(__cont.begin(), __cont.end(), __value),
- __cont.end());
- return __osz - __cont.size();
+ _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __c = __cont;
+ using namespace __gnu_cxx;
+ const auto __osz = __c.size();
+ const auto __end = __c.end();
+ auto __removed = std::__remove_if(__c.begin(), __end,
+ __ops::__iter_equals_val(__value));
+ __c.erase(__removed, __end);
+ return __osz - __c.size();
}
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 0b25792..2db1c05 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -67,6 +67,9 @@
# include <bits/ranges_cmp.h>
# include <compare>
#endif
+#if __cplusplus > 202002L
+# include <bits/move_only_function.h>
+#endif
#endif // C++11
@@ -1117,9 +1120,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename _Val = typename iterator_traits<_RAIter>::value_type,
typename _Diff = typename iterator_traits<_RAIter>::difference_type>
using __boyer_moore_base_t
- = conditional_t<__is_byte_like<_Val, _Pred>::value,
- __boyer_moore_array_base<_Diff, 256, _Pred>,
- __boyer_moore_map_base<_Val, _Diff, _Hash, _Pred>>;
+ = __conditional_t<__is_byte_like<_Val, _Pred>::value,
+ __boyer_moore_array_base<_Diff, 256, _Pred>,
+ __boyer_moore_map_base<_Val, _Diff, _Hash, _Pred>>;
template<typename _RAIter, typename _Hash
= hash<typename iterator_traits<_RAIter>::value_type>,
diff --git a/libstdc++-v3/include/std/map b/libstdc++-v3/include/std/map
index 44bd44b..2926558 100644
--- a/libstdc++-v3/include/std/map
+++ b/libstdc++-v3/include/std/map
@@ -95,13 +95,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename _Predicate>
inline typename map<_Key, _Tp, _Compare, _Alloc>::size_type
erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& __c = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Tp, typename _Compare, typename _Alloc,
typename _Predicate>
inline typename multimap<_Key, _Tp, _Compare, _Alloc>::size_type
erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& __c = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++20
diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex
index 7ab4ee1..12918fd 100644
--- a/libstdc++-v3/include/std/mutex
+++ b/libstdc++-v3/include/std/mutex
@@ -36,10 +36,10 @@
#else
#include <tuple>
-#include <chrono>
#include <exception>
#include <type_traits>
#include <system_error>
+#include <bits/chrono.h>
#include <bits/std_mutex.h>
#include <bits/unique_lock.h>
#if ! _GTHREAD_USE_MUTEX_TIMEDLOCK
diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream
index ddb33fe..7d39c57 100644
--- a/libstdc++-v3/include/std/ostream
+++ b/libstdc++-v3/include/std/ostream
@@ -251,6 +251,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return *this << "nullptr"; }
#endif
+#if __cplusplus > 202002L
+ __attribute__((__always_inline__))
+ __ostream_type&
+ operator<<(const volatile void* __p)
+ { return _M_insert(const_cast<const void*>(__p)); }
+#endif
+
/**
* @brief Extracting from another streambuf.
* @param __sb A pointer to a streambuf
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index b373e4f..07eae0c 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -770,11 +770,11 @@ namespace __detail
// Data members using this alias should use [[no_unique_address]] so that
// they take no space when not needed.
template<bool _Present, typename _Tp>
- using __maybe_present_t = conditional_t<_Present, _Tp, _Empty>;
+ using __maybe_present_t = __conditional_t<_Present, _Tp, _Empty>;
// Alias for a type that is conditionally const.
template<bool _Const, typename _Tp>
- using __maybe_const_t = conditional_t<_Const, const _Tp, _Tp>;
+ using __maybe_const_t = __conditional_t<_Const, const _Tp, _Tp>;
} // namespace __detail
@@ -2920,9 +2920,9 @@ namespace views::__adaptor
bool _M_trailing_empty = false;
public:
- using iterator_concept = conditional_t<forward_range<_Base>,
- forward_iterator_tag,
- input_iterator_tag>;
+ using iterator_concept = __conditional_t<forward_range<_Base>,
+ forward_iterator_tag,
+ input_iterator_tag>;
// iterator_category defined in __lazy_split_view_outer_iter_cat
using difference_type = range_difference_t<_Base>;
diff --git a/libstdc++-v3/include/std/set b/libstdc++-v3/include/std/set
index f1e1864..24e6e63 100644
--- a/libstdc++-v3/include/std/set
+++ b/libstdc++-v3/include/std/set
@@ -91,13 +91,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename _Predicate>
inline typename set<_Key, _Compare, _Alloc>::size_type
erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __c = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Compare, typename _Alloc,
typename _Predicate>
inline typename multiset<_Key, _Compare, _Alloc>::size_type
erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __c = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++20
diff --git a/libstdc++-v3/include/std/shared_mutex b/libstdc++-v3/include/std/shared_mutex
index edf6dcd..4611a10 100644
--- a/libstdc++-v3/include/std/shared_mutex
+++ b/libstdc++-v3/include/std/shared_mutex
@@ -33,7 +33,7 @@
#if __cplusplus >= 201402L
-#include <chrono>
+#include <bits/chrono.h>
#include <bits/functexcept.h>
#include <bits/move.h> // move, __exchange
#include <bits/std_mutex.h> // defer_lock_t
diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string
index 0147e48..95412b6 100644
--- a/libstdc++-v3/include/std/string
+++ b/libstdc++-v3/include/std/string
@@ -48,9 +48,7 @@
#include <bits/stl_function.h> // For less
#include <ext/numeric_traits.h>
#include <bits/stl_algobase.h>
-#if __cplusplus > 201703L
-# include <bits/stl_algo.h> // For remove and remove_if
-#endif // C++20
+#include <bits/refwrap.h>
#include <bits/range_access.h>
#include <bits/basic_string.h>
#include <bits/basic_string.tcc>
@@ -125,9 +123,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline typename basic_string<_CharT, _Traits, _Alloc>::size_type
erase_if(basic_string<_CharT, _Traits, _Alloc>& __cont, _Predicate __pred)
{
+ using namespace __gnu_cxx;
const auto __osz = __cont.size();
- __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred),
- __cont.end());
+ const auto __end = __cont.end();
+ auto __removed = std::__remove_if(__cont.begin(), __end,
+ __ops::__pred_iter(std::ref(__pred)));
+ __cont.erase(__removed, __end);
return __osz - __cont.size();
}
@@ -135,9 +136,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline typename basic_string<_CharT, _Traits, _Alloc>::size_type
erase(basic_string<_CharT, _Traits, _Alloc>& __cont, const _Up& __value)
{
+ using namespace __gnu_cxx;
const auto __osz = __cont.size();
- __cont.erase(std::remove(__cont.begin(), __cont.end(), __value),
- __cont.end());
+ const auto __end = __cont.end();
+ auto __removed = std::__remove_if(__cont.begin(), __end,
+ __ops::__iter_equals_val(__value));
+ __cont.erase(__removed, __end);
return __osz - __cont.size();
}
_GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view
index d8cbee9..996b03f 100644
--- a/libstdc++-v3/include/std/string_view
+++ b/libstdc++-v3/include/std/string_view
@@ -168,6 +168,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif // C++23
#endif // C++20
+ basic_string_view(nullptr_t) = delete;
+
constexpr basic_string_view&
operator=(const basic_string_view&) noexcept = default;
diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread
index f51392a..4651908 100644
--- a/libstdc++-v3/include/std/thread
+++ b/libstdc++-v3/include/std/thread
@@ -99,6 +99,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#ifdef __cpp_lib_jthread
+#ifndef __STRICT_ANSI__
+ template<typename _Callable, typename... _Args>
+ constexpr bool __pmf_expects_stop_token = false;
+
+ template<typename _Callable, typename _Obj, typename... _Args>
+ constexpr bool __pmf_expects_stop_token<_Callable, _Obj, _Args...>
+ = __and_<is_member_function_pointer<remove_reference_t<_Callable>>,
+ is_invocable<_Callable, _Obj, stop_token, _Args...>>::value;
+#endif
+
/// A thread that can be requested to stop and automatically joined.
class jthread
{
@@ -211,6 +221,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static thread
_S_create(stop_source& __ssrc, _Callable&& __f, _Args&&... __args)
{
+#ifndef __STRICT_ANSI__
+ if constexpr (__pmf_expects_stop_token<_Callable, _Args...>)
+ return _S_create_pmf(__ssrc, __f, std::forward<_Args>(__args)...);
+ else
+#endif
if constexpr(is_invocable_v<decay_t<_Callable>, stop_token,
decay_t<_Args>...>)
return thread{std::forward<_Callable>(__f), __ssrc.get_token(),
@@ -226,6 +241,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
+#ifndef __STRICT_ANSI__
+ template<typename _Callable, typename _Obj, typename... _Args>
+ static thread
+ _S_create_pmf(stop_source& __ssrc, _Callable __f, _Obj&& __obj,
+ _Args&&... __args)
+ {
+ return thread{__f, std::forward<_Obj>(__obj), __ssrc.get_token(),
+ std::forward<_Args>(__args)...};
+ }
+#endif
+
stop_source _M_stop_source;
thread _M_thread;
};
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 120c80a..94a4f0a 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -66,8 +66,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Use the Empty Base-class Optimization for empty, non-final types.
template<typename _Tp>
using __empty_not_final
- = typename conditional<__is_final(_Tp), false_type,
- __is_empty_non_tuple<_Tp>>::type;
+ = __conditional_t<__is_final(_Tp), false_type,
+ __is_empty_non_tuple<_Tp>>;
template<size_t _Idx, typename _Head,
bool = __empty_not_final<_Head>::value>
@@ -905,9 +905,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX20_CONSTEXPR
tuple&
- operator=(typename conditional<__assignable<const _Elements&...>(),
- const tuple&,
- const __nonesuch&>::type __in)
+ operator=(__conditional_t<__assignable<const _Elements&...>(),
+ const tuple&,
+ const __nonesuch&> __in)
noexcept(__nothrow_assignable<const _Elements&...>())
{
this->_M_assign(__in);
@@ -916,9 +916,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX20_CONSTEXPR
tuple&
- operator=(typename conditional<__assignable<_Elements...>(),
- tuple&&,
- __nonesuch&&>::type __in)
+ operator=(__conditional_t<__assignable<_Elements...>(),
+ tuple&&,
+ __nonesuch&&> __in)
noexcept(__nothrow_assignable<_Elements...>())
{
this->_M_assign(std::move(__in));
@@ -1274,9 +1274,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX20_CONSTEXPR
tuple&
- operator=(typename conditional<__assignable<const _T1&, const _T2&>(),
- const tuple&,
- const __nonesuch&>::type __in)
+ operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
+ const tuple&,
+ const __nonesuch&> __in)
noexcept(__nothrow_assignable<const _T1&, const _T2&>())
{
this->_M_assign(__in);
@@ -1285,9 +1285,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX20_CONSTEXPR
tuple&
- operator=(typename conditional<__assignable<_T1, _T2>(),
- tuple&&,
- __nonesuch&&>::type __in)
+ operator=(__conditional_t<__assignable<_T1, _T2>(),
+ tuple&&,
+ __nonesuch&&> __in)
noexcept(__nothrow_assignable<_T1, _T2>())
{
this->_M_assign(std::move(__in));
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index a0010d9..35ff580 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -100,8 +100,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Metaprogramming helper types.
- template<bool, typename, typename>
- struct conditional;
+ template<bool>
+ struct __conditional
+ {
+ template<typename _Tp, typename>
+ using type = _Tp;
+ };
+
+ template<>
+ struct __conditional<false>
+ {
+ template<typename, typename _Up>
+ using type = _Up;
+ };
+
+ // More efficient version of std::conditional_t for internal use (and C++11)
+ template<bool _Cond, typename _If, typename _Else>
+ using __conditional_t
+ = typename __conditional<_Cond>::template type<_If, _Else>;
/// @cond undocumented
template <typename _Type>
@@ -126,12 +142,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _B1, typename _B2>
struct __or_<_B1, _B2>
- : public conditional<_B1::value, _B1, _B2>::type
+ : public __conditional_t<_B1::value, _B1, _B2>
{ };
template<typename _B1, typename _B2, typename _B3, typename... _Bn>
struct __or_<_B1, _B2, _B3, _Bn...>
- : public conditional<_B1::value, _B1, __or_<_B2, _B3, _Bn...>>::type
+ : public __conditional_t<_B1::value, _B1, __or_<_B2, _B3, _Bn...>>
{ };
template<typename...>
@@ -149,12 +165,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _B1, typename _B2>
struct __and_<_B1, _B2>
- : public conditional<_B1::value, _B2, _B1>::type
+ : public __conditional_t<_B1::value, _B2, _B1>
{ };
template<typename _B1, typename _B2, typename _B3, typename... _Bn>
struct __and_<_B1, _B2, _B3, _Bn...>
- : public conditional<_B1::value, __and_<_B2, _B3, _Bn...>, _B1>::type
+ : public __conditional_t<_B1::value, __and_<_B2, _B3, _Bn...>, _B1>
{ };
template<typename _Pp>
@@ -2491,11 +2507,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
typedef __remove_cvref_t<_Arg> _Argval;
typedef _Res _Class::* _MemPtr;
- typedef typename conditional<__or_<is_same<_Argval, _Class>,
+ typedef typename __conditional_t<__or_<is_same<_Argval, _Class>,
is_base_of<_Class, _Argval>>::value,
__result_of_memobj_ref<_MemPtr, _Arg>,
__result_of_memobj_deref<_MemPtr, _Arg>
- >::type::type type;
+ >::type type;
};
template<typename _MemPtr, typename _Arg, typename... _Args>
@@ -2506,10 +2522,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
typedef typename remove_reference<_Arg>::type _Argval;
typedef _Res _Class::* _MemPtr;
- typedef typename conditional<is_base_of<_Class, _Argval>::value,
+ typedef typename __conditional_t<is_base_of<_Class, _Argval>::value,
__result_of_memfun_ref<_MemPtr, _Arg, _Args...>,
__result_of_memfun_deref<_MemPtr, _Arg, _Args...>
- >::type::type type;
+ >::type type;
};
// _GLIBCXX_RESOLVE_LIB_DEFECTS
diff --git a/libstdc++-v3/include/std/unordered_map b/libstdc++-v3/include/std/unordered_map
index e671506..774c21f 100644
--- a/libstdc++-v3/include/std/unordered_map
+++ b/libstdc++-v3/include/std/unordered_map
@@ -83,7 +83,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline typename unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>::size_type
erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __c
+ = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Tp, typename _Hash, typename _CPred,
typename _Alloc, typename _Predicate>
@@ -91,7 +95,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
size_type
erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __c
+ = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++20
diff --git a/libstdc++-v3/include/std/unordered_set b/libstdc++-v3/include/std/unordered_set
index 1ad93d0..3859eea 100644
--- a/libstdc++-v3/include/std/unordered_set
+++ b/libstdc++-v3/include/std/unordered_set
@@ -83,14 +83,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline typename unordered_set<_Key, _Hash, _CPred, _Alloc>::size_type
erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>& __c = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Hash, typename _CPred, typename _Alloc,
typename _Predicate>
inline typename unordered_multiset<_Key, _Hash, _CPred, _Alloc>::size_type
erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __c
+ = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++20
diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index 6383cf4..6377b67 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -71,7 +71,7 @@ namespace __variant
} // namespace __variant
} // namespace __detail
-#define __cpp_lib_variant 201606L
+#define __cpp_lib_variant 202102L
template<typename... _Types> class tuple;
template<typename... _Types> class variant;
@@ -202,6 +202,28 @@ namespace __variant
std::forward<_Variants>(__variants)...);
}
+ // The __as function templates implement the exposition-only "as-variant"
+
+ template<typename... _Types>
+ constexpr std::variant<_Types...>&
+ __as(std::variant<_Types...>& __v) noexcept
+ { return __v; }
+
+ template<typename... _Types>
+ constexpr const std::variant<_Types...>&
+ __as(const std::variant<_Types...>& __v) noexcept
+ { return __v; }
+
+ template<typename... _Types>
+ constexpr std::variant<_Types...>&&
+ __as(std::variant<_Types...>&& __v) noexcept
+ { return std::move(__v); }
+
+ template<typename... _Types>
+ constexpr const std::variant<_Types...>&&
+ __as(const std::variant<_Types...>&& __v) noexcept
+ { return std::move(__v); }
+
// _Uninitialized<T> is guaranteed to be a trivially destructible type,
// even if T is not.
template<typename _Type, bool = std::is_trivially_destructible_v<_Type>>
@@ -463,6 +485,12 @@ namespace __variant
{
if constexpr (__variant::__never_valueless<_Types...>())
return true;
+ // It would be nice if we could just return true for -fno-exceptions.
+ // It's possible (but inadvisable) that a std::variant could become
+ // valueless in a translation unit compiled with -fexceptions and then
+ // be passed to functions compiled with -fno-exceptions. We would need
+ // some #ifdef _GLIBCXX_NO_EXCEPTIONS_GLOBALLY property to elide all
+ // checks for valueless_by_exception().
return this->_M_index != static_cast<__index_type>(variant_npos);
}
@@ -1063,8 +1091,12 @@ namespace __variant
std::index_sequence<__indices...>>
: _Base_dedup<__indices, __poison_hash<remove_const_t<_Types>>>... { };
- template<size_t _Np, typename _Variant>
- using __get_t = decltype(std::get<_Np>(std::declval<_Variant>()));
+ // Equivalent to decltype(get<_Np>(as-variant(declval<_Variant>())))
+ template<size_t _Np, typename _Variant,
+ typename _AsV = decltype(__variant::__as(std::declval<_Variant>())),
+ typename _Tp = variant_alternative_t<_Np, remove_reference_t<_AsV>>>
+ using __get_t
+ = __conditional_t<is_lvalue_reference_v<_Variant>, _Tp&, _Tp&&>;
// Return type of std::visit.
template<typename _Visitor, typename... _Variants>
@@ -1728,12 +1760,90 @@ namespace __variant
constexpr decltype(auto)
__do_visit(_Visitor&& __visitor, _Variants&&... __variants)
{
- constexpr auto& __vtable = __detail::__variant::__gen_vtable<
- _Result_type, _Visitor&&, _Variants&&...>::_S_vtable;
+ // Get the silly case of visiting no variants out of the way first.
+ if constexpr (sizeof...(_Variants) == 0)
+ return std::forward<_Visitor>(__visitor)();
+ else
+ {
+ constexpr size_t __max = 11; // "These go to eleven."
+
+ // The type of the first variant in the pack.
+ using _V0
+ = typename __detail::__variant::_Nth_type<0, _Variants...>::type;
+ // The number of alternatives in that first variant.
+ constexpr auto __n = variant_size_v<remove_reference_t<_V0>>;
+
+ if constexpr (sizeof...(_Variants) > 1 || __n > __max)
+ {
+ // Use a jump table for the general case.
+ constexpr auto& __vtable = __detail::__variant::__gen_vtable<
+ _Result_type, _Visitor&&, _Variants&&...>::_S_vtable;
+
+ auto __func_ptr = __vtable._M_access(__variants.index()...);
+ return (*__func_ptr)(std::forward<_Visitor>(__visitor),
+ std::forward<_Variants>(__variants)...);
+ }
+ else // We have a single variant with a small number of alternatives.
+ {
+ // A name for the first variant in the pack.
+ _V0& __v0
+ = [](_V0& __v, ...) -> _V0& { return __v; }(__variants...);
+
+ using __detail::__variant::_Multi_array;
+ using __detail::__variant::__gen_vtable_impl;
+ using _Ma = _Multi_array<_Result_type (*)(_Visitor&&, _V0&&)>;
- auto __func_ptr = __vtable._M_access(__variants.index()...);
- return (*__func_ptr)(std::forward<_Visitor>(__visitor),
- std::forward<_Variants>(__variants)...);
+#ifdef _GLIBCXX_DEBUG
+# define _GLIBCXX_VISIT_UNREACHABLE __builtin_trap
+#else
+# define _GLIBCXX_VISIT_UNREACHABLE __builtin_unreachable
+#endif
+
+#define _GLIBCXX_VISIT_CASE(N) \
+ case N: \
+ { \
+ if constexpr (N < __n) \
+ { \
+ return __gen_vtable_impl<_Ma, index_sequence<N>>:: \
+ __visit_invoke(std::forward<_Visitor>(__visitor), \
+ std::forward<_V0>(__v0)); \
+ } \
+ else _GLIBCXX_VISIT_UNREACHABLE(); \
+ }
+
+ switch (__v0.index())
+ {
+ _GLIBCXX_VISIT_CASE(0)
+ _GLIBCXX_VISIT_CASE(1)
+ _GLIBCXX_VISIT_CASE(2)
+ _GLIBCXX_VISIT_CASE(3)
+ _GLIBCXX_VISIT_CASE(4)
+ _GLIBCXX_VISIT_CASE(5)
+ _GLIBCXX_VISIT_CASE(6)
+ _GLIBCXX_VISIT_CASE(7)
+ _GLIBCXX_VISIT_CASE(8)
+ _GLIBCXX_VISIT_CASE(9)
+ _GLIBCXX_VISIT_CASE(10)
+ case variant_npos:
+ using __detail::__variant::__variant_idx_cookie;
+ using __detail::__variant::__variant_cookie;
+ if constexpr (is_same_v<_Result_type, __variant_idx_cookie>
+ || is_same_v<_Result_type, __variant_cookie>)
+ {
+ using _Npos = index_sequence<variant_npos>;
+ return __gen_vtable_impl<_Ma, _Npos>::
+ __visit_invoke(std::forward<_Visitor>(__visitor),
+ std::forward<_V0>(__v0));
+ }
+ else
+ _GLIBCXX_VISIT_UNREACHABLE();
+ default:
+ _GLIBCXX_VISIT_UNREACHABLE();
+ }
+#undef _GLIBCXX_VISIT_CASE
+#undef _GLIBCXX_VISIT_UNREACHABLE
+ }
+ }
}
/// @endcond
@@ -1741,7 +1851,9 @@ namespace __variant
constexpr __detail::__variant::__visit_result_t<_Visitor, _Variants...>
visit(_Visitor&& __visitor, _Variants&&... __variants)
{
- if ((__variants.valueless_by_exception() || ...))
+ namespace __variant = std::__detail::__variant;
+
+ if ((__variant::__as(__variants).valueless_by_exception() || ...))
__throw_bad_variant_access("std::visit: variant is valueless");
using _Result_type
@@ -1751,10 +1863,11 @@ namespace __variant
if constexpr (sizeof...(_Variants) == 1)
{
+ using _Vp = decltype(__variant::__as(std::declval<_Variants>()...));
+
constexpr bool __visit_rettypes_match = __detail::__variant::
- __check_visitor_results<_Visitor, _Variants...>(
- std::make_index_sequence<
- std::variant_size<remove_reference_t<_Variants>...>::value>());
+ __check_visitor_results<_Visitor, _Vp>(
+ make_index_sequence<variant_size_v<remove_reference_t<_Vp>>>());
if constexpr (!__visit_rettypes_match)
{
static_assert(__visit_rettypes_match,
@@ -1765,12 +1878,12 @@ namespace __variant
else
return std::__do_visit<_Tag>(
std::forward<_Visitor>(__visitor),
- std::forward<_Variants>(__variants)...);
+ static_cast<_Vp>(__variants)...);
}
else
return std::__do_visit<_Tag>(
std::forward<_Visitor>(__visitor),
- std::forward<_Variants>(__variants)...);
+ __variant::__as(std::forward<_Variants>(__variants))...);
}
#if __cplusplus > 201703L
@@ -1778,11 +1891,13 @@ namespace __variant
constexpr _Res
visit(_Visitor&& __visitor, _Variants&&... __variants)
{
- if ((__variants.valueless_by_exception() || ...))
+ namespace __variant = std::__detail::__variant;
+
+ if ((__variant::__as(__variants).valueless_by_exception() || ...))
__throw_bad_variant_access("std::visit<R>: variant is valueless");
return std::__do_visit<_Res>(std::forward<_Visitor>(__visitor),
- std::forward<_Variants>(__variants)...);
+ __variant::__as(std::forward<_Variants>(__variants))...);
}
#endif
diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector
index f804f40..835fa8a 100644
--- a/libstdc++-v3/include/std/vector
+++ b/libstdc++-v3/include/std/vector
@@ -58,14 +58,12 @@
#pragma GCC system_header
#include <bits/stl_algobase.h>
-#if __cplusplus > 201703L
-# include <bits/stl_algo.h> // For remove and remove_if
-#endif // C++20
#include <bits/allocator.h>
#include <bits/stl_construct.h>
#include <bits/stl_uninitialized.h>
#include <bits/stl_vector.h>
#include <bits/stl_bvector.h>
+#include <bits/refwrap.h>
#include <bits/range_access.h>
#ifndef _GLIBCXX_EXPORT_TEMPLATE
@@ -107,20 +105,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline typename vector<_Tp, _Alloc>::size_type
erase_if(vector<_Tp, _Alloc>& __cont, _Predicate __pred)
{
- const auto __osz = __cont.size();
- __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred),
- __cont.end());
- return __osz - __cont.size();
+ _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __c = __cont;
+ using namespace __gnu_cxx;
+ const auto __osz = __c.size();
+ const auto __end = __c.end();
+ auto __removed(std::__remove_if(__c.begin(), __end,
+ __ops::__pred_iter(std::ref(__pred))));
+ __c.erase(__removed, __end);
+ return __osz - __c.size();
}
template<typename _Tp, typename _Alloc, typename _Up>
inline typename vector<_Tp, _Alloc>::size_type
erase(vector<_Tp, _Alloc>& __cont, const _Up& __value)
{
- const auto __osz = __cont.size();
- __cont.erase(std::remove(__cont.begin(), __cont.end(), __value),
- __cont.end());
- return __osz - __cont.size();
+ _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __c = __cont;
+ using namespace __gnu_cxx;
+ const auto __osz = __c.size();
+ const auto __end = __c.end();
+ auto __removed = std::__remove_if(__c.begin(), __end,
+ __ops::__iter_equals_val(__value));
+ __c.erase(__removed, __end);
+ return __osz - __c.size();
}
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index f41004b..24b86e0 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -171,7 +171,7 @@
# define __cpp_lib_to_chars 201611L
#endif
#define __cpp_lib_unordered_map_try_emplace 201411
-#define __cpp_lib_variant 201606L
+#define __cpp_lib_variant 202102L
#endif
#if __cplusplus >= 202002L
@@ -281,8 +281,10 @@
#if __cplusplus > 202002L
// c++2b
+#define __cpp_lib_adaptor_iterator_pair_constructor 202106L
#define __cpp_lib_invoke_r 202106L
#define __cpp_lib_is_scoped_enum 202011L
+#define __cpp_lib_move_only_function 202110L
#define __cpp_lib_string_contains 202011L
#define __cpp_lib_to_underlying 202102L
#endif // C++2b
diff --git a/libstdc++-v3/src/c++11/functexcept.cc b/libstdc++-v3/src/c++11/functexcept.cc
index 6f00713..d1570b6 100644
--- a/libstdc++-v3/src/c++11/functexcept.cc
+++ b/libstdc++-v3/src/c++11/functexcept.cc
@@ -88,6 +88,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
__throw_out_of_range_fmt(const char* __fmt, ...)
{
+#if _GLIBCXX_HOSTED && _GLIBCXX_VERBOSE && __cpp_exceptions
const size_t __len = __builtin_strlen(__fmt);
// We expect at most 2 numbers, and 1 short string. The additional
// 512 bytes should provide more than enough space for expansion.
@@ -96,9 +97,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
va_list __ap;
va_start(__ap, __fmt);
- __gnu_cxx::__snprintf_lite(__s, __alloca_size, __fmt, __ap);
- _GLIBCXX_THROW_OR_ABORT(out_of_range(_(__s)));
+ __gnu_cxx::__snprintf_lite(__s, __alloca_size, _(__fmt), __ap);
+ throw out_of_range(__s);
va_end(__ap); // Not reached.
+#else
+ __throw_out_of_range(__fmt);
+#endif
}
void
diff --git a/libstdc++-v3/src/c++11/snprintf_lite.cc b/libstdc++-v3/src/c++11/snprintf_lite.cc
index dcf8421..ffeb7bf 100644
--- a/libstdc++-v3/src/c++11/snprintf_lite.cc
+++ b/libstdc++-v3/src/c++11/snprintf_lite.cc
@@ -24,17 +24,8 @@
// <http://www.gnu.org/licenses/>.
#include <stdarg.h>
+#include <stddef.h>
#include <bits/functexcept.h>
-#include <bits/locale_facets.h>
-
-namespace std {
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
- template<typename _CharT, typename _ValueT>
- int
- __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
- ios_base::fmtflags __flags, bool __dec);
-_GLIBCXX_END_NAMESPACE_VERSION
-}
namespace __gnu_cxx {
diff --git a/libstdc++-v3/src/c++11/system_error.cc b/libstdc++-v3/src/c++11/system_error.cc
index f12290a..f1cfc03 100644
--- a/libstdc++-v3/src/c++11/system_error.cc
+++ b/libstdc++-v3/src/c++11/system_error.cc
@@ -32,52 +32,228 @@
#include <errno.h>
#undef __sso_string
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <memory>
+#include <windows.h>
+#endif
+
namespace
{
using std::string;
- struct generic_error_category : public std::error_category
+ template<typename T>
+ struct constant_init
+ {
+ union {
+ unsigned char unused;
+ T obj;
+ };
+ constexpr constant_init() : obj() { }
+
+ ~constant_init() { /* do nothing, union member is not destroyed */ }
+ };
+
+ struct generic_error_category final : public std::error_category
{
- virtual const char*
- name() const noexcept
+ const char*
+ name() const noexcept final
{ return "generic"; }
_GLIBCXX_DEFAULT_ABI_TAG
- virtual string
- message(int i) const
+ string
+ message(int i) const final
{
// XXX locale issues: how does one get or set loc.
// _GLIBCXX_HAVE_STRERROR_L, strerror_l(i, cloc)
return string(strerror(i));
}
+
+ // Override this to avoid a virtual call to default_error_condition(i).
+ bool
+ equivalent(int i, const std::error_condition& cond) const noexcept final
+ { return i == cond.value() && *this == cond.category(); }
};
- struct system_error_category : public std::error_category
+ __constinit constant_init<generic_error_category> generic_category_instance{};
+
+ struct system_error_category final : public std::error_category
{
- virtual const char*
- name() const noexcept
+ const char*
+ name() const noexcept final
{ return "system"; }
_GLIBCXX_DEFAULT_ABI_TAG
- virtual string
- message(int i) const
+ string
+ message(int i) const final
{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ char* buf = nullptr;
+ auto len
+ = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ nullptr,
+ i,
+ LANG_USER_DEFAULT,
+ reinterpret_cast<LPTSTR>(&buf),
+ 0,
+ nullptr);
+ if (len > 0)
+ {
+ struct deleter {
+ void operator()(void* p) const { ::LocalFree(p); }
+ };
+ std::unique_ptr<char[], deleter> guard(buf);
+ if (len > 3 && !__builtin_memcmp(buf + len - 3, ".\r\n", 3)) [[likely]]
+ len -= 3;
+ return string(buf, len);
+ }
+ return string("Unknown error code");
+#else
// XXX locale issues: how does one get or set loc.
// _GLIBCXX_HAVE_STRERROR_L, strerror_l(i, cloc)
return string(strerror(i));
+#endif
}
- virtual std::error_condition
- default_error_condition(int ev) const noexcept
+ std::error_condition
+ default_error_condition(int ev) const noexcept final
{
+ // Use generic category for all known POSIX errno values (including zero)
+ // and system category otherwise.
switch (ev)
{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ case 0:
+ return {0, generic_category_instance.obj};
+ // Convert Windows error code into a corresponding POSIX errno value.
+#define X(w, e) case ERROR_##w: return {e, generic_category_instance.obj};
+ // This list is based on Cygwin's winsup/cygwin/errno.cc
+ X (ACCESS_DENIED, EACCES);
+ X (ACTIVE_CONNECTIONS, EAGAIN);
+ X (ALREADY_EXISTS, EEXIST);
+ X (BAD_DEVICE, ENODEV);
+ X (BAD_EXE_FORMAT, ENOEXEC);
+ X (BAD_NETPATH, ENOENT);
+ X (BAD_NET_NAME, ENOENT);
+ X (BAD_NET_RESP, ENOSYS);
+ X (BAD_PATHNAME, ENOENT);
+ X (BAD_PIPE, EINVAL);
+ X (BAD_UNIT, ENODEV);
+ X (BAD_USERNAME, EINVAL);
+ X (BEGINNING_OF_MEDIA, EIO);
+ X (BROKEN_PIPE, EPIPE);
+ X (BUSY, EBUSY);
+ X (BUS_RESET, EIO);
+ X (CALL_NOT_IMPLEMENTED, ENOSYS);
+ X (CANCELLED, EINTR);
+ X (CANNOT_MAKE, EPERM);
+ X (CHILD_NOT_COMPLETE, EBUSY);
+ X (COMMITMENT_LIMIT, EAGAIN);
+ X (CONNECTION_REFUSED, ECONNREFUSED);
+ X (CRC, EIO);
+ X (DEVICE_DOOR_OPEN, EIO);
+ X (DEVICE_IN_USE, EAGAIN);
+ X (DEVICE_REQUIRES_CLEANING, EIO);
+ X (DEV_NOT_EXIST, ENOENT);
+ X (DIRECTORY, ENOTDIR);
+ X (DIR_NOT_EMPTY, ENOTEMPTY);
+ X (DISK_CORRUPT, EIO);
+#ifdef ENOSPC
+ X (DISK_FULL, ENOSPC);
+#endif
+ X (DS_GENERIC_ERROR, EIO);
+#ifdef ENOSPC
+ X (END_OF_MEDIA, ENOSPC);
+#endif
+ X (EOM_OVERFLOW, EIO);
+ X (EXE_MACHINE_TYPE_MISMATCH, ENOEXEC);
+ X (EXE_MARKED_INVALID, ENOEXEC);
+ X (FILEMARK_DETECTED, EIO);
+ X (FILENAME_EXCED_RANGE, ENAMETOOLONG);
+ X (FILE_CORRUPT, EEXIST);
+ X (FILE_EXISTS, EEXIST);
+ X (FILE_INVALID, ENXIO);
+ X (FILE_NOT_FOUND, ENOENT);
+#ifdef ENOSPC
+ X (HANDLE_DISK_FULL, ENOSPC);
+#endif
+ X (INVALID_ADDRESS, EINVAL);
+ X (INVALID_AT_INTERRUPT_TIME, EINTR);
+ X (INVALID_BLOCK_LENGTH, EIO);
+ X (INVALID_DATA, EINVAL);
+ X (INVALID_DRIVE, ENODEV);
+ X (INVALID_EA_NAME, EINVAL);
+ X (INVALID_EXE_SIGNATURE, ENOEXEC);
+ X (INVALID_HANDLE, EBADF);
+ X (INVALID_NAME, ENOENT);
+ X (INVALID_PARAMETER, EINVAL);
+ X (INVALID_SIGNAL_NUMBER, EINVAL);
+ X (IOPL_NOT_ENABLED, ENOEXEC);
+ X (IO_DEVICE, EIO);
+ X (IO_INCOMPLETE, EAGAIN);
+ X (IO_PENDING, EAGAIN);
+ X (LOCK_VIOLATION, EBUSY);
+ X (MAX_THRDS_REACHED, EAGAIN);
+ X (META_EXPANSION_TOO_LONG, EINVAL);
+ X (MOD_NOT_FOUND, ENOENT);
+ X (MORE_DATA, EMSGSIZE);
+ X (NEGATIVE_SEEK, EINVAL);
+ X (NETNAME_DELETED, ENOENT);
+ X (NOACCESS, EFAULT);
+ X (NONE_MAPPED, EINVAL);
+ X (NONPAGED_SYSTEM_RESOURCES, EAGAIN);
+ X (NOT_ENOUGH_MEMORY, ENOMEM);
+ X (NOT_ENOUGH_QUOTA, EIO);
+#ifdef EPERM
+ X (NOT_OWNER, EPERM);
+#else
+ X (NOT_OWNER, EACCES);
+#endif
+ X (NOT_SAME_DEVICE, EXDEV);
+ X (NOT_SUPPORTED, ENOSYS);
+ X (NO_DATA, EPIPE);
+ X (NO_DATA_DETECTED, EIO);
+ X (NO_MORE_SEARCH_HANDLES, ENFILE);
+ X (NO_PROC_SLOTS, EAGAIN);
+ X (NO_SIGNAL_SENT, EIO);
+ X (NO_SYSTEM_RESOURCES, EFBIG);
+ X (NO_TOKEN, EINVAL);
+ X (OPEN_FAILED, EIO);
+ X (OPEN_FILES, EAGAIN);
+ X (OUTOFMEMORY, ENOMEM);
+ X (PAGED_SYSTEM_RESOURCES, EAGAIN);
+ X (PAGEFILE_QUOTA, EAGAIN);
+ X (PATH_NOT_FOUND, ENOENT);
+ X (PIPE_BUSY, EBUSY);
+ X (PIPE_CONNECTED, EBUSY);
+ X (POSSIBLE_DEADLOCK, EDEADLK);
+ X (PRIVILEGE_NOT_HELD, EPERM);
+ X (PROCESS_ABORTED, EFAULT);
+ X (PROC_NOT_FOUND, ESRCH);
+ X (SECTOR_NOT_FOUND, EINVAL);
+ X (SEEK, EINVAL);
+ X (SERVICE_REQUEST_TIMEOUT, EBUSY);
+ X (SETMARK_DETECTED, EIO);
+ X (SHARING_BUFFER_EXCEEDED, ENOLCK);
+ X (SHARING_VIOLATION, EBUSY);
+ X (SIGNAL_PENDING, EBUSY);
+ X (SIGNAL_REFUSED, EIO);
+ X (THREAD_1_INACTIVE, EINVAL);
+ X (TIMEOUT, EBUSY);
+ X (TOO_MANY_LINKS, EMLINK);
+ X (TOO_MANY_OPEN_FILES, EMFILE);
+ X (UNEXP_NET_ERR, EIO);
+ X (WORKING_SET_QUOTA, EAGAIN);
+ X (WRITE_PROTECT, EROFS);
+#undef X
+
+#else
// List of errno macros from [cerrno.syn].
// C11 only defines EDOM, EILSEQ and ERANGE, the rest are from POSIX.
// They expand to integer constant expressions with type int,
// and distinct positive values, suitable for use in #if directives.
// POSIX adds more macros (but they're not defined on all targets,
- // see config/os/*/error_constants.h), and POSIX allows
+ // see config/os/.../error_constants.h), and POSIX allows
// EAGAIN == EWOULDBLOCK and ENOTSUP == EOPNOTSUPP.
#ifdef E2BIG
@@ -310,7 +486,8 @@ namespace
#ifdef EXDEV
case EXDEV:
#endif
- return std::error_condition(ev, std::generic_category());
+ case 0:
+ return std::error_condition(ev, generic_category_instance.obj);
/* Additional system-dependent mappings from non-standard error codes
* to one of the POSIX values above would go here, e.g.
@@ -318,14 +495,19 @@ namespace
return std::error_condition(EINVAL, std::generic_category());
*/
+#endif
default:
- return std::error_condition(ev, std::system_category());
+ return std::error_condition(ev, *this);
}
}
+
+ // Override this to avoid a virtual call to default_error_condition(i).
+ bool
+ equivalent(int i, const std::error_condition& cond) const noexcept final
+ { return system_error_category::default_error_condition(i) == cond; }
};
- const generic_error_category generic_category_instance{};
- const system_error_category system_category_instance{};
+ __constinit constant_init<system_error_category> system_category_instance{};
}
namespace std _GLIBCXX_VISIBILITY(default)
@@ -335,16 +517,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
__throw_system_error(int __i __attribute__((unused)))
{
- _GLIBCXX_THROW_OR_ABORT(system_error(error_code(__i, generic_category())));
+ _GLIBCXX_THROW_OR_ABORT(system_error(__i, generic_category_instance.obj));
}
error_category::~error_category() = default;
const error_category&
- _V2::system_category() noexcept { return system_category_instance; }
+ _V2::system_category() noexcept { return system_category_instance.obj; }
const error_category&
- _V2::generic_category() noexcept { return generic_category_instance; }
+ _V2::generic_category() noexcept { return generic_category_instance.obj; }
system_error::~system_error() = default;
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 2eac997..5b7f7ed 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -113,7 +113,7 @@ fs::absolute(const path& p, error_code& ec)
while (len > buf.size());
if (len == 0)
- ec.assign((int)GetLastError(), std::system_category());
+ ec = __last_system_error();
else
{
buf.resize(len);
@@ -353,7 +353,7 @@ fs::copy(const path& from, const path& to, copy_options options,
}
if (is_other(f) || is_other(t))
{
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::invalid_argument);
return;
}
if (is_directory(f) && is_regular_file(t))
@@ -412,7 +412,7 @@ fs::copy(const path& from, const path& to, copy_options options,
else
ec.clear();
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
}
@@ -435,7 +435,7 @@ fs::copy_file(const path& from, const path& to, copy_options options,
return do_copy_file(from.c_str(), to.c_str(), copy_file_options(options),
nullptr, nullptr, ec);
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
return false;
#endif
}
@@ -583,7 +583,7 @@ namespace
created = true;
}
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
return created;
}
@@ -631,7 +631,7 @@ fs::create_directory(const path& p, const path& attributes,
}
return create_dir(p, static_cast<perms>(st.st_mode), ec);
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
return false;
#endif
}
@@ -652,7 +652,7 @@ fs::create_directory_symlink(const path& to, const path& new_symlink,
error_code& ec) noexcept
{
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#else
create_symlink(to, new_symlink, ec);
#endif
@@ -682,9 +682,9 @@ fs::create_hard_link(const path& to, const path& new_hard_link,
if (CreateHardLinkW(new_hard_link.c_str(), to.c_str(), NULL))
ec.clear();
else
- ec.assign((int)GetLastError(), system_category());
+ ec = __last_system_error();
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
}
@@ -708,7 +708,7 @@ fs::create_symlink(const path& to, const path& new_symlink,
else
ec.clear();
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
}
@@ -776,7 +776,7 @@ fs::current_path(error_code& ec)
}
#endif // __GLIBC__
#else // _GLIBCXX_HAVE_UNISTD_H
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
return p;
}
@@ -799,7 +799,7 @@ fs::current_path(const path& p, error_code& ec) noexcept
else
ec.clear();
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
}
@@ -839,7 +839,7 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept
{
if (is_other(s1) && is_other(s2))
{
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::__unsupported();
return false;
}
ec.clear();
@@ -874,12 +874,12 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept
if (!h1 || !h2)
{
if (!h1 && !h2)
- ec.assign((int)GetLastError(), system_category());
+ ec = __last_system_error();
return false;
}
if (!h1.get_info() || !h2.get_info())
{
- ec.assign((int)GetLastError(), system_category());
+ ec = __last_system_error();
return false;
}
return h1.info.dwVolumeSerialNumber == h2.info.dwVolumeSerialNumber
@@ -897,7 +897,7 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept
ec.clear();
return false;
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
return false;
}
@@ -928,7 +928,7 @@ namespace
ec.clear();
return f(st);
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
return deflt;
#endif
}
@@ -953,10 +953,10 @@ fs::file_size(const path& p, error_code& ec) noexcept
if (s.type == file_type::directory)
ec = std::make_error_code(std::errc::is_a_directory);
else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::__unsupported();
}
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
return -1;
}
@@ -978,7 +978,7 @@ fs::hard_link_count(const path& p, error_code& ec) noexcept
return do_stat(p, ec, std::mem_fn(&stat_type::st_nlink),
static_cast<uintmax_t>(-1));
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
return static_cast<uintmax_t>(-1);
#endif
}
@@ -1026,7 +1026,7 @@ fs::last_write_time(const path& p, error_code& ec) noexcept
},
file_time_type::min());
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
return file_time_type::min();
#endif
}
@@ -1072,7 +1072,7 @@ fs::last_write_time(const path& p,
else
ec.clear();
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
}
@@ -1121,7 +1121,7 @@ fs::permissions(const path& p, perms prms, perm_options opts,
err = errno;
#else
if (nofollow && is_symlink(st))
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::__unsupported();
else if (posix::chmod(p.c_str(), static_cast<posix::mode_t>(prms)))
err = errno;
#endif
@@ -1206,7 +1206,7 @@ fs::path fs::read_symlink(const path& p, error_code& ec)
}
while (true);
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
return result;
}
@@ -1255,7 +1255,7 @@ fs::remove(const path& p, error_code& ec) noexcept
return true;
}
else if (!ec)
- ec.assign((int)GetLastError(), system_category());
+ ec = __last_system_error();
}
else if (status_known(st))
ec.clear();
@@ -1434,7 +1434,7 @@ fs::resize_file(const path& p, uintmax_t size)
void
fs::resize_file(const path& p, uintmax_t size, error_code& ec) noexcept
{
- if (size > static_cast<uintmax_t>(std::numeric_limits<off_t>::max()))
+ if (size > static_cast<uintmax_t>(std::numeric_limits<posix::off_t>::max()))
ec.assign(EINVAL, std::generic_category());
else if (posix::truncate(p.c_str(), size))
ec.assign(errno, std::generic_category());
diff --git a/libstdc++-v3/src/c++98/list.cc b/libstdc++-v3/src/c++98/list.cc
index 18f0e13..c2f5c43 100644
--- a/libstdc++-v3/src/c++98/list.cc
+++ b/libstdc++-v3/src/c++98/list.cc
@@ -94,6 +94,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_transfer(_List_node_base * const __first,
_List_node_base * const __last) _GLIBCXX_USE_NOEXCEPT
{
+ __glibcxx_assert(__first != __last);
+
if (this != __last)
{
// Remove [first, last) from its old position.
diff --git a/libstdc++-v3/src/filesystem/ops-common.h b/libstdc++-v3/src/filesystem/ops-common.h
index bf26c06..b314763 100644
--- a/libstdc++-v3/src/filesystem/ops-common.h
+++ b/libstdc++-v3/src/filesystem/ops-common.h
@@ -57,6 +57,42 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ // Get the last OS error (for POSIX this is just errno).
+ inline error_code
+ __last_system_error() noexcept
+ {
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+ return {(int)::GetLastError(), std::system_category()};
+#else
+ return {errno, std::generic_category()};
+#endif
+ }
+
+ // Get an error code indicating unsupported functionality.
+ //
+ // This should be used when a function is unable to behave as specified
+ // due to an incomplete or partial implementation, e.g.
+ // filesystem::equivalent(a, b) if is_other(a) && is_other(b) is true.
+ //
+ // Use errc::function_not_supported for functions that are entirely
+ // unimplemented, e.g. create_symlink on Windows.
+ //
+ // Use errc::invalid_argument for requests to perform operations outside
+ // the spec, e.g. trying to copy a directory using filesystem::copy_file.
+ inline error_code
+ __unsupported() noexcept
+ {
+#if defined ENOTSUP
+ return std::make_error_code(std::errc::not_supported);
+#elif defined EOPNOTSUPP
+ // This is supposed to be for socket operations
+ return std::make_error_code(std::errc::operation_not_supported);
+#else
+ return std::make_error_code(std::errc::invalid_argument);
+#endif
+ }
+
namespace filesystem
{
namespace __gnu_posix
@@ -116,6 +152,7 @@ namespace __gnu_posix
return -1;
}
+ using off_t = _off64_t;
inline int truncate(const wchar_t* path, _off64_t length)
{
const int fd = ::_wopen(path, _O_BINARY|_O_RDWR);
@@ -152,6 +189,7 @@ namespace __gnu_posix
using ::utime;
# endif
using ::rename;
+ using ::off_t;
# ifdef _GLIBCXX_HAVE_TRUNCATE
using ::truncate;
# else
@@ -171,15 +209,16 @@ namespace __gnu_posix
# endif
using char_type = char;
#else // ! _GLIBCXX_FILESYSTEM_IS_WINDOWS && ! _GLIBCXX_HAVE_UNISTD_H
- inline int open(const char*, int, ...) { errno = ENOTSUP; return -1; }
- inline int close(int) { errno = ENOTSUP; return -1; }
+ inline int open(const char*, int, ...) { errno = ENOSYS; return -1; }
+ inline int close(int) { errno = ENOSYS; return -1; }
using mode_t = int;
- inline int chmod(const char*, mode_t) { errno = ENOTSUP; return -1; }
- inline int mkdir(const char*, mode_t) { errno = ENOTSUP; return -1; }
- inline char* getcwd(char*, size_t) { errno = ENOTSUP; return nullptr; }
- inline int chdir(const char*) { errno = ENOTSUP; return -1; }
- inline int rename(const char*, const char*) { errno = ENOTSUP; return -1; }
- inline int truncate(const char*, long) { errno = ENOTSUP; return -1; }
+ inline int chmod(const char*, mode_t) { errno = ENOSYS; return -1; }
+ inline int mkdir(const char*, mode_t) { errno = ENOSYS; return -1; }
+ inline char* getcwd(char*, size_t) { errno = ENOSYS; return nullptr; }
+ inline int chdir(const char*) { errno = ENOSYS; return -1; }
+ inline int rename(const char*, const char*) { errno = ENOSYS; return -1; }
+ using off_t = long;
+ inline int truncate(const char*, off_t) { errno = ENOSYS; return -1; }
using char_type = char;
#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS
} // namespace __gnu_posix
@@ -362,7 +401,7 @@ _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
// 2712. copy_file() has a number of unspecified error conditions
if (!is_regular_file(f))
{
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::invalid_argument);
return false;
}
@@ -370,7 +409,7 @@ _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
{
if (!is_regular_file(t))
{
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::invalid_argument);
return false;
}
@@ -401,7 +440,7 @@ _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
}
else if (!is_regular_file(t))
{
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::invalid_argument);
return false;
}
}
@@ -558,9 +597,9 @@ _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
ec.clear();
}
else
- ec.assign((int)GetLastError(), std::system_category());
+ ec = std::__last_system_error();
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
}
#pragma GCC diagnostic pop
@@ -583,7 +622,7 @@ _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
} while (len > buf.size());
if (len == 0)
- ec.assign((int)GetLastError(), std::system_category());
+ ec = __last_system_error();
else
ec.clear();
diff --git a/libstdc++-v3/src/filesystem/ops.cc b/libstdc++-v3/src/filesystem/ops.cc
index b0a0f15..94b4123 100644
--- a/libstdc++-v3/src/filesystem/ops.cc
+++ b/libstdc++-v3/src/filesystem/ops.cc
@@ -293,7 +293,7 @@ fs::copy(const path& from, const path& to, copy_options options,
}
if (is_other(f) || is_other(t))
{
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::invalid_argument);
return;
}
if (is_directory(f) && is_regular_file(t))
@@ -372,7 +372,7 @@ fs::copy_file(const path& from, const path& to, copy_options options,
return do_copy_file(from.c_str(), to.c_str(), copy_file_options(options),
nullptr, nullptr, ec);
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
return false;
#endif
}
@@ -491,7 +491,7 @@ namespace
created = true;
}
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
return created;
}
@@ -539,7 +539,7 @@ fs::create_directory(const path& p, const path& attributes,
}
return create_dir(p, static_cast<perms>(st.st_mode), ec);
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
return false;
#endif
}
@@ -560,7 +560,7 @@ fs::create_directory_symlink(const path& to, const path& new_symlink,
error_code& ec) noexcept
{
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#else
create_symlink(to, new_symlink, ec);
#endif
@@ -590,9 +590,9 @@ fs::create_hard_link(const path& to, const path& new_hard_link,
if (CreateHardLinkW(new_hard_link.c_str(), to.c_str(), NULL))
ec.clear();
else
- ec.assign((int)GetLastError(), system_category());
+ ec = __last_system_error();
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
}
@@ -616,7 +616,7 @@ fs::create_symlink(const path& to, const path& new_symlink,
else
ec.clear();
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
}
@@ -683,7 +683,7 @@ fs::current_path(error_code& ec)
}
#endif // __GLIBC__
#else // _GLIBCXX_HAVE_UNISTD_H
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
return p;
}
@@ -706,7 +706,7 @@ fs::current_path(const path& p, error_code& ec) noexcept
else
ec.clear();
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
}
@@ -746,7 +746,7 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept
{
if (is_other(s1) && is_other(s2))
{
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::__unsupported();
return false;
}
ec.clear();
@@ -762,7 +762,7 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept
ec.clear();
return false;
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
return false;
}
@@ -793,7 +793,7 @@ namespace
ec.clear();
return f(st);
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
return deflt;
#endif
}
@@ -817,7 +817,7 @@ fs::file_size(const path& p, error_code& ec) noexcept
if (s.type == file_type::directory)
ec = std::make_error_code(std::errc::is_a_directory);
else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::__unsupported();
}
return -1;
}
@@ -920,7 +920,7 @@ fs::last_write_time(const path& p __attribute__((__unused__)),
else
ec.clear();
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
}
@@ -967,7 +967,7 @@ fs::permissions(const path& p, perms prms, error_code& ec) noexcept
err = errno;
#else
if (nofollow && is_symlink(st))
- ec = std::make_error_code(std::errc::operation_not_supported);
+ ec = std::__unsupported();
else if (posix::chmod(p.c_str(), static_cast<mode_t>(prms)))
err = errno;
#endif
@@ -1032,7 +1032,7 @@ fs::path fs::read_symlink(const path& p [[gnu::unused]], error_code& ec)
}
while (true);
#else
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::make_error_code(std::errc::function_not_supported);
#endif
return result;
}
@@ -1062,7 +1062,7 @@ fs::remove(const path& p, error_code& ec) noexcept
return true;
}
else if (!ec)
- ec.assign((int)GetLastError(), system_category());
+ ec = __last_system_error();
}
else if (status_known(st))
ec.clear();
@@ -1153,16 +1153,12 @@ fs::resize_file(const path& p, uintmax_t size)
void
fs::resize_file(const path& p, uintmax_t size, error_code& ec) noexcept
{
-#ifdef _GLIBCXX_HAVE_UNISTD_H
- if (size > static_cast<uintmax_t>(std::numeric_limits<off_t>::max()))
+ if (size > static_cast<uintmax_t>(std::numeric_limits<posix::off_t>::max()))
ec.assign(EINVAL, std::generic_category());
else if (posix::truncate(p.c_str(), size))
ec.assign(errno, std::generic_category());
else
ec.clear();
-#else
- ec = std::make_error_code(std::errc::not_supported);
-#endif
}
@@ -1280,7 +1276,7 @@ fs::system_complete(const path& p, error_code& ec)
|| p.root_name() == base.root_name())
return absolute(p, base);
// else TODO
- ec = std::make_error_code(std::errc::not_supported);
+ ec = std::__unsupported();
return {};
#else
if (ec.value())
diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_category/102425.cc b/libstdc++-v3/testsuite/19_diagnostics/error_category/102425.cc
new file mode 100644
index 0000000..069b5e2
--- /dev/null
+++ b/libstdc++-v3/testsuite/19_diagnostics/error_category/102425.cc
@@ -0,0 +1,18 @@
+// { dg-do run { target c++11 } }
+#include <system_error>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ // PR libstdc++/102425
+ VERIFY( std::error_code() == std::error_condition() );
+
+ auto zero = std::system_category().default_error_condition(0);
+ // This is the condition that the equality above relies on:
+ VERIFY( zero.category() == std::generic_category() );
+}
+
+int main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc b/libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc
index 855f528..c289d53 100644
--- a/libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc
+++ b/libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc
@@ -34,6 +34,19 @@ test02()
const std::error_category& cat = std::system_category();
std::error_condition cond;
+#if defined __MING32__ || defined __MINGW64__
+ cond = cat.default_error_condition(8); // ERROR_NOT_ENOUGH_MEMORY
+ VERIFY( cond.value() == ENOMEM );
+ VERIFY( cond.category() == std::generic_category() );
+ VERIFY( cond == std::errc::not_enough_memory );
+
+ cond = cat.default_error_condition(5); // ERROR_ACCESS_DENIED
+ VERIFY( cond.value() == EACCES );
+ VERIFY( cond.category() == std::generic_category() );
+ VERIFY( cond == std::errc::permission_denied );
+ return;
+#endif
+
// As of 2011, ISO C only defines EDOM, EILSEQ and ERANGE:
cond = cat.default_error_condition(EDOM);
VERIFY( cond.value() == EDOM );
@@ -99,8 +112,13 @@ test03()
// set "C" locale to get expected message
auto loc = std::locale::global(std::locale::classic());
+#if defined __MING32__ || defined __MINGW64__
+ std::string msg = std::system_category().message(5); // ERROR_ACCESS_DENIED
+ VERIFY(msg == "Access denied");
+#else
std::string msg = std::system_category().message(EBADF);
VERIFY( msg.find("file") != std::string::npos );
+#endif
std::locale::global(loc);
}
diff --git a/libstdc++-v3/testsuite/19_diagnostics/headers/system_error/93151.cc b/libstdc++-v3/testsuite/19_diagnostics/headers/system_error/93151.cc
index c54c9a3..6aca63d 100644
--- a/libstdc++-v3/testsuite/19_diagnostics/headers/system_error/93151.cc
+++ b/libstdc++-v3/testsuite/19_diagnostics/headers/system_error/93151.cc
@@ -1,4 +1,5 @@
// { dg-do compile { target c++11 } }
+// { dg-add-options no_pch }
// Copyright (C) 2020-2021 Free Software Foundation, Inc.
//
diff --git a/libstdc++-v3/testsuite/19_diagnostics/system_error/cons-1.cc b/libstdc++-v3/testsuite/19_diagnostics/system_error/cons-1.cc
index effb670..168a6fc 100644
--- a/libstdc++-v3/testsuite/19_diagnostics/system_error/cons-1.cc
+++ b/libstdc++-v3/testsuite/19_diagnostics/system_error/cons-1.cc
@@ -26,19 +26,19 @@ int main()
{
const std::string s("too late: boulangerie out of pain au raisin");
const std::error_code
- e(std::make_error_code(std::errc::operation_not_supported));
+ e(std::make_error_code(std::errc::invalid_argument));
// 1
{
std::system_error err1(e, s);
- VERIFY( err1.code() == e );
+ VERIFY( err1.code() == e );
VERIFY( std::string(err1.what()).find(s) != std::string::npos );
}
// 2
{
std::system_error err2(95, std::system_category(), s);
- VERIFY( err2.code() == std::error_code(95, std::system_category()) );
+ VERIFY( err2.code() == std::error_code(95, std::system_category()) );
VERIFY( std::string((err2.what(), s)).find(s) != std::string::npos );
}
diff --git a/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc b/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc
index 3e80b73..a18e05e 100644
--- a/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc
@@ -26,4 +26,4 @@ struct D : B { };
D d;
std::default_delete<B[]> db;
typedef decltype(db(&d)) type; // { dg-error "no match" }
-// { dg-prune-output "no type named 'type' in 'struct std::enable_if" }
+// { dg-prune-output "enable_if" }
diff --git a/libstdc++-v3/testsuite/20_util/forward/c_neg.cc b/libstdc++-v3/testsuite/20_util/forward/c_neg.cc
index dc7ec51..3875792 100644
--- a/libstdc++-v3/testsuite/20_util/forward/c_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/forward/c_neg.cc
@@ -17,7 +17,7 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-error "must not be an lvalue reference" "" { target *-*-* } 0 }
+// { dg-error "convert an rvalue to an lvalue" "" { target *-*-* } 0 }
#include <list>
diff --git a/libstdc++-v3/testsuite/20_util/forward/f_neg.cc b/libstdc++-v3/testsuite/20_util/forward/f_neg.cc
index 4ccd726..51ccaf2 100644
--- a/libstdc++-v3/testsuite/20_util/forward/f_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/forward/f_neg.cc
@@ -17,7 +17,7 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-error "must not be an lvalue reference" "" { target *-*-* } 0 }
+// { dg-error "convert an rvalue to an lvalue" "" { target *-*-* } 0 }
#include <utility>
diff --git a/libstdc++-v3/testsuite/20_util/integer_comparisons/greater.cc b/libstdc++-v3/testsuite/20_util/integer_comparisons/greater.cc
new file mode 100644
index 0000000..e564d8d
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/integer_comparisons/greater.cc
@@ -0,0 +1,61 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do run { target c++20 } }
+
+#include <utility>
+#include <limits>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ unsigned int u = std::numeric_limits<unsigned int>::max();
+ int s = -1;
+ VERIFY( !std::cmp_greater(s, u) );
+ VERIFY( std::cmp_greater(u, s) );
+ u = (unsigned) std::numeric_limits<int>::max() + 1U;
+ VERIFY( !std::cmp_greater(s, u) );
+ VERIFY( std::cmp_greater(u, s) );
+}
+
+constexpr bool
+test02()
+{
+ unsigned int u = std::numeric_limits<unsigned int>::max();
+ int s = -1;
+ if (std::cmp_greater(s, u))
+ throw 1;
+ if (!std::cmp_greater(u, s))
+ throw 2;
+ return true;
+}
+
+void
+test03()
+{
+ short ss = -1;
+ int s = -1;
+ VERIFY( !std::cmp_greater(s, ss) );
+ VERIFY( !std::cmp_greater(ss, s) );
+
+ unsigned int u = (unsigned int) -1;
+ VERIFY( !std::cmp_greater(s, u) );
+ VERIFY( std::cmp_greater(u, s) );
+ VERIFY( !std::cmp_greater(ss, u) );
+ VERIFY( std::cmp_greater(u, ss) );
+
+ unsigned long long ul = (unsigned long long) -1;
+ VERIFY( !std::cmp_greater(s, ul) );
+ VERIFY( std::cmp_greater(ul, s) );
+ VERIFY( !std::cmp_greater(ss, ul) );
+ VERIFY( std::cmp_greater(ul, ss) );
+ VERIFY( !std::cmp_greater(u, ul) );
+ VERIFY( std::cmp_greater(ul, u) );
+}
+
+int
+main()
+{
+ test01();
+ static_assert( test02() );
+ test03();
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.h b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.h
index 62b3db8..d6f166b 100644
--- a/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.h
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.h
@@ -285,7 +285,9 @@ void test01()
static_assert(test_property<is_nothrow_swappable,
std::queue<ThrowCopyConsClass>>(true), "");
static_assert(test_property<is_nothrow_swappable,
- std::priority_queue<ThrowCopyConsClass>>(true), "");
+ std::priority_queue<ThrowCopyConsClass,
+ std::vector<ThrowCopyConsClass>,
+ comps::CompareNoThrowCopyable>>(true), "");
static_assert(test_property<is_nothrow_swappable,
std::stack<ThrowCopyConsClass>>(true), "");
static_assert(test_property<is_nothrow_swappable,
diff --git a/libstdc++-v3/testsuite/20_util/is_swappable/value.h b/libstdc++-v3/testsuite/20_util/is_swappable/value.h
index 2f7a00b..eb3f96d 100644
--- a/libstdc++-v3/testsuite/20_util/is_swappable/value.h
+++ b/libstdc++-v3/testsuite/20_util/is_swappable/value.h
@@ -55,6 +55,13 @@ namespace funny {
{
friend void swap(F3&, F3) {}
};
+
+ struct DummyCmp
+ {
+ template<class T>
+ bool operator()(const T&, const T&) const
+ { return false; }
+ };
}
void test01()
{
@@ -152,7 +159,9 @@ void test01()
static_assert(test_property<is_swappable,
std::priority_queue<int>[1][2][3]>(true), "");
static_assert(test_property<is_swappable,
- std::priority_queue<construct::Nontrivial>>(true), "");
+ std::priority_queue<construct::Nontrivial,
+ std::vector<construct::Nontrivial>,
+ funny::DummyCmp>>(true), "");
static_assert(test_property<is_swappable,
std::stack<int>>(true), "");
static_assert(test_property<is_swappable,
diff --git a/libstdc++-v3/testsuite/20_util/is_trivially_constructible/value.cc b/libstdc++-v3/testsuite/20_util/is_trivially_constructible/value.cc
index 488ea75..fd1fbb0 100644
--- a/libstdc++-v3/testsuite/20_util/is_trivially_constructible/value.cc
+++ b/libstdc++-v3/testsuite/20_util/is_trivially_constructible/value.cc
@@ -105,7 +105,7 @@ void test01()
static_assert(test_property<is_trivially_constructible,
PODType, const PODType&>(true), "");
static_assert(test_property<is_trivially_constructible,
- PODType, int, int>(false), "");
+ PODType, int, int>(__cplusplus >= 202002L), "");
static_assert(test_property<is_trivially_constructible,
NType>(false), "");
static_assert(test_property<is_trivially_constructible,
diff --git a/libstdc++-v3/testsuite/20_util/move_only_function/call.cc b/libstdc++-v3/testsuite/20_util/move_only_function/call.cc
new file mode 100644
index 0000000..9ca0a60
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/move_only_function/call.cc
@@ -0,0 +1,199 @@
+// { dg-options "-std=gnu++23" }
+// { dg-do run { target c++23 } }
+
+#include <functional>
+#include <utility>
+#include <testsuite_hooks.h>
+
+using std::move_only_function;
+
+using std::is_same_v;
+using std::is_invocable_v;
+using std::is_nothrow_invocable_v;
+using std::invoke_result_t;
+
+// Check return types
+static_assert( is_same_v<void, invoke_result_t<move_only_function<void()>>> );
+static_assert( is_same_v<int, invoke_result_t<move_only_function<int()>>> );
+static_assert( is_same_v<int&, invoke_result_t<move_only_function<int&()>>> );
+
+// With const qualifier
+static_assert( ! is_invocable_v< move_only_function<void()> const > );
+static_assert( ! is_invocable_v< move_only_function<void()> const &> );
+static_assert( is_invocable_v< move_only_function<void() const> > );
+static_assert( is_invocable_v< move_only_function<void() const> &> );
+static_assert( is_invocable_v< move_only_function<void() const> const > );
+static_assert( is_invocable_v< move_only_function<void() const> const &> );
+
+// With no ref-qualifier
+static_assert( is_invocable_v< move_only_function<void()> > );
+static_assert( is_invocable_v< move_only_function<void()> &> );
+static_assert( is_invocable_v< move_only_function<void() const> > );
+static_assert( is_invocable_v< move_only_function<void() const> &> );
+static_assert( is_invocable_v< move_only_function<void() const> const > );
+static_assert( is_invocable_v< move_only_function<void() const> const &> );
+
+// With & ref-qualifier
+static_assert( ! is_invocable_v< move_only_function<void()&> > );
+static_assert( is_invocable_v< move_only_function<void()&> &> );
+static_assert( is_invocable_v< move_only_function<void() const&> > );
+static_assert( is_invocable_v< move_only_function<void() const&> &> );
+static_assert( is_invocable_v< move_only_function<void() const&> const > );
+static_assert( is_invocable_v< move_only_function<void() const&> const &> );
+
+// With && ref-qualifier
+static_assert( is_invocable_v< move_only_function<void()&&> > );
+static_assert( ! is_invocable_v< move_only_function<void()&&> &> );
+static_assert( is_invocable_v< move_only_function<void() const&&> > );
+static_assert( ! is_invocable_v< move_only_function<void() const&&> &> );
+static_assert( is_invocable_v< move_only_function<void() const&&> const > );
+static_assert( ! is_invocable_v< move_only_function<void() const&&> const &> );
+
+// With noexcept-specifier
+static_assert( ! is_nothrow_invocable_v< move_only_function<void()> > );
+static_assert( ! is_nothrow_invocable_v< move_only_function<void() noexcept(false)> > );
+static_assert( is_nothrow_invocable_v< move_only_function<void() noexcept> > );
+static_assert( is_nothrow_invocable_v< move_only_function<void()& noexcept>& > );
+
+void
+test01()
+{
+ struct F
+ {
+ int operator()() { return 0; }
+ int operator()() const { return 1; }
+ };
+
+ move_only_function<int()> f0{F{}};
+ VERIFY( f0() == 0 );
+ VERIFY( std::move(f0)() == 0 );
+
+ move_only_function<int() const> f1{F{}};
+ VERIFY( f1() == 1 );
+ VERIFY( std::as_const(f1)() == 1 );
+ VERIFY( std::move(f1)() == 1 );
+ VERIFY( std::move(std::as_const(f1))() == 1 );
+
+ move_only_function<int()&> f2{F{}};
+ VERIFY( f2() == 0 );
+ // Not rvalue-callable: std::move(f2)()
+
+ move_only_function<int() const&> f3{F{}};
+ VERIFY( f3() == 1 );
+ VERIFY( std::as_const(f3)() == 1 );
+ VERIFY( std::move(f3)() == 1 );
+ VERIFY( std::move(std::as_const(f3))() == 1 );
+
+ move_only_function<int()&&> f4{F{}};
+ // Not lvalue-callable: f4()
+ VERIFY( std::move(f4)() == 0 );
+
+ move_only_function<int() const&&> f5{F{}};
+ // Not lvalue-callable: f5()
+ VERIFY( std::move(f5)() == 1 );
+ VERIFY( std::move(std::as_const(f5))() == 1 );
+}
+
+void
+test02()
+{
+ struct F
+ {
+ int operator()() & { return 0; }
+ int operator()() && { return 1; }
+ };
+
+ move_only_function<int()> f0{F{}};
+ VERIFY( f0() == 0 );
+ VERIFY( std::move(f0)() == 0 );
+
+ move_only_function<int()&&> f1{F{}};
+ // Not lvalue callable: f1()
+ VERIFY( std::move(f1)() == 1 );
+
+ move_only_function<int()&> f2{F{}};
+ VERIFY( f2() == 0 );
+ // Not rvalue-callable: std::move(f2)()
+}
+
+void
+test03()
+{
+ struct F
+ {
+ int operator()() const & { return 0; }
+ int operator()() && { return 1; }
+ };
+
+ move_only_function<int()> f0{F{}};
+ VERIFY( f0() == 0 );
+ VERIFY( std::move(f0)() == 0 );
+
+ move_only_function<int()&&> f1{F{}};
+ // Not lvalue callable: f1()
+ VERIFY( std::move(f1)() == 1 );
+
+ move_only_function<int() const> f2{F{}};
+ VERIFY( f2() == 0 );
+ VERIFY( std::as_const(f2)() == 0 );
+ VERIFY( std::move(f2)() == 0 );
+ VERIFY( std::move(std::as_const(f2))() == 0 );
+
+ move_only_function<int() const &&> f3{F{}};
+ // Not lvalue callable: f3()
+ VERIFY( std::move(f3)() == 0 );
+ VERIFY( std::move(std::as_const(f3))() == 0 );
+
+ move_only_function<int() const &> f4{F{}};
+ VERIFY( f4() == 0 );
+ VERIFY( std::as_const(f4)() == 0 );
+ // Not rvalue-callable: std::move(f4)()
+}
+
+void
+test04()
+{
+ struct F
+ {
+ int operator()() & { return 0; }
+ int operator()() && { return 1; }
+ int operator()() const & { return 2; }
+ int operator()() const && { return 3; }
+ };
+
+ move_only_function<int()> f0{F{}};
+ VERIFY( f0() == 0 );
+ VERIFY( std::move(f0)() == 0 );
+
+ move_only_function<int()&> f1{F{}};
+ VERIFY( f1() == 0 );
+ // Not rvalue-callable: std::move(f1)()
+
+ move_only_function<int()&&> f2{F{}};
+ // Not lvalue callable: f2()
+ VERIFY( std::move(f2)() == 1 );
+
+ move_only_function<int() const> f3{F{}};
+ VERIFY( f3() == 2 );
+ VERIFY( std::as_const(f3)() == 2 );
+ VERIFY( std::move(f3)() == 2 );
+ VERIFY( std::move(std::as_const(f3))() == 2 );
+
+ move_only_function<int() const &> f4{F{}};
+ VERIFY( f4() == 2 );
+ VERIFY( std::as_const(f4)() == 2 );
+ // Not rvalue-callable: std::move(f4)()
+
+ move_only_function<int() const &&> f5{F{}};
+ // Not lvalue callable: f5()
+ VERIFY( std::move(f5)() == 3 );
+ VERIFY( std::move(std::as_const(f5))() == 3 );
+}
+
+int main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+}
diff --git a/libstdc++-v3/testsuite/20_util/move_only_function/cons.cc b/libstdc++-v3/testsuite/20_util/move_only_function/cons.cc
new file mode 100644
index 0000000..0992f10
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/move_only_function/cons.cc
@@ -0,0 +1,98 @@
+// { dg-options "-std=gnu++23" }
+// { dg-do compile { target c++23 } }
+
+#include <functional>
+
+#ifndef __cpp_lib_move_only_function
+# error "Feature-test macro for move_only_function missing in <functional>"
+#elif __cpp_lib_move_only_function != 202110L
+# error "Feature-test macro for move_only_function has wrong value in <functional>"
+#endif
+
+using std::move_only_function;
+
+using std::is_constructible_v;
+using std::is_copy_constructible_v;
+using std::is_nothrow_default_constructible_v;
+using std::is_nothrow_move_constructible_v;
+using std::is_nothrow_constructible_v;
+using std::nullptr_t;
+using std::in_place_type_t;
+
+static_assert( is_nothrow_default_constructible_v<move_only_function<void()>> );
+static_assert( is_nothrow_constructible_v<move_only_function<void()>, nullptr_t> );
+static_assert( is_nothrow_move_constructible_v<move_only_function<void()>> );
+static_assert( ! is_copy_constructible_v<move_only_function<void()>> );
+
+static_assert( is_constructible_v<move_only_function<void()>, void()> );
+static_assert( is_constructible_v<move_only_function<void()>, void(&)()> );
+static_assert( is_constructible_v<move_only_function<void()>, void(*)()> );
+static_assert( is_constructible_v<move_only_function<void()>, int()> );
+static_assert( is_constructible_v<move_only_function<void()>, int(&)()> );
+static_assert( is_constructible_v<move_only_function<void()>, int(*)()> );
+static_assert( ! is_constructible_v<move_only_function<void()>, void(int)> );
+static_assert( is_constructible_v<move_only_function<void(int)>, void(int)> );
+
+static_assert( is_constructible_v<move_only_function<void(int)>,
+ in_place_type_t<void(*)(int)>, void(int)> );
+
+static_assert( is_constructible_v<move_only_function<void()>,
+ void() noexcept> );
+static_assert( is_constructible_v<move_only_function<void() noexcept>,
+ void() noexcept> );
+static_assert( ! is_constructible_v<move_only_function<void() noexcept>,
+ void() > );
+
+struct Q
+{
+ void operator()() const &;
+ void operator()() &&;
+};
+
+static_assert( is_constructible_v<move_only_function<void()>, Q> );
+static_assert( is_constructible_v<move_only_function<void() const>, Q> );
+static_assert( is_constructible_v<move_only_function<void() &>, Q> );
+static_assert( is_constructible_v<move_only_function<void() const &>, Q> );
+static_assert( is_constructible_v<move_only_function<void() &&>, Q> );
+static_assert( is_constructible_v<move_only_function<void() const &&>, Q> );
+
+struct R
+{
+ void operator()() &;
+ void operator()() &&;
+};
+
+static_assert( is_constructible_v<move_only_function<void()>, R> );
+static_assert( is_constructible_v<move_only_function<void()&>, R> );
+static_assert( is_constructible_v<move_only_function<void()&&>, R> );
+static_assert( ! is_constructible_v<move_only_function<void() const>, R> );
+static_assert( ! is_constructible_v<move_only_function<void() const&>, R> );
+static_assert( ! is_constructible_v<move_only_function<void() const&&>, R> );
+
+// The following nothrow-constructible guarantees are a GCC extension,
+// not required by the standard.
+
+static_assert( is_nothrow_constructible_v<move_only_function<void()>, void()> );
+static_assert( is_nothrow_constructible_v<move_only_function<void(int)>,
+ in_place_type_t<void(*)(int)>,
+ void(int)> );
+
+// These types are all small and nothrow move constructible
+struct F { void operator()(); };
+struct G { void operator()() const; };
+static_assert( is_nothrow_constructible_v<move_only_function<void()>, F> );
+static_assert( is_nothrow_constructible_v<move_only_function<void()>, G> );
+static_assert( is_nothrow_constructible_v<move_only_function<void() const>, G> );
+
+struct H {
+ H(int);
+ H(int, int) noexcept;
+ void operator()() noexcept;
+};
+static_assert( is_nothrow_constructible_v<move_only_function<void()>, H> );
+static_assert( is_nothrow_constructible_v<move_only_function<void() noexcept>,
+ H> );
+static_assert( ! is_nothrow_constructible_v<move_only_function<void() noexcept>,
+ in_place_type_t<H>, int> );
+static_assert( is_nothrow_constructible_v<move_only_function<void() noexcept>,
+ in_place_type_t<H>, int, int> );
diff --git a/libstdc++-v3/testsuite/20_util/move_only_function/move.cc b/libstdc++-v3/testsuite/20_util/move_only_function/move.cc
new file mode 100644
index 0000000..f1f0fb5
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/move_only_function/move.cc
@@ -0,0 +1,109 @@
+// { dg-options "-std=gnu++23" }
+// { dg-do run { target c++23 } }
+
+#include <functional>
+#include <testsuite_hooks.h>
+
+using std::move_only_function;
+
+void
+test01()
+{
+ // Small type with non-throwing move constructor. Not allocated on the heap.
+ struct F
+ {
+ F() = default;
+ F(const F& f) : counters(f.counters) { ++counters.copy; }
+ F(F&& f) noexcept : counters(f.counters) { ++counters.move; }
+
+ F& operator=(F&&) = delete;
+
+ struct Counters
+ {
+ int copy = 0;
+ int move = 0;
+ } counters;
+
+ const Counters& operator()() const { return counters; }
+ };
+
+ F f;
+ std::move_only_function<const F::Counters&() const> m1(f);
+ VERIFY( m1().copy == 1 );
+ VERIFY( m1().move == 0 );
+
+ // This will move construct a new target object and destroy the old one:
+ auto m2 = std::move(m1);
+ VERIFY( m1 == nullptr && m2 != nullptr );
+ VERIFY( m2().copy == 1 );
+ VERIFY( m2().move == 1 );
+
+ m1 = std::move(m2);
+ VERIFY( m1 != nullptr && m2 == nullptr );
+ VERIFY( m1().copy == 1 );
+ VERIFY( m1().move == 2 );
+
+ m2 = std::move(f);
+ VERIFY( m2().copy == 0 );
+ VERIFY( m2().move == 2 ); // Move construct target object, then swap into m2.
+ const int moves = m1().move + m2().move;
+ // This will do three moves:
+ swap(m1, m2);
+ VERIFY( m1().copy == 0 );
+ VERIFY( m2().copy == 1 );
+ VERIFY( (m1().move + m2().move) == (moves + 3) );
+}
+
+void
+test02()
+{
+ // Move constructor is potentially throwing. Allocated on the heap.
+ struct F
+ {
+ F() = default;
+ F(const F& f) noexcept : counters(f.counters) { ++counters.copy; }
+ F(F&& f) noexcept(false) : counters(f.counters) { ++counters.move; }
+
+ F& operator=(F&&) = delete;
+
+ struct Counters
+ {
+ int copy = 0;
+ int move = 0;
+ } counters;
+
+ Counters operator()() const noexcept { return counters; }
+ };
+
+ F f;
+ std::move_only_function<F::Counters() const> m1(f);
+ VERIFY( m1().copy == 1 );
+ VERIFY( m1().move == 0 );
+
+ // The target object is on the heap so this just moves a pointer:
+ auto m2 = std::move(m1);
+ VERIFY( m1 == nullptr && m2 != nullptr );
+ VERIFY( m2().copy == 1 );
+ VERIFY( m2().move == 0 );
+
+ m1 = std::move(m2);
+ VERIFY( m1 != nullptr && m2 == nullptr );
+ VERIFY( m1().copy == 1 );
+ VERIFY( m1().move == 0 );
+
+ m2 = std::move(f);
+ VERIFY( m2().copy == 0 );
+ VERIFY( m2().move == 1 );
+ const int moves = m1().move + m2().move;
+ // This just swaps the pointers, so no moves:
+ swap(m1, m2);
+ VERIFY( m1().copy == 0 );
+ VERIFY( m2().copy == 1 );
+ VERIFY( (m1().move + m2().move) == moves );
+}
+
+int main()
+{
+ test01();
+ test02();
+}
diff --git a/libstdc++-v3/testsuite/20_util/move_only_function/version.cc b/libstdc++-v3/testsuite/20_util/move_only_function/version.cc
new file mode 100644
index 0000000..9fe52f4
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/move_only_function/version.cc
@@ -0,0 +1,10 @@
+// { dg-options "-std=gnu++23" }
+// { dg-do compile { target c++23 } }
+
+#include <version>
+
+#ifndef __cpp_lib_move_only_function
+# error "Feature-test macro for move_only_function missing in <version>"
+#elif __cpp_lib_move_only_function != 202110L
+# error "Feature-test macro for move_only_function has wrong value in <version>"
+#endif
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/memory_management_tools/destroy_neg.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/memory_management_tools/destroy_neg.cc
index e114168..dfdead4 100644
--- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/memory_management_tools/destroy_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/memory_management_tools/destroy_neg.cc
@@ -47,5 +47,3 @@ test02()
}
// { dg-error "value type is destructible" "" { target *-*-* } 0 }
-// { dg-error "use of deleted function" "" { target c++20 } 0 }
-// { dg-error "is private within this context" "" { target c++20 } 0 }
diff --git a/libstdc++-v3/testsuite/20_util/variant/visit_inherited.cc b/libstdc++-v3/testsuite/20_util/variant/visit_inherited.cc
new file mode 100644
index 0000000..ade8309
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/variant/visit_inherited.cc
@@ -0,0 +1,36 @@
+// { dg-do compile { target c++17 } }
+
+#include <variant>
+
+// P2062R2 Inheriting from std::variant (resolving LWG 3052)
+
+#if __cpp_lib_variant < 202102L
+#error __cpp_lib_variant has the wrong value in <variant>
+#endif
+
+struct V : std::variant<int> {
+ using std::variant<int>::variant;
+};
+
+constexpr int
+test01()
+{
+ V v = 42;
+ return std::visit([](int&){ return 17; }, v);
+}
+static_assert( test01() == 17 );
+
+constexpr int
+test02()
+{
+ const V c = 77;
+ std::variant<char*, long> x = 88L;
+ return std::visit([](auto&& a, auto&& b) {
+ if constexpr (std::is_same_v<decltype(a), const int&&>)
+ if constexpr (std::is_same_v<decltype(b), long&&>)
+ return 99;
+ return 0;
+ },
+ std::move(c), std::move(x));
+}
+static_assert( test02() == 99 );
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/nullptr.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/nullptr.cc
new file mode 100644
index 0000000..fdb24ae
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/nullptr.cc
@@ -0,0 +1,4 @@
+// { dg-do compile { target c++11 } }
+#include <string>
+
+std::string s = nullptr; // { dg-error "deleted" "P2166R1" }
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/cons/char/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/cons/char/nonnull.cc
index b33af08..f42f95e 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string_view/cons/char/nonnull.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/cons/char/nonnull.cc
@@ -25,5 +25,5 @@ test01()
{
std::string_view s((const char*)nullptr); // { dg-warning "\\\[-Wnonnull" }
std::string_view t((char*)nullptr); // { dg-warning "\\\[-Wnonnull" }
- std::string_view u(nullptr); // { dg-warning "\\\[-Wnonnull" }
+ std::string_view u(nullptr); // { dg-error "deleted" }
}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/cons/wchar_t/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/cons/wchar_t/nonnull.cc
index 4c10131..e480f7c 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string_view/cons/wchar_t/nonnull.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/cons/wchar_t/nonnull.cc
@@ -25,5 +25,5 @@ test01()
{
std::wstring_view s((const wchar_t*)nullptr); // { dg-warning "\\\[-Wnonnull" }
std::wstring_view t((wchar_t*)nullptr); // { dg-warning "\\\[-Wnonnull" }
- std::wstring_view u(nullptr); // { dg-warning "\\\[-Wnonnull" }
+ std::wstring_view u(nullptr); // { dg-error "deleted" }
}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/trivially_copyable.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/trivially_copyable.cc
new file mode 100644
index 0000000..3f2589c
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/trivially_copyable.cc
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++17 } }
+
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2251r1.pdf
+
+#include <string_view>
+
+static_assert( std::is_trivially_copyable_v<std::string_view> );
+static_assert( std::is_trivially_copyable_v<std::wstring_view> );
+
+struct traits : std::char_traits<char> { };
+static_assert( std::is_trivially_copyable_v<std::basic_string_view<char, traits>> );
diff --git a/libstdc++-v3/testsuite/23_containers/deque/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/deque/cons/deduction.cc
index 8a38351..5cb0a58 100644
--- a/libstdc++-v3/testsuite/23_containers/deque/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/deque/cons/deduction.cc
@@ -19,6 +19,7 @@
#include <deque>
#include <testsuite_iterators.h>
+#include <testsuite_allocator.h>
template<typename T>
using input_iterator_seq
@@ -67,3 +68,31 @@ test02()
std::deque s4(1U, 2L, std::allocator<long>());
check_type<std::deque<long>>(s4);
}
+
+struct Pool;
+
+template<typename T>
+struct Alloc : __gnu_test::SimpleAllocator<T>
+{
+ Alloc(Pool*) { }
+
+ template<typename U>
+ Alloc(const Alloc<U>&) { }
+};
+
+void
+test_p1518r2()
+{
+ // P1518R2 - Stop overconstraining allocators in container deduction guides.
+ // This is a C++23 feature but we support it for C++17 too.
+
+ using Deque = std::deque<unsigned, Alloc<unsigned>>;
+ Pool* p = nullptr;
+ Deque d(p);
+
+ std::deque s1(d, p);
+ check_type<Deque>(s1);
+
+ std::deque s2(std::move(d), p);
+ check_type<Deque>(s2);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/deque/requirements/explicit_instantiation/3.cc b/libstdc++-v3/testsuite/23_containers/deque/requirements/explicit_instantiation/3.cc
index 0cbedf4..2a23eaa 100644
--- a/libstdc++-v3/testsuite/23_containers/deque/requirements/explicit_instantiation/3.cc
+++ b/libstdc++-v3/testsuite/23_containers/deque/requirements/explicit_instantiation/3.cc
@@ -22,7 +22,7 @@
// { dg-do compile }
// The extension that implicitly rebinds allocators is in gnu++98/11/14/17 only
-// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" } }
+// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" "-D_GLIBCXX_CONCEPT_CHECKS*" } }
// libstdc++/21770
template class std::deque<int, std::allocator<char> >;
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/forward_list/cons/deduction.cc
index eb39682..701231d 100644
--- a/libstdc++-v3/testsuite/23_containers/forward_list/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/cons/deduction.cc
@@ -19,6 +19,7 @@
#include <forward_list>
#include <testsuite_iterators.h>
+#include <testsuite_allocator.h>
template<typename T>
using input_iterator_seq
@@ -67,3 +68,31 @@ test02()
std::forward_list s4(1U, 2L, std::allocator<long>());
check_type<std::forward_list<long>>(s4);
}
+
+struct Pool;
+
+template<typename T>
+struct Alloc : __gnu_test::SimpleAllocator<T>
+{
+ Alloc(Pool*) { }
+
+ template<typename U>
+ Alloc(const Alloc<U>&) { }
+};
+
+void
+test_p1518r2()
+{
+ // P1518R2 - Stop overconstraining allocators in container deduction guides.
+ // This is a C++23 feature but we support it for C++17 too.
+
+ using Flist = std::forward_list<unsigned, Alloc<unsigned>>;
+ Pool* p = nullptr;
+ Flist f(p);
+
+ std::forward_list s1(f, p);
+ check_type<Flist>(s1);
+
+ std::forward_list s2(std::move(f), p);
+ check_type<Flist>(s2);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/3.cc b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/3.cc
index 58ea6b1..60dd1a8 100644
--- a/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/3.cc
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/3.cc
@@ -23,7 +23,7 @@
// { dg-do compile { target c++11 } }
// The extension that implicitly rebinds allocators is in gnu++98/11/14/17 only
-// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" } }
+// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" "-D_GLIBCXX_CONCEPT_CHECKS*" } }
// libstdc++/21770
template class std::forward_list<int, std::allocator<char> >;
diff --git a/libstdc++-v3/testsuite/23_containers/list/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/list/cons/deduction.cc
index 3ad1d3f..c747509 100644
--- a/libstdc++-v3/testsuite/23_containers/list/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/cons/deduction.cc
@@ -19,6 +19,7 @@
#include <list>
#include <testsuite_iterators.h>
+#include <testsuite_allocator.h>
template<typename T>
using input_iterator_seq
@@ -67,3 +68,31 @@ test02()
std::list s4(1U, 2L, std::allocator<long>());
check_type<std::list<long>>(s4);
}
+
+struct Pool;
+
+template<typename T>
+struct Alloc : __gnu_test::SimpleAllocator<T>
+{
+ Alloc(Pool*) { }
+
+ template<typename U>
+ Alloc(const Alloc<U>&) { }
+};
+
+void
+test_p1518r2()
+{
+ // P1518R2 - Stop overconstraining allocators in container deduction guides.
+ // This is a C++23 feature but we support it for C++17 too.
+
+ using List = std::list<unsigned, Alloc<unsigned>>;
+ Pool* p = nullptr;
+ List l(p);
+
+ std::list s1(l, p);
+ check_type<List>(s1);
+
+ std::list s2(std::move(l), p);
+ check_type<List>(s2);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/list/operations/66742.cc b/libstdc++-v3/testsuite/23_containers/list/operations/66742.cc
new file mode 100644
index 0000000..24bda39
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/list/operations/66742.cc
@@ -0,0 +1,55 @@
+// { dg-do run { target c++11 } }
+
+#include <list>
+#include <testsuite_allocator.h>
+#include <testsuite_hooks.h>
+
+// PR libstdc++/66742
+// abort on sorting list with custom allocator that is not stateless
+
+template<typename List, typename Cmp = std::less<typename List::value_type>>
+bool is_sorted(const List& l, Cmp cmp = {})
+{
+ auto it = l.begin();
+ auto next = it;
+ const auto end = l.end();
+ if (it == end)
+ return true;
+ while (++next != end)
+ if (cmp(*next, *it))
+ return false;
+ else
+ it = next;
+ return true;
+}
+
+void
+test01()
+{
+ using Alloc = __gnu_test::uneq_allocator<int>;
+ Alloc a1(1);
+ std::list<int, Alloc> l(a1);
+ for (int i = 0; i < 1000; ++i)
+ {
+ l.push_front(i);
+ l.push_back(i + (i % 3));
+ }
+ const auto orig = l;
+
+ l.sort();
+ VERIFY( is_sorted(l) );
+ l.sort();
+ VERIFY( is_sorted(l) );
+
+ l = orig;
+ l.sort(std::less<int>());
+ VERIFY( is_sorted(l) );
+ l.sort(std::greater<int>());
+ VERIFY( is_sorted(l, std::greater<int>()) );
+}
+
+int
+main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/explicit_instantiation/3.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/explicit_instantiation/3.cc
index 735ae11..f4e42ff 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/explicit_instantiation/3.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/explicit_instantiation/3.cc
@@ -22,7 +22,7 @@
// { dg-do compile }
// The extension that implicitly rebinds allocators is in gnu++98/11/14/17 only
-// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" } }
+// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" "-D_GLIBCXX_CONCEPT_CHECKS*" } }
// libstdc++/21770
template class std::list<int, std::allocator<char> >;
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/explicit_instantiation/5.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/explicit_instantiation/5.cc
index 24219bc..4844324 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/explicit_instantiation/5.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/explicit_instantiation/5.cc
@@ -24,6 +24,7 @@
// libstdc++/50118
template class std::list<int, __gnu_test::ExplicitConsAlloc<int> >;
-#if !defined __STRICT_ANSI__ && __cplusplus <= 201703L
+#if !defined __STRICT_ANSI__ && __cplusplus <= 201703L \
+ && !defined _GLIBCXX_CONCEPT_CHECKS
template class std::list<int, __gnu_test::ExplicitConsAlloc<char> >;
#endif
diff --git a/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc
index e72033c..f8e6e6e 100644
--- a/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc
@@ -222,3 +222,39 @@ void h()
std::map<int, double, std::less<int>,
SimpleAllocator<value_type>>>);
}
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+ typename require_same<T, U>::type
+ check_type(U&) { }
+
+struct Pool;
+
+template<typename T>
+struct Alloc : __gnu_test::SimpleAllocator<T>
+{
+ Alloc(Pool*) { }
+
+ template<typename U>
+ Alloc(const Alloc<U>&) { }
+};
+
+void
+test_p1518r2()
+{
+ // P1518R2 - Stop overconstraining allocators in container deduction guides.
+ // This is a C++23 feature but we support it for C++17 too.
+
+ using PairAlloc = Alloc<std::pair<const unsigned, void*>>;
+ using Map = std::map<unsigned, void*, std::greater<>, PairAlloc>;
+ Pool* p = nullptr;
+ Map m(p);
+
+ std::map s1(m, p);
+ check_type<Map>(s1);
+
+ std::map s2(std::move(m), p);
+ check_type<Map>(s2);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/map/requirements/explicit_instantiation/3.cc b/libstdc++-v3/testsuite/23_containers/map/requirements/explicit_instantiation/3.cc
index c281f1f..f0d5e8a 100644
--- a/libstdc++-v3/testsuite/23_containers/map/requirements/explicit_instantiation/3.cc
+++ b/libstdc++-v3/testsuite/23_containers/map/requirements/explicit_instantiation/3.cc
@@ -22,7 +22,7 @@
// { dg-do compile }
// The extension that implicitly rebinds allocators is in gnu++98/11/14/17 only
-// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" } }
+// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" "-D_GLIBCXX_CONCEPT_CHECKS*" } }
// libstdc++/21770
template class std::map<int, double, std::less<int>, std::allocator<char> >;
diff --git a/libstdc++-v3/testsuite/23_containers/map/requirements/explicit_instantiation/5.cc b/libstdc++-v3/testsuite/23_containers/map/requirements/explicit_instantiation/5.cc
index 1764722..62d4868 100644
--- a/libstdc++-v3/testsuite/23_containers/map/requirements/explicit_instantiation/5.cc
+++ b/libstdc++-v3/testsuite/23_containers/map/requirements/explicit_instantiation/5.cc
@@ -27,7 +27,8 @@ using __gnu_test::ExplicitConsAlloc;
// libstdc++/50118
template class std::map<int, int, std::less<int>,
ExplicitConsAlloc<std::pair<const int, int> > >;
-#if !defined __STRICT_ANSI__ && __cplusplus <= 201703L
+#if !defined __STRICT_ANSI__ && __cplusplus <= 201703L \
+ && !defined _GLIBCXX_CONCEPT_CHECKS
template class std::map<int, int, std::less<int>,
ExplicitConsAlloc<char> >;
#endif
diff --git a/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc
index ffc7502..f0699e2 100644
--- a/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc
@@ -174,3 +174,39 @@ void h()
std::multimap<int, double, std::less<int>,
SimpleAllocator<value_type>>>);
}
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+ typename require_same<T, U>::type
+ check_type(U&) { }
+
+struct Pool;
+
+template<typename T>
+struct Alloc : __gnu_test::SimpleAllocator<T>
+{
+ Alloc(Pool*) { }
+
+ template<typename U>
+ Alloc(const Alloc<U>&) { }
+};
+
+void
+test_p1518r2()
+{
+ // P1518R2 - Stop overconstraining allocators in container deduction guides.
+ // This is a C++23 feature but we support it for C++17 too.
+
+ using PairAlloc = Alloc<std::pair<const unsigned, void*>>;
+ using MMap = std::multimap<unsigned, void*, std::greater<>, PairAlloc>;
+ Pool* p = nullptr;
+ MMap m(p);
+
+ std::multimap s1(m, p);
+ check_type<MMap>(s1);
+
+ std::multimap s2(std::move(m), p);
+ check_type<MMap>(s2);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/multimap/requirements/explicit_instantiation/3.cc b/libstdc++-v3/testsuite/23_containers/multimap/requirements/explicit_instantiation/3.cc
index 083061c..3c7c0af 100644
--- a/libstdc++-v3/testsuite/23_containers/multimap/requirements/explicit_instantiation/3.cc
+++ b/libstdc++-v3/testsuite/23_containers/multimap/requirements/explicit_instantiation/3.cc
@@ -22,7 +22,7 @@
// { dg-do compile }
// The extension that implicitly rebinds allocators is in gnu++98/11/14/17 only
-// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" } }
+// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" "-D_GLIBCXX_CONCEPT_CHECKS*" } }
// libstdc++/21770
template class std::multimap<int, double, std::less<int>, std::allocator<char> >;
diff --git a/libstdc++-v3/testsuite/23_containers/multimap/requirements/explicit_instantiation/5.cc b/libstdc++-v3/testsuite/23_containers/multimap/requirements/explicit_instantiation/5.cc
index d0b9209..87f5ae4 100644
--- a/libstdc++-v3/testsuite/23_containers/multimap/requirements/explicit_instantiation/5.cc
+++ b/libstdc++-v3/testsuite/23_containers/multimap/requirements/explicit_instantiation/5.cc
@@ -27,7 +27,8 @@ using __gnu_test::ExplicitConsAlloc;
// libstdc++/50118
template class std::multimap<int, int, std::less<int>,
ExplicitConsAlloc<std::pair<const int, int> > >;
-#if !defined __STRICT_ANSI__ && __cplusplus <= 201703L
+#if !defined __STRICT_ANSI__ && __cplusplus <= 201703L \
+ && !defined _GLIBCXX_CONCEPT_CHECKS
template class std::multimap<int, int, std::less<int>,
ExplicitConsAlloc<char> >;
#endif
diff --git a/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc
index 8b7a160..7f4581a6 100644
--- a/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc
@@ -130,3 +130,38 @@ void g()
std::multiset<int, std::less<int>,
SimpleAllocator<value_type>>>);
}
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+ typename require_same<T, U>::type
+ check_type(U&) { }
+
+struct Pool;
+
+template<typename T>
+struct Alloc : __gnu_test::SimpleAllocator<T>
+{
+ Alloc(Pool*) { }
+
+ template<typename U>
+ Alloc(const Alloc<U>&) { }
+};
+
+void
+test_p1518r2()
+{
+ // P1518R2 - Stop overconstraining allocators in container deduction guides.
+ // This is a C++23 feature but we support it for C++17 too.
+
+ using MSet = std::multiset<unsigned, std::greater<>, Alloc<unsigned>>;
+ Pool* p = nullptr;
+ MSet s(p);
+
+ std::multiset s1(s, p);
+ check_type<MSet>(s1);
+
+ std::multiset s2(std::move(s), p);
+ check_type<MSet>(s2);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/multiset/requirements/explicit_instantiation/3.cc b/libstdc++-v3/testsuite/23_containers/multiset/requirements/explicit_instantiation/3.cc
index 1e6dbf9..19d64c2 100644
--- a/libstdc++-v3/testsuite/23_containers/multiset/requirements/explicit_instantiation/3.cc
+++ b/libstdc++-v3/testsuite/23_containers/multiset/requirements/explicit_instantiation/3.cc
@@ -22,7 +22,7 @@
// { dg-do compile }
// The extension that implicitly rebinds allocators is in gnu++98/11/14/17 only
-// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" } }
+// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" "-D_GLIBCXX_CONCEPT_CHECKS*" } }
// libstdc++/21770
template class std::multiset<int, std::less<int>, std::allocator<char> >;
diff --git a/libstdc++-v3/testsuite/23_containers/multiset/requirements/explicit_instantiation/5.cc b/libstdc++-v3/testsuite/23_containers/multiset/requirements/explicit_instantiation/5.cc
index b66d59d..00f7fde 100644
--- a/libstdc++-v3/testsuite/23_containers/multiset/requirements/explicit_instantiation/5.cc
+++ b/libstdc++-v3/testsuite/23_containers/multiset/requirements/explicit_instantiation/5.cc
@@ -25,7 +25,8 @@
// libstdc++/50118
template class std::multiset<int, std::less<int>,
__gnu_test::ExplicitConsAlloc<int> >;
-#if !defined __STRICT_ANSI__ && __cplusplus <= 201703L
+#if !defined __STRICT_ANSI__ && __cplusplus <= 201703L \
+ && !defined _GLIBCXX_CONCEPT_CHECKS
template class std::multiset<int, std::less<int>,
__gnu_test::ExplicitConsAlloc<char> >;
#endif
diff --git a/libstdc++-v3/testsuite/23_containers/priority_queue/deduction.cc b/libstdc++-v3/testsuite/23_containers/priority_queue/deduction.cc
index 05c4c57..816efab 100644
--- a/libstdc++-v3/testsuite/23_containers/priority_queue/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/priority_queue/deduction.cc
@@ -21,6 +21,7 @@
#include <deque>
#include <vector>
#include <testsuite_iterators.h>
+#include <testsuite_allocator.h>
template<typename T, typename U> struct require_same;
template<typename T> struct require_same<T, T> { using type = void; };
@@ -116,3 +117,39 @@ test02()
std::priority_queue s14(seq.begin(), seq.end(), cmp, std::deque<short>{});
check_type<std::priority_queue<short, std::deque<short>, Cmp>>(s14);
}
+
+struct Pool;
+
+template<typename T>
+struct Alloc : __gnu_test::SimpleAllocator<T>
+{
+ Alloc(Pool*) { }
+
+ template<typename U>
+ Alloc(const Alloc<U>&) { }
+};
+
+void
+test_p1518r2()
+{
+ // P1518R2 - Stop overconstraining allocators in container deduction guides.
+ // This is a C++23 feature but we support it for C++17 too.
+
+ using Vector = std::vector<short, Alloc<short>>;
+ using Cmp = std::greater<long>;
+ Pool* p = nullptr;
+ Vector v(p);
+ Cmp cmp;
+
+ std::priority_queue q1(cmp, v, p);
+ check_type<std::priority_queue<short, Vector, Cmp>>(q1);
+
+ std::priority_queue q2(cmp, std::move(v), p);
+ check_type<std::priority_queue<short, Vector, Cmp>>(q2);
+
+ std::priority_queue q3(q1, p);
+ check_type<std::priority_queue<short, Vector, Cmp>>(q3);
+
+ std::priority_queue q4(std::move(q1), p);
+ check_type<std::priority_queue<short, Vector, Cmp>>(q4);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/priority_queue/lwg3506.cc b/libstdc++-v3/testsuite/23_containers/priority_queue/lwg3506.cc
new file mode 100644
index 0000000..c9c803d
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/priority_queue/lwg3506.cc
@@ -0,0 +1,54 @@
+// { dg-do run { target c++11 } }
+
+#include <queue>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+void
+test_lwg3506()
+{
+ // LWG 3506 Missing allocator-extended constructors for priority_queue
+
+ using Alloc = __gnu_test::uneq_allocator<int>;
+
+ using Container = std::vector<int, Alloc>;
+
+ struct Queue : std::priority_queue<int, Container>
+ {
+ using priority_queue::priority_queue;
+
+ Alloc get_allocator() const { return c.get_allocator(); }
+ };
+
+ using Compare = Queue::value_compare;
+
+ const Alloc a1(1), a2(2), a3(3), a4(4);
+ const int vals[] = { 5, 3, 9, 1, 7 };
+ Container cont({ 20, 30, 40 }, Alloc(99));
+
+ Queue q1(vals, vals+5, a1);
+ VERIFY( q1.get_allocator() == a1 );
+ VERIFY( q1.size() == 5 );
+ VERIFY( q1.top() == 9 );
+
+ Queue q2(vals, vals+5, Compare(), a2);
+ VERIFY( q2.get_allocator() == a2 );
+ VERIFY( q2.size() == 5 );
+ VERIFY( q2.top() == 9 );
+
+ Queue q3(vals, vals+5, Compare(), cont, a3);
+ VERIFY( q3.get_allocator() == a3 );
+ VERIFY( q3.size() == 8 );
+ VERIFY( q3.top() == 40 );
+
+ Queue q4(vals, vals+5, Compare(), std::move(cont), a4);
+ VERIFY( q4.get_allocator() == a4 );
+ VERIFY( q4.size() == 8 );
+ VERIFY( q4.top() == 40 );
+ VERIFY( cont.empty() );
+}
+
+int main()
+{
+ test_lwg3506();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/priority_queue/lwg3522.cc b/libstdc++-v3/testsuite/23_containers/priority_queue/lwg3522.cc
new file mode 100644
index 0000000..c026438
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/priority_queue/lwg3522.cc
@@ -0,0 +1,24 @@
+// { dg-do compile { target c++11 } }
+
+#include <queue>
+
+// LWG 3522
+// Missing requirement on InputIterator template parameter for priority_queue
+// constructors
+std::priority_queue<int> x = {1, 2}; // { dg-error "could not convert" }
+
+using Q = std::priority_queue<int>;
+using Compare = Q::value_compare;
+using Sequence = Q::container_type;
+
+static_assert( ! std::is_constructible<Q, int, int>(),
+ "priority_queue(InputIterator, InputIterator) is constrained" );
+
+static_assert( ! std::is_constructible<Q, int, int, Compare>(),
+ "priority_queue(InputIterator, InputIterator, const Compare&) "
+ " is constrained" );
+
+static_assert( ! std::is_constructible<Q, int, int, Compare, const Sequence&>(),
+ "and with const Sequence lvalue argument" );
+static_assert( ! std::is_constructible<Q, int, int, Compare, Sequence>(),
+ "and with Sequence rvalue argument" );
diff --git a/libstdc++-v3/testsuite/23_containers/priority_queue/lwg3529.cc b/libstdc++-v3/testsuite/23_containers/priority_queue/lwg3529.cc
new file mode 100644
index 0000000..014b5aa
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/priority_queue/lwg3529.cc
@@ -0,0 +1,13 @@
+// { dg-do compile { target c++11 } }
+
+#include <queue>
+
+struct C : std::vector<int>
+{
+ C(int*, int*) { }
+};
+
+int i;
+
+// LWG 3529. priority_queue(first, last) should construct c with (first, last)
+std::priority_queue<int, C> q(&i, &i);
diff --git a/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1.cc b/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1.cc
index d1e18f8..a425001 100644
--- a/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1.cc
@@ -24,12 +24,15 @@
template class std::priority_queue<int>;
-struct NonDefaultConstructible : std::vector<int> {
- NonDefaultConstructible(int) { }
-};
struct Cmp : std::less<int> {
Cmp(int) { }
};
+template class std::priority_queue<int, std::vector<int>, Cmp>;
+
+#ifndef _GLIBCXX_CONCEPT_CHECKS
+struct NonDefaultConstructible : std::vector<int> {
+ NonDefaultConstructible(int) { }
+};
template class std::priority_queue<int, NonDefaultConstructible>;
template class std::priority_queue<int, NonDefaultConstructible, Cmp>;
-template class std::priority_queue<int, std::vector<int>, Cmp>;
+#endif
diff --git a/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1_c++98.cc b/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1_c++98.cc
index def9259..28549f5 100644
--- a/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1_c++98.cc
+++ b/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1_c++98.cc
@@ -24,12 +24,15 @@
template class std::priority_queue<int>;
-struct NonDefaultConstructible : std::vector<int> {
- NonDefaultConstructible(int) { }
-};
struct Cmp : std::less<int> {
Cmp(int) { }
};
+template class std::priority_queue<int, std::vector<int>, Cmp>;
+
+#ifndef _GLIBCXX_CONCEPT_CHECKS
+struct NonDefaultConstructible : std::vector<int> {
+ NonDefaultConstructible(int) { }
+};
template class std::priority_queue<int, NonDefaultConstructible>;
template class std::priority_queue<int, NonDefaultConstructible, Cmp>;
-template class std::priority_queue<int, std::vector<int>, Cmp>;
+#endif
diff --git a/libstdc++-v3/testsuite/23_containers/queue/cons_from_iters.cc b/libstdc++-v3/testsuite/23_containers/queue/cons_from_iters.cc
new file mode 100644
index 0000000..b826e74
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/queue/cons_from_iters.cc
@@ -0,0 +1,68 @@
+// Copyright (C) 2021 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++23" }
+// { dg-do run { target c++23 } }
+
+#include <queue>
+
+#ifndef __cpp_lib_adaptor_iterator_pair_constructor
+#error Feature test macro for iterator pair constructors is missing in <queue>
+#elif __cpp_lib_adaptor_iterator_pair_constructor != 202106L
+#error Feature test macro for iterator pair constructors has wrong value in <queue>
+#endif
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+void
+test_p1425r4()
+{
+ const int vals[] = { 5, 4, 3, 2, 1, 9 };
+
+ std::queue<int> q(std::begin(vals), std::end(vals));
+ VERIFY( q.size() == std::size(vals) );
+ VERIFY( q.front() == 5 );
+ VERIFY( q.back() == 9 );
+
+ using Alloc = __gnu_test::uneq_allocator<int>;
+
+ struct Queue : std::queue<int, std::deque<int, Alloc>>
+ {
+ using queue::queue;
+
+ Alloc get_allocator() const { return c.get_allocator(); }
+ };
+
+ Alloc a0, a1(1);
+ Queue q0(std::next(vals), std::end(vals));
+ VERIFY( q0.size() == std::size(vals) - 1 );
+ VERIFY( q0.front() == 4 );
+ VERIFY( q0.back() == 9 );
+ VERIFY( q0.get_allocator() == a0 );
+
+ Queue q1(std::next(vals, 2), std::end(vals), a1);
+ VERIFY( q1.size() == std::size(vals) - 2 );
+ VERIFY( q1.front() == 3 );
+ VERIFY( q1.back() == 9 );
+ VERIFY( q1.get_allocator() == a1 );
+}
+
+int main()
+{
+ test_p1425r4();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/queue/deduction.cc b/libstdc++-v3/testsuite/23_containers/queue/deduction.cc
index ab28f83..2642ece 100644
--- a/libstdc++-v3/testsuite/23_containers/queue/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/queue/deduction.cc
@@ -20,6 +20,7 @@
#include <queue>
#include <deque>
#include <list>
+#include <testsuite_allocator.h>
template<typename T, typename U> struct require_same;
template<typename T> struct require_same<T, T> { using type = void; };
@@ -86,3 +87,36 @@ test02()
std::queue s8(std::move(l), l.get_allocator());
check_type<std::queue<long, std::list<long>>>(s8);
}
+
+struct Pool;
+
+template<typename T>
+struct Alloc : __gnu_test::SimpleAllocator<T>
+{
+ Alloc(Pool*) { }
+
+ template<typename U>
+ Alloc(const Alloc<U>&) { }
+};
+
+void
+test_p1518r2()
+{
+ // P1518R2 - Stop overconstraining allocators in container deduction guides.
+ // This is a C++23 feature but we support it for C++17 too.
+
+ using Deque = std::deque<unsigned, Alloc<unsigned>>;
+ using List = std::list<long, Alloc<long>>;
+ Pool* p = nullptr;
+ Deque d(p);
+ List l(p);
+
+ std::queue q1(d, p);
+ check_type<std::queue<unsigned, Deque>>(q1);
+
+ std::queue q2(l, p);
+ check_type<std::queue<long, List>>(q2);
+
+ std::queue q3(q2, p);
+ check_type<std::queue<long, List>>(q3);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1.cc b/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1.cc
index b737a15..3b9090c 100644
--- a/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1.cc
@@ -24,7 +24,9 @@
template class std::queue<int>;
+#ifndef _GLIBCXX_CONCEPT_CHECKS
struct NonDefaultConstructible : std::deque<int> {
NonDefaultConstructible(int) { }
};
template class std::queue<int, NonDefaultConstructible>;
+#endif
diff --git a/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1_c++98.cc b/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1_c++98.cc
index 2e2d6a4..1cc4410 100644
--- a/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1_c++98.cc
+++ b/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1_c++98.cc
@@ -24,7 +24,9 @@
template class std::queue<int>;
+#ifndef _GLIBCXX_CONCEPT_CHECKS
struct NonDefaultConstructible : std::deque<int> {
NonDefaultConstructible(int) { }
};
template class std::queue<int, NonDefaultConstructible>;
+#endif
diff --git a/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc
index 14f36b7..d77b9fc 100644
--- a/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc
@@ -131,3 +131,38 @@ void g()
std::set<int, std::less<int>,
SimpleAllocator<value_type>>>);
}
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+ typename require_same<T, U>::type
+ check_type(U&) { }
+
+struct Pool;
+
+template<typename T>
+struct Alloc : __gnu_test::SimpleAllocator<T>
+{
+ Alloc(Pool*) { }
+
+ template<typename U>
+ Alloc(const Alloc<U>&) { }
+};
+
+void
+test_p1518r2()
+{
+ // P1518R2 - Stop overconstraining allocators in container deduction guides.
+ // This is a C++23 feature but we support it for C++17 too.
+
+ using Set = std::set<unsigned, std::greater<>, Alloc<unsigned>>;
+ Pool* p = nullptr;
+ Set s(p);
+
+ std::set s1(s, p);
+ check_type<Set>(s1);
+
+ std::set s2(std::move(s), p);
+ check_type<Set>(s2);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/set/requirements/explicit_instantiation/3.cc b/libstdc++-v3/testsuite/23_containers/set/requirements/explicit_instantiation/3.cc
index b55d518..17c2177 100644
--- a/libstdc++-v3/testsuite/23_containers/set/requirements/explicit_instantiation/3.cc
+++ b/libstdc++-v3/testsuite/23_containers/set/requirements/explicit_instantiation/3.cc
@@ -22,7 +22,7 @@
// { dg-do compile }
// The extension that implicitly rebinds allocators is in gnu++98/11/14/17 only
-// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" } }
+// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" "-D_GLIBCXX_CONCEPT_CHECKS*" } }
// libstdc++/21770
template class std::set<int, std::less<int>, std::allocator<char> >;
diff --git a/libstdc++-v3/testsuite/23_containers/set/requirements/explicit_instantiation/5.cc b/libstdc++-v3/testsuite/23_containers/set/requirements/explicit_instantiation/5.cc
index 29e3ec3..d224e85 100644
--- a/libstdc++-v3/testsuite/23_containers/set/requirements/explicit_instantiation/5.cc
+++ b/libstdc++-v3/testsuite/23_containers/set/requirements/explicit_instantiation/5.cc
@@ -25,7 +25,8 @@
// libstdc++/50118
template class std::set<int, std::less<int>,
__gnu_test::ExplicitConsAlloc<int> >;
-#if !defined __STRICT_ANSI__ && __cplusplus <= 201703L
+#if !defined __STRICT_ANSI__ && __cplusplus <= 201703L \
+ && !defined _GLIBCXX_CONCEPT_CHECKS
template class std::set<int, std::less<int>,
__gnu_test::ExplicitConsAlloc<char> >;
#endif
diff --git a/libstdc++-v3/testsuite/23_containers/span/trivially_copyable.cc b/libstdc++-v3/testsuite/23_containers/span/trivially_copyable.cc
new file mode 100644
index 0000000..e374829
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/span/trivially_copyable.cc
@@ -0,0 +1,13 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2251r1.pdf
+
+#include <span>
+
+static_assert( std::is_trivially_copyable_v<std::span<int>> );
+static_assert( std::is_trivially_copyable_v<std::span<int, 42>> );
+
+struct NonTrivial { NonTrivial(); NonTrivial(const NonTrivial&); };
+static_assert( std::is_trivially_copyable_v<std::span<NonTrivial>> );
+static_assert( std::is_trivially_copyable_v<std::span<NonTrivial, 99>> );
diff --git a/libstdc++-v3/testsuite/23_containers/stack/cons_from_iters.cc b/libstdc++-v3/testsuite/23_containers/stack/cons_from_iters.cc
new file mode 100644
index 0000000..ee06679d
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/stack/cons_from_iters.cc
@@ -0,0 +1,65 @@
+// Copyright (C) 2021 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++23" }
+// { dg-do run { target c++23 } }
+
+#include <stack>
+
+#ifndef __cpp_lib_adaptor_iterator_pair_constructor
+#error Feature test macro for iterator pair constructors is missing in <stack>
+#elif __cpp_lib_adaptor_iterator_pair_constructor != 202106L
+#error Feature test macro for iterator pair constructors has wrong value in <stack>
+#endif
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+void
+test_p1425r4()
+{
+ const int vals[] = { 1, 2, 3, 7, 8, 9, 5, 6, 7 };
+
+ std::stack<int> s(std::begin(vals), std::end(vals));
+ VERIFY( s.size() == std::size(vals) );
+ VERIFY( s.top() == 7 );
+
+ using Alloc = __gnu_test::uneq_allocator<int>;
+
+ struct Stack : std::stack<int, std::deque<int, Alloc>>
+ {
+ using stack::stack;
+
+ Alloc get_allocator() const { return c.get_allocator(); }
+ };
+
+ Alloc a0, a1(1);
+ Stack s0(std::begin(vals), std::end(vals) - 1);
+ VERIFY( s0.size() == std::size(vals) - 1 );
+ VERIFY( s0.top() == 6 );
+ VERIFY( s0.get_allocator() == a0 );
+
+ Stack s1(std::begin(vals), std::end(vals) - 2, a1);
+ VERIFY( s1.size() == std::size(vals) - 2 );
+ VERIFY( s1.top() == 5 );
+ VERIFY( s1.get_allocator() == a1 );
+}
+
+int main()
+{
+ test_p1425r4();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/stack/deduction.cc b/libstdc++-v3/testsuite/23_containers/stack/deduction.cc
index db8e31e..169a063 100644
--- a/libstdc++-v3/testsuite/23_containers/stack/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/stack/deduction.cc
@@ -20,6 +20,7 @@
#include <stack>
#include <deque>
#include <list>
+#include <testsuite_allocator.h>
template<typename T, typename U> struct require_same;
template<typename T> struct require_same<T, T> { using type = void; };
@@ -58,7 +59,7 @@ test01()
void
test02()
- {
+{
std::deque<unsigned> d;
std::list<long> l;
diff --git a/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1.cc b/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1.cc
index 8002099..82e8e85 100644
--- a/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1.cc
@@ -24,7 +24,9 @@
template class std::stack<int>;
+#ifndef _GLIBCXX_CONCEPT_CHECKS
struct NonDefaultConstructible : std::deque<int> {
NonDefaultConstructible(int) { }
};
template class std::stack<int, NonDefaultConstructible>;
+#endif
diff --git a/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1_c++98.cc b/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1_c++98.cc
index c66c597..8ff20fc 100644
--- a/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1_c++98.cc
+++ b/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1_c++98.cc
@@ -24,7 +24,9 @@
template class std::stack<int>;
+#ifndef _GLIBCXX_CONCEPT_CHECKS
struct NonDefaultConstructible : std::deque<int> {
NonDefaultConstructible(int) { }
};
template class std::stack<int, NonDefaultConstructible>;
+#endif
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
index 0785447..8b69af8 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
@@ -124,3 +124,41 @@ void f()
std::equal_to<int>,
SimpleAllocator<std::pair<const int, double>>>>);
}
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+ typename require_same<T, U>::type
+ check_type(U&) { }
+
+struct Pool;
+
+template<typename T>
+struct Alloc : __gnu_test::SimpleAllocator<T>
+{
+ Alloc(Pool*) { }
+
+ template<typename U>
+ Alloc(const Alloc<U>&) { }
+};
+
+void
+test_p1518r2()
+{
+ // P1518R2 - Stop overconstraining allocators in container deduction guides.
+ // This is a C++23 feature but we support it for C++17 too.
+
+ using PairAlloc = Alloc<std::pair<const unsigned, void*>>;
+ using Hash = std::hash<unsigned long>;
+ using Eq = std::equal_to<>;
+ using UMap = std::unordered_map<unsigned, void*, Hash, Eq, PairAlloc>;
+ Pool* p = nullptr;
+ UMap m(p);
+
+ std::unordered_map s1(m, p);
+ check_type<UMap>(s1);
+
+ std::unordered_map s2(std::move(m), p);
+ check_type<UMap>(s2);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/requirements/explicit_instantiation/3.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/requirements/explicit_instantiation/3.cc
index 7985f7a..e9c9367 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/requirements/explicit_instantiation/3.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/requirements/explicit_instantiation/3.cc
@@ -1,6 +1,6 @@
// { dg-do compile { target c++11 } }
// The extension that implicitly rebinds allocators is in gnu++98/11/14/17 only
-// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" } }
+// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" "-D_GLIBCXX_CONCEPT_CHECKS*" } }
// Copyright (C) 2007-2021 Free Software Foundation, Inc.
//
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
index d8a6f51..e7e535b 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
@@ -133,3 +133,41 @@ void f()
std::equal_to<int>,
SimpleAllocator<std::pair<const int, double>>>>);
}
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+ typename require_same<T, U>::type
+ check_type(U&) { }
+
+struct Pool;
+
+template<typename T>
+struct Alloc : __gnu_test::SimpleAllocator<T>
+{
+ Alloc(Pool*) { }
+
+ template<typename U>
+ Alloc(const Alloc<U>&) { }
+};
+
+void
+test_p1518r2()
+{
+ // P1518R2 - Stop overconstraining allocators in container deduction guides.
+ // This is a C++23 feature but we support it for C++17 too.
+
+ using PairAlloc = Alloc<std::pair<const unsigned, void*>>;
+ using Hash = std::hash<unsigned long>;
+ using Eq = std::equal_to<>;
+ using UMMap = std::unordered_multimap<unsigned, void*, Hash, Eq, PairAlloc>;
+ Pool* p = nullptr;
+ UMMap m(p);
+
+ std::unordered_multimap s1(m, p);
+ check_type<UMMap>(s1);
+
+ std::unordered_multimap s2(std::move(m), p);
+ check_type<UMMap>(s2);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/requirements/explicit_instantiation/3.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/requirements/explicit_instantiation/3.cc
index 3d39b88..35a47fa 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/requirements/explicit_instantiation/3.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/requirements/explicit_instantiation/3.cc
@@ -1,6 +1,6 @@
// { dg-do compile { target c++11 } }
// The extension that implicitly rebinds allocators is in gnu++98/11/14/17 only
-// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" } }
+// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" "-D_GLIBCXX_CONCEPT_CHECKS*" } }
// Copyright (C) 2007-2021 Free Software Foundation, Inc.
//
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc
index 25c2715..22b7297 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc
@@ -142,3 +142,40 @@ void f()
std::equal_to<int>,
SimpleAllocator<int>>>);
}
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+ typename require_same<T, U>::type
+ check_type(U&) { }
+
+struct Pool;
+
+template<typename T>
+struct Alloc : __gnu_test::SimpleAllocator<T>
+{
+ Alloc(Pool*) { }
+
+ template<typename U>
+ Alloc(const Alloc<U>&) { }
+};
+
+void
+test_p1518r2()
+{
+ // P1518R2 - Stop overconstraining allocators in container deduction guides.
+ // This is a C++23 feature but we support it for C++17 too.
+
+ using Hash = std::hash<unsigned long>;
+ using Eq = std::equal_to<>;
+ using UMSet = std::unordered_multiset<unsigned, Hash, Eq, Alloc<unsigned>>;
+ Pool* p = nullptr;
+ UMSet s(p);
+
+ std::unordered_multiset s1(s, p);
+ check_type<UMSet>(s1);
+
+ std::unordered_multiset s2(std::move(s), p);
+ check_type<UMSet>(s2);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/requirements/explicit_instantiation/3.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/requirements/explicit_instantiation/3.cc
index 4c6c984..3effea3 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/requirements/explicit_instantiation/3.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/requirements/explicit_instantiation/3.cc
@@ -1,6 +1,6 @@
// { dg-do compile { target c++11 } }
// The extension that implicitly rebinds allocators is in gnu++98/11/14/17 only
-// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" } }
+// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" "-D_GLIBCXX_CONCEPT_CHECKS*" } }
// Copyright (C) 2007-2021 Free Software Foundation, Inc.
//
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc
index b8c45d2..db58581 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc
@@ -137,3 +137,40 @@ void f()
std::equal_to<int>,
SimpleAllocator<int>>>);
}
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+ typename require_same<T, U>::type
+ check_type(U&) { }
+
+struct Pool;
+
+template<typename T>
+struct Alloc : __gnu_test::SimpleAllocator<T>
+{
+ Alloc(Pool*) { }
+
+ template<typename U>
+ Alloc(const Alloc<U>&) { }
+};
+
+void
+test_p1518r2()
+{
+ // P1518R2 - Stop overconstraining allocators in container deduction guides.
+ // This is a C++23 feature but we support it for C++17 too.
+
+ using Hash = std::hash<unsigned long>;
+ using Eq = std::equal_to<>;
+ using USet = std::unordered_set<unsigned, Hash, Eq, Alloc<unsigned>>;
+ Pool* p = nullptr;
+ USet s(p);
+
+ std::unordered_set s1(s, p);
+ check_type<USet>(s1);
+
+ std::unordered_set s2(std::move(s), p);
+ check_type<USet>(s2);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/requirements/explicit_instantiation/3.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/requirements/explicit_instantiation/3.cc
index da47539..bd86858 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/requirements/explicit_instantiation/3.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/requirements/explicit_instantiation/3.cc
@@ -1,6 +1,6 @@
// { dg-do compile { target c++11 } }
// The extension that implicitly rebinds allocators is in gnu++98/11/14/17 only
-// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" } }
+// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" "-D_GLIBCXX_CONCEPT_CHECKS*" } }
// Copyright (C) 2007-2021 Free Software Foundation, Inc.
//
diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/deduction.cc
index 9f7b761..542a0d7 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/cons/deduction.cc
@@ -19,6 +19,7 @@
#include <vector>
#include <testsuite_iterators.h>
+#include <testsuite_allocator.h>
template<typename T>
using input_iterator_seq
@@ -50,6 +51,24 @@ test01()
}
void
+test01b()
+{
+ std::vector<bool> s0;
+
+ std::vector s1 = s0;
+ check_type<std::vector<bool>>(s1);
+
+ std::vector s2 = std::move(s0);
+ check_type<std::vector<bool>>(s2);
+
+ const std::vector s3 = s0;
+ check_type<const std::vector<bool>>(s3);
+
+ const std::vector s4 = s3;
+ check_type<const std::vector<bool>>(s4);
+}
+
+void
test02()
{
unsigned a[1] = {};
@@ -67,3 +86,59 @@ test02()
std::vector s4(1U, 2L, std::allocator<long>());
check_type<std::vector<long>>(s4);
}
+
+void
+test02b()
+{
+ bool a[1] = {};
+ input_iterator_seq<bool> seq(a);
+
+ std::vector s1(seq.begin(), seq.end());
+ check_type<std::vector<bool>>(s1);
+
+ std::vector s2(seq.begin(), seq.end(), std::allocator<bool>());
+ check_type<std::vector<bool>>(s2);
+
+ std::vector s3(1U, true);
+ check_type<std::vector<bool>>(s3);
+
+ std::vector s4(1U, true, std::allocator<bool>());
+ check_type<std::vector<bool>>(s4);
+}
+
+struct Pool;
+
+template<typename T>
+struct Alloc : __gnu_test::SimpleAllocator<T>
+{
+ Alloc(Pool*) { }
+
+ template<typename U>
+ Alloc(const Alloc<U>&) { }
+};
+
+void
+test_p1518r2()
+{
+ // P1518R2 - Stop overconstraining allocators in container deduction guides.
+ // This is a C++23 feature but we support it for C++17 too.
+
+ using Vector = std::vector<unsigned, Alloc<unsigned>>;
+ Pool* p = nullptr;
+ Vector v(p);
+
+ std::vector s1(v, p);
+ check_type<Vector>(s1);
+
+ std::vector s2(std::move(v), p);
+ check_type<Vector>(s2);
+
+ using BVector = std::vector<bool, Alloc<bool>>;
+ BVector b(p);
+
+ std::vector s3(b, p);
+ check_type<BVector>(s3);
+
+ std::vector s4(std::move(b), p);
+ check_type<BVector>(s4);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/ext_pointer/explicit_instantiation/3.cc b/libstdc++-v3/testsuite/23_containers/vector/ext_pointer/explicit_instantiation/3.cc
index 1614989..0dcfbd6 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/ext_pointer/explicit_instantiation/3.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/ext_pointer/explicit_instantiation/3.cc
@@ -25,7 +25,7 @@
// { dg-do compile }
// The extension that implicitly rebinds allocators is in gnu++98/11/14/17 only
-// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" } }
+// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" "-D_GLIBCXX_CONCEPT_CHECKS*" } }
// libstdc++/21770
template class std::vector<int, __gnu_cxx::_ExtPtr_allocator<char> >;
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/explicit_instantiation/3.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/explicit_instantiation/3.cc
index 8c96e9a..39316ee 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/explicit_instantiation/3.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/explicit_instantiation/3.cc
@@ -22,7 +22,7 @@
// { dg-do compile }
// The extension that implicitly rebinds allocators is in gnu++98/11/14/17 only
-// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" } }
+// { dg-skip-if "" { *-*-* } { "-std=c++*" "-std=gnu++2*" "-D_GLIBCXX_CONCEPT_CHECKS*" } }
// libstdc++/21770
template class std::vector<int, std::allocator<char> >;
diff --git a/libstdc++-v3/testsuite/24_iterators/normal_iterator/to_address.cc b/libstdc++-v3/testsuite/24_iterators/normal_iterator/to_address.cc
new file mode 100644
index 0000000..510d627
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/normal_iterator/to_address.cc
@@ -0,0 +1,6 @@
+// { dg-do compile { target { c++11 } } }
+#include <string>
+#include <memory>
+
+char* p = std::__to_address(std::string("1").begin());
+const char* q = std::__to_address(std::string("2").cbegin());
diff --git a/libstdc++-v3/testsuite/24_iterators/operations/prev_neg.cc b/libstdc++-v3/testsuite/24_iterators/operations/prev_neg.cc
index cafafc4..cc64854 100644
--- a/libstdc++-v3/testsuite/24_iterators/operations/prev_neg.cc
+++ b/libstdc++-v3/testsuite/24_iterators/operations/prev_neg.cc
@@ -38,5 +38,5 @@ test02()
{
const Y array[1] = { };
(void) std::prev(array + 1);
- // { dg-error "forward_iterator" "" { target *-*-* } 223 }
+ // { dg-error "forward_iterator" "" { target *-*-* } 239 }
}
diff --git a/libstdc++-v3/testsuite/24_iterators/output/concept.cc b/libstdc++-v3/testsuite/24_iterators/output/concept.cc
index ddb646b..a052438 100644
--- a/libstdc++-v3/testsuite/24_iterators/output/concept.cc
+++ b/libstdc++-v3/testsuite/24_iterators/output/concept.cc
@@ -68,7 +68,7 @@ using std::string;
using std::string_view;
using std::vector;
-struct B { };
+struct B { bool operator<(const B&) const; };
static_assert( output_iterator< array<int, 1>::iterator, int > );
static_assert( output_iterator< array<B, 1>::iterator, B > );
diff --git a/libstdc++-v3/testsuite/24_iterators/range_operations/lwg3392.cc b/libstdc++-v3/testsuite/24_iterators/range_operations/lwg3392.cc
new file mode 100644
index 0000000..3278035
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/range_operations/lwg3392.cc
@@ -0,0 +1,30 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+
+#include <iterator>
+
+struct movable_iterator
+{
+ using difference_type = long;
+
+ movable_iterator() = default;
+ movable_iterator(movable_iterator&&) = default;
+ movable_iterator& operator=(movable_iterator&&) = default;
+
+ int operator*() const { return 1; }
+
+ movable_iterator& operator++() { return *this; }
+ void operator++(int) { }
+
+ bool operator==(const movable_iterator&) const = default;
+};
+
+using namespace std;
+
+constexpr counted_iterator<movable_iterator> it({}, 3);
+
+static_assert( sized_sentinel_for<std::default_sentinel_t, counted_iterator<movable_iterator>> );
+// LWG 3392
+// ranges::distance() cannot be used on a move-only iterator
+// with a sized sentinel
+static_assert( ranges::distance(it, default_sentinel) == 3 );
diff --git a/libstdc++-v3/testsuite/24_iterators/reverse_iterator/noexcept.cc b/libstdc++-v3/testsuite/24_iterators/reverse_iterator/noexcept.cc
new file mode 100644
index 0000000..df4b1b0
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/reverse_iterator/noexcept.cc
@@ -0,0 +1,92 @@
+// { dg-do compile { target c++11 } }
+
+#include <iterator>
+
+template<typename T, bool Nothrow>
+struct bidi
+{
+ using value_type = T;
+ using pointer = T*;
+ using reference = T&;
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::bidirectional_iterator_tag;
+
+ T* ptr;
+
+ bidi(T* ptr = nullptr) noexcept(Nothrow) : ptr(ptr) { }
+
+ bidi(const bidi& iter) noexcept(Nothrow) : ptr(iter.ptr) { }
+
+ template<typename U>
+ bidi(const bidi<U, Nothrow>& iter) noexcept(Nothrow) : ptr(iter.ptr) { }
+
+ bidi& operator=(const bidi& iter) noexcept(Nothrow)
+ {
+ ptr = iter.ptr;
+ return *this;
+ }
+
+ template<typename U>
+ bidi& operator=(const bidi<U, Nothrow>& iter) noexcept(Nothrow)
+ {
+ ptr = iter.ptr;
+ return *this;
+ }
+
+ bidi& operator++() { ++ptr; return *this; }
+ bidi& operator--() { --ptr; return *this; }
+ bidi operator++(int) { bidi tmp = *this; ++ptr; return tmp; }
+ bidi operator--(int) { bidi tmp = *this; --ptr; return tmp; }
+
+ reference operator*() const { return *ptr; }
+ pointer operator->() const { return ptr; }
+};
+
+void
+test01()
+{
+ using B1 = bidi<int, true>;
+ using R1 = std::reverse_iterator<B1>;
+ static_assert( std::is_nothrow_default_constructible<R1>(), "" );
+ static_assert( std::is_nothrow_copy_constructible<R1>(), "" );
+ static_assert( std::is_nothrow_move_constructible<R1>(), "" );
+ static_assert( std::is_nothrow_copy_assignable<R1>(), "" );
+ static_assert( std::is_nothrow_move_assignable<R1>(), "" );
+ static_assert( std::is_nothrow_constructible<R1, const B1&>(), "" );
+ static_assert( std::is_nothrow_constructible<R1, B1>(), "" );
+
+ using B2 = bidi<const int, true>;
+ using R2 = std::reverse_iterator<B2>;
+ // Test conversions from reverse_iterator<B1> to reverse_iterator<B2>.
+ static_assert( std::is_nothrow_constructible<R2, const R1&>(), "" );
+ static_assert( std::is_nothrow_assignable<R2&, const R1&>(), "" );
+ // And from B1 to reverse_iterator<B2>.
+ static_assert( std::is_nothrow_constructible<R2, const B2&>(), "" );
+ static_assert( std::is_nothrow_constructible<R2, B2>(), "" );
+ static_assert( std::is_nothrow_constructible<R2, const B1&>(), "" );
+ static_assert( std::is_nothrow_constructible<R2, B1>(), "" );
+
+ using B3 = bidi<int, false>;
+ using R3 = std::reverse_iterator<B3>;
+ static_assert( ! std::is_nothrow_default_constructible<R3>(), "" );
+ static_assert( ! std::is_nothrow_copy_constructible<R3>(), "" );
+ static_assert( ! std::is_nothrow_move_constructible<R3>(), "" );
+ static_assert( ! std::is_nothrow_copy_assignable<R3>(), "" );
+ static_assert( ! std::is_nothrow_move_assignable<R3>(), "" );
+ static_assert( ! std::is_nothrow_constructible<R3, const B3&>(), "" );
+ static_assert( ! std::is_nothrow_constructible<R3, B3>(), "" );
+
+ using B4 = bidi<const int, false>;
+ using R4 = std::reverse_iterator<B4>;
+ // Test conversions from reverse_iterator<B3> to reverse_iterator<B4>.
+ static_assert( ! std::is_nothrow_constructible<R4, const R3&>(), "" );
+ static_assert( ! std::is_nothrow_assignable<R4&, const R3&>(), "" );
+ // And from B3 to reverse_iterator<B4>.
+ static_assert( ! std::is_nothrow_constructible<R4, const B4&>(), "" );
+ static_assert( ! std::is_nothrow_constructible<R4, B4>(), "" );
+ static_assert( ! std::is_nothrow_constructible<R4, const B3&>(), "" );
+ static_assert( ! std::is_nothrow_constructible<R4, B3>(), "" );
+
+ static_assert( noexcept(std::declval<R1&>().base()), "" );
+ static_assert( ! noexcept(std::declval<R3&>().base()), "" );
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/34595.cc b/libstdc++-v3/testsuite/25_algorithms/copy/34595.cc
index c534eeb..513425a 100644
--- a/libstdc++-v3/testsuite/25_algorithms/copy/34595.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/copy/34595.cc
@@ -27,11 +27,12 @@ class Counting_output_iterator
public:
Counting_output_iterator() : c(0) {}
Counting_output_iterator& operator++() { return *this; }
+ Counting_output_iterator operator++(int) { return *this; }
Counting_output_iterator& operator*() { return *this; }
-
+
template <typename T>
void operator=(const T&) { ++c; }
-
+
std::size_t current_counter() const { return c; }
};
diff --git a/libstdc++-v3/testsuite/25_algorithms/is_permutation/2.cc b/libstdc++-v3/testsuite/25_algorithms/is_permutation/2.cc
index 8d15c22..252226c 100644
--- a/libstdc++-v3/testsuite/25_algorithms/is_permutation/2.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/is_permutation/2.cc
@@ -20,6 +20,7 @@
// 25.2.12 [alg.is_permutation] Is permutation
#include <algorithm>
+#include <iterator>
#include <functional>
#include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/25_algorithms/unique_copy/check_type.cc b/libstdc++-v3/testsuite/25_algorithms/unique_copy/check_type.cc
index af86548..27b3579 100644
--- a/libstdc++-v3/testsuite/25_algorithms/unique_copy/check_type.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/unique_copy/check_type.cc
@@ -25,27 +25,35 @@
using __gnu_test::input_iterator_wrapper;
using __gnu_test::output_iterator_wrapper;
-struct S1 { };
+template<typename T>
+struct iter_facade
+{
+ T& operator++();
+ T operator++(int);
+ T& operator*() const;
+};
+
+struct S1 : iter_facade<S1> { };
-struct S2
+struct S2 : iter_facade<S2>
{
S2(const S1&) {}
};
-bool
+bool
operator==(const S1&, const S1&) {return true;}
-struct X1 { };
+struct X1 : iter_facade<X1> { };
-struct X2
+struct X2 : iter_facade<X2>
{
X2(const X1&) {}
};
-bool
+bool
predicate(const X1&, const X1&) {return true;}
-output_iterator_wrapper<S2>
+output_iterator_wrapper<S2>
test1(input_iterator_wrapper<S1>& s1, output_iterator_wrapper<S2>& s2)
{ return std::unique_copy(s1, s1, s2); }
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/volatile_ptr.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/volatile_ptr.cc
new file mode 100644
index 0000000..151e13d
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/volatile_ptr.cc
@@ -0,0 +1,15 @@
+// { dg-options "-std=gnu++23 -fno-inline" }
+// { dg-do run { target c++23 } }
+
+#include <sstream>
+#include <testsuite_hooks.h>
+
+int main()
+{
+ int i = 0;
+ volatile void* vp = &i;
+ std::ostringstream s1, s2;
+ s1 << &i;
+ s2 << vp;
+ VERIFY( s1.str() == s2.str() );
+}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/multiline.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/multiline.cc
new file mode 100644
index 0000000..a1982fc
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/multiline.cc
@@ -0,0 +1,74 @@
+// { dg-do run { target c++11 } }
+#include <regex>
+#include <testsuite_hooks.h>
+
+#if __cplusplus >= 201703L || !defined __STRICT_ANSI__
+static_assert( std::regex_constants::multiline == std::regex::multiline );
+static_assert( std::regex_constants::__multiline == std::regex::multiline );
+#else
+namespace test { constexpr int multiline = 0; }
+namespace check {
+ using namespace test;
+ using namespace std::regex_constants;
+ int ml = multiline;
+}
+#endif
+
+void
+test01()
+{
+ using namespace std::regex_constants;
+
+ std::regex ml{"^a.$", __multiline};
+ VERIFY( ml.flags() == __multiline );
+ VERIFY(!std::regex_search("abx\nxab", ml));
+ VERIFY(std::regex_search("x\nab", ml));
+ VERIFY(std::regex_search("ab\n", ml));
+ VERIFY(std::regex_search("x\nab\nx", ml));
+
+ ml.assign("a$\n^b$\n^c", ECMAScript|__multiline);
+ VERIFY( ml.flags() == ECMAScript|__multiline );
+ VERIFY( regex_search("a\nb\nc", ml) );
+
+ ml.assign("a$\n^b$\n^c", ECMAScript|__multiline|icase);
+ VERIFY( ml.flags() == ECMAScript|__multiline|icase );
+ VERIFY( regex_search("A\nB\nC", ml) );
+}
+
+void
+test_pr102480()
+{
+ using namespace std::regex_constants;
+
+ std::regex re("^a");
+ std::regex reml("^a", __multiline);
+ VERIFY( std::regex_match("\na" + 1, re));
+ VERIFY( std::regex_match("\na" + 1, reml));
+ // PR libstdc++/102480
+ VERIFY(!std::regex_match("\na" + 1, re, match_prev_avail));
+ VERIFY( std::regex_match("\na" + 1, reml, match_prev_avail));
+ VERIFY(!std::regex_match("\na" + 1, re, match_not_bol));
+ VERIFY(!std::regex_match("\na" + 1, re, match_prev_avail|match_not_bol));
+ VERIFY( std::regex_match("\na" + 1, reml, match_prev_avail|match_not_bol));
+ VERIFY(!std::regex_match("\ra" + 1, re, match_prev_avail));
+ VERIFY( std::regex_match("\ra" + 1, reml, match_prev_avail));
+ VERIFY(!std::regex_match("xa" + 1, re, match_prev_avail));
+ VERIFY(!std::regex_match("xa" + 1, reml, match_prev_avail));
+
+ std::regex bre("^a", basic|__multiline);
+ VERIFY(std::regex_match("\na" + 1, bre));
+ VERIFY(!std::regex_match("\na" + 1, bre, match_not_bol));
+ // multiline is ignored for any grammar except ECMAScript,
+ // so none of the following should match even though
+ // match_prev_avail is set and *--first == '\n'.
+ VERIFY(!std::regex_match("\na" + 1, bre, match_prev_avail));
+ VERIFY(!std::regex_match("\na" + 1, bre, match_prev_avail|match_not_bol));
+ VERIFY(!std::regex_match("\ra" + 1, bre, match_prev_avail));
+ VERIFY(!std::regex_match("xa" + 1, bre, match_prev_avail));
+}
+
+int main()
+{
+ test01();
+ test_pr102480();
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/84110.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/84110.cc
new file mode 100644
index 0000000..b9971dc
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/84110.cc
@@ -0,0 +1,39 @@
+// { dg-do run { target c++11 } }
+#include <regex>
+#include <string>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ const std::string s(1ul, '\0');
+ std::regex re(s);
+ VERIFY( std::regex_match(s, re) ); // PR libstdc++/84110
+
+#if __cpp_exceptions
+ using namespace std::regex_constants;
+ for (auto syn : {basic, extended, awk, grep, egrep})
+ {
+ try
+ {
+ std::regex{s, syn}; // '\0' is not valid for other grammars
+ VERIFY( false );
+ }
+ catch (const std::regex_error&)
+ {
+ }
+ }
+#endif
+}
+
+void test02()
+{
+ const std::string s("uh-\0h", 5);
+ std::regex re(s);
+ VERIFY( std::regex_match(s, re) );
+}
+
+int main()
+{
+ test01();
+ test02();
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/exception_safety.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/exception_safety.cc
new file mode 100644
index 0000000..462eebc
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/exception_safety.cc
@@ -0,0 +1,20 @@
+// { dg-do run { target c++11 } }
+#include <regex>
+#include <testsuite_hooks.h>
+
+int main()
+{
+ const auto f = std::regex::ECMAScript|std::regex::icase;
+ std::regex re("abc", f);
+ try
+ {
+ re.assign("[", std::regex::extended);
+ VERIFY( false );
+ }
+ catch (const std::regex_error&)
+ {
+ // [re.regex.assign] "If an exception is thrown, *this is unchanged."
+ VERIFY( re.flags() == f );
+ VERIFY( std::regex_match("abc", re) );
+ }
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/other.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/other.cc
new file mode 100644
index 0000000..f9b68a7
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/other.cc
@@ -0,0 +1,37 @@
+// { dg-do run { target c++11 } }
+#include <regex>
+#include <testsuite_iterators.h>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ signed char s[] = { 'a', '.' };
+ std::regex re(s, s+2); // This used to fail up to GCC 11.2
+ // VERIFY( regex_match("an", re) );
+
+ std::wstring str = L"xx";
+ str[0] = '1';
+ str[1] = '2';
+ re.assign(str.begin(), str.end());
+ VERIFY( regex_match("12", re) );
+}
+
+void
+test02()
+{
+ int i[] = { 'a', '.', '[', 'x', 'y', 'z', ']' };
+ __gnu_test::forward_container<int> fwd(i);
+ std::regex re(fwd.begin(), fwd.end());
+ VERIFY( regex_match("any", re) );
+
+ __gnu_test::input_container<int> input(i);
+ re.assign(input.begin(), input.end(), std::regex::icase);
+ VERIFY( regex_match("ANY", re) );
+}
+
+int main()
+{
+ test01();
+ test02();
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/grammar.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/grammar.cc
new file mode 100644
index 0000000..fd8531c
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/grammar.cc
@@ -0,0 +1,53 @@
+// { dg-do run { target c++11 } }
+#include <regex>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ std::regex re{""};
+ VERIFY( re.flags() & std::regex::ECMAScript );
+
+ std::regex re2{"", std::regex::flag_type{}};
+ VERIFY( re2.flags() == std::regex::flag_type() ); // See also PR 83598
+}
+
+void
+test02()
+{
+ // A valid value of type syntax_option_type shall have at most one of the
+ // grammar elements ECMAScript, basic, extended, awk, grep, egrep, set.
+
+ try
+ {
+ std::regex{"", std::regex::ECMAScript|std::regex::basic};
+ VERIFY( false );
+ }
+ catch (const std::regex_error&)
+ {
+ }
+
+ try
+ {
+ std::regex{"", std::regex::extended|std::regex::basic};
+ VERIFY( false );
+ }
+ catch (const std::regex_error&)
+ {
+ }
+
+ try
+ {
+ std::regex{"", std::regex::grep|std::regex::basic};
+ VERIFY( false );
+ }
+ catch (const std::regex_error&)
+ {
+ }
+}
+
+int main()
+{
+ test01();
+ test02();
+}
diff --git a/libstdc++-v3/testsuite/30_threads/jthread/100612.cc b/libstdc++-v3/testsuite/30_threads/jthread/100612.cc
new file mode 100644
index 0000000..d6c8170
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/jthread/100612.cc
@@ -0,0 +1,24 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-pthread" { target pthread } }
+// { dg-require-gthreads "" }
+
+#include <thread>
+
+void
+test_pfm()
+{
+ // PR libstdc++/100612
+ struct X
+ {
+ void run(std::stop_token) { }
+ void run_arg(int) { }
+ void run_args(std::stop_token, int, int) { }
+ };
+
+ X x;
+
+ std::jthread{&X::run, &x};
+ std::jthread{&X::run_arg, &x, 1};
+ std::jthread{&X::run_args, &x, 1, 1};
+}
diff --git a/libstdc++-v3/testsuite/30_threads/thread/cons/3.cc b/libstdc++-v3/testsuite/30_threads/thread/cons/3.cc
index efdc631..6677156 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/cons/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/cons/3.cc
@@ -21,12 +21,12 @@
// <http://www.gnu.org/licenses/>.
-#include <functional> // std::unary_function, std::ref
+#include <functional> // std::ref
#include <thread>
#include <system_error>
#include <testsuite_hooks.h>
-struct copyable : public std::unary_function<std::thread::id&, void>
+struct copyable
{
copyable() = default;
~copyable() = default;
@@ -84,5 +84,4 @@ void test03()
int main()
{
test03();
- return 0;
}
diff --git a/libstdc++-v3/testsuite/30_threads/thread/cons/4.cc b/libstdc++-v3/testsuite/30_threads/thread/cons/4.cc
index d74ad97..9508cb4 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/cons/4.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/cons/4.cc
@@ -21,12 +21,12 @@
// <http://www.gnu.org/licenses/>.
-#include <functional> // std::unary_function, std::ref, std::cref
+#include <functional> // std::ref, std::cref
#include <thread>
#include <system_error>
#include <testsuite_hooks.h>
-struct noncopyable : std::unary_function<std::thread::id&, void>
+struct noncopyable
{
noncopyable() = default;
~noncopyable() = default;
diff --git a/libstdc++-v3/testsuite/30_threads/thread/cons/5.cc b/libstdc++-v3/testsuite/30_threads/thread/cons/5.cc
index 74dcd84..6d4d685 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/cons/5.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/cons/5.cc
@@ -21,12 +21,12 @@
// <http://www.gnu.org/licenses/>.
-#include <functional> // std::unary_function, std::ref
+#include <functional> // std::ref
#include <thread>
#include <system_error>
#include <testsuite_hooks.h>
-struct nonconst : public std::unary_function<std::thread::id&, void>
+struct nonconst
{
void operator()(std::thread::id& id)
{
diff --git a/libstdc++-v3/testsuite/ext/pb_ds/example/basic_multimap.cc b/libstdc++-v3/testsuite/ext/pb_ds/example/basic_multimap.cc
index 1d0b491..143f3ee 100644
--- a/libstdc++-v3/testsuite/ext/pb_ds/example/basic_multimap.cc
+++ b/libstdc++-v3/testsuite/ext/pb_ds/example/basic_multimap.cc
@@ -51,9 +51,9 @@ using namespace __gnu_pbds;
// A simple hash functor.
// hash could serve instead of this functor, but it is not yet
// standard everywhere.
-struct string_hash : public unary_function<string, size_t>
+struct string_hash
{
- inline size_t
+ size_t
operator()(const string& r_s) const
{
size_t ret = 0;
diff --git a/libstdc++-v3/testsuite/ext/pb_ds/example/erase_if.cc b/libstdc++-v3/testsuite/ext/pb_ds/example/erase_if.cc
index 74ed846..bb8e9c4 100644
--- a/libstdc++-v3/testsuite/ext/pb_ds/example/erase_if.cc
+++ b/libstdc++-v3/testsuite/ext/pb_ds/example/erase_if.cc
@@ -48,7 +48,7 @@ using namespace __gnu_pbds;
// The following functor takes a map's value-type object and returns
// whether its key is between two numbers.
-struct between : public unary_function<pair<const int, char>, bool>
+struct between
{
// Constructor taking two numbers determining a range.
between(int b, int e) : m_b(b), m_e(e)
@@ -56,7 +56,7 @@ struct between : public unary_function<pair<const int, char>, bool>
// Operator determining whether a value-type object's key is within
// the range.
- inline bool
+ bool
operator()(const pair<const int, char>& r_val)
{ return r_val.first >= m_b&& r_val.first < m_e; }
diff --git a/libstdc++-v3/testsuite/ext/pb_ds/example/hash_illegal_resize.cc b/libstdc++-v3/testsuite/ext/pb_ds/example/hash_illegal_resize.cc
index d045b40..73eda50 100644
--- a/libstdc++-v3/testsuite/ext/pb_ds/example/hash_illegal_resize.cc
+++ b/libstdc++-v3/testsuite/ext/pb_ds/example/hash_illegal_resize.cc
@@ -62,9 +62,9 @@ using namespace __gnu_pbds;
// A simple hash functor.
// hash could serve instead of this functor, but it is not yet
// standard everywhere.
-struct int_hash : public unary_function<int, size_t>
+struct int_hash
{
- inline size_t
+ size_t
operator()(const int& r_i) const
{ return r_i; }
};
diff --git a/libstdc++-v3/testsuite/ext/pb_ds/example/hash_initial_size.cc b/libstdc++-v3/testsuite/ext/pb_ds/example/hash_initial_size.cc
index 0fe99d2..a69c9c9 100644
--- a/libstdc++-v3/testsuite/ext/pb_ds/example/hash_initial_size.cc
+++ b/libstdc++-v3/testsuite/ext/pb_ds/example/hash_initial_size.cc
@@ -49,9 +49,9 @@ using namespace __gnu_pbds;
// A simple hash functor.
// hash could serve instead of this functor, but it is not yet
// standard everywhere.
-struct int_hash : public unary_function<int, size_t>
+struct int_hash
{
- inline size_t
+ size_t
operator()(const int& r_i) const
{ return r_i; }
};
diff --git a/libstdc++-v3/testsuite/ext/pb_ds/example/hash_load_set_change.cc b/libstdc++-v3/testsuite/ext/pb_ds/example/hash_load_set_change.cc
index 976291f..8f7ed27 100644
--- a/libstdc++-v3/testsuite/ext/pb_ds/example/hash_load_set_change.cc
+++ b/libstdc++-v3/testsuite/ext/pb_ds/example/hash_load_set_change.cc
@@ -51,9 +51,9 @@ using namespace __gnu_pbds;
// A simple hash functor.
// hash could serve instead of this functor, but it is not yet
// standard everywhere.
-struct int_hash : public unary_function<int, size_t>
+struct int_hash
{
- inline size_t
+ size_t
operator()(int i) const
{ return i; }
};
diff --git a/libstdc++-v3/testsuite/ext/pb_ds/example/hash_mod.cc b/libstdc++-v3/testsuite/ext/pb_ds/example/hash_mod.cc
index f57a6ad..d42e6d8 100644
--- a/libstdc++-v3/testsuite/ext/pb_ds/example/hash_mod.cc
+++ b/libstdc++-v3/testsuite/ext/pb_ds/example/hash_mod.cc
@@ -49,9 +49,9 @@ using namespace __gnu_pbds;
// A simple hash functor.
// hash could serve instead of this functor, but it is not yet
// standard everywhere.
-struct int_hash : public unary_function<int, size_t>
+struct int_hash
{
- inline size_t
+ size_t
operator()(int i) const
{ return i; }
};
diff --git a/libstdc++-v3/testsuite/ext/pb_ds/example/hash_resize.cc b/libstdc++-v3/testsuite/ext/pb_ds/example/hash_resize.cc
index 53c5e26..f8e4a7b 100644
--- a/libstdc++-v3/testsuite/ext/pb_ds/example/hash_resize.cc
+++ b/libstdc++-v3/testsuite/ext/pb_ds/example/hash_resize.cc
@@ -50,9 +50,9 @@ using namespace __gnu_pbds;
// A simple hash functor.
// hash could serve instead of this functor, but it is not yet
// standard everywhere.
-struct int_hash : public unary_function<int, size_t>
+struct int_hash
{
- inline size_t
+ size_t
operator()(const int& r_i) const
{ return r_i; }
};
diff --git a/libstdc++-v3/testsuite/ext/pb_ds/example/hash_shift_mask.cc b/libstdc++-v3/testsuite/ext/pb_ds/example/hash_shift_mask.cc
index 19fb3d3..0ea02da 100644
--- a/libstdc++-v3/testsuite/ext/pb_ds/example/hash_shift_mask.cc
+++ b/libstdc++-v3/testsuite/ext/pb_ds/example/hash_shift_mask.cc
@@ -51,9 +51,9 @@ using namespace __gnu_pbds;
// A simple hash functor. hash could serve instead of this functor,
// but it is not yet standard everywhere.
-struct simple_int_hash : public unary_function<int, size_t>
+struct simple_int_hash
{
- inline size_t
+ size_t
operator()(int i) const
{ return i; }
};
diff --git a/libstdc++-v3/testsuite/ext/pb_ds/example/priority_queue_dijkstra.cc b/libstdc++-v3/testsuite/ext/pb_ds/example/priority_queue_dijkstra.cc
index 1910e2c..d99ebff7 100644
--- a/libstdc++-v3/testsuite/ext/pb_ds/example/priority_queue_dijkstra.cc
+++ b/libstdc++-v3/testsuite/ext/pb_ds/example/priority_queue_dijkstra.cc
@@ -61,9 +61,9 @@ using namespace __gnu_pbds;
typedef std::pair<size_t, size_t> pq_value;
// Comparison functor used to compare priority-queue value types.
-struct pq_value_cmp : public binary_function<pq_value, pq_value, bool>
+struct pq_value_cmp
{
- inline bool
+ bool
operator()(const pq_value& r_lhs, const pq_value& r_rhs) const
{
// Note that a value is considered smaller than a different value
diff --git a/libstdc++-v3/testsuite/ext/pb_ds/example/ranged_hash.cc b/libstdc++-v3/testsuite/ext/pb_ds/example/ranged_hash.cc
index a5b1898..86c37d4 100644
--- a/libstdc++-v3/testsuite/ext/pb_ds/example/ranged_hash.cc
+++ b/libstdc++-v3/testsuite/ext/pb_ds/example/ranged_hash.cc
@@ -60,7 +60,6 @@ using namespace __gnu_pbds;
* for larger sizes it uses a more complicated hash function.
*/
class simple_string_ranged_hash_fn
- : public unary_function<string, size_t>
{
public:
typedef size_t size_type;
diff --git a/libstdc++-v3/testsuite/ext/pb_ds/example/store_hash.cc b/libstdc++-v3/testsuite/ext/pb_ds/example/store_hash.cc
index 0bf6b06..5dd9cb7 100644
--- a/libstdc++-v3/testsuite/ext/pb_ds/example/store_hash.cc
+++ b/libstdc++-v3/testsuite/ext/pb_ds/example/store_hash.cc
@@ -53,9 +53,9 @@ using namespace std;
using namespace __gnu_pbds;
// A string hash functor.
-struct string_hash : public unary_function<string, size_t>
+struct string_hash
{
- inline size_t
+ size_t
operator()(string str) const
{
string::const_iterator b = str.begin();