aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2021-12-09 11:38:40 +0100
committerMartin Liska <mliska@suse.cz>2021-12-09 11:38:40 +0100
commit7a81590757659982cb9b93b922a4c182aa40e2d8 (patch)
tree6aa576127aba8f373e779fe7f82f4956a2d0861a /gcc
parent4cba2fa027afd5f815bd9bf3965afe1972c7387c (diff)
parent5791bf7a0a7705be6c3989c445e7c739220f3290 (diff)
downloadgcc-7a81590757659982cb9b93b922a4c182aa40e2d8.zip
gcc-7a81590757659982cb9b93b922a4c182aa40e2d8.tar.gz
gcc-7a81590757659982cb9b93b922a4c182aa40e2d8.tar.bz2
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog681
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/ada/ChangeLog760
-rw-r--r--gcc/ada/Makefile.rtl2
-rw-r--r--gcc/ada/contracts.adb2
-rw-r--r--gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst2
-rw-r--r--gcc/ada/exp_aggr.adb12
-rw-r--r--gcc/ada/exp_ch13.adb2
-rw-r--r--gcc/ada/exp_ch13.ads3
-rw-r--r--gcc/ada/exp_ch3.adb374
-rw-r--r--gcc/ada/exp_ch3.ads28
-rw-r--r--gcc/ada/exp_ch6.adb2
-rw-r--r--gcc/ada/exp_imgv.adb3
-rw-r--r--gcc/ada/exp_spark.adb289
-rw-r--r--gcc/ada/exp_util.adb1
-rw-r--r--gcc/ada/freeze.adb11
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in4
-rw-r--r--gcc/ada/gcc-interface/a-assert.adb52
-rw-r--r--gcc/ada/gcc-interface/a-assert.ads50
-rw-r--r--gcc/ada/gcc-interface/decl.c26
-rw-r--r--gcc/ada/gcc-interface/gigi.h7
-rw-r--r--gcc/ada/gcc-interface/trans.c30
-rw-r--r--gcc/ada/gcc-interface/utils.c17
-rw-r--r--gcc/ada/gen_il-fields.ads2
-rw-r--r--gcc/ada/gen_il-gen-gen_nodes.adb2
-rw-r--r--gcc/ada/gen_il-gen.adb6
-rw-r--r--gcc/ada/gnat_rm.texi2
-rw-r--r--gcc/ada/libgnarl/a-taside.ads2
-rw-r--r--gcc/ada/libgnarl/s-interr.adb12
-rw-r--r--gcc/ada/libgnarl/s-intman.ads4
-rw-r--r--gcc/ada/libgnarl/s-intman__posix.adb6
-rw-r--r--gcc/ada/libgnarl/s-mudido__affinity.adb6
-rw-r--r--gcc/ada/libgnarl/s-osinte__linux.ads8
-rw-r--r--gcc/ada/libgnarl/s-taprop__linux.adb8
-rw-r--r--gcc/ada/libgnarl/s-tasdeb.adb2
-rw-r--r--gcc/ada/libgnarl/s-tasdeb.ads2
-rw-r--r--gcc/ada/libgnarl/s-tasinf__linux.ads4
-rw-r--r--gcc/ada/libgnarl/s-taskin.adb2
-rw-r--r--gcc/ada/libgnarl/s-taskin.ads2
-rw-r--r--gcc/ada/libgnarl/s-tasren.adb16
-rw-r--r--gcc/ada/libgnarl/s-tassta.adb2
-rw-r--r--gcc/ada/libgnarl/s-tataat.adb2
-rw-r--r--gcc/ada/libgnarl/s-tpobop.adb12
-rw-r--r--gcc/ada/libgnat/a-calend.adb6
-rw-r--r--gcc/ada/libgnat/a-calend.ads2
-rw-r--r--gcc/ada/libgnat/a-cfinve.adb4
-rw-r--r--gcc/ada/libgnat/a-chahan.adb4
-rw-r--r--gcc/ada/libgnat/a-chtgbo.adb2
-rw-r--r--gcc/ada/libgnat/a-cobove.adb8
-rw-r--r--gcc/ada/libgnat/a-cofove.adb4
-rw-r--r--gcc/ada/libgnat/a-cohata.ads2
-rw-r--r--gcc/ada/libgnat/a-coinve.adb6
-rw-r--r--gcc/ada/libgnat/a-convec.adb12
-rw-r--r--gcc/ada/libgnat/a-coprnu.ads4
-rw-r--r--gcc/ada/libgnat/a-direct.adb14
-rw-r--r--gcc/ada/libgnat/a-direct.ads4
-rw-r--r--gcc/ada/libgnat/a-direio.adb2
-rw-r--r--gcc/ada/libgnat/a-nbnbre.adb10
-rw-r--r--gcc/ada/libgnat/a-ngrear.adb4
-rw-r--r--gcc/ada/libgnat/a-stbubo.adb6
-rw-r--r--gcc/ada/libgnat/a-stbufo.adb2
-rw-r--r--gcc/ada/libgnat/a-stbuun.adb6
-rw-r--r--gcc/ada/libgnat/a-stbuut.adb8
-rw-r--r--gcc/ada/libgnat/a-stmaco.ads44
-rw-r--r--gcc/ada/libgnat/a-strbou.ads38
-rw-r--r--gcc/ada/libgnat/a-strfix.ads6
-rw-r--r--gcc/ada/libgnat/a-strmap.adb4
-rw-r--r--gcc/ada/libgnat/a-strmap.ads2
-rw-r--r--gcc/ada/libgnat/a-strsup.adb36
-rw-r--r--gcc/ada/libgnat/a-strsup.ads36
-rw-r--r--gcc/ada/libgnat/a-sttebu.adb4
-rw-r--r--gcc/ada/libgnat/a-stuten.ads2
-rw-r--r--gcc/ada/libgnat/a-stwibo.ads4
-rw-r--r--gcc/ada/libgnat/a-stwima.ads3
-rw-r--r--gcc/ada/libgnat/a-stwisu.adb32
-rw-r--r--gcc/ada/libgnat/a-stzbou.ads6
-rw-r--r--gcc/ada/libgnat/a-stzmap.ads3
-rw-r--r--gcc/ada/libgnat/a-stzsup.adb32
-rw-r--r--gcc/ada/libgnat/a-swmwco.ads60
-rw-r--r--gcc/ada/libgnat/a-szmzco.ads60
-rw-r--r--gcc/ada/libgnat/a-teioed.adb4
-rw-r--r--gcc/ada/libgnat/a-wtedit.adb4
-rw-r--r--gcc/ada/libgnat/a-ztedit.adb4
-rw-r--r--gcc/ada/libgnat/g-arrspl.adb16
-rw-r--r--gcc/ada/libgnat/g-catiio.adb4
-rw-r--r--gcc/ada/libgnat/g-cgideb.adb4
-rw-r--r--gcc/ada/libgnat/g-comlin.adb8
-rw-r--r--gcc/ada/libgnat/g-comlin.ads4
-rw-r--r--gcc/ada/libgnat/g-debpoo.adb4
-rw-r--r--gcc/ada/libgnat/g-expect.adb10
-rw-r--r--gcc/ada/libgnat/g-forstr.adb6
-rw-r--r--gcc/ada/libgnat/g-memdum.adb4
-rw-r--r--gcc/ada/libgnat/g-rannum.adb2
-rw-r--r--gcc/ada/libgnat/g-sechas.adb6
-rw-r--r--gcc/ada/libgnat/g-sehamd.ads2
-rw-r--r--gcc/ada/libgnat/g-sehash.ads4
-rw-r--r--gcc/ada/libgnat/g-sercom.ads4
-rw-r--r--gcc/ada/libgnat/g-sercom__linux.adb12
-rw-r--r--gcc/ada/libgnat/g-shsh32.ads12
-rw-r--r--gcc/ada/libgnat/g-shsh64.ads12
-rw-r--r--gcc/ada/libgnat/g-socket.adb30
-rw-r--r--gcc/ada/libgnat/g-socket.ads40
-rw-r--r--gcc/ada/libgnat/g-socpol.adb16
-rw-r--r--gcc/ada/libgnat/g-socpol.ads8
-rw-r--r--gcc/ada/libgnat/g-sothco.ads12
-rw-r--r--gcc/ada/libgnat/g-spipat.adb4
-rw-r--r--gcc/ada/libgnat/i-c.adb472
-rw-r--r--gcc/ada/libgnat/i-c.ads420
-rw-r--r--gcc/ada/libgnat/i-cobol.ads8
-rw-r--r--gcc/ada/libgnat/i-pacdec.adb4
-rw-r--r--gcc/ada/libgnat/i-pacdec.ads4
-rw-r--r--gcc/ada/libgnat/s-aridou.adb243
-rw-r--r--gcc/ada/libgnat/s-arit32.adb449
-rw-r--r--gcc/ada/libgnat/s-arit32.ads68
-rw-r--r--gcc/ada/libgnat/s-arit64.ads3
-rw-r--r--gcc/ada/libgnat/s-bitops.adb4
-rw-r--r--gcc/ada/libgnat/s-crc32.adb4
-rw-r--r--gcc/ada/libgnat/s-gearop.adb4
-rw-r--r--gcc/ada/libgnat/s-genbig.adb30
-rw-r--r--gcc/ada/libgnat/s-htable.adb2
-rw-r--r--gcc/ada/libgnat/s-imgboo.adb12
-rw-r--r--gcc/ada/libgnat/s-imgboo.ads26
-rw-r--r--gcc/ada/libgnat/s-imgcha.adb8
-rw-r--r--gcc/ada/libgnat/s-os_lib.adb2
-rw-r--r--gcc/ada/libgnat/s-powflt.ads42
-rw-r--r--gcc/ada/libgnat/s-powlfl.ads90
-rw-r--r--gcc/ada/libgnat/s-powllf.ads110
-rw-r--r--gcc/ada/libgnat/s-rannum.adb14
-rw-r--r--gcc/ada/libgnat/s-rannum.ads2
-rw-r--r--gcc/ada/libgnat/s-regexp.adb24
-rw-r--r--gcc/ada/libgnat/s-regpat.adb20
-rw-r--r--gcc/ada/libgnat/s-regpat.ads4
-rw-r--r--gcc/ada/libgnat/s-scaval__128.adb8
-rw-r--r--gcc/ada/libgnat/s-statxd.adb22
-rw-r--r--gcc/ada/libgnat/s-stausa.adb12
-rw-r--r--gcc/ada/libgnat/s-strops.adb2
-rw-r--r--gcc/ada/libgnat/s-valboo.adb18
-rw-r--r--gcc/ada/libgnat/s-valboo.ads54
-rw-r--r--gcc/ada/libgnat/s-valrea.adb12
-rw-r--r--gcc/ada/libgnat/s-valuer.adb5
-rw-r--r--gcc/ada/libgnat/s-valueu.adb2
-rw-r--r--gcc/ada/libgnat/s-valuti.adb166
-rw-r--r--gcc/ada/libgnat/s-valuti.ads265
-rw-r--r--gcc/ada/libgnat/s-wchcon.ads8
-rw-r--r--gcc/ada/libgnat/s-widint.ads15
-rw-r--r--gcc/ada/libgnat/s-widlli.ads15
-rw-r--r--gcc/ada/libgnat/s-widllli.ads15
-rw-r--r--gcc/ada/libgnat/s-widlllu.ads11
-rw-r--r--gcc/ada/libgnat/s-widllu.ads11
-rw-r--r--gcc/ada/libgnat/s-widthi.adb133
-rw-r--r--gcc/ada/libgnat/s-widthi.ads7
-rw-r--r--gcc/ada/libgnat/s-widthu.adb54
-rw-r--r--gcc/ada/libgnat/s-widthu.ads7
-rw-r--r--gcc/ada/libgnat/s-widuns.ads11
-rw-r--r--gcc/ada/par-ch4.adb6
-rw-r--r--gcc/ada/rtsfind.adb14
-rw-r--r--gcc/ada/rtsfind.ads2
-rw-r--r--gcc/ada/scng.adb4
-rw-r--r--gcc/ada/sem_aggr.adb24
-rw-r--r--gcc/ada/sem_ch12.adb276
-rw-r--r--gcc/ada/sem_ch13.adb28
-rw-r--r--gcc/ada/sem_ch3.adb51
-rw-r--r--gcc/ada/sem_ch6.adb4
-rw-r--r--gcc/ada/sem_ch8.adb1
-rw-r--r--gcc/ada/sem_util.adb41
-rw-r--r--gcc/ada/sem_util.ads6
-rw-r--r--gcc/ada/sem_warn.adb69
-rw-r--r--gcc/ada/snames.ads-tmpl1
-rw-r--r--gcc/ada/sprint.adb5
-rw-r--r--gcc/ada/vxworks7-cert-rtp-link__ppcXX.spec10
-rw-r--r--gcc/analyzer/ChangeLog19
-rw-r--r--gcc/analyzer/constraint-manager.cc149
-rw-r--r--gcc/analyzer/constraint-manager.h2
-rw-r--r--gcc/analyzer/region-model-reachability.cc13
-rw-r--r--gcc/attribs.c2
-rw-r--r--gcc/attribs.h1
-rw-r--r--gcc/auto-profile.c20
-rw-r--r--gcc/c-family/ChangeLog12
-rw-r--r--gcc/c-family/c-pch.c15
-rw-r--r--gcc/c-family/c.opt4
-rw-r--r--gcc/c/ChangeLog24
-rw-r--r--gcc/c/c-parser.c57
-rw-r--r--gcc/c/c-typeck.c102
-rw-r--r--gcc/common.opt8
-rw-r--r--gcc/common/config/riscv/riscv-common.c38
-rw-r--r--gcc/config.gcc7
-rw-r--r--gcc/config/aarch64/aarch64-protos.h1
-rw-r--r--gcc/config/aarch64/aarch64-simd.md65
-rw-r--r--gcc/config/aarch64/aarch64.c12
-rw-r--r--gcc/config/avr/avr.c9
-rw-r--r--gcc/config/avr/genmultilib.awk16
-rw-r--r--gcc/config/avr/t-avr1
-rw-r--r--gcc/config/bpf/bpf.c27
-rw-r--r--gcc/config/darwin.c2
-rw-r--r--gcc/config/darwin.h9
-rw-r--r--gcc/config/host-darwin.c191
-rw-r--r--gcc/config/i386/i386-expand.c15
-rw-r--r--gcc/config/i386/i386-options.c101
-rw-r--r--gcc/config/i386/i386-options.h6
-rw-r--r--gcc/config/i386/i386-protos.h1
-rw-r--r--gcc/config/i386/i386.c38
-rw-r--r--gcc/config/i386/i386.h20
-rw-r--r--gcc/config/i386/i386.md10
-rw-r--r--gcc/config/i386/i386.opt8
-rw-r--r--gcc/config/i386/sse.md197
-rw-r--r--gcc/config/i386/x86-tune.def14
-rw-r--r--gcc/config/mips/mips.h6
-rw-r--r--gcc/config/mips/mips.md10
-rw-r--r--gcc/config/mips/mips.opt4
-rw-r--r--gcc/config/nvptx/nvptx.md26
-rw-r--r--gcc/config/pa/pa.c4
-rw-r--r--gcc/config/pru/pru.c19
-rwxr-xr-xgcc/config/riscv/arch-canonicalize16
-rw-r--r--gcc/config/riscv/riscv-opts.h22
-rw-r--r--gcc/config/riscv/riscv.opt3
-rw-r--r--gcc/config/rs6000/altivec.h518
-rw-r--r--gcc/config/rs6000/rs6000-builtin-new.def30
-rw-r--r--gcc/config/rs6000/rs6000-c.c11
-rw-r--r--gcc/config/rs6000/rs6000-call.c64
-rw-r--r--gcc/config/rs6000/rs6000-gen-builtins.c2
-rw-r--r--gcc/config/rs6000/rs6000-internal.h3
-rw-r--r--gcc/config/rs6000/rs6000.c43
-rw-r--r--gcc/config/rs6000/xmmintrin.h2
-rw-r--r--gcc/config/s390/s390.c2
-rw-r--r--gcc/config/vxworks.h2
-rwxr-xr-xgcc/configure7
-rw-r--r--gcc/configure.ac5
-rw-r--r--gcc/coverage.c3
-rw-r--r--gcc/cp/ChangeLog92
-rw-r--r--gcc/cp/constexpr.c140
-rw-r--r--gcc/cp/cp-gimplify.c3
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/cxx-pretty-print.c4
-rw-r--r--gcc/cp/error.c10
-rw-r--r--gcc/cp/parser.c123
-rw-r--r--gcc/cp/pt.c21
-rw-r--r--gcc/cp/semantics.c737
-rw-r--r--gcc/cp/tree.c12
-rw-r--r--gcc/cp/typeck.c14
-rw-r--r--gcc/cse.c7
-rw-r--r--gcc/d/ChangeLog74
-rw-r--r--gcc/d/Make-lang.in42
-rw-r--r--gcc/d/d-builtins.cc7
-rw-r--r--gcc/d/d-codegen.cc36
-rw-r--r--gcc/d/d-frontend.cc11
-rw-r--r--gcc/d/d-frontend.h2
-rw-r--r--gcc/d/d-gimplify.cc65
-rw-r--r--gcc/d/d-lang.cc18
-rw-r--r--gcc/d/d-spec.cc18
-rw-r--r--gcc/d/d-tree.h9
-rw-r--r--gcc/d/decl.cc155
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/README.md18
-rw-r--r--gcc/d/dmd/VERSION2
-rw-r--r--gcc/d/dmd/aggregate.d81
-rw-r--r--gcc/d/dmd/aggregate.h17
-rw-r--r--gcc/d/dmd/aliasthis.d23
-rw-r--r--gcc/d/dmd/arrayop.d2
-rw-r--r--gcc/d/dmd/attrib.d22
-rw-r--r--gcc/d/dmd/blockexit.d4
-rw-r--r--gcc/d/dmd/builtin.d2
-rw-r--r--gcc/d/dmd/chkformat.d8
-rw-r--r--gcc/d/dmd/clone.d139
-rw-r--r--gcc/d/dmd/common/README.md7
-rw-r--r--gcc/d/dmd/common/file.d576
-rw-r--r--gcc/d/dmd/common/outbuffer.d (renamed from gcc/d/dmd/root/outbuffer.d)243
-rw-r--r--gcc/d/dmd/common/outbuffer.h (renamed from gcc/d/dmd/root/outbuffer.h)10
-rw-r--r--gcc/d/dmd/common/string.d209
-rw-r--r--gcc/d/dmd/cond.d3
-rw-r--r--gcc/d/dmd/cparse.d225
-rw-r--r--gcc/d/dmd/cppmangle.d15
-rw-r--r--gcc/d/dmd/ctfeexpr.d5
-rw-r--r--gcc/d/dmd/dcast.d136
-rw-r--r--gcc/d/dmd/dclass.d23
-rw-r--r--gcc/d/dmd/declaration.d161
-rw-r--r--gcc/d/dmd/declaration.h9
-rw-r--r--gcc/d/dmd/dinterpret.d46
-rw-r--r--gcc/d/dmd/dmacro.d2
-rw-r--r--gcc/d/dmd/dmangle.d53
-rw-r--r--gcc/d/dmd/dmodule.d142
-rw-r--r--gcc/d/dmd/doc.d28
-rw-r--r--gcc/d/dmd/dscope.d15
-rw-r--r--gcc/d/dmd/dstruct.d39
-rw-r--r--gcc/d/dmd/dsymbol.d110
-rw-r--r--gcc/d/dmd/dsymbol.h20
-rw-r--r--gcc/d/dmd/dsymbolsem.d167
-rw-r--r--gcc/d/dmd/dtemplate.d41
-rw-r--r--gcc/d/dmd/dtoh.d31
-rw-r--r--gcc/d/dmd/dversion.d2
-rw-r--r--gcc/d/dmd/expression.d104
-rw-r--r--gcc/d/dmd/expression.h55
-rw-r--r--gcc/d/dmd/expressionsem.d426
-rw-r--r--gcc/d/dmd/file_manager.d301
-rw-r--r--gcc/d/dmd/file_manager.h (renamed from gcc/d/dmd/root/root.h)17
-rw-r--r--gcc/d/dmd/func.d76
-rw-r--r--gcc/d/dmd/globals.d27
-rw-r--r--gcc/d/dmd/globals.h23
-rw-r--r--gcc/d/dmd/gluelayer.d1
-rw-r--r--gcc/d/dmd/hdrgen.d20
-rw-r--r--gcc/d/dmd/iasmgcc.d2
-rw-r--r--gcc/d/dmd/id.d11
-rw-r--r--gcc/d/dmd/identifier.d2
-rw-r--r--gcc/d/dmd/importc.d171
-rw-r--r--gcc/d/dmd/init.d2
-rw-r--r--gcc/d/dmd/initsem.d128
-rw-r--r--gcc/d/dmd/intrange.h177
-rw-r--r--gcc/d/dmd/json.d6
-rw-r--r--gcc/d/dmd/lambdacomp.d2
-rw-r--r--gcc/d/dmd/lexer.d237
-rw-r--r--gcc/d/dmd/lexer.h75
-rw-r--r--gcc/d/dmd/macro.h38
-rw-r--r--gcc/d/dmd/mars.h93
-rw-r--r--gcc/d/dmd/module.h2
-rw-r--r--gcc/d/dmd/mtype.d211
-rw-r--r--gcc/d/dmd/mtype.h4
-rw-r--r--gcc/d/dmd/ob.d2
-rw-r--r--gcc/d/dmd/objc.d2
-rw-r--r--gcc/d/dmd/opover.d43
-rw-r--r--gcc/d/dmd/optimize.d2
-rw-r--r--gcc/d/dmd/parse.d12
-rw-r--r--gcc/d/dmd/parse.h192
-rw-r--r--gcc/d/dmd/printast.d2
-rw-r--r--gcc/d/dmd/root/README.md1
-rw-r--r--gcc/d/dmd/root/aav.h22
-rw-r--r--gcc/d/dmd/root/checkedint.h30
-rw-r--r--gcc/d/dmd/root/file.d529
-rw-r--r--gcc/d/dmd/root/filename.d102
-rw-r--r--gcc/d/dmd/root/hash.h76
-rw-r--r--gcc/d/dmd/root/rootobject.d2
-rw-r--r--gcc/d/dmd/root/speller.h16
-rw-r--r--gcc/d/dmd/root/stringtable.h56
-rw-r--r--gcc/d/dmd/safe.d2
-rw-r--r--gcc/d/dmd/semantic2.d4
-rw-r--r--gcc/d/dmd/semantic3.d18
-rw-r--r--gcc/d/dmd/statement.d8
-rw-r--r--gcc/d/dmd/statement.h6
-rw-r--r--gcc/d/dmd/statement_rewrite_walker.h172
-rw-r--r--gcc/d/dmd/statementsem.d160
-rw-r--r--gcc/d/dmd/staticcond.d2
-rw-r--r--gcc/d/dmd/target.d3
-rw-r--r--gcc/d/dmd/target.h3
-rw-r--r--gcc/d/dmd/template.h10
-rw-r--r--gcc/d/dmd/tokens.d2
-rw-r--r--gcc/d/dmd/tokens.h1
-rw-r--r--gcc/d/dmd/traits.d33
-rw-r--r--gcc/d/dmd/typesem.d48
-rw-r--r--gcc/d/dmd/typinf.d238
-rw-r--r--gcc/d/dmd/utf.h117
-rw-r--r--gcc/d/dmd/utils.d2
-rw-r--r--gcc/d/expr.cc12
-rw-r--r--gcc/d/gdc.texi9
-rw-r--r--gcc/d/lang.opt4
-rw-r--r--gcc/d/modules.cc2
-rw-r--r--gcc/d/types.cc19
-rw-r--r--gcc/doc/gty.texi9
-rw-r--r--gcc/doc/install.texi4
-rw-r--r--gcc/doc/invoke.texi51
-rw-r--r--gcc/doc/tm.texi5
-rw-r--r--gcc/doc/tm.texi.in2
-rw-r--r--gcc/dwarf2cfi.c264
-rw-r--r--gcc/dwarf2out.c54
-rw-r--r--gcc/dwarf2out.h36
-rw-r--r--gcc/expr.c2
-rw-r--r--gcc/file-prefix-map.c17
-rw-r--r--gcc/file-prefix-map.h2
-rw-r--r--gcc/fold-const.c26
-rw-r--r--gcc/fold-const.h1
-rw-r--r--gcc/fortran/ChangeLog74
-rw-r--r--gcc/fortran/array.c19
-rw-r--r--gcc/fortran/dump-parse-tree.c18
-rw-r--r--gcc/fortran/expr.c25
-rw-r--r--gcc/fortran/frontend-passes.c4
-rw-r--r--gcc/fortran/gfortran.h4
-rw-r--r--gcc/fortran/match.c9
-rw-r--r--gcc/fortran/openmp.c578
-rw-r--r--gcc/fortran/parse.c19
-rw-r--r--gcc/fortran/resolve.c9
-rw-r--r--gcc/fortran/symbol.c3
-rw-r--r--gcc/fortran/trans-openmp.c35
-rw-r--r--gcc/fortran/trans-stmt.c17
-rw-r--r--gcc/gcc.c6
-rw-r--r--gcc/gengtype-state.c32
-rw-r--r--gcc/gengtype.c39
-rw-r--r--gcc/gengtype.h6
-rw-r--r--gcc/ggc-common.c52
-rw-r--r--gcc/ggc.h4
-rw-r--r--gcc/gimple-harden-conditionals.cc141
-rw-r--r--gcc/gimple-range-cache.cc73
-rw-r--r--gcc/gimple-range-cache.h1
-rw-r--r--gcc/gimple-range-edge.cc3
-rw-r--r--gcc/gimple-range-gori.cc77
-rw-r--r--gcc/gimple-range-gori.h6
-rw-r--r--gcc/gimple-range-path.cc23
-rw-r--r--gcc/gimple-range-path.h2
-rw-r--r--gcc/gimple-range.cc29
-rw-r--r--gcc/gimplify.c344
-rw-r--r--gcc/hash-map.h6
-rw-r--r--gcc/ifcvt.c4
-rw-r--r--gcc/internal-fn.c17
-rw-r--r--gcc/ipa-modref-tree.c2
-rw-r--r--gcc/ira-color.c31
-rw-r--r--gcc/lto-opts.c1
-rw-r--r--gcc/match.pd22
-rw-r--r--gcc/objc/ChangeLog8
-rw-r--r--gcc/objc/objc-next-metadata-tags.h2
-rw-r--r--gcc/objc/objc-next-runtime-abi-01.c9
-rw-r--r--gcc/objc/objc-next-runtime-abi-02.c9
-rw-r--r--gcc/objc/objc-runtime-shared-support.c9
-rw-r--r--gcc/omp-low.c2
-rw-r--r--gcc/opt-functions.awk2
-rw-r--r--gcc/opts-common.c21
-rw-r--r--gcc/opts-global.c4
-rw-r--r--gcc/opts.c2
-rw-r--r--gcc/opts.h4
-rw-r--r--gcc/output.h14
-rw-r--r--gcc/predict.c2
-rw-r--r--gcc/profile-count.c48
-rw-r--r--gcc/profile-count.h6
-rw-r--r--gcc/profile.c4
-rw-r--r--gcc/reg-stack.c5
-rw-r--r--gcc/target.def8
-rw-r--r--gcc/testsuite/ChangeLog450
-rw-r--r--gcc/testsuite/c-c++-common/goacc/deep-copy-arrayofstruct.c5
-rw-r--r--gcc/testsuite/c-c++-common/goacc/pr102432.c23
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr102432.c23
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-enter-data-1.c24
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-implicit-map-2.c52
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-fp-except1.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype-bitfield1.C65
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype-bitfield2.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/decltype-auto2.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/decltype-auto3.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/decltype-auto4.C65
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/constexpr-if36.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp-decltype1.C28
-rw-r--r--gcc/testsuite/g++.dg/cpp23/concepts-err1.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/bit-cast11.C63
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/bit-cast12.C68
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/bit-cast13.C63
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/bit-cast14.C75
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/scope1.C12
-rw-r--r--gcc/testsuite/g++.dg/ext/integer-pack5.C29
-rw-r--r--gcc/testsuite/g++.dg/gomp/target-3.C36
-rw-r--r--gcc/testsuite/g++.dg/gomp/target-lambda-1.C94
-rw-r--r--gcc/testsuite/g++.dg/gomp/target-lambda-2.C35
-rw-r--r--gcc/testsuite/g++.dg/gomp/target-this-1.C33
-rw-r--r--gcc/testsuite/g++.dg/gomp/target-this-2.C49
-rw-r--r--gcc/testsuite/g++.dg/gomp/target-this-3.C105
-rw-r--r--gcc/testsuite/g++.dg/gomp/target-this-4.C107
-rw-r--r--gcc/testsuite/g++.dg/gomp/target-this-5.C34
-rw-r--r--gcc/testsuite/g++.dg/gomp/this-2.C24
-rw-r--r--gcc/testsuite/g++.dg/pr103024.C12
-rw-r--r--gcc/testsuite/g++.dg/pr103530.C27
-rw-r--r--gcc/testsuite/g++.dg/template/lookup18.C17
-rw-r--r--gcc/testsuite/g++.dg/torture/pr71792.C42
-rwxr-xr-xgcc/testsuite/g++.target/i386/pr100738-1.C19
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/leak-3.c41
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr103526.c50
-rw-r--r--gcc/testsuite/gcc.dg/bic-bitmask-18.c2
-rw-r--r--gcc/testsuite/gcc.dg/fold-condneg-1.c59
-rw-r--r--gcc/testsuite/gcc.dg/fold-condneg-2.c11
-rw-r--r--gcc/testsuite/gcc.dg/fold-condnot-1.c84
-rw-r--r--gcc/testsuite/gcc.dg/gomp/target-3.c16
-rw-r--r--gcc/testsuite/gcc.dg/loop-unswitch-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/loop-unswitch-2.c5
-rw-r--r--gcc/testsuite/gcc.dg/loop-unswitch-3.c7
-rw-r--r--gcc/testsuite/gcc.dg/loop-unswitch-4.c1
-rw-r--r--gcc/testsuite/gcc.dg/loop-unswitch-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr101145-1.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr101145-2.c15
-rw-r--r--gcc/testsuite/gcc.dg/pr103028.c21
-rw-r--r--gcc/testsuite/gcc.dg/pr103594.c14
-rw-r--r--gcc/testsuite/gcc.dg/sibcall-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/sibcall-10.c6
-rw-r--r--gcc/testsuite/gcc.dg/sibcall-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/sibcall-3.c6
-rw-r--r--gcc/testsuite/gcc.dg/sibcall-4.c6
-rw-r--r--gcc/testsuite/gcc.dg/sibcall-9.c6
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr103596.c36
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/init-array.c43
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/nonzero-1a.c11
-rw-r--r--gcc/testsuite/gcc.dg/ubsan/pr103456.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr103517.c13
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr103544.c24
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr103581.c59
-rw-r--r--gcc/testsuite/gcc.target/aarch64/aapcs64/macro-def.h2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-1.c15
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-2.c11
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-3.c11
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-4.c11
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr103149.c14
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pred-combine-and.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-1c.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memcpy-17.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memcpy-18.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memcpy-19.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memcpy-20.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memcpy-21.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-45.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-46.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-47.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-48.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-49.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102327-1.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102811-1.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102811.c (renamed from gcc/testsuite/gcc.target/i386/avx512vl-vcvtps2ph-pr102811.c)0
-rw-r--r--gcc/testsuite/gcc.target/i386/pr103097.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/pr103404.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/pr83782-1.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/pr83782-2.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/pr95740.c26
-rw-r--r--gcc/testsuite/gcc.target/mips/mips.exp1
-rw-r--r--gcc/testsuite/gcc.target/mips/unaligned-2.c53
-rw-r--r--gcc/testsuite/gcc.target/mips/unaligned-3.c53
-rw-r--r--gcc/testsuite/gcc.target/nvptx/exttrunc-1.c20
-rw-r--r--gcc/testsuite/gcc.target/nvptx/exttrunc-2.c17
-rw-r--r--gcc/testsuite/gcc.target/nvptx/exttrunc-3.c17
-rw-r--r--gcc/testsuite/gcc.target/nvptx/exttrunc-4.c17
-rw-r--r--gcc/testsuite/gcc.target/nvptx/exttrunc-5.c17
-rw-r--r--gcc/testsuite/gcc.target/nvptx/exttrunc-6.c17
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-5.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-3.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-5.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/cmpb-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/cmpb-3.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/cmpb32-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/crypto-builtin-2.c14
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-splat-floatdouble.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-splat-longlong.c10
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-splat-misc-invalid.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c6
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr101324.c17
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr103127.c19
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80315-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80315-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80315-3.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80315-4.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr88100.c12
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pragma_misc9.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pragma_power8.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pragma_power9.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/rop-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/rop-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/rop-3.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/rop-4.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/rop-5.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/test_fpscr_drn_builtin_error.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/test_fpscr_rn_builtin_error.c12
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-gnb-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec_reve_1.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsu/vec-all-nez-7.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsu/vec-any-eqz-7.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsu/vec-cmpnez-7.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsu/vec-cntlz-lsbb-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsu/vec-cnttz-lsbb-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-13.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-12.c2
-rw-r--r--gcc/testsuite/gcc.target/pru/pru_irq_map.c8
-rw-r--r--gcc/testsuite/gcc.target/riscv/pr103302.c47
-rw-r--r--gcc/testsuite/gdc.test/compilable/b19294.d69
-rw-r--r--gcc/testsuite/gdc.test/compilable/cdcmp.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables_22285.d15
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_ignored.d5
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/cstuff3.c6
-rw-r--r--gcc/testsuite/gdc.test/compilable/mixintype2.d49
-rw-r--r--gcc/testsuite/gdc.test/compilable/noreturn1.d49
-rw-r--r--gcc/testsuite/gdc.test/compilable/previewall.d10
-rw-r--r--gcc/testsuite/gdc.test/compilable/reinterpretctfe.d14
-rw-r--r--gcc/testsuite/gdc.test/compilable/sroa.d55
-rw-r--r--gcc/testsuite/gdc.test/compilable/stc_traits.d172
-rw-r--r--gcc/testsuite/gdc.test/compilable/test15711.d31
-rw-r--r--gcc/testsuite/gdc.test/compilable/test16492.d87
-rw-r--r--gcc/testsuite/gdc.test/compilable/test19482.d68
-rw-r--r--gcc/testsuite/gdc.test/compilable/test21438.d15
-rw-r--r--gcc/testsuite/gdc.test/compilable/test21794.d52
-rw-r--r--gcc/testsuite/gdc.test/compilable/test21850.d35
-rw-r--r--gcc/testsuite/gdc.test/compilable/test22214.d16
-rw-r--r--gcc/testsuite/gdc.test/compilable/test22224.d4
-rw-r--r--gcc/testsuite/gdc.test/compilable/test22228.d11
-rw-r--r--gcc/testsuite/gdc.test/compilable/test22292.d155
-rw-r--r--gcc/testsuite/gdc.test/compilable/test22388.d22
-rw-r--r--gcc/testsuite/gdc.test/compilable/test22410.d59
-rw-r--r--gcc/testsuite/gdc.test/compilable/test22420.d88
-rw-r--r--gcc/testsuite/gdc.test/compilable/test22421.d19
-rw-r--r--gcc/testsuite/gdc.test/compilable/test318.d19
-rw-r--r--gcc/testsuite/gdc.test/compilable/test4090.d17
-rw-r--r--gcc/testsuite/gdc.test/compilable/test9766.d4
-rw-r--r--gcc/testsuite/gdc.test/compilable/testcstuff3.d4
-rw-r--r--gcc/testsuite/gdc.test/compilable/transition_in.d26
-rw-r--r--gcc/testsuite/gdc.test/compilable/zerosize.d13
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag10327.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag20059.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail20618.d16
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail21091a.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail21091b.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail22084.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail22151.d24
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail22366.d15
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail225.d17
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail287.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail318.d8
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail318_b.d11
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail7173.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/foreach.d14
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/foreach2.d22
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice10212.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice22377.d8
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice7782.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/imp22329.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/noreturn.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/noreturn2.d90
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/reserved_version.d6
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d6
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test17425.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test17868b.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test20998.d120
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test21093.d56
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test21380.d46
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test21930.d27
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test22329.d21
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test22361.d11
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/testOpApply.d161
-rw-r--r--gcc/testsuite/gdc.test/runnable/aliasthis.d36
-rw-r--r--gcc/testsuite/gdc.test/runnable/dhry.d16
-rw-r--r--gcc/testsuite/gdc.test/runnable/fix22372.d38
-rw-r--r--gcc/testsuite/gdc.test/runnable/interpret.d57
-rw-r--r--gcc/testsuite/gdc.test/runnable/noreturn1.d47
-rw-r--r--gcc/testsuite/gdc.test/runnable/noreturn2.d220
-rw-r--r--gcc/testsuite/gdc.test/runnable/sroa13220.d103
-rw-r--r--gcc/testsuite/gdc.test/runnable/test15624.d51
-rw-r--r--gcc/testsuite/gdc.test/runnable/test21039.d27
-rw-r--r--gcc/testsuite/gdc.test/runnable/test22205.d17
-rw-r--r--gcc/testsuite/gdc.test/runnable/test22278.d24
-rw-r--r--gcc/testsuite/gdc.test/runnable/testOpApply.d142
-rw-r--r--gcc/testsuite/gdc.test/runnable/testmainb.d15
-rw-r--r--gcc/testsuite/gdc.test/runnable/uda.d48
-rw-r--r--gcc/testsuite/gdc.test/runnable/ufcs.d1
-rw-r--r--gcc/testsuite/gdc.test/runnable_cxx/extra-files/cpp22287.cpp337
-rw-r--r--gcc/testsuite/gdc.test/runnable_cxx/test22287.d327
-rw-r--r--gcc/testsuite/gfortran.dg/allocate_with_mold_4.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/allocate_with_source_26.f908
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/finalize-1.f8
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/affinity-clause-1.f906
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/affinity-clause-5.f904
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic-10.f9032
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic-12.f90364
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic-15.f9044
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic-16.f9036
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic-17.f9041
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic-18.f9027
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic-19.f9039
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic-2.f9042
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic-20.f9039
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic-22.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic-24.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic-25.f9053
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic-26.f9075
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic.f9040
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/defaultmap-4.f9044
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/defaultmap-5.f9030
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/defaultmap-6.f9020
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/map-3.f904
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/pr78260-2.f908
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/pr78260-3.f904
-rw-r--r--gcc/testsuite/gfortran.dg/pr103505.f909
-rw-r--r--gcc/testsuite/gfortran.dg/pr103588.f908
-rw-r--r--gcc/testsuite/gfortran.dg/pr103607.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/pr103609.f9015
-rw-r--r--gcc/testsuite/gfortran.dg/select_9.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/shape_11.f9016
-rw-r--r--gcc/testsuite/lib/gcc-dg.exp14
-rw-r--r--gcc/testsuite/lib/target-supports.exp6
-rw-r--r--gcc/tree-core.h2
-rw-r--r--gcc/tree-pretty-print.c8
-rw-r--r--gcc/tree-ssa-loop-niter.c19
-rw-r--r--gcc/tree-ssa-loop-unswitch.c129
-rw-r--r--gcc/tree-ssa-propagate.c62
-rw-r--r--gcc/tree-ssa-propagate.h2
-rw-r--r--gcc/tree-ssa-sccvn.c2
-rw-r--r--gcc/tree-vect-slp.c19
-rw-r--r--gcc/tree-vect-stmts.c79
-rw-r--r--gcc/tree-vectorizer.h9
-rw-r--r--gcc/value-range.cc46
-rw-r--r--gcc/varasm.c13
692 files changed, 21122 insertions, 6415 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d8101a3..66c7532 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,684 @@
+2021-12-08 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.h (DARWIN_PIE_SPEC): Add -no_pie when
+ linking mdynamic-no-pic code on macOS > 10.7.
+
+2021-12-08 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * config/pru/pru.c (pru_section_type_flags): New function.
+ (TARGET_SECTION_TYPE_FLAGS): Wire it.
+
+2021-12-08 David Faust <david.faust@oracle.com>
+
+ * config/bpf/bpf.c (handle_attr_preserve): Avoid calling
+ is_gimple_assign with a NULL pointer.
+
+2021-12-08 Martin Liska <mliska@suse.cz>
+
+ * profile-count.c (profile_count::dump): Add function
+ that can dump to a provided buffer.
+ (profile_probability::dump): Likewise.
+ * profile-count.h: Likewise.
+ * tree-ssa-loop-unswitch.c (tree_unswitch_single_loop):
+ Use dump_printf_loc infrastructure.
+ (tree_unswitch_outer_loop): Likewise.
+ (find_loop_guard): Likewise.
+ (hoist_guard): Likewise.
+
+2021-12-08 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * gimplify.c (extract_base_bit_offset): Add 'tree *offsetp' parameter,
+ accomodate case where 'offset' return of get_inner_reference is
+ non-NULL.
+ (is_or_contains_p): Further robustify conditions.
+ (omp_target_reorder_clauses): In alloc/to/from sorting phase, also
+ move following GOMP_MAP_ALWAYS_POINTER maps along. Add new sorting
+ phase where we make sure pointers with an attach/detach map are ordered
+ correctly.
+ (gimplify_scan_omp_clauses): Add modifications to avoid creating
+ GOMP_MAP_STRUCT and associated alloc map for attach/detach maps.
+
+2021-12-08 Roger Sayle <roger@nextmovesoftware.com>
+
+ * config/nvptx/nvptx.md (*extend_trunc_<mode>2_qi,
+ *extend_trunc_<mode>2_hi, *extend_trunc_di2_si): New insns.
+ Use cvt to perform sign-extension of truncation in one step.
+
+2021-12-08 Chung-Lin Tang <cltang@codesourcery.com>
+
+ PR middle-end/92120
+ * gimplify.c ("tree-hash-traits.h"): Add include.
+ (gimplify_scan_omp_clauses): Change struct_map_to_clause to type
+ hash_map<tree_operand, tree> *. Adjust struct map handling to handle
+ cases of *A and A->B expressions. Under !DECL_P case of
+ GOMP_CLAUSE_MAP handling, add STRIP_NOPS for indir_p case, add to
+ struct_deref_set for map(*ptr_to_struct) cases. Add MEM_REF case when
+ handling component_ref_p case. Add unshare_expr and gimplification
+ when created GOMP_MAP_STRUCT is not a DECL. Add code to add
+ firstprivate pointer for *pointer-to-struct case.
+ (gimplify_adjust_omp_clauses): Move GOMP_MAP_STRUCT removal code for
+ exit data directives code to earlier position.
+ * omp-low.c (lower_omp_target):
+ Handle GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION, and
+ GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION map kinds.
+ * tree-pretty-print.c (dump_omp_clause): Likewise.
+
+2021-12-08 Andrew Stubbs <ams@codesourcery.com>
+ Hafiz Abid Qadeer <abidh@codesourcery.com>
+
+ * dwarf2cfi.c (dw_stack_pointer_regnum): Change type to struct cfa_reg.
+ (dw_frame_pointer_regnum): Likewise.
+ (new_cfi_row): Use set_by_dwreg.
+ (get_cfa_from_loc_descr): Use set_by_dwreg. Support register spans.
+ handle DW_OP_bregx with DW_OP_breg{0-31}. Support DW_OP_lit*,
+ DW_OP_const*, DW_OP_minus, DW_OP_shl and DW_OP_plus.
+ (lookup_cfa_1): Use set_by_dwreg.
+ (def_cfa_0): Update for cfa_reg and support register spans.
+ (reg_save): Change sreg parameter to struct cfa_reg. Support register
+ spans.
+ (dwf_cfa_reg): New function.
+ (dwarf2out_flush_queued_reg_saves): Use dwf_cfa_reg instead of
+ dwf_regno.
+ (dwarf2out_frame_debug_def_cfa): Likewise.
+ (dwarf2out_frame_debug_adjust_cfa): Likewise.
+ (dwarf2out_frame_debug_cfa_offset): Likewise. Update reg_save usage.
+ (dwarf2out_frame_debug_cfa_register): Likewise.
+ (dwarf2out_frame_debug_expr): Likewise.
+ (create_pseudo_cfg): Use set_by_dwreg.
+ (initial_return_save): Use set_by_dwreg and dwf_cfa_reg,
+ (create_cie_data): Use dwf_cfa_reg.
+ (execute_dwarf2_frame): Use dwf_cfa_reg.
+ (dump_cfi_row): Use set_by_dwreg.
+ * dwarf2out.c (build_span_loc, build_breg_loc): New function.
+ (build_cfa_loc): Support register spans.
+ (build_cfa_aligned_loc): Update cfa_reg usage.
+ (convert_cfa_to_fb_loc_list): Use set_by_dwreg.
+ * dwarf2out.h (struct cfa_reg): New type.
+ (struct dw_cfa_location): Use struct cfa_reg.
+ (build_span_loc): New prototype.
+
+2021-12-08 Haochen Jiang <haochen.jiang@intel.com>
+
+ PR target/100738
+ * config/i386/sse.md
+ (*<sse4_1>_blendv<ssefltmodesuffix><avxsizesuffix>_not_ltint):
+ Add new define_insn_and_split.
+
+2021-12-08 Alexandre Oliva <oliva@adacore.com>
+
+ PR middle-end/103149
+ * gimple-harden-conditionals.cc (detach_value): Use memory if
+ general regs won't do.
+
+2021-12-07 Martin Liska <mliska@suse.cz>
+
+ PR middle-end/103438
+ * config/s390/s390.c (s390_valid_target_attribute_inner_p):
+ Use new enum CLVC_INTEGER.
+ * opt-functions.awk: Use new CLVC_INTEGER.
+ * opts-common.c (set_option): Likewise.
+ (option_enabled): Return -1,0,1 for CLVC_INTEGER.
+ (get_option_state): Use new CLVC_INTEGER.
+ (control_warning_option): Likewise.
+ * opts.h (enum cl_var_type): Likewise.
+
+2021-12-07 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/103594
+ * config/i386/i386.c (ix86_call_use_plt_p): Check FUNCTION_DECL
+ before calling cgraph_node::get.
+
+2021-12-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/103596
+ * tree-ssa-sccvn.c (eliminate_dom_walker::eliminate_stmt):
+ Note we are not propagating into a PHI argument to may_propagate_copy.
+ * tree-ssa-propagate.h (may_propagate_copy): Add
+ argument specifying whether we propagate into a PHI arg.
+ * tree-ssa-propagate.c (may_propagate_copy): Likewise.
+ When not doing so we can replace an abnormal with
+ something else.
+ (may_propagate_into_stmt): Update may_propagate_copy calls.
+ (replace_exp_1): Move propagation checking code to
+ propagate_value and rename to ...
+ (replace_exp): ... this and elide previous wrapper.
+ (propagate_value): Perform checking with adjusted
+ may_propagate_copy call and dispatch to replace_exp.
+
+2021-12-07 Matthias Kretz <m.kretz@gsi.de>
+
+ * hash-map.h (hash_map::traverse): Let both overloads behave the
+ same.
+ * predict.c (assert_is_empty): Return true, thus not changing
+ behavior.
+
+2021-12-07 YunQiang Su <yunqiang.su@cipunited.com>
+
+ * config/mips/mips.h (ISA_HAS_UNALIGNED_ACCESS, STRICT_ALIGNMENT):
+ R6 can unaligned access.
+ * config/mips/mips.md (movmisalign<mode>): Likewise.
+ * config/mips/mips.opt: add -m(no-)unaligned-access
+ * doc/invoke.texi: Likewise.
+
+2021-12-07 Eugene Rozenfeld <erozen@microsoft.com>
+
+ * auto-profile.c (afdo_propagate_edge): Improve count propagation algorithm.
+
+2021-12-06 Paul A. Clarke <pc@us.ibm.com>
+
+ PR target/103545
+ * config/rs6000/xmmintrin.h (_mm_movemask_ps): Replace "vector" with
+ "__vector".
+
+2021-12-06 Jose E. Marchesi <jose.marchesi@oracle.com>
+
+ * config/bpf/bpf.c (bpf_handle_preserve_access_index_attribute):
+ Mark arguments `args' and flags' as unused.
+ (bpf_core_newdecl): Remove unused local `newdecl'.
+ (bpf_core_newdecl): Remove unused argument `loc'.
+ (ctfc_debuginfo_early_finish_p): Remove unused function.
+ (TARGET_CTFC_DEBUGINFO_EARLY_FINISH_P): Remove definition.
+ (bpf_core_walk): Do not pass a location to bpf_core_newdecl.
+
+2021-12-06 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gimple-range-edge.cc (gimple_outgoing_range::edge_range_p): Add
+ a shortcut for blocks with single successors.
+ * gimple-range-gori.cc (gori_map::calculate_gori): Likewise.
+
+2021-12-06 Richard Sandiford <richard.sandiford@arm.com>
+
+ * value-range.cc (irange::irange_union): Use quick_push rather
+ than safe_push. Use widest_int rather than wide_int. Avoid
+ assigning wi::to_* results to wide*_int temporaries.
+
+2021-12-06 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-cache.cc (ranger_cache::fill_block_cache): Check for
+ a range from dominators before filling the cache.
+ (ranger_cache::range_from_dom): New.
+ * gimple-range-cache.h (ranger_cache::range_from_dom): Add prototype.
+
+2021-12-06 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-gori.h (class gori_compute):: Add prototypes.
+ * gimple-range-gori.cc (gori_compute::has_edge_range_p): Add alternate
+ API for basic block. Call for edge alterantive.
+ (gori_compute::may_recompute_p): Ditto.
+
+2021-12-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/103581
+ * tree-vect-stmts.c (vect_build_gather_load_calls): Properly
+ guard all the AVX512 mask cases.
+
+2021-12-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/103544
+ * tree-vect-slp.c (vect_analyze_slp): Only add a SLP reduction
+ opportunity if the stmt in question is the reduction root.
+ (dot_slp_tree): Add missing check for NULL child.
+
+2021-12-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR pch/71934
+ * config/avr/avr.c (avr_output_data_section_asm_op,
+ avr_output_bss_section_asm_op): Change argument type from const void *
+ to const char *.
+
+2021-12-06 Tamar Christina <tamar.christina@arm.com>
+
+ PR rtl-optimization/103404
+ * cse.c (find_sets_in_insn): Don't select elements out of a V1 mode
+ subreg.
+
+2021-12-06 Hongtao Liu <Hongtao.liu@intel.com>
+ Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/95740
+ * config/i386/i386.c (ix86_preferred_reload_class): Allow
+ integer regs when moves between register units are cheap.
+ * config/i386/i386.h (INT_SSE_CLASS_P): New.
+
+2021-12-05 David Edelsohn <dje.gcc@gmail.com>
+
+ * config/rs6000/rs6000-call.c (rs6000_init_builtins): Move
+ AIX math builtin initialization before new_builtins_are_live.
+
+2021-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/x86-tune.def (X86_TUNE_PARTIAL_REG_DEPENDENCY): Fix
+ comment typo, Preffer -> prefer.
+ * ipa-modref-tree.c (modref_access_node::closer_pair_p): Likewise.
+
+2021-12-04 Alexandre Oliva <oliva@adacore.com>
+
+ PR rtl-optimization/103028
+ * ifcvt.c (find_cond_trap): Validate new insns more strictly
+ after reload.
+
+2021-12-03 Martin Liska <mliska@suse.cz>
+ Peter Bergner <bergner@linux.ibm.com>
+
+ PR target/101324
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Move the
+ disabling of shrink-wrapping when using -mrop-protect from here...
+ (rs6000_override_options_after_change): ...to here.
+
+2021-12-03 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/103269
+ * config/i386/i386-expand.c (ix86_expand_builtin): Pass PVW_NONE
+ and PVW_NONE to ix86_target_string.
+ * config/i386/i386-options.c (ix86_target_string): Add arguments
+ for move_max and store_max.
+ (ix86_target_string::add_vector_width): New lambda.
+ (ix86_debug_options): Pass ix86_move_max and ix86_store_max to
+ ix86_target_string.
+ (ix86_function_specific_print): Pass ptr->x_ix86_move_max and
+ ptr->x_ix86_store_max to ix86_target_string.
+ (ix86_valid_target_attribute_tree): Handle x_ix86_move_max and
+ x_ix86_store_max.
+ (ix86_option_override_internal): Set the default x_ix86_move_max
+ and x_ix86_store_max.
+ * config/i386/i386-options.h (ix86_target_string): Add
+ prefer_vector_width and prefer_vector_width.
+ * config/i386/i386.h (TARGET_AVX256_MOVE_BY_PIECES): Removed.
+ (TARGET_AVX256_STORE_BY_PIECES): Likewise.
+ (MOVE_MAX): Use 64 if ix86_move_max or ix86_store_max ==
+ PVW_AVX512. Use 32 if ix86_move_max or ix86_store_max >=
+ PVW_AVX256.
+ (STORE_MAX_PIECES): Use 64 if ix86_store_max == PVW_AVX512.
+ Use 32 if ix86_store_max >= PVW_AVX256.
+ * config/i386/i386.opt: Add -mmove-max=bits and -mstore-max=bits.
+ * config/i386/x86-tune.def (X86_TUNE_AVX512_MOVE_BY_PIECES): New.
+ (X86_TUNE_AVX512_STORE_BY_PIECES): Likewise.
+ * doc/invoke.texi: Document -mmove-max=bits and -mstore-max=bits.
+
+2021-12-03 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_builtin_reciprocal): Fix builtin
+ identifiers.
+
+2021-12-03 SiYu Wu <siyu@isrc.iscas.ac.cn>
+
+ * common/config/riscv/riscv-common.c (riscv_implied_info):
+ Add K-ext related entry.
+ (riscv_supported_std_ext): Add 'k'.
+ * config/riscv/arch-canonicalize (CANONICAL_ORDER): Add 'k'.
+ (IMPLIED_EXT): Add K-ext related entry.
+
+2021-12-03 SiYu Wu <siyu@isrc.iscas.ac.cn>
+
+ * common/config/riscv/riscv-common.c (riscv_ext_version_table):
+ Add zbk* and zk*.
+ * config/riscv/riscv-opts.h (MASK_ZBKB): New.
+ (MASK_ZBKC): Ditto.
+ (MASK_ZBKX): Ditto.
+ (MASK_ZKNE): Ditto.
+ (MASK_ZKND): Ditto.
+ (MASK_ZKNH): Ditto.
+ (MASK_ZKR): Ditto.
+ (MASK_ZKSED): Ditto.
+ (MASK_ZKSH): Ditto.
+ (MASK_ZKT): Ditto.
+ (TARGET_ZBKB): Ditto.
+ (TARGET_ZBKC): Ditto.
+ (TARGET_ZBKX): Ditto.
+ (TARGET_ZKNE): Ditto.
+ (TARGET_ZKND): Ditto.
+ (TARGET_ZKNH): Ditto.
+ (TARGET_ZKR): Ditto.
+ (TARGET_ZKSED): Ditto.
+ (TARGET_ZKSH): Ditto.
+ (TARGET_ZKT): Ditto.
+ * config/riscv/riscv.opt (riscv_zk_subext): New.
+
+2021-12-03 Tamar Christina <tamar.christina@arm.com>
+
+ * tree-vect-stmts.c (prepare_load_store_mask): Rename to...
+ (prepare_vec_mask): ...This and record operations that have already been
+ masked.
+ (vectorizable_call): Use it.
+ (vectorizable_operation): Likewise.
+ (vectorizable_store): Likewise.
+ (vectorizable_load): Likewise.
+ * tree-vectorizer.h (class _loop_vec_info): Add vec_cond_masked_set.
+ (vec_cond_masked_set_type, tree_cond_mask_hash): New.
+
+2021-12-03 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/51469
+ PR target/83782
+ * target.def (ifunc_ref_local_ok): Add a target hook.
+ * varasm.c (default_binds_local_p_3): Force indirect function
+ resolver non-local only if targetm.ifunc_ref_local_ok returns
+ false.
+ * config/i386/i386-expand.c (ix86_expand_call): Call
+ ix86_call_use_plt_p to check if PLT should be used.
+ * config/i386/i386-protos.h (ix86_call_use_plt_p): New.
+ * config/i386/i386.c (output_pic_addr_const): Call
+ ix86_call_use_plt_p to check if "@PLT" is needed.
+ (ix86_call_use_plt_p): New.
+ (TARGET_IFUNC_REF_LOCAL_OK): New.
+ * doc/tm.texi.in: Add TARGET_IFUNC_REF_LOCAL_OK.
+ * doc/tm.texi: Regenerated.
+
+2021-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ * attribs.h (simple_cst_list_equal): Declare.
+ * attribs.c (simple_cst_list_equal): No longer static.
+ * config/i386/i386-options.c (target_attribute_cache): New variable.
+ (ix86_valid_target_attribute_p): Cache DECL_FUNCTION_SPECIFIC_TARGET
+ and DECL_FUNCTION_SPECIFIC_OPTIMIZATION based on args.
+
+2021-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR pch/71934
+ * ggc.h (gt_pch_note_callback): Declare.
+ * gengtype.h (enum typekind): Add TYPE_CALLBACK.
+ (callback_type): Declare.
+ * gengtype.c (dbgprint_count_type_at): Handle TYPE_CALLBACK.
+ (callback_type): New variable.
+ (process_gc_options): Add CALLBACK argument, handle callback
+ option.
+ (set_gc_used_type): Adjust process_gc_options caller, if callback,
+ set type to &callback_type.
+ (output_mangled_typename): Handle TYPE_CALLBACK.
+ (walk_type): Likewise. Handle callback option.
+ (write_types_process_field): Handle TYPE_CALLBACK.
+ (write_types_local_user_process_field): Likewise.
+ (write_types_local_process_field): Likewise.
+ (write_root): Likewise.
+ (dump_typekind): Likewise.
+ (dump_type): Likewise.
+ * gengtype-state.c (type_lineloc): Handle TYPE_CALLBACK.
+ (state_writer::write_state_callback_type): New method.
+ (state_writer::write_state_type): Handle TYPE_CALLBACK.
+ (read_state_callback_type): New function.
+ (read_state_type): Handle TYPE_CALLBACK.
+ * ggc-common.c (callback_vec): New variable.
+ (gt_pch_note_callback): New function.
+ (gt_pch_save): Stream out gt_pch_save function address and relocation
+ table.
+ (gt_pch_restore): Stream in saved gt_pch_save function address and
+ relocation table and apply relocations if needed.
+ * doc/gty.texi (callback): Document new GTY option.
+ * varasm.c (get_unnamed_section): Change callback argument's type and
+ last argument's type from const void * to const char *.
+ (output_section_asm_op): Change argument's type from const void *
+ to const char *, remove unnecessary cast.
+ * tree-core.h (struct tree_translation_unit_decl): Drop GTY((skip))
+ from language member.
+ * output.h (unnamed_section_callback): Change argument type from
+ const void * to const char *.
+ (struct unnamed_section): Use GTY((callback)) instead of GTY((skip))
+ for callback member. Change data member type from const void *
+ to const char *.
+ (struct noswitch_section): Use GTY((callback)) instead of GTY((skip))
+ for callback member.
+ (get_unnamed_section): Change callback argument's type and
+ last argument's type from const void * to const char *.
+ (output_section_asm_op): Change argument's type from const void *
+ to const char *.
+ * config/avr/avr.c (avr_output_progmem_section_asm_op): Likewise.
+ Remove unneeded cast.
+ * config/darwin.c (output_objc_section_asm_op): Change argument's type
+ from const void * to const char *.
+ * config/pa/pa.c (som_output_text_section_asm_op): Likewise.
+ (som_output_comdat_data_section_asm_op): Likewise.
+ * config/rs6000/rs6000.c (rs6000_elf_output_toc_section_asm_op):
+ Likewise.
+ (rs6000_xcoff_output_readonly_section_asm_op): Likewise. Instead
+ of dereferencing directive hardcode variable names and decide based on
+ whether directive is NULL or not.
+ (rs6000_xcoff_output_readwrite_section_asm_op): Change argument's type
+ from const void * to const char *.
+ (rs6000_xcoff_output_tls_section_asm_op): Likewise. Instead
+ of dereferencing directive hardcode variable names and decide based on
+ whether directive is NULL or not.
+ (rs6000_xcoff_output_toc_section_asm_op): Change argument's type
+ from const void * to const char *.
+ (rs6000_xcoff_asm_init_sections): Adjust get_unnamed_section callers.
+
+2021-12-03 Richard Purdie <richard.purdie@linuxfoundation.org>
+
+ * Makefile.in: Fix "argument list too long" from install-plugins.
+
+2021-12-03 Matt Jacobson <mhjacobson@me.com>
+
+ * config.gcc: For the AVR target, populate TM_MULTILIB_CONFIG.
+ * config/avr/genmultilib.awk: Add ability to filter generated multilib
+ list.
+ * config/avr/t-avr: Pass TM_MULTILIB_CONFIG to genmultilib.awk.
+ * configure.ac: Update help string for --with-multilib-list.
+ * configure: Regenerate.
+
+2021-12-02 Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
+
+ * configure: Regenerate.
+ * configure.ac: Define TARGET_LIBC_GNUSTACK on musl.
+
+2021-12-02 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR target/55610
+ * config/host-darwin.c (TRY_EMPTY_VM_SPACE,
+ SAFE_ALLOC_SIZE): New.
+ (darwin_gt_pch_get_address): Rewrite to use nominated
+ memory segments rather than part of the compiler __DATA
+ segment.
+ (darwin_gt_pch_use_address): Likewise.
+
+2021-12-02 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * doc/install.texi (*-*-freebsd*): Remove references to
+ FreeBSD 1 and FreeBSD 2.
+
+2021-12-02 Vladimir N. Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/103437
+ * ira-color.c (setup_allocno_priorities): Switch off backup code
+ for overflow if compiler has __builtin_smul_overflow. Use <
+ for comparison with -INT_MAX.
+
+2021-12-02 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * config/rs6000/altivec.h: Delete a number of #defines that are now
+ superfluous. Alphabetize. Include rs6000-vecdefines.h. Include some
+ synonyms.
+ * config/rs6000/rs6000-builtin-new.def (CMPB): Flag as no32bit.
+ (BPERMD): Flag as 32bit (needing special handling for 32-bit).
+ (UNPACK_TD): Return unsigned long long instead of unsigned long.
+ (GET_TEXASR): Return unsigned long instead of unsigned long long.
+ (GET_TEXASRU): Likewise.
+ (GET_TFHAR): Likewise.
+ (GET_TFIAR): Likewise.
+ (SET_TEXASR): Pass unsigned long instead of unsigned long long.
+ (SET_TEXASRU): Likewise.
+ (SET_TFHAR): Likewise.
+ (SET_TFIAR): Likewise.
+ (TABORTDC): Likewise.
+ (TABORTDCI): Likewise.
+ * config/rs6000/rs6000-call.c (rs6000_expand_new_builtin): Fix error
+ handling for no32bit. Add 32bit handling for RS6000_BIF_BPERMD.
+ * config/rs6000/rs6000-gen-builtins.c (write_init_file): Initialize
+ new_builtins_are_live to 1.
+
+2021-12-02 Vladimir N. Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/103437
+ * ira-color.c (setup_allocno_priorities): Use long long
+ multiplication as backup for overflow processing.
+
+2021-12-02 Tamar Christina <tamar.christina@arm.com>
+
+ * config/aarch64/aarch64-protos.h (aarch64_gen_shareable_zero): New.
+ * config/aarch64/aarch64-simd.md (aarch64_rshrn<mode>,
+ aarch64_rshrn2<mode>): Generate rounding half-ing add when appropriate.
+ * config/aarch64/aarch64.c (aarch64_gen_shareable_zero): New.
+
+2021-12-02 Vladimir N. Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/103437
+ * ira-color.c (setup_allocno_priorities): Process multiplication
+ overflow.
+
+2021-12-02 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/96092
+ * common.opt: New option.
+ * coverage.c (coverage_begin_function): Emit filename with
+ remap_profile_filename.
+ * doc/invoke.texi: Document the new option.
+ * file-prefix-map.c (add_profile_prefix_map): New.
+ (remap_profile_filename): Likewise.
+ * file-prefix-map.h (add_profile_prefix_map): Likewise.
+ (remap_profile_filename): Likewise.
+ * lto-opts.c (lto_write_options): Handle
+ OPT_fprofile_prefix_map_.
+ * opts-global.c (handle_common_deferred_options): Likewise.
+ * opts.c (common_handle_option): Likewise.
+ (gen_command_line_string): Likewise.
+ * profile.c (output_location): Emit filename with
+ remap_profile_filename.
+
+2021-12-02 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/103271
+ * internal-fn.c (expand_DEFERRED_INIT): When the base
+ of the LHS is a decl with matching constant size use
+ that as the initialization target instead of an
+ eventual VLA typed one.
+
+2021-12-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/103527
+ * tree-vect-stmts.c (vect_build_gather_load_calls): Always
+ use a truth type for building the vector mask.
+
+2021-12-02 Rasmus Villemoes <rasmus.villemoes@prevas.dk>
+
+ * config/vxworks.h (LTO_PLUGIN_SPEC): Adapt to corrected
+ spelling of -linker-output-auto-nolto-rel.
+
+2021-12-01 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/102811
+ * config/i386/sse.md (VI2F): Remove mode iterator.
+ (VI2F_256_512): New mode iterator.
+ (vec_set<V8_128:mode>_0): New insn pattern.
+ (vec_set<VI2F_256_512:mode>_0>): Rename from vec_set<VI2F:mode>mode.
+ Use VI2F_256_512 mode iterator instead of VI2F.
+ (*axv512fp16_movsh): Remove.
+ (<sse2p4_1>_pinsr<ssemodesuffix>): Add (x,x,x) AVX2 alternative.
+ Do not disable V8HF mode insn on AVX2 targets.
+ (pinsrw -> pbroadcast + pblendw peephole2): New peephole.
+ (pinsrw -> pbroadcast + pblendw splitter): New post-reload splitter.
+ * config/i386/i386.md (extendhfsf): Call gen_vec_setv8hf_0.
+ * config/i386/i386-expand.c (ix86_expand_vector_set)
+ <case E_V8HFmode>: Use vec_merge path for TARGET_AVX2.
+
+2021-12-01 Roger Sayle <roger@nextmovesoftware.com>
+ Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-loop-niter.c (number_of_iterations_until_wrap):
+ Check if simplify_using_initial_conditions allows us to
+ simplify the expression for may_be_zero.
+ * match.pd (X != C ? -X : -C -> -X): New transform.
+ (X != C ? ~X : ~C -> ~X): Likewise.
+ ((X+1) > Y ? -X : 1 -> X >= Y ? -X : 1): Likewise.
+
+2021-12-01 Peter Bergner <bergner@linux.ibm.com>
+
+ PR middle-end/103127
+ * gimplify.c (is_var_need_auto_init): Handle opaque types.
+
+2021-12-01 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * common.opt (static-libphobos): Add option.
+ * config/darwin.h (LINK_SPEC): Substitute -lgphobos with libgphobos.a
+ when linking statically.
+ * gcc.c (driver_handle_option): Set -static-libphobos as always valid.
+
+2021-12-01 Jason Merrill <jason@redhat.com>
+
+ PR c++/103310
+ * fold-const.c (maybe_nonzero_address): Use get_create or get
+ depending on folding_initializer.
+ (fold_binary_initializer_loc): New.
+ * fold-const.h (fold_binary_initializer_loc): Declare.
+ * varasm.c (mark_weak): Don't use the decl location.
+ * doc/invoke.texi: Document -fconstexpr-fp-except.
+
+2021-12-01 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ PR target/102347
+ * config/rs6000/rs6000-c.c (rs6000-builtins.h): Stop including.
+ (rs6000-internal.h): Include.
+ (altivec_resolve_new_overloaded_builtin): Move call to
+ rs6000_invalid_new_builtin here from rs6000_new_builtin_decl.
+ * config/rs6000/rs6000-call.c (rs6000-builtins.h): Stop including.
+ (rs6000_invalid_new_builtin): Remove static qualifier.
+ (rs6000_new_builtin_decl): Remove test for supported builtin.
+ * config/rs6000/rs6000-internal.h (rs6000-builtins.h): Include.
+ (rs6000_invalid_new_builtin): Declare.
+ * config/rs6000/rs6000.c (rs6000-builtins.h): Don't include.
+
+2021-12-01 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/103409
+ * gimple-range-path.cc (path_range_query::compute_ranges_in_phis):
+ Do all the work with just one ssa_global_cache.
+ * gimple-range-path.h: Remove m_tmp_phi_cache.
+
+2021-12-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/103517
+ * tree-vect-slp.c (vect_build_slp_tree_1): When allowing two
+ different component references, check the codes of both them,
+ rather than just the first.
+
+2021-12-01 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/103464
+ * gimple-range.cc (gimple_ranger::prefill_name): Process phis also.
+ (gimple_ranger::prefill_stmt_dependencies): Ditto.
+
+2021-12-01 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * doc/install.texi (Prerequisites): Add note that D front end now
+ requires GDC installed in order to bootstrap.
+ (Building): Add D compiler section, referencing prerequisites.
+
+2021-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/x86-tune.def (X86_TUNE_SCHEDULE,
+ X86_TUNE_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY,
+ X86_TUNE_MISALIGNED_MOVE_STRING_PRO_EPILOGUES): Formatting fixes.
+ (X86_TUNE_USE_GATHER): Put m_GENERIC last for consistency.
+
+2021-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/102356
+ * rtl.h (simplify_context): Add assoc_count member and
+ max_assoc_count static member.
+ * simplify-rtx.c (simplify_associative_operation): Don't reassociate
+ more than max_assoc_count times within one outermost simplify_* call.
+ * dwarf2out.c (mem_loc_descriptor): Optimize binary operation
+ with both operands the same using DW_OP_dup.
+
+2021-12-01 Tamar Christina <tamar.christina@arm.com>
+
+ * match.pd: Move below pattern that rewrites to EQ, NE.
+ * tree.c (bitmask_inv_cst_vector_p): Correct do .. while indentation.
+
+2021-12-01 Siddhesh Poyarekar <siddhesh@gotplt.org>
+ Martin Liška <mliska@suse.cz>
+
+ PR tree-optimization/103456
+ * tree-object-size.c (merge_object_sizes): Update osi->changed
+ only if object_sizes_set succeeded.
+
2021-11-30 liuhongt <hongtao.liu@intel.com>
PR target/103463
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index d78b194..6f8b77f 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20211201
+20211209
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 81ea8a7..2a0be9e 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -3691,7 +3691,7 @@ install-plugin: installdirs lang.install-plugin s-header-vars install-gengtype
# We keep the directory structure for files in config, common/config or
# c-family and .def files. All other files are flattened to a single directory.
$(mkinstalldirs) $(DESTDIR)$(plugin_includedir)
- headers=`echo $(PLUGIN_HEADERS) $$(cd $(srcdir); echo *.h *.def) | tr ' ' '\012' | sort -u`; \
+ headers=`echo $(sort $(PLUGIN_HEADERS)) $$(cd $(srcdir); echo *.h *.def) | tr ' ' '\012' | sort -u`; \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`; \
for file in $$headers; do \
if [ -f $$file ] ; then \
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 411115d..7d7d811 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,763 @@
+2021-12-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/Make-lang.in (ADA_GENERATED_FILES): Add warning.
+
+2021-12-02 Marc Poulhiès <poulhies@adacore.com>
+
+ * gcc-interface/a-assert.ads, gcc-interface/a-assert.adb: Remove.
+
+2021-12-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity): Do not back-annotate a
+ maximum size for the Esize of limited record and concurrent types.
+
+2021-12-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/gigi.h (aggregate_type_contains_array_p): Delete.
+ (type_has_variable_size): Declare.
+ * gcc-interface/decl.c (adjust_packed): Return 0 only if the field
+ type is an array with variable size.
+ * gcc-interface/utils.c (aggregate_type_contains_array_p): Make
+ static and remove SELF_REFERENTIAL parameter.
+ (type_has_variable_size): Make public.
+ (create_field_decl): Adjust call to aggregate_type_contains_array_p.
+
+2021-12-02 Justin Squirek <squirek@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity): Skip normal
+ processing for Itypes that are E_Class_Wide_Subtype with
+ Equivalent_Type set.
+
+2021-12-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Call_to_gnu): Rename GNAT_NAME variable
+ into GNAT_SUBPROG to avoid later shadowing.
+
+2021-12-02 Yannick Moy <moy@adacore.com>
+
+ * libgnat/s-arit32.adb: Add ghost instances and lemmas.
+ (Scaled_Divide32): Add ghost code to prove. Minor code
+ modification to return early in error when divisor is zero.
+ * libgnat/s-arit32.ads: Add ghost instances and utilities.
+ (Scaled_Divide32): Add contract.
+
+2021-12-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ * sprint.adb (Source_Dump): Set both Print_Generated_Code and
+ Debug_Generated_Code to False at the end.
+
+2021-12-02 Marc Poulhiès <poulhies@adacore.com>
+
+ * sem_aggr.adb (Resolve_Array_Aggregate): Filter out nodes not
+ coming from source before emitting the warning.
+
+2021-12-02 Yannick Moy <moy@adacore.com>
+
+ * libgnat/s-aridou.adb (Log_Single_Size, Big_0): New ghost
+ constants.
+ (Lemma_Mult_Non_Negative, Lemma_Mult_Non_Positive,
+ Lemma_Not_In_Range_Big2xx64): New lemmas on big integers.
+ (Double_Divide): Remove justifications. Amend for that local
+ lemma Prove_Overflow_Case.
+ (Scaled_Divide): Remove justifications. Insert for that local
+ lemmas Prove_Negative_Dividend, Prove_Positive_Dividend and
+ Prove_Q_Too_Big, and amend local lemma Prove_Overflow. To prove
+ the loop invariant on (Shift mod 2 = 0), introduce local ghost
+ variable Iter to count loop iterations, and relate its value to
+ the value of Shift through Log_Single_Size, with the help of
+ local lemma Prove_Power. Deal with proof regression by adding
+ new local lemma Prove_First_Iteration and local ghost variable
+ D123.
+ * libgnat/s-arit64.ads (Multiply_With_Ovflo_Check64): Remove
+ unnecessary Pure_Function on function as package is Pure.
+
+2021-12-02 Yannick Moy <moy@adacore.com>
+
+ * libgnat/s-widthi.adb: Add pragma Annotate.
+
+2021-12-02 Yannick Moy <moy@adacore.com>
+
+ * libgnat/s-widint.ads: Mark in SPARK.
+ * libgnat/s-widlli.ads: Likewise.
+ * libgnat/s-widllli.ads: Likewise.
+ * libgnat/s-widlllu.ads: Likewise.
+ * libgnat/s-widllu.ads: Disable ghost/contract.
+ * libgnat/s-widthi.adb: Replicate and adapt the proof from
+ s-widthu.adb.
+ * libgnat/s-widthi.ads: Add minimal postcondition.
+ * libgnat/s-widthu.adb: Fix comments in the modular case.
+ * libgnat/s-widthu.ads: Add minimal postcondition.
+ * libgnat/s-widuns.ads: Disable ghost/contract.
+
+2021-12-02 Piotr Trojanek <trojanek@adacore.com>
+
+ * rtsfind.ads (RE_Id, RE_Unit_Table): Add RE_Suspension_Object.
+ * sem_util.adb (Is_Descendant_Of_Suspension_Object): Use Is_RTE.
+ (Is_Suspension_Object): Remove body.
+ * sem_util.ads (Is_Suspension_Object): Remove spec.
+ * snames.ads-tmpl (Name_Suspension_Object): Remove, now
+ unreferenced.
+
+2021-12-02 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_util.adb (Append_Freeze_Action): Tune whitespace to make
+ the code look similar to Append_Freeze_Actions, which takes a
+ List_Id.
+ * sem_ch6.adb (Analyze_Return_Type): Cleanup with
+ Append_Freeze_Action.
+ * exp_ch3.adb (Build_Access_Subprogram_Wrapper_Body): Likewise.
+ * sem_ch3.adb (Build_Access_Subprogram_Wrapper): Likewise.
+ * contracts.adb (Add_Indirect_Call_Wrapper): Remove extra call
+ to Ensure_Freeze_Node.
+ (Add_Call_Helper): Likewise.
+ * freeze.adb (Check_Inherited_Conditions): Likewise.
+ (Attribute_Renaming): Likewise.
+ * sem_ch8.adb: Likewise.
+
+2021-12-02 Piotr Trojanek <trojanek@adacore.com>
+
+ * doc/gnat_rm/standard_and_implementation_defined_restrictions.rst
+ (No_Dispatching_Calls): Fix whitespace in example code.
+ * gnat_rm.texi: Regenerate.
+ * exp_ch13.adb (Expand_N_Freeze_Entity): Replace low-level
+ membership test with a high-level wrapper.
+ * exp_ch3.adb (Expand_Freeze_Record_Type): Remove unnecessary
+ initialization of list of wrapper declarations and unnecessary
+ guard for list of their bodies (if no bodies are created then
+ Append_Freeze_Actions is a no-op).
+
+2021-12-02 Marc Poulhiès <poulhies@adacore.com>
+
+ * exp_imgv.adb (Append_Table_To): Add new parameter to
+ Make_Aggregate call.
+ * gen_il-fields.ads (Opt_Field_Enum):
+ Add Is_Parenthesis_Aggregate and Is_Enum_Array_Aggregate.
+ * gen_il-gen-gen_nodes.adb (Union): Add Is_Enum_Array_Aggregate
+ and Is_Parenthesis_Aggregate field to N_Aggregate.
+ * libgnarl/s-interr.adb (User_Handler, User_Entry, Blocked)
+ (Ignored, Last_Unblocker, Server_ID): Likewise.
+ * libgnarl/s-intman.ads (Keep_Unmasked, Reserve): Likewise.
+ * libgnarl/s-intman__posix.adb (Exception_Interrupts)
+ (Initialize): Likewise.
+ * libgnarl/s-mudido__affinity.adb (Create): Likewise.
+ * libgnarl/s-osinte__linux.ads (Unmasked, Reserved): Likewise.
+ * libgnarl/s-taprop__linux.adb (Create_Task, Set_Task_Affinity)
+ * libgnarl/s-tasdeb.adb (Trace_On): Likewise.
+ * libgnarl/s-tasdeb.ads (Known_Tasks): Likewise.
+ * libgnarl/s-tasinf__linux.ads (Any_CPU, No_CPU): Likewise.
+ * libgnarl/s-taskin.adb (Initialize_ATCB): Likewise.
+ * libgnarl/s-taskin.ads (Ada_Task_Control_Block): Likewise.
+ * libgnarl/s-tasren.adb (Default_Treatment)
+ (New_State): Likewise.
+ * libgnarl/s-tassta.adb (Trace_Unhandled_Exception_In_Task):
+ Likewise.
+ * libgnarl/s-tataat.adb (Index_Array): Likewise.
+ * libgnarl/s-tpobop.adb (New_State): Likewise.
+ * libgnat/a-calend.adb (Cumulative_Days_Before_Month)
+ (Leap_Second_Times): Likewise.
+ * libgnat/a-calend.ads (Days_In_Month): Likewise.
+ * libgnat/a-cfinve.adb (Insert): Likewise.
+ * libgnat/a-chahan.adb (Char_Map): Likewise.
+ * libgnat/a-chtgbo.adb (Clear): Likewise.
+ * libgnat/a-cobove.adb ("&", Insert, To_Vector): Likewise.
+ * libgnat/a-cofove.adb (Insert, To_Vector): Likewise.
+ * libgnat/a-cohata.ads (Hash_Table_Type): Likewise.
+ * libgnat/a-coinve.adb (Merge, Insert, Insert_Space): Likewise.
+ * libgnat/a-convec.adb (Insert, To_Vector): Likewise.
+ * libgnat/a-coprnu.ads (Primes): Likewise.
+ * libgnat/a-direct.adb (Empty_String): Use regular "" instead
+ of aggregate.
+ (Start_Search_Internal, Name_Case_Equivalence, Search)
+ (Start_Search, Start_Search_Internal): Use bracket for
+ aggregate.
+ * libgnat/a-direct.ads (Start_Search,Search): Likewise.
+ * libgnat/a-direio.adb (Zeroes): Likewise.
+ * libgnat/a-nbnbre.adb (Leading_Padding, Trailing_Padding)
+ (Numerator_Image): Likewise.
+ * libgnat/a-ngrear.adb (Jacobi): Likewise.
+ * libgnat/a-stbubo.adb (Get_UTF_8): Likewise.
+ * libgnat/a-stbufo.adb (Put): Likewise.
+ * libgnat/a-stbuun.adb (Get_UTF_8): Likewise.
+ * libgnat/a-stbuut.adb (Put_7bit, Put_Character)
+ (Put_Wide_Character, Put_Wide_Wide_Character): Likewise.
+ * libgnat/a-stmaco.ads (Control_Set,Graphic_Set,Letter_Set)
+ (Lower_Set, Upper_Set, Basic_Set, Decimal_Digit_Set)
+ (Hexadecimal_Digit_Set, Alphanumeric_Set, Special_Set)
+ (ISO_646_Set): Likewise.
+ * libgnat/a-strbou.ads (Insert, Tail, "*", Replicate)
+ (Null_Bounded_String): Likewise.
+ * libgnat/a-strfix.ads (Head, Tail): Likewise.
+ * libgnat/a-strmap.adb (To_Domain, Lemma_Is_Sorted): Likewise.
+ * libgnat/a-strmap.ads (Null_Set): Likewise.
+ * libgnat/a-strsup.adb (Super_Head, Super_Replicate)
+ (Super_Tail): Likewise.
+ * libgnat/a-strsup.ads (Super_Head, Super_Tail, Times)
+ (Super_Replicate): Likewise.
+ * libgnat/a-sttebu.adb (Put_UTF8, Wide_Put_UTF_16): Likewise.
+ * libgnat/a-stuten.ads (BOM_16): Likewise.
+ * libgnat/a-stwibo.ads (Null_Bounded_Wide_String): Likewise.
+ * libgnat/a-stwima.ads (Null_Range): Likewise.
+ * libgnat/a-stwisu.adb (Super_Head, Super_Replicate)
+ (Super_Tail): Likewise.
+ * libgnat/a-stzbou.ads
+ (Null_Bounded_Wide_Wide_String): Likewise.
+ * libgnat/a-stzmap.ads (Null_Range): Likewise.
+ * libgnat/a-stzsup.adb (Super_Head, Super_Replicate)
+ (Super_Tail, Super_Trim): Likewise.
+ * libgnat/a-swmwco.ads (Control_Ranges, Graphic_Ranges)
+ (Letter_Ranges, Lower_Ranges, Upeer_Ranges, Basic_Ranges)
+ (Decimal_Digit_Ranges, Hexadecimal_Digit_Ranges)
+ (Alphanumeric_Ranges, Special_Graphic_Ranges, ISO_646_Ranges)
+ (Character_Ranges, Lower_Case_Mapping, Upper_Case_Mapping)
+ (Basic_Mapping): Likewise.
+ * libgnat/a-szmzco.ads (Control_Ranges, Graphic_Ranges)
+ (Letter_Ranges, Lower_Ranges, Upeer_Ranges, Basic_Ranges)
+ (Decimal_Digit_Ranges, Hexadecimal_Digit_Ranges)
+ (Alphanumeric_Ranges, Special_Graphic_Ranges, ISO_646_Ranges)
+ (Character_Ranges, Lower_Case_Mapping, Upper_Case_Mapping)
+ (Basic_Mapping): Likewise.
+ * libgnat/a-teioed.adb (Format_Number): Likewise.
+ * libgnat/a-wtedit.adb (Format_Number): Likewise.
+ * libgnat/a-ztedit.adb (Format_Number): Likewise.
+ * libgnat/g-arrspl.adb (Separators): Likewise.
+ * libgnat/g-catiio.adb (Month_Name_To_Number): Likewise.
+ * libgnat/g-cgideb.adb (NL, Title): Likewise.
+ * libgnat/g-comlin.adb (Internal_Initialize_Option_Scan)
+ (Display_Section_Help): Likewise.
+ * libgnat/g-comlin.ads (Opt_Parser_Data): Likewise.
+ * libgnat/g-debpoo.adb (Set_Dead_Beef, Dump): Likewise.
+ * libgnat/g-expect.adb (Expect, Has_Process, Send): Likewise.
+ * libgnat/g-forstr.adb ("+", Get_Formatted): Likewise.
+ * libgnat/g-memdum.adb (Dump): Likewise.
+ * libgnat/g-rannum.adb (Image): Likewise.
+ * libgnat/g-sechas.adb (Final, HMAC_Initial_Context): Likewise.
+ * libgnat/g-sehamd.ads (Initial_State): Likewise.
+ * libgnat/g-sehash.ads (Initial_State): Likewise.
+ * libgnat/g-sercom.ads (Data_Rate_Value): Likewise.
+ * libgnat/g-sercom__linux.adb (C_Data_Rate, C_Bits, C_Stop_Bits)
+ (C_Parity): Likewise.
+ * libgnat/g-shsh32.ads (K, Transform): Likewise.
+ * libgnat/g-shsh64.ads (K, Transform): Likewise.
+ * libgnat/g-socket.adb (Levels, Modes, Shutmodes, Requests)
+ (Options, Flags, Get_Name_Info, Image): Likewise.
+ * libgnat/g-socket.ads (Inet_Addr_Bytes_Length, Inet_Addr_Type)
+ (IPv4_To_IPv6_Prefix, Any_Inet_Addr, Any_Inet6_Addr)
+ (No_Inet_Addr, Broadcast_Inet_Addr, Loopback_Inet_Addr)
+ (Loopback_Inet6_Addr, Unspecified_Group_Inet_Addr)
+ (All_Hosts_Group_Inet_Addr, All_Routers_Group_Inet_Addr)
+ (Unspecified_Group_Inet6_Addr, All_Hosts_Group_Inet6_Addr)
+ (All_Routers_Group_Inet6_Addr): Likewise.
+ * libgnat/g-socpol.adb (To_C, Status, Get_Events): Likewise.
+ * libgnat/g-socpol.ads (Input_Event, Output_Event, Both_Event)
+ (Error_Event): Likewise.
+ * libgnat/g-sothco.ads (Families, Lengths, Sockaddr): Likewise.
+ * libgnat/g-spipat.adb (OK_For_Simple_Arbno): Likewise.
+ * libgnat/i-cobol.ads (Ada_To_COBOL, COBOL_To_Ada): Likewise.
+ * libgnat/i-pacdec.adb (Packed_Byte): Likewise.
+ * libgnat/i-pacdec.ads (Packed_Size): Likewise.
+ * libgnat/s-bitops.adb (Masks): Likewise.
+ * libgnat/s-crc32.adb (Table): Likewise.
+ * libgnat/s-gearop.adb (Unit_Matrix, Unit_Vector): Likewise.
+ * libgnat/s-genbig.adb (Out_data, Zero_Data, Big_Exp, Big_Mul)
+ (To_Bignum, To_String, Image, Leading_Padding): Likewise.
+ * libgnat/s-htable.adb (Reset): Likewise.
+ * libgnat/s-imgcha.adb (C0, C1): Likewise.
+ * libgnat/s-powflt.ads (Powten): Likewise.
+ * libgnat/s-powlfl.ads (Powten): Likewise.
+ * libgnat/s-powllf.ads (Powten): Likewise.
+ * libgnat/s-rannum.adb (Matrix_A, Random_Float_Template, Image):
+ Likewise.
+ * libgnat/s-rannum.ads (Generator): Likewise.
+ * libgnat/s-regexp.adb (Compile,Create_Primary_Table)
+ (Create_Primary_Table_Glob, Create_Secondary_Table, Compile):
+ Likewise.
+ * libgnat/s-regpat.adb (Bit_Conversion, Set, Dump_Until)
+ (Dump_Current, Dump_Error, Try, Reset_Class): Likewise.
+ * libgnat/s-regpat.ads (Pattern_Matcher, Never_Match): Likewise.
+ * libgnat/s-scaval__128.adb (Initialize): Likewise.
+ * libgnat/s-statxd.adb (Fields, W_F, W_LF)
+ (W_LLF, W_SF): Likewise.
+ * libgnat/s-stausa.adb (Initialize, Initialize_Analyzer)
+ (Output_Results): Likewise.
+ * libgnat/s-strops.adb (Str_Concat_SC): Likewise.
+ * libgnat/s-valrea.adb (Maxexp32, Maxexp64, Maxexp80): Likewise.
+ * libgnat/s-wchcon.ads (WC_Encoding_Letters)
+ (WC_Longest_Sequences): Likewise.
+ * par-ch4.adb (P_Aggregate_Or_Paren_Expr): Set
+ Is_Parenthesis_Aggregate when creating a N_Aggregate using
+ parenthesis.
+ * scng.adb (Scan): Lower version needed for bracket syntax from
+ Extensions to Ada2022.
+ * sem_aggr.adb (Resolve_Aggregate): Raise error for container
+ aggregate using parenthesis instead of bracket.
+ (Resolve_Array_Aggregate): Raise warning for aggregate using
+ parenthesis in Ada2022 with obsolescent warning enabled and not
+ in GNAT mode.
+ * sem_util.ads (Check_Ambiguous_Aggregate): Typo fix in comment.
+
+2021-12-02 Piotr Trojanek <trojanek@adacore.com>
+
+ * libgnarl/a-taside.ads (Activation_Is_Complete): Add pragma
+ Inline.
+
+2021-12-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ * sem_ch12.adb (Freeze_Package_Instance): Consistently consider
+ the freeze node of the parent and use large inequality for
+ Slocs.
+ (Freeze_Subprogram_Instance): Likewise.
+ (Insert_Freeze_Node_For_Instance): For an instance in a package
+ spec with no source body that immediately follows, consider the
+ body of the package for the placement of the freeze node and go
+ to the outer level if there is no such body.
+
+2021-12-02 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch13.ads (Expand_N_Freeze_Entity): Add note about a SPARK
+ twin.
+ * exp_ch3.ads (Freeze_Type): Likewise.
+ * exp_spark.adb (Expand_SPARK_N_Freeze_Entity): Mimic what is
+ done in Freeze_Entity.
+ (SPARK_Freeze_Type): Mimic what is done in Freeze_Type; add call
+ to Make_Predefined_Primitive_Eq_Spec.
+
+2021-12-02 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch3.adb (Make_Predefined_Primitive_Specs): Move code for
+ spec of dispatching equality.
+ (Predefined_Primitive_Bodies): Move code for body if dispatching
+ equality.
+ (Make_Predefined_Primitive_Eq_Spec): Separated code for spec of
+ dispatching equality.
+ (Predefined_Primitive_Eq_Body): Separated code for body of
+ dispatching equality.
+ * exp_ch3.ads: Update.
+
+2021-12-02 Piotr Trojanek <trojanek@adacore.com>
+
+ * libgnat/s-valuti.ads (Scan_Natural_Ghost): Split body from
+ spec and put it into private part, so that GNATprove can pick it
+ both when analysing the unit and its clients.
+
+2021-12-02 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_aggr.adb, exp_ch6.adb, par-ch4.adb, sem_ch13.adb: Remove
+ extra space after ":=" symbol.
+ * gen_il-gen.adb: Likewise; add missing headerbox.
+
+2021-12-02 Richard Kenner <kenner@adacore.com>
+
+ * rtsfind.adb (Maybe_Add_With): Ensure that the added "with" is
+ never marked as ignored ghost code.
+
+2021-12-02 Piotr Trojanek <trojanek@adacore.com>
+
+ * freeze.adb (Freeze_Entity): Replace First_Entity/Next_Entity
+ with First_Component/Next_Component; remove condition with Ekind
+ equal to E_Component.
+ * sem_ch13.adb (Check_Record_Representation_Clause): Likewise
+ for component-or-discriminant.
+ * sem_util.adb (Is_Fully_Initialized_Type): Likewise; rename Ent
+ to a more specific Comp.
+ * sem_warn.adb (Check_References): Likewise.
+
+2021-12-02 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_warn.adb (Warn_On_Unassigned_Out_Parameter): Move inner
+ loop at the beginning of subprogram, so it is executed only
+ once; fix order in the "add an ad hoc" phrase.
+
+2021-12-02 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_warn.adb (Check_References): Remove redundant condition.
+
+2021-12-02 Doug Rupp <rupp@adacore.com>
+
+ * vxworks7-cert-rtp-link__ppcXX.spec: New file.
+ * Makefile.rtl: Use it.
+
+2021-12-02 Yannick Moy <moy@adacore.com>
+
+ * libgnat/i-c.adb: Add ghost code.
+ (C_Length_Ghost): New ghost functions to query the C length of a
+ string.
+ (To_Ada): Insert constant Count_Cst where needed to comply with
+ SPARK. Homogeneize code between variants for char, wchar_t,
+ char16_t and char32_t. Use char16_nul and char32_nul
+ systematically instead of their value. Fix the type of index To
+ to be Integer instead of Positive, to avoid a possible range
+ check failure on an empty Target. Insert an exit statement to
+ avoid a possible overflow failure when the last index in Target
+ is Natural'Last (possibly on a small string as well).
+ * libgnat/i-c.ads: Add contracts.
+ (C_Length_Ghost): New ghost functions to query the C length of a
+ string.
+ * libgnat/s-os_lib.adb: Remove pragma Compiler_Unit_Warning
+ causing a spurious error during compilation of GNAT, as this
+ pragma is not needed anymore now that we bootstrap (stage1) with
+ the base compiler runtime.
+
+2021-12-02 Piotr Trojanek <trojanek@adacore.com>
+
+ * libgnarl/a-taside.ads (Activation_Is_Complete): Add
+ precondition.
+
+2021-12-02 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch3.adb (Check_Derived_Type): Rename local variables; fix
+ style in comment.
+
+2021-12-02 Yannick Moy <moy@adacore.com>
+
+ * libgnat/s-valboo.adb (First_Non_Space_Ghost): Move to
+ utilities.
+ (Value_Boolean): Prefix call to First_Non_Space_Ghost.
+ * libgnat/s-valboo.ads (First_Non_Space_Ghost): Move to
+ utilities.
+ (Is_Boolean_Image_Ghost, Value_Boolean): Prefix call to
+ First_Non_Space_Ghost.
+ * libgnat/s-valuer.adb (Scan_Raw_Real): Adapt to change of
+ function Scan_Exponent to procedure.
+ * libgnat/s-valueu.adb (Scan_Raw_Unsigned): Adapt to change of
+ function Scan_Exponent to procedure.
+ * libgnat/s-valuti.adb (First_Non_Space_Ghost): Function moved
+ here.
+ (Last_Number_Ghost): New ghost query function.
+ (Scan_Exponent): Change function with side-effects into
+ procedure, to mark in SPARK. Prove procedure wrt contract.
+ Change type of local P to avoid possible range check failure (it
+ is not known whether this can be activated by callers).
+ (Scan_Plus_Sign, Scan_Sign): Change type of local P to avoid
+ possible range check failure. Add loop invariants and assertions
+ for proof.
+ (Scan_Trailing_Blanks): Add loop invariant.
+ (Scan_Underscore): Remove SPARK_Mode Off.
+ * libgnat/s-valuti.ads (First_Non_Space_Ghost): Function moved
+ here.
+ (Last_Number_Ghost, Only_Number_Ghost, Is_Natural_Format_Ghost,
+ Scan_Natural_Ghost): New ghost query functions.
+ (Scan_Plus_Sign, Scan_Sign, Scan_Exponent, Scan_Trailing_Blanks,
+ Scan_Underscore): Add functional contracts.
+
+2021-12-02 Yannick Moy <moy@adacore.com>
+
+ * libgnat/s-imgboo.adb: Mark in SPARK.
+ * libgnat/s-imgboo.ads: Mark in SPARK. Change from Pure to
+ Preelaborate unit in order to be able to depend on
+ System.Val_Bool.
+ (Image_Boolean): Functionally specify the result of the
+ procedure by calling System.Val_Bool.Value_Boolean on the
+ result.
+ * libgnat/s-valboo.adb: Mark in SPARK.
+ (First_Non_Space_Ghost): New ghost function.
+ (Value_Boolean): Change type of L and F to avoid possible range
+ check failure on empty Str.
+ * libgnat/s-valboo.ads: Mark in SPARK. Duplicate with-clause
+ from body in the spec to be able to call
+ System.Val_Util.Only_Space_Ghost in the contract.
+ (First_Non_Space_Ghost): New ghost function computing the first
+ non-space character in a string.
+ (Is_Boolean_Image_Ghost): New ghost function computing whether a
+ string is the image of a boolean value.
+ (Value_Boolean): Add in precondition the conditions to avoid
+ raising Constraint_Error. This precondition is never executed,
+ and only used in proof, thanks to the use of pragma
+ Assertion_Policy. Given that precondition, the postcondition can
+ simply check the first non-space character to decide whether
+ True or False is read.
+ * libgnat/s-valuti.adb: Mark in SPARK, but use SPARK_Mode Off on
+ all subprograms not yet proved.
+ (Bad_Value): Annotate expected exception.
+ (Normalize_String): Rewrite to avoid possible overflow when
+ incrementing F in the first loop. Add loop invariants.
+ * libgnat/s-valuti.ads: Mark in SPARK.
+ (Bad_Value): Add Depends contract to avoid warning on unused S.
+ (Only_Space_Ghost): New ghost function to query if string has
+ only space in the specified range.
+ (Normalize_String): Add functional contract.
+ (Scan_Exponent): Mark spec as not in SPARK as this function has
+ side-effects.
+
+2021-12-02 Pascal Obry <obry@adacore.com>
+
+ * libgnat/g-socket.ads (Max_Name_Length): Initialize with
+ NI_MAXHOST.
+
+2021-12-02 Pascal Obry <obry@adacore.com>
+
+ * libgnat/g-socket.ads: Minor style fix.
+
+2021-12-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * einfo.ads (E_Decimal_Fixed_Point_Subtype): Fix pasto.
+ * freeze.adb (Freeze_Fixed_Point_Type): Retrieve the underlying type
+ of the first subtype and do not use a stale value of Small_Value.
+ * sem_res.adb (Resolve_Real_Literal): In the case of a fixed-point
+ type, make sure that the base type is frozen and use its Small_Value
+ to compute the corresponding integer value of the literal.
+
+2021-12-01 Piotr Trojanek <trojanek@adacore.com>
+
+ * libgnat/a-cbdlli.ads (List): Remove extra space in Aggregate
+ aspect.
+
+2021-12-01 Gary Dismukes <dismukes@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_pragmas.rst: Add
+ documentation of the new form of formal subprogram default in
+ the section on language extensions (pragma Extensions_Allowed).
+ * gnat_rm.texi: Regenerate.
+ * gen_il-gen-gen_nodes.adb: Add Expression as a syntactic field
+ of N_Formal_(Abstract|Concrete)_Subprogram_Declaration nodes.
+ * par-ch12.adb (P_Formal_Subprogram_Declaration): Add parsing
+ support for the new default of a parenthesized expression for
+ formal functions. Issue an error when extensions are not
+ allowed, suggesting use of -gnatX. Update comment with extended
+ syntax for SUBPROGRAM_DEFAULT.
+ * sem_ch12.adb (Analyze_Formal_Subprogram_Declaration): Issue an
+ error when an expression default is given for an abstract formal
+ function. When a default expression is present for a formal
+ function, install the function's formals and preanalyze the
+ expression.
+ (Instantiate_Formal_Subprogram): Fix typo in RM paragraph in a
+ comment. When a formal function has a default expression,
+ create a body for the function that will evaluate the expression
+ and will be called when the default applies in an instantiation.
+ The implicit function is marked as inlined and as having
+ convention Intrinsic.
+
+2021-12-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * sem_elab.adb (Previous_Suitable_Construct): New function declared
+ in the Early_Call_Region_Processor package.
+ (Find_ECR): Call it to get the previous node at the start.
+ (Include): Call it to get the previous node during the traversal.
+
+2021-12-01 Bob Duff <duff@adacore.com>
+
+ * sem_prag.adb (Process_Compile_Time_Warning_Or_Error): Do not
+ follow the Corresponding_Spec pointer if Acts_As_Spec is True,
+ because Corresponding_Spec is Empty in that case, so we would
+ exit the loop prematurely, and incorrectly think we are not
+ inside a generic unit when we are.
+
+2021-12-01 Bob Duff <duff@adacore.com>
+
+ * par-ch3.adb (P_Access_Type_Definition): If Not_Null_Subtype is
+ True, give an error in the access-to-subprogram cases.
+
+2021-12-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * sem_ch12.adb (Freeze_Package_Instance): Move up.
+
+2021-12-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * sem_ch12.adb (Freeze_Subprogram_Body): Rename into...
+ (Freeze_Subprogram_Instance): ...this and change the name of the
+ first parameter and local variables for the sake of consistency.
+ (Insert_Freeze_Node_For_Instance): Use local variable Par_Inst.
+ (Install_Body): Rename into...
+ (Freeze_Package_Instance): ...this, remove first parameter and
+ change the name of local variables for the sake of consistency.
+ Do not deal with the special case of incomplete actual types here
+ and do not insert the body.
+ (Instantiate_Package_Body): Deal with the special case of incomplete
+ actual types here and insert the body. Call Freeze_Package_Instance
+ only if expansion is done.
+ (Instantiate_Subprogram_Body): Minor consistency tweak.
+
+2021-12-01 Etienne Servais <servais@adacore.com>
+
+ * sem_aggr.adb (Resolve_Aggregate): Fix typo in comment.
+
+2021-12-01 Steve Baird <baird@adacore.com>
+
+ * sem_case.adb (Check_Bindings): Provide a second strategy for
+ implementing bindings and choose which strategy to use for a
+ given binding. The previous approach was to introduce a new
+ object and assign the bound value to the object. The new
+ approach is to introduce a renaming of a dereference of an
+ access value that references the appropriate subcomponent, so no
+ copies are made. The original strategy is still used if the
+ type of the object is elementary. When the renaming approach is
+ used, the initialization of the access value is not generated
+ until expansion. Until this missing initialization is added, the
+ tree looks like a known-at-compile-time dereference of a null
+ access value: Temp : Some_Access_Type; Obj : Designated_Type
+ renames Temp.all; This leads to problems, so a bogus initial
+ value is provided here and then later deleted during expansion.
+ (Check_Composite_Case_Selector): Disallow a case selector
+ expression that requires finalization. Note that it is ok if the
+ selector's type requires finalization, as long as the expression
+ itself doesn't have any "newly constructed" parts.
+ * exp_ch5.adb (Pattern_Match): Detect the case where analysis of
+ a general (i.e., composite selector type) case statement chose
+ to implement a binding as a renaming rather than by making a
+ copy. In that case, generate the assignments to initialize the
+ access-valued object whose designated value is later renamed
+ (and remove the bogus initial value for that object that was
+ added during analysis).
+ * sem_util.ads, sem_util.adb: Add new function
+ Is_Newly_Constructed corresponding to RM 4.4 term.
+
+2021-12-01 Richard Kenner <kenner@adacore.com>
+
+ * frontend.adb (Frontend): Do unnesting after ignored ghost code
+ has been removed.
+ * inline.adb (Analyze_Inlined_Bodies): Don't put ignored ghost
+ entities on inlined subprogram list.
+
+2021-12-01 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * libgnarl/s-tasren.adb (Timed_Task_Entry_Call): Replace
+ Defer_Abort and Undefer_Abort with Defer_Abort_Nestable and
+ Undefer_Abort_Nestable.
+
+2021-12-01 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * exp_ch7.adb (Cleanup_Record): Don't process parent.
+
+2021-12-01 Justin Squirek <squirek@adacore.com>
+
+ * sem_attr.adb (Type_Key): Avoid premature use warnings when the
+ prefix is a generic actual.
+
+2021-12-01 Richard Kenner <kenner@adacore.com>
+
+ * gnat1drv.adb (Gnat1drv): Force generation of object file if
+ compilation unit is an ignored ghost.
+
+2021-12-01 Patrick Bernardi <bernardi@adacore.com>
+
+ * tracebak.c: Add AArch64 RTEMS support.
+
+2021-12-01 Patrick Bernardi <bernardi@adacore.com>
+
+ * init.c: Add __gnat_error_handler and __gnat_install_handler
+ for RTEMS.
+
+2021-12-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * sprint.ads (Source_Dump): Fix typo in comment.
+ * sprint.adb (Source_Dump): Set Dump_Freeze_Null for both -gnatG
+ and -gnatD.
+ * switch-c.adb (Scan_Front_End_Switches) <'D'>: Remove obsolete
+ kludge.
+
+2021-12-01 Yannick Moy <moy@adacore.com>
+
+ * einfo.ads (Direct_Primitive_Operations): Update the doc to
+ indicate that this field is used for all types now.
+ * sem_ch4.adb (Try_Object_Operation): Add parameter
+ Allow_Extensions set to True to pretend that extensions are
+ allowed.
+ * sem_ch4.ads: Same.
+ * sem_ch6.adb: Do not require Extensions_Allowed.
+ * sem_ch8.adb (Find_Selected_Component): Remove duplicate
+ "where" in comment. Improve the error messages regarding use of
+ prefixed calls.
+
+2021-12-01 Yannick Moy <moy@adacore.com>
+
+ * sem_util.adb (Is_Extended_Precision_Floating_Point_Type): New
+ function.
+ * sem_util.ads (Is_Extended_Precision_Floating_Point_Type): New
+ function.
+
+2021-12-01 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_aggr.adb, sem_cat.adb, sem_ch10.adb, sem_ch12.adb,
+ sem_elim.adb, sem_util.adb: Replace uses of Subprogram_Kind with
+ Is_Subprogram.
+
+2021-12-01 Piotr Trojanek <trojanek@adacore.com>
+
+ * libgnat/a-coinho.ads: Sync whitespace with
+ a-coinho__shared.ads.
+ * libgnat/a-coinho__shared.ads: Sync whitespace with
+ a-coinho.ads.
+
+2021-12-01 Piotr Trojanek <trojanek@adacore.com>
+
+ * Makefile.rtl (GNATRTL_TASKING_OBJS): Sort.
+ (GNATRTL_NONTASKING_OBJS): Sort.
+
+2021-12-01 Piotr Trojanek <trojanek@adacore.com>
+
+ * Makefile.rtl: Remove extra whitespace in special compilation
+ rules.
+
+2021-12-01 Piotr Trojanek <trojanek@adacore.com>
+
+ * doc/gnat_rm/the_gnat_library.rst (System.Atomic_Counters):
+ Sync description with comment in s-atocou.ads.
+ * gnat-style.texi, gnat_rm.texi, gnat_ugn.texi: Regenerate.
+
+2021-12-01 Yannick Moy <moy@adacore.com>
+
+ * sem_ch10.adb (Is_Private_Library_Unit): Move query to
+ Sem_Util for sharing.
+ * sem_ch7.adb (Analyze_Package_Body_Helper): Add continuation
+ message.
+ * sem_prag.adb (Analyze_Part_Of): Call new function
+ Is_Private_Library_Unit.
+ (Check_Valid_Library_Unit_Pragma): Specialize error messages on
+ misplaced pragmas.
+ (Analyze_Refined_State_In_Decl_Part): Recognize missing Part_Of
+ on object in private part.
+ * sem_util.adb (Check_State_Refinements): Add continuation
+ message.
+ (Find_Placement_In_State_Space): Fix detection of placement,
+ which relied wrongly on queries In_Package_Body/In_Private_Part
+ which do not provide the right information here for all cases.
+ (Is_Private_Library_Unit): Move query here for sharing.
+ * sem_util.ads (Is_Private_Library_Unit): Move query here for
+ sharing.
+
+2021-12-01 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_ch3.adb (Analyze_Full_Type_Declaration): If the full type
+ has a primitives list but its base type doesn't, set the base
+ type's list to the full type's list (covers certain constrained
+ cases, such as for arrays).
+ (Analyze_Incomplete_Type_Decl): Unconditionally initialize an
+ incomplete type's primitives list.
+ (Analyze_Subtype_Declaration): Unconditionally set a subtype's
+ primitives list to the base type's list, so the lists are
+ shared.
+ (Build_Derived_Private_Type): Unconditionally initialize a
+ derived private type's list to a new empty list.
+ (Build_Derived_Record_Type): Unconditionally initialize a
+ derived record type's list to a new empty list (now a single
+ call for tagged and untagged cases).
+ (Derived_Type_Declaration): Unconditionally initialize a derived
+ type's list to a new empty list in error cases (when Parent_Type
+ is undefined or illegal).
+ (Process_Full_View): Unconditionally copy the primitive
+ operations from the private view to the full view (rather than
+ conditioning it on whether extensions are enabled).
+ * sem_ch7.adb (New_Private_Type): Unconditionally initialize an
+ untagged private type's primitives list to a new empty list.
+
+2021-12-01 Etienne Servais <servais@adacore.com>
+
+ * libgnat/a-cbhase.adb, libgnat/a-cborse.adb,
+ libgnat/a-cihase.adb, libgnat/a-ciorse.adb,
+ libgnat/a-cohase.adb, libgnat/a-coorse.adb
+ (Constant_Reference,Reference_Preserving_Key): Refactor using
+ the equivalence stated in the RM.
+
+2021-12-01 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch3.adb (Make_Eq_Body): Refactor to avoid appending to an
+ empty list; also, when exiting early we will not create any
+ list; fix style in comment.
+
+2021-12-01 Piotr Trojanek <trojanek@adacore.com>
+
+ * repinfo.adb (List_Entities): Simplify detection of entries;
+ refactor potentially redundant comparison.
+
2021-11-29 Eric Gallager <egallager@gcc.gnu.org>
PR other/103021
diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl
index 72b07f4..c966c25 100644
--- a/gcc/ada/Makefile.rtl
+++ b/gcc/ada/Makefile.rtl
@@ -1186,7 +1186,7 @@ ifeq ($(strip $(filter-out powerpc% wrs vxworks vxworksspe vxworks7% vxworks7spe
else
GCC_SPEC_FILES+=vxworks7-rtp-base-link.spec
endif
- GCC_SPEC_FILES+=vxworks7-cert-rtp-link.spec
+ GCC_SPEC_FILES+=vxworks7-cert-rtp-link__ppcXX.spec
else
GCC_SPEC_FILES+=vxworks-$(ARCH_STR)-link.spec
GCC_SPEC_FILES+=vxworks-cert-$(ARCH_STR)-link.spec
diff --git a/gcc/ada/contracts.adb b/gcc/ada/contracts.adb
index 2726486..98f469b 100644
--- a/gcc/ada/contracts.adb
+++ b/gcc/ada/contracts.adb
@@ -3761,7 +3761,6 @@ package body Contracts is
ICW_Decl := Build_ICW_Decl;
- Ensure_Freeze_Node (Tagged_Type);
Append_Freeze_Action (Tagged_Type, ICW_Decl);
Analyze (ICW_Decl);
@@ -4034,7 +4033,6 @@ package body Contracts is
-- 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);
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 cbd780b..6d60e66 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
@@ -239,7 +239,7 @@ The following example indicates constructs that violate this restriction.
with Pkg; use Pkg;
procedure Example is
procedure Test (O : T'Class) is
- N : Natural := O'Size;-- Error: Dispatching call
+ N : Natural := O'Size; -- Error: Dispatching call
C : T'Class := O; -- Error: implicit Dispatching Call
begin
if O in DT'Class then -- OK : Membership test
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index af39ba5..bdb483e 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -7546,11 +7546,11 @@ package body Exp_Aggr is
Parameter_Associations => Params));
end if;
- Loop_Stat := Make_Implicit_Loop_Statement
- (Node => N,
- Identifier => Empty,
- Iteration_Scheme => L_Iteration_Scheme,
- Statements => Stats);
+ Loop_Stat := Make_Implicit_Loop_Statement
+ (Node => N,
+ Identifier => Empty,
+ Iteration_Scheme => L_Iteration_Scheme,
+ Statements => Stats);
Append (Loop_Stat, Aggr_Code);
end Expand_Iterated_Component;
@@ -7825,7 +7825,7 @@ package body Exp_Aggr is
-- required size for the aggregwte : call the provided
-- constructor rather than the Empty aggregate.
- Index := Make_Op_Add (Loc,
+ Index := Make_Op_Add (Loc,
Left_Opnd => New_Copy_Tree (Type_Low_Bound (Index_Type)),
Right_Opnd => Make_Integer_Literal (Loc, Siz - 1));
diff --git a/gcc/ada/exp_ch13.adb b/gcc/ada/exp_ch13.adb
index 479deca..6665daa 100644
--- a/gcc/ada/exp_ch13.adb
+++ b/gcc/ada/exp_ch13.adb
@@ -491,7 +491,7 @@ package body Exp_Ch13 is
-- a constrained type extension with inherited discriminants.
if Is_Type (E_Scope)
- and then Ekind (E_Scope) not in Concurrent_Kind
+ and then not Is_Concurrent_Type (E_Scope)
then
E_Scope := Scope (E_Scope);
diff --git a/gcc/ada/exp_ch13.ads b/gcc/ada/exp_ch13.ads
index 1c5301d..f5dcfe0 100644
--- a/gcc/ada/exp_ch13.ads
+++ b/gcc/ada/exp_ch13.ads
@@ -32,6 +32,9 @@ package Exp_Ch13 is
procedure Expand_N_Attribute_Definition_Clause (N : Node_Id);
procedure Expand_N_Free_Statement (N : Node_Id);
procedure Expand_N_Freeze_Entity (N : Node_Id);
+ -- Note: for GNATprove we have a minimal variant of this routine in
+ -- Exp_SPARK.Expand_SPARK_N_Freeze_Entity. They need to be kept in sync.
+
procedure Expand_N_Record_Representation_Clause (N : Node_Id);
end Exp_Ch13;
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index 6c3fb01..828f5a5 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -287,13 +287,7 @@ package body Exp_Ch3 is
-- controlled components that require finalization actions (the deep
-- in the name refers to the fact that the action applies to components).
--
- -- The list is returned in Predef_List. The Parameter Renamed_Eq either
- -- returns the value Empty, or else the defining unit name for the
- -- predefined equality function in the case where the type has a primitive
- -- operation that is a renaming of predefined equality (but only if there
- -- is also an overriding user-defined equality function). The returned
- -- Renamed_Eq will be passed to the corresponding parameter of
- -- Predefined_Primitive_Bodies.
+ -- The list of specs is returned in Predef_List
function Has_New_Non_Standard_Rep (T : Entity_Id) return Boolean;
-- Returns True if there are representation clauses for type T that are not
@@ -586,8 +580,7 @@ package body Exp_Ch3 is
-- Place body in list of freeze actions for the type.
- Ensure_Freeze_Node (Type_Id);
- Append_Freeze_Actions (Type_Id, New_List (Body_Node));
+ Append_Freeze_Action (Type_Id, Body_Node);
end Build_Access_Subprogram_Wrapper_Body;
---------------------------
@@ -5501,7 +5494,7 @@ package body Exp_Ch3 is
Comp_Typ : Entity_Id;
Predef_List : List_Id;
- Wrapper_Decl_List : List_Id := No_List;
+ Wrapper_Decl_List : List_Id;
Wrapper_Body_List : List_Id := No_List;
Renamed_Eq : Node_Id := Empty;
@@ -5912,9 +5905,7 @@ package body Exp_Ch3 is
-- Ada 2005 (AI-391): If any wrappers were created for nonoverridden
-- inherited functions, then add their bodies to the freeze actions.
- if Present (Wrapper_Body_List) then
- Append_Freeze_Actions (Typ, Wrapper_Body_List);
- end if;
+ Append_Freeze_Actions (Typ, Wrapper_Body_List);
-- Create extra formals for the primitive operations of the type.
-- This must be done before analyzing the body of the initialization
@@ -10366,13 +10357,13 @@ package body Exp_Ch3 is
return Decl_List;
end Make_Null_Procedure_Specs;
- -------------------------------------
- -- Make_Predefined_Primitive_Specs --
- -------------------------------------
+ ---------------------------------------
+ -- Make_Predefined_Primitive_Eq_Spec --
+ ---------------------------------------
- procedure Make_Predefined_Primitive_Specs
+ procedure Make_Predefined_Primitive_Eq_Spec
(Tag_Typ : Entity_Id;
- Predef_List : out List_Id;
+ Predef_List : List_Id;
Renamed_Eq : out Entity_Id)
is
function Is_Predefined_Eq_Renaming (Prim : Node_Id) return Boolean;
@@ -10394,10 +10385,10 @@ package body Exp_Ch3 is
-- Local variables
- Loc : constant Source_Ptr := Sloc (Tag_Typ);
- Res : constant List_Id := New_List;
- Eq_Name : Name_Id := Name_Op_Eq;
- Eq_Needed : Boolean;
+ Loc : constant Source_Ptr := Sloc (Tag_Typ);
+
+ Eq_Name : Name_Id := Name_Op_Eq;
+ Eq_Needed : Boolean := True;
Eq_Spec : Node_Id;
Prim : Elmt_Id;
@@ -10405,13 +10396,144 @@ package body Exp_Ch3 is
-- Set to True if Tag_Typ has a primitive that renames the predefined
-- equality operator. Used to implement (RM 8-5-4(8)).
- use Exp_Put_Image;
-
-- Start of processing for Make_Predefined_Primitive_Specs
begin
Renamed_Eq := Empty;
+ Prim := First_Elmt (Primitive_Operations (Tag_Typ));
+ while Present (Prim) loop
+
+ -- If a primitive is encountered that renames the predefined equality
+ -- operator before reaching any explicit equality primitive, then we
+ -- still need to create a predefined equality function, because calls
+ -- to it can occur via the renaming. A new name is created for the
+ -- equality to avoid conflicting with any user-defined equality.
+ -- (Note that this doesn't account for renamings of equality nested
+ -- within subpackages???)
+
+ if Is_Predefined_Eq_Renaming (Node (Prim)) then
+ Has_Predef_Eq_Renaming := True;
+ Eq_Name := New_External_Name (Chars (Node (Prim)), 'E');
+
+ -- User-defined equality
+
+ elsif Is_User_Defined_Equality (Node (Prim)) then
+ if No (Alias (Node (Prim)))
+ or else Nkind (Unit_Declaration_Node (Node (Prim))) =
+ N_Subprogram_Renaming_Declaration
+ then
+ Eq_Needed := False;
+ exit;
+
+ -- If the parent is not an interface type and has an abstract
+ -- equality function explicitly defined in the sources, then the
+ -- inherited equality is abstract as well, and no body can be
+ -- created for it.
+
+ elsif not Is_Interface (Etype (Tag_Typ))
+ and then Present (Alias (Node (Prim)))
+ and then Comes_From_Source (Alias (Node (Prim)))
+ and then Is_Abstract_Subprogram (Alias (Node (Prim)))
+ then
+ Eq_Needed := False;
+ exit;
+
+ -- If the type has an equality function corresponding with a
+ -- primitive defined in an interface type, the inherited equality
+ -- is abstract as well, and no body can be created for it.
+
+ elsif Present (Alias (Node (Prim)))
+ and then Comes_From_Source (Ultimate_Alias (Node (Prim)))
+ and then
+ Is_Interface
+ (Find_Dispatching_Type (Ultimate_Alias (Node (Prim))))
+ then
+ Eq_Needed := False;
+ exit;
+ end if;
+ end if;
+
+ Next_Elmt (Prim);
+ end loop;
+
+ -- If a renaming of predefined equality was found but there was no
+ -- user-defined equality (so Eq_Needed is still true), then set the name
+ -- back to Name_Op_Eq. But in the case where a user-defined equality was
+ -- located after such a renaming, then the predefined equality function
+ -- is still needed, so Eq_Needed must be set back to True.
+
+ if Eq_Name /= Name_Op_Eq then
+ if Eq_Needed then
+ Eq_Name := Name_Op_Eq;
+ else
+ Eq_Needed := True;
+ end if;
+ end if;
+
+ if Eq_Needed then
+ Eq_Spec := Predef_Spec_Or_Body (Loc,
+ Tag_Typ => Tag_Typ,
+ Name => Eq_Name,
+ Profile => New_List (
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, Name_X),
+ Parameter_Type => New_Occurrence_Of (Tag_Typ, Loc)),
+
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, Name_Y),
+ Parameter_Type => New_Occurrence_Of (Tag_Typ, Loc))),
+ Ret_Type => Standard_Boolean);
+ Append_To (Predef_List, Eq_Spec);
+
+ if Has_Predef_Eq_Renaming then
+ Renamed_Eq := Defining_Unit_Name (Specification (Eq_Spec));
+
+ Prim := First_Elmt (Primitive_Operations (Tag_Typ));
+ while Present (Prim) loop
+
+ -- Any renamings of equality that appeared before an overriding
+ -- equality must be updated to refer to the entity for the
+ -- predefined equality, otherwise calls via the renaming would
+ -- get incorrectly resolved to call the user-defined equality
+ -- function.
+
+ if Is_Predefined_Eq_Renaming (Node (Prim)) then
+ Set_Alias (Node (Prim), Renamed_Eq);
+
+ -- Exit upon encountering a user-defined equality
+
+ elsif Chars (Node (Prim)) = Name_Op_Eq
+ and then No (Alias (Node (Prim)))
+ then
+ exit;
+ end if;
+
+ Next_Elmt (Prim);
+ end loop;
+ end if;
+ end if;
+ end Make_Predefined_Primitive_Eq_Spec;
+
+ -------------------------------------
+ -- Make_Predefined_Primitive_Specs --
+ -------------------------------------
+
+ procedure Make_Predefined_Primitive_Specs
+ (Tag_Typ : Entity_Id;
+ Predef_List : out List_Id;
+ Renamed_Eq : out Entity_Id)
+ is
+ Loc : constant Source_Ptr := Sloc (Tag_Typ);
+ Res : constant List_Id := New_List;
+
+ use Exp_Put_Image;
+
+ begin
+ Renamed_Eq := Empty;
+
-- Spec of _Size
Append_To (Res, Predef_Spec_Or_Body (Loc,
@@ -10462,126 +10584,10 @@ package body Exp_Ch3 is
-- Spec of "=" is expanded if the type is not limited and if a user
-- defined "=" was not already declared for the non-full view of a
- -- private extension
+ -- private extension.
if not Is_Limited_Type (Tag_Typ) then
- Eq_Needed := True;
- Prim := First_Elmt (Primitive_Operations (Tag_Typ));
- while Present (Prim) loop
-
- -- If a primitive is encountered that renames the predefined
- -- equality operator before reaching any explicit equality
- -- primitive, then we still need to create a predefined equality
- -- function, because calls to it can occur via the renaming. A
- -- new name is created for the equality to avoid conflicting with
- -- any user-defined equality. (Note that this doesn't account for
- -- renamings of equality nested within subpackages???)
-
- if Is_Predefined_Eq_Renaming (Node (Prim)) then
- Has_Predef_Eq_Renaming := True;
- Eq_Name := New_External_Name (Chars (Node (Prim)), 'E');
-
- -- User-defined equality
-
- elsif Is_User_Defined_Equality (Node (Prim)) then
- if No (Alias (Node (Prim)))
- or else Nkind (Unit_Declaration_Node (Node (Prim))) =
- N_Subprogram_Renaming_Declaration
- then
- Eq_Needed := False;
- exit;
-
- -- If the parent is not an interface type and has an abstract
- -- equality function explicitly defined in the sources, then
- -- the inherited equality is abstract as well, and no body can
- -- be created for it.
-
- elsif not Is_Interface (Etype (Tag_Typ))
- and then Present (Alias (Node (Prim)))
- and then Comes_From_Source (Alias (Node (Prim)))
- and then Is_Abstract_Subprogram (Alias (Node (Prim)))
- then
- Eq_Needed := False;
- exit;
-
- -- If the type has an equality function corresponding with
- -- a primitive defined in an interface type, the inherited
- -- equality is abstract as well, and no body can be created
- -- for it.
-
- elsif Present (Alias (Node (Prim)))
- and then Comes_From_Source (Ultimate_Alias (Node (Prim)))
- and then
- Is_Interface
- (Find_Dispatching_Type (Ultimate_Alias (Node (Prim))))
- then
- Eq_Needed := False;
- exit;
- end if;
- end if;
-
- Next_Elmt (Prim);
- end loop;
-
- -- If a renaming of predefined equality was found but there was no
- -- user-defined equality (so Eq_Needed is still true), then set the
- -- name back to Name_Op_Eq. But in the case where a user-defined
- -- equality was located after such a renaming, then the predefined
- -- equality function is still needed, so Eq_Needed must be set back
- -- to True.
-
- if Eq_Name /= Name_Op_Eq then
- if Eq_Needed then
- Eq_Name := Name_Op_Eq;
- else
- Eq_Needed := True;
- end if;
- end if;
-
- if Eq_Needed then
- Eq_Spec := Predef_Spec_Or_Body (Loc,
- Tag_Typ => Tag_Typ,
- Name => Eq_Name,
- Profile => New_List (
- Make_Parameter_Specification (Loc,
- Defining_Identifier =>
- Make_Defining_Identifier (Loc, Name_X),
- Parameter_Type => New_Occurrence_Of (Tag_Typ, Loc)),
-
- Make_Parameter_Specification (Loc,
- Defining_Identifier =>
- Make_Defining_Identifier (Loc, Name_Y),
- Parameter_Type => New_Occurrence_Of (Tag_Typ, Loc))),
- Ret_Type => Standard_Boolean);
- Append_To (Res, Eq_Spec);
-
- if Has_Predef_Eq_Renaming then
- Renamed_Eq := Defining_Unit_Name (Specification (Eq_Spec));
-
- Prim := First_Elmt (Primitive_Operations (Tag_Typ));
- while Present (Prim) loop
-
- -- Any renamings of equality that appeared before an
- -- overriding equality must be updated to refer to the
- -- entity for the predefined equality, otherwise calls via
- -- the renaming would get incorrectly resolved to call the
- -- user-defined equality function.
-
- if Is_Predefined_Eq_Renaming (Node (Prim)) then
- Set_Alias (Node (Prim), Renamed_Eq);
-
- -- Exit upon encountering a user-defined equality
-
- elsif Chars (Node (Prim)) = Name_Op_Eq
- and then No (Alias (Node (Prim)))
- then
- exit;
- end if;
-
- Next_Elmt (Prim);
- end loop;
- end if;
- end if;
+ Make_Predefined_Primitive_Eq_Spec (Tag_Typ, Res, Renamed_Eq);
-- Spec for dispatching assignment
@@ -10926,31 +10932,21 @@ package body Exp_Ch3 is
For_Body => False);
end Predef_Stream_Attr_Spec;
- ---------------------------------
- -- Predefined_Primitive_Bodies --
- ---------------------------------
+ ----------------------------------
+ -- Predefined_Primitive_Eq_Body --
+ ----------------------------------
- function Predefined_Primitive_Bodies
- (Tag_Typ : Entity_Id;
- Renamed_Eq : Entity_Id) return List_Id
+ procedure Predefined_Primitive_Eq_Body
+ (Tag_Typ : Entity_Id;
+ Predef_List : List_Id;
+ Renamed_Eq : Entity_Id)
is
- Loc : constant Source_Ptr := Sloc (Tag_Typ);
- Res : constant List_Id := New_List;
- Adj_Call : Node_Id;
Decl : Node_Id;
- Fin_Call : Node_Id;
- Prim : Elmt_Id;
Eq_Needed : Boolean;
Eq_Name : Name_Id;
- Ent : Entity_Id;
-
- pragma Warnings (Off, Ent);
-
- use Exp_Put_Image;
+ Prim : Elmt_Id;
begin
- pragma Assert (not Is_Interface (Tag_Typ));
-
-- See if we have a predefined "=" operator
if Present (Renamed_Eq) then
@@ -11004,6 +11000,48 @@ package body Exp_Ch3 is
end loop;
end if;
+ -- If equality is needed, we will have its name
+
+ pragma Assert (Eq_Needed = Present (Eq_Name));
+
+ -- Body for equality
+
+ if Eq_Needed then
+ Decl := Make_Eq_Body (Tag_Typ, Eq_Name);
+ Append_To (Predef_List, Decl);
+ end if;
+
+ -- Body for inequality (if required)
+
+ Decl := Make_Neq_Body (Tag_Typ);
+
+ if Present (Decl) then
+ Append_To (Predef_List, Decl);
+ end if;
+ end Predefined_Primitive_Eq_Body;
+
+ ---------------------------------
+ -- Predefined_Primitive_Bodies --
+ ---------------------------------
+
+ function Predefined_Primitive_Bodies
+ (Tag_Typ : Entity_Id;
+ Renamed_Eq : Entity_Id) return List_Id
+ is
+ Loc : constant Source_Ptr := Sloc (Tag_Typ);
+ Res : constant List_Id := New_List;
+ Adj_Call : Node_Id;
+ Decl : Node_Id;
+ Fin_Call : Node_Id;
+ Ent : Entity_Id;
+
+ pragma Warnings (Off, Ent);
+
+ use Exp_Put_Image;
+
+ begin
+ pragma Assert (not Is_Interface (Tag_Typ));
+
-- Body of _Size
Decl := Predef_Spec_Or_Body (Loc,
@@ -11118,21 +11156,9 @@ package body Exp_Ch3 is
end if;
if not Is_Limited_Type (Tag_Typ) then
+ -- Body for equality and inequality
- -- Body for equality
-
- if Eq_Needed then
- Decl := Make_Eq_Body (Tag_Typ, Eq_Name);
- Append_To (Res, Decl);
- end if;
-
- -- Body for inequality (if required)
-
- Decl := Make_Neq_Body (Tag_Typ);
-
- if Present (Decl) then
- Append_To (Res, Decl);
- end if;
+ Predefined_Primitive_Eq_Body (Tag_Typ, Res, Renamed_Eq);
-- Body for dispatching assignment
diff --git a/gcc/ada/exp_ch3.ads b/gcc/ada/exp_ch3.ads
index 0c5f9cc..c7648e6 100644
--- a/gcc/ada/exp_ch3.ads
+++ b/gcc/ada/exp_ch3.ads
@@ -114,6 +114,9 @@ package Exp_Ch3 is
-- delete the node if it is present just for front end purpose and we don't
-- want Gigi to see the node. This function can't delete the node itself
-- since it would confuse any remaining processing of the freeze node.
+ --
+ -- Note: for GNATprove we have a minimal variant of this routine in
+ -- Exp_SPARK.SPARK_Freeze_Type. They need to be kept in sync.
function Get_Simple_Init_Val
(Typ : Entity_Id;
@@ -155,6 +158,20 @@ package Exp_Ch3 is
-- initialized; if Variable_Comps is True then tags components located at
-- variable positions of Target are initialized.
+ procedure Make_Predefined_Primitive_Eq_Spec
+ (Tag_Typ : Entity_Id;
+ Predef_List : List_Id;
+ Renamed_Eq : out Entity_Id);
+ -- Creates spec for the predefined equality on a tagged type Tag_Typ, if
+ -- required. If created, it will be appended to Predef_List.
+ --
+ -- The Parameter Renamed_Eq either returns the value Empty, or else
+ -- the defining unit name for the predefined equality function in the
+ -- case where the type has a primitive operation that is a renaming
+ -- of predefined equality (but only if there is also an overriding
+ -- user-defined equality function). The returned Renamed_Eq will be
+ -- passed to the corresponding parameter of Predefined_Primitive_Bodies.
+
function Make_Tag_Assignment (N : Node_Id) return Node_Id;
-- An object declaration that has an initialization for a tagged object
-- requires a separate reassignment of the tag of the given type, because
@@ -163,4 +180,15 @@ package Exp_Ch3 is
-- clause the assignment is handled as part of the freezing of the object,
-- see Check_Address_Clause.
+ procedure Predefined_Primitive_Eq_Body
+ (Tag_Typ : Entity_Id;
+ Predef_List : List_Id;
+ Renamed_Eq : Entity_Id);
+ -- Creates body for the predefined equality (and ineqality, if required) on
+ -- a tagged type Tag_Typ. If created they will be appended to Predef_List.
+ --
+ -- The spec for the equality function has been created by
+ -- Make_Predefined_Primitive_Eq_Spec; see there for description of
+ -- the Renamed_Eq parameter.
+
end Exp_Ch3;
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index fa1a89a..f433fa7 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -10206,7 +10206,7 @@ package body Exp_Ch6 is
-- If function is inherited, a conversion may be necessary.
if Nkind (Par) = N_Assignment_Statement then
- Last_Actual := Name (Par);
+ Last_Actual := Name (Par);
if not Comes_From_Source (Orig_Func)
and then Etype (Orig_Func) /= Etype (Func_Id)
diff --git a/gcc/ada/exp_imgv.adb b/gcc/ada/exp_imgv.adb
index 69b9f2d..f2c5129 100644
--- a/gcc/ada/exp_imgv.adb
+++ b/gcc/ada/exp_imgv.adb
@@ -159,7 +159,8 @@ package body Exp_Imgv is
Make_Component_Definition (Loc,
Aliased_Present => False,
Subtype_Indication => New_Occurrence_Of (Ctyp, Loc))),
- Expression => Make_Aggregate (Loc, Expressions => V)));
+ Expression => Make_Aggregate (Loc, Expressions => V,
+ Is_Enum_Array_Aggregate => True)));
end Append_Table_To;
-- Start of Build_Enumeration_Image_Tables
diff --git a/gcc/ada/exp_spark.adb b/gcc/ada/exp_spark.adb
index bce745b..84927f8 100644
--- a/gcc/ada/exp_spark.adb
+++ b/gcc/ada/exp_spark.adb
@@ -29,15 +29,22 @@ with Einfo; use Einfo;
with Einfo.Entities; use Einfo.Entities;
with Einfo.Utils; use Einfo.Utils;
with Exp_Attr;
+with Exp_Ch3;
with Exp_Ch4;
with Exp_Ch5; use Exp_Ch5;
with Exp_Dbug; use Exp_Dbug;
with Exp_Util; use Exp_Util;
+with Ghost; use Ghost;
with Namet; use Namet;
with Nlists; use Nlists;
with Nmake; use Nmake;
+with Opt; use Opt;
+with Restrict; use Restrict;
+with Rident; use Rident;
with Rtsfind; use Rtsfind;
with Sem; use Sem;
+with Sem_Aux; use Sem_Aux;
+with Sem_Ch7; use Sem_Ch7;
with Sem_Ch8; use Sem_Ch8;
with Sem_Prag; use Sem_Prag;
with Sem_Res; use Sem_Res;
@@ -62,8 +69,10 @@ package body Exp_SPARK is
procedure Expand_SPARK_N_Delta_Aggregate (N : Node_Id);
-- Perform delta-aggregate-specific expansion
- procedure Expand_SPARK_N_Freeze_Type (E : Entity_Id);
- -- Build the DIC procedure of a type when needed, if not already done
+ procedure Expand_SPARK_N_Freeze_Entity (N : Node_Id);
+ -- Do a minimal expansion of freeze entities required by GNATprove. It is
+ -- a subset of what is done for GNAT in Exp_Ch13.Expand_N_Freeze_Entity.
+ -- Those two routines should be kept in sync.
procedure Expand_SPARK_N_Loop_Statement (N : Node_Id);
-- Perform loop-statement-specific expansion
@@ -80,6 +89,20 @@ package body Exp_SPARK is
procedure Expand_SPARK_Delta_Or_Update (Typ : Entity_Id; Aggr : Node_Id);
-- Common expansion for attribute Update and delta aggregates
+ procedure SPARK_Freeze_Type (N : Node_Id);
+ -- Do a minimal type freezing required by GNATprove. It is a subset of what
+ -- is done for GNAT in Exp_Ch3.Freeze_Type. Those two routines should be
+ -- kept in sync.
+ --
+ -- Currently in freezing we build the spec of dispatching equality. This
+ -- spec is needed to properly resolve references to the equality operator.
+ -- The body is not needed, because proof knows how to directly synthesize a
+ -- logical meaning for it. Also, for tagged types with extension the
+ -- expanded body would compare the _parent component, which is
+ -- intentionally not generated in the GNATprove mode.
+ --
+ -- We build the DIC procedure body here as well.
+
------------------
-- Expand_SPARK --
------------------
@@ -140,8 +163,12 @@ package body Exp_SPARK is
Expand_SPARK_N_Op_Ne (N);
when N_Freeze_Entity =>
+ -- Currently we only expand type freeze entities, so ignore other
+ -- freeze entites, because it is expensive to create a suitable
+ -- freezing environment.
+
if Is_Type (Entity (N)) then
- Expand_SPARK_N_Freeze_Type (Entity (N));
+ Expand_SPARK_N_Freeze_Entity (N);
end if;
-- In SPARK mode, no other constructs require expansion
@@ -350,23 +377,176 @@ package body Exp_SPARK is
end if;
end Expand_SPARK_Delta_Or_Update;
- --------------------------------
- -- Expand_SPARK_N_Freeze_Type --
- --------------------------------
+ ----------------------------------
+ -- Expand_SPARK_N_Freeze_Entity --
+ ----------------------------------
+
+ procedure Expand_SPARK_N_Freeze_Entity (N : Entity_Id) is
+ E : constant Entity_Id := Entity (N);
+
+ Action : Node_Id;
+ E_Scope : Entity_Id;
+ In_Other_Scope : Boolean;
+ In_Outer_Scope : Boolean;
- procedure Expand_SPARK_N_Freeze_Type (E : Entity_Id) is
begin
- -- When a DIC is inherited by a tagged type, it may need to be
- -- specialized to the descendant type, hence build a separate DIC
- -- procedure for it as done during regular expansion for compilation.
+ -- Here E is a type or a subprogram
- if Has_DIC (E) and then Is_Tagged_Type (E) then
- -- Why is this needed for DIC, but not for other aspects (such as
- -- Type_Invariant)???
+ E_Scope := Scope (E);
+
+ -- This is an error protection against previous errors
+
+ if No (E_Scope) then
+ Check_Error_Detected;
+ return;
+ end if;
+
+ -- The entity may be a subtype declared for a constrained record
+ -- component, in which case the relevant scope is the scope of
+ -- the record. This happens for class-wide subtypes created for
+ -- a constrained type extension with inherited discriminants.
+
+ if Is_Type (E_Scope)
+ and then not Is_Concurrent_Type (E_Scope)
+ then
+ E_Scope := Scope (E_Scope);
+
+ -- The entity may be a subtype declared for an iterator
+
+ elsif Ekind (E_Scope) = E_Loop then
+ E_Scope := Scope (E_Scope);
+ end if;
+
+ -- If we are freezing entities defined in protected types, they belong
+ -- in the enclosing scope, given that the original type has been
+ -- expanded away. The same is true for entities in task types, in
+ -- particular the parameter records of entries (Entities in bodies are
+ -- all frozen within the body). If we are in the task body, this is a
+ -- proper scope. If we are within a subprogram body, the proper scope
+ -- is the corresponding spec. This may happen for itypes generated in
+ -- the bodies of protected operations.
+
+ if Ekind (E_Scope) = E_Protected_Type
+ or else (Ekind (E_Scope) = E_Task_Type
+ and then not Has_Completion (E_Scope))
+ then
+ E_Scope := Scope (E_Scope);
- Build_DIC_Procedure_Body (E);
+ elsif Ekind (E_Scope) = E_Subprogram_Body then
+ E_Scope := Corresponding_Spec (Unit_Declaration_Node (E_Scope));
end if;
- end Expand_SPARK_N_Freeze_Type;
+
+ -- If the scope of the entity is in open scopes, it is the current one
+ -- or an enclosing one, including a loop, a block, or a subprogram.
+
+ if In_Open_Scopes (E_Scope) then
+ In_Other_Scope := False;
+ In_Outer_Scope := E_Scope /= Current_Scope;
+
+ -- Otherwise it is a local package or a different compilation unit
+
+ else
+ In_Other_Scope := True;
+ In_Outer_Scope := False;
+ end if;
+
+ -- If the entity being frozen is defined in a scope that is not
+ -- currently on the scope stack, we must establish the proper
+ -- visibility before freezing the entity and related subprograms.
+
+ if In_Other_Scope then
+ Push_Scope (E_Scope);
+
+ -- Finalizers are little odd in terms of freezing. The spec of the
+ -- procedure appears in the declarations while the body appears in
+ -- the statement part of a single construct. Since the finalizer must
+ -- be called by the At_End handler of the construct, the spec is
+ -- manually frozen right after its declaration. The only side effect
+ -- of this action appears in contexts where the construct is not in
+ -- its final resting place. These contexts are:
+
+ -- * Entry bodies - The declarations and statements are moved to
+ -- the procedure equivalen of the entry.
+ -- * Protected subprograms - The declarations and statements are
+ -- moved to the non-protected version of the subprogram.
+ -- * Task bodies - The declarations and statements are moved to the
+ -- task body procedure.
+ -- * Blocks that will be rewritten as subprograms when unnesting
+ -- is in effect.
+
+ -- Visible declarations do not need to be installed in these three
+ -- cases since it does not make semantic sense to do so. All entities
+ -- referenced by a finalizer are visible and already resolved, plus
+ -- the enclosing scope may not have visible declarations at all.
+
+ if Ekind (E) = E_Procedure
+ and then Is_Finalizer (E)
+ and then
+ (Is_Entry (E_Scope)
+ or else (Is_Subprogram (E_Scope)
+ and then Is_Protected_Type (Scope (E_Scope)))
+ or else Is_Task_Type (E_Scope)
+ or else Ekind (E_Scope) = E_Block)
+ then
+ null;
+ else
+ Install_Visible_Declarations (E_Scope);
+ end if;
+
+ if Is_Concurrent_Type (E_Scope)
+ or else Is_Package_Or_Generic_Package (E_Scope)
+ then
+ Install_Private_Declarations (E_Scope);
+ end if;
+
+ -- If the entity is in an outer scope, then that scope needs to
+ -- temporarily become the current scope so that operations created
+ -- during type freezing will be declared in the right scope and
+ -- can properly override any corresponding inherited operations.
+
+ elsif In_Outer_Scope then
+ Push_Scope (E_Scope);
+ end if;
+
+ -- Remember that we are processing a freezing entity and its freezing
+ -- nodes. This flag (non-zero = set) is used to avoid the need of
+ -- climbing through the tree while processing the freezing actions (ie.
+ -- to avoid generating spurious warnings or to avoid killing constant
+ -- indications while processing the code associated with freezing
+ -- actions). We use a counter to deal with nesting.
+
+ Inside_Freezing_Actions := Inside_Freezing_Actions + 1;
+
+ -- Currently only types require freezing in SPARK
+
+ SPARK_Freeze_Type (N);
+
+ -- Analyze actions in freeze node, if any
+
+ Action := First (Actions (N));
+ while Present (Action) loop
+ Analyze (Action);
+ Next (Action);
+ end loop;
+
+ -- Pop scope if we installed one for the analysis
+
+ if In_Other_Scope then
+ if Ekind (Current_Scope) = E_Package then
+ End_Package_Scope (E_Scope);
+ else
+ End_Scope;
+ end if;
+
+ elsif In_Outer_Scope then
+ Pop_Scope;
+ end if;
+
+ -- Restore previous value of the nesting-level counter that records
+ -- whether we are inside a (possibly nested) call to this procedure.
+
+ Inside_Freezing_Actions := Inside_Freezing_Actions - 1;
+ end Expand_SPARK_N_Freeze_Entity;
----------------------------------------
-- Expand_SPARK_N_Attribute_Reference --
@@ -705,4 +885,83 @@ package body Exp_SPARK is
end if;
end Expand_SPARK_Potential_Renaming;
+ -----------------------
+ -- SPARK_Freeze_Type --
+ -----------------------
+
+ procedure SPARK_Freeze_Type (N : Entity_Id) is
+ Typ : constant Entity_Id := Entity (N);
+
+ Renamed_Eq : Node_Id;
+ -- Defining unit name for the predefined equality function in the case
+ -- where the type has a primitive operation that is a renaming of
+ -- predefined equality (but only if there is also an overriding
+ -- user-defined equality function). Used to pass this entity from
+ -- Make_Predefined_Primitive_Specs to Predefined_Primitive_Bodies.
+
+ Decl : Node_Id;
+ Eq_Spec : Node_Id := Empty;
+ Predef_List : List_Id;
+
+ 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
+
+ begin
+ -- The type being frozen may be subject to pragma Ghost. Set the mode
+ -- now to ensure that any nodes generated during freezing are properly
+ -- marked as Ghost.
+
+ Set_Ghost_Mode (Typ);
+
+ -- When a DIC is inherited by a tagged type, it may need to be
+ -- specialized to the descendant type, hence build a separate DIC
+ -- procedure for it as done during regular expansion for compilation.
+
+ if Has_DIC (Typ) and then Is_Tagged_Type (Typ) then
+ -- Why is this needed for DIC, but not for other aspects (such as
+ -- Type_Invariant)???
+
+ Build_DIC_Procedure_Body (Typ);
+ end if;
+
+ if Ekind (Typ) = E_Record_Type
+ and then Is_Tagged_Type (Typ)
+ and then not Is_Interface (Typ)
+ and then not Is_Limited_Type (Typ)
+ then
+ if Is_CPP_Class (Root_Type (Typ))
+ and then Convention (Typ) = Convention_CPP
+ then
+ null;
+
+ -- Do not add the spec of the predefined primitives if we are
+ -- compiling under restriction No_Dispatching_Calls.
+
+ elsif not Restriction_Active (No_Dispatching_Calls) then
+ Set_Is_Frozen (Typ, False);
+
+ Predef_List := New_List;
+ Exp_Ch3.Make_Predefined_Primitive_Eq_Spec
+ (Typ, Predef_List, Renamed_Eq);
+ Eq_Spec := First (Predef_List);
+ Insert_List_Before_And_Analyze (N, Predef_List);
+
+ Set_Is_Frozen (Typ);
+
+ -- Remove link from the parent list to the spec and body of
+ -- the dispatching equality, but keep the link in the opposite
+ -- direction, to allow up-traversal of the AST.
+
+ if Present (Eq_Spec) then
+ Decl := Parent (Eq_Spec);
+ Remove (Eq_Spec);
+ Set_Parent (Eq_Spec, Decl);
+ end if;
+ end if;
+ end if;
+
+ Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ end SPARK_Freeze_Type;
+
end Exp_SPARK;
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 1bba059..0aa7937 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -458,7 +458,6 @@ package body Exp_Util is
else
Append (N, Actions (Fnode));
end if;
-
end Append_Freeze_Action;
---------------------------
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index ad841cf..bd03ffa 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -2044,9 +2044,8 @@ package body Freeze is
-- node of the record type declaration to ensure that it will
-- override the internal primitive built by Derive_Subprogram.
- Ensure_Freeze_Node (R);
-
if Late_Overriding then
+ Ensure_Freeze_Node (R);
Insert_Before_And_Analyze (Freeze_Node (R), DTW_Decl);
else
Append_Freeze_Action (R, DTW_Decl);
@@ -6328,11 +6327,9 @@ package body Freeze is
-- to the components of Rec.
begin
- Comp := First_Entity (E);
+ Comp := First_Component (E);
while Present (Comp) loop
- if Ekind (Comp) = E_Component
- and then Has_Delayed_Aspects (Comp)
- then
+ if Has_Delayed_Aspects (Comp) then
if not Rec_Pushed then
Push_Scope (E);
Rec_Pushed := True;
@@ -6348,7 +6345,7 @@ package body Freeze is
Analyze_Aspects_At_Freeze_Point (Comp);
end if;
- Next_Entity (Comp);
+ Next_Component (Comp);
end loop;
-- Pop the scope if Rec scope has been pushed on the scope stack
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index c01945b..911deb7 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -1181,6 +1181,10 @@ ada/mdll-utl.o : ada/mdll-utl.adb ada/mdll.ads ada/mdll-utl.ads ada/sdefault.ads
# All generated files. Perhaps we should build all of these in the same
# subdirectory, and get rid of ada/bldtools.
+# Warning: the files starting with ada/gnat.ads are not really generated,
+# instead they are copied from the libgnat subdirectory of the source tree
+# during all the stages of the bootstrap, i.e. including stage #1, which
+# means that they still need to be compilable by the base compiler.
ADA_GENERATED_FILES = \
ada/sinfo.h ada/einfo.h ada/nmake.adb ada/nmake.ads \
ada/snames.ads ada/snames.adb ada/snames.h \
diff --git a/gcc/ada/gcc-interface/a-assert.adb b/gcc/ada/gcc-interface/a-assert.adb
deleted file mode 100644
index 429b14b..0000000
--- a/gcc/ada/gcc-interface/a-assert.adb
+++ /dev/null
@@ -1,52 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- A D A . A S S E R T --
--- --
--- B o d y --
--- --
--- Copyright (C) 2007-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. --
--- --
-------------------------------------------------------------------------------
-
-package body Ada.Assertions is
-
- ------------
- -- Assert --
- ------------
-
- procedure Assert (Check : Boolean) is
- begin
- if Check = False then
- raise Ada.Assertions.Assertion_Error;
- end if;
- end Assert;
-
- procedure Assert (Check : Boolean; Message : String) is
- begin
- if Check = False then
- raise Ada.Assertions.Assertion_Error with Message;
- end if;
- end Assert;
-
-end Ada.Assertions;
diff --git a/gcc/ada/gcc-interface/a-assert.ads b/gcc/ada/gcc-interface/a-assert.ads
deleted file mode 100644
index 55ed806..0000000
--- a/gcc/ada/gcc-interface/a-assert.ads
+++ /dev/null
@@ -1,50 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- A D A . A S S E R T I O N S --
--- --
--- Copyright (C) 2015-2021, Free Software Foundation, Inc. --
--- --
--- S p e c --
--- --
--- This specification is derived from the Ada Reference Manual for use with --
--- GNAT. The copyright notice above, and the license provisions that follow --
--- apply solely to the contracts that have been added. --
--- --
--- 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. --
--- --
-------------------------------------------------------------------------------
-
--- This version is used to bootstrap the compiler only.
--- It can be removed when we switch to using a GNAT from 2014 or later.
-
-pragma Compiler_Unit_Warning;
-
-package Ada.Assertions is
- pragma Pure;
-
- Assertion_Error : exception;
-
- procedure Assert (Check : Boolean);
-
- procedure Assert (Check : Boolean; Message : String);
-
-end Ada.Assertions;
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 449463e..93b6eb5 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -335,11 +335,14 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* Since a use of an itype is a definition, process it as such if it is in
the main unit, except for E_Access_Subtype because it's actually a use
- of its base type, see below. */
+ of its base type, and for E_Class_Wide_Subtype with an Equivalent_Type
+ because it's actually a use of the latter type. */
if (!definition
&& is_type
&& Is_Itype (gnat_entity)
&& Ekind (gnat_entity) != E_Access_Subtype
+ && !(Ekind (gnat_entity) == E_Class_Wide_Subtype
+ && Present (Equivalent_Type (gnat_entity)))
&& !present_gnu_tree (gnat_entity)
&& In_Extended_Main_Code_Unit (gnat_entity))
{
@@ -4423,8 +4426,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
tree size = TYPE_SIZE (gnu_type);
/* If the size is self-referential, annotate the maximum value
- after saturating it, if need be, to avoid a No_Uint value. */
- if (CONTAINS_PLACEHOLDER_P (size))
+ after saturating it, if need be, to avoid a No_Uint value.
+ But do not do it for cases where Analyze_Object_Declaration
+ in Sem_Ch3 would build a default subtype for objects. */
+ if (CONTAINS_PLACEHOLDER_P (size)
+ && !Is_Limited_Record (gnat_entity)
+ && !Is_Concurrent_Type (gnat_entity))
{
const unsigned int align
= UI_To_Int (Alignment (gnat_entity)) * BITS_PER_UNIT;
@@ -7218,13 +7225,12 @@ choices_to_gnu (tree gnu_operand, Node_Id gnat_choices)
static int
adjust_packed (tree field_type, tree record_type, int packed)
{
- /* If the field contains an array with self-referential size, we'd better
- not pack it because this would misalign it and, therefore, cause large
- temporaries to be created in case we need to take the address of the
- field. See addressable_p and the notes on the addressability issues
- for further details. */
- if (AGGREGATE_TYPE_P (field_type)
- && aggregate_type_contains_array_p (field_type, true))
+ /* If the field is an array of variable size, we'd better not pack it because
+ this would misalign it and, therefore, probably cause large temporarie to
+ be created in case we need to take its address. See addressable_p and the
+ notes on the addressability issues for further details. */
+ if (TREE_CODE (field_type) == ARRAY_TYPE
+ && type_has_variable_size (field_type))
return 0;
/* In the other cases, we can honor the packing. */
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index 1b55ec5..4b4a14d 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -838,10 +838,9 @@ extern tree get_base_type (tree type);
in bits. If we don't know anything about the alignment, return 0. */
extern unsigned int known_alignment (tree exp);
-/* Return true if TYPE, an aggregate type, contains (or is) an array.
- If SELF_REFERENTIAL is true, then an additional requirement on the
- array is that it be self-referential. */
-extern bool aggregate_type_contains_array_p (tree type, bool self_referential);
+/* Return true if TYPE is a type with variable size or a padding type with a
+ field of variable size or a record that has a field with such a type. */
+extern bool type_has_variable_size (tree type);
/* Return true if VALUE is a multiple of FACTOR. FACTOR must be a power
of 2. */
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index a932ca2..3d0820f 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -4453,14 +4453,14 @@ static tree
Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
atomic_acces_t atomic_access, bool atomic_sync)
{
- const Node_Id gnat_name = Name (gnat_node);
const bool function_call = (Nkind (gnat_node) == N_Function_Call);
const bool returning_value = (function_call && !gnu_target);
/* The GCC node corresponding to the GNAT subprogram name. This can either
be a FUNCTION_DECL node if we are dealing with a standard subprogram call,
or an indirect reference expression (an INDIRECT_REF node) pointing to a
subprogram. */
- tree gnu_subprog = gnat_to_gnu (gnat_name);
+ const Node_Id gnat_subprog = Name (gnat_node);
+ tree gnu_subprog = gnat_to_gnu (gnat_subprog);
/* The FUNCTION_TYPE node giving the GCC type of the subprogram. */
tree gnu_subprog_type = TREE_TYPE (gnu_subprog);
/* The return type of the FUNCTION_TYPE. */
@@ -4487,12 +4487,12 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
explicit dereference. In that case, get the list of formal args from the
type the access type is pointing to. Otherwise, get the formals from the
entity being called. */
- if (Nkind (gnat_name) == N_Explicit_Dereference)
+ if (Nkind (gnat_subprog) == N_Explicit_Dereference)
{
const Entity_Id gnat_prefix_type
- = Underlying_Type (Etype (Prefix (gnat_name)));
+ = Underlying_Type (Etype (Prefix (gnat_subprog)));
- gnat_formal = First_Formal_With_Extras (Etype (gnat_name));
+ gnat_formal = First_Formal_With_Extras (Etype (gnat_subprog));
variadic = IN (Convention (gnat_prefix_type), Convention_C_Variadic);
/* If the access type doesn't require foreign-compatible representation,
@@ -4502,7 +4502,7 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
&& Can_Use_Internal_Rep (gnat_prefix_type);
}
- else if (Nkind (gnat_name) == N_Attribute_Reference)
+ else if (Nkind (gnat_subprog) == N_Attribute_Reference)
{
/* Assume here that this must be 'Elab_Body or 'Elab_Spec. */
gnat_formal = Empty;
@@ -4512,15 +4512,15 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
else
{
- gcc_checking_assert (Is_Entity_Name (gnat_name));
+ gcc_checking_assert (Is_Entity_Name (gnat_subprog));
- gnat_formal = First_Formal_With_Extras (Entity (gnat_name));
- variadic = IN (Convention (Entity (gnat_name)), Convention_C_Variadic);
+ gnat_formal = First_Formal_With_Extras (Entity (gnat_subprog));
+ variadic = IN (Convention (Entity (gnat_subprog)), Convention_C_Variadic);
by_descriptor = false;
/* If we are calling a stubbed function, then raise Program_Error, but
elaborate all our args first. */
- if (Convention (Entity (gnat_name)) == Convention_Stubbed)
+ if (Convention (Entity (gnat_subprog)) == Convention_Stubbed)
{
tree call_expr = build_call_raise (PE_Stubbed_Subprogram_Called,
gnat_node, N_Raise_Program_Error);
@@ -4769,8 +4769,8 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
/* Do not initialize it for the _Init parameter of an initialization
procedure since no data is meant to be passed in. */
if (Ekind (gnat_formal) == E_Out_Parameter
- && Is_Entity_Name (gnat_name)
- && Is_Init_Proc (Entity (gnat_name)))
+ && Is_Entity_Name (gnat_subprog)
+ && Is_Init_Proc (Entity (gnat_subprog)))
gnu_name = gnu_temp = create_temporary ("A", TREE_TYPE (gnu_name));
/* Initialize it on the fly like for an implicit temporary in the
@@ -5101,10 +5101,10 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
if (function_call)
gnu_cico_list = TREE_CHAIN (gnu_cico_list);
- if (Nkind (gnat_name) == N_Explicit_Dereference)
- gnat_formal = First_Formal_With_Extras (Etype (gnat_name));
+ if (Nkind (gnat_subprog) == N_Explicit_Dereference)
+ gnat_formal = First_Formal_With_Extras (Etype (gnat_subprog));
else
- gnat_formal = First_Formal_With_Extras (Entity (gnat_name));
+ gnat_formal = First_Formal_With_Extras (Entity (gnat_subprog));
for (gnat_actual = First_Actual (gnat_node);
Present (gnat_actual);
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index ab5ca5b..d5dd04a 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -2902,12 +2902,10 @@ create_var_decl (tree name, tree asm_name, tree type, tree init,
return var_decl;
}
-/* Return true if TYPE, an aggregate type, contains (or is) an array.
- If SELF_REFERENTIAL is true, then an additional requirement on the
- array is that it be self-referential. */
+/* Return true if TYPE, an aggregate type, contains (or is) an array. */
-bool
-aggregate_type_contains_array_p (tree type, bool self_referential)
+static bool
+aggregate_type_contains_array_p (tree type)
{
switch (TREE_CODE (type))
{
@@ -2918,14 +2916,13 @@ aggregate_type_contains_array_p (tree type, bool self_referential)
tree field;
for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (AGGREGATE_TYPE_P (TREE_TYPE (field))
- && aggregate_type_contains_array_p (TREE_TYPE (field),
- self_referential))
+ && aggregate_type_contains_array_p (TREE_TYPE (field)))
return true;
return false;
}
case ARRAY_TYPE:
- return self_referential ? type_contains_placeholder_p (type) : true;
+ return true;
default:
gcc_unreachable ();
@@ -2935,7 +2932,7 @@ aggregate_type_contains_array_p (tree type, bool self_referential)
/* Return true if TYPE is a type with variable size or a padding type with a
field of variable size or a record that has a field with such a type. */
-static bool
+bool
type_has_variable_size (tree type)
{
tree field;
@@ -3037,7 +3034,7 @@ create_field_decl (tree name, tree type, tree record_type, tree size, tree pos,
|| (!pos && type_has_variable_size (type))
|| (!pos
&& AGGREGATE_TYPE_P (type)
- && aggregate_type_contains_array_p (type, false))))
+ && aggregate_type_contains_array_p (type))))
SET_DECL_ALIGN (field_decl, BITS_PER_UNIT);
/* Bump the alignment if need be, either for bitfield/packing purposes or
diff --git a/gcc/ada/gen_il-fields.ads b/gcc/ada/gen_il-fields.ads
index f3f3ca4..ca3439e 100644
--- a/gcc/ada/gen_il-fields.ads
+++ b/gcc/ada/gen_il-fields.ads
@@ -258,6 +258,8 @@ package Gen_IL.Fields is
Is_Folded_In_Parser,
Is_Generic_Contract_Pragma,
Is_Homogeneous_Aggregate,
+ Is_Parenthesis_Aggregate,
+ Is_Enum_Array_Aggregate,
Is_Ignored,
Is_Ignored_Ghost_Pragma,
Is_In_Discriminant_Check,
diff --git a/gcc/ada/gen_il-gen-gen_nodes.adb b/gcc/ada/gen_il-gen-gen_nodes.adb
index 9937919..9f9fef9 100644
--- a/gcc/ada/gen_il-gen-gen_nodes.adb
+++ b/gcc/ada/gen_il-gen-gen_nodes.adb
@@ -481,7 +481,9 @@ begin -- Gen_IL.Gen.Gen_Nodes
(Sy (Expressions, List_Id, Default_No_List),
Sy (Component_Associations, List_Id, Default_No_List),
Sy (Null_Record_Present, Flag),
+ Sy (Is_Parenthesis_Aggregate, Flag),
Sy (Is_Homogeneous_Aggregate, Flag),
+ Sy (Is_Enum_Array_Aggregate, Flag),
Sm (Aggregate_Bounds, Node_Id),
Sm (Entity_Or_Associated_Node, Node_Id), -- just Associated_Node
Sm (Compile_Time_Known_Aggregate, Flag),
diff --git a/gcc/ada/gen_il-gen.adb b/gcc/ada/gen_il-gen.adb
index f058c5a..2e81149 100644
--- a/gcc/ada/gen_il-gen.adb
+++ b/gcc/ada/gen_il-gen.adb
@@ -2135,9 +2135,13 @@ package body Gen_IL.Gen is
procedure One_Comp (F : Field_Enum);
+ --------------
+ -- One_Comp --
+ --------------
+
procedure One_Comp (F : Field_Enum) is
pragma Annotate (Codepeer, Modified, Field_Table);
- Offset : constant Field_Offset := Field_Table (F).Offset;
+ Offset : constant Field_Offset := Field_Table (F).Offset;
begin
if First_Time then
First_Time := False;
diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi
index 9f92812..70e8c36 100644
--- a/gcc/ada/gnat_rm.texi
+++ b/gcc/ada/gnat_rm.texi
@@ -12621,7 +12621,7 @@ end Pkg;
with Pkg; use Pkg;
procedure Example is
procedure Test (O : T'Class) is
- N : Natural := O'Size;-- Error: Dispatching call
+ N : Natural := O'Size; -- Error: Dispatching call
C : T'Class := O; -- Error: implicit Dispatching Call
begin
if O in DT'Class then -- OK : Membership test
diff --git a/gcc/ada/libgnarl/a-taside.ads b/gcc/ada/libgnarl/a-taside.ads
index a3b1e94..1e78626 100644
--- a/gcc/ada/libgnarl/a-taside.ads
+++ b/gcc/ada/libgnarl/a-taside.ads
@@ -92,7 +92,9 @@ is
function Activation_Is_Complete (T : Task_Id) return Boolean with
Volatile_Function,
+ Pre => T /= Null_Task_Id,
Global => Tasking_State;
+ pragma Inline (Activation_Is_Complete);
private
pragma SPARK_Mode (Off);
diff --git a/gcc/ada/libgnarl/s-interr.adb b/gcc/ada/libgnarl/s-interr.adb
index 7d36b9f..dc1ed17 100644
--- a/gcc/ada/libgnarl/s-interr.adb
+++ b/gcc/ada/libgnarl/s-interr.adb
@@ -159,7 +159,7 @@ package body System.Interrupts is
end record;
User_Handler : array (Interrupt_ID'Range) of Handler_Assoc :=
- (others => (null, Static => False));
+ [others => (null, Static => False)];
pragma Volatile_Components (User_Handler);
-- Holds the protected procedure handler (if any) and its Static
-- information for each interrupt. A handler is a Static one if it is
@@ -167,27 +167,27 @@ package body System.Interrupts is
-- not static)
User_Entry : array (Interrupt_ID'Range) of Entry_Assoc :=
- (others => (T => Null_Task, E => Null_Task_Entry));
+ [others => (T => Null_Task, E => Null_Task_Entry)];
pragma Volatile_Components (User_Entry);
-- Holds the task and entry index (if any) for each interrupt
- Blocked : array (Interrupt_ID'Range) of Boolean := (others => False);
+ Blocked : array (Interrupt_ID'Range) of Boolean := [others => False];
pragma Atomic_Components (Blocked);
-- True iff the corresponding interrupt is blocked in the process level
- Ignored : array (Interrupt_ID'Range) of Boolean := (others => False);
+ Ignored : array (Interrupt_ID'Range) of Boolean := [others => False];
pragma Atomic_Components (Ignored);
-- True iff the corresponding interrupt is blocked in the process level
Last_Unblocker :
- array (Interrupt_ID'Range) of Task_Id := (others => Null_Task);
+ array (Interrupt_ID'Range) of Task_Id := [others => Null_Task];
pragma Atomic_Components (Last_Unblocker);
-- Holds the ID of the last Task which Unblocked this Interrupt. It
-- contains Null_Task if no tasks have ever requested the Unblocking
-- operation or the Interrupt is currently Blocked.
Server_ID : array (Interrupt_ID'Range) of Task_Id :=
- (others => Null_Task);
+ [others => Null_Task];
pragma Atomic_Components (Server_ID);
-- Holds the Task_Id of the Server_Task for each interrupt. Task_Id is
-- needed to accomplish locking per Interrupt base. Also is needed to
diff --git a/gcc/ada/libgnarl/s-intman.ads b/gcc/ada/libgnarl/s-intman.ads
index c493163..663aed9 100644
--- a/gcc/ada/libgnarl/s-intman.ads
+++ b/gcc/ada/libgnarl/s-intman.ads
@@ -74,7 +74,7 @@ package System.Interrupt_Management is
-- The interrupt that is used to implement task abort if an interrupt is
-- used for that purpose. This is one of the reserved interrupts.
- Keep_Unmasked : Interrupt_Set := (others => False);
+ Keep_Unmasked : Interrupt_Set := [others => False];
-- Keep_Unmasked (I) is true iff the interrupt I is one that must be kept
-- unmasked at all times, except (perhaps) for short critical sections.
-- This includes interrupts that are mapped to exceptions (see
@@ -83,7 +83,7 @@ package System.Interrupt_Management is
-- reasons. Where interrupts are implemented as OS signals, and signal
-- masking is per-task, the interrupt should be unmasked in ALL TASKS.
- Reserve : Interrupt_Set := (others => False);
+ Reserve : Interrupt_Set := [others => False];
-- Reserve (I) is true iff the interrupt I is one that cannot be permitted
-- to be attached to a user handler. The possible reasons are many. For
-- example, it may be mapped to an exception used to implement task abort,
diff --git a/gcc/ada/libgnarl/s-intman__posix.adb b/gcc/ada/libgnarl/s-intman__posix.adb
index ae3d77e..f0f65cd 100644
--- a/gcc/ada/libgnarl/s-intman__posix.adb
+++ b/gcc/ada/libgnarl/s-intman__posix.adb
@@ -66,7 +66,7 @@ package body System.Interrupt_Management is
type Interrupt_List is array (Interrupt_ID range <>) of Interrupt_ID;
Exception_Interrupts : constant Interrupt_List :=
- (SIGFPE, SIGILL, SIGSEGV, SIGBUS);
+ [SIGFPE, SIGILL, SIGSEGV, SIGBUS];
Unreserve_All_Interrupts : constant Interfaces.C.int;
pragma Import
@@ -206,8 +206,8 @@ package body System.Interrupt_Management is
act.sa_mask := Signal_Mask;
- pragma Assert (Keep_Unmasked = (Interrupt_ID'Range => False));
- pragma Assert (Reserve = (Interrupt_ID'Range => False));
+ pragma Assert (Keep_Unmasked = [Interrupt_ID'Range => False]);
+ pragma Assert (Reserve = [Interrupt_ID'Range => False]);
-- Process state of exception signals
diff --git a/gcc/ada/libgnarl/s-mudido__affinity.adb b/gcc/ada/libgnarl/s-mudido__affinity.adb
index 5a9ccaf..7118a1d 100644
--- a/gcc/ada/libgnarl/s-mudido__affinity.adb
+++ b/gcc/ada/libgnarl/s-mudido__affinity.adb
@@ -113,7 +113,7 @@ package body System.Multiprocessors.Dispatching_Domains is
function Create (First : CPU; Last : CPU_Range) return Dispatching_Domain is
begin
- return Create ((First .. Last => True));
+ return Create ([First .. Last => True]);
end Create;
function Create (Set : CPU_Set) return Dispatching_Domain is
@@ -156,7 +156,7 @@ package body System.Multiprocessors.Dispatching_Domains is
ST.System_Domain (Rng);
Actual : constant ST.Dispatching_Domain :=
ST_DD_Slice and not System_Domain_Slice;
- Expected : constant ST.Dispatching_Domain := (Rng => False);
+ Expected : constant ST.Dispatching_Domain := [Rng => False];
begin
if Actual /= Expected then
raise Dispatching_Domain_Error with
@@ -184,7 +184,7 @@ package body System.Multiprocessors.Dispatching_Domains is
New_System_Domain (Rng) := New_System_Domain (Rng) and not ST_DD_Slice;
- if New_System_Domain = (New_System_Domain'Range => False) then
+ if New_System_Domain = [New_System_Domain'Range => False] then
raise Dispatching_Domain_Error with
"would leave System_Dispatching_Domain empty";
end if;
diff --git a/gcc/ada/libgnarl/s-osinte__linux.ads b/gcc/ada/libgnarl/s-osinte__linux.ads
index cda0f8e..4f682e0 100644
--- a/gcc/ada/libgnarl/s-osinte__linux.ads
+++ b/gcc/ada/libgnarl/s-osinte__linux.ads
@@ -132,7 +132,7 @@ package System.OS_Interface is
type Signal_Set is array (Natural range <>) of Signal;
- Unmasked : constant Signal_Set := (
+ Unmasked : constant Signal_Set := [
SIGTRAP,
-- To enable debugging on multithreaded applications, mark SIGTRAP to
-- be kept unmasked.
@@ -148,9 +148,9 @@ package System.OS_Interface is
SIGKILL, SIGSTOP
-- These two signals actually can't be masked (POSIX won't allow it)
- );
+ ];
- Reserved : constant Signal_Set := (
+ Reserved : constant Signal_Set := [
SIG32, SIG33, SIG34
-- glibc POSIX threads implementation uses two (NPTL) or three
-- (LinuxThreads) real-time signals for its own use (see SIGNAL(7)).
@@ -158,7 +158,7 @@ package System.OS_Interface is
-- not permit these signals to be used by the public signal.h API.
-- While LinuxThreads is mostly likely unused now, SIG34 is still
-- reserved as this behavior is consistent with past GNAT releases.
- );
+ ];
type sigset_t is private;
diff --git a/gcc/ada/libgnarl/s-taprop__linux.adb b/gcc/ada/libgnarl/s-taprop__linux.adb
index 1c8c6bd..2738934 100644
--- a/gcc/ada/libgnarl/s-taprop__linux.adb
+++ b/gcc/ada/libgnarl/s-taprop__linux.adb
@@ -973,8 +973,8 @@ package body System.Task_Primitives.Operations is
elsif T.Common.Domain /= null and then
(T.Common.Domain /= ST.System_Domain
or else T.Common.Domain.all /=
- (Multiprocessors.CPU'First ..
- Multiprocessors.Number_Of_CPUs => True))
+ [Multiprocessors.CPU'First ..
+ Multiprocessors.Number_Of_CPUs => True])
then
declare
CPUs : constant size_t :=
@@ -1494,8 +1494,8 @@ package body System.Task_Primitives.Operations is
elsif T.Common.Domain /= null and then
(T.Common.Domain /= ST.System_Domain
or else T.Common.Domain.all /=
- (Multiprocessors.CPU'First ..
- Multiprocessors.Number_Of_CPUs => True))
+ [Multiprocessors.CPU'First ..
+ Multiprocessors.Number_Of_CPUs => True])
then
-- Set the affinity to all the processors belonging to the
-- dispatching domain. To avoid changing CPU affinities when
diff --git a/gcc/ada/libgnarl/s-tasdeb.adb b/gcc/ada/libgnarl/s-tasdeb.adb
index d4f37f0..edb2503 100644
--- a/gcc/ada/libgnarl/s-tasdeb.adb
+++ b/gcc/ada/libgnarl/s-tasdeb.adb
@@ -54,7 +54,7 @@ package body System.Tasking.Debug is
type Trace_Flag_Set is array (Character) of Boolean;
- Trace_On : Trace_Flag_Set := ('A' .. 'Z' => False, others => True);
+ Trace_On : Trace_Flag_Set := ['A' .. 'Z' => False, others => True];
Stderr_Fd : constant := 2;
-- File descriptor for standard error
diff --git a/gcc/ada/libgnarl/s-tasdeb.ads b/gcc/ada/libgnarl/s-tasdeb.ads
index eebb2a9..8d75a5e 100644
--- a/gcc/ada/libgnarl/s-tasdeb.ads
+++ b/gcc/ada/libgnarl/s-tasdeb.ads
@@ -65,7 +65,7 @@ package System.Tasking.Debug is
-- General GDB support --
-------------------------
- Known_Tasks : array (0 .. 999) of Task_Id := (others => null)
+ Known_Tasks : array (0 .. 999) of Task_Id := [others => null]
with Atomic_Components;
-- Global array of tasks read by gdb, and updated by Create_Task and
-- Finalize_TCB. Ensure access to its components is atomic to allow
diff --git a/gcc/ada/libgnarl/s-tasinf__linux.ads b/gcc/ada/libgnarl/s-tasinf__linux.ads
index e6da750..f2877e6 100644
--- a/gcc/ada/libgnarl/s-tasinf__linux.ads
+++ b/gcc/ada/libgnarl/s-tasinf__linux.ads
@@ -79,8 +79,8 @@ package System.Task_Info is
subtype CPU_Set is System.OS_Interface.cpu_set_t;
- Any_CPU : constant CPU_Set := (bits => (others => True));
- No_CPU : constant CPU_Set := (bits => (others => False));
+ Any_CPU : constant CPU_Set := (bits => [others => True]);
+ No_CPU : constant CPU_Set := (bits => [others => False]);
Invalid_CPU_Number : exception;
-- Raised when an invalid CPU mask has been specified
diff --git a/gcc/ada/libgnarl/s-taskin.adb b/gcc/ada/libgnarl/s-taskin.adb
index 1e6f42d..478809c 100644
--- a/gcc/ada/libgnarl/s-taskin.adb
+++ b/gcc/ada/libgnarl/s-taskin.adb
@@ -140,7 +140,7 @@ package body System.Tasking is
T.Common.Global_Task_Lock_Nesting := 0;
T.Common.Fall_Back_Handler := null;
T.Common.Specific_Handler := null;
- T.Common.Debug_Events := (others => False);
+ T.Common.Debug_Events := [others => False];
T.Common.Task_Image_Len := 0;
if T.Common.Parent = null then
diff --git a/gcc/ada/libgnarl/s-taskin.ads b/gcc/ada/libgnarl/s-taskin.ads
index 1751553..0073c19 100644
--- a/gcc/ada/libgnarl/s-taskin.ads
+++ b/gcc/ada/libgnarl/s-taskin.ads
@@ -1157,7 +1157,7 @@ package System.Tasking is
-- non-terminated task so that the associated storage is automatically
-- reclaimed when the task terminates.
- Attributes : Attribute_Array := (others => 0);
+ Attributes : Attribute_Array := [others => 0];
-- Task attributes
-- IMPORTANT Note: the Entry_Queues field is last for efficiency of
diff --git a/gcc/ada/libgnarl/s-tasren.adb b/gcc/ada/libgnarl/s-tasren.adb
index fa10b0c..7b11d39 100644
--- a/gcc/ada/libgnarl/s-tasren.adb
+++ b/gcc/ada/libgnarl/s-tasren.adb
@@ -59,28 +59,28 @@ package body System.Tasking.Rendezvous is
----------------
Default_Treatment : constant array (Select_Modes) of Select_Treatment :=
- (Simple_Mode => No_Alternative_Open,
+ [Simple_Mode => No_Alternative_Open,
Else_Mode => Else_Selected,
Terminate_Mode => Terminate_Selected,
- Delay_Mode => No_Alternative_Open);
+ Delay_Mode => No_Alternative_Open];
New_State : constant array (Boolean, Entry_Call_State)
of Entry_Call_State :=
- (True =>
- (Never_Abortable => Never_Abortable,
+ [True =>
+ [Never_Abortable => Never_Abortable,
Not_Yet_Abortable => Now_Abortable,
Was_Abortable => Now_Abortable,
Now_Abortable => Now_Abortable,
Done => Done,
- Cancelled => Cancelled),
+ Cancelled => Cancelled],
False =>
- (Never_Abortable => Never_Abortable,
+ [Never_Abortable => Never_Abortable,
Not_Yet_Abortable => Not_Yet_Abortable,
Was_Abortable => Was_Abortable,
Now_Abortable => Now_Abortable,
Done => Done,
- Cancelled => Cancelled)
- );
+ Cancelled => Cancelled]
+ ];
-----------------------
-- Local Subprograms --
diff --git a/gcc/ada/libgnarl/s-tassta.adb b/gcc/ada/libgnarl/s-tassta.adb
index bbc7d14..245145cf 100644
--- a/gcc/ada/libgnarl/s-tassta.adb
+++ b/gcc/ada/libgnarl/s-tassta.adb
@@ -1462,7 +1462,7 @@ package body System.Tasking.Stages is
To_Stderr (System.Address_Image (To_Address (Self_Id)));
To_Stderr (" terminated by unhandled exception");
- To_Stderr ((1 => ASCII.LF));
+ To_Stderr ([ASCII.LF]);
To_Stderr (Exception_Information (Excep.all));
Initialization.Task_Unlock (Self_Id);
end Trace_Unhandled_Exception_In_Task;
diff --git a/gcc/ada/libgnarl/s-tataat.adb b/gcc/ada/libgnarl/s-tataat.adb
index d3b23bb..ebc16e9 100644
--- a/gcc/ada/libgnarl/s-tataat.adb
+++ b/gcc/ada/libgnarl/s-tataat.adb
@@ -47,7 +47,7 @@ package body System.Tasking.Task_Attributes is
end record;
Index_Array : array (1 .. Max_Attribute_Count) of Index_Info :=
- (others => (False, False));
+ [others => (False, False)];
-- Note that this package will use an efficient implementation with no
-- locks and no extra dynamic memory allocation if Attribute can fit in a
diff --git a/gcc/ada/libgnarl/s-tpobop.adb b/gcc/ada/libgnarl/s-tpobop.adb
index 5739eaa..90e45e9 100644
--- a/gcc/ada/libgnarl/s-tpobop.adb
+++ b/gcc/ada/libgnarl/s-tpobop.adb
@@ -942,21 +942,21 @@ package body System.Tasking.Protected_Objects.Operations is
New_State : constant array (Boolean, Entry_Call_State)
of Entry_Call_State :=
- (True =>
- (Never_Abortable => Never_Abortable,
+ [True =>
+ [Never_Abortable => Never_Abortable,
Not_Yet_Abortable => Now_Abortable,
Was_Abortable => Now_Abortable,
Now_Abortable => Now_Abortable,
Done => Done,
- Cancelled => Cancelled),
+ Cancelled => Cancelled],
False =>
- (Never_Abortable => Never_Abortable,
+ [Never_Abortable => Never_Abortable,
Not_Yet_Abortable => Not_Yet_Abortable,
Was_Abortable => Was_Abortable,
Now_Abortable => Now_Abortable,
Done => Done,
- Cancelled => Cancelled)
- );
+ Cancelled => Cancelled]
+ ];
procedure Update_For_Queue_To_PO
(Entry_Call : Entry_Call_Link;
diff --git a/gcc/ada/libgnat/a-calend.adb b/gcc/ada/libgnat/a-calend.adb
index b24e95d..3d7ae90 100644
--- a/gcc/ada/libgnat/a-calend.adb
+++ b/gcc/ada/libgnat/a-calend.adb
@@ -206,14 +206,14 @@ is
Cumulative_Days_Before_Month :
constant array (Month_Number) of Natural :=
- (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
+ [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
-- The following table contains the hard time values of all existing leap
-- seconds. The values are produced by the utility program xleaps.adb. This
-- must be updated when additional leap second times are defined.
Leap_Second_Times : constant array (1 .. Leap_Seconds_Count) of Time_Rep :=
- (-5601484800000000000,
+ [-5601484800000000000,
-5585587199000000000,
-5554051198000000000,
-5522515197000000000,
@@ -239,7 +239,7 @@ is
-4449513577000000000,
-4339180776000000000,
-4244572775000000000,
- -4197052774000000000);
+ -4197052774000000000];
---------
-- "+" --
diff --git a/gcc/ada/libgnat/a-calend.ads b/gcc/ada/libgnat/a-calend.ads
index cd3fed5..caca8da 100644
--- a/gcc/ada/libgnat/a-calend.ads
+++ b/gcc/ada/libgnat/a-calend.ads
@@ -242,7 +242,7 @@ private
-- epoch) expressed in nanoseconds. Note that year 2100 is non-leap.
Days_In_Month : constant array (Month_Number) of Day_Number :=
- (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
+ [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
-- Days in month for non-leap year, leap year case is adjusted in code
Invalid_Time_Zone_Offset : Long_Integer;
diff --git a/gcc/ada/libgnat/a-cfinve.adb b/gcc/ada/libgnat/a-cfinve.adb
index d0c7e82..4770608 100644
--- a/gcc/ada/libgnat/a-cfinve.adb
+++ b/gcc/ada/libgnat/a-cfinve.adb
@@ -871,7 +871,7 @@ is
J := To_Array_Index (Before);
- Elems (Container) (J .. J - 1 + Count) := (others => H (New_Item));
+ Elems (Container) (J .. J - 1 + Count) := [others => H (New_Item)];
end Insert;
procedure Insert
@@ -1445,7 +1445,7 @@ is
(Capacity => Length,
Last => Last,
Elements_Ptr => <>,
- Elements => (others => H (New_Item)));
+ Elements => [others => H (New_Item)]);
end;
end To_Vector;
diff --git a/gcc/ada/libgnat/a-chahan.adb b/gcc/ada/libgnat/a-chahan.adb
index 411d485..387af42 100644
--- a/gcc/ada/libgnat/a-chahan.adb
+++ b/gcc/ada/libgnat/a-chahan.adb
@@ -64,7 +64,7 @@ is
Graphic : constant Character_Flags := Alphanum or Special;
Char_Map : constant array (Character) of Character_Flags :=
- (
+ [
NUL => Control,
SOH => Control,
STX => Control,
@@ -282,7 +282,7 @@ is
LC_Y_Acute => Lower,
LC_Icelandic_Thorn => Lower + Basic,
LC_Y_Diaeresis => Lower
- );
+ ];
---------------------
-- Is_Alphanumeric --
diff --git a/gcc/ada/libgnat/a-chtgbo.adb b/gcc/ada/libgnat/a-chtgbo.adb
index 678cdc0..e6db47f 100644
--- a/gcc/ada/libgnat/a-chtgbo.adb
+++ b/gcc/ada/libgnat/a-chtgbo.adb
@@ -60,7 +60,7 @@ package body Ada.Containers.Hash_Tables.Generic_Bounded_Operations is
-- HT.Busy := 0;
-- HT.Lock := 0;
HT.Free := -1;
- HT.Buckets := (others => 0); -- optimize this somehow ???
+ HT.Buckets := [others => 0]; -- optimize this somehow ???
end Clear;
--------------------------
diff --git a/gcc/ada/libgnat/a-cobove.adb b/gcc/ada/libgnat/a-cobove.adb
index e56cb94..f340f23 100644
--- a/gcc/ada/libgnat/a-cobove.adb
+++ b/gcc/ada/libgnat/a-cobove.adb
@@ -258,7 +258,7 @@ package body Ada.Containers.Bounded_Vectors is
end if;
return Vector'(Capacity => 2,
- Elements => (Left, Right),
+ Elements => [Left, Right],
Last => Index_Type'First + 1,
others => <>);
end "&";
@@ -1227,7 +1227,7 @@ package body Ada.Containers.Bounded_Vectors is
-- The new items are being appended to the vector, so no
-- sliding of existing elements is required.
- EA (J .. New_Length) := (others => New_Item);
+ EA (J .. New_Length) := [others => New_Item];
else
-- The new items are being inserted before some existing
@@ -1235,7 +1235,7 @@ package body Ada.Containers.Bounded_Vectors is
-- new home.
EA (J + Count .. New_Length) := EA (J .. Old_Length);
- EA (J .. J + Count - 1) := (others => New_Item);
+ EA (J .. J + Count - 1) := [others => New_Item];
end if;
if Index_Type'Base'Last >= Count_Type'Pos (Count_Type'Last) then
@@ -2770,7 +2770,7 @@ package body Ada.Containers.Bounded_Vectors is
end if;
return V : Vector (Capacity => Length) do
- V.Elements := (others => New_Item);
+ V.Elements := [others => New_Item];
V.Last := Last;
end return;
end To_Vector;
diff --git a/gcc/ada/libgnat/a-cofove.adb b/gcc/ada/libgnat/a-cofove.adb
index c7f4f06..4031e99 100644
--- a/gcc/ada/libgnat/a-cofove.adb
+++ b/gcc/ada/libgnat/a-cofove.adb
@@ -763,7 +763,7 @@ is
J := To_Array_Index (Before);
- Container.Elements (J .. J - 1 + Count) := (others => New_Item);
+ Container.Elements (J .. J - 1 + Count) := [others => New_Item];
end Insert;
procedure Insert
@@ -1304,7 +1304,7 @@ is
return
(Capacity => Length,
Last => Last,
- Elements => (others => New_Item));
+ Elements => [others => New_Item]);
end;
end To_Vector;
diff --git a/gcc/ada/libgnat/a-cohata.ads b/gcc/ada/libgnat/a-cohata.ads
index f7e44a3..a52f542 100644
--- a/gcc/ada/libgnat/a-cohata.ads
+++ b/gcc/ada/libgnat/a-cohata.ads
@@ -73,7 +73,7 @@ package Ada.Containers.Hash_Tables is
TC : aliased Helpers.Tamper_Counts;
Free : Count_Type'Base := -1;
Nodes : Nodes_Type (1 .. Capacity);
- Buckets : Buckets_Type (1 .. Modulus) := (others => 0);
+ Buckets : Buckets_Type (1 .. Modulus) := [others => 0];
end record;
package Implementation is new Helpers.Generic_Implementation;
diff --git a/gcc/ada/libgnat/a-coinve.adb b/gcc/ada/libgnat/a-coinve.adb
index 9df6e3d..7ed88a5 100644
--- a/gcc/ada/libgnat/a-coinve.adb
+++ b/gcc/ada/libgnat/a-coinve.adb
@@ -1027,7 +1027,7 @@ is
SA (Index_Type'First .. Source.Last);
begin
TA (Index_Type'First .. J) := Src;
- Src := (others => null);
+ Src := [others => null];
end;
Source.Last := No_Index;
@@ -1472,7 +1472,7 @@ is
-- we started by clearing out all of the stale values,
-- leaving a "hole" in the middle of the array.
- E (K .. Index - 1) := (others => null);
+ E (K .. Index - 1) := [others => null];
raise;
end;
end if;
@@ -2157,7 +2157,7 @@ is
end if;
E (Index .. New_Last) := E (Before .. Container.Last);
- E (Before .. Index - 1) := (others => null);
+ E (Before .. Index - 1) := [others => null];
end if;
end;
diff --git a/gcc/ada/libgnat/a-convec.adb b/gcc/ada/libgnat/a-convec.adb
index 5cede72..6f39ceb 100644
--- a/gcc/ada/libgnat/a-convec.adb
+++ b/gcc/ada/libgnat/a-convec.adb
@@ -1161,7 +1161,7 @@ is
Container.Elements := new Elements_Type'
(Last => New_Last,
- EA => (others => New_Item));
+ EA => [others => New_Item]);
-- The allocation of the new, internal array succeeded, so it is now
-- safe to update the Last index, restoring container invariants.
@@ -1189,7 +1189,7 @@ is
-- The new items are being appended to the vector, so no
-- sliding of existing elements is required.
- EA (Before .. New_Last) := (others => New_Item);
+ EA (Before .. New_Last) := [others => New_Item];
else
-- The new items are being inserted before some existing
@@ -1204,7 +1204,7 @@ is
end if;
EA (Index .. New_Last) := EA (Before .. Container.Last);
- EA (Before .. Index - 1) := (others => New_Item);
+ EA (Before .. Index - 1) := [others => New_Item];
end if;
end;
@@ -1270,7 +1270,7 @@ is
SA (Index_Type'First .. Before - 1);
if Before > Container.Last then
- DA (Before .. New_Last) := (others => New_Item);
+ DA (Before .. New_Last) := [others => New_Item];
else
-- The new items are being inserted before some existing elements,
@@ -1282,7 +1282,7 @@ is
Index := Index_Type'Base (Count_Type'Base (Before) + Count);
end if;
- DA (Before .. Index - 1) := (others => New_Item);
+ DA (Before .. Index - 1) := [others => New_Item];
DA (Index .. New_Last) := SA (Before .. Container.Last);
end if;
@@ -3265,7 +3265,7 @@ is
Last := Index_Type'Base (Count_Type'Base (No_Index) + Length);
end if;
- Elements := new Elements_Type'(Last, EA => (others => New_Item));
+ Elements := new Elements_Type'(Last, EA => [others => New_Item]);
return (Controlled with Elements, Last, TC => <>);
end To_Vector;
diff --git a/gcc/ada/libgnat/a-coprnu.ads b/gcc/ada/libgnat/a-coprnu.ads
index 7f5f7bd..8a267fb 100644
--- a/gcc/ada/libgnat/a-coprnu.ads
+++ b/gcc/ada/libgnat/a-coprnu.ads
@@ -38,12 +38,12 @@ package Ada.Containers.Prime_Numbers is
type Primes_Type is array (Positive range <>) of Hash_Type;
Primes : constant Primes_Type :=
- (53, 97, 193, 389, 769,
+ [53, 97, 193, 389, 769,
1543, 3079, 6151, 12289, 24593,
49157, 98317, 196613, 393241, 786433,
1572869, 3145739, 6291469, 12582917, 25165843,
50331653, 100663319, 201326611, 402653189, 805306457,
- 1610612741, 3221225473, 4294967291);
+ 1610612741, 3221225473, 4294967291];
function To_Prime (Length : Count_Type) return Hash_Type;
-- Returns the smallest value in Primes not less than Length
diff --git a/gcc/ada/libgnat/a-direct.adb b/gcc/ada/libgnat/a-direct.adb
index 20616a2..41dca3c 100644
--- a/gcc/ada/libgnat/a-direct.adb
+++ b/gcc/ada/libgnat/a-direct.adb
@@ -89,7 +89,7 @@ package body Ada.Directories is
end record;
-- The current state of a search
- Empty_String : constant String := (1 .. 0 => ASCII.NUL);
+ Empty_String : constant String := "";
-- Empty string, returned by function Extension when there is no extension
procedure Free is new Ada.Unchecked_Deallocation (Search_Data, Search_Ptr);
@@ -107,7 +107,7 @@ package body Ada.Directories is
(Search : in out Search_Type;
Directory : String;
Pattern : String;
- Filter : Filter_Type := (others => True);
+ Filter : Filter_Type := [others => True];
Force_Case_Insensitive : Boolean);
-- Similar to Start_Search except we can force a search to be
-- case-insensitive, which is important for detecting the name-case
@@ -1094,7 +1094,7 @@ package body Ada.Directories is
(Search => S,
Directory => To_String (Dir_Path),
Pattern => "",
- Filter => (Directory => False, others => True));
+ Filter => [Directory => False, others => True]);
loop
Get_Next_Entry (S, Test_File);
@@ -1114,7 +1114,7 @@ package body Ada.Directories is
(Search => S,
Directory => To_String (Dir_Path),
Pattern => Simple_Name (Test_File),
- Filter => (Directory => False, others => True),
+ Filter => [Directory => False, others => True],
Force_Case_Insensitive => True);
-- We will find at least one match due to the search hitting our test
@@ -1215,7 +1215,7 @@ package body Ada.Directories is
procedure Search
(Directory : String;
Pattern : String;
- Filter : Filter_Type := (others => True);
+ Filter : Filter_Type := [others => True];
Process : not null access procedure
(Directory_Entry : Directory_Entry_Type))
is
@@ -1401,7 +1401,7 @@ package body Ada.Directories is
(Search : in out Search_Type;
Directory : String;
Pattern : String;
- Filter : Filter_Type := (others => True))
+ Filter : Filter_Type := [others => True])
is
begin
Start_Search_Internal (Search, Directory, Pattern, Filter, False);
@@ -1415,7 +1415,7 @@ package body Ada.Directories is
(Search : in out Search_Type;
Directory : String;
Pattern : String;
- Filter : Filter_Type := (others => True);
+ Filter : Filter_Type := [others => True];
Force_Case_Insensitive : Boolean)
is
function opendir (file_name : String) return DIRs;
diff --git a/gcc/ada/libgnat/a-direct.ads b/gcc/ada/libgnat/a-direct.ads
index 12f3bd4..a88cd01 100644
--- a/gcc/ada/libgnat/a-direct.ads
+++ b/gcc/ada/libgnat/a-direct.ads
@@ -366,7 +366,7 @@ package Ada.Directories is
(Search : in out Search_Type;
Directory : String;
Pattern : String;
- Filter : Filter_Type := (others => True));
+ Filter : Filter_Type := [others => True]);
-- Starts a search in the directory entry in the directory named by
-- Directory for entries matching Pattern. Pattern represents a file name
-- matching pattern. If Pattern is null, all items in the directory are
@@ -407,7 +407,7 @@ package Ada.Directories is
procedure Search
(Directory : String;
Pattern : String;
- Filter : Filter_Type := (others => True);
+ Filter : Filter_Type := [others => True];
Process : not null access procedure
(Directory_Entry : Directory_Entry_Type));
-- Searches in the directory named by Directory for entries matching
diff --git a/gcc/ada/libgnat/a-direio.adb b/gcc/ada/libgnat/a-direio.adb
index f83b34b..1258bee 100644
--- a/gcc/ada/libgnat/a-direio.adb
+++ b/gcc/ada/libgnat/a-direio.adb
@@ -45,7 +45,7 @@ with Ada.Unchecked_Conversion;
package body Ada.Direct_IO is
Zeroes : constant System.Storage_Elements.Storage_Array :=
- (1 .. System.Storage_Elements.Storage_Offset (Bytes) => 0);
+ [1 .. System.Storage_Elements.Storage_Offset (Bytes) => 0];
-- Buffer used to fill out partial records
package FCB renames System.File_Control_Block;
diff --git a/gcc/ada/libgnat/a-nbnbre.adb b/gcc/ada/libgnat/a-nbnbre.adb
index e45bc6d..d1820f4 100644
--- a/gcc/ada/libgnat/a-nbnbre.adb
+++ b/gcc/ada/libgnat/a-nbnbre.adb
@@ -441,8 +441,8 @@ package body Ada.Numerics.Big_Numbers.Big_Reals is
if Str = "" then
return Leading_Padding ("0", Min_Length, Char);
else
- return (1 .. Integer'Max (Integer (Min_Length) - Str'Length, 0)
- => Char) & Str;
+ return [1 .. Integer'Max (Integer (Min_Length) - Str'Length, 0)
+ => Char] & Str;
end if;
end Leading_Padding;
@@ -468,8 +468,8 @@ package body Ada.Numerics.Big_Numbers.Big_Reals is
return Str (Str'First .. Str'First + Length - 1);
else
return Str &
- (1 .. Integer'Max (Integer (Length) - Str'Length, 0)
- => Char);
+ [1 .. Integer'Max (Integer (Length) - Str'Length, 0)
+ => Char];
end if;
end Trailing_Padding;
@@ -495,7 +495,7 @@ package body Ada.Numerics.Big_Numbers.Big_Reals is
if Index < 0 then
return Leading_Padding ("0", Fore)
& "."
- & Trailing_Padding ((1 .. -Index => '0') & Str, Aft)
+ & Trailing_Padding ([1 .. -Index => '0'] & Str, Aft)
& (if Exp = 0 then "" else "E+" & Image (Natural (Exp)));
else
return Leading_Padding (Str (Str'First .. Index), Fore)
diff --git a/gcc/ada/libgnat/a-ngrear.adb b/gcc/ada/libgnat/a-ngrear.adb
index 820e6f7..5095db8 100644
--- a/gcc/ada/libgnat/a-ngrear.adb
+++ b/gcc/ada/libgnat/a-ngrear.adb
@@ -614,7 +614,7 @@ package body Ada.Numerics.Generic_Real_Arrays is
-- different bounds, so take care indexing elements. Assignment
-- as a whole is fine as sliding is automatic in that case.
- Vectors := (if not Compute_Vectors then (1 .. 0 => (1 .. 0 => 0.0))
+ Vectors := (if not Compute_Vectors then [1 .. 0 => [1 .. 0 => 0.0]]
else Unit_Matrix (Vectors'Length (1), Vectors'Length (2)));
Values := Diagonal (M);
@@ -637,7 +637,7 @@ package body Ada.Numerics.Generic_Real_Arrays is
-- an absolute value that exceeds the threshold.
Diag := Values;
- Diag_Adj := (others => 0.0); -- Accumulates adjustments to Diag
+ Diag_Adj := [others => 0.0]; -- Accumulates adjustments to Diag
for Row in 1 .. N - 1 loop
for Col in Row + 1 .. N loop
diff --git a/gcc/ada/libgnat/a-stbubo.adb b/gcc/ada/libgnat/a-stbubo.adb
index a3e0e32..6e729ed 100644
--- a/gcc/ada/libgnat/a-stbubo.adb
+++ b/gcc/ada/libgnat/a-stbubo.adb
@@ -90,10 +90,10 @@ package body Ada.Strings.Text_Buffers.Bounded is
-- If this aggregate becomes illegal due to new field, don't
-- forget to add corresponding assignment statement below.
Dummy : array (1 .. 0) of Buffer_Type (0) :=
- (others =>
- (Max_Characters => 0, Chars => <>, Indentation => <>,
+ [others =>
+ [Max_Characters => 0, Chars => <>, Indentation => <>,
Indent_Pending => <>, UTF_8_Length => <>, UTF_8_Column => <>,
- All_7_Bits => <>, All_8_Bits => <>, Truncated => <>));
+ All_7_Bits => <>, All_8_Bits => <>, Truncated => <>]];
begin
Buffer.Indentation := Defaulted.Indentation;
Buffer.Indent_Pending := Defaulted.Indent_Pending;
diff --git a/gcc/ada/libgnat/a-stbufo.adb b/gcc/ada/libgnat/a-stbufo.adb
index 8ac5512..7cf7a34 100644
--- a/gcc/ada/libgnat/a-stbufo.adb
+++ b/gcc/ada/libgnat/a-stbufo.adb
@@ -42,7 +42,7 @@ package body Ada.Strings.Text_Buffers.Formatting is
X1, X2, X3, X4, X5, X6, X7, X8, X9 : Utils.UTF_8_Lines := "")
is
J : Positive := T'First;
- Used : array (1 .. 9) of Boolean := (others => False);
+ Used : array (1 .. 9) of Boolean := [others => False];
begin
while J <= T'Last loop
if T (J) = '\' then
diff --git a/gcc/ada/libgnat/a-stbuun.adb b/gcc/ada/libgnat/a-stbuun.adb
index 9ae3d28..b97ec02 100644
--- a/gcc/ada/libgnat/a-stbuun.adb
+++ b/gcc/ada/libgnat/a-stbuun.adb
@@ -103,10 +103,10 @@ package body Ada.Strings.Text_Buffers.Unbounded is
-- If this aggregate becomes illegal due to new field, don't
-- forget to add corresponding assignment statement below.
Dummy : array (1 .. 0) of Buffer_Type :=
- (others =>
- (Indentation => <>, Indent_Pending => <>, UTF_8_Length => <>,
+ [others =>
+ [Indentation => <>, Indent_Pending => <>, UTF_8_Length => <>,
UTF_8_Column => <>, All_7_Bits => <>, All_8_Bits => <>,
- List => <>, Last_Used => <>));
+ List => <>, Last_Used => <>]];
begin
Buffer.Indentation := Defaulted.Indentation;
Buffer.Indent_Pending := Defaulted.Indent_Pending;
diff --git a/gcc/ada/libgnat/a-stbuut.adb b/gcc/ada/libgnat/a-stbuut.adb
index b32b2d3..2d7d371 100644
--- a/gcc/ada/libgnat/a-stbuut.adb
+++ b/gcc/ada/libgnat/a-stbuut.adb
@@ -35,28 +35,28 @@ package body Ada.Strings.Text_Buffers.Utils is
(Buffer : in out Root_Buffer_Type'Class; Item : Character_7)
is
begin
- Put (Buffer, (1 => Item));
+ Put (Buffer, [Item]);
end Put_7bit;
procedure Put_Character
(Buffer : in out Root_Buffer_Type'Class; Item : Character)
is
begin
- Put (Buffer, (1 => Item));
+ Put (Buffer, [Item]);
end Put_Character;
procedure Put_Wide_Character
(Buffer : in out Root_Buffer_Type'Class; Item : Wide_Character)
is
begin
- Wide_Put (Buffer, (1 => Item));
+ Wide_Put (Buffer, [Item]);
end Put_Wide_Character;
procedure Put_Wide_Wide_Character
(Buffer : in out Root_Buffer_Type'Class; Item : Wide_Wide_Character)
is
begin
- Wide_Wide_Put (Buffer, (1 => Item));
+ Wide_Wide_Put (Buffer, [Item]);
end Put_Wide_Wide_Character;
procedure Put_UTF_8_Lines
diff --git a/gcc/ada/libgnat/a-stmaco.ads b/gcc/ada/libgnat/a-stmaco.ads
index 4d280ec..8d2f6f7 100644
--- a/gcc/ada/libgnat/a-stmaco.ads
+++ b/gcc/ada/libgnat/a-stmaco.ads
@@ -64,37 +64,37 @@ private
package L renames Ada.Characters.Latin_1;
Control_Set : constant Character_Set :=
- (L.NUL .. L.US => True,
+ [L.NUL .. L.US => True,
L.DEL .. L.APC => True,
- others => False);
+ others => False];
Graphic_Set : constant Character_Set :=
- (L.Space .. L.Tilde => True,
+ [L.Space .. L.Tilde => True,
L.No_Break_Space .. L.LC_Y_Diaeresis => True,
- others => False);
+ others => False];
Letter_Set : constant Character_Set :=
- ('A' .. 'Z' => True,
+ ['A' .. 'Z' => True,
L.LC_A .. L.LC_Z => True,
L.UC_A_Grave .. L.UC_O_Diaeresis => True,
L.UC_O_Oblique_Stroke .. L.LC_O_Diaeresis => True,
L.LC_O_Oblique_Stroke .. L.LC_Y_Diaeresis => True,
- others => False);
+ others => False];
Lower_Set : constant Character_Set :=
- (L.LC_A .. L.LC_Z => True,
+ [L.LC_A .. L.LC_Z => True,
L.LC_German_Sharp_S .. L.LC_O_Diaeresis => True,
L.LC_O_Oblique_Stroke .. L.LC_Y_Diaeresis => True,
- others => False);
+ others => False];
Upper_Set : constant Character_Set :=
- ('A' .. 'Z' => True,
+ ['A' .. 'Z' => True,
L.UC_A_Grave .. L.UC_O_Diaeresis => True,
L.UC_O_Oblique_Stroke .. L.UC_Icelandic_Thorn => True,
- others => False);
+ others => False];
Basic_Set : constant Character_Set :=
- ('A' .. 'Z' => True,
+ ['A' .. 'Z' => True,
L.LC_A .. L.LC_Z => True,
L.UC_AE_Diphthong .. L.UC_AE_Diphthong => True,
L.LC_AE_Diphthong .. L.LC_AE_Diphthong => True,
@@ -103,40 +103,40 @@ private
L.LC_Icelandic_Thorn .. L.LC_Icelandic_Thorn => True,
L.UC_Icelandic_Eth .. L.UC_Icelandic_Eth => True,
L.LC_Icelandic_Eth .. L.LC_Icelandic_Eth => True,
- others => False);
+ others => False];
Decimal_Digit_Set : constant Character_Set :=
- ('0' .. '9' => True,
- others => False);
+ ['0' .. '9' => True,
+ others => False];
Hexadecimal_Digit_Set : constant Character_Set :=
- ('0' .. '9' => True,
+ ['0' .. '9' => True,
'A' .. 'F' => True,
L.LC_A .. L.LC_F => True,
- others => False);
+ others => False];
Alphanumeric_Set : constant Character_Set :=
- ('0' .. '9' => True,
+ ['0' .. '9' => True,
'A' .. 'Z' => True,
L.LC_A .. L.LC_Z => True,
L.UC_A_Grave .. L.UC_O_Diaeresis => True,
L.UC_O_Oblique_Stroke .. L.LC_O_Diaeresis => True,
L.LC_O_Oblique_Stroke .. L.LC_Y_Diaeresis => True,
- others => False);
+ others => False];
Special_Set : constant Character_Set :=
- (L.Space .. L.Solidus => True,
+ [L.Space .. L.Solidus => True,
L.Colon .. L.Commercial_At => True,
L.Left_Square_Bracket .. L.Grave => True,
L.Left_Curly_Bracket .. L.Tilde => True,
L.No_Break_Space .. L.Inverted_Question => True,
L.Multiplication_Sign .. L.Multiplication_Sign => True,
L.Division_Sign .. L.Division_Sign => True,
- others => False);
+ others => False];
ISO_646_Set : constant Character_Set :=
- (L.NUL .. L.DEL => True,
- others => False);
+ [L.NUL .. L.DEL => True,
+ others => False];
Lower_Case_Map : constant Character_Mapping :=
(L.NUL & -- NUL 0
diff --git a/gcc/ada/libgnat/a-strbou.ads b/gcc/ada/libgnat/a-strbou.ads
index e820184..6efdebc 100644
--- a/gcc/ada/libgnat/a-strbou.ads
+++ b/gcc/ada/libgnat/a-strbou.ads
@@ -2202,7 +2202,7 @@ package Ada.Strings.Bounded with SPARK_Mode is
Slice (Head'Result, 1, Length (Source)) = To_String (Source)
and then
Slice (Head'Result, Length (Source) + 1, Count) =
- (1 .. Count - Length (Source) => Pad),
+ [1 .. Count - Length (Source) => Pad],
Count > Max_Length and then Drop = Right
=>
@@ -2213,13 +2213,13 @@ package Ada.Strings.Bounded with SPARK_Mode is
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),
+ [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),
+ To_String (Head'Result) = [1 .. Max_Length => Pad],
others
=>
@@ -2232,7 +2232,7 @@ package Ada.Strings.Bounded with SPARK_Mode is
and then
Slice (Head'Result,
Max_Length - Count + Length (Source) + 1, Max_Length) =
- (1 .. Count - Length (Source) => Pad));
+ [1 .. Count - Length (Source) => Pad]);
procedure Head
(Source : in out Bounded_String;
@@ -2258,7 +2258,7 @@ package Ada.Strings.Bounded with SPARK_Mode is
To_String (Source'Old)
and then
Slice (Source, Length (Source'Old) + 1, Count) =
- (1 .. Count - Length (Source'Old) => Pad),
+ [1 .. Count - Length (Source'Old) => Pad],
Count > Max_Length and then Drop = Right
=>
@@ -2270,13 +2270,13 @@ package Ada.Strings.Bounded with SPARK_Mode is
To_String (Source'Old)
and then
Slice (Source, Length (Source'Old) + 1, Max_Length) =
- (1 .. Max_Length - Length (Source'Old) => Pad),
+ [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),
+ To_String (Source) = [1 .. Max_Length => Pad],
others
=>
@@ -2290,7 +2290,7 @@ package Ada.Strings.Bounded with SPARK_Mode is
and then
Slice (Source,
Max_Length - Count + Length (Source'Old) + 1, Max_Length) =
- (1 .. Count - Length (Source'Old) => Pad));
+ [1 .. Count - Length (Source'Old) => Pad]);
function Tail
(Source : Bounded_String;
@@ -2316,7 +2316,7 @@ package Ada.Strings.Bounded with SPARK_Mode is
Length (Tail'Result) = Count
and then
Slice (Tail'Result, 1, Count - Length (Source)) =
- (1 .. Count - Length (Source) => Pad)
+ [1 .. Count - Length (Source) => Pad]
and then
Slice (Tail'Result, Count - Length (Source) + 1, Count) =
To_String (Source),
@@ -2328,7 +2328,7 @@ package Ada.Strings.Bounded with SPARK_Mode is
Length (Tail'Result) = Max_Length
and then
Slice (Tail'Result, 1, Max_Length - Length (Source)) =
- (1 .. Max_Length - Length (Source) => Pad)
+ [1 .. Max_Length - Length (Source) => Pad]
and then
(if Length (Source) > 0 then
Slice (Tail'Result,
@@ -2339,7 +2339,7 @@ package Ada.Strings.Bounded with SPARK_Mode is
=>
-- Source is fully dropped on the right
- To_String (Tail'Result) = (1 .. Max_Length => Pad),
+ To_String (Tail'Result) = [1 .. Max_Length => Pad],
others
=>
@@ -2348,7 +2348,7 @@ package Ada.Strings.Bounded with SPARK_Mode is
Length (Tail'Result) = Max_Length
and then
Slice (Tail'Result, 1, Count - Length (Source)) =
- (1 .. Count - Length (Source) => Pad)
+ [1 .. Count - Length (Source) => Pad]
and then
Slice (Tail'Result, Count - Length (Source) + 1, Max_Length) =
Slice (Source, 1, Max_Length - Count + Length (Source)));
@@ -2378,7 +2378,7 @@ package Ada.Strings.Bounded with SPARK_Mode is
Length (Source) = Count
and then
Slice (Source, 1, Count - Length (Source'Old)) =
- (1 .. Count - Length (Source'Old) => Pad)
+ [1 .. Count - Length (Source'Old) => Pad]
and then
Slice (Source, Count - Length (Source'Old) + 1, Count) =
To_String (Source'Old),
@@ -2390,7 +2390,7 @@ package Ada.Strings.Bounded with SPARK_Mode is
Length (Source) = Max_Length
and then
Slice (Source, 1, Max_Length - Length (Source'Old)) =
- (1 .. Max_Length - Length (Source'Old) => Pad)
+ [1 .. Max_Length - Length (Source'Old) => Pad]
and then
(if Length (Source'Old) > 0 then
Slice (Source,
@@ -2401,7 +2401,7 @@ package Ada.Strings.Bounded with SPARK_Mode is
=>
-- Source is fully dropped at the right
- To_String (Source) = (1 .. Max_Length => Pad),
+ To_String (Source) = [1 .. Max_Length => Pad],
others
=>
@@ -2410,7 +2410,7 @@ package Ada.Strings.Bounded with SPARK_Mode is
Length (Source) = Max_Length
and then
Slice (Source, 1, Count - Length (Source'Old)) =
- (1 .. Count - Length (Source'Old) => Pad)
+ [1 .. Count - Length (Source'Old) => Pad]
and then
Slice (Source, Count - Length (Source'Old) + 1, Max_Length) =
Slice (Source'Old,
@@ -2425,7 +2425,7 @@ package Ada.Strings.Bounded with SPARK_Mode is
Right : Character) return Bounded_String
with
Pre => Left <= Max_Length,
- Post => To_String ("*"'Result) = (1 .. Left => Right);
+ Post => To_String ("*"'Result) = [1 .. Left => Right];
function "*"
(Left : Natural;
@@ -2461,7 +2461,7 @@ package Ada.Strings.Bounded with SPARK_Mode is
Pre => (if Count > Max_Length then Drop /= Error),
Post =>
To_String (Replicate'Result) =
- (1 .. Natural'Min (Max_Length, Count) => Item);
+ [1 .. Natural'Min (Max_Length, Count) => Item];
function Replicate
(Count : Natural;
@@ -2565,7 +2565,7 @@ package Ada.Strings.Bounded with SPARK_Mode is
(Max_Length => Max_Length,
Current_Length => 0,
Data =>
- (1 .. Max_Length => ASCII.NUL));
+ [1 .. Max_Length => ASCII.NUL]);
pragma Inline (To_Bounded_String);
diff --git a/gcc/ada/libgnat/a-strfix.ads b/gcc/ada/libgnat/a-strfix.ads
index 1d9fd1b..0d6c5d0 100644
--- a/gcc/ada/libgnat/a-strfix.ads
+++ b/gcc/ada/libgnat/a-strfix.ads
@@ -1258,7 +1258,7 @@ package Ada.Strings.Fixed with SPARK_Mode is
Head'Result (1 .. Source'Length) = Source
and then
Head'Result (Source'Length + 1 .. Count)
- = (1 .. Count - Source'Length => Pad)),
+ = [1 .. Count - Source'Length => Pad]),
Global => null;
-- Returns a string of length Count. If Count <= Source'Length, the string
-- comprises the first Count characters of Source. Otherwise, its contents
@@ -1315,10 +1315,10 @@ package Ada.Strings.Fixed with SPARK_Mode is
-- characters.
(if Source'Length = 0
- then Tail'Result = (1 .. Count => Pad)
+ then Tail'Result = [1 .. Count => Pad]
else
Tail'Result (1 .. Count - Source'Length)
- = (1 .. Count - Source'Length => Pad)
+ = [1 .. Count - Source'Length => Pad]
and then
Tail'Result (Count - Source'Length + 1 .. Tail'Result'Last)
= Source)),
diff --git a/gcc/ada/libgnat/a-strmap.adb b/gcc/ada/libgnat/a-strmap.adb
index c87f4e5..d6b05d2 100644
--- a/gcc/ada/libgnat/a-strmap.adb
+++ b/gcc/ada/libgnat/a-strmap.adb
@@ -135,7 +135,7 @@ is
J : Natural;
type Character_Index is array (Character) of Natural with Ghost;
- Indexes : Character_Index := (others => 0) with Ghost;
+ Indexes : Character_Index := [others => 0] with Ghost;
begin
J := 0;
@@ -367,7 +367,7 @@ is
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;
+ Indexes : Character_Index := [others => 0] with Ghost;
-- Start of processing for To_Range
diff --git a/gcc/ada/libgnat/a-strmap.ads b/gcc/ada/libgnat/a-strmap.ads
index 1a15d5d..320564e 100644
--- a/gcc/ada/libgnat/a-strmap.ads
+++ b/gcc/ada/libgnat/a-strmap.ads
@@ -376,7 +376,7 @@ private
-- the defined operations in the spec, but the operations defined
-- on Character_Set_Internal remain visible.
- Null_Set : constant Character_Set := (others => False);
+ Null_Set : constant Character_Set := [others => False];
type Character_Mapping is array (Character) of Character;
diff --git a/gcc/ada/libgnat/a-strsup.adb b/gcc/ada/libgnat/a-strsup.adb
index a94d6ca..b9d3669 100644
--- a/gcc/ada/libgnat/a-strsup.adb
+++ b/gcc/ada/libgnat/a-strsup.adb
@@ -844,7 +844,7 @@ package body Ada.Strings.Superbounded with SPARK_Mode is
elsif Count <= Max_Length then
Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
- Result.Data (Slen + 1 .. Count) := (others => Pad);
+ Result.Data (Slen + 1 .. Count) := [others => Pad];
Result.Current_Length := Count;
else
@@ -853,18 +853,18 @@ package body Ada.Strings.Superbounded with SPARK_Mode is
Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
if Slen < Max_Length then
- Result.Data (Slen + 1 .. Max_Length) := (others => Pad);
+ Result.Data (Slen + 1 .. Max_Length) := [others => Pad];
end if;
when Strings.Left =>
if Npad >= Max_Length then
- Result.Data := (others => Pad);
+ Result.Data := [others => Pad];
else
Result.Data (1 .. Max_Length - Npad) :=
Source.Data (Count - Max_Length + 1 .. Slen);
Result.Data (Max_Length - Npad + 1 .. Max_Length) :=
- (others => Pad);
+ [others => Pad];
end if;
when Strings.Error =>
@@ -893,26 +893,26 @@ package body Ada.Strings.Superbounded with SPARK_Mode is
Source.Current_Length := Count;
elsif Count <= Max_Length then
- Source.Data (Slen + 1 .. Count) := (others => Pad);
+ Source.Data (Slen + 1 .. Count) := [others => Pad];
Source.Current_Length := Count;
else
case Drop is
when Strings.Right =>
if Slen < Max_Length then
- Source.Data (Slen + 1 .. Max_Length) := (others => Pad);
+ Source.Data (Slen + 1 .. Max_Length) := [others => Pad];
end if;
when Strings.Left =>
if Npad > Max_Length then
- Source.Data := (others => Pad);
+ Source.Data := [others => Pad];
else
Temp := Source.Data;
Source.Data (1 .. Max_Length - Npad) :=
Temp (Count - Max_Length + 1 .. Slen);
Source.Data (Max_Length - Npad + 1 .. Max_Length) :=
- (others => Pad);
+ [others => Pad];
end if;
when Strings.Error =>
@@ -1385,14 +1385,14 @@ package body Ada.Strings.Superbounded with SPARK_Mode is
begin
if Count <= Max_Length then
- Result.Data (1 .. Count) := (others => Item);
+ 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.Data (1 .. Max_Length) := [others => Item];
Result.Current_Length := Max_Length;
end if;
@@ -1686,7 +1686,7 @@ package body Ada.Strings.Superbounded with SPARK_Mode is
end if;
elsif Count <= Max_Length then
- Result.Data (1 .. Npad) := (others => Pad);
+ Result.Data (1 .. Npad) := [others => Pad];
if Slen > 0 then
Result.Data (Npad + 1 .. Count) := Source.Data (1 .. Slen);
@@ -1698,16 +1698,16 @@ package body Ada.Strings.Superbounded with SPARK_Mode is
case Drop is
when Strings.Right =>
if Npad >= Max_Length then
- Result.Data := (others => Pad);
+ Result.Data := [others => Pad];
else
- Result.Data (1 .. Npad) := (others => Pad);
+ Result.Data (1 .. Npad) := [others => Pad];
Result.Data (Npad + 1 .. Max_Length) :=
Source.Data (1 .. Max_Length - Npad);
end if;
when Strings.Left =>
- Result.Data (1 .. Max_Length - Slen) := (others => Pad);
+ Result.Data (1 .. Max_Length - Slen) := [others => Pad];
Result.Data (Max_Length - Slen + 1 .. Max_Length) :=
Source.Data (1 .. Slen);
@@ -1743,7 +1743,7 @@ package body Ada.Strings.Superbounded with SPARK_Mode is
end if;
elsif Count <= Max_Length then
- Source.Data (1 .. Npad) := (others => Pad);
+ Source.Data (1 .. Npad) := [others => Pad];
if Slen > 0 then
Source.Data (Npad + 1 .. Count) := Temp (1 .. Slen);
@@ -1755,16 +1755,16 @@ package body Ada.Strings.Superbounded with SPARK_Mode is
case Drop is
when Strings.Right =>
if Npad >= Max_Length then
- Source.Data := (others => Pad);
+ Source.Data := [others => Pad];
else
- Source.Data (1 .. Npad) := (others => Pad);
+ Source.Data (1 .. Npad) := [others => Pad];
Source.Data (Npad + 1 .. Max_Length) :=
Temp (1 .. Max_Length - Npad);
end if;
when Strings.Left =>
- Source.Data (1 .. Max_Length - Slen) := (others => Pad);
+ Source.Data (1 .. Max_Length - Slen) := [others => Pad];
Source.Data (Max_Length - Slen + 1 .. Max_Length) :=
Temp (1 .. Slen);
diff --git a/gcc/ada/libgnat/a-strsup.ads b/gcc/ada/libgnat/a-strsup.ads
index ae4339f..5e582c7 100644
--- a/gcc/ada/libgnat/a-strsup.ads
+++ b/gcc/ada/libgnat/a-strsup.ads
@@ -2322,7 +2322,7 @@ package Ada.Strings.Superbounded with SPARK_Mode is
and then
String'(Super_Slice (Super_Head'Result,
Super_Length (Source) + 1, Count)) =
- (1 .. Count - Super_Length (Source) => Pad),
+ [1 .. Count - Super_Length (Source) => Pad],
Count > Source.Max_Length and then Drop = Right
=>
-- Source is followed by Pad characters
@@ -2334,13 +2334,13 @@ package Ada.Strings.Superbounded with SPARK_Mode is
and then
String'(Super_Slice (Super_Head'Result,
Super_Length (Source) + 1, Source.Max_Length)) =
- (1 .. Source.Max_Length - Super_Length (Source) => Pad),
+ [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),
+ [1 .. Source.Max_Length => Pad],
others
=>
-- Source is partly dropped on the left
@@ -2355,7 +2355,7 @@ package Ada.Strings.Superbounded with SPARK_Mode is
String'(Super_Slice (Super_Head'Result,
Source.Max_Length - Count + Super_Length (Source) + 1,
Source.Max_Length)) =
- (1 .. Count - Super_Length (Source) => Pad)),
+ [1 .. Count - Super_Length (Source) => Pad]),
Global => null;
procedure Super_Head
@@ -2382,7 +2382,7 @@ package Ada.Strings.Superbounded with SPARK_Mode is
and then
String'(Super_Slice (Source,
Super_Length (Source'Old) + 1, Count)) =
- (1 .. Count - Super_Length (Source'Old) => Pad),
+ [1 .. Count - Super_Length (Source'Old) => Pad],
Count > Source.Max_Length and then Drop = Right
=>
-- Source is followed by Pad characters
@@ -2394,12 +2394,12 @@ package Ada.Strings.Superbounded with SPARK_Mode is
and then
String'(Super_Slice (Source,
Super_Length (Source'Old) + 1, Source.Max_Length)) =
- (1 .. Source.Max_Length - Super_Length (Source'Old) => Pad),
+ [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),
+ Super_To_String (Source) = [1 .. Source.Max_Length => Pad],
others
=>
-- Source is partly dropped on the left
@@ -2414,7 +2414,7 @@ package Ada.Strings.Superbounded with SPARK_Mode is
String'(Super_Slice (Source,
Source.Max_Length - Count + Super_Length (Source'Old) + 1,
Source.Max_Length)) =
- (1 .. Count - Super_Length (Source'Old) => Pad)),
+ [1 .. Count - Super_Length (Source'Old) => Pad]),
Global => null;
function Super_Tail
@@ -2443,7 +2443,7 @@ package Ada.Strings.Superbounded with SPARK_Mode is
and then
String'(Super_Slice (Super_Tail'Result,
1, Count - Super_Length (Source))) =
- (1 .. Count - Super_Length (Source) => Pad)
+ [1 .. Count - Super_Length (Source) => Pad]
and then
Super_Slice (Super_Tail'Result,
Count - Super_Length (Source) + 1, Count) =
@@ -2456,7 +2456,7 @@ package Ada.Strings.Superbounded with SPARK_Mode is
and then
String'(Super_Slice (Super_Tail'Result,
1, Source.Max_Length - Super_Length (Source))) =
- (1 .. Source.Max_Length - Super_Length (Source) => Pad)
+ [1 .. Source.Max_Length - Super_Length (Source) => Pad]
and then
(if Super_Length (Source) > 0 then
Super_Slice (Super_Tail'Result,
@@ -2469,7 +2469,7 @@ package Ada.Strings.Superbounded with SPARK_Mode is
-- Source is fully dropped on the right
Super_To_String (Super_Tail'Result) =
- (1 .. Source.Max_Length => Pad),
+ [1 .. Source.Max_Length => Pad],
others
=>
-- Source is partly dropped on the right
@@ -2478,7 +2478,7 @@ package Ada.Strings.Superbounded with SPARK_Mode is
and then
String'(Super_Slice (Super_Tail'Result,
1, Count - Super_Length (Source))) =
- (1 .. Count - Super_Length (Source) => Pad)
+ [1 .. Count - Super_Length (Source) => Pad]
and then
String'(Super_Slice (Super_Tail'Result,
Count - Super_Length (Source) + 1, Source.Max_Length)) =
@@ -2512,7 +2512,7 @@ package Ada.Strings.Superbounded with SPARK_Mode is
and then
String'(Super_Slice (Source,
1, Count - Super_Length (Source'Old))) =
- (1 .. Count - Super_Length (Source'Old) => Pad)
+ [1 .. Count - Super_Length (Source'Old) => Pad]
and then
Super_Slice (Source,
Count - Super_Length (Source'Old) + 1, Count) =
@@ -2525,7 +2525,7 @@ package Ada.Strings.Superbounded with SPARK_Mode is
and then
String'(Super_Slice (Source,
1, Source.Max_Length - Super_Length (Source'Old))) =
- (1 .. Source.Max_Length - Super_Length (Source'Old) => Pad)
+ [1 .. Source.Max_Length - Super_Length (Source'Old) => Pad]
and then
(if Super_Length (Source'Old) > 0 then
Super_Slice (Source,
@@ -2537,7 +2537,7 @@ package Ada.Strings.Superbounded with SPARK_Mode is
=>
-- Source is fully dropped on the right
- Super_To_String (Source) = (1 .. Source.Max_Length => Pad),
+ Super_To_String (Source) = [1 .. Source.Max_Length => Pad],
others
=>
-- Source is partly dropped on the right
@@ -2546,7 +2546,7 @@ package Ada.Strings.Superbounded with SPARK_Mode is
and then
String'(Super_Slice (Source,
1, Count - Super_Length (Source'Old))) =
- (1 .. Count - Super_Length (Source'Old) => Pad)
+ [1 .. Count - Super_Length (Source'Old) => Pad]
and then
String'(Super_Slice (Source,
Count - Super_Length (Source'Old) + 1, Source.Max_Length)) =
@@ -2569,7 +2569,7 @@ package Ada.Strings.Superbounded with SPARK_Mode is
with
Pre => Left <= Max_Length,
Post => Times'Result.Max_Length = Max_Length
- and then Super_To_String (Times'Result) = (1 .. Left => Right),
+ and then Super_To_String (Times'Result) = [1 .. Left => Right],
Global => null;
-- Note the additional parameter Max_Length
@@ -2613,7 +2613,7 @@ package Ada.Strings.Superbounded with SPARK_Mode is
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),
+ [1 .. Natural'Min (Max_Length, Count) => Item],
Global => null;
-- Note the additional parameter Max_Length
diff --git a/gcc/ada/libgnat/a-sttebu.adb b/gcc/ada/libgnat/a-sttebu.adb
index bc0c6ce..f86a969 100644
--- a/gcc/ada/libgnat/a-sttebu.adb
+++ b/gcc/ada/libgnat/a-sttebu.adb
@@ -94,7 +94,7 @@ package body Ada.Strings.Text_Buffers is
Buffer.Indent_Pending := False;
if Buffer.Indentation > 0 then
Put_UTF_8_Implementation
- (Buffer, (1 .. Buffer.Indentation => ' '));
+ (Buffer, [1 .. Buffer.Indentation => ' ']);
end if;
end if;
@@ -111,7 +111,7 @@ package body Ada.Strings.Text_Buffers is
procedure New_Line (Buffer : in out Buffer_Type) is
begin
Buffer.Indent_Pending := False; -- just for a moment
- Put (Buffer, (1 => ASCII.LF));
+ Put (Buffer, [ASCII.LF]);
Buffer.Indent_Pending := True;
Buffer.UTF_8_Column := 1;
end New_Line;
diff --git a/gcc/ada/libgnat/a-stuten.ads b/gcc/ada/libgnat/a-stuten.ads
index fba30df..209c84a 100644
--- a/gcc/ada/libgnat/a-stuten.ads
+++ b/gcc/ada/libgnat/a-stuten.ads
@@ -94,7 +94,7 @@ package Ada.Strings.UTF_Encoding is
Character'Val (16#FE#);
BOM_16 : constant UTF_16_Wide_String :=
- (1 => Wide_Character'Val (16#FEFF#));
+ [Wide_Character'Val (16#FEFF#)];
function Encoding
(Item : UTF_String;
diff --git a/gcc/ada/libgnat/a-stwibo.ads b/gcc/ada/libgnat/a-stwibo.ads
index 9b3d0ad..1ddb83a 100644
--- a/gcc/ada/libgnat/a-stwibo.ads
+++ b/gcc/ada/libgnat/a-stwibo.ads
@@ -487,8 +487,8 @@ package Ada.Strings.Wide_Bounded is
(Max_Length => Max_Length,
Current_Length => 0,
Data =>
- (1 .. Max_Length =>
- Wide_Superbounded.Wide_NUL));
+ [1 .. Max_Length =>
+ Wide_Superbounded.Wide_NUL]);
pragma Inline (To_Bounded_Wide_String);
diff --git a/gcc/ada/libgnat/a-stwima.ads b/gcc/ada/libgnat/a-stwima.ads
index fba510a..6b5765f 100644
--- a/gcc/ada/libgnat/a-stwima.ads
+++ b/gcc/ada/libgnat/a-stwima.ads
@@ -181,8 +181,7 @@ private
overriding procedure Adjust (Object : in out Wide_Character_Set);
overriding procedure Finalize (Object : in out Wide_Character_Set);
- Null_Range : aliased constant Wide_Character_Ranges :=
- (1 .. 0 => (Low => ' ', High => ' '));
+ Null_Range : aliased constant Wide_Character_Ranges := [];
Null_Set : constant Wide_Character_Set :=
(AF.Controlled with
diff --git a/gcc/ada/libgnat/a-stwisu.adb b/gcc/ada/libgnat/a-stwisu.adb
index b81be14..302bf0f 100644
--- a/gcc/ada/libgnat/a-stwisu.adb
+++ b/gcc/ada/libgnat/a-stwisu.adb
@@ -852,7 +852,7 @@ package body Ada.Strings.Wide_Superbounded is
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.Data (Slen + 1 .. Count) := [others => Pad];
else
Result.Current_Length := Max_Length;
@@ -860,17 +860,17 @@ package body Ada.Strings.Wide_Superbounded is
case Drop is
when Strings.Right =>
Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
- Result.Data (Slen + 1 .. Max_Length) := (others => Pad);
+ Result.Data (Slen + 1 .. Max_Length) := [others => Pad];
when Strings.Left =>
if Npad >= Max_Length then
- Result.Data := (others => Pad);
+ Result.Data := [others => Pad];
else
Result.Data (1 .. Max_Length - Npad) :=
Source.Data (Count - Max_Length + 1 .. Slen);
Result.Data (Max_Length - Npad + 1 .. Max_Length) :=
- (others => Pad);
+ [others => Pad];
end if;
when Strings.Error =>
@@ -898,18 +898,18 @@ package body Ada.Strings.Wide_Superbounded is
elsif Count <= Max_Length then
Source.Current_Length := Count;
- Source.Data (Slen + 1 .. Count) := (others => Pad);
+ Source.Data (Slen + 1 .. Count) := [others => Pad];
else
Source.Current_Length := Max_Length;
case Drop is
when Strings.Right =>
- Source.Data (Slen + 1 .. Max_Length) := (others => Pad);
+ Source.Data (Slen + 1 .. Max_Length) := [others => Pad];
when Strings.Left =>
if Npad > Max_Length then
- Source.Data := (others => Pad);
+ Source.Data := [others => Pad];
else
Temp := Source.Data;
@@ -1386,7 +1386,7 @@ package body Ada.Strings.Wide_Superbounded is
Result.Current_Length := Max_Length;
end if;
- Result.Data (1 .. Result.Current_Length) := (others => Item);
+ Result.Data (1 .. Result.Current_Length) := [others => Item];
return Result;
end Super_Replicate;
@@ -1542,7 +1542,7 @@ package body Ada.Strings.Wide_Superbounded is
elsif Count <= Max_Length then
Result.Current_Length := Count;
- Result.Data (1 .. Npad) := (others => Pad);
+ Result.Data (1 .. Npad) := [others => Pad];
Result.Data (Npad + 1 .. Count) := Source.Data (1 .. Slen);
else
@@ -1551,16 +1551,16 @@ package body Ada.Strings.Wide_Superbounded is
case Drop is
when Strings.Right =>
if Npad >= Max_Length then
- Result.Data := (others => Pad);
+ Result.Data := [others => Pad];
else
- Result.Data (1 .. Npad) := (others => Pad);
+ Result.Data (1 .. Npad) := [others => Pad];
Result.Data (Npad + 1 .. Max_Length) :=
Source.Data (1 .. Max_Length - Npad);
end if;
when Strings.Left =>
- Result.Data (1 .. Max_Length - Slen) := (others => Pad);
+ Result.Data (1 .. Max_Length - Slen) := [others => Pad];
Result.Data (Max_Length - Slen + 1 .. Max_Length) :=
Source.Data (1 .. Slen);
@@ -1592,7 +1592,7 @@ package body Ada.Strings.Wide_Superbounded is
elsif Count <= Max_Length then
Source.Current_Length := Count;
- Source.Data (1 .. Npad) := (others => Pad);
+ Source.Data (1 .. Npad) := [others => Pad];
Source.Data (Npad + 1 .. Count) := Temp (1 .. Slen);
else
@@ -1601,10 +1601,10 @@ package body Ada.Strings.Wide_Superbounded is
case Drop is
when Strings.Right =>
if Npad >= Max_Length then
- Source.Data := (others => Pad);
+ Source.Data := [others => Pad];
else
- Source.Data (1 .. Npad) := (others => Pad);
+ Source.Data (1 .. Npad) := [others => Pad];
Source.Data (Npad + 1 .. Max_Length) :=
Temp (1 .. Max_Length - Npad);
end if;
@@ -1744,7 +1744,7 @@ package body Ada.Strings.Wide_Superbounded is
end loop;
end if;
- Source.Data := (others => Wide_NUL);
+ Source.Data := [others => Wide_NUL];
Source.Current_Length := Last - First + 1;
Source.Data (1 .. Source.Current_Length) := Temp (First .. Last);
end Super_Trim;
diff --git a/gcc/ada/libgnat/a-stzbou.ads b/gcc/ada/libgnat/a-stzbou.ads
index d49d577..ae45e7c 100644
--- a/gcc/ada/libgnat/a-stzbou.ads
+++ b/gcc/ada/libgnat/a-stzbou.ads
@@ -493,11 +493,11 @@ package Ada.Strings.Wide_Wide_Bounded is
-- the Wide_Wide_Superbounded package.
Null_Bounded_Wide_Wide_String : constant Bounded_Wide_Wide_String :=
- (Max_Length => Max_Length,
+ [Max_Length => Max_Length,
Current_Length => 0,
Data =>
- (1 .. Max_Length =>
- Wide_Wide_Superbounded.Wide_Wide_NUL));
+ [1 .. Max_Length =>
+ Wide_Wide_Superbounded.Wide_Wide_NUL]];
pragma Inline (To_Bounded_Wide_Wide_String);
diff --git a/gcc/ada/libgnat/a-stzmap.ads b/gcc/ada/libgnat/a-stzmap.ads
index 14650da..86ee971 100644
--- a/gcc/ada/libgnat/a-stzmap.ads
+++ b/gcc/ada/libgnat/a-stzmap.ads
@@ -183,8 +183,7 @@ private
procedure Adjust (Object : in out Wide_Wide_Character_Set);
procedure Finalize (Object : in out Wide_Wide_Character_Set);
- Null_Range : aliased constant Wide_Wide_Character_Ranges :=
- (1 .. 0 => (Low => ' ', High => ' '));
+ Null_Range : aliased constant Wide_Wide_Character_Ranges := [];
Null_Set : constant Wide_Wide_Character_Set :=
(AF.Controlled with
diff --git a/gcc/ada/libgnat/a-stzsup.adb b/gcc/ada/libgnat/a-stzsup.adb
index 92790a1..6799797 100644
--- a/gcc/ada/libgnat/a-stzsup.adb
+++ b/gcc/ada/libgnat/a-stzsup.adb
@@ -853,7 +853,7 @@ package body Ada.Strings.Wide_Wide_Superbounded is
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.Data (Slen + 1 .. Count) := [others => Pad];
else
Result.Current_Length := Max_Length;
@@ -861,17 +861,17 @@ package body Ada.Strings.Wide_Wide_Superbounded is
case Drop is
when Strings.Right =>
Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
- Result.Data (Slen + 1 .. Max_Length) := (others => Pad);
+ Result.Data (Slen + 1 .. Max_Length) := [others => Pad];
when Strings.Left =>
if Npad >= Max_Length then
- Result.Data := (others => Pad);
+ Result.Data := [others => Pad];
else
Result.Data (1 .. Max_Length - Npad) :=
Source.Data (Count - Max_Length + 1 .. Slen);
Result.Data (Max_Length - Npad + 1 .. Max_Length) :=
- (others => Pad);
+ [others => Pad];
end if;
when Strings.Error =>
@@ -899,18 +899,18 @@ package body Ada.Strings.Wide_Wide_Superbounded is
elsif Count <= Max_Length then
Source.Current_Length := Count;
- Source.Data (Slen + 1 .. Count) := (others => Pad);
+ Source.Data (Slen + 1 .. Count) := [others => Pad];
else
Source.Current_Length := Max_Length;
case Drop is
when Strings.Right =>
- Source.Data (Slen + 1 .. Max_Length) := (others => Pad);
+ Source.Data (Slen + 1 .. Max_Length) := [others => Pad];
when Strings.Left =>
if Npad > Max_Length then
- Source.Data := (others => Pad);
+ Source.Data := [others => Pad];
else
Temp := Source.Data;
@@ -1389,7 +1389,7 @@ package body Ada.Strings.Wide_Wide_Superbounded is
Result.Current_Length := Max_Length;
end if;
- Result.Data (1 .. Result.Current_Length) := (others => Item);
+ Result.Data (1 .. Result.Current_Length) := [others => Item];
return Result;
end Super_Replicate;
@@ -1546,7 +1546,7 @@ package body Ada.Strings.Wide_Wide_Superbounded is
elsif Count <= Max_Length then
Result.Current_Length := Count;
- Result.Data (1 .. Npad) := (others => Pad);
+ Result.Data (1 .. Npad) := [others => Pad];
Result.Data (Npad + 1 .. Count) := Source.Data (1 .. Slen);
else
@@ -1555,16 +1555,16 @@ package body Ada.Strings.Wide_Wide_Superbounded is
case Drop is
when Strings.Right =>
if Npad >= Max_Length then
- Result.Data := (others => Pad);
+ Result.Data := [others => Pad];
else
- Result.Data (1 .. Npad) := (others => Pad);
+ Result.Data (1 .. Npad) := [others => Pad];
Result.Data (Npad + 1 .. Max_Length) :=
Source.Data (1 .. Max_Length - Npad);
end if;
when Strings.Left =>
- Result.Data (1 .. Max_Length - Slen) := (others => Pad);
+ Result.Data (1 .. Max_Length - Slen) := [others => Pad];
Result.Data (Max_Length - Slen + 1 .. Max_Length) :=
Source.Data (1 .. Slen);
@@ -1596,7 +1596,7 @@ package body Ada.Strings.Wide_Wide_Superbounded is
elsif Count <= Max_Length then
Source.Current_Length := Count;
- Source.Data (1 .. Npad) := (others => Pad);
+ Source.Data (1 .. Npad) := [others => Pad];
Source.Data (Npad + 1 .. Count) := Temp (1 .. Slen);
else
@@ -1605,10 +1605,10 @@ package body Ada.Strings.Wide_Wide_Superbounded is
case Drop is
when Strings.Right =>
if Npad >= Max_Length then
- Source.Data := (others => Pad);
+ Source.Data := [others => Pad];
else
- Source.Data (1 .. Npad) := (others => Pad);
+ Source.Data (1 .. Npad) := [others => Pad];
Source.Data (Npad + 1 .. Max_Length) :=
Temp (1 .. Max_Length - Npad);
end if;
@@ -1752,7 +1752,7 @@ package body Ada.Strings.Wide_Wide_Superbounded is
end loop;
end if;
- Source.Data := (others => Wide_Wide_NUL);
+ Source.Data := [others => Wide_Wide_NUL];
Source.Current_Length := Last - First + 1;
Source.Data (1 .. Source.Current_Length) := Temp (First .. Last);
end Super_Trim;
diff --git a/gcc/ada/libgnat/a-swmwco.ads b/gcc/ada/libgnat/a-swmwco.ads
index 0f92502..2e2ab44 100644
--- a/gcc/ada/libgnat/a-swmwco.ads
+++ b/gcc/ada/libgnat/a-swmwco.ads
@@ -66,52 +66,52 @@ private
subtype WC is Wide_Character;
Control_Ranges : aliased constant Wide_Character_Ranges :=
- ((W.NUL, W.US),
- (W.DEL, W.APC));
+ [ (W.NUL, W.US),
+ (W.DEL, W.APC)];
Control_Set : constant Wide_Character_Set :=
(AF.Controlled with
Control_Ranges'Unrestricted_Access);
Graphic_Ranges : aliased constant Wide_Character_Ranges :=
- ((W.Space, W.Tilde),
- (WC'Val (256), WC'Last));
+ [ (W.Space, W.Tilde),
+ (WC'Val (256), WC'Last)];
Graphic_Set : constant Wide_Character_Set :=
(AF.Controlled with
Graphic_Ranges'Unrestricted_Access);
Letter_Ranges : aliased constant Wide_Character_Ranges :=
- (('A', 'Z'),
- (W.LC_A, W.LC_Z),
- (W.UC_A_Grave, W.UC_O_Diaeresis),
- (W.UC_O_Oblique_Stroke, W.LC_O_Diaeresis),
- (W.LC_O_Oblique_Stroke, W.LC_Y_Diaeresis));
+ [ ('A', 'Z'),
+ (W.LC_A, W.LC_Z),
+ (W.UC_A_Grave, W.UC_O_Diaeresis),
+ (W.UC_O_Oblique_Stroke, W.LC_O_Diaeresis),
+ (W.LC_O_Oblique_Stroke, W.LC_Y_Diaeresis)];
Letter_Set : constant Wide_Character_Set :=
(AF.Controlled with
Letter_Ranges'Unrestricted_Access);
Lower_Ranges : aliased constant Wide_Character_Ranges :=
- (1 => (W.LC_A, W.LC_Z),
+ [1 => (W.LC_A, W.LC_Z),
2 => (W.LC_German_Sharp_S, W.LC_O_Diaeresis),
- 3 => (W.LC_O_Oblique_Stroke, W.LC_Y_Diaeresis));
+ 3 => (W.LC_O_Oblique_Stroke, W.LC_Y_Diaeresis)];
Lower_Set : constant Wide_Character_Set :=
(AF.Controlled with
Lower_Ranges'Unrestricted_Access);
Upper_Ranges : aliased constant Wide_Character_Ranges :=
- (1 => ('A', 'Z'),
+ [1 => ('A', 'Z'),
2 => (W.UC_A_Grave, W.UC_O_Diaeresis),
- 3 => (W.UC_O_Oblique_Stroke, W.UC_Icelandic_Thorn));
+ 3 => (W.UC_O_Oblique_Stroke, W.UC_Icelandic_Thorn)];
Upper_Set : constant Wide_Character_Set :=
(AF.Controlled with
Upper_Ranges'Unrestricted_Access);
Basic_Ranges : aliased constant Wide_Character_Ranges :=
- (1 => ('A', 'Z'),
+ [1 => ('A', 'Z'),
2 => (W.LC_A, W.LC_Z),
3 => (W.UC_AE_Diphthong, W.UC_AE_Diphthong),
4 => (W.LC_AE_Diphthong, W.LC_AE_Diphthong),
@@ -119,69 +119,69 @@ private
6 => (W.UC_Icelandic_Thorn, W.UC_Icelandic_Thorn),
7 => (W.LC_Icelandic_Thorn, W.LC_Icelandic_Thorn),
8 => (W.UC_Icelandic_Eth, W.UC_Icelandic_Eth),
- 9 => (W.LC_Icelandic_Eth, W.LC_Icelandic_Eth));
+ 9 => (W.LC_Icelandic_Eth, W.LC_Icelandic_Eth)];
Basic_Set : constant Wide_Character_Set :=
(AF.Controlled with
Basic_Ranges'Unrestricted_Access);
Decimal_Digit_Ranges : aliased constant Wide_Character_Ranges :=
- (1 => ('0', '9'));
+ [ ('0', '9')];
Decimal_Digit_Set : constant Wide_Character_Set :=
(AF.Controlled with
Decimal_Digit_Ranges'Unrestricted_Access);
Hexadecimal_Digit_Ranges : aliased constant Wide_Character_Ranges :=
- (1 => ('0', '9'),
+ [1 => ('0', '9'),
2 => ('A', 'F'),
- 3 => (W.LC_A, W.LC_F));
+ 3 => (W.LC_A, W.LC_F)];
Hexadecimal_Digit_Set : constant Wide_Character_Set :=
(AF.Controlled with
Hexadecimal_Digit_Ranges'Unrestricted_Access);
Alphanumeric_Ranges : aliased constant Wide_Character_Ranges :=
- (1 => ('0', '9'),
+ [1 => ('0', '9'),
2 => ('A', 'Z'),
3 => (W.LC_A, W.LC_Z),
4 => (W.UC_A_Grave, W.UC_O_Diaeresis),
5 => (W.UC_O_Oblique_Stroke, W.LC_O_Diaeresis),
- 6 => (W.LC_O_Oblique_Stroke, W.LC_Y_Diaeresis));
+ 6 => (W.LC_O_Oblique_Stroke, W.LC_Y_Diaeresis)];
Alphanumeric_Set : constant Wide_Character_Set :=
(AF.Controlled with
Alphanumeric_Ranges'Unrestricted_Access);
Special_Graphic_Ranges : aliased constant Wide_Character_Ranges :=
- (1 => (Wide_Space, W.Solidus),
+ [1 => (Wide_Space, W.Solidus),
2 => (W.Colon, W.Commercial_At),
3 => (W.Left_Square_Bracket, W.Grave),
4 => (W.Left_Curly_Bracket, W.Tilde),
5 => (W.No_Break_Space, W.Inverted_Question),
6 => (W.Multiplication_Sign, W.Multiplication_Sign),
- 7 => (W.Division_Sign, W.Division_Sign));
+ 7 => (W.Division_Sign, W.Division_Sign)];
Special_Graphic_Set : constant Wide_Character_Set :=
(AF.Controlled with
Special_Graphic_Ranges'Unrestricted_Access);
ISO_646_Ranges : aliased constant Wide_Character_Ranges :=
- (1 => (W.NUL, W.DEL));
+ [ (W.NUL, W.DEL)];
ISO_646_Set : constant Wide_Character_Set :=
(AF.Controlled with
ISO_646_Ranges'Unrestricted_Access);
Character_Ranges : aliased constant Wide_Character_Ranges :=
- (1 => (W.NUL, WC'Val (255)));
+ [ (W.NUL, WC'Val (255))];
Character_Set : constant Wide_Character_Set :=
(AF.Controlled with
Character_Ranges'Unrestricted_Access);
Lower_Case_Mapping : aliased constant Wide_Character_Mapping_Values :=
- (Length => 56,
+ [Length => 56,
Domain =>
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" &
@@ -247,14 +247,14 @@ private
W.LC_U_Circumflex &
W.LC_U_Diaeresis &
W.LC_Y_Acute &
- W.LC_Icelandic_Thorn);
+ W.LC_Icelandic_Thorn];
Lower_Case_Map : constant Wide_Character_Mapping :=
(AF.Controlled with
Map => Lower_Case_Mapping'Unrestricted_Access);
Upper_Case_Mapping : aliased constant Wide_Character_Mapping_Values :=
- (Length => 56,
+ [Length => 56,
Domain =>
"abcdefghijklmnopqrstuvwxyz" &
@@ -320,14 +320,14 @@ private
W.UC_U_Circumflex &
W.UC_U_Diaeresis &
W.UC_Y_Acute &
- W.UC_Icelandic_Thorn);
+ W.UC_Icelandic_Thorn];
Upper_Case_Map : constant Wide_Character_Mapping :=
(AF.Controlled with
Upper_Case_Mapping'Unrestricted_Access);
Basic_Mapping : aliased constant Wide_Character_Mapping_Values :=
- (Length => 55,
+ [Length => 55,
Domain =>
W.UC_A_Grave &
@@ -441,7 +441,7 @@ private
'u' & -- LC_U_Circumflex
'u' & -- LC_U_Diaeresis
'y' & -- LC_Y_Acute
- 'y'); -- LC_Y_Diaeresis
+ 'y']; -- LC_Y_Diaeresis
Basic_Map : constant Wide_Character_Mapping :=
(AF.Controlled with
diff --git a/gcc/ada/libgnat/a-szmzco.ads b/gcc/ada/libgnat/a-szmzco.ads
index 82f0a6b..a5b8afc 100644
--- a/gcc/ada/libgnat/a-szmzco.ads
+++ b/gcc/ada/libgnat/a-szmzco.ads
@@ -66,52 +66,52 @@ private
subtype WC is Wide_Wide_Character;
Control_Ranges : aliased constant Wide_Wide_Character_Ranges :=
- ((W.NUL, W.US),
- (W.DEL, W.APC));
+ [ (W.NUL, W.US),
+ (W.DEL, W.APC)];
Control_Set : constant Wide_Wide_Character_Set :=
(AF.Controlled with
Control_Ranges'Unrestricted_Access);
Graphic_Ranges : aliased constant Wide_Wide_Character_Ranges :=
- ((W.Space, W.Tilde),
- (WC'Val (256), WC'Last));
+ [ (W.Space, W.Tilde),
+ (WC'Val (256), WC'Last)];
Graphic_Set : constant Wide_Wide_Character_Set :=
(AF.Controlled with
Graphic_Ranges'Unrestricted_Access);
Letter_Ranges : aliased constant Wide_Wide_Character_Ranges :=
- (('A', 'Z'),
- (W.LC_A, W.LC_Z),
- (W.UC_A_Grave, W.UC_O_Diaeresis),
- (W.UC_O_Oblique_Stroke, W.LC_O_Diaeresis),
- (W.LC_O_Oblique_Stroke, W.LC_Y_Diaeresis));
+ [ ('A', 'Z'),
+ (W.LC_A, W.LC_Z),
+ (W.UC_A_Grave, W.UC_O_Diaeresis),
+ (W.UC_O_Oblique_Stroke, W.LC_O_Diaeresis),
+ (W.LC_O_Oblique_Stroke, W.LC_Y_Diaeresis)];
Letter_Set : constant Wide_Wide_Character_Set :=
(AF.Controlled with
Letter_Ranges'Unrestricted_Access);
Lower_Ranges : aliased constant Wide_Wide_Character_Ranges :=
- (1 => (W.LC_A, W.LC_Z),
+ [1 => (W.LC_A, W.LC_Z),
2 => (W.LC_German_Sharp_S, W.LC_O_Diaeresis),
- 3 => (W.LC_O_Oblique_Stroke, W.LC_Y_Diaeresis));
+ 3 => (W.LC_O_Oblique_Stroke, W.LC_Y_Diaeresis)];
Lower_Set : constant Wide_Wide_Character_Set :=
(AF.Controlled with
Lower_Ranges'Unrestricted_Access);
Upper_Ranges : aliased constant Wide_Wide_Character_Ranges :=
- (1 => ('A', 'Z'),
+ [1 => ('A', 'Z'),
2 => (W.UC_A_Grave, W.UC_O_Diaeresis),
- 3 => (W.UC_O_Oblique_Stroke, W.UC_Icelandic_Thorn));
+ 3 => (W.UC_O_Oblique_Stroke, W.UC_Icelandic_Thorn)];
Upper_Set : constant Wide_Wide_Character_Set :=
(AF.Controlled with
Upper_Ranges'Unrestricted_Access);
Basic_Ranges : aliased constant Wide_Wide_Character_Ranges :=
- (1 => ('A', 'Z'),
+ [1 => ('A', 'Z'),
2 => (W.LC_A, W.LC_Z),
3 => (W.UC_AE_Diphthong, W.UC_AE_Diphthong),
4 => (W.LC_AE_Diphthong, W.LC_AE_Diphthong),
@@ -119,69 +119,69 @@ private
6 => (W.UC_Icelandic_Thorn, W.UC_Icelandic_Thorn),
7 => (W.LC_Icelandic_Thorn, W.LC_Icelandic_Thorn),
8 => (W.UC_Icelandic_Eth, W.UC_Icelandic_Eth),
- 9 => (W.LC_Icelandic_Eth, W.LC_Icelandic_Eth));
+ 9 => (W.LC_Icelandic_Eth, W.LC_Icelandic_Eth)];
Basic_Set : constant Wide_Wide_Character_Set :=
(AF.Controlled with
Basic_Ranges'Unrestricted_Access);
Decimal_Digit_Ranges : aliased constant Wide_Wide_Character_Ranges :=
- (1 => ('0', '9'));
+ [ ('0', '9')];
Decimal_Digit_Set : constant Wide_Wide_Character_Set :=
(AF.Controlled with
Decimal_Digit_Ranges'Unrestricted_Access);
Hexadecimal_Digit_Ranges : aliased constant Wide_Wide_Character_Ranges :=
- (1 => ('0', '9'),
+ [1 => ('0', '9'),
2 => ('A', 'F'),
- 3 => (W.LC_A, W.LC_F));
+ 3 => (W.LC_A, W.LC_F)];
Hexadecimal_Digit_Set : constant Wide_Wide_Character_Set :=
(AF.Controlled with
Hexadecimal_Digit_Ranges'Unrestricted_Access);
Alphanumeric_Ranges : aliased constant Wide_Wide_Character_Ranges :=
- (1 => ('0', '9'),
+ [1 => ('0', '9'),
2 => ('A', 'Z'),
3 => (W.LC_A, W.LC_Z),
4 => (W.UC_A_Grave, W.UC_O_Diaeresis),
5 => (W.UC_O_Oblique_Stroke, W.LC_O_Diaeresis),
- 6 => (W.LC_O_Oblique_Stroke, W.LC_Y_Diaeresis));
+ 6 => (W.LC_O_Oblique_Stroke, W.LC_Y_Diaeresis)];
Alphanumeric_Set : constant Wide_Wide_Character_Set :=
(AF.Controlled with
Alphanumeric_Ranges'Unrestricted_Access);
Special_Graphic_Ranges : aliased constant Wide_Wide_Character_Ranges :=
- (1 => (Wide_Wide_Space, W.Solidus),
+ [1 => (Wide_Wide_Space, W.Solidus),
2 => (W.Colon, W.Commercial_At),
3 => (W.Left_Square_Bracket, W.Grave),
4 => (W.Left_Curly_Bracket, W.Tilde),
5 => (W.No_Break_Space, W.Inverted_Question),
6 => (W.Multiplication_Sign, W.Multiplication_Sign),
- 7 => (W.Division_Sign, W.Division_Sign));
+ 7 => (W.Division_Sign, W.Division_Sign)];
Special_Graphic_Set : constant Wide_Wide_Character_Set :=
(AF.Controlled with
Special_Graphic_Ranges'Unrestricted_Access);
ISO_646_Ranges : aliased constant Wide_Wide_Character_Ranges :=
- (1 => (W.NUL, W.DEL));
+ [ (W.NUL, W.DEL)];
ISO_646_Set : constant Wide_Wide_Character_Set :=
(AF.Controlled with
ISO_646_Ranges'Unrestricted_Access);
Character_Ranges : aliased constant Wide_Wide_Character_Ranges :=
- (1 => (W.NUL, WC'Val (255)));
+ [ (W.NUL, WC'Val (255))];
Character_Set : constant Wide_Wide_Character_Set :=
(AF.Controlled with
Character_Ranges'Unrestricted_Access);
Lower_Case_Mapping : aliased constant Wide_Wide_Character_Mapping_Values :=
- (Length => 56,
+ [Length => 56,
Domain =>
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" &
@@ -247,14 +247,14 @@ private
W.LC_U_Circumflex &
W.LC_U_Diaeresis &
W.LC_Y_Acute &
- W.LC_Icelandic_Thorn);
+ W.LC_Icelandic_Thorn];
Lower_Case_Map : constant Wide_Wide_Character_Mapping :=
(AF.Controlled with
Map => Lower_Case_Mapping'Unrestricted_Access);
Upper_Case_Mapping : aliased constant Wide_Wide_Character_Mapping_Values :=
- (Length => 56,
+ [Length => 56,
Domain =>
"abcdefghijklmnopqrstuvwxyz" &
@@ -320,14 +320,14 @@ private
W.UC_U_Circumflex &
W.UC_U_Diaeresis &
W.UC_Y_Acute &
- W.UC_Icelandic_Thorn);
+ W.UC_Icelandic_Thorn];
Upper_Case_Map : constant Wide_Wide_Character_Mapping :=
(AF.Controlled with
Upper_Case_Mapping'Unrestricted_Access);
Basic_Mapping : aliased constant Wide_Wide_Character_Mapping_Values :=
- (Length => 55,
+ [Length => 55,
Domain =>
W.UC_A_Grave &
@@ -441,7 +441,7 @@ private
'u' & -- LC_U_Circumflex
'u' & -- LC_U_Diaeresis
'y' & -- LC_Y_Acute
- 'y'); -- LC_Y_Diaeresis
+ 'y']; -- LC_Y_Diaeresis
Basic_Map : constant Wide_Wide_Character_Mapping :=
(AF.Controlled with
diff --git a/gcc/ada/libgnat/a-teioed.adb b/gcc/ada/libgnat/a-teioed.adb
index 6f198e5..36c73b8 100644
--- a/gcc/ada/libgnat/a-teioed.adb
+++ b/gcc/ada/libgnat/a-teioed.adb
@@ -279,13 +279,13 @@ package body Ada.Text_IO.Editing is
or else Pic.Start_Currency < Pic.Radix_Position
then
Answer (Pic.Start_Currency .. Pic.End_Currency) :=
- (others => ' ');
+ [others => ' '];
Answer (Pic.End_Currency - Currency_Symbol'Length + 1 ..
Pic.End_Currency) := Currency_Symbol;
else
Answer (Pic.Start_Currency .. Pic.End_Currency) :=
- (others => ' ');
+ [others => ' '];
Answer (Pic.Start_Currency ..
Pic.Start_Currency + Currency_Symbol'Length - 1) :=
Currency_Symbol;
diff --git a/gcc/ada/libgnat/a-wtedit.adb b/gcc/ada/libgnat/a-wtedit.adb
index 57ed1dd..e4e7bb0 100644
--- a/gcc/ada/libgnat/a-wtedit.adb
+++ b/gcc/ada/libgnat/a-wtedit.adb
@@ -450,13 +450,13 @@ package body Ada.Wide_Text_IO.Editing is
or else Pic.Start_Currency < Pic.Radix_Position
then
Answer (Pic.Start_Currency .. Pic.End_Currency) :=
- (others => ' ');
+ [others => ' '];
Answer (Pic.End_Currency - Currency_Symbol'Length + 1 ..
Pic.End_Currency) := Currency_Symbol;
else
Answer (Pic.Start_Currency .. Pic.End_Currency) :=
- (others => ' ');
+ [others => ' '];
Answer (Pic.Start_Currency ..
Pic.Start_Currency + Currency_Symbol'Length - 1) :=
Currency_Symbol;
diff --git a/gcc/ada/libgnat/a-ztedit.adb b/gcc/ada/libgnat/a-ztedit.adb
index b044621..41668de 100644
--- a/gcc/ada/libgnat/a-ztedit.adb
+++ b/gcc/ada/libgnat/a-ztedit.adb
@@ -451,13 +451,13 @@ package body Ada.Wide_Wide_Text_IO.Editing is
or else Pic.Start_Currency < Pic.Radix_Position
then
Answer (Pic.Start_Currency .. Pic.End_Currency) :=
- (others => ' ');
+ [others => ' '];
Answer (Pic.End_Currency - Currency_Symbol'Length + 1 ..
Pic.End_Currency) := Currency_Symbol;
else
Answer (Pic.Start_Currency .. Pic.End_Currency) :=
- (others => ' ');
+ [others => ' '];
Answer (Pic.Start_Currency ..
Pic.Start_Currency + Currency_Symbol'Length - 1) :=
Currency_Symbol;
diff --git a/gcc/ada/libgnat/g-arrspl.adb b/gcc/ada/libgnat/g-arrspl.adb
index 6a8518b..3c1f59a 100644
--- a/gcc/ada/libgnat/g-arrspl.adb
+++ b/gcc/ada/libgnat/g-arrspl.adb
@@ -181,20 +181,20 @@ package body GNAT.Array_Split is
then
-- Whole string, or no separator used
- return (Before => Array_End,
- After => Array_End);
+ return [Before => Array_End,
+ After => Array_End];
elsif Index = 1 then
- return (Before => Array_End,
- After => S.D.Source (S.D.Slices (Index).Stop + 1));
+ return [Before => Array_End,
+ After => S.D.Source (S.D.Slices (Index).Stop + 1)];
elsif Index = S.D.N_Slice then
- return (Before => S.D.Source (S.D.Slices (Index).Start - 1),
- After => Array_End);
+ return [Before => S.D.Source (S.D.Slices (Index).Start - 1),
+ After => Array_End];
else
- return (Before => S.D.Source (S.D.Slices (Index).Start - 1),
- After => S.D.Source (S.D.Slices (Index).Stop + 1));
+ return [Before => S.D.Source (S.D.Slices (Index).Start - 1),
+ After => S.D.Source (S.D.Slices (Index).Stop + 1)];
end if;
end Separators;
diff --git a/gcc/ada/libgnat/g-catiio.adb b/gcc/ada/libgnat/g-catiio.adb
index 462e0d2..1fdf151 100644
--- a/gcc/ada/libgnat/g-catiio.adb
+++ b/gcc/ada/libgnat/g-catiio.adb
@@ -627,8 +627,8 @@ package body GNAT.Calendar.Time_IO is
subtype String3 is String (1 .. 3);
Abbrev_Upper_Month_Names :
constant array (Ada.Calendar.Month_Number) of String3 :=
- ("JAN", "FEB", "MAR", "APR", "MAY", "JUN",
- "JUL", "AUG", "SEP", "OCT", "NOV", "DEC");
+ ["JAN", "FEB", "MAR", "APR", "MAY", "JUN",
+ "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"];
-- Short version of the month names, used when parsing date strings
S : String := Str;
diff --git a/gcc/ada/libgnat/g-cgideb.adb b/gcc/ada/libgnat/g-cgideb.adb
index f127ded..2527c9b 100644
--- a/gcc/ada/libgnat/g-cgideb.adb
+++ b/gcc/ada/libgnat/g-cgideb.adb
@@ -167,7 +167,7 @@ package body GNAT.CGI.Debug is
package body HTML_IO is
- NL : constant String := (1 => ASCII.LF);
+ NL : constant String := [ASCII.LF];
function Bold (S : String) return String;
-- Returns S as an HTML bold string
@@ -270,7 +270,7 @@ package body GNAT.CGI.Debug is
function Title (IO : Format; Str : String) return String is
Spaces : constant Natural := (80 - Str'Length) / 2;
- Indent : constant String (1 .. Spaces) := (others => ' ');
+ Indent : constant String (1 .. Spaces) := [others => ' '];
begin
return Indent & Str & New_Line (IO);
end Title;
diff --git a/gcc/ada/libgnat/g-comlin.adb b/gcc/ada/libgnat/g-comlin.adb
index 7f7040b..4cbfd57 100644
--- a/gcc/ada/libgnat/g-comlin.adb
+++ b/gcc/ada/libgnat/g-comlin.adb
@@ -1063,7 +1063,7 @@ package body GNAT.Command_Line is
Parser.In_Expansion := False;
Parser.Switch_Character := Switch_Char;
Parser.Stop_At_First := Stop_At_First_Non_Switch;
- Parser.Section := (others => 1);
+ Parser.Section := [others => 1];
-- If we are using sections, we have to preprocess the command line to
-- delimit them. A section can be repeated, so we just give each item
@@ -3225,7 +3225,7 @@ package body GNAT.Command_Line is
if N /= "" then
Put (" ");
Put (N);
- Put ((1 .. Max_Len - N'Length + 1 => ' '));
+ Put ([1 .. Max_Len - N'Length + 1 => ' ']);
if Config.Switches (S).Help /= null then
Put (Config.Switches (S).Help.all);
@@ -3243,8 +3243,8 @@ package body GNAT.Command_Line is
if Config.Aliases (A).Section.all = Section then
Put (" ");
Put (Config.Aliases (A).Alias.all);
- Put ((1 .. Max_Len - Config.Aliases (A).Alias'Length + 1
- => ' '));
+ Put ([1 .. Max_Len - Config.Aliases (A).Alias'Length + 1
+ => ' ']);
Put ("Equivalent to " & Config.Aliases (A).Expansion.all);
New_Line;
end if;
diff --git a/gcc/ada/libgnat/g-comlin.ads b/gcc/ada/libgnat/g-comlin.ads
index e5f493e..3738432 100644
--- a/gcc/ada/libgnat/g-comlin.ads
+++ b/gcc/ada/libgnat/g-comlin.ads
@@ -1097,11 +1097,11 @@ private
-- This type and this variable are provided to store the current switch
-- and parameter.
- Is_Switch : Is_Switch_Type (1 .. Arg_Count) := (others => False);
+ Is_Switch : Is_Switch_Type (1 .. Arg_Count) := [others => False];
-- Indicates wich arguments on the command line are considered not be
-- switches or parameters to switches (leaving e.g. filenames,...)
- Section : Section_Type (1 .. Arg_Count) := (others => 1);
+ Section : Section_Type (1 .. Arg_Count) := [others => 1];
-- Contains the number of the section associated with the current
-- switch. If this number is 0, then it is a section delimiter, which is
-- never returned by GetOpt.
diff --git a/gcc/ada/libgnat/g-debpoo.adb b/gcc/ada/libgnat/g-debpoo.adb
index 0092139..5d707ca 100644
--- a/gcc/ada/libgnat/g-debpoo.adb
+++ b/gcc/ada/libgnat/g-debpoo.adb
@@ -1148,7 +1148,7 @@ package body GNAT.Debug_Pools is
Modulo : constant Storage_Count :=
Size_In_Storage_Elements mod Dead_Bytes;
begin
- M.all := (others => Dead);
+ M.all := [others => Dead];
-- Any bytes left (up to three of them)
@@ -1942,7 +1942,7 @@ package body GNAT.Debug_Pools is
Grand_Total : Float;
Max : array (1 .. Size) of Traceback_Htable_Elem_Ptr :=
- (others => null);
+ [others => null];
-- Sorted array for the biggest memory users
Allocated_In_Pool : Byte_Count;
diff --git a/gcc/ada/libgnat/g-expect.adb b/gcc/ada/libgnat/g-expect.adb
index b945731..89ede30 100644
--- a/gcc/ada/libgnat/g-expect.adb
+++ b/gcc/ada/libgnat/g-expect.adb
@@ -351,7 +351,7 @@ package body GNAT.Expect is
Full_Buffer : Boolean := False)
is
N : Expect_Match;
- Descriptors : Array_Of_Pd := (1 => Descriptor'Unrestricted_Access);
+ Descriptors : Array_Of_Pd := [Descriptor'Unrestricted_Access];
Try_Until : constant Time := Clock + Duration (Timeout) / 1000.0;
Timeout_Tmp : Integer := Timeout;
@@ -508,7 +508,7 @@ package body GNAT.Expect is
Full_Buffer : Boolean := False)
is
N : Expect_Match;
- Descriptors : Array_Of_Pd := (1 => Descriptor'Unrestricted_Access);
+ Descriptors : Array_Of_Pd := [Descriptor'Unrestricted_Access];
begin
pragma Assert (Matched'First = 0);
@@ -1078,7 +1078,7 @@ package body GNAT.Expect is
function Has_Process (Regexp : Multiprocess_Regexp_Array) return Boolean is
begin
- return Regexp /= (Regexp'Range => (null, null));
+ return Regexp /= [Regexp'Range => (null, null)];
end Has_Process;
---------------
@@ -1294,8 +1294,8 @@ package body GNAT.Expect is
Add_LF : Boolean := True;
Empty_Buffer : Boolean := False)
is
- Line_Feed : aliased constant String := (1 .. 1 => ASCII.LF);
- Descriptors : Array_Of_Pd := (1 => Descriptor'Unrestricted_Access);
+ Line_Feed : aliased constant String := [1 .. 1 => ASCII.LF];
+ Descriptors : Array_Of_Pd := [Descriptor'Unrestricted_Access];
Result : Expect_Match;
Discard : Natural;
diff --git a/gcc/ada/libgnat/g-forstr.adb b/gcc/ada/libgnat/g-forstr.adb
index 04539be..51858ed 100644
--- a/gcc/ada/libgnat/g-forstr.adb
+++ b/gcc/ada/libgnat/g-forstr.adb
@@ -131,7 +131,7 @@ package body GNAT.Formatted_String is
return Formatted_String'
(Finalization.Controlled with
D => new Data'(Format'Length, 1, 1,
- Null_Unbounded_String, 0, 0, (0, 0), Format));
+ Null_Unbounded_String, 0, 0, [0, 0], Format));
end "+";
---------
@@ -433,7 +433,7 @@ package body GNAT.Formatted_String is
declare
R : String (1 .. Natural'Max (Natural'Max (F_Spec.Width, Len),
- Length (Res))) := (others => ' ');
+ Length (Res))) := [others => ' '];
begin
if F_Spec.Left_Justify then
R (1 .. Length (Res)) := To_String (Res);
@@ -785,7 +785,7 @@ package body GNAT.Formatted_String is
elsif F.Precision > E - S + 1 then
Len := F.Precision - (E - S + 1);
- Buffer (S - Len .. S - 1) := (others => '0');
+ Buffer (S - Len .. S - 1) := [others => '0'];
S := S - Len;
end if;
diff --git a/gcc/ada/libgnat/g-memdum.adb b/gcc/ada/libgnat/g-memdum.adb
index cd8f7ca..310923f 100644
--- a/gcc/ada/libgnat/g-memdum.adb
+++ b/gcc/ada/libgnat/g-memdum.adb
@@ -128,7 +128,7 @@ package body GNAT.Memory_Dump is
(Count - Ctr, 16, 0, Offset_Buf, Last);
Len := Last - 4;
- Line_Buf (1 .. AIL - Len - 2) := (others => '0');
+ Line_Buf (1 .. AIL - Len - 2) := [others => '0'];
Line_Buf (AIL - Len - 1 .. AIL - 2) :=
Offset_Buf (4 .. Last - 1);
Line_Buf (AIL - 1 .. AIL) := ": ";
@@ -138,7 +138,7 @@ package body GNAT.Memory_Dump is
null;
end case;
- Line_Buf (AIL + 1 .. Line_Buf'Last) := (others => ' ');
+ Line_Buf (AIL + 1 .. Line_Buf'Last) := [others => ' '];
Line_Buf (AIL + 3 * 16 + 1) := '"';
end if;
diff --git a/gcc/ada/libgnat/g-rannum.adb b/gcc/ada/libgnat/g-rannum.adb
index 2983201..7688781 100644
--- a/gcc/ada/libgnat/g-rannum.adb
+++ b/gcc/ada/libgnat/g-rannum.adb
@@ -385,7 +385,7 @@ is
Result : Image_String;
begin
- Result := (others => ' ');
+ Result := [others => ' '];
Result (1 .. Sys_Max_Image_Width) := Image (Gen.Rep);
if Gen.Have_Gaussian then
diff --git a/gcc/ada/libgnat/g-sechas.adb b/gcc/ada/libgnat/g-sechas.adb
index 178b59b..70911c0 100644
--- a/gcc/ada/libgnat/g-sechas.adb
+++ b/gcc/ada/libgnat/g-sechas.adb
@@ -238,7 +238,7 @@ package body GNAT.Secure_Hashes is
mod FC.M_State.Block_Length;
declare
Pad : Stream_Element_Array (1 .. 1 + Zeroes + Size_Length) :=
- (1 => 128, others => 0);
+ [1 => 128, others => 0];
Index : Stream_Element_Offset;
First_Index : Stream_Element_Offset;
@@ -281,7 +281,7 @@ package body GNAT.Secure_Hashes is
declare
Outer_C : Context;
Opad : Stream_Element_Array :=
- (1 .. Stream_Element_Offset (Block_Length) => 16#5c#);
+ [1 .. Stream_Element_Offset (Block_Length) => 16#5c#];
begin
for J in C.Key'Range loop
@@ -329,7 +329,7 @@ package body GNAT.Secure_Hashes is
declare
Ipad : Stream_Element_Array :=
- (1 .. Stream_Element_Offset (Block_Length) => 16#36#);
+ [1 .. Stream_Element_Offset (Block_Length) => 16#36#];
begin
for J in C.Key'Range loop
diff --git a/gcc/ada/libgnat/g-sehamd.ads b/gcc/ada/libgnat/g-sehamd.ads
index 148ecb1..ca9fbfd 100644
--- a/gcc/ada/libgnat/g-sehamd.ads
+++ b/gcc/ada/libgnat/g-sehamd.ads
@@ -68,7 +68,7 @@ private
Initial_D : constant := 16#10325476#;
Initial_State : constant Hash_State.State :=
- (Initial_A, Initial_B, Initial_C, Initial_D);
+ [Initial_A, Initial_B, Initial_C, Initial_D];
-- Initialization vector from RFC 1321
end GNAT.Secure_Hashes.MD5;
diff --git a/gcc/ada/libgnat/g-sehash.ads b/gcc/ada/libgnat/g-sehash.ads
index 602032f..3a24088 100644
--- a/gcc/ada/libgnat/g-sehash.ads
+++ b/gcc/ada/libgnat/g-sehash.ads
@@ -62,11 +62,11 @@ package GNAT.Secure_Hashes.SHA1 is
private
Initial_State : constant Hash_State.State :=
- (0 => 16#67452301#,
+ [0 => 16#67452301#,
1 => 16#EFCDAB89#,
2 => 16#98BADCFE#,
3 => 16#10325476#,
- 4 => 16#C3D2E1F0#);
+ 4 => 16#C3D2E1F0#];
-- Initialization vector from FIPS PUB 180-3
end GNAT.Secure_Hashes.SHA1;
diff --git a/gcc/ada/libgnat/g-sercom.ads b/gcc/ada/libgnat/g-sercom.ads
index 4c9b0b7..c05e00e 100644
--- a/gcc/ada/libgnat/g-sercom.ads
+++ b/gcc/ada/libgnat/g-sercom.ads
@@ -192,7 +192,7 @@ private
end record;
Data_Rate_Value : constant array (Data_Rate) of Interfaces.C.unsigned :=
- (B75 => 75,
+ [B75 => 75,
B110 => 110,
B150 => 150,
B300 => 300,
@@ -217,7 +217,7 @@ private
B2500000 => 2_500_000,
B3000000 => 3_000_000,
B3500000 => 3_500_000,
- B4000000 => 4_000_000);
+ B4000000 => 4_000_000];
function To_C (Port : Serial_Port) return Serial_Port_Descriptor is
(Port.H);
diff --git a/gcc/ada/libgnat/g-sercom__linux.adb b/gcc/ada/libgnat/g-sercom__linux.adb
index dbcb171..3d62b61 100644
--- a/gcc/ada/libgnat/g-sercom__linux.adb
+++ b/gcc/ada/libgnat/g-sercom__linux.adb
@@ -80,7 +80,7 @@ package body GNAT.Serial_Communications is
pragma Import (C, fcntl, "fcntl");
C_Data_Rate : constant array (Data_Rate) of unsigned :=
- (B75 => OSC.B75,
+ [B75 => OSC.B75,
B110 => OSC.B110,
B150 => OSC.B150,
B300 => OSC.B300,
@@ -105,18 +105,18 @@ package body GNAT.Serial_Communications is
B2500000 => OSC.B2500000,
B3000000 => OSC.B3000000,
B3500000 => OSC.B3500000,
- B4000000 => OSC.B4000000);
+ B4000000 => OSC.B4000000];
C_Bits : constant array (Data_Bits) of unsigned :=
- (CS7 => OSC.CS7, CS8 => OSC.CS8);
+ [CS7 => OSC.CS7, CS8 => OSC.CS8];
C_Stop_Bits : constant array (Stop_Bits_Number) of unsigned :=
- (One => 0, Two => OSC.CSTOPB);
+ [One => 0, Two => OSC.CSTOPB];
C_Parity : constant array (Parity_Check) of unsigned :=
- (None => 0,
+ [None => 0,
Odd => OSC.PARENB or OSC.PARODD,
- Even => OSC.PARENB);
+ Even => OSC.PARENB];
procedure Raise_Error (Message : String; Error : Integer := Errno);
pragma No_Return (Raise_Error);
diff --git a/gcc/ada/libgnat/g-shsh32.ads b/gcc/ada/libgnat/g-shsh32.ads
index f23075b..de51e72 100644
--- a/gcc/ada/libgnat/g-shsh32.ads
+++ b/gcc/ada/libgnat/g-shsh32.ads
@@ -50,7 +50,7 @@ package GNAT.Secure_Hashes.SHA2_32 is
-- SHA-224 and SHA-256 operate on 32-bit big endian words
K : constant Hash_State.State (0 .. 63) :=
- (16#428a2f98#, 16#71374491#, 16#b5c0fbcf#, 16#e9b5dba5#,
+ [16#428a2f98#, 16#71374491#, 16#b5c0fbcf#, 16#e9b5dba5#,
16#3956c25b#, 16#59f111f1#, 16#923f82a4#, 16#ab1c5ed5#,
16#d807aa98#, 16#12835b01#, 16#243185be#, 16#550c7dc3#,
16#72be5d74#, 16#80deb1fe#, 16#9bdc06a7#, 16#c19bf174#,
@@ -65,7 +65,7 @@ package GNAT.Secure_Hashes.SHA2_32 is
16#19a4c116#, 16#1e376c08#, 16#2748774c#, 16#34b0bcb5#,
16#391c0cb3#, 16#4ed8aa4a#, 16#5b9cca4f#, 16#682e6ff3#,
16#748f82ee#, 16#78a5636f#, 16#84c87814#, 16#8cc70208#,
- 16#90befffa#, 16#a4506ceb#, 16#bef9a3f7#, 16#c67178f2#);
+ 16#90befffa#, 16#a4506ceb#, 16#bef9a3f7#, 16#c67178f2#];
-- Constants from FIPS PUB 180-3
function Sigma0 (X : Word) return Word;
@@ -86,23 +86,23 @@ package GNAT.Secure_Hashes.SHA2_32 is
S1 => S1);
SHA224_Init_State : constant Hash_State.State (0 .. 7) :=
- (0 => 16#c1059ed8#,
+ [0 => 16#c1059ed8#,
1 => 16#367cd507#,
2 => 16#3070dd17#,
3 => 16#f70e5939#,
4 => 16#ffc00b31#,
5 => 16#68581511#,
6 => 16#64f98fa7#,
- 7 => 16#befa4fa4#);
+ 7 => 16#befa4fa4#];
SHA256_Init_State : constant Hash_State.State (0 .. 7) :=
- (0 => 16#6a09e667#,
+ [0 => 16#6a09e667#,
1 => 16#bb67ae85#,
2 => 16#3c6ef372#,
3 => 16#a54ff53a#,
4 => 16#510e527f#,
5 => 16#9b05688c#,
6 => 16#1f83d9ab#,
- 7 => 16#5be0cd19#);
+ 7 => 16#5be0cd19#];
-- Initialization vectors from FIPS PUB 180-3
end GNAT.Secure_Hashes.SHA2_32;
diff --git a/gcc/ada/libgnat/g-shsh64.ads b/gcc/ada/libgnat/g-shsh64.ads
index 1d67007..8440e5d 100644
--- a/gcc/ada/libgnat/g-shsh64.ads
+++ b/gcc/ada/libgnat/g-shsh64.ads
@@ -50,7 +50,7 @@ package GNAT.Secure_Hashes.SHA2_64 is
-- SHA-384 and SHA-512 operate on 64-bit big endian words
K : Hash_State.State (0 .. 79) :=
- (16#428a2f98d728ae22#, 16#7137449123ef65cd#,
+ [16#428a2f98d728ae22#, 16#7137449123ef65cd#,
16#b5c0fbcfec4d3b2f#, 16#e9b5dba58189dbbc#,
16#3956c25bf348b538#, 16#59f111f1b605d019#,
16#923f82a4af194f9b#, 16#ab1c5ed5da6d8118#,
@@ -89,7 +89,7 @@ package GNAT.Secure_Hashes.SHA2_64 is
16#28db77f523047d84#, 16#32caab7b40c72493#,
16#3c9ebe0a15c9bebc#, 16#431d67c49c100d4c#,
16#4cc5d4becb3e42b6#, 16#597f299cfc657e2a#,
- 16#5fcb6fab3ad6faec#, 16#6c44198c4a475817#);
+ 16#5fcb6fab3ad6faec#, 16#6c44198c4a475817#];
-- Constants from FIPS PUB 180-3
function Sigma0 (X : Word) return Word;
@@ -110,23 +110,23 @@ package GNAT.Secure_Hashes.SHA2_64 is
S1 => S1);
SHA384_Init_State : constant Hash_State.State :=
- (0 => 16#cbbb9d5dc1059ed8#,
+ [0 => 16#cbbb9d5dc1059ed8#,
1 => 16#629a292a367cd507#,
2 => 16#9159015a3070dd17#,
3 => 16#152fecd8f70e5939#,
4 => 16#67332667ffc00b31#,
5 => 16#8eb44a8768581511#,
6 => 16#db0c2e0d64f98fa7#,
- 7 => 16#47b5481dbefa4fa4#);
+ 7 => 16#47b5481dbefa4fa4#];
SHA512_Init_State : constant Hash_State.State :=
- (0 => 16#6a09e667f3bcc908#,
+ [0 => 16#6a09e667f3bcc908#,
1 => 16#bb67ae8584caa73b#,
2 => 16#3c6ef372fe94f82b#,
3 => 16#a54ff53a5f1d36f1#,
4 => 16#510e527fade682d1#,
5 => 16#9b05688c2b3e6c1f#,
6 => 16#1f83d9abfb41bd6b#,
- 7 => 16#5be0cd19137e2179#);
+ 7 => 16#5be0cd19137e2179#];
-- Initialization vectors from FIPS PUB 180-3
end GNAT.Secure_Hashes.SHA2_64;
diff --git a/gcc/ada/libgnat/g-socket.adb b/gcc/ada/libgnat/g-socket.adb
index 75a2b27..c603a2d 100644
--- a/gcc/ada/libgnat/g-socket.adb
+++ b/gcc/ada/libgnat/g-socket.adb
@@ -71,31 +71,31 @@ package body GNAT.Sockets is
-- Correspondence tables
Levels : constant array (Level_Type) of C.int :=
- (Socket_Level => SOSC.SOL_SOCKET,
+ [Socket_Level => SOSC.SOL_SOCKET,
IP_Protocol_For_IP_Level => SOSC.IPPROTO_IP,
IP_Protocol_For_IPv6_Level => SOSC.IPPROTO_IPV6,
IP_Protocol_For_UDP_Level => SOSC.IPPROTO_UDP,
IP_Protocol_For_TCP_Level => SOSC.IPPROTO_TCP,
IP_Protocol_For_ICMP_Level => SOSC.IPPROTO_ICMP,
IP_Protocol_For_IGMP_Level => SOSC.IPPROTO_IGMP,
- IP_Protocol_For_RAW_Level => SOSC.IPPROTO_RAW);
+ IP_Protocol_For_RAW_Level => SOSC.IPPROTO_RAW];
Modes : constant array (Mode_Type) of C.int :=
- (Socket_Stream => SOSC.SOCK_STREAM,
+ [Socket_Stream => SOSC.SOCK_STREAM,
Socket_Datagram => SOSC.SOCK_DGRAM,
- Socket_Raw => SOSC.SOCK_RAW);
+ Socket_Raw => SOSC.SOCK_RAW];
Shutmodes : constant array (Shutmode_Type) of C.int :=
- (Shut_Read => SOSC.SHUT_RD,
+ [Shut_Read => SOSC.SHUT_RD,
Shut_Write => SOSC.SHUT_WR,
- Shut_Read_Write => SOSC.SHUT_RDWR);
+ Shut_Read_Write => SOSC.SHUT_RDWR];
Requests : constant array (Request_Name) of SOSC.IOCTL_Req_T :=
- (Non_Blocking_IO => SOSC.FIONBIO,
- N_Bytes_To_Read => SOSC.FIONREAD);
+ [Non_Blocking_IO => SOSC.FIONBIO,
+ N_Bytes_To_Read => SOSC.FIONREAD];
Options : constant array (Specific_Option_Name) of C.int :=
- (Keep_Alive => SOSC.SO_KEEPALIVE,
+ [Keep_Alive => SOSC.SO_KEEPALIVE,
Keep_Alive_Count => SOSC.TCP_KEEPCNT,
Keep_Alive_Idle => SOSC.TCP_KEEPIDLE,
Keep_Alive_Interval => SOSC.TCP_KEEPINTVL,
@@ -120,15 +120,15 @@ package body GNAT.Sockets is
IPv6_Only => SOSC.IPV6_V6ONLY,
Send_Timeout => SOSC.SO_SNDTIMEO,
Receive_Timeout => SOSC.SO_RCVTIMEO,
- Busy_Polling => SOSC.SO_BUSY_POLL);
+ Busy_Polling => SOSC.SO_BUSY_POLL];
-- ??? Note: for OpenSolaris, Receive_Packet_Info should be IP_RECVPKTINFO,
-- but for Linux compatibility this constant is the same as IP_PKTINFO.
Flags : constant array (0 .. 3) of C.int :=
- (0 => SOSC.MSG_OOB, -- Process_Out_Of_Band_Data
+ [0 => SOSC.MSG_OOB, -- Process_Out_Of_Band_Data
1 => SOSC.MSG_PEEK, -- Peek_At_Incoming_Data
2 => SOSC.MSG_WAITALL, -- Wait_For_A_Full_Reception
- 3 => SOSC.MSG_EOR); -- Send_End_Of_Record
+ 3 => SOSC.MSG_EOR]; -- Send_End_Of_Record
Socket_Error_Id : constant Exception_Id := Socket_Error'Identity;
Host_Error_Id : constant Exception_Id := Host_Error'Identity;
@@ -1184,8 +1184,8 @@ package body GNAT.Sockets is
Numeric_Serv : Boolean := False) return Host_Service
is
SA : aliased Sockaddr;
- H : aliased C.char_array := (1 .. SOSC.NI_MAXHOST => C.nul);
- S : aliased C.char_array := (1 .. SOSC.NI_MAXSERV => C.nul);
+ H : aliased C.char_array := [1 .. SOSC.NI_MAXHOST => C.nul];
+ S : aliased C.char_array := [1 .. SOSC.NI_MAXSERV => C.nul];
RC : C.int;
Len : C.int;
begin
@@ -1621,7 +1621,7 @@ package body GNAT.Sockets is
when Family_Inet => 4 * Value.Sin_V4'Length,
when Family_Inet6 => 6 * 5 + 4 * 4);
-- 1234:1234:1234:1234:1234:1234:123.123.123.123
- Dst : aliased C.char_array := (1 .. C.size_t (Size) => C.nul);
+ Dst : aliased C.char_array := [1 .. C.size_t (Size) => C.nul];
Ia : aliased In_Addr_Union (Value.Family);
begin
case Value.Family is
diff --git a/gcc/ada/libgnat/g-socket.ads b/gcc/ada/libgnat/g-socket.ads
index 4372f3e..443b61c 100644
--- a/gcc/ada/libgnat/g-socket.ads
+++ b/gcc/ada/libgnat/g-socket.ads
@@ -506,7 +506,7 @@ package GNAT.Sockets is
-- Octet for Internet address
Inet_Addr_Bytes_Length : constant array (Family_Inet_4_6) of Natural :=
- (Family_Inet => 4, Family_Inet6 => 16);
+ [Family_Inet => 4, Family_Inet6 => 16];
type Inet_Addr_Bytes is array (Natural range <>) of Inet_Addr_Comp_Type;
@@ -521,10 +521,10 @@ package GNAT.Sockets is
type Inet_Addr_Type (Family : Family_Inet_4_6 := Family_Inet) is record
case Family is
when Family_Inet =>
- Sin_V4 : Inet_Addr_V4_Type := (others => 0);
+ Sin_V4 : Inet_Addr_V4_Type := [others => 0];
when Family_Inet6 =>
- Sin_V6 : Inet_Addr_V6_Type := (others => 0);
+ Sin_V6 : Inet_Addr_V6_Type := [others => 0];
end case;
end record;
@@ -571,7 +571,7 @@ package GNAT.Sockets is
-- Idem for IPv6 protocol
IPv4_To_IPv6_Prefix : constant Inet_Addr_Bytes :=
- (1 .. 10 => 0, 11 .. 12 => 255);
+ [1 .. 10 => 0, 11 .. 12 => 255];
-- Prefix for IPv4 mapped to IPv6 addresses
-- Functions to handle masks and prefixes
@@ -1122,7 +1122,7 @@ package GNAT.Sockets is
Family : Family_Type := Family_Inet;
Mode : Mode_Type := Socket_Stream;
Level : Level_Type := IP_Protocol_For_IP_Level);
- -- Create an endpoint for communication. Raises Socket_Error on error.
+ -- Create an endpoint for communication. Raises Socket_Error on error
procedure Create_Socket_Pair
(Left : out Socket_Type;
@@ -1529,37 +1529,39 @@ private
No_Port : constant Port_Type := 0;
Any_Inet_Addr : constant Inet_Addr_Type :=
- (Family_Inet, (others => 0));
+ (Family_Inet, [others => 0]);
Any_Inet6_Addr : constant Inet_Addr_Type :=
- (Family_Inet6, (others => 0));
+ (Family_Inet6, [others => 0]);
No_Inet_Addr : constant Inet_Addr_Type :=
- (Family_Inet, (others => 0));
+ (Family_Inet, [others => 0]);
Broadcast_Inet_Addr : constant Inet_Addr_Type :=
- (Family_Inet, (others => 255));
+ (Family_Inet, [others => 255]);
Loopback_Inet_Addr : constant Inet_Addr_Type :=
- (Family_Inet, (127, 0, 0, 1));
+ (Family_Inet, [127, 0, 0, 1]);
Loopback_Inet6_Addr : constant Inet_Addr_Type :=
(Family_Inet6,
- (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1));
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
Unspecified_Group_Inet_Addr : constant Inet_Addr_Type :=
- (Family_Inet, (224, 0, 0, 0));
+ (Family_Inet, [224, 0, 0, 0]);
All_Hosts_Group_Inet_Addr : constant Inet_Addr_Type :=
- (Family_Inet, (224, 0, 0, 1));
+ (Family_Inet, [224, 0, 0, 1]);
All_Routers_Group_Inet_Addr : constant Inet_Addr_Type :=
- (Family_Inet, (224, 0, 0, 2));
+ (Family_Inet, [224, 0, 0, 2]);
Unspecified_Group_Inet6_Addr : constant Inet_Addr_Type :=
- (Family_Inet6, (255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+ (Family_Inet6, [255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
All_Hosts_Group_Inet6_Addr : constant Inet_Addr_Type :=
- (Family_Inet6, (255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1));
+ (Family_Inet6, [255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
All_Routers_Group_Inet6_Addr : constant Inet_Addr_Type :=
- (Family_Inet6, (255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2));
+ (Family_Inet6, [255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
No_Sock_Addr : constant Sock_Addr_Type := (Family_Inet, No_Inet_Addr, 0);
- Max_Name_Length : constant := 64;
- -- The constant MAXHOSTNAMELEN is usually set to 64
+ Max_Name_Length : constant := SOSC.NI_MAXHOST;
+ -- Most systems don't provide constants that specify the maximum size
+ -- of either a FQDN or a service name. In order to aid applications in
+ -- allocating buffers, the constant NI_MAXHOST is defined in <netdb.h>.
subtype Name_Index is Natural range 1 .. Max_Name_Length;
diff --git a/gcc/ada/libgnat/g-socpol.adb b/gcc/ada/libgnat/g-socpol.adb
index 3f153af..1592594 100644
--- a/gcc/ada/libgnat/g-socpol.adb
+++ b/gcc/ada/libgnat/g-socpol.adb
@@ -36,7 +36,7 @@ with GNAT.Sockets.Thin;
package body GNAT.Sockets.Poll is
To_C : constant array (Wait_Event_Type) of Events_Type :=
- (Input => SOC.POLLIN or SOC.POLLPRI, Output => SOC.POLLOUT);
+ [Input => SOC.POLLIN or SOC.POLLPRI, Output => SOC.POLLOUT];
-- To convert Wait_Event_Type to C I/O events flags
procedure Set_Mode (Item : out Pollfd; Mode : Wait_Event_Set);
@@ -50,11 +50,11 @@ package body GNAT.Sockets.Poll is
-- raise Constraint_Error if Index is more than number of sockets in Self
function Status (Item : Pollfd) return Event_Set is
- (Input => (Item.REvents and To_C (Input)) /= 0,
- Output => (Item.REvents and To_C (Output)) /= 0,
- Error => (Item.REvents and SOC.POLLERR) /= 0,
- Hang_Up => (Item.REvents and SOC.POLLHUP) /= 0,
- Invalid_Request => (Item.REvents and SOC.POLLNVAL) /= 0);
+ ([Input => (Item.REvents and To_C (Input)) /= 0,
+ Output => (Item.REvents and To_C (Output)) /= 0,
+ Error => (Item.REvents and SOC.POLLERR) /= 0,
+ Hang_Up => (Item.REvents and SOC.POLLHUP) /= 0,
+ Invalid_Request => (Item.REvents and SOC.POLLNVAL) /= 0]);
-- Get I/O events from C word
procedure Wait
@@ -188,8 +188,8 @@ package body GNAT.Sockets.Poll is
begin
Check_Range (Self, Index);
return
- (Input => (Self.Fds (Index).Events and To_C (Input)) /= 0,
- Output => (Self.Fds (Index).Events and To_C (Output)) /= 0);
+ [Input => (Self.Fds (Index).Events and To_C (Input)) /= 0,
+ Output => (Self.Fds (Index).Events and To_C (Output)) /= 0];
end Get_Events;
------------
diff --git a/gcc/ada/libgnat/g-socpol.ads b/gcc/ada/libgnat/g-socpol.ads
index 71ce1bb..348cc6f 100644
--- a/gcc/ada/libgnat/g-socpol.ads
+++ b/gcc/ada/libgnat/g-socpol.ads
@@ -171,10 +171,10 @@ package GNAT.Sockets.Poll is
private
- Input_Event : constant Wait_Event_Set := (Input => True, Output => False);
- Output_Event : constant Wait_Event_Set := (Input => False, Output => True);
- Both_Events : constant Wait_Event_Set := (others => True);
- Error_Event : constant Wait_Event_Set := (others => False);
+ Input_Event : constant Wait_Event_Set := [Input => True, Output => False];
+ Output_Event : constant Wait_Event_Set := [Input => False, Output => True];
+ Both_Events : constant Wait_Event_Set := [others => True];
+ Error_Event : constant Wait_Event_Set := [others => False];
package SOC renames System.OS_Constants;
diff --git a/gcc/ada/libgnat/g-sothco.ads b/gcc/ada/libgnat/g-sothco.ads
index b48657b..761bcb1 100644
--- a/gcc/ada/libgnat/g-sothco.ads
+++ b/gcc/ada/libgnat/g-sothco.ads
@@ -75,16 +75,16 @@ package GNAT.Sockets.Thin_Common is
-------------------------------------------
Families : constant array (Family_Type) of C.int :=
- (Family_Unspec => SOSC.AF_UNSPEC,
+ [Family_Unspec => SOSC.AF_UNSPEC,
Family_Unix => SOSC.AF_UNIX,
Family_Inet => SOSC.AF_INET,
- Family_Inet6 => SOSC.AF_INET6);
+ Family_Inet6 => SOSC.AF_INET6];
Lengths : constant array (Family_Type) of C.unsigned_char :=
- (Family_Unspec => 0,
+ [Family_Unspec => 0,
Family_Unix => SOSC.SIZEOF_sockaddr_un,
Family_Inet => SOSC.SIZEOF_sockaddr_in,
- Family_Inet6 => SOSC.SIZEOF_sockaddr_in6);
+ Family_Inet6 => SOSC.SIZEOF_sockaddr_in6];
----------------------------
-- Generic socket address --
@@ -160,7 +160,7 @@ package GNAT.Sockets.Thin_Common is
Sin_Addr : In_Addr := (others => 0);
-- IPv4 address
- Sin_Zero : C.char_array (1 .. 8) := (others => C.nul);
+ Sin_Zero : C.char_array (1 .. 8) := [others => C.nul];
-- Padding
--
-- Note that some platforms require that all unused (reserved) bytes
@@ -174,7 +174,7 @@ package GNAT.Sockets.Thin_Common is
-- Port in network byte order
Sin6_FlowInfo : Interfaces.Unsigned_32 := 0;
- Sin6_Addr : In6_Addr := (others => 0);
+ Sin6_Addr : In6_Addr := [others => 0];
Sin6_Scope_Id : Interfaces.Unsigned_32 := 0;
when Family_Unix =>
diff --git a/gcc/ada/libgnat/g-spipat.adb b/gcc/ada/libgnat/g-spipat.adb
index 97cfdf9..353a92d 100644
--- a/gcc/ada/libgnat/g-spipat.adb
+++ b/gcc/ada/libgnat/g-spipat.adb
@@ -367,7 +367,7 @@ package body GNAT.Spitbol.Patterns is
-- one character on success, and not to make any entries on the stack.
OK_For_Simple_Arbno : constant array (Pattern_Code) of Boolean :=
- (PC_Any_CS |
+ [PC_Any_CS |
PC_Any_CH |
PC_Any_VF |
PC_Any_VP |
@@ -387,7 +387,7 @@ package body GNAT.Spitbol.Patterns is
PC_String_4 |
PC_String_5 |
PC_String_6 => True,
- others => False);
+ others => False];
-------------------------------
-- The Pattern History Stack --
diff --git a/gcc/ada/libgnat/i-c.adb b/gcc/ada/libgnat/i-c.adb
index 5be50ff..4ec920f 100644
--- a/gcc/ada/libgnat/i-c.adb
+++ b/gcc/ada/libgnat/i-c.adb
@@ -29,7 +29,77 @@
-- --
------------------------------------------------------------------------------
-package body Interfaces.C is
+-- 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.
+
+pragma Assertion_Policy (Ghost => Ignore,
+ Loop_Invariant => Ignore,
+ Assert => Ignore);
+
+package body Interfaces.C
+ with SPARK_Mode
+is
+
+ --------------------
+ -- C_Length_Ghost --
+ --------------------
+
+ function C_Length_Ghost (Item : char_array) return size_t is
+ begin
+ for J in Item'Range loop
+ if Item (J) = nul then
+ return J - Item'First;
+ end if;
+
+ pragma Loop_Invariant
+ (for all K in Item'First .. J => Item (K) /= nul);
+ end loop;
+
+ raise Program_Error;
+ end C_Length_Ghost;
+
+ function C_Length_Ghost (Item : wchar_array) return size_t is
+ begin
+ for J in Item'Range loop
+ if Item (J) = wide_nul then
+ return J - Item'First;
+ end if;
+
+ pragma Loop_Invariant
+ (for all K in Item'First .. J => Item (K) /= wide_nul);
+ end loop;
+
+ raise Program_Error;
+ end C_Length_Ghost;
+
+ function C_Length_Ghost (Item : char16_array) return size_t is
+ begin
+ for J in Item'Range loop
+ if Item (J) = char16_nul then
+ return J - Item'First;
+ end if;
+
+ pragma Loop_Invariant
+ (for all K in Item'First .. J => Item (K) /= char16_nul);
+ end loop;
+
+ raise Program_Error;
+ end C_Length_Ghost;
+
+ function C_Length_Ghost (Item : char32_array) return size_t is
+ begin
+ for J in Item'Range loop
+ if Item (J) = char32_nul then
+ return J - Item'First;
+ end if;
+
+ pragma Loop_Invariant
+ (for all K in Item'First .. J => Item (K) /= char32_nul);
+ end loop;
+
+ raise Program_Error;
+ end C_Length_Ghost;
-----------------------
-- Is_Nul_Terminated --
@@ -43,6 +113,9 @@ package body Interfaces.C is
if Item (J) = nul then
return True;
end if;
+
+ pragma Loop_Invariant
+ (for all K in Item'First .. J => Item (K) /= nul);
end loop;
return False;
@@ -56,6 +129,9 @@ package body Interfaces.C is
if Item (J) = wide_nul then
return True;
end if;
+
+ pragma Loop_Invariant
+ (for all K in Item'First .. J => Item (K) /= wide_nul);
end loop;
return False;
@@ -69,6 +145,9 @@ package body Interfaces.C is
if Item (J) = char16_nul then
return True;
end if;
+
+ pragma Loop_Invariant
+ (for all K in Item'First .. J => Item (K) /= char16_nul);
end loop;
return False;
@@ -82,6 +161,9 @@ package body Interfaces.C is
if Item (J) = char32_nul then
return True;
end if;
+
+ pragma Loop_Invariant
+ (for all K in Item'First .. J => Item (K) /= char32_nul);
end loop;
return False;
@@ -112,6 +194,13 @@ package body Interfaces.C is
From := Item'First;
loop
+ pragma Loop_Invariant (From in Item'Range);
+ pragma Loop_Invariant
+ (for some J in From .. Item'Last => Item (J) = nul);
+ pragma Loop_Invariant
+ (for all J in Item'First .. From when J /= From =>
+ Item (J) /= nul);
+
if From > Item'Last then
raise Terminator_Error;
elsif Item (From) = nul then
@@ -121,6 +210,8 @@ package body Interfaces.C is
end if;
end loop;
+ pragma Assert (From = Item'First + C_Length_Ghost (Item));
+
Count := Natural (From - Item'First);
else
@@ -128,11 +219,17 @@ package body Interfaces.C is
end if;
declare
- R : String (1 .. Count);
+ Count_Cst : constant Natural := Count;
+ R : String (1 .. Count_Cst) with Relaxed_Initialization;
begin
for J in R'Range loop
- R (J) := To_Ada (Item (size_t (J) + (Item'First - 1)));
+ R (J) := To_Ada (Item (size_t (J) - 1 + Item'First));
+
+ pragma Loop_Invariant (for all K in 1 .. J => R (K)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ R (K) = To_Ada (Item (size_t (K) - 1 + Item'First)));
end loop;
return R;
@@ -148,12 +245,19 @@ package body Interfaces.C is
Trim_Nul : Boolean := True)
is
From : size_t;
- To : Positive;
+ To : Integer;
begin
if Trim_Nul then
From := Item'First;
loop
+ pragma Loop_Invariant (From in Item'Range);
+ pragma Loop_Invariant
+ (for some J in From .. Item'Last => Item (J) = nul);
+ pragma Loop_Invariant
+ (for all J in Item'First .. From when J /= From =>
+ Item (J) /= nul);
+
if From > Item'Last then
raise Terminator_Error;
elsif Item (From) = nul then
@@ -178,11 +282,28 @@ package body Interfaces.C is
for J in 1 .. Count loop
Target (To) := Character (Item (From));
+
+ pragma Loop_Invariant (From in Item'Range);
+ pragma Loop_Invariant (To in Target'Range);
+ pragma Loop_Invariant (To = Target'First + (J - 1));
+ pragma Loop_Invariant (From = Item'First + size_t (J - 1));
+ pragma Loop_Invariant
+ (for all J in Target'First .. To => Target (J)'Initialized);
+ pragma Loop_Invariant
+ (Target (Target'First .. To)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Target'First .. To =>
+ Target (K) =
+ To_Ada (Item (size_t (K - Target'First) + Item'First)));
+
+ -- Avoid possible overflow when incrementing To in the last
+ -- iteration of the loop.
+ exit when J = Count;
+
From := From + 1;
To := To + 1;
end loop;
end if;
-
end To_Ada;
-- Convert wchar_t to Wide_Character
@@ -206,6 +327,13 @@ package body Interfaces.C is
From := Item'First;
loop
+ pragma Loop_Invariant (From in Item'Range);
+ pragma Loop_Invariant
+ (for some J in From .. Item'Last => Item (J) = wide_nul);
+ pragma Loop_Invariant
+ (for all J in Item'First .. From when J /= From =>
+ Item (J) /= wide_nul);
+
if From > Item'Last then
raise Terminator_Error;
elsif Item (From) = wide_nul then
@@ -215,6 +343,8 @@ package body Interfaces.C is
end if;
end loop;
+ pragma Assert (From = Item'First + C_Length_Ghost (Item));
+
Count := Natural (From - Item'First);
else
@@ -222,11 +352,17 @@ package body Interfaces.C is
end if;
declare
- R : Wide_String (1 .. Count);
+ Count_Cst : constant Natural := Count;
+ R : Wide_String (1 .. Count_Cst) with Relaxed_Initialization;
begin
for J in R'Range loop
- R (J) := To_Ada (Item (size_t (J) + (Item'First - 1)));
+ R (J) := To_Ada (Item (size_t (J) - 1 + Item'First));
+
+ pragma Loop_Invariant (for all K in 1 .. J => R (K)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ R (K) = To_Ada (Item (size_t (K) - 1 + Item'First)));
end loop;
return R;
@@ -242,12 +378,19 @@ package body Interfaces.C is
Trim_Nul : Boolean := True)
is
From : size_t;
- To : Positive;
+ To : Integer;
begin
if Trim_Nul then
From := Item'First;
loop
+ pragma Loop_Invariant (From in Item'Range);
+ pragma Loop_Invariant
+ (for some J in From .. Item'Last => Item (J) = wide_nul);
+ pragma Loop_Invariant
+ (for all J in Item'First .. From when J /= From =>
+ Item (J) /= wide_nul);
+
if From > Item'Last then
raise Terminator_Error;
elsif Item (From) = wide_nul then
@@ -272,6 +415,24 @@ package body Interfaces.C is
for J in 1 .. Count loop
Target (To) := To_Ada (Item (From));
+
+ pragma Loop_Invariant (From in Item'Range);
+ pragma Loop_Invariant (To in Target'Range);
+ pragma Loop_Invariant (To = Target'First + (J - 1));
+ pragma Loop_Invariant (From = Item'First + size_t (J - 1));
+ pragma Loop_Invariant
+ (for all J in Target'First .. To => Target (J)'Initialized);
+ pragma Loop_Invariant
+ (Target (Target'First .. To)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Target'First .. To =>
+ Target (K) =
+ To_Ada (Item (size_t (K - Target'First) + Item'First)));
+
+ -- Avoid possible overflow when incrementing To in the last
+ -- iteration of the loop.
+ exit when J = Count;
+
From := From + 1;
To := To + 1;
end loop;
@@ -299,15 +460,24 @@ package body Interfaces.C is
From := Item'First;
loop
+ pragma Loop_Invariant (From in Item'Range);
+ pragma Loop_Invariant
+ (for some J in From .. Item'Last => Item (J) = char16_nul);
+ pragma Loop_Invariant
+ (for all J in Item'First .. From when J /= From =>
+ Item (J) /= char16_nul);
+
if From > Item'Last then
raise Terminator_Error;
- elsif Item (From) = char16_t'Val (0) then
+ elsif Item (From) = char16_nul then
exit;
else
From := From + 1;
end if;
end loop;
+ pragma Assert (From = Item'First + C_Length_Ghost (Item));
+
Count := Natural (From - Item'First);
else
@@ -315,11 +485,17 @@ package body Interfaces.C is
end if;
declare
- R : Wide_String (1 .. Count);
+ Count_Cst : constant Natural := Count;
+ R : Wide_String (1 .. Count_Cst) with Relaxed_Initialization;
begin
for J in R'Range loop
- R (J) := To_Ada (Item (size_t (J) + (Item'First - 1)));
+ R (J) := To_Ada (Item (size_t (J) - 1 + Item'First));
+
+ pragma Loop_Invariant (for all K in 1 .. J => R (K)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ R (K) = To_Ada (Item (size_t (K) - 1 + Item'First)));
end loop;
return R;
@@ -335,15 +511,22 @@ package body Interfaces.C is
Trim_Nul : Boolean := True)
is
From : size_t;
- To : Positive;
+ To : Integer;
begin
if Trim_Nul then
From := Item'First;
loop
+ pragma Loop_Invariant (From in Item'Range);
+ pragma Loop_Invariant
+ (for some J in From .. Item'Last => Item (J) = char16_nul);
+ pragma Loop_Invariant
+ (for all J in Item'First .. From when J /= From =>
+ Item (J) /= char16_nul);
+
if From > Item'Last then
raise Terminator_Error;
- elsif Item (From) = char16_t'Val (0) then
+ elsif Item (From) = char16_nul then
exit;
else
From := From + 1;
@@ -365,6 +548,24 @@ package body Interfaces.C is
for J in 1 .. Count loop
Target (To) := To_Ada (Item (From));
+
+ pragma Loop_Invariant (From in Item'Range);
+ pragma Loop_Invariant (To in Target'Range);
+ pragma Loop_Invariant (To = Target'First + (J - 1));
+ pragma Loop_Invariant (From = Item'First + size_t (J - 1));
+ pragma Loop_Invariant
+ (for all J in Target'First .. To => Target (J)'Initialized);
+ pragma Loop_Invariant
+ (Target (Target'First .. To)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Target'First .. To =>
+ Target (K) =
+ To_Ada (Item (size_t (K - Target'First) + Item'First)));
+
+ -- Avoid possible overflow when incrementing To in the last
+ -- iteration of the loop.
+ exit when J = Count;
+
From := From + 1;
To := To + 1;
end loop;
@@ -392,15 +593,24 @@ package body Interfaces.C is
From := Item'First;
loop
+ pragma Loop_Invariant (From in Item'Range);
+ pragma Loop_Invariant
+ (for some J in From .. Item'Last => Item (J) = char32_nul);
+ pragma Loop_Invariant
+ (for all J in Item'First .. From when J /= From =>
+ Item (J) /= char32_nul);
+
if From > Item'Last then
raise Terminator_Error;
- elsif Item (From) = char32_t'Val (0) then
+ elsif Item (From) = char32_nul then
exit;
else
From := From + 1;
end if;
end loop;
+ pragma Assert (From = Item'First + C_Length_Ghost (Item));
+
Count := Natural (From - Item'First);
else
@@ -408,11 +618,17 @@ package body Interfaces.C is
end if;
declare
- R : Wide_Wide_String (1 .. Count);
+ Count_Cst : constant Natural := Count;
+ R : Wide_Wide_String (1 .. Count_Cst) with Relaxed_Initialization;
begin
for J in R'Range loop
- R (J) := To_Ada (Item (size_t (J) + (Item'First - 1)));
+ R (J) := To_Ada (Item (size_t (J) - 1 + Item'First));
+
+ pragma Loop_Invariant (for all K in 1 .. J => R (K)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ R (K) = To_Ada (Item (size_t (K) - 1 + Item'First)));
end loop;
return R;
@@ -428,15 +644,22 @@ package body Interfaces.C is
Trim_Nul : Boolean := True)
is
From : size_t;
- To : Positive;
+ To : Integer;
begin
if Trim_Nul then
From := Item'First;
loop
+ pragma Loop_Invariant (From in Item'Range);
+ pragma Loop_Invariant
+ (for some J in From .. Item'Last => Item (J) = char32_nul);
+ pragma Loop_Invariant
+ (for all J in Item'First .. From when J /= From =>
+ Item (J) /= char32_nul);
+
if From > Item'Last then
raise Terminator_Error;
- elsif Item (From) = char32_t'Val (0) then
+ elsif Item (From) = char32_nul then
exit;
else
From := From + 1;
@@ -458,6 +681,24 @@ package body Interfaces.C is
for J in 1 .. Count loop
Target (To) := To_Ada (Item (From));
+
+ pragma Loop_Invariant (From in Item'Range);
+ pragma Loop_Invariant (To in Target'Range);
+ pragma Loop_Invariant (To = Target'First + (J - 1));
+ pragma Loop_Invariant (From = Item'First + size_t (J - 1));
+ pragma Loop_Invariant
+ (for all J in Target'First .. To => Target (J)'Initialized);
+ pragma Loop_Invariant
+ (Target (Target'First .. To)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Target'First .. To =>
+ Target (K) =
+ To_Ada (Item (size_t (K - Target'First) + Item'First)));
+
+ -- Avoid possible overflow when incrementing To in the last
+ -- iteration of the loop.
+ exit when J = Count;
+
From := From + 1;
To := To + 1;
end loop;
@@ -484,14 +725,26 @@ package body Interfaces.C is
begin
if Append_Nul then
declare
- R : char_array (0 .. Item'Length);
+ R : char_array (0 .. Item'Length) with Relaxed_Initialization;
begin
for J in Item'Range loop
R (size_t (J - Item'First)) := To_C (Item (J));
+
+ pragma Loop_Invariant
+ (for all K in 0 .. size_t (J - Item'First) =>
+ R (K)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ R (size_t (K - Item'First)) = To_C (Item (K)));
end loop;
R (R'Last) := nul;
+
+ pragma Assert
+ (for all J in Item'Range =>
+ R (size_t (J - Item'First)) = To_C (Item (J)));
+
return R;
end;
@@ -512,11 +765,19 @@ package body Interfaces.C is
else
declare
- R : char_array (0 .. Item'Length - 1);
+ R : char_array (0 .. Item'Length - 1)
+ with Relaxed_Initialization;
begin
for J in Item'Range loop
R (size_t (J - Item'First)) := To_C (Item (J));
+
+ pragma Loop_Invariant
+ (for all K in 0 .. size_t (J - Item'First) =>
+ R (K)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ R (size_t (K - Item'First)) = To_C (Item (K)));
end loop;
return R;
@@ -543,6 +804,19 @@ package body Interfaces.C is
To := Target'First;
for From in Item'Range loop
Target (To) := char (Item (From));
+
+ pragma Loop_Invariant (To in Target'Range);
+ pragma Loop_Invariant
+ (To - Target'First = size_t (From - Item'First));
+ pragma Loop_Invariant
+ (for all J in Target'First .. To => Target (J)'Initialized);
+ pragma Loop_Invariant
+ (Target (Target'First .. To)'Initialized);
+ pragma Loop_Invariant
+ (for all J in Item'First .. From =>
+ Target (Target'First + size_t (J - Item'First)) =
+ To_C (Item (J)));
+
To := To + 1;
end loop;
@@ -576,14 +850,26 @@ package body Interfaces.C is
begin
if Append_Nul then
declare
- R : wchar_array (0 .. Item'Length);
+ R : wchar_array (0 .. Item'Length) with Relaxed_Initialization;
begin
for J in Item'Range loop
R (size_t (J - Item'First)) := To_C (Item (J));
+
+ pragma Loop_Invariant
+ (for all K in 0 .. size_t (J - Item'First) =>
+ R (K)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ R (size_t (K - Item'First)) = To_C (Item (K)));
end loop;
R (R'Last) := wide_nul;
+
+ pragma Assert
+ (for all J in Item'Range =>
+ R (size_t (J - Item'First)) = To_C (Item (J)));
+
return R;
end;
@@ -600,11 +886,19 @@ package body Interfaces.C is
else
declare
- R : wchar_array (0 .. Item'Length - 1);
+ R : wchar_array (0 .. Item'Length - 1)
+ with Relaxed_Initialization;
begin
- for J in size_t range 0 .. Item'Length - 1 loop
- R (J) := To_C (Item (Integer (J) + Item'First));
+ for J in Item'Range loop
+ R (size_t (J - Item'First)) := To_C (Item (J));
+
+ pragma Loop_Invariant
+ (for all K in 0 .. size_t (J - Item'First) =>
+ R (K)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ R (size_t (K - Item'First)) = To_C (Item (K)));
end loop;
return R;
@@ -631,9 +925,31 @@ package body Interfaces.C is
To := Target'First;
for From in Item'Range loop
Target (To) := To_C (Item (From));
+
+ pragma Loop_Invariant (To in Target'Range);
+ pragma Loop_Invariant
+ (To - Target'First = size_t (From - Item'First));
+ pragma Loop_Invariant
+ (for all J in Target'First .. To => Target (J)'Initialized);
+ pragma Loop_Invariant
+ (Target (Target'First .. To)'Initialized);
+ pragma Loop_Invariant
+ (for all J in Item'First .. From =>
+ Target (Target'First + size_t (J - Item'First)) =
+ To_C (Item (J)));
+
To := To + 1;
end loop;
+ pragma Assert
+ (for all J in Item'Range =>
+ Target (Target'First + size_t (J - Item'First)) =
+ To_C (Item (J)));
+ pragma Assert
+ (if Item'Length /= 0 then
+ Target (Target'First ..
+ Target'First + (Item'Length - 1))'Initialized);
+
if Append_Nul then
if To > Target'Last then
raise Constraint_Error;
@@ -664,14 +980,26 @@ package body Interfaces.C is
begin
if Append_Nul then
declare
- R : char16_array (0 .. Item'Length);
+ R : char16_array (0 .. Item'Length) with Relaxed_Initialization;
begin
for J in Item'Range loop
R (size_t (J - Item'First)) := To_C (Item (J));
+
+ pragma Loop_Invariant
+ (for all K in 0 .. size_t (J - Item'First) =>
+ R (K)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ R (size_t (K - Item'First)) = To_C (Item (K)));
end loop;
- R (R'Last) := char16_t'Val (0);
+ R (R'Last) := char16_nul;
+
+ pragma Assert
+ (for all J in Item'Range =>
+ R (size_t (J - Item'First)) = To_C (Item (J)));
+
return R;
end;
@@ -688,11 +1016,19 @@ package body Interfaces.C is
else
declare
- R : char16_array (0 .. Item'Length - 1);
+ R : char16_array (0 .. Item'Length - 1)
+ with Relaxed_Initialization;
begin
- for J in size_t range 0 .. Item'Length - 1 loop
- R (J) := To_C (Item (Integer (J) + Item'First));
+ for J in Item'Range loop
+ R (size_t (J - Item'First)) := To_C (Item (J));
+
+ pragma Loop_Invariant
+ (for all K in 0 .. size_t (J - Item'First) =>
+ R (K)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ R (size_t (K - Item'First)) = To_C (Item (K)));
end loop;
return R;
@@ -719,14 +1055,36 @@ package body Interfaces.C is
To := Target'First;
for From in Item'Range loop
Target (To) := To_C (Item (From));
+
+ pragma Loop_Invariant (To in Target'Range);
+ pragma Loop_Invariant
+ (To - Target'First = size_t (From - Item'First));
+ pragma Loop_Invariant
+ (for all J in Target'First .. To => Target (J)'Initialized);
+ pragma Loop_Invariant
+ (Target (Target'First .. To)'Initialized);
+ pragma Loop_Invariant
+ (for all J in Item'First .. From =>
+ Target (Target'First + size_t (J - Item'First)) =
+ To_C (Item (J)));
+
To := To + 1;
end loop;
+ pragma Assert
+ (for all J in Item'Range =>
+ Target (Target'First + size_t (J - Item'First)) =
+ To_C (Item (J)));
+ pragma Assert
+ (if Item'Length /= 0 then
+ Target (Target'First ..
+ Target'First + (Item'Length - 1))'Initialized);
+
if Append_Nul then
if To > Target'Last then
raise Constraint_Error;
else
- Target (To) := char16_t'Val (0);
+ Target (To) := char16_nul;
Count := Item'Length + 1;
end if;
@@ -752,14 +1110,26 @@ package body Interfaces.C is
begin
if Append_Nul then
declare
- R : char32_array (0 .. Item'Length);
+ R : char32_array (0 .. Item'Length) with Relaxed_Initialization;
begin
for J in Item'Range loop
R (size_t (J - Item'First)) := To_C (Item (J));
+
+ pragma Loop_Invariant
+ (for all K in 0 .. size_t (J - Item'First) =>
+ R (K)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ R (size_t (K - Item'First)) = To_C (Item (K)));
end loop;
- R (R'Last) := char32_t'Val (0);
+ R (R'Last) := char32_nul;
+
+ pragma Assert
+ (for all J in Item'Range =>
+ R (size_t (J - Item'First)) = To_C (Item (J)));
+
return R;
end;
@@ -775,11 +1145,19 @@ package body Interfaces.C is
else
declare
- R : char32_array (0 .. Item'Length - 1);
+ R : char32_array (0 .. Item'Length - 1)
+ with Relaxed_Initialization;
begin
- for J in size_t range 0 .. Item'Length - 1 loop
- R (J) := To_C (Item (Integer (J) + Item'First));
+ for J in Item'Range loop
+ R (size_t (J - Item'First)) := To_C (Item (J));
+
+ pragma Loop_Invariant
+ (for all K in 0 .. size_t (J - Item'First) =>
+ R (K)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ R (size_t (K - Item'First)) = To_C (Item (K)));
end loop;
return R;
@@ -806,14 +1184,36 @@ package body Interfaces.C is
To := Target'First;
for From in Item'Range loop
Target (To) := To_C (Item (From));
+
+ pragma Loop_Invariant (To in Target'Range);
+ pragma Loop_Invariant
+ (To - Target'First = size_t (From - Item'First));
+ pragma Loop_Invariant
+ (for all J in Target'First .. To => Target (J)'Initialized);
+ pragma Loop_Invariant
+ (Target (Target'First .. To)'Initialized);
+ pragma Loop_Invariant
+ (for all J in Item'First .. From =>
+ Target (Target'First + size_t (J - Item'First)) =
+ To_C (Item (J)));
+
To := To + 1;
end loop;
+ pragma Assert
+ (for all J in Item'Range =>
+ Target (Target'First + size_t (J - Item'First)) =
+ To_C (Item (J)));
+ pragma Assert
+ (if Item'Length /= 0 then
+ Target (Target'First ..
+ Target'First + (Item'Length - 1))'Initialized);
+
if Append_Nul then
if To > Target'Last then
raise Constraint_Error;
else
- Target (To) := char32_t'Val (0);
+ Target (To) := char32_nul;
Count := Item'Length + 1;
end if;
diff --git a/gcc/ada/libgnat/i-c.ads b/gcc/ada/libgnat/i-c.ads
index 428ea49..2023b75 100644
--- a/gcc/ada/libgnat/i-c.ads
+++ b/gcc/ada/libgnat/i-c.ads
@@ -13,10 +13,30 @@
-- --
------------------------------------------------------------------------------
+-- 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);
+
with System.Parameters;
-package Interfaces.C is
- pragma Pure;
+package Interfaces.C
+ with SPARK_Mode, Pure
+is
+ -- Each of the types declared in Interfaces.C is C-compatible.
+
+ -- The types int, short, long, unsigned, ptrdiff_t, size_t, double,
+ -- char, wchar_t, char16_t, and char32_t correspond respectively to the
+ -- C types having the same names. The types signed_char, unsigned_short,
+ -- unsigned_long, unsigned_char, C_bool, C_float, and long_double
+ -- correspond respectively to the C types signed char, unsigned
+ -- short, unsigned long, unsigned char, bool, float, and long double.
-- Declaration's based on C's <limits.h>
@@ -49,7 +69,11 @@ package Interfaces.C is
type unsigned_char is mod (UCHAR_MAX + 1);
for unsigned_char'Size use CHAR_BIT;
- subtype plain_char is unsigned_char; -- ??? should be parameterized
+ -- Note: Ada RM states that the type of the subtype plain_char is either
+ -- signed_char or unsigned_char, depending on the C implementation. GNAT
+ -- instead choses unsigned_char always.
+
+ subtype plain_char is unsigned_char;
-- Note: the Integer qualifications used in the declaration of ptrdiff_t
-- avoid ambiguities when compiling in the presence of s-auxdec.ads and
@@ -80,33 +104,133 @@ package Interfaces.C is
nul : constant char := char'First;
- function To_C (Item : Character) return char;
- function To_Ada (Item : char) return Character;
+ -- The functions To_C and To_Ada map between the Ada type Character and the
+ -- C type char.
+
+ function To_C (Item : Character) return char
+ with
+ Post => To_C'Result = char'Val (Character'Pos (Item));
+
+ function To_Ada (Item : char) return Character
+ with
+ Post => To_Ada'Result = Character'Val (char'Pos (Item));
type char_array is array (size_t range <>) of aliased char;
for char_array'Component_Size use CHAR_BIT;
- function Is_Nul_Terminated (Item : char_array) return Boolean;
+ function Is_Nul_Terminated (Item : char_array) return Boolean
+ with
+ Post => Is_Nul_Terminated'Result = (for some C of Item => C = nul);
+ -- The result of Is_Nul_Terminated is True if Item contains nul, and is
+ -- False otherwise.
+
+ function C_Length_Ghost (Item : char_array) return size_t
+ with
+ Ghost,
+ Pre => Is_Nul_Terminated (Item),
+ Post => C_Length_Ghost'Result <= Item'Last - Item'First
+ and then Item (Item'First + C_Length_Ghost'Result) = nul
+ and then (for all J in Item'First .. Item'First + C_Length_Ghost'Result
+ when J /= Item'First + C_Length_Ghost'Result =>
+ Item (J) /= nul);
+ -- Ghost function to compute the length of a char_array up to the first nul
+ -- character.
function To_C
(Item : String;
- Append_Nul : Boolean := True) return char_array;
+ Append_Nul : Boolean := True) return char_array
+ with
+ Pre => not (Append_Nul = False and then Item'Length = 0),
+ Post => To_C'Result'First = 0
+ and then To_C'Result'Length =
+ (if Append_Nul then Item'Length + 1 else Item'Length)
+ and then (for all J in Item'Range =>
+ To_C'Result (size_t (J - Item'First)) = To_C (Item (J)))
+ and then (if Append_Nul then To_C'Result (To_C'Result'Last) = nul);
+ -- The result of To_C is a char_array value of length Item'Length (if
+ -- Append_Nul is False) or Item'Length+1 (if Append_Nul is True). The lower
+ -- bound is 0. For each component Item(I), the corresponding component
+ -- in the result is To_C applied to Item(I). The value nul is appended if
+ -- Append_Nul is True. If Append_Nul is False and Item'Length is 0, then
+ -- To_C propagates Constraint_Error.
function To_Ada
(Item : char_array;
- Trim_Nul : Boolean := True) return String;
+ Trim_Nul : Boolean := True) return String
+ with
+ Pre => (if Trim_Nul then
+ Is_Nul_Terminated (Item)
+ and then C_Length_Ghost (Item) <= size_t (Natural'Last)
+ else
+ Item'Last - Item'First < size_t (Natural'Last)),
+ Post => To_Ada'Result'First = 1
+ and then To_Ada'Result'Length =
+ (if Trim_Nul then C_Length_Ghost (Item) else Item'Length)
+ and then (for all J in To_Ada'Result'Range =>
+ To_Ada'Result (J) =
+ To_Ada (Item (size_t (J) - 1 + Item'First)));
+ -- The result of To_Ada is a String whose length is Item'Length (if
+ -- Trim_Nul is False) or the length of the slice of Item preceding the
+ -- first nul (if Trim_Nul is True). The lower bound of the result is 1.
+ -- If Trim_Nul is False, then for each component Item(I) the corresponding
+ -- component in the result is To_Ada applied to Item(I). If Trim_Nul
+ -- is True, then for each component Item(I) before the first nul the
+ -- corresponding component in the result is To_Ada applied to Item(I). The
+ -- function propagates Terminator_Error if Trim_Nul is True and Item does
+ -- not contain nul.
procedure To_C
(Item : String;
Target : out char_array;
Count : out size_t;
- Append_Nul : Boolean := True);
+ Append_Nul : Boolean := True)
+ with
+ Relaxed_Initialization => Target,
+ Pre => Target'Length >=
+ (if Append_Nul then Item'Length + 1 else Item'Length),
+ Post => Count = (if Append_Nul then Item'Length + 1 else Item'Length)
+ and then
+ (if Count /= 0 then
+ Target (Target'First .. Target'First + (Count - 1))'Initialized)
+ and then
+ (for all J in Item'Range =>
+ Target (Target'First + size_t (J - Item'First)) = To_C (Item (J)))
+ and then
+ (if Append_Nul then Target (Target'First + (Count - 1)) = nul);
+ -- For procedure To_C, each element of Item is converted (via the To_C
+ -- function) to a char, which is assigned to the corresponding element of
+ -- Target. If Append_Nul is True, nul is then assigned to the next element
+ -- of Target. In either case, Count is set to the number of Target elements
+ -- assigned. If Target is not long enough, Constraint_Error is propagated.
procedure To_Ada
(Item : char_array;
Target : out String;
Count : out Natural;
- Trim_Nul : Boolean := True);
+ Trim_Nul : Boolean := True)
+ with
+ Relaxed_Initialization => Target,
+ Pre => (if Trim_Nul then
+ Is_Nul_Terminated (Item)
+ and then C_Length_Ghost (Item) <= size_t (Target'Length)
+ else
+ Item'Last - Item'First < size_t (Target'Length)),
+ Post => Count =
+ (if Trim_Nul then Natural (C_Length_Ghost (Item)) else Item'Length)
+ and then
+ (if Count /= 0 then
+ Target (Target'First .. Target'First + (Count - 1))'Initialized)
+ and then
+ (for all J in Target'First .. Target'First + (Count - 1) =>
+ Target (J) =
+ To_Ada (Item (size_t (J - Target'First) + Item'First)));
+ -- For procedure To_Ada, each element of Item (if Trim_Nul is False) or
+ -- each element of Item preceding the first nul (if Trim_Nul is True) is
+ -- converted (via the To_Ada function) to a Character, which is assigned
+ -- to the corresponding element of Target. Count is set to the number of
+ -- Target elements assigned. If Target is not long enough, Constraint_Error
+ -- is propagated. If Trim_Nul is True and Item does not contain nul, then
+ -- Terminator_Error is propagated.
------------------------------------
-- Wide Character and Wide String --
@@ -117,32 +241,110 @@ package Interfaces.C is
wide_nul : constant wchar_t := wchar_t'First;
- function To_C (Item : Wide_Character) return wchar_t;
- function To_Ada (Item : wchar_t) return Wide_Character;
+ -- To_C and To_Ada provide the mappings between the Ada and C wide
+ -- character types.
+
+ function To_C (Item : Wide_Character) return wchar_t
+ with
+ Post => To_C'Result = wchar_t (Item);
+
+ function To_Ada (Item : wchar_t) return Wide_Character
+ with
+ Post => To_Ada'Result = Wide_Character (Item);
type wchar_array is array (size_t range <>) of aliased wchar_t;
- function Is_Nul_Terminated (Item : wchar_array) return Boolean;
+ function Is_Nul_Terminated (Item : wchar_array) return Boolean
+ with
+ Post => Is_Nul_Terminated'Result = (for some C of Item => C = wide_nul);
+ -- The result of Is_Nul_Terminated is True if Item contains wide_nul, and
+ -- is False otherwise.
+
+ -- The To_C and To_Ada subprograms that convert between Wide_String and
+ -- wchar_array have analogous effects to the To_C and To_Ada subprograms
+ -- that convert between String and char_array, except that wide_nul is
+ -- used instead of nul.
+
+ function C_Length_Ghost (Item : wchar_array) return size_t
+ with
+ Ghost,
+ Pre => Is_Nul_Terminated (Item),
+ Post => C_Length_Ghost'Result <= Item'Last - Item'First
+ and then Item (Item'First + C_Length_Ghost'Result) = wide_nul
+ and then (for all J in Item'First .. Item'First + C_Length_Ghost'Result
+ when J /= Item'First + C_Length_Ghost'Result =>
+ Item (J) /= wide_nul);
+ -- Ghost function to compute the length of a wchar_array up to the first
+ -- wide_nul character.
function To_C
(Item : Wide_String;
- Append_Nul : Boolean := True) return wchar_array;
+ Append_Nul : Boolean := True) return wchar_array
+ with
+ Pre => not (Append_Nul = False and then Item'Length = 0),
+ Post => To_C'Result'First = 0
+ and then To_C'Result'Length =
+ (if Append_Nul then Item'Length + 1 else Item'Length)
+ and then (for all J in Item'Range =>
+ To_C'Result (size_t (J - Item'First)) = To_C (Item (J)))
+ and then (if Append_Nul then To_C'Result (To_C'Result'Last) = wide_nul);
function To_Ada
(Item : wchar_array;
- Trim_Nul : Boolean := True) return Wide_String;
+ Trim_Nul : Boolean := True) return Wide_String
+ with
+ Pre => (if Trim_Nul then
+ Is_Nul_Terminated (Item)
+ and then C_Length_Ghost (Item) <= size_t (Natural'Last)
+ else
+ Item'Last - Item'First < size_t (Natural'Last)),
+ Post => To_Ada'Result'First = 1
+ and then To_Ada'Result'Length =
+ (if Trim_Nul then C_Length_Ghost (Item) else Item'Length)
+ and then (for all J in To_Ada'Result'Range =>
+ To_Ada'Result (J) =
+ To_Ada (Item (size_t (J) - 1 + Item'First)));
procedure To_C
(Item : Wide_String;
Target : out wchar_array;
Count : out size_t;
- Append_Nul : Boolean := True);
+ Append_Nul : Boolean := True)
+ with
+ Relaxed_Initialization => Target,
+ Pre => Target'Length >=
+ (if Append_Nul then Item'Length + 1 else Item'Length),
+ Post => Count = (if Append_Nul then Item'Length + 1 else Item'Length)
+ and then
+ (if Count /= 0 then
+ Target (Target'First .. Target'First + (Count - 1))'Initialized)
+ and then
+ (for all J in Item'Range =>
+ Target (Target'First + size_t (J - Item'First)) = To_C (Item (J)))
+ and then
+ (if Append_Nul then Target (Target'First + (Count - 1)) = wide_nul);
procedure To_Ada
(Item : wchar_array;
Target : out Wide_String;
Count : out Natural;
- Trim_Nul : Boolean := True);
+ Trim_Nul : Boolean := True)
+ with
+ Relaxed_Initialization => Target,
+ Pre => (if Trim_Nul then
+ Is_Nul_Terminated (Item)
+ and then C_Length_Ghost (Item) <= size_t (Target'Length)
+ else
+ Item'Last - Item'First < size_t (Target'Length)),
+ Post => Count =
+ (if Trim_Nul then Natural (C_Length_Ghost (Item)) else Item'Length)
+ and then
+ (if Count /= 0 then
+ Target (Target'First .. Target'First + (Count - 1))'Initialized)
+ and then
+ (for all J in Target'First .. Target'First + (Count - 1) =>
+ Target (J) =
+ To_Ada (Item (size_t (J - Target'First) + Item'First)));
Terminator_Error : exception;
@@ -156,40 +358,118 @@ package Interfaces.C is
char16_nul : constant char16_t := char16_t'Val (0);
pragma Ada_05 (char16_nul);
- function To_C (Item : Wide_Character) return char16_t;
+ -- To_C and To_Ada provide mappings between the Ada and C 16-bit character
+ -- types.
+
+ function To_C (Item : Wide_Character) return char16_t
+ with
+ Post => To_C'Result = char16_t (Item);
pragma Ada_05 (To_C);
- function To_Ada (Item : char16_t) return Wide_Character;
+ function To_Ada (Item : char16_t) return Wide_Character
+ with
+ Post => To_Ada'Result = Wide_Character (Item);
pragma Ada_05 (To_Ada);
type char16_array is array (size_t range <>) of aliased char16_t;
pragma Ada_05 (char16_array);
- function Is_Nul_Terminated (Item : char16_array) return Boolean;
+ function Is_Nul_Terminated (Item : char16_array) return Boolean
+ with
+ Post => Is_Nul_Terminated'Result = (for some C of Item => C = char16_nul);
pragma Ada_05 (Is_Nul_Terminated);
+ -- The result of Is_Nul_Terminated is True if Item contains char16_nul, and
+ -- is False otherwise.
+
+ -- The To_C and To_Ada subprograms that convert between Wide_String and
+ -- char16_array have analogous effects to the To_C and To_Ada subprograms
+ -- that convert between String and char_array, except that char16_nul is
+ -- used instead of nul.
+
+ function C_Length_Ghost (Item : char16_array) return size_t
+ with
+ Ghost,
+ Pre => Is_Nul_Terminated (Item),
+ Post => C_Length_Ghost'Result <= Item'Last - Item'First
+ and then Item (Item'First + C_Length_Ghost'Result) = char16_nul
+ and then (for all J in Item'First .. Item'First + C_Length_Ghost'Result
+ when J /= Item'First + C_Length_Ghost'Result =>
+ Item (J) /= char16_nul);
+ -- Ghost function to compute the length of a char16_array up to the first
+ -- char16_nul character.
function To_C
(Item : Wide_String;
- Append_Nul : Boolean := True) return char16_array;
+ Append_Nul : Boolean := True) return char16_array
+ with
+ Pre => not (Append_Nul = False and then Item'Length = 0),
+ Post => To_C'Result'First = 0
+ and then To_C'Result'Length =
+ (if Append_Nul then Item'Length + 1 else Item'Length)
+ and then (for all J in Item'Range =>
+ To_C'Result (size_t (J - Item'First)) = To_C (Item (J)))
+ and then
+ (if Append_Nul then To_C'Result (To_C'Result'Last) = char16_nul);
pragma Ada_05 (To_C);
function To_Ada
(Item : char16_array;
- Trim_Nul : Boolean := True) return Wide_String;
+ Trim_Nul : Boolean := True) return Wide_String
+ with
+ Pre => (if Trim_Nul then
+ Is_Nul_Terminated (Item)
+ and then C_Length_Ghost (Item) <= size_t (Natural'Last)
+ else
+ Item'Last - Item'First < size_t (Natural'Last)),
+ Post => To_Ada'Result'First = 1
+ and then To_Ada'Result'Length =
+ (if Trim_Nul then C_Length_Ghost (Item) else Item'Length)
+ and then (for all J in To_Ada'Result'Range =>
+ To_Ada'Result (J) =
+ To_Ada (Item (size_t (J) - 1 + Item'First)));
pragma Ada_05 (To_Ada);
procedure To_C
(Item : Wide_String;
Target : out char16_array;
Count : out size_t;
- Append_Nul : Boolean := True);
+ Append_Nul : Boolean := True)
+ with
+ Relaxed_Initialization => Target,
+ Pre => Target'Length >=
+ (if Append_Nul then Item'Length + 1 else Item'Length),
+ Post => Count = (if Append_Nul then Item'Length + 1 else Item'Length)
+ and then
+ (if Count /= 0 then
+ Target (Target'First .. Target'First + (Count - 1))'Initialized)
+ and then
+ (for all J in Item'Range =>
+ Target (Target'First + size_t (J - Item'First)) = To_C (Item (J)))
+ and then
+ (if Append_Nul then Target (Target'First + (Count - 1)) = char16_nul);
pragma Ada_05 (To_C);
procedure To_Ada
(Item : char16_array;
Target : out Wide_String;
Count : out Natural;
- Trim_Nul : Boolean := True);
+ Trim_Nul : Boolean := True)
+ with
+ Relaxed_Initialization => Target,
+ Pre => (if Trim_Nul then
+ Is_Nul_Terminated (Item)
+ and then C_Length_Ghost (Item) <= size_t (Target'Length)
+ else
+ Item'Last - Item'First < size_t (Target'Length)),
+ Post => Count =
+ (if Trim_Nul then Natural (C_Length_Ghost (Item)) else Item'Length)
+ and then
+ (if Count /= 0 then
+ Target (Target'First .. Target'First + (Count - 1))'Initialized)
+ and then
+ (for all J in Target'First .. Target'First + (Count - 1) =>
+ Target (J) =
+ To_Ada (Item (size_t (J - Target'First) + Item'First)));
pragma Ada_05 (To_Ada);
type char32_t is new Wide_Wide_Character;
@@ -198,40 +478,118 @@ package Interfaces.C is
char32_nul : constant char32_t := char32_t'Val (0);
pragma Ada_05 (char32_nul);
- function To_C (Item : Wide_Wide_Character) return char32_t;
+ -- To_C and To_Ada provide mappings between the Ada and C 32-bit character
+ -- types.
+
+ function To_C (Item : Wide_Wide_Character) return char32_t
+ with
+ Post => To_C'Result = char32_t (Item);
pragma Ada_05 (To_C);
- function To_Ada (Item : char32_t) return Wide_Wide_Character;
+ function To_Ada (Item : char32_t) return Wide_Wide_Character
+ with
+ Post => To_Ada'Result = Wide_Wide_Character (Item);
pragma Ada_05 (To_Ada);
type char32_array is array (size_t range <>) of aliased char32_t;
pragma Ada_05 (char32_array);
- function Is_Nul_Terminated (Item : char32_array) return Boolean;
+ function Is_Nul_Terminated (Item : char32_array) return Boolean
+ with
+ Post => Is_Nul_Terminated'Result = (for some C of Item => C = char32_nul);
pragma Ada_05 (Is_Nul_Terminated);
+ -- The result of Is_Nul_Terminated is True if Item contains char32_nul, and
+ -- is False otherwise.
+
+ function C_Length_Ghost (Item : char32_array) return size_t
+ with
+ Ghost,
+ Pre => Is_Nul_Terminated (Item),
+ Post => C_Length_Ghost'Result <= Item'Last - Item'First
+ and then Item (Item'First + C_Length_Ghost'Result) = char32_nul
+ and then (for all J in Item'First .. Item'First + C_Length_Ghost'Result
+ when J /= Item'First + C_Length_Ghost'Result =>
+ Item (J) /= char32_nul);
+ -- Ghost function to compute the length of a char32_array up to the first
+ -- char32_nul character.
+
+ -- The To_C and To_Ada subprograms that convert between Wide_Wide_String
+ -- and char32_array have analogous effects to the To_C and To_Ada
+ -- subprograms that convert between String and char_array, except
+ -- that char32_nul is used instead of nul.
function To_C
(Item : Wide_Wide_String;
- Append_Nul : Boolean := True) return char32_array;
+ Append_Nul : Boolean := True) return char32_array
+ with
+ Pre => not (Append_Nul = False and then Item'Length = 0),
+ Post => To_C'Result'First = 0
+ and then To_C'Result'Length =
+ (if Append_Nul then Item'Length + 1 else Item'Length)
+ and then (for all J in Item'Range =>
+ To_C'Result (size_t (J - Item'First)) = To_C (Item (J)))
+ and then
+ (if Append_Nul then To_C'Result (To_C'Result'Last) = char32_nul);
pragma Ada_05 (To_C);
function To_Ada
(Item : char32_array;
- Trim_Nul : Boolean := True) return Wide_Wide_String;
+ Trim_Nul : Boolean := True) return Wide_Wide_String
+ with
+ Pre => (if Trim_Nul then
+ Is_Nul_Terminated (Item)
+ and then C_Length_Ghost (Item) <= size_t (Natural'Last)
+ else
+ Item'Last - Item'First < size_t (Natural'Last)),
+ Post => To_Ada'Result'First = 1
+ and then To_Ada'Result'Length =
+ (if Trim_Nul then C_Length_Ghost (Item) else Item'Length)
+ and then (for all J in To_Ada'Result'Range =>
+ To_Ada'Result (J) =
+ To_Ada (Item (size_t (J) - 1 + Item'First)));
pragma Ada_05 (To_Ada);
procedure To_C
(Item : Wide_Wide_String;
Target : out char32_array;
Count : out size_t;
- Append_Nul : Boolean := True);
+ Append_Nul : Boolean := True)
+ with
+ Relaxed_Initialization => Target,
+ Pre => Target'Length >=
+ (if Append_Nul then Item'Length + 1 else Item'Length),
+ Post => Count = (if Append_Nul then Item'Length + 1 else Item'Length)
+ and then
+ (if Count /= 0 then
+ Target (Target'First .. Target'First + (Count - 1))'Initialized)
+ and then
+ (for all J in Item'Range =>
+ Target (Target'First + size_t (J - Item'First)) = To_C (Item (J)))
+ and then
+ (if Append_Nul then Target (Target'First + (Count - 1)) = char32_nul);
pragma Ada_05 (To_C);
procedure To_Ada
(Item : char32_array;
Target : out Wide_Wide_String;
Count : out Natural;
- Trim_Nul : Boolean := True);
+ Trim_Nul : Boolean := True)
+ with
+ Relaxed_Initialization => Target,
+ Pre => (if Trim_Nul then
+ Is_Nul_Terminated (Item)
+ and then C_Length_Ghost (Item) <= size_t (Target'Length)
+ else
+ Item'Last - Item'First < size_t (Target'Length)),
+ Post => Count =
+ (if Trim_Nul then Natural (C_Length_Ghost (Item)) else Item'Length)
+ and then
+ (if Count /= 0 then
+ Target (Target'First .. Target'First + (Count - 1))'Initialized)
+ and then
+ (for all J in Target'First .. Target'First + (Count - 1) =>
+ Target (J) =
+ To_Ada (Item (size_t (J - Target'First) + Item'First)));
pragma Ada_05 (To_Ada);
end Interfaces.C;
diff --git a/gcc/ada/libgnat/i-cobol.ads b/gcc/ada/libgnat/i-cobol.ads
index cf96e25..33fa1ae 100644
--- a/gcc/ada/libgnat/i-cobol.ads
+++ b/gcc/ada/libgnat/i-cobol.ads
@@ -61,7 +61,7 @@ package Interfaces.COBOL is
type COBOL_Character is new Character;
- Ada_To_COBOL : array (Standard.Character) of COBOL_Character := (
+ Ada_To_COBOL : array (Standard.Character) of COBOL_Character := [
COBOL_Character'Val (000), COBOL_Character'Val (001),
COBOL_Character'Val (002), COBOL_Character'Val (003),
COBOL_Character'Val (004), COBOL_Character'Val (005),
@@ -189,9 +189,9 @@ package Interfaces.COBOL is
COBOL_Character'Val (248), COBOL_Character'Val (249),
COBOL_Character'Val (250), COBOL_Character'Val (251),
COBOL_Character'Val (252), COBOL_Character'Val (253),
- COBOL_Character'Val (254), COBOL_Character'Val (255));
+ COBOL_Character'Val (254), COBOL_Character'Val (255)];
- COBOL_To_Ada : array (COBOL_Character) of Standard.Character := (
+ COBOL_To_Ada : array (COBOL_Character) of Standard.Character := [
Standard.Character'Val (000), Standard.Character'Val (001),
Standard.Character'Val (002), Standard.Character'Val (003),
Standard.Character'Val (004), Standard.Character'Val (005),
@@ -319,7 +319,7 @@ package Interfaces.COBOL is
Standard.Character'Val (248), Standard.Character'Val (249),
Standard.Character'Val (250), Standard.Character'Val (251),
Standard.Character'Val (252), Standard.Character'Val (253),
- Standard.Character'Val (254), Standard.Character'Val (255));
+ Standard.Character'Val (254), Standard.Character'Val (255)];
type Alphanumeric is array (Positive range <>) of COBOL_Character;
-- pragma Pack (Alphanumeric);
diff --git a/gcc/ada/libgnat/i-pacdec.adb b/gcc/ada/libgnat/i-pacdec.adb
index 8b8acc9..4364888 100644
--- a/gcc/ada/libgnat/i-pacdec.adb
+++ b/gcc/ada/libgnat/i-pacdec.adb
@@ -48,7 +48,7 @@ package body Interfaces.Packed_Decimal is
-- using table look up in this direction because divides are expensive.
Packed_Byte : constant array (00 .. 99) of Unsigned_8 :=
- (16#00#, 16#01#, 16#02#, 16#03#, 16#04#,
+ [16#00#, 16#01#, 16#02#, 16#03#, 16#04#,
16#05#, 16#06#, 16#07#, 16#08#, 16#09#,
16#10#, 16#11#, 16#12#, 16#13#, 16#14#,
16#15#, 16#16#, 16#17#, 16#18#, 16#19#,
@@ -67,7 +67,7 @@ package body Interfaces.Packed_Decimal is
16#80#, 16#81#, 16#82#, 16#83#, 16#84#,
16#85#, 16#86#, 16#87#, 16#88#, 16#89#,
16#90#, 16#91#, 16#92#, 16#93#, 16#94#,
- 16#95#, 16#96#, 16#97#, 16#98#, 16#99#);
+ 16#95#, 16#96#, 16#97#, 16#98#, 16#99#];
---------------------
-- Int32_To_Packed --
diff --git a/gcc/ada/libgnat/i-pacdec.ads b/gcc/ada/libgnat/i-pacdec.ads
index d68767f..bcfa1b7 100644
--- a/gcc/ada/libgnat/i-pacdec.ads
+++ b/gcc/ada/libgnat/i-pacdec.ads
@@ -91,7 +91,7 @@ package Interfaces.Packed_Decimal is
-- Range of possible byte lengths
Packed_Size : constant array (1 .. 18) of Byte_Length :=
- (01 => 01, -- Length in bytes for digits 1
+ [01 => 01, -- Length in bytes for digits 1
02 => 02, -- Length in bytes for digits 2
03 => 02, -- Length in bytes for digits 2
04 => 03, -- Length in bytes for digits 2
@@ -108,7 +108,7 @@ package Interfaces.Packed_Decimal is
15 => 08, -- Length in bytes for digits 2
16 => 09, -- Length in bytes for digits 2
17 => 09, -- Length in bytes for digits 2
- 18 => 10); -- Length in bytes for digits 2
+ 18 => 10]; -- Length in bytes for digits 2
-------------------------
-- Conversion Routines --
diff --git a/gcc/ada/libgnat/s-aridou.adb b/gcc/ada/libgnat/s-aridou.adb
index 67f2440..0a75f08 100644
--- a/gcc/ada/libgnat/s-aridou.adb
+++ b/gcc/ada/libgnat/s-aridou.adb
@@ -55,6 +55,15 @@ is
Double_Size : constant Natural := Double_Int'Size;
Single_Size : constant Natural := Double_Int'Size / 2;
+ -- Log of Single_Size in base 2, so that Single_Size = 2 ** Log_Single_Size
+ Log_Single_Size : constant Natural :=
+ (case Single_Size is
+ when 32 => 5,
+ when 64 => 6,
+ when 128 => 7,
+ when others => raise Program_Error)
+ with Ghost;
+
-- Power-of-two constants. Use the names Big_2xx32, Big_2xx63 and Big_2xx64
-- even if Single_Size might not be 32 and Double_Size might not be 64, as
-- this facilitates code and proof understanding, compared to more generic
@@ -66,6 +75,9 @@ is
pragma Warnings
(Off, "non-static constant in preelaborated unit",
Reason => "Ghost code is not compiled");
+ Big_0 : constant Big_Integer :=
+ Big (Double_Uns'(0))
+ with Ghost;
Big_2xx32 : constant Big_Integer :=
Big (Double_Int'(2 ** Single_Size))
with Ghost;
@@ -198,6 +210,20 @@ is
Ghost,
Post => abs (X * Y) = abs X * abs Y;
+ procedure Lemma_Mult_Non_Negative (X, Y : Big_Integer)
+ with
+ Ghost,
+ Pre => (X >= Big_0 and then Y >= Big_0)
+ or else (X <= Big_0 and then Y <= Big_0),
+ Post => X * Y >= Big_0;
+
+ procedure Lemma_Mult_Non_Positive (X, Y : Big_Integer)
+ with
+ Ghost,
+ Pre => (X <= Big_0 and then Y >= Big_0)
+ or else (X >= Big_0 and then Y <= Big_0),
+ Post => X * Y <= Big_0;
+
procedure Lemma_Abs_Rem_Commutation (X, Y : Big_Integer)
with
Ghost,
@@ -407,6 +433,11 @@ is
Pre => Y /= 0,
Post => X rem Y = X rem (-Y);
+ procedure Lemma_Not_In_Range_Big2xx64
+ with
+ Post => not In_Double_Int_Range (Big_2xx64)
+ and then not In_Double_Int_Range (-Big_2xx64);
+
procedure Lemma_Powers_Of_2 (M, N : Natural)
with
Ghost,
@@ -551,7 +582,10 @@ is
procedure Lemma_Mult_Commutation (X, Y : Double_Int) is null;
procedure Lemma_Mult_Commutation (X, Y, Z : Double_Uns) is null;
procedure Lemma_Mult_Distribution (X, Y, Z : Big_Integer) is null;
+ procedure Lemma_Mult_Non_Negative (X, Y : Big_Integer) is null;
+ procedure Lemma_Mult_Non_Positive (X, Y : Big_Integer) is null;
procedure Lemma_Neg_Rem (X, Y : Big_Integer) is null;
+ procedure Lemma_Not_In_Range_Big2xx64 is null;
procedure Lemma_Rem_Commutation (X, Y : Double_Uns) is null;
procedure Lemma_Rem_Is_Ident (X, Y : Big_Integer) is null;
procedure Lemma_Rem_Sign (X, Y : Big_Integer) is null;
@@ -722,21 +756,15 @@ is
-- Local lemmas
- function Is_Division_By_Zero_Case return Boolean is
- (Y = 0 or else Z = 0)
- with Ghost;
-
- function Is_Overflow_Case return Boolean is
- (not In_Double_Int_Range (Big (X) / (Big (Y) * Big (Z))))
- with
- Ghost,
- Pre => Y /= 0 and Z /= 0;
-
procedure Prove_Overflow_Case
with
Ghost,
Pre => X = Double_Int'First and then Big (Y) * Big (Z) = -1,
- Post => Is_Overflow_Case;
+ Post => not In_Double_Int_Range (Big (X) / (Big (Y) * Big (Z)))
+ and then not In_Double_Int_Range
+ (Round_Quotient (Big (X), Big (Y) * Big (Z),
+ Big (X) / (Big (Y) * Big (Z)),
+ Big (X) rem (Big (Y) * Big (Z))));
-- Proves the special case where -2**(Double_Size - 1) is divided by -1,
-- generating an overflow.
@@ -852,11 +880,7 @@ is
begin
if Yu = 0 or else Zu = 0 then
- pragma Assert (Is_Division_By_Zero_Case);
Raise_Error;
- pragma Annotate
- (GNATprove, Intentional, "call to nonreturning subprogram",
- "Constraint_Error is raised in case of division by zero");
end if;
pragma Assert (Mult /= 0);
@@ -998,9 +1022,6 @@ is
if X = Double_Int'First and then Du = 1 and then not Den_Pos then
Prove_Overflow_Case;
Raise_Error;
- pragma Annotate
- (GNATprove, Intentional, "call to nonreturning subprogram",
- "Constraint_Error is raised in case of overflow");
end if;
-- Perform the actual division
@@ -1624,11 +1645,10 @@ is
Quot : Big_Integer with Ghost;
Big_R : Big_Integer with Ghost;
Big_Q : Big_Integer with Ghost;
+ Inter : Natural with Ghost;
-- Local lemmas
- function Is_Division_By_Zero_Case return Boolean is (Z = 0) with Ghost;
-
procedure Prove_Dividend_Scaling
with
Ghost,
@@ -1666,13 +1686,61 @@ is
-- Proves correctness of the multiplication of divisor by quotient to
-- compute amount to subtract.
+ procedure Prove_Negative_Dividend
+ with
+ Ghost,
+ Pre => Z /= 0
+ and then Big (Qu) = abs Big_Q
+ and then In_Double_Int_Range (Big_Q)
+ and then Big (Ru) = abs Big_R
+ and then ((X >= 0 and Y < 0) or (X < 0 and Y >= 0))
+ and then Big_Q =
+ (if Round then Round_Quotient (Big (X) * Big (Y), Big (Z),
+ Big (X) * Big (Y) / Big (Z),
+ Big (X) * Big (Y) rem Big (Z))
+ else Big (X) * Big (Y) / Big (Z))
+ and then Big_R = Big (X) * Big (Y) rem Big (Z),
+ Post =>
+ (if Z > 0 then Big_Q <= Big_0
+ and then In_Double_Int_Range (-Big (Qu))
+ else Big_Q >= Big_0
+ and then In_Double_Int_Range (Big (Qu)))
+ and then In_Double_Int_Range (-Big (Ru));
+ -- Proves the sign of rounded quotient when dividend is non-positive
+
procedure Prove_Overflow
with
Ghost,
Pre => Z /= 0 and then Mult >= Big_2xx64 * Big (Double_Uns'(abs Z)),
- Post => not In_Double_Int_Range (Big (X) * Big (Y) / Big (Z));
+ Post => not In_Double_Int_Range (Big (X) * Big (Y) / Big (Z))
+ and then not In_Double_Int_Range
+ (Round_Quotient (Big (X) * Big (Y), Big (Z),
+ Big (X) * Big (Y) / Big (Z),
+ Big (X) * Big (Y) rem Big (Z)));
-- Proves overflow case when the quotient has at least 3 digits
+ procedure Prove_Positive_Dividend
+ with
+ Ghost,
+ Pre => Z /= 0
+ and then Big (Qu) = abs Big_Q
+ and then In_Double_Int_Range (Big_Q)
+ and then Big (Ru) = abs Big_R
+ and then ((X >= 0 and Y >= 0) or (X < 0 and Y < 0))
+ and then Big_Q =
+ (if Round then Round_Quotient (Big (X) * Big (Y), Big (Z),
+ Big (X) * Big (Y) / Big (Z),
+ Big (X) * Big (Y) rem Big (Z))
+ else Big (X) * Big (Y) / Big (Z))
+ and then Big_R = Big (X) * Big (Y) rem Big (Z),
+ Post =>
+ (if Z > 0 then Big_Q >= Big_0
+ and then In_Double_Int_Range (Big (Qu))
+ else Big_Q <= Big_0
+ and then In_Double_Int_Range (-Big (Qu)))
+ and then In_Double_Int_Range (Big (Ru));
+ -- Proves the sign of rounded quotient when dividend is non-negative
+
procedure Prove_Qd_Calculation_Part_1 (J : Integer)
with
Ghost,
@@ -1689,6 +1757,14 @@ is
-- by the first digit of the divisor is not an underestimate (so
-- readjusting down works).
+ procedure Prove_Q_Too_Big
+ with
+ Ghost,
+ Pre => In_Double_Int_Range (Big_Q)
+ and then abs Big_Q = Big_2xx64,
+ Post => False;
+ -- Proves the inconsistency when Q is equal to Big_2xx64
+
procedure Prove_Rescaling
with
Ghost,
@@ -1846,6 +1922,15 @@ is
Big (Double_Uns (S1)));
end Prove_Multiplication;
+ -----------------------------
+ -- Prove_Negative_Dividend --
+ -----------------------------
+
+ procedure Prove_Negative_Dividend is
+ begin
+ Lemma_Mult_Non_Positive (Big (X), Big (Y));
+ end Prove_Negative_Dividend;
+
--------------------
-- Prove_Overflow --
--------------------
@@ -1857,6 +1942,15 @@ is
Lemma_Abs_Div_Commutation (Big (X) * Big (Y), Big (Z));
end Prove_Overflow;
+ -----------------------------
+ -- Prove_Positive_Dividend --
+ -----------------------------
+
+ procedure Prove_Positive_Dividend is
+ begin
+ Lemma_Mult_Non_Negative (Big (X), Big (Y));
+ end Prove_Positive_Dividend;
+
---------------------------------
-- Prove_Qd_Calculation_Part_1 --
---------------------------------
@@ -1889,6 +1983,16 @@ is
end Prove_Qd_Calculation_Part_1;
---------------------
+ -- Prove_Q_Too_Big --
+ ---------------------
+
+ procedure Prove_Q_Too_Big is
+ begin
+ pragma Assert (Big_Q = Big_2xx64 or Big_Q = -Big_2xx64);
+ Lemma_Not_In_Range_Big2xx64;
+ end Prove_Q_Too_Big;
+
+ ---------------------
-- Prove_Rescaling --
---------------------
@@ -1974,11 +2078,7 @@ is
begin
if Z = 0 then
- pragma Assert (Is_Division_By_Zero_Case);
Raise_Error;
- pragma Annotate
- (GNATprove, Intentional, "call to nonreturning subprogram",
- "Constraint_Error is raised in case of division by zero");
end if;
Quot := Big (X) * Big (Y) / Big (Z);
@@ -2136,9 +2236,6 @@ is
Prove_Overflow;
Raise_Error;
- pragma Annotate
- (GNATprove, Intentional, "call to nonreturning subprogram",
- "Constraint_Error is raised in case of overflow");
-- Here we are dividing at most three digits by one digit
@@ -2159,9 +2256,6 @@ is
Lemma_Ge_Commutation (D (1) & D (2), Zu);
Prove_Overflow;
Raise_Error;
- pragma Annotate
- (GNATprove, Intentional, "call to nonreturning subprogram",
- "Constraint_Error is raised in case of overflow");
-- This is the complex case where we definitely have a double digit
-- divisor and a dividend of at least three digits. We use the classical
@@ -2177,6 +2271,7 @@ is
Mask := Single_Uns'Last;
Scale := 0;
+ Inter := 0;
pragma Assert (Big_2xx (Scale) = 1);
while Shift > 1 loop
@@ -2187,18 +2282,27 @@ is
pragma Loop_Invariant (Zu = Shift_Left (abs Z, Scale));
pragma Loop_Invariant (Big (Zu) =
Big (Double_Uns'(abs Z)) * Big_2xx (Scale));
+ pragma Loop_Invariant (Inter in 0 .. Log_Single_Size - 1);
+ pragma Loop_Invariant (Shift = 2 ** (Log_Single_Size - Inter));
pragma Loop_Invariant (Shift mod 2 = 0);
- pragma Annotate
- (GNATprove, False_Positive, "loop invariant",
- "Shift actually is a power of 2");
- -- Note : this scaling algorithm only works when Single_Size is a
- -- power of 2.
declare
+ -- Local ghost variables
+
Shift_Prev : constant Natural := Shift with Ghost;
Mask_Prev : constant Single_Uns := Mask with Ghost;
Zu_Prev : constant Double_Uns := Zu with Ghost;
+ -- Local lemmas
+
+ procedure Prove_Power
+ with
+ Ghost,
+ Pre => Inter in 0 .. Log_Single_Size - 1
+ and then Shift = 2 ** (Log_Single_Size - Inter),
+ Post => Shift / 2 = 2 ** (Log_Single_Size - (Inter + 1))
+ and then (Shift = 2 or (Shift / 2) mod 2 = 0);
+
procedure Prove_Shifting
with
Ghost,
@@ -2211,6 +2315,12 @@ is
and then (Hi (Zu_Prev) and Mask_Prev and not Mask) /= 0,
Post => (Hi (Zu) and Mask) /= 0;
+ -----------------
+ -- Prove_Power --
+ -----------------
+
+ procedure Prove_Power is null;
+
--------------------
-- Prove_Shifting --
--------------------
@@ -2218,8 +2328,11 @@ is
procedure Prove_Shifting is null;
begin
+ Prove_Power;
+
Shift := Shift / 2;
+ Inter := Inter + 1;
pragma Assert (Shift_Prev = 2 * Shift);
Mask := Shift_Left (Mask, Shift);
@@ -2306,7 +2419,29 @@ is
-- Loop to compute quotient digits, runs twice for Qd (1) and Qd (2)
declare
- Qd1 : Single_Uns := 0 with Ghost;
+ -- Local lemmas
+
+ procedure Prove_First_Iteration (X1, X2, X3, X4 : Single_Uns)
+ with
+ Ghost,
+ Pre => X1 = 0,
+ Post =>
+ Big_2xx32 * Big3 (X1, X2, X3) + Big (Double_Uns (X4))
+ = Big3 (X2, X3, X4);
+
+ ---------------------------
+ -- Prove_First_Iteration --
+ ---------------------------
+
+ procedure Prove_First_Iteration (X1, X2, X3, X4 : Single_Uns) is
+ null;
+
+ -- Local ghost variables
+
+ Qd1 : Single_Uns := 0 with Ghost;
+ D123 : constant Big_Integer := Big3 (D (1), D (2), D (3))
+ with Ghost;
+
begin
for J in 1 .. 2 loop
Lemma_Hi_Lo (D (J) & D (J + 1), D (J), D (J + 1));
@@ -2432,12 +2567,11 @@ is
if J = 1 then
Qd1 := Qd (1);
- pragma Assert
- (Big_2xx32 * Big_2xx32 * Big (Double_Uns (D (1))) = 0);
- pragma Assert
- (Mult * Big_2xx (Scale) =
- Big_2xx32 * Big3 (S1, S2, S3)
- + Big3 (D (2), D (3), D (4)));
+ Lemma_Substitution
+ (Mult * Big_2xx (Scale), Big_2xx32, D123,
+ Big3 (D (1), D (2), D (3)) + Big3 (S1, S2, S3),
+ Big (Double_Uns (D (4))));
+ Prove_First_Iteration (D (1), D (2), D (3), D (4));
Lemma_Substitution (Mult * Big_2xx (Scale), Big_2xx32,
Big3 (S1, S2, S3),
Big (Double_Uns (Qd1)) * Big (Zu),
@@ -2510,11 +2644,8 @@ is
-- an overflow when the quotient is too large.
if Qu = Double_Uns'Last then
- pragma Assert (abs Big_Q = Big_2xx64);
+ Prove_Q_Too_Big;
Raise_Error;
- pragma Annotate
- (GNATprove, Intentional, "call to nonreturning subprogram",
- "Constraint_Error is raised in case of overflow");
end if;
Lemma_Add_One (Qu);
@@ -2530,28 +2661,18 @@ is
-- Case of dividend (X * Y) sign positive
if (X >= 0 and then Y >= 0) or else (X < 0 and then Y < 0) then
- R := To_Pos_Int (Ru);
- pragma Annotate
- (GNATprove, Intentional, "precondition",
- "Constraint_Error is raised in case of overflow");
+ Prove_Positive_Dividend;
+ R := To_Pos_Int (Ru);
Q := (if Z > 0 then To_Pos_Int (Qu) else To_Neg_Int (Qu));
- pragma Annotate
- (GNATprove, Intentional, "precondition",
- "Constraint_Error is raised in case of overflow");
-- Case of dividend (X * Y) sign negative
else
- R := To_Neg_Int (Ru);
- pragma Annotate
- (GNATprove, Intentional, "precondition",
- "Constraint_Error is raised in case of overflow");
+ Prove_Negative_Dividend;
+ R := To_Neg_Int (Ru);
Q := (if Z > 0 then To_Neg_Int (Qu) else To_Pos_Int (Qu));
- pragma Annotate
- (GNATprove, Intentional, "precondition",
- "Constraint_Error is raised in case of overflow");
end if;
Prove_Sign_R;
diff --git a/gcc/ada/libgnat/s-arit32.adb b/gcc/ada/libgnat/s-arit32.adb
index f9cd7fe..ac6582f 100644
--- a/gcc/ada/libgnat/s-arit32.adb
+++ b/gcc/ada/libgnat/s-arit32.adb
@@ -29,9 +29,24 @@
-- --
------------------------------------------------------------------------------
+-- Preconditions, postconditions, 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.
+
+pragma Assertion_Policy (Pre => Ignore,
+ Post => Ignore,
+ Ghost => Ignore,
+ Loop_Invariant => Ignore,
+ Assert => Ignore);
+
+with Ada.Numerics.Big_Numbers.Big_Integers_Ghost;
+use Ada.Numerics.Big_Numbers.Big_Integers_Ghost;
with Ada.Unchecked_Conversion;
-package body System.Arith_32 is
+package body System.Arith_32
+ with SPARK_Mode
+is
pragma Suppress (Overflow_Check);
pragma Suppress (Range_Check);
@@ -43,27 +58,65 @@ package body System.Arith_32 is
function To_Int is new Ada.Unchecked_Conversion (Uns32, Int32);
+ package Unsigned_Conversion is new Unsigned_Conversions (Int => Uns32);
+
+ function Big (Arg : Uns32) return Big_Integer is
+ (Unsigned_Conversion.To_Big_Integer (Arg))
+ with Ghost;
+
+ package Unsigned_Conversion_64 is new Unsigned_Conversions (Int => Uns64);
+
+ function Big (Arg : Uns64) return Big_Integer is
+ (Unsigned_Conversion_64.To_Big_Integer (Arg))
+ with Ghost;
+
+ pragma Warnings
+ (Off, "non-preelaborable call not allowed in preelaborated unit",
+ Reason => "Ghost code is not compiled");
+ Big_0 : constant Big_Integer :=
+ Big (Uns32'(0))
+ with Ghost;
+ Big_2xx32 : constant Big_Integer :=
+ Big (Uns32'(2 ** 32 - 1)) + 1
+ with Ghost;
+ Big_2xx64 : constant Big_Integer :=
+ Big (Uns64'(2 ** 64 - 1)) + 1
+ with Ghost;
+ pragma Warnings
+ (On, "non-preelaborable call not allowed in preelaborated unit");
+
-----------------------
-- Local Subprograms --
-----------------------
function "abs" (X : Int32) return Uns32 is
(if X = Int32'First
- then 2**31
+ then Uns32'(2**31)
else Uns32 (Int32'(abs X)));
-- Convert absolute value of X to unsigned. Note that we can't just use
-- the expression of the Else since it overflows for X = Int32'First.
+ function Lo (A : Uns64) return Uns32 is (Uns32 (A and (2 ** 32 - 1)));
+ -- Low order half of 64-bit value
+
function Hi (A : Uns64) return Uns32 is (Uns32 (Shift_Right (A, 32)));
-- High order half of 64-bit value
- function To_Neg_Int (A : Uns32) return Int32;
+ function To_Neg_Int (A : Uns32) return Int32
+ with
+ Annotate => (GNATprove, Terminating),
+ Pre => In_Int32_Range (-Big (A)),
+ Post => Big (To_Neg_Int'Result) = -Big (A);
-- Convert to negative integer equivalent. If the input is in the range
-- 0 .. 2**31, then the corresponding nonpositive signed integer (obtained
-- by negating the given value) is returned, otherwise constraint error is
-- raised.
- function To_Pos_Int (A : Uns32) return Int32;
+ function To_Pos_Int (A : Uns32) return Int32
+ with
+ Annotate => (GNATprove, Terminating),
+ Pre => In_Int32_Range (Big (A)),
+ Post => Big (To_Pos_Int'Result) = Big (A);
-- Convert to positive integer equivalent. If the input is in the range
-- 0 .. 2**31 - 1, then the corresponding nonnegative signed integer is
-- returned, otherwise constraint error is raised.
@@ -72,6 +125,168 @@ package body System.Arith_32 is
pragma No_Return (Raise_Error);
-- Raise constraint error with appropriate message
+ ------------------
+ -- Local Lemmas --
+ ------------------
+
+ procedure Lemma_Abs_Commutation (X : Int32)
+ with
+ Ghost,
+ Post => abs (Big (X)) = Big (Uns32'(abs X));
+
+ procedure Lemma_Abs_Div_Commutation (X, Y : Big_Integer)
+ with
+ Ghost,
+ Pre => Y /= 0,
+ Post => abs (X / Y) = abs X / abs Y;
+
+ procedure Lemma_Abs_Mult_Commutation (X, Y : Big_Integer)
+ with
+ Ghost,
+ Post => abs (X * Y) = abs X * abs Y;
+
+ procedure Lemma_Abs_Rem_Commutation (X, Y : Big_Integer)
+ with
+ Ghost,
+ Pre => Y /= 0,
+ Post => abs (X rem Y) = (abs X) rem (abs Y);
+
+ procedure Lemma_Div_Commutation (X, Y : Uns64)
+ with
+ Ghost,
+ Pre => Y /= 0,
+ Post => Big (X) / Big (Y) = Big (X / Y);
+
+ procedure Lemma_Div_Ge (X, Y, Z : Big_Integer)
+ with
+ Ghost,
+ Pre => Z > 0 and then X >= Y * Z,
+ Post => X / Z >= Y;
+
+ procedure Lemma_Ge_Commutation (A, B : Uns32)
+ with
+ Ghost,
+ Pre => A >= B,
+ Post => Big (A) >= Big (B);
+
+ procedure Lemma_Hi_Lo (Xu : Uns64; Xhi, Xlo : Uns32)
+ with
+ Ghost,
+ Pre => Xhi = Hi (Xu) and Xlo = Lo (Xu),
+ Post => Big (Xu) = Big_2xx32 * Big (Xhi) + Big (Xlo);
+
+ procedure Lemma_Mult_Commutation (X, Y, Z : Uns64)
+ with
+ Ghost,
+ Pre => Big (X) * Big (Y) < Big_2xx64 and then Z = X * Y,
+ Post => Big (X) * Big (Y) = Big (Z);
+
+ procedure Lemma_Mult_Non_Negative (X, Y : Big_Integer)
+ with
+ Ghost,
+ Pre => (X >= Big_0 and then Y >= Big_0)
+ or else (X <= Big_0 and then Y <= Big_0),
+ Post => X * Y >= Big_0;
+
+ procedure Lemma_Mult_Non_Positive (X, Y : Big_Integer)
+ with
+ Ghost,
+ Pre => (X <= Big_0 and then Y >= Big_0)
+ or else (X >= Big_0 and then Y <= Big_0),
+ Post => X * Y <= Big_0;
+
+ procedure Lemma_Neg_Div (X, Y : Big_Integer)
+ with
+ Ghost,
+ Pre => Y /= 0,
+ Post => X / Y = (-X) / (-Y);
+
+ procedure Lemma_Neg_Rem (X, Y : Big_Integer)
+ with
+ Ghost,
+ Pre => Y /= 0,
+ Post => X rem Y = X rem (-Y);
+
+ procedure Lemma_Not_In_Range_Big2xx32
+ with
+ Post => not In_Int32_Range (Big_2xx32)
+ and then not In_Int32_Range (-Big_2xx32);
+
+ procedure Lemma_Rem_Commutation (X, Y : Uns64)
+ with
+ Ghost,
+ Pre => Y /= 0,
+ Post => Big (X) rem Big (Y) = Big (X rem Y);
+
+ -----------------------------
+ -- Local lemma null bodies --
+ -----------------------------
+
+ procedure Lemma_Abs_Commutation (X : Int32) is null;
+ procedure Lemma_Abs_Mult_Commutation (X, Y : Big_Integer) is null;
+ procedure Lemma_Div_Commutation (X, Y : Uns64) is null;
+ procedure Lemma_Div_Ge (X, Y, Z : Big_Integer) is null;
+ procedure Lemma_Ge_Commutation (A, B : Uns32) is null;
+ procedure Lemma_Mult_Commutation (X, Y, Z : Uns64) is null;
+ procedure Lemma_Mult_Non_Negative (X, Y : Big_Integer) is null;
+ procedure Lemma_Mult_Non_Positive (X, Y : Big_Integer) is null;
+ procedure Lemma_Neg_Rem (X, Y : Big_Integer) is null;
+ procedure Lemma_Not_In_Range_Big2xx32 is null;
+ procedure Lemma_Rem_Commutation (X, Y : Uns64) is null;
+
+ -------------------------------
+ -- Lemma_Abs_Div_Commutation --
+ -------------------------------
+
+ procedure Lemma_Abs_Div_Commutation (X, Y : Big_Integer) is
+ begin
+ if Y < 0 then
+ if X < 0 then
+ pragma Assert (abs (X / Y) = abs (X / (-Y)));
+ else
+ Lemma_Neg_Div (X, Y);
+ pragma Assert (abs (X / Y) = abs ((-X) / (-Y)));
+ end if;
+ end if;
+ end Lemma_Abs_Div_Commutation;
+
+ -------------------------------
+ -- Lemma_Abs_Rem_Commutation --
+ -------------------------------
+
+ procedure Lemma_Abs_Rem_Commutation (X, Y : Big_Integer) is
+ begin
+ if Y < 0 then
+ Lemma_Neg_Rem (X, Y);
+ if X < 0 then
+ pragma Assert (X rem Y = -((-X) rem (-Y)));
+ pragma Assert (abs (X rem Y) = (abs X) rem (abs Y));
+ else
+ pragma Assert (abs (X rem Y) = (abs X) rem (abs Y));
+ end if;
+ end if;
+ end Lemma_Abs_Rem_Commutation;
+
+ -----------------
+ -- Lemma_Hi_Lo --
+ -----------------
+
+ procedure Lemma_Hi_Lo (Xu : Uns64; Xhi, Xlo : Uns32) is
+ begin
+ pragma Assert (Uns64 (Xhi) = Xu / Uns64'(2 ** 32));
+ pragma Assert (Uns64 (Xlo) = Xu mod 2 ** 32);
+ end Lemma_Hi_Lo;
+
+ -------------------
+ -- Lemma_Neg_Div --
+ -------------------
+
+ procedure Lemma_Neg_Div (X, Y : Big_Integer) is
+ begin
+ pragma Assert ((-X) / (-Y) = -(X / (-Y)));
+ pragma Assert (X / (-Y) = -(X / Y));
+ end Lemma_Neg_Div;
+
-----------------
-- Raise_Error --
-----------------
@@ -79,6 +294,9 @@ package body System.Arith_32 is
procedure Raise_Error is
begin
raise Constraint_Error with "32-bit arithmetic overflow";
+ pragma Annotate
+ (GNATprove, Intentional, "exception might be raised",
+ "Procedure Raise_Error is called to signal input errors");
end Raise_Error;
-------------------
@@ -101,51 +319,252 @@ package body System.Arith_32 is
Ru : Uns32;
-- Unsigned quotient and remainder
+ -- Local ghost variables
+
+ Mult : constant Big_Integer := abs (Big (X) * Big (Y)) with Ghost;
+ Quot : Big_Integer with Ghost;
+ Big_R : Big_Integer with Ghost;
+ Big_Q : Big_Integer with Ghost;
+
+ -- Local lemmas
+
+ procedure Prove_Negative_Dividend
+ with
+ Ghost,
+ Pre => Z /= 0
+ and then ((X >= 0 and Y < 0) or (X < 0 and Y >= 0))
+ and then Big_Q =
+ (if Round then Round_Quotient (Big (X) * Big (Y), Big (Z),
+ Big (X) * Big (Y) / Big (Z),
+ Big (X) * Big (Y) rem Big (Z))
+ else Big (X) * Big (Y) / Big (Z)),
+ Post =>
+ (if Z > 0 then Big_Q <= Big_0 else Big_Q >= Big_0);
+ -- Proves the sign of rounded quotient when dividend is non-positive
+
+ procedure Prove_Overflow
+ with
+ Ghost,
+ Pre => Z /= 0 and then Mult >= Big_2xx32 * Big (Uns32'(abs Z)),
+ Post => not In_Int32_Range (Big (X) * Big (Y) / Big (Z))
+ and then not In_Int32_Range
+ (Round_Quotient (Big (X) * Big (Y), Big (Z),
+ Big (X) * Big (Y) / Big (Z),
+ Big (X) * Big (Y) rem Big (Z)));
+ -- Proves overflow case
+
+ procedure Prove_Positive_Dividend
+ with
+ Ghost,
+ Pre => Z /= 0
+ and then ((X >= 0 and Y >= 0) or (X < 0 and Y < 0))
+ and then Big_Q =
+ (if Round then Round_Quotient (Big (X) * Big (Y), Big (Z),
+ Big (X) * Big (Y) / Big (Z),
+ Big (X) * Big (Y) rem Big (Z))
+ else Big (X) * Big (Y) / Big (Z)),
+ Post =>
+ (if Z > 0 then Big_Q >= Big_0 else Big_Q <= Big_0);
+ -- Proves the sign of rounded quotient when dividend is non-negative
+
+ procedure Prove_Rounding_Case
+ with
+ Ghost,
+ Pre => Z /= 0
+ and then Quot = Big (X) * Big (Y) / Big (Z)
+ and then Big_R = Big (X) * Big (Y) rem Big (Z)
+ and then Big_Q =
+ Round_Quotient (Big (X) * Big (Y), Big (Z), Quot, Big_R)
+ and then Big (Ru) = abs Big_R
+ and then Big (Zu) = Big (Uns32'(abs Z)),
+ Post => abs Big_Q =
+ (if Ru > (Zu - Uns32'(1)) / Uns32'(2)
+ then abs Quot + 1
+ else abs Quot);
+ -- Proves correctness of the rounding of the unsigned quotient
+
+ procedure Prove_Sign_R
+ with
+ Ghost,
+ Pre => Z /= 0 and then Big_R = Big (X) * Big (Y) rem Big (Z),
+ Post => In_Int32_Range (Big_R);
+
+ procedure Prove_Signs
+ with
+ Ghost,
+ Pre => Z /= 0
+ and then Quot = Big (X) * Big (Y) / Big (Z)
+ and then Big_R = Big (X) * Big (Y) rem Big (Z)
+ and then Big_Q =
+ (if Round then
+ Round_Quotient (Big (X) * Big (Y), Big (Z), Quot, Big_R)
+ else Quot)
+ and then Big (Ru) = abs Big_R
+ and then Big (Qu) = abs Big_Q
+ and then In_Int32_Range (Big_Q)
+ and then In_Int32_Range (Big_R)
+ and then R =
+ (if (X >= 0) = (Y >= 0) then To_Pos_Int (Ru) else To_Neg_Int (Ru))
+ and then Q =
+ (if ((X >= 0) = (Y >= 0)) = (Z >= 0) then To_Pos_Int (Qu)
+ else To_Neg_Int (Qu)), -- need to ensure To_Pos_Int precondition
+ Post => Big (R) = Big_R and then Big (Q) = Big_Q;
+ -- Proves final signs match the intended result after the unsigned
+ -- division is done.
+
+ -----------------------------
+ -- Prove_Negative_Dividend --
+ -----------------------------
+
+ procedure Prove_Negative_Dividend is
+ begin
+ Lemma_Mult_Non_Positive (Big (X), Big (Y));
+ end Prove_Negative_Dividend;
+
+ --------------------
+ -- Prove_Overflow --
+ --------------------
+
+ procedure Prove_Overflow is
+ begin
+ Lemma_Div_Ge (Mult, Big_2xx32, Big (Uns32'(abs Z)));
+ Lemma_Abs_Commutation (Z);
+ Lemma_Abs_Div_Commutation (Big (X) * Big (Y), Big (Z));
+ end Prove_Overflow;
+
+ -----------------------------
+ -- Prove_Positive_Dividend --
+ -----------------------------
+
+ procedure Prove_Positive_Dividend is
+ begin
+ Lemma_Mult_Non_Negative (Big (X), Big (Y));
+ end Prove_Positive_Dividend;
+
+ -------------------------
+ -- Prove_Rounding_Case --
+ -------------------------
+
+ procedure Prove_Rounding_Case is
+ begin
+ if Same_Sign (Big (X) * Big (Y), Big (Z)) then
+ null;
+ end if;
+ end Prove_Rounding_Case;
+
+ ------------------
+ -- Prove_Sign_R --
+ ------------------
+
+ procedure Prove_Sign_R is
+ begin
+ pragma Assert (In_Int32_Range (Big (Z)));
+ end Prove_Sign_R;
+
+ -----------------
+ -- Prove_Signs --
+ -----------------
+
+ procedure Prove_Signs is null;
+
+ -- Start of processing for Scaled_Divide32
+
begin
-- First do the 64-bit multiplication
D := Uns64 (Xu) * Uns64 (Yu);
+ pragma Assert (Mult = Big (D));
+ Lemma_Hi_Lo (D, Hi (D), Lo (D));
+ pragma Assert (Mult = Big_2xx32 * Big (Hi (D)) + Big (Lo (D)));
+
+ -- If divisor is zero, raise error
+
+ if Z = 0 then
+ Raise_Error;
+ end if;
+
+ Quot := Big (X) * Big (Y) / Big (Z);
+ Big_R := Big (X) * Big (Y) rem Big (Z);
+ if Round then
+ Big_Q := Round_Quotient (Big (X) * Big (Y), Big (Z), Quot, Big_R);
+ else
+ Big_Q := Quot;
+ end if;
+
-- If dividend is too large, raise error
if Hi (D) >= Zu then
+ Lemma_Ge_Commutation (Hi (D), Zu);
+ pragma Assert (Mult >= Big_2xx32 * Big (Zu));
+ Prove_Overflow;
Raise_Error;
+ end if;
-- Then do the 64-bit division
- else
- Qu := Uns32 (D / Uns64 (Zu));
- Ru := Uns32 (D rem Uns64 (Zu));
- end if;
+ Qu := Uns32 (D / Uns64 (Zu));
+ Ru := Uns32 (D rem Uns64 (Zu));
+
+ Lemma_Abs_Div_Commutation (Big (X) * Big (Y), Big (Z));
+ Lemma_Abs_Rem_Commutation (Big (X) * Big (Y), Big (Z));
+ Lemma_Abs_Mult_Commutation (Big (X), Big (Y));
+ Lemma_Abs_Commutation (X);
+ Lemma_Abs_Commutation (Y);
+ Lemma_Abs_Commutation (Z);
+ Lemma_Mult_Commutation (Uns64 (Xu), Uns64 (Yu), D);
+ Lemma_Div_Commutation (D, Uns64 (Zu));
+ Lemma_Rem_Commutation (D, Uns64 (Zu));
+
+ pragma Assert (Big (Ru) = abs Big_R);
+ pragma Assert (Big (Qu) = abs Quot);
+ pragma Assert (Big (Zu) = Big (Uns32'(abs Z)));
-- Deal with rounding case
- if Round and then Ru > (Zu - Uns32'(1)) / Uns32'(2) then
+ if Round then
+ Prove_Rounding_Case;
- -- Protect against wrapping around when rounding, by signaling
- -- an overflow when the quotient is too large.
+ if Ru > (Zu - Uns32'(1)) / Uns32'(2) then
+ pragma Assert (abs Big_Q = Big (Qu) + 1);
- if Qu = Uns32'Last then
- Raise_Error;
- end if;
+ -- Protect against wrapping around when rounding, by signaling
+ -- an overflow when the quotient is too large.
- Qu := Qu + Uns32'(1);
+ if Qu = Uns32'Last then
+ pragma Assert (abs Big_Q = Big_2xx32);
+ Lemma_Not_In_Range_Big2xx32;
+ Raise_Error;
+ end if;
+
+ Qu := Qu + Uns32'(1);
+ end if;
end if;
+ pragma Assert (Big (Qu) = abs Big_Q);
+ pragma Assert (Big (Ru) = abs Big_R);
+
-- Set final signs (RM 4.5.5(27-30))
-- Case of dividend (X * Y) sign positive
if (X >= 0 and then Y >= 0) or else (X < 0 and then Y < 0) then
+ Prove_Positive_Dividend;
+
R := To_Pos_Int (Ru);
Q := (if Z > 0 then To_Pos_Int (Qu) else To_Neg_Int (Qu));
-- Case of dividend (X * Y) sign negative
else
+ Prove_Negative_Dividend;
+
R := To_Neg_Int (Ru);
Q := (if Z > 0 then To_Neg_Int (Qu) else To_Pos_Int (Qu));
end if;
+
+ Prove_Sign_R;
+ Prove_Signs;
end Scaled_Divide32;
----------------
diff --git a/gcc/ada/libgnat/s-arit32.ads b/gcc/ada/libgnat/s-arit32.ads
index 5dc197d..5163351 100644
--- a/gcc/ada/libgnat/s-arit32.ads
+++ b/gcc/ada/libgnat/s-arit32.ads
@@ -33,17 +33,79 @@
-- signed integer values in cases where either overflow checking is
-- required, or intermediate results are longer than 32 bits.
+-- 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);
+
with Interfaces;
+with Ada.Numerics.Big_Numbers.Big_Integers_Ghost;
-package System.Arith_32 is
- pragma Pure;
+package System.Arith_32
+ with Pure, SPARK_Mode
+is
+ use type Ada.Numerics.Big_Numbers.Big_Integers_Ghost.Big_Integer;
+ use type Interfaces.Integer_32;
subtype Int32 is Interfaces.Integer_32;
+ subtype Big_Integer is
+ Ada.Numerics.Big_Numbers.Big_Integers_Ghost.Big_Integer
+ with Ghost;
+
+ package Signed_Conversion is new
+ Ada.Numerics.Big_Numbers.Big_Integers_Ghost.Signed_Conversions
+ (Int => Int32);
+
+ function Big (Arg : Int32) return Big_Integer is
+ (Signed_Conversion.To_Big_Integer (Arg))
+ with Ghost;
+
+ function In_Int32_Range (Arg : Big_Integer) return Boolean is
+ (Ada.Numerics.Big_Numbers.Big_Integers_Ghost.In_Range
+ (Arg, Big (Int32'First), Big (Int32'Last)))
+ with Ghost;
+
+ function Same_Sign (X, Y : Big_Integer) return Boolean is
+ (X = Big (Int32'(0))
+ or else Y = Big (Int32'(0))
+ or else (X < Big (Int32'(0))) = (Y < Big (Int32'(0))))
+ with Ghost;
+
+ function Round_Quotient (X, Y, Q, R : Big_Integer) return Big_Integer is
+ (if abs R > (abs Y - Big (Int32'(1))) / Big (Int32'(2)) then
+ (if Same_Sign (X, Y) then Q + Big (Int32'(1))
+ else Q - Big (Int32'(1)))
+ else
+ Q)
+ with
+ Ghost,
+ Pre => Y /= 0 and then Q = X / Y and then R = X rem Y;
+
procedure Scaled_Divide32
(X, Y, Z : Int32;
Q, R : out Int32;
- Round : Boolean);
+ Round : Boolean)
+ with
+ Pre => Z /= 0
+ and then In_Int32_Range
+ (if Round then Round_Quotient (Big (X) * Big (Y), Big (Z),
+ Big (X) * Big (Y) / Big (Z),
+ Big (X) * Big (Y) rem Big (Z))
+ else Big (X) * Big (Y) / Big (Z)),
+ Post => Big (R) = Big (X) * Big (Y) rem Big (Z)
+ and then
+ (if Round then
+ Big (Q) = Round_Quotient (Big (X) * Big (Y), Big (Z),
+ Big (X) * Big (Y) / Big (Z), Big (R))
+ else
+ Big (Q) = Big (X) * Big (Y) / Big (Z));
-- Performs the division of (X * Y) / Z, storing the quotient in Q
-- and the remainder in R. Constraint_Error is raised if Z is zero,
-- or if the quotient does not fit in 32 bits. Round indicates if
diff --git a/gcc/ada/libgnat/s-arit64.ads b/gcc/ada/libgnat/s-arit64.ads
index fbfd0f6..9e8492d 100644
--- a/gcc/ada/libgnat/s-arit64.ads
+++ b/gcc/ada/libgnat/s-arit64.ads
@@ -60,7 +60,7 @@ is
subtype Big_Integer is
Ada.Numerics.Big_Numbers.Big_Integers_Ghost.Big_Integer
- with Ghost;
+ with Ghost;
package Signed_Conversion is new
Ada.Numerics.Big_Numbers.Big_Integers_Ghost.Signed_Conversions
@@ -91,7 +91,6 @@ is
function Multiply_With_Ovflo_Check64 (X, Y : Int64) return Int64
with
- Pure_Function,
Pre => In_Int64_Range (Big (X) * Big (Y)),
Post => Multiply_With_Ovflo_Check64'Result = X * Y;
pragma Export (C, Multiply_With_Ovflo_Check64, "__gnat_mulv64");
diff --git a/gcc/ada/libgnat/s-bitops.adb b/gcc/ada/libgnat/s-bitops.adb
index 45290d3..0535341 100644
--- a/gcc/ada/libgnat/s-bitops.adb
+++ b/gcc/ada/libgnat/s-bitops.adb
@@ -59,14 +59,14 @@ package body System.Bit_Ops is
-- The following is an array of masks used to mask the final byte, either
-- at the high end (big-endian case) or the low end (little-endian case).
- Masks : constant array (1 .. 7) of Packed_Byte := (
+ Masks : constant array (1 .. 7) of Packed_Byte := [
(1 - LE) * 2#1000_0000# + LE * 2#0000_0001#,
(1 - LE) * 2#1100_0000# + LE * 2#0000_0011#,
(1 - LE) * 2#1110_0000# + LE * 2#0000_0111#,
(1 - LE) * 2#1111_0000# + LE * 2#0000_1111#,
(1 - LE) * 2#1111_1000# + LE * 2#0001_1111#,
(1 - LE) * 2#1111_1100# + LE * 2#0011_1111#,
- (1 - LE) * 2#1111_1110# + LE * 2#0111_1111#);
+ (1 - LE) * 2#1111_1110# + LE * 2#0111_1111#];
-----------------------
-- Local Subprograms --
diff --git a/gcc/ada/libgnat/s-crc32.adb b/gcc/ada/libgnat/s-crc32.adb
index 9f34ed5..ea4446a 100644
--- a/gcc/ada/libgnat/s-crc32.adb
+++ b/gcc/ada/libgnat/s-crc32.adb
@@ -41,7 +41,7 @@ package body System.CRC32 is
-- than processing the byte bit by bit.
Table : constant array (CRC32 range 0 .. 255) of CRC32 :=
- (16#0000_0000#, 16#7707_3096#, 16#EE0E_612C#, 16#9909_51BA#,
+ [16#0000_0000#, 16#7707_3096#, 16#EE0E_612C#, 16#9909_51BA#,
16#076D_C419#, 16#706A_F48F#, 16#E963_A535#, 16#9E64_95A3#,
16#0EDB_8832#, 16#79DC_B8A4#, 16#E0D5_E91E#, 16#97D2_D988#,
16#09B6_4C2B#, 16#7EB1_7CBD#, 16#E7B8_2D07#, 16#90BF_1D91#,
@@ -104,7 +104,7 @@ package body System.CRC32 is
16#BDBD_F21C#, 16#CABA_C28A#, 16#53B3_9330#, 16#24B4_A3A6#,
16#BAD0_3605#, 16#CDD7_0693#, 16#54DE_5729#, 16#23D9_67BF#,
16#B366_7A2E#, 16#C461_4AB8#, 16#5D68_1B02#, 16#2A6F_2B94#,
- 16#B40B_BE37#, 16#C30C_8EA1#, 16#5A05_DF1B#, 16#2D02_EF8D#);
+ 16#B40B_BE37#, 16#C30C_8EA1#, 16#5A05_DF1B#, 16#2D02_EF8D#];
---------------
-- Get_Value --
diff --git a/gcc/ada/libgnat/s-gearop.adb b/gcc/ada/libgnat/s-gearop.adb
index 957efd5..92af09d 100644
--- a/gcc/ada/libgnat/s-gearop.adb
+++ b/gcc/ada/libgnat/s-gearop.adb
@@ -883,7 +883,7 @@ package body System.Generic_Array_Operations is
return R : Matrix (First_1 .. Check_Unit_Last (First_1, Order, First_1),
First_2 .. Check_Unit_Last (First_2, Order, First_2))
do
- R := (others => (others => Zero));
+ R := [others => [others => Zero]];
for J in 0 .. Order - 1 loop
R (First_1 + J, First_2 + J) := One;
@@ -902,7 +902,7 @@ package body System.Generic_Array_Operations is
is
begin
return R : Vector (First .. Check_Unit_Last (Index, Order, First)) do
- R := (others => Zero);
+ R := [others => Zero];
R (Index) := One;
end return;
end Unit_Vector;
diff --git a/gcc/ada/libgnat/s-genbig.adb b/gcc/ada/libgnat/s-genbig.adb
index 8d03f0a..47d8311 100644
--- a/gcc/ada/libgnat/s-genbig.adb
+++ b/gcc/ada/libgnat/s-genbig.adb
@@ -50,10 +50,10 @@ package body System.Generic_Bignums is
subtype LLI is Long_Long_Integer;
- One_Data : constant Digit_Vector (1 .. 1) := (1 => 1);
+ One_Data : constant Digit_Vector (1 .. 1) := [1];
-- Constant one
- Zero_Data : constant Digit_Vector (1 .. 0) := (1 .. 0 => 0);
+ Zero_Data : constant Digit_Vector (1 .. 0) := [];
-- Constant zero
-----------------------
@@ -332,7 +332,7 @@ package body System.Generic_Bignums is
elsif X.Len = 1 and then X.D (1) = 2 and then Y.D (1) < 32 then
declare
D : constant Digit_Vector (1 .. 1) :=
- (1 => Shift_Left (SD'(1), Natural (Y.D (1))));
+ [Shift_Left (SD'(1), Natural (Y.D (1)))];
begin
return Normalize (D, X.Neg);
end;
@@ -573,7 +573,7 @@ package body System.Generic_Bignums is
-------------
function Big_Mul (X, Y : Bignum) return Big_Integer is
- Result : Digit_Vector (1 .. X.Len + Y.Len) := (others => 0);
+ Result : Digit_Vector (1 .. X.Len + Y.Len) := [others => 0];
-- Accumulate result (max length of result is sum of operand lengths)
L : Length;
@@ -1149,22 +1149,22 @@ package body System.Generic_Bignums is
begin
if X = 0 then
- return Allocate_Big_Integer ((1 .. 0 => <>), False);
+ return Allocate_Big_Integer ([], False);
-- One word result
elsif X in -(2 ** 32 - 1) .. +(2 ** 32 - 1) then
- return Allocate_Big_Integer ((1 => SD (abs X)), X < 0);
+ return Allocate_Big_Integer ([SD (abs X)], X < 0);
-- Large negative number annoyance
elsif X = -2 ** 63 then
- return Allocate_Big_Integer ((2 ** 31, 0), True);
+ return Allocate_Big_Integer ([2 ** 31, 0], True);
elsif Long_Long_Long_Integer'Size = 128
and then X = Long_Long_Long_Integer'First
then
- return Allocate_Big_Integer ((2 ** 31, 0, 0, 0), True);
+ return Allocate_Big_Integer ([2 ** 31, 0, 0, 0], True);
-- Other negative numbers
@@ -1196,17 +1196,17 @@ package body System.Generic_Bignums is
function To_Bignum (X : Unsigned_128) return Big_Integer is
begin
if X = 0 then
- return Allocate_Big_Integer ((1 .. 0 => <>), False);
+ return Allocate_Big_Integer ([], False);
-- One word result
elsif X < 2 ** 32 then
- return Allocate_Big_Integer ((1 => SD (X)), False);
+ return Allocate_Big_Integer ([SD (X)], False);
-- Two word result
elsif Shift_Right (X, 32) < 2 ** 32 then
- return Allocate_Big_Integer ((SD (X / Base), SD (X mod Base)), False);
+ return Allocate_Big_Integer ([SD (X / Base), SD (X mod Base)], False);
-- Three or four word result
@@ -1241,7 +1241,7 @@ package body System.Generic_Bignums is
function To_String
(X : Bignum; Width : Natural := 0; Base : Positive := 10) return String
is
- Big_Base : aliased Bignum_Data := (1, False, (1 => SD (Base)));
+ Big_Base : aliased Bignum_Data := (1, False, [SD (Base)]);
function Add_Base (S : String) return String;
-- Add base information if Base /= 10
@@ -1285,7 +1285,7 @@ package body System.Generic_Bignums is
function Image (Arg : Bignum) return String is
begin
if Big_LT (Arg, Big_Base'Unchecked_Access) then
- return (1 => Hex_Chars (Natural (From_Bignum (Arg))));
+ return [Hex_Chars (Natural (From_Bignum (Arg)))];
else
declare
Div : aliased Big_Integer;
@@ -1315,8 +1315,8 @@ package body System.Generic_Bignums is
Min_Length : Natural;
Char : Character := ' ') return String is
begin
- return (1 .. Integer'Max (Integer (Min_Length) - Str'Length, 0)
- => Char) & Str;
+ return [1 .. Integer'Max (Integer (Min_Length) - Str'Length, 0)
+ => Char] & Str;
end Leading_Padding;
Zero : aliased Bignum_Data := (0, False, D => Zero_Data);
diff --git a/gcc/ada/libgnat/s-htable.adb b/gcc/ada/libgnat/s-htable.adb
index af2db2f..90bfc13 100644
--- a/gcc/ada/libgnat/s-htable.adb
+++ b/gcc/ada/libgnat/s-htable.adb
@@ -173,7 +173,7 @@ package body System.HTable is
begin
-- Use an aggregate for efficiency reasons
- Table := (others => Null_Ptr);
+ Table := [others => Null_Ptr];
end Reset;
---------
diff --git a/gcc/ada/libgnat/s-imgboo.adb b/gcc/ada/libgnat/s-imgboo.adb
index 69ee639..4c1f7c9 100644
--- a/gcc/ada/libgnat/s-imgboo.adb
+++ b/gcc/ada/libgnat/s-imgboo.adb
@@ -29,7 +29,17 @@
-- --
------------------------------------------------------------------------------
-package body System.Img_Bool is
+-- 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.
+
+pragma Assertion_Policy (Ghost => Ignore,
+ Loop_Invariant => Ignore,
+ Assert => Ignore);
+
+package body System.Img_Bool
+ with SPARK_Mode
+is
-------------------
-- Image_Boolean --
diff --git a/gcc/ada/libgnat/s-imgboo.ads b/gcc/ada/libgnat/s-imgboo.ads
index 45b3bfa..35de7ef 100644
--- a/gcc/ada/libgnat/s-imgboo.ads
+++ b/gcc/ada/libgnat/s-imgboo.ads
@@ -31,13 +31,33 @@
-- Boolean'Image
-package System.Img_Bool is
- pragma Pure;
+-- 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);
+
+with System.Val_Bool;
+
+package System.Img_Bool
+ with SPARK_Mode, Preelaborate
+is
procedure Image_Boolean
(V : Boolean;
S : in out String;
- P : out Natural);
+ P : out Natural)
+ with
+ Pre => S'First = 1
+ and then (if V then S'Length >= 4 else S'Length >= 5),
+ Post => (if V then P = 4 else P = 5)
+ and then System.Val_Bool.Is_Boolean_Image_Ghost (S (1 .. P))
+ and then System.Val_Bool.Value_Boolean (S (1 .. P)) = V;
-- Computes Boolean'Image (V) and stores the result in S (1 .. P)
-- setting the resulting value of P. The caller guarantees that S
-- is long enough to hold the result, and that S'First is 1.
diff --git a/gcc/ada/libgnat/s-imgcha.adb b/gcc/ada/libgnat/s-imgcha.adb
index bfcae49..8c58b19 100644
--- a/gcc/ada/libgnat/s-imgcha.adb
+++ b/gcc/ada/libgnat/s-imgcha.adb
@@ -48,7 +48,7 @@ package body System.Img_Char is
range Character'Val (16#00#) .. Character'Val (16#1F#);
C0 : constant array (C0_Range) of Cname :=
- (Character'Val (16#00#) => "NUL",
+ [Character'Val (16#00#) => "NUL",
Character'Val (16#01#) => "SOH",
Character'Val (16#02#) => "STX",
Character'Val (16#03#) => "ETX",
@@ -79,13 +79,13 @@ package body System.Img_Char is
Character'Val (16#1C#) => "FS ",
Character'Val (16#1D#) => "GS ",
Character'Val (16#1E#) => "RS ",
- Character'Val (16#1F#) => "US ");
+ Character'Val (16#1F#) => "US "];
subtype C1_Range is Character
range Character'Val (16#7F#) .. Character'Val (16#9F#);
C1 : constant array (C1_Range) of Cname :=
- (Character'Val (16#7F#) => "DEL",
+ [Character'Val (16#7F#) => "DEL",
Character'Val (16#80#) => "res",
Character'Val (16#81#) => "res",
Character'Val (16#82#) => "BPH",
@@ -117,7 +117,7 @@ package body System.Img_Char is
Character'Val (16#9C#) => "ST ",
Character'Val (16#9D#) => "OSC",
Character'Val (16#9E#) => "PM ",
- Character'Val (16#9F#) => "APC");
+ Character'Val (16#9F#) => "APC"];
begin
-- Control characters are represented by their names (RM 3.5(32))
diff --git a/gcc/ada/libgnat/s-os_lib.adb b/gcc/ada/libgnat/s-os_lib.adb
index 19f4cf7..7df06c4 100644
--- a/gcc/ada/libgnat/s-os_lib.adb
+++ b/gcc/ada/libgnat/s-os_lib.adb
@@ -29,8 +29,6 @@
-- --
------------------------------------------------------------------------------
-pragma Compiler_Unit_Warning;
-
with Ada.Unchecked_Conversion;
with Ada.Unchecked_Deallocation;
with System; use System;
diff --git a/gcc/ada/libgnat/s-powflt.ads b/gcc/ada/libgnat/s-powflt.ads
index 0967403..4dc490c 100644
--- a/gcc/ada/libgnat/s-powflt.ads
+++ b/gcc/ada/libgnat/s-powflt.ads
@@ -42,26 +42,26 @@ package System.Powten_Flt is
-- Largest power of ten exactly representable with a double Float
Powten : constant array (0 .. Maxpow, 1 .. 2) of Float :=
- (00 => (1.0E+00, 0.0),
- 01 => (1.0E+01, 0.0),
- 02 => (1.0E+02, 0.0),
- 03 => (1.0E+03, 0.0),
- 04 => (1.0E+04, 0.0),
- 05 => (1.0E+05, 0.0),
- 06 => (1.0E+06, 0.0),
- 07 => (1.0E+07, 0.0),
- 08 => (1.0E+08, 0.0),
- 09 => (1.0E+09, 0.0),
- 10 => (1.0E+10, 0.0),
- 11 => (1.0E+11, 1.0E+11 - Float'Machine (1.0E+11)),
- 12 => (1.0E+12, 1.0E+12 - Float'Machine (1.0E+12)),
- 13 => (1.0E+13, 1.0E+13 - Float'Machine (1.0E+13)),
- 14 => (1.0E+14, 1.0E+14 - Float'Machine (1.0E+14)),
- 15 => (1.0E+15, 1.0E+15 - Float'Machine (1.0E+15)),
- 16 => (1.0E+16, 1.0E+16 - Float'Machine (1.0E+16)),
- 17 => (1.0E+17, 1.0E+17 - Float'Machine (1.0E+17)),
- 18 => (1.0E+18, 1.0E+18 - Float'Machine (1.0E+18)),
- 19 => (1.0E+19, 1.0E+19 - Float'Machine (1.0E+19)),
- 20 => (1.0E+20, 1.0E+20 - Float'Machine (1.0E+20)));
+ [00 => [1.0E+00, 0.0],
+ 01 => [1.0E+01, 0.0],
+ 02 => [1.0E+02, 0.0],
+ 03 => [1.0E+03, 0.0],
+ 04 => [1.0E+04, 0.0],
+ 05 => [1.0E+05, 0.0],
+ 06 => [1.0E+06, 0.0],
+ 07 => [1.0E+07, 0.0],
+ 08 => [1.0E+08, 0.0],
+ 09 => [1.0E+09, 0.0],
+ 10 => [1.0E+10, 0.0],
+ 11 => [1.0E+11, 1.0E+11 - Float'Machine (1.0E+11)],
+ 12 => [1.0E+12, 1.0E+12 - Float'Machine (1.0E+12)],
+ 13 => [1.0E+13, 1.0E+13 - Float'Machine (1.0E+13)],
+ 14 => [1.0E+14, 1.0E+14 - Float'Machine (1.0E+14)],
+ 15 => [1.0E+15, 1.0E+15 - Float'Machine (1.0E+15)],
+ 16 => [1.0E+16, 1.0E+16 - Float'Machine (1.0E+16)],
+ 17 => [1.0E+17, 1.0E+17 - Float'Machine (1.0E+17)],
+ 18 => [1.0E+18, 1.0E+18 - Float'Machine (1.0E+18)],
+ 19 => [1.0E+19, 1.0E+19 - Float'Machine (1.0E+19)],
+ 20 => [1.0E+20, 1.0E+20 - Float'Machine (1.0E+20)]];
end System.Powten_Flt;
diff --git a/gcc/ada/libgnat/s-powlfl.ads b/gcc/ada/libgnat/s-powlfl.ads
index 7800f2f..0ae36ec 100644
--- a/gcc/ada/libgnat/s-powlfl.ads
+++ b/gcc/ada/libgnat/s-powlfl.ads
@@ -42,50 +42,50 @@ package System.Powten_LFlt is
-- Largest power of ten exactly representable with a double Long_Float
Powten : constant array (0 .. Maxpow, 1 .. 2) of Long_Float :=
- (00 => (1.0E+00, 0.0),
- 01 => (1.0E+01, 0.0),
- 02 => (1.0E+02, 0.0),
- 03 => (1.0E+03, 0.0),
- 04 => (1.0E+04, 0.0),
- 05 => (1.0E+05, 0.0),
- 06 => (1.0E+06, 0.0),
- 07 => (1.0E+07, 0.0),
- 08 => (1.0E+08, 0.0),
- 09 => (1.0E+09, 0.0),
- 10 => (1.0E+10, 0.0),
- 11 => (1.0E+11, 0.0),
- 12 => (1.0E+12, 0.0),
- 13 => (1.0E+13, 0.0),
- 14 => (1.0E+14, 0.0),
- 15 => (1.0E+15, 0.0),
- 16 => (1.0E+16, 0.0),
- 17 => (1.0E+17, 0.0),
- 18 => (1.0E+18, 0.0),
- 19 => (1.0E+19, 0.0),
- 20 => (1.0E+20, 0.0),
- 21 => (1.0E+21, 0.0),
- 22 => (1.0E+22, 0.0),
- 23 => (1.0E+23, 1.0E+23 - Long_Float'Machine (1.0E+23)),
- 24 => (1.0E+24, 1.0E+24 - Long_Float'Machine (1.0E+24)),
- 25 => (1.0E+25, 1.0E+25 - Long_Float'Machine (1.0E+25)),
- 26 => (1.0E+26, 1.0E+26 - Long_Float'Machine (1.0E+26)),
- 27 => (1.0E+27, 1.0E+27 - Long_Float'Machine (1.0E+27)),
- 28 => (1.0E+28, 1.0E+28 - Long_Float'Machine (1.0E+28)),
- 29 => (1.0E+29, 1.0E+29 - Long_Float'Machine (1.0E+29)),
- 30 => (1.0E+30, 1.0E+30 - Long_Float'Machine (1.0E+30)),
- 31 => (1.0E+31, 1.0E+31 - Long_Float'Machine (1.0E+31)),
- 32 => (1.0E+32, 1.0E+32 - Long_Float'Machine (1.0E+32)),
- 33 => (1.0E+33, 1.0E+33 - Long_Float'Machine (1.0E+33)),
- 34 => (1.0E+34, 1.0E+34 - Long_Float'Machine (1.0E+34)),
- 35 => (1.0E+35, 1.0E+35 - Long_Float'Machine (1.0E+35)),
- 36 => (1.0E+36, 1.0E+36 - Long_Float'Machine (1.0E+36)),
- 37 => (1.0E+37, 1.0E+37 - Long_Float'Machine (1.0E+37)),
- 38 => (1.0E+38, 1.0E+38 - Long_Float'Machine (1.0E+38)),
- 39 => (1.0E+39, 1.0E+39 - Long_Float'Machine (1.0E+39)),
- 40 => (1.0E+40, 1.0E+40 - Long_Float'Machine (1.0E+40)),
- 41 => (1.0E+41, 1.0E+41 - Long_Float'Machine (1.0E+41)),
- 42 => (1.0E+42, 1.0E+42 - Long_Float'Machine (1.0E+42)),
- 43 => (1.0E+43, 1.0E+43 - Long_Float'Machine (1.0E+43)),
- 44 => (1.0E+44, 1.0E+44 - Long_Float'Machine (1.0E+44)));
+ [00 => [1.0E+00, 0.0],
+ 01 => [1.0E+01, 0.0],
+ 02 => [1.0E+02, 0.0],
+ 03 => [1.0E+03, 0.0],
+ 04 => [1.0E+04, 0.0],
+ 05 => [1.0E+05, 0.0],
+ 06 => [1.0E+06, 0.0],
+ 07 => [1.0E+07, 0.0],
+ 08 => [1.0E+08, 0.0],
+ 09 => [1.0E+09, 0.0],
+ 10 => [1.0E+10, 0.0],
+ 11 => [1.0E+11, 0.0],
+ 12 => [1.0E+12, 0.0],
+ 13 => [1.0E+13, 0.0],
+ 14 => [1.0E+14, 0.0],
+ 15 => [1.0E+15, 0.0],
+ 16 => [1.0E+16, 0.0],
+ 17 => [1.0E+17, 0.0],
+ 18 => [1.0E+18, 0.0],
+ 19 => [1.0E+19, 0.0],
+ 20 => [1.0E+20, 0.0],
+ 21 => [1.0E+21, 0.0],
+ 22 => [1.0E+22, 0.0],
+ 23 => [1.0E+23, 1.0E+23 - Long_Float'Machine (1.0E+23)],
+ 24 => [1.0E+24, 1.0E+24 - Long_Float'Machine (1.0E+24)],
+ 25 => [1.0E+25, 1.0E+25 - Long_Float'Machine (1.0E+25)],
+ 26 => [1.0E+26, 1.0E+26 - Long_Float'Machine (1.0E+26)],
+ 27 => [1.0E+27, 1.0E+27 - Long_Float'Machine (1.0E+27)],
+ 28 => [1.0E+28, 1.0E+28 - Long_Float'Machine (1.0E+28)],
+ 29 => [1.0E+29, 1.0E+29 - Long_Float'Machine (1.0E+29)],
+ 30 => [1.0E+30, 1.0E+30 - Long_Float'Machine (1.0E+30)],
+ 31 => [1.0E+31, 1.0E+31 - Long_Float'Machine (1.0E+31)],
+ 32 => [1.0E+32, 1.0E+32 - Long_Float'Machine (1.0E+32)],
+ 33 => [1.0E+33, 1.0E+33 - Long_Float'Machine (1.0E+33)],
+ 34 => [1.0E+34, 1.0E+34 - Long_Float'Machine (1.0E+34)],
+ 35 => [1.0E+35, 1.0E+35 - Long_Float'Machine (1.0E+35)],
+ 36 => [1.0E+36, 1.0E+36 - Long_Float'Machine (1.0E+36)],
+ 37 => [1.0E+37, 1.0E+37 - Long_Float'Machine (1.0E+37)],
+ 38 => [1.0E+38, 1.0E+38 - Long_Float'Machine (1.0E+38)],
+ 39 => [1.0E+39, 1.0E+39 - Long_Float'Machine (1.0E+39)],
+ 40 => [1.0E+40, 1.0E+40 - Long_Float'Machine (1.0E+40)],
+ 41 => [1.0E+41, 1.0E+41 - Long_Float'Machine (1.0E+41)],
+ 42 => [1.0E+42, 1.0E+42 - Long_Float'Machine (1.0E+42)],
+ 43 => [1.0E+43, 1.0E+43 - Long_Float'Machine (1.0E+43)],
+ 44 => [1.0E+44, 1.0E+44 - Long_Float'Machine (1.0E+44)]];
end System.Powten_LFlt;
diff --git a/gcc/ada/libgnat/s-powllf.ads b/gcc/ada/libgnat/s-powllf.ads
index b1f8ae9..eaba6c1 100644
--- a/gcc/ada/libgnat/s-powllf.ads
+++ b/gcc/ada/libgnat/s-powllf.ads
@@ -44,60 +44,60 @@ package System.Powten_LLF is
-- Largest power of ten exactly representable with a double Long_Long_Float
Powten : constant array (0 .. 54, 1 .. 2) of Long_Long_Float :=
- (00 => (1.0E+00, 0.0),
- 01 => (1.0E+01, 0.0),
- 02 => (1.0E+02, 0.0),
- 03 => (1.0E+03, 0.0),
- 04 => (1.0E+04, 0.0),
- 05 => (1.0E+05, 0.0),
- 06 => (1.0E+06, 0.0),
- 07 => (1.0E+07, 0.0),
- 08 => (1.0E+08, 0.0),
- 09 => (1.0E+09, 0.0),
- 10 => (1.0E+10, 0.0),
- 11 => (1.0E+11, 0.0),
- 12 => (1.0E+12, 0.0),
- 13 => (1.0E+13, 0.0),
- 14 => (1.0E+14, 0.0),
- 15 => (1.0E+15, 0.0),
- 16 => (1.0E+16, 0.0),
- 17 => (1.0E+17, 0.0),
- 18 => (1.0E+18, 0.0),
- 19 => (1.0E+19, 0.0),
- 20 => (1.0E+20, 0.0),
- 21 => (1.0E+21, 0.0),
- 22 => (1.0E+22, 0.0),
- 23 => (1.0E+23, 1.0E+23 - Long_Long_Float'Machine (1.0E+23)),
- 24 => (1.0E+24, 1.0E+24 - Long_Long_Float'Machine (1.0E+24)),
- 25 => (1.0E+25, 1.0E+25 - Long_Long_Float'Machine (1.0E+25)),
- 26 => (1.0E+26, 1.0E+26 - Long_Long_Float'Machine (1.0E+26)),
- 27 => (1.0E+27, 1.0E+27 - Long_Long_Float'Machine (1.0E+27)),
- 28 => (1.0E+28, 1.0E+28 - Long_Long_Float'Machine (1.0E+28)),
- 29 => (1.0E+29, 1.0E+29 - Long_Long_Float'Machine (1.0E+29)),
- 30 => (1.0E+30, 1.0E+30 - Long_Long_Float'Machine (1.0E+30)),
- 31 => (1.0E+31, 1.0E+31 - Long_Long_Float'Machine (1.0E+31)),
- 32 => (1.0E+32, 1.0E+32 - Long_Long_Float'Machine (1.0E+32)),
- 33 => (1.0E+33, 1.0E+33 - Long_Long_Float'Machine (1.0E+33)),
- 34 => (1.0E+34, 1.0E+34 - Long_Long_Float'Machine (1.0E+34)),
- 35 => (1.0E+35, 1.0E+35 - Long_Long_Float'Machine (1.0E+35)),
- 36 => (1.0E+36, 1.0E+36 - Long_Long_Float'Machine (1.0E+36)),
- 37 => (1.0E+37, 1.0E+37 - Long_Long_Float'Machine (1.0E+37)),
- 38 => (1.0E+38, 1.0E+38 - Long_Long_Float'Machine (1.0E+38)),
- 39 => (1.0E+39, 1.0E+39 - Long_Long_Float'Machine (1.0E+39)),
- 40 => (1.0E+40, 1.0E+40 - Long_Long_Float'Machine (1.0E+40)),
- 41 => (1.0E+41, 1.0E+41 - Long_Long_Float'Machine (1.0E+41)),
- 42 => (1.0E+42, 1.0E+42 - Long_Long_Float'Machine (1.0E+42)),
- 43 => (1.0E+43, 1.0E+43 - Long_Long_Float'Machine (1.0E+43)),
- 44 => (1.0E+44, 1.0E+44 - Long_Long_Float'Machine (1.0E+44)),
- 45 => (1.0E+45, 1.0E+45 - Long_Long_Float'Machine (1.0E+45)),
- 46 => (1.0E+46, 1.0E+46 - Long_Long_Float'Machine (1.0E+46)),
- 47 => (1.0E+47, 1.0E+47 - Long_Long_Float'Machine (1.0E+47)),
- 48 => (1.0E+48, 1.0E+48 - Long_Long_Float'Machine (1.0E+48)),
- 49 => (1.0E+49, 1.0E+49 - Long_Long_Float'Machine (1.0E+49)),
- 50 => (1.0E+50, 1.0E+50 - Long_Long_Float'Machine (1.0E+50)),
- 51 => (1.0E+51, 1.0E+51 - Long_Long_Float'Machine (1.0E+51)),
- 52 => (1.0E+52, 1.0E+52 - Long_Long_Float'Machine (1.0E+52)),
- 53 => (1.0E+53, 1.0E+53 - Long_Long_Float'Machine (1.0E+53)),
- 54 => (1.0E+54, 1.0E+54 - Long_Long_Float'Machine (1.0E+54)));
+ [00 => [1.0E+00, 0.0],
+ 01 => [1.0E+01, 0.0],
+ 02 => [1.0E+02, 0.0],
+ 03 => [1.0E+03, 0.0],
+ 04 => [1.0E+04, 0.0],
+ 05 => [1.0E+05, 0.0],
+ 06 => [1.0E+06, 0.0],
+ 07 => [1.0E+07, 0.0],
+ 08 => [1.0E+08, 0.0],
+ 09 => [1.0E+09, 0.0],
+ 10 => [1.0E+10, 0.0],
+ 11 => [1.0E+11, 0.0],
+ 12 => [1.0E+12, 0.0],
+ 13 => [1.0E+13, 0.0],
+ 14 => [1.0E+14, 0.0],
+ 15 => [1.0E+15, 0.0],
+ 16 => [1.0E+16, 0.0],
+ 17 => [1.0E+17, 0.0],
+ 18 => [1.0E+18, 0.0],
+ 19 => [1.0E+19, 0.0],
+ 20 => [1.0E+20, 0.0],
+ 21 => [1.0E+21, 0.0],
+ 22 => [1.0E+22, 0.0],
+ 23 => [1.0E+23, 1.0E+23 - Long_Long_Float'Machine (1.0E+23)],
+ 24 => [1.0E+24, 1.0E+24 - Long_Long_Float'Machine (1.0E+24)],
+ 25 => [1.0E+25, 1.0E+25 - Long_Long_Float'Machine (1.0E+25)],
+ 26 => [1.0E+26, 1.0E+26 - Long_Long_Float'Machine (1.0E+26)],
+ 27 => [1.0E+27, 1.0E+27 - Long_Long_Float'Machine (1.0E+27)],
+ 28 => [1.0E+28, 1.0E+28 - Long_Long_Float'Machine (1.0E+28)],
+ 29 => [1.0E+29, 1.0E+29 - Long_Long_Float'Machine (1.0E+29)],
+ 30 => [1.0E+30, 1.0E+30 - Long_Long_Float'Machine (1.0E+30)],
+ 31 => [1.0E+31, 1.0E+31 - Long_Long_Float'Machine (1.0E+31)],
+ 32 => [1.0E+32, 1.0E+32 - Long_Long_Float'Machine (1.0E+32)],
+ 33 => [1.0E+33, 1.0E+33 - Long_Long_Float'Machine (1.0E+33)],
+ 34 => [1.0E+34, 1.0E+34 - Long_Long_Float'Machine (1.0E+34)],
+ 35 => [1.0E+35, 1.0E+35 - Long_Long_Float'Machine (1.0E+35)],
+ 36 => [1.0E+36, 1.0E+36 - Long_Long_Float'Machine (1.0E+36)],
+ 37 => [1.0E+37, 1.0E+37 - Long_Long_Float'Machine (1.0E+37)],
+ 38 => [1.0E+38, 1.0E+38 - Long_Long_Float'Machine (1.0E+38)],
+ 39 => [1.0E+39, 1.0E+39 - Long_Long_Float'Machine (1.0E+39)],
+ 40 => [1.0E+40, 1.0E+40 - Long_Long_Float'Machine (1.0E+40)],
+ 41 => [1.0E+41, 1.0E+41 - Long_Long_Float'Machine (1.0E+41)],
+ 42 => [1.0E+42, 1.0E+42 - Long_Long_Float'Machine (1.0E+42)],
+ 43 => [1.0E+43, 1.0E+43 - Long_Long_Float'Machine (1.0E+43)],
+ 44 => [1.0E+44, 1.0E+44 - Long_Long_Float'Machine (1.0E+44)],
+ 45 => [1.0E+45, 1.0E+45 - Long_Long_Float'Machine (1.0E+45)],
+ 46 => [1.0E+46, 1.0E+46 - Long_Long_Float'Machine (1.0E+46)],
+ 47 => [1.0E+47, 1.0E+47 - Long_Long_Float'Machine (1.0E+47)],
+ 48 => [1.0E+48, 1.0E+48 - Long_Long_Float'Machine (1.0E+48)],
+ 49 => [1.0E+49, 1.0E+49 - Long_Long_Float'Machine (1.0E+49)],
+ 50 => [1.0E+50, 1.0E+50 - Long_Long_Float'Machine (1.0E+50)],
+ 51 => [1.0E+51, 1.0E+51 - Long_Long_Float'Machine (1.0E+51)],
+ 52 => [1.0E+52, 1.0E+52 - Long_Long_Float'Machine (1.0E+52)],
+ 53 => [1.0E+53, 1.0E+53 - Long_Long_Float'Machine (1.0E+53)],
+ 54 => [1.0E+54, 1.0E+54 - Long_Long_Float'Machine (1.0E+54)]];
end System.Powten_LLF;
diff --git a/gcc/ada/libgnat/s-rannum.adb b/gcc/ada/libgnat/s-rannum.adb
index 92a91a6..147cc9a 100644
--- a/gcc/ada/libgnat/s-rannum.adb
+++ b/gcc/ada/libgnat/s-rannum.adb
@@ -109,7 +109,7 @@ is
Upper_Mask : constant := 2**31;
Matrix_A : constant array (State_Val range 0 .. 1) of State_Val
- := (0, 16#9908b0df#);
+ := [0, 16#9908b0df#];
-- The twist transformation is represented by a matrix of the form
--
-- [ 0 I(31) ]
@@ -275,16 +275,16 @@ is
Trailing_Ones : constant array (Unsigned_32 range 0 .. 15)
of Bit_Count :=
- (2#00000# => 0, 2#00001# => 1, 2#00010# => 0, 2#00011# => 2,
+ [2#00000# => 0, 2#00001# => 1, 2#00010# => 0, 2#00011# => 2,
2#00100# => 0, 2#00101# => 1, 2#00110# => 0, 2#00111# => 3,
2#01000# => 0, 2#01001# => 1, 2#01010# => 0, 2#01011# => 2,
- 2#01100# => 0, 2#01101# => 1, 2#01110# => 0, 2#01111# => 4);
+ 2#01100# => 0, 2#01101# => 1, 2#01110# => 0, 2#01111# => 4];
Pow_Tab : constant array (Bit_Count range 0 .. 3) of Real
- := (0 => 2.0**(0 - T'Machine_Mantissa),
+ := [0 => 2.0**(0 - T'Machine_Mantissa),
1 => 2.0**(-1 - T'Machine_Mantissa),
2 => 2.0**(-2 - T'Machine_Mantissa),
- 3 => 2.0**(-3 - T'Machine_Mantissa));
+ 3 => 2.0**(-3 - T'Machine_Mantissa)];
Extra_Bits : constant Natural :=
(Unsigned'Size - T'Machine_Mantissa + 1);
@@ -662,7 +662,7 @@ is
Result : Image_String;
begin
- Result := (others => ' ');
+ Result := [others => ' '];
for J in Of_State'Range loop
Insert_Image (Result, J, Of_State (J));
@@ -675,7 +675,7 @@ is
Result : Image_String;
begin
- Result := (others => ' ');
+ Result := [others => ' '];
for J in 0 .. N - 1 loop
Insert_Image (Result, J, Gen.S ((J + Gen.I) mod N));
end loop;
diff --git a/gcc/ada/libgnat/s-rannum.ads b/gcc/ada/libgnat/s-rannum.ads
index 99ed57d..24c8d7f 100644
--- a/gcc/ada/libgnat/s-rannum.ads
+++ b/gcc/ada/libgnat/s-rannum.ads
@@ -157,7 +157,7 @@ private
Writable : Writable_Access (Generator'Access);
-- This self reference allows functions to modify Generator arguments
- S : State := (others => 0);
+ S : State := [others => 0];
-- The shift register, a circular buffer
I : Integer := N;
diff --git a/gcc/ada/libgnat/s-regexp.adb b/gcc/ada/libgnat/s-regexp.adb
index 8f1940a..bb21ef7 100644
--- a/gcc/ada/libgnat/s-regexp.adb
+++ b/gcc/ada/libgnat/s-regexp.adb
@@ -124,7 +124,7 @@ package body System.Regexp is
-- The pattern which is really compiled (when the pattern is case
-- insensitive, we convert this string to lower-cases).
- Map : Mapping := (others => 0);
+ Map : Mapping := [others => 0];
-- Mapping between characters and columns in the tables
Alphabet_Size : Column_Index := 0;
@@ -1103,7 +1103,7 @@ package body System.Regexp is
-- Start of processing for Create_Primary_Table
begin
- Table.all := (others => (others => 0));
+ Table.all := [others => [others => 0]];
Create_Simple (S'First, S'Last, Start_State, End_State);
Num_States := Current_State;
end Create_Primary_Table;
@@ -1372,7 +1372,7 @@ package body System.Regexp is
-- Start of processing for Create_Primary_Table_Glob
begin
- Table.all := (others => (others => 0));
+ Table.all := [others => [others => 0]];
Create_Simple (S'First, S'Last, Start_State, End_State);
Num_States := Current_State;
end Create_Primary_Table_Glob;
@@ -1392,7 +1392,7 @@ package body System.Regexp is
pragma Pack (Meta_State);
-- Whether a state from first_table belongs to a metastate.
- No_States : constant Meta_State := (others => False);
+ No_States : constant Meta_State := [others => False];
type Meta_States_Array is array (State_Index range <>) of Meta_State;
type Meta_States_List is access all Meta_States_Array;
@@ -1444,25 +1444,25 @@ package body System.Regexp is
if Meta_States = null then
Meta_States := new Meta_States_Array
(1 .. State_Index'Max (Last_Index, Meta) + 1);
- Meta_States (Meta_States'Range) := (others => No_States);
+ Meta_States (Meta_States'Range) := [others => No_States];
Table := new Meta_States_Transition_Arr
(1 .. State_Index'Max (Last_Index, Meta) + 1);
- Table.all := (others => (others => 0));
+ Table.all := [others => [others => 0]];
elsif Meta > Meta_States'Last then
Meta_States := new Meta_States_Array
(1 .. State_Index'Max (2 * Tmp'Last, Meta));
Meta_States (Tmp'Range) := Tmp.all;
Meta_States (Tmp'Last + 1 .. Meta_States'Last) :=
- (others => No_States);
+ [others => No_States];
Unchecked_Free (Tmp);
Table := new Meta_States_Transition_Arr
(1 .. State_Index'Max (2 * Tmp2'Last, Meta) + 1);
Table (Tmp2'Range) := Tmp2.all;
Table (Tmp2'Last + 1 .. Table'Last) :=
- (others => (others => 0));
+ [others => [others => 0]];
Unchecked_Free (Tmp2);
end if;
end Ensure_Meta_State;
@@ -1595,9 +1595,9 @@ package body System.Regexp is
R => new Regexp_Value'
(Alphabet_Size => 0,
Num_States => 1,
- Map => (others => 0),
- States => (others => (others => 1)),
- Is_Final => (others => True),
+ Map => [others => 0],
+ States => [others => [others => 1]],
+ Is_Final => [others => True],
Case_Sensitive => True));
end if;
@@ -1726,7 +1726,7 @@ package body System.Regexp is
New_Columns := Table'Last (2) * (Column / Table'Last (2) + 1);
New_Table := new Regexp_Array (Table'First (1) .. New_Lines,
Table'First (2) .. New_Columns);
- New_Table.all := (others => (others => 0));
+ New_Table.all := [others => [others => 0]];
for J in Table'Range (1) loop
for K in Table'Range (2) loop
diff --git a/gcc/ada/libgnat/s-regpat.adb b/gcc/ada/libgnat/s-regpat.adb
index b40f682..00833bb 100644
--- a/gcc/ada/libgnat/s-regpat.adb
+++ b/gcc/ada/libgnat/s-regpat.adb
@@ -199,7 +199,7 @@ package body System.Regpat is
type Bit_Conversion_Array is array (Class_Byte range 0 .. 7) of Class_Byte;
Bit_Conversion : constant Bit_Conversion_Array :=
- (1, 2, 4, 8, 16, 32, 64, 128);
+ [1, 2, 4, 8, 16, 32, 64, 128];
type Std_Class is (ANYOF_NONE,
ANYOF_ALNUM, -- Alphanumeric class [a-zA-Z0-9]
@@ -2111,9 +2111,9 @@ package body System.Regpat is
declare
Point : constant String := Pointer'Image (Index);
begin
- Put ((1 .. 4 - Point'Length => ' ')
+ Put ([1 .. 4 - Point'Length => ' ']
& Point & ":"
- & (1 .. Local_Indent * 2 => ' ') & Opcode'Image (Op));
+ & [1 .. Local_Indent * 2 => ' '] & Opcode'Image (Op));
end;
-- Print the parenthesis number
@@ -2506,11 +2506,11 @@ package body System.Regpat is
begin
if Prefix then
- Put ((1 .. 5 - Pos'Length => ' '));
+ Put ([1 .. 5 - Pos'Length => ' ']);
Put (Pos & " <"
& Data (Input_Pos
.. Integer'Min (Last_In_Data, Input_Pos + Length - 1)));
- Put ((1 .. Length - 1 - Last_In_Data + Input_Pos => ' '));
+ Put ([1 .. Length - 1 - Last_In_Data + Input_Pos => ' ']);
Put ("> |");
else
@@ -2527,7 +2527,7 @@ package body System.Regpat is
procedure Dump_Error (Msg : String) is
begin
Put (" | ");
- Put ((1 .. Dump_Indent * 2 => ' '));
+ Put ([1 .. Dump_Indent * 2 => ' ']);
Put_Line (Msg);
end Dump_Error;
@@ -3381,7 +3381,7 @@ package body System.Regpat is
begin
Input_Pos := Pos;
Last_Paren := 0;
- Matches_Full := (others => No_Match);
+ Matches_Full := [others => No_Match];
if Match (Program_First) then
Matches_Full (0) := (Pos, Input_Pos - 1);
@@ -3397,7 +3397,7 @@ package body System.Regpat is
-- Do we have the regexp Never_Match?
if Self.Size = 0 then
- Matches := (others => No_Match);
+ Matches := [others => No_Match];
return;
end if;
@@ -3420,7 +3420,7 @@ package body System.Regpat is
end loop;
if Next_Try = 0 then
- Matches := (others => No_Match);
+ Matches := [others => No_Match];
return; -- Not present
end if;
end;
@@ -3740,7 +3740,7 @@ package body System.Regpat is
procedure Reset_Class (Bitmap : out Character_Class) is
begin
- Bitmap := (others => 0);
+ Bitmap := [others => 0];
end Reset_Class;
------------------
diff --git a/gcc/ada/libgnat/s-regpat.ads b/gcc/ada/libgnat/s-regpat.ads
index 8fac30a..637e76c 100644
--- a/gcc/ada/libgnat/s-regpat.ads
+++ b/gcc/ada/libgnat/s-regpat.ads
@@ -639,10 +639,10 @@ private
Paren_Count : Natural := 0; -- # paren groups
Flags : Regexp_Flags := No_Flags;
Program : Program_Data (Program_First .. Size) :=
- (others => ASCII.NUL);
+ [others => ASCII.NUL];
end record;
Never_Match : constant Pattern_Matcher :=
- (0, ASCII.NUL, False, 0, 0, 0, No_Flags, (others => ASCII.NUL));
+ (0, ASCII.NUL, False, 0, 0, 0, No_Flags, [others => ASCII.NUL]);
end System.Regpat;
diff --git a/gcc/ada/libgnat/s-scaval__128.adb b/gcc/ada/libgnat/s-scaval__128.adb
index 7bb5696..2276fcc 100644
--- a/gcc/ada/libgnat/s-scaval__128.adb
+++ b/gcc/ada/libgnat/s-scaval__128.adb
@@ -180,7 +180,7 @@ package body System.Scalar_Values is
IV_Ilf := To_ByteLF (IS_Iu8);
if EFloat then
- IV_Ill := (0, 0, 0, 0, 0, 0, 0, 16#C0#, 16#FF#, 16#FF#, 0, 0);
+ IV_Ill := [0, 0, 0, 0, 0, 0, 0, 16#C0#, 16#FF#, 16#FF#, 0, 0];
end if;
-- LO (Low values)
@@ -209,7 +209,7 @@ package body System.Scalar_Values is
IV_Ilf := To_ByteLF (16#FFF0_0000_0000_0000#);
if EFloat then
- IV_Ill := (0, 0, 0, 0, 0, 0, 0, 16#80#, 16#FF#, 16#FF#, 0, 0);
+ IV_Ill := [0, 0, 0, 0, 0, 0, 0, 16#80#, 16#FF#, 16#FF#, 0, 0];
end if;
-- HI (High values)
@@ -238,7 +238,7 @@ package body System.Scalar_Values is
IV_Ilf := To_ByteLF (16#7FF0_0000_0000_0000#);
if EFloat then
- IV_Ill := (0, 0, 0, 0, 0, 0, 0, 16#80#, 16#FF#, 16#7F#, 0, 0);
+ IV_Ill := [0, 0, 0, 0, 0, 0, 0, 16#80#, 16#FF#, 16#7F#, 0, 0];
end if;
-- -Shh (hex byte)
@@ -281,7 +281,7 @@ package body System.Scalar_Values is
IV_Ilf := To_ByteLF (IS_Is8);
if EFloat then
- IV_Ill := (B, B, B, B, B, B, B, B, B, B, B, B);
+ IV_Ill := [B, B, B, B, B, B, B, B, B, B, B, B];
end if;
end if;
diff --git a/gcc/ada/libgnat/s-statxd.adb b/gcc/ada/libgnat/s-statxd.adb
index af88f7d..4de49a9 100644
--- a/gcc/ada/libgnat/s-statxd.adb
+++ b/gcc/ada/libgnat/s-statxd.adb
@@ -72,40 +72,40 @@ package body System.Stream_Attributes.XDR is
type Precision is (Single, Double, Quadruple);
- Fields : constant array (Precision) of Field_Type := (
+ Fields : constant array (Precision) of Field_Type := [
-- Single precision
- (E_Size => 8,
+ [E_Size => 8,
E_Bias => 127,
F_Size => 23,
E_Last => 2 ** 8 - 1,
F_Mask => 16#7F#, -- 2 ** 7 - 1,
E_Bytes => 2,
F_Bytes => 3,
- F_Bits => 23 mod US),
+ F_Bits => 23 mod US],
-- Double precision
- (E_Size => 11,
+ [E_Size => 11,
E_Bias => 1023,
F_Size => 52,
E_Last => 2 ** 11 - 1,
F_Mask => 16#0F#, -- 2 ** 4 - 1,
E_Bytes => 2,
F_Bytes => 7,
- F_Bits => 52 mod US),
+ F_Bits => 52 mod US],
-- Quadruple precision
- (E_Size => 15,
+ [E_Size => 15,
E_Bias => 16383,
F_Size => 112,
E_Last => 2 ** 8 - 1,
F_Mask => 16#FF#, -- 2 ** 8 - 1,
E_Bytes => 2,
F_Bytes => 14,
- F_Bits => 112 mod US));
+ F_Bits => 112 mod US]];
-- The representation of all items requires a multiple of four bytes
-- (or 32 bits) of data. The bytes are numbered 0 through n-1. The bytes
@@ -1244,7 +1244,7 @@ package body System.Stream_Attributes.XDR is
Is_Positive : Boolean;
E : Integer;
F : Float;
- S : SEA (1 .. F_L) := (others => 0);
+ S : SEA (1 .. F_L) := [others => 0];
begin
if not Item'Valid then
@@ -1390,7 +1390,7 @@ package body System.Stream_Attributes.XDR is
Is_Positive : Boolean;
E : Integer;
F : Long_Float;
- S : SEA (1 .. LF_L) := (others => 0);
+ S : SEA (1 .. LF_L) := [others => 0];
begin
if not Item'Valid then
@@ -1519,7 +1519,7 @@ package body System.Stream_Attributes.XDR is
Is_Positive : Boolean;
E : Integer;
F : Long_Long_Float := Item;
- S : SEA (1 .. LLF_L) := (others => 0);
+ S : SEA (1 .. LLF_L) := [others => 0];
begin
if not Item'Valid then
@@ -1737,7 +1737,7 @@ package body System.Stream_Attributes.XDR is
Is_Positive : Boolean;
E : Integer;
F : Short_Float;
- S : SEA (1 .. SF_L) := (others => 0);
+ S : SEA (1 .. SF_L) := [others => 0];
begin
if not Item'Valid then
diff --git a/gcc/ada/libgnat/s-stausa.adb b/gcc/ada/libgnat/s-stausa.adb
index 8bd6c5b..cd34ab6 100644
--- a/gcc/ada/libgnat/s-stausa.adb
+++ b/gcc/ada/libgnat/s-stausa.adb
@@ -127,10 +127,10 @@ package body System.Stack_Usage is
Result_Array := new Result_Array_Type (1 .. Buffer_Size);
Result_Array.all :=
- (others =>
- (Task_Name => (others => ASCII.NUL),
+ [others =>
+ [Task_Name => [others => ASCII.NUL],
Value => 0,
- Stack_Size => 0));
+ Stack_Size => 0]];
-- Set the Is_Enabled flag to true, so that the task wrapper knows that
-- it has to handle dynamic stack analysis
@@ -282,7 +282,7 @@ package body System.Stack_Usage is
Analyzer.Pattern_Size := Pattern_Size;
Analyzer.Pattern := Pattern;
Analyzer.Result_Id := Next_Id;
- Analyzer.Task_Name := (others => ' ');
+ Analyzer.Task_Name := [others => ' '];
-- Compute the task name, and truncate if bigger than Task_Name_Length
@@ -455,12 +455,12 @@ package body System.Stack_Usage is
Stack_Size_Blanks : constant
String (1 .. Max_Stack_Size_Len -
Stack_Size_Str'Length) :=
- (others => ' ');
+ [others => ' '];
Stack_Usage_Blanks : constant
String (1 .. Max_Actual_Use_Len -
Actual_Size_Str'Length) :=
- (others => ' ');
+ [others => ' '];
begin
if Stack_Size_Str'Length > Max_Stack_Size_Len then
diff --git a/gcc/ada/libgnat/s-strops.adb b/gcc/ada/libgnat/s-strops.adb
index 1644d85..f576692 100644
--- a/gcc/ada/libgnat/s-strops.adb
+++ b/gcc/ada/libgnat/s-strops.adb
@@ -92,7 +92,7 @@ package body System.String_Ops is
function Str_Concat_SC (X : String; Y : Character) return String is
begin
if X'Length = 0 then
- return (1 => Y);
+ return [Y];
else
declare
diff --git a/gcc/ada/libgnat/s-valboo.adb b/gcc/ada/libgnat/s-valboo.adb
index 4ec1e19..7559de3 100644
--- a/gcc/ada/libgnat/s-valboo.adb
+++ b/gcc/ada/libgnat/s-valboo.adb
@@ -29,22 +29,34 @@
-- --
------------------------------------------------------------------------------
+-- 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.
+
+pragma Assertion_Policy (Ghost => Ignore,
+ Loop_Invariant => Ignore,
+ Assert => Ignore);
+
with System.Val_Util; use System.Val_Util;
-package body System.Val_Bool is
+package body System.Val_Bool
+ with SPARK_Mode
+is
-------------------
-- Value_Boolean --
-------------------
function Value_Boolean (Str : String) return Boolean is
- F : Natural;
- L : Natural;
+ F : Integer;
+ L : Integer;
S : String (Str'Range) := Str;
begin
Normalize_String (S, F, L);
+ pragma Assert (F = System.Val_Util.First_Non_Space_Ghost (S));
+
if S (F .. L) = "TRUE" then
return True;
diff --git a/gcc/ada/libgnat/s-valboo.ads b/gcc/ada/libgnat/s-valboo.ads
index 2129c5ac..c4448e4 100644
--- a/gcc/ada/libgnat/s-valboo.ads
+++ b/gcc/ada/libgnat/s-valboo.ads
@@ -29,10 +29,60 @@
-- --
------------------------------------------------------------------------------
-package System.Val_Bool 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);
+
+with System.Val_Util;
+
+package System.Val_Bool
+ with SPARK_Mode
+is
pragma Preelaborate;
- function Value_Boolean (Str : String) return Boolean;
+ function Is_Boolean_Image_Ghost (Str : String) return Boolean is
+ (not System.Val_Util.Only_Space_Ghost (Str, Str'First, Str'Last)
+ and then
+ (declare
+ F : constant Positive := System.Val_Util.First_Non_Space_Ghost (Str);
+ begin
+ (F <= Str'Last - 3
+ and then Str (F) in 't' | 'T'
+ and then Str (F + 1) in 'r' | 'R'
+ and then Str (F + 2) in 'u' | 'U'
+ and then Str (F + 3) in 'e' | 'E'
+ and then
+ (if F + 3 < Str'Last then
+ System.Val_Util.Only_Space_Ghost (Str, F + 4, Str'Last)))
+ or else
+ (F <= Str'Last - 4
+ and then Str (F) in 'f' | 'F'
+ and then Str (F + 1) in 'a' | 'A'
+ and then Str (F + 2) in 'l' | 'L'
+ and then Str (F + 3) in 's' | 'S'
+ and then Str (F + 4) in 'e' | 'E'
+ and then
+ (if F + 4 < Str'Last then
+ System.Val_Util.Only_Space_Ghost (Str, F + 5, Str'Last)))))
+ with
+ Ghost;
+ -- Ghost function that returns True iff Str is the image of a boolean, that
+ -- is "true" or "false" in any capitalization, possibly surounded by space
+ -- characters.
+
+ function Value_Boolean (Str : String) return Boolean
+ with
+ Pre => Is_Boolean_Image_Ghost (Str),
+ Post =>
+ Value_Boolean'Result =
+ (Str (System.Val_Util.First_Non_Space_Ghost (Str)) in 't' | 'T');
-- Computes Boolean'Value (Str)
end System.Val_Bool;
diff --git a/gcc/ada/libgnat/s-valrea.adb b/gcc/ada/libgnat/s-valrea.adb
index bc5465c..b37383a 100644
--- a/gcc/ada/libgnat/s-valrea.adb
+++ b/gcc/ada/libgnat/s-valrea.adb
@@ -63,19 +63,19 @@ package body System.Val_Real is
-- index N is the largest K such that N**K <= Num'Last.
Maxexp32 : constant array (Base_T) of Positive :=
- (2 => 127, 3 => 80, 4 => 63, 5 => 55, 6 => 49,
+ [2 => 127, 3 => 80, 4 => 63, 5 => 55, 6 => 49,
7 => 45, 8 => 42, 9 => 40, 10 => 38, 11 => 37,
- 12 => 35, 13 => 34, 14 => 33, 15 => 32, 16 => 31);
+ 12 => 35, 13 => 34, 14 => 33, 15 => 32, 16 => 31];
Maxexp64 : constant array (Base_T) of Positive :=
- (2 => 1023, 3 => 646, 4 => 511, 5 => 441, 6 => 396,
+ [2 => 1023, 3 => 646, 4 => 511, 5 => 441, 6 => 396,
7 => 364, 8 => 341, 9 => 323, 10 => 308, 11 => 296,
- 12 => 285, 13 => 276, 14 => 268, 15 => 262, 16 => 255);
+ 12 => 285, 13 => 276, 14 => 268, 15 => 262, 16 => 255];
Maxexp80 : constant array (Base_T) of Positive :=
- (2 => 16383, 3 => 10337, 4 => 8191, 5 => 7056, 6 => 6338,
+ [2 => 16383, 3 => 10337, 4 => 8191, 5 => 7056, 6 => 6338,
7 => 5836, 8 => 5461, 9 => 5168, 10 => 4932, 11 => 4736,
- 12 => 4570, 13 => 4427, 14 => 4303, 15 => 4193, 16 => 4095);
+ 12 => 4570, 13 => 4427, 14 => 4303, 15 => 4193, 16 => 4095];
package Double_Real is new System.Double_Real (Num);
use type Double_Real.Double_T;
diff --git a/gcc/ada/libgnat/s-valuer.adb b/gcc/ada/libgnat/s-valuer.adb
index ff78c4b..a1793fa 100644
--- a/gcc/ada/libgnat/s-valuer.adb
+++ b/gcc/ada/libgnat/s-valuer.adb
@@ -511,6 +511,8 @@ package body System.Value_R is
Value : Uns;
-- Mantissa as an Integer
+ Expon : Integer;
+
begin
-- The default base is 10
@@ -643,7 +645,8 @@ package body System.Value_R is
-- Update pointer and scan exponent
Ptr.all := Index;
- Scale := Scale + Scan_Exponent (Str, Ptr, Max, Real => True);
+ Scan_Exponent (Str, Ptr, Max, Expon, Real => True);
+ Scale := Scale + Expon;
-- Here is where we check for a bad based number
diff --git a/gcc/ada/libgnat/s-valueu.adb b/gcc/ada/libgnat/s-valueu.adb
index b385a9b..5b77358 100644
--- a/gcc/ada/libgnat/s-valueu.adb
+++ b/gcc/ada/libgnat/s-valueu.adb
@@ -234,7 +234,7 @@ package body System.Value_U is
-- Come here with scanned unsigned value in Uval. The only remaining
-- required step is to deal with exponent if one is present.
- Expon := Scan_Exponent (Str, Ptr, Max);
+ Scan_Exponent (Str, Ptr, Max, Expon);
if Expon /= 0 and then Uval /= 0 then
diff --git a/gcc/ada/libgnat/s-valuti.adb b/gcc/ada/libgnat/s-valuti.adb
index 31edc40..3e62d09 100644
--- a/gcc/ada/libgnat/s-valuti.adb
+++ b/gcc/ada/libgnat/s-valuti.adb
@@ -29,15 +29,27 @@
-- --
------------------------------------------------------------------------------
+-- 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.
+
+pragma Assertion_Policy (Ghost => Ignore,
+ Loop_Invariant => Ignore,
+ Assert => Ignore);
+
with System.Case_Util; use System.Case_Util;
-package body System.Val_Util is
+package body System.Val_Util
+ with SPARK_Mode
+is
---------------
-- Bad_Value --
---------------
procedure Bad_Value (S : String) is
+ pragma Annotate (GNATprove, Intentional, "exception might be raised",
+ "Intentional exception from Bad_Value");
begin
-- Bad_Value might be called with very long strings allocated on the
-- heap. Limit the size of the message so that we avoid creating a
@@ -50,6 +62,41 @@ package body System.Val_Util is
end if;
end Bad_Value;
+ ---------------------------
+ -- First_Non_Space_Ghost --
+ ---------------------------
+
+ function First_Non_Space_Ghost (S : String) return Positive is
+ begin
+ for J in S'Range loop
+ if S (J) /= ' ' then
+ return J;
+ end if;
+
+ pragma Loop_Invariant (for all K in S'First .. J => S (K) = ' ');
+ end loop;
+
+ raise Program_Error;
+ end First_Non_Space_Ghost;
+
+ -----------------------
+ -- Last_Number_Ghost --
+ -----------------------
+
+ function Last_Number_Ghost (Str : String) return Positive is
+ begin
+ for J in Str'Range loop
+ if Str (J) not in '0' .. '9' | '_' then
+ return J - 1;
+ end if;
+
+ pragma Loop_Invariant
+ (for all K in Str'First .. J => Str (K) in '0' .. '9' | '_');
+ end loop;
+
+ return Str'Last;
+ end Last_Number_Ghost;
+
----------------------
-- Normalize_String --
----------------------
@@ -62,21 +109,33 @@ package body System.Val_Util is
F := S'First;
L := S'Last;
+ -- Case of empty string
+
+ if F > L then
+ return;
+ end if;
+
-- Scan for leading spaces
- while F <= L and then S (F) = ' ' loop
+ while F < L and then S (F) = ' ' loop
+ pragma Loop_Invariant (F in S'First .. L - 1);
+ pragma Loop_Invariant (for all J in S'First .. F => S (J) = ' ');
F := F + 1;
end loop;
- -- Case of no nonspace characters found
+ -- Case of no nonspace characters found. Decrease L to ensure L < F
+ -- without risking an overflow if F is Integer'Last.
- if F > L then
+ if S (F) = ' ' then
+ L := L - 1;
return;
end if;
-- Scan for trailing spaces
while S (L) = ' ' loop
+ pragma Loop_Invariant (L in F + 1 .. S'Last);
+ pragma Loop_Invariant (for all J in L .. S'Last => S (J) = ' ');
L := L - 1;
end loop;
@@ -85,6 +144,8 @@ package body System.Val_Util is
if S (F) /= ''' then
for J in F .. L loop
S (J) := To_Upper (S (J));
+ pragma Loop_Invariant
+ (for all K in F .. J => S (K) = To_Upper (S'Loop_Entry (K)));
end loop;
end if;
end Normalize_String;
@@ -93,13 +154,14 @@ package body System.Val_Util is
-- Scan_Exponent --
-------------------
- function Scan_Exponent
+ procedure Scan_Exponent
(Str : String;
Ptr : not null access Integer;
Max : Integer;
- Real : Boolean := False) return Integer
+ Exp : out Integer;
+ Real : Boolean := False)
is
- P : Natural := Ptr.all;
+ P : Integer := Ptr.all;
M : Boolean;
X : Integer;
@@ -107,7 +169,8 @@ package body System.Val_Util is
if P >= Max
or else (Str (P) /= 'E' and then Str (P) /= 'e')
then
- return 0;
+ Exp := 0;
+ return;
end if;
-- We have an E/e, see if sign follows
@@ -118,7 +181,8 @@ package body System.Val_Util is
P := P + 1;
if P > Max then
- return 0;
+ Exp := 0;
+ return;
else
M := False;
end if;
@@ -127,7 +191,8 @@ package body System.Val_Util is
P := P + 1;
if P > Max or else not Real then
- return 0;
+ Exp := 0;
+ return;
else
M := True;
end if;
@@ -137,7 +202,8 @@ package body System.Val_Util is
end if;
if Str (P) not in '0' .. '9' then
- return 0;
+ Exp := 0;
+ return;
end if;
-- Scan out the exponent value as an unsigned integer. Values larger
@@ -148,28 +214,52 @@ package body System.Val_Util is
X := 0;
- loop
- if X < (Integer'Last / 10) then
- X := X * 10 + (Character'Pos (Str (P)) - Character'Pos ('0'));
- end if;
-
- P := P + 1;
-
- exit when P > Max;
-
- if Str (P) = '_' then
- Scan_Underscore (Str, P, Ptr, Max, False);
- else
- exit when Str (P) not in '0' .. '9';
- end if;
- end loop;
+ declare
+ Rest : constant String := Str (P .. Max) with Ghost;
+ Last : constant Natural := Last_Number_Ghost (Rest) with Ghost;
+
+ begin
+ pragma Assert (Is_Natural_Format_Ghost (Rest));
+
+ loop
+ pragma Assert (Str (P) = Rest (P));
+ pragma Assert (Str (P) in '0' .. '9');
+
+ if X < (Integer'Last / 10) then
+ X := X * 10 + (Character'Pos (Str (P)) - Character'Pos ('0'));
+ end if;
+
+ pragma Loop_Invariant (X >= 0);
+ pragma Loop_Invariant (P in P'Loop_Entry .. Last);
+ pragma Loop_Invariant (Str (P) in '0' .. '9');
+ pragma Loop_Invariant
+ (Scan_Natural_Ghost (Rest, P'Loop_Entry, 0)
+ = (if P = Max
+ or else Rest (P + 1) not in '0' .. '9' | '_'
+ or else X >= Integer'Last / 10
+ then
+ X
+ else
+ Scan_Natural_Ghost (Rest, P + 1, X)));
+
+ P := P + 1;
+
+ exit when P > Max;
+
+ if Str (P) = '_' then
+ Scan_Underscore (Str, P, Ptr, Max, False);
+ else
+ exit when Str (P) not in '0' .. '9';
+ end if;
+ end loop;
+ end;
if M then
X := -X;
end if;
Ptr.all := P;
- return X;
+ Exp := X;
end Scan_Exponent;
--------------------
@@ -182,7 +272,7 @@ package body System.Val_Util is
Max : Integer;
Start : out Positive)
is
- P : Natural := Ptr.all;
+ P : Integer := Ptr.all;
begin
if P > Max then
@@ -194,6 +284,12 @@ package body System.Val_Util is
while Str (P) = ' ' loop
P := P + 1;
+ pragma Loop_Invariant (Ptr.all = Ptr.all'Loop_Entry);
+ pragma Loop_Invariant (P in Ptr.all .. Max);
+ pragma Loop_Invariant (for some J in P .. Max => Str (J) /= ' ');
+ pragma Loop_Invariant
+ (for all J in Ptr.all .. P - 1 => Str (J) = ' ');
+
if P > Max then
Ptr.all := P;
Bad_Value (Str);
@@ -202,6 +298,8 @@ package body System.Val_Util is
Start := P;
+ pragma Assert (Start = First_Non_Space_Ghost (Str (Ptr.all .. Max)));
+
-- Skip past an initial plus sign
if Str (P) = '+' then
@@ -227,7 +325,7 @@ package body System.Val_Util is
Minus : out Boolean;
Start : out Positive)
is
- P : Natural := Ptr.all;
+ P : Integer := Ptr.all;
begin
-- Deal with case of null string (all blanks). As per spec, we raise
@@ -242,6 +340,12 @@ package body System.Val_Util is
while Str (P) = ' ' loop
P := P + 1;
+ pragma Loop_Invariant (Ptr.all = Ptr.all'Loop_Entry);
+ pragma Loop_Invariant (P in Ptr.all .. Max);
+ pragma Loop_Invariant (for some J in P .. Max => Str (J) /= ' ');
+ pragma Loop_Invariant
+ (for all J in Ptr.all .. P - 1 => Str (J) = ' ');
+
if P > Max then
Ptr.all := P;
Bad_Value (Str);
@@ -250,6 +354,8 @@ package body System.Val_Util is
Start := P;
+ pragma Assert (Start = First_Non_Space_Ghost (Str (Ptr.all .. Max)));
+
-- Remember an initial minus sign
if Str (P) = '-' then
@@ -289,6 +395,8 @@ package body System.Val_Util is
if Str (J) /= ' ' then
Bad_Value (Str);
end if;
+
+ pragma Loop_Invariant (for all K in P .. J => Str (K) = ' ');
end loop;
end Scan_Trailing_Blanks;
diff --git a/gcc/ada/libgnat/s-valuti.ads b/gcc/ada/libgnat/s-valuti.ads
index 3d426d9..7483f2c 100644
--- a/gcc/ada/libgnat/s-valuti.ads
+++ b/gcc/ada/libgnat/s-valuti.ads
@@ -31,16 +31,72 @@
-- This package provides some common utilities used by the s-valxxx files
-package System.Val_Util is
- pragma Pure;
+-- 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.
- procedure Bad_Value (S : String);
+pragma Assertion_Policy (Pre => Ignore,
+ Post => Ignore,
+ Contract_Cases => Ignore,
+ Ghost => Ignore);
+
+with System.Case_Util;
+
+package System.Val_Util
+ with SPARK_Mode, Pure
+is
+ pragma Unevaluated_Use_Of_Old (Allow);
+
+ procedure Bad_Value (S : String)
+ with
+ Depends => (null => S);
pragma No_Return (Bad_Value);
-- Raises constraint error with message: bad input for 'Value: "xxx"
+ function Only_Space_Ghost (S : String; From, To : Integer) return Boolean is
+ (for all J in From .. To => S (J) = ' ')
+ with
+ Ghost,
+ Pre => From > To or else (From >= S'First and then To <= S'Last);
+ -- Ghost function that returns True if S has only space characters from
+ -- index From to index To.
+
+ function First_Non_Space_Ghost (S : String) return Positive
+ with
+ Ghost,
+ Pre => not Only_Space_Ghost (S, S'First, S'Last),
+ Post => First_Non_Space_Ghost'Result in S'Range
+ and then S (First_Non_Space_Ghost'Result) /= ' '
+ and then Only_Space_Ghost
+ (S, S'First, First_Non_Space_Ghost'Result - 1);
+ -- Ghost function that returns the index of the first non-space character
+ -- in S, which necessarily exists given the precondition on S.
+
procedure Normalize_String
(S : in out String;
- F, L : out Integer);
+ F, L : out Integer)
+ with
+ Post => (if Only_Space_Ghost (S'Old, S'First, S'Last) then
+ F > L
+ else
+ F >= S'First
+ and then L <= S'Last
+ and then F <= L
+ and then Only_Space_Ghost (S'Old, S'First, F - 1)
+ and then S'Old (F) /= ' '
+ and then S'Old (L) /= ' '
+ and then
+ (if L < S'Last then
+ Only_Space_Ghost (S'Old, L + 1, S'Last))
+ and then
+ (if S'Old (F) /= ''' then
+ (for all J in S'Range =>
+ (if J in F .. L then
+ S (J) = System.Case_Util.To_Upper (S'Old (J))
+ else
+ S (J) = S'Old (J)))));
-- This procedure scans the string S setting F to be the index of the first
-- non-blank character of S and L to be the index of the last non-blank
-- character of S. Any lower case characters present in S will be folded to
@@ -52,7 +108,27 @@ package System.Val_Util is
Ptr : not null access Integer;
Max : Integer;
Minus : out Boolean;
- Start : out Positive);
+ Start : out Positive)
+ with
+ Pre =>
+ -- Ptr.all .. Max is either an empty range, or a valid range in Str
+ (Ptr.all > Max or else (Ptr.all >= Str'First and then Max <= Str'Last))
+ and then not Only_Space_Ghost (Str, Ptr.all, Max)
+ and then
+ (declare
+ F : constant Positive :=
+ First_Non_Space_Ghost (Str (Ptr.all .. Max));
+ begin
+ (if Str (F) in '+' | '-' then
+ F <= Max - 1 and then Str (F + 1) /= ' ')),
+ Post =>
+ (declare
+ F : constant Positive :=
+ First_Non_Space_Ghost (Str (Ptr.all'Old .. Max));
+ begin
+ Minus = (Str (F) = '-')
+ and then Ptr.all = (if Str (F) in '+' | '-' then F + 1 else F)
+ and then Start = F);
-- The Str, Ptr, Max parameters are as for the scan routines (Str is the
-- string to be scanned starting at Ptr.all, and Max is the index of the
-- last character in the string). Scan_Sign first scans out any initial
@@ -77,15 +153,135 @@ package System.Val_Util is
(Str : String;
Ptr : not null access Integer;
Max : Integer;
- Start : out Positive);
+ Start : out Positive)
+ with
+ Pre =>
+ -- Ptr.all .. Max is either an empty range, or a valid range in Str
+ (Ptr.all > Max or else (Ptr.all >= Str'First and then Max <= Str'Last))
+ and then not Only_Space_Ghost (Str, Ptr.all, Max)
+ and then
+ (declare
+ F : constant Positive :=
+ First_Non_Space_Ghost (Str (Ptr.all .. Max));
+ begin
+ (if Str (F) = '+' then
+ F <= Max - 1 and then Str (F + 1) /= ' ')),
+ Post =>
+ (declare
+ F : constant Positive :=
+ First_Non_Space_Ghost (Str (Ptr.all'Old .. Max));
+ begin
+ Ptr.all = (if Str (F) = '+' then F + 1 else F)
+ and then Start = F);
-- Same as Scan_Sign, but allows only plus, not minus. This is used for
-- modular types.
- function Scan_Exponent
+ function Only_Number_Ghost (Str : String; From, To : Integer) return Boolean
+ is
+ (for all J in From .. To => Str (J) in '0' .. '9' | '_')
+ with
+ Ghost,
+ Pre => From > To or else (From >= Str'First and then To <= Str'Last);
+ -- Ghost function that returns True if S has only number characters from
+ -- index From to index To.
+
+ function Last_Number_Ghost (Str : String) return Positive
+ with
+ Ghost,
+ Pre => Str /= "" and then Str (Str'First) in '0' .. '9',
+ Post => Last_Number_Ghost'Result in Str'Range
+ and then (if Last_Number_Ghost'Result < Str'Last then
+ Str (Last_Number_Ghost'Result + 1) not in '0' .. '9' | '_')
+ and then Only_Number_Ghost (Str, Str'First, Last_Number_Ghost'Result);
+ -- Ghost function that returns the index of the last character in S that
+ -- is either a figure or underscore, which necessarily exists given the
+ -- precondition on S.
+
+ function Is_Natural_Format_Ghost (Str : String) return Boolean is
+ (Str /= ""
+ and then Str (Str'First) in '0' .. '9'
+ and then
+ (declare
+ L : constant Positive := Last_Number_Ghost (Str);
+ begin
+ Str (L) in '0' .. '9'
+ and then (for all J in Str'First .. L =>
+ (if Str (J) = '_' then Str (J + 1) /= '_'))))
+ with
+ Ghost;
+ -- Ghost function that determines if Str has the correct format for a
+ -- natural number, consisting in a sequence of figures possibly separated
+ -- by single underscores. It may be followed by other characters.
+
+ function Scan_Natural_Ghost
+ (Str : String;
+ P : Natural;
+ Acc : Natural)
+ return Natural
+ with
+ Ghost,
+ Subprogram_Variant => (Increases => P),
+ Pre => Is_Natural_Format_Ghost (Str)
+ and then P in Str'First .. Last_Number_Ghost (Str)
+ and then Acc < Integer'Last / 10;
+ -- Ghost function that recursively computes the natural number in Str, up
+ -- to the first number greater or equal to Natural'Last / 10, assuming Acc
+ -- has been scanned already and scanning continues at index P.
+
+ procedure Scan_Exponent
(Str : String;
Ptr : not null access Integer;
Max : Integer;
- Real : Boolean := False) return Integer;
+ Exp : out Integer;
+ Real : Boolean := False)
+ with
+ Pre =>
+ -- Ptr.all .. Max is either an empty range, or a valid range in Str
+ (Ptr.all > Max or else (Ptr.all >= Str'First and then Max <= Str'Last))
+ and then
+ Max < Natural'Last
+ and then
+ (if Ptr.all < Max and then Str (Ptr.all) in 'E' | 'e' then
+ (declare
+ Plus_Sign : constant Boolean := Str (Ptr.all + 1) = '+';
+ Minus_Sign : constant Boolean := Str (Ptr.all + 1) = '-';
+ Sign : constant Boolean := Plus_Sign or Minus_Sign;
+ begin
+ (if Minus_Sign and not Real then True
+ elsif Sign
+ and then (Ptr.all > Max - 2
+ or else Str (Ptr.all + 2) not in '0' .. '9')
+ then True
+ else
+ (declare
+ Start : constant Natural :=
+ (if Sign then Ptr.all + 2 else Ptr.all + 1);
+ begin
+ Is_Natural_Format_Ghost (Str (Start .. Max)))))),
+ Post =>
+ (if Ptr.all'Old < Max and then Str (Ptr.all'Old) in 'E' | 'e' then
+ (declare
+ Plus_Sign : constant Boolean := Str (Ptr.all'Old + 1) = '+';
+ Minus_Sign : constant Boolean := Str (Ptr.all'Old + 1) = '-';
+ Sign : constant Boolean := Plus_Sign or Minus_Sign;
+ Unchanged : constant Boolean :=
+ Exp = 0 and Ptr.all = Ptr.all'Old;
+ begin
+ (if Minus_Sign and not Real then Unchanged
+ elsif Sign
+ and then (Ptr.all'Old > Max - 2
+ or else Str (Ptr.all'Old + 2) not in '0' .. '9')
+ then Unchanged
+ else
+ (declare
+ Start : constant Natural :=
+ (if Sign then Ptr.all'Old + 2 else Ptr.all'Old + 1);
+ Value : constant Natural :=
+ Scan_Natural_Ghost (Str (Start .. Max), Start, 0);
+ begin
+ Exp = (if Minus_Sign then -Value else Value))))
+ else
+ Exp = 0 and Ptr.all = Ptr.all'Old);
-- Called to scan a possible exponent. Str, Ptr, Max are as described above
-- for Scan_Sign. If Ptr.all < Max and Str (Ptr.all) = 'E' or 'e', then an
-- exponent is scanned out, with the exponent value returned in Exp, and
@@ -100,18 +296,37 @@ package System.Val_Util is
-- This routine must not be called with Str'Last = Positive'Last. There is
-- no check for this case, the caller must ensure this condition is met.
- procedure Scan_Trailing_Blanks (Str : String; P : Positive);
+ procedure Scan_Trailing_Blanks (Str : String; P : Positive)
+ with
+ Pre => P >= Str'First
+ and then Only_Space_Ghost (Str, P, Str'Last);
-- Checks that the remainder of the field Str (P .. Str'Last) is all
-- blanks. Raises Constraint_Error if a non-blank character is found.
+ pragma Warnings
+ (GNATprove, Off, """Ptr"" is not modified",
+ Reason => "Ptr is actually modified when raising an exception");
procedure Scan_Underscore
(Str : String;
P : in out Natural;
Ptr : not null access Integer;
Max : Integer;
- Ext : Boolean);
+ Ext : Boolean)
+ with
+ Pre => P in Str'Range
+ and then Str (P) = '_'
+ and then Max in Str'Range
+ and then P < Max
+ and then
+ (if Ext then
+ Str (P + 1) in '0' .. '9' | 'A' .. 'F' | 'a' .. 'f'
+ else
+ Str (P + 1) in '0' .. '9'),
+ Post =>
+ P = P'Old + 1
+ and then Ptr.all = Ptr.all;
-- Called if an underscore is encountered while scanning digits. Str (P)
- -- contains the underscore. Ptr it the pointer to be returned to the
+ -- contains the underscore. Ptr is the pointer to be returned to the
-- ultimate caller of the scan routine, Max is the maximum subscript in
-- Str, and Ext indicates if extended digits are allowed. In the case
-- where the underscore is invalid, Constraint_Error is raised with Ptr
@@ -120,5 +335,33 @@ package System.Val_Util is
--
-- This routine must not be called with Str'Last = Positive'Last. There is
-- no check for this case, the caller must ensure this condition is met.
+ pragma Warnings (GNATprove, On, """Ptr"" is not modified");
+
+private
+
+ ------------------------
+ -- Scan_Natural_Ghost --
+ ------------------------
+
+ function Scan_Natural_Ghost
+ (Str : String;
+ P : Natural;
+ Acc : Natural)
+ return Natural
+ is
+ (if Str (P) = '_' then
+ Scan_Natural_Ghost (Str, P + 1, Acc)
+ else
+ (declare
+ Shift_Acc : constant Natural :=
+ Acc * 10 + (Character'Pos (Str (P)) - Character'Pos ('0'));
+ begin
+ (if P = Str'Last
+ or else Str (P + 1) not in '0' .. '9' | '_'
+ or else Shift_Acc >= Integer'Last / 10
+ then
+ Shift_Acc
+ else
+ Scan_Natural_Ghost (Str, P + 1, Shift_Acc))));
end System.Val_Util;
diff --git a/gcc/ada/libgnat/s-wchcon.ads b/gcc/ada/libgnat/s-wchcon.ads
index 3e82260..897f595 100644
--- a/gcc/ada/libgnat/s-wchcon.ads
+++ b/gcc/ada/libgnat/s-wchcon.ads
@@ -167,12 +167,12 @@ package System.WCh_Con is
-- no ambiguity in Ada sources, since the above sequences are illegal Ada).
WC_Encoding_Letters : constant array (WC_Encoding_Method) of Character :=
- (WCEM_Hex => 'h',
+ [WCEM_Hex => 'h',
WCEM_Upper => 'u',
WCEM_Shift_JIS => 's',
WCEM_EUC => 'e',
WCEM_UTF8 => '8',
- WCEM_Brackets => 'b');
+ WCEM_Brackets => 'b'];
-- Letters used for selection of wide character encoding method in the
-- compiler options (-gnatW? switch) and for Wide_Text_IO (WCEM parameter
-- in the form string).
@@ -191,12 +191,12 @@ package System.WCh_Con is
-- or wide wide character sequence for any of the active encoding methods.
WC_Longest_Sequences : constant array (WC_Encoding_Method) of Natural :=
- (WCEM_Hex => 5,
+ [WCEM_Hex => 5,
WCEM_Upper => 2,
WCEM_Shift_JIS => 2,
WCEM_EUC => 2,
WCEM_UTF8 => 6,
- WCEM_Brackets => 12);
+ WCEM_Brackets => 12];
-- The longest number of characters that can be used for a wide character
-- or wide wide character sequence using the given encoding method.
diff --git a/gcc/ada/libgnat/s-widint.ads b/gcc/ada/libgnat/s-widint.ads
index f9b5eda..fb71618 100644
--- a/gcc/ada/libgnat/s-widint.ads
+++ b/gcc/ada/libgnat/s-widint.ads
@@ -31,9 +31,22 @@
-- Width attribute for signed integers up to Integer
+-- 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);
+
with System.Width_I;
-package System.Wid_Int is
+package System.Wid_Int
+ with SPARK_Mode
+is
function Width_Integer is new Width_I (Integer);
pragma Pure_Function (Width_Integer);
diff --git a/gcc/ada/libgnat/s-widlli.ads b/gcc/ada/libgnat/s-widlli.ads
index 708dbdc..07ff8bf 100644
--- a/gcc/ada/libgnat/s-widlli.ads
+++ b/gcc/ada/libgnat/s-widlli.ads
@@ -31,9 +31,22 @@
-- Width attribute for signed integers larger than Integer
+-- 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);
+
with System.Width_I;
-package System.Wid_LLI is
+package System.Wid_LLI
+ with SPARK_Mode
+is
function Width_Long_Long_Integer is new Width_I (Long_Long_Integer);
pragma Pure_Function (Width_Long_Long_Integer);
diff --git a/gcc/ada/libgnat/s-widllli.ads b/gcc/ada/libgnat/s-widllli.ads
index 82a7e3d..af35616 100644
--- a/gcc/ada/libgnat/s-widllli.ads
+++ b/gcc/ada/libgnat/s-widllli.ads
@@ -31,9 +31,22 @@
-- Width attribute for signed integers larger than Long_Long_Integer
+-- 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);
+
with System.Width_I;
-package System.Wid_LLLI is
+package System.Wid_LLLI
+ with SPARK_Mode
+is
function Width_Long_Long_Long_Integer is
new Width_I (Long_Long_Long_Integer);
diff --git a/gcc/ada/libgnat/s-widlllu.ads b/gcc/ada/libgnat/s-widlllu.ads
index 10a0c9c..fd6534f 100644
--- a/gcc/ada/libgnat/s-widlllu.ads
+++ b/gcc/ada/libgnat/s-widlllu.ads
@@ -31,6 +31,17 @@
-- Width attribute for modular integers larger than Long_Long_Integer
+-- 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);
+
with System.Width_U;
with System.Unsigned_Types;
diff --git a/gcc/ada/libgnat/s-widllu.ads b/gcc/ada/libgnat/s-widllu.ads
index 7eaf966..ce01285 100644
--- a/gcc/ada/libgnat/s-widllu.ads
+++ b/gcc/ada/libgnat/s-widllu.ads
@@ -31,6 +31,17 @@
-- Width attribute for modular integers larger than Integer
+-- 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);
+
with System.Width_U;
with System.Unsigned_Types;
diff --git a/gcc/ada/libgnat/s-widthi.adb b/gcc/ada/libgnat/s-widthi.adb
index 2f2d5e0..e47c8c13 100644
--- a/gcc/ada/libgnat/s-widthi.adb
+++ b/gcc/ada/libgnat/s-widthi.adb
@@ -29,10 +29,109 @@
-- --
------------------------------------------------------------------------------
+with Ada.Numerics.Big_Numbers.Big_Integers_Ghost;
+use Ada.Numerics.Big_Numbers.Big_Integers_Ghost;
+
function System.Width_I (Lo, Hi : Int) return Natural is
+
+ -- 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.
+
+ pragma Assertion_Policy (Ghost => Ignore,
+ Loop_Invariant => Ignore,
+ Assert => Ignore);
+
+ -----------------------
+ -- Local Subprograms --
+ -----------------------
+
+ package Signed_Conversion is new Signed_Conversions (Int => Int);
+
+ function Big (Arg : Int) return Big_Integer renames
+ Signed_Conversion.To_Big_Integer;
+
+ -- Maximum value of exponent for 10 that fits in Uns'Base
+ function Max_Log10 return Natural is
+ (case Int'Base'Size is
+ when 8 => 2,
+ when 16 => 4,
+ when 32 => 9,
+ when 64 => 19,
+ when 128 => 38,
+ when others => raise Program_Error)
+ with Ghost;
+
+ ------------------
+ -- Local Lemmas --
+ ------------------
+
+ procedure Lemma_Lower_Mult (A, B, C : Big_Natural)
+ with
+ Ghost,
+ Pre => A <= B,
+ Post => A * C <= B * C;
+
+ procedure Lemma_Div_Commutation (X, Y : Int)
+ with
+ Ghost,
+ Pre => X >= 0 and Y > 0,
+ Post => Big (X) / Big (Y) = Big (X / Y);
+
+ procedure Lemma_Div_Twice (X : Big_Natural; Y, Z : Big_Positive)
+ with
+ Ghost,
+ Post => X / Y / Z = X / (Y * Z);
+
+ ----------------------
+ -- Lemma_Lower_Mult --
+ ----------------------
+
+ procedure Lemma_Lower_Mult (A, B, C : Big_Natural) is null;
+
+ ---------------------------
+ -- Lemma_Div_Commutation --
+ ---------------------------
+
+ procedure Lemma_Div_Commutation (X, Y : Int) is null;
+
+ ---------------------
+ -- Lemma_Div_Twice --
+ ---------------------
+
+ procedure Lemma_Div_Twice (X : Big_Natural; Y, Z : Big_Positive) is
+ XY : constant Big_Natural := X / Y;
+ YZ : constant Big_Natural := Y * Z;
+ XYZ : constant Big_Natural := X / Y / Z;
+ R : constant Big_Natural := (XY rem Z) * Y + (X rem Y);
+ begin
+ pragma Assert (X = XY * Y + (X rem Y));
+ pragma Assert (XY = XY / Z * Z + (XY rem Z));
+ pragma Assert (X = XYZ * YZ + R);
+ pragma Assert ((XY rem Z) * Y <= (Z - 1) * Y);
+ pragma Assert (R <= YZ - 1);
+ pragma Assert (X / YZ = (XYZ * YZ + R) / YZ);
+ pragma Assert (X / YZ = XYZ + R / YZ);
+ end Lemma_Div_Twice;
+
+ -- Local variables
+
W : Natural;
T : Int;
+ -- Local ghost variables
+
+ Max_W : constant Natural := Max_Log10 with Ghost;
+ Big_10 : constant Big_Integer := Big (10) with Ghost;
+
+ Pow : Big_Integer := 1 with Ghost;
+ T_Init : constant Int :=
+ Int'Max (abs (Int'Max (Lo, Int'First + 1)),
+ abs (Int'Max (Hi, Int'First + 1)))
+ with Ghost;
+
+-- Start of processing for System.Width_I
+
begin
if Lo > Hi then
return 0;
@@ -52,10 +151,44 @@ begin
-- Increase value if more digits required
while T >= 10 loop
+ Lemma_Div_Commutation (T, 10);
+ Lemma_Div_Twice (Big (T_Init), Big_10 ** (W - 2), Big_10);
+
T := T / 10;
W := W + 1;
+ Pow := Pow * 10;
+
+ pragma Loop_Invariant (T >= 0);
+ pragma Loop_Invariant (W in 3 .. Max_W + 3);
+ pragma Loop_Invariant (Pow = Big_10 ** (W - 2));
+ pragma Loop_Invariant (Big (T) = Big (T_Init) / Pow);
+ pragma Loop_Variant (Decreases => T);
+ pragma Annotate
+ (CodePeer, False_Positive,
+ "validity check", "confusion on generated code");
end loop;
+ declare
+ F : constant Big_Integer := Big_10 ** (W - 2) with Ghost;
+ Q : constant Big_Integer := Big (T_Init) / F with Ghost;
+ R : constant Big_Integer := Big (T_Init) rem F with Ghost;
+ begin
+ pragma Assert (Q < Big_10);
+ pragma Assert (Big (T_Init) = Q * F + R);
+ Lemma_Lower_Mult (Q, Big (9), F);
+ pragma Assert (Big (T_Init) <= Big (9) * F + F - 1);
+ pragma Assert (Big (T_Init) < Big_10 * F);
+ pragma Assert (Big_10 * F = Big_10 ** (W - 1));
+ end;
+
+ -- This is an expression of the functional postcondition for Width_I,
+ -- which cannot be expressed readily as a postcondition as this would
+ -- require making the instantiation Signed_Conversion and function Big
+ -- available from the spec.
+
+ pragma Assert (Big (Int'Max (Lo, Int'First + 1)) < Big_10 ** (W - 1));
+ pragma Assert (Big (Int'Max (Hi, Int'First + 1)) < Big_10 ** (W - 1));
+
return W;
end if;
diff --git a/gcc/ada/libgnat/s-widthi.ads b/gcc/ada/libgnat/s-widthi.ads
index 37865b89..44e448d 100644
--- a/gcc/ada/libgnat/s-widthi.ads
+++ b/gcc/ada/libgnat/s-widthi.ads
@@ -36,4 +36,9 @@ generic
type Int is range <>;
-function System.Width_I (Lo, Hi : Int) return Natural;
+function System.Width_I (Lo, Hi : Int) return Natural
+with
+ Post => (if Lo > Hi then
+ System.Width_I'Result = 0
+ else
+ System.Width_I'Result > 0);
diff --git a/gcc/ada/libgnat/s-widthu.adb b/gcc/ada/libgnat/s-widthu.adb
index 79a0074..0be44ff 100644
--- a/gcc/ada/libgnat/s-widthu.adb
+++ b/gcc/ada/libgnat/s-widthu.adb
@@ -42,14 +42,14 @@ function System.Width_U (Lo, Hi : Uns) return Natural is
Loop_Invariant => Ignore,
Assert => Ignore);
- W : Natural;
- T : Uns;
+ -----------------------
+ -- Local Subprograms --
+ -----------------------
package Unsigned_Conversion is new Unsigned_Conversions (Int => Uns);
- function Big (Arg : Uns) return Big_Integer is
- (Unsigned_Conversion.To_Big_Integer (Arg))
- with Ghost;
+ function Big (Arg : Uns) return Big_Integer renames
+ Unsigned_Conversion.To_Big_Integer;
-- Maximum value of exponent for 10 that fits in Uns'Base
function Max_Log10 return Natural is
@@ -62,8 +62,9 @@ function System.Width_U (Lo, Hi : Uns) return Natural is
when others => raise Program_Error)
with Ghost;
- Max_W : constant Natural := Max_Log10 with Ghost;
- Big_10 : constant Big_Integer := Big (10) with Ghost;
+ ------------------
+ -- Local Lemmas --
+ ------------------
procedure Lemma_Lower_Mult (A, B, C : Big_Natural)
with
@@ -82,15 +83,21 @@ function System.Width_U (Lo, Hi : Uns) return Natural is
Ghost,
Post => X / Y / Z = X / (Y * Z);
- procedure Lemma_Lower_Mult (A, B, C : Big_Natural) is
- begin
- null;
- end Lemma_Lower_Mult;
+ ----------------------
+ -- Lemma_Lower_Mult --
+ ----------------------
- procedure Lemma_Div_Commutation (X, Y : Uns) is
- begin
- null;
- end Lemma_Div_Commutation;
+ procedure Lemma_Lower_Mult (A, B, C : Big_Natural) is null;
+
+ ---------------------------
+ -- Lemma_Div_Commutation --
+ ---------------------------
+
+ procedure Lemma_Div_Commutation (X, Y : Uns) is null;
+
+ ---------------------
+ -- Lemma_Div_Twice --
+ ---------------------
procedure Lemma_Div_Twice (X : Big_Natural; Y, Z : Big_Positive) is
XY : constant Big_Natural := X / Y;
@@ -107,20 +114,31 @@ function System.Width_U (Lo, Hi : Uns) return Natural is
pragma Assert (X / YZ = XYZ + R / YZ);
end Lemma_Div_Twice;
+ -- Local variables
+
+ W : Natural;
+ T : Uns;
+
+ -- Local ghost variables
+
+ Max_W : constant Natural := Max_Log10 with Ghost;
+ Big_10 : constant Big_Integer := Big (10) with Ghost;
+
Pow : Big_Integer := 1 with Ghost;
T_Init : constant Uns := Uns'Max (Lo, Hi) with Ghost;
+-- Start of processing for System.Width_U
+
begin
if Lo > Hi then
return 0;
else
- -- Minimum value is 2, one for sign, one for digit
+ -- Minimum value is 2, one for space, one for digit
W := 2;
- -- Get max of absolute values, but avoid bomb if we have the maximum
- -- negative number (note that First + 1 has same digits as First)
+ -- Get max of absolute values
T := Uns'Max (Lo, Hi);
diff --git a/gcc/ada/libgnat/s-widthu.ads b/gcc/ada/libgnat/s-widthu.ads
index 7b71119..c70d7ae 100644
--- a/gcc/ada/libgnat/s-widthu.ads
+++ b/gcc/ada/libgnat/s-widthu.ads
@@ -36,4 +36,9 @@ generic
type Uns is mod <>;
-function System.Width_U (Lo, Hi : Uns) return Natural;
+function System.Width_U (Lo, Hi : Uns) return Natural
+with
+ Post => (if Lo > Hi then
+ System.Width_U'Result = 0
+ else
+ System.Width_U'Result > 0);
diff --git a/gcc/ada/libgnat/s-widuns.ads b/gcc/ada/libgnat/s-widuns.ads
index 713532e..f694470 100644
--- a/gcc/ada/libgnat/s-widuns.ads
+++ b/gcc/ada/libgnat/s-widuns.ads
@@ -31,6 +31,17 @@
-- Width attribute for modular integers up to Integer
+-- 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);
+
with System.Width_U;
with System.Unsigned_Types;
diff --git a/gcc/ada/par-ch4.adb b/gcc/ada/par-ch4.adb
index 545d83b..d985003 100644
--- a/gcc/ada/par-ch4.adb
+++ b/gcc/ada/par-ch4.adb
@@ -1694,6 +1694,10 @@ package body Ch4 is
end if;
end if;
when Tok_Left_Paren =>
+ if Nkind (Aggregate_Node) = N_Aggregate then
+ Set_Is_Parenthesis_Aggregate (Aggregate_Node);
+ end if;
+
T_Right_Paren;
when others => raise Program_Error;
end case;
@@ -3482,7 +3486,7 @@ package body Ch4 is
New_Node (N_Loop_Parameter_Specification, Prev_Token_Ptr);
Set_Defining_Identifier (Loop_Spec, Id);
- Choice := First (Discrete_Choices (Assoc_Node));
+ Choice := First (Discrete_Choices (Assoc_Node));
Assoc_Node :=
New_Node (N_Iterated_Element_Association, Prev_Token_Ptr);
Set_Loop_Parameter_Specification (Assoc_Node, Loop_Spec);
diff --git a/gcc/ada/rtsfind.adb b/gcc/ada/rtsfind.adb
index 5a89076..0c3a043 100644
--- a/gcc/ada/rtsfind.adb
+++ b/gcc/ada/rtsfind.adb
@@ -1248,9 +1248,10 @@ package body Rtsfind is
-- for this unit to the current compilation unit.
declare
- LibUnit : constant Node_Id := Unit (Cunit (U.Unum));
- Clause : Node_Id;
- Withn : Node_Id;
+ LibUnit : constant Node_Id := Unit (Cunit (U.Unum));
+ Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
+ Clause : Node_Id;
+ Withn : Node_Id;
begin
Clause := U.First_Implicit_With;
@@ -1262,11 +1263,18 @@ package body Rtsfind is
Clause := Next_Implicit_With (Clause);
end loop;
+ -- We want to make sure that the "with" we create below isn't
+ -- marked as ignored ghost code because this list may be walked
+ -- later, after ignored ghost code is converted to a null
+ -- statement.
+
+ Ghost_Mode := None;
Withn :=
Make_With_Clause (Standard_Location,
Name =>
Make_Unit_Name
(U, Defining_Unit_Name (Specification (LibUnit))));
+ Ghost_Mode := Saved_GM;
Set_Corresponding_Spec (Withn, U.Entity);
Set_First_Name (Withn);
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index bedea07..2802a64 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -626,6 +626,7 @@ package Rtsfind is
RE_Wait_For_Release, -- Ada.Synchronous_Barriers
RE_Suspend_Until_True, -- Ada.Synchronous_Task_Control
+ RE_Suspension_Object, -- Ada.Synchronous_Task_Control
RE_Access_Level, -- Ada.Tags
RE_Alignment, -- Ada.Tags
@@ -2311,6 +2312,7 @@ package Rtsfind is
RE_Wait_For_Release => Ada_Synchronous_Barriers,
RE_Suspend_Until_True => Ada_Synchronous_Task_Control,
+ RE_Suspension_Object => Ada_Synchronous_Task_Control,
RE_Access_Level => Ada_Tags,
RE_Alignment => Ada_Tags,
diff --git a/gcc/ada/scng.adb b/gcc/ada/scng.adb
index fd184b5..33a7267 100644
--- a/gcc/ada/scng.adb
+++ b/gcc/ada/scng.adb
@@ -1425,11 +1425,11 @@ package body Scng is
when '[' =>
- -- [] under -gnatX is an aggregate notation and the special
+ -- [] under -gnat2022 is an aggregate notation and the special
-- wide character notation becomes unsupported since the two
-- are ambiguous.
- if Extensions_Allowed then
+ if Ada_Version >= Ada_2022 then
Scan_Ptr := Scan_Ptr + 1;
Token := Tok_Left_Bracket;
return;
diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb
index 5f9865e..6e76e3d 100644
--- a/gcc/ada/sem_aggr.adb
+++ b/gcc/ada/sem_aggr.adb
@@ -248,7 +248,7 @@ package body Sem_Aggr is
-- The procedure works by recursively checking each nested aggregate.
-- Specifically, after checking a sub-aggregate nested at the i-th level
-- we recursively check all the subaggregates at the i+1-st level (if any).
- -- Note that for aggregates analysis and resolution go hand in hand.
+ -- Note that aggregates analysis and resolution go hand in hand.
-- Aggregate analysis has been delayed up to here and it is done while
-- resolving the aggregate.
--
@@ -918,6 +918,12 @@ package body Sem_Aggr is
and then Ekind (Typ) /= E_Record_Type
and then Ada_Version >= Ada_2022
then
+ -- Check for Ada 2022 and () aggregate.
+
+ if not Is_Homogeneous_Aggregate (N) then
+ Error_Msg_N ("container aggregate must use '['], not ()", N);
+ end if;
+
Resolve_Container_Aggregate (N, Typ);
elsif Is_Record_Type (Typ) then
@@ -1792,6 +1798,22 @@ package body Sem_Aggr is
return False;
end if;
+ -- Disable the warning for GNAT Mode to allow for easier transition.
+
+ if Ada_Version >= Ada_2022
+ and then Warn_On_Obsolescent_Feature
+ and then not GNAT_Mode
+ and then not Is_Homogeneous_Aggregate (N)
+ and then not Is_Enum_Array_Aggregate (N)
+ and then Is_Parenthesis_Aggregate (N)
+ and then Nkind (Parent (N)) /= N_Qualified_Expression
+ and then Comes_From_Source (N)
+ then
+ Error_Msg_N
+ ("?j?array aggregate using () is an" &
+ " obsolescent syntax, use '['] instead", N);
+ end if;
+
-- STEP 1: make sure the aggregate is correctly formatted
if Present (Component_Associations (N)) then
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index e0f7249..83ae95e 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -732,9 +732,10 @@ package body Sem_Ch12 is
-- associated freeze node. Insert the freeze node before the first source
-- body which follows immediately after N. If no such body is found, the
-- freeze node is inserted at the end of the declarative region which
- -- contains N. This can also be invoked to insert the freeze node of a
- -- package that encloses an instantiation, in which case N may denote an
- -- arbitrary node.
+ -- contains N, unless the instantiation is done in a package spec that is
+ -- not at library level, in which case it is inserted at the outer level.
+ -- This can also be invoked to insert the freeze node of a package that
+ -- encloses an instantiation, in which case N may denote an arbitrary node.
procedure Install_Formal_Packages (Par : Entity_Id);
-- Install the visible part of any formal of the parent that is a formal
@@ -9208,8 +9209,7 @@ package body Sem_Ch12 is
-- of a package declaration, and the inner instance is in
-- the corresponding private part.
- if Parent (List_Containing (Get_Unit_Instantiation_Node
- (Par_Id)))
+ if Parent (List_Containing (Freeze_Node (Par_Id)))
= Parent (List_Containing (N))
and then Sloc (Freeze_Node (Par_Id)) <= Sloc (N)
then
@@ -9266,7 +9266,8 @@ package body Sem_Ch12 is
-- the body.
elsif In_Same_List (Freeze_Node (Par_Id), Parent (N))
- and then Sloc (Freeze_Node (Par_Id)) < Sloc (Parent (N))
+ and then
+ Sloc (Freeze_Node (Par_Id)) <= Sloc (Parent (N))
then
Insert_Freeze_Node_For_Instance
(Parent (N), Freeze_Node (Enclosing));
@@ -9403,7 +9404,7 @@ package body Sem_Ch12 is
-- after that of Parent_Inst. This relation is established by
-- comparing the Slocs of Parent_Inst freeze node and Inst.
- elsif In_Same_List (Get_Unit_Instantiation_Node (Par_Id), N)
+ elsif In_Same_List (Freeze_Node (Par_Id), N)
and then Sloc (Freeze_Node (Par_Id)) <= Sloc (N)
then
Insert_Freeze_Node_For_Instance (N, F_Node);
@@ -9844,12 +9845,6 @@ package body Sem_Ch12 is
(N : Node_Id;
F_Node : Node_Id)
is
- Decl : Node_Id;
- Decls : List_Id;
- Inst : Entity_Id;
- Par_Inst : Node_Id;
- Par_N : Node_Id;
-
function Enclosing_Body (N : Node_Id) return Node_Id;
-- Find enclosing package or subprogram body, if any. Freeze node may
-- be placed at end of current declarative list if previous instance
@@ -9908,138 +9903,183 @@ package body Sem_Ch12 is
return Empty;
end Previous_Instance;
+ -- Local variables
+
+ Decl : Node_Id;
+ Decls : List_Id;
+ Inst : Entity_Id;
+ Par_Inst : Node_Id;
+ Par_N : Node_Id;
+
-- Start of processing for Insert_Freeze_Node_For_Instance
begin
- if not Is_List_Member (F_Node) then
- Decl := N;
- Decls := List_Containing (N);
- Par_N := Parent (Decls);
- Inst := Entity (F_Node);
+ -- Nothing to do if the freeze node has already been inserted
- -- When processing a subprogram instantiation, utilize the actual
- -- subprogram instantiation rather than its package wrapper as it
- -- carries all the context information.
+ if Is_List_Member (F_Node) then
+ return;
+ end if;
- if Is_Wrapper_Package (Inst) then
- Inst := Related_Instance (Inst);
- end if;
+ Inst := Entity (F_Node);
- Par_Inst := Parent (Inst);
+ -- When processing a subprogram instantiation, utilize the actual
+ -- subprogram instantiation rather than its package wrapper as it
+ -- carries all the context information.
- -- If this is a package instance, check whether the generic is
- -- declared in a previous instance and the current instance is
- -- not within the previous one.
+ if Is_Wrapper_Package (Inst) then
+ Inst := Related_Instance (Inst);
+ end if;
- if Present (Generic_Parent (Par_Inst)) and then Is_In_Main_Unit (N)
- then
- declare
- Enclosing_N : constant Node_Id := Enclosing_Body (N);
- Par_I : constant Entity_Id :=
- Previous_Instance (Generic_Parent (Par_Inst));
- Scop : Entity_Id;
+ Par_Inst := Parent (Inst);
- begin
- if Present (Par_I)
- and then Earlier (N, Freeze_Node (Par_I))
- then
- Scop := Scope (Inst);
-
- -- If the current instance is within the one that contains
- -- the generic, the freeze node for the current one must
- -- appear in the current declarative part. Ditto, if the
- -- current instance is within another package instance or
- -- within a body that does not enclose the current instance.
- -- In these three cases the freeze node of the previous
- -- instance is not relevant.
-
- while Present (Scop) and then Scop /= Standard_Standard loop
- exit when Scop = Par_I
- or else
- (Is_Generic_Instance (Scop)
- and then Scope_Depth (Scop) > Scope_Depth (Par_I));
- Scop := Scope (Scop);
- end loop;
+ -- If this is a package instance, check whether the generic is declared
+ -- in a previous instance and the current instance is not within the
+ -- previous one.
- -- Previous instance encloses current instance
+ if Present (Generic_Parent (Par_Inst)) and then Is_In_Main_Unit (N) then
+ declare
+ Enclosing_N : constant Node_Id := Enclosing_Body (N);
+ Par_I : constant Entity_Id :=
+ Previous_Instance (Generic_Parent (Par_Inst));
+ Scop : Entity_Id;
- if Scop = Par_I then
- null;
+ begin
+ if Present (Par_I) and then Earlier (N, Freeze_Node (Par_I)) then
+ Scop := Scope (Inst);
- -- If the next node is a source body we must freeze in
- -- the current scope as well.
+ -- If the current instance is within the one that contains
+ -- the generic, the freeze node for the current one must
+ -- appear in the current declarative part. Ditto, if the
+ -- current instance is within another package instance or
+ -- within a body that does not enclose the current instance.
+ -- In these three cases the freeze node of the previous
+ -- instance is not relevant.
- elsif Present (Next (N))
- and then Nkind (Next (N)) in N_Subprogram_Body
- | N_Package_Body
- and then Comes_From_Source (Next (N))
- then
- null;
+ while Present (Scop) and then Scop /= Standard_Standard loop
+ exit when Scop = Par_I
+ or else
+ (Is_Generic_Instance (Scop)
+ and then Scope_Depth (Scop) > Scope_Depth (Par_I));
+ Scop := Scope (Scop);
+ end loop;
- -- Current instance is within an unrelated instance
+ -- Previous instance encloses current instance
- elsif Is_Generic_Instance (Scop) then
- null;
+ if Scop = Par_I then
+ null;
- -- Current instance is within an unrelated body
+ -- If the next node is a source body we must freeze in the
+ -- current scope as well.
- elsif Present (Enclosing_N)
- and then Enclosing_N /= Enclosing_Body (Par_I)
- then
- null;
+ elsif Present (Next (N))
+ and then Nkind (Next (N)) in N_Subprogram_Body
+ | N_Package_Body
+ and then Comes_From_Source (Next (N))
+ then
+ null;
- else
- Insert_After (Freeze_Node (Par_I), F_Node);
- return;
- end if;
- end if;
- end;
- end if;
+ -- Current instance is within an unrelated instance
- -- When the instantiation occurs in a package declaration, append the
- -- freeze node to the private declarations (if any).
+ elsif Is_Generic_Instance (Scop) then
+ null;
- if Nkind (Par_N) = N_Package_Specification
- and then Decls = Visible_Declarations (Par_N)
- and then not Is_Empty_List (Private_Declarations (Par_N))
- then
- Decls := Private_Declarations (Par_N);
- Decl := First (Decls);
- end if;
-
- -- Determine the proper freeze point of a package instantiation. We
- -- adhere to the general rule of a package or subprogram body causing
- -- freezing of anything before it in the same declarative region. In
- -- this case, the proper freeze point of a package instantiation is
- -- before the first source body which follows, or before a stub. This
- -- ensures that entities coming from the instance are already frozen
- -- and usable in source bodies.
-
- if Nkind (Par_N) /= N_Package_Declaration
- and then Ekind (Inst) = E_Package
- and then Is_Generic_Instance (Inst)
- and then not In_Same_Source_Unit (Generic_Parent (Par_Inst), Inst)
- then
- while Present (Decl) loop
- if (Nkind (Decl) in N_Unit_Body
- or else
- Nkind (Decl) in N_Body_Stub)
- and then Comes_From_Source (Decl)
+ -- Current instance is within an unrelated body
+
+ elsif Present (Enclosing_N)
+ and then Enclosing_N /= Enclosing_Body (Par_I)
then
- Insert_Before (Decl, F_Node);
+ null;
+
+ else
+ Insert_After (Freeze_Node (Par_I), F_Node);
return;
end if;
+ end if;
+ end;
+ end if;
- Next (Decl);
- end loop;
- end if;
+ Decl := N;
+ Decls := List_Containing (N);
+ Par_N := Parent (Decls);
- -- In a package declaration, or if no previous body, insert at end
- -- of list.
+ -- Determine the proper freeze point of an instantiation
- Set_Sloc (F_Node, Sloc (Last (Decls)));
- Insert_After (Last (Decls), F_Node);
+ if Is_Generic_Instance (Inst) then
+ loop
+ -- When the instantiation occurs in a package spec, append the
+ -- freeze node to the private declarations (if any).
+
+ if Nkind (Par_N) = N_Package_Specification
+ and then Decls = Visible_Declarations (Par_N)
+ and then not Is_Empty_List (Private_Declarations (Par_N))
+ then
+ Decls := Private_Declarations (Par_N);
+ Decl := First (Decls);
+ end if;
+
+ -- We adhere to the general rule of a package or subprogram body
+ -- causing freezing of anything before it in the same declarative
+ -- region. In this respect, the proper freeze point of a package
+ -- instantiation is before the first source body which follows, or
+ -- before a stub. This ensures that entities from the instance are
+ -- already frozen and therefore usable in source bodies.
+
+ if Nkind (Par_N) /= N_Package_Declaration
+ and then
+ not In_Same_Source_Unit (Generic_Parent (Par_Inst), Inst)
+ then
+ while Present (Decl) loop
+ if (Nkind (Decl) in N_Unit_Body
+ or else
+ Nkind (Decl) in N_Body_Stub)
+ and then Comes_From_Source (Decl)
+ then
+ Set_Sloc (F_Node, Sloc (Decl));
+ Insert_Before (Decl, F_Node);
+ return;
+ end if;
+
+ Next (Decl);
+ end loop;
+ end if;
+
+ -- When the instantiation occurs in a package spec and there is
+ -- no source body which follows, and the package has a body but
+ -- is delayed, then insert immediately before its freeze node.
+
+ if Nkind (Par_N) = N_Package_Specification
+ and then Present (Corresponding_Body (Parent (Par_N)))
+ and then Present (Freeze_Node (Defining_Entity (Par_N)))
+ then
+ Set_Sloc (F_Node, Sloc (Freeze_Node (Defining_Entity (Par_N))));
+ Insert_Before (Freeze_Node (Defining_Entity (Par_N)), F_Node);
+ return;
+
+ -- When the instantiation occurs in a package spec and there is
+ -- no source body which follows, not even of the package itself
+ -- then insert into the declaration list of the outer level.
+
+ elsif Nkind (Par_N) = N_Package_Specification
+ and then No (Corresponding_Body (Parent (Par_N)))
+ and then Is_List_Member (Parent (Par_N))
+ then
+ Decl := Parent (Par_N);
+ Decls := List_Containing (Decl);
+ Par_N := Parent (Decls);
+
+ -- In a package declaration, or if no source body which follows
+ -- and at library level, then insert at end of list.
+
+ else
+ exit;
+ end if;
+ end loop;
end if;
+
+ -- Insert and adjust the Sloc of the freeze node
+
+ Set_Sloc (F_Node, Sloc (Last (Decls)));
+ Insert_After (Last (Decls), F_Node);
end Insert_Freeze_Node_For_Instance;
-----------------------------
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index d63d60f..ba41209 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -12284,26 +12284,18 @@ package body Sem_Ch13 is
-- Find maximum bit of any component of the parent type
Parent_Last_Bit := UI_From_Int (System_Address_Size - 1);
- Pcomp := First_Entity (Tagged_Parent);
+ Pcomp := First_Component_Or_Discriminant (Tagged_Parent);
while Present (Pcomp) loop
- if Ekind (Pcomp) in E_Discriminant | E_Component then
- if Present (Component_Bit_Offset (Pcomp))
- and then Known_Static_Esize (Pcomp)
- then
- Parent_Last_Bit :=
- UI_Max
- (Parent_Last_Bit,
- Component_Bit_Offset (Pcomp) + Esize (Pcomp) - 1);
- end if;
- else
-
- -- Skip anonymous types generated for constrained array
- -- or record components.
-
- null;
+ if Present (Component_Bit_Offset (Pcomp))
+ and then Known_Static_Esize (Pcomp)
+ then
+ Parent_Last_Bit :=
+ UI_Max
+ (Parent_Last_Bit,
+ Component_Bit_Offset (Pcomp) + Esize (Pcomp) - 1);
end if;
- Next_Entity (Pcomp);
+ Next_Component_Or_Discriminant (Pcomp);
end loop;
end if;
end;
@@ -15558,7 +15550,7 @@ package body Sem_Ch13 is
Add_Unnamed_Subp := Subp;
elsif Op_Name = Name_New_Indexed then
- New_Indexed_Subp := Subp;
+ New_Indexed_Subp := Subp;
elsif Op_Name = Name_Assign_Indexed then
Assign_Indexed_Subp := Subp;
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index edcc1ca..6b25a6a 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -6815,8 +6815,7 @@ package body Sem_Ch3 is
-- in a dispatch table.
if not GNATprove_Mode then
- Ensure_Freeze_Node (Id);
- Append_Freeze_Actions (Id, New_List (New_Decl));
+ Append_Freeze_Action (Id, 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
@@ -16369,12 +16368,12 @@ package body Sem_Ch3 is
------------------------
function Check_Derived_Type return Boolean is
- E : Entity_Id;
- Elmt : Elmt_Id;
- List : Elist_Id;
- New_Subp : Entity_Id;
- Op_Elmt : Elmt_Id;
- Subp : Entity_Id;
+ E : Entity_Id;
+ Derived_Elmt : Elmt_Id;
+ Derived_Op : Entity_Id;
+ Derived_Ops : Elist_Id;
+ Parent_Elmt : Elmt_Id;
+ Parent_Op : Entity_Id;
begin
-- Traverse list of entities in the current scope searching for
@@ -16389,7 +16388,7 @@ package body Sem_Ch3 is
-- Disable this test if Derived_Type completes an incomplete
-- type because in such case more primitives can be added
-- later to the list of primitives of Derived_Type by routine
- -- Process_Incomplete_Dependents
+ -- Process_Incomplete_Dependents.
return True;
end if;
@@ -16397,13 +16396,13 @@ package body Sem_Ch3 is
Next_Entity (E);
end loop;
- List := Collect_Primitive_Operations (Derived_Type);
- Elmt := First_Elmt (List);
+ Derived_Ops := Collect_Primitive_Operations (Derived_Type);
- Op_Elmt := First_Elmt (Op_List);
- while Present (Op_Elmt) loop
- Subp := Node (Op_Elmt);
- New_Subp := Node (Elmt);
+ Derived_Elmt := First_Elmt (Derived_Ops);
+ Parent_Elmt := First_Elmt (Op_List);
+ while Present (Parent_Elmt) loop
+ Parent_Op := Node (Parent_Elmt);
+ Derived_Op := Node (Derived_Elmt);
-- At this early stage Derived_Type has no entities with attribute
-- Interface_Alias. In addition, such primitives are always
@@ -16411,31 +16410,31 @@ package body Sem_Ch3 is
-- Therefore, if found we can safely stop processing pending
-- entities.
- exit when Present (Interface_Alias (Subp));
+ exit when Present (Interface_Alias (Parent_Op));
-- Handle hidden entities
- if not Is_Predefined_Dispatching_Operation (Subp)
- and then Is_Hidden (Subp)
+ if not Is_Predefined_Dispatching_Operation (Parent_Op)
+ and then Is_Hidden (Parent_Op)
then
- if Present (New_Subp)
- and then Primitive_Names_Match (Subp, New_Subp)
+ if Present (Derived_Op)
+ and then Primitive_Names_Match (Parent_Op, Derived_Op)
then
- Next_Elmt (Elmt);
+ Next_Elmt (Derived_Elmt);
end if;
else
- if not Present (New_Subp)
- or else Ekind (Subp) /= Ekind (New_Subp)
- or else not Primitive_Names_Match (Subp, New_Subp)
+ if No (Derived_Op)
+ or else Ekind (Parent_Op) /= Ekind (Derived_Op)
+ or else not Primitive_Names_Match (Parent_Op, Derived_Op)
then
return False;
end if;
- Next_Elmt (Elmt);
+ Next_Elmt (Derived_Elmt);
end if;
- Next_Elmt (Op_Elmt);
+ Next_Elmt (Parent_Elmt);
end loop;
return True;
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 9c21732..fa4de4c 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -2715,13 +2715,11 @@ package body Sem_Ch6 is
end if;
else
- Ensure_Freeze_Node (Typ);
-
declare
IR : constant Node_Id := Make_Itype_Reference (Sloc (N));
begin
Set_Itype (IR, Etype (Designator));
- Append_Freeze_Actions (Typ, New_List (IR));
+ Append_Freeze_Action (Typ, IR);
end;
end if;
diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
index e3a4881..34f7ac1 100644
--- a/gcc/ada/sem_ch8.adb
+++ b/gcc/ada/sem_ch8.adb
@@ -4689,7 +4689,6 @@ package body Sem_Ch8 is
if Is_Tagged_Type (Etype (P))
and then In_Open_Scopes (Scope (Etype (P)))
then
- Ensure_Freeze_Node (Etype (P));
Append_Freeze_Action (Etype (P), Body_Node);
else
Rewrite (N, Body_Node);
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 2f5070a..882eb23 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -17236,7 +17236,7 @@ package body Sem_Util is
-- The current type is a match
- if Is_Suspension_Object (Cur_Typ) then
+ if Is_RTE (Cur_Typ, RE_Suspension_Object) then
return True;
-- Stop the traversal once the root of the derivation chain has been
@@ -17803,15 +17803,14 @@ package body Sem_Util is
-- Otherwise see if all record components are initialized
declare
- Ent : Entity_Id;
+ Comp : Entity_Id;
begin
- Ent := First_Entity (Typ);
- while Present (Ent) loop
- if Ekind (Ent) = E_Component
- and then (No (Parent (Ent))
- or else No (Expression (Parent (Ent))))
- and then not Is_Fully_Initialized_Type (Etype (Ent))
+ Comp := First_Component (Typ);
+ while Present (Comp) loop
+ if (No (Parent (Comp))
+ or else No (Expression (Parent (Comp))))
+ and then not Is_Fully_Initialized_Type (Etype (Comp))
-- Special VM case for tag components, which need to be
-- defined in this case, but are never initialized as VMs
@@ -17819,12 +17818,12 @@ package body Sem_Util is
-- uninitialized case. Note that this applies both to the
-- uTag entry and the main vtable pointer (CPP_Class case).
- and then (Tagged_Type_Expansion or else not Is_Tag (Ent))
+ and then (Tagged_Type_Expansion or else not Is_Tag (Comp))
then
return False;
end if;
- Next_Entity (Ent);
+ Next_Component (Comp);
end loop;
end;
@@ -21124,28 +21123,6 @@ package body Sem_Util is
return True;
end Is_Suitable_Primitive;
- --------------------------
- -- Is_Suspension_Object --
- --------------------------
-
- function Is_Suspension_Object (Id : Entity_Id) return Boolean is
- begin
- -- This approach does an exact name match rather than to rely on
- -- RTSfind. Routine Is_Effectively_Volatile is used by clients of the
- -- front end at point where all auxiliary tables are locked and any
- -- modifications to them are treated as violations. Do not tamper with
- -- the tables, instead examine the Chars fields of all the scopes of Id.
-
- return
- Chars (Id) = Name_Suspension_Object
- and then Present (Scope (Id))
- and then Chars (Scope (Id)) = Name_Synchronous_Task_Control
- and then Present (Scope (Scope (Id)))
- and then Chars (Scope (Scope (Id))) = Name_Ada
- and then Present (Scope (Scope (Scope (Id))))
- and then Scope (Scope (Scope (Id))) = Standard_Standard;
- end Is_Suspension_Object;
-
----------------------------
-- Is_Synchronized_Object --
----------------------------
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index 2878fce..b2bd9d5 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -372,7 +372,7 @@ package Sem_Util is
procedure Check_Ambiguous_Aggregate (Call : Node_Id);
-- Additional information on an ambiguous call in Ada_2022 when a
-- subprogram call has an actual that is an aggregate, and the
- -- presence of container aggregates (or types with the correwponding
+ -- presence of container aggregates (or types with the corresponding
-- aspect) provides an additional interpretation. Message indicates
-- that an aggregate actual should carry a type qualification.
@@ -2440,10 +2440,6 @@ package Sem_Util is
-- Determine whether arbitrary subprogram Subp_Id may act as a primitive of
-- an arbitrary tagged type.
- function Is_Suspension_Object (Id : Entity_Id) return Boolean;
- -- Determine whether arbitrary entity Id denotes Suspension_Object defined
- -- in Ada.Synchronous_Task_Control.
-
function Is_Synchronized_Object (Id : Entity_Id) return Boolean;
-- Determine whether entity Id denotes an object and if it does, whether
-- this object is synchronized as specified in SPARK RM 9.1. To qualify as
diff --git a/gcc/ada/sem_warn.adb b/gcc/ada/sem_warn.adb
index d9d5d95..951b9f8 100644
--- a/gcc/ada/sem_warn.adb
+++ b/gcc/ada/sem_warn.adb
@@ -1548,18 +1548,17 @@ package body Sem_Warn is
Comp : Entity_Id;
begin
- Comp := First_Entity (E1T);
+ Comp := First_Component (E1T);
while Present (Comp) loop
- if Ekind (Comp) = E_Component
- and then Nkind (Parent (Comp)) =
- N_Component_Declaration
+ if Nkind (Parent (Comp)) =
+ N_Component_Declaration
and then No (Expression (Parent (Comp)))
then
Error_Msg_Node_2 := Comp;
exit;
end if;
- Next_Entity (Comp);
+ Next_Component (Comp);
end loop;
end;
end if;
@@ -1569,15 +1568,13 @@ package body Sem_Warn is
-- For access types, UR was only set for dereferences,
-- so the issue is that the value may be null.
- if not Is_Trivial_Subprogram (Scope (E1)) then
- if not Warnings_Off_E1 then
- if Is_Access_Type (Etype (Parent (UR))) then
- Error_Msg_N ("??`&.&` may be null!", UR);
- else
- Error_Msg_N
- ("??`&.&` may be referenced before "
- & "it has a value!", UR);
- end if;
+ if not Warnings_Off_E1 then
+ if Is_Access_Type (Etype (Parent (UR))) then
+ Error_Msg_N ("??`&.&` may be null!", UR);
+ else
+ Error_Msg_N
+ ("??`&.&` may be referenced before "
+ & "it has a value!", UR);
end if;
end if;
@@ -4239,8 +4236,7 @@ package body Sem_Warn is
(Return_Node : Node_Id;
Scope_Id : Entity_Id)
is
- Form : Entity_Id;
- Form2 : Entity_Id;
+ Form : Entity_Id;
begin
-- Ignore if procedure or return statement does not come from source
@@ -4251,6 +4247,26 @@ package body Sem_Warn is
return;
end if;
+ -- Before we issue the warning, add an ad hoc defence against the most
+ -- common case of false positives with this warning which is the case
+ -- where there is a Boolean OUT parameter that has been set, and whose
+ -- meaning is "ignore the values of the other parameters". We can't of
+ -- course reliably tell this case at compile time, but the following
+ -- test kills a lot of false positives, without generating a significant
+ -- number of false negatives (missed real warnings).
+
+ Form := First_Formal (Scope_Id);
+ while Present (Form) loop
+ if Ekind (Form) = E_Out_Parameter
+ and then Root_Type (Etype (Form)) = Standard_Boolean
+ and then not Never_Set_In_Source_Check_Spec (Form)
+ then
+ return;
+ end if;
+
+ Next_Formal (Form);
+ end loop;
+
-- Loop through formals
Form := First_Formal (Scope_Id);
@@ -4265,27 +4281,6 @@ package body Sem_Warn is
and then Is_Scalar_Type (Etype (Form))
and then not Present (Unset_Reference (Form))
then
- -- Before we issue the warning, an add ad hoc defence against the
- -- most common case of false positives with this warning which is
- -- the case where there is a Boolean OUT parameter that has been
- -- set, and whose meaning is "ignore the values of the other
- -- parameters". We can't of course reliably tell this case at
- -- compile time, but the following test kills a lot of false
- -- positives, without generating a significant number of false
- -- negatives (missed real warnings).
-
- Form2 := First_Formal (Scope_Id);
- while Present (Form2) loop
- if Ekind (Form2) = E_Out_Parameter
- and then Root_Type (Etype (Form2)) = Standard_Boolean
- and then not Never_Set_In_Source_Check_Spec (Form2)
- then
- return;
- end if;
-
- Next_Formal (Form2);
- end loop;
-
-- Here all conditions are met, record possible unset reference
Set_Unset_Reference (Form, Return_Node);
diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl
index e1af28b..cf4327a 100644
--- a/gcc/ada/snames.ads-tmpl
+++ b/gcc/ada/snames.ads-tmpl
@@ -1401,7 +1401,6 @@ package Snames is
-- e.g. Name_UP_RESULT corresponds to the name "RESULT".
Name_UP_RESULT : constant Name_Id := N + $;
- Name_Suspension_Object : constant Name_Id := N + $;
Name_Synchronous_Task_Control : constant Name_Id := N + $;
-- Names used to implement iterators over predefined containers
diff --git a/gcc/ada/sprint.adb b/gcc/ada/sprint.adb
index c13be5d..ba2ab3a 100644
--- a/gcc/ada/sprint.adb
+++ b/gcc/ada/sprint.adb
@@ -673,6 +673,11 @@ package body Sprint is
end if;
end loop;
end if;
+
+ -- See above for the rationale, but we cannot do it earlier for them
+
+ Print_Generated_Code := False;
+ Debug_Generated_Code := False;
end Source_Dump;
---------------------
diff --git a/gcc/ada/vxworks7-cert-rtp-link__ppcXX.spec b/gcc/ada/vxworks7-cert-rtp-link__ppcXX.spec
new file mode 100644
index 0000000..8671cea
--- /dev/null
+++ b/gcc/ada/vxworks7-cert-rtp-link__ppcXX.spec
@@ -0,0 +1,10 @@
+*self_spec:
++ %{!nostdlib:-nodefaultlibs -nostartfiles}
+
+*link:
++ %{!nostdlib:%{mrtp:%{!shared: \
+ %(base_link) \
+ -lcert -lgnu \
+ -L%:getenv(VSB_DIR /usr/lib/common/objcert) \
+ -T%:getenv(VSB_DIR /usr/ldscripts/rtp.ld) \
+ }}}
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index 6c51da2..bcbd8de 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,22 @@
+2021-12-06 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/103533
+ * constraint-manager.cc (equiv_class::contains_non_constant_p):
+ New.
+ (constraint_manager::canonicalize): Call it when determining
+ redundant ECs.
+ (selftest::test_purging): New selftest.
+ (selftest::run_constraint_manager_tests): Likewise.
+ * constraint-manager.h (equiv_class::contains_non_constant_p):
+ New decl.
+
+2021-12-01 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/102471
+ * region-model-reachability.cc (reachable_regions::handle_parm):
+ Treat all svalues within a compound parm has reachable, and those
+ wrapped in a cast.
+
2021-11-29 David Malcolm <dmalcolm@redhat.com>
PR analyzer/103217
diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc
index ea6b5dc..76e44e7 100644
--- a/gcc/analyzer/constraint-manager.cc
+++ b/gcc/analyzer/constraint-manager.cc
@@ -1145,6 +1145,30 @@ equiv_class::canonicalize ()
m_vars.qsort (svalue::cmp_ptr_ptr);
}
+/* Return true if this EC contains a variable, false if it merely
+ contains constants.
+ Subroutine of constraint_manager::canonicalize, for removing
+ redundant ECs. */
+
+bool
+equiv_class::contains_non_constant_p () const
+{
+ if (m_constant)
+ {
+ for (auto iter : m_vars)
+ if (iter->maybe_get_constant ())
+ continue;
+ else
+ /* We have {non-constant == constant}. */
+ return true;
+ /* We only have constants. */
+ return false;
+ }
+ else
+ /* Return true if we have {non-constant == non-constant}. */
+ return m_vars.length () > 1;
+}
+
/* Get a debug string for C_OP. */
const char *
@@ -2718,8 +2742,7 @@ constraint_manager::canonicalize ()
{
equiv_class *ec = m_equiv_classes[i];
if (!used_ecs.contains (ec)
- && ((ec->m_vars.length () < 2 && ec->m_constant == NULL_TREE)
- || (ec->m_vars.length () == 0)))
+ && !ec->contains_non_constant_p ())
{
m_equiv_classes.unordered_remove (i);
delete ec;
@@ -3704,6 +3727,127 @@ test_many_constants ()
}
}
+/* Verify that purging state relating to a variable doesn't leave stray
+ equivalence classes (after canonicalization). */
+
+static void
+test_purging (void)
+{
+ tree int_0 = build_int_cst (integer_type_node, 0);
+ tree a = build_global_decl ("a", integer_type_node);
+ tree b = build_global_decl ("b", integer_type_node);
+
+ /* "a != 0". */
+ {
+ region_model_manager mgr;
+ region_model model (&mgr);
+ ADD_SAT_CONSTRAINT (model, a, NE_EXPR, int_0);
+ ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
+ ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
+
+ /* Purge state for "a". */
+ const svalue *sval_a = model.get_rvalue (a, NULL);
+ model.purge_state_involving (sval_a, NULL);
+ model.canonicalize ();
+ /* We should have an empty constraint_manager. */
+ ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0);
+ ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
+ }
+
+ /* "a != 0" && "b != 0". */
+ {
+ region_model_manager mgr;
+ region_model model (&mgr);
+ ADD_SAT_CONSTRAINT (model, a, NE_EXPR, int_0);
+ ADD_SAT_CONSTRAINT (model, b, NE_EXPR, int_0);
+ ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 3);
+ ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 2);
+
+ /* Purge state for "a". */
+ const svalue *sval_a = model.get_rvalue (a, NULL);
+ model.purge_state_involving (sval_a, NULL);
+ model.canonicalize ();
+ /* We should just have the constraint/ECs involving b != 0. */
+ ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
+ ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
+ ASSERT_CONDITION_TRUE (model, b, NE_EXPR, int_0);
+ }
+
+ /* "a != 0" && "b == 0". */
+ {
+ region_model_manager mgr;
+ region_model model (&mgr);
+ ADD_SAT_CONSTRAINT (model, a, NE_EXPR, int_0);
+ ADD_SAT_CONSTRAINT (model, b, EQ_EXPR, int_0);
+ ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
+ ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
+
+ /* Purge state for "a". */
+ const svalue *sval_a = model.get_rvalue (a, NULL);
+ model.purge_state_involving (sval_a, NULL);
+ model.canonicalize ();
+ /* We should just have the EC involving b == 0. */
+ ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
+ ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
+ ASSERT_CONDITION_TRUE (model, b, EQ_EXPR, int_0);
+ }
+
+ /* "a == 0". */
+ {
+ region_model_manager mgr;
+ region_model model (&mgr);
+ ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_0);
+ ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
+ ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
+
+ /* Purge state for "a". */
+ const svalue *sval_a = model.get_rvalue (a, NULL);
+ model.purge_state_involving (sval_a, NULL);
+ model.canonicalize ();
+ /* We should have an empty constraint_manager. */
+ ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0);
+ ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
+ }
+
+ /* "a == 0" && "b != 0". */
+ {
+ region_model_manager mgr;
+ region_model model (&mgr);
+ ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_0);
+ ADD_SAT_CONSTRAINT (model, b, NE_EXPR, int_0);
+ ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
+ ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
+
+ /* Purge state for "a". */
+ const svalue *sval_a = model.get_rvalue (a, NULL);
+ model.purge_state_involving (sval_a, NULL);
+ model.canonicalize ();
+ /* We should just have the constraint/ECs involving b != 0. */
+ ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
+ ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
+ ASSERT_CONDITION_TRUE (model, b, NE_EXPR, int_0);
+ }
+
+ /* "a == 0" && "b == 0". */
+ {
+ region_model_manager mgr;
+ region_model model (&mgr);
+ ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_0);
+ ADD_SAT_CONSTRAINT (model, b, EQ_EXPR, int_0);
+ ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
+ ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
+
+ /* Purge state for "a". */
+ const svalue *sval_a = model.get_rvalue (a, NULL);
+ model.purge_state_involving (sval_a, NULL);
+ model.canonicalize ();
+ /* We should just have the EC involving b == 0. */
+ ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
+ ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
+ ASSERT_CONDITION_TRUE (model, b, EQ_EXPR, int_0);
+ }
+}
+
/* Implementation detail of ASSERT_DUMP_BOUNDED_RANGES_EQ. */
static void
@@ -4035,6 +4179,7 @@ run_constraint_manager_tests (bool transitivity)
test_constraint_impl ();
test_equality ();
test_many_constants ();
+ test_purging ();
test_bounded_range ();
test_bounded_ranges ();
diff --git a/gcc/analyzer/constraint-manager.h b/gcc/analyzer/constraint-manager.h
index 0a430ea..c7b9d9c 100644
--- a/gcc/analyzer/constraint-manager.h
+++ b/gcc/analyzer/constraint-manager.h
@@ -248,6 +248,8 @@ public:
json::object *to_json () const;
+ bool contains_non_constant_p () const;
+
/* An equivalence class can contain multiple constants (e.g. multiple
different zeroes, for different types); these are just for the last
constant added. */
diff --git a/gcc/analyzer/region-model-reachability.cc b/gcc/analyzer/region-model-reachability.cc
index b5ae787..f82f7e6 100644
--- a/gcc/analyzer/region-model-reachability.cc
+++ b/gcc/analyzer/region-model-reachability.cc
@@ -258,6 +258,19 @@ reachable_regions::handle_parm (const svalue *sval, tree param_type)
const region *pointee_reg = parm_ptr->get_pointee ();
add (pointee_reg, is_mutable);
}
+ /* Treat all svalues within a compound_svalue as reachable. */
+ if (const compound_svalue *compound_sval
+ = sval->dyn_cast_compound_svalue ())
+ {
+ for (compound_svalue::iterator_t iter = compound_sval->begin ();
+ iter != compound_sval->end (); ++iter)
+ {
+ const svalue *iter_sval = (*iter).second;
+ handle_sval (iter_sval);
+ }
+ }
+ if (const svalue *cast = sval->maybe_undo_cast ())
+ handle_sval (cast);
}
/* Update the store to mark the clusters that were found to be mutable
diff --git a/gcc/attribs.c b/gcc/attribs.c
index c252f5a..32c9415 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -1285,7 +1285,7 @@ cmp_attrib_identifiers (const_tree attr1, const_tree attr2)
/* Compare two constructor-element-type constants. Return 1 if the lists
are known to be equal; otherwise return 0. */
-static bool
+bool
simple_cst_list_equal (const_tree l1, const_tree l2)
{
while (l1 != NULL_TREE && l2 != NULL_TREE)
diff --git a/gcc/attribs.h b/gcc/attribs.h
index 73f0ccc..f5899d8 100644
--- a/gcc/attribs.h
+++ b/gcc/attribs.h
@@ -60,6 +60,7 @@ extern tree build_type_attribute_variant (tree, tree);
extern tree build_decl_attribute_variant (tree, tree);
extern tree build_type_attribute_qual_variant (tree, tree, int);
+extern bool simple_cst_list_equal (const_tree, const_tree);
extern bool attribute_value_equal (const_tree, const_tree);
/* Return 0 if the attributes for two types are incompatible, 1 if they
diff --git a/gcc/auto-profile.c b/gcc/auto-profile.c
index 4c1fc6b..dfcd681 100644
--- a/gcc/auto-profile.c
+++ b/gcc/auto-profile.c
@@ -1192,7 +1192,8 @@ afdo_find_equiv_class (bb_set *annotated_bb)
/* If a basic block's count is known, and only one of its in/out edges' count
is unknown, its count can be calculated. Meanwhile, if all of the in/out
edges' counts are known, then the basic block's unknown count can also be
- calculated.
+ calculated. Also, if a block has a single predecessor or successor, the block's
+ count can be propagated to that predecessor or successor.
IS_SUCC is true if out edges of a basic blocks are examined.
Update ANNOTATED_BB accordingly.
Return TRUE if any basic block/edge count is changed. */
@@ -1208,6 +1209,7 @@ afdo_propagate_edge (bool is_succ, bb_set *annotated_bb)
edge e, unknown_edge = NULL;
edge_iterator ei;
int num_unknown_edge = 0;
+ int num_edge = 0;
profile_count total_known_count = profile_count::zero ().afdo ();
FOR_EACH_EDGE (e, ei, is_succ ? bb->succs : bb->preds)
@@ -1217,6 +1219,7 @@ afdo_propagate_edge (bool is_succ, bb_set *annotated_bb)
num_unknown_edge++, unknown_edge = e;
else
total_known_count += AFDO_EINFO (e)->get_count ();
+ num_edge++;
}
/* Be careful not to annotate block with no successor in special cases. */
@@ -1230,7 +1233,20 @@ afdo_propagate_edge (bool is_succ, bb_set *annotated_bb)
else if (num_unknown_edge == 1 && is_bb_annotated (bb, *annotated_bb))
{
if (bb->count > total_known_count)
- AFDO_EINFO (unknown_edge)->set_count (bb->count - total_known_count);
+ {
+ profile_count new_count = bb->count - total_known_count;
+ AFDO_EINFO(unknown_edge)->set_count(new_count);
+ if (num_edge == 1)
+ {
+ basic_block succ_or_pred_bb = is_succ ? unknown_edge->dest : unknown_edge->src;
+ if (new_count > succ_or_pred_bb->count)
+ {
+ succ_or_pred_bb->count = new_count;
+ if (!is_bb_annotated (succ_or_pred_bb, *annotated_bb))
+ set_bb_annotated (succ_or_pred_bb, annotated_bb);
+ }
+ }
+ }
else
AFDO_EINFO (unknown_edge)->set_count (profile_count::zero().afdo ());
AFDO_EINFO (unknown_edge)->set_annotated ();
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 6104dc6..f652f59 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,15 @@
+2021-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR pch/71934
+ * c-pch.c (struct c_pch_validity): Remove pch_init member.
+ (pch_init): Don't initialize v.pch_init.
+ (c_common_valid_pch): Don't warn and punt if .text addresses change.
+
+2021-12-01 Jason Merrill <jason@redhat.com>
+
+ PR c++/103310
+ * c.opt: Add -fconstexpr-fp-except.
+
2021-11-29 Richard Biener <rguenther@suse.de>
* c-format.c (check_format_string): Remove spurious
diff --git a/gcc/c-family/c-pch.c b/gcc/c-family/c-pch.c
index 5da6042..2cafa13 100644
--- a/gcc/c-family/c-pch.c
+++ b/gcc/c-family/c-pch.c
@@ -54,7 +54,6 @@ struct c_pch_validity
{
uint32_t pch_write_symbols;
signed char match[MATCH_SIZE];
- void (*pch_init) (void);
size_t target_data_length;
};
@@ -117,7 +116,6 @@ pch_init (void)
gcc_assert (v.match[i] == *pch_matching[i].flag_var);
}
}
- v.pch_init = &pch_init;
target_validity = targetm.get_pch_validity (&v.target_data_length);
if (fwrite (partial_pch, IDENT_LENGTH, 1, f) != 1
@@ -278,19 +276,6 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
}
}
- /* If the text segment was not loaded at the same address as it was
- when the PCH file was created, function pointers loaded from the
- PCH will not be valid. We could in theory remap all the function
- pointers, but no support for that exists at present.
- Since we have the same executable, it should only be necessary to
- check one function. */
- if (v.pch_init != &pch_init)
- {
- cpp_warning (pfile, CPP_W_INVALID_PCH,
- "%s: had text segment at different address", name);
- return 2;
- }
-
/* Check the target-specific validity data. */
{
void *this_file_data = xmalloc (v.target_data_length);
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 4b8a094..915204e 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1615,6 +1615,10 @@ fconstexpr-cache-depth=
C++ ObjC++ Joined RejectNegative UInteger Var(constexpr_cache_depth) Init(8)
-fconstexpr-cache-depth=<number> Specify maximum constexpr recursion cache depth.
+fconstexpr-fp-except
+C++ ObjC++ Var(flag_constexpr_fp_except) Init(0)
+Allow IEC559 floating point exceptions in constant expressions.
+
fconstexpr-loop-limit=
C++ ObjC++ Joined RejectNegative UInteger Var(constexpr_loop_limit) Init(262144)
-fconstexpr-loop-limit=<number> Specify maximum constexpr loop iteration count.
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index d7c5de5..fb2ef2a 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,27 @@
+2021-12-08 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * c-parser.c (struct omp_dim): New struct type for use inside
+ c_parser_omp_variable_list.
+ (c_parser_omp_variable_list): Allow multiple levels of array and
+ component accesses in array section base-pointer expression.
+ (c_parser_omp_clause_to): Set 'allow_deref' to true in call to
+ c_parser_omp_var_list_parens.
+ (c_parser_omp_clause_from): Likewise.
+ * c-typeck.c (handle_omp_array_sections_1): Extend allowed range
+ of base-pointer expressions involving INDIRECT/MEM/ARRAY_REF and
+ POINTER_PLUS_EXPR.
+ (c_finish_omp_clauses): Extend allowed ranged of expressions
+ involving INDIRECT/MEM/ARRAY_REF and POINTER_PLUS_EXPR.
+
+2021-12-08 Chung-Lin Tang <cltang@codesourcery.com>
+
+ PR middle-end/92120
+ * c-parser.c (c_parser_omp_clause_map): Set 'allow_deref' argument in
+ call to c_parser_omp_variable_list to 'true'.
+ * c-typeck.c (handle_omp_array_sections_1): Add strip of MEM_REF in
+ array base handling.
+ (c_finish_omp_clauses): Handle 'A->member' case in map clauses.
+
2021-11-30 Thomas Schwinge <thomas@codesourcery.com>
* c-typeck.c (c_finish_omp_clauses): Remove "gang reduction on an
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index af2bb5b..e99c847 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -12989,19 +12989,29 @@ c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list)
The optional ALLOW_DEREF argument is true if list items can use the deref
(->) operator. */
+struct omp_dim
+{
+ tree low_bound, length;
+ location_t loc;
+ bool no_colon;
+ omp_dim (tree lb, tree len, location_t lo, bool nc)
+ : low_bound (lb), length (len), loc (lo), no_colon (nc) {}
+};
+
static tree
c_parser_omp_variable_list (c_parser *parser,
location_t clause_loc,
enum omp_clause_code kind, tree list,
bool allow_deref = false)
{
+ auto_vec<omp_dim> dims;
+ bool array_section_p;
auto_vec<c_token> tokens;
unsigned int tokens_avail = 0;
bool first = true;
while (1)
{
- bool array_section_p = false;
if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
{
if (c_parser_next_token_is_not (parser, CPP_NAME)
@@ -13120,6 +13130,7 @@ c_parser_omp_variable_list (c_parser *parser,
case OMP_CLAUSE_MAP:
case OMP_CLAUSE_FROM:
case OMP_CLAUSE_TO:
+ start_component_ref:
while (c_parser_next_token_is (parser, CPP_DOT)
|| (allow_deref
&& c_parser_next_token_is (parser, CPP_DEREF)))
@@ -13147,9 +13158,13 @@ c_parser_omp_variable_list (c_parser *parser,
case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_IN_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
+ array_section_p = false;
+ dims.truncate (0);
while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
{
+ location_t loc = UNKNOWN_LOCATION;
tree low_bound = NULL_TREE, length = NULL_TREE;
+ bool no_colon = false;
c_parser_consume_token (parser);
if (!c_parser_next_token_is (parser, CPP_COLON))
@@ -13160,9 +13175,13 @@ c_parser_omp_variable_list (c_parser *parser,
expr = convert_lvalue_to_rvalue (expr_loc, expr,
false, true);
low_bound = expr.value;
+ loc = expr_loc;
}
if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
- length = integer_one_node;
+ {
+ length = integer_one_node;
+ no_colon = true;
+ }
else
{
/* Look for `:'. */
@@ -13191,8 +13210,33 @@ c_parser_omp_variable_list (c_parser *parser,
break;
}
- t = tree_cons (low_bound, length, t);
+ dims.safe_push (omp_dim (low_bound, length, loc, no_colon));
+ }
+
+ if (t != error_mark_node)
+ {
+ if ((kind == OMP_CLAUSE_MAP
+ || kind == OMP_CLAUSE_FROM
+ || kind == OMP_CLAUSE_TO)
+ && !array_section_p
+ && (c_parser_next_token_is (parser, CPP_DOT)
+ || (allow_deref
+ && c_parser_next_token_is (parser,
+ CPP_DEREF))))
+ {
+ for (unsigned i = 0; i < dims.length (); i++)
+ {
+ gcc_assert (dims[i].length == integer_one_node);
+ t = build_array_ref (dims[i].loc,
+ t, dims[i].low_bound);
+ }
+ goto start_component_ref;
+ }
+ else
+ for (unsigned i = 0; i < dims.length (); i++)
+ t = tree_cons (dims[i].low_bound, dims[i].length, t);
}
+
if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
&& t != error_mark_node
&& parser->tokens_avail != 2)
@@ -16194,7 +16238,8 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
c_parser_consume_token (parser);
}
- nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list);
+ nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list,
+ true);
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
OMP_CLAUSE_SET_MAP_KIND (c, kind);
@@ -16438,7 +16483,7 @@ c_parser_omp_clause_device_type (c_parser *parser, tree list)
static tree
c_parser_omp_clause_to (c_parser *parser, tree list)
{
- return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO, list);
+ return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO, list, true);
}
/* OpenMP 4.0:
@@ -16447,7 +16492,7 @@ c_parser_omp_clause_to (c_parser *parser, tree list)
static tree
c_parser_omp_clause_from (c_parser *parser, tree list)
{
- return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FROM, list);
+ return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FROM, list, true);
}
/* OpenMP 4.0:
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 7524304..78a6c68 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -13220,6 +13220,18 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
return error_mark_node;
}
+ while (TREE_CODE (t) == INDIRECT_REF)
+ {
+ t = TREE_OPERAND (t, 0);
+ STRIP_NOPS (t);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ }
+ while (TREE_CODE (t) == COMPOUND_EXPR)
+ {
+ t = TREE_OPERAND (t, 1);
+ STRIP_NOPS (t);
+ }
if (TREE_CODE (t) == COMPONENT_REF
&& (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO
@@ -13241,6 +13253,15 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
return error_mark_node;
}
t = TREE_OPERAND (t, 0);
+ while (TREE_CODE (t) == MEM_REF
+ || TREE_CODE (t) == INDIRECT_REF
+ || TREE_CODE (t) == ARRAY_REF)
+ {
+ t = TREE_OPERAND (t, 0);
+ STRIP_NOPS (t);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ }
if (ort == C_ORT_ACC && TREE_CODE (t) == MEM_REF)
{
if (maybe_ne (mem_ref_offset (t), 0))
@@ -13528,15 +13549,25 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
return error_mark_node;
}
/* If there is a pointer type anywhere but in the very first
- array-section-subscript, the array section can't be contiguous. */
+ array-section-subscript, the array section could be non-contiguous. */
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY
&& TREE_CODE (TREE_CHAIN (t)) == TREE_LIST)
{
- error_at (OMP_CLAUSE_LOCATION (c),
- "array section is not contiguous in %qs clause",
- omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
- return error_mark_node;
+ /* If any prior dimension has a non-one length, then deem this
+ array section as non-contiguous. */
+ for (tree d = TREE_CHAIN (t); TREE_CODE (d) == TREE_LIST;
+ d = TREE_CHAIN (d))
+ {
+ tree d_length = TREE_VALUE (d);
+ if (d_length == NULL_TREE || !integer_onep (d_length))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "array section is not contiguous in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ }
}
}
else
@@ -14085,6 +14116,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
tree ordered_clause = NULL_TREE;
tree schedule_clause = NULL_TREE;
bool oacc_async = false;
+ bool indir_component_ref_p = false;
tree last_iterators = NULL_TREE;
bool last_iterators_remove = false;
tree *nogroup_seen = NULL;
@@ -14884,8 +14916,20 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
if (TREE_CODE (t) == COMPONENT_REF
&& TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
{
- while (TREE_CODE (t) == COMPONENT_REF)
- t = TREE_OPERAND (t, 0);
+ do
+ {
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == MEM_REF
+ || TREE_CODE (t) == INDIRECT_REF)
+ {
+ t = TREE_OPERAND (t, 0);
+ STRIP_NOPS (t);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ }
+ }
+ while (TREE_CODE (t) == COMPONENT_REF);
+
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
&& OMP_CLAUSE_MAP_IMPLICIT (c)
&& (bitmap_bit_p (&map_head, DECL_UID (t))
@@ -14952,6 +14996,32 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bias) to zero here, so it is not set erroneously to the pointer
size later on in gimplify.c. */
OMP_CLAUSE_SIZE (c) = size_zero_node;
+ while (TREE_CODE (t) == INDIRECT_REF
+ || TREE_CODE (t) == ARRAY_REF)
+ {
+ t = TREE_OPERAND (t, 0);
+ STRIP_NOPS (t);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ }
+ while (TREE_CODE (t) == COMPOUND_EXPR)
+ {
+ t = TREE_OPERAND (t, 1);
+ STRIP_NOPS (t);
+ }
+ indir_component_ref_p = false;
+ if (TREE_CODE (t) == COMPONENT_REF
+ && (TREE_CODE (TREE_OPERAND (t, 0)) == MEM_REF
+ || TREE_CODE (TREE_OPERAND (t, 0)) == INDIRECT_REF
+ || TREE_CODE (TREE_OPERAND (t, 0)) == ARRAY_REF))
+ {
+ t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
+ indir_component_ref_p = true;
+ STRIP_NOPS (t);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ }
+
if (TREE_CODE (t) == COMPONENT_REF
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_)
{
@@ -14987,7 +15057,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
}
t = TREE_OPERAND (t, 0);
- if (ort == C_ORT_ACC && TREE_CODE (t) == MEM_REF)
+ if (TREE_CODE (t) == MEM_REF)
{
if (maybe_ne (mem_ref_offset (t), 0))
error_at (OMP_CLAUSE_LOCATION (c),
@@ -14996,6 +15066,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
else
t = TREE_OPERAND (t, 0);
}
+ while (TREE_CODE (t) == MEM_REF
+ || TREE_CODE (t) == INDIRECT_REF
+ || TREE_CODE (t) == ARRAY_REF)
+ {
+ t = TREE_OPERAND (t, 0);
+ STRIP_NOPS (t);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ }
}
if (remove)
break;
@@ -15024,6 +15103,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
else if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
|| (OMP_CLAUSE_MAP_KIND (c)
!= GOMP_MAP_FIRSTPRIVATE_POINTER))
+ && !indir_component_ref_p
&& !c_mark_addressable (t))
remove = true;
else if (!(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
@@ -15066,7 +15146,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
"%qD appears more than once in data clauses", t);
remove = true;
}
- else if (bitmap_bit_p (&map_head, DECL_UID (t)))
+ else if (bitmap_bit_p (&map_head, DECL_UID (t))
+ && !bitmap_bit_p (&map_field_head, DECL_UID (t)))
{
if (ort == C_ORT_ACC)
error_at (OMP_CLAUSE_LOCATION (c),
@@ -15080,8 +15161,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bitmap_set_bit (&map_firstprivate_head, DECL_UID (t));
}
else if (bitmap_bit_p (&map_head, DECL_UID (t))
- && (ort == C_ORT_ACC
- || !bitmap_bit_p (&map_field_head, DECL_UID (t))))
+ && !bitmap_bit_p (&map_field_head, DECL_UID (t)))
{
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
error_at (OMP_CLAUSE_LOCATION (c),
diff --git a/gcc/common.opt b/gcc/common.opt
index 755e1a2..445a53a 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -2327,6 +2327,10 @@ fprofile-prefix-path=
Common Joined RejectNegative Var(profile_prefix_path)
Remove prefix from absolute path before mangling name for -fprofile-generate= and -fprofile-use=.
+fprofile-prefix-map=
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fprofile-prefix-map=<old>=<new> Map one directory name to another in GCOV coverage result.
+
fprofile-generate
Common
Enable common options for generating profile info for profile feedback directed optimizations.
@@ -3531,6 +3535,10 @@ static-libgfortran
Driver
; Documented for Fortran, but always accepted by driver.
+static-libphobos
+Driver
+; Documented for D, but always accepted by driver.
+
static-libstdc++
Driver
diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c
index b8dd0ae..f352ff4 100644
--- a/gcc/common/config/riscv/riscv-common.c
+++ b/gcc/common/config/riscv/riscv-common.c
@@ -50,6 +50,20 @@ static const riscv_implied_info_t riscv_implied_info[] =
{"d", "f"},
{"f", "zicsr"},
{"d", "zicsr"},
+ {"zk", "zkn"},
+ {"zk", "zkr"},
+ {"zk", "zkt"},
+ {"zkn", "zbkb"},
+ {"zkn", "zbkc"},
+ {"zkn", "zbkx"},
+ {"zkn", "zkne"},
+ {"zkn", "zknd"},
+ {"zkn", "zknh"},
+ {"zks", "zbkb"},
+ {"zks", "zbkc"},
+ {"zks", "zbkx"},
+ {"zks", "zksed"},
+ {"zks", "zksh"},
{NULL, NULL}
};
@@ -106,6 +120,17 @@ static const struct riscv_ext_version riscv_ext_version_table[] =
{"zbc", ISA_SPEC_CLASS_NONE, 1, 0},
{"zbs", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"zbkb", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"zbkc", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"zbkx", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"zkne", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"zknd", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"zknh", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"zkr", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"zksed", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"zksh", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"zkt", ISA_SPEC_CLASS_NONE, 1, 0},
+
/* Terminate the list. */
{NULL, ISA_SPEC_CLASS_NONE, 0, 0}
};
@@ -491,7 +516,7 @@ riscv_subset_list::lookup (const char *subset, int major_version,
static const char *
riscv_supported_std_ext (void)
{
- return "mafdqlcbjtpvn";
+ return "mafdqlcbjktpvn";
}
/* Parsing subset version.
@@ -915,6 +940,17 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
{"zbc", &gcc_options::x_riscv_zb_subext, MASK_ZBC},
{"zbs", &gcc_options::x_riscv_zb_subext, MASK_ZBS},
+ {"zbkb", &gcc_options::x_riscv_zk_subext, MASK_ZBKB},
+ {"zbkc", &gcc_options::x_riscv_zk_subext, MASK_ZBKC},
+ {"zbkx", &gcc_options::x_riscv_zk_subext, MASK_ZBKX},
+ {"zknd", &gcc_options::x_riscv_zk_subext, MASK_ZKND},
+ {"zkne", &gcc_options::x_riscv_zk_subext, MASK_ZKNE},
+ {"zknh", &gcc_options::x_riscv_zk_subext, MASK_ZKNH},
+ {"zkr", &gcc_options::x_riscv_zk_subext, MASK_ZKR},
+ {"zksed", &gcc_options::x_riscv_zk_subext, MASK_ZKSED},
+ {"zksh", &gcc_options::x_riscv_zk_subext, MASK_ZKSH},
+ {"zkt", &gcc_options::x_riscv_zk_subext, MASK_ZKT},
+
{NULL, NULL, 0}
};
diff --git a/gcc/config.gcc b/gcc/config.gcc
index edd1265..1ca9d36 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -4315,6 +4315,13 @@ case "${target}" in
fi
;;
+ avr-*-*)
+ # Handle --with-multilib-list.
+ if test "x${with_multilib_list}" != xdefault; then
+ TM_MULTILIB_CONFIG="${with_multilib_list}"
+ fi
+ ;;
+
csky-*-*)
supported_defaults="cpu endian float"
;;
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index f7887d0..f7f5cae 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -846,6 +846,7 @@ const char *aarch64_output_move_struct (rtx *operands);
rtx aarch64_return_addr_rtx (void);
rtx aarch64_return_addr (int, rtx);
rtx aarch64_simd_gen_const_vector_dup (machine_mode, HOST_WIDE_INT);
+rtx aarch64_gen_shareable_zero (machine_mode);
bool aarch64_simd_mem_operand_p (rtx);
bool aarch64_sve_ld1r_operand_p (rtx);
bool aarch64_sve_ld1rq_operand_p (rtx);
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index 8e61dd9..175a9f0 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -1956,20 +1956,32 @@
(match_operand:SI 2 "aarch64_simd_shift_imm_offset_<vn_mode>")]
"TARGET_SIMD"
{
- operands[2] = aarch64_simd_gen_const_vector_dup (<MODE>mode,
- INTVAL (operands[2]));
- rtx tmp = gen_reg_rtx (<VNARROWQ2>mode);
- if (BYTES_BIG_ENDIAN)
- emit_insn (gen_aarch64_rshrn<mode>_insn_be (tmp, operands[1],
- operands[2], CONST0_RTX (<VNARROWQ>mode)));
+ if (INTVAL (operands[2]) == GET_MODE_UNIT_BITSIZE (<VNARROWQ>mode))
+ {
+ rtx tmp0 = aarch64_gen_shareable_zero (<MODE>mode);
+ emit_insn (gen_aarch64_raddhn<mode> (operands[0], operands[1], tmp0));
+ }
else
- emit_insn (gen_aarch64_rshrn<mode>_insn_le (tmp, operands[1],
- operands[2], CONST0_RTX (<VNARROWQ>mode)));
-
- /* The intrinsic expects a narrow result, so emit a subreg that will get
- optimized away as appropriate. */
- emit_move_insn (operands[0], lowpart_subreg (<VNARROWQ>mode, tmp,
- <VNARROWQ2>mode));
+ {
+ rtx tmp = gen_reg_rtx (<VNARROWQ2>mode);
+ operands[2] = aarch64_simd_gen_const_vector_dup (<MODE>mode,
+ INTVAL (operands[2]));
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (
+ gen_aarch64_rshrn<mode>_insn_be (tmp, operands[1],
+ operands[2],
+ CONST0_RTX (<VNARROWQ>mode)));
+ else
+ emit_insn (
+ gen_aarch64_rshrn<mode>_insn_le (tmp, operands[1],
+ operands[2],
+ CONST0_RTX (<VNARROWQ>mode)));
+
+ /* The intrinsic expects a narrow result, so emit a subreg that will
+ get optimized away as appropriate. */
+ emit_move_insn (operands[0], lowpart_subreg (<VNARROWQ>mode, tmp,
+ <VNARROWQ2>mode));
+ }
DONE;
}
)
@@ -2049,14 +2061,27 @@
(match_operand:SI 3 "aarch64_simd_shift_imm_offset_<vn_mode>")]
"TARGET_SIMD"
{
- operands[3] = aarch64_simd_gen_const_vector_dup (<MODE>mode,
- INTVAL (operands[3]));
- if (BYTES_BIG_ENDIAN)
- emit_insn (gen_aarch64_rshrn2<mode>_insn_be (operands[0], operands[1],
- operands[2], operands[3]));
+ if (INTVAL (operands[3]) == GET_MODE_UNIT_BITSIZE (<VNARROWQ2>mode))
+ {
+ rtx tmp = aarch64_gen_shareable_zero (<MODE>mode);
+ emit_insn (gen_aarch64_raddhn2<mode> (operands[0], operands[1],
+ operands[2], tmp));
+ }
else
- emit_insn (gen_aarch64_rshrn2<mode>_insn_le (operands[0], operands[1],
- operands[2], operands[3]));
+ {
+ operands[3] = aarch64_simd_gen_const_vector_dup (<MODE>mode,
+ INTVAL (operands[3]));
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_aarch64_rshrn2<mode>_insn_be (operands[0],
+ operands[1],
+ operands[2],
+ operands[3]));
+ else
+ emit_insn (gen_aarch64_rshrn2<mode>_insn_le (operands[0],
+ operands[1],
+ operands[2],
+ operands[3]));
+ }
DONE;
}
)
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 7389b59..be24b73 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -20414,6 +20414,18 @@ aarch64_mov_operand_p (rtx x, machine_mode mode)
== SYMBOL_TINY_ABSOLUTE;
}
+/* Create a 0 constant that is based on V4SI to allow CSE to optimally share
+ the constant creation. */
+
+rtx
+aarch64_gen_shareable_zero (machine_mode mode)
+{
+ machine_mode zmode = V4SImode;
+ rtx tmp = gen_reg_rtx (zmode);
+ emit_move_insn (tmp, CONST0_RTX (zmode));
+ return lowpart_subreg (mode, tmp, zmode);
+}
+
/* Return a const_int vector of VAL. */
rtx
aarch64_simd_gen_const_vector_dup (machine_mode mode, HOST_WIDE_INT val)
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 200701a..1c2f7d5 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -10089,7 +10089,7 @@ avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
to track need of __do_copy_data. */
static void
-avr_output_data_section_asm_op (const void *data)
+avr_output_data_section_asm_op (const char *data)
{
avr_need_copy_data_p = true;
@@ -10102,7 +10102,7 @@ avr_output_data_section_asm_op (const void *data)
to track need of __do_clear_bss. */
static void
-avr_output_bss_section_asm_op (const void *data)
+avr_output_bss_section_asm_op (const char *data)
{
avr_need_clear_bss_p = true;
@@ -10114,10 +10114,9 @@ avr_output_bss_section_asm_op (const void *data)
/* Unnamed section callback for progmem*.data sections. */
static void
-avr_output_progmem_section_asm_op (const void *data)
+avr_output_progmem_section_asm_op (const char *data)
{
- fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n",
- (const char*) data);
+ fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n", data);
}
diff --git a/gcc/config/avr/genmultilib.awk b/gcc/config/avr/genmultilib.awk
index efe41dd..c5f6ed0 100644
--- a/gcc/config/avr/genmultilib.awk
+++ b/gcc/config/avr/genmultilib.awk
@@ -67,6 +67,16 @@ BEGIN {
dir_long_double = "long-double" (96 - with_long_double)
opt_long_double = "mlong-double=" (96 - with_long_double)
+
+ if (with_multilib_list != "")
+ {
+ split(with_multilib_list, multilib_list, ",")
+
+ for (i in multilib_list)
+ {
+ multilibs[multilib_list[i]] = 1
+ }
+ }
}
##################################################################
@@ -137,6 +147,9 @@ BEGIN {
if (core == "avr1")
next
+ if (with_multilib_list != "" && !(core in multilibs))
+ next
+
option[core] = "mmcu=" core
m_options = m_options m_sep option[core]
@@ -150,6 +163,9 @@ BEGIN {
if (core == "avr1")
next
+ if (with_multilib_list != "" && !(core in multilibs))
+ next
+
opts = option[core]
# split device specific feature list
diff --git a/gcc/config/avr/t-avr b/gcc/config/avr/t-avr
index 06a0a3a..3120b19 100644
--- a/gcc/config/avr/t-avr
+++ b/gcc/config/avr/t-avr
@@ -127,6 +127,7 @@ t-multilib-avr: $(srcdir)/config/avr/genmultilib.awk \
-v HAVE_LONG_DOUBLE64=$(HAVE_LONG_DOUBLE64) \
-v with_double=$(WITH_DOUBLE) \
-v with_long_double=$(WITH_LONG_DOUBLE) \
+ -v with_multilib_list=$(TM_MULTILIB_CONFIG) \
-f $< $< $(AVR_MCUS) > $@
include t-multilib-avr
diff --git a/gcc/config/bpf/bpf.c b/gcc/config/bpf/bpf.c
index 82bb698..c054c1e 100644
--- a/gcc/config/bpf/bpf.c
+++ b/gcc/config/bpf/bpf.c
@@ -129,8 +129,8 @@ bpf_handle_fndecl_attribute (tree *node, tree name,
static tree
bpf_handle_preserve_access_index_attribute (tree *node, tree name,
- tree args,
- int flags,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED,
bool *no_add_attrs)
{
if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE)
@@ -258,20 +258,6 @@ bpf_option_override (void)
#undef TARGET_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE bpf_option_override
-/* Return FALSE iff -mcore has been specified. */
-
-static bool
-ctfc_debuginfo_early_finish_p (void)
-{
- if (TARGET_BPF_CORE)
- return false;
- else
- return true;
-}
-
-#undef TARGET_CTFC_DEBUGINFO_EARLY_FINISH_P
-#define TARGET_CTFC_DEBUGINFO_EARLY_FINISH_P ctfc_debuginfo_early_finish_p
-
/* Implement TARGET_ASM_INIT_SECTIONS. */
static void
@@ -1266,15 +1252,14 @@ bpf_core_get_index (const tree node)
return -1;
}
-/* Synthesize a new builtin function declaration at LOC with signature TYPE.
+/* Synthesize a new builtin function declaration with signature TYPE.
Used by bpf_resolve_overloaded_builtin to resolve calls to
__builtin_preserve_access_index. */
static tree
-bpf_core_newdecl (location_t loc, tree type)
+bpf_core_newdecl (tree type)
{
tree rettype = build_function_type_list (type, type, NULL);
- tree newdecl = NULL_TREE;
char name[80];
int len = snprintf (name, sizeof (name), "%s", "__builtin_pai_");
@@ -1317,7 +1302,7 @@ bpf_core_walk (tree *tp, int *walk_subtrees, void *data)
if (bpf_core_is_maybe_aggregate_access (*tp))
{
- tree newdecl = bpf_core_newdecl (loc, TREE_TYPE (*tp));
+ tree newdecl = bpf_core_newdecl (TREE_TYPE (*tp));
tree newcall = build_call_expr_loc (loc, newdecl, 1, *tp);
*tp = newcall;
*walk_subtrees = 0;
@@ -1497,7 +1482,7 @@ handle_attr_preserve (function *fn)
&& TREE_CODE (TREE_OPERAND (expr, 0)) == SSA_NAME)
{
gimple *def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (expr, 0));
- if (is_gimple_assign (def_stmt))
+ if (def_stmt && is_gimple_assign (def_stmt))
expr = gimple_assign_rhs1 (def_stmt);
}
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index c5ba792..8ad5b26 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -134,7 +134,7 @@ int emit_aligned_common = false;
DIRECTIVE is as for output_section_asm_op. */
static void
-output_objc_section_asm_op (const void *directive)
+output_objc_section_asm_op (const char *directive)
{
static bool been_here = false;
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index 8d8d402..0ce1320 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -288,13 +288,17 @@ extern GTY(()) int darwin_ms_struct;
#define DARWIN_RDYNAMIC "%{rdynamic:%nrdynamic is not supported}"
#endif
-/* FIXME: we should check that the linker supports the -pie and -no_pie.
+/* Code built with mdynamic-no-pic does not support PIE/PIC, so we disallow
+ these combinations; we also ensure that the no_pie option is passed to
+ ld64 on system versions that default to PIE when mdynamic-no-pic is given.
+ FIXME: we should check that the linker supports the -pie and -no_pie.
options. */
#define DARWIN_PIE_SPEC \
"%{pie|fpie|fPIE:\
%{mdynamic-no-pic: \
%n'-mdynamic-no-pic' overrides '-pie', '-fpie' or '-fPIE'; \
- :%:version-compare(>= 10.5 mmacosx-version-min= -pie) }} "
+ :%:version-compare(>= 10.5 mmacosx-version-min= -pie) }; \
+ mdynamic-no-pic:%:version-compare(>= 10.7 mmacosx-version-min= -no_pie) } "
#define DARWIN_NOPIE_SPEC \
"%{no-pie|fno-pie|fno-PIE: \
@@ -450,6 +454,7 @@ extern GTY(()) int darwin_ms_struct;
%:replace-outfile(-lobjc libobjc-gnu.a%s); \
:%:replace-outfile(-lobjc -lobjc-gnu )}}\
%{static|static-libgcc|static-libgfortran:%:replace-outfile(-lgfortran libgfortran.a%s)}\
+ %{static|static-libgcc|static-libphobos:%:replace-outfile(-lgphobos libgphobos.a%s)}\
%{static|static-libgcc|static-libstdc++|static-libgfortran:%:replace-outfile(-lgomp libgomp.a%s)}\
%{static|static-libgcc|static-libstdc++:%:replace-outfile(-lstdc++ libstdc++.a%s)}\
%{force_cpusubtype_ALL:-arch %(darwin_arch)} \
diff --git a/gcc/config/host-darwin.c b/gcc/config/host-darwin.c
index 14a01fe..559b919f 100644
--- a/gcc/config/host-darwin.c
+++ b/gcc/config/host-darwin.c
@@ -20,62 +20,177 @@
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "options.h"
#include "diagnostic-core.h"
#include "config/host-darwin.h"
-
-/* Yes, this is really supposed to work. */
-/* This allows for a pagesize of 16384, which we have on Darwin20, but should
- continue to work OK for pagesize 4096 which we have on earlier versions.
- The size is 1 (binary) Gb. */
-static char pch_address_space[65536*16384] __attribute__((aligned (16384)));
-
-/* Return the address of the PCH address space, if the PCH will fit in it. */
+#include <errno.h>
+
+/* For Darwin (macOS only) platforms, without ASLR (PIE) enabled on the
+ binaries, the following VM addresses are expected to be available.
+ NOTE, that for aarch64, ASLR is always enabled - but the VM address
+ mentioned below is available (at least on Darwin20).
+
+ The spaces should all have 512Mb available c.f. PCH files for large
+ C++ or Objective-C in the range of 150Mb for 64b hosts.
+
+ We also try to steer clear of places already used for sanitizers. */
+
+#define PAGE_SZ 4096
+#if defined(__x86_64) && defined(__LP64__)
+# define TRY_EMPTY_VM_SPACE 0x180000000000ULL
+# define SAFE_ALLOC_SIZE 0x20000000
+#elif defined(__x86_64)
+# define TRY_EMPTY_VM_SPACE 0x00006fe00000ULL
+# define SAFE_ALLOC_SIZE 0x20000000
+#elif defined(__i386)
+# define TRY_EMPTY_VM_SPACE 0x00006fe00000ULL
+# define SAFE_ALLOC_SIZE 0x20000000
+#elif defined(__POWERPC__) && defined(__LP64__)
+# define TRY_EMPTY_VM_SPACE 0x180000000000ULL
+# define SAFE_ALLOC_SIZE 0x20000000
+#elif defined(__POWERPC__)
+# define TRY_EMPTY_VM_SPACE 0x00006fe00000ULL
+# define SAFE_ALLOC_SIZE 0x20000000
+#elif defined(__aarch64__)
+# undef PAGE_SZ
+# define PAGE_SZ 16384
+# define TRY_EMPTY_VM_SPACE 0x180000000000ULL
+# define SAFE_ALLOC_SIZE 0x20000000
+#else
+# error "unknown Darwin target"
+#endif
+
+/* Try to map a known position in the VM. The current PCH implementation
+ can adjust values at write-time, but not at read-time thus we need to
+ pick up the same position when reading as we got at write-time. */
void *
-darwin_gt_pch_get_address (size_t sz, int fd ATTRIBUTE_UNUSED)
+darwin_gt_pch_get_address (size_t sz, int fd)
{
- if (sz <= sizeof (pch_address_space))
- return pch_address_space;
- else
- return NULL;
+ if (sz > SAFE_ALLOC_SIZE)
+ {
+ error ("PCH memory request exceeds the available space");
+ return NULL;
+ }
+
+ /* Now try with the constraint that we really want this address... */
+ void *addr = mmap ((void *)TRY_EMPTY_VM_SPACE, sz, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED, fd, 0);
+
+ if (addr != (void *) MAP_FAILED)
+ munmap (addr, sz);
+
+ /* This ought to be the only alternative to failure, but there are comments
+ that suggest some versions of mmap can be buggy and return a different
+ value. */
+ if (addr == (void *) TRY_EMPTY_VM_SPACE)
+ return addr;
+
+ warning (OPT_Winvalid_pch, "PCH memory [fixed at %p] is not available %m",
+ (void *) TRY_EMPTY_VM_SPACE);
+
+ /* OK try to find a space without the constraint. */
+ addr = mmap ((void *) TRY_EMPTY_VM_SPACE, sz, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, fd, 0);
+
+ /* If we failed this time, that means there is *no* large enough free
+ space. */
+ if (addr == (void *) MAP_FAILED)
+ {
+ error ("no memory is available for PCH : %m");
+ return NULL;
+ }
+
+ /* Unmap the area before returning. */
+ munmap (addr, sz);
+
+ /* If we got the exact area we requested, then that's great. */
+ if (TRY_EMPTY_VM_SPACE && addr == (void *) TRY_EMPTY_VM_SPACE)
+ return addr;
+
+ warning (OPT_Winvalid_pch, "PCH memory at %p is not available",
+ (void *) TRY_EMPTY_VM_SPACE);
+
+ /* Otherwise, we need to try again but put some buffer space first. */
+ size_t buffer_size = 32 * 1024 * 1024;
+ void *buffer = mmap (0, buffer_size, PROT_NONE,
+ MAP_PRIVATE | MAP_ANON, -1, 0);
+ addr = mmap ((void *)TRY_EMPTY_VM_SPACE, sz, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, fd, 0);
+ if (buffer != (void *) MAP_FAILED)
+ munmap (buffer, buffer_size);
+
+ if (addr == (void *) MAP_FAILED)
+ {
+ error ("PCH memory not available %m");
+ return NULL;
+ }
+
+ warning (OPT_Winvalid_pch, "PCH memory at %p used instead", addr);
+ munmap (addr, sz);
+ return addr;
}
-/* Check ADDR and SZ for validity, and deallocate (using munmap) that part of
- pch_address_space beyond SZ. */
+/* Try to mmap the PCH file at ADDR for SZ bytes at OFF offset in the file.
+ If we succeed return 1, if we cannot mmap the desired address, then we
+ fail with -1. */
int
darwin_gt_pch_use_address (void *addr, size_t sz, int fd, size_t off)
{
- const size_t pagesize = getpagesize();
- void *mmap_result;
- int ret;
+ void *mapped_addr;
+
+ /* We're called with size == 0 if we're not planning to load a PCH
+ file at all. This allows the hook to free any static space that
+ we might have allocated at link time. */
+ if (sz == 0)
+ return -1;
- gcc_assert ((size_t)pch_address_space % pagesize == 0
- && sizeof (pch_address_space) % pagesize == 0);
-
- ret = (addr == pch_address_space && sz <= sizeof (pch_address_space));
- if (! ret)
- sz = 0;
+ gcc_checking_assert (!(off % PAGE_SZ));
+ if (addr != (void *) TRY_EMPTY_VM_SPACE)
+ warning (OPT_Winvalid_pch, "PCH at %p does not use the default position",
+ addr);
- /* Round the size to a whole page size. Normally this is a no-op. */
- sz = (sz + pagesize - 1) / pagesize * pagesize;
+ /* Try to map the file with MAP_PRIVATE and FIXED. */
+ mapped_addr = mmap (addr, sz, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED, fd, (off_t) off);
- if (munmap (pch_address_space + sz, sizeof (pch_address_space) - sz) != 0)
- fatal_error (input_location,
- "could not unmap %<pch_address_space%>: %m");
+ /* Hopefully, we succeed. */
+ if (mapped_addr == addr)
+ return 1;
- if (ret)
+ warning (OPT_Winvalid_pch, "PCH private mmap of written position (%p)"
+ " failed [errno %d] %m", addr, errno);
+
+ if (mapped_addr != (void *) MAP_FAILED)
+ munmap (mapped_addr, sz);
+
+ /* Try to make an anonymous private mmap at the desired location. */
+ mapped_addr = mmap (addr, sz, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, (off_t)0);
+
+ if (mapped_addr != addr)
{
- mmap_result = mmap (addr, sz,
- PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED,
- fd, off);
+ warning (OPT_Winvalid_pch, "PCH anon mmap at written position (%p)"
+ " failed [errno %d] %m", addr, errno);
+ if (mapped_addr != (void *) MAP_FAILED)
+ munmap (mapped_addr, sz);
+ return -1;
+ }
+
+ if (lseek (fd, off, SEEK_SET) == (off_t) -1)
+ return -1;
- /* The file might not be mmap-able. */
- ret = mmap_result != (void *) MAP_FAILED;
+ while (sz)
+ {
+ ssize_t nbytes;
- /* Sanity check for broken MAP_FIXED. */
- gcc_assert (!ret || mmap_result == addr);
+ nbytes = read (fd, addr, MIN (sz, (size_t) -1 >> 1));
+ if (nbytes <= 0)
+ return -1;
+ addr = (char *) addr + nbytes;
+ sz -= nbytes;
}
- return ret;
+ return 1;
}
diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c
index 354a9a7..2bbb28e5 100644
--- a/gcc/config/i386/i386-expand.c
+++ b/gcc/config/i386/i386-expand.c
@@ -9133,7 +9133,7 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
it an indirect call. */
if (flag_pic
&& GET_CODE (addr) == SYMBOL_REF
- && !SYMBOL_REF_LOCAL_P (addr))
+ && ix86_call_use_plt_p (addr))
{
if (flag_plt
&& (SYMBOL_REF_DECL (addr) == NULL_TREE
@@ -12305,6 +12305,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
char *opts = ix86_target_string (bisa, bisa2, 0, 0, NULL, NULL,
(enum fpmath_unit) 0,
(enum prefer_vector_width) 0,
+ PVW_NONE, PVW_NONE,
false, add_abi_p);
if (!opts)
error ("%qE needs unknown isa option", fndecl);
@@ -16204,18 +16205,8 @@ ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt)
}
return;
- case E_V8HFmode:
- if (TARGET_AVX2)
- {
- mmode = SImode;
- gen_blendm = gen_sse4_1_pblendph;
- blendm_const = true;
- }
- else
- use_vec_merge = true;
- break;
-
case E_V8HImode:
+ case E_V8HFmode:
case E_V2HImode:
use_vec_merge = TARGET_SSE2;
break;
diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c
index a4da833..53bd55a 100644
--- a/gcc/config/i386/i386-options.c
+++ b/gcc/config/i386/i386-options.c
@@ -364,6 +364,8 @@ ix86_target_string (HOST_WIDE_INT isa, HOST_WIDE_INT isa2,
const char *arch, const char *tune,
enum fpmath_unit fpmath,
enum prefer_vector_width pvw,
+ enum prefer_vector_width move_max,
+ enum prefer_vector_width store_max,
bool add_nl_p, bool add_abi_p)
{
/* Flag options. */
@@ -542,10 +544,10 @@ ix86_target_string (HOST_WIDE_INT isa, HOST_WIDE_INT isa2,
}
}
- /* Add -mprefer-vector-width= option. */
- if (pvw)
+ auto add_vector_width = [&opts, &num] (prefer_vector_width pvw,
+ const char *cmd)
{
- opts[num][0] = "-mprefer-vector-width=";
+ opts[num][0] = cmd;
switch ((int) pvw)
{
case PVW_AVX128:
@@ -563,7 +565,19 @@ ix86_target_string (HOST_WIDE_INT isa, HOST_WIDE_INT isa2,
default:
gcc_unreachable ();
}
- }
+ };
+
+ /* Add -mprefer-vector-width= option. */
+ if (pvw)
+ add_vector_width (pvw, "-mprefer-vector-width=");
+
+ /* Add -mmove-max= option. */
+ if (move_max)
+ add_vector_width (move_max, "-mmove-max=");
+
+ /* Add -mstore-max= option. */
+ if (store_max)
+ add_vector_width (store_max, "-mstore-max=");
/* Any options? */
if (num == 0)
@@ -630,6 +644,7 @@ ix86_debug_options (void)
target_flags, ix86_target_flags,
ix86_arch_string, ix86_tune_string,
ix86_fpmath, prefer_vector_width_type,
+ ix86_move_max, ix86_store_max,
true, true);
if (opts)
@@ -892,7 +907,9 @@ ix86_function_specific_print (FILE *file, int indent,
= ix86_target_string (ptr->x_ix86_isa_flags, ptr->x_ix86_isa_flags2,
ptr->x_target_flags, ptr->x_ix86_target_flags,
NULL, NULL, ptr->x_ix86_fpmath,
- ptr->x_prefer_vector_width_type, false, true);
+ ptr->x_prefer_vector_width_type,
+ ptr->x_ix86_move_max, ptr->x_ix86_store_max,
+ false, true);
gcc_assert (ptr->arch < PROCESSOR_max);
fprintf (file, "%*sarch = %d (%s)\n",
@@ -1318,6 +1335,10 @@ ix86_valid_target_attribute_tree (tree fndecl, tree args,
const char *orig_tune_string = opts->x_ix86_tune_string;
enum fpmath_unit orig_fpmath_set = opts_set->x_ix86_fpmath;
enum prefer_vector_width orig_pvw_set = opts_set->x_prefer_vector_width_type;
+ enum prefer_vector_width orig_ix86_move_max_set
+ = opts_set->x_ix86_move_max;
+ enum prefer_vector_width orig_ix86_store_max_set
+ = opts_set->x_ix86_store_max;
int orig_tune_defaulted = ix86_tune_defaulted;
int orig_arch_specified = ix86_arch_specified;
char *option_strings[IX86_FUNCTION_SPECIFIC_MAX] = { NULL, NULL };
@@ -1393,6 +1414,8 @@ ix86_valid_target_attribute_tree (tree fndecl, tree args,
opts->x_ix86_tune_string = orig_tune_string;
opts_set->x_ix86_fpmath = orig_fpmath_set;
opts_set->x_prefer_vector_width_type = orig_pvw_set;
+ opts_set->x_ix86_move_max = orig_ix86_move_max_set;
+ opts_set->x_ix86_store_max = orig_ix86_store_max_set;
opts->x_ix86_excess_precision = orig_ix86_excess_precision;
opts->x_ix86_unsafe_math_optimizations
= orig_ix86_unsafe_math_optimizations;
@@ -1403,6 +1426,8 @@ ix86_valid_target_attribute_tree (tree fndecl, tree args,
return t;
}
+static GTY(()) tree target_attribute_cache[3];
+
/* Hook to validate attribute((target("string"))). */
bool
@@ -1423,6 +1448,19 @@ ix86_valid_target_attribute_p (tree fndecl,
&& strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), "default") == 0)
return true;
+ if ((DECL_FUNCTION_SPECIFIC_TARGET (fndecl) == target_attribute_cache[1]
+ || DECL_FUNCTION_SPECIFIC_TARGET (fndecl) == NULL_TREE)
+ && (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl)
+ == target_attribute_cache[2]
+ || DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) == NULL_TREE)
+ && simple_cst_list_equal (args, target_attribute_cache[0]))
+ {
+ DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = target_attribute_cache[1];
+ DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl)
+ = target_attribute_cache[2];
+ return true;
+ }
+
tree old_optimize = build_optimization_node (&global_options,
&global_options_set);
@@ -1459,8 +1497,17 @@ ix86_valid_target_attribute_p (tree fndecl,
if (new_target == error_mark_node)
ret = false;
- else if (fndecl && new_target)
+ else if (new_target)
{
+ if (DECL_FUNCTION_SPECIFIC_TARGET (fndecl) == NULL_TREE
+ && DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) == NULL_TREE)
+ {
+ target_attribute_cache[0] = copy_list (args);
+ target_attribute_cache[1] = new_target;
+ target_attribute_cache[2]
+ = old_optimize != new_optimize ? new_optimize : NULL_TREE;
+ }
+
DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
if (old_optimize != new_optimize)
@@ -2667,6 +2714,48 @@ ix86_option_override_internal (bool main_args_p,
&& (opts_set->x_prefer_vector_width_type == PVW_NONE))
opts->x_prefer_vector_width_type = PVW_AVX256;
+ if (opts_set->x_ix86_move_max == PVW_NONE)
+ {
+ /* Set the maximum number of bits can be moved from memory to
+ memory efficiently. */
+ if (ix86_tune_features[X86_TUNE_AVX512_MOVE_BY_PIECES])
+ opts->x_ix86_move_max = PVW_AVX512;
+ else if (ix86_tune_features[X86_TUNE_AVX256_MOVE_BY_PIECES])
+ opts->x_ix86_move_max = PVW_AVX256;
+ else
+ {
+ opts->x_ix86_move_max = opts->x_prefer_vector_width_type;
+ if (opts_set->x_ix86_move_max == PVW_NONE)
+ {
+ if (TARGET_AVX512F_P (opts->x_ix86_isa_flags))
+ opts->x_ix86_move_max = PVW_AVX512;
+ else
+ opts->x_ix86_move_max = PVW_AVX128;
+ }
+ }
+ }
+
+ if (opts_set->x_ix86_store_max == PVW_NONE)
+ {
+ /* Set the maximum number of bits can be stored to memory
+ efficiently. */
+ if (ix86_tune_features[X86_TUNE_AVX512_STORE_BY_PIECES])
+ opts->x_ix86_store_max = PVW_AVX512;
+ else if (ix86_tune_features[X86_TUNE_AVX256_STORE_BY_PIECES])
+ opts->x_ix86_store_max = PVW_AVX256;
+ else
+ {
+ opts->x_ix86_store_max = opts->x_prefer_vector_width_type;
+ if (opts_set->x_ix86_store_max == PVW_NONE)
+ {
+ if (TARGET_AVX512F_P (opts->x_ix86_isa_flags))
+ opts->x_ix86_store_max = PVW_AVX512;
+ else
+ opts->x_ix86_store_max = PVW_AVX128;
+ }
+ }
+ }
+
if (opts->x_ix86_recip_name)
{
char *p = ASTRDUP (opts->x_ix86_recip_name);
diff --git a/gcc/config/i386/i386-options.h b/gcc/config/i386/i386-options.h
index cdaca26..e218e24 100644
--- a/gcc/config/i386/i386-options.h
+++ b/gcc/config/i386/i386-options.h
@@ -26,8 +26,10 @@ char *ix86_target_string (HOST_WIDE_INT isa, HOST_WIDE_INT isa2,
int flags, int flags2,
const char *arch, const char *tune,
enum fpmath_unit fpmath,
- enum prefer_vector_width pvw, bool add_nl_p,
- bool add_abi_p);
+ enum prefer_vector_width pvw,
+ enum prefer_vector_width move_max,
+ enum prefer_vector_width store_max,
+ bool add_nl_p, bool add_abi_p);
extern enum attr_cpu ix86_schedule;
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 1cd2197..7ffb408 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -152,6 +152,7 @@ extern void ix86_expand_sse_movcc (rtx, rtx, rtx, rtx);
extern void ix86_expand_sse_unpack (rtx, rtx, bool, bool);
extern bool ix86_expand_int_addcc (rtx[]);
extern rtx_insn *ix86_expand_call (rtx, rtx, rtx, rtx, rtx, bool);
+extern bool ix86_call_use_plt_p (rtx);
extern void ix86_split_call_vzeroupper (rtx, rtx);
extern void x86_initialize_trampoline (rtx, rtx, rtx);
extern rtx ix86_zero_extend_to_Pmode (rtx);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 80fee62..f1e41fd 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -12150,7 +12150,7 @@ output_pic_addr_const (FILE *file, rtx x, int code)
assemble_name (file, name);
}
if (!TARGET_MACHO && !(TARGET_64BIT && TARGET_PECOFF)
- && code == 'P' && ! SYMBOL_REF_LOCAL_P (x))
+ && code == 'P' && ix86_call_use_plt_p (x))
fputs ("@PLT", file);
break;
@@ -15980,6 +15980,27 @@ ix86_zero_extend_to_Pmode (rtx exp)
return force_reg (Pmode, convert_to_mode (Pmode, exp, 1));
}
+/* Return true if the function is called via PLT. */
+
+bool
+ix86_call_use_plt_p (rtx call_op)
+{
+ if (SYMBOL_REF_LOCAL_P (call_op))
+ {
+ if (SYMBOL_REF_DECL (call_op)
+ && TREE_CODE (SYMBOL_REF_DECL (call_op)) == FUNCTION_DECL)
+ {
+ /* NB: All ifunc functions must be called via PLT. */
+ cgraph_node *node
+ = cgraph_node::get (SYMBOL_REF_DECL (call_op));
+ if (node && node->ifunc_resolver)
+ return true;
+ }
+ return false;
+ }
+ return true;
+}
+
/* Return true if the function being called was marked with attribute
"noplt" or using -fno-plt and we are compiling for non-PIC. We need
to handle the non-PIC case in the backend because there is no easy
@@ -19194,9 +19215,17 @@ ix86_preferred_reload_class (rtx x, reg_class_t regclass)
return NO_REGS;
}
- /* Prefer SSE regs only, if we can use them for math. */
+ /* Prefer SSE if we can use them for math. Also allow integer regs
+ when moves between register units are cheap. */
if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
- return SSE_CLASS_P (regclass) ? regclass : NO_REGS;
+ {
+ if (TARGET_INTER_UNIT_MOVES_FROM_VEC
+ && TARGET_INTER_UNIT_MOVES_TO_VEC
+ && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (word_mode))
+ return INT_SSE_CLASS_P (regclass) ? regclass : NO_REGS;
+ else
+ return SSE_CLASS_P (regclass) ? regclass : NO_REGS;
+ }
/* Generally when we see PLUS here, it's the function invariant
(plus soft-fp const_int). Which can only be computed into general
@@ -24582,6 +24611,9 @@ ix86_libgcc_floating_mode_supported_p
#define TARGET_GET_MULTILIB_ABI_NAME \
ix86_get_multilib_abi_name
+#undef TARGET_IFUNC_REF_LOCAL_OK
+#define TARGET_IFUNC_REF_LOCAL_OK hook_bool_void_true
+
static bool ix86_libc_has_fast_function (int fcode ATTRIBUTE_UNUSED)
{
#ifdef OPTION_GLIBC
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 2fda1e0..46fdd6e 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -408,10 +408,6 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST];
ix86_tune_features[X86_TUNE_AVOID_LEA_FOR_ADDR]
#define TARGET_SOFTWARE_PREFETCHING_BENEFICIAL \
ix86_tune_features[X86_TUNE_SOFTWARE_PREFETCHING_BENEFICIAL]
-#define TARGET_AVX256_MOVE_BY_PIECES \
- ix86_tune_features[X86_TUNE_AVX256_MOVE_BY_PIECES]
-#define TARGET_AVX256_STORE_BY_PIECES \
- ix86_tune_features[X86_TUNE_AVX256_STORE_BY_PIECES]
#define TARGET_AVX256_SPLIT_REGS \
ix86_tune_features[X86_TUNE_AVX256_SPLIT_REGS]
#define TARGET_GENERAL_REGS_SSE_SPILL \
@@ -1283,6 +1279,8 @@ enum reg_class
reg_class_subset_p ((CLASS), FLOAT_REGS)
#define SSE_CLASS_P(CLASS) \
reg_class_subset_p ((CLASS), ALL_SSE_REGS)
+#define INT_SSE_CLASS_P(CLASS) \
+ reg_class_subset_p ((CLASS), INT_SSE_REGS)
#define MMX_CLASS_P(CLASS) \
((CLASS) == MMX_REGS)
#define MASK_CLASS_P(CLASS) \
@@ -1807,12 +1805,13 @@ typedef struct ix86_args {
MOVE_MAX_PIECES defaults to MOVE_MAX. */
#define MOVE_MAX \
- ((TARGET_AVX512F && !TARGET_PREFER_AVX256) \
+ ((TARGET_AVX512F \
+ && (ix86_move_max == PVW_AVX512 \
+ || ix86_store_max == PVW_AVX512)) \
? 64 \
: ((TARGET_AVX \
- && !TARGET_PREFER_AVX128 \
- && (TARGET_AVX256_MOVE_BY_PIECES \
- || TARGET_AVX256_STORE_BY_PIECES)) \
+ && (ix86_move_max >= PVW_AVX256 \
+ || ix86_store_max >= PVW_AVX256)) \
? 32 \
: ((TARGET_SSE2 \
&& TARGET_SSE_UNALIGNED_LOAD_OPTIMAL \
@@ -1825,11 +1824,10 @@ typedef struct ix86_args {
store_by_pieces of 16/32/64 bytes. */
#define STORE_MAX_PIECES \
(TARGET_INTER_UNIT_MOVES_TO_VEC \
- ? ((TARGET_AVX512F && !TARGET_PREFER_AVX256) \
+ ? ((TARGET_AVX512F && ix86_store_max == PVW_AVX512) \
? 64 \
: ((TARGET_AVX \
- && !TARGET_PREFER_AVX128 \
- && TARGET_AVX256_STORE_BY_PIECES) \
+ && ix86_store_max >= PVW_AVX256) \
? 32 \
: ((TARGET_SSE2 \
&& TARGET_SSE_UNALIGNED_STORE_OPTIMAL) \
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 4e9fae8..9d7d116 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -4656,15 +4656,7 @@
rtx tmp = gen_reg_rtx (V8HFmode);
rtx zero = force_reg (V8HFmode, CONST0_RTX (V8HFmode));
- if (TARGET_AVX2)
- {
- rtx dup = gen_reg_rtx (V8HFmode);
- emit_move_insn (dup, gen_rtx_VEC_DUPLICATE (V8HFmode, operands[1]));
- emit_move_insn (tmp, gen_rtx_VEC_MERGE (V8HFmode, dup,
- zero, const1_rtx));
- }
- else
- emit_insn (gen_sse2_pinsrph (tmp, zero, operands[1], const1_rtx));
+ emit_insn (gen_vec_setv8hf_0 (tmp, zero, operands[1]));
emit_insn (gen_vcvtph2ps (res, gen_lowpart (V8HImode, tmp)));
emit_move_insn (operands[0], gen_lowpart (SFmode, res));
DONE;
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 3e67c53..e1af3e4 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -624,6 +624,14 @@ Enum(prefer_vector_width) String(256) Value(PVW_AVX256)
EnumValue
Enum(prefer_vector_width) String(512) Value(PVW_AVX512)
+mmove-max=
+Target RejectNegative Joined Var(ix86_move_max) Enum(prefer_vector_width) Init(PVW_NONE) Save
+Maximum number of bits that can be moved from memory to memory efficiently.
+
+mstore-max=
+Target RejectNegative Joined Var(ix86_store_max) Enum(prefer_vector_width) Init(PVW_NONE) Save
+Maximum number of bits that can be stored to memory efficiently.
+
;; ISA support
m32
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 08bdcdd..5421fb5 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -827,7 +827,7 @@
(V32HF "TARGET_AVX512BW")])
;; Int-float size matches
-(define_mode_iterator VI2F [V8HI V16HI V32HI V8HF V16HF V32HF])
+(define_mode_iterator VI2F_256_512 [V16HI V32HI V16HF V32HF])
(define_mode_iterator VI4F_128 [V4SI V4SF])
(define_mode_iterator VI8F_128 [V2DI V2DF])
(define_mode_iterator VI4F_256 [V8SI V8SF])
@@ -10170,13 +10170,84 @@
]
(symbol_ref "true")))])
+(define_insn "vec_set<mode>_0"
+ [(set (match_operand:V8_128 0 "register_operand"
+ "=v,v,v,x,x,Yr,*x,x,x,x,v,v")
+ (vec_merge:V8_128
+ (vec_duplicate:V8_128
+ (match_operand:<ssescalarmode> 2 "nonimmediate_operand"
+ " r,m,v,r,m,Yr,*x,r,m,x,r,m"))
+ (match_operand:V8_128 1 "reg_or_0_operand"
+ " C,C,v,0,0,0 ,0 ,x,x,x,v,v")
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "@
+ vmovw\t{%k2, %0|%0, %k2}
+ vmovw\t{%2, %0|%0, %2}
+ vmovsh\t{%2, %1, %0|%0, %1, %2}
+ pinsrw\t{$0, %k2, %0|%0, %k2, 0}
+ pinsrw\t{$0, %2, %0|%0, %2, 0}
+ pblendw\t{$1, %2, %0|%0, %2, 1}
+ pblendw\t{$1, %2, %0|%0, %2, 1}
+ vpinsrw\t{$0, %k2, %1, %0|%0, %1, %k2, 0}
+ vpinsrw\t{$0, %2, %1, %0|%0, %1, %2, 0}
+ vpblendw\t{$1, %2, %1, %0|%0, %1, %2, 1}
+ vpinsrw\t{$0, %k2, %1, %0|%0, %1, %k2, 0}
+ vpinsrw\t{$0, %2, %1, %0|%0, %1, %2, 0}"
+ [(set (attr "isa")
+ (cond [(eq_attr "alternative" "0,1,2")
+ (const_string "avx512fp16")
+ (eq_attr "alternative" "3")
+ (const_string "noavx")
+ (eq_attr "alternative" "4,5,6")
+ (const_string "sse4_noavx")
+ (eq_attr "alternative" "7,8,9")
+ (const_string "avx")
+ (eq_attr "alternative" "10,11")
+ (const_string "avx512bw")
+ ]
+ (const_string "*")))
+ (set (attr "type")
+ (if_then_else (eq_attr "alternative" "0,1,2,5,6,9")
+ (const_string "ssemov")
+ (const_string "sselog")))
+ (set (attr "prefix_data16")
+ (if_then_else (eq_attr "alternative" "3,4")
+ (const_string "1")
+ (const_string "*")))
+ (set (attr "prefix_extra")
+ (if_then_else (eq_attr "alternative" "5,6,7,8,9")
+ (const_string "1")
+ (const_string "*")))
+ (set (attr "length_immediate")
+ (if_then_else (eq_attr "alternative" "0,1,2")
+ (const_string "*")
+ (const_string "1")))
+ (set (attr "prefix")
+ (cond [(eq_attr "alternative" "0,1,2,10,11")
+ (const_string "evex")
+ (eq_attr "alternative" "7,8,9")
+ (const_string "vex")
+ ]
+ (const_string "orig")))
+ (set (attr "mode")
+ (if_then_else (eq_attr "alternative" "0,1,2")
+ (const_string "HF")
+ (const_string "TI")))
+ (set (attr "enabled")
+ (cond [(and (not (match_test "<MODE>mode == V8HFmode"))
+ (eq_attr "alternative" "2"))
+ (symbol_ref "false")
+ ]
+ (const_string "*")))])
+
;; vmovw clears also the higer bits
(define_insn "vec_set<mode>_0"
- [(set (match_operand:VI2F 0 "register_operand" "=v,v")
- (vec_merge:VI2F
- (vec_duplicate:VI2F
+ [(set (match_operand:VI2F_256_512 0 "register_operand" "=v,v")
+ (vec_merge:VI2F_256_512
+ (vec_duplicate:VI2F_256_512
(match_operand:<ssescalarmode> 2 "nonimmediate_operand" "r,m"))
- (match_operand:VI2F 1 "const0_operand" "C,C")
+ (match_operand:VI2F_256_512 1 "const0_operand" "C,C")
(const_int 1)))]
"TARGET_AVX512FP16"
"@
@@ -10186,19 +10257,6 @@
(set_attr "prefix" "evex")
(set_attr "mode" "HF")])
-(define_insn "*avx512fp16_movsh"
- [(set (match_operand:V8HF 0 "register_operand" "=v")
- (vec_merge:V8HF
- (vec_duplicate:V8HF
- (match_operand:HF 2 "register_operand" "v"))
- (match_operand:V8HF 1 "register_operand" "v")
- (const_int 1)))]
- "TARGET_AVX512FP16"
- "vmovsh\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "type" "ssemov")
- (set_attr "prefix" "evex")
- (set_attr "mode" "HF")])
-
(define_insn "avx512fp16_movsh"
[(set (match_operand:V8HF 0 "register_operand" "=v")
(vec_merge:V8HF
@@ -17312,20 +17370,20 @@
(V4SI "avx512dq") (V2DI "avx512dq")])
;; sse4_1_pinsrd must come before sse2_loadld since it is preferred.
-;; For V8HFmode and TARGET_AVX2, broadcastw + pblendw should be better.
(define_insn "<sse2p4_1>_pinsr<ssemodesuffix>"
- [(set (match_operand:PINSR_MODE 0 "register_operand" "=x,x,x,x,v,v")
+ [(set (match_operand:PINSR_MODE 0 "register_operand" "=x,x,x,x,v,v,x")
(vec_merge:PINSR_MODE
(vec_duplicate:PINSR_MODE
- (match_operand:<ssescalarmode> 2 "nonimmediate_operand" "r,m,r,m,r,m"))
- (match_operand:PINSR_MODE 1 "register_operand" "0,0,x,x,v,v")
+ (match_operand:<ssescalarmode> 2 "nonimmediate_operand" "r,m,r,m,r,m,x"))
+ (match_operand:PINSR_MODE 1 "register_operand" "0,0,x,x,v,v,x")
(match_operand:SI 3 "const_int_operand")))]
"TARGET_SSE2
&& ((unsigned) exact_log2 (INTVAL (operands[3]))
- < GET_MODE_NUNITS (<MODE>mode))
- && !(<MODE>mode == V8HFmode && TARGET_AVX2)"
+ < GET_MODE_NUNITS (<MODE>mode))"
{
- operands[3] = GEN_INT (exact_log2 (INTVAL (operands[3])));
+ HOST_WIDE_INT items = INTVAL (operands[3]);
+
+ operands[3] = GEN_INT (exact_log2 (items));
switch (which_alternative)
{
@@ -17343,33 +17401,83 @@
case 3:
case 5:
return "vpinsr<sseintmodesuffix>\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+ case 6:
+ /* This pattern needs to be shadowed with vec_set{v8hi,v8hf}_0. */
+ gcc_assert (items > 1);
+ return "#";
default:
gcc_unreachable ();
}
}
- [(set_attr "isa" "noavx,noavx,avx,avx,<pinsr_evex_isa>,<pinsr_evex_isa>")
+ [(set_attr "isa" "noavx,noavx,avx,avx,<pinsr_evex_isa>,<pinsr_evex_isa>,avx2")
(set_attr "type" "sselog")
(set (attr "prefix_rex")
(if_then_else
(and (not (match_test "TARGET_AVX"))
- (eq (const_string "<MODE>mode") (const_string "V2DImode")))
+ (match_test "GET_MODE_NUNITS (<MODE>mode) == 2"))
(const_string "1")
(const_string "*")))
(set (attr "prefix_data16")
(if_then_else
(and (not (match_test "TARGET_AVX"))
- (eq (const_string "<MODE>mode") (const_string "V8HImode")))
+ (match_test "GET_MODE_NUNITS (<MODE>mode) == 8"))
(const_string "1")
(const_string "*")))
(set (attr "prefix_extra")
(if_then_else
(and (not (match_test "TARGET_AVX"))
- (eq (const_string "<MODE>mode") (const_string "V8HImode")))
+ (match_test "GET_MODE_NUNITS (<MODE>mode) == 8"))
(const_string "*")
(const_string "1")))
(set_attr "length_immediate" "1")
- (set_attr "prefix" "orig,orig,vex,vex,evex,evex")
- (set_attr "mode" "TI")])
+ (set_attr "prefix" "orig,orig,vex,vex,evex,evex,vex")
+ (set_attr "mode" "TI")
+ (set (attr "enabled")
+ (cond [(and (not (match_test "GET_MODE_NUNITS (<MODE>mode) == 8"))
+ (eq_attr "alternative" "6"))
+ (symbol_ref "false")
+ ]
+ (const_string "*")))])
+
+;; For TARGET_AVX2, implement insert from XMM reg with PBROADCASTW + PBLENDW.
+;; First try to get a scratch register and go through it. In case this fails,
+;; overwrite source reg with broadcasted value and blend from there.
+(define_peephole2
+ [(match_scratch:V8_128 4 "x")
+ (set (match_operand:V8_128 0 "sse_reg_operand")
+ (vec_merge:V8_128
+ (vec_duplicate:V8_128
+ (match_operand:<ssescalarmode> 2 "sse_reg_operand"))
+ (match_operand:V8_128 1 "sse_reg_operand")
+ (match_operand:SI 3 "const_int_operand")))]
+ "TARGET_AVX2
+ && INTVAL (operands[3]) > 1
+ && ((unsigned) exact_log2 (INTVAL (operands[3]))
+ < GET_MODE_NUNITS (<MODE>mode))"
+ [(set (match_dup 4)
+ (vec_duplicate:V8_128 (match_dup 2)))
+ (set (match_dup 0)
+ (vec_merge:V8_128 (match_dup 4) (match_dup 1) (match_dup 3)))])
+
+(define_split
+ [(set (match_operand:V8_128 0 "sse_reg_operand")
+ (vec_merge:V8_128
+ (vec_duplicate:V8_128
+ (match_operand:<ssescalarmode> 2 "sse_reg_operand"))
+ (match_operand:V8_128 1 "sse_reg_operand")
+ (match_operand:SI 3 "const_int_operand")))]
+ "TARGET_AVX2 && epilogue_completed
+ && INTVAL (operands[3]) > 1
+ && ((unsigned) exact_log2 (INTVAL (operands[3]))
+ < GET_MODE_NUNITS (<MODE>mode))"
+ [(set (match_dup 4)
+ (vec_duplicate:V8_128 (match_dup 2)))
+ (set (match_dup 0)
+ (vec_merge:V8_128 (match_dup 4) (match_dup 1) (match_dup 3)))]
+{
+ operands[4] = lowpart_subreg (<MODE>mode, operands[2],
+ <ssescalarmode>mode);
+})
(define_expand "<extract_type>_vinsert<shuffletype><extract_suf>_mask"
[(match_operand:AVX512_VEC 0 "register_operand")
@@ -20659,6 +20767,33 @@
(set_attr "btver2_decode" "vector,vector,vector")
(set_attr "mode" "<ssefltvecmode>")])
+;; PR target/100738: Transform vpcmpeqd + vpxor + vblendvps to vblendvps for inverted mask;
+(define_insn_and_split "*<sse4_1>_blendv<ssefltmodesuffix><avxsizesuffix>_not_ltint"
+ [(set (match_operand:<ssebytemode> 0 "register_operand")
+ (unspec:<ssebytemode>
+ [(match_operand:<ssebytemode> 1 "register_operand")
+ (match_operand:<ssebytemode> 2 "vector_operand")
+ (subreg:<ssebytemode>
+ (lt:VI48_AVX
+ (subreg:VI48_AVX
+ (not:<ssebytemode>
+ (match_operand:<ssebytemode> 3 "register_operand")) 0)
+ (match_operand:VI48_AVX 4 "const0_operand")) 0)]
+ UNSPEC_BLENDV))]
+ "TARGET_SSE4_1 && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(set (match_dup 0)
+ (unspec:<ssefltvecmode>
+ [(match_dup 2) (match_dup 1) (match_dup 3)] UNSPEC_BLENDV))]
+{
+ operands[0] = gen_lowpart (<ssefltvecmode>mode, operands[0]);
+ operands[1] = gen_lowpart (<ssefltvecmode>mode, operands[1]);
+ operands[2] = force_reg (<ssefltvecmode>mode,
+ gen_lowpart (<ssefltvecmode>mode, operands[2]));
+ operands[3] = gen_lowpart (<ssefltvecmode>mode, operands[3]);
+})
+
(define_insn "<sse4_1>_dp<ssemodesuffix><avxsizesuffix>"
[(set (match_operand:VF_128_256 0 "register_operand" "=Yr,*x,x")
(unspec:VF_128_256
diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def
index dab4b3d..de9759a 100644
--- a/gcc/config/i386/x86-tune.def
+++ b/gcc/config/i386/x86-tune.def
@@ -45,8 +45,8 @@ DEF_TUNE (X86_TUNE_SCHEDULE, "schedule",
| m_GOLDMONT_PLUS | m_TREMONT | m_ALDERLAKE | m_GENERIC)
/* X86_TUNE_PARTIAL_REG_DEPENDENCY: Enable more register renaming
- on modern chips. Preffer stores affecting whole integer register
- over partial stores. For example preffer MOVZBL or MOVQ to load 8bit
+ on modern chips. Prefer stores affecting whole integer register
+ over partial stores. For example prefer MOVZBL or MOVQ to load 8bit
value over movb. */
DEF_TUNE (X86_TUNE_PARTIAL_REG_DEPENDENCY, "partial_reg_dependency",
m_P4_NOCONA | m_CORE2 | m_NEHALEM | m_SANDYBRIDGE | m_CORE_AVX2
@@ -512,6 +512,16 @@ DEF_TUNE (X86_TUNE_AVX256_MOVE_BY_PIECES, "avx256_move_by_pieces",
DEF_TUNE (X86_TUNE_AVX256_STORE_BY_PIECES, "avx256_store_by_pieces",
m_CORE_AVX512)
+/* X86_TUNE_AVX512_MOVE_BY_PIECES: Optimize move_by_pieces with 512-bit
+ AVX instructions. */
+DEF_TUNE (X86_TUNE_AVX512_MOVE_BY_PIECES, "avx512_move_by_pieces",
+ m_SAPPHIRERAPIDS)
+
+/* X86_TUNE_AVX512_STORE_BY_PIECES: Optimize store_by_pieces with 512-bit
+ AVX instructions. */
+DEF_TUNE (X86_TUNE_AVX512_STORE_BY_PIECES, "avx512_store_by_pieces",
+ m_SAPPHIRERAPIDS)
+
/*****************************************************************************/
/*****************************************************************************/
/* Historical relics: tuning flags that helps a specific old CPU designs */
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 973372e..34490bf 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -243,6 +243,10 @@ struct mips_cpu_info {
&& (mips_isa_rev >= 6 \
|| ISA_HAS_MSA))
+/* ISA load/store instructions can handle unaligned address */
+#define ISA_HAS_UNALIGNED_ACCESS (TARGET_UNALIGNED_ACCESS \
+ && (mips_isa_rev >= 6))
+
/* The ISA compression flags that are currently in effect. */
#define TARGET_COMPRESSION (target_flags & (MASK_MIPS16 | MASK_MICROMIPS))
@@ -1684,7 +1688,7 @@ FP_ASM_SPEC "\
(ISA_HAS_MSA ? BITS_PER_MSA_REG : LONG_DOUBLE_TYPE_SIZE)
/* All accesses must be aligned. */
-#define STRICT_ALIGNMENT 1
+#define STRICT_ALIGNMENT (!ISA_HAS_UNALIGNED_ACCESS)
/* Define this if you wish to imitate the way many other C compilers
handle alignment of bitfields and the structures that contain
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 455b9b8..e35d57d 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -4459,6 +4459,16 @@
[(set_attr "move_type" "store")
(set_attr "mode" "<MODE>")])
+;; Unaligned direct access
+(define_expand "movmisalign<mode>"
+ [(set (match_operand:JOIN_MODE 0)
+ (match_operand:JOIN_MODE 1))]
+ "ISA_HAS_UNALIGNED_ACCESS"
+{
+ if (mips_legitimize_move (<MODE>mode, operands[0], operands[1]))
+ DONE;
+})
+
;; An instruction to calculate the high part of a 64-bit SYMBOL_ABSOLUTE.
;; The required value is:
;;
diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt
index 6af8037..ebb4c61 100644
--- a/gcc/config/mips/mips.opt
+++ b/gcc/config/mips/mips.opt
@@ -404,6 +404,10 @@ mtune=
Target RejectNegative Joined Var(mips_tune_option) ToLower Enum(mips_arch_opt_value)
-mtune=PROCESSOR Optimize the output for PROCESSOR.
+munaligned-access
+Target Var(TARGET_UNALIGNED_ACCESS) Init(1)
+Generate code with unaligned load store, valid for MIPS R6.
+
muninit-const-in-rodata
Target Var(TARGET_UNINIT_CONST_IN_RODATA)
Put uninitialized constants in ROM (needs -membedded-data).
diff --git a/gcc/config/nvptx/nvptx.md b/gcc/config/nvptx/nvptx.md
index 108de1c..b7a0393 100644
--- a/gcc/config/nvptx/nvptx.md
+++ b/gcc/config/nvptx/nvptx.md
@@ -401,6 +401,32 @@
%.\\tst%A0.u%T0\\t%0, %1;"
[(set_attr "subregs_ok" "true")])
+;; Sign-extensions of truncations
+
+(define_insn "*extend_trunc_<mode>2_qi"
+ [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R")
+ (sign_extend:HSDIM
+ (truncate:QI (match_operand:HSDIM 1 "nvptx_register_operand" "R"))))]
+ ""
+ "%.\\tcvt.s%T0.s8\\t%0, %1;"
+ [(set_attr "subregs_ok" "true")])
+
+(define_insn "*extend_trunc_<mode>2_hi"
+ [(set (match_operand:SDIM 0 "nvptx_register_operand" "=R")
+ (sign_extend:SDIM
+ (truncate:HI (match_operand:SDIM 1 "nvptx_register_operand" "R"))))]
+ ""
+ "%.\\tcvt.s%T0.s16\\t%0, %1;"
+ [(set_attr "subregs_ok" "true")])
+
+(define_insn "*extend_trunc_di2_si"
+ [(set (match_operand:DI 0 "nvptx_register_operand" "=R")
+ (sign_extend:DI
+ (truncate:SI (match_operand:DI 1 "nvptx_register_operand" "R"))))]
+ ""
+ "%.\\tcvt.s64.s32\\t%0, %1;"
+ [(set_attr "subregs_ok" "true")])
+
;; Integer arithmetic
(define_insn "add<mode>3"
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index f22d25a..2b10ef3 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -10009,7 +10009,7 @@ pa_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
to the default text subspace. */
static void
-som_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED)
+som_output_text_section_asm_op (const char *data ATTRIBUTE_UNUSED)
{
gcc_assert (TARGET_SOM);
if (TARGET_GAS)
@@ -10053,7 +10053,7 @@ som_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED)
sections. This function is only used with SOM. */
static void
-som_output_comdat_data_section_asm_op (const void *data)
+som_output_comdat_data_section_asm_op (const char *data)
{
in_section = NULL;
output_section_asm_op (data);
diff --git a/gcc/config/pru/pru.c b/gcc/config/pru/pru.c
index 9f264b4..01d283f 100644
--- a/gcc/config/pru/pru.c
+++ b/gcc/config/pru/pru.c
@@ -2022,6 +2022,23 @@ pru_assemble_integer (rtx x, unsigned int size, int aligned_p)
}
}
+/* Implement TARGET_SECTION_TYPE_FLAGS. */
+
+static unsigned int
+pru_section_type_flags (tree decl, const char *name, int reloc)
+{
+ unsigned int flags = default_section_type_flags (decl, name, reloc);
+
+ /* The .pru_irq_map section is not meant to be loaded into the target
+ memory. Instead its contents are read by the host remoteproc loader.
+ To prevent being marked as a loadable (allocated) section, the
+ .pru_irq_map section is intercepted and marked as a debug section. */
+ if (!strcmp (name, ".pru_irq_map"))
+ flags = SECTION_DEBUG | SECTION_RETAIN;
+
+ return flags;
+}
+
/* Implement TARGET_ASM_FILE_START. */
static void
@@ -3071,6 +3088,8 @@ pru_unwind_word_mode (void)
#define TARGET_ASM_FUNCTION_PROLOGUE pru_asm_function_prologue
#undef TARGET_ASM_INTEGER
#define TARGET_ASM_INTEGER pru_assemble_integer
+#undef TARGET_SECTION_TYPE_FLAGS
+#define TARGET_SECTION_TYPE_FLAGS pru_section_type_flags
#undef TARGET_ASM_FILE_START
#define TARGET_ASM_FILE_START pru_file_start
diff --git a/gcc/config/riscv/arch-canonicalize b/gcc/config/riscv/arch-canonicalize
index c7df3c8..90dbd19 100755
--- a/gcc/config/riscv/arch-canonicalize
+++ b/gcc/config/riscv/arch-canonicalize
@@ -28,7 +28,7 @@ import itertools
from functools import reduce
-CANONICAL_ORDER = "imafdgqlcbjtpvn"
+CANONICAL_ORDER = "imafdgqlcbjktpvn"
LONG_EXT_PREFIXES = ['z', 's', 'h', 'x']
#
@@ -36,6 +36,20 @@ LONG_EXT_PREFIXES = ['z', 's', 'h', 'x']
#
IMPLIED_EXT = {
"d" : ["f"],
+ "zk" : ["zkn"],
+ "zk" : ["zkr"],
+ "zk" : ["zkt"],
+ "zkn" : ["zbkb"],
+ "zkn" : ["zbkc"],
+ "zkn" : ["zbkx"],
+ "zkn" : ["zkne"],
+ "zkn" : ["zknd"],
+ "zkn" : ["zknh"],
+ "zks" : ["zbkb"],
+ "zks" : ["zbkc"],
+ "zks" : ["zbkx"],
+ "zks" : ["zksed"],
+ "zks" : ["zksh"],
}
def arch_canonicalize(arch):
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 2efc4b8..f65ff67 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -83,4 +83,26 @@ enum stack_protector_guard {
#define TARGET_ZBC ((riscv_zb_subext & MASK_ZBC) != 0)
#define TARGET_ZBS ((riscv_zb_subext & MASK_ZBS) != 0)
+#define MASK_ZBKB (1 << 0)
+#define MASK_ZBKC (1 << 1)
+#define MASK_ZBKX (1 << 2)
+#define MASK_ZKNE (1 << 3)
+#define MASK_ZKND (1 << 4)
+#define MASK_ZKNH (1 << 5)
+#define MASK_ZKR (1 << 6)
+#define MASK_ZKSED (1 << 7)
+#define MASK_ZKSH (1 << 8)
+#define MASK_ZKT (1 << 9)
+
+#define TARGET_ZBKB ((riscv_zk_subext & MASK_ZBKB) != 0)
+#define TARGET_ZBKC ((riscv_zk_subext & MASK_ZBKC) != 0)
+#define TARGET_ZBKX ((riscv_zk_subext & MASK_ZBKX) != 0)
+#define TARGET_ZKNE ((riscv_zk_subext & MASK_ZKNE) != 0)
+#define TARGET_ZKND ((riscv_zk_subext & MASK_ZKND) != 0)
+#define TARGET_ZKNH ((riscv_zk_subext & MASK_ZKNH) != 0)
+#define TARGET_ZKR ((riscv_zk_subext & MASK_ZKR) != 0)
+#define TARGET_ZKSED ((riscv_zk_subext & MASK_ZKSED) != 0)
+#define TARGET_ZKSH ((riscv_zk_subext & MASK_ZKSH) != 0)
+#define TARGET_ZKT ((riscv_zk_subext & MASK_ZKT) != 0)
+
#endif /* ! GCC_RISCV_OPTS_H */
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 15bf89e..6170009 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -198,6 +198,9 @@ int riscv_zi_subext
TargetVariable
int riscv_zb_subext
+TargetVariable
+int riscv_zk_subext
+
Enum
Name(isa_spec_class) Type(enum riscv_isa_spec_class)
Supported ISA specs (for use with the -misa-spec= option):
diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h
index ea72c9c..204910d 100644
--- a/gcc/config/rs6000/altivec.h
+++ b/gcc/config/rs6000/altivec.h
@@ -55,32 +55,36 @@
#define __CR6_LT 2
#define __CR6_LT_REV 3
-/* Synonyms. */
+#include "rs6000-vecdefines.h"
+
+/* Deprecated interfaces. */
+#define vec_lvx vec_ld
+#define vec_lvxl vec_ldl
+#define vec_stvx vec_st
+#define vec_stvxl vec_stl
#define vec_vaddcuw vec_addc
#define vec_vand vec_and
#define vec_vandc vec_andc
-#define vec_vrfip vec_ceil
#define vec_vcmpbfp vec_cmpb
#define vec_vcmpgefp vec_cmpge
#define vec_vctsxs vec_cts
#define vec_vctuxs vec_ctu
#define vec_vexptefp vec_expte
-#define vec_vrfim vec_floor
-#define vec_lvx vec_ld
-#define vec_lvxl vec_ldl
#define vec_vlogefp vec_loge
#define vec_vmaddfp vec_madd
#define vec_vmhaddshs vec_madds
-#define vec_vmladduhm vec_mladd
#define vec_vmhraddshs vec_mradds
+#define vec_vmladduhm vec_mladd
#define vec_vnmsubfp vec_nmsub
#define vec_vnor vec_nor
#define vec_vor vec_or
-#define vec_vpkpx vec_packpx
#define vec_vperm vec_perm
-#define vec_permxor __builtin_vec_vpermxor
+#define vec_vpkpx vec_packpx
#define vec_vrefp vec_re
+#define vec_vrfim vec_floor
#define vec_vrfin vec_round
+#define vec_vrfip vec_ceil
+#define vec_vrfiz vec_trunc
#define vec_vrsqrtefp vec_rsqrte
#define vec_vsel vec_sel
#define vec_vsldoi vec_sld
@@ -91,440 +95,54 @@
#define vec_vspltisw vec_splat_s32
#define vec_vsr vec_srl
#define vec_vsro vec_sro
-#define vec_stvx vec_st
-#define vec_stvxl vec_stl
#define vec_vsubcuw vec_subc
#define vec_vsum2sws vec_sum2s
#define vec_vsumsws vec_sums
-#define vec_vrfiz vec_trunc
#define vec_vxor vec_xor
+/* For _ARCH_PWR8. Always define to support #pragma GCC target. */
+#define vec_vclz vec_cntlz
+#define vec_vgbbd vec_gb
+#define vec_vmrgew vec_mergee
+#define vec_vmrgow vec_mergeo
+#define vec_vpopcntu vec_popcnt
+#define vec_vrld vec_rl
+#define vec_vsld vec_sl
+#define vec_vsrd vec_sr
+#define vec_vsrad vec_sra
+
+/* For _ARCH_PWR9. Always define to support #pragma GCC target. */
+#define vec_extract_fp_from_shorth vec_extract_fp32_from_shorth
+#define vec_extract_fp_from_shortl vec_extract_fp32_from_shortl
+#define vec_vctz vec_cnttz
+
+/* Synonyms. */
/* Functions that are resolved by the backend to one of the
typed builtins. */
-#define vec_vaddfp __builtin_vec_vaddfp
-#define vec_addc __builtin_vec_addc
-#define vec_adde __builtin_vec_adde
-#define vec_addec __builtin_vec_addec
-#define vec_vaddsws __builtin_vec_vaddsws
-#define vec_vaddshs __builtin_vec_vaddshs
-#define vec_vaddsbs __builtin_vec_vaddsbs
-#define vec_vavgsw __builtin_vec_vavgsw
-#define vec_vavguw __builtin_vec_vavguw
-#define vec_vavgsh __builtin_vec_vavgsh
-#define vec_vavguh __builtin_vec_vavguh
-#define vec_vavgsb __builtin_vec_vavgsb
-#define vec_vavgub __builtin_vec_vavgub
-#define vec_ceil __builtin_vec_ceil
-#define vec_cmpb __builtin_vec_cmpb
-#define vec_vcmpeqfp __builtin_vec_vcmpeqfp
-#define vec_cmpge __builtin_vec_cmpge
-#define vec_vcmpgtfp __builtin_vec_vcmpgtfp
-#define vec_vcmpgtsw __builtin_vec_vcmpgtsw
-#define vec_vcmpgtuw __builtin_vec_vcmpgtuw
-#define vec_vcmpgtsh __builtin_vec_vcmpgtsh
-#define vec_vcmpgtuh __builtin_vec_vcmpgtuh
-#define vec_vcmpgtsb __builtin_vec_vcmpgtsb
-#define vec_vcmpgtub __builtin_vec_vcmpgtub
-#define vec_vcfsx __builtin_vec_vcfsx
-#define vec_vcfux __builtin_vec_vcfux
-#define vec_cts __builtin_vec_cts
-#define vec_ctu __builtin_vec_ctu
#define vec_cpsgn(x,y) __builtin_vec_copysign(y,x)
-#define vec_double __builtin_vec_double
-#define vec_doublee __builtin_vec_doublee
-#define vec_doubleo __builtin_vec_doubleo
-#define vec_doublel __builtin_vec_doublel
-#define vec_doubleh __builtin_vec_doubleh
-#define vec_expte __builtin_vec_expte
-#define vec_float __builtin_vec_float
-#define vec_float2 __builtin_vec_float2
-#define vec_floate __builtin_vec_floate
-#define vec_floato __builtin_vec_floato
-#define vec_floor __builtin_vec_floor
-#define vec_loge __builtin_vec_loge
-#define vec_madd __builtin_vec_madd
-#define vec_madds __builtin_vec_madds
-#define vec_mtvscr __builtin_vec_mtvscr
-#define vec_reve __builtin_vec_vreve
-#define vec_vmaxfp __builtin_vec_vmaxfp
-#define vec_vmaxsw __builtin_vec_vmaxsw
-#define vec_vmaxsh __builtin_vec_vmaxsh
-#define vec_vmaxsb __builtin_vec_vmaxsb
-#define vec_vminfp __builtin_vec_vminfp
-#define vec_vminsw __builtin_vec_vminsw
-#define vec_vminsh __builtin_vec_vminsh
-#define vec_vminsb __builtin_vec_vminsb
-#define vec_mradds __builtin_vec_mradds
-#define vec_vmsumshm __builtin_vec_vmsumshm
-#define vec_vmsumuhm __builtin_vec_vmsumuhm
-#define vec_vmsummbm __builtin_vec_vmsummbm
-#define vec_vmsumubm __builtin_vec_vmsumubm
-#define vec_vmsumshs __builtin_vec_vmsumshs
-#define vec_vmsumuhs __builtin_vec_vmsumuhs
-#define vec_vmsumudm __builtin_vec_vmsumudm
-#define vec_vmulesb __builtin_vec_vmulesb
-#define vec_vmulesh __builtin_vec_vmulesh
-#define vec_vmuleuh __builtin_vec_vmuleuh
-#define vec_vmuleub __builtin_vec_vmuleub
-#define vec_vmulosh __builtin_vec_vmulosh
-#define vec_vmulouh __builtin_vec_vmulouh
-#define vec_vmulosb __builtin_vec_vmulosb
-#define vec_vmuloub __builtin_vec_vmuloub
-#define vec_nmsub __builtin_vec_nmsub
-#define vec_packpx __builtin_vec_packpx
-#define vec_vpkswss __builtin_vec_vpkswss
-#define vec_vpkuwus __builtin_vec_vpkuwus
-#define vec_vpkshss __builtin_vec_vpkshss
-#define vec_vpkuhus __builtin_vec_vpkuhus
-#define vec_vpkswus __builtin_vec_vpkswus
-#define vec_vpkshus __builtin_vec_vpkshus
-#define vec_re __builtin_vec_re
-#define vec_round __builtin_vec_round
-#define vec_recipdiv __builtin_vec_recipdiv
-#define vec_rlmi __builtin_vec_rlmi
-#define vec_vrlnm __builtin_vec_rlnm
#define vec_rlnm(a,b,c) (__builtin_vec_rlnm((a),((c)<<8)|(b)))
-#define vec_rsqrt __builtin_vec_rsqrt
-#define vec_rsqrte __builtin_vec_rsqrte
-#define vec_signed __builtin_vec_vsigned
-#define vec_signed2 __builtin_vec_vsigned2
-#define vec_signede __builtin_vec_vsignede
-#define vec_signedo __builtin_vec_vsignedo
-#define vec_unsigned __builtin_vec_vunsigned
-#define vec_unsigned2 __builtin_vec_vunsigned2
-#define vec_unsignede __builtin_vec_vunsignede
-#define vec_unsignedo __builtin_vec_vunsignedo
-#define vec_vsubfp __builtin_vec_vsubfp
-#define vec_subc __builtin_vec_subc
-#define vec_sube __builtin_vec_sube
-#define vec_subec __builtin_vec_subec
-#define vec_vsubsws __builtin_vec_vsubsws
-#define vec_vsubshs __builtin_vec_vsubshs
-#define vec_vsubsbs __builtin_vec_vsubsbs
-#define vec_sum4s __builtin_vec_sum4s
-#define vec_vsum4shs __builtin_vec_vsum4shs
-#define vec_vsum4sbs __builtin_vec_vsum4sbs
-#define vec_vsum4ubs __builtin_vec_vsum4ubs
-#define vec_sum2s __builtin_vec_sum2s
-#define vec_sums __builtin_vec_sums
-#define vec_trunc __builtin_vec_trunc
-#define vec_vupkhpx __builtin_vec_vupkhpx
-#define vec_vupkhsh __builtin_vec_vupkhsh
-#define vec_vupkhsb __builtin_vec_vupkhsb
-#define vec_vupklpx __builtin_vec_vupklpx
-#define vec_vupklsh __builtin_vec_vupklsh
-#define vec_vupklsb __builtin_vec_vupklsb
-#define vec_abs __builtin_vec_abs
-#define vec_nabs __builtin_vec_nabs
-#define vec_abss __builtin_vec_abss
-#define vec_add __builtin_vec_add
-#define vec_adds __builtin_vec_adds
-#define vec_and __builtin_vec_and
-#define vec_andc __builtin_vec_andc
-#define vec_avg __builtin_vec_avg
-#define vec_cmpeq __builtin_vec_cmpeq
-#define vec_cmpne __builtin_vec_cmpne
-#define vec_cmpgt __builtin_vec_cmpgt
-#define vec_ctf __builtin_vec_ctf
-#define vec_dst __builtin_vec_dst
-#define vec_dstst __builtin_vec_dstst
-#define vec_dststt __builtin_vec_dststt
-#define vec_dstt __builtin_vec_dstt
-#define vec_ld __builtin_vec_ld
-#define vec_lde __builtin_vec_lde
-#define vec_ldl __builtin_vec_ldl
-#define vec_lvebx __builtin_vec_lvebx
-#define vec_lvehx __builtin_vec_lvehx
-#define vec_lvewx __builtin_vec_lvewx
-#define vec_xl_zext __builtin_vec_ze_lxvrx
-#define vec_xl_sext __builtin_vec_se_lxvrx
-#define vec_xst_trunc __builtin_vec_tr_stxvrx
-#define vec_neg __builtin_vec_neg
-#define vec_pmsum_be __builtin_vec_vpmsum
-#define vec_shasigma_be __builtin_crypto_vshasigma
-/* Cell only intrinsics. */
-#ifdef __PPU__
-#define vec_lvlx __builtin_vec_lvlx
-#define vec_lvlxl __builtin_vec_lvlxl
-#define vec_lvrx __builtin_vec_lvrx
-#define vec_lvrxl __builtin_vec_lvrxl
-#endif
-#define vec_lvsl __builtin_vec_lvsl
-#define vec_lvsr __builtin_vec_lvsr
-#define vec_max __builtin_vec_max
-#define vec_mergee __builtin_vec_vmrgew
-#define vec_mergeh __builtin_vec_mergeh
-#define vec_mergel __builtin_vec_mergel
-#define vec_mergeo __builtin_vec_vmrgow
-#define vec_min __builtin_vec_min
-#define vec_mladd __builtin_vec_mladd
-#define vec_msum __builtin_vec_msum
-#define vec_msums __builtin_vec_msums
-#define vec_mul __builtin_vec_mul
-#define vec_mule __builtin_vec_mule
-#define vec_mulo __builtin_vec_mulo
-#define vec_nor __builtin_vec_nor
-#define vec_or __builtin_vec_or
-#define vec_pack __builtin_vec_pack
-#define vec_packs __builtin_vec_packs
-#define vec_packsu __builtin_vec_packsu
-#define vec_perm __builtin_vec_perm
-#define vec_rl __builtin_vec_rl
-#define vec_sel __builtin_vec_sel
-#define vec_sl __builtin_vec_sl
-#define vec_sld __builtin_vec_sld
-#define vec_sldw __builtin_vsx_xxsldwi
-#define vec_sll __builtin_vec_sll
-#define vec_slo __builtin_vec_slo
-#define vec_splat __builtin_vec_splat
-#define vec_sr __builtin_vec_sr
-#define vec_sra __builtin_vec_sra
-#define vec_srl __builtin_vec_srl
-#define vec_sro __builtin_vec_sro
-#define vec_st __builtin_vec_st
-#define vec_ste __builtin_vec_ste
-#define vec_stl __builtin_vec_stl
-#define vec_stvebx __builtin_vec_stvebx
-#define vec_stvehx __builtin_vec_stvehx
-#define vec_stvewx __builtin_vec_stvewx
-/* Cell only intrinsics. */
-#ifdef __PPU__
-#define vec_stvlx __builtin_vec_stvlx
-#define vec_stvlxl __builtin_vec_stvlxl
-#define vec_stvrx __builtin_vec_stvrx
-#define vec_stvrxl __builtin_vec_stvrxl
-#endif
-#define vec_sub __builtin_vec_sub
-#define vec_subs __builtin_vec_subs
-#define vec_sum __builtin_vec_sum
-#define vec_unpackh __builtin_vec_unpackh
-#define vec_unpackl __builtin_vec_unpackl
-#define vec_vaddubm __builtin_vec_vaddubm
-#define vec_vaddubs __builtin_vec_vaddubs
-#define vec_vadduhm __builtin_vec_vadduhm
-#define vec_vadduhs __builtin_vec_vadduhs
-#define vec_vadduwm __builtin_vec_vadduwm
-#define vec_vadduws __builtin_vec_vadduws
-#define vec_vcmpequb __builtin_vec_vcmpequb
-#define vec_vcmpequh __builtin_vec_vcmpequh
-#define vec_vcmpequw __builtin_vec_vcmpequw
-#define vec_vmaxub __builtin_vec_vmaxub
-#define vec_vmaxuh __builtin_vec_vmaxuh
-#define vec_vmaxuw __builtin_vec_vmaxuw
-#define vec_vminub __builtin_vec_vminub
-#define vec_vminuh __builtin_vec_vminuh
-#define vec_vminuw __builtin_vec_vminuw
-#define vec_vmrghb __builtin_vec_vmrghb
-#define vec_vmrghh __builtin_vec_vmrghh
-#define vec_vmrghw __builtin_vec_vmrghw
-#define vec_vmrglb __builtin_vec_vmrglb
-#define vec_vmrglh __builtin_vec_vmrglh
-#define vec_vmrglw __builtin_vec_vmrglw
-#define vec_vpkuhum __builtin_vec_vpkuhum
-#define vec_vpkuwum __builtin_vec_vpkuwum
-#define vec_vrlb __builtin_vec_vrlb
-#define vec_vrlh __builtin_vec_vrlh
-#define vec_vrlw __builtin_vec_vrlw
-#define vec_vslb __builtin_vec_vslb
-#define vec_vslh __builtin_vec_vslh
-#define vec_vslw __builtin_vec_vslw
-#define vec_vspltb __builtin_vec_vspltb
-#define vec_vsplth __builtin_vec_vsplth
-#define vec_vspltw __builtin_vec_vspltw
-#define vec_vsrab __builtin_vec_vsrab
-#define vec_vsrah __builtin_vec_vsrah
-#define vec_vsraw __builtin_vec_vsraw
-#define vec_vsrb __builtin_vec_vsrb
-#define vec_vsrh __builtin_vec_vsrh
-#define vec_vsrw __builtin_vec_vsrw
-#define vec_vsububs __builtin_vec_vsububs
-#define vec_vsububm __builtin_vec_vsububm
-#define vec_vsubuhm __builtin_vec_vsubuhm
-#define vec_vsubuhs __builtin_vec_vsubuhs
-#define vec_vsubuwm __builtin_vec_vsubuwm
-#define vec_vsubuws __builtin_vec_vsubuws
-#define vec_xor __builtin_vec_xor
-
-#define vec_extract __builtin_vec_extract
-#define vec_insert __builtin_vec_insert
-#define vec_splats __builtin_vec_splats
-#define vec_promote __builtin_vec_promote
#ifdef __VSX__
/* VSX additions */
-#define vec_div __builtin_vec_div
-#define vec_mul __builtin_vec_mul
-#define vec_msub __builtin_vec_msub
-#define vec_nmadd __builtin_vec_nmadd
-#define vec_nearbyint __builtin_vec_nearbyint
-#define vec_rint __builtin_vec_rint
-#define vec_sqrt __builtin_vec_sqrt
#define vec_vsx_ld __builtin_vec_vsx_ld
#define vec_vsx_st __builtin_vec_vsx_st
-#define vec_xl __builtin_vec_vsx_ld
-#define vec_xl_be __builtin_vec_xl_be
-#define vec_xst __builtin_vec_vsx_st
-#define vec_xst_be __builtin_vec_xst_be
-
-/* Note, xxsldi and xxpermdi were added as __builtin_vsx_<xxx> functions
- instead of __builtin_vec_<xxx> */
-#define vec_xxsldwi __builtin_vsx_xxsldwi
-#define vec_xxpermdi __builtin_vsx_xxpermdi
-#endif
-
-#ifdef _ARCH_PWR8
-/* Vector additions added in ISA 2.07. */
-#define vec_eqv __builtin_vec_eqv
-#define vec_nand __builtin_vec_nand
-#define vec_orc __builtin_vec_orc
-#define vec_vaddcuq __builtin_vec_vaddcuq
-#define vec_vaddudm __builtin_vec_vaddudm
-#define vec_vadduqm __builtin_vec_vadduqm
-#define vec_vbpermq __builtin_vec_vbpermq
-#define vec_bperm __builtin_vec_vbperm_api
-#define vec_vclz __builtin_vec_vclz
-#define vec_cntlz __builtin_vec_vclz
-#define vec_vclzb __builtin_vec_vclzb
-#define vec_vclzd __builtin_vec_vclzd
-#define vec_vclzh __builtin_vec_vclzh
-#define vec_vclzw __builtin_vec_vclzw
-#define vec_vaddecuq __builtin_vec_vaddecuq
-#define vec_vaddeuqm __builtin_vec_vaddeuqm
-#define vec_vsubecuq __builtin_vec_vsubecuq
-#define vec_vsubeuqm __builtin_vec_vsubeuqm
-#define vec_vgbbd __builtin_vec_vgbbd
-#define vec_gb __builtin_vec_vgbbd
-#define vec_vmaxsd __builtin_vec_vmaxsd
-#define vec_vmaxud __builtin_vec_vmaxud
-#define vec_vminsd __builtin_vec_vminsd
-#define vec_vminud __builtin_vec_vminud
-#define vec_vmrgew __builtin_vec_vmrgew
-#define vec_vmrgow __builtin_vec_vmrgow
-#define vec_vpksdss __builtin_vec_vpksdss
-#define vec_vpksdus __builtin_vec_vpksdus
-#define vec_vpkudum __builtin_vec_vpkudum
-#define vec_vpkudus __builtin_vec_vpkudus
-#define vec_vpopcnt __builtin_vec_vpopcnt
-#define vec_vpopcntb __builtin_vec_vpopcntb
-#define vec_vpopcntd __builtin_vec_vpopcntd
-#define vec_vpopcnth __builtin_vec_vpopcnth
-#define vec_vpopcntw __builtin_vec_vpopcntw
-#define vec_popcnt __builtin_vec_vpopcntu
-#define vec_vrld __builtin_vec_vrld
-#define vec_vsld __builtin_vec_vsld
-#define vec_vsrad __builtin_vec_vsrad
-#define vec_vsrd __builtin_vec_vsrd
-#define vec_vsubcuq __builtin_vec_vsubcuq
-#define vec_vsubudm __builtin_vec_vsubudm
-#define vec_vsubuqm __builtin_vec_vsubuqm
-#define vec_vupkhsw __builtin_vec_vupkhsw
-#define vec_vupklsw __builtin_vec_vupklsw
-#define vec_revb __builtin_vec_revb
-#define vec_sbox_be __builtin_crypto_vsbox_be
-#define vec_cipher_be __builtin_crypto_vcipher_be
-#define vec_cipherlast_be __builtin_crypto_vcipherlast_be
-#define vec_ncipher_be __builtin_crypto_vncipher_be
-#define vec_ncipherlast_be __builtin_crypto_vncipherlast_be
-#endif
-
-#ifdef __POWER9_VECTOR__
-/* Vector additions added in ISA 3.0. */
-#define vec_first_match_index __builtin_vec_first_match_index
-#define vec_first_match_or_eos_index __builtin_vec_first_match_or_eos_index
-#define vec_first_mismatch_index __builtin_vec_first_mismatch_index
-#define vec_first_mismatch_or_eos_index __builtin_vec_first_mismatch_or_eos_index
-#define vec_pack_to_short_fp32 __builtin_vec_convert_4f32_8f16
-#define vec_parity_lsbb __builtin_vec_vparity_lsbb
-#define vec_vctz __builtin_vec_vctz
-#define vec_cnttz __builtin_vec_vctz
-#define vec_vctzb __builtin_vec_vctzb
-#define vec_vctzd __builtin_vec_vctzd
-#define vec_vctzh __builtin_vec_vctzh
-#define vec_vctzw __builtin_vec_vctzw
-#define vec_extract4b __builtin_vec_extract4b
-#define vec_insert4b __builtin_vec_insert4b
-#define vec_vprtyb __builtin_vec_vprtyb
-#define vec_vprtybd __builtin_vec_vprtybd
-#define vec_vprtybw __builtin_vec_vprtybw
-
-#ifdef _ARCH_PPC64
-#define vec_vprtybq __builtin_vec_vprtybq
-#endif
-
-#define vec_absd __builtin_vec_vadu
-#define vec_absdb __builtin_vec_vadub
-#define vec_absdh __builtin_vec_vaduh
-#define vec_absdw __builtin_vec_vaduw
-
-#define vec_slv __builtin_vec_vslv
-#define vec_srv __builtin_vec_vsrv
-
-#define vec_extract_exp __builtin_vec_extract_exp
-#define vec_extract_sig __builtin_vec_extract_sig
-#define vec_insert_exp __builtin_vec_insert_exp
-#define vec_test_data_class __builtin_vec_test_data_class
-
-#define vec_extract_fp_from_shorth __builtin_vec_vextract_fp_from_shorth
-#define vec_extract_fp_from_shortl __builtin_vec_vextract_fp_from_shortl
-#define vec_extract_fp32_from_shorth __builtin_vec_vextract_fp_from_shorth
-#define vec_extract_fp32_from_shortl __builtin_vec_vextract_fp_from_shortl
-
-#define scalar_extract_exp __builtin_vec_scalar_extract_exp
-#define scalar_extract_sig __builtin_vec_scalar_extract_sig
-#define scalar_insert_exp __builtin_vec_scalar_insert_exp
-#define scalar_test_data_class __builtin_vec_scalar_test_data_class
-#define scalar_test_neg __builtin_vec_scalar_test_neg
-
-#define scalar_cmp_exp_gt __builtin_vec_scalar_cmp_exp_gt
-#define scalar_cmp_exp_lt __builtin_vec_scalar_cmp_exp_lt
-#define scalar_cmp_exp_eq __builtin_vec_scalar_cmp_exp_eq
-#define scalar_cmp_exp_unordered __builtin_vec_scalar_cmp_exp_unordered
-
-#ifdef _ARCH_PPC64
-#define vec_xl_len __builtin_vec_lxvl
-#define vec_xst_len __builtin_vec_stxvl
-#define vec_xl_len_r __builtin_vec_xl_len_r
-#define vec_xst_len_r __builtin_vec_xst_len_r
-#endif
-
-#define vec_cmpnez __builtin_vec_vcmpnez
-
-#define vec_cntlz_lsbb __builtin_vec_vclzlsbb
-#define vec_cnttz_lsbb __builtin_vec_vctzlsbb
-
-#define vec_test_lsbb_all_ones __builtin_vec_xvtlsbb_all_ones
-#define vec_test_lsbb_all_zeros __builtin_vec_xvtlsbb_all_zeros
-
-#define vec_xlx __builtin_vec_vextulx
-#define vec_xrx __builtin_vec_vexturx
-#define vec_signexti __builtin_vec_vsignexti
-#define vec_signextll __builtin_vec_vsignextll
+#define __builtin_vec_xl __builtin_vec_vsx_ld
+#define __builtin_vec_xst __builtin_vec_vsx_st
-#endif
-
-/* BCD builtins, map ABI builtin name to existing builtin name. */
-#define __builtin_bcdadd __builtin_vec_bcdadd
-#define __builtin_bcdadd_lt __builtin_vec_bcdadd_lt
-#define __builtin_bcdadd_eq __builtin_vec_bcdadd_eq
-#define __builtin_bcdadd_gt __builtin_vec_bcdadd_gt
#define __builtin_bcdadd_ofl __builtin_vec_bcdadd_ov
-#define __builtin_bcdadd_ov __builtin_vec_bcdadd_ov
-#define __builtin_bcdsub __builtin_vec_bcdsub
-#define __builtin_bcdsub_lt __builtin_vec_bcdsub_lt
-#define __builtin_bcdsub_eq __builtin_vec_bcdsub_eq
-#define __builtin_bcdsub_gt __builtin_vec_bcdsub_gt
#define __builtin_bcdsub_ofl __builtin_vec_bcdsub_ov
-#define __builtin_bcdsub_ov __builtin_vec_bcdsub_ov
-#define __builtin_bcdinvalid __builtin_vec_bcdinvalid
-#define __builtin_bcdmul10 __builtin_vec_bcdmul10
-#define __builtin_bcddiv10 __builtin_vec_bcddiv10
-#define __builtin_bcd2dfp __builtin_vec_denb2dfp
#define __builtin_bcdcmpeq(a,b) __builtin_vec_bcdsub_eq(a,b,0)
#define __builtin_bcdcmpgt(a,b) __builtin_vec_bcdsub_gt(a,b,0)
#define __builtin_bcdcmplt(a,b) __builtin_vec_bcdsub_lt(a,b,0)
#define __builtin_bcdcmpge(a,b) __builtin_vec_bcdsub_ge(a,b,0)
#define __builtin_bcdcmple(a,b) __builtin_vec_bcdsub_le(a,b,0)
+#endif
+/* For _ARCH_PWR10. Always define to support #pragma GCC target. */
+#define __builtin_vec_se_lxvrx __builtin_vec_xl_sext
+#define __builtin_vec_tr_stxvrx __builtin_vec_xst_trunc
+#define __builtin_vec_ze_lxvrx __builtin_vec_xl_zext
+#define __builtin_vsx_xxpermx __builtin_vec_xxpermx
/* Predicates.
For C++, we use templates in order to allow non-parenthesized arguments.
@@ -700,14 +318,9 @@ __altivec_scalar_pred(vec_any_nle,
#define vec_any_nle(a1, a2) __builtin_vec_vcmpge_p (__CR6_LT_REV, (a2), (a1))
#endif
-/* These do not accept vectors, so they do not have a __builtin_vec_*
- counterpart. */
+/* Miscellaneous definitions. */
#define vec_dss(x) __builtin_altivec_dss((x))
#define vec_dssall() __builtin_altivec_dssall ()
-#define vec_mfvscr() ((__vector unsigned short) __builtin_altivec_mfvscr ())
-#define vec_splat_s8(x) __builtin_altivec_vspltisb ((x))
-#define vec_splat_s16(x) __builtin_altivec_vspltish ((x))
-#define vec_splat_s32(x) __builtin_altivec_vspltisw ((x))
#define vec_splat_u8(x) ((__vector unsigned char) vec_splat_s8 ((x)))
#define vec_splat_u16(x) ((__vector unsigned short) vec_splat_s16 ((x)))
#define vec_splat_u32(x) ((__vector unsigned int) vec_splat_s32 ((x)))
@@ -716,59 +329,4 @@ __altivec_scalar_pred(vec_any_nle,
to #define vec_step to __builtin_vec_step. */
#define vec_step(x) __builtin_vec_step (* (__typeof__ (x) *) 0)
-#ifdef _ARCH_PWR10
-#define vec_signextq __builtin_vec_vsignextq
-#define vec_dive __builtin_vec_dive
-#define vec_mod __builtin_vec_mod
-
-/* May modify these macro definitions if future capabilities overload
- with support for different vector argument and result types. */
-#define vec_cntlzm(a, b) __builtin_altivec_vclzdm (a, b)
-#define vec_cnttzm(a, b) __builtin_altivec_vctzdm (a, b)
-#define vec_pdep(a, b) __builtin_altivec_vpdepd (a, b)
-#define vec_pext(a, b) __builtin_altivec_vpextd (a, b)
-#define vec_cfuge(a, b) __builtin_altivec_vcfuged (a, b)
-#define vec_genpcvm(a, b) __builtin_vec_xxgenpcvm (a, b)
-
-/* Overloaded built-in functions for ISA 3.1. */
-#define vec_extractl(a, b, c) __builtin_vec_extractl (a, b, c)
-#define vec_extracth(a, b, c) __builtin_vec_extracth (a, b, c)
-#define vec_insertl(a, b, c) __builtin_vec_insertl (a, b, c)
-#define vec_inserth(a, b, c) __builtin_vec_inserth (a, b, c)
-#define vec_replace_elt(a, b, c) __builtin_vec_replace_elt (a, b, c)
-#define vec_replace_unaligned(a, b, c) __builtin_vec_replace_un (a, b, c)
-#define vec_sldb(a, b, c) __builtin_vec_sldb (a, b, c)
-#define vec_srdb(a, b, c) __builtin_vec_srdb (a, b, c)
-#define vec_splati(a) __builtin_vec_xxspltiw (a)
-#define vec_splatid(a) __builtin_vec_xxspltid (a)
-#define vec_splati_ins(a, b, c) __builtin_vec_xxsplti32dx (a, b, c)
-#define vec_blendv(a, b, c) __builtin_vec_xxblend (a, b, c)
-#define vec_permx(a, b, c, d) __builtin_vec_xxpermx (a, b, c, d)
-
-#define vec_gnb(a, b) __builtin_vec_gnb (a, b)
-#define vec_clrl(a, b) __builtin_vec_clrl (a, b)
-#define vec_clrr(a, b) __builtin_vec_clrr (a, b)
-#define vec_ternarylogic(a, b, c, d) __builtin_vec_xxeval (a, b, c, d)
-
-#define vec_strir(a) __builtin_vec_strir (a)
-#define vec_stril(a) __builtin_vec_stril (a)
-
-#define vec_strir_p(a) __builtin_vec_strir_p (a)
-#define vec_stril_p(a) __builtin_vec_stril_p (a)
-
-#define vec_mulh(a, b) __builtin_vec_mulh ((a), (b))
-#define vec_dive(a, b) __builtin_vec_dive ((a), (b))
-#define vec_mod(a, b) __builtin_vec_mod ((a), (b))
-
-/* VSX Mask Manipulation builtin. */
-#define vec_genbm __builtin_vec_mtvsrbm
-#define vec_genhm __builtin_vec_mtvsrhm
-#define vec_genwm __builtin_vec_mtvsrwm
-#define vec_gendm __builtin_vec_mtvsrdm
-#define vec_genqm __builtin_vec_mtvsrqm
-#define vec_cntm __builtin_vec_cntm
-#define vec_expandm __builtin_vec_vexpandm
-#define vec_extractm __builtin_vec_vextractm
-#endif
-
#endif /* _ALTIVEC_H */
diff --git a/gcc/config/rs6000/rs6000-builtin-new.def b/gcc/config/rs6000/rs6000-builtin-new.def
index 58dfce1..30556e5 100644
--- a/gcc/config/rs6000/rs6000-builtin-new.def
+++ b/gcc/config/rs6000/rs6000-builtin-new.def
@@ -273,7 +273,7 @@
; Power6 builtins requiring 64-bit GPRs (even with 32-bit addressing).
[power6-64]
const signed long __builtin_p6_cmpb (signed long, signed long);
- CMPB cmpbdi3 {}
+ CMPB cmpbdi3 {no32bit}
; AltiVec builtins.
@@ -2018,7 +2018,7 @@
ADDG6S addg6s {}
const signed long __builtin_bpermd (signed long, signed long);
- BPERMD bpermd_di {}
+ BPERMD bpermd_di {32bit}
const unsigned int __builtin_cbcdtd (unsigned int);
CBCDTD cbcdtd {}
@@ -2971,7 +2971,7 @@
void __builtin_set_fpscr_drn (const int[0,7]);
SET_FPSCR_DRN rs6000_set_fpscr_drn {}
- const unsigned long __builtin_unpack_dec128 (_Decimal128, const int<1>);
+ const unsigned long long __builtin_unpack_dec128 (_Decimal128, const int<1>);
UNPACK_TD unpacktd {}
@@ -3014,39 +3014,39 @@
[htm]
- unsigned long long __builtin_get_texasr ();
+ unsigned long __builtin_get_texasr ();
GET_TEXASR nothing {htm,htmspr}
- unsigned long long __builtin_get_texasru ();
+ unsigned long __builtin_get_texasru ();
GET_TEXASRU nothing {htm,htmspr}
- unsigned long long __builtin_get_tfhar ();
+ unsigned long __builtin_get_tfhar ();
GET_TFHAR nothing {htm,htmspr}
- unsigned long long __builtin_get_tfiar ();
+ unsigned long __builtin_get_tfiar ();
GET_TFIAR nothing {htm,htmspr}
- void __builtin_set_texasr (unsigned long long);
+ void __builtin_set_texasr (unsigned long);
SET_TEXASR nothing {htm,htmspr}
- void __builtin_set_texasru (unsigned long long);
+ void __builtin_set_texasru (unsigned long);
SET_TEXASRU nothing {htm,htmspr}
- void __builtin_set_tfhar (unsigned long long);
+ void __builtin_set_tfhar (unsigned long);
SET_TFHAR nothing {htm,htmspr}
- void __builtin_set_tfiar (unsigned long long);
+ void __builtin_set_tfiar (unsigned long);
SET_TFIAR nothing {htm,htmspr}
unsigned int __builtin_tabort (unsigned int);
TABORT tabort {htm,htmcr}
- unsigned int __builtin_tabortdc (unsigned long long, unsigned long long, \
- unsigned long long);
+ unsigned int __builtin_tabortdc (unsigned long, unsigned long, \
+ unsigned long);
TABORTDC tabortdc {htm,htmcr}
- unsigned int __builtin_tabortdci (unsigned long long, unsigned long long, \
- unsigned long long);
+ unsigned int __builtin_tabortdci (unsigned long, unsigned long, \
+ unsigned long);
TABORTDCI tabortdci {htm,htmcr}
unsigned int __builtin_tabortwc (unsigned int, unsigned int, unsigned int);
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index 5eeac9d..8e83d97 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -35,7 +35,7 @@
#include "langhooks.h"
#include "c/c-tree.h"
-#include "rs6000-builtins.h"
+#include "rs6000-internal.h"
static tree altivec_resolve_new_overloaded_builtin (location_t, tree, void *);
@@ -2987,11 +2987,14 @@ altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
const char *name = rs6000_overload_info[adj_fcode].ovld_name;
if (!supported)
{
+ /* Indicate that the instantiation of the overloaded builtin
+ name is not available with the target flags in effect. */
+ rs6000_gen_builtins fcode = (rs6000_gen_builtins) instance->bifid;
+ rs6000_invalid_new_builtin (fcode);
+ /* Provide clarity of the relationship between the overload
+ and the instantiation. */
const char *internal_name
= rs6000_builtin_info_x[instance->bifid].bifname;
- /* An error message making reference to the name of the
- non-overloaded function has already been issued. Add
- clarification of the previous message. */
rich_location richloc (line_table, input_location);
inform (&richloc,
"overloaded builtin %qs is implemented by builtin %qs",
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index cd477fa..d9736ea 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -69,7 +69,6 @@
#include "opts.h"
#include "rs6000-internal.h"
-#include "rs6000-builtins.h"
#if TARGET_MACHO
#include "gstab.h" /* for N_SLINE */
@@ -11905,7 +11904,7 @@ rs6000_invalid_builtin (enum rs6000_builtins fncode)
/* Raise an error message for a builtin function that is called without the
appropriate target options being set. */
-static void
+void
rs6000_invalid_new_builtin (enum rs6000_gen_builtins fncode)
{
size_t j = (size_t) fncode;
@@ -15737,9 +15736,10 @@ rs6000_expand_new_builtin (tree exp, rtx target,
}
if (bif_is_no32bit (*bifaddr) && TARGET_32BIT)
- fatal_error (input_location,
- "%<%s%> is not supported in 32-bit mode",
- bifaddr->bifname);
+ {
+ error ("%<%s%> is not supported in 32-bit mode", bifaddr->bifname);
+ return const0_rtx;
+ }
if (bif_is_cpu (*bifaddr))
return new_cpu_expand_builtin (fcode, exp, target);
@@ -15763,6 +15763,8 @@ rs6000_expand_new_builtin (tree exp, rtx target,
{
if (fcode == RS6000_BIF_MFTB)
icode = CODE_FOR_rs6000_mftb_si;
+ else if (fcode == RS6000_BIF_BPERMD)
+ icode = CODE_FOR_bpermd_si;
else
gcc_unreachable ();
}
@@ -16477,6 +16479,29 @@ rs6000_init_builtins (void)
fprintf (stderr, "\nEnd autogenerated built-in functions.\n\n\n");
}
+ if (TARGET_XCOFF)
+ {
+ /* AIX libm provides clog as __clog. */
+ if ((tdecl = builtin_decl_explicit (BUILT_IN_CLOG)) != NULL_TREE)
+ set_user_assembler_name (tdecl, "__clog");
+
+ /* When long double is 64 bit, some long double builtins of libc
+ functions (like __builtin_frexpl) must call the double version
+ (frexp) not the long double version (frexpl) that expects a 128 bit
+ argument. */
+ if (! TARGET_LONG_DOUBLE_128)
+ {
+ if ((tdecl = builtin_decl_explicit (BUILT_IN_FMODL)) != NULL_TREE)
+ set_user_assembler_name (tdecl, "fmod");
+ if ((tdecl = builtin_decl_explicit (BUILT_IN_FREXPL)) != NULL_TREE)
+ set_user_assembler_name (tdecl, "frexp");
+ if ((tdecl = builtin_decl_explicit (BUILT_IN_LDEXPL)) != NULL_TREE)
+ set_user_assembler_name (tdecl, "ldexp");
+ if ((tdecl = builtin_decl_explicit (BUILT_IN_MODFL)) != NULL_TREE)
+ set_user_assembler_name (tdecl, "modf");
+ }
+ }
+
if (new_builtins_are_live)
{
altivec_builtin_mask_for_load
@@ -16576,29 +16601,6 @@ rs6000_init_builtins (void)
def_builtin ("__builtin_cpu_is", ftype, RS6000_BUILTIN_CPU_IS);
def_builtin ("__builtin_cpu_supports", ftype, RS6000_BUILTIN_CPU_SUPPORTS);
- if (TARGET_XCOFF)
- {
- /* AIX libm provides clog as __clog. */
- if ((tdecl = builtin_decl_explicit (BUILT_IN_CLOG)) != NULL_TREE)
- set_user_assembler_name (tdecl, "__clog");
-
- /* When long double is 64 bit, some long double builtins of libc
- functions (like __builtin_frexpl) must call the double version
- (frexp) not the long double version (frexpl) that expects a 128 bit
- argument. */
- if (! TARGET_LONG_DOUBLE_128)
- {
- if ((tdecl = builtin_decl_explicit (BUILT_IN_FMODL)) != NULL_TREE)
- set_user_assembler_name (tdecl, "fmod");
- if ((tdecl = builtin_decl_explicit (BUILT_IN_FREXPL)) != NULL_TREE)
- set_user_assembler_name (tdecl, "frexp");
- if ((tdecl = builtin_decl_explicit (BUILT_IN_LDEXPL)) != NULL_TREE)
- set_user_assembler_name (tdecl, "ldexp");
- if ((tdecl = builtin_decl_explicit (BUILT_IN_MODFL)) != NULL_TREE)
- set_user_assembler_name (tdecl, "modf");
- }
- }
-
#ifdef SUBTARGET_INIT_BUILTINS
SUBTARGET_INIT_BUILTINS;
#endif
@@ -16624,12 +16626,6 @@ rs6000_new_builtin_decl (unsigned code, bool /* initialize_p */)
if (fcode >= RS6000_OVLD_MAX)
return error_mark_node;
- if (!rs6000_new_builtin_is_supported (fcode))
- {
- rs6000_invalid_new_builtin (fcode);
- return error_mark_node;
- }
-
return rs6000_builtin_decls_x[code];
}
diff --git a/gcc/config/rs6000/rs6000-gen-builtins.c b/gcc/config/rs6000/rs6000-gen-builtins.c
index 4ce83bd..d2e9c4c 100644
--- a/gcc/config/rs6000/rs6000-gen-builtins.c
+++ b/gcc/config/rs6000/rs6000-gen-builtins.c
@@ -2845,7 +2845,7 @@ write_init_file (void)
fprintf (init_file, "#include \"rs6000-builtins.h\"\n");
fprintf (init_file, "\n");
- fprintf (init_file, "int new_builtins_are_live = 0;\n\n");
+ fprintf (init_file, "int new_builtins_are_live = 1;\n\n");
fprintf (init_file, "tree rs6000_builtin_decls_x[RS6000_OVLD_MAX];\n\n");
diff --git a/gcc/config/rs6000/rs6000-internal.h b/gcc/config/rs6000/rs6000-internal.h
index 88cf9bd..a880fd3 100644
--- a/gcc/config/rs6000/rs6000-internal.h
+++ b/gcc/config/rs6000/rs6000-internal.h
@@ -22,6 +22,8 @@
#ifndef GCC_RS6000_INTERNAL_H
#define GCC_RS6000_INTERNAL_H
+#include "rs6000-builtins.h"
+
/* Structure used to define the rs6000 stack */
typedef struct rs6000_stack {
int reload_completed; /* stack info won't change from here on */
@@ -140,6 +142,7 @@ extern void rs6000_output_mi_thunk (FILE *file,
extern bool rs6000_output_addr_const_extra (FILE *file, rtx x);
extern bool rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi);
extern tree rs6000_build_builtin_va_list (void);
+extern void rs6000_invalid_new_builtin (rs6000_gen_builtins fncode);
extern void rs6000_va_start (tree valist, rtx nextarg);
extern tree rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
gimple_seq *post_p);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 289c1b3..5e12998 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -78,7 +78,6 @@
#include "case-cfn-macros.h"
#include "ppc-auxv.h"
#include "rs6000-internal.h"
-#include "rs6000-builtins.h"
#include "opts.h"
/* This file should be included last. */
@@ -3478,6 +3477,10 @@ rs6000_override_options_after_change (void)
}
else if (!OPTION_SET_P (flag_cunroll_grow_size))
flag_cunroll_grow_size = flag_peel_loops || optimize >= 3;
+
+ /* If we are inserting ROP-protect instructions, disable shrink wrap. */
+ if (rs6000_rop_protect)
+ flag_shrink_wrap = 0;
}
#ifdef TARGET_USES_LINUX64_OPT
@@ -4042,10 +4045,6 @@ rs6000_option_override_internal (bool global_init_p)
&& ((rs6000_isa_flags_explicit & OPTION_MASK_QUAD_MEMORY_ATOMIC) == 0))
rs6000_isa_flags |= OPTION_MASK_QUAD_MEMORY_ATOMIC;
- /* If we are inserting ROP-protect instructions, disable shrink wrap. */
- if (rs6000_rop_protect)
- flag_shrink_wrap = 0;
-
/* If we can shrink-wrap the TOC register save separately, then use
-msave-toc-indirect unless explicitly disabled. */
if ((rs6000_isa_flags_explicit & OPTION_MASK_SAVE_TOC_INDIRECT) == 0
@@ -20600,7 +20599,7 @@ rs6000_ms_bitfield_layout_p (const_tree record_type)
/* A get_unnamed_section callback, used for switching to toc_section. */
static void
-rs6000_elf_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED)
+rs6000_elf_output_toc_section_asm_op (const char *data ATTRIBUTE_UNUSED)
{
if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
&& TARGET_MINIMAL_TOC)
@@ -21304,35 +21303,39 @@ rs6000_xcoff_asm_globalize_label (FILE *stream, const char *name)
points to the section string variable. */
static void
-rs6000_xcoff_output_readonly_section_asm_op (const void *directive)
+rs6000_xcoff_output_readonly_section_asm_op (const char *directive)
{
fprintf (asm_out_file, "\t.csect %s[RO],%s\n",
- *(const char *const *) directive,
+ directive
+ ? xcoff_private_rodata_section_name
+ : xcoff_read_only_section_name,
XCOFF_CSECT_DEFAULT_ALIGNMENT_STR);
}
/* Likewise for read-write sections. */
static void
-rs6000_xcoff_output_readwrite_section_asm_op (const void *directive)
+rs6000_xcoff_output_readwrite_section_asm_op (const char *)
{
fprintf (asm_out_file, "\t.csect %s[RW],%s\n",
- *(const char *const *) directive,
+ xcoff_private_data_section_name,
XCOFF_CSECT_DEFAULT_ALIGNMENT_STR);
}
static void
-rs6000_xcoff_output_tls_section_asm_op (const void *directive)
+rs6000_xcoff_output_tls_section_asm_op (const char *directive)
{
fprintf (asm_out_file, "\t.csect %s[TL],%s\n",
- *(const char *const *) directive,
+ directive
+ ? xcoff_private_data_section_name
+ : xcoff_tls_data_section_name,
XCOFF_CSECT_DEFAULT_ALIGNMENT_STR);
}
/* A get_unnamed_section callback, used for switching to toc_section. */
static void
-rs6000_xcoff_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED)
+rs6000_xcoff_output_toc_section_asm_op (const char *data ATTRIBUTE_UNUSED)
{
if (TARGET_MINIMAL_TOC)
{
@@ -21359,26 +21362,26 @@ rs6000_xcoff_asm_init_sections (void)
{
read_only_data_section
= get_unnamed_section (0, rs6000_xcoff_output_readonly_section_asm_op,
- &xcoff_read_only_section_name);
+ NULL);
private_data_section
= get_unnamed_section (SECTION_WRITE,
rs6000_xcoff_output_readwrite_section_asm_op,
- &xcoff_private_data_section_name);
+ NULL);
read_only_private_data_section
= get_unnamed_section (0, rs6000_xcoff_output_readonly_section_asm_op,
- &xcoff_private_rodata_section_name);
+ "");
tls_data_section
= get_unnamed_section (SECTION_TLS,
rs6000_xcoff_output_tls_section_asm_op,
- &xcoff_tls_data_section_name);
+ NULL);
tls_private_data_section
= get_unnamed_section (SECTION_TLS,
rs6000_xcoff_output_tls_section_asm_op,
- &xcoff_private_data_section_name);
+ "");
toc_section
= get_unnamed_section (0, rs6000_xcoff_output_toc_section_asm_op, NULL);
@@ -22742,7 +22745,7 @@ rs6000_builtin_reciprocal (tree fndecl)
{
switch (DECL_MD_FUNCTION_CODE (fndecl))
{
- case VSX_BUILTIN_XVSQRTDP:
+ case RS6000_BIF_XVSQRTDP:
if (!RS6000_RECIP_AUTO_RSQRTE_P (V2DFmode))
return NULL_TREE;
@@ -22750,7 +22753,7 @@ rs6000_builtin_reciprocal (tree fndecl)
return rs6000_builtin_decls_x[RS6000_BIF_RSQRT_2DF];
return rs6000_builtin_decls[VSX_BUILTIN_RSQRT_2DF];
- case VSX_BUILTIN_XVSQRTSP:
+ case RS6000_BIF_XVSQRTSP:
if (!RS6000_RECIP_AUTO_RSQRTE_P (V4SFmode))
return NULL_TREE;
diff --git a/gcc/config/rs6000/xmmintrin.h b/gcc/config/rs6000/xmmintrin.h
index 4c093fd..31d26ad 100644
--- a/gcc/config/rs6000/xmmintrin.h
+++ b/gcc/config/rs6000/xmmintrin.h
@@ -1353,7 +1353,7 @@ extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artifici
_mm_movemask_ps (__m128 __A)
{
#ifdef _ARCH_PWR10
- return vec_extractm ((vector unsigned int) __A);
+ return vec_extractm ((__vector unsigned int) __A);
#else
__vector unsigned long long result;
static const __vector unsigned int perm_mask =
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 510e7f5..3a22f78 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -15926,7 +15926,7 @@ s390_valid_target_attribute_inner_p (tree args,
new_opts_set->x_target_flags |= mask;
}
- else if (cl_options[opt].var_type == CLVC_BOOLEAN)
+ else if (cl_options[opt].var_type == CLVC_INTEGER)
{
int value;
diff --git a/gcc/config/vxworks.h b/gcc/config/vxworks.h
index e41f16a..bddf2c3 100644
--- a/gcc/config/vxworks.h
+++ b/gcc/config/vxworks.h
@@ -306,4 +306,4 @@ extern void vxworks_emit_call_builtin___clear_cache (rtx begin, rtx end);
further incremental LTO linking. We do not do repeated incremental linking
so silence the warning (instead of passing -flinker-output=nolto-rel). */
#undef LTO_PLUGIN_SPEC
-#define LTO_PLUGIN_SPEC "%{!mrtp:-plugin-opt=-linker-output-auto-notlo-rel}"
+#define LTO_PLUGIN_SPEC "%{!mrtp:-plugin-opt=-linker-output-auto-nolto-rel}"
diff --git a/gcc/configure b/gcc/configure
index a5160da..de20e5d 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -1831,8 +1831,8 @@ Optional Packages:
Root for documentation URLs
--with-changes-root-url=URL
Root for GCC changes URLs
- --with-multilib-list select multilibs (AArch64, ARM, OR1K, RISC-V, SH and
- x86-64 only)
+ --with-multilib-list select multilibs (AArch64, ARM, AVR, 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.
@@ -31381,6 +31381,9 @@ fi
# Check if the target LIBC handles PT_GNU_STACK.
gcc_cv_libc_gnustack=unknown
case "$target" in
+ mips*-*-linux-musl*)
+ gcc_cv_libc_gnustack=yes
+ ;;
mips*-*-linux*)
if test $glibc_version_major -gt 2 \
diff --git a/gcc/configure.ac b/gcc/configure.ac
index df4d2d8..2b4914b 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1171,7 +1171,7 @@ if test "x$enable_offload_defaulted" = xyes; then
fi
AC_ARG_WITH(multilib-list,
-[AS_HELP_STRING([--with-multilib-list], [select multilibs (AArch64, ARM, OR1K, RISC-V, SH and x86-64 only)])],
+[AS_HELP_STRING([--with-multilib-list], [select multilibs (AArch64, ARM, AVR, OR1K, RISC-V, SH and x86-64 only)])],
:,
with_multilib_list=default)
@@ -6963,6 +6963,9 @@ fi
# Check if the target LIBC handles PT_GNU_STACK.
gcc_cv_libc_gnustack=unknown
case "$target" in
+ mips*-*-linux-musl*)
+ gcc_cv_libc_gnustack=yes
+ ;;
mips*-*-linux*)
GCC_GLIBC_VERSION_GTE_IFELSE([2], [31], [gcc_cv_libc_gnustack=yes], )
;;
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 4daa3f9..7f8b532 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "profile.h"
#include "diagnostic.h"
#include "varasm.h"
+#include "file-prefix-map.h"
#include "gcov-io.c"
@@ -646,7 +647,7 @@ coverage_begin_function (unsigned lineno_checksum, unsigned cfg_checksum)
gcov_write_unsigned (DECL_ARTIFICIAL (current_function_decl)
&& !DECL_FUNCTION_VERSIONED (current_function_decl)
&& !DECL_LAMBDA_FUNCTION_P (current_function_decl));
- gcov_write_filename (startloc.file);
+ gcov_write_filename (remap_profile_filename (startloc.file));
gcov_write_unsigned (startloc.line);
gcov_write_unsigned (startloc.column);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 72e099a..9a8e7fb 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,95 @@
+2021-12-08 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * parser.c (struct omp_dim): New struct type for use inside
+ cp_parser_omp_var_list_no_open.
+ (cp_parser_omp_var_list_no_open): Allow multiple levels of array and
+ component accesses in array section base-pointer expression.
+ (cp_parser_omp_all_clauses): Set 'allow_deref' to true in call to
+ cp_parser_omp_var_list for to/from clauses.
+ * semantics.c (handle_omp_array_sections_1): Extend allowed range
+ of base-pointer expressions involving INDIRECT/MEM/ARRAY_REF and
+ POINTER_PLUS_EXPR.
+ (handle_omp_array_sections): Adjust pointer map generation of
+ references.
+ (finish_omp_clauses): Extend allowed ranged of expressions
+ involving INDIRECT/MEM/ARRAY_REF and POINTER_PLUS_EXPR.
+
+2021-12-08 Chung-Lin Tang <cltang@codesourcery.com>
+
+ PR middle-end/92120
+ * cp-tree.h (finish_omp_target): New declaration.
+ (finish_omp_target_clauses): Likewise.
+ * parser.c (cp_parser_omp_clause_map): Adjust call to
+ cp_parser_omp_var_list_no_open to set 'allow_deref' argument to true.
+ (cp_parser_omp_target): Factor out code, adjust into calls to new
+ function finish_omp_target.
+ * pt.c (tsubst_expr): Add call to finish_omp_target_clauses for
+ OMP_TARGET case.
+ * semantics.c (handle_omp_array_sections_1): Add handling to create
+ 'this->member' from 'member' FIELD_DECL. Remove case of rejecting
+ 'this' when not in declare simd.
+ (handle_omp_array_sections): Likewise.
+ (finish_omp_clauses): Likewise. Adjust to allow 'this[]' in OpenMP
+ map clauses. Handle 'A->member' case in map clauses. Remove case of
+ rejecting 'this' when not in declare simd.
+ (struct omp_target_walk_data): New struct for walking over
+ target-directive tree body.
+ (finish_omp_target_clauses_r): New function for tree walk.
+ (finish_omp_target_clauses): New function.
+ (finish_omp_target): New function.
+
+2021-12-07 Marek Polacek <polacek@redhat.com>
+
+ PR c++/95009
+ * typeck.c (is_bitfield_expr_with_lowered_type) <case MODIFY_EXPR>:
+ Handle UNARY_PLUS_EXPR, NEGATE_EXPR, NON_LVALUE_EXPR, BIT_NOT_EXPR,
+ P*CREMENT_EXPR too.
+
+2021-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ * cp-tree.h (is_byte_access_type_not_plain_char): Declare.
+ * tree.c (is_byte_access_type_not_plain_char): New function.
+ * constexpr.c (clear_uchar_or_std_byte_in_mask): New function.
+ (cxx_eval_bit_cast): Don't error about padding bits if target
+ type is unsigned char or std::byte, instead return no clearing
+ ctor. Use clear_uchar_or_std_byte_in_mask.
+
+2021-12-03 Jason Merrill <jason@redhat.com>
+
+ * error.c (current_dump_scope): New variable.
+ (dump_scope): Check it.
+ (dump_function_decl): Set it.
+
+2021-12-03 Marek Polacek <polacek@redhat.com>
+
+ PR c++/103403
+ * cp-gimplify.c (cp_fold): Don't recurse if maybe_undo_parenthesized_ref
+ doesn't change its argument.
+ * pt.c (do_auto_deduction): Don't strip REFERENCE_REF_P trees if they
+ are REF_PARENTHESIZED_P. Use stripped_init when checking for
+ id-expression.
+ * semantics.c (force_paren_expr): Set REF_PARENTHESIZED_P on
+ REFERENCE_REF_P trees too.
+ (maybe_undo_parenthesized_ref): Remove dead code.
+
+2021-12-02 Marek Polacek <polacek@redhat.com>
+
+ PR c++/94490
+ * pt.c (expand_integer_pack): Call
+ instantiate_non_dependent_expr_sfinae.
+
+2021-12-02 Marek Polacek <polacek@redhat.com>
+
+ PR c++/103408
+ * cxx-pretty-print.c (pp_cxx_parameter_mapping): Print "<unnamed>"
+ rather than crash on an unnamed template parameter.
+
+2021-12-01 Jason Merrill <jason@redhat.com>
+
+ PR c++/103310
+ * constexpr.c (cxx_eval_binary_expression): Use
+ fold_binary_initializer_loc if manifestly cxeval.
+
2021-11-30 Jason Merrill <jason@redhat.com>
* cp-gimplify.c (genericize_if_stmt): Always build a COND_EXPR.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index d66a565..d851fae 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3366,7 +3366,14 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
}
if (r == NULL_TREE)
- r = fold_binary_loc (loc, code, type, lhs, rhs);
+ {
+ if (ctx->manifestly_const_eval
+ && (flag_constexpr_fp_except
+ || TREE_CODE (type) != REAL_TYPE))
+ r = fold_binary_initializer_loc (loc, code, type, lhs, rhs);
+ else
+ r = fold_binary_loc (loc, code, type, lhs, rhs);
+ }
if (r == NULL_TREE
&& (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
@@ -4268,6 +4275,118 @@ check_bit_cast_type (const constexpr_ctx *ctx, location_t loc, tree type,
return false;
}
+/* Helper function for cxx_eval_bit_cast. For unsigned char or
+ std::byte members of CONSTRUCTOR (recursively) if they contain
+ some indeterminate bits (as set in MASK), remove the ctor elts,
+ mark the CONSTRUCTOR as CONSTRUCTOR_NO_CLEARING and clear the
+ bits in MASK. */
+
+static void
+clear_uchar_or_std_byte_in_mask (location_t loc, tree t, unsigned char *mask)
+{
+ if (TREE_CODE (t) != CONSTRUCTOR)
+ return;
+
+ unsigned i, j = 0;
+ tree index, value;
+ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), i, index, value)
+ {
+ tree type = TREE_TYPE (value);
+ if (TREE_CODE (TREE_TYPE (t)) != ARRAY_TYPE
+ && DECL_BIT_FIELD_TYPE (index) != NULL_TREE)
+ {
+ if (is_byte_access_type_not_plain_char (DECL_BIT_FIELD_TYPE (index)))
+ {
+ HOST_WIDE_INT fldsz = TYPE_PRECISION (TREE_TYPE (index));
+ gcc_assert (fldsz != 0);
+ HOST_WIDE_INT pos = int_byte_position (index);
+ HOST_WIDE_INT bpos
+ = tree_to_uhwi (DECL_FIELD_BIT_OFFSET (index));
+ bpos %= BITS_PER_UNIT;
+ HOST_WIDE_INT end
+ = ROUND_UP (bpos + fldsz, BITS_PER_UNIT) / BITS_PER_UNIT;
+ gcc_assert (end == 1 || end == 2);
+ unsigned char *p = mask + pos;
+ unsigned char mask_save[2];
+ mask_save[0] = mask[pos];
+ mask_save[1] = end == 2 ? mask[pos + 1] : 0;
+ if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
+ sorry_at (loc, "PDP11 bit-field handling unsupported"
+ " in %qs", "__builtin_bit_cast");
+ else if (BYTES_BIG_ENDIAN)
+ {
+ /* Big endian. */
+ if (bpos + fldsz <= BITS_PER_UNIT)
+ *p &= ~(((1 << fldsz) - 1)
+ << (BITS_PER_UNIT - bpos - fldsz));
+ else
+ {
+ gcc_assert (bpos);
+ *p &= ~(((1U << BITS_PER_UNIT) - 1) >> bpos);
+ p++;
+ fldsz -= BITS_PER_UNIT - bpos;
+ gcc_assert (fldsz && fldsz < BITS_PER_UNIT);
+ *p &= ((1U << BITS_PER_UNIT) - 1) >> fldsz;
+ }
+ }
+ else
+ {
+ /* Little endian. */
+ if (bpos + fldsz <= BITS_PER_UNIT)
+ *p &= ~(((1 << fldsz) - 1) << bpos);
+ else
+ {
+ gcc_assert (bpos);
+ *p &= ~(((1 << BITS_PER_UNIT) - 1) << bpos);
+ p++;
+ fldsz -= BITS_PER_UNIT - bpos;
+ gcc_assert (fldsz && fldsz < BITS_PER_UNIT);
+ *p &= ~((1 << fldsz) - 1);
+ }
+ }
+ if (mask_save[0] != mask[pos]
+ || (end == 2 && mask_save[1] != mask[pos + 1]))
+ {
+ CONSTRUCTOR_NO_CLEARING (t) = 1;
+ continue;
+ }
+ }
+ }
+ else if (is_byte_access_type_not_plain_char (type))
+ {
+ HOST_WIDE_INT pos;
+ if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
+ pos = tree_to_shwi (index);
+ else
+ pos = int_byte_position (index);
+ if (mask[pos])
+ {
+ CONSTRUCTOR_NO_CLEARING (t) = 1;
+ mask[pos] = 0;
+ continue;
+ }
+ }
+ if (TREE_CODE (value) == CONSTRUCTOR)
+ {
+ HOST_WIDE_INT pos;
+ if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
+ pos = tree_to_shwi (index)
+ * tree_to_shwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (t))));
+ else
+ pos = int_byte_position (index);
+ clear_uchar_or_std_byte_in_mask (loc, value, mask + pos);
+ }
+ if (i != j)
+ {
+ CONSTRUCTOR_ELT (t, j)->index = index;
+ CONSTRUCTOR_ELT (t, j)->value = value;
+ }
+ ++j;
+ }
+ if (CONSTRUCTOR_NELTS (t) != j)
+ vec_safe_truncate (CONSTRUCTOR_ELTS (t), j);
+}
+
/* Subroutine of cxx_eval_constant_expression.
Attempt to evaluate a BIT_CAST_EXPR. */
@@ -4344,12 +4463,27 @@ cxx_eval_bit_cast (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
tree r = NULL_TREE;
if (can_native_interpret_type_p (TREE_TYPE (t)))
- r = native_interpret_expr (TREE_TYPE (t), ptr, len);
+ {
+ r = native_interpret_expr (TREE_TYPE (t), ptr, len);
+ if (is_byte_access_type_not_plain_char (TREE_TYPE (t)))
+ {
+ gcc_assert (len == 1);
+ if (mask[0])
+ {
+ memset (mask, 0, len);
+ r = build_constructor (TREE_TYPE (r), NULL);
+ CONSTRUCTOR_NO_CLEARING (r) = 1;
+ }
+ }
+ }
else if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE)
{
r = native_interpret_aggregate (TREE_TYPE (t), ptr, 0, len);
if (r != NULL_TREE)
- clear_type_padding_in_mask (TREE_TYPE (t), mask);
+ {
+ clear_type_padding_in_mask (TREE_TYPE (t), mask);
+ clear_uchar_or_std_byte_in_mask (loc, r, mask);
+ }
}
if (r != NULL_TREE)
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 0a002db..e3ede02 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -2421,7 +2421,8 @@ cp_fold (tree x)
if (REF_PARENTHESIZED_P (x))
{
tree p = maybe_undo_parenthesized_ref (x);
- return cp_fold (p);
+ if (p != x)
+ return cp_fold (p);
}
goto unary;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1ee2c57..b1c3bc5 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7671,6 +7671,8 @@ extern tree start_lambda_function (tree fn, tree lambda_expr);
extern void finish_lambda_function (tree body);
extern bool regenerated_lambda_fn_p (tree);
extern tree most_general_lambda (tree);
+extern tree finish_omp_target (location_t, tree, tree, bool);
+extern void finish_omp_target_clauses (location_t, tree, tree *);
/* in tree.c */
extern int cp_tree_operand_length (const_tree);
@@ -7791,6 +7793,7 @@ extern tree build_dummy_object (tree);
extern tree maybe_dummy_object (tree, tree *);
extern bool is_dummy_object (const_tree);
extern bool is_byte_access_type (tree);
+extern bool is_byte_access_type_not_plain_char (tree);
extern const struct attribute_spec cxx_attribute_table[];
extern tree make_ptrmem_cst (tree, tree);
extern tree cp_build_type_attribute_variant (tree, tree);
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index 25cabfe..3ea357d 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -2891,8 +2891,10 @@ pp_cxx_parameter_mapping (cxx_pretty_printer *pp, tree map)
if (TYPE_P (parm))
pp->type_id (parm);
+ else if (tree name = DECL_NAME (TEMPLATE_PARM_DECL (parm)))
+ pp_cxx_tree_identifier (pp, name);
else
- pp_cxx_tree_identifier (pp, DECL_NAME (TEMPLATE_PARM_DECL (parm)));
+ pp->translate_string ("<unnamed>");
pp_cxx_whitespace (pp);
pp_equal (pp);
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 98c1f0e..daea3b3 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -211,6 +211,10 @@ dump_module_suffix (cxx_pretty_printer *pp, tree decl)
}
}
+/* The scope of the declaration we're currently printing, to avoid redundantly
+ dumping the same scope on parameter types. */
+static tree current_dump_scope;
+
/* Dump a scope, if deemed necessary. */
static void
@@ -218,7 +222,7 @@ dump_scope (cxx_pretty_printer *pp, tree scope, int flags)
{
int f = flags & (TFF_SCOPE | TFF_CHASE_TYPEDEF);
- if (scope == NULL_TREE)
+ if (scope == NULL_TREE || scope == current_dump_scope)
return;
/* Enum values within an unscoped enum will be CONST_DECL with an
@@ -1756,6 +1760,10 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags)
else
dump_scope (pp, CP_DECL_CONTEXT (t), flags);
+ /* Name lookup for the rest of the function declarator is implicitly in the
+ scope of the function, so avoid printing redundant scope qualifiers. */
+ auto cds = make_temp_override (current_dump_scope, CP_DECL_CONTEXT (t));
+
dump_function_name (pp, t, dump_function_name_flags);
if (!(flags & TFF_NO_FUNCTION_ARGUMENTS))
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 55e6a1a..6f273bf 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -36406,11 +36406,22 @@ check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
The optional ALLOW_DEREF argument is true if list items can use the deref
(->) operator. */
+struct omp_dim
+{
+ tree low_bound, length;
+ location_t loc;
+ bool no_colon;
+ omp_dim (tree lb, tree len, location_t lo, bool nc)
+ : low_bound (lb), length (len), loc (lo), no_colon (nc) {}
+};
+
static tree
cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
tree list, bool *colon,
bool allow_deref = false)
{
+ auto_vec<omp_dim> dims;
+ bool array_section_p;
cp_token *token;
bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
if (colon)
@@ -36491,6 +36502,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
case OMP_CLAUSE_MAP:
case OMP_CLAUSE_FROM:
case OMP_CLAUSE_TO:
+ start_component_ref:
while (cp_lexer_next_token_is (parser->lexer, CPP_DOT)
|| (allow_deref
&& cp_lexer_next_token_is (parser->lexer, CPP_DEREF)))
@@ -36514,14 +36526,19 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_IN_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
+ array_section_p = false;
+ dims.truncate (0);
while (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
{
+ location_t loc = UNKNOWN_LOCATION;
tree low_bound = NULL_TREE, length = NULL_TREE;
+ bool no_colon = false;
parser->colon_corrects_to_scope_p = false;
cp_lexer_consume_token (parser->lexer);
if (!cp_lexer_next_token_is (parser->lexer, CPP_COLON))
{
+ loc = cp_lexer_peek_token (parser->lexer)->location;
low_bound = cp_parser_expression (parser);
/* Later handling is not prepared to see through these. */
gcc_checking_assert (!location_wrapper_p (low_bound));
@@ -36530,7 +36547,10 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
parser->colon_corrects_to_scope_p
= saved_colon_corrects_to_scope_p;
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_SQUARE))
- length = integer_one_node;
+ {
+ length = integer_one_node;
+ no_colon = true;
+ }
else
{
/* Look for `:'. */
@@ -36543,6 +36563,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
}
if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
cp_parser_commit_to_tentative_parse (parser);
+ else
+ array_section_p = true;
if (!cp_lexer_next_token_is (parser->lexer,
CPP_CLOSE_SQUARE))
{
@@ -36561,8 +36583,30 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
goto skip_comma;
}
- decl = tree_cons (low_bound, length, decl);
+ dims.safe_push (omp_dim (low_bound, length, loc, no_colon));
+ }
+
+ if ((kind == OMP_CLAUSE_MAP
+ || kind == OMP_CLAUSE_FROM
+ || kind == OMP_CLAUSE_TO)
+ && !array_section_p
+ && (cp_lexer_next_token_is (parser->lexer, CPP_DOT)
+ || (allow_deref
+ && cp_lexer_next_token_is (parser->lexer,
+ CPP_DEREF))))
+ {
+ for (unsigned i = 0; i < dims.length (); i++)
+ {
+ gcc_assert (dims[i].length == integer_one_node);
+ decl = build_array_ref (dims[i].loc,
+ decl, dims[i].low_bound);
+ }
+ goto start_component_ref;
}
+ else
+ for (unsigned i = 0; i < dims.length (); i++)
+ decl = tree_cons (dims[i].low_bound, dims[i].length, decl);
+
break;
default:
break;
@@ -39315,7 +39359,7 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list)
}
nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_MAP, list,
- NULL);
+ NULL, true);
for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
OMP_CLAUSE_SET_MAP_KIND (c, kind);
@@ -40064,11 +40108,13 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_TO_DECLARE,
clauses);
else
- clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_TO, clauses);
+ clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_TO, clauses,
+ true);
c_name = "to";
break;
case PRAGMA_OMP_CLAUSE_FROM:
- clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FROM, clauses);
+ clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FROM, clauses,
+ true);
c_name = "from";
break;
case PRAGMA_OMP_CLAUSE_UNIFORM:
@@ -44105,8 +44151,6 @@ static bool
cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
enum pragma_context context, bool *if_p)
{
- tree *pc = NULL, stmt;
-
if (flag_openmp)
omp_requires_mask
= (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
@@ -44211,16 +44255,10 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
= cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = tc;
}
- tree stmt = make_node (OMP_TARGET);
- TREE_TYPE (stmt) = void_type_node;
- OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
- c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
- OMP_TARGET_BODY (stmt) = body;
- OMP_TARGET_COMBINED (stmt) = 1;
- SET_EXPR_LOCATION (stmt, pragma_tok->location);
- add_stmt (stmt);
- pc = &OMP_TARGET_CLAUSES (stmt);
- goto check_clauses;
+ c_omp_adjust_map_clauses (cclauses[C_OMP_CLAUSE_SPLIT_TARGET], true);
+ finish_omp_target (pragma_tok->location,
+ cclauses[C_OMP_CLAUSE_SPLIT_TARGET], body, true);
+ return true;
}
else if (!flag_openmp) /* flag_openmp_simd */
{
@@ -44255,13 +44293,10 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
return false;
}
- stmt = make_node (OMP_TARGET);
- TREE_TYPE (stmt) = void_type_node;
-
- OMP_TARGET_CLAUSES (stmt)
- = cp_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
- "#pragma omp target", pragma_tok, false);
- for (tree c = OMP_TARGET_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
+ tree clauses = cp_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
+ "#pragma omp target", pragma_tok,
+ false);
+ for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
{
tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
@@ -44270,45 +44305,13 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
OMP_CLAUSE_CHAIN (c) = nc;
}
- OMP_TARGET_CLAUSES (stmt)
- = finish_omp_clauses (OMP_TARGET_CLAUSES (stmt), C_ORT_OMP_TARGET);
- c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
+ clauses = finish_omp_clauses (clauses, C_ORT_OMP_TARGET);
- pc = &OMP_TARGET_CLAUSES (stmt);
+ c_omp_adjust_map_clauses (clauses, true);
keep_next_level (true);
- OMP_TARGET_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p);
-
- SET_EXPR_LOCATION (stmt, pragma_tok->location);
- add_stmt (stmt);
+ tree body = cp_parser_omp_structured_block (parser, if_p);
-check_clauses:
- while (*pc)
- {
- if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
- switch (OMP_CLAUSE_MAP_KIND (*pc))
- {
- case GOMP_MAP_TO:
- case GOMP_MAP_ALWAYS_TO:
- case GOMP_MAP_FROM:
- case GOMP_MAP_ALWAYS_FROM:
- case GOMP_MAP_TOFROM:
- case GOMP_MAP_ALWAYS_TOFROM:
- case GOMP_MAP_ALLOC:
- case GOMP_MAP_FIRSTPRIVATE_POINTER:
- case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
- case GOMP_MAP_ALWAYS_POINTER:
- case GOMP_MAP_ATTACH_DETACH:
- break;
- default:
- error_at (OMP_CLAUSE_LOCATION (*pc),
- "%<#pragma omp target%> with map-type other "
- "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
- "on %<map%> clause");
- *pc = OMP_CLAUSE_CHAIN (*pc);
- continue;
- }
- pc = &OMP_CLAUSE_CHAIN (*pc);
- }
+ finish_omp_target (pragma_tok->location, clauses, body, false);
return true;
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f4b9d96..9834baf 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -3792,6 +3792,7 @@ expand_integer_pack (tree call, tree args, tsubst_flags_t complain,
}
else
{
+ hi = instantiate_non_dependent_expr_sfinae (hi, complain);
hi = cxx_constant_value (hi);
int len = valid_constant_size_p (hi) ? tree_to_shwi (hi) : -1;
@@ -18974,6 +18975,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
t = copy_node (t);
OMP_BODY (t) = stmt;
OMP_CLAUSES (t) = tmp;
+
+ if (TREE_CODE (t) == OMP_TARGET)
+ finish_omp_target_clauses (EXPR_LOCATION (t), OMP_BODY (t),
+ &OMP_CLAUSES (t));
+
if (TREE_CODE (t) == OMP_TARGET && OMP_TARGET_COMBINED (t))
{
tree teams = cp_walk_tree (&stmt, tsubst_find_omp_teams, NULL, NULL);
@@ -29888,13 +29894,18 @@ do_auto_deduction (tree type, tree init, tree auto_node,
}
else if (AUTO_IS_DECLTYPE (auto_node))
{
+ /* Figure out if INIT is an unparenthesized id-expression or an
+ unparenthesized class member access. */
tree stripped_init = tree_strip_any_location_wrapper (init);
- if (REFERENCE_REF_P (stripped_init))
+ /* We need to be able to tell '(r)' and 'r' apart (when it's of
+ reference type). Only the latter is an id-expression. */
+ if (REFERENCE_REF_P (stripped_init)
+ && !REF_PARENTHESIZED_P (stripped_init))
stripped_init = TREE_OPERAND (stripped_init, 0);
- bool id = (DECL_P (stripped_init)
- || ((TREE_CODE (init) == COMPONENT_REF
- || TREE_CODE (init) == SCOPE_REF)
- && !REF_PARENTHESIZED_P (init)));
+ const bool id = (DECL_P (stripped_init)
+ || ((TREE_CODE (stripped_init) == COMPONENT_REF
+ || TREE_CODE (stripped_init) == SCOPE_REF)
+ && !REF_PARENTHESIZED_P (stripped_init)));
tree deduced = finish_decltype_type (init, id, complain);
deduced = canonicalize_type_argument (deduced, complain);
if (deduced == error_mark_node)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index cd19564..cdf63c1 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2049,7 +2049,8 @@ force_paren_expr (tree expr, bool even_uneval)
return expr;
if (TREE_CODE (expr) == COMPONENT_REF
- || TREE_CODE (expr) == SCOPE_REF)
+ || TREE_CODE (expr) == SCOPE_REF
+ || REFERENCE_REF_P (expr))
REF_PARENTHESIZED_P (expr) = true;
else if (DECL_P (tree_strip_any_location_wrapper (expr)))
{
@@ -2072,19 +2073,8 @@ maybe_undo_parenthesized_ref (tree t)
if (cxx_dialect < cxx14)
return t;
- if (INDIRECT_REF_P (t) && REF_PARENTHESIZED_P (t))
- {
- t = TREE_OPERAND (t, 0);
- while (TREE_CODE (t) == NON_LVALUE_EXPR
- || TREE_CODE (t) == NOP_EXPR)
- t = TREE_OPERAND (t, 0);
-
- gcc_assert (TREE_CODE (t) == ADDR_EXPR
- || TREE_CODE (t) == STATIC_CAST_EXPR);
- t = TREE_OPERAND (t, 0);
- }
- else if ((TREE_CODE (t) == PAREN_EXPR || TREE_CODE (t) == VIEW_CONVERT_EXPR)
- && REF_PARENTHESIZED_P (t))
+ if ((TREE_CODE (t) == PAREN_EXPR || TREE_CODE (t) == VIEW_CONVERT_EXPR)
+ && REF_PARENTHESIZED_P (t))
t = TREE_OPERAND (t, 0);
return t;
@@ -5035,6 +5025,18 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
&& TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
t = TREE_OPERAND (t, 0);
ret = t;
+ while (TREE_CODE (t) == INDIRECT_REF)
+ {
+ t = TREE_OPERAND (t, 0);
+ STRIP_NOPS (t);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ }
+ while (TREE_CODE (t) == COMPOUND_EXPR)
+ {
+ t = TREE_OPERAND (t, 1);
+ STRIP_NOPS (t);
+ }
if (TREE_CODE (t) == COMPONENT_REF
&& (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO
@@ -5059,15 +5061,20 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
return error_mark_node;
}
t = TREE_OPERAND (t, 0);
- if (ort == C_ORT_ACC && TREE_CODE (t) == INDIRECT_REF)
- t = TREE_OPERAND (t, 0);
+ while (TREE_CODE (t) == MEM_REF
+ || TREE_CODE (t) == INDIRECT_REF
+ || TREE_CODE (t) == ARRAY_REF)
+ {
+ t = TREE_OPERAND (t, 0);
+ STRIP_NOPS (t);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ }
}
if (REFERENCE_REF_P (t))
t = TREE_OPERAND (t, 0);
}
- if (TREE_CODE (t) == FIELD_DECL
- && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY
- || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND))
+ if (TREE_CODE (t) == FIELD_DECL)
ret = finish_non_static_data_member (t, NULL_TREE, NULL_TREE);
else if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
{
@@ -5083,18 +5090,6 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
return error_mark_node;
}
- else if ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP
- && TREE_CODE (t) == PARM_DECL
- && DECL_ARTIFICIAL (t)
- && DECL_NAME (t) == this_identifier
- && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY
- && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
- {
- error_at (OMP_CLAUSE_LOCATION (c),
- "%<this%> allowed in OpenMP only in %<declare simd%>"
- " clauses");
- return error_mark_node;
- }
else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
&& VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
@@ -5357,15 +5352,25 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
return error_mark_node;
}
/* If there is a pointer type anywhere but in the very first
- array-section-subscript, the array section can't be contiguous. */
+ array-section-subscript, the array section could be non-contiguous. */
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
&& TREE_CODE (TREE_CHAIN (t)) == TREE_LIST)
{
- error_at (OMP_CLAUSE_LOCATION (c),
- "array section is not contiguous in %qs clause",
- omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
- return error_mark_node;
+ /* If any prior dimension has a non-one length, then deem this
+ array section as non-contiguous. */
+ for (tree d = TREE_CHAIN (t); TREE_CODE (d) == TREE_LIST;
+ d = TREE_CHAIN (d))
+ {
+ tree d_length = TREE_VALUE (d);
+ if (d_length == NULL_TREE || !integer_onep (d_length))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "array section is not contiguous in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ }
}
}
else
@@ -5609,6 +5614,8 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
}
OMP_CLAUSE_DECL (c) = first;
OMP_CLAUSE_SIZE (c) = size;
+ if (TREE_CODE (t) == FIELD_DECL)
+ t = finish_non_static_data_member (t, NULL_TREE, NULL_TREE);
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
|| (TREE_CODE (t) == COMPONENT_REF
&& TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE))
@@ -5634,16 +5641,37 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
default:
break;
}
+ bool reference_always_pointer = true;
tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
OMP_CLAUSE_MAP);
if (TREE_CODE (t) == COMPONENT_REF)
- OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
+ {
+ OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
+
+ if ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP
+ && TYPE_REF_P (TREE_TYPE (t)))
+ {
+ if (TREE_CODE (TREE_TYPE (TREE_TYPE (t))) == ARRAY_TYPE)
+ OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
+ else
+ t = convert_from_reference (t);
+
+ reference_always_pointer = false;
+ }
+ }
else if (REFERENCE_REF_P (t)
&& TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
{
- t = TREE_OPERAND (t, 0);
- gomp_map_kind k = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
- : GOMP_MAP_ALWAYS_POINTER;
+ gomp_map_kind k;
+ if ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP
+ && TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
+ k = GOMP_MAP_ATTACH_DETACH;
+ else
+ {
+ t = TREE_OPERAND (t, 0);
+ k = (ort == C_ORT_ACC
+ ? GOMP_MAP_ATTACH_DETACH : GOMP_MAP_ALWAYS_POINTER);
+ }
OMP_CLAUSE_SET_MAP_KIND (c2, k);
}
else
@@ -5667,8 +5695,10 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
OMP_CLAUSE_SIZE (c2) = t;
OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
OMP_CLAUSE_CHAIN (c) = c2;
+
ptr = OMP_CLAUSE_DECL (c2);
- if (OMP_CLAUSE_MAP_KIND (c2) != GOMP_MAP_FIRSTPRIVATE_POINTER
+ if (reference_always_pointer
+ && OMP_CLAUSE_MAP_KIND (c2) != GOMP_MAP_FIRSTPRIVATE_POINTER
&& TYPE_REF_P (TREE_TYPE (ptr))
&& INDIRECT_TYPE_P (TREE_TYPE (TREE_TYPE (ptr))))
{
@@ -6621,6 +6651,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bool order_seen = false;
bool schedule_seen = false;
bool oacc_async = false;
+ bool indir_component_ref_p = false;
tree last_iterators = NULL_TREE;
bool last_iterators_remove = false;
/* 1 if normal/task reduction has been seen, -1 if inscan reduction
@@ -7868,10 +7899,22 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
if (TREE_CODE (t) == COMPONENT_REF
&& TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
{
- while (TREE_CODE (t) == COMPONENT_REF)
- t = TREE_OPERAND (t, 0);
- if (REFERENCE_REF_P (t))
- t = TREE_OPERAND (t, 0);
+ do
+ {
+ t = TREE_OPERAND (t, 0);
+ if (REFERENCE_REF_P (t))
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == MEM_REF
+ || TREE_CODE (t) == INDIRECT_REF)
+ {
+ t = TREE_OPERAND (t, 0);
+ STRIP_NOPS (t);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ }
+ }
+ while (TREE_CODE (t) == COMPONENT_REF);
+
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
&& OMP_CLAUSE_MAP_IMPLICIT (c)
&& (bitmap_bit_p (&map_head, DECL_UID (t))
@@ -7942,11 +7985,34 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
&& TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
{
t = TREE_OPERAND (t, 0);
- OMP_CLAUSE_DECL (c) = t;
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH_DETACH)
+ OMP_CLAUSE_DECL (c) = t;
+ }
+ while (TREE_CODE (t) == INDIRECT_REF
+ || TREE_CODE (t) == ARRAY_REF)
+ {
+ t = TREE_OPERAND (t, 0);
+ STRIP_NOPS (t);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ }
+ while (TREE_CODE (t) == COMPOUND_EXPR)
+ {
+ t = TREE_OPERAND (t, 1);
+ STRIP_NOPS (t);
}
+ indir_component_ref_p = false;
if (TREE_CODE (t) == COMPONENT_REF
- && TREE_CODE (TREE_OPERAND (t, 0)) == INDIRECT_REF)
- t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
+ && (TREE_CODE (TREE_OPERAND (t, 0)) == INDIRECT_REF
+ || TREE_CODE (TREE_OPERAND (t, 0)) == ARRAY_REF))
+ {
+ t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
+ indir_component_ref_p = true;
+ STRIP_NOPS (t);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ }
if (TREE_CODE (t) == COMPONENT_REF
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_)
{
@@ -7980,6 +8046,24 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
}
t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == MEM_REF)
+ {
+ if (maybe_ne (mem_ref_offset (t), 0))
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "cannot dereference %qE in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ else
+ t = TREE_OPERAND (t, 0);
+ }
+ while (TREE_CODE (t) == MEM_REF
+ || TREE_CODE (t) == INDIRECT_REF
+ || TREE_CODE (t) == ARRAY_REF)
+ {
+ t = TREE_OPERAND (t, 0);
+ STRIP_NOPS (t);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ }
}
if (remove)
break;
@@ -7993,6 +8077,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
goto handle_map_references;
}
}
+ if (!processing_template_decl
+ && TREE_CODE (t) == FIELD_DECL)
+ {
+ OMP_CLAUSE_DECL (c) = finish_non_static_data_member (t, NULL_TREE,
+ NULL_TREE);
+ break;
+ }
if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
{
if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
@@ -8019,19 +8110,12 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
- else if (ort != C_ORT_ACC && t == current_class_ptr)
- {
- error_at (OMP_CLAUSE_LOCATION (c),
- "%<this%> allowed in OpenMP only in %<declare simd%>"
- " clauses");
- remove = true;
- break;
- }
else if (!processing_template_decl
&& !TYPE_REF_P (TREE_TYPE (t))
&& (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
|| (OMP_CLAUSE_MAP_KIND (c)
!= GOMP_MAP_FIRSTPRIVATE_POINTER))
+ && !indir_component_ref_p
&& !cxx_mark_addressable (t))
remove = true;
else if (!(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
@@ -8077,7 +8161,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
"%qD appears more than once in data clauses", t);
remove = true;
}
- else if (bitmap_bit_p (&map_head, DECL_UID (t)))
+ else if (bitmap_bit_p (&map_head, DECL_UID (t))
+ && !bitmap_bit_p (&map_field_head, DECL_UID (t)))
{
if (ort == C_ORT_ACC)
error_at (OMP_CLAUSE_LOCATION (c),
@@ -8124,8 +8209,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
else
{
bitmap_set_bit (&map_head, DECL_UID (t));
- if (t != OMP_CLAUSE_DECL (c)
- && TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
+
+ tree decl = OMP_CLAUSE_DECL (c);
+ if (t != decl
+ && (TREE_CODE (decl) == COMPONENT_REF
+ || (INDIRECT_REF_P (decl)
+ && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
+ && TYPE_REF_P (TREE_TYPE (TREE_OPERAND (decl, 0))))))
bitmap_set_bit (&map_field_head, DECL_UID (t));
}
handle_map_references:
@@ -8154,7 +8244,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
OMP_CLAUSE_MAP);
if (TREE_CODE (t) == COMPONENT_REF)
- OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
+ OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
else
OMP_CLAUSE_SET_MAP_KIND (c2,
GOMP_MAP_FIRSTPRIVATE_REFERENCE);
@@ -9187,6 +9277,533 @@ finish_omp_construct (enum tree_code code, tree body, tree clauses)
return add_stmt (stmt);
}
+/* Used to walk OpenMP target directive body. */
+
+struct omp_target_walk_data
+{
+ /* Holds the 'this' expression found in current function. */
+ tree current_object;
+
+ /* True if the 'this' expression was accessed in the target body. */
+ bool this_expr_accessed;
+
+ /* For non-static functions, record which pointer-typed members were
+ accessed, and the whole expression. */
+ hash_map<tree, tree> ptr_members_accessed;
+
+ /* Record which lambda objects were accessed in target body. */
+ hash_set<tree> lambda_objects_accessed;
+
+ /* For lambda functions, the __closure object expression of the current
+ function, and the set of captured variables accessed in target body. */
+ tree current_closure;
+ hash_set<tree> closure_vars_accessed;
+
+ /* Local variables declared inside a BIND_EXPR, used to filter out such
+ variables when recording lambda_objects_accessed. */
+ hash_set<tree> local_decls;
+};
+
+/* Helper function of finish_omp_target_clauses, called via
+ cp_walk_tree_without_duplicates. Traverse body of OpenMP target
+ directive *TP, and fill out omp_target_walk_data passed in *PTR. */
+
+static tree
+finish_omp_target_clauses_r (tree *tp, int *walk_subtrees, void *ptr)
+{
+ tree t = *tp;
+ struct omp_target_walk_data *data = (struct omp_target_walk_data *) ptr;
+ tree current_object = data->current_object;
+ tree current_closure = data->current_closure;
+
+ /* References inside of these expression codes shouldn't incur any
+ form of mapping, so return early. */
+ if (TREE_CODE (t) == SIZEOF_EXPR
+ || TREE_CODE (t) == ALIGNOF_EXPR)
+ {
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+
+ if (current_object)
+ {
+ tree this_expr = TREE_OPERAND (current_object, 0);
+
+ if (operand_equal_p (t, this_expr))
+ {
+ data->this_expr_accessed = true;
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+
+ if (TREE_CODE (t) == COMPONENT_REF
+ && POINTER_TYPE_P (TREE_TYPE (t))
+ && operand_equal_p (TREE_OPERAND (t, 0), current_object)
+ && TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL)
+ {
+ data->this_expr_accessed = true;
+ tree fld = TREE_OPERAND (t, 1);
+ if (data->ptr_members_accessed.get (fld) == NULL)
+ {
+ if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
+ t = convert_from_reference (t);
+ data->ptr_members_accessed.put (fld, t);
+ }
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+ }
+
+ /* When the current_function_decl is a lambda function, the closure object
+ argument's type seems to not yet have fields layed out, so a recording
+ of DECL_VALUE_EXPRs during the target body walk seems the only way to
+ find them. */
+ if (current_closure
+ && (TREE_CODE (t) == VAR_DECL
+ || TREE_CODE (t) == PARM_DECL
+ || TREE_CODE (t) == RESULT_DECL)
+ && DECL_HAS_VALUE_EXPR_P (t)
+ && TREE_CODE (DECL_VALUE_EXPR (t)) == COMPONENT_REF
+ && operand_equal_p (current_closure,
+ TREE_OPERAND (DECL_VALUE_EXPR (t), 0)))
+ {
+ if (!data->closure_vars_accessed.contains (t))
+ data->closure_vars_accessed.add (t);
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+
+ if (TREE_CODE (t) == BIND_EXPR)
+ {
+ tree block = BIND_EXPR_BLOCK (t);
+ for (tree var = BLOCK_VARS (block); var; var = DECL_CHAIN (var))
+ if (!data->local_decls.contains (var))
+ data->local_decls.add (var);
+ return NULL_TREE;
+ }
+
+ if (TREE_TYPE (t) && LAMBDA_TYPE_P (TREE_TYPE (t)))
+ {
+ tree lt = TREE_TYPE (t);
+ gcc_assert (CLASS_TYPE_P (lt));
+
+ if (!data->lambda_objects_accessed.contains (t)
+ /* Do not prepare to create target maps for locally declared
+ lambdas or anonymous ones. */
+ && !data->local_decls.contains (t)
+ && TREE_CODE (t) != TARGET_EXPR)
+ data->lambda_objects_accessed.add (t);
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+
+ return NULL_TREE;
+}
+
+/* Helper function for finish_omp_target, and also from tsubst_expr.
+ Create additional clauses for mapping of non-static members, lambda objects,
+ etc. */
+
+void
+finish_omp_target_clauses (location_t loc, tree body, tree *clauses_ptr)
+{
+ omp_target_walk_data data;
+ data.this_expr_accessed = false;
+
+ tree ct = current_nonlambda_class_type ();
+ if (ct)
+ {
+ tree object = maybe_dummy_object (ct, NULL);
+ object = maybe_resolve_dummy (object, true);
+ data.current_object = object;
+ }
+ else
+ data.current_object = NULL_TREE;
+
+ if (DECL_LAMBDA_FUNCTION_P (current_function_decl))
+ {
+ tree closure = DECL_ARGUMENTS (current_function_decl);
+ data.current_closure = build_indirect_ref (loc, closure, RO_UNARY_STAR);
+ }
+ else
+ data.current_closure = NULL_TREE;
+
+ cp_walk_tree_without_duplicates (&body, finish_omp_target_clauses_r, &data);
+
+ auto_vec<tree, 16> new_clauses;
+
+ tree omp_target_this_expr = NULL_TREE;
+ tree *explicit_this_deref_map = NULL;
+ if (data.this_expr_accessed)
+ {
+ omp_target_this_expr = TREE_OPERAND (data.current_object, 0);
+
+ /* See if explicit user-specified map(this[:]) clause already exists.
+ If not, we create an implicit map(tofrom:this[:1]) clause. */
+ for (tree *cp = clauses_ptr; *cp; cp = &OMP_CLAUSE_CHAIN (*cp))
+ if (OMP_CLAUSE_CODE (*cp) == OMP_CLAUSE_MAP
+ && (TREE_CODE (OMP_CLAUSE_DECL (*cp)) == INDIRECT_REF
+ || TREE_CODE (OMP_CLAUSE_DECL (*cp)) == MEM_REF)
+ && operand_equal_p (TREE_OPERAND (OMP_CLAUSE_DECL (*cp), 0),
+ omp_target_this_expr))
+ {
+ explicit_this_deref_map = cp;
+ break;
+ }
+ }
+
+ if (DECL_LAMBDA_FUNCTION_P (current_function_decl)
+ && (data.this_expr_accessed
+ || !data.closure_vars_accessed.is_empty ()))
+ {
+ /* For lambda functions, we need to first create a copy of the
+ __closure object. */
+ tree closure = DECL_ARGUMENTS (current_function_decl);
+ tree c = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TO);
+ OMP_CLAUSE_DECL (c)
+ = build_indirect_ref (loc, closure, RO_UNARY_STAR);
+ OMP_CLAUSE_SIZE (c)
+ = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (closure)));
+ new_clauses.safe_push (c);
+
+ tree closure_obj = OMP_CLAUSE_DECL (c);
+ tree closure_type = TREE_TYPE (closure_obj);
+
+ gcc_assert (LAMBDA_TYPE_P (closure_type)
+ && CLASS_TYPE_P (closure_type));
+
+ tree c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
+ OMP_CLAUSE_DECL (c2) = closure;
+ OMP_CLAUSE_SIZE (c2) = size_zero_node;
+ new_clauses.safe_push (c2);
+ }
+
+ if (data.this_expr_accessed)
+ {
+ /* If the this-expr was accessed, create a map(*this) clause. */
+ enum gomp_map_kind kind = GOMP_MAP_TOFROM;
+ if (explicit_this_deref_map)
+ {
+ tree this_map = *explicit_this_deref_map;
+ tree nc = OMP_CLAUSE_CHAIN (this_map);
+ gcc_assert (nc != NULL_TREE
+ && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
+ && (OMP_CLAUSE_MAP_KIND (nc)
+ == GOMP_MAP_FIRSTPRIVATE_POINTER));
+ kind = OMP_CLAUSE_MAP_KIND (this_map);
+ /* Remove the original 'map(*this) map(firstprivate_ptr:this)'
+ two-map sequence away from the chain. */
+ *explicit_this_deref_map = OMP_CLAUSE_CHAIN (nc);
+ }
+ tree c = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (c, kind);
+ OMP_CLAUSE_DECL (c)
+ = build_indirect_ref (loc, omp_target_this_expr, RO_UNARY_STAR);
+ OMP_CLAUSE_SIZE (c)
+ = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (omp_target_this_expr)));
+ new_clauses.safe_push (c);
+
+ /* If we're in a lambda function, the this-pointer will actually be
+ '__closure->this', a mapped member of __closure, hence always_pointer.
+ Otherwise it's a firstprivate pointer. */
+ enum gomp_map_kind ptr_kind
+ = (DECL_LAMBDA_FUNCTION_P (current_function_decl)
+ ? GOMP_MAP_ALWAYS_POINTER
+ : GOMP_MAP_FIRSTPRIVATE_POINTER);
+ c = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (c, ptr_kind);
+ OMP_CLAUSE_DECL (c) = omp_target_this_expr;
+ OMP_CLAUSE_SIZE (c) = size_zero_node;
+ new_clauses.safe_push (c);
+ }
+
+ if (DECL_LAMBDA_FUNCTION_P (current_function_decl))
+ {
+ if (omp_target_this_expr)
+ {
+ STRIP_NOPS (omp_target_this_expr);
+ gcc_assert (DECL_HAS_VALUE_EXPR_P (omp_target_this_expr));
+ omp_target_this_expr = DECL_VALUE_EXPR (omp_target_this_expr);
+ }
+
+ for (hash_set<tree>::iterator i = data.closure_vars_accessed.begin ();
+ i != data.closure_vars_accessed.end (); ++i)
+ {
+ tree orig_decl = *i;
+ tree closure_expr = DECL_VALUE_EXPR (orig_decl);
+
+ if (TREE_CODE (TREE_TYPE (orig_decl)) == POINTER_TYPE
+ || TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE)
+ {
+ /* this-pointer is processed above, outside this loop. */
+ if (omp_target_this_expr
+ && operand_equal_p (closure_expr, omp_target_this_expr))
+ continue;
+
+ bool ptr_p = TREE_CODE (TREE_TYPE (orig_decl)) == POINTER_TYPE;
+ enum gomp_map_kind kind, ptr_kind, nc_kind;
+ tree size;
+
+ if (ptr_p)
+ {
+ /* For pointers, default mapped as zero-length array
+ section. */
+ kind = GOMP_MAP_ALLOC;
+ nc_kind = GOMP_MAP_FIRSTPRIVATE_POINTER;
+ ptr_kind = GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION;
+ size = size_zero_node;
+ }
+ else
+ {
+ /* For references, default mapped as appearing on map
+ clause. */
+ kind = GOMP_MAP_TOFROM;
+ nc_kind = GOMP_MAP_FIRSTPRIVATE_REFERENCE;
+ ptr_kind = GOMP_MAP_ALWAYS_POINTER;
+ size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (closure_expr)));
+ }
+
+ for (tree *p = clauses_ptr; *p; p = &OMP_CLAUSE_CHAIN (*p))
+ if (OMP_CLAUSE_CODE (*p) == OMP_CLAUSE_MAP
+ && (TREE_CODE (OMP_CLAUSE_DECL (*p)) == INDIRECT_REF
+ || TREE_CODE (OMP_CLAUSE_DECL (*p)) == MEM_REF)
+ && operand_equal_p (TREE_OPERAND (OMP_CLAUSE_DECL (*p), 0),
+ orig_decl))
+ {
+ /* If this was already specified by user as a map,
+ save the user specified map kind, delete the
+ "map(*ptr/ref), map(firstprivate ptr/ref)" sequence,
+ and insert our own sequence:
+ "map(*__closure->ptr/ref), map(<ptr_kind>:__closure->ref"
+ */
+ tree nc = OMP_CLAUSE_CHAIN (*p);
+ gcc_assert (nc != NULL_TREE
+ && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_KIND (nc) == nc_kind);
+ /* Update with user specified kind and size. */
+ kind = OMP_CLAUSE_MAP_KIND (*p);
+ size = OMP_CLAUSE_SIZE (*p);
+ *p = OMP_CLAUSE_CHAIN (nc);
+ break;
+ }
+
+ tree c = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (c, kind);
+ OMP_CLAUSE_DECL (c)
+ = build_indirect_ref (loc, closure_expr, RO_UNARY_STAR);
+ OMP_CLAUSE_SIZE (c) = size;
+ if (ptr_p)
+ OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1;
+ new_clauses.safe_push (c);
+
+ c = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (c, ptr_kind);
+ OMP_CLAUSE_DECL (c) = closure_expr;
+ OMP_CLAUSE_SIZE (c) = size_zero_node;
+ new_clauses.safe_push (c);
+ }
+ }
+ }
+
+ if (!data.ptr_members_accessed.is_empty ())
+ for (hash_map<tree, tree>::iterator i = data.ptr_members_accessed.begin ();
+ i != data.ptr_members_accessed.end (); ++i)
+ {
+ /* For each referenced member that is of pointer or reference-to-pointer
+ type, create the equivalent of map(alloc:this->ptr[:0]). */
+ tree field_decl = (*i).first;
+ tree ptr_member = (*i).second;
+
+ for (tree c = *clauses_ptr; c; c = OMP_CLAUSE_CHAIN (c))
+ {
+ /* If map(this->ptr[:N] already exists, avoid creating another
+ such map. */
+ tree decl = OMP_CLAUSE_DECL (c);
+ if ((TREE_CODE (decl) == INDIRECT_REF
+ || TREE_CODE (decl) == MEM_REF)
+ && operand_equal_p (TREE_OPERAND (decl, 0), ptr_member))
+ goto next_ptr_member;
+ }
+
+ if (!cxx_mark_addressable (ptr_member))
+ gcc_unreachable ();
+
+ if (TREE_CODE (TREE_TYPE (field_decl)) == REFERENCE_TYPE)
+ {
+ /* For reference to pointers, we need to map the referenced
+ pointer first for things to be correct. */
+ tree ptr_member_type = TREE_TYPE (ptr_member);
+
+ /* Map pointer target as zero-length array section. */
+ tree c = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALLOC);
+ OMP_CLAUSE_DECL (c)
+ = build1 (INDIRECT_REF, TREE_TYPE (ptr_member_type), ptr_member);
+ OMP_CLAUSE_SIZE (c) = size_zero_node;
+ OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1;
+
+ /* Map pointer to zero-length array section. */
+ tree c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND
+ (c2, GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION);
+ OMP_CLAUSE_DECL (c2) = ptr_member;
+ OMP_CLAUSE_SIZE (c2) = size_zero_node;
+
+ /* Attach reference-to-pointer field to pointer. */
+ tree c3 = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_ATTACH);
+ OMP_CLAUSE_DECL (c3) = TREE_OPERAND (ptr_member, 0);
+ OMP_CLAUSE_SIZE (c3) = size_zero_node;
+
+ new_clauses.safe_push (c);
+ new_clauses.safe_push (c2);
+ new_clauses.safe_push (c3);
+ }
+ else if (TREE_CODE (TREE_TYPE (field_decl)) == POINTER_TYPE)
+ {
+ /* Map pointer target as zero-length array section. */
+ tree c = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALLOC);
+ OMP_CLAUSE_DECL (c) = build_indirect_ref (loc, ptr_member,
+ RO_UNARY_STAR);
+ OMP_CLAUSE_SIZE (c) = size_zero_node;
+ OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1;
+
+ /* Attach zero-length array section to pointer. */
+ tree c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND
+ (c2, GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION);
+ OMP_CLAUSE_DECL (c2) = ptr_member;
+ OMP_CLAUSE_SIZE (c2) = size_zero_node;
+
+ new_clauses.safe_push (c);
+ new_clauses.safe_push (c2);
+ }
+ else
+ gcc_unreachable ();
+
+ next_ptr_member:
+ ;
+ }
+
+ for (hash_set<tree>::iterator i = data.lambda_objects_accessed.begin ();
+ i != data.lambda_objects_accessed.end (); ++i)
+ {
+ tree lobj = *i;
+ if (TREE_CODE (lobj) == TARGET_EXPR)
+ lobj = TREE_OPERAND (lobj, 0);
+
+ tree lt = TREE_TYPE (lobj);
+ gcc_assert (LAMBDA_TYPE_P (lt) && CLASS_TYPE_P (lt));
+
+ tree lc = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (lc, GOMP_MAP_TO);
+ OMP_CLAUSE_DECL (lc) = lobj;
+ OMP_CLAUSE_SIZE (lc) = TYPE_SIZE_UNIT (lt);
+ new_clauses.safe_push (lc);
+
+ for (tree fld = TYPE_FIELDS (lt); fld; fld = DECL_CHAIN (fld))
+ {
+ if (TREE_CODE (TREE_TYPE (fld)) == POINTER_TYPE)
+ {
+ tree exp = build3 (COMPONENT_REF, TREE_TYPE (fld),
+ lobj, fld, NULL_TREE);
+ tree c = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALLOC);
+ OMP_CLAUSE_DECL (c)
+ = build_indirect_ref (loc, exp, RO_UNARY_STAR);
+ OMP_CLAUSE_SIZE (c) = size_zero_node;
+ OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1;
+ new_clauses.safe_push (c);
+
+ c = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND
+ (c, GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION);
+ OMP_CLAUSE_DECL (c) = exp;
+ OMP_CLAUSE_SIZE (c) = size_zero_node;
+ new_clauses.safe_push (c);
+ }
+ else if (TREE_CODE (TREE_TYPE (fld)) == REFERENCE_TYPE)
+ {
+ tree exp = build3 (COMPONENT_REF, TREE_TYPE (fld),
+ lobj, fld, NULL_TREE);
+ tree c = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
+ OMP_CLAUSE_DECL (c)
+ = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
+ OMP_CLAUSE_SIZE (c)
+ = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (exp)));
+ new_clauses.safe_push (c);
+
+ c = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_POINTER);
+ OMP_CLAUSE_DECL (c) = exp;
+ OMP_CLAUSE_SIZE (c) = size_zero_node;
+ new_clauses.safe_push (c);
+ }
+ }
+ }
+
+ tree c = *clauses_ptr;
+ for (int i = new_clauses.length () - 1; i >= 0; i--)
+ {
+ OMP_CLAUSE_CHAIN (new_clauses[i]) = c;
+ c = new_clauses[i];
+ }
+ *clauses_ptr = c;
+}
+
+/* Called from cp_parser_omp_target. Create additional implicit clauses for
+ OpenMP target directives, and do sanity checks. */
+
+tree
+finish_omp_target (location_t loc, tree clauses, tree body, bool combined_p)
+{
+ if (!processing_template_decl)
+ finish_omp_target_clauses (loc, body, &clauses);
+
+ tree stmt = make_node (OMP_TARGET);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_TARGET_CLAUSES (stmt) = clauses;
+ OMP_TARGET_BODY (stmt) = body;
+ OMP_TARGET_COMBINED (stmt) = combined_p;
+ SET_EXPR_LOCATION (stmt, loc);
+
+ tree c = clauses;
+ while (c)
+ {
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
+ switch (OMP_CLAUSE_MAP_KIND (c))
+ {
+ case GOMP_MAP_TO:
+ case GOMP_MAP_ALWAYS_TO:
+ case GOMP_MAP_FROM:
+ case GOMP_MAP_ALWAYS_FROM:
+ case GOMP_MAP_TOFROM:
+ case GOMP_MAP_ALWAYS_TOFROM:
+ case GOMP_MAP_ALLOC:
+ case GOMP_MAP_FIRSTPRIVATE_POINTER:
+ case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
+ case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
+ case GOMP_MAP_ATTACH:
+ case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
+ case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
+ break;
+ default:
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<#pragma omp target%> with map-type other "
+ "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
+ "on %<map%> clause");
+ break;
+ }
+ c = OMP_CLAUSE_CHAIN (c);
+ }
+ return add_stmt (stmt);
+}
+
tree
finish_omp_parallel (tree clauses, tree body)
{
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 1471ed8..52c5683 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -4311,6 +4311,18 @@ is_byte_access_type (tree type)
&& !strcmp ("byte", TYPE_NAME_STRING (type)));
}
+/* Returns true if TYPE is unsigned char or std::byte. */
+
+bool
+is_byte_access_type_not_plain_char (tree type)
+{
+ type = TYPE_MAIN_VARIANT (type);
+ if (type == char_type_node)
+ return false;
+
+ return is_byte_access_type (type);
+}
+
/* Returns 1 iff type T is something we want to treat as a scalar type for
the purpose of deciding whether it is trivial/POD/standard-layout. */
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 5ed9a5a..4e60db4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2209,9 +2209,9 @@ invalid_nonstatic_memfn_p (location_t loc, tree expr, tsubst_flags_t complain)
return false;
}
-/* If EXP is a reference to a bitfield, and the type of EXP does not
- match the declared type of the bitfield, return the declared type
- of the bitfield. Otherwise, return NULL_TREE. */
+/* If EXP is a reference to a bit-field, and the type of EXP does not
+ match the declared type of the bit-field, return the declared type
+ of the bit-field. Otherwise, return NULL_TREE. */
tree
is_bitfield_expr_with_lowered_type (const_tree exp)
@@ -2230,6 +2230,14 @@ is_bitfield_expr_with_lowered_type (const_tree exp)
case MODIFY_EXPR:
case SAVE_EXPR:
+ case UNARY_PLUS_EXPR:
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case NEGATE_EXPR:
+ case NON_LVALUE_EXPR:
+ case BIT_NOT_EXPR:
return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
case COMPONENT_REF:
diff --git a/gcc/cse.c b/gcc/cse.c
index c1c7d0c..dc5d5ae 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -4275,7 +4275,12 @@ find_sets_in_insn (rtx_insn *insn, vec<struct set> *psets)
else if (GET_CODE (SET_SRC (x)) == CALL)
;
else if (GET_CODE (SET_SRC (x)) == CONST_VECTOR
- && GET_MODE_CLASS (GET_MODE (SET_SRC (x))) != MODE_VECTOR_BOOL)
+ && GET_MODE_CLASS (GET_MODE (SET_SRC (x))) != MODE_VECTOR_BOOL
+ /* Prevent duplicates from being generated if the type is a V1
+ type and a subreg. Folding this will result in the same
+ element as folding x itself. */
+ && !(SUBREG_P (SET_DEST (x))
+ && known_eq (GET_MODE_NUNITS (GET_MODE (SET_SRC (x))), 1)))
{
/* First register the vector itself. */
add_to_set (psets, x);
diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog
index c985f00..370e33c 100644
--- a/gcc/d/ChangeLog
+++ b/gcc/d/ChangeLog
@@ -1,3 +1,77 @@
+2021-12-08 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * dmd/MERGE: Merge upstream dmd 568496d5b.
+ * Make-lang.in (D_FRONTEND_OBJS): Add d/common-file.o,
+ d/common-outbuffer.o, d/common-string.o, d/file_manager.o,
+ d/importc.o. Remove d/root-outbuffer.o.
+ (d/common-%.o): New recipe.
+ * d-builtins.cc (build_frontend_type): Update for new front-end
+ interface.
+ (d_build_d_type_nodes): Set noreturn_type_node.
+ * d-codegen.cc (d_build_call): Don't call function if one of the
+ arguments is type 'noreturn'.
+ (build_vthis_function): Propagate TYPE_QUAL_VOLATILE from original
+ function type.
+ * d-frontend.cc (eval_builtin): Update signature.
+ (getTypeInfoType): Likewise.
+ (toObjFile): New function.
+ * d-gimplify.cc (d_gimplify_call_expr): Always evaluate arguments from
+ left to right.
+ * d-lang.cc (d_handle_option): Handle OPT_ftransition_in.
+ (d_parse_file): Don't generate D main if it is declared in user code.
+ * d-tree.h (CALL_EXPR_ARGS_ORDERED): Remove.
+ (enum d_tree_index): Add DTI_BOTTOM_TYPE.
+ (noreturn_type_node): New.
+ * decl.cc (apply_pragma_crt): Remove.
+ (DeclVisitor::visit): Update for new front-end interface.
+ (DeclVisitor::visit (PragmaDeclaration *)): Don't handle
+ crt_constructor and crt_destructor pragmas.
+ (DeclVisitor::visit (VarDeclaration *)): Don't generate declarations
+ of type 'noreturn'.
+ (DeclVisitor::visit (FuncDeclaration *)): Stop adding parameters when
+ 'noreturn' type has been encountered.
+ (get_symbol_decl): Set DECL_STATIC_CONSTRUCTOR and
+ DECL_STATIC_DESTRUCTOR on decl node if requested.
+ (aggregate_initializer_decl): Update for new front-end interface.
+ * expr.cc (ExprVisitor::visit (CallExp *)): Always use the 'this'
+ object as the result of calling any constructor function.
+ (ExprVisitor::visit): Update for new front-end interface.
+ * gdc.texi (Runtime Options): Document -fmain and -ftransition=in.
+ * lang.opt (ftransition=in): New option.
+ * modules.cc (get_internal_fn): Update for new front-end interface.
+ * types.cc (TypeVisitor::visit): Likewise.
+ (TypeVisitor::visit (TypeNoreturn *)): Return noreturn_type_node.
+ (TypeVisitor::visit (TypeFunction *)): Stop adding parameters when
+ 'notreturn' type has been encountered. Qualify function types that
+ return 'noreturn' as TYPE_QUAL_VOLATILE.
+
+2021-12-02 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/103520
+ * d-frontend.h (gc_disable): Declare.
+ * d-lang.cc (d_init_options): Disable the D runtime garbage collector
+ after initializing.
+
+2021-12-02 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * Make-lang.in (D_FRONTEND_OBJS): Prefix object files from the root
+ package with root-.
+ (d/root-%.o): New recipe.
+
+2021-12-01 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * d-spec.cc (lang_specific_driver): Set SKIPOPT on -static-libstdc++
+ and -static-libphobos only when target supports LD_STATIC_DYNAMIC.
+ Remove generate_option to re-add -static-libstdc++.
+
+2021-12-01 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * gdc.texi (Runtime Options): Document -fcheckaction=, -fextern-std=,
+ -fpreview=, -frevert=.
+ (Code Generation): Document -fdump-c++-spec=, -fdump-c++-spec-verbose,
+ -fsave-mixins=.
+ (Warnings): Update list of supported -ftransitions=.
+
2021-11-30 Iain Buclaw <ibuclaw@gdcproject.org>
* dmd/MERGE: Merge upstream dmd b8384668f.
diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in
index 4c0a032..d7f7147 100644
--- a/gcc/d/Make-lang.in
+++ b/gcc/d/Make-lang.in
@@ -74,24 +74,24 @@ endif
# D Frontend object files.
D_FRONTEND_OBJS = \
- d/aav.o \
d/access.o \
d/aggregate.o \
d/aliasthis.o \
d/apply.o \
- d/array.o \
d/arrayop.o \
d/arraytypes.o \
d/attrib.o \
d/ast_node.o \
d/astcodegen.o \
d/astenums.o \
- d/bitarray.o \
d/blockexit.o \
d/builtin.o \
d/canthrow.o \
d/chkformat.o \
d/clone.o \
+ d/common-file.o \
+ d/common-outbuffer.o \
+ d/common-string.o \
d/compiler.o \
d/complex.o \
d/cond.o \
@@ -99,7 +99,6 @@ D_FRONTEND_OBJS = \
d/cparse.o \
d/cppmangle.o \
d/ctfeexpr.o \
- d/ctfloat.o \
d/ctorflow.o \
d/dcast.o \
d/dclass.o \
@@ -124,13 +123,11 @@ D_FRONTEND_OBJS = \
d/escape.o \
d/expression.o \
d/expressionsem.o \
- d/file.o \
- d/filename.o \
+ d/file_manager.o \
d/foreachvar.o \
d/func.o \
d/globals.o \
d/gluelayer.o \
- d/hash.o \
d/hdrgen.o \
d/iasm.o \
d/iasmgcc.o \
@@ -138,6 +135,7 @@ D_FRONTEND_OBJS = \
d/identifier.o \
d/impcnvtab.o \
d/imphint.o \
+ d/importc.o \
d/init.o \
d/initsem.o \
d/inline.o \
@@ -145,7 +143,6 @@ D_FRONTEND_OBJS = \
d/json.o \
d/lambdacomp.o \
d/lexer.o \
- d/longdouble.o \
d/mtype.o \
d/nogc.o \
d/nspace.o \
@@ -153,29 +150,36 @@ D_FRONTEND_OBJS = \
d/objc.o \
d/opover.o \
d/optimize.o \
- d/outbuffer.o \
d/parse.o \
d/parsetimevisitor.o \
d/permissivevisitor.o \
- d/port.o \
d/printast.o \
- d/region.o \
- d/rmem.o \
- d/rootobject.o \
+ d/root-aav.o \
+ d/root-array.o \
+ d/root-bitarray.o \
+ d/root-ctfloat.o \
+ d/root-file.o \
+ d/root-filename.o \
+ d/root-hash.o \
+ d/root-longdouble.o \
+ d/root-port.o \
+ d/root-region.o \
+ d/root-rmem.o \
+ d/root-rootobject.o \
+ d/root-speller.o \
+ d/root-string.o \
+ d/root-stringtable.o \
d/safe.o \
d/sapply.o \
d/semantic2.o \
d/semantic3.o \
d/sideeffect.o \
- d/speller.o \
d/statement.o \
d/statement_rewrite_walker.o \
d/statementsem.o \
d/staticassert.o \
d/staticcond.o \
d/stmtstate.o \
- d/string.o \
- d/stringtable.o \
d/target.o \
d/templateparamsem.o \
d/tokens.o \
@@ -393,6 +397,10 @@ d/%.o: d/dmd/%.d
$(DCOMPILE) $(D_INCLUDES) $<
$(DPOSTCOMPILE)
-d/%.o: d/dmd/root/%.d
+d/common-%.o: d/dmd/common/%.d
+ $(DCOMPILE) $(D_INCLUDES) $<
+ $(DPOSTCOMPILE)
+
+d/root-%.o: d/dmd/root/%.d
$(DCOMPILE) $(D_INCLUDES) $<
$(DPOSTCOMPILE)
diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index ab3a950..ea8e1ed 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -236,7 +236,7 @@ build_frontend_type (tree type)
sdecl->parent = stubmod;
sdecl->structsize = int_size_in_bytes (type);
sdecl->alignsize = TYPE_ALIGN_UNIT (type);
- sdecl->alignment = STRUCTALIGN_DEFAULT;
+ sdecl->alignment.setDefault ();
sdecl->sizeok = Sizeok::done;
sdecl->type = (TypeStruct::create (sdecl))->addMod (mod);
sdecl->type->ctype = type;
@@ -275,7 +275,7 @@ build_frontend_type (tree type)
NULL);
vd->parent = sdecl;
vd->offset = tree_to_uhwi (byte_position (field));
- vd->semanticRun = PASSsemanticdone;
+ vd->semanticRun = PASS::semanticdone;
vd->csym = field;
sdecl->members->push (vd);
sdecl->fields.push (vd);
@@ -856,6 +856,9 @@ d_build_d_type_nodes (void)
ireal_type_node = build_distinct_type_copy (long_double_type_node);
TYPE_IMAGINARY_FLOAT (ireal_type_node) = 1;
+ /* Noreturn type. */
+ noreturn_type_node = build_distinct_type_copy (void_type_node);
+
/* Calling build_ctype() links the front-end Type to the GCC node,
and sets the TYPE_NAME to the D language type. */
for (unsigned ty = 0; ty < (unsigned) TY::TMAX; ty++)
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 403e3c7..c082ac5 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -2140,6 +2140,7 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
/* Build the argument list for the call. */
vec <tree, va_gc> *args = NULL;
tree saved_args = NULL_TREE;
+ bool noreturn_call = false;
/* If this is a delegate call or a nested function being called as
a delegate, the object should not be NULL. */
@@ -2165,9 +2166,9 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
}
}
- size_t nparams = tf->parameterList.length ();
+ const size_t nparams = tf->parameterList.length ();
/* if _arguments[] is the first argument. */
- size_t varargs = tf->isDstyleVariadic ();
+ const size_t varargs = tf->isDstyleVariadic ();
/* Assumes arguments->length <= formal_args->length if (!tf->varargs). */
for (size_t i = 0; i < arguments->length; ++i)
@@ -2206,6 +2207,11 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
build_address (targ));
}
+ /* Type `noreturn` is a terminator, as no other arguments can possibly
+ be evaluated after it. */
+ if (TREE_TYPE (targ) == noreturn_type_node)
+ noreturn_call = true;
+
vec_safe_push (args, targ);
}
}
@@ -2217,13 +2223,27 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
saved_args = compound_expr (callee, saved_args);
}
+ /* If we saw a `noreturn` parameter, any unreachable argument evaluations
+ after it are discarded, as well as the function call itself. */
+ if (noreturn_call)
+ {
+ if (TREE_SIDE_EFFECTS (callee))
+ saved_args = compound_expr (callee, saved_args);
+
+ tree arg;
+ unsigned int ix;
+
+ FOR_EACH_VEC_SAFE_ELT (args, ix, arg)
+ saved_args = compound_expr (saved_args, arg);
+
+ /* Add a stub result type for the expression. */
+ tree result = build_zero_cst (TREE_TYPE (ctype));
+ return compound_expr (saved_args, result);
+ }
+
tree result = build_call_vec (TREE_TYPE (ctype), callee, args);
SET_EXPR_LOCATION (result, input_location);
- /* Enforce left to right evaluation. */
- if (tf->linkage == LINK::d)
- CALL_EXPR_ARGS_ORDERED (result) = 1;
-
result = maybe_expand_intrinsic (result);
/* Return the value in a temporary slot so that it can be evaluated
@@ -2296,6 +2316,10 @@ build_vthis_function (tree basetype, tree type)
TYPE_ARG_TYPES (type));
tree fntype = build_function_type (TREE_TYPE (type), argtypes);
+ /* Copy volatile qualifiers from the original function type. */
+ if (TYPE_QUALS (type) & TYPE_QUAL_VOLATILE)
+ fntype = build_qualified_type (fntype, TYPE_QUAL_VOLATILE);
+
if (RECORD_OR_UNION_TYPE_P (basetype))
TYPE_METHOD_BASETYPE (fntype) = TYPE_MAIN_VARIANT (basetype);
else
diff --git a/gcc/d/d-frontend.cc b/gcc/d/d-frontend.cc
index 522095f..b2e52c0 100644
--- a/gcc/d/d-frontend.cc
+++ b/gcc/d/d-frontend.cc
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic.h"
#include "d-tree.h"
+#include "d-frontend.h"
/* Implements back-end specific interfaces used by the frontend. */
@@ -51,7 +52,7 @@ isBuiltin (FuncDeclaration *fd)
Return result; NULL if cannot evaluate it. */
Expression *
-eval_builtin (Loc loc, FuncDeclaration *fd, Expressions *arguments)
+eval_builtin (const Loc &loc, FuncDeclaration *fd, Expressions *arguments)
{
if (fd->builtin == BUILTIN::unimp)
return NULL;
@@ -78,10 +79,16 @@ eval_builtin (Loc loc, FuncDeclaration *fd, Expressions *arguments)
/* Build and return typeinfo type for TYPE. */
Type *
-getTypeInfoType (Loc loc, Type *type, Scope *sc)
+getTypeInfoType (const Loc &loc, Type *type, Scope *sc)
{
gcc_assert (type->ty != TY::Terror);
check_typeinfo_type (loc, sc);
create_typeinfo (type, sc ? sc->_module->importedFrom : NULL);
return type->vtinfo->type;
}
+
+void
+toObjFile (Dsymbol *ds, bool)
+{
+ build_decl_tree (ds);
+}
diff --git a/gcc/d/d-frontend.h b/gcc/d/d-frontend.h
index 3edf812..e7695d5 100644
--- a/gcc/d/d-frontend.h
+++ b/gcc/d/d-frontend.h
@@ -21,7 +21,7 @@ along with GCC; see the file COPYING3. If not see
/* These functions are defined in D runtime. */
extern "C" int rt_init (void);
extern "C" int rt_term (void);
-//extern "C" void gc_disable (void);
+extern "C" void gc_disable (void);
extern "C" void *gc_malloc (size_t sz, unsigned ba = 0, const void *ti = NULL);
extern "C" void gc_free (void *);
extern "C" void gc_collect (void);
diff --git a/gcc/d/d-gimplify.cc b/gcc/d/d-gimplify.cc
index 0fa7442..e366881 100644
--- a/gcc/d/d-gimplify.cc
+++ b/gcc/d/d-gimplify.cc
@@ -120,52 +120,47 @@ d_gimplify_addr_expr (tree *expr_p)
static gimplify_status
d_gimplify_call_expr (tree *expr_p, gimple_seq *pre_p)
{
- if (CALL_EXPR_ARGS_ORDERED (*expr_p))
- {
- /* Strictly evaluate all arguments from left to right. */
- int nargs = call_expr_nargs (*expr_p);
- location_t loc = EXPR_LOC_OR_LOC (*expr_p, input_location);
+ /* Strictly evaluate all arguments from left to right. */
+ int nargs = call_expr_nargs (*expr_p);
+ location_t loc = EXPR_LOC_OR_LOC (*expr_p, input_location);
- /* No need to enforce evaluation order if only one argument. */
- if (nargs < 2)
- return GS_UNHANDLED;
+ /* No need to enforce evaluation order if only one argument. */
+ if (nargs < 2)
+ return GS_UNHANDLED;
- /* Or if all arguments are already free of side-effects. */
- bool has_side_effects = false;
- for (int i = 0; i < nargs; i++)
+ /* Or if all arguments are already free of side-effects. */
+ bool has_side_effects = false;
+ for (int i = 0; i < nargs; i++)
+ {
+ if (TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, i)))
{
- if (TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, i)))
- {
- has_side_effects = true;
- break;
- }
+ has_side_effects = true;
+ break;
}
+ }
- if (!has_side_effects)
- return GS_UNHANDLED;
-
- /* Leave the last argument for gimplify_call_expr. */
- for (int i = 0; i < nargs - 1; i++)
- {
- tree new_arg = CALL_EXPR_ARG (*expr_p, i);
+ if (!has_side_effects)
+ return GS_UNHANDLED;
- /* If argument has a side-effect, gimplify_arg will handle it. */
- if (gimplify_arg (&new_arg, pre_p, loc) == GS_ERROR)
- return GS_ERROR;
+ /* Leave the last argument for gimplify_call_expr. */
+ for (int i = 0; i < nargs - 1; i++)
+ {
+ tree new_arg = CALL_EXPR_ARG (*expr_p, i);
- /* Even if an argument itself doesn't have any side-effects, it
- might be altered by another argument in the list. */
- if (new_arg == CALL_EXPR_ARG (*expr_p, i)
- && !really_constant_p (new_arg))
- new_arg = get_formal_tmp_var (new_arg, pre_p);
+ /* If argument has a side-effect, gimplify_arg will handle it. */
+ if (gimplify_arg (&new_arg, pre_p, loc) == GS_ERROR)
+ return GS_ERROR;
- CALL_EXPR_ARG (*expr_p, i) = new_arg;
- }
+ /* Even if an argument itself doesn't have any side-effects, it
+ might be altered by another argument in the list. */
+ if (new_arg == CALL_EXPR_ARG (*expr_p, i)
+ && !really_constant_p (new_arg))
+ new_arg = get_formal_tmp_var (new_arg, pre_p);
- return GS_OK;
+ CALL_EXPR_ARG (*expr_p, i) = new_arg;
}
- return GS_UNHANDLED;
+ return GS_OK;
}
/* Gimplify an UNSIGNED_RSHIFT_EXPR node. */
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index d20370e..576eefc 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -288,7 +288,7 @@ d_init_options (unsigned int, cl_decoded_option *decoded_options)
{
/* Initialize the D runtime. */
rt_init ();
-// gc_disable ();
+ gc_disable ();
/* Set default values. */
global._init ();
@@ -674,6 +674,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
case OPT_ftransition_all:
global.params.vfield = value;
global.params.vgc = value;
+ global.params.vin = value;
global.params.vmarkdown= value;
global.params.vtls = value;
break;
@@ -682,6 +683,10 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
global.params.vfield = value;
break;
+ case OPT_ftransition_in:
+ global.params.vin = value;
+ break;
+
case OPT_ftransition_nogc:
global.params.vgc = value;
break;
@@ -1176,6 +1181,14 @@ d_parse_file (void)
{
Module *m = modules[i];
+ /* If this is the `__main` module, check that `D main` hasn't already
+ been declared in user code before running semantic on it. */
+ if (m == main_module && global.hasMainFunction)
+ {
+ modules.remove (i);
+ continue;
+ }
+
if (global.params.verbose)
message ("semantic %s", m->toChars ());
@@ -1357,6 +1370,9 @@ d_parse_file (void)
for (size_t i = 0; i < modules.length; i++)
{
Module *m = modules[i];
+
+ /* Skip generating code for header files, or when the module wasn't
+ specified by `-fonly=`. */
if ((m->isHdrFile && m != main_module)
|| (d_option.fonly && m != Module::rootModule))
continue;
diff --git a/gcc/d/d-spec.cc b/gcc/d/d-spec.cc
index b12d28f..1304126 100644
--- a/gcc/d/d-spec.cc
+++ b/gcc/d/d-spec.cc
@@ -253,13 +253,23 @@ lang_specific_driver (cl_decoded_option **in_decoded_options,
case OPT_static_libstdc__:
saw_static_libcxx = true;
+#ifdef HAVE_LD_STATIC_DYNAMIC
+ /* Remove -static-libstdc++ from the command only if target supports
+ LD_STATIC_DYNAMIC. When not supported, it is left in so that a
+ back-end target can use outfile substitution. */
args[i] |= SKIPOPT;
+#endif
break;
case OPT_static_libphobos:
if (phobos_library != PHOBOS_NOLINK)
phobos_library = PHOBOS_STATIC;
+#ifdef HAVE_LD_STATIC_DYNAMIC
+ /* Remove -static-libphobos from the command only if target supports
+ LD_STATIC_DYNAMIC. When not supported, it is left in so that a
+ back-end target can use outfile substitution. */
args[i] |= SKIPOPT;
+#endif
break;
case OPT_shared_libphobos:
@@ -460,7 +470,7 @@ lang_specific_driver (cl_decoded_option **in_decoded_options,
#endif
}
- if (saw_libcxx || need_stdcxx)
+ if (saw_libcxx || saw_static_libcxx || need_stdcxx)
{
#ifdef HAVE_LD_STATIC_DYNAMIC
if (saw_static_libcxx && !static_link)
@@ -468,12 +478,6 @@ lang_specific_driver (cl_decoded_option **in_decoded_options,
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;
diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
index 328b6b8..a5970d8 100644
--- a/gcc/d/d-tree.h
+++ b/gcc/d/d-tree.h
@@ -47,7 +47,6 @@ typedef Array <Expression *> Expressions;
/* Usage of TREE_LANG_FLAG_?:
0: METHOD_CALL_EXPR
- 1: CALL_EXPR_ARGS_ORDERED (in CALL_EXPR).
Usage of TYPE_LANG_FLAG_?:
0: TYPE_SHARED
@@ -351,11 +350,6 @@ lang_tree_node
#define METHOD_CALL_EXPR(NODE) \
(TREE_LANG_FLAG_0 (NODE))
-/* True if all arguments in a call expression should be evaluated in the
- order they are given (left to right). */
-#define CALL_EXPR_ARGS_ORDERED(NODE) \
- (TREE_LANG_FLAG_1 (CALL_EXPR_CHECK (NODE)))
-
/* True if the type was declared 'shared'. */
#define TYPE_SHARED(NODE) \
(TYPE_LANG_FLAG_0 (NODE))
@@ -430,6 +424,7 @@ enum d_tree_index
DTI_ARRAY_TYPE,
DTI_NULL_ARRAY,
+ DTI_BOTTOM_TYPE,
DTI_MAX
};
@@ -465,6 +460,8 @@ extern GTY(()) tree d_global_trees[DTI_MAX];
#define array_type_node d_global_trees[DTI_ARRAY_TYPE]
/* Null initializer for dynamic arrays. */
#define null_array_node d_global_trees[DTI_NULL_ARRAY]
+/* The bottom type, referred to as `noreturn` in code. */
+#define noreturn_type_node d_global_trees[DTI_BOTTOM_TYPE]
/* A prefix for internal variables, which are not user-visible. */
#if !defined (NO_DOT_IN_LABEL)
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index e28a581..a4976b6 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -116,59 +116,6 @@ gcc_attribute_p (Dsymbol *decl)
return false;
}
-/* Subroutine of pragma declaration visitor for marking the function in the
- defined in SYM as a global constructor or destructor. If ISCTOR is true,
- then we're applying pragma(crt_constructor). */
-
-static int
-apply_pragma_crt (Dsymbol *sym, bool isctor)
-{
- AttribDeclaration *ad = sym->isAttribDeclaration ();
- if (ad != NULL)
- {
- int nested = 0;
-
- /* Walk all declarations of the attribute scope. */
- Dsymbols *ds = ad->include (NULL);
- if (ds)
- {
- for (size_t i = 0; i < ds->length; i++)
- nested += apply_pragma_crt ((*ds)[i], isctor);
- }
-
- return nested;
- }
-
- FuncDeclaration *fd = sym->isFuncDeclaration ();
- if (fd != NULL)
- {
- tree decl = get_decl_tree (fd);
-
- /* Apply flags to the function. */
- if (isctor)
- {
- DECL_STATIC_CONSTRUCTOR (decl) = 1;
- decl_init_priority_insert (decl, DEFAULT_INIT_PRIORITY);
- }
- else
- {
- DECL_STATIC_DESTRUCTOR (decl) = 1;
- decl_fini_priority_insert (decl, DEFAULT_INIT_PRIORITY);
- }
-
- if (fd->linkage != LINK::c)
- {
- error_at (make_location_t (fd->loc),
- "must be %<extern(C)%> for %<pragma(%s)%>",
- isctor ? "crt_constructor" : "crt_destructor");
- }
-
- return 1;
- }
-
- return 0;
-}
-
/* Implements the visitor interface to lower all Declaration AST classes
emitted from the D Front-end to GCC trees.
All visit methods accept one parameter D, which holds the frontend AST
@@ -210,18 +157,18 @@ public:
void visit (Module *d)
{
- if (d->semanticRun >= PASSobj)
+ if (d->semanticRun >= PASS::obj)
return;
build_module_tree (d);
- d->semanticRun = PASSobj;
+ d->semanticRun = PASS::obj;
}
/* Write the imported symbol to debug. */
void visit (Import *d)
{
- if (d->semanticRun >= PASSobj)
+ if (d->semanticRun >= PASS::obj)
return;
/* Implements import declarations by telling the debug back-end we are
@@ -266,7 +213,7 @@ public:
false, false);
}
- d->semanticRun = PASSobj;
+ d->semanticRun = PASS::obj;
}
/* Expand any local variables found in tuples. */
@@ -312,18 +259,6 @@ public:
"pragma(%s) not implemented", d->ident->toChars ());
}
}
- else if (d->ident == Identifier::idPool ("crt_constructor")
- || d->ident == Identifier::idPool ("crt_destructor"))
- {
- /* Handle pragma(crt_constructor) and pragma(crt_destructor). Apply
- flag to indicate that the functions enclosed should run automatically
- at the beginning or end of execution. */
- bool isctor = (d->ident == Identifier::idPool ("crt_constructor"));
-
- if (apply_pragma_crt (d, isctor) > 1)
- error_at (make_location_t (d->loc),
- "can only apply to a single declaration");
- }
visit ((AttribDeclaration *) d);
}
@@ -422,7 +357,7 @@ public:
void visit (StructDeclaration *d)
{
- if (d->semanticRun >= PASSobj)
+ if (d->semanticRun >= PASS::obj)
return;
if (d->type->ty == TY::Terror)
@@ -470,7 +405,7 @@ public:
if (d->xhash)
this->build_dsymbol (d->xhash);
- d->semanticRun = PASSobj;
+ d->semanticRun = PASS::obj;
}
/* Finish semantic analysis of functions in vtbl for class CD. */
@@ -537,7 +472,7 @@ public:
void visit (ClassDeclaration *d)
{
- if (d->semanticRun >= PASSobj)
+ if (d->semanticRun >= PASS::obj)
return;
if (d->type->ty == TY::Terror)
@@ -603,7 +538,7 @@ public:
if (TYPE_NAME (ctype))
d_pushdecl (TYPE_NAME (ctype));
- d->semanticRun = PASSobj;
+ d->semanticRun = PASS::obj;
}
/* Write out compiler generated TypeInfo and vtables for the given interface
@@ -611,7 +546,7 @@ public:
void visit (InterfaceDeclaration *d)
{
- if (d->semanticRun >= PASSobj)
+ if (d->semanticRun >= PASS::obj)
return;
if (d->type->ty == TY::Terror)
@@ -646,7 +581,7 @@ public:
if (TYPE_NAME (ctype))
d_pushdecl (TYPE_NAME (ctype));
- d->semanticRun = PASSobj;
+ d->semanticRun = PASS::obj;
}
/* Write out compiler generated TypeInfo and initializer for the given
@@ -654,7 +589,7 @@ public:
void visit (EnumDeclaration *d)
{
- if (d->semanticRun >= PASSobj)
+ if (d->semanticRun >= PASS::obj)
return;
if (d->errors || d->type->ty == TY::Terror)
@@ -685,7 +620,7 @@ public:
if (TYPE_NAME (ctype))
d_pushdecl (TYPE_NAME (ctype));
- d->semanticRun = PASSobj;
+ d->semanticRun = PASS::obj;
}
/* Finish up a variable declaration and push it into the current scope.
@@ -693,7 +628,7 @@ public:
void visit (VarDeclaration *d)
{
- if (d->semanticRun >= PASSobj)
+ if (d->semanticRun >= PASS::obj)
return;
if (d->type->ty == TY::Terror)
@@ -703,6 +638,21 @@ public:
return;
}
+ /* Variables of type `noreturn` are just placeholders, and evaluate to
+ `assert(0)` if ever read. */
+ if (d->type->isTypeNoreturn ())
+ {
+ if (!d->isDataseg () && !d->isMember ()
+ && d->_init && !d->_init->isVoidInitializer ())
+ {
+ Expression *e = d->type->defaultInitLiteral (d->loc);
+ tree exp = build_expr (e);
+ add_stmt (exp);
+ }
+
+ return;
+ }
+
if (d->aliassym)
{
this->build_dsymbol (d->toAlias ());
@@ -762,7 +712,7 @@ public:
/* Frontend should have already caught this. */
gcc_assert (!integer_zerop (size)
- || d->type->toBasetype ()->ty == TY::Tsarray);
+ || d->type->toBasetype ()->isTypeSArray ());
d_finish_decl (decl);
@@ -797,7 +747,7 @@ public:
}
}
- d->semanticRun = PASSobj;
+ d->semanticRun = PASS::obj;
}
/* Generate and compile a static TypeInfo declaration, but only if it is
@@ -805,7 +755,7 @@ public:
void visit (TypeInfoDeclaration *d)
{
- if (d->semanticRun >= PASSobj)
+ if (d->semanticRun >= PASS::obj)
return;
if (speculative_type_p (d->tinfo))
@@ -814,7 +764,7 @@ public:
tree t = get_typeinfo_decl (d);
DECL_INITIAL (t) = layout_typeinfo (d);
d_finish_decl (t);
- d->semanticRun = PASSobj;
+ d->semanticRun = PASS::obj;
}
/* Finish up a function declaration and compile it all the way
@@ -823,7 +773,7 @@ public:
void visit (FuncDeclaration *d)
{
/* Already generated the function. */
- if (d->semanticRun >= PASSobj)
+ if (d->semanticRun >= PASS::obj)
return;
/* Don't emit any symbols from gcc.attribute module. */
@@ -861,7 +811,7 @@ public:
}
/* Ensure all semantic passes have run. */
- if (d->semanticRun < PASSsemantic3)
+ if (d->semanticRun < PASS::semantic3)
{
d->functionSemantic3 ();
Module::runDeferredSemantic3 ();
@@ -887,8 +837,8 @@ public:
message ("function %s", d->toPrettyChars ());
/* Start generating code for this function. */
- gcc_assert (d->semanticRun == PASSsemantic3done);
- d->semanticRun = PASSobj;
+ gcc_assert (d->semanticRun == PASS::semantic3done);
+ d->semanticRun = PASS::obj;
tree old_context = start_function (d);
@@ -927,12 +877,19 @@ public:
}
/* formal function parameters. */
- size_t n_parameters = d->parameters ? d->parameters->length : 0;
+ const size_t n_parameters = d->parameters ? d->parameters->length : 0;
for (size_t i = 0; i < n_parameters; i++)
{
VarDeclaration *param = (*d->parameters)[i];
+
parm_decl = get_symbol_decl (param);
+
+ /* Type `noreturn` is a terminator, as no other arguments can possibly
+ be evaluated after it. */
+ if (TREE_TYPE (parm_decl) == noreturn_type_node)
+ break;
+
/* Chain them in the correct order. */
param_list = chainon (param_list, parm_decl);
}
@@ -1136,9 +1093,9 @@ get_symbol_decl (Declaration *decl)
declaration_type (vd));
/* If any alignment was set on the declaration. */
- if (vd->alignment != STRUCTALIGN_DEFAULT)
+ if (!vd->alignment.isDefault ())
{
- SET_DECL_ALIGN (decl->csym, vd->alignment * BITS_PER_UNIT);
+ SET_DECL_ALIGN (decl->csym, vd->alignment.get () * BITS_PER_UNIT);
DECL_USER_ALIGN (decl->csym) = 1;
}
@@ -1321,6 +1278,20 @@ get_symbol_decl (Declaration *decl)
else if (fd->inlining == PINLINE::never)
DECL_UNINLINABLE (decl->csym) = 1;
+ /* In [pragma/crtctor], Annotates a function so it is run after the C
+ runtime library is initialized and before the D runtime library is
+ initialized. */
+ if (fd->isCrtCtorDtor == 1)
+ {
+ DECL_STATIC_CONSTRUCTOR (decl->csym) = 1;
+ decl_init_priority_insert (decl->csym, DEFAULT_INIT_PRIORITY);
+ }
+ else if (fd->isCrtCtorDtor == 2)
+ {
+ DECL_STATIC_DESTRUCTOR (decl->csym) = 1;
+ decl_fini_priority_insert (decl->csym, DEFAULT_INIT_PRIORITY);
+ }
+
/* Function was declared `naked'. */
if (fd->naked)
{
@@ -1342,7 +1313,7 @@ get_symbol_decl (Declaration *decl)
DECL_FINAL_P (decl->csym) = 1;
/* Function is of type `noreturn' or `typeof(*null)'. */
- if (fd->type->nextOf ()->ty == TY::Tnoreturn)
+ if (fd->type->nextOf ()->isTypeNoreturn ())
TREE_THIS_VOLATILE (decl->csym) = 1;
/* Check whether this function is expanded by the frontend. */
@@ -2246,9 +2217,9 @@ aggregate_initializer_decl (AggregateDeclaration *decl)
TREE_READONLY (sinit) = 1;
/* Honor struct alignment set by user. */
- if (sd && sd->alignment != STRUCTALIGN_DEFAULT)
+ if (sd && !sd->alignment.isDefault ())
{
- SET_DECL_ALIGN (sinit, sd->alignment * BITS_PER_UNIT);
+ SET_DECL_ALIGN (sinit, sd->alignment.get () * BITS_PER_UNIT);
DECL_USER_ALIGN (sinit) = true;
}
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 129050b..d23e1fe 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-b8384668f28741ad5884fc055a2bdb9c05fd95ec
+568496d5b6ed02d577dfa86f73c7bb4edee05813
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/README.md b/gcc/d/dmd/README.md
index 720d256..3cb7e12 100644
--- a/gcc/d/dmd/README.md
+++ b/gcc/d/dmd/README.md
@@ -20,6 +20,7 @@ this license for that file.
|--------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [dmd/](https://github.com/dlang/dmd/tree/master/src/dmd) | The dmd driver and front-end |
| [dmd/backend/](https://github.com/dlang/dmd/tree/master/src/dmd/backend) | Code generation for x86 or x86-64. Shared by the [Digital Mars C compiler](https://github.com/DigitalMars/Compiler/), but not [LDC](https://github.com/ldc-developers/ldc) or [GDC](https://gdcproject.org/). |
+| [dmd/common/](https://github.com/dlang/dmd/tree/master/src/dmd/common) | Code shared by the front-end and back-end |
| [dmd/root/](https://github.com/dlang/dmd/tree/master/src/dmd/root) | Meant as a portable utility library, but ["it wasn't very good and the only project left using it is dmd"](https://github.com/dlang/dmd/pull/9844#issuecomment-498479516). |
DMD has a mostly flat directory structure, so this section aims to divide all source files into logical groups for easier navigation.
@@ -126,6 +127,7 @@ Note that these groups have no strict meaning, the category assignments are a bi
| [optimize.d](https://github.com/dlang/dmd/blob/master/src/dmd/optimize.d) | Do constant folding more generally |
| [dcast.d](https://github.com/dlang/dmd/blob/master/src/dmd/dcast.d) | Implicit or explicit cast(), finding common types e.g. in `x ? a : b`, integral promotions |
| [impcnvtab.d](https://github.com/dlang/dmd/blob/master/src/dmd/impcnvtab.d) | Define an implicit conversion table for basic types |
+| [importc.d](https://github.com/dlang/dmd/blob/master/src/dmd/importc.d) | Helpers specific to ImportC |
| [sideeffect.d](https://github.com/dlang/dmd/blob/master/src/dmd/sideeffect.d) | Extract side-effects of expressions for certain lowerings. |
**Compile Time Function Execution (CTFE)**
@@ -243,14 +245,14 @@ Note that these groups have no strict meaning, the category assignments are a bi
Note: many other utilities are in [dmd/root](https://github.com/dlang/dmd/tree/master/src/dmd/root).
-| File | Purpose |
-|-----------------------------------------------------------------------------|---------------------------------------------------|
-| [env.d](https://github.com/dlang/dmd/blob/master/src/dmd/env.d) | Modify environment variables |
-| [console.d](https://github.com/dlang/dmd/blob/master/src/dmd/console.d) | Print error messages in color |
-| [utf.d](https://github.com/dlang/dmd/blob/master/src/dmd/utf.d) | Encoding/decoding Unicode text |
-| [filecache.d](https://github.com/dlang/dmd/blob/master/src/dmd/filecache.d) | Keep file contents in memory |
-| [utils.d](https://github.com/dlang/dmd/blob/master/src/dmd/utils.d) | Utility functions related to files and file paths |
-| [complex.d](https://github.com/dlang/dmd/blob/master/src/dmd/complex.d) | A complex number type |
+| File | Purpose |
+|-----------------------------------------------------------------------------------|---------------------------------------------------|
+| [env.d](https://github.com/dlang/dmd/blob/master/src/dmd/env.d) | Modify environment variables |
+| [console.d](https://github.com/dlang/dmd/blob/master/src/dmd/console.d) | Print error messages in color |
+| [utf.d](https://github.com/dlang/dmd/blob/master/src/dmd/utf.d) | Encoding/decoding Unicode text |
+| [file_manager.d](https://github.com/dlang/dmd/blob/master/src/dmd/file_manager.d) | Keep file contents in memory |
+| [utils.d](https://github.com/dlang/dmd/blob/master/src/dmd/utils.d) | Utility functions related to files and file paths |
+| [complex.d](https://github.com/dlang/dmd/blob/master/src/dmd/complex.d) | A complex number type |
| File | Purpose |
|---------------------------------------------------------------------------------|---------------------------------------------------------------|
diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION
index 64ce79a..fa5940e 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@
-v2.097.2
+v2.098.0
diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d
index cff4b9f..1fe8e80 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/dmd/aggregate.d
@@ -21,6 +21,7 @@ import dmd.aliasthis;
import dmd.apply;
import dmd.arraytypes;
import dmd.astenums;
+import dmd.attrib;
import dmd.declaration;
import dmd.dscope;
import dmd.dstruct;
@@ -115,11 +116,12 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
AliasThis aliasthis; /// forward unresolved lookups to aliasthis
- DtorDeclarations dtors; /// Array of destructors
- DtorDeclaration dtor; /// aggregate destructor calling dtors and member constructors
- DtorDeclaration primaryDtor;/// non-deleting C++ destructor, same as dtor for D
+ DtorDeclarations userDtors; /// user-defined destructors (`~this()`) - mixins can yield multiple ones
+ DtorDeclaration aggrDtor; /// aggregate destructor calling userDtors and fieldDtor (and base class aggregate dtor for C++ classes)
+ DtorDeclaration dtor; /// the aggregate destructor exposed as `__xdtor` alias
+ /// (same as aggrDtor, except for C++ classes with virtual dtor on Windows)
DtorDeclaration tidtor; /// aggregate destructor used in TypeInfo (must have extern(D) ABI)
- FuncDeclaration fieldDtor; /// aggregate destructor for just the fields
+ DtorDeclaration fieldDtor; /// function destructing (non-inherited) fields
Expression getRTInfo; /// pointer to GC info generated by object.RTInfo(this)
@@ -177,7 +179,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
* Returns:
* false if failed to determine the size.
*/
- final bool determineSize(Loc loc)
+ final bool determineSize(const ref Loc loc)
{
//printf("AggregateDeclaration::determineSize() %s, sizeok = %d\n", toChars(), sizeok);
@@ -331,7 +333,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
* false if any errors occur.
* Otherwise, returns true and the missing arguments will be pushed in elements[].
*/
- final bool fill(Loc loc, Expressions* elements, bool ctorinit)
+ final bool fill(const ref Loc loc, Expressions* elements, bool ctorinit)
{
//printf("AggregateDeclaration::fill() %s\n", toChars());
assert(sizeok == Sizeok.done);
@@ -482,45 +484,52 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
* Align sizes of 0, as we may not know array sizes yet.
* Params:
* alignment = struct alignment that is in effect
- * size = alignment requirement of field
+ * memalignsize = natural alignment of field
* poffset = pointer to offset to be aligned
*/
- extern (D) static void alignmember(structalign_t alignment, uint size, uint* poffset) pure nothrow @safe
+ extern (D) static void alignmember(structalign_t alignment, uint memalignsize, uint* poffset) pure nothrow @safe
{
- //printf("alignment = %d, size = %d, offset = %d\n",alignment,size,offset);
- switch (alignment)
- {
- case cast(structalign_t)1:
- // No alignment
- break;
+ //debug printf("alignment = %u %d, size = %u, offset = %u\n", alignment.get(), alignment.isPack(), memalignsize, *poffset);
+ uint alignvalue;
- case cast(structalign_t)STRUCTALIGN_DEFAULT:
+ if (alignment.isDefault())
+ {
// Alignment in Target::fieldalignsize must match what the
// corresponding C compiler's default alignment behavior is.
- assert(size > 0 && !(size & (size - 1)));
- *poffset = (*poffset + size - 1) & ~(size - 1);
- break;
-
- default:
+ alignvalue = memalignsize;
+ }
+ else if (alignment.isPack()) // #pragma pack semantics
+ {
+ alignvalue = alignment.get();
+ if (memalignsize < alignvalue)
+ alignvalue = memalignsize; // align to min(memalignsize, alignment)
+ }
+ else if (alignment.get() > 1)
+ {
// Align on alignment boundary, which must be a positive power of 2
- assert(alignment > 0 && !(alignment & (alignment - 1)));
- *poffset = (*poffset + alignment - 1) & ~(alignment - 1);
- break;
+ alignvalue = alignment.get();
}
+ else
+ return;
+
+ assert(alignvalue > 0 && !(alignvalue & (alignvalue - 1)));
+ *poffset = (*poffset + alignvalue - 1) & ~(alignvalue - 1);
}
/****************************************
- * Place a member (mem) into an aggregate (agg), which can be a struct, union or class
+ * Place a field (mem) into an aggregate (agg), which can be a struct, union or class
+ * Params:
+ * nextoffset = location just past the end of the previous field in the aggregate.
+ * Updated to be just past the end of this field to be placed, i.e. the future nextoffset
+ * memsize = size of field
+ * memalignsize = natural alignment of field
+ * alignment = alignment in effect for this field
+ * paggsize = size of aggregate (updated)
+ * paggalignsize = alignment of aggregate (updated)
+ * isunion = the aggregate is a union
* Returns:
- * offset to place field at
+ * aligned offset to place field at
*
- * nextoffset: next location in aggregate
- * memsize: size of member
- * memalignsize: natural alignment of member
- * alignment: alignment in effect for this member
- * paggsize: size of aggregate (updated)
- * paggalignsize: alignment of aggregate (updated)
- * isunion: the aggregate is a union
*/
extern (D) static uint placeField(uint* nextoffset, uint memsize, uint memalignsize,
structalign_t alignment, uint* paggsize, uint* paggalignsize, bool isunion)
@@ -528,7 +537,8 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
uint ofs = *nextoffset;
const uint actualAlignment =
- alignment == STRUCTALIGN_DEFAULT ? memalignsize : alignment;
+ alignment.isDefault() || alignment.isPack() && memalignsize < alignment.get()
+ ? memalignsize : alignment.get();
// Ensure no overflow
bool overflow;
@@ -536,7 +546,10 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
addu(ofs, sz, overflow);
if (overflow) assert(0);
- alignmember(alignment, memalignsize, &ofs);
+ // Skip no-op for noreturn without custom aligment
+ if (memsize != 0 || !alignment.isDefault())
+ alignmember(alignment, memalignsize, &ofs);
+
uint memoffset = ofs;
ofs += memsize;
if (ofs > *paggsize)
diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h
index f8d2f45..48e5f4a 100644
--- a/gcc/d/dmd/aggregate.h
+++ b/gcc/d/dmd/aggregate.h
@@ -105,11 +105,12 @@ public:
AliasThis *aliasthis; // forward unresolved lookups to aliasthis
- DtorDeclarations dtors; // Array of destructors
- DtorDeclaration *dtor; // aggregate destructor
- DtorDeclaration *primaryDtor; // non-deleting C++ destructor, same as dtor for D
+ DtorDeclarations userDtors; // user-defined destructors (`~this()`) - mixins can yield multiple ones
+ DtorDeclaration *aggrDtor; // aggregate destructor calling userDtors and fieldDtor (and base class aggregate dtor for C++ classes)
+ DtorDeclaration *dtor; // the aggregate destructor exposed as `__xdtor` alias
+ // (same as aggrDtor, except for C++ classes with virtual dtor on Windows)
DtorDeclaration *tidtor; // aggregate destructor used in TypeInfo (must have extern(D) ABI)
- FuncDeclaration *fieldDtor; // aggregate destructor for just the fields
+ DtorDeclaration *fieldDtor; // function destructing (non-inherited) fields
Expression *getRTInfo; // pointer to GC info generated by object.RTInfo(this)
@@ -121,10 +122,10 @@ public:
virtual Scope *newScope(Scope *sc);
void setScope(Scope *sc);
size_t nonHiddenFields();
- bool determineSize(Loc loc);
+ bool determineSize(const Loc &loc);
virtual void finalizeSize() = 0;
d_uns64 size(const Loc &loc);
- bool fill(Loc loc, Expressions *elements, bool ctorinit);
+ bool fill(const Loc &loc, Expressions *elements, bool ctorinit);
Type *getType();
bool isDeprecated() const; // is aggregate deprecated?
void setDeprecated();
@@ -184,7 +185,7 @@ public:
// ABI-specific type(s) if the struct can be passed in registers
TypeTuple *argTypes;
- static StructDeclaration *create(Loc loc, Identifier *id, bool inObject);
+ static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject);
StructDeclaration *syntaxCopy(Dsymbol *s);
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
const char *kind() const;
@@ -277,7 +278,7 @@ public:
ObjcClassDeclaration objc; // Data for a class declaration that is needed for the Objective-C integration
Symbol *cpp_type_info_ptr_sym; // cached instance of class Id.cpp_type_info_ptr
- static ClassDeclaration *create(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject);
+ static ClassDeclaration *create(const Loc &loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject);
const char *toPrettyChars(bool QualifyTypes = false);
ClassDeclaration *syntaxCopy(Dsymbol *s);
Scope *newScope(Scope *sc);
diff --git a/gcc/d/dmd/aliasthis.d b/gcc/d/dmd/aliasthis.d
index 81e0d7e..e048cdc 100644
--- a/gcc/d/dmd/aliasthis.d
+++ b/gcc/d/dmd/aliasthis.d
@@ -72,17 +72,32 @@ extern (C++) final class AliasThis : Dsymbol
}
}
-Expression resolveAliasThis(Scope* sc, Expression e, bool gag = false)
+/*************************************
+ * Find the `alias this` symbol of e's type.
+ * Params:
+ * sc = context
+ * e = expression forming the `this`
+ * gag = if true do not print errors, return null instead
+ * findOnly = don't do further processing like resolving properties,
+ * i.e. just return plain dotExp() result.
+ * Returns:
+ * Expression that is `e.aliasthis`
+ */
+Expression resolveAliasThis(Scope* sc, Expression e, bool gag = false, bool findOnly = false)
{
+ import dmd.typesem : dotExp;
for (AggregateDeclaration ad = isAggregate(e.type); ad;)
{
if (ad.aliasthis)
{
- uint olderrors = gag ? global.startGagging() : 0;
Loc loc = e.loc;
Type tthis = (e.op == TOK.type ? e.type : null);
- e = new DotIdExp(loc, e, ad.aliasthis.ident);
- e = e.expressionSemantic(sc);
+ const flags = DotExpFlag.noAliasThis | (gag ? DotExpFlag.gag : 0);
+ uint olderrors = gag ? global.startGagging() : 0;
+ e = dotExp(e.type, sc, e, ad.aliasthis.ident, flags);
+ if (!e || findOnly)
+ return gag && global.endGagging(olderrors) ? null : e;
+
if (tthis && ad.aliasthis.sym.needThis())
{
if (e.op == TOK.variable)
diff --git a/gcc/d/dmd/arrayop.d b/gcc/d/dmd/arrayop.d
index 66be73e..e2b3319 100644
--- a/gcc/d/dmd/arrayop.d
+++ b/gcc/d/dmd/arrayop.d
@@ -26,7 +26,7 @@ import dmd.globals;
import dmd.id;
import dmd.identifier;
import dmd.mtype;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.statement;
import dmd.tokens;
import dmd.visitor;
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index ae8f65b..0bf40ef 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -42,7 +42,7 @@ import dmd.id;
import dmd.identifier;
import dmd.mtype;
import dmd.objc; // for objc.addSymbols
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.target; // for target.systemLinkage
import dmd.tokens;
import dmd.visitor;
@@ -696,12 +696,9 @@ extern (C++) final class AlignDeclaration : AttribDeclaration
{
Expressions* exps; /// Expression(s) yielding the desired alignment,
/// the largest value wins
- enum structalign_t UNKNOWN = 0; /// alignment not yet computed
- static assert(STRUCTALIGN_DEFAULT != UNKNOWN);
-
- /// the actual alignment, `UNKNOWN` until it's either set to the value of `ealign`
- /// or `STRUCTALIGN_DEFAULT` if `ealign` is null ( / an error ocurred)
- structalign_t salign = UNKNOWN;
+ /// the actual alignment is Unknown until it's either set to the value of `ealign`
+ /// or the default if `ealign` is null ( / an error ocurred)
+ structalign_t salign;
extern (D) this(const ref Loc loc, Expression exp, Dsymbols* decl)
@@ -709,8 +706,7 @@ extern (C++) final class AlignDeclaration : AttribDeclaration
super(loc, null, decl);
if (exp)
{
- if (!exps)
- exps = new Expressions();
+ exps = new Expressions();
exps.push(exp);
}
}
@@ -721,6 +717,12 @@ extern (C++) final class AlignDeclaration : AttribDeclaration
this.exps = exps;
}
+ extern (D) this(const ref Loc loc, structalign_t salign, Dsymbols* decl)
+ {
+ super(loc, null, decl);
+ this.salign = salign;
+ }
+
override AlignDeclaration syntaxCopy(Dsymbol s)
{
assert(!s);
@@ -1196,7 +1198,7 @@ extern (C++) final class StaticForeachDeclaration : AttribDeclaration
// expand static foreach
import dmd.statementsem: makeTupleForeach;
- Dsymbols* d = makeTupleForeach!(true,true)(_scope, sfe.aggrfe, decl, sfe.needExpansion);
+ Dsymbols* d = makeTupleForeach!(true,true)(_scope, sfe.aggrfe, decl, sfe.needExpansion).decl;
if (d) // process generated declarations
{
// Add members lazily.
diff --git a/gcc/d/dmd/blockexit.d b/gcc/d/dmd/blockexit.d
index 1fd9005..0ecd635 100644
--- a/gcc/d/dmd/blockexit.d
+++ b/gcc/d/dmd/blockexit.d
@@ -108,7 +108,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
return;
}
}
- if (s.exp.type.toBasetype().isTypeNoreturn())
+ if (s.exp.type && s.exp.type.toBasetype().isTypeNoreturn())
result = BE.halt;
if (canThrow(s.exp, func, mustNotThrow))
result |= BE.throw_;
@@ -146,7 +146,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
else if (sd && (!sd.statement.hasCode() || sd.statement.isCaseStatement() || sd.statement.isErrorStatement()))
{
}
- else
+ else if (!func.getModule().isCFile)
{
const(char)* gototype = s.isCaseStatement() ? "case" : "default";
s.deprecation("switch case fallthrough - use 'goto %s;' if intended", gototype);
diff --git a/gcc/d/dmd/builtin.d b/gcc/d/dmd/builtin.d
index b99f690..c4f84b1 100644
--- a/gcc/d/dmd/builtin.d
+++ b/gcc/d/dmd/builtin.d
@@ -30,4 +30,4 @@ public extern (C++) BUILTIN isBuiltin(FuncDeclaration fd);
* Evaluate builtin function.
* Return result; NULL if cannot evaluate it.
*/
-public extern (C++) Expression eval_builtin(Loc loc, FuncDeclaration fd, Expressions* arguments);
+public extern (C++) Expression eval_builtin(const ref Loc loc, FuncDeclaration fd, Expressions* arguments);
diff --git a/gcc/d/dmd/chkformat.d b/gcc/d/dmd/chkformat.d
index 97adc5a..b168b4f 100644
--- a/gcc/d/dmd/chkformat.d
+++ b/gcc/d/dmd/chkformat.d
@@ -690,8 +690,8 @@ Format parsePrintfFormatSpecifier(scope const char[] format, ref size_t idx,
return error();
while ('0' <= format[i] && format[i] <= '9')
{
- ++i;
- if (i == length)
+ ++i;
+ if (i == length)
return error();
}
}
@@ -720,8 +720,8 @@ Format parsePrintfFormatSpecifier(scope const char[] format, ref size_t idx,
return error();
while ('0' <= format[i] && format[i] <= '9')
{
- ++i;
- if (i == length)
+ ++i;
+ if (i == length)
return error();
}
}
diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d
index d300617..da66812 100644
--- a/gcc/d/dmd/clone.d
+++ b/gcc/d/dmd/clone.d
@@ -794,6 +794,19 @@ FuncDeclaration buildXtoHash(StructDeclaration sd, Scope* sc)
if (!needToHash(sd))
return null;
+ /* The trouble is that the following code relies on .tupleof, but .tupleof
+ * is not allowed for C files. If we allow it for C files, then that turns on
+ * the other D properties, too, such as .dup which will then conflict with allowed
+ * field names.
+ * One way to fix it is to replace the following foreach and .tupleof with C
+ * statements and expressions.
+ * But, it's debatable whether C structs should even need toHash().
+ * Note that it would only be necessary if it has floating point fields.
+ * For now, we'll just not generate a toHash() for C files.
+ */
+ if (sc.flags & SCOPE.Cfile)
+ return null;
+
//printf("StructDeclaration::buildXtoHash() %s\n", sd.toPrettyChars());
Loc declLoc; // loc is unnecessary so __xtoHash is never called directly
Loc loc; // internal code should have no loc to prevent coverage
@@ -831,31 +844,31 @@ FuncDeclaration buildXtoHash(StructDeclaration sd, Scope* sc)
}
/*****************************************
- * Create inclusive destructor for struct/class by aggregating
- * all the destructors in dtors[] with the destructors for
+ * Create aggregate destructor for struct/class by aggregating
+ * all the destructors in userDtors[] with the destructors for
* all the members.
+ * Sets ad's fieldDtor, aggrDtor, dtor and tidtor fields.
* Params:
* ad = struct or class to build destructor for
* sc = context
- * Returns:
- * generated function, null if none needed
* Note:
* Close similarity with StructDeclaration::buildPostBlit(),
* and the ordering changes (runs backward instead of forwards).
*/
-DtorDeclaration buildDtor(AggregateDeclaration ad, Scope* sc)
+void buildDtors(AggregateDeclaration ad, Scope* sc)
{
//printf("AggregateDeclaration::buildDtor() %s\n", ad.toChars());
if (ad.isUnionDeclaration())
- return null; // unions don't have destructors
+ return; // unions don't have destructors
StorageClass stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
- Loc declLoc = ad.dtors.dim ? ad.dtors[0].loc : ad.loc;
+ Loc declLoc = ad.userDtors.dim ? ad.userDtors[0].loc : ad.loc;
Loc loc; // internal code should have no loc to prevent coverage
FuncDeclaration xdtor_fwd = null;
- // if the dtor is an extern(C++) prototype, then we expect it performs a full-destruction; we don't need to build a full-dtor
- const bool dtorIsCppPrototype = ad.dtors.dim == 1 && ad.dtors[0].linkage == LINK.cpp && !ad.dtors[0].fbody;
+ // Build the field destructor (`ad.fieldDtor`), if needed.
+ // If the user dtor is an extern(C++) prototype, then we expect it performs a full-destruction and skip building.
+ const bool dtorIsCppPrototype = ad.userDtors.dim && ad.userDtors[0].linkage == LINK.cpp && !ad.userDtors[0].fbody;
if (!dtorIsCppPrototype)
{
Expression e = null;
@@ -936,36 +949,6 @@ DtorDeclaration buildDtor(AggregateDeclaration ad, Scope* sc)
e = Expression.combine(ex, e); // combine in reverse order
}
- /* extern(C++) destructors call into super to destruct the full hierarchy
- */
- ClassDeclaration cldec = ad.isClassDeclaration();
- if (cldec && cldec.classKind == ClassKind.cpp && cldec.baseClass && cldec.baseClass.primaryDtor)
- {
- // WAIT BUT: do I need to run `cldec.baseClass.dtor` semantic? would it have been run before?
- cldec.baseClass.dtor.functionSemantic();
-
- stc = mergeFuncAttrs(stc, cldec.baseClass.primaryDtor);
- if (!(stc & STC.disable))
- {
- // super.__xdtor()
-
- Expression ex = new SuperExp(loc);
-
- // This is a hack so we can call destructors on const/immutable objects.
- // Do it as a type 'paint'.
- ex = new CastExp(loc, ex, cldec.baseClass.type.mutableOf());
- if (stc & STC.safe)
- stc = (stc & ~STC.safe) | STC.trusted;
-
- ex = new DotVarExp(loc, ex, cldec.baseClass.primaryDtor, false);
- ex = new CallExp(loc, ex);
-
- e = Expression.combine(e, ex); // super dtor last
- }
- }
-
- /* Build our own "destructor" which executes e
- */
if (e || (stc & STC.disable))
{
//printf("Building __fieldDtor(), %s\n", e.toChars());
@@ -973,29 +956,45 @@ DtorDeclaration buildDtor(AggregateDeclaration ad, Scope* sc)
dd.generated = true;
dd.storage_class |= STC.inference;
dd.fbody = new ExpStatement(loc, e);
- ad.dtors.shift(dd);
ad.members.push(dd);
dd.dsymbolSemantic(sc);
ad.fieldDtor = dd;
}
}
- DtorDeclaration xdtor = null;
- switch (ad.dtors.dim)
+ // Generate list of dtors to call in that order
+ DtorDeclarations dtors;
+ foreach_reverse (userDtor; ad.userDtors[])
+ dtors.push(userDtor);
+ if (ad.fieldDtor)
+ dtors.push(ad.fieldDtor);
+ if (!dtorIsCppPrototype)
+ {
+ // extern(C++) destructors call into super to destruct the full hierarchy
+ ClassDeclaration cldec = ad.isClassDeclaration();
+ if (cldec && cldec.classKind == ClassKind.cpp && cldec.baseClass && cldec.baseClass.aggrDtor)
+ dtors.push(cldec.baseClass.aggrDtor);
+ }
+
+ // Set/build `ad.aggrDtor`
+ switch (dtors.dim)
{
case 0:
break;
case 1:
- xdtor = ad.dtors[0];
+ // Use the single existing dtor directly as aggregate dtor.
+ // Note that this might be `cldec.baseClass.aggrDtor`.
+ ad.aggrDtor = dtors[0];
break;
default:
+ // Build the aggregate destructor, calling all dtors in order.
assert(!dtorIsCppPrototype);
Expression e = null;
e = null;
stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
- foreach (FuncDeclaration fd; ad.dtors)
+ foreach (FuncDeclaration fd; dtors)
{
stc = mergeFuncAttrs(stc, fd);
if (stc & STC.disable)
@@ -1005,8 +1004,9 @@ DtorDeclaration buildDtor(AggregateDeclaration ad, Scope* sc)
}
Expression ex = new ThisExp(loc);
ex = new DotVarExp(loc, ex, fd, false);
- ex = new CallExp(loc, ex);
- e = Expression.combine(ex, e);
+ CallExp ce = new CallExp(loc, ex);
+ ce.directcall = true;
+ e = Expression.combine(e, ce);
}
auto dd = new DtorDeclaration(declLoc, Loc.initial, stc, Id.__aggrDtor);
dd.generated = true;
@@ -1014,19 +1014,20 @@ DtorDeclaration buildDtor(AggregateDeclaration ad, Scope* sc)
dd.fbody = new ExpStatement(loc, e);
ad.members.push(dd);
dd.dsymbolSemantic(sc);
- xdtor = dd;
+ ad.aggrDtor = dd;
break;
}
- ad.primaryDtor = xdtor;
-
- if (xdtor && xdtor.linkage == LINK.cpp && !target.cpp.twoDtorInVtable)
- xdtor = buildWindowsCppDtor(ad, xdtor, sc);
+ // Set/build `ad.dtor`.
+ // On Windows, the dtor in the vtable is a shim with different signature.
+ ad.dtor = (ad.aggrDtor && ad.aggrDtor.linkage == LINK.cpp && !target.cpp.twoDtorInVtable)
+ ? buildWindowsCppDtor(ad, ad.aggrDtor, sc)
+ : ad.aggrDtor;
- // Add an __xdtor alias to make the inclusive dtor accessible
- if (xdtor)
+ // Add an __xdtor alias to make `ad.dtor` accessible
+ if (ad.dtor)
{
- auto _alias = new AliasDeclaration(Loc.initial, Id.__xdtor, xdtor);
+ auto _alias = new AliasDeclaration(Loc.initial, Id.__xdtor, ad.dtor);
_alias.dsymbolSemantic(sc);
ad.members.push(_alias);
if (xdtor_fwd)
@@ -1035,7 +1036,8 @@ DtorDeclaration buildDtor(AggregateDeclaration ad, Scope* sc)
_alias.addMember(sc, ad); // add to symbol table
}
- return xdtor;
+ // Set/build `ad.tidtor`
+ ad.tidtor = buildExternDDtor(ad, sc);
}
/**
@@ -1069,17 +1071,16 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara
auto ftype = new TypeFunction(ParameterList(params), Type.tvoidptr, LINK.cpp, dtor.storage_class);
auto func = new DtorDeclaration(dtor.loc, dtor.loc, dtor.storage_class, Id.cppdtor);
func.type = ftype;
- if (dtor.fbody)
- {
- const loc = dtor.loc;
- auto stmts = new Statements;
- auto call = new CallExp(loc, dtor, null);
- call.directcall = true;
- stmts.push(new ExpStatement(loc, call));
- stmts.push(new ReturnStatement(loc, new CastExp(loc, new ThisExp(loc), Type.tvoidptr)));
- func.fbody = new CompoundStatement(loc, stmts);
- func.generated = true;
- }
+
+ // Always generate the function with body, because it is not exported from DLLs.
+ const loc = dtor.loc;
+ auto stmts = new Statements;
+ auto call = new CallExp(loc, dtor, null);
+ call.directcall = true;
+ stmts.push(new ExpStatement(loc, call));
+ stmts.push(new ReturnStatement(loc, new CastExp(loc, new ThisExp(loc), Type.tvoidptr)));
+ func.fbody = new CompoundStatement(loc, stmts);
+ func.generated = true;
auto sc2 = sc.push();
sc2.stc &= ~STC.static_; // not a static destructor
@@ -1094,7 +1095,7 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara
}
/**
- * build a shim function around the compound dtor that translates
+ * build a shim function around the aggregate dtor that translates
* a C++ destructor to a destructor with extern(D) calling convention
*
* Params:
@@ -1104,9 +1105,9 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara
* Returns:
* the shim destructor, semantically analyzed and added to the class as a member
*/
-DtorDeclaration buildExternDDtor(AggregateDeclaration ad, Scope* sc)
+private DtorDeclaration buildExternDDtor(AggregateDeclaration ad, Scope* sc)
{
- auto dtor = ad.primaryDtor;
+ auto dtor = ad.aggrDtor;
if (!dtor)
return null;
diff --git a/gcc/d/dmd/common/README.md b/gcc/d/dmd/common/README.md
new file mode 100644
index 0000000..a9b65c3
--- /dev/null
+++ b/gcc/d/dmd/common/README.md
@@ -0,0 +1,7 @@
+# Table of contents
+
+| File | Purpose |
+|------------------------------------------------------------------------------------|-----------------------------------------------------------------|
+| [file.d](https://github.com/dlang/dmd/blob/master/src/dmd/common/file.d) | Functions and objects dedicated to file I/O and management |
+| [outbuffer.d](https://github.com/dlang/dmd/blob/master/src/dmd/common/outbuffer.d) | An expandable buffer in which you can write text or binary data |
+| [string.d](https://github.com/dlang/dmd/blob/master/src/dmd/common/string.d) | Common string functions including filename manipulation |
diff --git a/gcc/d/dmd/common/file.d b/gcc/d/dmd/common/file.d
new file mode 100644
index 0000000..b8cde37
--- /dev/null
+++ b/gcc/d/dmd/common/file.d
@@ -0,0 +1,576 @@
+/**
+ * File utilities.
+ *
+ * Functions and objects dedicated to file I/O and management. TODO: Move here artifacts
+ * from places such as root/ so both the frontend and the backend have access to them.
+ *
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
+ * Authors: Walter Bright, http://www.digitalmars.com
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/file.d, common/_file.d)
+ * Documentation: https://dlang.org/phobos/dmd_common_file.html
+ * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/file.d
+ */
+
+module dmd.common.file;
+
+import core.stdc.errno : errno;
+import core.stdc.stdio : fprintf, remove, rename, stderr;
+import core.stdc.stdlib : exit;
+import core.stdc.string : strerror;
+import core.sys.windows.winbase;
+import core.sys.windows.winnt;
+import core.sys.posix.fcntl;
+import core.sys.posix.unistd;
+
+import dmd.common.string;
+
+/**
+Encapsulated management of a memory-mapped file.
+
+Params:
+Datum = the mapped data type: Use a POD of size 1 for read/write mapping
+and a `const` version thereof for read-only mapping. Other primitive types
+should work, but have not been yet tested.
+*/
+struct FileMapping(Datum)
+{
+ static assert(__traits(isPOD, Datum) && Datum.sizeof == 1,
+ "Not tested with other data types yet. Add new types with care.");
+
+ version(Posix) enum invalidHandle = -1;
+ else version(Windows) enum invalidHandle = INVALID_HANDLE_VALUE;
+
+ // state {
+ /// Handle of underlying file
+ private auto handle = invalidHandle;
+ /// File mapping object needed on Windows
+ version(Windows) private HANDLE fileMappingObject = invalidHandle;
+ /// Memory-mapped array
+ private Datum[] data;
+ /// Name of underlying file, zero-terminated
+ private const(char)* name;
+ // state }
+
+ /**
+ Open `filename` and map it in memory. If `Datum` is `const`, opens for
+ read-only and maps the content in memory; no error is issued if the file
+ does not exist. This makes it easy to treat a non-existing file as empty.
+
+ If `Datum` is mutable, opens for read/write (creates file if it does not
+ exist) and fails fatally on any error.
+
+ Due to quirks in `mmap`, if the file is empty, `handle` is valid but `data`
+ is `null`. This state is valid and accounted for.
+
+ Params:
+ filename = the name of the file to be mapped in memory
+ */
+ this(const char* filename)
+ {
+ version (Posix)
+ {
+ import core.sys.posix.sys.mman;
+ import core.sys.posix.fcntl : open, O_CREAT, O_RDONLY, O_RDWR, S_IRGRP, S_IROTH, S_IRUSR, S_IWUSR;
+
+ handle = open(filename, is(Datum == const) ? O_RDONLY : (O_CREAT | O_RDWR),
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+ if (handle == invalidHandle)
+ {
+ static if (is(Datum == const))
+ {
+ // No error, nonexisting file in read mode behaves like an empty file.
+ return;
+ }
+ else
+ {
+ fprintf(stderr, "open(\"%s\") failed: %s\n", filename, strerror(errno));
+ exit(1);
+ }
+ }
+
+ const size = fileSize(handle);
+
+ if (size > 0 && size != ulong.max && size <= size_t.max)
+ {
+ auto p = mmap(null, cast(size_t) size, is(Datum == const) ? PROT_READ : PROT_WRITE, MAP_SHARED, handle, 0);
+ if (p == MAP_FAILED)
+ {
+ fprintf(stderr, "mmap(null, %zu) for \"%s\" failed: %s\n", cast(size_t) size, filename, strerror(errno));
+ exit(1);
+ }
+ // The cast below will always work because it's gated by the `size <= size_t.max` condition.
+ data = cast(Datum[]) p[0 .. cast(size_t) size];
+ }
+ }
+ else version(Windows)
+ {
+ static if (is(Datum == const))
+ {
+ enum createFileMode = GENERIC_READ;
+ enum openFlags = OPEN_EXISTING;
+ }
+ else
+ {
+ enum createFileMode = GENERIC_READ | GENERIC_WRITE;
+ enum openFlags = CREATE_ALWAYS;
+ }
+
+ handle = filename.asDString.extendedPathThen!(p => CreateFileW(p.ptr, createFileMode, 0, null, openFlags, FILE_ATTRIBUTE_NORMAL, null));
+ if (handle == invalidHandle)
+ {
+ static if (is(Datum == const))
+ {
+ return;
+ }
+ else
+ {
+ fprintf(stderr, "CreateFileW() failed for \"%s\": %d\n", filename, GetLastError());
+ exit(1);
+ }
+ }
+ createMapping(filename, fileSize(handle));
+ }
+ else static assert(0);
+
+ // Save the name for later. Technically there's no need: on Linux one can use readlink on /proc/self/fd/NNN.
+ // On BSD and OSX one can use fcntl with F_GETPATH. On Windows one can use GetFileInformationByHandleEx.
+ // But just saving the name is simplest, fastest, and most portable...
+ import core.stdc.string : strlen;
+ import core.stdc.stdlib : malloc;
+ import core.stdc.string : memcpy;
+ auto totalNameLength = filename.strlen() + 1;
+ name = cast(char*) memcpy(malloc(totalNameLength), filename, totalNameLength);
+ name || assert(0, "FileMapping: Out of memory.");
+ }
+
+ /**
+ Common code factored opportunistically. Windows only. Assumes `handle` is
+ already pointing to an opened file. Initializes the `fileMappingObject`
+ and `data` members.
+
+ Params:
+ filename = the file to be mapped
+ size = the size of the file in bytes
+ */
+ version(Windows) private void createMapping(const char* filename, ulong size)
+ {
+ assert(size <= size_t.max || size == ulong.max);
+ assert(handle != invalidHandle);
+ assert(data is null);
+ assert(fileMappingObject == invalidHandle);
+
+ if (size == 0 || size == ulong.max)
+ return;
+
+ static if (is(Datum == const))
+ {
+ enum fileMappingFlags = PAGE_READONLY;
+ enum mapViewFlags = FILE_MAP_READ;
+ }
+ else
+ {
+ enum fileMappingFlags = PAGE_READWRITE;
+ enum mapViewFlags = FILE_MAP_WRITE;
+ }
+
+ fileMappingObject = CreateFileMappingW(handle, null, fileMappingFlags, 0, 0, null);
+ if (!fileMappingObject)
+ {
+ fprintf(stderr, "CreateFileMappingW(%p) failed for %llu bytes of \"%s\": %d\n",
+ handle, size, filename, GetLastError());
+ fileMappingObject = invalidHandle; // by convention always use invalidHandle, not null
+ exit(1);
+ }
+ auto p = MapViewOfFile(fileMappingObject, mapViewFlags, 0, 0, 0);
+ if (!p)
+ {
+ fprintf(stderr, "MapViewOfFile() failed for \"%s\": %d\n", filename, GetLastError());
+ exit(1);
+ }
+ data = cast(Datum[]) p[0 .. cast(size_t) size];
+ }
+
+ // Not copyable or assignable (for now).
+ @disable this(const FileMapping!Datum rhs);
+ @disable void opAssign(const ref FileMapping!Datum rhs);
+
+ /**
+ Frees resources associated with this mapping. However, it does not deallocate the name.
+ */
+ ~this() pure nothrow
+ {
+ if (!active)
+ return;
+ fakePure({
+ version (Posix)
+ {
+ import core.sys.posix.sys.mman : munmap;
+ import core.sys.posix.unistd : close;
+
+ // Cannot call fprintf from inside a destructor, so exiting silently.
+
+ if (data.ptr && munmap(cast(void*) data.ptr, data.length) != 0)
+ {
+ exit(1);
+ }
+ data = null;
+ if (handle != invalidHandle && close(handle) != 0)
+ {
+ exit(1);
+ }
+ handle = invalidHandle;
+ }
+ else version(Windows)
+ {
+ if (data.ptr !is null && UnmapViewOfFile(cast(void*) data.ptr) == 0)
+ {
+ exit(1);
+ }
+ data = null;
+ if (fileMappingObject != invalidHandle && CloseHandle(fileMappingObject) == 0)
+ {
+ exit(1);
+ }
+ fileMappingObject = invalidHandle;
+ if (handle != invalidHandle && CloseHandle(handle) == 0)
+ {
+ exit(1);
+ }
+ handle = invalidHandle;
+ }
+ else static assert(0);
+ });
+ }
+
+ /**
+ Returns the zero-terminated file name associated with the mapping. Can NOT
+ be saved beyond the lifetime of `this`.
+ */
+ private const(char)* filename() const pure @nogc @safe nothrow { return name; }
+
+ /**
+ Frees resources associated with this mapping. However, it does not deallocate the name.
+ Reinitializes `this` as a fresh object that can be reused.
+ */
+ void close()
+ {
+ __dtor();
+ handle = invalidHandle;
+ version(Windows) fileMappingObject = invalidHandle;
+ data = null;
+ name = null;
+ }
+
+ /**
+ Deletes the underlying file and frees all resources associated.
+ Reinitializes `this` as a fresh object that can be reused.
+
+ This function does not abort if the file cannot be deleted, but does print
+ a message on `stderr` and returns `false` to the caller. The underlying
+ rationale is to give the caller the option to continue execution if
+ deleting the file is not important.
+
+ Returns: `true` iff the file was successfully deleted. If the file was not
+ deleted, prints a message to `stderr` and returns `false`.
+ */
+ static if (!is(Datum == const))
+ bool discard()
+ {
+ // Truncate file to zero so unflushed buffers are not flushed unnecessarily.
+ resize(0);
+ auto deleteme = name;
+ close();
+ // In-memory resource freed, now get rid of the underlying temp file.
+ version(Posix)
+ {
+ import core.sys.posix.unistd : unlink;
+ if (unlink(deleteme) != 0)
+ {
+ fprintf(stderr, "unlink(\"%s\") failed: %s\n", filename, strerror(errno));
+ return false;
+ }
+ }
+ else version(Windows)
+ {
+ import core.sys.windows.winbase;
+ if (deleteme.asDString.extendedPathThen!(p => DeleteFileW(p.ptr)) == 0)
+ {
+ fprintf(stderr, "DeleteFileW error %d\n", GetLastError());
+ return false;
+ }
+ }
+ else static assert(0);
+ return true;
+ }
+
+ /**
+ Queries whether `this` is currently associated with a file.
+
+ Returns: `true` iff there is an active mapping.
+ */
+ bool active() const pure @nogc nothrow
+ {
+ return handle !is invalidHandle;
+ }
+
+ /**
+ Queries the length of the file associated with this mapping. If not
+ active, returns 0.
+
+ Returns: the length of the file, or 0 if no file associated.
+ */
+ size_t length() const pure @nogc @safe nothrow { return data.length; }
+
+ /**
+ Get a slice to the contents of the entire file.
+
+ Returns: the contents of the file. If not active, returns the `null` slice.
+ */
+ auto opSlice() pure @nogc @safe nothrow { return data; }
+
+ /**
+ Resizes the file and mapping to the specified `size`.
+
+ Params:
+ size = new length requested
+ */
+ static if (!is(Datum == const))
+ void resize(size_t size) pure
+ {
+ assert(handle != invalidHandle);
+ fakePure({
+ version(Posix)
+ {
+ import core.sys.posix.unistd : ftruncate;
+ import core.sys.posix.sys.mman;
+
+ if (data.length)
+ {
+ assert(data.ptr, "Corrupt memory mapping");
+ // assert(0) here because it would indicate an internal error
+ munmap(cast(void*) data.ptr, data.length) == 0 || assert(0);
+ data = null;
+ }
+ if (ftruncate(handle, size) != 0)
+ {
+ fprintf(stderr, "ftruncate() failed for \"%s\": %s\n", filename, strerror(errno));
+ exit(1);
+ }
+ if (size > 0)
+ {
+ auto p = mmap(null, size, PROT_WRITE, MAP_SHARED, handle, 0);
+ if (cast(ssize_t) p == -1)
+ {
+ fprintf(stderr, "mmap() failed for \"%s\": %s\n", filename, strerror(errno));
+ exit(1);
+ }
+ data = cast(Datum[]) p[0 .. size];
+ }
+ }
+ else version(Windows)
+ {
+ // Per documentation, must unmap first.
+ if (data.length > 0 && UnmapViewOfFile(cast(void*) data.ptr) == 0)
+ {
+ fprintf(stderr, "UnmapViewOfFile(%p) failed for memory mapping of \"%s\": %d\n",
+ data.ptr, filename, GetLastError());
+ exit(1);
+ }
+ data = null;
+ if (fileMappingObject != invalidHandle && CloseHandle(fileMappingObject) == 0)
+ {
+ fprintf(stderr, "CloseHandle() failed for memory mapping of \"%s\": %d\n", filename, GetLastError());
+ exit(1);
+ }
+ fileMappingObject = invalidHandle;
+ LARGE_INTEGER biggie;
+ biggie.QuadPart = size;
+ if (SetFilePointerEx(handle, biggie, null, FILE_BEGIN) == 0 || SetEndOfFile(handle) == 0)
+ {
+ fprintf(stderr, "SetFilePointer() failed for \"%s\": %d\n", filename, GetLastError());
+ exit(1);
+ }
+ createMapping(name, size);
+ }
+ else static assert(0);
+ });
+ }
+
+ /**
+ Unconditionally and destructively moves the underlying file to `filename`.
+ If the operation succeeds, returns true. Upon failure, prints a message to
+ `stderr` and returns `false`. In all cases it closes the underlying file.
+
+ Params: filename = zero-terminated name of the file to move to.
+
+ Returns: `true` iff the operation was successful.
+ */
+ bool moveToFile(const char* filename)
+ {
+ assert(name !is null);
+
+ // Fetch the name and then set it to `null` so it doesn't get deallocated
+ auto oldname = name;
+ import core.stdc.stdlib;
+ scope(exit) free(cast(void*) oldname);
+ name = null;
+ close();
+
+ // Rename the underlying file to the target, no copy necessary.
+ version(Posix)
+ {
+ if (.rename(oldname, filename) != 0)
+ {
+ fprintf(stderr, "rename(\"%s\", \"%s\") failed: %s\n", oldname, filename, strerror(errno));
+ return false;
+ }
+ }
+ else version(Windows)
+ {
+ import core.sys.windows.winbase;
+ auto r = oldname.asDString.extendedPathThen!(
+ p1 => filename.asDString.extendedPathThen!(p2 => MoveFileExW(p1.ptr, p2.ptr, MOVEFILE_REPLACE_EXISTING))
+ );
+ if (r == 0)
+ {
+ fprintf(stderr, "MoveFileExW(\"%s\", \"%s\") failed: %d\n", oldname, filename, GetLastError());
+ return false;
+ }
+ }
+ else static assert(0);
+ return true;
+ }
+}
+
+/// Write a file, returning `true` on success.
+extern(D) static bool writeFile(const(char)* name, const void[] data) nothrow
+{
+ version (Posix)
+ {
+ int fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, (6 << 6) | (4 << 3) | 4);
+ if (fd == -1)
+ goto err;
+ if (.write(fd, data.ptr, data.length) != data.length)
+ goto err2;
+ if (close(fd) == -1)
+ goto err;
+ return true;
+ err2:
+ close(fd);
+ .remove(name);
+ err:
+ return false;
+ }
+ else version (Windows)
+ {
+ DWORD numwritten; // here because of the gotos
+ const nameStr = name.asDString;
+ // work around Windows file path length limitation
+ // (see documentation for extendedPathThen).
+ HANDLE h = nameStr.extendedPathThen!
+ (p => CreateFileW(p.ptr,
+ GENERIC_WRITE,
+ 0,
+ null,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
+ null));
+ if (h == INVALID_HANDLE_VALUE)
+ goto err;
+
+ if (WriteFile(h, data.ptr, cast(DWORD)data.length, &numwritten, null) != TRUE)
+ goto err2;
+ if (numwritten != data.length)
+ goto err2;
+ if (!CloseHandle(h))
+ goto err;
+ return true;
+ err2:
+ CloseHandle(h);
+ nameStr.extendedPathThen!(p => DeleteFileW(p.ptr));
+ err:
+ return false;
+ }
+ else
+ {
+ static assert(0);
+ }
+}
+
+/// Touch a file to current date
+bool touchFile(const char* namez)
+{
+ version (Windows)
+ {
+ FILETIME ft = void;
+ SYSTEMTIME st = void;
+ GetSystemTime(&st);
+ SystemTimeToFileTime(&st, &ft);
+
+ import core.stdc.string : strlen;
+
+ // get handle to file
+ HANDLE h = namez[0 .. namez.strlen()].extendedPathThen!(p => CreateFile(p.ptr,
+ FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ null, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, null));
+ if (h == INVALID_HANDLE_VALUE)
+ return false;
+
+ const f = SetFileTime(h, null, null, &ft); // set last write time
+
+ if (!CloseHandle(h))
+ return false;
+
+ return f != 0;
+ }
+ else version (Posix)
+ {
+ import core.sys.posix.utime;
+ return utime(namez, null) == 0;
+ }
+ else
+ static assert(0);
+}
+
+// Feel free to make these public if used elsewhere.
+/**
+Size of a file in bytes.
+Params: fd = file handle
+Returns: file size in bytes, or `ulong.max` on any error.
+*/
+version (Posix)
+private ulong fileSize(int fd)
+{
+ import core.sys.posix.sys.stat;
+ stat_t buf;
+ if (fstat(fd, &buf) == 0)
+ return buf.st_size;
+ return ulong.max;
+}
+
+/// Ditto
+version (Windows)
+private ulong fileSize(HANDLE fd)
+{
+ ulong result;
+ if (GetFileSizeEx(fd, cast(LARGE_INTEGER*) &result) == 0)
+ return result;
+ return ulong.max;
+}
+
+/**
+Runs a non-pure function or delegate as pure code. Use with caution.
+
+Params:
+fun = the delegate to run, usually inlined: `fakePure({ ... });`
+
+Returns: whatever `fun` returns.
+*/
+private auto ref fakePure(F)(scope F fun) pure
+{
+ mixin("alias PureFun = " ~ F.stringof ~ " pure;");
+ return (cast(PureFun) fun)();
+}
diff --git a/gcc/d/dmd/root/outbuffer.d b/gcc/d/dmd/common/outbuffer.d
index e756917..c5a8437 100644
--- a/gcc/d/dmd/root/outbuffer.d
+++ b/gcc/d/dmd/common/outbuffer.d
@@ -9,14 +9,21 @@
* Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/outbuffer.d
*/
-module dmd.root.outbuffer;
+module dmd.common.outbuffer;
import core.stdc.stdarg;
import core.stdc.stdio;
import core.stdc.string;
-import dmd.root.rmem;
-import dmd.root.rootobject;
-import dmd.root.string;
+import core.stdc.stdlib;
+
+// In theory these functions should also restore errno, but we don't care because
+// we abort application on error anyway.
+extern (C) private pure @system @nogc nothrow
+{
+ pragma(mangle, "malloc") void* pureMalloc(size_t);
+ pragma(mangle, "realloc") void* pureRealloc(void* ptr, size_t size);
+ pragma(mangle, "free") void pureFree(void* ptr);
+}
debug
{
@@ -29,7 +36,7 @@ a contiguous array or a memory-mapped file.
*/
struct OutBuffer
{
- import dmd.root.file : FileMapping;
+ import dmd.common.file : FileMapping, touchFile, writeFile;
// IMPORTANT: PLEASE KEEP STATE AND DESTRUCTOR IN SYNC WITH DEFINITION IN ./outbuffer.h.
// state {
@@ -48,6 +55,14 @@ struct OutBuffer
// state }
/**
+ Construct given size.
+ */
+ this(size_t initialSize) nothrow
+ {
+ reserve(initialSize);
+ }
+
+ /**
Construct from filename. Will map the file into memory (or create it anew
if necessary) and start writing at the beginning of it.
@@ -56,14 +71,36 @@ struct OutBuffer
*/
@trusted this(const(char)* filename)
{
- fileMapping = new FileMapping!ubyte(filename);
+ FileMapping!ubyte model;
+ fileMapping = cast(FileMapping!ubyte*) malloc(model.sizeof);
+ memcpy(fileMapping, &model, model.sizeof);
+ fileMapping.__ctor(filename);
+ //fileMapping = new FileMapping!ubyte(filename);
data = (*fileMapping)[];
}
/**
+ Frees resources associated.
+ */
+ extern (C++) void dtor() nothrow @trusted
+ {
+ if (fileMapping)
+ {
+ if (fileMapping.active)
+ fileMapping.close();
+ fileMapping = null;
+ }
+ else
+ {
+ debug (stomp) memset(data.ptr, 0xFF, data.length);
+ free(data.ptr);
+ }
+ }
+
+ /**
Frees resources associated automatically.
*/
- extern (C++) ~this() pure nothrow
+ extern (C++) ~this() pure nothrow @trusted
{
if (fileMapping)
{
@@ -74,10 +111,23 @@ struct OutBuffer
else
{
debug (stomp) memset(data.ptr, 0xFF, data.length);
- mem.xfree(data.ptr);
+ pureFree(data.ptr);
}
}
+ /// For porting with ease from dmd.backend.outbuf.Outbuffer
+ ubyte* buf() nothrow {
+ return data.ptr;
+ }
+
+ /// For porting with ease from dmd.backend.outbuf.Outbuffer
+ ubyte** bufptr() nothrow {
+ static struct Array { size_t length; ubyte* ptr; }
+ auto a = cast(Array*) &data;
+ assert(a.length == data.length && a.ptr == data.ptr);
+ return &a.ptr;
+ }
+
extern (C++) size_t length() const pure @nogc @safe nothrow { return offset; }
/**********************
@@ -109,7 +159,7 @@ struct OutBuffer
else
{
debug (stomp) memset(data.ptr, 0xFF, data.length);
- mem.xfree(extractData());
+ pureFree(extractData());
}
}
@@ -141,17 +191,18 @@ struct OutBuffer
{
debug (stomp)
{
- auto p = cast(ubyte*)mem.xmalloc(size);
+ auto p = cast(ubyte*) pureMalloc(size);
+ p || assert(0, "OutBuffer: out of memory.");
memcpy(p, data.ptr, offset);
memset(data.ptr, 0xFF, data.length); // stomp old location
- mem.xfree(data.ptr);
+ pureFree(data.ptr);
memset(p + offset, 0xff, size - offset); // stomp unused data
}
else
{
- auto p = cast(ubyte*)mem.xrealloc(data.ptr, size);
- if (mem.isGCEnabled) // clear currently unused data to avoid false pointers
- memset(p + offset + nbytes, 0xff, size - offset - nbytes);
+ auto p = cast(ubyte*) pureRealloc(data.ptr, size);
+ p || assert(0, "OutBuffer: out of memory.");
+ memset(p + offset + nbytes, 0xff, size - offset - nbytes);
}
data = p[0 .. size];
}
@@ -164,7 +215,7 @@ struct OutBuffer
*/
extern (C++) void setsize(size_t size) pure nothrow @nogc @safe
{
- assert(size <= offset);
+ assert(size <= data.length);
offset = size;
}
@@ -185,6 +236,14 @@ struct OutBuffer
notlinehead = true;
}
+ // Write an array to the buffer, no reserve check
+ @trusted nothrow
+ void writen(const void *b, size_t len)
+ {
+ memcpy(data.ptr + offset, b, len);
+ offset += len;
+ }
+
extern (C++) void write(const(void)* data, size_t nbytes) pure nothrow
{
write(data[0 .. nbytes]);
@@ -199,27 +258,90 @@ struct OutBuffer
offset += buf.length;
}
- extern (C++) void writestring(const(char)* string) pure nothrow
+ /**
+ * Writes a 16 bit value, no reserve check.
+ */
+ @trusted nothrow
+ void write16n(int v)
{
- write(string.toDString);
+ auto x = cast(ushort) v;
+ data[offset] = x & 0x00FF;
+ data[offset + 1] = x >> 8u;
+ offset += 2;
}
+ /**
+ * Writes a 16 bit value.
+ */
+ void write16(int v) nothrow
+ {
+ auto u = cast(ushort) v;
+ write(&u, u.sizeof);
+ }
+
+ /**
+ * Writes a 32 bit int.
+ */
+ void write32(int v) nothrow @trusted
+ {
+ write(&v, v.sizeof);
+ }
+
+ /**
+ * Writes a 64 bit int.
+ */
+ @trusted void write64(long v) nothrow
+ {
+ write(&v, v.sizeof);
+ }
+
+ /// NOT zero-terminated
+ extern (C++) void writestring(const(char)* s) pure nothrow
+ {
+ if (!s)
+ return;
+ import core.stdc.string : strlen;
+ write(s[0 .. strlen(s)]);
+ }
+
+ /// ditto
void writestring(const(char)[] s) pure nothrow
{
write(s);
}
+ /// ditto
void writestring(string s) pure nothrow
{
write(s);
}
+ /// NOT zero-terminated, followed by newline
void writestringln(const(char)[] s) pure nothrow
{
writestring(s);
writenl();
}
+ // Zero-terminated
+ void writeString(const(char)* s) pure nothrow @trusted
+ {
+ write(s[0 .. strlen(s)+1]);
+ }
+
+ /// ditto
+ void writeString(const(char)[] s) pure nothrow
+ {
+ write(s);
+ writeByte(0);
+ }
+
+ /// ditto
+ void writeString(string s) pure nothrow
+ {
+ writeString(cast(const(char)[])(s));
+ }
+
extern (C++) void prependstring(const(char)* string) pure nothrow
{
size_t len = strlen(string);
@@ -244,6 +366,38 @@ struct OutBuffer
notlinehead = false;
}
+ // Write n zeros; return pointer to start of zeros
+ @trusted
+ void *writezeros(size_t n) nothrow
+ {
+ reserve(n);
+ auto result = memset(data.ptr + offset, 0, n);
+ offset += n;
+ return result;
+ }
+
+ // Position buffer to accept the specified number of bytes at offset
+ @trusted
+ void position(size_t where, size_t nbytes) nothrow
+ {
+ if (where + nbytes > data.length)
+ {
+ reserve(where + nbytes - offset);
+ }
+ offset = where;
+
+ debug assert(offset + nbytes <= data.length);
+ }
+
+ /**
+ * Writes an 8 bit byte, no reserve check.
+ */
+ extern (C++) @trusted nothrow
+ void writeByten(int b)
+ {
+ this.data[offset++] = cast(ubyte) b;
+ }
+
extern (C++) void writeByte(uint b) pure nothrow
{
if (doindent && !notlinehead && b != '\n')
@@ -369,14 +523,6 @@ struct OutBuffer
}
}
- extern (C++) void write(RootObject obj) /*nothrow*/
- {
- if (obj)
- {
- writestring(obj.toChars());
- }
- }
-
extern (C++) void fill0(size_t nbytes) pure nothrow
{
reserve(nbytes);
@@ -428,8 +574,8 @@ struct OutBuffer
break;
}
offset += count;
- if (mem.isGCEnabled)
- memset(data.ptr + offset, 0xff, psize - count);
+ // if (mem.isGCEnabled)
+ memset(data.ptr + offset, 0xff, psize - count);
}
static if (__VERSION__ < 2092)
@@ -460,7 +606,6 @@ struct OutBuffer
*/
extern (C++) void print(ulong u) pure nothrow
{
- //import core.internal.string; // not available
UnsignedStringBuf buf = void;
writestring(unsignedToTempString(u, buf));
}
@@ -558,6 +703,11 @@ struct OutBuffer
return extractData()[0 .. length];
}
+ extern (D) byte[] extractUbyteSlice(bool nullTerminate = false) pure nothrow
+ {
+ return cast(byte[]) extractSlice(nullTerminate);
+ }
+
// Append terminating null if necessary and get view of internal buffer
extern (C++) char* peekChars() pure nothrow
{
@@ -577,6 +727,36 @@ struct OutBuffer
return extractData();
}
+ void writesLEB128(int value) pure nothrow
+ {
+ while (1)
+ {
+ ubyte b = value & 0x7F;
+
+ value >>= 7; // arithmetic right shift
+ if ((value == 0 && !(b & 0x40)) ||
+ (value == -1 && (b & 0x40)))
+ {
+ writeByte(b);
+ break;
+ }
+ writeByte(b | 0x80);
+ }
+ }
+
+ void writeuLEB128(uint value) pure nothrow
+ {
+ do
+ {
+ ubyte b = value & 0x7F;
+
+ value >>= 7;
+ if (value)
+ b |= 0x80;
+ writeByte(b);
+ } while (value);
+ }
+
/**
Destructively saves the contents of `this` to `filename`. As an
optimization, if the file already has identical contents with the buffer,
@@ -591,7 +771,6 @@ struct OutBuffer
*/
extern(D) bool moveToFile(const char* filename)
{
- import dmd.root.file;
bool result = true;
const bool identical = this[] == FileMapping!(const ubyte)(filename)[];
@@ -615,12 +794,12 @@ struct OutBuffer
else
{
if (!identical)
- File.write(filename, this[]);
+ writeFile(filename, this[]);
destroy();
}
return identical
- ? result && File.touch(filename)
+ ? result && touchFile(filename)
: result;
}
}
@@ -645,7 +824,7 @@ char[] unsignedToTempString(ulong value, char[] buf, uint radix = 10) @safe pure
else
{
ubyte x = cast(ubyte)(value % radix);
- value = value / radix;
+ value /= radix;
buf[--i] = cast(char)((x < 10) ? x + '0' : x - 10 + 'a');
}
} while (value);
diff --git a/gcc/d/dmd/root/outbuffer.h b/gcc/d/dmd/common/outbuffer.h
index b635373..a5e3f9c 100644
--- a/gcc/d/dmd/root/outbuffer.h
+++ b/gcc/d/dmd/common/outbuffer.h
@@ -4,14 +4,14 @@
* http://www.digitalmars.com
* Distributed under the Boost Software License, Version 1.0.
* http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/dlang/dmd/blob/master/src/dmd/root/outbuffer.h
+ * https://github.com/dlang/dmd/blob/master/src/dmd/common/outbuffer.h
*/
#pragma once
-#include "dsystem.h"
-#include "dcompat.h"
-#include "rmem.h"
+#include "../root/dsystem.h"
+#include "../root/dcompat.h"
+#include "../root/rmem.h"
class RootObject;
@@ -22,7 +22,7 @@ private:
DArray<unsigned char> data;
d_size_t offset;
bool notlinehead;
- void* fileMapping; // pointer to a file mapping object not used on the C++ side
+ void *fileMapping; // pointer to a file mapping object not used on the C++ side
public:
bool doindent;
bool spaces;
diff --git a/gcc/d/dmd/common/string.d b/gcc/d/dmd/common/string.d
new file mode 100644
index 0000000..026374a
--- /dev/null
+++ b/gcc/d/dmd/common/string.d
@@ -0,0 +1,209 @@
+/**
+ * Common string functions including filename manipulation.
+ *
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
+ * Authors: Walter Bright, http://www.digitalmars.com
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/string.d, common/_string.d)
+ * Documentation: https://dlang.org/phobos/dmd_common_string.html
+ * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/string.d
+ */
+module dmd.common.string;
+
+/**
+Defines a temporary array using a fixed-length buffer as back store. If the length
+of the buffer suffices, it is readily used. Otherwise, `malloc` is used to
+allocate memory for the array and `free` is used for deallocation in the
+destructor.
+
+This type is meant to use exclusively as an automatic variable. It is not
+default constructible or copyable.
+*/
+struct SmallBuffer(T)
+{
+ import core.stdc.stdlib : malloc, free;
+
+ private T[] _extent;
+ private bool needsFree;
+
+ @disable this(); // no default ctor
+ @disable this(ref const SmallBuffer!T); // noncopyable, nonassignable
+
+ this(size_t len, T[] buffer)
+ {
+ if (len <= buffer.length)
+ {
+ _extent = buffer[0 .. len];
+ }
+ else
+ {
+ _extent = (cast(typeof(_extent.ptr)) malloc(len * _extent[0].sizeof))[0 .. len];
+ _extent.ptr || assert(0, "Out of memory.");
+ needsFree = true;
+ }
+ assert(this.length == len);
+ }
+
+ ~this()
+ {
+ if (needsFree)
+ free(_extent.ptr);
+ }
+
+ void create(size_t len)
+ {
+ if (len <= _extent.length)
+ {
+ _extent = _extent[0 .. len];
+ }
+ else
+ {
+ __dtor();
+ _extent = (cast(typeof(_extent.ptr)) malloc(len * _extent[0].sizeof))[0 .. len];
+ _extent.ptr || assert(0, "Out of memory.");
+ needsFree = true;
+ }
+ assert(this.length == len);
+ }
+
+ // Force accesses to extent to be scoped.
+ scope inout extent()
+ {
+ return _extent;
+ }
+
+ alias extent this;
+}
+
+/// ditto
+unittest
+{
+ char[230] buf = void;
+ auto a = SmallBuffer!char(10, buf);
+ assert(a[] is buf[0 .. 10]);
+ auto b = SmallBuffer!char(1000, buf);
+ assert(b[] !is buf[]);
+ b.create(1000);
+ assert(b.length == 1000);
+ assert(b[] !is buf[]);
+}
+
+/**
+Converts a zero-terminated C string to a D slice. Takes linear time and allocates no memory.
+
+Params:
+stringz = the C string to be converted
+
+Returns:
+a slice comprehending the string. The terminating 0 is not part of the slice.
+*/
+auto asDString(C)(C* stringz) pure @nogc nothrow
+{
+ import core.stdc.string : strlen;
+ return stringz[0 .. strlen(stringz)];
+}
+
+///
+unittest
+{
+ const char* p = "123".ptr;
+ assert(p.asDString == "123");
+}
+
+/**
+(Windows only) Converts a narrow string to a wide string using `buffer` as strorage. Returns a slice managed by
+`buffer` containing the converted string. The terminating zero is not part of the returned slice,
+but is guaranteed to follow it.
+*/
+version(Windows) wchar[] toWStringz(const(char)[] narrow, ref SmallBuffer!wchar buffer) nothrow
+{
+ import core.sys.windows.winnls : CP_ACP, MultiByteToWideChar;
+ // assume filenames encoded in system default Windows ANSI code page
+ enum CodePage = CP_ACP;
+
+ if (narrow is null)
+ return null;
+
+ const requiredLength = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, cast(int) buffer.length);
+ if (requiredLength < cast(int) buffer.length)
+ {
+ buffer[requiredLength] = 0;
+ return buffer[0 .. requiredLength];
+ }
+
+ buffer.create(requiredLength + 1);
+ const length = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, requiredLength);
+ assert(length == requiredLength);
+ buffer[length] = 0;
+ return buffer[0 .. length];
+}
+
+/**************************************
+* Converts a path to one suitable to be passed to Win32 API
+* functions that can deal with paths longer than 248
+* characters then calls the supplied function on it.
+*
+* Params:
+* path = The Path to call F on.
+*
+* Returns:
+* The result of calling F on path.
+*
+* References:
+* https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
+*/
+version(Windows) auto extendedPathThen(alias F)(const(char)[] path)
+{
+ import core.sys.windows.winbase;
+ import core.sys.windows.winnt;
+
+ if (!path.length)
+ return F((wchar[]).init);
+
+ wchar[1024] buf = void;
+ auto store = SmallBuffer!wchar(buf.length, buf);
+ auto wpath = toWStringz(path, store);
+
+ // GetFullPathNameW expects a sized buffer to store the result in. Since we don't
+ // know how large it has to be, we pass in null and get the needed buffer length
+ // as the return code.
+ const pathLength = GetFullPathNameW(&wpath[0],
+ 0 /*length8*/,
+ null /*output buffer*/,
+ null /*filePartBuffer*/);
+ if (pathLength == 0)
+ {
+ return F((wchar[]).init);
+ }
+
+ // wpath is the UTF16 version of path, but to be able to use
+ // extended paths, we need to prefix with `\\?\` and the absolute
+ // path.
+ static immutable prefix = `\\?\`w;
+
+ // prefix only needed for long names and non-UNC names
+ const needsPrefix = pathLength >= MAX_PATH && (wpath[0] != '\\' || wpath[1] != '\\');
+ const prefixLength = needsPrefix ? prefix.length : 0;
+
+ // +1 for the null terminator
+ const bufferLength = pathLength + prefixLength + 1;
+
+ wchar[1024] absBuf = void;
+ auto absPath = SmallBuffer!wchar(bufferLength, absBuf);
+
+ absPath[0 .. prefixLength] = prefix[0 .. prefixLength];
+
+ const absPathRet = GetFullPathNameW(&wpath[0],
+ cast(uint)(absPath.length - prefixLength - 1),
+ &absPath[prefixLength],
+ null /*filePartBuffer*/);
+
+ if (absPathRet == 0 || absPathRet > absPath.length - prefixLength)
+ {
+ return F((wchar[]).init);
+ }
+
+ absPath[$ - 1] = '\0';
+ // Strip null terminator from the slice
+ return F(absPath[0 .. $ - 1]);
+}
diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d
index d4a8b13..05bd4bd 100644
--- a/gcc/d/dmd/cond.d
+++ b/gcc/d/dmd/cond.d
@@ -28,7 +28,7 @@ import dmd.globals;
import dmd.identifier;
import dmd.mtype;
import dmd.typesem;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rootobject;
import dmd.root.string;
import dmd.tokens;
@@ -452,7 +452,6 @@ extern (C++) final class StaticForeach : RootObject
sc = sc.startCTFE();
aggrfe.aggr = aggrfe.aggr.expressionSemantic(sc);
sc = sc.endCTFE();
- aggrfe.aggr = aggrfe.aggr.optimize(WANTvalue);
}
if (aggrfe && aggrfe.aggr.type.toBasetype().ty == Terror)
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index bb40649..7d8ab67 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -23,7 +23,7 @@ import dmd.lexer;
import dmd.parse;
import dmd.errors;
import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rmem;
import dmd.root.rootobject;
import dmd.root.string;
@@ -72,6 +72,7 @@ final class CParser(AST) : Parser!AST
{
//printf("cparseTranslationUnit()\n");
symbols = new AST.Dsymbols();
+ addBuiltinDeclarations();
while (1)
{
if (token.value == TOK.endOfFile)
@@ -756,7 +757,6 @@ final class CParser(AST) : Parser!AST
switch (token.value)
{
case TOK.dot:
- case TOK.arrow:
nextToken();
if (token.value == TOK.identifier)
{
@@ -767,6 +767,19 @@ final class CParser(AST) : Parser!AST
error("identifier expected following `.`, not `%s`", token.toChars());
break;
+ case TOK.arrow:
+ nextToken();
+ if (token.value == TOK.identifier)
+ {
+ Identifier id = token.ident;
+ auto die = new AST.DotIdExp(loc, e, id);
+ die.arrow = true;
+ e = die;
+ break;
+ }
+ error("identifier expected following `->`, not `%s`", token.toChars());
+ break;
+
case TOK.plusPlus:
e = new AST.PostExp(TOK.plusPlus, loc, e);
break;
@@ -949,6 +962,7 @@ final class CParser(AST) : Parser!AST
nextToken();
auto t = cparseTypeName();
check(TOK.rightParenthesis);
+ pt = &token;
if (token.value == TOK.leftCurly)
{
@@ -957,6 +971,17 @@ final class CParser(AST) : Parser!AST
auto ce = new AST.CompoundLiteralExp(loc, t, ci);
return cparsePostfixOperators(ce);
}
+ else if (t.isTypeIdentifier() &&
+ token.value == TOK.leftParenthesis &&
+ !isCastExpression(pt))
+ {
+ /* this might actually be a function
+ * call that looks like `(a)(b)` or even `(a)(b,c)`
+ */
+ auto ie = new AST.IdentifierExp(loc, t.isTypeIdentifier().ident);
+ ie.parens = true; // disambiguate it from being a declaration
+ return new AST.CallExp(loc, ie, cparseArguments());
+ }
else
{
// ( type-name ) cast-expression
@@ -1451,6 +1476,7 @@ final class CParser(AST) : Parser!AST
auto symbolsSave = symbols;
Specifier specifier;
+ specifier.packalign = this.packalign;
auto tspec = cparseDeclarationSpecifiers(level, specifier);
/* If a declarator does not follow, it is unnamed
@@ -1459,7 +1485,8 @@ final class CParser(AST) : Parser!AST
{
nextToken();
auto tt = tspec.isTypeTag();
- if (!tt || !tt.id)
+ if (!tt ||
+ !tt.id && (tt.tok == TOK.struct_ || tt.tok == TOK.union_))
return; // legal but meaningless empty declaration, ignore it
/* `struct tag;` and `struct tag { ... };`
@@ -1493,7 +1520,7 @@ final class CParser(AST) : Parser!AST
{
Identifier id;
AST.Expression asmname;
- auto dt = cparseDeclarator(DTR.xdirect, tspec, id);
+ auto dt = cparseDeclarator(DTR.xdirect, tspec, id, specifier);
if (!dt)
{
panic();
@@ -1674,6 +1701,8 @@ final class CParser(AST) : Parser!AST
return;
case TOK.comma:
+ if (!symbolsSave)
+ symbolsSave = symbols;
nextToken();
break;
@@ -1720,8 +1749,9 @@ final class CParser(AST) : Parser!AST
*/
auto pl = ft.parameterList;
pl.hasIdentifierList = true; // semantic needs to know to adjust parameter types
- if (pl.varargs != AST.VarArg.none)
+ if (pl.varargs != AST.VarArg.none && pl.length)
error("function identifier-list cannot end with `...`");
+ ft.parameterList.varargs = AST.VarArg.variadic; // but C11 allows extra arguments
auto plLength = pl.length;
if (symbols.length != plLength)
error("%d identifiers does not match %d declarations", cast(int)plLength, cast(int)symbols.length);
@@ -1756,7 +1786,10 @@ final class CParser(AST) : Parser!AST
}
}
if (!p.type)
+ {
error("no declaration for identifier `%s`", p.ident.toChars());
+ p.type = AST.Type.terror;
+ }
}
}
@@ -2240,14 +2273,14 @@ final class CParser(AST) : Parser!AST
* declarator = declarator kind
* t = base type to start with
* pident = set to Identifier if there is one, null if not
- * storageClass = any storage classes seen so far that apply to a function
+ * specifier = specifiers in and out
* Returns:
* type declared. If a TypeFunction is returned, this.symbols is the
* symbol table for the parameter-type-list, which will contain any
* declared struct, union or enum tags.
*/
private AST.Type cparseDeclarator(DTR declarator, AST.Type t,
- out Identifier pident, StorageClass storageClass = 0)
+ out Identifier pident, ref Specifier specifier)
{
//printf("cparseDeclarator(%d)\n", declarator);
AST.Types constTypes; // all the Types that will need `const` applied to them
@@ -2285,6 +2318,8 @@ final class CParser(AST) : Parser!AST
const mod = cparseTypeQualifierList();
if (mod & MOD.xconst)
constTypes.push(t);
+ if (token.value == TOK.__attribute__)
+ cparseGnuAttributes(specifier);
continue;
default:
@@ -2352,8 +2387,9 @@ final class CParser(AST) : Parser!AST
}
else
{
- // An array of unknown size, fake it with a DArray
- ta = new AST.TypeDArray(t); // []
+ /* C11 6.7.6.2-4 An [ ] array is an incomplete array type
+ */
+ ta = new AST.TypeSArray(t);
}
check(TOK.rightBracket);
@@ -2388,7 +2424,7 @@ final class CParser(AST) : Parser!AST
/* C11 6.7.6.2-1: the element type shall not be an incomplete or
* function type.
*/
- if (ta.isTypeDArray() && !isVLA)
+ if (ta.isTypeSArray() && ta.isTypeSArray().isIncomplete() && !isVLA)
error("array type has incomplete element type `%s`", ta.toChars());
}
@@ -2489,9 +2525,10 @@ final class CParser(AST) : Parser!AST
AST.Type cparseTypeName()
{
Specifier specifier;
+ specifier.packalign.setDefault();
auto tspec = cparseSpecifierQualifierList(LVL.global, specifier);
Identifier id;
- return cparseDeclarator(DTR.xabstract, tspec, id);
+ return cparseDeclarator(DTR.xabstract, tspec, id, specifier);
}
/***********************************
@@ -2525,13 +2562,19 @@ final class CParser(AST) : Parser!AST
StorageClass varargsStc;
check(TOK.leftParenthesis);
- if (token.value == TOK.void_ && peekNext() == TOK.rightParenthesis)
+ if (token.value == TOK.void_ && peekNext() == TOK.rightParenthesis) // func(void)
{
nextToken();
nextToken();
return AST.ParameterList(parameters, varargs, varargsStc);
}
+ if (token.value == TOK.rightParenthesis) // func()
+ {
+ nextToken();
+ return AST.ParameterList(parameters, AST.VarArg.variadic, varargsStc);
+ }
+
/* The check for identifier-list comes later,
* when doing the trailing declaration-list (opt)
*/
@@ -2541,6 +2584,8 @@ final class CParser(AST) : Parser!AST
break;
if (token.value == TOK.dotDotDot)
{
+ if (parameters.length == 0) // func(...)
+ error("named parameter required before `...`");
varargs = AST.VarArg.variadic; // C-style variadics
nextToken();
check(TOK.rightParenthesis);
@@ -2548,10 +2593,16 @@ final class CParser(AST) : Parser!AST
}
Specifier specifier;
+ specifier.packalign.setDefault();
auto tspec = cparseDeclarationSpecifiers(LVL.prototype, specifier);
+ if (tspec && specifier.mod & MOD.xconst)
+ {
+ tspec = toConst(tspec);
+ specifier.mod = MOD.xnone; // 'used' it
+ }
Identifier id;
- auto t = cparseDeclarator(DTR.xparameter, tspec, id);
+ auto t = cparseDeclarator(DTR.xparameter, tspec, id, specifier);
if (specifier.mod & MOD.xconst)
t = toConst(t);
auto param = new AST.Parameter(STC.parameter, t, id, null, null);
@@ -2920,6 +2971,7 @@ final class CParser(AST) : Parser!AST
* enum gnu-attributes (opt) identifier
*/
Specifier specifier;
+ specifier.packalign.setDefault();
if (token.value == TOK.__attribute__)
cparseGnuAttributes(specifier);
@@ -2950,6 +3002,16 @@ final class CParser(AST) : Parser!AST
nextToken();
auto mloc = token.loc;
+ if (token.value == TOK.__attribute__)
+ {
+ /* gnu-attributes can appear here, but just scan and ignore them
+ * https://gcc.gnu.org/onlinedocs/gcc/Enumerator-Attributes.html
+ */
+ Specifier specifierx;
+ specifierx.packalign.setDefault();
+ cparseGnuAttributes(specifierx);
+ }
+
AST.Expression value;
if (token.value == TOK.assign)
{
@@ -2958,6 +3020,16 @@ final class CParser(AST) : Parser!AST
// TODO C11 6.7.2.2-2 value must fit into an int
}
+ if (token.value == TOK.__attribute__)
+ {
+ /* gnu-attributes can appear here, but just scan and ignore them
+ * https://gcc.gnu.org/onlinedocs/gcc/Enumerator-Attributes.html
+ */
+ Specifier specifierx;
+ specifierx.packalign.setDefault();
+ cparseGnuAttributes(specifierx);
+ }
+
auto em = new AST.EnumMember(mloc, ident, value, null, 0, null, null);
members.push(em);
@@ -3037,14 +3109,12 @@ final class CParser(AST) : Parser!AST
check(TOK.rightCurly);
if ((*members).length == 0) // C11 6.7.2.1-8
- /* TODO: not strict enough, should really be contains "no named members",
- * not just "no members".
- * I.e. an unnamed bit field, _Static_assert, etc, are not named members,
- * but will pass this check.
- * Be careful to detect named members that come anonymous structs.
- * Correctly doing this will likely mean moving it to typesem.d.
+ {
+ /* allow empty structs as an extension
+ * struct-declarator-list:
+ * struct-declarator (opt)
*/
- error("empty struct-declaration-list for `%s %s`", Token.toChars(structOrUnion), tag ? tag.toChars() : "Anonymous".ptr);
+ }
}
else if (!tag)
error("missing tag `identifier` after `%s`", Token.toChars(structOrUnion));
@@ -3083,7 +3153,13 @@ final class CParser(AST) : Parser!AST
auto symbolsSave = symbols;
Specifier specifier;
+ specifier.packalign = this.packalign;
auto tspec = cparseSpecifierQualifierList(LVL.member, specifier);
+ if (tspec && specifier.mod & MOD.xconst)
+ {
+ tspec = toConst(tspec);
+ specifier.mod = MOD.xnone; // 'used' it
+ }
/* If a declarator does not follow, it is unnamed
*/
@@ -3139,12 +3215,14 @@ final class CParser(AST) : Parser!AST
dt = tspec;
}
else
- dt = cparseDeclarator(DTR.xdirect, tspec, id);
- if (!dt)
{
- panic();
- nextToken();
- break; // error recovery
+ dt = cparseDeclarator(DTR.xdirect, tspec, id, specifier);
+ if (!dt)
+ {
+ panic();
+ nextToken();
+ break; // error recovery
+ }
}
AST.Expression width;
@@ -3155,9 +3233,6 @@ final class CParser(AST) : Parser!AST
width = cparseConstantExp();
}
- if (specifier.mod & MOD.xconst)
- dt = toConst(dt);
-
/* GNU Extensions
* struct-declarator:
* declarator gnu-attributes (opt)
@@ -3234,8 +3309,8 @@ final class CParser(AST) : Parser!AST
*/
private bool isCDeclaration(ref Token* pt)
{
- //printf("isCDeclaration()\n");
auto t = pt;
+ //printf("isCDeclaration() %s\n", t.toChars());
if (!isDeclarationSpecifiers(t))
return false;
@@ -3360,8 +3435,8 @@ final class CParser(AST) : Parser!AST
*/
private bool isAssignmentExpression(ref Token* pt)
{
- //printf("isAssignmentExpression()\n");
auto t = pt;
+ //printf("isAssignmentExpression() %s\n", t.toChars());
/* This doesn't actually check for grammar matching an
* assignment-expression. It just matches ( ) [ ] looking for
@@ -3384,6 +3459,15 @@ final class CParser(AST) : Parser!AST
case TOK.leftParenthesis:
if (!skipParens(t, &t))
return false;
+ /*
+ https://issues.dlang.org/show_bug.cgi?id=22267
+ Fix issue 22267: If the parser encounters the following
+ `identifier variableName = (expression);`
+ the initializer is not identified as such since the parentheses
+ cause the parser to keep walking indefinitely
+ (whereas `(1) + 1` would not be affected.).
+ */
+ any = true;
continue;
case TOK.leftBracket:
@@ -3391,6 +3475,11 @@ final class CParser(AST) : Parser!AST
return false;
continue;
+ case TOK.leftCurly:
+ if (!skipBraces(t))
+ return false;
+ continue;
+
default:
any = true; // assume token was part of an a-e
t = peek(t);
@@ -3427,6 +3516,7 @@ final class CParser(AST) : Parser!AST
auto t = pt;
+ bool seenType;
bool any;
while (1)
{
@@ -3445,9 +3535,19 @@ final class CParser(AST) : Parser!AST
case TOK._Bool:
//case TOK._Imaginary:
case TOK._Complex:
- case TOK.identifier: // typedef-name
t = peek(t);
+ seenType = true;
any = true;
+ continue;
+
+ case TOK.identifier: // typedef-name
+ if (!seenType)
+ {
+ t = peek(t);
+ seenType = true;
+ any = true;
+ continue;
+ }
break;
case TOK.struct_:
@@ -3878,6 +3978,10 @@ final class CParser(AST) : Parser!AST
t = tk;
break;
}
+
+ if (tk.value == TOK.leftParenthesis && peek(tk).value == TOK.rightParenthesis)
+ return false; // (type-name)() is not a cast (it might be a function call)
+
if (!isCastExpression(tk, true))
{
if (afterParenType) // could be ( type-name ) ( unary-expression )
@@ -4071,6 +4175,7 @@ final class CParser(AST) : Parser!AST
SCW scw; /// storage-class specifiers
MOD mod; /// type qualifiers
AST.Expressions* alignExps; /// alignment
+ structalign_t packalign; /// #pragma pack alignment value
}
/***********************
@@ -4089,19 +4194,19 @@ final class CParser(AST) : Parser!AST
if (level == LVL.global)
{
if (specifier.scw & SCW.xextern)
- stc = AST.STC.extern_;
+ stc = AST.STC.extern_;
}
else if (level == LVL.local)
{
if (specifier.scw & SCW.xextern)
- stc = AST.STC.extern_;
+ stc = AST.STC.extern_;
else if (specifier.scw & SCW.xstatic)
stc = AST.STC.static_;
}
else if (level == LVL.member)
{
if (specifier.scw & SCW.xextern)
- stc = AST.STC.extern_;
+ stc = AST.STC.extern_;
else if (specifier.scw & SCW.xstatic)
stc = AST.STC.static_;
}
@@ -4111,21 +4216,23 @@ final class CParser(AST) : Parser!AST
if (level == LVL.global)
{
if (specifier.scw & SCW.xextern)
- stc = AST.STC.extern_ | AST.STC.gshared;
+ stc = AST.STC.extern_ | AST.STC.gshared;
+ else if (specifier.scw & SCW.xstatic)
+ stc = AST.STC.gshared | AST.STC.static_;
else
stc = AST.STC.gshared;
}
else if (level == LVL.local)
{
if (specifier.scw & SCW.xextern)
- stc = AST.STC.extern_ | AST.STC.gshared;
+ stc = AST.STC.extern_ | AST.STC.gshared;
else if (specifier.scw & SCW.xstatic)
stc = AST.STC.gshared;
}
else if (level == LVL.member)
{
if (specifier.scw & SCW.xextern)
- stc = AST.STC.extern_ | AST.STC.gshared;
+ stc = AST.STC.extern_ | AST.STC.gshared;
else if (specifier.scw & SCW.xstatic)
stc = AST.STC.gshared;
}
@@ -4235,15 +4342,59 @@ final class CParser(AST) : Parser!AST
*/
private AST.Dsymbol applySpecifier(AST.Dsymbol s, ref Specifier specifier)
{
+ //printf("applySpecifier() %s\n", s.toChars());
if (specifier.alignExps)
{
+ //printf(" applying _Alignas %s, packalign %d\n", (*specifier.alignExps)[0].toChars(), cast(int)specifier.packalign);
// Wrap declaration in an AlignDeclaration
auto decls = new AST.Dsymbols(1);
(*decls)[0] = s;
s = new AST.AlignDeclaration(s.loc, specifier.alignExps, decls);
}
+ else if (!specifier.packalign.isDefault())
+ {
+ //printf(" applying packalign %d\n", cast(int)specifier.packalign);
+ // Wrap #pragma pack in an AlignDeclaration
+ auto decls = new AST.Dsymbols(1);
+ (*decls)[0] = s;
+ s = new AST.AlignDeclaration(s.loc, specifier.packalign, decls);
+ }
return s;
}
+ /***********************************
+ * Add global target-dependent builtin declarations.
+ */
+ private void addBuiltinDeclarations()
+ {
+ void genBuiltinFunc(Identifier id, AST.VarArg va)
+ {
+ auto tva_list = new AST.TypeIdentifier(Loc.initial, Id.builtin_va_list);
+ auto parameters = new AST.Parameters();
+ parameters.push(new AST.Parameter(STC.parameter | STC.ref_, tva_list, null, null, null));
+ auto pl = AST.ParameterList(parameters, va, 0);
+ auto tf = new AST.TypeFunction(pl, AST.Type.tvoid, LINK.c, 0);
+ auto s = new AST.FuncDeclaration(Loc.initial, Loc.initial, id, AST.STC.static_, tf, false);
+ symbols.push(s);
+ }
+
+ /* void __builtin_va_start(__builtin_va_list, ...);
+ * The second argument is supposed to be of any type, so fake it with the ...
+ */
+ genBuiltinFunc(Id.builtin_va_start, AST.VarArg.variadic);
+
+ /* void __builtin_va_end(__builtin_va_list);
+ */
+ genBuiltinFunc(Id.builtin_va_end, AST.VarArg.none);
+
+ /* struct __va_list_tag
+ * {
+ * uint, uint, void*, void*
+ * }
+ */
+ auto s = new AST.StructDeclaration(Loc.initial, Id.va_list_tag, false);
+ symbols.push(s);
+ }
+
//}
}
diff --git a/gcc/d/dmd/cppmangle.d b/gcc/d/dmd/cppmangle.d
index 0381f9a..df742c0 100644
--- a/gcc/d/dmd/cppmangle.d
+++ b/gcc/d/dmd/cppmangle.d
@@ -41,7 +41,7 @@ import dmd.identifier;
import dmd.mtype;
import dmd.nspace;
import dmd.root.array;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rootobject;
import dmd.root.string;
import dmd.target;
@@ -98,21 +98,20 @@ extern(C++) const(char)* cppThunkMangleItanium(FuncDeclaration fd, int offset)
}
/******************************
- * Determine if sym is the 'primary' destructor, that is,
- * the most-aggregate destructor (the one that is defined as __xdtor)
+ * Determine if sym is a full aggregate destructor.
* Params:
* sym = Dsymbol
* Returns:
- * true if sym is the primary destructor for an aggregate
+ * true if sym is an aggregate destructor
*/
-bool isPrimaryDtor(const Dsymbol sym)
+bool isAggregateDtor(const Dsymbol sym)
{
const dtor = sym.isDtorDeclaration();
if (!dtor)
return false;
const ad = dtor.isMember();
assert(ad);
- return dtor == ad.primaryDtor;
+ return dtor == ad.aggrDtor;
}
/// Context used when processing pre-semantic AST
@@ -1069,7 +1068,7 @@ private final class CppMangleVisitor : Visitor
if (auto ctor = d.isCtorDeclaration())
buf.writestring(ctor.isCpCtor ? "C2" : "C1");
- else if (d.isPrimaryDtor())
+ else if (d.isAggregateDtor())
buf.writestring("D1");
else if (d.ident && d.ident == Id.assign)
buf.writestring("aS");
@@ -1184,7 +1183,7 @@ private final class CppMangleVisitor : Visitor
mangleFunctionParameters(tf.parameterList);
return;
}
- else if (d.isPrimaryDtor())
+ else if (d.isAggregateDtor())
{
buf.writestring("D1");
mangleFunctionParameters(tf.parameterList);
diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d
index 22633a8..7f76d75 100644
--- a/gcc/d/dmd/ctfeexpr.d
+++ b/gcc/d/dmd/ctfeexpr.d
@@ -685,6 +685,11 @@ bool isSafePointerCast(Type srcPointee, Type destPointee)
// It's OK if both are the same (modulo const)
if (srcPointee.constConv(destPointee))
return true;
+
+ // It's ok to cast from/to shared because CTFE is single threaded anyways
+ if (srcPointee.unSharedOf() == destPointee.unSharedOf())
+ return true;
+
// It's OK if function pointers differ only in safe/pure/nothrow
if (srcPointee.ty == Tfunction && destPointee.ty == Tfunction)
return srcPointee.covariant(destPointee) == Covariant.yes ||
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 4c70565..87c3ada 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -31,12 +31,13 @@ import dmd.func;
import dmd.globals;
import dmd.impcnvtab;
import dmd.id;
+import dmd.importc;
import dmd.init;
import dmd.intrange;
import dmd.mtype;
import dmd.opover;
import dmd.root.ctfloat;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rmem;
import dmd.tokens;
import dmd.typesem;
@@ -1445,6 +1446,29 @@ MATCH implicitConvTo(Expression e, Type t)
if (tb.ty == Tpointer && e.e1.op == TOK.string_)
e.e1.accept(this);
}
+
+ override void visit(TupleExp e)
+ {
+ result = e.type.implicitConvTo(t);
+ if (result != MATCH.nomatch)
+ return;
+
+ /* If target type is a tuple of same length, test conversion of
+ * each expression to the corresponding type in the tuple.
+ */
+ TypeTuple totuple = t.isTypeTuple();
+ if (totuple && e.exps.length == totuple.arguments.length)
+ {
+ result = MATCH.exact;
+ foreach (i, ex; *e.exps)
+ {
+ auto to = (*totuple.arguments)[i].type;
+ MATCH mi = ex.implicitConvTo(to);
+ if (mi < result)
+ result = mi;
+ }
+ }
+ }
}
scope ImplicitConvTo v = new ImplicitConvTo(t);
@@ -1476,12 +1500,8 @@ MATCH cimplicitConvTo(Expression e, Type t)
return MATCH.convert;
if (tb.isintegral() && typeb.ty == Tpointer) // C11 6.3.2.3-6
return MATCH.convert;
- if (tb.ty == Tpointer && typeb.ty == Tpointer)
- {
- if (tb.isTypePointer().next.ty == Tvoid ||
- typeb.isTypePointer().next.ty == Tvoid)
- return MATCH.convert; // convert to/from void* C11 6.3.2.3-1
- }
+ if (tb.ty == Tpointer && typeb.ty == Tpointer) // C11 6.3.2.3-7
+ return MATCH.convert;
return implicitConvTo(e, t);
}
@@ -2189,13 +2209,20 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
return;
}
+ /* If target type is a tuple of same length, cast each expression to
+ * the corresponding type in the tuple.
+ */
+ TypeTuple totuple;
+ if (auto tt = t.isTypeTuple())
+ totuple = e.exps.length == tt.arguments.length ? tt : null;
+
TupleExp te = e.copy().isTupleExp();
te.e0 = e.e0 ? e.e0.copy() : null;
te.exps = e.exps.copy();
for (size_t i = 0; i < te.exps.dim; i++)
{
Expression ex = (*te.exps)[i];
- ex = ex.castTo(sc, t);
+ ex = ex.castTo(sc, totuple ? (*totuple.arguments)[i].type : t);
(*te.exps)[i] = ex;
}
result = te;
@@ -2821,6 +2848,13 @@ Type typeMerge(Scope* sc, TOK op, ref Expression pe1, ref Expression pe2)
Expression e1 = pe1;
Expression e2 = pe2;
+ // ImportC: do array/function conversions
+ if (sc)
+ {
+ e1 = e1.arrayFuncConv(sc);
+ e2 = e2.arrayFuncConv(sc);
+ }
+
Type Lret(Type result)
{
pe1 = e1;
@@ -2838,7 +2872,7 @@ Type typeMerge(Scope* sc, TOK op, ref Expression pe1, ref Expression pe2)
return result;
}
- /// Converts one of the expression too the other
+ /// Converts one of the expression to the other
Type convert(ref Expression from, Type to)
{
from = from.castTo(sc, to);
@@ -2856,6 +2890,22 @@ Type typeMerge(Scope* sc, TOK op, ref Expression pe1, ref Expression pe2)
Type t1b = e1.type.toBasetype();
Type t2b = e2.type.toBasetype();
+ if (sc && sc.flags & SCOPE.Cfile)
+ {
+ // Integral types can be implicitly converted to pointers
+ if ((t1b.ty == Tpointer) != (t2b.ty == Tpointer))
+ {
+ if (t1b.isintegral())
+ {
+ return convert(e1, t2b);
+ }
+ else if (t2b.isintegral())
+ {
+ return convert(e2, t1b);
+ }
+ }
+ }
+
if (op != TOK.question || t1b.ty != t2b.ty && (t1b.isTypeBasic() && t2b.isTypeBasic()))
{
if (op == TOK.question && t1b.ty.isSomeChar() && t2b.ty.isSomeChar())
@@ -3132,6 +3182,14 @@ Lagain:
Lcc:
while (1)
{
+ MATCH i1woat = MATCH.exact;
+ MATCH i2woat = MATCH.exact;
+
+ if (auto t2c = t2.isTypeClass())
+ i1woat = t2c.implicitConvToWithoutAliasThis(t1);
+ if (auto t1c = t1.isTypeClass())
+ i2woat = t1c.implicitConvToWithoutAliasThis(t2);
+
MATCH i1 = e2.implicitConvTo(t1);
MATCH i2 = e1.implicitConvTo(t2);
@@ -3144,11 +3202,26 @@ Lagain:
i2 = MATCH.nomatch;
}
- if (i2)
+ // Match but without 'alias this' on classes
+ if (i2 && i2woat)
return coerce(t2);
- if (i1)
+ if (i1 && i1woat)
return coerce(t1);
+ // Here use implicitCastTo() instead of castTo() to try 'alias this' on classes
+ Type coerceImplicit(Type towards)
+ {
+ e1 = e1.implicitCastTo(sc, towards);
+ e2 = e2.implicitCastTo(sc, towards);
+ return Lret(towards);
+ }
+
+ // Implicit conversion with 'alias this'
+ if (i2)
+ return coerceImplicit(t2);
+ if (i1)
+ return coerceImplicit(t1);
+
if (t1.ty == Tclass && t2.ty == Tclass)
{
TypeClass tc1 = t1.isTypeClass();
@@ -3257,29 +3330,26 @@ Lagain:
}
}
- if (t1.ty == Tstruct || t2.ty == Tstruct)
+ if (t1.ty == Tstruct && t1.isTypeStruct().sym.aliasthis)
{
- if (t1.ty == Tstruct && t1.isTypeStruct().sym.aliasthis)
- {
- if (isRecursiveAliasThis(att1, e1.type))
- return null;
- //printf("att tmerge(s || s) e1 = %s\n", e1.type.toChars());
- e1 = resolveAliasThis(sc, e1);
- t1 = e1.type;
- t = t1;
- goto Lagain;
- }
- if (t2.ty == Tstruct && t2.isTypeStruct().sym.aliasthis)
- {
- if (isRecursiveAliasThis(att2, e2.type))
- return null;
- //printf("att tmerge(s || s) e2 = %s\n", e2.type.toChars());
- e2 = resolveAliasThis(sc, e2);
- t2 = e2.type;
- t = t2;
- goto Lagain;
- }
- return null;
+ if (isRecursiveAliasThis(att1, e1.type))
+ return null;
+ //printf("att tmerge(s || s) e1 = %s\n", e1.type.toChars());
+ e1 = resolveAliasThis(sc, e1);
+ t1 = e1.type;
+ t = t1;
+ goto Lagain;
+ }
+
+ if (t2.ty == Tstruct && t2.isTypeStruct().sym.aliasthis)
+ {
+ if (isRecursiveAliasThis(att2, e2.type))
+ return null;
+ //printf("att tmerge(s || s) e2 = %s\n", e2.type.toChars());
+ e2 = resolveAliasThis(sc, e2);
+ t2 = e2.type;
+ t = t2;
+ goto Lagain;
}
if ((e1.op == TOK.string_ || e1.op == TOK.null_) && e1.implicitConvTo(t2))
diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d
index b065251..34a236b 100644
--- a/gcc/d/dmd/dclass.d
+++ b/gcc/d/dmd/dclass.d
@@ -20,6 +20,7 @@ import dmd.aggregate;
import dmd.apply;
import dmd.arraytypes;
import dmd.astenums;
+import dmd.attrib;
import dmd.gluelayer;
import dmd.declaration;
import dmd.dscope;
@@ -367,7 +368,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
baseok = Baseok.none;
}
- static ClassDeclaration create(Loc loc, Identifier id, BaseClasses* baseclasses, Dsymbols* members, bool inObject)
+ static ClassDeclaration create(const ref Loc loc, Identifier id, BaseClasses* baseclasses, Dsymbols* members, bool inObject)
{
return new ClassDeclaration(loc, id, baseclasses, members, inObject);
}
@@ -607,7 +608,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
if (!b.sym.alignsize)
b.sym.alignsize = target.ptrsize;
- alignmember(b.sym.alignsize, b.sym.alignsize, &offset);
+ alignmember(structalign_t(cast(ushort)b.sym.alignsize), b.sym.alignsize, &offset);
assert(bi < vtblInterfaces.dim);
BaseClass* bv = (*vtblInterfaces)[bi];
@@ -725,6 +726,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
void searchVtbl(ref Dsymbols vtbl)
{
+ bool seenInterfaceVirtual;
foreach (s; vtbl)
{
auto fd = s.isFuncDeclaration();
@@ -748,6 +750,23 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
if (fd == fdmatch)
continue;
+ /* Functions overriding interface functions for extern(C++) with VC++
+ * are not in the normal vtbl, but in vtblFinal. If the implementation
+ * is again overridden in a child class, both would be found here.
+ * The function in the child class should override the function
+ * in the base class, which is done here, because searchVtbl is first
+ * called for the child class. Checking seenInterfaceVirtual makes
+ * sure, that the compared functions are not in the same vtbl.
+ */
+ if (fd.interfaceVirtual &&
+ fd.interfaceVirtual is fdmatch.interfaceVirtual &&
+ !seenInterfaceVirtual &&
+ fdmatch.type.covariant(fd.type) == Covariant.yes)
+ {
+ seenInterfaceVirtual = true;
+ continue;
+ }
+
{
// Function type matching: exact > covariant
MATCH m1 = tf.equals(fd.type) ? MATCH.exact : MATCH.nomatch;
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 0f40c11..e3f135a 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -16,6 +16,7 @@ import core.stdc.stdio;
import dmd.aggregate;
import dmd.arraytypes;
import dmd.astenums;
+import dmd.attrib;
import dmd.ctorflow;
import dmd.dclass;
import dmd.delegatize;
@@ -34,7 +35,7 @@ import dmd.init;
import dmd.initsem;
import dmd.intrange;
import dmd.mtype;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rootobject;
import dmd.target;
import dmd.tokens;
@@ -705,7 +706,7 @@ extern (C++) final class AliasDeclaration : Declaration
assert(s);
}
- static AliasDeclaration create(Loc loc, Identifier id, Type type)
+ static AliasDeclaration create(const ref Loc loc, Identifier id, Type type)
{
return new AliasDeclaration(loc, id, type);
}
@@ -1192,14 +1193,7 @@ extern (C++) class VarDeclaration : Declaration
/* If coming after a bit field in progress,
* advance past the field
*/
- if (fieldState.inFlight)
- {
- fieldState.inFlight = false;
- if (0 && target.os & Target.OS.Posix)
- fieldState.offset += (fieldState.bitOffset + 7) / 8;
- else if (0 &&target.os == Target.OS.Windows)
- fieldState.offset += fieldState.fieldSize;
- }
+ fieldState.inFlight = false;
const sz = t.size(loc);
assert(sz != SIZE_INVALID && sz < uint.max);
@@ -1743,13 +1737,23 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
{
- //printf("BitFieldDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
+ //printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
+ static void print(const ref FieldState fieldState)
+ {
+ printf("FieldState.offset = %d bytes\n", fieldState.offset);
+ printf(" .fieldOffset = %d bytes\n", fieldState.fieldOffset);
+ printf(" .bitOffset = %d bits\n", fieldState.bitOffset);
+ printf(" .fieldSize = %d bytes\n", fieldState.fieldSize);
+ printf(" .inFlight = %d\n\n", fieldState.inFlight);
+ }
+ //print(fieldState);
Type t = type.toBasetype();
+ const bool anon = isAnonymous();
// List in ad.fields. Even if the type is error, it's necessary to avoid
// pointless error diagnostic "more initializers than fields" on struct literal.
- if (!isAnonymous())
+ if (!anon)
ad.fields.push(this);
if (t.ty == Terror)
@@ -1760,17 +1764,36 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
uint memsize = cast(uint)sz; // size of member
uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
- if (fieldWidth == 0 && !isAnonymous())
+ if (fieldWidth == 0 && !anon)
error(loc, "named bit fields cannot have 0 width");
if (fieldWidth > memsize * 8)
error(loc, "bit field width %d is larger than type", fieldWidth);
+ const style = target.c.bitFieldStyle;
+
void startNewField()
{
+ uint alignsize;
+ if (style == TargetC.BitFieldStyle.Gcc_Clang)
+ {
+ if (fieldWidth > 32)
+ alignsize = memalignsize;
+ else if (fieldWidth > 16)
+ alignsize = 4;
+ else if (fieldWidth > 8)
+ alignsize = 2;
+ else
+ alignsize = 1;
+ }
+ else
+ alignsize = memsize; // not memalignsize
+
+ uint dummy;
offset = AggregateDeclaration.placeField(
&fieldState.offset,
- memsize, memalignsize, alignment,
- &ad.structsize, &ad.alignsize,
+ memsize, alignsize, alignment,
+ &ad.structsize,
+ (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? &dummy : &ad.alignsize,
isunion);
fieldState.inFlight = true;
@@ -1779,19 +1802,92 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
fieldState.fieldSize = memsize;
}
- if (!fieldState.inFlight || fieldWidth == 0)
+ if (style == TargetC.BitFieldStyle.Gcc_Clang)
{
- startNewField();
+ if (fieldWidth == 0)
+ {
+ if (!isunion)
+ {
+ // Use type of zero width field to align to next field
+ fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
+ ad.structsize = fieldState.offset;
+ }
+
+ fieldState.inFlight = false;
+ return;
+ }
+
+ if (ad.alignsize == 0)
+ ad.alignsize = 1;
+ if (!anon &&
+ ad.alignsize < memalignsize)
+ ad.alignsize = memalignsize;
+ }
+ else if (style == TargetC.BitFieldStyle.MS)
+ {
+ if (ad.alignsize == 0)
+ ad.alignsize = 1;
+ if (fieldWidth == 0)
+ {
+ if (fieldState.inFlight && !isunion)
+ {
+ // documentation says align to next int
+ //const alsz = cast(uint)Type.tint32.size();
+ const alsz = memsize; // but it really does this
+ fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
+ ad.structsize = fieldState.offset;
+ }
+
+ fieldState.inFlight = false;
+ return;
+ }
+ }
+ else if (style == TargetC.BitFieldStyle.DM)
+ {
+ if (anon && fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0))
+ return; // this probably should be a bug in DMC
+ if (ad.alignsize == 0)
+ ad.alignsize = 1;
+ if (fieldWidth == 0)
+ {
+ if (fieldState.inFlight && !isunion)
+ {
+ const alsz = memsize;
+ fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
+ ad.structsize = fieldState.offset;
+ }
+
+ fieldState.inFlight = false;
+ return;
+ }
}
- if (0 && target.os & Target.OS.Posix)
+ if (!fieldState.inFlight)
+ {
+ startNewField();
+ }
+ else if (style == TargetC.BitFieldStyle.Gcc_Clang)
{
- if ((fieldState.offset%4 * 8) + fieldState.bitOffset + fieldWidth > int.sizeof * 8)
+ if (fieldState.bitOffset + fieldWidth > memsize * 8)
{
+ //printf("start1 fieldState.bitOffset:%u fieldWidth:%u memsize:%u\n", fieldState.bitOffset, fieldWidth, memsize);
startNewField();
}
+ else
+ {
+ // if alignment boundary is crossed
+ uint start = fieldState.fieldOffset * 8 + fieldState.bitOffset;
+ uint end = start + fieldWidth;
+ //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize);
+ if (start / (memalignsize * 8) != (end - 1) / (memalignsize * 8))
+ {
+ //printf("alignment is crossed\n");
+ startNewField();
+ }
+ }
}
- else if (1 || target.os == Target.OS.Windows)
+ else if (style == TargetC.BitFieldStyle.DM ||
+ style == TargetC.BitFieldStyle.MS)
{
if (memsize != fieldState.fieldSize ||
fieldState.bitOffset + fieldWidth > fieldState.fieldSize * 8)
@@ -1799,22 +1895,29 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
startNewField();
}
}
+ else
+ assert(0);
offset = fieldState.fieldOffset;
bitOffset = fieldState.bitOffset;
- if (0 && target.os & Target.OS.Posix)
+
+ const pastField = bitOffset + fieldWidth;
+ if (style == TargetC.BitFieldStyle.Gcc_Clang)
{
- while (bitOffset > memsize * 8)
- {
- bitOffset -= 8;
- offset += 1;
- }
+ auto size = (pastField + 7) / 8;
+ fieldState.fieldSize = size;
+ //printf(" offset: %d, size: %d\n", offset, size);
+ ad.structsize = offset + size;
}
+ else
+ fieldState.fieldSize = memsize;
+ //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
+ //print(fieldState);
- //fieldState.fieldSize = memsize;
if (!isunion)
{
- fieldState.bitOffset += fieldWidth;
+ fieldState.offset = offset + fieldState.fieldSize;
+ fieldState.bitOffset = pastField;
}
//printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
@@ -1861,7 +1964,7 @@ extern (C++) class TypeInfoDeclaration : VarDeclaration
storage_class = STC.static_ | STC.gshared;
visibility = Visibility(Visibility.Kind.public_);
linkage = LINK.c;
- alignment = target.ptrsize;
+ alignment.set(target.ptrsize);
}
static TypeInfoDeclaration create(Type tinfo)
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 1c56def..4a4c353 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -188,7 +188,7 @@ public:
Dsymbol *overnext; // next in overload list
Dsymbol *_import; // !=NULL if unresolved internal alias for selective import
- static AliasDeclaration *create(Loc loc, Identifier *id, Type *type);
+ static AliasDeclaration *create(const Loc &loc, Identifier *id, Type *type);
AliasDeclaration *syntaxCopy(Dsymbol *);
bool overloadInsert(Dsymbol *s);
const char *kind() const;
@@ -511,7 +511,7 @@ enum class BUILTIN : unsigned char
toPrecReal
};
-Expression *eval_builtin(Loc loc, FuncDeclaration *fd, Expressions *arguments);
+Expression *eval_builtin(const Loc &loc, FuncDeclaration *fd, Expressions *arguments);
BUILTIN isBuiltin(FuncDeclaration *fd);
class FuncDeclaration : public Declaration
@@ -535,6 +535,8 @@ public:
VarDeclaration *vresult; // result variable for out contracts
LabelDsymbol *returnLabel; // where the return goes
+ void *isTypeIsolatedCache; // An AA on the D side to cache an expensive check result
+
// used to prevent symbols in different
// scopes from having the same name
DsymbolTable *localsymtab;
@@ -839,9 +841,6 @@ public:
class NewDeclaration : public FuncDeclaration
{
public:
- Parameters *parameters;
- VarArg varargs;
-
NewDeclaration *syntaxCopy(Dsymbol *);
const char *kind() const;
bool isVirtual() const;
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 541fac7..a1f36c0 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -42,6 +42,7 @@ import dmd.mtype;
import dmd.printast;
import dmd.root.rmem;
import dmd.root.array;
+import dmd.root.ctfloat;
import dmd.root.region;
import dmd.root.rootobject;
import dmd.statement;
@@ -75,6 +76,7 @@ public Expression ctfeInterpret(Expression e)
case TOK.template_: // non-eponymous template/instance
case TOK.scope_: // ditto
case TOK.dotTemplateDeclaration: // ditto, e.e1 doesn't matter here
+ case TOK.dotTemplateInstance: // ditto
case TOK.dot: // ditto
if (e.type.ty == Terror)
return ErrorExp.get();
@@ -2167,26 +2169,20 @@ public:
return;
}
- // Note: This is a workaround for
- // https://issues.dlang.org/show_bug.cgi?id=17351
- // The aforementioned bug triggers when passing manifest constant by `ref`.
- // If there was not a previous reference to them, they are
- // not cached and trigger a "cannot be read at compile time".
- // This fix is a crude solution to get it to work. A more proper
- // approach would be to resolve the forward reference, but that is
- // much more involved.
- if (goal == CTFEGoal.LValue && e.var.type.isMutable())
+ if (goal == CTFEGoal.LValue)
{
if (auto v = e.var.isVarDeclaration())
{
- if (!v.isDataseg() && !v.isCTFE() && !istate)
- {
- e.error("variable `%s` cannot be read at compile time", v.toChars());
- result = CTFEExp.cantexp;
- return;
- }
if (!hasValue(v))
{
+ // Compile-time known non-CTFE variable from an outer context
+ // e.g. global or from a ref argument
+ if (v.isConst() || v.isImmutable())
+ {
+ result = getVarExp(e.loc, istate, v, goal);
+ return;
+ }
+
if (!v.isCTFE() && v.isDataseg())
e.error("static variable `%s` cannot be read at compile time", v.toChars());
else // CTFE initiated from inside a function
@@ -2201,7 +2197,7 @@ public:
Expression ev = getValue(v);
if (ev.op == TOK.variable ||
ev.op == TOK.index ||
- ev.op == TOK.slice ||
+ (ev.op == TOK.slice && ev.type.toBasetype().ty == Tsarray) ||
ev.op == TOK.dotVariable)
{
result = interpret(pue, ev, istate, goal);
@@ -2836,8 +2832,7 @@ public:
auto se = ctfeEmplaceExp!StructLiteralExp(e.loc, cast(StructDeclaration)cd, elems, e.newtype);
se.origin = se;
se.ownedByCtfe = OwnedBy.ctfe;
- emplaceExp!(ClassReferenceExp)(pue, e.loc, se, e.type);
- Expression eref = pue.exp();
+ Expression eref = ctfeEmplaceExp!ClassReferenceExp(e.loc, se, e.type);
if (e.member)
{
// Call constructor
@@ -6024,12 +6019,23 @@ public:
}
if (e.to.ty == Tsarray)
e1 = resolveSlice(e1);
- if (e.to.toBasetype().ty == Tbool && e1.type.ty == Tpointer)
+
+ auto tobt = e.to.toBasetype();
+ if (tobt.ty == Tbool && e1.type.ty == Tpointer)
{
emplaceExp!(IntegerExp)(pue, e.loc, e1.op != TOK.null_, e.to);
result = pue.exp();
return;
}
+ else if (tobt.isTypeBasic() && e1.op == TOK.null_)
+ {
+ if (tobt.isintegral())
+ emplaceExp!(IntegerExp)(pue, e.loc, 0, e.to);
+ else if (tobt.isreal())
+ emplaceExp!(RealExp)(pue, e.loc, CTFloat.zero, e.to);
+ result = pue.exp();
+ return;
+ }
result = ctfeCast(pue, e.loc, e.type, e.to, e1);
}
@@ -6306,7 +6312,7 @@ public:
auto tsa = cast(TypeSArray)v.type;
auto len = cast(size_t)tsa.dim.toInteger();
UnionExp ue = void;
- result = createBlockDuplicatedArrayLiteral(&ue, ex.loc, v.type, ex, len);
+ result = createBlockDuplicatedArrayLiteral(&ue, e.loc, v.type, result, len);
if (result == ue.exp())
result = ue.copy();
(*se.elements)[i] = result;
diff --git a/gcc/d/dmd/dmacro.d b/gcc/d/dmd/dmacro.d
index ddfee2c..357f7bd 100644
--- a/gcc/d/dmd/dmacro.d
+++ b/gcc/d/dmd/dmacro.d
@@ -16,7 +16,7 @@ import core.stdc.string;
import dmd.doc;
import dmd.errors;
import dmd.globals;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rmem;
extern (C++) struct MacroTable
diff --git a/gcc/d/dmd/dmangle.d b/gcc/d/dmd/dmangle.d
index 71b8c7a..c417f93 100644
--- a/gcc/d/dmd/dmangle.d
+++ b/gcc/d/dmd/dmangle.d
@@ -139,7 +139,7 @@ import dmd.id;
import dmd.identifier;
import dmd.mtype;
import dmd.root.ctfloat;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.aav;
import dmd.root.string;
import dmd.root.stringtable;
@@ -1259,14 +1259,49 @@ public:
override void visit(Parameter p)
{
- if (p.storageClass & STC.scope_ && !(p.storageClass & STC.scopeinferred))
- buf.writeByte('M');
+ // https://dlang.org/spec/abi.html#Parameter
+
+ auto stc = p.storageClass;
+
+ // Inferred storage classes don't get mangled in
+ if (stc & STC.scopeinferred)
+ stc &= ~(STC.scope_ | STC.scopeinferred);
+ if (stc & STC.returninferred)
+ stc &= ~(STC.return_ | STC.returninferred);
// 'return inout ref' is the same as 'inout ref'
- if ((p.storageClass & (STC.return_ | STC.wild)) == STC.return_ &&
- !(p.storageClass & STC.returninferred))
- buf.writestring("Nk");
- switch (p.storageClass & (STC.IOR | STC.lazy_))
+ if ((stc & (STC.return_ | STC.wild)) == (STC.return_ | STC.wild))
+ stc &= ~STC.return_;
+
+ // much like hdrgen.stcToBuffer()
+ string rrs;
+ const isout = (stc & STC.out_) != 0;
+ final switch (buildScopeRef(stc))
+ {
+ case ScopeRef.None:
+ case ScopeRef.Scope:
+ case ScopeRef.Ref:
+ case ScopeRef.Return:
+ case ScopeRef.RefScope:
+ break;
+
+ case ScopeRef.ReturnScope: rrs = "NkM"; goto L1; // return scope
+ case ScopeRef.ReturnRef: rrs = isout ? "NkJ" : "NkK"; goto L1; // return ref
+ case ScopeRef.ReturnRef_Scope: rrs = isout ? "MNkJ" : "MNkK"; goto L1; // scope return ref
+ case ScopeRef.Ref_ReturnScope: rrs = isout ? "NkMJ" : "NkMK"; goto L1; // return scope ref
+ L1:
+ buf.writestring(rrs);
+ stc &= ~(STC.out_ | STC.scope_ | STC.ref_ | STC.return_);
+ break;
+ }
+
+ if (stc & STC.scope_)
+ buf.writeByte('M'); // scope
+
+ if (stc & STC.return_)
+ buf.writestring("Nk"); // return
+
+ switch (stc & (STC.IOR | STC.lazy_))
{
case 0:
break;
@@ -1288,10 +1323,10 @@ public:
default:
debug
{
- printf("storageClass = x%llx\n", p.storageClass & (STC.IOR | STC.lazy_));
+ printf("storageClass = x%llx\n", stc & (STC.IOR | STC.lazy_));
}
assert(0);
}
- visitWithMask(p.type, (p.storageClass & STC.in_) ? MODFlags.const_ : 0);
+ visitWithMask(p.type, (stc & STC.in_) ? MODFlags.const_ : 0);
}
}
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 768eaa0..4e00713 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -31,6 +31,7 @@ import dmd.dsymbolsem;
import dmd.errors;
import dmd.expression;
import dmd.expressionsem;
+import dmd.file_manager;
import dmd.globals;
import dmd.id;
import dmd.identifier;
@@ -39,7 +40,7 @@ import dmd.cparse;
import dmd.root.array;
import dmd.root.file;
import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.port;
import dmd.root.rmem;
import dmd.root.rootobject;
@@ -50,113 +51,6 @@ import dmd.target;
import dmd.utils;
import dmd.visitor;
-enum package_d = "package." ~ mars_ext;
-enum package_di = "package." ~ hdr_ext;
-
-/********************************************
- * Look for the source file if it's different from filename.
- * Look for .di, .d, directory, and along global.path.
- * Does not open the file.
- * Params:
- * filename = as supplied by the user
- * path = path to look for filename
- * Returns:
- * the found file name or
- * `null` if it is not different from filename.
- */
-private const(char)[] lookForSourceFile(const char[] filename, const char*[] path)
-{
- //printf("lookForSourceFile(`%.*s`)\n", cast(int)filename.length, filename.ptr);
- /* Search along path[] for .di file, then .d file, then .i file, then .c file.
- */
- const sdi = FileName.forceExt(filename, hdr_ext);
- if (FileName.exists(sdi) == 1)
- return sdi;
- scope(exit) FileName.free(sdi.ptr);
-
- const sd = FileName.forceExt(filename, mars_ext);
- if (FileName.exists(sd) == 1)
- return sd;
- scope(exit) FileName.free(sd.ptr);
-
- const si = FileName.forceExt(filename, i_ext);
- if (FileName.exists(si) == 1)
- return si;
- scope(exit) FileName.free(si.ptr);
-
- const sc = FileName.forceExt(filename, c_ext);
- if (FileName.exists(sc) == 1)
- return sc;
- scope(exit) FileName.free(sc.ptr);
-
- if (FileName.exists(filename) == 2)
- {
- /* The filename exists and it's a directory.
- * Therefore, the result should be: filename/package.d
- * iff filename/package.d is a file
- */
- const ni = FileName.combine(filename, package_di);
- if (FileName.exists(ni) == 1)
- return ni;
- FileName.free(ni.ptr);
-
- const n = FileName.combine(filename, package_d);
- if (FileName.exists(n) == 1)
- return n;
- FileName.free(n.ptr);
- }
- if (FileName.absolute(filename))
- return null;
- if (!path.length)
- return null;
- foreach (entry; path)
- {
- const p = entry.toDString();
-
- const(char)[] n = FileName.combine(p, sdi);
- if (FileName.exists(n) == 1) {
- return n;
- }
- FileName.free(n.ptr);
-
- n = FileName.combine(p, sd);
- if (FileName.exists(n) == 1) {
- return n;
- }
- FileName.free(n.ptr);
-
- n = FileName.combine(p, si);
- if (FileName.exists(n) == 1) {
- return n;
- }
- FileName.free(n.ptr);
-
- n = FileName.combine(p, sc);
- if (FileName.exists(n) == 1) {
- return n;
- }
- FileName.free(n.ptr);
-
- const b = FileName.removeExt(filename);
- n = FileName.combine(p, b);
- FileName.free(b.ptr);
- if (FileName.exists(n) == 2)
- {
- const n2i = FileName.combine(n, package_di);
- if (FileName.exists(n2i) == 1)
- return n2i;
- FileName.free(n2i.ptr);
- const n2 = FileName.combine(n, package_d);
- if (FileName.exists(n2) == 1) {
- return n2;
- }
- FileName.free(n2.ptr);
- }
- FileName.free(n.ptr);
- }
- return null;
-}
-
// function used to call semantic3 on a module's dependencies
void semantic3OnDependencies(Module m)
{
@@ -414,8 +308,8 @@ extern (C++) class Package : ScopeDsymbol
packages ~= s.ident;
reverse(packages);
- if (lookForSourceFile(getFilename(packages, ident), global.path ? (*global.path)[] : null))
- Module.load(Loc(), packages, this.ident);
+ if (FileManager.lookForSourceFile(getFilename(packages, ident), global.path ? (*global.path)[] : null))
+ Module.load(Loc.initial, packages, this.ident);
else
isPkgMod = PKG.package_;
}
@@ -598,12 +492,12 @@ extern (C++) final class Module : Package
return new Module(Loc.initial, filename, ident, doDocComment, doHdrGen);
}
- extern (C++) static Module load(Loc loc, Identifiers* packages, Identifier ident)
+ extern (C++) static Module load(const ref Loc loc, Identifiers* packages, Identifier ident)
{
return load(loc, packages ? (*packages)[] : null, ident);
}
- extern (D) static Module load(Loc loc, Identifier[] packages, Identifier ident)
+ extern (D) static Module load(const ref Loc loc, Identifier[] packages, Identifier ident)
{
//printf("Module::load(ident = '%s')\n", ident.toChars());
// Build module filename by turning:
@@ -612,7 +506,7 @@ extern (C++) final class Module : Package
// foo\bar\baz
const(char)[] filename = getFilename(packages, ident);
// Look for the source file
- if (const result = lookForSourceFile(filename, global.path ? (*global.path)[] : null))
+ if (const result = FileManager.lookForSourceFile(filename, global.path ? (*global.path)[] : null))
filename = result; // leaks
auto m = new Module(loc, filename, ident, 0, 0);
@@ -737,7 +631,12 @@ extern (C++) final class Module : Package
if (isPackageMod)
.error(loc, "importing package '%s' requires a 'package.d' file which cannot be found in '%s'", toChars(), srcfile.toChars());
else
- error(loc, "is in file '%s' which cannot be read", srcfile.toChars());
+ {
+ .error(loc, "unable to read module `%s`", toChars());
+ const pkgfile = FileName.combine(FileName.removeExt(srcfile.toString()), package_d);
+ .errorSupplemental(loc, "Expected '%s' or '%s' in one of the following import paths:",
+ srcfile.toChars(), pkgfile.ptr);
+ }
}
if (!global.gag)
{
@@ -776,14 +675,25 @@ extern (C++) final class Module : Package
return true; // already read
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile.toChars());
- auto readResult = File.read(srcfile.toChars());
if (global.params.emitMakeDeps)
{
global.params.makeDeps.push(srcfile.toChars());
}
- return loadSourceBuffer(loc, readResult);
+ if (auto readResult = FileManager.fileManager.lookup(srcfile))
+ {
+ srcBuffer = readResult;
+ return true;
+ }
+
+ auto readResult = File.read(srcfile.toChars());
+ if (loadSourceBuffer(loc, readResult))
+ {
+ FileManager.fileManager.add(srcfile, srcBuffer);
+ return true;
+ }
+ return false;
}
/// syntactic parse
diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d
index 9b4329b..f9b765c 100644
--- a/gcc/d/dmd/doc.d
+++ b/gcc/d/dmd/doc.d
@@ -45,7 +45,7 @@ import dmd.mtype;
import dmd.root.array;
import dmd.root.file;
import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.port;
import dmd.root.rmem;
import dmd.root.string;
@@ -3995,8 +3995,8 @@ private size_t startTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const r
const iDelimiterRowEnd = parseTableDelimiterRow(buf, iEnd + 1, inQuote, columnAlignments);
if (iDelimiterRowEnd)
{
- const delta = replaceTableRow(buf, iStart, iEnd, loc, inlineDelimiters, columnAlignments, true);
- if (delta)
+ size_t delta;
+ if (replaceTableRow(buf, iStart, iEnd, loc, inlineDelimiters, columnAlignments, true, delta))
{
buf.remove(iEnd + delta, iDelimiterRowEnd - iEnd);
buf.insert(iEnd + delta, "$(TBODY ");
@@ -4023,12 +4023,15 @@ private size_t startTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const r
* headerRow = if `true` then the number of columns will be enforced to match
* `columnAlignments.length` and the row will be surrounded by a
* `THEAD` macro
- * Returns: the number of characters added by replacing the row, or `0` if unchanged
+ * delta = the number of characters added by replacing the row, or `0` if unchanged
+ * Returns: `true` if a table row was found and replaced
*/
-private size_t replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, TableColumnAlignment[] columnAlignments, bool headerRow)
+private bool replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, TableColumnAlignment[] columnAlignments, bool headerRow, out size_t delta)
{
+ delta = 0;
+
if (!columnAlignments.length || iStart == iEnd)
- return 0;
+ return false;
iStart = skipChars(buf, iStart, " \t");
int cellCount = 0;
@@ -4045,7 +4048,7 @@ private size_t replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, co
++cellCount;
if (headerRow && cellCount != columnAlignments.length)
- return 0;
+ return false;
if (headerRow && global.params.vmarkdown)
{
@@ -4053,8 +4056,6 @@ private size_t replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, co
message(loc, "Ddoc: formatting table '%.*s'", cast(int)s.length, s.ptr);
}
- size_t delta = 0;
-
void replaceTableCell(size_t iCellStart, size_t iCellEnd, int cellIndex, int di)
{
const eDelta = replaceMarkdownEmphasis(buf, loc, inlineDelimiters, di);
@@ -4146,7 +4147,7 @@ private size_t replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, co
delta += 9;
}
- return delta;
+ return true;
}
/****************************************************
@@ -4182,7 +4183,8 @@ private size_t endTable(ref OutBuffer buf, size_t i, ref TableColumnAlignment[]
*/
private size_t endRowAndTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, ref TableColumnAlignment[] columnAlignments)
{
- size_t delta = replaceTableRow(buf, iStart, iEnd, loc, inlineDelimiters, columnAlignments, false);
+ size_t delta;
+ replaceTableRow(buf, iStart, iEnd, loc, inlineDelimiters, columnAlignments, false, delta);
delta += endTable(buf, iEnd + delta, columnAlignments);
return delta;
}
@@ -4263,8 +4265,8 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
i += startTable(buf, iLineStart, i, loc, lineQuoted, inlineDelimiters, columnAlignments);
else if (columnAlignments.length)
{
- const delta = replaceTableRow(buf, iLineStart, i, loc, inlineDelimiters, columnAlignments, false);
- if (delta)
+ size_t delta;
+ if (replaceTableRow(buf, iLineStart, i, loc, inlineDelimiters, columnAlignments, false, delta))
i += delta;
else
i += endTable(buf, i, columnAlignments);
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index 638fc7e..42c0d18 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -33,7 +33,7 @@ import dmd.func;
import dmd.globals;
import dmd.id;
import dmd.identifier;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rmem;
import dmd.root.speller;
import dmd.statement;
@@ -730,12 +730,21 @@ struct Scope
}
}
+ /******************************
+ */
structalign_t alignment()
{
if (aligndecl)
- return aligndecl.getAlignment(&this);
+ {
+ auto ad = aligndecl.getAlignment(&this);
+ return ad.salign;
+ }
else
- return STRUCTALIGN_DEFAULT;
+ {
+ structalign_t sa;
+ sa.setDefault();
+ return sa;
+ }
}
/**********************************
diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d
index 80ecd36..0925e7c 100644
--- a/gcc/d/dmd/dstruct.d
+++ b/gcc/d/dmd/dstruct.d
@@ -16,6 +16,7 @@ module dmd.dstruct;
import dmd.aggregate;
import dmd.arraytypes;
import dmd.astenums;
+import dmd.attrib;
import dmd.declaration;
import dmd.dmodule;
import dmd.dscope;
@@ -127,7 +128,7 @@ extern (C++) void semanticTypeInfo(Scope* sc, Type t)
*/
if (!sd.members)
return; // opaque struct
- if (!sd.xeq && !sd.xcmp && !sd.postblit && !sd.dtor && !sd.xhash && !search_toString(sd))
+ if (!sd.xeq && !sd.xcmp && !sd.postblit && !sd.tidtor && !sd.xhash && !search_toString(sd))
return; // none of TypeInfo-specific members
// If the struct is in a non-root module, run semantic3 to get
@@ -232,7 +233,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration
}
}
- static StructDeclaration create(Loc loc, Identifier id, bool inObject)
+ static StructDeclaration create(const ref Loc loc, Identifier id, bool inObject)
{
return new StructDeclaration(loc, id, inObject);
}
@@ -297,22 +298,46 @@ extern (C++) class StructDeclaration : AggregateDeclaration
return;
}
- // 0 sized struct's are set to 1 byte
if (structsize == 0)
{
hasNoFields = true;
alignsize = 1;
- if (classKind != classKind.c) // C gets a struct size of 0
- structsize = 1;
+
+ // A fine mess of what size a zero sized struct should be
+ final switch (classKind)
+ {
+ case ClassKind.d:
+ case ClassKind.cpp:
+ structsize = 1;
+ break;
+
+ case ClassKind.c:
+ case ClassKind.objc:
+ if (target.c.bitFieldStyle == TargetC.BitFieldStyle.MS)
+ {
+ /* Undocumented MS behavior for:
+ * struct S { int :0; };
+ */
+ structsize = 4;
+ }
+ else if (target.c.bitFieldStyle == TargetC.BitFieldStyle.DM)
+ {
+ structsize = 0;
+ alignsize = 0;
+ }
+ else
+ structsize = 0;
+ break;
+ }
}
// Round struct size up to next alignsize boundary.
// This will ensure that arrays of structs will get their internals
// aligned properly.
- if (alignment == STRUCTALIGN_DEFAULT)
+ if (alignment.isDefault() || alignment.isPack())
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
else
- structsize = (structsize + alignment - 1) & ~(alignment - 1);
+ structsize = (structsize + alignment.get() - 1) & ~(alignment.get() - 1);
sizeok = Sizeok.done;
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index 3a6dff2..9aa435d 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -187,7 +187,7 @@ struct Visibility
}
}
-enum PASS : int
+enum PASS : ubyte
{
init, // initial state
semantic, // semantic() started
@@ -225,11 +225,13 @@ enum : int
*/
struct FieldState
{
- uint offset; /// offset for next field
+ uint offset; /// byte offset for next field
- uint fieldOffset; /// offset for the start of the bit field
+ uint fieldOffset; /// byte offset for the start of the bit field
+ uint fieldSize; /// byte size of field
+ uint fieldAlign; /// byte alignment of field
uint bitOffset; /// bit offset for field
- uint fieldSize; /// size of field in bytes
+
bool inFlight; /// bit field is in flight
}
@@ -793,10 +795,18 @@ extern (C++) class Dsymbol : ASTNode
Dsymbol s2 = sds.symtabLookup(this,ident);
// If using C tag/prototype/forward declaration rules
- if (sc.flags & SCOPE.Cfile &&
- handleTagSymbols(*sc, this, s2, sds))
+ if (sc.flags & SCOPE.Cfile)
+ {
+ if (handleTagSymbols(*sc, this, s2, sds))
+ return;
+ if (handleSymbolRedeclarations(*sc, this, s2, sds))
return;
+ sds.multiplyDefined(Loc.initial, this, s2); // ImportC doesn't allow overloading
+ errors = true;
+ return;
+ }
+
if (!s2.overloadInsert(this))
{
sds.multiplyDefined(Loc.initial, this, s2);
@@ -2384,3 +2394,91 @@ Dsymbol handleTagSymbols(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
}
+/**********************************************
+ * ImportC allows redeclarations of C variables, functions and typedefs.
+ * extern int x;
+ * int x = 3;
+ * and:
+ * extern void f();
+ * void f() { }
+ * Attempt to merge them.
+ * Params:
+ * sc = context
+ * s = symbol to add to symbol table
+ * s2 = existing declaration
+ * sds = symbol table
+ * Returns:
+ * if s and s2 are successfully put in symbol table then return the merged symbol,
+ * null if they conflict
+ */
+Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
+{
+ enum log = false;
+ if (log) printf("handleSymbolRedeclarations('%s')\n", s.toChars());
+
+ static Dsymbol collision()
+ {
+ if (log) printf(" collision\n");
+ return null;
+ }
+
+ auto vd = s.isVarDeclaration(); // new declaration
+ auto vd2 = s2.isVarDeclaration(); // existing declaration
+ if (vd && vd2)
+ {
+ // if one is `static` and the other isn't
+ if ((vd.storage_class ^ vd2.storage_class) & STC.static_)
+ return collision();
+
+ const i1 = vd._init && ! vd._init.isVoidInitializer();
+ const i2 = vd2._init && !vd2._init.isVoidInitializer();
+
+ if (i1 && i2)
+ return collision(); // can't both have initializers
+
+ if (i1)
+ return vd;
+
+ /* BUG: the types should match, which needs semantic() to be run on it
+ * extern int x;
+ * int x; // match
+ * typedef int INT;
+ * INT x; // match
+ * long x; // collision
+ * We incorrectly ignore these collisions
+ */
+ return vd2;
+ }
+
+ auto fd = s.isFuncDeclaration(); // new declaration
+ auto fd2 = s2.isFuncDeclaration(); // existing declaration
+ if (fd && fd2)
+ {
+ // if one is `static` and the other isn't
+ if ((fd.storage_class ^ fd2.storage_class) & STC.static_)
+ return collision();
+
+ if (fd.fbody && fd2.fbody)
+ return collision(); // can't both have bodies
+
+ if (fd.fbody)
+ return fd;
+
+ /* BUG: just like with VarDeclaration, the types should match, which needs semantic() to be run on it.
+ * FuncDeclaration::semantic2() can detect this, but it relies overnext being set.
+ */
+ return fd2;
+ }
+
+ auto td = s.isAliasDeclaration(); // new declaration
+ auto td2 = s2.isAliasDeclaration(); // existing declaration
+ if (td && td2)
+ {
+ /* BUG: just like with variables and functions, the types should match, which needs semantic() to be run on it.
+ * FuncDeclaration::semantic2() can detect this, but it relies overnext being set.
+ */
+ return td2;
+ }
+
+ return collision();
+}
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index f43bc83..02252fd 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -108,7 +108,21 @@ struct Visibility
/* State of symbol in winding its way through the passes of the compiler
*/
-enum PASS
+enum class PASS : uint8_t
+{
+ init, // initial state
+ semantic, // semantic() started
+ semanticdone, // semantic() done
+ semantic2, // semantic2() started
+ semantic2done, // semantic2() done
+ semantic3, // semantic3() started
+ semantic3done, // semantic3() done
+ inline_, // inline started
+ inlinedone, // inline done
+ obj // toObjFile() run
+};
+
+enum
{
PASSinit, // initial state
PASSsemantic, // semantic() started
@@ -145,8 +159,10 @@ struct FieldState
unsigned offset;
unsigned fieldOffset;
+ unsigned fieldSize;
+ unsigned fieldAlign;
unsigned bitOffset;
- unsigned fieldSice;
+
bool inFlight;
};
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index eac2095..047c1eb 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -56,7 +56,7 @@ import dmd.objc;
import dmd.opover;
import dmd.parse;
import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rmem;
import dmd.root.rootobject;
import dmd.semantic2;
@@ -109,17 +109,18 @@ extern(C++) void dsymbolSemantic(Dsymbol dsym, Scope* sc)
* ad = AlignmentDeclaration
* sc = context
* Returns:
- * alignment as numerical value that is never 0.
- * STRUCTALIGN_DEFAULT is used instead.
- * STRUCTALIGN_DEFAULT is returned for errors
+ * ad with alignment value determined
*/
-structalign_t getAlignment(AlignDeclaration ad, Scope* sc)
+AlignDeclaration getAlignment(AlignDeclaration ad, Scope* sc)
{
- if (ad.salign != ad.UNKNOWN) // UNKNOWN is 0
- return ad.salign;
+ if (!ad.salign.isUnknown()) // UNKNOWN is 0
+ return ad;
if (!ad.exps)
- return ad.salign = STRUCTALIGN_DEFAULT;
+ {
+ ad.salign.setDefault();
+ return ad;
+ }
dinteger_t strictest = 0; // strictest alignment
bool errors;
@@ -140,7 +141,7 @@ structalign_t getAlignment(AlignDeclaration ad, Scope* sc)
if (sc.flags & SCOPE.Cfile && n == 0) // C11 6.7.5-6 allows 0 for alignment
continue;
- if (n < 1 || n & (n - 1) || structalign_t.max < n || !e.type.isintegral())
+ if (n < 1 || n & (n - 1) || ushort.max < n || !e.type.isintegral())
{
error(ad.loc, "alignment must be an integer positive power of 2, not 0x%llx", cast(ulong)n);
errors = true;
@@ -150,10 +151,12 @@ structalign_t getAlignment(AlignDeclaration ad, Scope* sc)
}
}
- ad.salign = (errors || strictest == 0) // C11 6.7.5-6 says alignment of 0 means no effect
- ? STRUCTALIGN_DEFAULT
- : cast(structalign_t) strictest;
- return ad.salign;
+ if (errors || strictest == 0) // C11 6.7.5-6 says alignment of 0 means no effect
+ ad.salign.setDefault();
+ else
+ ad.salign.set(cast(uint) strictest);
+
+ return ad;
}
const(char)* getMessage(DeprecatedDeclaration dd)
@@ -365,16 +368,31 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
dsym.semanticRun = PASS.semantic;
- /* Pick up storage classes from context, but except synchronized,
- * override, abstract, and final.
- */
- dsym.storage_class |= (sc.stc & ~(STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_));
+ // 'static foreach' variables should not inherit scope properties
+ // https://issues.dlang.org/show_bug.cgi?id=19482
+ if ((dsym.storage_class & (STC.foreach_ | STC.local)) == (STC.foreach_ | STC.local))
+ {
+ dsym.linkage = LINK.d;
+ dsym.visibility = Visibility(Visibility.Kind.public_);
+ dsym.overlapped = false; // unset because it is modified early on this function
+ dsym.userAttribDecl = null; // unset because it is set by Dsymbol.setScope()
+ }
+ else
+ {
+ /* Pick up storage classes from context, but except synchronized,
+ * override, abstract, and final.
+ */
+ dsym.storage_class |= (sc.stc & ~(STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_));
+ dsym.userAttribDecl = sc.userAttribDecl;
+ dsym.cppnamespace = sc.namespace;
+ dsym.linkage = sc.linkage;
+ dsym.visibility = sc.visibility;
+ dsym.alignment = sc.alignment();
+ }
+
if (dsym.storage_class & STC.extern_ && dsym._init)
dsym.error("extern symbols cannot have initializers");
- dsym.userAttribDecl = sc.userAttribDecl;
- dsym.cppnamespace = sc.namespace;
-
AggregateDeclaration ad = dsym.isThis();
if (ad)
dsym.storage_class |= ad.storage_class & STC.TYPECTOR;
@@ -431,16 +449,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
dsym.errors = true;
dsym.type.checkDeprecated(dsym.loc, sc);
- dsym.linkage = sc.linkage;
dsym.parent = sc.parent;
//printf("this = %p, parent = %p, '%s'\n", dsym, dsym.parent, dsym.parent.toChars());
- dsym.visibility = sc.visibility;
/* If scope's alignment is the default, use the type's alignment,
* otherwise the scope overrrides.
*/
- dsym.alignment = sc.alignment();
- if (dsym.alignment == STRUCTALIGN_DEFAULT)
+ if (dsym.alignment.isDefault())
dsym.alignment = dsym.type.alignment(); // use type's alignment
//printf("sc.stc = %x\n", sc.stc);
@@ -935,6 +950,15 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
sc = sc.push();
sc.stc &= ~(STC.TYPECTOR | STC.pure_ | STC.nothrow_ | STC.nogc | STC.ref_ | STC.disable);
+ if (sc.flags & SCOPE.Cfile &&
+ dsym.type.isTypeSArray() &&
+ dsym.type.isTypeSArray().isIncomplete() &&
+ dsym._init.isVoidInitializer() &&
+ !(dsym.storage_class & STC.field))
+ {
+ dsym.error("incomplete array type must have initializer");
+ }
+
ExpInitializer ei = dsym._init.isExpInitializer();
if (ei) // https://issues.dlang.org/show_bug.cgi?id=13424
@@ -971,6 +995,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
ei = new ExpInitializer(dsym._init.loc, e);
dsym._init = ei;
}
+ else if (sc.flags & SCOPE.Cfile && dsym.type.isTypeSArray() &&
+ dsym.type.isTypeSArray().isIncomplete())
+ {
+ // C11 6.7.9-22 determine the size of the incomplete array,
+ // or issue an error that the initializer is invalid.
+ dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITinterpret);
+ }
Expression exp = ei.exp;
Expression e1 = new VarExp(dsym.loc, dsym);
@@ -1056,18 +1087,29 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// could crash (inf. recursion) on a mod/pkg referencing itself
if (ei && (ei.exp.op != TOK.scope_ ? true : !ei.exp.isScopeExp().sds.isPackage()))
{
- Expression exp = ei.exp.syntaxCopy();
-
- bool needctfe = dsym.isDataseg() || (dsym.storage_class & STC.manifest);
- if (needctfe)
- sc = sc.startCTFE();
- exp = exp.expressionSemantic(sc);
- exp = resolveProperties(sc, exp);
- if (needctfe)
- sc = sc.endCTFE();
+ if (ei.exp.type)
+ {
+ // If exp is already resolved we are done, our original init exp
+ // could have a type painting that we need to respect
+ // e.g. ['a'] typed as string, or [['z'], ""] as string[]
+ // See https://issues.dlang.org/show_bug.cgi?id=15711
+ }
+ else
+ {
+ Expression exp = ei.exp.syntaxCopy();
+
+ bool needctfe = dsym.isDataseg() || (dsym.storage_class & STC.manifest);
+ if (needctfe)
+ sc = sc.startCTFE();
+ exp = exp.expressionSemantic(sc);
+ exp = resolveProperties(sc, exp);
+ if (needctfe)
+ sc = sc.endCTFE();
+ ei.exp = exp;
+ }
Type tb2 = dsym.type.toBasetype();
- Type ti = exp.type.toBasetype();
+ Type ti = ei.exp.type.toBasetype();
/* The problem is the following code:
* struct CopyTest {
@@ -1091,11 +1133,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (sd.postblit && tb2.toDsymbol(null) == sd)
{
// The only allowable initializer is a (non-copy) constructor
- if (exp.isLvalue())
+ if (ei.exp.isLvalue())
dsym.error("of type struct `%s` uses `this(this)`, which is not allowed in static initialization", tb2.toChars());
}
}
- ei.exp = exp;
}
dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITinterpret);
@@ -1708,6 +1749,36 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
{
if (pd.args && pd.args.dim != 0)
pd.error("takes no argument");
+ else
+ {
+ immutable isCtor = pd.ident == Id.crt_constructor;
+
+ static uint recurse(Dsymbol s, bool isCtor)
+ {
+ if (auto ad = s.isAttribDeclaration())
+ {
+ uint nestedCount;
+ auto decls = ad.include(null);
+ if (decls)
+ {
+ for (size_t i = 0; i < decls.dim; ++i)
+ nestedCount += recurse((*decls)[i], isCtor);
+ }
+ return nestedCount;
+ }
+ else if (auto f = s.isFuncDeclaration())
+ {
+ f.isCrtCtorDtor |= isCtor ? 1 : 2;
+ return 1;
+ }
+ else
+ return 0;
+ assert(0);
+ }
+
+ if (recurse(pd, isCtor) > 1)
+ pd.error("can only apply to a single declaration");
+ }
return declarations();
}
else if (pd.ident == Id.printf || pd.ident == Id.scanf)
@@ -2445,6 +2516,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
tempdecl.parent = sc.parent;
tempdecl.visibility = sc.visibility;
+ tempdecl.userAttribDecl = sc.userAttribDecl;
tempdecl.cppnamespace = sc.namespace;
tempdecl.isstatic = tempdecl.toParent().isModule() || (tempdecl._scope.stc & STC.static_);
tempdecl.deprecated_ = !!(sc.stc & STC.deprecated_);
@@ -2973,6 +3045,16 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (auto pragmadecl = sc.inlining)
funcdecl.inlining = pragmadecl.evalPragmaInline(sc);
+ // check pragma(crt_constructor)
+ if (funcdecl.isCrtCtorDtor)
+ {
+ if (funcdecl.linkage != LINK.c)
+ {
+ funcdecl.error("must be `extern(C)` for `pragma(%s)`",
+ funcdecl.isCrtCtorDtor == 1 ? "crt_constructor".ptr : "crt_destructor".ptr);
+ }
+ }
+
funcdecl.visibility = sc.visibility;
funcdecl.userAttribDecl = sc.userAttribDecl;
UserAttributeDeclaration.checkGNUABITag(funcdecl, funcdecl.linkage);
@@ -3799,6 +3881,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}
}
+ if (funcdecl.fbody && sc._module.isRoot() &&
+ (funcdecl.isMain() || funcdecl.isWinMain() || funcdecl.isDllMain() || funcdecl.isCMain()))
+ global.hasMainFunction = true;
+
if (funcdecl.fbody && funcdecl.isMain() && sc._module.isRoot())
{
// check if `_d_cmain` is defined
@@ -3995,7 +4081,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
return;
}
if (dd.ident == Id.dtor && dd.semanticRun < PASS.semantic)
- ad.dtors.push(dd);
+ ad.userDtors.push(dd);
if (!dd.type)
{
dd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, dd.storage_class);
@@ -4417,8 +4503,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// Look for the constructor
sd.ctor = sd.searchCtor();
- sd.dtor = buildDtor(sd, sc2);
- sd.tidtor = buildExternDDtor(sd, sc2);
+ buildDtors(sd, sc2);
+
sd.hasCopyCtor = buildCopyCtor(sd, sc2);
sd.postblit = buildPostBlit(sd, sc2);
@@ -5057,8 +5143,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}
}
- cldec.dtor = buildDtor(cldec, sc2);
- cldec.tidtor = buildExternDDtor(cldec, sc2);
+ buildDtors(cldec, sc2);
if (cldec.classKind == ClassKind.cpp && cldec.cppDtorVtblIndex != -1)
{
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index c3503bb..9d7957a 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -67,7 +67,7 @@ import dmd.initsem;
import dmd.mtype;
import dmd.opover;
import dmd.root.array;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rootobject;
import dmd.semantic2;
import dmd.semantic3;
@@ -985,9 +985,9 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
buf.writenl();
buf.writestring(" ");
}
- buf.write((*parameters)[i]);
+ write(buf, (*parameters)[i]);
buf.writestring(" = ");
- buf.write(tiargs[i]);
+ write(buf, tiargs[i]);
}
// write remaining variadic arguments on the last line
if (variadic)
@@ -998,16 +998,16 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
buf.writenl();
buf.writestring(" ");
}
- buf.write((*parameters)[end]);
+ write(buf, (*parameters)[end]);
buf.writestring(" = ");
buf.writeByte('(');
if (cast(int)tiargs.length - end > 0)
{
- buf.write(tiargs[end]);
+ write(buf, tiargs[end]);
foreach (j; parameters.length .. tiargs.length)
{
buf.writestring(", ");
- buf.write(tiargs[j]);
+ write(buf, tiargs[j]);
}
}
buf.writeByte(')');
@@ -1919,8 +1919,15 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
/* If a semantic error occurs while doing alias this,
* eg purity(https://issues.dlang.org/show_bug.cgi?id=7295),
* just regard it as not a match.
- */
- if (auto e = resolveAliasThis(sc, farg, true))
+ *
+ * We also save/restore sc.func.flags to avoid messing up
+ * attribute inference in the evaluation.
+ */
+ const oldflags = sc.func ? sc.func.flags : 0;
+ auto e = resolveAliasThis(sc, farg, true);
+ if (sc.func)
+ sc.func.flags = oldflags;
+ if (e)
{
farg = e;
goto Lretry;
@@ -5340,7 +5347,7 @@ extern (C++) class TemplateParameter : ASTNode
abstract RootObject specialization();
- abstract RootObject defaultArg(Loc instLoc, Scope* sc);
+ abstract RootObject defaultArg(const ref Loc instLoc, Scope* sc);
abstract bool hasDefaultArg();
@@ -5422,7 +5429,7 @@ extern (C++) class TemplateTypeParameter : TemplateParameter
return specType;
}
- override final RootObject defaultArg(Loc instLoc, Scope* sc)
+ override final RootObject defaultArg(const ref Loc instLoc, Scope* sc)
{
Type t = defaultType;
if (t)
@@ -5541,7 +5548,7 @@ extern (C++) final class TemplateValueParameter : TemplateParameter
return specValue;
}
- override RootObject defaultArg(Loc instLoc, Scope* sc)
+ override RootObject defaultArg(const ref Loc instLoc, Scope* sc)
{
Expression e = defaultValue;
if (e)
@@ -5640,7 +5647,7 @@ extern (C++) final class TemplateAliasParameter : TemplateParameter
return specAlias;
}
- override RootObject defaultArg(Loc instLoc, Scope* sc)
+ override RootObject defaultArg(const ref Loc instLoc, Scope* sc)
{
RootObject da = defaultAlias;
Type ta = isType(defaultAlias);
@@ -5741,7 +5748,7 @@ extern (C++) final class TemplateTupleParameter : TemplateParameter
return null;
}
- override RootObject defaultArg(Loc instLoc, Scope* sc)
+ override RootObject defaultArg(const ref Loc instLoc, Scope* sc)
{
return null;
}
@@ -8413,3 +8420,11 @@ private struct MATCHpair
this.mfa = mfa;
}
}
+
+private void write(ref OutBuffer buf, RootObject obj)
+{
+ if (obj)
+ {
+ buf.writestring(obj.toChars());
+ }
+}
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index 28054d0..e19adfc 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -17,6 +17,7 @@ import core.stdc.ctype;
import dmd.astcodegen;
import dmd.arraytypes;
+import dmd.attrib;
import dmd.dsymbol;
import dmd.errors;
import dmd.globals;
@@ -25,7 +26,7 @@ import dmd.root.filename;
import dmd.visitor;
import dmd.tokens;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.utils;
//debug = Debug_DtoH;
@@ -254,7 +255,7 @@ public:
Identifier ident;
/// Original type of the currently visited declaration
- AST.Type* origType;
+ AST.Type origType;
/// Last written visibility level applying to the current scope
AST.Visibility.Kind currentVisibility;
@@ -706,6 +707,10 @@ public:
// printf("FuncDeclaration %s %s\n", fd.toPrettyChars(), fd.type.toChars());
visited[cast(void*)fd] = true;
+ // silently ignore non-user-defined destructors
+ if (fd.generated && fd.isDtorDeclaration())
+ return;
+
// Note that tf might be null for templated (member) functions
auto tf = cast(AST.TypeFunction)fd.type;
if ((tf && tf.linkage != LINK.c && tf.linkage != LINK.cpp) || (!tf && fd.isPostBlitDeclaration()))
@@ -841,12 +846,12 @@ public:
return;
if (vd.originalType && vd.type == AST.Type.tsize_t)
- origType = &vd.originalType;
+ origType = vd.originalType;
scope(exit) origType = null;
- if (vd.alignment != STRUCTALIGN_DEFAULT)
+ if (!vd.alignment.isDefault())
{
- buf.printf("// Ignoring var %s alignment %u", vd.toChars(), vd.alignment);
+ buf.printf("// Ignoring var %s alignment %d", vd.toChars(), vd.alignment.get());
buf.writenl();
}
@@ -1008,12 +1013,12 @@ public:
if (ad.originalType && ad.type.ty == AST.Tpointer &&
(cast(AST.TypePointer)t).nextOf.ty == AST.Tfunction)
{
- origType = &ad.originalType;
+ origType = ad.originalType;
}
scope(exit) origType = null;
buf.writestring("typedef ");
- typeToBuffer(origType ? *origType : t, ad);
+ typeToBuffer(origType !is null ? origType : t, ad);
writeDeclEnd();
return;
}
@@ -1346,7 +1351,7 @@ public:
/// Starts a custom alignment section using `#pragma pack` if
/// `alignment` specifies a custom alignment
- private void pushAlignToBuffer(uint alignment)
+ private void pushAlignToBuffer(structalign_t alignment)
{
// DMD ensures alignment is a power of two
//assert(alignment > 0 && ((alignment & (alignment - 1)) == 0),
@@ -1354,20 +1359,20 @@ public:
// When no alignment is specified, `uint.max` is the default
// FIXME: alignment is 0 for structs templated members
- if (alignment == STRUCTALIGN_DEFAULT || (tdparent && alignment == 0))
+ if (alignment.isDefault() || (tdparent && alignment.isUnknown()))
{
return;
}
- buf.printf("#pragma pack(push, %d)", alignment);
+ buf.printf("#pragma pack(push, %d)", alignment.get());
buf.writenl();
}
/// Ends a custom alignment section using `#pragma pack` if
/// `alignment` specifies a custom alignment
- private void popAlignToBuffer(uint alignment)
+ private void popAlignToBuffer(structalign_t alignment)
{
- if (alignment == STRUCTALIGN_DEFAULT || (tdparent && alignment == 0))
+ if (alignment.isDefault() || (tdparent && alignment.isUnknown()))
return;
buf.writestringln("#pragma pack(pop)");
@@ -1645,7 +1650,7 @@ public:
}
this.ident = s.ident;
- auto type = origType ? *origType : t;
+ auto type = origType !is null ? origType : t;
AST.Dsymbol customLength;
// Check for quirks that are usually resolved during semantic
diff --git a/gcc/d/dmd/dversion.d b/gcc/d/dmd/dversion.d
index 0dff754..49ee4b3 100644
--- a/gcc/d/dmd/dversion.d
+++ b/gcc/d/dmd/dversion.d
@@ -22,7 +22,7 @@ import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.globals;
import dmd.identifier;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.visitor;
/***********************************************************
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 0d6fa1e..2a62332 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -59,7 +59,7 @@ import dmd.opover;
import dmd.optimize;
import dmd.root.ctfloat;
import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rmem;
import dmd.root.rootobject;
import dmd.root.string;
@@ -1201,20 +1201,14 @@ extern (C++) abstract class Expression : ASTNode
// DtorDeclaration without parents should fail at an earlier stage
auto ad = cast(AggregateDeclaration) f.toParent2();
assert(ad);
- assert(ad.dtors.length);
- // Search for the user-defined destructor (if any)
- foreach(dtor; ad.dtors)
+ if (ad.userDtors.dim)
{
- if (dtor.generated)
- continue;
-
- if (!check(dtor)) // doesn't match check (e.g. is impure as well)
+ if (!check(ad.userDtors[0])) // doesn't match check (e.g. is impure as well)
return;
// Sanity check
- assert(!check(cast(DtorDeclaration) ad.fieldDtor));
- break;
+ assert(!check(ad.fieldDtor));
}
dd.loc.errorSupplemental("%s`%s.~this` is %.*s because of the following field's destructors:",
@@ -1781,13 +1775,13 @@ extern (C++) final class IntegerExp : Expression
this.value = cast(d_int32)value;
}
- static IntegerExp create(Loc loc, dinteger_t value, Type type)
+ static IntegerExp create(const ref Loc loc, dinteger_t value, Type type)
{
return new IntegerExp(loc, value, type);
}
// Same as create, but doesn't allocate memory.
- static void emplace(UnionExp* pue, Loc loc, dinteger_t value, Type type)
+ static void emplace(UnionExp* pue, const ref Loc loc, dinteger_t value, Type type)
{
emplaceExp!(IntegerExp)(pue, loc, value, type);
}
@@ -2052,13 +2046,13 @@ extern (C++) final class RealExp : Expression
this.type = type;
}
- static RealExp create(Loc loc, real_t value, Type type)
+ static RealExp create(const ref Loc loc, real_t value, Type type)
{
return new RealExp(loc, value, type);
}
// Same as create, but doesn't allocate memory.
- static void emplace(UnionExp* pue, Loc loc, real_t value, Type type)
+ static void emplace(UnionExp* pue, const ref Loc loc, real_t value, Type type)
{
emplaceExp!(RealExp)(pue, loc, value, type);
}
@@ -2127,13 +2121,13 @@ extern (C++) final class ComplexExp : Expression
//printf("ComplexExp::ComplexExp(%s)\n", toChars());
}
- static ComplexExp create(Loc loc, complex_t value, Type type)
+ static ComplexExp create(const ref Loc loc, complex_t value, Type type)
{
return new ComplexExp(loc, value, type);
}
// Same as create, but doesn't allocate memory.
- static void emplace(UnionExp* pue, Loc loc, complex_t value, Type type)
+ static void emplace(UnionExp* pue, const ref Loc loc, complex_t value, Type type)
{
emplaceExp!(ComplexExp)(pue, loc, value, type);
}
@@ -2203,7 +2197,7 @@ extern (C++) class IdentifierExp : Expression
this.ident = ident;
}
- static IdentifierExp create(Loc loc, Identifier ident)
+ static IdentifierExp create(const ref Loc loc, Identifier ident)
{
return new IdentifierExp(loc, ident);
}
@@ -2421,28 +2415,28 @@ extern (C++) final class StringExp : Expression
this.postfix = postfix;
}
- static StringExp create(Loc loc, char* s)
+ static StringExp create(const ref Loc loc, const(char)* s)
{
return new StringExp(loc, s.toDString());
}
- static StringExp create(Loc loc, void* string, size_t len)
+ static StringExp create(const ref Loc loc, const(void)* string, size_t len)
{
return new StringExp(loc, string[0 .. len]);
}
// Same as create, but doesn't allocate memory.
- static void emplace(UnionExp* pue, Loc loc, char* s)
+ static void emplace(UnionExp* pue, const ref Loc loc, const(char)* s)
{
emplaceExp!(StringExp)(pue, loc, s.toDString());
}
- extern (D) static void emplace(UnionExp* pue, Loc loc, const(void)[] string)
+ extern (D) static void emplace(UnionExp* pue, const ref Loc loc, const(void)[] string)
{
emplaceExp!(StringExp)(pue, loc, string);
}
- extern (D) static void emplace(UnionExp* pue, Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix)
+ extern (D) static void emplace(UnionExp* pue, const ref Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix)
{
emplaceExp!(StringExp)(pue, loc, string, len, sz, postfix);
}
@@ -2863,7 +2857,7 @@ extern (C++) final class TupleExp : Expression
}
}
- static TupleExp create(Loc loc, Expressions* exps)
+ static TupleExp create(const ref Loc loc, Expressions* exps)
{
return new TupleExp(loc, exps);
}
@@ -2946,13 +2940,13 @@ extern (C++) final class ArrayLiteralExp : Expression
this.elements = elements;
}
- static ArrayLiteralExp create(Loc loc, Expressions* elements)
+ static ArrayLiteralExp create(const ref Loc loc, Expressions* elements)
{
return new ArrayLiteralExp(loc, null, elements);
}
// Same as create, but doesn't allocate memory.
- static void emplace(UnionExp* pue, Loc loc, Expressions* elements)
+ static void emplace(UnionExp* pue, const ref Loc loc, Expressions* elements)
{
emplaceExp!(ArrayLiteralExp)(pue, loc, null, elements);
}
@@ -3188,7 +3182,7 @@ extern (C++) final class StructLiteralExp : Expression
//printf("StructLiteralExp::StructLiteralExp(%s)\n", toChars());
}
- static StructLiteralExp create(Loc loc, StructDeclaration sd, void* elements, Type stype = null)
+ static StructLiteralExp create(const ref Loc loc, StructDeclaration sd, void* elements, Type stype = null)
{
return new StructLiteralExp(loc, sd, cast(Expressions*)elements, stype);
}
@@ -3532,7 +3526,7 @@ extern (C++) final class NewExp : Expression
this.arguments = arguments;
}
- static NewExp create(Loc loc, Expression thisexp, Expressions* newargs, Type newtype, Expressions* arguments)
+ static NewExp create(const ref Loc loc, Expression thisexp, Expressions* newargs, Type newtype, Expressions* arguments)
{
return new NewExp(loc, thisexp, newargs, newtype, arguments);
}
@@ -3653,7 +3647,7 @@ extern (C++) final class VarExp : SymbolExp
this.type = var.type;
}
- static VarExp create(Loc loc, Declaration var, bool hasOverloads = true)
+ static VarExp create(const ref Loc loc, Declaration var, bool hasOverloads = true)
{
return new VarExp(loc, var, hasOverloads);
}
@@ -3965,6 +3959,7 @@ extern (C++) final class FuncExp : Expression
auto tfy = new TypeFunction(tfx.parameterList, tof.next,
tfx.linkage, STC.undefined_);
tfy.mod = tfx.mod;
+ tfy.trust = tfx.trust;
tfy.isnothrow = tfx.isnothrow;
tfy.isnogc = tfx.isnogc;
tfy.purity = tfx.purity;
@@ -4688,6 +4683,7 @@ extern (C++) final class DotIdExp : UnaExp
Identifier ident;
bool noderef; // true if the result of the expression will never be dereferenced
bool wantsym; // do not replace Symbol with its initializer during semantic()
+ bool arrow; // ImportC: if -> instead of .
extern (D) this(const ref Loc loc, Expression e, Identifier ident)
{
@@ -4695,7 +4691,7 @@ extern (C++) final class DotIdExp : UnaExp
this.ident = ident;
}
- static DotIdExp create(Loc loc, Expression e, Identifier ident)
+ static DotIdExp create(const ref Loc loc, Expression e, Identifier ident)
{
return new DotIdExp(loc, e, ident);
}
@@ -4889,6 +4885,31 @@ extern (C++) final class DotTemplateInstanceExp : UnaExp
return ti.updateTempDecl(sc, s);
}
+ override bool checkType()
+ {
+ // Same logic as ScopeExp.checkType()
+ if (ti.tempdecl &&
+ ti.semantictiargsdone &&
+ ti.semanticRun == PASS.init)
+ {
+ error("partial %s `%s` has no type", ti.kind(), toChars());
+ return true;
+ }
+ return false;
+ }
+
+ override bool checkValue()
+ {
+ if (ti.tempdecl &&
+ ti.semantictiargsdone &&
+ ti.semanticRun == PASS.init)
+
+ error("partial %s `%s` has no value", ti.kind(), toChars());
+ else
+ error("%s `%s` has no value", ti.kind(), ti.toChars());
+ return true;
+ }
+
override void accept(Visitor v)
{
v.visit(this);
@@ -4987,17 +5008,17 @@ extern (C++) final class CallExp : UnaExp
this.f = fd;
}
- static CallExp create(Loc loc, Expression e, Expressions* exps)
+ static CallExp create(const ref Loc loc, Expression e, Expressions* exps)
{
return new CallExp(loc, e, exps);
}
- static CallExp create(Loc loc, Expression e)
+ static CallExp create(const ref Loc loc, Expression e)
{
return new CallExp(loc, e);
}
- static CallExp create(Loc loc, Expression e, Expression earg1)
+ static CallExp create(const ref Loc loc, Expression e, Expression earg1)
{
return new CallExp(loc, e, earg1);
}
@@ -5009,7 +5030,7 @@ extern (C++) final class CallExp : UnaExp
* fd = the declaration of the function to call
* earg1 = the function argument
*/
- static CallExp create(Loc loc, FuncDeclaration fd, Expression earg1)
+ static CallExp create(const ref Loc loc, FuncDeclaration fd, Expression earg1)
{
return new CallExp(loc, fd, earg1);
}
@@ -5167,6 +5188,19 @@ extern (C++) final class PtrExp : UnaExp
override Expression modifiableLvalue(Scope* sc, Expression e)
{
//printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type.toChars());
+ Declaration var;
+ if (auto se = e1.isSymOffExp())
+ var = se.var;
+ else if (auto ve = e1.isVarExp())
+ var = ve.var;
+ if (var && var.type.isFunction_Delegate_PtrToFunction())
+ {
+ if (var.type.isTypeFunction())
+ error("function `%s` is not an lvalue and cannot be modified", var.toChars());
+ else
+ error("function pointed to by `%s` is not an lvalue and cannot be modified", var.toChars());
+ return ErrorExp.get();
+ }
return Expression.modifiableLvalue(sc, e);
}
@@ -5331,13 +5365,13 @@ extern (C++) final class VectorExp : UnaExp
to = cast(TypeVector)t;
}
- static VectorExp create(Loc loc, Expression e, Type t)
+ static VectorExp create(const ref Loc loc, Expression e, Type t)
{
return new VectorExp(loc, e, t);
}
// Same as create, but doesn't allocate memory.
- static void emplace(UnionExp* pue, Loc loc, Expression e, Type type)
+ static void emplace(UnionExp* pue, const ref Loc loc, Expression e, Type type)
{
emplaceExp!(VectorExp)(pue, loc, e, type);
}
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index dec3713..691364c 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -57,6 +57,9 @@ enum
OWNEDcache // constant value cached for CTFE
};
+#define WANTvalue 0 // default
+#define WANTexpand 1 // expand const/immutable variables if possible
+
/**
* Specifies how the checkModify deals with certain situations
*/
@@ -239,8 +242,8 @@ class IntegerExp : public Expression
public:
dinteger_t value;
- static IntegerExp *create(Loc loc, dinteger_t value, Type *type);
- static void emplace(UnionExp *pue, Loc loc, dinteger_t value, Type *type);
+ static IntegerExp *create(const Loc &loc, dinteger_t value, Type *type);
+ static void emplace(UnionExp *pue, const Loc &loc, dinteger_t value, Type *type);
bool equals(const RootObject *o) const;
dinteger_t toInteger();
real_t toReal();
@@ -269,8 +272,8 @@ class RealExp : public Expression
public:
real_t value;
- static RealExp *create(Loc loc, real_t value, Type *type);
- static void emplace(UnionExp *pue, Loc loc, real_t value, Type *type);
+ static RealExp *create(const Loc &loc, real_t value, Type *type);
+ static void emplace(UnionExp *pue, const Loc &loc, real_t value, Type *type);
bool equals(const RootObject *o) const;
dinteger_t toInteger();
uinteger_t toUInteger();
@@ -286,8 +289,8 @@ class ComplexExp : public Expression
public:
complex_t value;
- static ComplexExp *create(Loc loc, complex_t value, Type *type);
- static void emplace(UnionExp *pue, Loc loc, complex_t value, Type *type);
+ static ComplexExp *create(const Loc &loc, complex_t value, Type *type);
+ static void emplace(UnionExp *pue, const Loc &loc, complex_t value, Type *type);
bool equals(const RootObject *o) const;
dinteger_t toInteger();
uinteger_t toUInteger();
@@ -303,7 +306,7 @@ class IdentifierExp : public Expression
public:
Identifier *ident;
- static IdentifierExp *create(Loc loc, Identifier *ident);
+ static IdentifierExp *create(const Loc &loc, Identifier *ident);
bool isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
void accept(Visitor *v) { v->visit(this); }
@@ -365,10 +368,9 @@ public:
utf8_t postfix; // 'c', 'w', 'd'
OwnedBy ownedByCtfe;
- static StringExp *create(Loc loc, char *s);
- static StringExp *create(Loc loc, void *s, size_t len);
- static void emplace(UnionExp *pue, Loc loc, char *s);
- static void emplace(UnionExp *pue, Loc loc, void *s, size_t len);
+ static StringExp *create(const Loc &loc, const char *s);
+ static StringExp *create(const Loc &loc, const void *s, size_t len);
+ static void emplace(UnionExp *pue, const Loc &loc, const char *s);
bool equals(const RootObject *o) const;
StringExp *toStringExp();
StringExp *toUTF8(Scope *sc);
@@ -397,7 +399,7 @@ public:
*/
Expressions *exps;
- static TupleExp *create(Loc loc, Expressions *exps);
+ static TupleExp *create(const Loc &loc, Expressions *exps);
TupleExp *toTupleExp();
TupleExp *syntaxCopy();
bool equals(const RootObject *o) const;
@@ -412,8 +414,8 @@ public:
Expressions *elements;
OwnedBy ownedByCtfe;
- static ArrayLiteralExp *create(Loc loc, Expressions *elements);
- static void emplace(UnionExp *pue, Loc loc, Expressions *elements);
+ static ArrayLiteralExp *create(const Loc &loc, Expressions *elements);
+ static void emplace(UnionExp *pue, const Loc &loc, Expressions *elements);
ArrayLiteralExp *syntaxCopy();
bool equals(const RootObject *o) const;
Expression *getElement(d_size_t i); // use opIndex instead
@@ -468,7 +470,7 @@ public:
bool isOriginal; // used when moving instances to indicate `this is this.origin`
OwnedBy ownedByCtfe;
- static StructLiteralExp *create(Loc loc, StructDeclaration *sd, void *elements, Type *stype = NULL);
+ static StructLiteralExp *create(const Loc &loc, StructDeclaration *sd, void *elements, Type *stype = NULL);
bool equals(const RootObject *o) const;
StructLiteralExp *syntaxCopy();
Expression *getField(Type *type, unsigned offset);
@@ -528,7 +530,7 @@ public:
bool onstack; // allocate on stack
bool thrownew; // this NewExp is the expression of a ThrowStatement
- static NewExp *create(Loc loc, Expression *thisexp, Expressions *newargs, Type *newtype, Expressions *arguments);
+ static NewExp *create(const Loc &loc, Expression *thisexp, Expressions *newargs, Type *newtype, Expressions *arguments);
NewExp *syntaxCopy();
void accept(Visitor *v) { v->visit(this); }
@@ -576,7 +578,7 @@ class VarExp : public SymbolExp
{
public:
bool delegateWasExtracted;
- static VarExp *create(Loc loc, Declaration *var, bool hasOverloads = true);
+ static VarExp *create(const Loc &loc, Declaration *var, bool hasOverloads = true);
bool equals(const RootObject *o) const;
bool isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
@@ -746,8 +748,9 @@ public:
Identifier *ident;
bool noderef; // true if the result of the expression will never be dereferenced
bool wantsym; // do not replace Symbol with its initializer during semantic()
+ bool arrow; // ImportC: if -> instead of .
- static DotIdExp *create(Loc loc, Expression *e, Identifier *ident);
+ static DotIdExp *create(const Loc &loc, Expression *e, Identifier *ident);
void accept(Visitor *v) { v->visit(this); }
};
@@ -780,6 +783,8 @@ public:
DotTemplateInstanceExp *syntaxCopy();
bool findTempDecl(Scope *sc);
+ bool checkType();
+ bool checkValue();
void accept(Visitor *v) { v->visit(this); }
};
@@ -812,10 +817,10 @@ public:
bool ignoreAttributes; // don't enforce attributes (e.g. call @gc function in @nogc code)
VarDeclaration *vthis2; // container for multi-context
- static CallExp *create(Loc loc, Expression *e, Expressions *exps);
- static CallExp *create(Loc loc, Expression *e);
- static CallExp *create(Loc loc, Expression *e, Expression *earg1);
- static CallExp *create(Loc loc, FuncDeclaration *fd, Expression *earg1);
+ static CallExp *create(const Loc &loc, Expression *e, Expressions *exps);
+ static CallExp *create(const Loc &loc, Expression *e);
+ static CallExp *create(const Loc &loc, Expression *e, Expression *earg1);
+ static CallExp *create(const Loc &loc, FuncDeclaration *fd, Expression *earg1);
CallExp *syntaxCopy();
bool isLvalue();
@@ -893,8 +898,8 @@ public:
unsigned dim; // number of elements in the vector
OwnedBy ownedByCtfe;
- static VectorExp *create(Loc loc, Expression *e, Type *t);
- static void emplace(UnionExp *pue, Loc loc, Expression *e, Type *t);
+ static VectorExp *create(const Loc &loc, Expression *e, Type *t);
+ static void emplace(UnionExp *pue, const Loc &loc, Expression *e, Type *t);
VectorExp *syntaxCopy();
void accept(Visitor *v) { v->visit(this); }
};
@@ -1272,7 +1277,7 @@ public:
class GenericExp : Expression
{
- Expression cntlExp;
+ Expression *cntlExp;
Types *types;
Expressions *exps;
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 3b604af..8e152d6 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -43,12 +43,14 @@ import dmd.dtemplate;
import dmd.errors;
import dmd.escape;
import dmd.expression;
+import dmd.file_manager;
import dmd.func;
import dmd.globals;
import dmd.hdrgen;
import dmd.id;
import dmd.identifier;
import dmd.imphint;
+import dmd.importc;
import dmd.init;
import dmd.initsem;
import dmd.inline;
@@ -62,7 +64,7 @@ import dmd.printast;
import dmd.root.ctfloat;
import dmd.root.file;
import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rootobject;
import dmd.root.string;
import dmd.semantic2;
@@ -1239,6 +1241,10 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
tthis = dve.e1.type;
goto Lfd;
}
+ else if (sc && sc.flags & SCOPE.Cfile && e1.op == TOK.variable && !e2)
+ {
+ // ImportC: do not implicitly call function if no ( ) are present
+ }
else if (e1.op == TOK.variable && e1.type && (e1.type.toBasetype().ty == Tfunction || (cast(VarExp)e1).var.isOverDeclaration()))
{
s = (cast(VarExp)e1).var;
@@ -1388,7 +1394,6 @@ private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
Type t0 = null;
Expression e0 = null;
- size_t j0 = ~0;
bool foundType;
for (size_t i = 0; i < exps.dim; i++)
@@ -1441,17 +1446,16 @@ private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
{
// https://issues.dlang.org/show_bug.cgi?id=21285
// Functions and delegates don't convert correctly with castTo below
- exps[j0] = condexp.e1;
+ exps[i] = condexp.e1;
e = condexp.e2;
}
else
{
// Convert to common type
- exps[j0] = condexp.e1.castTo(sc, condexp.type);
+ exps[i] = condexp.e1.castTo(sc, condexp.type);
e = condexp.e2.castTo(sc, condexp.type);
}
}
- j0 = i;
e0 = e;
t0 = e.type;
if (e.op != TOK.error)
@@ -1599,6 +1603,7 @@ private bool preFunctionParameters(Scope* sc, Expressions* exps, const bool repo
{
Expression arg = (*exps)[i];
arg = resolveProperties(sc, arg);
+ arg = arg.arrayFuncConv(sc);
if (arg.op == TOK.type)
{
// for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
@@ -4297,7 +4302,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* expr.foo!(tiargs)(funcargs)
*/
Ldotti:
- if (exp.e1.op == TOK.dotTemplateInstance && !exp.e1.type)
+ if (exp.e1.op == TOK.dotTemplateInstance)
{
DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)exp.e1;
TemplateInstance ti = se.ti;
@@ -4352,7 +4357,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* We handle such earlier, so go back.
* Note that in the rewrite, we carefully did not run semantic() on e1
*/
- if (exp.e1.op == TOK.dotTemplateInstance && !exp.e1.type)
+ if (exp.e1.op == TOK.dotTemplateInstance)
{
goto Ldotti;
}
@@ -4419,6 +4424,26 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
else if (exp.e1.op == TOK.type && (sc && sc.flags & SCOPE.Cfile))
{
+ const numArgs = exp.arguments ? exp.arguments.length : 0;
+ if (e1org.parens && numArgs >= 1)
+ {
+ /* Ambiguous cases arise from CParser where there is not enough
+ * information to determine if we have a function call or a cast.
+ * ( type-name ) ( identifier ) ;
+ * ( identifier ) ( identifier ) ;
+ * If exp.e1 is a type-name, then this is a cast.
+ */
+ Expression arg;
+ foreach (a; (*exp.arguments)[])
+ {
+ arg = arg ? new CommaExp(a.loc, arg, a) : a;
+ }
+ auto t = exp.e1.isTypeExp().type;
+ auto e = new CastExp(exp.loc, arg, t);
+ result = e.expressionSemantic(sc);
+ return;
+ }
+
/* Ambiguous cases arise from CParser where there is not enough
* information to determine if we have a function call or declaration.
* type-name ( identifier ) ;
@@ -4426,7 +4451,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* If exp.e1 is a type-name, then this is a declaration. C11 does not
* have type construction syntax, so don't convert this to a cast().
*/
- if (exp.arguments && exp.arguments.dim == 1)
+ if (numArgs == 1)
{
Expression arg = (*exp.arguments)[0];
if (auto ie = (*exp.arguments)[0].isIdentifierExp())
@@ -4638,15 +4663,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
UnaExp ue = cast(UnaExp)exp.e1;
- Expression ue1 = ue.e1;
- Expression ue1old = ue1; // need for 'right this' check
- VarDeclaration v;
- if (ue1.op == TOK.variable && (v = (cast(VarExp)ue1).var.isVarDeclaration()) !is null && v.needThis())
- {
- ue.e1 = new TypeExp(ue1.loc, ue1.type);
- ue1 = null;
- }
-
+ Expression ue1old = ue.e1; // need for 'right this' check
DotVarExp dve;
DotTemplateExp dte;
Dsymbol s;
@@ -4665,7 +4682,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
// Do overload resolution
- exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue1 ? ue1.type : null, exp.arguments, FuncResolveFlag.standard);
+ exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue.e1.type, exp.arguments, FuncResolveFlag.standard);
if (!exp.f || exp.f.errors || exp.f.type.ty == Terror)
return setError();
@@ -4677,7 +4694,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
auto ad2 = b.sym;
ue.e1 = ue.e1.castTo(sc, ad2.type.addMod(ue.e1.type.mod));
ue.e1 = ue.e1.expressionSemantic(sc);
- ue1 = ue.e1;
auto vi = exp.f.findVtblIndex(&ad2.vtbl, cast(int)ad2.vtbl.dim);
assert(vi >= 0);
exp.f = ad2.vtbl[vi].isFuncDeclaration();
@@ -6036,17 +6052,29 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
{
- auto readResult = File.read(name);
- if (!readResult.success)
+ auto fileName = FileName(name.toDString);
+ if (auto fmResult = FileManager.fileManager.lookup(fileName))
{
- e.error("cannot read file `%s`", name);
- return setError();
+ se = new StringExp(e.loc, fmResult.data);
}
else
{
- // take ownership of buffer (probably leaking)
- auto data = readResult.extractSlice();
- se = new StringExp(e.loc, data);
+ auto readResult = File.read(name);
+ if (!readResult.success)
+ {
+ e.error("cannot read file `%s`", name);
+ return setError();
+ }
+ else
+ {
+ // take ownership of buffer (probably leaking)
+ auto data = readResult.extractSlice();
+ se = new StringExp(e.loc, data);
+
+ FileBuffer* fileBuffer = FileBuffer.create();
+ fileBuffer.data = data;
+ FileManager.fileManager.add(fileName, fileBuffer);
+ }
}
}
result = se.expressionSemantic(sc);
@@ -6357,7 +6385,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = e;
return;
}
- exp.type = Type.tnoreturn;
+
+ // Only override the type when it isn't already some flavour of noreturn,
+ // e.g. when this assert was generated by defaultInitLiteral
+ if (!exp.type || !exp.type.isTypeNoreturn())
+ exp.type = Type.tnoreturn;
}
else
exp.type = Type.tvoid;
@@ -6374,12 +6406,53 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
printf("DotIdExp::semantic(this = %p, '%s')\n", exp, exp.toChars());
//printf("e1.op = %d, '%s'\n", e1.op, Token::toChars(e1.op));
}
+ if (exp.arrow) // ImportC only
+ exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
+
+ if (sc.flags & SCOPE.Cfile)
+ {
+ if (exp.ident == Id.__xalignof && exp.e1.isTypeExp())
+ {
+ // C11 6.5.3 says _Alignof only applies to types
+ Expression e;
+ Type t;
+ Dsymbol s;
+ dmd.typesem.resolve(exp.e1.type, exp.e1.loc, sc, e, t, s, true);
+ if (e)
+ {
+ exp.e1.error("argument to `_Alignof` must be a type");
+ return setError();
+ }
+ else if (t)
+ {
+ result = new IntegerExp(exp.loc, t.alignsize, Type.tsize_t);
+ }
+ else if (s)
+ {
+ exp.e1.error("argument to `_Alignof` must be a type");
+ return setError();
+ }
+ else
+ assert(0);
+ return;
+ }
+ }
+
+ if (sc.flags & SCOPE.Cfile && exp.ident != Id.__sizeof)
+ {
+ result = fieldLookup(exp.e1, sc, exp.ident);
+ return;
+ }
+
Expression e = exp.semanticY(sc, 1);
+
if (e && isDotOpDispatch(e))
{
+ auto ode = e;
uint errors = global.startGagging();
e = resolvePropertiesX(sc, e);
- if (global.endGagging(errors))
+ // Any error or if 'e' is not resolved, go to UFCS
+ if (global.endGagging(errors) || e is ode)
e = null; /* fall down to UFCS */
else
{
@@ -6580,10 +6653,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
printf("DotTemplateInstanceExp::semantic('%s')\n", exp.toChars());
}
+ if (exp.type)
+ {
+ result = exp;
+ return;
+ }
// Indicate we need to resolve by UFCS.
Expression e = exp.semanticY(sc, 1);
if (!e)
e = resolveUFCSProperties(sc, exp);
+ if (e is exp)
+ e.type = Type.tvoid; // Unresolved type, because it needs inference
result = e;
}
@@ -7908,6 +7988,16 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
dinteger_t length = el.toInteger();
auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length));
exp.upperIsInBounds = bounds.contains(uprRange);
+ if (exp.lwr.op == TOK.int64 && exp.upr.op == TOK.int64 && exp.lwr.toInteger() > exp.upr.toInteger())
+ {
+ exp.error("in slice `%s[%llu .. %llu]`, lower bound is greater than upper bound", exp.e1.toChars, exp.lwr.toInteger(), exp.upr.toInteger());
+ return setError();
+ }
+ if (exp.upr.op == TOK.int64 && exp.upr.toInteger() > length)
+ {
+ exp.error("in slice `%s[%llu .. %llu]`, upper bound is greater than array length `%llu`", exp.e1.toChars, exp.lwr.toInteger(), exp.upr.toInteger(), length);
+ return setError();
+ }
}
else if (exp.upr.op == TOK.int64 && exp.upr.toInteger() == 0)
{
@@ -7965,6 +8055,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
printf("ArrayExp::semantic('%s')\n", exp.toChars());
}
assert(!exp.type);
+
+ result = exp.carraySemantic(sc); // C semantics
+ if (result)
+ return;
+
Expression e = exp.op_overload(sc);
if (e)
{
@@ -8019,6 +8114,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
override void visit(CommaExp e)
{
+ //printf("Semantic.CommaExp() %s\n", e.toChars());
if (e.type)
{
result = e;
@@ -8042,10 +8138,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (checkNonAssignmentArrayOp(e.e1))
return setError();
+ // Comma expressions trigger this conversion
+ e.e2 = e.e2.arrayFuncConv(sc);
+
e.type = e.e2.type;
if (e.type is Type.tvoid)
discardValue(e.e1);
- else if (!e.allowCommaExp && !e.isGenerated)
+ else if (!e.allowCommaExp && !e.isGenerated && !(sc.flags & SCOPE.Cfile))
e.error("Using the result of a comma expression is not allowed");
result = e;
}
@@ -8143,7 +8242,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// operator overloading should be handled in ArrayExp already.
if (!exp.e1.type)
- exp.e1 = exp.e1.expressionSemantic(sc);
+ exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
assert(exp.e1.type); // semantic() should already be run on it
if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple)
{
@@ -8191,7 +8290,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
if (t1b.ty == Ttuple)
sc = sc.startCTFE();
- exp.e2 = exp.e2.expressionSemantic(sc);
+ exp.e2 = exp.e2.expressionSemantic(sc).arrayFuncConv(sc);
exp.e2 = resolveProperties(sc, exp.e2);
if (t1b.ty == Ttuple)
sc = sc.endCTFE();
@@ -8515,7 +8614,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (auto e2comma = exp.e2.isCommaExp())
{
- if (!e2comma.isGenerated)
+ if (!e2comma.isGenerated && !(sc.flags & SCOPE.Cfile))
exp.error("Using the result of a comma expression is not allowed");
/* Rewrite to get rid of the comma from rvalue
@@ -8659,6 +8758,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
e1x = e;
}
+ else if (sc.flags & SCOPE.Cfile && e1x.isDotIdExp())
+ {
+ auto die = e1x.isDotIdExp();
+ e1x = fieldLookup(die.e1, sc, die.ident);
+ }
else if (auto die = e1x.isDotIdExp())
{
Expression e = die.semanticY(sc, 1);
@@ -8672,10 +8776,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* In order to make sure that UFCS is tried with correct parameters, e2
* needs to have semantic ran on it.
*/
+ auto ode = e;
exp.e2 = exp.e2.expressionSemantic(sc);
uint errors = global.startGagging();
e = resolvePropertiesX(sc, e, exp.e2);
- if (global.endGagging(errors))
+ // Any error or if 'e' is not resolved, go to UFCS
+ if (global.endGagging(errors) || e is ode)
e = null; /* fall down to UFCS */
else
return setResult(e);
@@ -8717,12 +8823,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
Expression e2x = inferType(exp.e2, t1.baseElemOf());
e2x = e2x.expressionSemantic(sc);
+ if (!t1.isTypeSArray())
+ e2x = e2x.arrayFuncConv(sc);
e2x = resolveProperties(sc, e2x);
if (e2x.op == TOK.type)
e2x = resolveAliasThis(sc, e2x); //https://issues.dlang.org/show_bug.cgi?id=17684
if (e2x.op == TOK.error)
return setResult(e2x);
- // We skip checking the value for structs/classes as these might have
+ // We delay checking the value for structs/classes as these might have
// an opAssign defined.
if ((t1.ty != Tstruct && t1.ty != Tclass && e2x.checkValue()) ||
e2x.checkSharedAccess(sc))
@@ -9208,6 +9316,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
else
assert(exp.op == TOK.blit);
+ if (e2x.checkValue())
+ return setError();
+
exp.e1 = e1x;
exp.e2 = e2x;
}
@@ -9223,6 +9334,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
}
+ if (exp.e2.checkValue())
+ return setError();
}
else if (t1.ty == Tsarray)
{
@@ -9672,7 +9785,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.type = exp.e1.type;
assert(exp.type);
auto res = exp.op == TOK.assign ? exp.reorderSettingAAElem(sc) : exp;
- checkAssignEscape(sc, res, false);
+ Expression tmp;
+ /* https://issues.dlang.org/show_bug.cgi?id=22366
+ *
+ * `reorderSettingAAElem` creates a tree of comma expressions, however,
+ * `checkAssignExp` expects only AssignExps.
+ */
+ checkAssignEscape(sc, Expression.extractLast(res, tmp), false);
return setResult(res);
}
@@ -9944,6 +10063,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
+ /* ImportC: convert arrays to pointers, functions to pointers to functions
+ */
+ exp.e1 = exp.e1.arrayFuncConv(sc);
+ exp.e2 = exp.e2.arrayFuncConv(sc);
+
Type tb1 = exp.e1.type.toBasetype();
Type tb2 = exp.e2.type.toBasetype();
@@ -10045,6 +10169,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
+ /* ImportC: convert arrays to pointers, functions to pointers to functions
+ */
+ exp.e1 = exp.e1.arrayFuncConv(sc);
+ exp.e2 = exp.e2.arrayFuncConv(sc);
+
Type t1 = exp.e1.type.toBasetype();
Type t2 = exp.e2.type.toBasetype();
@@ -11539,12 +11668,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
ec = ec.toBoolean(sc);
CtorFlow ctorflow_root = sc.ctorflow.clone();
- Expression e1x = exp.e1.expressionSemantic(sc);
+ Expression e1x = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
e1x = resolveProperties(sc, e1x);
CtorFlow ctorflow1 = sc.ctorflow;
sc.ctorflow = ctorflow_root;
- Expression e2x = exp.e2.expressionSemantic(sc);
+ Expression e2x = exp.e2.expressionSemantic(sc).arrayFuncConv(sc);
e2x = resolveProperties(sc, e2x);
sc.merge(exp.loc, ctorflow1);
@@ -11894,95 +12023,84 @@ Expression semanticX(DotIdExp exp, Scope* sc)
if (exp.ident == Id._mangleof)
{
// symbol.mangleof
- Dsymbol ds;
- switch (exp.e1.op)
+
+ // return mangleof as an Expression
+ static Expression dotMangleof(const ref Loc loc, Scope* sc, Dsymbol ds)
{
- case TOK.scope_:
- ds = (cast(ScopeExp)exp.e1).sds;
- goto L1;
- case TOK.variable:
- ds = (cast(VarExp)exp.e1).var;
- goto L1;
- case TOK.dotVariable:
- ds = (cast(DotVarExp)exp.e1).var;
- goto L1;
- case TOK.overloadSet:
- ds = (cast(OverExp)exp.e1).vars;
- goto L1;
- case TOK.template_:
- {
- TemplateExp te = cast(TemplateExp)exp.e1;
- ds = te.fd ? cast(Dsymbol)te.fd : te.td;
- }
- L1:
+ assert(ds);
+ if (auto f = ds.isFuncDeclaration())
{
- assert(ds);
- if (auto f = ds.isFuncDeclaration())
+ if (f.checkForwardRef(loc))
+ return ErrorExp.get();
+
+ if (f.flags & (FUNCFLAG.purityInprocess | FUNCFLAG.safetyInprocess |
+ FUNCFLAG.nothrowInprocess | FUNCFLAG.nogcInprocess))
{
- if (f.checkForwardRef(exp.loc))
- {
- return ErrorExp.get();
- }
- if (f.flags & (FUNCFLAG.purityInprocess | FUNCFLAG.safetyInprocess |
- FUNCFLAG.nothrowInprocess | FUNCFLAG.nogcInprocess))
- {
- f.error(exp.loc, "cannot retrieve its `.mangleof` while inferring attributes");
- return ErrorExp.get();
- }
+ f.error(loc, "cannot retrieve its `.mangleof` while inferring attributes");
+ return ErrorExp.get();
}
- OutBuffer buf;
- mangleToBuffer(ds, &buf);
- Expression e = new StringExp(exp.loc, buf.extractSlice());
- e = e.expressionSemantic(sc);
- return e;
}
- default:
- break;
+ OutBuffer buf;
+ mangleToBuffer(ds, &buf);
+ Expression e = new StringExp(loc, buf.extractSlice());
+ return e.expressionSemantic(sc);
+ }
+
+ Dsymbol ds;
+ switch (exp.e1.op)
+ {
+ case TOK.scope_: return dotMangleof(exp.loc, sc, exp.e1.isScopeExp().sds);
+ case TOK.variable: return dotMangleof(exp.loc, sc, exp.e1.isVarExp().var);
+ case TOK.dotVariable: return dotMangleof(exp.loc, sc, exp.e1.isDotVarExp().var);
+ case TOK.overloadSet: return dotMangleof(exp.loc, sc, exp.e1.isOverExp().vars);
+ case TOK.template_:
+ {
+ TemplateExp te = exp.e1.isTemplateExp();
+ return dotMangleof(exp.loc, sc, ds = te.fd ? te.fd.isDsymbol() : te.td);
+ }
+
+ default:
+ break;
}
}
- if (exp.e1.op == TOK.variable && exp.e1.type.toBasetype().ty == Tsarray && exp.ident == Id.length)
+ if (exp.e1.isVarExp() && exp.e1.type.toBasetype().isTypeSArray() && exp.ident == Id.length)
{
// bypass checkPurity
return exp.e1.type.dotExp(sc, exp.e1, exp.ident, exp.noderef ? DotExpFlag.noDeref : 0);
}
- if (exp.e1.op == TOK.dot)
- {
- }
- else
+ if (!exp.e1.isDotExp())
{
exp.e1 = resolvePropertiesX(sc, exp.e1);
}
- if (exp.e1.op == TOK.tuple && exp.ident == Id.offsetof)
+
+ if (auto te = exp.e1.isTupleExp())
{
- /* 'distribute' the .offsetof to each of the tuple elements.
- */
- TupleExp te = cast(TupleExp)exp.e1;
- auto exps = new Expressions(te.exps.dim);
- for (size_t i = 0; i < exps.dim; i++)
+ if (exp.ident == Id.offsetof)
{
- Expression e = (*te.exps)[i];
+ /* 'distribute' the .offsetof to each of the tuple elements.
+ */
+ auto exps = new Expressions(te.exps.dim);
+ foreach (i, e; (*te.exps)[])
+ {
+ (*exps)[i] = new DotIdExp(e.loc, e, Id.offsetof);
+ }
+ // Don't evaluate te.e0 in runtime
+ Expression e = new TupleExp(exp.loc, null, exps);
e = e.expressionSemantic(sc);
- e = new DotIdExp(e.loc, e, Id.offsetof);
- (*exps)[i] = e;
+ return e;
+ }
+ if (exp.ident == Id.length)
+ {
+ // Don't evaluate te.e0 in runtime
+ return new IntegerExp(exp.loc, te.exps.dim, Type.tsize_t);
}
- // Don't evaluate te.e0 in runtime
- Expression e = new TupleExp(exp.loc, null, exps);
- e = e.expressionSemantic(sc);
- return e;
- }
- if (exp.e1.op == TOK.tuple && exp.ident == Id.length)
- {
- TupleExp te = cast(TupleExp)exp.e1;
- // Don't evaluate te.e0 in runtime
- Expression e = new IntegerExp(exp.loc, te.exps.dim, Type.tsize_t);
- return e;
}
// https://issues.dlang.org/show_bug.cgi?id=14416
// Template has no built-in properties except for 'stringof'.
- if ((exp.e1.op == TOK.dotTemplateDeclaration || exp.e1.op == TOK.template_) && exp.ident != Id.stringof)
+ if ((exp.e1.isDotTemplateExp() || exp.e1.isTemplateExp()) && exp.ident != Id.stringof)
{
exp.error("template `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
return ErrorExp.get();
@@ -11996,8 +12114,15 @@ Expression semanticX(DotIdExp exp, Scope* sc)
return exp;
}
-// Resolve e1.ident without seeing UFCS.
-// If flag == 1, stop "not a property" error and return NULL.
+/******************************
+ * Resolve properties, i.e. `e1.ident`, without seeing UFCS.
+ * Params:
+ * exp = expression to resolve
+ * sc = context
+ * flag = if 1 then do not emit error messages, just return null
+ * Returns:
+ * resolved expression, null if error
+ */
Expression semanticY(DotIdExp exp, Scope* sc, int flag)
{
//printf("DotIdExp::semanticY(this = %p, '%s')\n", exp, exp.toChars());
@@ -12008,32 +12133,35 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
* to be classtype.id and baseclasstype.id
* if we have no this pointer.
*/
- if ((exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) && !hasThis(sc))
+ if ((exp.e1.isThisExp() || exp.e1.isSuperExp()) && !hasThis(sc))
{
if (AggregateDeclaration ad = sc.getStructClassScope())
{
- if (exp.e1.op == TOK.this_)
+ if (exp.e1.isThisExp())
{
exp.e1 = new TypeExp(exp.e1.loc, ad.type);
}
else
{
- ClassDeclaration cd = ad.isClassDeclaration();
- if (cd && cd.baseClass)
- exp.e1 = new TypeExp(exp.e1.loc, cd.baseClass.type);
+ if (auto cd = ad.isClassDeclaration())
+ {
+ if (cd.baseClass)
+ exp.e1 = new TypeExp(exp.e1.loc, cd.baseClass.type);
+ }
}
}
}
- Expression e = semanticX(exp, sc);
- if (e != exp)
- return e;
+ {
+ Expression e = semanticX(exp, sc);
+ if (e != exp)
+ return e;
+ }
Expression eleft;
Expression eright;
- if (exp.e1.op == TOK.dot)
+ if (auto de = exp.e1.isDotExp())
{
- DotExp de = cast(DotExp)exp.e1;
eleft = de.e1;
eright = de.e2;
}
@@ -12045,11 +12173,9 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
Type t1b = exp.e1.type.toBasetype();
- if (eright.op == TOK.scope_) // also used for template alias's
+ if (auto ie = eright.isScopeExp()) // also used for template alias's
{
- ScopeExp ie = cast(ScopeExp)eright;
-
- int flags = SearchLocalsOnly;
+ auto flags = SearchLocalsOnly;
/* Disable access to another module's private imports.
* The check for 'is sds our current module' is because
* the current module should have access to its own imports.
@@ -12082,13 +12208,11 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
exp.checkDeprecated(sc, s);
exp.checkDisabled(sc, s);
- EnumMember em = s.isEnumMember();
- if (em)
+ if (auto em = s.isEnumMember())
{
return em.getVarExp(exp.loc, sc);
}
- VarDeclaration v = s.isVarDeclaration();
- if (v)
+ if (auto v = s.isVarDeclaration())
{
//printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars());
if (!v.type ||
@@ -12100,7 +12224,7 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
exp.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars());
return ErrorExp.get();
}
- if (v.type.ty == Terror)
+ if (v.type.isTypeError())
return ErrorExp.get();
if ((v.storage_class & STC.manifest) && v._init && !exp.wantsym)
@@ -12114,13 +12238,14 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
error(exp.loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
return ErrorExp.get();
}
- e = v.expandInitializer(exp.loc);
+ auto e = v.expandInitializer(exp.loc);
v.inuse++;
e = e.expressionSemantic(sc);
v.inuse--;
return e;
}
+ Expression e;
if (v.needThis())
{
if (!eleft)
@@ -12141,12 +12266,12 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
return e.expressionSemantic(sc);
}
- FuncDeclaration f = s.isFuncDeclaration();
- if (f)
+ if (auto f = s.isFuncDeclaration())
{
//printf("it's a function\n");
if (!f.functionSemantic())
return ErrorExp.get();
+ Expression e;
if (f.needThis())
{
if (!eleft)
@@ -12167,6 +12292,7 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
}
if (auto td = s.isTemplateDeclaration())
{
+ Expression e;
if (eleft)
e = new DotTemplateExp(exp.loc, eleft, td);
else
@@ -12176,7 +12302,7 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
}
if (OverDeclaration od = s.isOverDeclaration())
{
- e = new VarExp(exp.loc, od, true);
+ Expression e = new VarExp(exp.loc, od, true);
if (eleft)
{
e = new CommaExp(exp.loc, eleft, e);
@@ -12184,8 +12310,7 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
}
return e;
}
- OverloadSet o = s.isOverloadSet();
- if (o)
+ if (auto o = s.isOverloadSet())
{
//printf("'%s' is an overload set\n", o.toChars());
return new OverExp(exp.loc, o);
@@ -12196,36 +12321,33 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
return (new TypeExp(exp.loc, t)).expressionSemantic(sc);
}
- TupleDeclaration tup = s.isTupleDeclaration();
- if (tup)
+ if (auto tup = s.isTupleDeclaration())
{
if (eleft)
{
- e = new DotVarExp(exp.loc, eleft, tup);
+ Expression e = new DotVarExp(exp.loc, eleft, tup);
e = e.expressionSemantic(sc);
return e;
}
- e = new TupleExp(exp.loc, tup);
+ Expression e = new TupleExp(exp.loc, tup);
e = e.expressionSemantic(sc);
return e;
}
- ScopeDsymbol sds = s.isScopeDsymbol();
- if (sds)
+ if (auto sds = s.isScopeDsymbol())
{
//printf("it's a ScopeDsymbol %s\n", ident.toChars());
- e = new ScopeExp(exp.loc, sds);
+ Expression e = new ScopeExp(exp.loc, sds);
e = e.expressionSemantic(sc);
if (eleft)
e = new DotExp(exp.loc, eleft, e);
return e;
}
- Import imp = s.isImport();
- if (imp)
+ if (auto imp = s.isImport())
{
- ie = new ScopeExp(exp.loc, imp.pkg);
- return ie.expressionSemantic(sc);
+ Expression se = new ScopeExp(exp.loc, imp.pkg);
+ return se.expressionSemantic(sc);
}
// BUG: handle other cases like in IdentifierExp::semantic()
debug
@@ -12236,7 +12358,7 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
}
else if (exp.ident == Id.stringof)
{
- e = new StringExp(exp.loc, ie.toString());
+ Expression e = new StringExp(exp.loc, ie.toString());
e = e.expressionSemantic(sc);
return e;
}
@@ -12263,9 +12385,11 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
Type t1bn = t1b.nextOf();
if (flag)
{
- AggregateDeclaration ad = isAggregate(t1bn);
- if (ad && !ad.members) // https://issues.dlang.org/show_bug.cgi?id=11312
- return null;
+ if (AggregateDeclaration ad = isAggregate(t1bn))
+ {
+ if (!ad.members) // https://issues.dlang.org/show_bug.cgi?id=11312
+ return null;
+ }
}
/* Rewrite:
@@ -12275,27 +12399,27 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
*/
if (flag && t1bn.ty == Tvoid)
return null;
- e = new PtrExp(exp.loc, exp.e1);
+ Expression e = new PtrExp(exp.loc, exp.e1);
e = e.expressionSemantic(sc);
return e.type.dotExp(sc, e, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
}
else if (exp.ident == Id.__xalignof &&
exp.e1.isVarExp() &&
exp.e1.isVarExp().var.isVarDeclaration() &&
- exp.e1.isVarExp().var.isVarDeclaration().alignment)
+ !exp.e1.isVarExp().var.isVarDeclaration().alignment.isUnknown())
{
// For `x.alignof` get the alignment of the variable, not the alignment of its type
const explicitAlignment = exp.e1.isVarExp().var.isVarDeclaration().alignment;
const naturalAlignment = exp.e1.type.alignsize();
- const actualAlignment = (explicitAlignment == STRUCTALIGN_DEFAULT ? naturalAlignment : explicitAlignment);
- e = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
+ const actualAlignment = explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get();
+ Expression e = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
return e;
}
else
{
- if (exp.e1.op == TOK.type || exp.e1.op == TOK.template_)
+ if (exp.e1.isTypeExp() || exp.e1.isTemplateExp())
flag = 0;
- e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
+ Expression e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
if (e)
e = e.expressionSemantic(sc);
return e;
@@ -12875,7 +12999,7 @@ private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions
const hasPointers = tb.hasPointers();
if (hasPointers)
{
- if ((stype.alignment() < target.ptrsize ||
+ if ((!stype.alignment.isDefault() && stype.alignment.get() < target.ptrsize ||
(v.offset & (target.ptrsize - 1))) &&
(sc.func && sc.func.setUnsafe()))
{
diff --git a/gcc/d/dmd/file_manager.d b/gcc/d/dmd/file_manager.d
new file mode 100644
index 0000000..05aeb7d
--- /dev/null
+++ b/gcc/d/dmd/file_manager.d
@@ -0,0 +1,301 @@
+/**
+ * Read a file from disk and store it in memory.
+ *
+ * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/file_manager.d, _file_manager.d)
+ * Documentation: https://dlang.org/phobos/dmd_file_manager.html
+ * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/file_manager.d
+ */
+
+module dmd.file_manager;
+
+import dmd.root.stringtable : StringTable;
+import dmd.root.file : File, FileBuffer;
+import dmd.root.filename : FileName;
+import dmd.root.string : toDString;
+import dmd.globals;
+import dmd.identifier;
+
+enum package_d = "package." ~ mars_ext;
+enum package_di = "package." ~ hdr_ext;
+
+extern(C++) struct FileManager
+{
+ private StringTable!(FileBuffer*) files;
+ private __gshared bool initialized = false;
+
+nothrow:
+ extern(D) private FileBuffer* readToFileBuffer(const(char)[] filename)
+ {
+ if (!initialized)
+ FileManager._init();
+
+ auto readResult = File.read(filename);
+ if (readResult.success)
+ {
+ FileBuffer* fb;
+ if (auto val = files.lookup(filename))
+ fb = val.value;
+
+ if (!fb)
+ fb = FileBuffer.create();
+
+ fb.data = readResult.extractSlice();
+
+ return files.insert(filename, fb) == null ? null : fb;
+ }
+ else
+ {
+ return null;
+ }
+
+ }
+
+ /********************************************
+ * Look for the source file if it's different from filename.
+ * Look for .di, .d, directory, and along global.path.
+ * Does not open the file.
+ * Params:
+ * filename = as supplied by the user
+ * path = path to look for filename
+ * Returns:
+ * the found file name or
+ * `null` if it is not different from filename.
+ */
+ extern(D) static const(char)[] lookForSourceFile(const char[] filename, const char*[] path)
+ {
+ //printf("lookForSourceFile(`%.*s`)\n", cast(int)filename.length, filename.ptr);
+ /* Search along path[] for .di file, then .d file, then .i file, then .c file.
+ */
+ const sdi = FileName.forceExt(filename, hdr_ext);
+ if (FileName.exists(sdi) == 1)
+ return sdi;
+ scope(exit) FileName.free(sdi.ptr);
+
+ const sd = FileName.forceExt(filename, mars_ext);
+ if (FileName.exists(sd) == 1)
+ return sd;
+ scope(exit) FileName.free(sd.ptr);
+
+ const si = FileName.forceExt(filename, i_ext);
+ if (FileName.exists(si) == 1)
+ return si;
+ scope(exit) FileName.free(si.ptr);
+
+ const sc = FileName.forceExt(filename, c_ext);
+ if (FileName.exists(sc) == 1)
+ return sc;
+ scope(exit) FileName.free(sc.ptr);
+
+ if (FileName.exists(filename) == 2)
+ {
+ /* The filename exists and it's a directory.
+ * Therefore, the result should be: filename/package.d
+ * iff filename/package.d is a file
+ */
+ const ni = FileName.combine(filename, package_di);
+ if (FileName.exists(ni) == 1)
+ return ni;
+ FileName.free(ni.ptr);
+
+ const n = FileName.combine(filename, package_d);
+ if (FileName.exists(n) == 1)
+ return n;
+ FileName.free(n.ptr);
+ }
+ if (FileName.absolute(filename))
+ return null;
+ if (!path.length)
+ return null;
+ foreach (entry; path)
+ {
+ const p = entry.toDString();
+
+ const(char)[] n = FileName.combine(p, sdi);
+ if (FileName.exists(n) == 1) {
+ return n;
+ }
+ FileName.free(n.ptr);
+
+ n = FileName.combine(p, sd);
+ if (FileName.exists(n) == 1) {
+ return n;
+ }
+ FileName.free(n.ptr);
+
+ n = FileName.combine(p, si);
+ if (FileName.exists(n) == 1) {
+ return n;
+ }
+ FileName.free(n.ptr);
+
+ n = FileName.combine(p, sc);
+ if (FileName.exists(n) == 1) {
+ return n;
+ }
+ FileName.free(n.ptr);
+
+ const b = FileName.removeExt(filename);
+ n = FileName.combine(p, b);
+ FileName.free(b.ptr);
+ if (FileName.exists(n) == 2)
+ {
+ const n2i = FileName.combine(n, package_di);
+ if (FileName.exists(n2i) == 1)
+ return n2i;
+ FileName.free(n2i.ptr);
+ const n2 = FileName.combine(n, package_d);
+ if (FileName.exists(n2) == 1) {
+ return n2;
+ }
+ FileName.free(n2.ptr);
+ }
+ FileName.free(n.ptr);
+ }
+ return null;
+ }
+
+ /**
+ * Looks up the given filename from the internal file buffer table.
+ * If the file does not already exist within the table, it will be read from the filesystem.
+ * If it has been read before,
+ *
+ * Returns: the loaded source file if it was found in memory,
+ * otherwise `null`
+ */
+ extern(D) FileBuffer* lookup(FileName filename)
+ {
+ if (!initialized)
+ FileManager._init();
+
+ if (auto val = files.lookup(filename.toString))
+ {
+ // There is a chance that the buffer could've been
+ // stolen by a reader with extractSlice, so we should
+ // try and do our reading logic if that happens.
+ if (val !is null && val.value.data !is null)
+ {
+ return val.value;
+ }
+ }
+
+ const name = filename.toString;
+ auto res = FileName.exists(name);
+ if (res == 1)
+ return readToFileBuffer(name);
+
+ const fullName = lookForSourceFile(name, global.path ? (*global.path)[] : null);
+ if (!fullName)
+ return null;
+
+ return readToFileBuffer(fullName);
+ }
+
+ extern(C++) FileBuffer* lookup(const(char)* filename)
+ {
+ return lookup(FileName(filename.toDString));
+ }
+
+ /**
+ * Looks up the given filename from the internal file buffer table, and returns the lines within the file.
+ * If the file does not already exist within the table, it will be read from the filesystem.
+ * If it has been read before,
+ *
+ * Returns: the loaded source file if it was found in memory,
+ * otherwise `null`
+ */
+ extern(D) const(char)[][] getLines(FileName file)
+ {
+ if (!initialized)
+ FileManager._init();
+
+ const(char)[][] lines;
+ if (FileBuffer* buffer = lookup(file))
+ {
+ ubyte[] slice = buffer.data[0 .. buffer.data.length];
+ size_t start, end;
+ ubyte c;
+ for (auto i = 0; i < slice.length; i++)
+ {
+ c = slice[i];
+ if (c == '\n' || c == '\r')
+ {
+ if (i != 0)
+ {
+ end = i;
+ lines ~= cast(const(char)[])slice[start .. end];
+ }
+ // Check for Windows-style CRLF newlines
+ if (c == '\r')
+ {
+ if (slice.length > i + 1 && slice[i + 1] == '\n')
+ {
+ // This is a CRLF sequence, skip over two characters
+ start = i + 2;
+ i++;
+ }
+ else
+ {
+ // Just a CR sequence
+ start = i + 1;
+ }
+ }
+ else
+ {
+ // The next line should start after the LF sequence
+ start = i + 1;
+ }
+ }
+ }
+
+ if (slice[$ - 1] != '\r' && slice[$ - 1] != '\n')
+ {
+ end = slice.length;
+ lines ~= cast(const(char)[])slice[start .. end];
+ }
+ }
+
+ return lines;
+ }
+
+ /**
+ * Adds a FileBuffer to the table.
+ *
+ * Returns: The FileBuffer added, or null
+ */
+ extern(D) FileBuffer* add(FileName filename, FileBuffer* filebuffer)
+ {
+ if (!initialized)
+ FileManager._init();
+
+ auto val = files.insert(filename.toString, filebuffer);
+ return val == null ? null : val.value;
+ }
+
+ extern(C++) FileBuffer* add(const(char)* filename, FileBuffer* filebuffer)
+ {
+ if (!initialized)
+ FileManager._init();
+
+ auto val = files.insert(filename.toDString, filebuffer);
+ return val == null ? null : val.value;
+ }
+
+ __gshared fileManager = FileManager();
+
+ // Initialize the global FileManager singleton
+ extern(C++) static __gshared void _init()
+ {
+ if (!initialized)
+ {
+ fileManager.initialize();
+ initialized = true;
+ }
+ }
+
+ void initialize()
+ {
+ files._init();
+ }
+}
diff --git a/gcc/d/dmd/root/root.h b/gcc/d/dmd/file_manager.h
index 667ce67..7488fab1 100644
--- a/gcc/d/dmd/root/root.h
+++ b/gcc/d/dmd/file_manager.h
@@ -4,17 +4,16 @@
* http://www.digitalmars.com
* Distributed under the Boost Software License, Version 1.0.
* http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/dlang/dmd/blob/master/src/dmd/root/root.h
+ * https://github.com/dlang/dmd/blob/master/src/dmd/file_manager.h
*/
#pragma once
-#include "object.h"
+#include "root/file.h"
-#include "filename.h"
-
-#include "file.h"
-
-#include "outbuffer.h"
-
-#include "array.h"
+struct FileManager
+{
+ static void _init();
+ FileBuffer* lookup(const char* filename);
+ FileBuffer* add(const char* filename, FileBuffer* filebuffer);
+};
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 7f0b0bb..2d6a756 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -45,7 +45,8 @@ import dmd.identifier;
import dmd.init;
import dmd.mtype;
import dmd.objc;
-import dmd.root.outbuffer;
+import dmd.root.aav;
+import dmd.common.outbuffer;
import dmd.root.rootobject;
import dmd.root.string;
import dmd.root.stringtable;
@@ -261,6 +262,8 @@ extern (C++) class FuncDeclaration : Declaration
VarDeclaration vresult; /// result variable for out contracts
LabelDsymbol returnLabel; /// where the return goes
+ bool[size_t] isTypeIsolatedCache; /// cache for the potentially very expensive isTypeIsolated check
+
// used to prevent symbols in different
// scopes from having the same name
DsymbolTable localsymtab;
@@ -740,7 +743,7 @@ extern (C++) class FuncDeclaration : Declaration
*/
final BaseClass* overrideInterface()
{
- if (ClassDeclaration cd = toParent2().isClassDeclaration())
+ for (ClassDeclaration cd = toParent2().isClassDeclaration(); cd; cd = cd.baseClass)
{
foreach (b; cd.interfaces)
{
@@ -1529,8 +1532,23 @@ extern (C++) class FuncDeclaration : Declaration
extern (D) final bool isTypeIsolated(Type t)
{
StringTable!Type parentTypes;
- parentTypes._init();
- return isTypeIsolated(t, parentTypes);
+ const uniqueTypeID = t.getUniqueID();
+ if (uniqueTypeID)
+ {
+ const cacheResultPtr = uniqueTypeID in isTypeIsolatedCache;
+ if (cacheResultPtr !is null)
+ return *cacheResultPtr;
+
+ parentTypes._init();
+ const isIsolated = isTypeIsolated(t, parentTypes);
+ isTypeIsolatedCache[uniqueTypeID] = isIsolated;
+ return isIsolated;
+ }
+ else
+ {
+ parentTypes._init();
+ return isTypeIsolated(t, parentTypes);
+ }
}
///ditto
@@ -2593,9 +2611,10 @@ extern (C++) class FuncDeclaration : Declaration
}
if (!tf.nextOf())
- error("must return `int` or `void`");
- else if (tf.nextOf().ty != Tint32 && tf.nextOf().ty != Tvoid)
- error("must return `int` or `void`, not `%s`", tf.nextOf().toChars());
+ // auto main(), check after semantic
+ assert(this.inferRetType);
+ else if (tf.nextOf().ty != Tint32 && tf.nextOf().ty != Tvoid && tf.nextOf().ty != Tnoreturn)
+ error("must return `int`, `void` or `noreturn`, not `%s`", tf.nextOf().toChars());
else if (tf.parameterList.varargs || nparams >= 2 || argerr)
error("parameters must be `main()` or `main(string[] args)`");
}
@@ -3054,7 +3073,11 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
return null;
bool hasOverloads = fd.overnext !is null;
- auto tf = fd.type.toTypeFunction();
+ auto tf = fd.type.isTypeFunction();
+ // if type is an error, the original type should be there for better diagnostics
+ if (!tf)
+ tf = fd.originalType.toTypeFunction();
+
if (tthis && !MODimplicitConv(tthis.mod, tf.mod)) // modifier mismatch
{
OutBuffer thisBuf, funcBuf;
@@ -3253,17 +3276,7 @@ private bool traverseIndirections(Type ta, Type tb)
{
//printf("traverseIndirections(%s, %s)\n", ta.toChars(), tb.toChars());
- /* Threaded list of aggregate types already examined,
- * used to break cycles.
- * Cycles in type graphs can only occur with aggregates.
- */
- static struct Ctxt
- {
- Ctxt* prev;
- Type type; // an aggregate type
- }
-
- static bool traverse(Type ta, Type tb, Ctxt* ctxt, bool reversePass)
+ static bool traverse(Type ta, Type tb, ref scope AssocArray!(const(char)*, bool) table, bool reversePass)
{
//printf("traverse(%s, %s)\n", ta.toChars(), tb.toChars());
ta = ta.baseElemOf();
@@ -3293,28 +3306,27 @@ private bool traverseIndirections(Type ta, Type tb)
if (tb.ty == Tclass || tb.ty == Tstruct)
{
- for (Ctxt* c = ctxt; c; c = c.prev)
- if (tb == c.type)
- return true;
- Ctxt c;
- c.prev = ctxt;
- c.type = tb;
-
/* Traverse the type of each field of the aggregate
*/
+ bool* found = table.getLvalue(tb.deco);
+ if (*found == true)
+ return true; // We have already seen this symbol, break the cycle
+ else
+ *found = true;
+
AggregateDeclaration sym = tb.toDsymbol(null).isAggregateDeclaration();
foreach (v; sym.fields)
{
Type tprmi = v.type.addMod(tb.mod);
//printf("\ttb = %s, tprmi = %s\n", tb.toChars(), tprmi.toChars());
- if (!traverse(ta, tprmi, &c, reversePass))
+ if (!traverse(ta, tprmi, table, reversePass))
return false;
}
}
else if (tb.ty == Tarray || tb.ty == Taarray || tb.ty == Tpointer)
{
Type tind = tb.nextOf();
- if (!traverse(ta, tind, ctxt, reversePass))
+ if (!traverse(ta, tind, table, reversePass))
return false;
}
else if (tb.hasPointers())
@@ -3325,7 +3337,10 @@ private bool traverseIndirections(Type ta, Type tb)
// Still no match, so try breaking up ta if we have not done so yet.
if (!reversePass)
- return traverse(tb, ta, ctxt, true);
+ {
+ scope newTable = AssocArray!(const(char)*, bool)();
+ return traverse(tb, ta, newTable, true);
+ }
return true;
}
@@ -3333,7 +3348,8 @@ private bool traverseIndirections(Type ta, Type tb)
// To handle arbitrary levels of indirections in both parameters, we
// recursively descend into aggregate members/levels of indirection in both
// `ta` and `tb` while avoiding cycles. Start with the original types.
- const result = traverse(ta, tb, null, false);
+ scope table = AssocArray!(const(char)*, bool)();
+ const result = traverse(ta, tb, table, false);
//printf(" returns %d\n", result);
return result;
}
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index 9b65d02..747a113 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -14,7 +14,7 @@ module dmd.globals;
import core.stdc.stdint;
import dmd.root.array;
import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.identifier;
/// Defines a setting for how compiler warnings and deprecations are handled
@@ -118,6 +118,7 @@ extern (C++) struct Param
bool vgc; // identify gc usage
bool vfield; // identify non-mutable field variables
bool vcomplex = true; // identify complex/imaginary type usage
+ bool vin; // identify 'in' parameters
ubyte symdebug; // insert debug symbolic information
bool symdebugref; // insert debug information for all referenced types, too
bool optimize; // run optimizer
@@ -261,11 +262,29 @@ extern (C++) struct Param
const(char)[] mapfile;
}
-alias structalign_t = uint;
+extern (C++) struct structalign_t
+{
+ private:
+ ushort value = 0; // unknown
+ enum STRUCTALIGN_DEFAULT = 1234; // default = match whatever the corresponding C compiler does
+ bool pack; // use #pragma pack semantics
+
+ public:
+ pure @safe @nogc nothrow:
+ bool isDefault() const { return value == STRUCTALIGN_DEFAULT; }
+ void setDefault() { value = STRUCTALIGN_DEFAULT; }
+ bool isUnknown() const { return value == 0; } // value is not set
+ void setUnknown() { value = 0; }
+ void set(uint value) { this.value = cast(ushort)value; }
+ uint get() const { return value; }
+ bool isPack() const { return pack; }
+ void setPack(bool pack) { this.pack = pack; }
+}
+//alias structalign_t = uint;
// magic value means "match whatever the underlying C compiler does"
// other values are all powers of 2
-enum STRUCTALIGN_DEFAULT = (cast(structalign_t)~0);
+//enum STRUCTALIGN_DEFAULT = (cast(structalign_t)~0);
enum mars_ext = "d"; // for D source files
enum doc_ext = "html"; // for Ddoc generated files
@@ -307,6 +326,8 @@ extern (C++) struct Global
Array!Identifier* versionids; /// command line versions and predefined versions
Array!Identifier* debugids; /// command line debug versions and predefined versions
+ bool hasMainFunction; /// Whether a main function has already been compiled in (for -main switch)
+
enum recursionLimit = 500; /// number of recursive template expansions before abort
nothrow:
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index 6e79474..2275ec5 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -12,7 +12,7 @@
#include "root/dcompat.h"
#include "root/ctfloat.h"
-#include "root/outbuffer.h"
+#include "common/outbuffer.h"
#include "root/filename.h"
#include "compiler.h"
@@ -107,6 +107,7 @@ struct Param
bool vgc; // identify gc usage
bool vfield; // identify non-mutable field variables
bool vcomplex; // identify complex/imaginary type usage
+ bool vin; // identify 'in' parameters
unsigned char symdebug; // insert debug symbolic information
bool symdebugref; // insert debug information for all referenced types, too
bool optimize; // run optimizer
@@ -238,10 +239,24 @@ struct Param
DString mapfile;
};
-typedef unsigned structalign_t;
+struct structalign_t
+{
+ unsigned short value;
+ bool pack;
+
+ bool isDefault() const;
+ void setDefault();
+ bool isUnknown() const;
+ void setUnknown();
+ void set(unsigned value);
+ unsigned get() const;
+ bool isPack() const;
+ void setPack(bool pack);
+};
+
// magic value means "match whatever the underlying C compiler does"
// other values are all powers of 2
-#define STRUCTALIGN_DEFAULT ((structalign_t) ~0)
+//#define STRUCTALIGN_DEFAULT ((structalign_t) ~0)
const DString mars_ext = "d";
const DString doc_ext = "html"; // for Ddoc generated files
@@ -274,6 +289,8 @@ struct Global
Array<class Identifier*>* versionids; // command line versions and predefined versions
Array<class Identifier*>* debugids; // command line debug versions and predefined versions
+ bool hasMainFunction;
+
/* Start gagging. Return the current number of gagged errors
*/
unsigned startGagging();
diff --git a/gcc/d/dmd/gluelayer.d b/gcc/d/dmd/gluelayer.d
index debb9ca..4018126 100644
--- a/gcc/d/dmd/gluelayer.d
+++ b/gcc/d/dmd/gluelayer.d
@@ -78,6 +78,7 @@ else version (IN_GCC)
extern (C++)
{
Statement asmSemantic(AsmStatement s, Scope* sc);
+ void toObjFile(Dsymbol ds, bool multiobj);
}
// stubs
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 8c31590..4ff07b5 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -44,7 +44,7 @@ import dmd.mtype;
import dmd.nspace;
import dmd.parse;
import dmd.root.ctfloat;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rootobject;
import dmd.root.string;
import dmd.statement;
@@ -909,6 +909,12 @@ public:
override void visit(AttribDeclaration d)
{
+ bool hasSTC;
+ if (auto stcd = d.isStorageClassDeclaration)
+ {
+ hasSTC = stcToBuffer(buf, stcd.stc);
+ }
+
if (!d.decl)
{
buf.writeByte(';');
@@ -918,10 +924,12 @@ public:
if (d.decl.dim == 0 || (hgs.hdrgen && d.decl.dim == 1 && (*d.decl)[0].isUnitTestDeclaration()))
{
// hack for bugzilla 8081
+ if (hasSTC) buf.writeByte(' ');
buf.writestring("{}");
}
else if (d.decl.dim == 1)
{
+ if (hasSTC) buf.writeByte(' ');
(*d.decl)[0].accept(this);
return;
}
@@ -941,8 +949,6 @@ public:
override void visit(StorageClassDeclaration d)
{
- if (stcToBuffer(buf, d.stc))
- buf.writeByte(' ');
visit(cast(AttribDeclaration)d);
}
@@ -1324,11 +1330,10 @@ public:
if (d.ident)
{
buf.writestring(d.ident.toString());
- buf.writeByte(' ');
}
if (d.memtype)
{
- buf.writestring(": ");
+ buf.writestring(" : ");
typeToBuffer(d.memtype, null, buf, hgs);
}
if (!d.members)
@@ -2362,7 +2367,10 @@ public:
override void visit(DotIdExp e)
{
expToBuffer(e.e1, PREC.primary, buf, hgs);
- buf.writeByte('.');
+ if (e.arrow)
+ buf.writestring("->");
+ else
+ buf.writeByte('.');
buf.writestring(e.ident.toString());
}
diff --git a/gcc/d/dmd/iasmgcc.d b/gcc/d/dmd/iasmgcc.d
index e61fb23..3ff0e89 100644
--- a/gcc/d/dmd/iasmgcc.d
+++ b/gcc/d/dmd/iasmgcc.d
@@ -300,7 +300,7 @@ Ldone:
* Returns:
* the completed gcc asm statement, or null if errors occurred
*/
-public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
+extern (C++) public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
{
//printf("GccAsmStatement.semantic()\n");
scope p = new Parser!ASTCodegen(sc._module, ";", false);
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index 1f04dcf..1ee5153 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -500,6 +500,17 @@ immutable Msgtable[] msgtable =
{ "vector_size" },
{ "__func__" },
{ "noreturn" },
+ { "__pragma", "pragma" },
+ { "builtin_va_list", "__builtin_va_list" },
+ { "builtin_va_start", "__builtin_va_start" },
+ { "builtin_va_arg", "__builtin_va_arg" },
+ { "builtin_va_copy", "__builtin_va_copy" },
+ { "builtin_va_end", "__builtin_va_end" },
+ { "va_list_tag", "__va_list_tag" },
+ { "pack" },
+ { "show" },
+ { "push" },
+ { "pop" },
];
diff --git a/gcc/d/dmd/identifier.d b/gcc/d/dmd/identifier.d
index 43a1435..8add74a 100644
--- a/gcc/d/dmd/identifier.d
+++ b/gcc/d/dmd/identifier.d
@@ -16,7 +16,7 @@ import core.stdc.stdio;
import core.stdc.string;
import dmd.globals;
import dmd.id;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rootobject;
import dmd.root.string;
import dmd.root.stringtable;
diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d
new file mode 100644
index 0000000..0dad1a8
--- /dev/null
+++ b/gcc/d/dmd/importc.d
@@ -0,0 +1,171 @@
+/**
+ * Contains semantic routines specific to ImportC
+ *
+ * Specification: C11
+ *
+ * Copyright: Copyright (C) 2021 by The D Language Foundation, All Rights Reserved
+ * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/importc.d, _importc.d)
+ * Documentation: https://dlang.org/phobos/dmd_importc.html
+ * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/importc.d
+ */
+
+module dmd.importc;
+
+import core.stdc.stdio;
+
+import dmd.dcast;
+import dmd.dscope;
+import dmd.dsymbol;
+import dmd.expression;
+import dmd.expressionsem;
+import dmd.identifier;
+import dmd.mtype;
+
+/**************************************
+ * C11 does not allow array or function parameters.
+ * Hence, adjust those types per C11 6.7.6.3 rules.
+ * Params:
+ * t = parameter type to adjust
+ * sc = context
+ * Returns:
+ * adjusted type
+ */
+Type cAdjustParamType(Type t, Scope* sc)
+{
+ if (!(sc.flags & SCOPE.Cfile))
+ return t;
+
+ Type tb = t.toBasetype();
+
+ /* C11 6.7.6.3-7 array of T is converted to pointer to T
+ */
+ if (auto ta = tb.isTypeDArray())
+ {
+ t = ta.next.pointerTo();
+ }
+ else if (auto ts = tb.isTypeSArray())
+ {
+ t = ts.next.pointerTo();
+ }
+ /* C11 6.7.6.3-8 function is converted to pointer to function
+ */
+ else if (tb.isTypeFunction())
+ {
+ t = tb.pointerTo();
+ }
+ return t;
+}
+
+/***********************************************
+ * C11 6.3.2.1-3 Convert expression that is an array of type to a pointer to type.
+ * C11 6.3.2.1-4 Convert expression that is a function to a pointer to a function.
+ * Params:
+ * e = ImportC expression to possibly convert
+ * sc = context
+ * Returns:
+ * converted expression
+ */
+Expression arrayFuncConv(Expression e, Scope* sc)
+{
+ //printf("arrayFuncConv() %s\n", e.toChars());
+ if (!(sc.flags & SCOPE.Cfile))
+ return e;
+
+ auto t = e.type.toBasetype();
+ if (auto ta = t.isTypeDArray())
+ {
+ e = e.castTo(sc, ta.next.pointerTo());
+ }
+ else if (auto ts = t.isTypeSArray())
+ {
+ e = e.castTo(sc, ts.next.pointerTo());
+ }
+ else if (t.isTypeFunction())
+ {
+ e = e.addressOf();
+ }
+ else
+ return e;
+ return e.expressionSemantic(sc);
+}
+
+/****************************************
+ * Run semantic on `e`.
+ * Expression `e` evaluates to an instance of a struct.
+ * Look up `ident` as a field of that struct.
+ * Params:
+ * e = evaluates to an instance of a struct
+ * sc = context
+ * id = identifier of a field in that struct
+ * Returns:
+ * if successful `e.ident`
+ * if not then `ErrorExp` and message is printed
+ */
+Expression fieldLookup(Expression e, Scope* sc, Identifier id)
+{
+ e = e.expressionSemantic(sc);
+ if (e.isErrorExp())
+ return e;
+
+ Dsymbol s;
+ auto t = e.type;
+ if (t.isTypePointer())
+ {
+ t = t.isTypePointer().next;
+ e = new PtrExp(e.loc, e);
+ }
+ if (auto ts = t.isTypeStruct())
+ s = ts.sym.search(e.loc, id, 0);
+ if (!s)
+ {
+ e.error("`%s` is not a member of `%s`", id.toChars(), t.toChars());
+ return ErrorExp.get();
+ }
+ Expression ef = new DotVarExp(e.loc, e, s.isDeclaration());
+ return ef.expressionSemantic(sc);
+}
+
+/****************************************
+ * C11 6.5.2.1-2
+ * Apply C semantics to `E[I]` expression.
+ * E1[E2] is lowered to *(E1 + E2)
+ * Params:
+ * ae = ArrayExp to run semantics on
+ * sc = context
+ * Returns:
+ * Expression if this was a C expression with completed semantic, null if not
+ */
+Expression carraySemantic(ArrayExp ae, Scope* sc)
+{
+ if (!(sc.flags & SCOPE.Cfile))
+ return null;
+
+ auto e1 = ae.e1.expressionSemantic(sc);
+
+ assert(ae.arguments.length == 1);
+ Expression e2 = (*ae.arguments)[0];
+
+ /* CTFE cannot do pointer arithmetic, but it can index arrays.
+ * So, rewrite as an IndexExp if we can.
+ */
+ auto t1 = e1.type.toBasetype();
+ if (t1.isTypeDArray() || t1.isTypeSArray())
+ {
+ e2 = e2.expressionSemantic(sc).arrayFuncConv(sc);
+ return new IndexExp(ae.loc, e1, e2).expressionSemantic(sc);
+ }
+
+ e1 = e1.arrayFuncConv(sc); // e1 might still be a function call
+ e2 = e2.expressionSemantic(sc);
+ auto t2 = e2.type.toBasetype();
+ if (t2.isTypeDArray() || t2.isTypeSArray())
+ {
+ return new IndexExp(ae.loc, e2, e1).expressionSemantic(sc); // swap operands
+ }
+
+ e2 = e2.arrayFuncConv(sc);
+ auto ep = new PtrExp(ae.loc, new AddExp(ae.loc, e1, e2));
+ return ep.expressionSemantic(sc);
+}
diff --git a/gcc/d/dmd/init.d b/gcc/d/dmd/init.d
index 45e101b..d036ee1 100644
--- a/gcc/d/dmd/init.d
+++ b/gcc/d/dmd/init.d
@@ -23,7 +23,7 @@ import dmd.globals;
import dmd.hdrgen;
import dmd.identifier;
import dmd.mtype;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rootobject;
import dmd.tokens;
import dmd.visitor;
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index ae8bde2..5828486 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -31,6 +31,7 @@ import dmd.func;
import dmd.globals;
import dmd.id;
import dmd.identifier;
+import dmd.importc;
import dmd.init;
import dmd.mtype;
import dmd.opover;
@@ -176,30 +177,35 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
break;
}
}
- else if (fieldi >= nfields)
+ if (j >= nfields)
{
- error(i.loc, "too many initializers for `%s`", sd.toChars());
+ error(i.value[j].loc, "too many initializers for `%s`", sd.toChars());
return err();
}
VarDeclaration vd = sd.fields[fieldi];
if (elems[fieldi])
{
- error(i.loc, "duplicate initializer for field `%s`", vd.toChars());
+ error(i.value[j].loc, "duplicate initializer for field `%s`", vd.toChars());
errors = true;
+ elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
+ ++fieldi;
continue;
}
// Check for @safe violations
if (vd.type.hasPointers)
{
- if ((t.alignment() < target.ptrsize ||
+ if ((!t.alignment.isDefault() && t.alignment.get() < target.ptrsize ||
(vd.offset & (target.ptrsize - 1))) &&
sc.func && sc.func.setUnsafe())
{
- error(i.loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code",
+ error(i.value[j].loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code",
sd.toChars(), vd.toChars());
errors = true;
+ elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
+ ++fieldi;
+ continue;
}
}
@@ -208,7 +214,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
{
if (vd.isOverlappedWith(v2) && elems[k])
{
- error(i.loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars());
+ error(elems[k].loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars());
errors = true;
continue;
}
@@ -222,6 +228,8 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
if (ex.op == TOK.error)
{
errors = true;
+ elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
+ ++fieldi;
continue;
}
@@ -363,10 +371,10 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
if (length > i.dim)
i.dim = length;
}
- if (t.ty == Tsarray)
+ if (auto tsa = t.isTypeSArray())
{
- uinteger_t edim = (cast(TypeSArray)t).dim.toInteger();
- if (i.dim > edim)
+ uinteger_t edim = tsa.dim.toInteger();
+ if (i.dim > edim && !(tsa.isIncomplete() && (sc.flags & SCOPE.Cfile)))
{
error(i.loc, "array initializer has %u elements, but array length is %llu", i.dim, edim);
return err();
@@ -398,6 +406,13 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
if (i.exp.op == TOK.error)
return err();
uint olderrors = global.errors;
+
+ /* ImportC: convert arrays to pointers, functions to pointers to functions
+ */
+ Type tb = t.toBasetype();
+ if (tb.isTypePointer())
+ i.exp = i.exp.arrayFuncConv(sc);
+
/* Save the expression before ctfe
* Otherwise the error message would contain for example "&[0][0]" instead of "new int"
* Regression: https://issues.dlang.org/show_bug.cgi?id=21687
@@ -408,7 +423,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
// If the result will be implicitly cast, move the cast into CTFE
// to avoid premature truncation of polysemous types.
// eg real [] x = [1.1, 2.2]; should use real precision.
- if (i.exp.implicitConvTo(t))
+ if (i.exp.implicitConvTo(t) && !(sc.flags & SCOPE.Cfile))
{
i.exp = i.exp.implicitCastTo(sc, t);
}
@@ -416,6 +431,11 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
{
return i;
}
+ if (sc.flags & SCOPE.Cfile)
+ /* the interpreter turns (char*)"string" into &"string"[0] which then
+ * it cannot interpret. Resolve that case by doing optimize() first
+ */
+ i.exp = i.exp.optimize(WANTvalue);
i.exp = i.exp.ctfeInterpret();
if (i.exp.op == TOK.voidExpression)
error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead.");
@@ -424,6 +444,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
{
i.exp = i.exp.optimize(WANTvalue);
}
+
if (!global.gag && olderrors != global.errors)
{
return i; // Failed, suppress duplicate error messages
@@ -445,7 +466,6 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
i.exp.error("cannot use non-constant CTFE pointer in an initializer `%s`", currExp.toChars());
return err();
}
- Type tb = t.toBasetype();
Type ti = i.exp.type.toBasetype();
if (i.exp.op == TOK.tuple && i.expandTuples && !i.exp.implicitConvTo(t))
{
@@ -470,13 +490,12 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
goto L1;
}
}
-
/* C11 6.7.9-14..15
* Initialize an array of unknown size with a string.
- * ImportC regards Tarray as an array of unknown size.
* Change to static array of known size
*/
- if (sc.flags & SCOPE.Cfile && i.exp.op == TOK.string_ && tb.ty == Tarray)
+ if (sc.flags & SCOPE.Cfile && i.exp.isStringExp() &&
+ tb.isTypeSArray() && tb.isTypeSArray().isIncomplete())
{
StringExp se = i.exp.isStringExp();
auto ts = new TypeSArray(tb.nextOf(), new IntegerExp(Loc.initial, se.len + 1, Type.tsize_t));
@@ -683,8 +702,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
}
auto tsa = t.isTypeSArray();
- auto ta = t.isTypeDArray();
- if (!(tsa || ta))
+ if (!tsa)
{
/* Not an array. See if it is `{ exp }` which can be
* converted to an ExpInitializer
@@ -722,19 +740,32 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
{
//printf(" type %s i %d dim %d dil.length = %d\n", t.toChars(), cast(int)i, cast(int)dim, cast(int)dil.length);
auto tn = t.nextOf().toBasetype();
- if (auto tna = tn.isTypeDArray())
+ auto tnsa = tn.isTypeSArray();
+ if (tnsa && tnsa.isIncomplete())
{
// C11 6.2.5-20 "element type shall be complete whenever the array type is specified"
- error(ci.loc, "incomplete element type `%s` not allowed", tna.toChars());
+ error(ci.loc, "incomplete element type `%s` not allowed", tnsa.toChars());
errors = true;
return 1;
}
if (i == dil.length)
return 0;
size_t n;
- auto tnsa = tn.isTypeSArray();
const nelems = tnsa ? cast(size_t)tnsa.dim.toInteger() : 0;
+ /* Run initializerSemantic on a single element.
+ */
+ Initializer elem(Initializer ie)
+ {
+ ++i;
+ auto tnx = tn; // in case initializerSemantic tries to change it
+ ie = ie.initializerSemantic(sc, tnx, needInterpret);
+ if (ie.isErrorInitializer())
+ errors = true;
+ assert(tnx == tn); // sub-types should not be modified
+ return ie;
+ }
+
foreach (j; 0 .. dim)
{
auto di = dil[i];
@@ -751,16 +782,17 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
}
else if (auto tns = tn.isTypeStruct())
{
- dil[n].initializer = structs(tns);
+ if (di.initializer.isExpInitializer())
+ {
+ // no braces enclosing struct initializer
+ dil[n].initializer = structs(tns);
+ }
+ else
+ dil[n].initializer = elem(di.initializer);
}
else
{
- ++i;
- auto tnx = tn; // in case initializerSemantic tries to change it
- di.initializer = di.initializer.initializerSemantic(sc, tnx, needInterpret);
- if (di.initializer.isErrorInitializer())
- errors = true;
- assert(tnx == tn); // sub-types should not be modified
+ di.initializer = elem(di.initializer);
}
++n;
if (i == dil.length)
@@ -770,16 +802,16 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
return n;
}
- size_t dim = ta ? dil.length : cast(size_t)tsa.dim.toInteger();
- auto n = array(t, dim);
+ size_t dim = tsa.isIncomplete() ? dil.length : cast(size_t)tsa.dim.toInteger();
+ auto newdim = array(t, dim);
if (errors)
return err();
- if (ta) // array of unknown length
+ if (tsa.isIncomplete()) // array of unknown length
{
// Change to array of known length
- tsa = new TypeSArray(tn, new IntegerExp(Loc.initial, n, Type.tsize_t));
+ tsa = new TypeSArray(tn, new IntegerExp(Loc.initial, newdim, Type.tsize_t));
tx = tsa; // rewrite caller's type
ci.type = tsa; // remember for later passes
}
@@ -799,6 +831,39 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
return err();
}
+ /* If an array of simple elements, replace with an ArrayInitializer
+ */
+ auto tnb = tn.toBasetype();
+ if (!(tnb.isTypeSArray() || tnb.isTypeStruct()))
+ {
+ auto ai = new ArrayInitializer(ci.loc);
+ ai.dim = cast(uint) dil.length;
+ ai.index.setDim(dil.length);
+ ai.value.setDim(dil.length);
+ foreach (const j; 0 .. dil.length)
+ {
+ ai.index[j] = null;
+ ai.value[j] = dil[j].initializer;
+ }
+ auto ty = tx;
+ return ai.initializerSemantic(sc, ty, needInterpret);
+ }
+
+ if (newdim < ci.initializerList.length && tnb.isTypeStruct())
+ {
+ // https://issues.dlang.org/show_bug.cgi?id=22375
+ // initializerList can be bigger than the number of actual elements
+ // to initialize for array of structs because it is not required
+ // for values to have proper bracing.
+ // i.e: These are all valid initializers for `struct{int a,b;}[3]`:
+ // {1,2,3,4}, {{1,2},3,4}, {1,2,{3,4}}, {{1,2},{3,4}}
+ // In all examples above, the new length of the initializer list
+ // has been shortened from four elements to two. This is important,
+ // because `dil` is written back to directly, making the lowered
+ // initializer `{{1,2},{3,4}}` and not `{{1,2},{3,4},3,4}`.
+ ci.initializerList.length = newdim;
+ }
+
return ci;
}
@@ -1263,6 +1328,3 @@ private bool hasNonConstPointers(Expression e)
}
return false;
}
-
-
-
diff --git a/gcc/d/dmd/intrange.h b/gcc/d/dmd/intrange.h
deleted file mode 100644
index fd61532..0000000
--- a/gcc/d/dmd/intrange.h
+++ /dev/null
@@ -1,177 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * written by KennyTM
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/dlang/dmd/blob/master/src/intrange.h
- */
-
-#pragma once
-
-#include "globals.h" // for uinteger_t
-class Type;
-class Expression;
-
-/**
-This class represents a "sign-extended number", i.e. a 65-bit number, which can
-represent all built-in integer types in D. This class is mainly used for
-performing value-range propagation only, therefore all arithmetic are done with
-saturation, not wrapping as usual.
-*/
-struct SignExtendedNumber
-{
- /// The lower 64-bit of the number.
- uinteger_t value;
- /// The sign (i.e. the most significant bit) of the number.
- bool negative;
-
- /// Create an uninitialized sign-extended number.
- SignExtendedNumber() {}
-
- /// Create a sign-extended number from an unsigned 64-bit number.
- SignExtendedNumber(uinteger_t value_)
- : value(value_), negative(false) {}
- /// Create a sign-extended number from the lower 64-bit and the sign bit.
- SignExtendedNumber(uinteger_t value_, bool negative_)
- : value(value_), negative(negative_) {}
-
- /// Create a sign-extended number from a signed 64-bit number.
- static SignExtendedNumber fromInteger(uinteger_t value_);
-
- /// Get the minimum or maximum value of a sign-extended number.
- static SignExtendedNumber extreme(bool minimum);
-
- // These names probably shouldn't be used anyway, as they are common macros
-#undef max
-#undef min
- static SignExtendedNumber max();
- static SignExtendedNumber min() { return SignExtendedNumber(0, true); }
-
- /// Check if the sign-extended number is minimum or zero.
- bool isMinimum() const { return negative && value == 0; }
-
- /// Compare two sign-extended number.
- bool operator==(const SignExtendedNumber&) const;
- bool operator!=(const SignExtendedNumber& a) const { return !(*this == a); }
- bool operator<(const SignExtendedNumber&) const;
- bool operator>(const SignExtendedNumber& a) const { return a < *this; }
- bool operator<=(const SignExtendedNumber& a) const { return !(a < *this); }
- bool operator>=(const SignExtendedNumber& a) const { return !(*this < a); }
-
- /// Increase the sign-extended number by 1 (saturated).
- SignExtendedNumber& operator++();
- /// Compute the saturated complement of a sign-extended number.
- SignExtendedNumber operator~() const;
- /// Compute the saturated negation of a sign-extended number.
- SignExtendedNumber operator-() const;
-
- /// Compute the saturated binary and of two sign-extended number.
- SignExtendedNumber operator&(const SignExtendedNumber&) const;
- /// Compute the saturated binary or of two sign-extended number.
- SignExtendedNumber operator|(const SignExtendedNumber&) const;
- /// Compute the saturated binary xor of two sign-extended number.
- SignExtendedNumber operator^(const SignExtendedNumber&) const;
- /// Compute the saturated sum of two sign-extended number.
- SignExtendedNumber operator+(const SignExtendedNumber&) const;
- /// Compute the saturated difference of two sign-extended number.
- SignExtendedNumber operator-(const SignExtendedNumber&) const;
- /// Compute the saturated product of two sign-extended number.
- SignExtendedNumber operator*(const SignExtendedNumber&) const;
- /// Compute the saturated quotient of two sign-extended number.
- SignExtendedNumber operator/(const SignExtendedNumber&) const;
- /// Compute the saturated modulus of two sign-extended number.
- SignExtendedNumber operator%(const SignExtendedNumber&) const;
-
- /// Compute the saturated shifts of two sign-extended number.
- SignExtendedNumber operator<<(const SignExtendedNumber&) const;
- SignExtendedNumber operator>>(const SignExtendedNumber&) const;
-};
-
-/**
-This class represents a range of integers, denoted by its lower and upper bounds
-(inclusive).
-*/
-struct IntRange
-{
- SignExtendedNumber imin, imax;
-
- /// Create an uninitialized range.
- IntRange() {}
-
- /// Create a range consisting of a single number.
- IntRange(const SignExtendedNumber& a)
- : imin(a), imax(a) {}
- /// Create a range with the lower and upper bounds.
- IntRange(const SignExtendedNumber& lower, const SignExtendedNumber& upper)
- : imin(lower), imax(upper) {}
-
- /// Create the tightest range containing all valid integers in the specified
- /// type.
- static IntRange fromType(Type *type);
- /// Create the tightest range containing all valid integers in the type with
- /// a forced signedness.
- static IntRange fromType(Type *type, bool isUnsigned);
-
-
- /// Create the tightest range containing all specified numbers.
- static IntRange fromNumbers2(const SignExtendedNumber numbers[2]);
- static IntRange fromNumbers4(const SignExtendedNumber numbers[4]);
-
- /// Create the widest range possible.
- static IntRange widest();
-
- /// Cast the integer range to a signed type with the given size mask.
- IntRange& castSigned(uinteger_t mask);
- /// Cast the integer range to an unsigned type with the given size mask.
- IntRange& castUnsigned(uinteger_t mask);
- /// Cast the integer range to the dchar type.
- IntRange& castDchar();
-
- /// Cast the integer range to a specific type.
- IntRange& cast(Type *type);
- /// Cast the integer range to a specific type, forcing it to be unsigned.
- IntRange& castUnsigned(Type *type);
-
- /// Check if this range contains another range.
- bool contains(const IntRange& a) const;
-
- /// Check if this range contains 0.
- bool containsZero() const;
-
- /// Compute the range of the negated absolute values of the original range.
- IntRange absNeg() const;
-
- /// Compute the union of two ranges.
- IntRange unionWith(const IntRange& other) const;
- void unionOrAssign(const IntRange& other, bool& union_);
-
- /// Dump the content of the integer range to the console.
- const IntRange& dump(const char* funcName, Expression *e) const;
-
- /// Split the range into two nonnegative- and negative-only subintervals.
- void splitBySign(IntRange& negRange, bool& hasNegRange,
- IntRange& nonNegRange, bool& hasNonNegRange) const;
-
- /// Credits to Timon Gehr maxOr, minOr, maxAnd, minAnd
- /// https://github.com/tgehr/d-compiler/blob/master/vrange.d
- static SignExtendedNumber maxOr(const IntRange&, const IntRange&);
- static SignExtendedNumber minOr(const IntRange&, const IntRange&);
- static SignExtendedNumber maxAnd(const IntRange&, const IntRange&);
- static SignExtendedNumber minAnd(const IntRange&, const IntRange&);
- static void swap(IntRange&, IntRange&);
-
- IntRange operator~() const;
- IntRange operator-() const;
- IntRange operator&(const IntRange&) const;
- IntRange operator|(const IntRange&) const;
- IntRange operator^(const IntRange&) const;
- IntRange operator+(const IntRange&) const;
- IntRange operator-(const IntRange&) const;
- IntRange operator*(const IntRange&) const;
- IntRange operator/(const IntRange&) const;
- IntRange operator%(const IntRange&) const;
- IntRange operator<<(const IntRange&) const;
- IntRange operator>>(const IntRange&) const;
-};
diff --git a/gcc/d/dmd/json.d b/gcc/d/dmd/json.d
index bfd31bc..fef5150 100644
--- a/gcc/d/dmd/json.d
+++ b/gcc/d/dmd/json.d
@@ -33,7 +33,7 @@ import dmd.hdrgen;
import dmd.id;
import dmd.identifier;
import dmd.mtype;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rootobject;
import dmd.root.string;
import dmd.target;
@@ -794,8 +794,8 @@ public:
property("init", d._init.toString());
if (d.isField())
property("offset", d.offset);
- if (d.alignment && d.alignment != STRUCTALIGN_DEFAULT)
- property("align", d.alignment);
+ if (!d.alignment.isUnknown() && !d.alignment.isDefault())
+ property("align", d.alignment.get());
objectEnd();
}
diff --git a/gcc/d/dmd/lambdacomp.d b/gcc/d/dmd/lambdacomp.d
index d29bdc1..44a6c06 100644
--- a/gcc/d/dmd/lambdacomp.d
+++ b/gcc/d/dmd/lambdacomp.d
@@ -27,7 +27,7 @@ import dmd.expression;
import dmd.func;
import dmd.dmangle;
import dmd.mtype;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rmem;
import dmd.root.stringtable;
import dmd.dscope;
diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d
index afffc2d..e2b4199 100644
--- a/gcc/d/dmd/lexer.d
+++ b/gcc/d/dmd/lexer.d
@@ -26,8 +26,9 @@ import dmd.errors;
import dmd.globals;
import dmd.id;
import dmd.identifier;
+import dmd.root.array;
import dmd.root.ctfloat;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.port;
import dmd.root.rmem;
import dmd.root.string;
@@ -229,6 +230,8 @@ class Lexer
ubyte long_doublesize; /// size of C long double, 8 or D real.sizeof
ubyte wchar_tsize; /// size of C wchar_t, 2 or 4
+ structalign_t packalign; /// current state of #pragma pack alignment (ImportC)
+
private
{
const(char)* base; // pointer to start of buffer
@@ -242,6 +245,10 @@ class Lexer
int lastDocLine; // last line of previous doc comment
Token* tokenFreelist;
+
+ // ImportC #pragma pack stack
+ Array!Identifier* records; // identifers (or null)
+ Array!structalign_t* packs; // parallel alignment values
}
nothrow:
@@ -273,6 +280,7 @@ class Lexer
this.commentToken = commentToken;
this.inTokenStringConstant = 0;
this.lastDocLine = 0;
+ this.packalign.setDefault();
//initKeywords();
/* If first line starts with '#!', ignore the line
*/
@@ -1146,6 +1154,11 @@ class Lexer
poundLine(n, false);
continue;
}
+ else if (n.ident == Id.__pragma && Ccompile)
+ {
+ pragmaDirective(scanloc);
+ continue;
+ }
else
{
const locx = loc();
@@ -2162,7 +2175,7 @@ class Lexer
case '.':
if (p[1] == '.')
goto Ldone; // if ".."
- if (base == 10 && (isalpha(p[1]) || p[1] == '_' || p[1] & 0x80))
+ if (base <= 10 && n > 0 && (isalpha(p[1]) || p[1] == '_' || p[1] & 0x80))
goto Ldone; // if ".identifier" or ".unicode"
if (base == 16 && (!ishex(p[1]) || p[1] == '_' || p[1] & 0x80))
goto Ldone; // if ".identifier" or ".unicode"
@@ -2911,6 +2924,220 @@ class Lexer
error(loc, "#line integer [\"filespec\"]\\n expected");
}
+ /*********************************************
+ * C11 6.10.6 Pragma directive
+ * # pragma pp-tokens(opt) new-line
+ * The C preprocessor sometimes leaves pragma directives in
+ * the preprocessed output. Ignore them.
+ * Upon return, p is at start of next line.
+ */
+ private void pragmaDirective(const ref Loc loc)
+ {
+ Token n;
+ scan(&n);
+ if (n.value == TOK.identifier && n.ident == Id.pack)
+ return pragmaPack(loc);
+ skipToNextLine();
+ }
+
+ /*********
+ * ImportC
+ * # pragma pack
+ * https://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Structure_002dPacking-Pragmas.html
+ * https://docs.microsoft.com/en-us/cpp/preprocessor/pack
+ * Scanner is on the `pack`
+ * Params:
+ * startloc = location to use for error messages
+ */
+ private void pragmaPack(const ref Loc startloc)
+ {
+ const loc = startloc;
+ Token n;
+ scan(&n);
+ if (n.value != TOK.leftParenthesis)
+ {
+ error(loc, "left parenthesis expected to follow `#pragma pack`");
+ skipToNextLine();
+ return;
+ }
+
+ void closingParen()
+ {
+ if (n.value != TOK.rightParenthesis)
+ {
+ error(loc, "right parenthesis expected to close `#pragma pack(`");
+ }
+ skipToNextLine();
+ }
+
+ void setPackAlign(ref const Token t)
+ {
+ const n = t.unsvalue;
+ if (n < 1 || n & (n - 1) || ushort.max < n)
+ error(loc, "pack must be an integer positive power of 2, not 0x%llx", cast(ulong)n);
+ packalign.set(cast(uint)n);
+ packalign.setPack(true);
+ }
+
+ scan(&n);
+
+ if (!records)
+ {
+ records = new Array!Identifier;
+ packs = new Array!structalign_t;
+ }
+
+ /* # pragma pack ( show )
+ */
+ if (n.value == TOK.identifier && n.ident == Id.show)
+ {
+ if (packalign.isDefault())
+ warning(startloc, "current pack attribute is default");
+ else
+ warning(startloc, "current pack attribute is %d", packalign.get());
+ scan(&n);
+ return closingParen();
+ }
+ /* # pragma pack ( push )
+ * # pragma pack ( push , identifier )
+ * # pragma pack ( push , integer )
+ * # pragma pack ( push , identifier , integer )
+ */
+ if (n.value == TOK.identifier && n.ident == Id.push)
+ {
+ scan(&n);
+ Identifier record = null;
+ if (n.value == TOK.comma)
+ {
+ scan(&n);
+ if (n.value == TOK.identifier)
+ {
+ record = n.ident;
+ scan(&n);
+ if (n.value == TOK.comma)
+ {
+ scan(&n);
+ if (n.value == TOK.int32Literal)
+ {
+ setPackAlign(n);
+ scan(&n);
+ }
+ else
+ error(loc, "alignment value expected, not `%s`", n.toChars());
+ }
+ }
+ else if (n.value == TOK.int32Literal)
+ {
+ setPackAlign(n);
+ scan(&n);
+ }
+ else
+ error(loc, "alignment value expected, not `%s`", n.toChars());
+ }
+ this.records.push(record);
+ this.packs.push(packalign);
+ return closingParen();
+ }
+ /* # pragma pack ( pop )
+ * # pragma pack ( pop PopList )
+ * PopList :
+ * , IdentifierOrInteger
+ * , IdentifierOrInteger PopList
+ * IdentifierOrInteger:
+ * identifier
+ * integer
+ */
+ if (n.value == TOK.identifier && n.ident == Id.pop)
+ {
+ scan(&n);
+ while (n.value == TOK.comma)
+ {
+ scan(&n);
+ if (n.value == TOK.identifier)
+ {
+ for (size_t len = this.records.length; len; --len)
+ {
+ if ((*this.records)[len - 1] == n.ident)
+ {
+ packalign = (*this.packs)[len - 1];
+ this.records.setDim(len - 1);
+ this.packs.setDim(len - 1);
+ break;
+ }
+ }
+ scan(&n);
+ }
+ else if (n.value == TOK.int32Literal)
+ {
+ setPackAlign(n);
+ this.records.push(null);
+ this.packs.push(packalign);
+ scan(&n);
+ }
+ }
+ return closingParen();
+ }
+ /* # pragma pack ( integer )
+ */
+ if (n.value == TOK.int32Literal)
+ {
+ setPackAlign(n);
+ scan(&n);
+ return closingParen();
+ }
+ /* # pragma pack ( )
+ */
+ if (n.value == TOK.rightParenthesis)
+ {
+ packalign.setDefault();
+ return closingParen();
+ }
+
+ error(loc, "unrecognized `#pragma pack(%s)`", n.toChars());
+ skipToNextLine();
+ }
+
+ /***************************************
+ * Scan forward to start of next line.
+ */
+ private void skipToNextLine()
+ {
+ while (1)
+ {
+ switch (*p)
+ {
+ case 0:
+ case 0x1A:
+ return; // do not advance p
+
+ case '\n':
+ ++p;
+ break;
+
+ case '\r':
+ ++p;
+ if (p[0] == '\n')
+ ++p;
+ break;
+
+ default:
+ if (*p & 0x80)
+ {
+ const u = decodeUTF();
+ if (u == PS || u == LS)
+ {
+ ++p;
+ break;
+ }
+ }
+ ++p;
+ continue;
+ }
+ break;
+ }
+ endOfLine();
+ }
+
/********************************************
* Decode UTF character.
* Issue error messages for invalid sequences.
@@ -3106,8 +3333,10 @@ class Lexer
return p;
}
-private:
- void endOfLine() pure @nogc @safe
+ /**************************
+ * `p` should be at start of next line
+ */
+ private void endOfLine() pure @nogc @safe
{
scanloc.linnum++;
line = p;
diff --git a/gcc/d/dmd/lexer.h b/gcc/d/dmd/lexer.h
deleted file mode 100644
index b36e7f7..0000000
--- a/gcc/d/dmd/lexer.h
+++ /dev/null
@@ -1,75 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/D-Programming-Language/dmd/blob/master/src/lexer.h
- */
-
-#pragma once
-
-#include "root/root.h"
-#include "globals.h"
-#include "tokens.h"
-
-struct StringTable;
-class Identifier;
-
-class Lexer
-{
-public:
- static OutBuffer stringbuffer;
-
- Loc scanloc; // for error messages
-
- const utf8_t *base; // pointer to start of buffer
- const utf8_t *end; // past end of buffer
- const utf8_t *p; // current character
- const utf8_t *line; // start of current line
- Token token;
- bool doDocComment; // collect doc comment information
- bool anyToken; // !=0 means seen at least one token
- bool commentToken; // !=0 means comments are TOKcomment's
- bool errors; // errors occurred during lexing or parsing
-
- Lexer(const char *filename,
- const utf8_t *base, size_t begoffset, size_t endoffset,
- bool doDocComment, bool commentToken);
-
- TOK nextToken();
- TOK peekNext();
- TOK peekNext2();
- void scan(Token *t);
- Token *peek(Token *t);
- Token *peekPastParen(Token *t);
- unsigned escapeSequence();
- TOK wysiwygStringConstant(Token *t, int tc);
- TOK hexStringConstant(Token *t);
- TOK delimitedStringConstant(Token *t);
- TOK tokenStringConstant(Token *t);
- TOK escapeStringConstant(Token *t);
- TOK charConstant(Token *t);
- void stringPostfix(Token *t);
- TOK number(Token *t);
- TOK inreal(Token *t);
-
- Loc loc()
- {
- scanloc.charnum = (unsigned)(1 + p-line);
- return scanloc;
- }
-
- void error(const char *format, ...);
- void error(Loc loc, const char *format, ...);
- void deprecation(const char *format, ...);
- void poundLine();
- unsigned decodeUTF();
- void getDocComment(Token *t, unsigned lineComment);
-
- static const utf8_t *combineComments(const utf8_t *c1, const utf8_t *c2);
-
-private:
- void endOfLine();
-};
diff --git a/gcc/d/dmd/macro.h b/gcc/d/dmd/macro.h
deleted file mode 100644
index 80ec36e..0000000
--- a/gcc/d/dmd/macro.h
+++ /dev/null
@@ -1,38 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/D-Programming-Language/dmd/blob/master/src/macro.h
- */
-
-#pragma once
-
-#include "root/dsystem.h"
-#include "root/port.h"
-
-
-struct Macro
-{
- private:
- Macro *next; // next in list
-
- const utf8_t *name; // macro name
- size_t namelen; // length of macro name
-
- const utf8_t *text; // macro replacement text
- size_t textlen; // length of replacement text
-
- int inuse; // macro is in use (don't expand)
-
- Macro(const utf8_t *name, size_t namelen, const utf8_t *text, size_t textlen);
- Macro *search(const utf8_t *name, size_t namelen);
-
- public:
- static Macro *define(Macro **ptable, const utf8_t *name, size_t namelen, const utf8_t *text, size_t textlen);
-
- void expand(OutBuffer *buf, size_t start, size_t *pend,
- const utf8_t *arg, size_t arglen);
-};
diff --git a/gcc/d/dmd/mars.h b/gcc/d/dmd/mars.h
deleted file mode 100644
index 9b9c278..0000000
--- a/gcc/d/dmd/mars.h
+++ /dev/null
@@ -1,93 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/dlang/dmd/blob/master/src/dmd/mars.h
- */
-
-#pragma once
-
-/*
-It is very important to use version control macros correctly - the
-idea is that host and target are independent. If these are done
-correctly, cross compilers can be built.
-The host compiler and host operating system are also different,
-and are predefined by the host compiler. The ones used in
-dmd are:
-
-Macros defined by the compiler, not the code:
-
- Compiler:
- __DMC__ Digital Mars compiler
- _MSC_VER Microsoft compiler
- __GNUC__ Gnu compiler
- __clang__ Clang compiler
-
- Host operating system:
- _WIN32 Microsoft NT, Windows 95, Windows 98, Win32s,
- Windows 2000, Win XP, Vista
- _WIN64 Windows for AMD64
- __linux__ Linux
- __APPLE__ Mac OSX
- __FreeBSD__ FreeBSD
- __OpenBSD__ OpenBSD
- __sun Solaris, OpenSolaris, SunOS, OpenIndiana, etc
-
-For the target systems, there are the target operating system and
-the target object file format:
-
- Target operating system:
- TARGET_WINDOS Covers 32 bit windows and 64 bit windows
- TARGET_LINUX Covers 32 and 64 bit linux
- TARGET_OSX Covers 32 and 64 bit Mac OSX
- TARGET_FREEBSD Covers 32 and 64 bit FreeBSD
- TARGET_OPENBSD Covers 32 and 64 bit OpenBSD
- TARGET_SOLARIS Covers 32 and 64 bit Solaris
-
- It is expected that the compiler for each platform will be able
- to generate 32 and 64 bit code from the same compiler binary.
-
- There are currently no macros for byte endianness order.
- */
-
-
-#include "root/dsystem.h"
-
-#ifdef __DMC__
-#ifdef DEBUG
-#undef assert
-#define assert(e) (static_cast<void>((e) || (printf("assert %s(%d) %s\n", __FILE__, __LINE__, #e), halt())))
-#endif
-#endif
-
-void unittests();
-
-struct OutBuffer;
-
-#include "globals.h"
-
-#include "root/ctfloat.h"
-
-#include "complex_t.h"
-
-#include "errors.h"
-
-class Dsymbol;
-class Library;
-struct File;
-void obj_start(char *srcfile);
-void obj_end(Library *library, File *objfile);
-void obj_append(Dsymbol *s);
-void obj_write_deferred(Library *library);
-
-/// Utility functions used by both main and frontend.
-void readFile(Loc loc, File *f);
-void writeFile(Loc loc, File *f);
-void ensurePathToNameExists(Loc loc, const char *name);
-
-const char *importHint(const char *s);
-/// Little helper function for writing out deps.
-void escapePath(OutBuffer *buf, const char *fname);
diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h
index 969290c..fe4c73a 100644
--- a/gcc/d/dmd/module.h
+++ b/gcc/d/dmd/module.h
@@ -119,7 +119,7 @@ public:
static Module* create(const char *arg, Identifier *ident, int doDocComment, int doHdrGen);
- static Module *load(Loc loc, Identifiers *packages, Identifier *ident);
+ static Module *load(const Loc &loc, Identifiers *packages, Identifier *ident);
const char *kind() const;
bool read(const Loc &loc); // read file, returns 'true' if succeed, 'false' otherwise.
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 80e4791..a21924b 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -43,7 +43,7 @@ import dmd.identifier;
import dmd.init;
import dmd.opover;
import dmd.root.ctfloat;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rmem;
import dmd.root.rootobject;
import dmd.root.stringtable;
@@ -237,6 +237,7 @@ enum DotExpFlag
{
gag = 1, // don't report "not a property" error and just return null
noDeref = 2, // the use of the expression will not attempt a dereference
+ noAliasThis = 4, // don't do 'alias this' resolution
}
/// Result of a check whether two types are covariant
@@ -426,6 +427,13 @@ extern (C++) abstract class Type : ASTNode
return DYNCAST.type;
}
+ /// Returns a non-zero unique ID for this Type, or returns 0 if the Type does not (yet) have a unique ID.
+ /// If `semantic()` has not been run, 0 is returned.
+ final size_t getUniqueID() const
+ {
+ return cast(size_t) deco;
+ }
+
extern (D)
final Mcache* getMcache()
{
@@ -2298,7 +2306,9 @@ extern (C++) abstract class Type : ASTNode
*/
structalign_t alignment()
{
- return STRUCTALIGN_DEFAULT;
+ structalign_t s;
+ s.setDefault();
+ return s;
}
/***************************************
@@ -3532,6 +3542,13 @@ extern (C++) final class TypeSArray : TypeArray
this.dim = dim;
}
+ extern (D) this(Type t) // for incomplete type
+ {
+ super(Tsarray, t);
+ //printf("TypeSArray()\n");
+ this.dim = new IntegerExp(0);
+ }
+
override const(char)* kind() const
{
return "sarray";
@@ -3546,6 +3563,15 @@ extern (C++) final class TypeSArray : TypeArray
return result;
}
+ /***
+ * C11 6.7.6.2-4 incomplete array type
+ * Returns: true if incomplete type
+ */
+ bool isIncomplete()
+ {
+ return dim.isIntegerExp() && dim.isIntegerExp().getInteger() == 0;
+ }
+
override d_uns64 size(const ref Loc loc)
{
//printf("TypeSArray::size()\n");
@@ -3952,65 +3978,37 @@ extern (C++) final class TypePointer : TypeNext
if (equals(to))
return MATCH.exact;
- if (next.ty == Tfunction)
- {
- if (auto tp = to.isTypePointer())
- {
- if (tp.next.ty == Tfunction)
- {
- if (next.equals(tp.next))
- return MATCH.constant;
-
- if (next.covariant(tp.next) == Covariant.yes)
- {
- Type tret = this.next.nextOf();
- Type toret = tp.next.nextOf();
- if (tret.ty == Tclass && toret.ty == Tclass)
- {
- /* https://issues.dlang.org/show_bug.cgi?id=10219
- * Check covariant interface return with offset tweaking.
- * interface I {}
- * class C : Object, I {}
- * I function() dg = function C() {} // should be error
- */
- int offset = 0;
- if (toret.isBaseOf(tret, &offset) && offset != 0)
- return MATCH.nomatch;
- }
- return MATCH.convert;
- }
- }
- else if (tp.next.ty == Tvoid)
- {
- // Allow conversions to void*
- return MATCH.convert;
- }
- }
+ // Only convert between pointers
+ auto tp = to.isTypePointer();
+ if (!tp)
return MATCH.nomatch;
- }
- else if (auto tp = to.isTypePointer())
+
+ assert(this.next);
+ assert(tp.next);
+
+ // Conversion to void*
+ if (tp.next.ty == Tvoid)
{
- assert(tp.next);
+ // Function pointer conversion doesn't check constness?
+ if (this.next.ty == Tfunction)
+ return MATCH.convert;
if (!MODimplicitConv(next.mod, tp.next.mod))
return MATCH.nomatch; // not const-compatible
- /* Alloc conversion to void*
- */
- if (next.ty != Tvoid && tp.next.ty == Tvoid)
- {
- return MATCH.convert;
- }
-
- MATCH m = next.constConv(tp.next);
- if (m > MATCH.nomatch)
- {
- if (m == MATCH.exact && mod != to.mod)
- m = MATCH.constant;
- return m;
- }
+ return this.next.ty == Tvoid ? MATCH.constant : MATCH.convert;
}
- return MATCH.nomatch;
+
+ // Conversion between function pointers
+ if (auto thisTf = this.next.isTypeFunction())
+ return thisTf.implicitPointerConv(tp.next);
+
+ // Default, no implicit conversion between the pointer targets
+ MATCH m = next.constConv(tp.next);
+
+ if (m == MATCH.exact && mod != to.mod)
+ m = MATCH.constant;
+ return m;
}
override MATCH constConv(Type to)
@@ -4760,7 +4758,10 @@ extern (C++) final class TypeFunction : TypeNext
}
}
else
- m = arg.implicitConvTo(tprm);
+ {
+ import dmd.dcast : cimplicitConvTo;
+ m = (sc && sc.flags & SCOPE.Cfile) ? arg.cimplicitConvTo(tprm) : arg.implicitConvTo(tprm);
+ }
}
//printf("match %d\n", m);
}
@@ -4971,6 +4972,47 @@ extern (C++) final class TypeFunction : TypeNext
return MATCH.nomatch;
}
+ /+
+ + Checks whether this function type is convertible to ` to`
+ + when used in a function pointer / delegate.
+ +
+ + Params:
+ + to = target type
+ +
+ + Returns:
+ + MATCH.nomatch: `to` is not a covaraint function
+ + MATCH.convert: `to` is a covaraint function
+ + MATCH.exact: `to` is identical to this function
+ +/
+ private MATCH implicitPointerConv(Type to)
+ {
+ assert(to);
+
+ if (this == to)
+ return MATCH.constant;
+
+ if (this.covariant(to) == Covariant.yes)
+ {
+ Type tret = this.nextOf();
+ Type toret = to.nextOf();
+ if (tret.ty == Tclass && toret.ty == Tclass)
+ {
+ /* https://issues.dlang.org/show_bug.cgi?id=10219
+ * Check covariant interface return with offset tweaking.
+ * interface I {}
+ * class C : Object, I {}
+ * I function() dg = function C() {} // should be error
+ */
+ int offset = 0;
+ if (toret.isBaseOf(tret, &offset) && offset != 0)
+ return MATCH.nomatch;
+ }
+ return MATCH.convert;
+ }
+
+ return MATCH.nomatch;
+ }
+
/** Extends TypeNext.constConv by also checking for matching attributes **/
override MATCH constConv(Type to)
{
@@ -5262,27 +5304,16 @@ extern (C++) final class TypeDelegate : TypeNext
if (this == to)
return MATCH.exact;
- version (all)
+ if (auto toDg = to.isTypeDelegate())
{
- // not allowing covariant conversions because it interferes with overriding
- if (to.ty == Tdelegate && this.nextOf().covariant(to.nextOf()) == Covariant.yes)
- {
- Type tret = this.next.nextOf();
- Type toret = (cast(TypeDelegate)to).next.nextOf();
- if (tret.ty == Tclass && toret.ty == Tclass)
- {
- /* https://issues.dlang.org/show_bug.cgi?id=10219
- * Check covariant interface return with offset tweaking.
- * interface I {}
- * class C : Object, I {}
- * I delegate() dg = delegate C() {} // should be error
- */
- int offset = 0;
- if (toret.isBaseOf(tret, &offset) && offset != 0)
- return MATCH.nomatch;
- }
- return MATCH.convert;
- }
+ MATCH m = this.next.isTypeFunction().implicitPointerConv(toDg.next);
+
+ // Retain the old behaviour for this refactoring
+ // Should probably be changed to constant to match function pointers
+ if (m > MATCH.convert)
+ m = MATCH.convert;
+
+ return m;
}
return MATCH.nomatch;
@@ -5516,6 +5547,11 @@ extern (C++) final class TypeIdentifier : TypeQualified
this.ident = ident;
}
+ static TypeIdentifier create(const ref Loc loc, Identifier ident)
+ {
+ return new TypeIdentifier(loc, ident);
+ }
+
override const(char)* kind() const
{
return "identifier";
@@ -5737,7 +5773,7 @@ extern (C++) final class TypeStruct : Type
override structalign_t alignment()
{
- if (sym.alignment == 0)
+ if (sym.alignment.isUnknown())
sym.size(sym.loc);
return sym.alignment;
}
@@ -6519,6 +6555,29 @@ extern (C++) final class TypeTuple : Type
return false;
}
+ override MATCH implicitConvTo(Type to)
+ {
+ if (this == to)
+ return MATCH.exact;
+ if (auto tt = to.isTypeTuple())
+ {
+ if (arguments.dim == tt.arguments.dim)
+ {
+ MATCH m = MATCH.exact;
+ for (size_t i = 0; i < tt.arguments.dim; i++)
+ {
+ Parameter arg1 = (*arguments)[i];
+ Parameter arg2 = (*tt.arguments)[i];
+ MATCH mi = arg1.type.implicitConvTo(arg2.type);
+ if (mi < m)
+ m = mi;
+ }
+ return m;
+ }
+ }
+ return MATCH.nomatch;
+ }
+
override void accept(Visitor v)
{
v.visit(this);
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index cdf221f..430b39b 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -224,6 +224,7 @@ public:
bool equivalent(Type *t);
// kludge for template.isType()
DYNCAST dyncast() const { return DYNCAST_TYPE; }
+ size_t getUniqueID() const;
Covariant covariant(Type *t, StorageClass *pstc = NULL);
const char *toChars() const;
char *toPrettyChars(bool QualifyTypes = false);
@@ -446,6 +447,7 @@ public:
const char *kind();
TypeSArray *syntaxCopy();
+ bool isIncomplete();
d_uns64 size(const Loc &loc);
unsigned alignsize();
bool isString();
@@ -582,6 +584,7 @@ struct ParameterList
Parameters* parameters;
StorageClass stc;
VarArg varargs;
+ bool hasIdentifierList; // true if C identifier-list style
size_t length();
Parameter *operator[](size_t i) { return Parameter::getNth(parameters, i); }
@@ -711,6 +714,7 @@ public:
Identifier *ident;
Dsymbol *originalSymbol; // The symbol representing this identifier, before alias resolution
+ static TypeIdentifier *create(const Loc &loc, Identifier *ident);
const char *kind();
TypeIdentifier *syntaxCopy();
Dsymbol *toDsymbol(Scope *sc);
diff --git a/gcc/d/dmd/ob.d b/gcc/d/dmd/ob.d
index 7719ccf..605e9f3 100644
--- a/gcc/d/dmd/ob.d
+++ b/gcc/d/dmd/ob.d
@@ -43,7 +43,7 @@ import dmd.tokens;
import dmd.visitor;
import dmd.root.bitarray;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
/**********************************
* Perform ownership/borrowing checks for funcdecl.
diff --git a/gcc/d/dmd/objc.d b/gcc/d/dmd/objc.d
index 85e371e..eb4ba1d 100644
--- a/gcc/d/dmd/objc.d
+++ b/gcc/d/dmd/objc.d
@@ -38,7 +38,7 @@ import dmd.id;
import dmd.identifier;
import dmd.mtype;
import dmd.root.array;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.stringtable;
import dmd.target;
import dmd.tokens;
diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d
index 4ef55f3..ff03a6e 100644
--- a/gcc/d/dmd/opover.d
+++ b/gcc/d/dmd/opover.d
@@ -213,9 +213,13 @@ private Expression checkAliasThisForLhs(AggregateDeclaration ad, Scope* sc, BinE
if (isRecursiveAliasThis(e.att1, e.e1.type))
return null;
//printf("att %s e1 = %s\n", Token::toChars(e.op), e.e1.type.toChars());
- Expression e1 = new DotIdExp(e.loc, e.e1, ad.aliasthis.ident);
BinExp be = cast(BinExp)e.copy();
- be.e1 = e1;
+ // Resolve 'alias this' but in case of assigment don't resolve properties yet
+ // because 'e1 = e2' could mean 'e1(e2)' or 'e1() = e2'
+ bool findOnly = (e.op == TOK.assign);
+ be.e1 = resolveAliasThis(sc, e.e1, true, findOnly);
+ if (!be.e1)
+ return null;
Expression result;
if (be.op == TOK.concatenateAssign)
@@ -237,9 +241,10 @@ private Expression checkAliasThisForRhs(AggregateDeclaration ad, Scope* sc, BinE
if (isRecursiveAliasThis(e.att2, e.e2.type))
return null;
//printf("att %s e2 = %s\n", Token::toChars(e.op), e.e2.type.toChars());
- Expression e2 = new DotIdExp(e.loc, e.e2, ad.aliasthis.ident);
BinExp be = cast(BinExp)e.copy();
- be.e2 = e2;
+ be.e2 = resolveAliasThis(sc, e.e2, true);
+ if (!be.e2)
+ return null;
Expression result;
if (be.op == TOK.concatenateAssign)
@@ -1744,11 +1749,31 @@ private FuncDeclaration findBestOpApplyMatch(Expression ethis, FuncDeclaration f
else if (m == match && m > MATCH.nomatch)
{
assert(fd_best);
- /* Ignore covariant matches, as later on it can be redone
- * after the opApply delegate has its attributes inferred.
- */
- if (tf.covariant(fd_best.type) != Covariant.yes &&
- fd_best.type.covariant(tf) != Covariant.yes)
+ auto bestTf = fd_best.type.isTypeFunction();
+ assert(bestTf);
+
+ // Found another overload with different attributes?
+ // e.g. @system vs. @safe opApply
+ bool ambig = tf.attributesEqual(bestTf);
+
+ // opApplies with identical attributes could still accept
+ // different function bodies as delegate
+ // => different parameters or attributes
+ if (ambig)
+ {
+ // Fetch the delegates that receive the function body
+ auto tfBody = tf.parameterList[0].type.isTypeDelegate().next;
+ assert(tfBody);
+
+ auto bestBody = bestTf.parameterList[0].type.isTypeDelegate().next;
+ assert(bestBody);
+
+ // Ignore covariant matches, as later on it can be redone
+ // after the opApply delegate has its attributes inferred.
+ ambig = !(tfBody.covariant(bestBody) == Covariant.yes || bestBody.covariant(tfBody) == Covariant.yes);
+ }
+
+ if (ambig)
fd_ambig = f; // not covariant, so ambiguous
}
return 0; // continue
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index 3ae3061..9f116fe 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -697,6 +697,8 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
// See if we can remove an unnecessary cast
ClassDeclaration cdfrom = e.e1.type.isClassHandle();
ClassDeclaration cdto = e.type.isClassHandle();
+ if (cdfrom.errors || cdto.errors)
+ return error();
if (cdto == ClassDeclaration.object && !cdfrom.isInterfaceDeclaration())
goto L1; // can always convert a class to Object
// Need to determine correct offset before optimizing away the cast.
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 21042dd..f00ceb6 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -22,7 +22,7 @@ import dmd.identifier;
import dmd.lexer;
import dmd.errors;
import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rmem;
import dmd.root.rootobject;
import dmd.root.string;
@@ -556,6 +556,9 @@ class Parser(AST) : Lexer
{
case TOK.leftParenthesis:
{
+ // MixinType
+ if (isDeclaration(&token, NeedDeclaratorId.mustIfDstyle, TOK.reserved, null))
+ goto Ldeclaration;
// mixin(string)
nextToken();
auto exps = parseArguments();
@@ -2954,6 +2957,8 @@ class Parser(AST) : Lexer
// Don't call nextToken again.
}
case TOK.in_:
+ if (global.params.vin)
+ message(scanloc, "Usage of 'in' on parameter");
stc = STC.in_;
goto L2;
@@ -5408,6 +5413,11 @@ class Parser(AST) : Lexer
stc = STC.scope_;
goto Lagain;
+ case TOK.out_:
+ error("cannot declare `out` loop variable, use `ref` instead");
+ stc = STC.out_;
+ goto Lagain;
+
case TOK.enum_:
stc = STC.manifest;
goto Lagain;
diff --git a/gcc/d/dmd/parse.h b/gcc/d/dmd/parse.h
deleted file mode 100644
index a2ad478..0000000
--- a/gcc/d/dmd/parse.h
+++ /dev/null
@@ -1,192 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/D-Programming-Language/dmd/blob/master/src/parse.h
- */
-
-#pragma once
-
-#include "arraytypes.h"
-#include "lexer.h"
-#include "enum.h"
-
-class Type;
-class TypeQualified;
-class Expression;
-class Declaration;
-class Statement;
-class Import;
-class Initializer;
-class FuncDeclaration;
-class CtorDeclaration;
-class PostBlitDeclaration;
-class DtorDeclaration;
-class StaticCtorDeclaration;
-class StaticDtorDeclaration;
-class SharedStaticCtorDeclaration;
-class SharedStaticDtorDeclaration;
-class ConditionalDeclaration;
-class InvariantDeclaration;
-class UnitTestDeclaration;
-class NewDeclaration;
-class DeleteDeclaration;
-class Condition;
-class Module;
-struct ModuleDeclaration;
-class TemplateDeclaration;
-class TemplateInstance;
-class StaticAssert;
-struct PrefixAttributes;
-
-/************************************
- * These control how parseStatement() works.
- */
-
-enum ParseStatementFlags
-{
- PSsemi = 1, // empty ';' statements are allowed, but deprecated
- PSscope = 2, // start a new scope
- PScurly = 4, // { } statement is required
- PScurlyscope = 8, // { } starts a new scope
- PSsemi_ok = 0x10 // empty ';' are really ok
-};
-
-
-class Parser : public Lexer
-{
-public:
- Module *mod;
- ModuleDeclaration *md;
- LINK linkage;
- CPPMANGLE cppmangle;
- Loc endloc; // set to location of last right curly
- int inBrackets; // inside [] of array index or slice
- Loc lookingForElse; // location of lonely if looking for an else
-
- Parser(Loc loc, Module *module, const utf8_t *base, size_t length, bool doDocComment);
- Parser(Module *module, const utf8_t *base, size_t length, bool doDocComment);
-
- Dsymbols *parseModule();
- Dsymbols *parseDeclDefs(int once, Dsymbol **pLastDecl = NULL, PrefixAttributes *pAttrs = NULL);
- Dsymbols *parseAutoDeclarations(StorageClass storageClass, const utf8_t *comment);
- Dsymbols *parseBlock(Dsymbol **pLastDecl, PrefixAttributes *pAttrs = NULL);
- StorageClass appendStorageClass(StorageClass storageClass, StorageClass stc, bool deprec = false);
- StorageClass parseAttribute(Expressions **pexps);
- StorageClass parsePostfix(StorageClass storageClass, Expressions **pudas);
- StorageClass parseTypeCtor();
- Expression *parseConstraint();
- TemplateDeclaration *parseTemplateDeclaration(bool ismixin = false);
- TemplateParameters *parseTemplateParameterList(int flag = 0);
- Dsymbol *parseMixin();
- Objects *parseTemplateArguments();
- RootObject *parseTypeOrAssignExp(TOK endtoken = TOKreserved);
- Objects *parseTemplateArgumentList();
- Objects *parseTemplateSingleArgument();
- StaticAssert *parseStaticAssert();
- TypeQualified *parseTypeof();
- Type *parseVector();
- LINK parseLinkage(Identifiers **, CPPMANGLE *, bool *);
- Identifiers *parseQualifiedIdentifier(const char *entity);
- Condition *parseDebugCondition();
- Condition *parseVersionCondition();
- Condition *parseStaticIfCondition();
- Dsymbol *parseCtor(PrefixAttributes *pAttrs);
- Dsymbol *parseDtor(PrefixAttributes *pAttrs);
- Dsymbol *parseStaticCtor(PrefixAttributes *pAttrs);
- Dsymbol *parseStaticDtor(PrefixAttributes *pAttrs);
- Dsymbol *parseSharedStaticCtor(PrefixAttributes *pAttrs);
- Dsymbol *parseSharedStaticDtor(PrefixAttributes *pAttrs);
- Dsymbol *parseInvariant(PrefixAttributes *pAttrs);
- Dsymbol *parseUnitTest(PrefixAttributes *pAttrs);
- Dsymbol *parseNew(PrefixAttributes *pAttrs);
- Dsymbol *parseDelete(PrefixAttributes *pAttrs);
- Parameters *parseParameters(VarArg *pvarargs, TemplateParameters **tpl = NULL);
- EnumDeclaration *parseEnum();
- Dsymbol *parseAggregate();
- BaseClasses *parseBaseClasses();
- Dsymbols *parseImport();
- Type *parseType(Identifier **pident = NULL, TemplateParameters **ptpl = NULL);
- Type *parseBasicType(bool dontLookDotIdents = false);
- Type *parseBasicTypeStartingAt(TypeQualified *tid, bool dontLookDotIdents);
- Type *parseBasicType2(Type *t);
- Type *parseDeclarator(Type *t, int *alt, Identifier **pident,
- TemplateParameters **tpl = NULL, StorageClass storage_class = 0, int *pdisable = NULL, Expressions **pudas = NULL);
- void parseStorageClasses(StorageClass &storage_class, LINK &link, bool &setAlignment, Expression *&ealign, Expressions *&udas);
- Dsymbols *parseDeclarations(bool autodecl, PrefixAttributes *pAttrs, const utf8_t *comment);
- Dsymbol *parseFunctionLiteral();
- FuncDeclaration *parseContracts(FuncDeclaration *f);
- void checkDanglingElse(Loc elseloc);
- void checkCstyleTypeSyntax(Loc loc, Type *t, int alt, Identifier *ident);
- Statement *parseForeach(Loc loc, bool *isRange, bool isDecl);
- Dsymbol *parseForeachStaticDecl(Loc loc, Dsymbol **pLastDecl);
- Statement *parseForeachStatic(Loc loc);
- /** endPtr used for documented unittests */
- Statement *parseStatement(int flags, const utf8_t** endPtr = NULL, Loc *pEndloc = NULL);
- Initializer *parseInitializer();
- Expression *parseDefaultInitExp();
- void check(Loc loc, TOK value);
- void check(TOK value);
- void check(TOK value, const char *string);
- void checkParens(TOK value, Expression *e);
- bool isDeclaration(Token *t, int needId, TOK endtok, Token **pt);
- bool isBasicType(Token **pt);
- bool isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok, bool allowAltSyntax = true);
- bool isParameters(Token **pt);
- bool isExpression(Token **pt);
- bool skipParens(Token *t, Token **pt);
- bool skipParensIf(Token *t, Token **pt);
- bool skipAttributes(Token *t, Token **pt);
-
- Expression *parseExpression();
- Expression *parsePrimaryExp();
- Expression *parseUnaryExp();
- Expression *parsePostExp(Expression *e);
- Expression *parseMulExp();
- Expression *parseAddExp();
- Expression *parseShiftExp();
- Expression *parseCmpExp();
- Expression *parseAndExp();
- Expression *parseXorExp();
- Expression *parseOrExp();
- Expression *parseAndAndExp();
- Expression *parseOrOrExp();
- Expression *parseCondExp();
- Expression *parseAssignExp();
-
- Expressions *parseArguments();
-
- Expression *parseNewExp(Expression *thisexp);
-
- void addComment(Dsymbol *s, const utf8_t *blockComment);
-};
-
-// Operator precedence - greater values are higher precedence
-
-enum PREC
-{
- PREC_zero,
- PREC_expr,
- PREC_assign,
- PREC_cond,
- PREC_oror,
- PREC_andand,
- PREC_or,
- PREC_xor,
- PREC_and,
- PREC_equal,
- PREC_rel,
- PREC_shift,
- PREC_add,
- PREC_mul,
- PREC_pow,
- PREC_unary,
- PREC_primary
-};
-
-extern PREC precedence[TOKMAX];
-
-void initPrecedence();
diff --git a/gcc/d/dmd/printast.d b/gcc/d/dmd/printast.d
index 3f12b17..414d6f6 100644
--- a/gcc/d/dmd/printast.d
+++ b/gcc/d/dmd/printast.d
@@ -59,7 +59,7 @@ extern (C++) final class PrintASTVisitor : Visitor
printIndent(indent);
import dmd.hdrgen : floatToBuffer;
- import dmd.root.outbuffer : OutBuffer;
+ import dmd.common.outbuffer : OutBuffer;
OutBuffer buf;
floatToBuffer(e.type, e.value, &buf, false);
printf("Real %s %s\n", buf.peekChars(), e.type ? e.type.toChars() : "");
diff --git a/gcc/d/dmd/root/README.md b/gcc/d/dmd/root/README.md
index 539b940..e062d93 100644
--- a/gcc/d/dmd/root/README.md
+++ b/gcc/d/dmd/root/README.md
@@ -11,7 +11,6 @@
| [hash.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/hash.d) | Calculate a hash for a byte array |
| [longdouble.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/longdouble.d) | 80-bit floating point number implementation in case they are not natively supported |
| [man.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/man.d) | Opens an online manual page |
-| [outbuffer.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/outbuffer.d) | An expandable buffer in which you can write text or binary data. |
| [port.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/port.d) | Portable routines for functions that have different implementations on different platforms |
| [region.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/region.d) | A region allocator |
| [response.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/response.d) | Parse command line arguments from response files |
diff --git a/gcc/d/dmd/root/aav.h b/gcc/d/dmd/root/aav.h
deleted file mode 100644
index c65b674..0000000
--- a/gcc/d/dmd/root/aav.h
+++ /dev/null
@@ -1,22 +0,0 @@
-
-/* Copyright (C) 2010-2021 by The D Language Foundation, All Rights Reserved
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
- * https://github.com/D-Programming-Language/dmd/blob/master/src/root/aav.h
- */
-
-#pragma once
-
-#include "dsystem.h"
-
-typedef void* Value;
-typedef void* Key;
-
-struct AA;
-
-size_t dmd_aaLen(AA* aa);
-Value* dmd_aaGet(AA** aa, Key key);
-Value dmd_aaGetRvalue(AA* aa, Key key);
-void dmd_aaRehash(AA** paa);
-
diff --git a/gcc/d/dmd/root/checkedint.h b/gcc/d/dmd/root/checkedint.h
deleted file mode 100644
index 8a7d9c9..0000000
--- a/gcc/d/dmd/root/checkedint.h
+++ /dev/null
@@ -1,30 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 2003-2021 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/D-Programming-Language/dmd/blob/master/src/root/checkedint.h
- */
-
-#include "dsystem.h"
-
-
-int adds(int x, int y, bool& overflow);
-int64_t adds(int64_t x, int64_t y, bool& overflow);
-unsigned addu(unsigned x, unsigned y, bool& overflow);
-uint64_t addu(uint64_t x, uint64_t y, bool& overflow);
-
-int subs(int x, int y, bool& overflow);
-int64_t subs(int64_t x, int64_t y, bool& overflow);
-unsigned subu(unsigned x, unsigned y, bool& overflow);
-uint64_t subu(uint64_t x, uint64_t y, bool& overflow);
-
-int negs(int x, bool& overflow);
-int64_t negs(int64_t x, bool& overflow);
-
-int muls(int x, int y, bool& overflow);
-int64_t muls(int64_t x, int64_t y, bool& overflow);
-unsigned mulu(unsigned x, unsigned y, bool& overflow);
-uint64_t mulu(uint64_t x, uint64_t y, bool& overflow);
diff --git a/gcc/d/dmd/root/file.d b/gcc/d/dmd/root/file.d
index ef6056c..64e9571 100644
--- a/gcc/d/dmd/root/file.d
+++ b/gcc/d/dmd/root/file.d
@@ -23,410 +23,8 @@ import dmd.root.filename;
import dmd.root.rmem;
import dmd.root.string;
-/**
-Encapsulated management of a memory-mapped file.
-
-Params:
-Datum = the mapped data type: Use a POD of size 1 for read/write mapping
-and a `const` version thereof for read-only mapping. Other primitive types
-should work, but have not been yet tested.
-*/
-struct FileMapping(Datum)
-{
- static assert(__traits(isPOD, Datum) && Datum.sizeof == 1,
- "Not tested with other data types yet. Add new types with care.");
-
- version(Posix) enum invalidHandle = -1;
- else version(Windows) enum invalidHandle = INVALID_HANDLE_VALUE;
-
- // state {
- /// Handle of underlying file
- private auto handle = invalidHandle;
- /// File mapping object needed on Windows
- version(Windows) private HANDLE fileMappingObject = invalidHandle;
- /// Memory-mapped array
- private Datum[] data;
- /// Name of underlying file, zero-terminated
- private const(char)* name;
- // state }
-
- /**
- Open `filename` and map it in memory. If `Datum` is `const`, opens for
- read-only and maps the content in memory; no error is issued if the file
- does not exist. This makes it easy to treat a non-existing file as empty.
-
- If `Datum` is mutable, opens for read/write (creates file if it does not
- exist) and fails fatally on any error.
-
- Due to quirks in `mmap`, if the file is empty, `handle` is valid but `data`
- is `null`. This state is valid and accounted for.
-
- Params:
- filename = the name of the file to be mapped in memory
- */
- this(const char* filename)
- {
- version (Posix)
- {
- import core.sys.posix.sys.mman;
- import core.sys.posix.fcntl;
-
- handle = .open(filename, is(Datum == const) ? O_RDONLY : (O_CREAT | O_RDWR),
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-
- if (handle == invalidHandle)
- {
- static if (is(Datum == const))
- {
- // No error, nonexisting file in read mode behaves like an empty file.
- return;
- }
- else
- {
- fprintf(stderr, "open(\"%s\") failed: %s\n", filename, strerror(errno));
- exit(1);
- }
- }
-
- const size = File.size(handle);
-
- if (size > 0 && size != ulong.max && size <= size_t.max)
- {
- auto p = mmap(null, cast(size_t) size, is(Datum == const) ? PROT_READ : PROT_WRITE, MAP_SHARED, handle, 0);
- if (p == MAP_FAILED)
- {
- fprintf(stderr, "mmap(null, %zu) for \"%s\" failed: %s\n", cast(size_t) size, filename, strerror(errno));
- exit(1);
- }
- // The cast below will always work because it's gated by the `size <= size_t.max` condition.
- data = cast(Datum[]) p[0 .. cast(size_t) size];
- }
- }
- else version(Windows)
- {
- static if (is(Datum == const))
- {
- enum createFileMode = GENERIC_READ;
- enum openFlags = OPEN_EXISTING;
- }
- else
- {
- enum createFileMode = GENERIC_READ | GENERIC_WRITE;
- enum openFlags = CREATE_ALWAYS;
- }
-
- handle = CreateFileA(filename, createFileMode, 0, null, openFlags, FILE_ATTRIBUTE_NORMAL, null);
- if (handle == invalidHandle)
- {
- static if (is(Datum == const))
- {
- return;
- }
- else
- {
- fprintf(stderr, "CreateFileA() failed for \"%s\": %d\n", filename, GetLastError());
- exit(1);
- }
- }
- createMapping(filename, File.size(handle));
- }
- else static assert(0);
-
- // Save the name for later. Technically there's no need: on Linux one can use readlink on /proc/self/fd/NNN.
- // On BSD and OSX one can use fcntl with F_GETPATH. On Windows one can use GetFileInformationByHandleEx.
- // But just saving the name is simplest, fastest, and most portable...
- import core.stdc.string : strlen;
- name = filename[0 .. filename.strlen() + 1].idup.ptr;
- }
-
- /**
- Common code factored opportunistically. Windows only. Assumes `handle` is
- already pointing to an opened file. Initializes the `fileMappingObject`
- and `data` members.
-
- Params:
- filename = the file to be mapped
- size = the size of the file in bytes
- */
- version(Windows) private void createMapping(const char* filename, ulong size)
- {
- assert(size <= size_t.max || size == ulong.max);
- assert(handle != invalidHandle);
- assert(data is null);
- assert(fileMappingObject == invalidHandle);
-
- if (size == 0 || size == ulong.max)
- return;
-
- static if (is(Datum == const))
- {
- enum fileMappingFlags = PAGE_READONLY;
- enum mapViewFlags = FILE_MAP_READ;
- }
- else
- {
- enum fileMappingFlags = PAGE_READWRITE;
- enum mapViewFlags = FILE_MAP_WRITE;
- }
-
- fileMappingObject = CreateFileMappingA(handle, null, fileMappingFlags, 0, 0, null);
- if (!fileMappingObject)
- {
- fprintf(stderr, "CreateFileMappingA(%p) failed for %llu bytes of \"%s\": %d\n",
- handle, size, filename, GetLastError());
- fileMappingObject = invalidHandle; // by convention always use invalidHandle, not null
- exit(1);
- }
- auto p = MapViewOfFile(fileMappingObject, mapViewFlags, 0, 0, 0);
- if (!p)
- {
- fprintf(stderr, "MapViewOfFile() failed for \"%s\": %d\n", filename, GetLastError());
- exit(1);
- }
- data = cast(Datum[]) p[0 .. cast(size_t) size];
- }
-
- // Not copyable or assignable (for now).
- @disable this(const FileMapping!Datum rhs);
- @disable void opAssign(const ref FileMapping!Datum rhs);
-
- /**
- Frees resources associated with this mapping. However, it does not deallocate the name.
- */
- ~this() pure nothrow
- {
- if (!active)
- return;
- fakePure({
- version (Posix)
- {
- import core.sys.posix.sys.mman : munmap;
-
- // Cannot call fprintf from inside a destructor, so exiting silently.
-
- if (data.ptr && munmap(cast(void*) data.ptr, data.length) != 0)
- {
- exit(1);
- }
- data = null;
- if (handle != invalidHandle && .close(handle) != 0)
- {
- exit(1);
- }
- handle = invalidHandle;
- }
- else version(Windows)
- {
- if (data.ptr !is null && UnmapViewOfFile(cast(void*) data.ptr) == 0)
- {
- exit(1);
- }
- data = null;
- if (fileMappingObject != invalidHandle && CloseHandle(fileMappingObject) == 0)
- {
- exit(1);
- }
- fileMappingObject = invalidHandle;
- if (handle != invalidHandle && CloseHandle(handle) == 0)
- {
- exit(1);
- }
- handle = invalidHandle;
- }
- else static assert(0);
- });
- }
-
- /**
- Returns the zero-terminated file name associated with the mapping. Can
- be saved beyond the lifetime of `this`.
- */
- const(char)* filename() const pure @nogc @safe nothrow { return name; }
-
- /**
- Frees resources associated with this mapping. However, it does not deallocate the name.
- Reinitializes `this` as a fresh object that can be reused.
- */
- void close()
- {
- __dtor();
- handle = invalidHandle;
- version(Windows) fileMappingObject = invalidHandle;
- data = null;
- name = null;
- }
-
- /**
- Deletes the underlying file and frees all resources associated.
- Reinitializes `this` as a fresh object that can be reused.
-
- This function does not abort if the file cannot be deleted, but does print
- a message on `stderr` and returns `false` to the caller. The underlying
- rationale is to give the caller the option to continue execution if
- deleting the file is not important.
-
- Returns: `true` iff the file was successfully deleted. If the file was not
- deleted, prints a message to `stderr` and returns `false`.
- */
- static if (!is(Datum == const))
- bool discard()
- {
- // Truncate file to zero so unflushed buffers are not flushed unnecessarily.
- resize(0);
- auto deleteme = name;
- close();
- // In-memory resource freed, now get rid of the underlying temp file.
- version(Posix)
- {
- import core.sys.posix.unistd;
- if (unlink(deleteme) != 0)
- {
- fprintf(stderr, "unlink(\"%s\") failed: %s\n", filename, strerror(errno));
- return false;
- }
- }
- else version(Windows)
- {
- import core.sys.windows.winbase;
- if (DeleteFileA(deleteme) == 0)
- {
- fprintf(stderr, "DeleteFileA error %d\n", GetLastError());
- return false;
- }
- }
- else static assert(0);
- return true;
- }
-
- /**
- Queries whether `this` is currently associated with a file.
-
- Returns: `true` iff there is an active mapping.
- */
- bool active() const pure @nogc nothrow
- {
- return handle !is invalidHandle;
- }
-
- /**
- Queries the length of the file associated with this mapping. If not
- active, returns 0.
-
- Returns: the length of the file, or 0 if no file associated.
- */
- size_t length() const pure @nogc @safe nothrow { return data.length; }
-
- /**
- Get a slice to the contents of the entire file.
-
- Returns: the contents of the file. If not active, returns the `null` slice.
- */
- auto opSlice() pure @nogc @safe nothrow { return data; }
-
- /**
- Resizes the file and mapping to the specified `size`.
-
- Params:
- size = new length requested
- */
- static if (!is(Datum == const))
- void resize(size_t size) pure
- {
- assert(handle != invalidHandle);
- fakePure({
- version(Posix)
- {
- import core.sys.posix.unistd : ftruncate;
- import core.sys.posix.sys.mman;
-
- if (data.length)
- {
- assert(data.ptr, "Corrupt memory mapping");
- // assert(0) here because it would indicate an internal error
- munmap(cast(void*) data.ptr, data.length) == 0 || assert(0);
- data = null;
- }
- if (ftruncate(handle, size) != 0)
- {
- fprintf(stderr, "ftruncate() failed for \"%s\": %s\n", filename, strerror(errno));
- exit(1);
- }
- if (size > 0)
- {
- auto p = mmap(null, size, PROT_WRITE, MAP_SHARED, handle, 0);
- if (cast(ssize_t) p == -1)
- {
- fprintf(stderr, "mmap() failed for \"%s\": %s\n", filename, strerror(errno));
- exit(1);
- }
- data = cast(Datum[]) p[0 .. size];
- }
- }
- else version(Windows)
- {
- // Per documentation, must unmap first.
- if (data.length > 0 && UnmapViewOfFile(cast(void*) data.ptr) == 0)
- {
- fprintf(stderr, "UnmapViewOfFile(%p) failed for memory mapping of \"%s\": %d\n",
- data.ptr, filename, GetLastError());
- exit(1);
- }
- data = null;
- if (fileMappingObject != invalidHandle && CloseHandle(fileMappingObject) == 0)
- {
- fprintf(stderr, "CloseHandle() failed for memory mapping of \"%s\": %d\n", filename, GetLastError());
- exit(1);
- }
- fileMappingObject = invalidHandle;
- LARGE_INTEGER biggie;
- biggie.QuadPart = size;
- if (SetFilePointerEx(handle, biggie, null, FILE_BEGIN) == 0 || SetEndOfFile(handle) == 0)
- {
- fprintf(stderr, "SetFilePointer() failed for \"%s\": %d\n", filename, GetLastError());
- exit(1);
- }
- createMapping(name, size);
- }
- else static assert(0);
- });
- }
-
- /**
- Unconditionally and destructively moves the underlying file to `filename`.
- If the operation succeds, returns true. Upon failure, prints a message to
- `stderr` and returns `false`.
-
- Params: filename = zero-terminated name of the file to move to.
-
- Returns: `true` iff the operation was successful.
- */
- bool moveToFile(const char* filename)
- {
- auto oldname = name;
-
- close();
- // Rename the underlying file to the target, no copy necessary.
- version(Posix)
- {
- if (.rename(oldname, filename) != 0)
- {
- fprintf(stderr, "rename(\"%s\", \"%s\") failed: %s\n", oldname, filename, strerror(errno));
- return false;
- }
- }
- else version(Windows)
- {
- import core.sys.windows.winbase;
- if (MoveFileExA(oldname, filename, MOVEFILE_REPLACE_EXISTING) == 0)
- {
- fprintf(stderr, "MoveFileExA(\"%s\", \"%s\") failed: %d\n", oldname, filename, GetLastError());
- return false;
- }
- }
- else static assert(0);
- return true;
- }
-}
+import dmd.common.file;
+import dmd.common.string;
/// Owns a (rmem-managed) file buffer.
struct FileBuffer
@@ -585,58 +183,8 @@ nothrow:
/// Write a file, returning `true` on success.
extern (D) static bool write(const(char)* name, const void[] data)
{
- version (Posix)
- {
- ssize_t numwritten;
- int fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, (6 << 6) | (4 << 3) | 4);
- if (fd == -1)
- goto err;
- numwritten = .write(fd, data.ptr, data.length);
- if (numwritten != data.length)
- goto err2;
- if (close(fd) == -1)
- goto err;
- return true;
- err2:
- close(fd);
- .remove(name);
- err:
- return false;
- }
- else version (Windows)
- {
- DWORD numwritten; // here because of the gotos
- const nameStr = name.toDString;
- // work around Windows file path length limitation
- // (see documentation for extendedPathThen).
- HANDLE h = nameStr.extendedPathThen!
- (p => CreateFileW(p.ptr,
- GENERIC_WRITE,
- 0,
- null,
- CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
- null));
- if (h == INVALID_HANDLE_VALUE)
- goto err;
-
- if (WriteFile(h, data.ptr, cast(DWORD)data.length, &numwritten, null) != TRUE)
- goto err2;
- if (numwritten != data.length)
- goto err2;
- if (!CloseHandle(h))
- goto err;
- return true;
- err2:
- CloseHandle(h);
- nameStr.extendedPathThen!(p => DeleteFileW(p.ptr));
- err:
- return false;
- }
- else
- {
- static assert(0);
- }
+ import dmd.common.file : writeFile;
+ return writeFile(name, data);
}
///ditto
@@ -717,42 +265,6 @@ nothrow:
return update(name, data[0 .. size]);
}
- /// Touch a file to current date
- static bool touch(const char* namez)
- {
- version (Windows)
- {
- FILETIME ft = void;
- SYSTEMTIME st = void;
- GetSystemTime(&st);
- SystemTimeToFileTime(&st, &ft);
-
- import core.stdc.string : strlen;
-
- // get handle to file
- HANDLE h = namez[0 .. namez.strlen()].extendedPathThen!(p => CreateFile(p.ptr,
- FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE,
- null, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, null));
- if (h == INVALID_HANDLE_VALUE)
- return false;
-
- const f = SetFileTime(h, null, null, &ft); // set last write time
-
- if (!CloseHandle(h))
- return false;
-
- return f != 0;
- }
- else version (Posix)
- {
- import core.sys.posix.utime;
- return utime(namez, null) == 0;
- }
- else
- static assert(0);
- }
-
/// Size of a file in bytes.
/// Params: namez = null-terminated filename
/// Returns: `ulong.max` on any error, the length otherwise.
@@ -777,38 +289,5 @@ nothrow:
// Error cases go here.
return ulong.max;
}
-
- /// Ditto
- version (Posix)
- static ulong size(int fd)
- {
- stat_t buf;
- if (fstat(fd, &buf) == 0)
- return buf.st_size;
- return ulong.max;
- }
-
- /// Ditto
- version (Windows)
- static ulong size(HANDLE fd)
- {
- ulong result;
- if (GetFileSizeEx(fd, cast(LARGE_INTEGER*) &result) == 0)
- return result;
- return ulong.max;
- }
}
-/**
-Runs a non-pure function or delegate as pure code. Use with caution.
-
-Params:
-fun = the delegate to run, usually inlined: `fakePure({ ... });`
-
-Returns: whatever `fun` returns.
-*/
-private auto ref fakePure(F)(scope F fun) pure
-{
- mixin("alias PureFun = " ~ F.stringof ~ " pure;");
- return (cast(PureFun) fun)();
-}
diff --git a/gcc/d/dmd/root/filename.d b/gcc/d/dmd/root/filename.d
index 1e4ccb5..d1500c8 100644
--- a/gcc/d/dmd/root/filename.d
+++ b/gcc/d/dmd/root/filename.d
@@ -16,7 +16,8 @@ import core.stdc.errno;
import core.stdc.string;
import dmd.root.array;
import dmd.root.file;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
+import dmd.common.file;
import dmd.root.port;
import dmd.root.rmem;
import dmd.root.rootobject;
@@ -1123,78 +1124,13 @@ version(Windows)
*/
private int _mkdir(const(char)[] path) nothrow
{
+ import dmd.common.string : extendedPathThen;
const createRet = path.extendedPathThen!(
p => CreateDirectoryW(&p[0], null /*securityAttributes*/));
// different conventions for CreateDirectory and mkdir
return createRet == 0 ? 1 : 0;
}
- /**************************************
- * Converts a path to one suitable to be passed to Win32 API
- * functions that can deal with paths longer than 248
- * characters then calls the supplied function on it.
- *
- * Params:
- * path = The Path to call F on.
- *
- * Returns:
- * The result of calling F on path.
- *
- * References:
- * https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
- */
- package auto extendedPathThen(alias F)(const(char)[] path)
- {
- if (!path.length)
- return F((wchar[]).init);
- return path.toWStringzThen!((wpath)
- {
- // GetFullPathNameW expects a sized buffer to store the result in. Since we don't
- // know how large it has to be, we pass in null and get the needed buffer length
- // as the return code.
- const pathLength = GetFullPathNameW(&wpath[0],
- 0 /*length8*/,
- null /*output buffer*/,
- null /*filePartBuffer*/);
- if (pathLength == 0)
- {
- return F((wchar[]).init);
- }
-
- // wpath is the UTF16 version of path, but to be able to use
- // extended paths, we need to prefix with `\\?\` and the absolute
- // path.
- static immutable prefix = `\\?\`w;
-
- // prefix only needed for long names and non-UNC names
- const needsPrefix = pathLength >= MAX_PATH && (wpath[0] != '\\' || wpath[1] != '\\');
- const prefixLength = needsPrefix ? prefix.length : 0;
-
- // +1 for the null terminator
- const bufferLength = pathLength + prefixLength + 1;
-
- wchar[1024] absBuf = void;
- wchar[] absPath = bufferLength > absBuf.length
- ? new wchar[bufferLength] : absBuf[0 .. bufferLength];
-
- absPath[0 .. prefixLength] = prefix[0 .. prefixLength];
-
- const absPathRet = GetFullPathNameW(&wpath[0],
- cast(uint)(absPath.length - prefixLength - 1),
- &absPath[prefixLength],
- null /*filePartBuffer*/);
-
- if (absPathRet == 0 || absPathRet > absPath.length - prefixLength)
- {
- return F((wchar[]).init);
- }
-
- absPath[$ - 1] = '\0';
- // Strip null terminator from the slice
- return F(absPath[0 .. $ - 1]);
- });
- }
-
/**********************************
* Converts a UTF-16 string to a (null-terminated) narrow string.
* Returns:
@@ -1223,33 +1159,6 @@ version(Windows)
}
/**********************************
- * Converts a narrow string to a (null-terminated) UTF-16 string.
- * Returns:
- * If `buffer` is specified and the result fits, a slice of that buffer,
- * otherwise a new buffer which can be released via `mem.xfree()`.
- * Nulls are propagated, i.e., if `narrow` is null, the returned slice is
- * null too.
- */
- wchar[] toWStringz(const(char)[] narrow, wchar[] buffer = null) nothrow
- {
- if (narrow is null)
- return null;
-
- const requiredLength = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, cast(int) buffer.length);
- if (requiredLength < buffer.length)
- {
- buffer[requiredLength] = 0;
- return buffer[0 .. requiredLength];
- }
-
- wchar* newBuffer = cast(wchar*) mem.xmalloc_noscan((requiredLength + 1) * wchar.sizeof);
- const length = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, newBuffer, requiredLength);
- assert(length == requiredLength);
- newBuffer[length] = 0;
- return newBuffer[0 .. length];
- }
-
- /**********************************
* Converts a slice of UTF-8 characters to an array of wchar that's null
* terminated so it can be passed to Win32 APIs then calls the supplied
* function on it.
@@ -1262,9 +1171,12 @@ version(Windows)
*/
private auto toWStringzThen(alias F)(const(char)[] str) nothrow
{
+ import dmd.common.string : SmallBuffer, toWStringz;
+
if (!str.length) return F(""w.ptr);
- wchar[1024] buf = void;
+ wchar[1024] support = void;
+ auto buf = SmallBuffer!wchar(support.length, support);
wchar[] wide = toWStringz(str, buf);
scope(exit) wide.ptr != buf.ptr && mem.xfree(wide.ptr);
diff --git a/gcc/d/dmd/root/hash.h b/gcc/d/dmd/root/hash.h
deleted file mode 100644
index 6a32200..0000000
--- a/gcc/d/dmd/root/hash.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * Compiler implementation of the D programming language
- * http://dlang.org
- *
- * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * Authors: Martin Nowak, Walter Bright, http://www.digitalmars.com
- * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DMDSRC root/_hash.h)
- */
-
-#pragma once
-
-#include "dsystem.h" // uint{8|16|32}_t
-
-// MurmurHash2 was written by Austin Appleby, and is placed in the public
-// domain. The author hereby disclaims copyright to this source code.
-// https://sites.google.com/site/murmurhash/
-static inline uint32_t calcHash(const uint8_t *data, size_t len)
-{
- // 'm' and 'r' are mixing constants generated offline.
- // They're not really 'magic', they just happen to work well.
-
- const uint32_t m = 0x5bd1e995;
- const int r = 24;
-
- // Initialize the hash to a 'random' value
-
- uint32_t h = (uint32_t)len;
-
- // Mix 4 bytes at a time into the hash
-
- while(len >= 4)
- {
- uint32_t k = data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0];
-
- k *= m;
- k ^= k >> r;
- k *= m;
-
- h *= m;
- h ^= k;
-
- data += 4;
- len -= 4;
- }
-
- // Handle the last few bytes of the input array
-
- switch(len & 3)
- {
- case 3: h ^= data[2] << 16; /* fall through */
- case 2: h ^= data[1] << 8; /* fall through */
- case 1: h ^= data[0];
- h *= m;
- }
-
- // Do a few final mixes of the hash to ensure the last few
- // bytes are well-incorporated.
-
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
-
- return h;
-}
-
-static inline uint32_t calcHash(const char *data, size_t len)
-{
- return calcHash((const uint8_t *)data, len);
-}
-
-// combine and mix two words (boost::hash_combine)
-static inline size_t mixHash(size_t h, size_t k)
-{
- return h ^ (k + 0x9e3779b9 + (h << 6) + (h >> 2));
-}
diff --git a/gcc/d/dmd/root/rootobject.d b/gcc/d/dmd/root/rootobject.d
index 854ec1a..64104b8 100644
--- a/gcc/d/dmd/root/rootobject.d
+++ b/gcc/d/dmd/root/rootobject.d
@@ -13,7 +13,7 @@ module dmd.root.rootobject;
import core.stdc.stdio;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
/***********************************************************
*/
diff --git a/gcc/d/dmd/root/speller.h b/gcc/d/dmd/root/speller.h
deleted file mode 100644
index bd53fc4..0000000
--- a/gcc/d/dmd/root/speller.h
+++ /dev/null
@@ -1,16 +0,0 @@
-
-/* Copyright (C) 2010-2021 by The D Language Foundation, All Rights Reserved
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
- * https://github.com/D-Programming-Language/dmd/blob/master/src/root/speller.h
- */
-
-#pragma once
-
-typedef void *(fp_speller_t)(void *, const char *, int*);
-
-extern const char idchars[];
-
-void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charset);
-
diff --git a/gcc/d/dmd/root/stringtable.h b/gcc/d/dmd/root/stringtable.h
deleted file mode 100644
index 51304d3..0000000
--- a/gcc/d/dmd/root/stringtable.h
+++ /dev/null
@@ -1,56 +0,0 @@
-
-/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/dlang/dmd/blob/master/src/dmd/root/stringtable.h
- */
-
-#pragma once
-
-#include "root.h"
-
-struct StringEntry;
-
-// StringValue is a variable-length structure. It has neither proper c'tors nor a
-// factory method because the only thing which should be creating these is StringTable.
-struct StringValue
-{
- void *ptrvalue;
- size_t length;
- char *lstring() { return (char *)(this + 1); }
-
- size_t len() const { return length; }
- const char *toDchars() const { return (const char *)(this + 1); }
-
- StringValue(); // not constructible
-};
-
-struct StringTable
-{
-private:
- StringEntry *table;
- size_t tabledim;
-
- uint8_t **pools;
- size_t npools;
- size_t nfill;
-
- size_t count;
-
-public:
- void _init(size_t size = 0);
- void reset(size_t size = 0);
- ~StringTable();
-
- StringValue *lookup(const char *s, size_t len);
- StringValue *insert(const char *s, size_t len, void *ptrvalue);
- StringValue *update(const char *s, size_t len);
- int apply(int (*fp)(StringValue *));
-
-private:
- uint32_t allocValue(const char *p, size_t length, void *ptrvalue);
- StringValue *getValue(uint32_t validx);
- size_t findSlot(hash_t hash, const char *s, size_t len);
- void grow();
-};
diff --git a/gcc/d/dmd/safe.d b/gcc/d/dmd/safe.d
index 35734b2..8904959 100644
--- a/gcc/d/dmd/safe.d
+++ b/gcc/d/dmd/safe.d
@@ -89,7 +89,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg)
if (hasPointers && v.type.toBasetype().ty != Tstruct)
{
- if ((ad.type.alignment() < target.ptrsize ||
+ if ((!ad.type.alignment.isDefault() && ad.type.alignment.get() < target.ptrsize ||
(v.offset & (target.ptrsize - 1))) &&
sc.func.setUnsafe())
{
diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d
index 7b2fa5e..993db90 100644
--- a/gcc/d/dmd/semantic2.d
+++ b/gcc/d/dmd/semantic2.d
@@ -53,7 +53,7 @@ import dmd.objc;
import dmd.opover;
import dmd.parse;
import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rmem;
import dmd.root.rootobject;
import dmd.sideeffect;
@@ -363,7 +363,7 @@ private extern(C++) final class Semantic2Visitor : Visitor
assert(fd.semanticRun <= PASS.semantic2);
fd.semanticRun = PASS.semantic2;
- //printf("FuncDeclaration::semantic2 [%s] fd0 = %s %s\n", loc.toChars(), toChars(), type.toChars());
+ //printf("FuncDeclaration::semantic2 [%s] fd: %s type: %s\n", fd.loc.toChars(), fd.toChars(), fd.type ? fd.type.toChars() : "".ptr);
// Only check valid functions which have a body to avoid errors
// for multiple declarations, e.g.
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index ac2b239..3852d0b 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -55,7 +55,7 @@ import dmd.objc;
import dmd.opover;
import dmd.parse;
import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rmem;
import dmd.root.rootobject;
import dmd.sideeffect;
@@ -407,7 +407,8 @@ private extern(C++) final class Semantic3Visitor : Visitor
sc2.insert(_arguments);
_arguments.parent = funcdecl;
}
- if (f.linkage == LINK.d || f.parameterList.length)
+ if ((f.linkage == LINK.d || f.parameterList.length) &&
+ !(sc.flags & SCOPE.Cfile)) // don't want to require importing stdarg for C files
{
// Declare _argptr
Type t = target.va_listType(funcdecl.loc, sc);
@@ -598,7 +599,10 @@ private extern(C++) final class Semantic3Visitor : Visitor
f.next = Type.tvoid;
if (f.checkRetType(funcdecl.loc))
funcdecl.fbody = new ErrorStatement();
+ else if (funcdecl.isMain())
+ funcdecl.checkDmain(); // Check main() parameters and return type
}
+
if (global.params.vcomplex && f.next !is null)
f.next.checkComplexTransition(funcdecl.loc, sc);
@@ -777,8 +781,14 @@ private extern(C++) final class Semantic3Visitor : Visitor
}
assert(!funcdecl.returnLabel);
}
- else if (f.next.ty == Tnoreturn)
+ else if (f.next.toBasetype().ty == Tnoreturn)
{
+ // Fallthrough despite being declared as noreturn? return is already rejected when evaluating the ReturnStatement
+ if (blockexit & BE.fallthru)
+ {
+ funcdecl.error("is typed as `%s` but does return", f.next.toChars());
+ funcdecl.loc.errorSupplemental("`noreturn` functions must either throw, abort or loop indefinitely");
+ }
}
else
{
@@ -1571,7 +1581,7 @@ private struct FuncDeclSem3
}
}
-private void semanticTypeInfoMembers(StructDeclaration sd)
+extern (C++) void semanticTypeInfoMembers(StructDeclaration sd)
{
if (sd.xeq &&
sd.xeq._scope &&
diff --git a/gcc/d/dmd/statement.d b/gcc/d/dmd/statement.d
index b49c903..91e3fe7 100644
--- a/gcc/d/dmd/statement.d
+++ b/gcc/d/dmd/statement.d
@@ -39,7 +39,7 @@ import dmd.id;
import dmd.identifier;
import dmd.dinterpret;
import dmd.mtype;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rootobject;
import dmd.sapply;
import dmd.sideeffect;
@@ -463,7 +463,7 @@ extern (C++) class ExpStatement : Statement
this.exp = new DeclarationExp(loc, declaration);
}
- static ExpStatement create(Loc loc, Expression exp)
+ static ExpStatement create(const ref Loc loc, Expression exp)
{
return new ExpStatement(loc, exp);
}
@@ -577,7 +577,7 @@ extern (C++) class CompoundStatement : Statement
statements.push(s);
}
- static CompoundStatement create(Loc loc, Statement s1, Statement s2)
+ static CompoundStatement create(const ref Loc loc, Statement s1, Statement s2)
{
return new CompoundStatement(loc, s1, s2);
}
@@ -1635,7 +1635,7 @@ extern (C++) final class TryFinallyStatement : Statement
this.bodyFallsThru = true; // assume true until statementSemantic()
}
- static TryFinallyStatement create(Loc loc, Statement _body, Statement finalbody)
+ static TryFinallyStatement create(const ref Loc loc, Statement _body, Statement finalbody)
{
return new TryFinallyStatement(loc, _body, finalbody);
}
diff --git a/gcc/d/dmd/statement.h b/gcc/d/dmd/statement.h
index 7825762..98b7bd3 100644
--- a/gcc/d/dmd/statement.h
+++ b/gcc/d/dmd/statement.h
@@ -186,7 +186,7 @@ class ExpStatement : public Statement
public:
Expression *exp;
- static ExpStatement *create(Loc loc, Expression *exp);
+ static ExpStatement *create(const Loc &loc, Expression *exp);
ExpStatement *syntaxCopy();
void accept(Visitor *v) { v->visit(this); }
@@ -218,7 +218,7 @@ class CompoundStatement : public Statement
public:
Statements *statements;
- static CompoundStatement *create(Loc loc, Statement *s1, Statement *s2);
+ static CompoundStatement *create(const Loc &loc, Statement *s1, Statement *s2);
CompoundStatement *syntaxCopy();
ReturnStatement *endsWithReturnStatement();
Statement *last();
@@ -615,7 +615,7 @@ public:
Statement *tryBody; // set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
bool bodyFallsThru; // true if _body falls through to finally
- static TryFinallyStatement *create(Loc loc, Statement *body, Statement *finalbody);
+ static TryFinallyStatement *create(const Loc &loc, Statement *body, Statement *finalbody);
TryFinallyStatement *syntaxCopy();
bool hasBreak() const;
bool hasContinue() const;
diff --git a/gcc/d/dmd/statement_rewrite_walker.h b/gcc/d/dmd/statement_rewrite_walker.h
deleted file mode 100644
index 28a930a..0000000
--- a/gcc/d/dmd/statement_rewrite_walker.h
+++ /dev/null
@@ -1,172 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- */
-
-#include "statement.h"
-#include "visitor.h"
-
-/* A visitor to walk entire statements and provides ability to replace any sub-statements.
- */
-class StatementRewriteWalker : public Visitor
-{
- /* Point the currently visited statement.
- * By using replaceCurrent() method, you can replace AST during walking.
- */
- Statement **ps;
-public:
- void visitStmt(Statement *&s) { ps = &s; s->accept(this); }
- void replaceCurrent(Statement *s) { *ps = s; }
-
- void visit(ErrorStatement *) { }
- void visit(PeelStatement *s)
- {
- if (s->s)
- visitStmt(s->s);
- }
- void visit(ExpStatement *) { }
- void visit(DtorExpStatement *) { }
- void visit(CompileStatement *) { }
- void visit(CompoundStatement *s)
- {
- if (s->statements && s->statements->length)
- {
- for (size_t i = 0; i < s->statements->length; i++)
- {
- if ((*s->statements)[i])
- visitStmt((*s->statements)[i]);
- }
- }
- }
- void visit(CompoundDeclarationStatement *s) { visit((CompoundStatement *)s); }
- void visit(UnrolledLoopStatement *s)
- {
- if (s->statements && s->statements->length)
- {
- for (size_t i = 0; i < s->statements->length; i++)
- {
- if ((*s->statements)[i])
- visitStmt((*s->statements)[i]);
- }
- }
- }
- void visit(ScopeStatement *s)
- {
- if (s->statement)
- visitStmt(s->statement);
- }
- void visit(WhileStatement *s)
- {
- if (s->_body)
- visitStmt(s->_body);
- }
- void visit(DoStatement *s)
- {
- if (s->_body)
- visitStmt(s->_body);
- }
- void visit(ForStatement *s)
- {
- if (s->_init)
- visitStmt(s->_init);
- if (s->_body)
- visitStmt(s->_body);
- }
- void visit(ForeachStatement *s)
- {
- if (s->_body)
- visitStmt(s->_body);
- }
- void visit(ForeachRangeStatement *s)
- {
- if (s->_body)
- visitStmt(s->_body);
- }
- void visit(IfStatement *s)
- {
- if (s->ifbody)
- visitStmt(s->ifbody);
- if (s->elsebody)
- visitStmt(s->elsebody);
- }
- void visit(ConditionalStatement *) { }
- void visit(PragmaStatement *) { }
- void visit(StaticAssertStatement *) { }
- void visit(SwitchStatement *s)
- {
- if (s->_body)
- visitStmt(s->_body);
- }
- void visit(CaseStatement *s)
- {
- if (s->statement)
- visitStmt(s->statement);
- }
- void visit(CaseRangeStatement *s)
- {
- if (s->statement)
- visitStmt(s->statement);
- }
- void visit(DefaultStatement *s)
- {
- if (s->statement)
- visitStmt(s->statement);
- }
- void visit(GotoDefaultStatement *) { }
- void visit(GotoCaseStatement *) { }
- void visit(SwitchErrorStatement *) { }
- void visit(ReturnStatement *) { }
- void visit(BreakStatement *) { }
- void visit(ContinueStatement *) { }
- void visit(SynchronizedStatement *s)
- {
- if (s->_body)
- visitStmt(s->_body);
- }
- void visit(WithStatement *s)
- {
- if (s->_body)
- visitStmt(s->_body);
- }
- void visit(TryCatchStatement *s)
- {
- if (s->_body)
- visitStmt(s->_body);
- if (s->catches && s->catches->length)
- {
- for (size_t i = 0; i < s->catches->length; i++)
- {
- Catch *c = (*s->catches)[i];
- if (c && c->handler)
- visitStmt(c->handler);
- }
- }
- }
- void visit(TryFinallyStatement *s)
- {
- if (s->_body)
- visitStmt(s->_body);
- if (s->finalbody)
- visitStmt(s->finalbody);
- }
- void visit(ScopeGuardStatement *) { }
- void visit(ThrowStatement *) { }
- void visit(DebugStatement *s)
- {
- if (s->statement)
- visitStmt(s->statement);
- }
- void visit(GotoStatement *) { }
- void visit(LabelStatement *s)
- {
- if (s->statement)
- visitStmt(s->statement);
- }
- void visit(AsmStatement *) { }
- void visit(ImportStatement *) { }
-};
-
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index f067c91..9eba2ff 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -54,7 +54,7 @@ import dmd.nogc;
import dmd.opover;
import dmd.parse;
import dmd.printast;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.string;
import dmd.semantic2;
import dmd.sideeffect;
@@ -659,20 +659,6 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
result = fs;
}
- /*******************
- * Determines the return type of makeTupleForeach.
- */
- private static template MakeTupleForeachRet(bool isDecl)
- {
- static if(isDecl)
- {
- alias MakeTupleForeachRet = Dsymbols*;
- }
- else
- {
- alias MakeTupleForeachRet = void;
- }
- }
/*******************
* Type check and unroll `foreach` over an expression tuple as well
@@ -696,29 +682,24 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
* expands the tuples into multiple `STC.local` `static foreach`
* variables.
*/
- MakeTupleForeachRet!isDecl makeTupleForeach(bool isStatic, bool isDecl)(ForeachStatement fs, TupleForeachArgs!(isStatic, isDecl) args)
+ auto makeTupleForeach(bool isStatic, bool isDecl)(ForeachStatement fs, Dsymbols* dbody, bool needExpansion)
{
- auto returnEarly()
- {
- static if (isDecl)
- {
- return null;
- }
- else
- {
- result = new ErrorStatement();
- return;
- }
- }
- static if(isDecl)
+ // Voldemort return type
+ union U
{
- static assert(isStatic);
- auto dbody = args[0];
+ Statement statement;
+ Dsymbols* decl;
}
- static if(isStatic)
+
+ U result;
+
+ auto returnEarly()
{
- auto needExpansion = args[$-1];
- assert(sc);
+ if (isDecl)
+ result.decl = null;
+ else
+ result.statement = new ErrorStatement();
+ return result;
}
auto loc = fs.loc;
@@ -827,7 +808,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
}
Initializer ie = new ExpInitializer(Loc.initial, new IntegerExp(k));
auto var = new VarDeclaration(loc, p.type, p.ident, ie);
- var.storage_class |= STC.manifest;
+ var.storage_class |= STC.foreach_ | STC.manifest;
static if(isStatic) var.storage_class |= STC.local;
static if(!isDecl)
{
@@ -919,8 +900,9 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
e = resolveProperties(sc, e);
Initializer ie = new ExpInitializer(Loc.initial, e);
auto v = new VarDeclaration(loc, type, ident, ie, storageClass);
+ v.storage_class |= STC.foreach_;
if (storageClass & STC.ref_)
- v.storage_class |= STC.ref_ | STC.foreach_;
+ v.storage_class |= STC.ref_;
if (isStatic || storageClass&STC.manifest || e.isConst() ||
e.op == TOK.string_ ||
e.op == TOK.structLiteral ||
@@ -1057,23 +1039,17 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
ls.gotoTarget = res;
if (te && te.e0)
res = new CompoundStatement(loc, new ExpStatement(te.e0.loc, te.e0), res);
+ result.statement = res;
}
else static if (!isDecl)
{
- Statement res = new CompoundStatement(loc, statements);
- }
- else
- {
- auto res = declarations;
- }
- static if (!isDecl)
- {
- result = res;
+ result.statement = new CompoundStatement(loc, statements);
}
else
{
- return res;
+ result.decl = declarations;
}
+ return result;
}
override void visit(ForeachStatement fs)
@@ -1202,10 +1178,10 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
if (tab.ty == Ttuple) // don't generate new scope for tuple loops
{
- makeTupleForeach!(false,false)(fs);
+ Statement s = makeTupleForeach!(false,false)(fs, null, false).statement;
if (vinit)
- result = new CompoundStatement(loc, new ExpStatement(loc, vinit), result);
- result = result.statementSemantic(sc);
+ s = new CompoundStatement(loc, new ExpStatement(loc, vinit), s);
+ result = s.statementSemantic(sc);
return;
}
@@ -2727,7 +2703,8 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
needswitcherror = true;
}
- if (!sc.sw.sdefault && (!ss.isFinal || needswitcherror || global.params.useAssert == CHECKENABLE.on))
+ if (!sc.sw.sdefault && !(sc.flags & SCOPE.Cfile) &&
+ (!ss.isFinal || needswitcherror || global.params.useAssert == CHECKENABLE.on))
{
ss.hasNoDefault = 1;
@@ -3061,7 +3038,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
if (lval - fval > 256)
{
- crs.error("had %llu cases which is more than 256 cases in case range", lval - fval);
+ crs.error("had %llu cases which is more than 257 cases in case range", 1 + lval - fval);
errors = true;
lval = fval + 256;
}
@@ -3295,12 +3272,14 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
if (e0)
e0 = e0.optimize(WANTvalue);
- /* Void-return function can have void typed expression
+ /* Void-return function can have void / noreturn typed expression
* on return statement.
*/
- if (tbret && tbret.ty == Tvoid || rs.exp.type.ty == Tvoid)
+ const convToVoid = rs.exp.type.ty == Tvoid || rs.exp.type.ty == Tnoreturn;
+
+ if (tbret && tbret.ty == Tvoid || convToVoid)
{
- if (rs.exp.type.ty != Tvoid)
+ if (!convToVoid)
{
rs.error("cannot return non-void from `void` function");
errors = true;
@@ -3345,7 +3324,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
}
else if (rs.exp.op != TOK.error)
{
- rs.error("Expected return type of `%s`, not `%s`:",
+ rs.error("expected return type of `%s`, not `%s`:",
tret.toChars(),
rs.exp.type.toChars());
errorSupplemental((fd.returns) ? (*fd.returns)[0].loc : fd.loc,
@@ -3409,10 +3388,20 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
}
else
{
+ // Type of the returned expression (if any), might've been moved to e0
+ auto resType = e0 ? e0.type : Type.tvoid;
+
// infer return type
if (fd.inferRetType)
{
- if (tf.next && tf.next.ty != Tvoid)
+ // 1. First `return <noreturn exp>?`
+ // 2. Potentially found a returning branch, update accordingly
+ if (!tf.next || tf.next.toBasetype().isTypeNoreturn())
+ {
+ tf.next = resType; // infer void or noreturn
+ }
+ // Found an actual return value before
+ else if (tf.next.ty != Tvoid && !resType.toBasetype().isTypeNoreturn())
{
if (tf.next.ty != Terror)
{
@@ -3421,20 +3410,23 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
errors = true;
tf.next = Type.terror;
}
- else
- tf.next = Type.tvoid;
- tret = tf.next;
+ tret = tf.next;
tbret = tret.toBasetype();
}
if (inferRef) // deduce 'auto ref'
tf.isref = false;
- if (tbret.ty != Tvoid) // if non-void return
+ if (tbret.ty != Tvoid && !resType.isTypeNoreturn()) // if non-void return
{
if (tbret.ty != Terror)
- rs.error("`return` expression expected");
+ {
+ if (e0)
+ rs.error("expected return type of `%s`, not `%s`", tret.toChars(), resType.toChars());
+ else
+ rs.error("`return` expression expected");
+ }
errors = true;
}
else if (fd.isMain())
@@ -3522,7 +3514,12 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
}
else
{
- result = new CompoundStatement(rs.loc, new ExpStatement(rs.loc, e0), rs);
+ auto es = new ExpStatement(rs.loc, e0);
+ if (e0.type.isTypeNoreturn())
+ result = es; // Omit unreachable return;
+ else
+ result = new CompoundStatement(rs.loc, es, rs);
+
return;
}
}
@@ -4014,7 +4011,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
/* If catch exception type is derived from Exception
*/
if (c.type.toBasetype().implicitConvTo(ClassDeclaration.exception.type) &&
- (!c.handler || !c.handler.comeFrom()))
+ (!c.handler || !c.handler.comeFrom()) && !(sc.flags & SCOPE.debug_))
{
// Remove c from the array of catches
tcs.catches.remove(i);
@@ -4570,44 +4567,13 @@ Statement scopeCode(Statement statement, Scope* sc, out Statement sentry, out St
/*******************
- * Determines additional argument types for makeTupleForeach.
- */
-static template TupleForeachArgs(bool isStatic, bool isDecl)
-{
- alias Seq(T...)=T;
- static if(isStatic) alias T = Seq!(bool);
- else alias T = Seq!();
- static if(!isDecl) alias TupleForeachArgs = T;
- else alias TupleForeachArgs = Seq!(Dsymbols*,T);
-}
-
-/*******************
- * Determines the return type of makeTupleForeach.
- */
-static template TupleForeachRet(bool isStatic, bool isDecl)
-{
- alias Seq(T...)=T;
- static if(!isDecl) alias TupleForeachRet = Statement;
- else alias TupleForeachRet = Dsymbols*;
-}
-
-
-/*******************
* See StatementSemanticVisitor.makeTupleForeach. This is a simple
* wrapper that returns the generated statements/declarations.
*/
-TupleForeachRet!(isStatic, isDecl) makeTupleForeach(bool isStatic, bool isDecl)(Scope* sc, ForeachStatement fs, TupleForeachArgs!(isStatic, isDecl) args)
+auto makeTupleForeach(bool isStatic, bool isDecl)(Scope* sc, ForeachStatement fs, Dsymbols* dbody, bool needExpansion)
{
scope v = new StatementSemanticVisitor(sc);
- static if(!isDecl)
- {
- v.makeTupleForeach!(isStatic, isDecl)(fs, args);
- return v.result;
- }
- else
- {
- return v.makeTupleForeach!(isStatic, isDecl)(fs, args);
- }
+ return v.makeTupleForeach!(isStatic, isDecl)(fs, dbody, needExpansion);
}
/*********************************
@@ -4731,7 +4697,7 @@ private Statements* flatten(Statement statement, Scope* sc)
sfs.sfe.prepare(sc);
if (sfs.sfe.ready())
{
- auto s = makeTupleForeach!(true, false)(sc, sfs.sfe.aggrfe, sfs.sfe.needExpansion);
+ Statement s = makeTupleForeach!(true, false)(sc, sfs.sfe.aggrfe, null, sfs.sfe.needExpansion).statement;
auto result = s.flatten(sc);
if (result)
{
diff --git a/gcc/d/dmd/staticcond.d b/gcc/d/dmd/staticcond.d
index 2f27414..d1578ec 100644
--- a/gcc/d/dmd/staticcond.d
+++ b/gcc/d/dmd/staticcond.d
@@ -22,7 +22,7 @@ import dmd.globals;
import dmd.identifier;
import dmd.mtype;
import dmd.root.array;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.tokens;
diff --git a/gcc/d/dmd/target.d b/gcc/d/dmd/target.d
index d5b3de2..16739ad 100644
--- a/gcc/d/dmd/target.d
+++ b/gcc/d/dmd/target.d
@@ -316,7 +316,8 @@ struct TargetC
enum BitFieldStyle : ubyte
{
Unspecified,
- Dm_Ms, /// Digital Mars and Microsoft C compilers
+ DM, /// Digital Mars 32 bit C compiler
+ MS, /// Microsoft 32 and 64 bit C compilers
/// https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160
/// https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160
Gcc_Clang, /// gcc and clang
diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h
index 83281a6..6a75ccc 100644
--- a/gcc/d/dmd/target.h
+++ b/gcc/d/dmd/target.h
@@ -63,7 +63,8 @@ struct TargetC
enum class BitFieldStyle : unsigned char
{
Unspecified,
- Dm_Ms, // Digital Mars and Microsoft C compilers
+ DM, // Digital Mars 32 bit C compiler
+ MS, // Microsoft 32 and 64 bit C compilers
// https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160
// https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160
Gcc_Clang, // gcc and clang
diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h
index 08ce9ac..69cc84f 100644
--- a/gcc/d/dmd/template.h
+++ b/gcc/d/dmd/template.h
@@ -131,7 +131,7 @@ public:
virtual bool declareParameter(Scope *sc) = 0;
virtual void print(RootObject *oarg, RootObject *oded) = 0;
virtual RootObject *specialization() = 0;
- virtual RootObject *defaultArg(Loc instLoc, Scope *sc) = 0;
+ virtual RootObject *defaultArg(const Loc &instLoc, Scope *sc) = 0;
virtual bool hasDefaultArg() = 0;
/* Create dummy argument based on parameter.
@@ -154,7 +154,7 @@ public:
bool declareParameter(Scope *sc);
void print(RootObject *oarg, RootObject *oded);
RootObject *specialization();
- RootObject *defaultArg(Loc instLoc, Scope *sc);
+ RootObject *defaultArg(const Loc &instLoc, Scope *sc);
bool hasDefaultArg();
RootObject *dummyArg();
void accept(Visitor *v) { v->visit(this); }
@@ -186,7 +186,7 @@ public:
bool declareParameter(Scope *sc);
void print(RootObject *oarg, RootObject *oded);
RootObject *specialization();
- RootObject *defaultArg(Loc instLoc, Scope *sc);
+ RootObject *defaultArg(const Loc &instLoc, Scope *sc);
bool hasDefaultArg();
RootObject *dummyArg();
void accept(Visitor *v) { v->visit(this); }
@@ -207,7 +207,7 @@ public:
bool declareParameter(Scope *sc);
void print(RootObject *oarg, RootObject *oded);
RootObject *specialization();
- RootObject *defaultArg(Loc instLoc, Scope *sc);
+ RootObject *defaultArg(const Loc &instLoc, Scope *sc);
bool hasDefaultArg();
RootObject *dummyArg();
void accept(Visitor *v) { v->visit(this); }
@@ -224,7 +224,7 @@ public:
bool declareParameter(Scope *sc);
void print(RootObject *oarg, RootObject *oded);
RootObject *specialization();
- RootObject *defaultArg(Loc instLoc, Scope *sc);
+ RootObject *defaultArg(const Loc &instLoc, Scope *sc);
bool hasDefaultArg();
RootObject *dummyArg();
void accept(Visitor *v) { v->visit(this); }
diff --git a/gcc/d/dmd/tokens.d b/gcc/d/dmd/tokens.d
index 7680fb8..1ea51a8 100644
--- a/gcc/d/dmd/tokens.d
+++ b/gcc/d/dmd/tokens.d
@@ -19,7 +19,7 @@ import core.stdc.string;
import dmd.globals;
import dmd.identifier;
import dmd.root.ctfloat;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rmem;
import dmd.utf;
diff --git a/gcc/d/dmd/tokens.h b/gcc/d/dmd/tokens.h
index 0fd6634..d14d0aa 100644
--- a/gcc/d/dmd/tokens.h
+++ b/gcc/d/dmd/tokens.h
@@ -187,6 +187,7 @@ enum
TOKarrow,
TOKcolonColon,
TOKwchar_tLiteral,
+ TOKcompoundLiteral,
TOKinline,
TOKregister,
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index 8f968ed..cc1d2e3 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -49,7 +49,7 @@ import dmd.tokens;
import dmd.typesem;
import dmd.visitor;
import dmd.root.rootobject;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.string;
enum LOGSEMANTIC = false;
@@ -1410,19 +1410,30 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
auto o = (*e.args)[0];
auto o1 = (*e.args)[1];
- FuncDeclaration fd;
- TypeFunction tf = toTypeFunction(o, fd);
-
ParameterList fparams;
- if (tf)
- fparams = tf.parameterList;
- else if (fd)
- fparams = fd.getParameterList();
+
+ CallExp ce;
+ if (auto exp = isExpression(o))
+ ce = exp.isCallExp();
+
+ if (ce)
+ {
+ fparams = ce.f.getParameterList();
+ }
else
{
- e.error("first argument to `__traits(getParameterStorageClasses, %s, %s)` is not a function",
- o.toChars(), o1.toChars());
- return ErrorExp.get();
+ FuncDeclaration fd;
+ auto tf = toTypeFunction(o, fd);
+ if (tf)
+ fparams = tf.parameterList;
+ else if (fd)
+ fparams = fd.getParameterList();
+ else
+ {
+ e.error("first argument to `__traits(getParameterStorageClasses, %s, %s)` is not a function or a function call",
+ o.toChars(), o1.toChars());
+ return ErrorExp.get();
+ }
}
// Avoid further analysis for invalid functions leading to misleading error messages
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index ace4e42..f75ae0e 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -44,6 +44,7 @@ import dmd.hdrgen;
import dmd.id;
import dmd.identifier;
import dmd.imphint;
+import dmd.importc;
import dmd.init;
import dmd.initsem;
import dmd.visitor;
@@ -53,7 +54,7 @@ import dmd.opover;
import dmd.parse;
import dmd.root.ctfloat;
import dmd.root.rmem;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.rootobject;
import dmd.root.string;
import dmd.root.stringtable;
@@ -1334,6 +1335,8 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
continue;
}
+ fparam.type = fparam.type.cAdjustParamType(sc); // adjust C array and function parameter types
+
Type t = fparam.type.toBasetype();
/* If fparam after semantic() turns out to be a tuple, the number of parameters may
@@ -1378,6 +1381,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
stc, narg.type, narg.ident, narg.defaultArg, narg.userAttribDecl);
}
fparam.type = new TypeTuple(newparams);
+ fparam.type = fparam.type.typeSemantic(loc, argsc);
}
fparam.storageClass = STC.parameter;
@@ -1627,7 +1631,8 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
errors = true;
}
- if (tf.parameterList.varargs == VarArg.variadic && tf.linkage != LINK.d && tf.parameterList.length == 0)
+ if (tf.parameterList.varargs == VarArg.variadic && tf.linkage != LINK.d && tf.parameterList.length == 0 &&
+ !(sc.flags & SCOPE.Cfile))
{
.error(loc, "variadic functions with non-D linkage must have at least one parameter");
errors = true;
@@ -1750,10 +1755,10 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
{
// if there was an error evaluating the symbol, it might actually
// be a type. Avoid misleading error messages.
- .error(loc, "`%s` had previous errors", mtype.toChars());
+ .error(loc, "`%s` had previous errors", mtype.toChars());
}
else
- .error(loc, "`%s` is used as a type", mtype.toChars());
+ .error(loc, "`%s` is used as a type", mtype.toChars());
return error();
}
return t;
@@ -2133,6 +2138,15 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
* struct S { int a; } *s;
*/
sd.members = mtype.members;
+ if (sd.semanticRun == PASS.semanticdone)
+ {
+ /* The first semantic pass marked `sd` as an opaque struct.
+ * Re-run semantic so that all newly assigned members are
+ * picked up and added to the symtab.
+ */
+ sd.semanticRun = PASS.semantic;
+ sd.dsymbolSemantic(sc);
+ }
}
else
{
@@ -2264,7 +2278,7 @@ RootObject compileTypeMixin(TypeMixin tm, Loc loc, Scope* sc)
* Returns:
* the type that was merged
*/
-Type merge(Type type)
+extern (C++) Type merge(Type type)
{
switch (type.ty)
{
@@ -2361,7 +2375,7 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden
{
const explicitAlignment = mt.alignment();
const naturalAlignment = mt.alignsize();
- const actualAlignment = (explicitAlignment == STRUCTALIGN_DEFAULT ? naturalAlignment : explicitAlignment);
+ const actualAlignment = (explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get());
e = new IntegerExp(loc, actualAlignment, Type.tsize_t);
}
else if (ident == Id._init)
@@ -3734,10 +3748,18 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
}
/***************************************
- * Figures out what to do with an undefined member reference
- * for classes and structs.
- *
- * If flag & 1, don't report "not a property" error and just return NULL.
+ * `ident` was not found as a member of `mt`.
+ * Attempt to use overloaded opDot(), overloaded opDispatch(), or `alias this`.
+ * If that fails, forward to visitType().
+ * Params:
+ * mt = class or struct
+ * sc = context
+ * e = `this` for `ident`
+ * ident = name of member
+ * flag = flag & 1, don't report "not a property" error and just return NULL.
+ * flag & DotExpFlag.noAliasThis, don't do 'alias this' resolution.
+ * Returns:
+ * resolved expression if found, otherwise null
*/
Expression noMember(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
{
@@ -3828,7 +3850,8 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
/* See if we should forward to the alias this.
*/
- auto alias_e = resolveAliasThis(sc, e, gagError);
+ auto alias_e = flag & DotExpFlag.noAliasThis ? null
+ : resolveAliasThis(sc, e, gagError);
if (alias_e && alias_e != e)
{
/* Rewrite e.ident as:
@@ -4611,7 +4634,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
* Returns:
* The initialization expression for the type.
*/
-Expression defaultInit(Type mt, const ref Loc loc)
+extern (C++) Expression defaultInit(Type mt, const ref Loc loc)
{
Expression visitBasic(TypeBasic mt)
{
@@ -4744,6 +4767,7 @@ Expression defaultInit(Type mt, const ref Loc loc)
}
auto cond = IntegerExp.createBool(false);
auto msg = new StringExp(loc, "Accessed expression of type `noreturn`");
+ msg.type = Type.tstring;
auto ae = new AssertExp(loc, cond, msg);
ae.type = mt;
return ae;
diff --git a/gcc/d/dmd/typinf.d b/gcc/d/dmd/typinf.d
index d8160f0..d05af61 100644
--- a/gcc/d/dmd/typinf.d
+++ b/gcc/d/dmd/typinf.d
@@ -1,5 +1,5 @@
/**
- * Generate `TypeInfo` objects, which are needed for run-time introspection of classes.
+ * Generate `TypeInfo` objects, which are needed for run-time introspection of types.
*
* Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
@@ -11,9 +11,87 @@
module dmd.typinf;
+import dmd.astenums;
+import dmd.declaration;
+import dmd.dmodule;
import dmd.dscope;
+import dmd.dclass;
+import dmd.dstruct;
+import dmd.errors;
import dmd.globals;
+import dmd.gluelayer;
import dmd.mtype;
+import dmd.visitor;
+import core.stdc.stdio;
+
+/****************************************************
+ * Generates the `TypeInfo` object associated with `torig` if it
+ * hasn't already been generated
+ * Params:
+ * loc = the location for reporting line numbers in errors
+ * torig = the type to generate the `TypeInfo` object for
+ * sc = the scope
+ */
+extern (C++) void genTypeInfo(const ref Loc loc, Type torig, Scope* sc)
+{
+ // printf("genTypeInfo() %s\n", torig.toChars());
+
+ // Even when compiling without `useTypeInfo` (e.g. -betterC) we should
+ // still be able to evaluate `TypeInfo` at compile-time, just not at runtime.
+ // https://issues.dlang.org/show_bug.cgi?id=18472
+ if (!sc || !(sc.flags & SCOPE.ctfe))
+ {
+ if (!global.params.useTypeInfo)
+ {
+ .error(loc, "`TypeInfo` cannot be used with -betterC");
+ fatal();
+ }
+ }
+
+ if (!Type.dtypeinfo)
+ {
+ .error(loc, "`object.TypeInfo` could not be found, but is implicitly used");
+ fatal();
+ }
+
+ Type t = torig.merge2(); // do this since not all Type's are merge'd
+ if (!t.vtinfo)
+ {
+ if (t.isShared()) // does both 'shared' and 'shared const'
+ t.vtinfo = TypeInfoSharedDeclaration.create(t);
+ else if (t.isConst())
+ t.vtinfo = TypeInfoConstDeclaration.create(t);
+ else if (t.isImmutable())
+ t.vtinfo = TypeInfoInvariantDeclaration.create(t);
+ else if (t.isWild())
+ t.vtinfo = TypeInfoWildDeclaration.create(t);
+ else
+ t.vtinfo = getTypeInfoDeclaration(t);
+ assert(t.vtinfo);
+
+ // ClassInfos are generated as part of ClassDeclaration codegen
+ const isUnqualifiedClassInfo = (t.ty == Tclass && !t.mod);
+
+ // generate a COMDAT for other TypeInfos not available as builtins in
+ // druntime
+ if (!isUnqualifiedClassInfo && !builtinTypeInfo(t))
+ {
+ if (sc) // if in semantic() pass
+ {
+ // Find module that will go all the way to an object file
+ Module m = sc._module.importedFrom;
+ m.members.push(t.vtinfo);
+ }
+ else // if in obj generation pass
+ {
+ toObjFile(t.vtinfo, global.params.multiobj);
+ }
+ }
+ }
+ if (!torig.vtinfo)
+ torig.vtinfo = t.vtinfo; // Types aren't merged, but we can share the vtinfo's
+ assert(torig.vtinfo);
+}
/****************************************************
* Gets the type of the `TypeInfo` object associated with `t`
@@ -24,5 +102,161 @@ import dmd.mtype;
* Returns:
* The type of the `TypeInfo` object associated with `t`
*/
-extern (C++) Type getTypeInfoType(Loc loc, Type t, Scope* sc);
+extern (C++) Type getTypeInfoType(const ref Loc loc, Type t, Scope* sc);
+
+private TypeInfoDeclaration getTypeInfoDeclaration(Type t)
+{
+ //printf("Type::getTypeInfoDeclaration() %s\n", t.toChars());
+ switch (t.ty)
+ {
+ case Tpointer:
+ return TypeInfoPointerDeclaration.create(t);
+ case Tarray:
+ return TypeInfoArrayDeclaration.create(t);
+ case Tsarray:
+ return TypeInfoStaticArrayDeclaration.create(t);
+ case Taarray:
+ return TypeInfoAssociativeArrayDeclaration.create(t);
+ case Tstruct:
+ return TypeInfoStructDeclaration.create(t);
+ case Tvector:
+ return TypeInfoVectorDeclaration.create(t);
+ case Tenum:
+ return TypeInfoEnumDeclaration.create(t);
+ case Tfunction:
+ return TypeInfoFunctionDeclaration.create(t);
+ case Tdelegate:
+ return TypeInfoDelegateDeclaration.create(t);
+ case Ttuple:
+ return TypeInfoTupleDeclaration.create(t);
+ case Tclass:
+ if ((cast(TypeClass)t).sym.isInterfaceDeclaration())
+ return TypeInfoInterfaceDeclaration.create(t);
+ else
+ return TypeInfoClassDeclaration.create(t);
+
+ default:
+ return TypeInfoDeclaration.create(t);
+ }
+}
+
+/**************************************************
+ * Returns:
+ * true if any part of type t is speculative.
+ * if t is null, returns false.
+ */
+bool isSpeculativeType(Type t)
+{
+ static bool visitVector(TypeVector t)
+ {
+ return isSpeculativeType(t.basetype);
+ }
+
+ static bool visitAArray(TypeAArray t)
+ {
+ return isSpeculativeType(t.index) ||
+ isSpeculativeType(t.next);
+ }
+
+ static bool visitStruct(TypeStruct t)
+ {
+ StructDeclaration sd = t.sym;
+ if (auto ti = sd.isInstantiated())
+ {
+ if (!ti.needsCodegen())
+ {
+ if (ti.minst || sd.requestTypeInfo)
+ return false;
+
+ /* https://issues.dlang.org/show_bug.cgi?id=14425
+ * TypeInfo_Struct would refer the members of
+ * struct (e.g. opEquals via xopEquals field), so if it's instantiated
+ * in speculative context, TypeInfo creation should also be
+ * stopped to avoid 'unresolved symbol' linker errors.
+ */
+ /* When -debug/-unittest is specified, all of non-root instances are
+ * automatically changed to speculative, and here is always reached
+ * from those instantiated non-root structs.
+ * Therefore, if the TypeInfo is not auctually requested,
+ * we have to elide its codegen.
+ */
+ return true;
+ }
+ }
+ else
+ {
+ //assert(!sd.inNonRoot() || sd.requestTypeInfo); // valid?
+ }
+ return false;
+ }
+
+ static bool visitClass(TypeClass t)
+ {
+ ClassDeclaration sd = t.sym;
+ if (auto ti = sd.isInstantiated())
+ {
+ if (!ti.needsCodegen() && !ti.minst)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static bool visitTuple(TypeTuple t)
+ {
+ if (t.arguments)
+ {
+ foreach (arg; *t.arguments)
+ {
+ if (isSpeculativeType(arg.type))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ if (!t)
+ return false;
+ Type tb = t.toBasetype();
+ switch (tb.ty)
+ {
+ case Tvector: return visitVector(tb.isTypeVector());
+ case Taarray: return visitAArray(tb.isTypeAArray());
+ case Tstruct: return visitStruct(tb.isTypeStruct());
+ case Tclass: return visitClass(tb.isTypeClass());
+ case Ttuple: return visitTuple(tb.isTypeTuple());
+ case Tenum: return false;
+ default:
+ return isSpeculativeType(tb.nextOf());
+
+ /* For TypeFunction, TypeInfo_Function doesn't store parameter types,
+ * so only the .next (the return type) is checked here.
+ */
+ }
+}
+
+/* ========================================================================= */
+
+/* Indicates whether druntime already contains an appropriate TypeInfo instance
+ * for the specified type (in module rt.util.typeinfo).
+ */
+extern (C++) bool builtinTypeInfo(Type t)
+{
+ if (!t.mod) // unqualified types only
+ {
+ // unqualified basic types + typeof(null)
+ if (t.isTypeBasic() || t.ty == Tnull)
+ return true;
+ // some unqualified arrays
+ if (t.ty == Tarray)
+ {
+ Type next = t.nextOf();
+ return (next.isTypeBasic() && !next.mod) // of unqualified basic types
+ || (next.ty == Tchar && next.mod == MODFlags.immutable_) // string
+ || (next.ty == Tchar && next.mod == MODFlags.const_); // const(char)[]
+ }
+ }
+ return false;
+}
diff --git a/gcc/d/dmd/utf.h b/gcc/d/dmd/utf.h
deleted file mode 100644
index b3782af..0000000
--- a/gcc/d/dmd/utf.h
+++ /dev/null
@@ -1,117 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 2003-2021 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/D-Programming-Language/dmd/blob/master/src/utf.h
- */
-
-#pragma once
-
-#include "root/dsystem.h"
-
-/// A UTF-8 code unit
-typedef unsigned char utf8_t;
-/// A UTF-16 code unit
-typedef unsigned short utf16_t;
-/// A UTF-32 code unit
-typedef unsigned int utf32_t;
-typedef utf32_t dchar_t;
-
-#define ALPHA_TABLE_LENGTH 245
-static utf16_t const ALPHA_TABLE[ALPHA_TABLE_LENGTH][2] =
-{
- { 0x00AA, 0x00AA }, { 0x00B5, 0x00B5 }, { 0x00B7, 0x00B7 }, { 0x00BA, 0x00BA },
- { 0x00C0, 0x00D6 }, { 0x00D8, 0x00F6 }, { 0x00F8, 0x01F5 }, { 0x01FA, 0x0217 },
- { 0x0250, 0x02A8 }, { 0x02B0, 0x02B8 }, { 0x02BB, 0x02BB }, { 0x02BD, 0x02C1 },
- { 0x02D0, 0x02D1 }, { 0x02E0, 0x02E4 }, { 0x037A, 0x037A }, { 0x0386, 0x0386 },
- { 0x0388, 0x038A }, { 0x038C, 0x038C }, { 0x038E, 0x03A1 }, { 0x03A3, 0x03CE },
- { 0x03D0, 0x03D6 }, { 0x03DA, 0x03DA }, { 0x03DC, 0x03DC }, { 0x03DE, 0x03DE },
- { 0x03E0, 0x03E0 }, { 0x03E2, 0x03F3 }, { 0x0401, 0x040C }, { 0x040E, 0x044F },
- { 0x0451, 0x045C }, { 0x045E, 0x0481 }, { 0x0490, 0x04C4 }, { 0x04C7, 0x04C8 },
- { 0x04CB, 0x04CC }, { 0x04D0, 0x04EB }, { 0x04EE, 0x04F5 }, { 0x04F8, 0x04F9 },
- { 0x0531, 0x0556 }, { 0x0559, 0x0559 }, { 0x0561, 0x0587 }, { 0x05B0, 0x05B9 },
- { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, { 0x05D0, 0x05EA },
- { 0x05F0, 0x05F2 }, { 0x0621, 0x063A }, { 0x0640, 0x0652 }, { 0x0660, 0x0669 },
- { 0x0670, 0x06B7 }, { 0x06BA, 0x06BE }, { 0x06C0, 0x06CE }, { 0x06D0, 0x06DC },
- { 0x06E5, 0x06E8 }, { 0x06EA, 0x06ED }, { 0x06F0, 0x06F9 }, { 0x0901, 0x0903 },
- { 0x0905, 0x0939 }, { 0x093D, 0x094D }, { 0x0950, 0x0952 }, { 0x0958, 0x0963 },
- { 0x0966, 0x096F }, { 0x0981, 0x0983 }, { 0x0985, 0x098C }, { 0x098F, 0x0990 },
- { 0x0993, 0x09A8 }, { 0x09AA, 0x09B0 }, { 0x09B2, 0x09B2 }, { 0x09B6, 0x09B9 },
- { 0x09BE, 0x09C4 }, { 0x09C7, 0x09C8 }, { 0x09CB, 0x09CD }, { 0x09DC, 0x09DD },
- { 0x09DF, 0x09E3 }, { 0x09E6, 0x09F1 }, { 0x0A02, 0x0A02 }, { 0x0A05, 0x0A0A },
- { 0x0A0F, 0x0A10 }, { 0x0A13, 0x0A28 }, { 0x0A2A, 0x0A30 }, { 0x0A32, 0x0A33 },
- { 0x0A35, 0x0A36 }, { 0x0A38, 0x0A39 }, { 0x0A3E, 0x0A42 }, { 0x0A47, 0x0A48 },
- { 0x0A4B, 0x0A4D }, { 0x0A59, 0x0A5C }, { 0x0A5E, 0x0A5E }, { 0x0A66, 0x0A6F },
- { 0x0A74, 0x0A74 }, { 0x0A81, 0x0A83 }, { 0x0A85, 0x0A8B }, { 0x0A8D, 0x0A8D },
- { 0x0A8F, 0x0A91 }, { 0x0A93, 0x0AA8 }, { 0x0AAA, 0x0AB0 }, { 0x0AB2, 0x0AB3 },
- { 0x0AB5, 0x0AB9 }, { 0x0ABD, 0x0AC5 }, { 0x0AC7, 0x0AC9 }, { 0x0ACB, 0x0ACD },
- { 0x0AD0, 0x0AD0 }, { 0x0AE0, 0x0AE0 }, { 0x0AE6, 0x0AEF }, { 0x0B01, 0x0B03 },
- { 0x0B05, 0x0B0C }, { 0x0B0F, 0x0B10 }, { 0x0B13, 0x0B28 }, { 0x0B2A, 0x0B30 },
- { 0x0B32, 0x0B33 }, { 0x0B36, 0x0B39 }, { 0x0B3D, 0x0B43 }, { 0x0B47, 0x0B48 },
- { 0x0B4B, 0x0B4D }, { 0x0B5C, 0x0B5D }, { 0x0B5F, 0x0B61 }, { 0x0B66, 0x0B6F },
- { 0x0B82, 0x0B83 }, { 0x0B85, 0x0B8A }, { 0x0B8E, 0x0B90 }, { 0x0B92, 0x0B95 },
- { 0x0B99, 0x0B9A }, { 0x0B9C, 0x0B9C }, { 0x0B9E, 0x0B9F }, { 0x0BA3, 0x0BA4 },
- { 0x0BA8, 0x0BAA }, { 0x0BAE, 0x0BB5 }, { 0x0BB7, 0x0BB9 }, { 0x0BBE, 0x0BC2 },
- { 0x0BC6, 0x0BC8 }, { 0x0BCA, 0x0BCD }, { 0x0BE7, 0x0BEF }, { 0x0C01, 0x0C03 },
- { 0x0C05, 0x0C0C }, { 0x0C0E, 0x0C10 }, { 0x0C12, 0x0C28 }, { 0x0C2A, 0x0C33 },
- { 0x0C35, 0x0C39 }, { 0x0C3E, 0x0C44 }, { 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D },
- { 0x0C60, 0x0C61 }, { 0x0C66, 0x0C6F }, { 0x0C82, 0x0C83 }, { 0x0C85, 0x0C8C },
- { 0x0C8E, 0x0C90 }, { 0x0C92, 0x0CA8 }, { 0x0CAA, 0x0CB3 }, { 0x0CB5, 0x0CB9 },
- { 0x0CBE, 0x0CC4 }, { 0x0CC6, 0x0CC8 }, { 0x0CCA, 0x0CCD }, { 0x0CDE, 0x0CDE },
- { 0x0CE0, 0x0CE1 }, { 0x0CE6, 0x0CEF }, { 0x0D02, 0x0D03 }, { 0x0D05, 0x0D0C },
- { 0x0D0E, 0x0D10 }, { 0x0D12, 0x0D28 }, { 0x0D2A, 0x0D39 }, { 0x0D3E, 0x0D43 },
- { 0x0D46, 0x0D48 }, { 0x0D4A, 0x0D4D }, { 0x0D60, 0x0D61 }, { 0x0D66, 0x0D6F },
- { 0x0E01, 0x0E3A }, { 0x0E40, 0x0E5B }, { 0x0E81, 0x0E82 },
- { 0x0E84, 0x0E84 }, { 0x0E87, 0x0E88 }, { 0x0E8A, 0x0E8A }, { 0x0E8D, 0x0E8D },
- { 0x0E94, 0x0E97 }, { 0x0E99, 0x0E9F }, { 0x0EA1, 0x0EA3 }, { 0x0EA5, 0x0EA5 },
- { 0x0EA7, 0x0EA7 }, { 0x0EAA, 0x0EAB }, { 0x0EAD, 0x0EAE }, { 0x0EB0, 0x0EB9 },
- { 0x0EBB, 0x0EBD }, { 0x0EC0, 0x0EC4 }, { 0x0EC6, 0x0EC6 }, { 0x0EC8, 0x0ECD },
- { 0x0ED0, 0x0ED9 }, { 0x0EDC, 0x0EDD }, { 0x0F00, 0x0F00 }, { 0x0F18, 0x0F19 },
- { 0x0F20, 0x0F33 }, { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 },
- { 0x0F3E, 0x0F47 }, { 0x0F49, 0x0F69 }, { 0x0F71, 0x0F84 }, { 0x0F86, 0x0F8B },
- { 0x0F90, 0x0F95 }, { 0x0F97, 0x0F97 }, { 0x0F99, 0x0FAD }, { 0x0FB1, 0x0FB7 },
- { 0x0FB9, 0x0FB9 }, { 0x10A0, 0x10C5 }, { 0x10D0, 0x10F6 }, { 0x1E00, 0x1E9B },
- { 0x1EA0, 0x1EF9 }, { 0x1F00, 0x1F15 }, { 0x1F18, 0x1F1D }, { 0x1F20, 0x1F45 },
- { 0x1F48, 0x1F4D }, { 0x1F50, 0x1F57 }, { 0x1F59, 0x1F59 }, { 0x1F5B, 0x1F5B },
- { 0x1F5D, 0x1F5D }, { 0x1F5F, 0x1F7D }, { 0x1F80, 0x1FB4 }, { 0x1FB6, 0x1FBC },
- { 0x1FBE, 0x1FBE }, { 0x1FC2, 0x1FC4 }, { 0x1FC6, 0x1FCC }, { 0x1FD0, 0x1FD3 },
- { 0x1FD6, 0x1FDB }, { 0x1FE0, 0x1FEC }, { 0x1FF2, 0x1FF4 }, { 0x1FF6, 0x1FFC },
- { 0x203F, 0x2040 }, { 0x207F, 0x207F }, { 0x2102, 0x2102 }, { 0x2107, 0x2107 },
- { 0x210A, 0x2113 }, { 0x2115, 0x2115 }, { 0x2118, 0x211D }, { 0x2124, 0x2124 },
- { 0x2126, 0x2126 }, { 0x2128, 0x2128 }, { 0x212A, 0x2131 }, { 0x2133, 0x2138 },
- { 0x2160, 0x2182 }, { 0x3005, 0x3007 }, { 0x3021, 0x3029 }, { 0x3041, 0x3093 },
- { 0x309B, 0x309C }, { 0x30A1, 0x30F6 }, { 0x30FB, 0x30FC }, { 0x3105, 0x312C },
- { 0x4E00, 0x9FA5 }, { 0xAC00, 0xD7A3 },
-};
-
-char const *const UTF8_DECODE_OK = NULL;
-extern char const UTF8_DECODE_OUTSIDE_CODE_SPACE[];
-extern char const UTF8_DECODE_TRUNCATED_SEQUENCE[];
-extern char const UTF8_DECODE_OVERLONG[];
-extern char const UTF8_DECODE_INVALID_TRAILER[];
-extern char const UTF8_DECODE_INVALID_CODE_POINT[];
-
-char const *const UTF16_DECODE_OK = NULL;
-extern char const UTF16_DECODE_TRUNCATED_SEQUENCE[];
-extern char const UTF16_DECODE_INVALID_SURROGATE[];
-extern char const UTF16_DECODE_UNPAIRED_SURROGATE[];
-extern char const UTF16_DECODE_INVALID_CODE_POINT[];
-
-/// \return true if \a c is a valid, non-private UTF-32 code point
-bool utf_isValidDchar(dchar_t c);
-
-bool isUniAlpha(dchar_t c);
-
-int utf_codeLengthChar(dchar_t c);
-int utf_codeLengthWchar(dchar_t c);
-int utf_codeLength(int sz, dchar_t c);
-
-void utf_encodeChar(utf8_t *s, dchar_t c);
-void utf_encodeWchar(utf16_t *s, dchar_t c);
-void utf_encode(int sz, void *s, dchar_t c);
-
-const char *utf_decodeChar(utf8_t const *s, size_t len, size_t *pidx, dchar_t *presult);
-const char *utf_decodeWchar(utf16_t const *s, size_t len, size_t *pidx, dchar_t *presult);
diff --git a/gcc/d/dmd/utils.d b/gcc/d/dmd/utils.d
index 600521f..6cd5d20 100644
--- a/gcc/d/dmd/utils.d
+++ b/gcc/d/dmd/utils.d
@@ -16,7 +16,7 @@ import dmd.errors;
import dmd.globals;
import dmd.root.file;
import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
import dmd.root.string;
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 3168056..8e1d43e 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -1757,7 +1757,7 @@ public:
/* C++ constructors return void, even though front-end semantic
treats them as implicitly returning `this'. Set returnvalue
to override the result of this expression. */
- if (fd->isCtorDeclaration () && fd->linkage == LINK::cpp)
+ if (fd->isCtorDeclaration ())
{
thisexp = d_save_expr (thisexp);
returnvalue = thisexp;
@@ -1846,6 +1846,11 @@ public:
{
tree init = TARGET_EXPR_INITIAL (cleanup);
TARGET_EXPR_INITIAL (cleanup) = compound_expr (init, exp);
+
+ /* Keep the return value outside the TARGET_EXPR. */
+ if (returnvalue != NULL_TREE)
+ cleanup = compound_expr (cleanup, TREE_OPERAND (exp, 1));
+
exp = cleanup;
}
@@ -1856,7 +1861,7 @@ public:
void visit (DelegateExp *e)
{
- if (e->func->semanticRun == PASSsemantic3done)
+ if (e->func->semanticRun == PASS::semantic3done)
{
/* Add the function as nested function if it belongs to this module.
ie: it is a member of this module, or it is a template instance. */
@@ -2593,7 +2598,8 @@ public:
/* Copy the string contents to a null terminated string. */
dinteger_t length = (e->len * e->sz);
char *string = XALLOCAVEC (char, length + 1);
- memcpy (string, e->string, length);
+ if (length > 0)
+ memcpy (string, e->string, length);
string[length] = '\0';
/* String value and type includes the null terminator. */
diff --git a/gcc/d/gdc.texi b/gcc/d/gdc.texi
index d94998e..9597f2d 100644
--- a/gcc/d/gdc.texi
+++ b/gcc/d/gdc.texi
@@ -252,6 +252,13 @@ Sets @code{__traits(getTargetInfo "cppStd")} to @code{202002}.
@cindex @option{-fno-invariants}
Turns off code generation for class @code{invariant} contracts.
+@item -fmain
+@cindex @option{-fmain}
+Generates a default @code{main()} function when compiling. This is useful when
+unittesting a library, as it enables running the unittests in a library without
+having to manually define an entry-point function. This option does nothing
+when @code{main} is already defined in user code.
+
@item -fno-moduleinfo
@cindex @option{-fmoduleinfo}
@cindex @option{-fno-moduleinfo}
@@ -711,6 +718,8 @@ List information on all D language transitions.
List all usages of complex or imaginary types.
@item field
List all non-mutable fields which occupy an object instance.
+@item in
+List all usages of @code{in} on parameter.
@item nogc
List all hidden GC allocations.
@item templates
diff --git a/gcc/d/lang.opt b/gcc/d/lang.opt
index f7f90fb..d0a5e2f 100644
--- a/gcc/d/lang.opt
+++ b/gcc/d/lang.opt
@@ -436,6 +436,10 @@ ftransition=field
D RejectNegative
List all non-mutable fields which occupy an object instance.
+ftransition=in
+D RejectNegative
+List all usages of 'in' on parameter.
+
ftransition=nogc
D RejectNegative
List all hidden GC allocations.
diff --git a/gcc/d/modules.cc b/gcc/d/modules.cc
index 06eb5ae..cb5c4a7 100644
--- a/gcc/d/modules.cc
+++ b/gcc/d/modules.cc
@@ -145,7 +145,7 @@ get_internal_fn (tree ident, const Visibility &visibility)
fd->loc = Loc (mod->srcfile.toChars (), 1, 0);
fd->parent = mod;
fd->visibility = visibility;
- fd->semanticRun = PASSsemantic3done;
+ fd->semanticRun = PASS::semantic3done;
return fd;
}
diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index db500ee..b39b92e 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -610,7 +610,8 @@ public:
void visit (TypeNoreturn *t)
{
- t->ctype = void_type_node;
+ t->ctype = noreturn_type_node;
+ TYPE_NAME (t->ctype) = get_identifier (t->toChars ());
}
/* Basic Data Types. */
@@ -770,11 +771,17 @@ public:
fnparams = chainon (fnparams, build_tree_list (0, type));
}
- size_t n_args = t->parameterList.length ();
+ const size_t n_args = t->parameterList.length ();
for (size_t i = 0; i < n_args; i++)
{
tree type = parameter_type (t->parameterList[i]);
+
+ /* Type `noreturn` is a terminator, as no other arguments can possibly
+ be evaluated after it. */
+ if (type == noreturn_type_node)
+ break;
+
fnparams = chainon (fnparams, build_tree_list (0, type));
}
@@ -797,6 +804,10 @@ public:
TYPE_LANG_SPECIFIC (t->ctype) = build_lang_type (t);
d_keep (t->ctype);
+ /* Qualify function types that have the type `noreturn` as volatile. */
+ if (fntype == noreturn_type_node)
+ t->ctype = build_qualified_type (t->ctype, TYPE_QUAL_VOLATILE);
+
/* Handle any special support for calling conventions. */
switch (t->linkage)
{
@@ -995,8 +1006,8 @@ public:
the context or laying out fields as those types may make
recursive references to this type. */
unsigned structsize = t->sym->structsize;
- unsigned alignsize = (t->sym->alignment != STRUCTALIGN_DEFAULT)
- ? t->sym->alignment : t->sym->alignsize;
+ unsigned alignsize = t->sym->alignment.isDefault ()
+ ? t->sym->alignsize : t->sym->alignment.get ();
TYPE_SIZE (t->ctype) = bitsize_int (structsize * BITS_PER_UNIT);
TYPE_SIZE_UNIT (t->ctype) = size_int (structsize);
diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
index b996ff2..ca2c840 100644
--- a/gcc/doc/gty.texi
+++ b/gcc/doc/gty.texi
@@ -205,6 +205,15 @@ If @code{skip} is applied to a field, the type machinery will ignore it.
This is somewhat dangerous; the only safe use is in a union when one
field really isn't ever used.
+@findex callback
+@item callback
+
+@code{callback} should be applied to fields with pointer to function type
+and causes the field to be ignored similarly to @code{skip}, except when
+writing PCH and the field is non-NULL it will remember the field's address
+for relocation purposes if the process writing PCH has different load base
+from a process reading PCH.
+
@findex for_user
@item for_user
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 49538dd..df3825f 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -3897,10 +3897,6 @@ This configuration is intended for embedded systems.
@end html
@anchor{x-x-freebsd}
@heading *-*-freebsd*
-Support for FreeBSD 1 was discontinued in GCC 3.2. Support for
-FreeBSD 2 (and any mutant a.out variants of FreeBSD 3) was
-discontinued in GCC 4.0.
-
In order to better utilize FreeBSD base system functionality and match
the configuration of the system compiler, GCC 4.5 and above as well as
GCC 4.4 past 2010-06-20 leverage SSP support in libc (which is present
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e3cfa9e..0b68449 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -576,7 +576,8 @@ Objective-C and Objective-C++ Dialects}.
-fvtv-counts -fvtv-debug @gol
-finstrument-functions @gol
-finstrument-functions-exclude-function-list=@var{sym},@var{sym},@dots{} @gol
--finstrument-functions-exclude-file-list=@var{file},@var{file},@dots{}}
+-finstrument-functions-exclude-file-list=@var{file},@var{file},@dots{}} @gol
+-fprofile-prefix-map=@var{old}=@var{new}
@item Preprocessor Options
@xref{Preprocessor Options,,Options Controlling the Preprocessor}.
@@ -1041,6 +1042,7 @@ Objective-C and Objective-C++ Dialects}.
-mcheck-zero-division -mno-check-zero-division @gol
-mdivide-traps -mdivide-breaks @gol
-mload-store-pairs -mno-load-store-pairs @gol
+-munaligned-access -mno-unaligned-access @gol
-mmemcpy -mno-memcpy -mlong-calls -mno-long-calls @gol
-mmad -mno-mad -mimadd -mno-imadd -mfused-madd -mno-fused-madd -nocpp @gol
-mfix-24k -mno-fix-24k @gol
@@ -1356,6 +1358,7 @@ See RS/6000 and PowerPC Options.
-mcld -mcx16 -msahf -mmovbe -mcrc32 -mmwait @gol
-mrecip -mrecip=@var{opt} @gol
-mvzeroupper -mprefer-avx128 -mprefer-vector-width=@var{opt} @gol
+-mmove-max=@var{bits} -mstore-max=@var{bits} @gol
-mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -msse4 -mavx @gol
-mavx2 -mavx512f -mavx512pf -mavx512er -mavx512cd -mavx512vl @gol
-mavx512bw -mavx512dq -mavx512ifma -mavx512vbmi -msha -maes @gol
@@ -2145,7 +2148,8 @@ files resided in directory @file{@var{new}} instead. Specifying this
option is equivalent to specifying all the individual
@option{-f*-prefix-map} options. This can be used to make reproducible
builds that are location independent. See also
-@option{-fmacro-prefix-map} and @option{-fdebug-prefix-map}.
+@option{-fmacro-prefix-map}, @option{-fdebug-prefix-map} and
+@option{-fprofile-prefix-map}.
@item -fplugin=@var{name}.so
@opindex fplugin
@@ -2998,6 +3002,20 @@ users are likely to want to adjust it, but if your code does heavy
constexpr calculations you might want to experiment to find which
value works best for you.
+@item -fconstexpr-fp-except
+@opindex fconstexpr-fp-except
+Annex F of the C standard specifies that IEC559 floating point
+exceptions encountered at compile time should not stop compilation.
+C++ compilers have historically not followed this guidance, instead
+treating floating point division by zero as non-constant even though
+it has a well defined value. This flag tells the compiler to give
+Annex F priority over other rules saying that a particular operation
+is undefined.
+
+@smallexample
+constexpr float inf = 1./0.; // OK with -fconstexpr-fp-except
+@end smallexample
+
@item -fconstexpr-loop-limit=@var{n}
@opindex fconstexpr-loop-limit
Set the maximum number of iterations for a loop in C++14 constexpr functions
@@ -15222,6 +15240,14 @@ In such setups @option{-fprofile-prefix-path=}@var{path} with @var{path}
pointing to the base directory of the build can be used to strip the irrelevant
part of the path and keep all file names relative to the main build directory.
+@item -fprofile-prefix-map=@var{old}=@var{new}
+@opindex fprofile-prefix-map
+When compiling files residing in directory @file{@var{old}}, record
+profiling information (with @option{--coverage})
+describing them as if the files resided in
+directory @file{@var{new}} instead.
+See also @option{-ffile-prefix-map}.
+
@item -fprofile-update=@var{method}
@opindex fprofile-update
@@ -25665,6 +25691,15 @@ instructions to enable load/store bonding. This option is enabled by
default but only takes effect when the selected architecture is known
to support bonding.
+@item -munaligned-access
+@itemx -mno-unaligned-access
+@opindex munaligned-access
+@opindex mno-unaligned-access
+Enable (disable) direct unaligned access for MIPS Release 6.
+MIPSr6 requires load/store unaligned-access support,
+by hardware or trap&emulate.
+So @option{-mno-unaligned-access} may be needed by kernel.
+
@item -mmemcpy
@itemx -mno-memcpy
@opindex mmemcpy
@@ -31807,6 +31842,18 @@ This option instructs GCC to use 128-bit AVX instructions instead of
This option instructs GCC to use @var{opt}-bit vector width in instructions
instead of default on the selected platform.
+@item -mmove-max=@var{bits}
+@opindex mmove-max
+This option instructs GCC to set the maximum number of bits can be
+moved from memory to memory efficiently to @var{bits}. The valid
+@var{bits} are 128, 256 and 512.
+
+@item -mstore-max=@var{bits}
+@opindex mstore-max
+This option instructs GCC to set the maximum number of bits can be
+stored to memory efficiently to @var{bits}. The valid @var{bits} are
+128, 256 and 512.
+
@table @samp
@item none
No extra limitations applied to GCC other than defined by the selected platform.
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 8b7f710..4179e14 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -13285,6 +13285,11 @@ The default value of this hook is based on target's libc.
@end deftypefn
@c hook-end
+@deftypefn {Target Hook} bool TARGET_IFUNC_REF_LOCAL_OK (void)
+Return true if it is OK to reference indirect function resolvers
+locally. The default is to return false.
+@end deftypefn
+
@deftypefn {Target Hook} {unsigned int} TARGET_ATOMIC_ALIGN_FOR_MODE (machine_mode @var{mode})
@c hook-start:TARGET_ATOMIC_ALIGN_FOR_MODE
If defined, this function returns an appropriate alignment in bits for an
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 2b9960b..50c4fe6 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -8098,6 +8098,8 @@ and the associated definitions of those functions.
@hook TARGET_HAS_IFUNC_P
+@hook TARGET_IFUNC_REF_LOCAL_OK
+
@hook TARGET_ATOMIC_ALIGN_FOR_MODE
@hook TARGET_ATOMIC_ASSIGN_EXPAND_FENV
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index df9b625..9dd1dfe 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -229,8 +229,8 @@ static vec<queued_reg_save> queued_reg_saves;
static bool any_cfis_emitted;
/* Short-hand for commonly used register numbers. */
-static unsigned dw_stack_pointer_regnum;
-static unsigned dw_frame_pointer_regnum;
+static struct cfa_reg dw_stack_pointer_regnum;
+static struct cfa_reg dw_frame_pointer_regnum;
/* Hook used by __throw. */
@@ -430,7 +430,7 @@ new_cfi_row (void)
{
dw_cfi_row *row = ggc_cleared_alloc<dw_cfi_row> ();
- row->cfa.reg = INVALID_REGNUM;
+ row->cfa.reg.set_by_dwreg (INVALID_REGNUM);
return row;
}
@@ -538,7 +538,7 @@ get_cfa_from_loc_descr (dw_cfa_location *cfa, struct dw_loc_descr_node *loc)
cfa->offset = 0;
cfa->base_offset = 0;
cfa->indirect = 0;
- cfa->reg = -1;
+ cfa->reg.set_by_dwreg (INVALID_REGNUM);
for (ptr = loc; ptr != NULL; ptr = ptr->dw_loc_next)
{
@@ -578,10 +578,10 @@ get_cfa_from_loc_descr (dw_cfa_location *cfa, struct dw_loc_descr_node *loc)
case DW_OP_reg29:
case DW_OP_reg30:
case DW_OP_reg31:
- cfa->reg = op - DW_OP_reg0;
+ cfa->reg.set_by_dwreg (op - DW_OP_reg0);
break;
case DW_OP_regx:
- cfa->reg = ptr->dw_loc_oprnd1.v.val_int;
+ cfa->reg.set_by_dwreg (ptr->dw_loc_oprnd1.v.val_int);
break;
case DW_OP_breg0:
case DW_OP_breg1:
@@ -615,16 +615,95 @@ get_cfa_from_loc_descr (dw_cfa_location *cfa, struct dw_loc_descr_node *loc)
case DW_OP_breg29:
case DW_OP_breg30:
case DW_OP_breg31:
- cfa->reg = op - DW_OP_breg0;
- cfa->base_offset = ptr->dw_loc_oprnd1.v.val_int;
- break;
case DW_OP_bregx:
- cfa->reg = ptr->dw_loc_oprnd1.v.val_int;
- cfa->base_offset = ptr->dw_loc_oprnd2.v.val_int;
+ if (cfa->reg.reg == INVALID_REGNUM)
+ {
+ unsigned regno
+ = (op == DW_OP_bregx
+ ? ptr->dw_loc_oprnd1.v.val_int : op - DW_OP_breg0);
+ cfa->reg.set_by_dwreg (regno);
+ cfa->base_offset = ptr->dw_loc_oprnd1.v.val_int;
+ }
+ else
+ {
+ /* Handle case when span can cover multiple registers. We
+ only support the simple case of consecutive registers
+ all with the same size. DWARF that we are dealing with
+ will look something like:
+ <DW_OP_bregx: (r49) 0; DW_OP_const1u: 32; DW_OP_shl;
+ DW_OP_bregx: (r48) 0; DW_OP_plus> */
+
+ unsigned regno
+ = (op == DW_OP_bregx
+ ? ptr->dw_loc_oprnd1.v.val_int : op - DW_OP_breg0);
+ gcc_assert (regno == cfa->reg.reg - 1);
+ cfa->reg.span++;
+ /* From all the consecutive registers used, we want to set
+ cfa->reg.reg to lower number register. */
+ cfa->reg.reg = regno;
+ /* The offset was the shift value. Use it to get the
+ span_width and then set it to 0. */
+ cfa->reg.span_width = cfa->offset.to_constant () / 8;
+ cfa->offset = 0;
+ }
break;
case DW_OP_deref:
cfa->indirect = 1;
break;
+ case DW_OP_shl:
+ break;
+ case DW_OP_lit0:
+ case DW_OP_lit1:
+ case DW_OP_lit2:
+ case DW_OP_lit3:
+ case DW_OP_lit4:
+ case DW_OP_lit5:
+ case DW_OP_lit6:
+ case DW_OP_lit7:
+ case DW_OP_lit8:
+ case DW_OP_lit9:
+ case DW_OP_lit10:
+ case DW_OP_lit11:
+ case DW_OP_lit12:
+ case DW_OP_lit13:
+ case DW_OP_lit14:
+ case DW_OP_lit15:
+ case DW_OP_lit16:
+ case DW_OP_lit17:
+ case DW_OP_lit18:
+ case DW_OP_lit19:
+ case DW_OP_lit20:
+ case DW_OP_lit21:
+ case DW_OP_lit22:
+ case DW_OP_lit23:
+ case DW_OP_lit24:
+ case DW_OP_lit25:
+ case DW_OP_lit26:
+ case DW_OP_lit27:
+ case DW_OP_lit28:
+ case DW_OP_lit29:
+ case DW_OP_lit30:
+ case DW_OP_lit31:
+ gcc_assert (known_eq (cfa->offset, 0));
+ cfa->offset = op - DW_OP_lit0;
+ break;
+ case DW_OP_const1u:
+ case DW_OP_const1s:
+ case DW_OP_const2u:
+ case DW_OP_const2s:
+ case DW_OP_const4s:
+ case DW_OP_const8s:
+ case DW_OP_constu:
+ case DW_OP_consts:
+ gcc_assert (known_eq (cfa->offset, 0));
+ cfa->offset = ptr->dw_loc_oprnd1.v.val_int;
+ break;
+ case DW_OP_minus:
+ cfa->offset = -cfa->offset;
+ break;
+ case DW_OP_plus:
+ /* The offset is already in place. */
+ break;
case DW_OP_plus_uconst:
cfa->offset = ptr->dw_loc_oprnd1.v.val_unsigned;
break;
@@ -648,11 +727,11 @@ lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc, dw_cfa_location *remember)
loc->offset = cfi->dw_cfi_oprnd1.dw_cfi_offset;
break;
case DW_CFA_def_cfa_register:
- loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
+ loc->reg.set_by_dwreg (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
break;
case DW_CFA_def_cfa:
case DW_CFA_def_cfa_sf:
- loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
+ loc->reg.set_by_dwreg (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
loc->offset = cfi->dw_cfi_oprnd2.dw_cfi_offset;
break;
case DW_CFA_def_cfa_expression:
@@ -798,6 +877,7 @@ def_cfa_0 (dw_cfa_location *old_cfa, dw_cfa_location *new_cfa)
HOST_WIDE_INT const_offset;
if (new_cfa->reg == old_cfa->reg
+ && new_cfa->reg.span == 1
&& !new_cfa->indirect
&& !old_cfa->indirect
&& new_cfa->offset.is_constant (&const_offset))
@@ -814,7 +894,8 @@ def_cfa_0 (dw_cfa_location *old_cfa, dw_cfa_location *new_cfa)
}
else if (new_cfa->offset.is_constant ()
&& known_eq (new_cfa->offset, old_cfa->offset)
- && old_cfa->reg != INVALID_REGNUM
+ && old_cfa->reg.reg != INVALID_REGNUM
+ && new_cfa->reg.span == 1
&& !new_cfa->indirect
&& !old_cfa->indirect)
{
@@ -824,10 +905,11 @@ def_cfa_0 (dw_cfa_location *old_cfa, dw_cfa_location *new_cfa)
been set as a register plus offset rather than a general
DW_CFA_def_cfa_expression. */
cfi->dw_cfi_opc = DW_CFA_def_cfa_register;
- cfi->dw_cfi_oprnd1.dw_cfi_reg_num = new_cfa->reg;
+ cfi->dw_cfi_oprnd1.dw_cfi_reg_num = new_cfa->reg.reg;
}
else if (new_cfa->indirect == 0
- && new_cfa->offset.is_constant (&const_offset))
+ && new_cfa->offset.is_constant (&const_offset)
+ && new_cfa->reg.span == 1)
{
/* Construct a "DW_CFA_def_cfa <register> <offset>" instruction,
indicating the CFA register has changed to <register> with
@@ -838,7 +920,7 @@ def_cfa_0 (dw_cfa_location *old_cfa, dw_cfa_location *new_cfa)
cfi->dw_cfi_opc = DW_CFA_def_cfa_sf;
else
cfi->dw_cfi_opc = DW_CFA_def_cfa;
- cfi->dw_cfi_oprnd1.dw_cfi_reg_num = new_cfa->reg;
+ cfi->dw_cfi_oprnd1.dw_cfi_reg_num = new_cfa->reg.reg;
cfi->dw_cfi_oprnd2.dw_cfi_offset = const_offset;
}
else
@@ -885,18 +967,18 @@ def_cfa_1 (dw_cfa_location *new_cfa)
}
/* Add the CFI for saving a register. REG is the CFA column number.
- If SREG is -1, the register is saved at OFFSET from the CFA;
+ If SREG is INVALID_REGISTER, the register is saved at OFFSET from the CFA;
otherwise it is saved in SREG. */
static void
-reg_save (unsigned int reg, unsigned int sreg, poly_int64 offset)
+reg_save (unsigned int reg, struct cfa_reg sreg, poly_int64 offset)
{
dw_fde_ref fde = cfun ? cfun->fde : NULL;
dw_cfi_ref cfi = new_cfi ();
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
- if (sreg == INVALID_REGNUM)
+ if (sreg.reg == INVALID_REGNUM)
{
HOST_WIDE_INT const_offset;
/* When stack is aligned, store REG using DW_CFA_expression with FP. */
@@ -926,7 +1008,7 @@ reg_save (unsigned int reg, unsigned int sreg, poly_int64 offset)
= build_cfa_loc (&cur_row->cfa, offset);
}
}
- else if (sreg == reg)
+ else if (sreg.reg == reg)
{
/* While we could emit something like DW_CFA_same_value or
DW_CFA_restore, we never expect to see something like that
@@ -934,10 +1016,16 @@ reg_save (unsigned int reg, unsigned int sreg, poly_int64 offset)
can always bypass this by using REG_CFA_RESTORE directly. */
gcc_unreachable ();
}
+ else if (sreg.span > 1)
+ {
+ cfi->dw_cfi_opc = DW_CFA_expression;
+ cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
+ cfi->dw_cfi_oprnd2.dw_cfi_loc = build_span_loc (sreg);
+ }
else
{
cfi->dw_cfi_opc = DW_CFA_register;
- cfi->dw_cfi_oprnd2.dw_cfi_reg_num = sreg;
+ cfi->dw_cfi_oprnd2.dw_cfi_reg_num = sreg.reg;
}
add_cfi (cfi);
@@ -1018,6 +1106,44 @@ dwf_regno (const_rtx reg)
return DWARF_FRAME_REGNUM (REGNO (reg));
}
+/* Like dwf_regno, but when the value can span multiple registers. */
+
+static struct cfa_reg
+dwf_cfa_reg (rtx reg)
+{
+ struct cfa_reg result;
+
+ gcc_assert (REGNO (reg) < FIRST_PSEUDO_REGISTER);
+
+ result.reg = dwf_regno (reg);
+ result.span = 1;
+ result.span_width = 0;
+
+ rtx span = targetm.dwarf_register_span (reg);
+ if (span)
+ {
+ /* We only support the simple case of consecutive registers all with the
+ same size. */
+ result.span = XVECLEN (span, 0);
+ result.span_width = GET_MODE_SIZE (GET_MODE (XVECEXP (span, 0, 0)))
+ .to_constant ();
+
+ if (CHECKING_P)
+ {
+ /* Ensure that the above assumption is accurate. */
+ for (unsigned int i = 0; i < result.span; i++)
+ {
+ gcc_assert (GET_MODE_SIZE (GET_MODE (XVECEXP (span, 0, i)))
+ .to_constant () == result.span_width);
+ gcc_assert (REG_P (XVECEXP (span, 0, i)));
+ gcc_assert (dwf_regno (XVECEXP (span, 0, i)) == result.reg + i);
+ }
+ }
+ }
+
+ return result;
+}
+
/* Compare X and Y for equivalence. The inputs may be REGs or PC_RTX. */
static bool
@@ -1086,7 +1212,8 @@ dwarf2out_flush_queued_reg_saves (void)
FOR_EACH_VEC_ELT (queued_reg_saves, i, q)
{
- unsigned int reg, sreg;
+ unsigned int reg;
+ struct cfa_reg sreg;
record_reg_saved_in_reg (q->saved_reg, q->reg);
@@ -1095,9 +1222,9 @@ dwarf2out_flush_queued_reg_saves (void)
else
reg = dwf_regno (q->reg);
if (q->saved_reg)
- sreg = dwf_regno (q->saved_reg);
+ sreg = dwf_cfa_reg (q->saved_reg);
else
- sreg = INVALID_REGNUM;
+ sreg.set_by_dwreg (INVALID_REGNUM);
reg_save (reg, sreg, q->cfa_offset);
}
@@ -1169,7 +1296,7 @@ dwarf2out_frame_debug_def_cfa (rtx pat)
/* ??? If this fails, we could be calling into the _loc functions to
define a full expression. So far no port does that. */
gcc_assert (REG_P (pat));
- cur_cfa->reg = dwf_regno (pat);
+ cur_cfa->reg = dwf_cfa_reg (pat);
}
/* A subroutine of dwarf2out_frame_debug, process a REG_ADJUST_CFA note. */
@@ -1186,7 +1313,7 @@ dwarf2out_frame_debug_adjust_cfa (rtx pat)
switch (GET_CODE (src))
{
case PLUS:
- gcc_assert (dwf_regno (XEXP (src, 0)) == cur_cfa->reg);
+ gcc_assert (dwf_cfa_reg (XEXP (src, 0)) == cur_cfa->reg);
cur_cfa->offset -= rtx_to_poly_int64 (XEXP (src, 1));
break;
@@ -1197,7 +1324,7 @@ dwarf2out_frame_debug_adjust_cfa (rtx pat)
gcc_unreachable ();
}
- cur_cfa->reg = dwf_regno (dest);
+ cur_cfa->reg = dwf_cfa_reg (dest);
gcc_assert (cur_cfa->indirect == 0);
}
@@ -1219,11 +1346,11 @@ dwarf2out_frame_debug_cfa_offset (rtx set)
switch (GET_CODE (addr))
{
case REG:
- gcc_assert (dwf_regno (addr) == cur_cfa->reg);
+ gcc_assert (dwf_cfa_reg (addr) == cur_cfa->reg);
offset = -cur_cfa->offset;
break;
case PLUS:
- gcc_assert (dwf_regno (XEXP (addr, 0)) == cur_cfa->reg);
+ gcc_assert (dwf_cfa_reg (XEXP (addr, 0)) == cur_cfa->reg);
offset = rtx_to_poly_int64 (XEXP (addr, 1)) - cur_cfa->offset;
break;
default:
@@ -1243,8 +1370,10 @@ dwarf2out_frame_debug_cfa_offset (rtx set)
/* ??? We'd like to use queue_reg_save, but we need to come up with
a different flushing heuristic for epilogues. */
+ struct cfa_reg invalid;
+ invalid.set_by_dwreg (INVALID_REGNUM);
if (!span)
- reg_save (sregno, INVALID_REGNUM, offset);
+ reg_save (sregno, invalid, offset);
else
{
/* We have a PARALLEL describing where the contents of SRC live.
@@ -1258,7 +1387,7 @@ dwarf2out_frame_debug_cfa_offset (rtx set)
{
rtx elem = XVECEXP (span, 0, par_index);
sregno = dwf_regno (src);
- reg_save (sregno, INVALID_REGNUM, span_offset);
+ reg_save (sregno, invalid, span_offset);
span_offset += GET_MODE_SIZE (GET_MODE (elem));
}
}
@@ -1270,7 +1399,8 @@ static void
dwarf2out_frame_debug_cfa_register (rtx set)
{
rtx src, dest;
- unsigned sregno, dregno;
+ unsigned sregno;
+ struct cfa_reg dregno;
src = XEXP (set, 1);
dest = XEXP (set, 0);
@@ -1281,7 +1411,7 @@ dwarf2out_frame_debug_cfa_register (rtx set)
else
sregno = dwf_regno (src);
- dregno = dwf_regno (dest);
+ dregno = dwf_cfa_reg (dest);
/* ??? We'd like to use queue_reg_save, but we need to come up with
a different flushing heuristic for epilogues. */
@@ -1667,7 +1797,7 @@ dwarf2out_frame_debug_expr (rtx expr)
{
/* Setting FP from SP. */
case REG:
- if (cur_cfa->reg == dwf_regno (src))
+ if (cur_cfa->reg == dwf_cfa_reg (src))
{
/* Rule 1 */
/* Update the CFA rule wrt SP or FP. Make sure src is
@@ -1677,7 +1807,7 @@ dwarf2out_frame_debug_expr (rtx expr)
ARM copies SP to a temporary register, and from there to
FP. So we just rely on the backends to only set
RTX_FRAME_RELATED_P on appropriate insns. */
- cur_cfa->reg = dwf_regno (dest);
+ cur_cfa->reg = dwf_cfa_reg (dest);
cur_trace->cfa_temp.reg = cur_cfa->reg;
cur_trace->cfa_temp.offset = cur_cfa->offset;
}
@@ -1698,7 +1828,7 @@ dwarf2out_frame_debug_expr (rtx expr)
{
gcc_assert (REGNO (dest) == HARD_FRAME_POINTER_REGNUM
&& fde->drap_reg != INVALID_REGNUM
- && cur_cfa->reg != dwf_regno (src)
+ && cur_cfa->reg != dwf_cfa_reg (src)
&& fde->rule18);
fde->rule18 = 0;
/* The save of hard frame pointer has been deferred
@@ -1722,7 +1852,7 @@ dwarf2out_frame_debug_expr (rtx expr)
/* Adjusting SP. */
if (REG_P (XEXP (src, 1)))
{
- gcc_assert (dwf_regno (XEXP (src, 1))
+ gcc_assert (dwf_cfa_reg (XEXP (src, 1))
== cur_trace->cfa_temp.reg);
offset = cur_trace->cfa_temp.offset;
}
@@ -1756,7 +1886,7 @@ dwarf2out_frame_debug_expr (rtx expr)
gcc_assert (frame_pointer_needed);
gcc_assert (REG_P (XEXP (src, 0))
- && dwf_regno (XEXP (src, 0)) == cur_cfa->reg);
+ && dwf_cfa_reg (XEXP (src, 0)) == cur_cfa->reg);
offset = rtx_to_poly_int64 (XEXP (src, 1));
if (GET_CODE (src) != MINUS)
offset = -offset;
@@ -1769,14 +1899,14 @@ dwarf2out_frame_debug_expr (rtx expr)
/* Rule 4 */
if (REG_P (XEXP (src, 0))
- && dwf_regno (XEXP (src, 0)) == cur_cfa->reg
+ && dwf_cfa_reg (XEXP (src, 0)) == cur_cfa->reg
&& poly_int_rtx_p (XEXP (src, 1), &offset))
{
/* Setting a temporary CFA register that will be copied
into the FP later on. */
offset = -offset;
cur_cfa->offset += offset;
- cur_cfa->reg = dwf_regno (dest);
+ cur_cfa->reg = dwf_cfa_reg (dest);
/* Or used to save regs to the stack. */
cur_trace->cfa_temp.reg = cur_cfa->reg;
cur_trace->cfa_temp.offset = cur_cfa->offset;
@@ -1784,13 +1914,13 @@ dwarf2out_frame_debug_expr (rtx expr)
/* Rule 5 */
else if (REG_P (XEXP (src, 0))
- && dwf_regno (XEXP (src, 0)) == cur_trace->cfa_temp.reg
+ && dwf_cfa_reg (XEXP (src, 0)) == cur_trace->cfa_temp.reg
&& XEXP (src, 1) == stack_pointer_rtx)
{
/* Setting a scratch register that we will use instead
of SP for saving registers to the stack. */
gcc_assert (cur_cfa->reg == dw_stack_pointer_regnum);
- cur_trace->cfa_store.reg = dwf_regno (dest);
+ cur_trace->cfa_store.reg = dwf_cfa_reg (dest);
cur_trace->cfa_store.offset
= cur_cfa->offset - cur_trace->cfa_temp.offset;
}
@@ -1799,7 +1929,7 @@ dwarf2out_frame_debug_expr (rtx expr)
else if (GET_CODE (src) == LO_SUM
&& poly_int_rtx_p (XEXP (src, 1),
&cur_trace->cfa_temp.offset))
- cur_trace->cfa_temp.reg = dwf_regno (dest);
+ cur_trace->cfa_temp.reg = dwf_cfa_reg (dest);
else
gcc_unreachable ();
}
@@ -1808,17 +1938,17 @@ dwarf2out_frame_debug_expr (rtx expr)
/* Rule 6 */
case CONST_INT:
case CONST_POLY_INT:
- cur_trace->cfa_temp.reg = dwf_regno (dest);
+ cur_trace->cfa_temp.reg = dwf_cfa_reg (dest);
cur_trace->cfa_temp.offset = rtx_to_poly_int64 (src);
break;
/* Rule 7 */
case IOR:
gcc_assert (REG_P (XEXP (src, 0))
- && dwf_regno (XEXP (src, 0)) == cur_trace->cfa_temp.reg
+ && dwf_cfa_reg (XEXP (src, 0)) == cur_trace->cfa_temp.reg
&& CONST_INT_P (XEXP (src, 1)));
- cur_trace->cfa_temp.reg = dwf_regno (dest);
+ cur_trace->cfa_temp.reg = dwf_cfa_reg (dest);
if (!can_ior_p (cur_trace->cfa_temp.offset, INTVAL (XEXP (src, 1)),
&cur_trace->cfa_temp.offset))
/* The target shouldn't generate this kind of CFI note if we
@@ -1851,14 +1981,17 @@ dwarf2out_frame_debug_expr (rtx expr)
dwarf2out_flush_queued_reg_saves ();
gcc_assert (cur_trace->cfa_store.reg
- == dwf_regno (XEXP (src, 0)));
+ == dwf_cfa_reg (XEXP (src, 0)));
fde->stack_realign = 1;
fde->stack_realignment = INTVAL (XEXP (src, 1));
cur_trace->cfa_store.offset = 0;
if (cur_cfa->reg != dw_stack_pointer_regnum
&& cur_cfa->reg != dw_frame_pointer_regnum)
- fde->drap_reg = cur_cfa->reg;
+ {
+ gcc_assert (cur_cfa->reg.span == 1);
+ fde->drap_reg = cur_cfa->reg.reg;
+ }
}
return;
@@ -1935,14 +2068,14 @@ dwarf2out_frame_debug_expr (rtx expr)
case MINUS:
case LO_SUM:
{
- unsigned int regno;
+ struct cfa_reg regno;
gcc_assert (REG_P (XEXP (XEXP (dest, 0), 0)));
offset = rtx_to_poly_int64 (XEXP (XEXP (dest, 0), 1));
if (GET_CODE (XEXP (dest, 0)) == MINUS)
offset = -offset;
- regno = dwf_regno (XEXP (XEXP (dest, 0), 0));
+ regno = dwf_cfa_reg (XEXP (XEXP (dest, 0), 0));
if (cur_cfa->reg == regno)
offset -= cur_cfa->offset;
@@ -1960,7 +2093,7 @@ dwarf2out_frame_debug_expr (rtx expr)
/* Without an offset. */
case REG:
{
- unsigned int regno = dwf_regno (XEXP (dest, 0));
+ struct cfa_reg regno = dwf_cfa_reg (XEXP (dest, 0));
if (cur_cfa->reg == regno)
offset = -cur_cfa->offset;
@@ -1977,7 +2110,7 @@ dwarf2out_frame_debug_expr (rtx expr)
/* Rule 14 */
case POST_INC:
gcc_assert (cur_trace->cfa_temp.reg
- == dwf_regno (XEXP (XEXP (dest, 0), 0)));
+ == dwf_cfa_reg (XEXP (XEXP (dest, 0), 0)));
offset = -cur_trace->cfa_temp.offset;
cur_trace->cfa_temp.offset -= GET_MODE_SIZE (GET_MODE (dest));
break;
@@ -1995,7 +2128,7 @@ dwarf2out_frame_debug_expr (rtx expr)
if (REG_P (src)
&& REGNO (src) != STACK_POINTER_REGNUM
&& REGNO (src) != HARD_FRAME_POINTER_REGNUM
- && dwf_regno (src) == cur_cfa->reg)
+ && dwf_cfa_reg (src) == cur_cfa->reg)
{
/* We're storing the current CFA reg into the stack. */
@@ -2012,7 +2145,7 @@ dwarf2out_frame_debug_expr (rtx expr)
&& cur_cfa->indirect == 0
&& cur_cfa->reg != dw_frame_pointer_regnum)
{
- gcc_assert (fde->drap_reg == cur_cfa->reg);
+ gcc_assert (fde->drap_reg == cur_cfa->reg.reg);
cur_cfa->indirect = 1;
cur_cfa->reg = dw_frame_pointer_regnum;
@@ -2039,7 +2172,7 @@ dwarf2out_frame_debug_expr (rtx expr)
x = XEXP (x, 0);
gcc_assert (REG_P (x));
- cur_cfa->reg = dwf_regno (x);
+ cur_cfa->reg = dwf_cfa_reg (x);
cur_cfa->base_offset = offset;
cur_cfa->indirect = 1;
break;
@@ -2951,7 +3084,7 @@ create_pseudo_cfg (void)
ti.head = get_insns ();
ti.beg_row = cie_cfi_row;
ti.cfa_store = cie_cfi_row->cfa;
- ti.cfa_temp.reg = INVALID_REGNUM;
+ ti.cfa_temp.reg.set_by_dwreg (INVALID_REGNUM);
trace_info.quick_push (ti);
if (cie_return_save)
@@ -3014,14 +3147,15 @@ create_pseudo_cfg (void)
static void
initial_return_save (rtx rtl)
{
- unsigned int reg = INVALID_REGNUM;
+ struct cfa_reg reg;
+ reg.set_by_dwreg (INVALID_REGNUM);
poly_int64 offset = 0;
switch (GET_CODE (rtl))
{
case REG:
/* RA is in a register. */
- reg = dwf_regno (rtl);
+ reg = dwf_cfa_reg (rtl);
break;
case MEM:
@@ -3062,9 +3196,9 @@ initial_return_save (rtx rtl)
gcc_unreachable ();
}
- if (reg != DWARF_FRAME_RETURN_COLUMN)
+ if (reg.reg != DWARF_FRAME_RETURN_COLUMN)
{
- if (reg != INVALID_REGNUM)
+ if (reg.reg != INVALID_REGNUM)
record_reg_saved_in_reg (rtl, pc_rtx);
reg_save (DWARF_FRAME_RETURN_COLUMN, reg, offset - cur_row->cfa.offset);
}
@@ -3076,7 +3210,8 @@ create_cie_data (void)
dw_cfa_location loc;
dw_trace_info cie_trace;
- dw_stack_pointer_regnum = DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM);
+ dw_stack_pointer_regnum = dwf_cfa_reg (gen_rtx_REG (Pmode,
+ STACK_POINTER_REGNUM));
memset (&cie_trace, 0, sizeof (cie_trace));
cur_trace = &cie_trace;
@@ -3135,7 +3270,8 @@ static unsigned int
execute_dwarf2_frame (void)
{
/* Different HARD_FRAME_POINTER_REGNUM might coexist in the same file. */
- dw_frame_pointer_regnum = DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM);
+ dw_frame_pointer_regnum
+ = dwf_cfa_reg (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM));
/* The first time we're called, compute the incoming frame state. */
if (cie_cfi_vec == NULL)
@@ -3515,7 +3651,7 @@ dump_cfi_row (FILE *f, dw_cfi_row *row)
{
dw_cfa_location dummy;
memset (&dummy, 0, sizeof (dummy));
- dummy.reg = INVALID_REGNUM;
+ dummy.reg.set_by_dwreg (INVALID_REGNUM);
cfi = def_cfa_0 (&dummy, &row->cfa);
}
output_cfi_directive (f, cfi);
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index e36ef56..d6513d3 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -2780,6 +2780,43 @@ output_loc_sequence_raw (dw_loc_descr_ref loc)
}
}
+static void
+build_breg_loc (struct dw_loc_descr_node **head, unsigned int regno)
+{
+ if (regno <= 31)
+ add_loc_descr (head, new_loc_descr ((enum dwarf_location_atom)
+ (DW_OP_breg0 + regno), 0, 0));
+ else
+ add_loc_descr (head, new_loc_descr (DW_OP_bregx, regno, 0));
+}
+
+/* Build a dwarf location for a cfa_reg spanning multiple
+ consecutive registers. */
+
+struct dw_loc_descr_node *
+build_span_loc (struct cfa_reg reg)
+{
+ struct dw_loc_descr_node *head = NULL;
+
+ gcc_assert (reg.span_width > 0);
+ gcc_assert (reg.span > 1);
+
+ /* Start from the highest number register as it goes in the upper bits. */
+ unsigned int regno = reg.reg + reg.span - 1;
+ build_breg_loc (&head, regno);
+
+ /* Deal with the remaining registers in the span. */
+ for (int i = reg.span - 2; i >= 0; i--)
+ {
+ add_loc_descr (&head, int_loc_descriptor (reg.span_width * 8));
+ add_loc_descr (&head, new_loc_descr (DW_OP_shl, 0, 0));
+ regno--;
+ build_breg_loc (&head, regno);
+ add_loc_descr (&head, new_loc_descr (DW_OP_plus, 0, 0));
+ }
+ return head;
+}
+
/* This function builds a dwarf location descriptor sequence from a
dw_cfa_location, adding the given OFFSET to the result of the
expression. */
@@ -2791,9 +2828,16 @@ build_cfa_loc (dw_cfa_location *cfa, poly_int64 offset)
offset += cfa->offset;
- if (cfa->indirect)
+ if (cfa->reg.span > 1)
+ {
+ head = build_span_loc (cfa->reg);
+
+ if (maybe_ne (offset, 0))
+ loc_descr_plus_const (&head, offset);
+ }
+ else if (cfa->indirect)
{
- head = new_reg_loc_descr (cfa->reg, cfa->base_offset);
+ head = new_reg_loc_descr (cfa->reg.reg, cfa->base_offset);
head->dw_loc_oprnd1.val_class = dw_val_class_const;
head->dw_loc_oprnd1.val_entry = NULL;
tmp = new_loc_descr (DW_OP_deref, 0, 0);
@@ -2801,7 +2845,7 @@ build_cfa_loc (dw_cfa_location *cfa, poly_int64 offset)
loc_descr_plus_const (&head, offset);
}
else
- head = new_reg_loc_descr (cfa->reg, offset);
+ head = new_reg_loc_descr (cfa->reg.reg, offset);
return head;
}
@@ -2819,7 +2863,7 @@ build_cfa_aligned_loc (dw_cfa_location *cfa,
= DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM);
/* When CFA is defined as FP+OFFSET, emulate stack alignment. */
- if (cfa->reg == HARD_FRAME_POINTER_REGNUM && cfa->indirect == 0)
+ if (cfa->reg.reg == HARD_FRAME_POINTER_REGNUM && cfa->indirect == 0)
{
head = new_reg_loc_descr (dwarf_fp, 0);
add_loc_descr (&head, int_loc_descriptor (alignment));
@@ -20882,7 +20926,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
list = NULL;
memset (&next_cfa, 0, sizeof (next_cfa));
- next_cfa.reg = INVALID_REGNUM;
+ next_cfa.reg.set_by_dwreg (INVALID_REGNUM);
remember = next_cfa;
start_label = fde->dw_fde_begin;
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index 312a990..f009834 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -119,6 +119,39 @@ struct GTY(()) dw_fde_node {
};
+/* This represents a register, in DWARF_FRAME_REGNUM space, for use in CFA
+ definitions and expressions.
+ Most architectures only need a single register number, but some (amdgcn)
+ have pointers that span multiple registers. DWARF permits arbitrary
+ register sets but existing use-cases only require contiguous register
+ sets, as represented here. */
+struct GTY(()) cfa_reg {
+ unsigned int reg;
+ unsigned short span;
+ unsigned short span_width; /* A.K.A. register mode size. */
+
+ cfa_reg& set_by_dwreg (unsigned int r)
+ {
+ reg = r;
+ span = 1;
+ span_width = 0; /* Unknown size (permitted when span == 1). */
+ return *this;
+ }
+
+ bool operator== (const cfa_reg &other) const
+ {
+ return (reg == other.reg && span == other.span
+ && (span_width == other.span_width
+ || (span == 1
+ && (span_width == 0 || other.span_width == 0))));
+ }
+
+ bool operator!= (const cfa_reg &other) const
+ {
+ return !(*this == other);
+ }
+};
+
/* This is how we define the location of the CFA. We use to handle it
as REG + OFFSET all the time, but now it can be more complex.
It can now be either REG + CFA_OFFSET or *(REG + BASE_OFFSET) + CFA_OFFSET.
@@ -128,7 +161,7 @@ struct GTY(()) dw_cfa_location {
poly_int64_pod offset;
poly_int64_pod base_offset;
/* REG is in DWARF_FRAME_REGNUM space, *not* normal REGNO space. */
- unsigned int reg;
+ struct cfa_reg reg;
BOOL_BITFIELD indirect : 1; /* 1 if CFA is accessed via a dereference. */
BOOL_BITFIELD in_use : 1; /* 1 if a saved cfa is stored here. */
};
@@ -285,6 +318,7 @@ extern struct dw_loc_descr_node *build_cfa_loc
(dw_cfa_location *, poly_int64);
extern struct dw_loc_descr_node *build_cfa_aligned_loc
(dw_cfa_location *, poly_int64, HOST_WIDE_INT);
+extern struct dw_loc_descr_node *build_span_loc (struct cfa_reg);
extern struct dw_loc_descr_node *mem_loc_descriptor
(rtx, machine_mode mode, machine_mode mem_mode,
enum var_init_status);
diff --git a/gcc/expr.c b/gcc/expr.c
index b281525..0365625 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -3929,7 +3929,7 @@ emit_move_multi_word (machine_mode mode, rtx x, rtx y)
hard regs shouldn't appear here except as return values.
We never want to emit such a clobber after reload. */
if (x != y
- && ! (reload_in_progress || reload_completed)
+ && ! (lra_in_progress || reload_in_progress || reload_completed)
&& need_clobber != 0)
emit_clobber (x);
diff --git a/gcc/file-prefix-map.c b/gcc/file-prefix-map.c
index ad242e5..290b4b2 100644
--- a/gcc/file-prefix-map.c
+++ b/gcc/file-prefix-map.c
@@ -92,6 +92,7 @@ remap_filename (file_prefix_map *maps, const char *filename)
/* Linked lists of file_prefix_map structures. */
static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map */
static file_prefix_map *debug_prefix_maps; /* -fdebug-prefix-map */
+static file_prefix_map *profile_prefix_maps; /* -fprofile-prefix-map */
/* Record a file prefix mapping for -fmacro-prefix-map. */
void
@@ -113,6 +114,14 @@ add_file_prefix_map (const char *arg)
{
add_prefix_map (macro_prefix_maps, arg, "-ffile-prefix-map");
add_prefix_map (debug_prefix_maps, arg, "-ffile-prefix-map");
+ add_prefix_map (profile_prefix_maps, arg, "-ffile-prefix-map");
+}
+
+/* Record a file prefix mapping for -fprofile-prefix-map. */
+void
+add_profile_prefix_map (const char *arg)
+{
+ add_prefix_map (profile_prefix_maps, arg, "-fprofile-prefix-map");
}
/* Remap using -fmacro-prefix-map. Return the GC-allocated new name
@@ -130,3 +139,11 @@ remap_debug_filename (const char *filename)
{
return remap_filename (debug_prefix_maps, filename);
}
+
+/* Remap using -fprofile-prefix-map. Return the GC-allocated new name
+ corresponding to FILENAME or FILENAME if no remapping was performed. */
+const char *
+remap_profile_filename (const char *filename)
+{
+ return remap_filename (profile_prefix_maps, filename);
+}
diff --git a/gcc/file-prefix-map.h b/gcc/file-prefix-map.h
index 5aecd5f..3a2b060 100644
--- a/gcc/file-prefix-map.h
+++ b/gcc/file-prefix-map.h
@@ -21,8 +21,10 @@
void add_macro_prefix_map (const char *);
void add_debug_prefix_map (const char *);
void add_file_prefix_map (const char *);
+void add_profile_prefix_map (const char *);
const char *remap_macro_filename (const char *);
const char *remap_debug_filename (const char *);
+const char *remap_profile_filename (const char *);
#endif /* !GCC_FILE_PREFIX_MAP_H */
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 90d8225..0b9a42f 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -85,8 +85,8 @@ along with GCC; see the file COPYING3. If not see
#include "asan.h"
#include "gimple-range.h"
-/* Nonzero if we are folding constants inside an initializer; zero
- otherwise. */
+/* Nonzero if we are folding constants inside an initializer or a C++
+ manifestly-constant-evaluated context; zero otherwise. */
int folding_initializer = 0;
/* The following constants represent a bit based encoding of GCC's
@@ -9924,8 +9924,15 @@ pointer_may_wrap_p (tree base, tree offset, poly_int64 bitpos)
static int
maybe_nonzero_address (tree decl)
{
+ /* Normally, don't do anything for variables and functions before symtab is
+ built; it is quite possible that DECL will be declared weak later.
+ But if folding_initializer, we need a constant answer now, so create
+ the symtab entry and prevent later weak declaration. */
if (DECL_P (decl) && decl_in_symtab_p (decl))
- if (struct symtab_node *symbol = symtab_node::get_create (decl))
+ if (struct symtab_node *symbol
+ = (folding_initializer
+ ? symtab_node::get_create (decl)
+ : symtab_node::get (decl)))
return symbol->nonzero_address ();
/* Function local objects are never NULL. */
@@ -13991,6 +13998,19 @@ fold_build_call_array_initializer_loc (location_t loc, tree type, tree fn,
return result;
}
+tree
+fold_binary_initializer_loc (location_t loc, tree_code code, tree type,
+ tree lhs, tree rhs)
+{
+ tree result;
+ START_FOLD_INIT;
+
+ result = fold_binary_loc (loc, code, type, lhs, rhs);
+
+ END_FOLD_INIT;
+ return result;
+}
+
#undef START_FOLD_INIT
#undef END_FOLD_INIT
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index 56e9d39..01bfe5d 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -77,6 +77,7 @@ extern tree fold_build_call_array_loc (location_t, tree, tree, int, tree *);
#define fold_build_call_array_initializer(T1,T2,N,T4)\
fold_build_call_array_initializer_loc (UNKNOWN_LOCATION, T1, T2, N, T4)
extern tree fold_build_call_array_initializer_loc (location_t, tree, tree, int, tree *);
+extern tree fold_binary_initializer_loc (location_t, tree_code, tree, tree, tree);
extern tree get_array_ctor_element_at_index (tree, offset_int,
unsigned * = NULL);
extern bool fold_convertible_p (const_tree, const_tree);
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index b6b26b4..c16ff2c 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,77 @@
+2021-12-08 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/103609
+ * symbol.c (gfc_sym_get_dummy_args): Catch NULL pointer
+ dereference.
+
+2021-12-08 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/103610
+ * array.c (spec_dimen_size): Fix simplification of SHAPE:
+ dimensions must be non-negative.
+
+2021-12-08 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * trans-openmp.c (gfc_trans_omp_array_section): Do not generate
+ GOMP_MAP_ALWAYS_POINTER map for main array maps of ARRAY_TYPE type.
+
+2021-12-07 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/103607
+ * frontend-passes.c (do_subscript): Ensure that array bounds are
+ of type INTEGER before performing checks on array subscripts.
+
+2021-12-07 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/103588
+ * array.c (gfc_ref_dimen_size): Do not generate internal error on
+ failed simplification of stride expression; just return failure.
+
+2021-12-07 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/103591
+ * match.c (match_case_selector): Check type of upper bound in case
+ range.
+
+2021-12-04 Tobias Burnus <tobias@codesourcery.com>
+
+ * dump-parse-tree.c (show_omp_clauses): Handle
+ weak/compare/fail clause.
+ * gfortran.h (gfc_omp_clauses): Add weak, compare, fail.
+ * openmp.c (enum omp_mask1, gfc_match_omp_clauses,
+ OMP_ATOMIC_CLAUSES): Update for new clauses.
+ (gfc_match_omp_atomic): Update for 5.1 atomic changes.
+ (is_conversion): Support widening in one go.
+ (is_scalar_intrinsic_expr): New.
+ (resolve_omp_atomic): Update for 5.1 atomic changes.
+ * parse.c (parse_omp_oacc_atomic): Update for compare.
+ * resolve.c (gfc_resolve_blocks): Update asserts.
+ * trans-openmp.c (gfc_trans_omp_atomic): Handle new clauses.
+
+2021-12-03 Harald Anlauf <anlauf@gmx.de>
+ Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/103505
+ * array.c (match_array_element_spec): Try to simplify array
+ element specifications to improve early checking.
+ * expr.c (gfc_try_simplify_expr): New. Try simplification of an
+ expression via gfc_simplify_expr. When an error occurs, roll
+ back.
+ * gfortran.h (gfc_try_simplify_expr): Declare it.
+
+2021-12-03 Tobias Burnus <tobias@codesourcery.com>
+
+ * trans-stmt.c (gfc_trans_allocate): Set e3_has_nodescriptor to true
+ only for non-named arrays.
+
+2021-12-02 Chung-Lin Tang <cltang@codesourcery.com>
+
+ PR fortran/90030
+ * trans-openmp.c (gfc_omp_finish_clause): Remove fold_convert to pointer
+ to char_type_node, add gcc_assert of POINTER_TYPE_P.
+ (gfc_trans_omp_array_section): Likewise.
+ (gfc_trans_omp_clauses): Likewise.
+
2021-11-30 Harald Anlauf <anlauf@gmx.de>
PR fortran/102787
diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c
index fbc6609..e4891df 100644
--- a/gcc/fortran/array.c
+++ b/gcc/fortran/array.c
@@ -492,6 +492,8 @@ match_array_element_spec (gfc_array_spec *as)
if (!gfc_expr_check_typed (*upper, gfc_current_ns, false))
return AS_UNKNOWN;
+ gfc_try_simplify_expr (*upper, 0);
+
if (((*upper)->expr_type == EXPR_CONSTANT
&& (*upper)->ts.type != BT_INTEGER) ||
((*upper)->expr_type == EXPR_FUNCTION
@@ -524,6 +526,8 @@ match_array_element_spec (gfc_array_spec *as)
if (!gfc_expr_check_typed (*upper, gfc_current_ns, false))
return AS_UNKNOWN;
+ gfc_try_simplify_expr (*upper, 0);
+
if (((*upper)->expr_type == EXPR_CONSTANT
&& (*upper)->ts.type != BT_INTEGER) ||
((*upper)->expr_type == EXPR_FUNCTION
@@ -2292,8 +2296,7 @@ gfc_copy_iterator (gfc_iterator *src)
/********* Subroutines for determining the size of an array *********/
/* These are needed just to accommodate RESHAPE(). There are no
- diagnostics here, we just return a negative number if something
- goes wrong. */
+ diagnostics here, we just return false if something goes wrong. */
/* Get the size of single dimension of an array specification. The
@@ -2326,6 +2329,9 @@ spec_dimen_size (gfc_array_spec *as, int dimen, mpz_t *result)
mpz_add_ui (*result, *result, 1);
+ if (mpz_cmp_si (*result, 0) < 0)
+ mpz_set_si (*result, 0);
+
return true;
}
@@ -2399,12 +2405,11 @@ gfc_ref_dimen_size (gfc_array_ref *ar, int dimen, mpz_t *result, mpz_t *end)
{
stride_expr = gfc_copy_expr(ar->stride[dimen]);
- if(!gfc_simplify_expr(stride_expr, 1))
- gfc_internal_error("Simplification error");
-
- if (stride_expr->expr_type != EXPR_CONSTANT
- || mpz_cmp_ui (stride_expr->value.integer, 0) == 0)
+ if (!gfc_simplify_expr (stride_expr, 1)
+ || stride_expr->expr_type != EXPR_CONSTANT
+ || mpz_cmp_ui (stride_expr->value.integer, 0) == 0)
{
+ gfc_free_expr (stride_expr);
mpz_clear (stride);
return false;
}
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 04660d5..2aa44ff 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -1810,6 +1810,10 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
}
fputc (')', dumpfile);
}
+ if (omp_clauses->weak)
+ fputs (" WEAK", dumpfile);
+ if (omp_clauses->compare)
+ fputs (" COMPARE", dumpfile);
if (omp_clauses->nogroup)
fputs (" NOGROUP", dumpfile);
if (omp_clauses->simd)
@@ -1926,6 +1930,20 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
fputc (' ', dumpfile);
fputs (memorder, dumpfile);
}
+ if (omp_clauses->fail != OMP_MEMORDER_UNSET)
+ {
+ const char *memorder;
+ switch (omp_clauses->fail)
+ {
+ case OMP_MEMORDER_ACQUIRE: memorder = "AQUIRE"; break;
+ case OMP_MEMORDER_RELAXED: memorder = "RELAXED"; break;
+ case OMP_MEMORDER_SEQ_CST: memorder = "SEQ_CST"; break;
+ default: gcc_unreachable ();
+ }
+ fputs (" FAIL(", dumpfile);
+ fputs (memorder, dumpfile);
+ putc (')', dumpfile);
+ }
if (omp_clauses->at != OMP_AT_UNSET)
{
if (omp_clauses->at != OMP_AT_COMPILATION)
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 4084d18..8708932 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -2331,6 +2331,31 @@ gfc_simplify_expr (gfc_expr *p, int type)
}
+/* Try simplification of an expression via gfc_simplify_expr.
+ When an error occurs (arithmetic or otherwise), roll back. */
+
+bool
+gfc_try_simplify_expr (gfc_expr *e, int type)
+{
+ gfc_expr *n;
+ bool t, saved_div0;
+
+ if (e == NULL || e->expr_type == EXPR_CONSTANT)
+ return true;
+
+ saved_div0 = gfc_seen_div0;
+ gfc_seen_div0 = false;
+ n = gfc_copy_expr (e);
+ t = gfc_simplify_expr (n, type) && !gfc_seen_div0;
+ if (t)
+ gfc_replace_expr (e, n);
+ else
+ gfc_free_expr (n);
+ gfc_seen_div0 = saved_div0;
+ return t;
+}
+
+
/* Returns the type of an expression with the exception that iterator
variables are automatically integers no matter what else they may
be declared as. */
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c
index 4764c83..57b24a1 100644
--- a/gcc/fortran/frontend-passes.c
+++ b/gcc/fortran/frontend-passes.c
@@ -2914,6 +2914,7 @@ do_subscript (gfc_expr **e)
{
if (ar->as->lower[i]
&& ar->as->lower[i]->expr_type == EXPR_CONSTANT
+ && ar->as->lower[i]->ts.type == BT_INTEGER
&& mpz_cmp (val, ar->as->lower[i]->value.integer) < 0)
gfc_warning (warn, "Array reference at %L out of bounds "
"(%ld < %ld) in loop beginning at %L",
@@ -2923,6 +2924,7 @@ do_subscript (gfc_expr **e)
if (ar->as->upper[i]
&& ar->as->upper[i]->expr_type == EXPR_CONSTANT
+ && ar->as->upper[i]->ts.type == BT_INTEGER
&& mpz_cmp (val, ar->as->upper[i]->value.integer) > 0)
gfc_warning (warn, "Array reference at %L out of bounds "
"(%ld > %ld) in loop beginning at %L",
@@ -2938,6 +2940,7 @@ do_subscript (gfc_expr **e)
{
if (ar->as->lower[i]
&& ar->as->lower[i]->expr_type == EXPR_CONSTANT
+ && ar->as->lower[i]->ts.type == BT_INTEGER
&& mpz_cmp (val, ar->as->lower[i]->value.integer) < 0)
gfc_warning (warn, "Array reference at %L out of bounds "
"(%ld < %ld) in loop beginning at %L",
@@ -2947,6 +2950,7 @@ do_subscript (gfc_expr **e)
if (ar->as->upper[i]
&& ar->as->upper[i]->expr_type == EXPR_CONSTANT
+ && ar->as->upper[i]->ts.type == BT_INTEGER
&& mpz_cmp (val, ar->as->upper[i]->value.integer) > 0)
gfc_warning (warn, "Array reference at %L out of bounds "
"(%ld > %ld) in loop beginning at %L",
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 1846ee4..e5d2dd7 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1529,10 +1529,11 @@ typedef struct gfc_omp_clauses
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, order_reproducible:1, capture:1;
- unsigned grainsize_strict:1, num_tasks_strict:1;
+ unsigned grainsize_strict:1, num_tasks_strict:1, compare:1, weak: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;
+ ENUM_BITFIELD (gfc_omp_memorder) fail:3;
ENUM_BITFIELD (gfc_omp_cancel_kind) cancel:3;
ENUM_BITFIELD (gfc_omp_proc_bind_kind) proc_bind:3;
ENUM_BITFIELD (gfc_omp_depend_op) depobj_update:3;
@@ -3585,6 +3586,7 @@ void gfc_free_ref_list (gfc_ref *);
void gfc_type_convert_binary (gfc_expr *, int);
bool gfc_is_constant_expr (gfc_expr *);
bool gfc_simplify_expr (gfc_expr *, int);
+bool gfc_try_simplify_expr (gfc_expr *, int);
int gfc_has_vector_index (gfc_expr *);
gfc_expr *gfc_get_expr (void);
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index 2bf2143..52bc5af 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -6075,6 +6075,15 @@ match_case_selector (gfc_case **cp)
m = gfc_match_init_expr (&c->high);
if (m == MATCH_ERROR)
goto cleanup;
+ if (m == MATCH_YES
+ && c->high->ts.type != BT_LOGICAL
+ && c->high->ts.type != BT_INTEGER
+ && c->high->ts.type != BT_CHARACTER)
+ {
+ gfc_error ("Expression in CASE selector at %L cannot be %s",
+ &c->high->where, gfc_typename (c->high));
+ goto cleanup;
+ }
/* MATCH_NO is fine. It's OK if nothing is there! */
}
}
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index d120be8..846fd7b 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -917,6 +917,9 @@ enum omp_mask1
OMP_CLAUSE_AT, /* OpenMP 5.1. */
OMP_CLAUSE_MESSAGE, /* OpenMP 5.1. */
OMP_CLAUSE_SEVERITY, /* OpenMP 5.1. */
+ OMP_CLAUSE_COMPARE, /* OpenMP 5.1. */
+ OMP_CLAUSE_FAIL, /* OpenMP 5.1. */
+ OMP_CLAUSE_WEAK, /* OpenMP 5.1. */
OMP_CLAUSE_NOWAIT,
/* This must come last. */
OMP_MASK1_LAST
@@ -1450,7 +1453,8 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
*cp = NULL;
while (1)
{
- if ((first || gfc_match_char (',') != MATCH_YES)
+ match m = MATCH_NO;
+ if ((first || (m = gfc_match_char (',')) != MATCH_YES)
&& (needs_space && gfc_match_space () != MATCH_YES))
break;
needs_space = false;
@@ -1460,7 +1464,11 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
gfc_omp_namelist **head;
old_loc = gfc_current_locus;
char pc = gfc_peek_ascii_char ();
- match m;
+ if (pc == '\n' && m == MATCH_YES)
+ {
+ gfc_error ("Clause expected at %C after trailing comma");
+ goto error;
+ }
switch (pc)
{
case 'a':
@@ -1654,6 +1662,16 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
continue;
}
}
+ if ((mask & OMP_CLAUSE_COMPARE)
+ && (m = gfc_match_dupl_check (!c->compare, "compare"))
+ != MATCH_NO)
+ {
+ if (m == MATCH_ERROR)
+ goto error;
+ c->compare = true;
+ needs_space = true;
+ continue;
+ }
if ((mask & OMP_CLAUSE_COPY)
&& gfc_match ("copy ( ") == MATCH_YES
&& gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
@@ -2009,6 +2027,27 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
}
break;
case 'f':
+ if ((mask & OMP_CLAUSE_FAIL)
+ && (m = gfc_match_dupl_check (c->fail == OMP_MEMORDER_UNSET,
+ "fail", true)) != MATCH_NO)
+ {
+ if (m == MATCH_ERROR)
+ goto error;
+ if (gfc_match ("seq_cst") == MATCH_YES)
+ c->fail = OMP_MEMORDER_SEQ_CST;
+ else if (gfc_match ("acquire") == MATCH_YES)
+ c->fail = OMP_MEMORDER_ACQUIRE;
+ else if (gfc_match ("relaxed") == MATCH_YES)
+ c->fail = OMP_MEMORDER_RELAXED;
+ else
+ {
+ gfc_error ("Expected SEQ_CST, ACQUIRE or RELAXED at %C");
+ break;
+ }
+ if (gfc_match (" )") != MATCH_YES)
+ goto error;
+ continue;
+ }
if ((mask & OMP_CLAUSE_FILTER)
&& (m = gfc_match_dupl_check (!c->filter, "filter", true,
&c->filter)) != MATCH_NO)
@@ -2903,6 +2942,16 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
}
continue;
}
+ if ((mask & OMP_CLAUSE_WEAK)
+ && (m = gfc_match_dupl_check (!c->weak, "weak"))
+ != MATCH_NO)
+ {
+ if (m == MATCH_ERROR)
+ goto error;
+ c->weak = true;
+ needs_space = true;
+ continue;
+ }
if ((mask & OMP_CLAUSE_WORKER)
&& (m = gfc_match_dupl_check (!c->worker, "worker")) != MATCH_NO)
{
@@ -3593,7 +3642,8 @@ cleanup:
(omp_mask (OMP_CLAUSE_TO) | OMP_CLAUSE_LINK | OMP_CLAUSE_DEVICE_TYPE)
#define OMP_ATOMIC_CLAUSES \
(omp_mask (OMP_CLAUSE_ATOMIC) | OMP_CLAUSE_CAPTURE | OMP_CLAUSE_HINT \
- | OMP_CLAUSE_MEMORDER)
+ | OMP_CLAUSE_MEMORDER | OMP_CLAUSE_COMPARE | OMP_CLAUSE_FAIL \
+ | OMP_CLAUSE_WEAK)
#define OMP_MASKED_CLAUSES \
(omp_mask (OMP_CLAUSE_FILTER))
#define OMP_ERROR_CLAUSES \
@@ -5718,6 +5768,7 @@ gfc_match_omp_ordered_depend (void)
- capture
- memory-order-clause: seq_cst | acq_rel | release | acquire | relaxed
- hint(hint-expr)
+ - OpenMP 5.1: compare | fail (seq_cst | acquire | relaxed ) | weak
*/
match
@@ -5729,12 +5780,25 @@ gfc_match_omp_atomic (void)
if (gfc_match_omp_clauses (&c, OMP_ATOMIC_CLAUSES, true, true) != MATCH_YES)
return MATCH_ERROR;
- if (c->capture && c->atomic_op != GFC_OMP_ATOMIC_UNSET)
- gfc_error ("OMP ATOMIC at %L with multiple atomic clauses", &loc);
-
if (c->atomic_op == GFC_OMP_ATOMIC_UNSET)
c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
+ if (c->capture && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
+ gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
+ "READ or WRITE", &loc, "CAPTURE");
+ if (c->compare && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
+ gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
+ "READ or WRITE", &loc, "COMPARE");
+ if (c->fail != OMP_MEMORDER_UNSET && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
+ gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
+ "READ or WRITE", &loc, "FAIL");
+ if (c->weak && !c->compare)
+ {
+ gfc_error ("!$OMP ATOMIC at %L with %s clause requires %s clause", &loc,
+ "WEAK", "COMPARE");
+ c->weak = false;
+ }
+
if (c->memorder == OMP_MEMORDER_UNSET)
{
gfc_namespace *prog_unit = gfc_current_ns;
@@ -5765,32 +5829,24 @@ gfc_match_omp_atomic (void)
switch (c->atomic_op)
{
case GFC_OMP_ATOMIC_READ:
- if (c->memorder == OMP_MEMORDER_ACQ_REL
- || c->memorder == OMP_MEMORDER_RELEASE)
+ if (c->memorder == OMP_MEMORDER_RELEASE)
{
gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
- "ACQ_REL or RELEASE clauses", &loc);
+ "RELEASE clause", &loc);
c->memorder = OMP_MEMORDER_SEQ_CST;
}
+ else if (c->memorder == OMP_MEMORDER_ACQ_REL)
+ c->memorder = OMP_MEMORDER_ACQUIRE;
break;
case GFC_OMP_ATOMIC_WRITE:
- if (c->memorder == OMP_MEMORDER_ACQ_REL
- || c->memorder == OMP_MEMORDER_ACQUIRE)
+ if (c->memorder == OMP_MEMORDER_ACQUIRE)
{
gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
- "ACQ_REL or ACQUIRE clauses", &loc);
- c->memorder = OMP_MEMORDER_SEQ_CST;
- }
- break;
- case GFC_OMP_ATOMIC_UPDATE:
- if ((c->memorder == OMP_MEMORDER_ACQ_REL
- || c->memorder == OMP_MEMORDER_ACQUIRE)
- && !c->capture)
- {
- gfc_error ("!$OMP ATOMIC UPDATE at %L incompatible with "
- "ACQ_REL or ACQUIRE clauses", &loc);
+ "ACQUIRE clause", &loc);
c->memorder = OMP_MEMORDER_SEQ_CST;
}
+ else if (c->memorder == OMP_MEMORDER_ACQ_REL)
+ c->memorder = OMP_MEMORDER_RELEASE;
break;
default:
break;
@@ -7451,20 +7507,24 @@ expr_references_sym (gfc_expr *e, gfc_symbol *s, gfc_expr *se)
/* If EXPR is a conversion function that widens the type
- if WIDENING is true or narrows the type if WIDENING is false,
+ if WIDENING is true or narrows the type if NARROW is true,
return the inner expression, otherwise return NULL. */
static gfc_expr *
-is_conversion (gfc_expr *expr, bool widening)
+is_conversion (gfc_expr *expr, bool narrowing, bool widening)
{
gfc_typespec *ts1, *ts2;
if (expr->expr_type != EXPR_FUNCTION
|| expr->value.function.isym == NULL
|| expr->value.function.esym != NULL
- || expr->value.function.isym->id != GFC_ISYM_CONVERSION)
+ || expr->value.function.isym->id != GFC_ISYM_CONVERSION
+ || (!narrowing && !widening))
return NULL;
+ if (narrowing && widening)
+ return expr->value.function.actual->expr;
+
if (widening)
{
ts1 = &expr->ts;
@@ -7483,163 +7543,297 @@ is_conversion (gfc_expr *expr, bool widening)
return NULL;
}
+static bool
+is_scalar_intrinsic_expr (gfc_expr *expr, bool must_be_var, bool conv_ok)
+{
+ if (must_be_var
+ && (expr->expr_type != EXPR_VARIABLE || !expr->symtree)
+ && (!conv_ok || !is_conversion (expr, true, true)))
+ return false;
+ return (expr->rank == 0
+ && !gfc_is_coindexed (expr)
+ && (expr->ts.type != BT_INTEGER
+ || expr->ts.type != BT_REAL
+ || expr->ts.type != BT_COMPLEX
+ || expr->ts.type != BT_LOGICAL));
+}
static void
resolve_omp_atomic (gfc_code *code)
{
gfc_code *atomic_code = code->block;
gfc_symbol *var;
- gfc_expr *expr2, *expr2_tmp;
+ gfc_expr *stmt_expr2, *capt_expr2;
gfc_omp_atomic_op aop
= (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
& GFC_OMP_ATOMIC_MASK);
+ gfc_code *stmt = NULL, *capture_stmt = NULL;
+ gfc_expr *comp_cond = NULL;
+ locus *loc = NULL;
code = code->block->next;
- /* resolve_blocks asserts this is initially EXEC_ASSIGN.
+ /* resolve_blocks asserts this is initially EXEC_ASSIGN or EXEC_IF
If it changed to EXEC_NOP, assume an error has been emitted already. */
- if (code->op == EXEC_NOP)
+ if (code->op == EXEC_NOP /* FIXME: || (code->next && code->next->op == EXEC_NOP)*/)
return;
- if (code->op != EXEC_ASSIGN)
+
+ if (code->op == EXEC_IF && code->block->op == EXEC_IF)
+ comp_cond = code->block->expr1;
+
+ if (atomic_code->ext.omp_clauses->compare
+ && atomic_code->ext.omp_clauses->capture)
{
- unexpected:
- gfc_error ("unexpected !$OMP ATOMIC expression at %L", &code->loc);
- return;
+ /* Must be either "if (x == e) then; x = d; else; v = x; end if"
+ or "v = expr" followed/preceded by
+ "if (x == e) then; x = d; end if" or "if (x == e) x = d". */
+ gfc_code *next = code;
+ if (code->op == EXEC_ASSIGN)
+ {
+ capture_stmt = code;
+ next = code->next;
+ }
+ if (next->op == EXEC_IF
+ && next->block
+ && next->block->op == EXEC_IF
+ && next->block->next->op == EXEC_ASSIGN)
+ {
+ stmt = next->block->next;
+ if (stmt->next)
+ {
+ loc = &stmt->loc;
+ goto unexpected;
+ }
+ }
+ if (stmt && !capture_stmt && next->block->block)
+ {
+ if (next->block->block->expr1)
+ gfc_error ("Expected ELSE at %L in atomic compare capture",
+ &next->block->block->expr1->where);
+ if (!code->block->block->next
+ || code->block->block->next->op != EXEC_ASSIGN)
+ {
+ loc = (code->block->block->next ? &code->block->block->next->loc
+ : &code->block->block->loc);
+ goto unexpected;
+ }
+ capture_stmt = code->block->block->next;
+ if (capture_stmt->next)
+ {
+ loc = &capture_stmt->next->loc;
+ goto unexpected;
+ }
+ }
+ if (stmt && !capture_stmt && code->op == EXEC_ASSIGN)
+ {
+ capture_stmt = code;
+ }
+ else if (!capture_stmt)
+ {
+ loc = &code->loc;
+ goto unexpected;
+ }
}
- if (!atomic_code->ext.omp_clauses->capture)
+ else if (atomic_code->ext.omp_clauses->compare)
{
- if (code->next != NULL)
+ /* Must be: "if (x == e) then; x = d; end if" or "if (x == e) x = d". */
+ if (code->op == EXEC_IF
+ && code->block
+ && code->block->op == EXEC_IF
+ && code->block->next->op == EXEC_ASSIGN)
+ {
+ stmt = code->block->next;
+ if (stmt->next || code->block->block)
+ {
+ loc = stmt->next ? &stmt->next->loc : &code->block->block->loc;
+ goto unexpected;
+ }
+ }
+ else
+ {
+ loc = &code->loc;
+ goto unexpected;
+ }
+ }
+ else if (atomic_code->ext.omp_clauses->capture)
+ {
+ /* Must be: "v = x" followed/preceded by "x = ...". */
+ if (code->op != EXEC_ASSIGN)
goto unexpected;
+ if (code->next->op != EXEC_ASSIGN)
+ {
+ loc = &code->next->loc;
+ goto unexpected;
+ }
+ gfc_expr *expr2, *expr2_next;
+ expr2 = is_conversion (code->expr2, true, true);
+ if (expr2 == NULL)
+ expr2 = code->expr2;
+ expr2_next = is_conversion (code->next->expr2, true, true);
+ if (expr2_next == NULL)
+ expr2_next = code->next->expr2;
+ if (code->expr1->expr_type == EXPR_VARIABLE
+ && code->next->expr1->expr_type == EXPR_VARIABLE
+ && expr2->expr_type == EXPR_VARIABLE
+ && expr2_next->expr_type == EXPR_VARIABLE)
+ {
+ if (code->expr1->symtree->n.sym == expr2_next->symtree->n.sym)
+ {
+ stmt = code;
+ capture_stmt = code->next;
+ }
+ else
+ {
+ capture_stmt = code;
+ stmt = code->next;
+ }
+ }
+ else if (expr2->expr_type == EXPR_VARIABLE)
+ {
+ capture_stmt = code;
+ stmt = code->next;
+ }
+ else
+ {
+ stmt = code;
+ capture_stmt = code->next;
+ }
+ gcc_assert (!code->next->next);
}
else
{
- if (code->next == NULL)
+ /* x = ... */
+ stmt = code;
+ if ((!atomic_code->ext.omp_clauses->compare && stmt->op != EXEC_ASSIGN)
+ || (atomic_code->ext.omp_clauses->compare && stmt->op != EXEC_IF))
goto unexpected;
- if (code->next->op == EXEC_NOP)
+ gcc_assert (!code->next);
+ }
+
+ if (comp_cond)
+ {
+ if (comp_cond->expr_type != EXPR_OP
+ || (comp_cond->value.op.op != INTRINSIC_EQ
+ && comp_cond->value.op.op != INTRINSIC_EQ_OS
+ && comp_cond->value.op.op != INTRINSIC_EQV))
+ {
+ gfc_error ("Expected %<==%>, %<.EQ.%> or %<.EQV.%> atomic comparison "
+ "expression at %L", &comp_cond->where);
+ return;
+ }
+ if (!is_scalar_intrinsic_expr (comp_cond->value.op.op1, true, false))
+ {
+ gfc_error ("Expected scalar intrinsic variable at %L in atomic "
+ "comparison", &comp_cond->value.op.op1->where);
+ return;
+ }
+ if (!gfc_resolve_expr (comp_cond->value.op.op2))
return;
- if (code->next->op != EXEC_ASSIGN || code->next->next)
+ if (!is_scalar_intrinsic_expr (comp_cond->value.op.op2, false, false))
{
- code = code->next;
- goto unexpected;
+ gfc_error ("Expected scalar intrinsic expression at %L in atomic "
+ "comparison", &comp_cond->value.op.op1->where);
+ return;
}
}
- if (code->expr1->expr_type != EXPR_VARIABLE
- || code->expr1->symtree == NULL
- || code->expr1->rank != 0
- || (code->expr1->ts.type != BT_INTEGER
- && code->expr1->ts.type != BT_REAL
- && code->expr1->ts.type != BT_COMPLEX
- && code->expr1->ts.type != BT_LOGICAL))
+ if (!is_scalar_intrinsic_expr (stmt->expr1, true, false))
{
gfc_error ("!$OMP ATOMIC statement must set a scalar variable of "
- "intrinsic type at %L", &code->loc);
+ "intrinsic type at %L", &stmt->expr1->where);
return;
}
- var = code->expr1->symtree->n.sym;
- expr2 = is_conversion (code->expr2, false);
- if (expr2 == NULL)
+ if (!gfc_resolve_expr (stmt->expr2))
+ return;
+ if (!is_scalar_intrinsic_expr (stmt->expr2, false, false))
{
- if (aop == GFC_OMP_ATOMIC_READ || aop == GFC_OMP_ATOMIC_WRITE)
- expr2 = is_conversion (code->expr2, true);
- if (expr2 == NULL)
- expr2 = code->expr2;
+ gfc_error ("!$OMP ATOMIC statement must assign an expression of "
+ "intrinsic type at %L", &stmt->expr2->where);
+ return;
}
+ if (gfc_expr_attr (stmt->expr1).allocatable)
+ {
+ gfc_error ("!$OMP ATOMIC with ALLOCATABLE variable at %L",
+ &stmt->expr1->where);
+ return;
+ }
+
+ var = stmt->expr1->symtree->n.sym;
+ stmt_expr2 = is_conversion (stmt->expr2, true, true);
+ if (stmt_expr2 == NULL)
+ stmt_expr2 = stmt->expr2;
+
switch (aop)
{
case GFC_OMP_ATOMIC_READ:
- if (expr2->expr_type != EXPR_VARIABLE
- || expr2->symtree == NULL
- || expr2->rank != 0
- || (expr2->ts.type != BT_INTEGER
- && expr2->ts.type != BT_REAL
- && expr2->ts.type != BT_COMPLEX
- && expr2->ts.type != BT_LOGICAL))
+ if (stmt_expr2->expr_type != EXPR_VARIABLE)
gfc_error ("!$OMP ATOMIC READ statement must read from a scalar "
- "variable of intrinsic type at %L", &expr2->where);
+ "variable of intrinsic type at %L", &stmt_expr2->where);
return;
case GFC_OMP_ATOMIC_WRITE:
- if (expr2->rank != 0 || expr_references_sym (code->expr2, var, NULL))
+ if (expr_references_sym (stmt_expr2, var, NULL))
gfc_error ("expr in !$OMP ATOMIC WRITE assignment var = expr "
"must be scalar and cannot reference var at %L",
- &expr2->where);
+ &stmt_expr2->where);
return;
default:
break;
}
+
+ if (atomic_code->ext.omp_clauses->compare
+ && !atomic_code->ext.omp_clauses->capture)
+ {
+ gfc_error ("Sorry, COMPARE clause in ATOMIC at %L is not yet "
+ "supported", &atomic_code->loc);
+ return;
+ }
+
if (atomic_code->ext.omp_clauses->capture)
{
- expr2_tmp = expr2;
- if (expr2 == code->expr2)
+ if (!is_scalar_intrinsic_expr (capture_stmt->expr1, true, false))
{
- expr2_tmp = is_conversion (code->expr2, true);
- if (expr2_tmp == NULL)
- expr2_tmp = expr2;
+ gfc_error ("!$OMP ATOMIC capture-statement must set a scalar "
+ "variable of intrinsic type at %L",
+ &capture_stmt->expr1->where);
+ return;
}
- if (expr2_tmp->expr_type == EXPR_VARIABLE)
+
+ if (!is_scalar_intrinsic_expr (capture_stmt->expr2, true, true))
{
- if (expr2_tmp->symtree == NULL
- || expr2_tmp->rank != 0
- || (expr2_tmp->ts.type != BT_INTEGER
- && expr2_tmp->ts.type != BT_REAL
- && expr2_tmp->ts.type != BT_COMPLEX
- && expr2_tmp->ts.type != BT_LOGICAL)
- || expr2_tmp->symtree->n.sym == var)
- {
- gfc_error ("!$OMP ATOMIC CAPTURE capture statement must read from "
- "a scalar variable of intrinsic type at %L",
- &expr2_tmp->where);
- return;
- }
- var = expr2_tmp->symtree->n.sym;
- code = code->next;
- if (code->expr1->expr_type != EXPR_VARIABLE
- || code->expr1->symtree == NULL
- || code->expr1->rank != 0
- || (code->expr1->ts.type != BT_INTEGER
- && code->expr1->ts.type != BT_REAL
- && code->expr1->ts.type != BT_COMPLEX
- && code->expr1->ts.type != BT_LOGICAL))
- {
- gfc_error ("!$OMP ATOMIC CAPTURE update statement must set "
- "a scalar variable of intrinsic type at %L",
- &code->expr1->where);
- return;
- }
- if (code->expr1->symtree->n.sym != var)
- {
- gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
- "different variable than update statement writes "
- "into at %L", &code->expr1->where);
- return;
- }
- expr2 = is_conversion (code->expr2, false);
- if (expr2 == NULL)
- expr2 = code->expr2;
+ gfc_error ("!$OMP ATOMIC capture-statement requires a scalar variable"
+ " of intrinsic type at %L", &capture_stmt->expr2->where);
+ return;
}
- }
+ capt_expr2 = is_conversion (capture_stmt->expr2, true, true);
+ if (capt_expr2 == NULL)
+ capt_expr2 = capture_stmt->expr2;
- if (gfc_expr_attr (code->expr1).allocatable)
- {
- gfc_error ("!$OMP ATOMIC with ALLOCATABLE variable at %L",
- &code->loc);
- return;
+ if (capt_expr2->symtree->n.sym != var)
+ {
+ gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
+ "different variable than update statement writes "
+ "into at %L", &capture_stmt->expr2->where);
+ return;
+ }
}
if (atomic_code->ext.omp_clauses->capture
- && code->next == NULL
- && code->expr2->rank == 0
- && !expr_references_sym (code->expr2, var, NULL))
+ && !expr_references_sym (stmt_expr2, var, NULL))
atomic_code->ext.omp_clauses->atomic_op
= (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
| GFC_OMP_ATOMIC_SWAP);
- else if (expr2->expr_type == EXPR_OP)
+ else if (stmt_expr2->expr_type == EXPR_OP)
{
gfc_expr *v = NULL, *e, *c;
- gfc_intrinsic_op op = expr2->value.op.op;
+ gfc_intrinsic_op op = stmt_expr2->value.op.op;
gfc_intrinsic_op alt_op = INTRINSIC_NONE;
+ if (atomic_code->ext.omp_clauses->fail != OMP_MEMORDER_UNSET
+ && !atomic_code->ext.omp_clauses->compare)
+ gfc_error ("!$OMP ATOMIC UPDATE at %L with FAIL clause requiries either"
+ " the COMPARE clause or using the intrinsic MIN/MAX "
+ "procedure", &atomic_code->loc);
switch (op)
{
case INTRINSIC_PLUS:
@@ -7666,7 +7860,7 @@ resolve_omp_atomic (gfc_code *code)
default:
gfc_error ("!$OMP ATOMIC assignment operator must be binary "
"+, *, -, /, .AND., .OR., .EQV. or .NEQV. at %L",
- &expr2->where);
+ &stmt_expr2->where);
return;
}
@@ -7676,12 +7870,12 @@ resolve_omp_atomic (gfc_code *code)
(expr) op var. We rely here on the fact that the matcher
for x op1 y op2 z where op1 and op2 have equal precedence
returns (x op1 y) op2 z. */
- e = expr2->value.op.op2;
+ e = stmt_expr2->value.op.op2;
if (e->expr_type == EXPR_VARIABLE
&& e->symtree != NULL
&& e->symtree->n.sym == var)
v = e;
- else if ((c = is_conversion (e, true)) != NULL
+ else if ((c = is_conversion (e, false, true)) != NULL
&& c->expr_type == EXPR_VARIABLE
&& c->symtree != NULL
&& c->symtree->n.sym == var)
@@ -7689,7 +7883,7 @@ resolve_omp_atomic (gfc_code *code)
else
{
gfc_expr **p = NULL, **q;
- for (q = &expr2->value.op.op1; (e = *q) != NULL; )
+ for (q = &stmt_expr2->value.op.op1; (e = *q) != NULL; )
if (e->expr_type == EXPR_VARIABLE
&& e->symtree != NULL
&& e->symtree->n.sym == var)
@@ -7697,7 +7891,7 @@ resolve_omp_atomic (gfc_code *code)
v = e;
break;
}
- else if ((c = is_conversion (e, true)) != NULL)
+ else if ((c = is_conversion (e, false, true)) != NULL)
q = &e->value.function.actual->expr;
else if (e->expr_type != EXPR_OP
|| (e->value.op.op != op
@@ -7713,7 +7907,7 @@ resolve_omp_atomic (gfc_code *code)
if (v == NULL)
{
gfc_error ("!$OMP ATOMIC assignment must be var = var op expr "
- "or var = expr op var at %L", &expr2->where);
+ "or var = expr op var at %L", &stmt_expr2->where);
return;
}
@@ -7728,7 +7922,7 @@ resolve_omp_atomic (gfc_code *code)
case INTRINSIC_NEQV:
gfc_error ("!$OMP ATOMIC var = var op expr not "
"mathematically equivalent to var = var op "
- "(expr) at %L", &expr2->where);
+ "(expr) at %L", &stmt_expr2->where);
break;
default:
break;
@@ -7736,43 +7930,44 @@ resolve_omp_atomic (gfc_code *code)
/* Canonicalize into var = var op (expr). */
*p = e->value.op.op2;
- e->value.op.op2 = expr2;
- e->ts = expr2->ts;
- if (code->expr2 == expr2)
- code->expr2 = expr2 = e;
+ e->value.op.op2 = stmt_expr2;
+ e->ts = stmt_expr2->ts;
+ if (stmt->expr2 == stmt_expr2)
+ stmt->expr2 = stmt_expr2 = e;
else
- code->expr2->value.function.actual->expr = expr2 = e;
+ stmt->expr2->value.function.actual->expr = stmt_expr2 = e;
- if (!gfc_compare_types (&expr2->value.op.op1->ts, &expr2->ts))
+ if (!gfc_compare_types (&stmt_expr2->value.op.op1->ts,
+ &stmt_expr2->ts))
{
- for (p = &expr2->value.op.op1; *p != v;
+ for (p = &stmt_expr2->value.op.op1; *p != v;
p = &(*p)->value.function.actual->expr)
;
*p = NULL;
- gfc_free_expr (expr2->value.op.op1);
- expr2->value.op.op1 = v;
- gfc_convert_type (v, &expr2->ts, 2);
+ gfc_free_expr (stmt_expr2->value.op.op1);
+ stmt_expr2->value.op.op1 = v;
+ gfc_convert_type (v, &stmt_expr2->ts, 2);
}
}
}
- if (e->rank != 0 || expr_references_sym (code->expr2, var, v))
+ if (e->rank != 0 || expr_references_sym (stmt->expr2, var, v))
{
gfc_error ("expr in !$OMP ATOMIC assignment var = var op expr "
"must be scalar and cannot reference var at %L",
- &expr2->where);
+ &stmt_expr2->where);
return;
}
}
- else if (expr2->expr_type == EXPR_FUNCTION
- && expr2->value.function.isym != NULL
- && expr2->value.function.esym == NULL
- && expr2->value.function.actual != NULL
- && expr2->value.function.actual->next != NULL)
+ else if (stmt_expr2->expr_type == EXPR_FUNCTION
+ && stmt_expr2->value.function.isym != NULL
+ && stmt_expr2->value.function.esym == NULL
+ && stmt_expr2->value.function.actual != NULL
+ && stmt_expr2->value.function.actual->next != NULL)
{
gfc_actual_arglist *arg, *var_arg;
- switch (expr2->value.function.isym->id)
+ switch (stmt_expr2->value.function.isym->id)
{
case GFC_ISYM_MIN:
case GFC_ISYM_MAX:
@@ -7780,31 +7975,37 @@ resolve_omp_atomic (gfc_code *code)
case GFC_ISYM_IAND:
case GFC_ISYM_IOR:
case GFC_ISYM_IEOR:
- if (expr2->value.function.actual->next->next != NULL)
+ if (stmt_expr2->value.function.actual->next->next != NULL)
{
gfc_error ("!$OMP ATOMIC assignment intrinsic IAND, IOR "
"or IEOR must have two arguments at %L",
- &expr2->where);
+ &stmt_expr2->where);
return;
}
break;
default:
gfc_error ("!$OMP ATOMIC assignment intrinsic must be "
"MIN, MAX, IAND, IOR or IEOR at %L",
- &expr2->where);
+ &stmt_expr2->where);
return;
}
var_arg = NULL;
- for (arg = expr2->value.function.actual; arg; arg = arg->next)
- {
- if ((arg == expr2->value.function.actual
- || (var_arg == NULL && arg->next == NULL))
- && arg->expr->expr_type == EXPR_VARIABLE
- && arg->expr->symtree != NULL
- && arg->expr->symtree->n.sym == var)
- var_arg = arg;
- else if (expr_references_sym (arg->expr, var, NULL))
+ for (arg = stmt_expr2->value.function.actual; arg; arg = arg->next)
+ {
+ gfc_expr *e = NULL;
+ if (arg == stmt_expr2->value.function.actual
+ || (var_arg == NULL && arg->next == NULL))
+ {
+ e = is_conversion (arg->expr, false, true);
+ if (!e)
+ e = arg->expr;
+ if (e->expr_type == EXPR_VARIABLE
+ && e->symtree != NULL
+ && e->symtree->n.sym == var)
+ var_arg = arg;
+ }
+ if ((!var_arg || !e) && expr_references_sym (arg->expr, var, NULL))
{
gfc_error ("!$OMP ATOMIC intrinsic arguments except one must "
"not reference %qs at %L",
@@ -7822,72 +8023,35 @@ resolve_omp_atomic (gfc_code *code)
if (var_arg == NULL)
{
gfc_error ("First or last !$OMP ATOMIC intrinsic argument must "
- "be %qs at %L", var->name, &expr2->where);
+ "be %qs at %L", var->name, &stmt_expr2->where);
return;
}
- if (var_arg != expr2->value.function.actual)
+ if (var_arg != stmt_expr2->value.function.actual)
{
/* Canonicalize, so that var comes first. */
gcc_assert (var_arg->next == NULL);
- for (arg = expr2->value.function.actual;
+ for (arg = stmt_expr2->value.function.actual;
arg->next != var_arg; arg = arg->next)
;
- var_arg->next = expr2->value.function.actual;
- expr2->value.function.actual = var_arg;
+ var_arg->next = stmt_expr2->value.function.actual;
+ stmt_expr2->value.function.actual = var_arg;
arg->next = NULL;
}
}
else
gfc_error ("!$OMP ATOMIC assignment must have an operator or "
- "intrinsic on right hand side at %L", &expr2->where);
-
- if (atomic_code->ext.omp_clauses->capture && code->next)
- {
- code = code->next;
- if (code->expr1->expr_type != EXPR_VARIABLE
- || code->expr1->symtree == NULL
- || code->expr1->rank != 0
- || (code->expr1->ts.type != BT_INTEGER
- && code->expr1->ts.type != BT_REAL
- && code->expr1->ts.type != BT_COMPLEX
- && code->expr1->ts.type != BT_LOGICAL))
- {
- gfc_error ("!$OMP ATOMIC CAPTURE capture statement must set "
- "a scalar variable of intrinsic type at %L",
- &code->expr1->where);
- return;
- }
+ "intrinsic on right hand side at %L", &stmt_expr2->where);
- expr2 = is_conversion (code->expr2, false);
- if (expr2 == NULL)
- {
- expr2 = is_conversion (code->expr2, true);
- if (expr2 == NULL)
- expr2 = code->expr2;
- }
+ if (atomic_code->ext.omp_clauses->compare)
+ gfc_error ("Sorry, COMPARE clause in ATOMIC at %L is not yet "
+ "supported", &atomic_code->loc);
+ return;
- if (expr2->expr_type != EXPR_VARIABLE
- || expr2->symtree == NULL
- || expr2->rank != 0
- || (expr2->ts.type != BT_INTEGER
- && expr2->ts.type != BT_REAL
- && expr2->ts.type != BT_COMPLEX
- && expr2->ts.type != BT_LOGICAL))
- {
- gfc_error ("!$OMP ATOMIC CAPTURE capture statement must read "
- "from a scalar variable of intrinsic type at %L",
- &expr2->where);
- return;
- }
- if (expr2->symtree->n.sym != var)
- {
- gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
- "different variable than update statement writes "
- "into at %L", &expr2->where);
- return;
- }
- }
+unexpected:
+ gfc_error ("unexpected !$OMP ATOMIC expression at %L",
+ loc ? loc : &code->loc);
+ return;
}
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 94b677f..1f11109 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -5313,7 +5313,22 @@ parse_omp_oacc_atomic (bool omp_p)
st = next_statement ();
if (st == ST_NONE)
unexpected_eof ();
- else if (st == ST_ASSIGNMENT)
+ else if (np->ext.omp_clauses->compare
+ && (st == ST_SIMPLE_IF || st == ST_IF_BLOCK))
+ {
+ count--;
+ if (st == ST_IF_BLOCK)
+ {
+ parse_if_block ();
+ /* With else (or elseif). */
+ if (gfc_state_stack->tail->block->block)
+ count--;
+ }
+ accept_statement (st);
+ }
+ else if (st == ST_ASSIGNMENT
+ && (!np->ext.omp_clauses->compare
+ || np->ext.omp_clauses->capture))
{
accept_statement (st);
count--;
@@ -5332,8 +5347,6 @@ parse_omp_oacc_atomic (bool omp_p)
gfc_warning_check ();
st = next_statement ();
}
- else if (np->ext.omp_clauses->capture)
- gfc_error ("Missing !$OMP END ATOMIC after !$OMP ATOMIC CAPTURE at %C");
return st;
}
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index f074a0a..0ed3197 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -10849,13 +10849,8 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns)
{
/* Verify this before calling gfc_resolve_code, which might
change it. */
- gcc_assert (b->next && b->next->op == EXEC_ASSIGN);
- gcc_assert ((!b->ext.omp_clauses->capture
- && b->next->next == NULL)
- || (b->ext.omp_clauses->capture
- && b->next->next != NULL
- && b->next->next->op == EXEC_ASSIGN
- && b->next->next->next == NULL));
+ gcc_assert (b->op == EXEC_OMP_ATOMIC
+ || (b->next && b->next->op == EXEC_ASSIGN));
}
break;
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index 179f602..ebd9984 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -5240,6 +5240,9 @@ gfc_sym_get_dummy_args (gfc_symbol *sym)
{
gfc_formal_arglist *dummies;
+ if (sym == NULL)
+ return NULL;
+
dummies = sym->formal;
if (dummies == NULL && sym->ts.interface != NULL)
dummies = sym->ts.interface->formal;
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 5b3c310..d8229a5 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -1564,7 +1564,7 @@ gfc_omp_finish_clause (tree c, gimple_seq *pre_p, bool openacc)
if (present)
ptr = gfc_build_cond_assign_expr (&block, present, ptr,
null_pointer_node);
- ptr = fold_convert (build_pointer_type (char_type_node), ptr);
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
ptr = build_fold_indirect_ref (ptr);
OMP_CLAUSE_DECL (c) = ptr;
c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
@@ -2381,7 +2381,7 @@ gfc_trans_omp_array_section (stmtblock_t *block, gfc_omp_namelist *n,
OMP_CLAUSE_SIZE (node), elemsz);
}
gcc_assert (se.post.head == NULL_TREE);
- ptr = fold_convert (build_pointer_type (char_type_node), ptr);
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
ptr = fold_convert (ptrdiff_type_node, ptr);
@@ -2460,6 +2460,9 @@ gfc_trans_omp_array_section (stmtblock_t *block, gfc_omp_namelist *n,
TREE_TYPE (TREE_TYPE (decl)),
decl, offset, NULL_TREE, NULL_TREE);
OMP_CLAUSE_DECL (node) = offset;
+
+ if (ptr_kind == GOMP_MAP_ALWAYS_POINTER)
+ return;
}
else
{
@@ -2849,8 +2852,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
{
decl = gfc_conv_descriptor_data_get (decl);
- decl = fold_convert (build_pointer_type (char_type_node),
- decl);
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
decl = build_fold_indirect_ref (decl);
}
else if (DECL_P (decl))
@@ -2873,8 +2875,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
}
gfc_add_block_to_block (&iter_block, &se.pre);
gfc_add_block_to_block (&iter_block, &se.post);
- ptr = fold_convert (build_pointer_type (char_type_node),
- ptr);
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
}
if (list == OMP_LIST_DEPEND)
@@ -3117,8 +3118,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
if (present)
ptr = gfc_build_cond_assign_expr (block, present, ptr,
null_pointer_node);
- ptr = fold_convert (build_pointer_type (char_type_node),
- ptr);
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
ptr = build_fold_indirect_ref (ptr);
OMP_CLAUSE_DECL (node) = ptr;
node2 = build_omp_clause (input_location,
@@ -3555,8 +3555,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
{
tree type = TREE_TYPE (decl);
tree ptr = gfc_conv_descriptor_data_get (decl);
- ptr = fold_convert (build_pointer_type (char_type_node),
- ptr);
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
ptr = build_fold_indirect_ref (ptr);
OMP_CLAUSE_DECL (node) = ptr;
OMP_CLAUSE_SIZE (node)
@@ -3606,8 +3605,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
OMP_CLAUSE_SIZE (node), elemsz);
}
gfc_add_block_to_block (block, &se.post);
- ptr = fold_convert (build_pointer_type (char_type_node),
- ptr);
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
}
omp_clauses = gfc_trans_add_clause (node, omp_clauses);
@@ -4497,7 +4495,7 @@ gfc_trans_omp_atomic (gfc_code *code)
enum tree_code op = ERROR_MARK;
enum tree_code aop = OMP_ATOMIC;
bool var_on_left = false;
- enum omp_memory_order mo;
+ enum omp_memory_order mo, fail_mo;
switch (atomic_code->ext.omp_clauses->memorder)
{
case OMP_MEMORDER_UNSET: mo = OMP_MEMORY_ORDER_UNSPECIFIED; break;
@@ -4508,6 +4506,15 @@ gfc_trans_omp_atomic (gfc_code *code)
case OMP_MEMORDER_SEQ_CST: mo = OMP_MEMORY_ORDER_SEQ_CST; break;
default: gcc_unreachable ();
}
+ switch (atomic_code->ext.omp_clauses->fail)
+ {
+ case OMP_MEMORDER_UNSET: fail_mo = OMP_FAIL_MEMORY_ORDER_UNSPECIFIED; break;
+ case OMP_MEMORDER_ACQUIRE: fail_mo = OMP_FAIL_MEMORY_ORDER_ACQUIRE; break;
+ case OMP_MEMORDER_RELAXED: fail_mo = OMP_FAIL_MEMORY_ORDER_RELAXED; break;
+ case OMP_MEMORDER_SEQ_CST: fail_mo = OMP_FAIL_MEMORY_ORDER_SEQ_CST; break;
+ default: gcc_unreachable ();
+ }
+ mo = (omp_memory_order) (mo | fail_mo);
code = code->block->next;
gcc_assert (code->op == EXEC_ASSIGN);
@@ -4738,6 +4745,7 @@ gfc_trans_omp_atomic (gfc_code *code)
{
x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
OMP_ATOMIC_MEMORY_ORDER (x) = mo;
+ OMP_ATOMIC_WEAK (x) = atomic_code->ext.omp_clauses->weak;
gfc_add_expr_to_block (&block, x);
}
else
@@ -4761,6 +4769,7 @@ gfc_trans_omp_atomic (gfc_code *code)
}
x = build2 (aop, type, lhsaddr, convert (type, x));
OMP_ATOMIC_MEMORY_ORDER (x) = mo;
+ OMP_ATOMIC_WEAK (x) = atomic_code->ext.omp_clauses->weak;
x = convert (TREE_TYPE (vse.expr), x);
gfc_add_modify (&block, vse.expr, x);
}
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 1fc6d3a..6b27b14 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -6638,16 +6638,13 @@ gfc_trans_allocate (gfc_code * code)
else
e3rhs = gfc_copy_expr (code->expr3);
- // We need to propagate the bounds of the expr3 for source=/mold=;
- // however, for nondescriptor arrays, we use internally a lower bound
- // of zero instead of one, which needs to be corrected for the allocate obj
- if (e3_is == E3_DESC)
- {
- symbol_attribute attr = gfc_expr_attr (code->expr3);
- if (code->expr3->expr_type == EXPR_ARRAY ||
- (!attr.allocatable && !attr.pointer))
- e3_has_nodescriptor = true;
- }
+ // We need to propagate the bounds of the expr3 for source=/mold=.
+ // However, for non-named arrays, the lbound has to be 1 and neither the
+ // bound used inside the called function even when returning an
+ // allocatable/pointer nor the zero used internally.
+ if (e3_is == E3_DESC
+ && code->expr3->expr_type != EXPR_VARIABLE)
+ e3_has_nodescriptor = true;
}
/* Loop over all objects to allocate. */
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 6ff2278..694c257 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -4576,10 +4576,12 @@ driver_handle_option (struct gcc_options *opts,
case OPT_static_libgcc:
case OPT_shared_libgcc:
case OPT_static_libgfortran:
+ case OPT_static_libphobos:
case OPT_static_libstdc__:
/* These are always valid, since gcc.c itself understands the
- first two, gfortranspec.c understands -static-libgfortran and
- g++spec.c understands -static-libstdc++ */
+ first two, gfortranspec.c understands -static-libgfortran,
+ d-spec.cc understands -static-libphobos, and g++spec.c
+ understands -static-libstdc++ */
validated = true;
break;
diff --git a/gcc/gengtype-state.c b/gcc/gengtype-state.c
index ac9d536..36a96e8 100644
--- a/gcc/gengtype-state.c
+++ b/gcc/gengtype-state.c
@@ -57,6 +57,7 @@ type_lineloc (const_type_p ty)
case TYPE_STRING:
case TYPE_POINTER:
case TYPE_ARRAY:
+ case TYPE_CALLBACK:
return NULL;
default:
gcc_unreachable ();
@@ -171,6 +172,7 @@ private:
void write_state_version (const char *version);
void write_state_scalar_type (type_p current);
void write_state_string_type (type_p current);
+ void write_state_callback_type (type_p current);
void write_state_undefined_type (type_p current);
void write_state_struct_union_type (type_p current, const char *kindstr);
void write_state_struct_type (type_p current);
@@ -898,6 +900,20 @@ state_writer::write_state_string_type (type_p current)
fatal ("Unexpected type in write_state_string_type");
}
+/* Write the callback type. There is only one such thing! */
+void
+state_writer::write_state_callback_type (type_p current)
+{
+ if (current == &callback_type)
+ {
+ write_any_indent (0);
+ fprintf (state_file, "callback ");
+ write_state_common_type_content (current);
+ }
+ else
+ fatal ("Unexpected type in write_state_callback_type");
+}
+
/* Write an undefined type. */
void
state_writer::write_state_undefined_type (type_p current)
@@ -1143,6 +1159,9 @@ state_writer::write_state_type (type_p current)
case TYPE_STRING:
write_state_string_type (current);
break;
+ case TYPE_CALLBACK:
+ write_state_callback_type (current);
+ break;
}
}
@@ -1477,6 +1496,14 @@ read_state_string_type (type_p *type)
read_state_common_type_content (*type);
}
+/* Read the callback_type. */
+static void
+read_state_callback_type (type_p *type)
+{
+ *type = &callback_type;
+ read_state_common_type_content (*type);
+}
+
/* Read a lang_bitmap representing a set of GCC front-end languages. */
static void
@@ -1834,6 +1861,11 @@ read_state_type (type_p *current)
next_state_tokens (1);
read_state_string_type (current);
}
+ else if (state_token_is_name (t0, "callback"))
+ {
+ next_state_tokens (1);
+ read_state_callback_type (current);
+ }
else if (state_token_is_name (t0, "undefined"))
{
*current = XCNEW (struct type);
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index a77cfd9..b9daaa4 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -172,6 +172,7 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t)
int nb_struct = 0, nb_union = 0, nb_array = 0, nb_pointer = 0;
int nb_lang_struct = 0;
int nb_user_struct = 0, nb_undefined = 0;
+ int nb_callback = 0;
type_p p = NULL;
for (p = t; p; p = p->next)
{
@@ -202,6 +203,9 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t)
case TYPE_ARRAY:
nb_array++;
break;
+ case TYPE_CALLBACK:
+ nb_callback++;
+ break;
case TYPE_LANG_STRUCT:
nb_lang_struct++;
break;
@@ -217,6 +221,8 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t)
fprintf (stderr, "@@%%@@ %d structs, %d unions\n", nb_struct, nb_union);
if (nb_pointer > 0 || nb_array > 0)
fprintf (stderr, "@@%%@@ %d pointers, %d arrays\n", nb_pointer, nb_array);
+ if (nb_callback > 0)
+ fprintf (stderr, "@@%%@@ %d callbacks\n", nb_callback);
if (nb_lang_struct > 0)
fprintf (stderr, "@@%%@@ %d lang_structs\n", nb_lang_struct);
if (nb_user_struct > 0)
@@ -495,6 +501,10 @@ struct type scalar_char = {
TYPE_SCALAR, 0, 0, 0, GC_USED, {0}
};
+struct type callback_type = {
+ TYPE_CALLBACK, 0, 0, 0, GC_USED, {0}
+};
+
/* Lists of various things. */
pair_p typedefs = NULL;
@@ -1464,7 +1474,7 @@ static void set_gc_used (pair_p);
static void
process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef,
- int *length, int *skip, type_p *nested_ptr)
+ int *length, int *skip, int *callback, type_p *nested_ptr)
{
options_p o;
for (o = opt; o; o = o->next)
@@ -1478,6 +1488,8 @@ process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef,
*length = 1;
else if (strcmp (o->name, "skip") == 0)
*skip = 1;
+ else if (strcmp (o->name, "callback") == 0)
+ *callback = 1;
else if (strcmp (o->name, "nested_ptr") == 0
&& o->kind == OPTION_NESTED)
*nested_ptr = ((const struct nested_ptr_data *) o->info.nested)->type;
@@ -1526,7 +1538,7 @@ set_gc_used_type (type_p t, enum gc_used_enum level,
type_p dummy2;
bool allow_undefined_field_types = (t->kind == TYPE_USER_STRUCT);
- process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy,
+ process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy, &dummy,
&dummy2);
if (t->u.s.base_class)
@@ -1542,9 +1554,10 @@ set_gc_used_type (type_p t, enum gc_used_enum level,
int maybe_undef = 0;
int length = 0;
int skip = 0;
+ int callback = 0;
type_p nested_ptr = NULL;
process_gc_options (f->opt, level, &maybe_undef, &length, &skip,
- &nested_ptr);
+ &callback, &nested_ptr);
if (nested_ptr && f->type->kind == TYPE_POINTER)
set_gc_used_type (nested_ptr, GC_POINTED_TO);
@@ -1554,6 +1567,8 @@ set_gc_used_type (type_p t, enum gc_used_enum level,
set_gc_used_type (f->type->u.p, GC_MAYBE_POINTED_TO);
else if (skip)
; /* target type is not used through this field */
+ else if (callback)
+ f->type = &callback_type;
else
set_gc_used_type (f->type, GC_USED, allow_undefined_field_types);
}
@@ -2519,6 +2534,7 @@ output_mangled_typename (outf_p of, const_type_p t)
{
case TYPE_NONE:
case TYPE_UNDEFINED:
+ case TYPE_CALLBACK:
gcc_unreachable ();
break;
case TYPE_POINTER:
@@ -2719,6 +2735,8 @@ walk_type (type_p t, struct walk_type_data *d)
;
else if (strcmp (oo->name, "for_user") == 0)
;
+ else if (strcmp (oo->name, "callback") == 0)
+ ;
else
error_at_line (d->line, "unknown option `%s'\n", oo->name);
@@ -2744,6 +2762,7 @@ walk_type (type_p t, struct walk_type_data *d)
{
case TYPE_SCALAR:
case TYPE_STRING:
+ case TYPE_CALLBACK:
d->process_field (t, d);
break;
@@ -3275,6 +3294,7 @@ write_types_process_field (type_p f, const struct walk_type_data *d)
break;
case TYPE_SCALAR:
+ case TYPE_CALLBACK:
break;
case TYPE_ARRAY:
@@ -3820,6 +3840,7 @@ write_types_local_user_process_field (type_p f, const struct walk_type_data *d)
break;
case TYPE_SCALAR:
+ case TYPE_CALLBACK:
break;
case TYPE_ARRAY:
@@ -3906,6 +3927,13 @@ write_types_local_process_field (type_p f, const struct walk_type_data *d)
case TYPE_SCALAR:
break;
+ case TYPE_CALLBACK:
+ oprintf (d->of, "%*sif ((void *)(%s) == this_obj)\n", d->indent, "",
+ d->prev_val[3]);
+ oprintf (d->of, "%*s gt_pch_note_callback (&(%s), this_obj);\n",
+ d->indent, "", d->val);
+ break;
+
case TYPE_ARRAY:
case TYPE_NONE:
case TYPE_UNDEFINED:
@@ -4434,6 +4462,7 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
case TYPE_UNDEFINED:
case TYPE_UNION:
case TYPE_LANG_STRUCT:
+ case TYPE_CALLBACK:
error_at_line (line, "global `%s' is unimplemented type", name);
}
}
@@ -4728,6 +4757,9 @@ dump_typekind (int indent, enum typekind kind)
case TYPE_ARRAY:
printf ("TYPE_ARRAY");
break;
+ case TYPE_CALLBACK:
+ printf ("TYPE_CALLBACK");
+ break;
case TYPE_LANG_STRUCT:
printf ("TYPE_LANG_STRUCT");
break;
@@ -4894,6 +4926,7 @@ dump_type (int indent, type_p t)
t->u.scalar_is_char ? "true" : "false");
break;
case TYPE_STRING:
+ case TYPE_CALLBACK:
break;
case TYPE_STRUCT:
case TYPE_UNION:
diff --git a/gcc/gengtype.h b/gcc/gengtype.h
index 8a7a549..8fa7064 100644
--- a/gcc/gengtype.h
+++ b/gcc/gengtype.h
@@ -154,6 +154,9 @@ enum typekind {
TYPE_UNION, /* Type for GTY-ed discriminated unions. */
TYPE_POINTER, /* Pointer type to GTY-ed type. */
TYPE_ARRAY, /* Array of GTY-ed types. */
+ TYPE_CALLBACK, /* A function pointer that needs relocation if
+ the executable has been loaded at a different
+ address. */
TYPE_LANG_STRUCT, /* GCC front-end language specific structs.
Various languages may have homonymous but
different structs. */
@@ -331,6 +334,9 @@ extern struct type string_type;
extern struct type scalar_nonchar;
extern struct type scalar_char;
+/* The one and only TYPE_CALLBACK. */
+extern struct type callback_type;
+
/* Test if a type is a union, either a plain one or a language
specific one. */
#define UNION_P(x) \
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index b6abed1..7c998e9 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -246,6 +246,7 @@ saving_hasher::equal (const ptr_data *p1, const void *p2)
}
static hash_table<saving_hasher> *saving_htab;
+static vec<void *> callback_vec;
/* Register an object in the hash table. */
@@ -278,6 +279,23 @@ gt_pch_note_object (void *obj, void *note_ptr_cookie,
return 1;
}
+/* Register address of a callback pointer. */
+void
+gt_pch_note_callback (void *obj, void *base)
+{
+ void *ptr;
+ memcpy (&ptr, obj, sizeof (void *));
+ if (ptr != NULL)
+ {
+ struct ptr_data *data
+ = (struct ptr_data *)
+ saving_htab->find_with_hash (base, POINTER_HASH (base));
+ gcc_assert (data);
+ callback_vec.safe_push ((char *) data->new_addr
+ + ((char *) obj - (char *) base));
+ }
+}
+
/* Register an object in the hash table. */
void
@@ -576,10 +594,20 @@ gt_pch_save (FILE *f)
ggc_pch_finish (state.d, state.f);
gt_pch_fixup_stringpool ();
+ unsigned num_callbacks = callback_vec.length ();
+ void (*pch_save) (FILE *) = &gt_pch_save;
+ if (fwrite (&pch_save, sizeof (pch_save), 1, f) != 1
+ || fwrite (&num_callbacks, sizeof (num_callbacks), 1, f) != 1
+ || (num_callbacks
+ && fwrite (callback_vec.address (), sizeof (void *), num_callbacks,
+ f) != num_callbacks))
+ fatal_error (input_location, "cannot write PCH file: %m");
+
XDELETE (state.ptrs);
XDELETE (this_object);
delete saving_htab;
saving_htab = NULL;
+ callback_vec.release ();
}
/* Read the state of the compiler back in from F. */
@@ -661,6 +689,30 @@ gt_pch_restore (FILE *f)
gt_pch_restore_stringpool ();
+ void (*pch_save) (FILE *);
+ unsigned num_callbacks;
+ if (fread (&pch_save, sizeof (pch_save), 1, f) != 1
+ || fread (&num_callbacks, sizeof (num_callbacks), 1, f) != 1)
+ fatal_error (input_location, "cannot read PCH file: %m");
+ if (pch_save != &gt_pch_save)
+ {
+ uintptr_t bias = (uintptr_t) &gt_pch_save - (uintptr_t) pch_save;
+ void **ptrs = XNEWVEC (void *, num_callbacks);
+ unsigned i;
+
+ if (fread (ptrs, sizeof (void *), num_callbacks, f) != num_callbacks)
+ fatal_error (input_location, "cannot read PCH file: %m");
+ for (i = 0; i < num_callbacks; ++i)
+ {
+ memcpy (&pch_save, ptrs[i], sizeof (pch_save));
+ pch_save = (void (*) (FILE *)) ((uintptr_t) pch_save + bias);
+ memcpy (ptrs[i], &pch_save, sizeof (pch_save));
+ }
+ XDELETE (ptrs);
+ }
+ else if (fseek (f, num_callbacks * sizeof (void *), SEEK_CUR) != 0)
+ fatal_error (input_location, "cannot read PCH file: %m");
+
/* Barring corruption of the PCH file, the restored line table should be
complete and usable. */
line_table = new_line_table;
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 5e921d9..c005f7e 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -46,6 +46,10 @@ typedef void (*gt_handle_reorder) (void *, void *, gt_pointer_operator,
/* Used by the gt_pch_n_* routines. Register an object in the hash table. */
extern int gt_pch_note_object (void *, void *, gt_note_pointers);
+/* Used by the gt_pch_p_* routines. Register address of a callback
+ pointer. */
+extern void gt_pch_note_callback (void *, void *);
+
/* Used by the gt_pch_n_* routines. Register that an object has a reorder
function. */
extern void gt_pch_note_reorder (void *, void *, gt_handle_reorder);
diff --git a/gcc/gimple-harden-conditionals.cc b/gcc/gimple-harden-conditionals.cc
index cfa2361..5e709c6 100644
--- a/gcc/gimple-harden-conditionals.cc
+++ b/gcc/gimple-harden-conditionals.cc
@@ -22,6 +22,8 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "backend.h"
+#include "target.h"
+#include "rtl.h"
#include "tree.h"
#include "fold-const.h"
#include "gimple.h"
@@ -33,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "cfghooks.h"
#include "cfgloop.h"
+#include "tree-eh.h"
#include "diagnostic.h"
#include "intl.h"
@@ -132,25 +135,78 @@ detach_value (location_t loc, gimple_stmt_iterator *gsip, tree val)
tree ret = make_ssa_name (TREE_TYPE (val));
SET_SSA_NAME_VAR_OR_IDENTIFIER (ret, SSA_NAME_IDENTIFIER (val));
- /* Output asm ("" : "=g" (ret) : "0" (val)); */
+ /* Some modes won't fit in general regs, so we fall back to memory
+ for them. ??? It would be ideal to try to identify an alternate,
+ wider or more suitable register class, and use the corresponding
+ constraint, but there's no logic to go from register class to
+ constraint, even if there is a corresponding constraint, and even
+ if we could enumerate constraints, we can't get to their string
+ either. So this will do for now. */
+ bool need_memory = true;
+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (val));
+ if (mode != BLKmode)
+ for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], i)
+ && targetm.hard_regno_mode_ok (i, mode))
+ {
+ need_memory = false;
+ break;
+ }
+
+ tree asminput = val;
+ tree asmoutput = ret;
+ const char *constraint_out = need_memory ? "=m" : "=g";
+ const char *constraint_in = need_memory ? "m" : "0";
+
+ if (need_memory)
+ {
+ tree temp = create_tmp_var (TREE_TYPE (val), "dtch");
+ mark_addressable (temp);
+
+ gassign *copyin = gimple_build_assign (temp, asminput);
+ gimple_set_location (copyin, loc);
+ gsi_insert_before (gsip, copyin, GSI_SAME_STMT);
+
+ asminput = asmoutput = temp;
+ }
+
+ /* Output an asm statement with matching input and output. It does
+ nothing, but after it the compiler no longer knows the output
+ still holds the same value as the input. */
vec<tree, va_gc> *inputs = NULL;
vec<tree, va_gc> *outputs = NULL;
vec_safe_push (outputs,
build_tree_list
(build_tree_list
- (NULL_TREE, build_string (2, "=g")),
- ret));
+ (NULL_TREE, build_string (strlen (constraint_out),
+ constraint_out)),
+ asmoutput));
vec_safe_push (inputs,
build_tree_list
(build_tree_list
- (NULL_TREE, build_string (1, "0")),
- val));
+ (NULL_TREE, build_string (strlen (constraint_in),
+ constraint_in)),
+ asminput));
gasm *detach = gimple_build_asm_vec ("", inputs, outputs,
NULL, NULL);
gimple_set_location (detach, loc);
gsi_insert_before (gsip, detach, GSI_SAME_STMT);
- SSA_NAME_DEF_STMT (ret) = detach;
+ if (need_memory)
+ {
+ gassign *copyout = gimple_build_assign (ret, asmoutput);
+ gimple_set_location (copyout, loc);
+ gsi_insert_before (gsip, copyout, GSI_SAME_STMT);
+ SSA_NAME_DEF_STMT (ret) = copyout;
+
+ gassign *clobber = gimple_build_assign (asmoutput,
+ build_clobber
+ (TREE_TYPE (asmoutput)));
+ gimple_set_location (clobber, loc);
+ gsi_insert_before (gsip, clobber, GSI_SAME_STMT);
+ }
+ else
+ SSA_NAME_DEF_STMT (ret) = detach;
return ret;
}
@@ -304,6 +360,24 @@ make_pass_harden_conditional_branches (gcc::context *ctxt)
return new pass_harden_conditional_branches (ctxt);
}
+/* Return the fallthru edge of a block whose other edge is an EH
+ edge. */
+static inline edge
+non_eh_succ_edge (basic_block bb)
+{
+ gcc_checking_assert (EDGE_COUNT (bb->succs) == 2);
+
+ edge ret = find_fallthru_edge (bb->succs);
+
+ int eh_idx = EDGE_SUCC (bb, 0) == ret;
+ edge eh = EDGE_SUCC (bb, eh_idx);
+
+ gcc_checking_assert (!(ret->flags & EDGE_EH)
+ && (eh->flags & EDGE_EH));
+
+ return ret;
+}
+
/* Harden boolean-yielding compares in FUN. */
unsigned int
@@ -394,7 +468,11 @@ pass_harden_compares::execute (function *fun)
if (VECTOR_TYPE_P (TREE_TYPE (op1)))
continue;
- gcc_checking_assert (TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE);
+ /* useless_type_conversion_p enables conversions from 1-bit
+ integer types to boolean to be discarded. */
+ gcc_checking_assert (TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE
+ || (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+ && TYPE_PRECISION (TREE_TYPE (lhs)) == 1));
tree rhs = copy_ssa_name (lhs);
@@ -405,6 +483,20 @@ pass_harden_compares::execute (function *fun)
won't be debug stmts only. */
gsi_next_nondebug (&gsi_split);
+ bool throwing_compare_p = stmt_ends_bb_p (asgn);
+ if (throwing_compare_p)
+ {
+ basic_block nbb = split_edge (non_eh_succ_edge
+ (gimple_bb (asgn)));
+ gsi_split = gsi_start_bb (nbb);
+
+ if (dump_file)
+ fprintf (dump_file,
+ "Splitting non-EH edge from block %i into %i"
+ " after a throwing compare\n",
+ gimple_bb (asgn)->index, nbb->index);
+ }
+
bool same_p = (op1 == op2);
op1 = detach_value (loc, &gsi_split, op1);
op2 = same_p ? op1 : detach_value (loc, &gsi_split, op2);
@@ -418,17 +510,46 @@ pass_harden_compares::execute (function *fun)
if (!gsi_end_p (gsi_split))
{
gsi_prev (&gsi_split);
- split_block (bb, gsi_stmt (gsi_split));
+ basic_block obb = gsi_bb (gsi_split);
+ basic_block nbb = split_block (obb, gsi_stmt (gsi_split))->dest;
gsi_next (&gsi_split);
gcc_checking_assert (gsi_end_p (gsi_split));
single_succ_edge (bb)->goto_locus = loc;
if (dump_file)
- fprintf (dump_file, "Splitting block %i\n", bb->index);
+ fprintf (dump_file,
+ "Splitting block %i into %i"
+ " before the conditional trap branch\n",
+ obb->index, nbb->index);
+ }
+
+ /* If the check assignment must end a basic block, we can't
+ insert the conditional branch in the same block, so split
+ the block again, and prepare to insert the conditional
+ branch in the new block.
+
+ Also assign an EH region to the compare. Even though it's
+ unlikely that the hardening compare will throw after the
+ original compare didn't, the compiler won't even know that
+ it's the same compare operands, so add the EH edge anyway. */
+ if (throwing_compare_p)
+ {
+ add_stmt_to_eh_lp (asgnck, lookup_stmt_eh_lp (asgn));
+ make_eh_edges (asgnck);
+
+ basic_block nbb = split_edge (non_eh_succ_edge
+ (gimple_bb (asgnck)));
+ gsi_split = gsi_start_bb (nbb);
+
+ if (dump_file)
+ fprintf (dump_file,
+ "Splitting non-EH edge from block %i into %i after"
+ " the newly-inserted reversed throwing compare\n",
+ gimple_bb (asgnck)->index, nbb->index);
}
- gcc_checking_assert (single_succ_p (bb));
+ gcc_checking_assert (single_succ_p (gsi_bb (gsi_split)));
insert_check_and_trap (loc, &gsi_split, EDGE_TRUE_VALUE,
EQ_EXPR, lhs, rhs);
diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index fe31e94..47e95ec 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -1312,6 +1312,20 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb)
fprintf (dump_file, " : ");
}
+ // If there are dominators, check if a dominators can supply the range.
+ if (dom_info_available_p (CDI_DOMINATORS)
+ && range_from_dom (block_result, name, bb))
+ {
+ m_on_entry.set_bb_range (name, bb, block_result);
+ if (DEBUG_RANGE_CACHE)
+ {
+ fprintf (dump_file, "Filled from dominator! : ");
+ block_result.dump (dump_file);
+ fprintf (dump_file, "\n");
+ }
+ return;
+ }
+
while (m_workback.length () > 0)
{
basic_block node = m_workback.pop ();
@@ -1394,3 +1408,62 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb)
fprintf (dump_file, " Propagation update done.\n");
}
+
+// Check to see if we can simply get the range from the dominator.
+
+bool
+ranger_cache::range_from_dom (irange &r, tree name, basic_block bb)
+{
+ gcc_checking_assert (dom_info_available_p (CDI_DOMINATORS));
+
+ // Search back to the definition block or entry block.
+ basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (name));
+ if (def_bb == NULL)
+ def_bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
+
+ // Flag if we encounter a block with non-null set.
+ bool non_null = false;
+ for (bb = get_immediate_dominator (CDI_DOMINATORS, bb);
+ bb && bb != def_bb;
+ bb = get_immediate_dominator (CDI_DOMINATORS, bb))
+ {
+ // If there is an outgoing range, the on-entry value won't work.
+ if (m_gori.has_edge_range_p (name, bb))
+ {
+ // Check if we can seed this block with a dominator value. THis will
+ // prevent the ache from being filled back further than this.
+ if (bb != def_bb && range_from_dom (r, name, bb))
+ m_on_entry.set_bb_range (name, bb, r);
+ return false;
+ }
+
+ // Flag if we see a non-null reference during this walk.
+ if (m_non_null.non_null_deref_p (name, bb, false))
+ non_null = true;
+
+ // If range-on-entry is set in this block, it can be used.
+ if (m_on_entry.get_bb_range (r, name, bb))
+ {
+ // Apply non-null if appropriate.
+ if (r.varying_p () && non_null)
+ {
+ gcc_checking_assert (POINTER_TYPE_P (TREE_TYPE (name)));
+ r.set_nonzero (TREE_TYPE (name));
+ }
+ return true;
+ }
+ }
+ // If this is the def block, and NAME is an export, then this value
+ // cannot be used.
+ if (bb == def_bb && m_gori.has_edge_range_p (name, bb))
+ return false;
+
+ // Otherwise choose the global value and use it.
+ get_global_range (r, name);
+ if (r.varying_p () && non_null)
+ {
+ gcc_checking_assert (POINTER_TYPE_P (TREE_TYPE (name)));
+ r.set_nonzero (TREE_TYPE (name));
+ }
+ return true;
+}
diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h
index eb7a875..2c52a0b 100644
--- a/gcc/gimple-range-cache.h
+++ b/gcc/gimple-range-cache.h
@@ -98,6 +98,7 @@ public:
virtual bool range_of_expr (irange &r, tree name, gimple *stmt);
virtual bool range_on_edge (irange &r, edge e, tree expr);
bool block_range (irange &r, basic_block bb, tree name, bool calc = true);
+ bool range_from_dom (irange &r, tree name, basic_block bb);
bool get_global_range (irange &r, tree name) const;
bool get_global_range (irange &r, tree name, bool &current_p);
diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc
index afffc8d..9e80523 100644
--- a/gcc/gimple-range-edge.cc
+++ b/gcc/gimple-range-edge.cc
@@ -182,6 +182,9 @@ gimple_outgoing_range::calc_switch_ranges (gswitch *sw)
gimple *
gimple_outgoing_range::edge_range_p (irange &r, edge e)
{
+ if (single_succ_p (e->src))
+ return NULL;
+
// Determine if there is an outgoing edge.
gimple *s = gimple_outgoing_range_stmt_p (e->src);
if (!s)
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 0dba34b..8691aba 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -555,6 +555,9 @@ gori_map::calculate_gori (basic_block bb)
m_outgoing[bb->index] = BITMAP_ALLOC (&m_bitmaps);
m_incoming[bb->index] = BITMAP_ALLOC (&m_bitmaps);
+ if (single_succ_p (bb))
+ return;
+
// If this block's last statement may generate range informaiton, go
// calculate it.
gimple *stmt = gimple_outgoing_range_stmt_p (bb);
@@ -1166,33 +1169,12 @@ gori_compute::compute_operand1_and_operand2_range (irange &r,
r.intersect (op_range);
return true;
}
-// Return TRUE if a range can be calculated or recomputed for NAME on edge E.
-
-bool
-gori_compute::has_edge_range_p (tree name, edge e)
-{
- // Check if NAME is an export or can be recomputed.
- if (e)
- return is_export_p (name, e->src) || may_recompute_p (name, e);
-
- // If no edge is specified, check if NAME can have a range calculated
- // on any edge.
- return is_export_p (name) || may_recompute_p (name);
-}
-// Dump what is known to GORI computes to listing file F.
-
-void
-gori_compute::dump (FILE *f)
-{
- gori_map::dump (f);
-}
-
-// Return TRUE if NAME can be recomputed on edge E. If any direct dependant
-// is exported on edge E, it may change the computed value of NAME.
+// Return TRUE if NAME can be recomputed on any edge exiting BB. If any
+// direct dependant is exported, it may also change the computed value of NAME.
bool
-gori_compute::may_recompute_p (tree name, edge e)
+gori_compute::may_recompute_p (tree name, basic_block bb)
{
tree dep1 = depend1 (name);
tree dep2 = depend2 (name);
@@ -1207,13 +1189,47 @@ gori_compute::may_recompute_p (tree name, edge e)
return false;
// If edge is specified, check if NAME can be recalculated on that edge.
- if (e)
- return ((is_export_p (dep1, e->src))
- || (dep2 && is_export_p (dep2, e->src)));
+ if (bb)
+ return ((is_export_p (dep1, bb))
+ || (dep2 && is_export_p (dep2, bb)));
return (is_export_p (dep1)) || (dep2 && is_export_p (dep2));
}
+// Return TRUE if NAME can be recomputed on edge E. If any direct dependant
+// is exported on edge E, it may change the computed value of NAME.
+
+bool
+gori_compute::may_recompute_p (tree name, edge e)
+{
+ gcc_checking_assert (e);
+ return may_recompute_p (name, e->src);
+}
+
+
+// Return TRUE if a range can be calculated or recomputed for NAME on any
+// edge exiting BB.
+
+bool
+gori_compute::has_edge_range_p (tree name, basic_block bb)
+{
+ // Check if NAME is an export or can be recomputed.
+ if (bb)
+ return is_export_p (name, bb) || may_recompute_p (name, bb);
+
+ // If no block is specified, check for anywhere in the IL.
+ return is_export_p (name) || may_recompute_p (name);
+}
+
+// Return TRUE if a range can be calculated or recomputed for NAME on edge E.
+
+bool
+gori_compute::has_edge_range_p (tree name, edge e)
+{
+ gcc_checking_assert (e);
+ return has_edge_range_p (name, e->src);
+}
+
// Calculate a range on edge E and return it in R. Try to evaluate a
// range for NAME on this edge. Return FALSE if this is either not a
// control edge or NAME is not defined by this edge.
@@ -1287,6 +1303,13 @@ gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name,
return false;
}
+// Dump what is known to GORI computes to listing file F.
+
+void
+gori_compute::dump (FILE *f)
+{
+ gori_map::dump (f);
+}
// ------------------------------------------------------------------------
// GORI iterator. Although we have bitmap iterators, don't expose that it
diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h
index ec0b951..b15497e 100644
--- a/gcc/gimple-range-gori.h
+++ b/gcc/gimple-range-gori.h
@@ -158,10 +158,12 @@ class gori_compute : public gori_map
public:
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);
+ bool has_edge_range_p (tree name, basic_block bb = NULL);
+ bool has_edge_range_p (tree name, edge e);
void dump (FILE *f);
private:
- bool may_recompute_p (tree name, edge e = NULL);
+ bool may_recompute_p (tree name, edge e);
+ bool may_recompute_p (tree name, basic_block bb = NULL);
bool compute_operand_range (irange &r, gimple *stmt, const irange &lhs,
tree name, class fur_source &src);
bool compute_operand_range_switch (irange &r, gswitch *s, const irange &lhs,
diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
index b9c7122..15ef72f 100644
--- a/gcc/gimple-range-path.cc
+++ b/gcc/gimple-range-path.cc
@@ -375,30 +375,29 @@ void
path_range_query::compute_ranges_in_phis (basic_block bb)
{
int_range_max r;
- gphi_iterator iter;
+ auto_bitmap phi_set;
// PHIs must be resolved simultaneously on entry to the block
// because any dependencies must be satistifed with values on entry.
// Thus, we calculate all PHIs first, and then update the cache at
// the end.
- m_tmp_phi_cache.clear ();
- for (iter = gsi_start_phis (bb); !gsi_end_p (iter); gsi_next (&iter))
+ for (auto iter = gsi_start_phis (bb); !gsi_end_p (iter); gsi_next (&iter))
{
gphi *phi = iter.phi ();
tree name = gimple_phi_result (phi);
if (import_p (name) && range_defined_in_block (r, name, bb))
- m_tmp_phi_cache.set_global_range (name, r);
- }
- for (iter = gsi_start_phis (bb); !gsi_end_p (iter); gsi_next (&iter))
- {
- gphi *phi = iter.phi ();
- tree name = gimple_phi_result (phi);
-
- if (m_tmp_phi_cache.get_global_range (r, name))
- set_cache (r, name);
+ {
+ unsigned v = SSA_NAME_VERSION (name);
+ set_cache (r, name);
+ bitmap_set_bit (phi_set, v);
+ // Pretend we don't have a cache entry for this name until
+ // we're done with all PHIs.
+ bitmap_clear_bit (m_has_cache_entry, v);
+ }
}
+ bitmap_ior_into (m_has_cache_entry, phi_set);
}
// Compute ranges defined in the current block, or exported to the
diff --git a/gcc/gimple-range-path.h b/gcc/gimple-range-path.h
index 57a9ae9..77c92c0 100644
--- a/gcc/gimple-range-path.h
+++ b/gcc/gimple-range-path.h
@@ -82,8 +82,6 @@ private:
// Range cache for SSA names.
ssa_global_cache *m_cache;
- ssa_global_cache m_tmp_phi_cache;
-
// Set for each SSA that has an active entry in the cache.
bitmap m_has_cache_entry;
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index 178a470..c8431a71 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -333,7 +333,7 @@ gimple_ranger::prefill_name (irange &r, tree name)
if (!gimple_range_ssa_p (name))
return;
gimple *stmt = SSA_NAME_DEF_STMT (name);
- if (!gimple_range_handler (stmt))
+ if (!gimple_range_handler (stmt) && !is_a<gphi *> (stmt))
return;
bool current;
@@ -356,8 +356,8 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa)
gimple *stmt = SSA_NAME_DEF_STMT (ssa);
gcc_checking_assert (stmt && gimple_bb (stmt));
- // Only pre-process range-ops.
- if (!gimple_range_handler (stmt))
+ // Only pre-process range-ops and phis.
+ if (!gimple_range_handler (stmt) && !is_a<gphi *> (stmt))
return;
// Mark where on the stack we are starting.
@@ -401,13 +401,22 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa)
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
}
- gcc_checking_assert (gimple_range_handler (stmt));
- tree op = gimple_range_operand2 (stmt);
- if (op)
- prefill_name (r, op);
- op = gimple_range_operand1 (stmt);
- if (op)
- prefill_name (r, op);
+ gphi *phi = dyn_cast <gphi *> (stmt);
+ if (phi)
+ {
+ for (unsigned x = 0; x < gimple_phi_num_args (phi); x++)
+ prefill_name (r, gimple_phi_arg_def (phi, x));
+ }
+ else
+ {
+ gcc_checking_assert (gimple_range_handler (stmt));
+ tree op = gimple_range_operand2 (stmt);
+ if (op)
+ prefill_name (r, op);
+ op = gimple_range_operand1 (stmt);
+ if (op)
+ prefill_name (r, op);
+ }
}
if (idx)
tracer.trailer (idx, "ROS ", false, ssa, r);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 8624f82..b118c72 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "tree-cfg.h"
#include "tree-ssa.h"
+#include "tree-hash-traits.h"
#include "omp-general.h"
#include "omp-low.h"
#include "gimple-low.h"
@@ -1829,6 +1830,7 @@ is_var_need_auto_init (tree decl)
|| !DECL_HARD_REGISTER (decl))
&& (flag_auto_var_init > AUTO_INIT_UNINITIALIZED)
&& (!lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl)))
+ && !OPAQUE_TYPE_P (TREE_TYPE (decl))
&& !is_empty_type (TREE_TYPE (decl)))
return true;
return false;
@@ -8658,7 +8660,7 @@ insert_struct_comp_map (enum tree_code code, tree c, tree struct_node,
static tree
extract_base_bit_offset (tree base, tree *base_ref, poly_int64 *bitposp,
- poly_offset_int *poffsetp)
+ poly_offset_int *poffsetp, tree *offsetp)
{
tree offset;
poly_int64 bitsize, bitpos;
@@ -8705,10 +8707,11 @@ extract_base_bit_offset (tree base, tree *base_ref, poly_int64 *bitposp,
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (base, 0))) == REFERENCE_TYPE)
base = TREE_OPERAND (base, 0);
- gcc_assert (offset == NULL_TREE || poly_int_tree_p (offset));
-
- if (offset)
- poffset = wi::to_poly_offset (offset);
+ if (offset && poly_int_tree_p (offset))
+ {
+ poffset = wi::to_poly_offset (offset);
+ offset = NULL_TREE;
+ }
else
poffset = 0;
@@ -8717,6 +8720,7 @@ extract_base_bit_offset (tree base, tree *base_ref, poly_int64 *bitposp,
*bitposp = bitpos;
*poffsetp = poffset;
+ *offsetp = offset;
/* Set *BASE_REF if BASE was a dereferenced reference variable. */
if (base_ref && orig_base != base)
@@ -8730,12 +8734,22 @@ extract_base_bit_offset (tree base, tree *base_ref, poly_int64 *bitposp,
static bool
is_or_contains_p (tree expr, tree base_ptr)
{
- while (expr != base_ptr)
- if (TREE_CODE (base_ptr) == COMPONENT_REF)
- base_ptr = TREE_OPERAND (base_ptr, 0);
- else
- break;
- return expr == base_ptr;
+ if ((TREE_CODE (expr) == INDIRECT_REF && TREE_CODE (base_ptr) == MEM_REF)
+ || (TREE_CODE (expr) == MEM_REF && TREE_CODE (base_ptr) == INDIRECT_REF))
+ return operand_equal_p (TREE_OPERAND (expr, 0),
+ TREE_OPERAND (base_ptr, 0));
+ while (!operand_equal_p (expr, base_ptr))
+ {
+ if (TREE_CODE (base_ptr) == COMPOUND_EXPR)
+ base_ptr = TREE_OPERAND (base_ptr, 1);
+ if (TREE_CODE (base_ptr) == COMPONENT_REF
+ || TREE_CODE (base_ptr) == POINTER_PLUS_EXPR
+ || TREE_CODE (base_ptr) == SAVE_EXPR)
+ base_ptr = TREE_OPERAND (base_ptr, 0);
+ else
+ break;
+ }
+ return operand_equal_p (expr, base_ptr);
}
/* Implement OpenMP 5.x map ordering rules for target directives. There are
@@ -8815,21 +8829,107 @@ omp_target_reorder_clauses (tree *list_p)
tree base_ptr = TREE_OPERAND (decl, 0);
STRIP_TYPE_NOPS (base_ptr);
for (unsigned int j = i + 1; j < atf.length (); j++)
- {
- tree *cp2 = atf[j];
- tree decl2 = OMP_CLAUSE_DECL (*cp2);
- if (is_or_contains_p (decl2, base_ptr))
- {
- /* Move *cp2 to before *cp. */
- tree c = *cp2;
- *cp2 = OMP_CLAUSE_CHAIN (c);
- OMP_CLAUSE_CHAIN (c) = *cp;
- *cp = c;
- atf[j] = NULL;
+ if (atf[j])
+ {
+ tree *cp2 = atf[j];
+ tree decl2 = OMP_CLAUSE_DECL (*cp2);
+
+ decl2 = OMP_CLAUSE_DECL (*cp2);
+ if (is_or_contains_p (decl2, base_ptr))
+ {
+ /* Move *cp2 to before *cp. */
+ tree c = *cp2;
+ *cp2 = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = *cp;
+ *cp = c;
+
+ if (*cp2 != NULL_TREE
+ && OMP_CLAUSE_CODE (*cp2) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_KIND (*cp2) == GOMP_MAP_ALWAYS_POINTER)
+ {
+ tree c2 = *cp2;
+ *cp2 = OMP_CLAUSE_CHAIN (c2);
+ OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = c2;
+ }
+
+ atf[j] = NULL;
}
- }
+ }
}
}
+
+ /* For attach_detach map clauses, if there is another map that maps the
+ attached/detached pointer, make sure that map is ordered before the
+ attach_detach. */
+ atf.truncate (0);
+ for (tree *cp = list_p; *cp; cp = &OMP_CLAUSE_CHAIN (*cp))
+ if (OMP_CLAUSE_CODE (*cp) == OMP_CLAUSE_MAP)
+ {
+ /* Collect alloc, to, from, to/from clauses, and
+ always_pointer/attach_detach clauses. */
+ gomp_map_kind k = OMP_CLAUSE_MAP_KIND (*cp);
+ if (k == GOMP_MAP_ALLOC
+ || k == GOMP_MAP_TO
+ || k == GOMP_MAP_FROM
+ || k == GOMP_MAP_TOFROM
+ || k == GOMP_MAP_ALWAYS_TO
+ || k == GOMP_MAP_ALWAYS_FROM
+ || k == GOMP_MAP_ALWAYS_TOFROM
+ || k == GOMP_MAP_ATTACH_DETACH
+ || k == GOMP_MAP_ALWAYS_POINTER)
+ atf.safe_push (cp);
+ }
+
+ for (unsigned int i = 0; i < atf.length (); i++)
+ if (atf[i])
+ {
+ tree *cp = atf[i];
+ tree ptr = OMP_CLAUSE_DECL (*cp);
+ STRIP_TYPE_NOPS (ptr);
+ if (OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_ATTACH_DETACH)
+ for (unsigned int j = i + 1; j < atf.length (); j++)
+ {
+ tree *cp2 = atf[j];
+ tree decl2 = OMP_CLAUSE_DECL (*cp2);
+ if (OMP_CLAUSE_MAP_KIND (*cp2) != GOMP_MAP_ATTACH_DETACH
+ && OMP_CLAUSE_MAP_KIND (*cp2) != GOMP_MAP_ALWAYS_POINTER
+ && is_or_contains_p (decl2, ptr))
+ {
+ /* Move *cp2 to before *cp. */
+ tree c = *cp2;
+ *cp2 = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = *cp;
+ *cp = c;
+ atf[j] = NULL;
+
+ /* If decl2 is of the form '*decl2_opnd0', and followed by an
+ ALWAYS_POINTER or ATTACH_DETACH of 'decl2_opnd0', move the
+ pointer operation along with *cp2. This can happen for C++
+ reference sequences. */
+ if (j + 1 < atf.length ()
+ && (TREE_CODE (decl2) == INDIRECT_REF
+ || TREE_CODE (decl2) == MEM_REF))
+ {
+ tree *cp3 = atf[j + 1];
+ tree decl3 = OMP_CLAUSE_DECL (*cp3);
+ tree decl2_opnd0 = TREE_OPERAND (decl2, 0);
+ if ((OMP_CLAUSE_MAP_KIND (*cp3) == GOMP_MAP_ALWAYS_POINTER
+ || OMP_CLAUSE_MAP_KIND (*cp3) == GOMP_MAP_ATTACH_DETACH)
+ && operand_equal_p (decl3, decl2_opnd0))
+ {
+ /* Also move *cp3 to before *cp. */
+ c = *cp3;
+ *cp2 = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = *cp;
+ *cp = c;
+ atf[j + 1] = NULL;
+ j += 1;
+ }
+ }
+ }
+ }
+ }
}
/* DECL is supposed to have lastprivate semantics in the outer contexts
@@ -8920,7 +9020,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
{
struct gimplify_omp_ctx *ctx, *outer_ctx;
tree c;
- hash_map<tree, tree> *struct_map_to_clause = NULL;
+ hash_map<tree_operand_hash, tree> *struct_map_to_clause = NULL;
+ hash_map<tree_operand_hash, tree *> *struct_seen_clause = NULL;
hash_set<tree> *struct_deref_set = NULL;
tree *prev_list_p = NULL, *orig_list_p = list_p;
int handled_depend_iterators = -1;
@@ -9364,7 +9465,14 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
GOVD_FIRSTPRIVATE | GOVD_SEEN);
}
- if (!DECL_P (decl))
+ if (TREE_CODE (decl) == TARGET_EXPR)
+ {
+ if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
+ is_gimple_lvalue, fb_lvalue)
+ == GS_ERROR)
+ remove = true;
+ }
+ else if (!DECL_P (decl))
{
tree d = decl, *pd;
if (TREE_CODE (d) == ARRAY_REF)
@@ -9380,12 +9488,16 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
&& TREE_CODE (decl) == INDIRECT_REF
&& TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
&& (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
- == REFERENCE_TYPE))
+ == REFERENCE_TYPE)
+ && (OMP_CLAUSE_MAP_KIND (c)
+ != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
{
pd = &TREE_OPERAND (decl, 0);
decl = TREE_OPERAND (decl, 0);
}
bool indir_p = false;
+ bool component_ref_p = false;
+ tree indir_base = NULL_TREE;
tree orig_decl = decl;
tree decl_ref = NULL_TREE;
if ((region_type & (ORT_ACC | ORT_TARGET | ORT_TARGET_DATA)) != 0
@@ -9396,6 +9508,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
while (TREE_CODE (decl) == COMPONENT_REF)
{
decl = TREE_OPERAND (decl, 0);
+ component_ref_p = true;
if (((TREE_CODE (decl) == MEM_REF
&& integer_zerop (TREE_OPERAND (decl, 1)))
|| INDIRECT_REF_P (decl))
@@ -9403,7 +9516,9 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
== POINTER_TYPE))
{
indir_p = true;
+ indir_base = decl;
decl = TREE_OPERAND (decl, 0);
+ STRIP_NOPS (decl);
}
if (TREE_CODE (decl) == INDIRECT_REF
&& DECL_P (TREE_OPERAND (decl, 0))
@@ -9415,8 +9530,11 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
}
}
}
- else if (TREE_CODE (decl) == COMPONENT_REF)
+ else if (TREE_CODE (decl) == COMPONENT_REF
+ && (OMP_CLAUSE_MAP_KIND (c)
+ != GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION))
{
+ component_ref_p = true;
while (TREE_CODE (decl) == COMPONENT_REF)
decl = TREE_OPERAND (decl, 0);
if (TREE_CODE (decl) == INDIRECT_REF
@@ -9445,7 +9563,9 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
!= GOMP_MAP_POINTER)
|| OMP_CLAUSE_DECL (next_clause) != decl)
&& (!struct_deref_set
- || !struct_deref_set->contains (decl)))
+ || !struct_deref_set->contains (decl))
+ && (!struct_map_to_clause
+ || !struct_map_to_clause->get (indir_base)))
{
if (!struct_deref_set)
struct_deref_set = new hash_set<tree> ();
@@ -9486,7 +9606,11 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
if (code == OACC_UPDATE
&& OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_POINTER);
- if (DECL_P (decl)
+ if ((DECL_P (decl)
+ || (component_ref_p
+ && (INDIRECT_REF_P (decl)
+ || TREE_CODE (decl) == MEM_REF
+ || TREE_CODE (decl) == ARRAY_REF)))
&& OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_TO_PSET
&& OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
&& OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH
@@ -9521,7 +9645,15 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
remove = true;
break;
}
- if (OMP_CLAUSE_CHAIN (*prev_list_p) != c)
+
+ /* The below prev_list_p based error recovery code is
+ currently no longer valid for OpenMP. */
+ if (code != OMP_TARGET
+ && code != OMP_TARGET_DATA
+ && code != OMP_TARGET_UPDATE
+ && code != OMP_TARGET_ENTER_DATA
+ && code != OMP_TARGET_EXIT_DATA
+ && OMP_CLAUSE_CHAIN (*prev_list_p) != c)
{
tree ch = OMP_CLAUSE_CHAIN (*prev_list_p);
if (ch == NULL_TREE || OMP_CLAUSE_CHAIN (ch) != c)
@@ -9534,16 +9666,21 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
poly_offset_int offset1;
poly_int64 bitpos1;
+ tree tree_offset1;
tree base_ref;
tree base
= extract_base_bit_offset (OMP_CLAUSE_DECL (c), &base_ref,
- &bitpos1, &offset1);
+ &bitpos1, &offset1,
+ &tree_offset1);
- gcc_assert (base == decl);
+ bool do_map_struct = (base == decl && !tree_offset1);
splay_tree_node n
- = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
+ = (DECL_P (decl)
+ ? splay_tree_lookup (ctx->variables,
+ (splay_tree_key) decl)
+ : NULL);
bool ptr = (OMP_CLAUSE_MAP_KIND (c)
== GOMP_MAP_ALWAYS_POINTER);
bool attach_detach = (OMP_CLAUSE_MAP_KIND (c)
@@ -9569,7 +9706,37 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
OMP_CLAUSE_SET_MAP_KIND (c, k);
has_attachments = true;
}
- if (n == NULL || (n->value & GOVD_MAP) == 0)
+
+ /* We currently don't handle non-constant offset accesses wrt to
+ GOMP_MAP_STRUCT elements. */
+ if (!do_map_struct)
+ goto skip_map_struct;
+
+ /* Nor for attach_detach for OpenMP. */
+ if ((code == OMP_TARGET
+ || code == OMP_TARGET_DATA
+ || code == OMP_TARGET_UPDATE
+ || code == OMP_TARGET_ENTER_DATA
+ || code == OMP_TARGET_EXIT_DATA)
+ && attach_detach)
+ {
+ if (DECL_P (decl))
+ {
+ if (struct_seen_clause == NULL)
+ struct_seen_clause
+ = new hash_map<tree_operand_hash, tree *>;
+ if (!struct_seen_clause->get (decl))
+ struct_seen_clause->put (decl, list_p);
+ }
+
+ goto skip_map_struct;
+ }
+
+ if ((DECL_P (decl)
+ && (n == NULL || (n->value & GOVD_MAP) == 0))
+ || (!DECL_P (decl)
+ && (!struct_map_to_clause
+ || struct_map_to_clause->get (decl) == NULL)))
{
tree l = build_omp_clause (OMP_CLAUSE_LOCATION (c),
OMP_CLAUSE_MAP);
@@ -9580,7 +9747,18 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
if (base_ref)
OMP_CLAUSE_DECL (l) = unshare_expr (base_ref);
else
- OMP_CLAUSE_DECL (l) = decl;
+ {
+ OMP_CLAUSE_DECL (l) = unshare_expr (decl);
+ if (!DECL_P (OMP_CLAUSE_DECL (l))
+ && (gimplify_expr (&OMP_CLAUSE_DECL (l),
+ pre_p, NULL, is_gimple_lvalue,
+ fb_lvalue)
+ == GS_ERROR))
+ {
+ remove = true;
+ break;
+ }
+ }
OMP_CLAUSE_SIZE (l)
= (!attach
? size_int (1)
@@ -9588,13 +9766,19 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
? DECL_SIZE_UNIT (OMP_CLAUSE_DECL (l))
: TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (l))));
if (struct_map_to_clause == NULL)
- struct_map_to_clause = new hash_map<tree, tree>;
+ struct_map_to_clause
+ = new hash_map<tree_operand_hash, tree>;
struct_map_to_clause->put (decl, l);
if (ptr || attach_detach)
{
- insert_struct_comp_map (code, c, l, *prev_list_p,
+ tree **sc = (struct_seen_clause
+ ? struct_seen_clause->get (decl)
+ : NULL);
+ tree *insert_node_pos = sc ? *sc : prev_list_p;
+
+ insert_struct_comp_map (code, c, l, *insert_node_pos,
NULL);
- *prev_list_p = l;
+ *insert_node_pos = l;
prev_list_p = NULL;
}
else
@@ -9622,15 +9806,41 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
flags |= GOVD_SEEN;
if (has_attachments)
flags |= GOVD_MAP_HAS_ATTACHMENTS;
- goto do_add_decl;
+
+ /* If this is a *pointer-to-struct expression, make sure a
+ firstprivate map of the base-pointer exists. */
+ if (component_ref_p
+ && ((TREE_CODE (decl) == MEM_REF
+ && integer_zerop (TREE_OPERAND (decl, 1)))
+ || INDIRECT_REF_P (decl))
+ && DECL_P (TREE_OPERAND (decl, 0))
+ && !splay_tree_lookup (ctx->variables,
+ ((splay_tree_key)
+ TREE_OPERAND (decl, 0))))
+ {
+ decl = TREE_OPERAND (decl, 0);
+ tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+ OMP_CLAUSE_MAP);
+ enum gomp_map_kind mkind
+ = GOMP_MAP_FIRSTPRIVATE_POINTER;
+ OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
+ OMP_CLAUSE_DECL (c2) = decl;
+ OMP_CLAUSE_SIZE (c2) = size_zero_node;
+ OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = c2;
+ }
+
+ if (DECL_P (decl))
+ goto do_add_decl;
}
else if (struct_map_to_clause)
{
tree *osc = struct_map_to_clause->get (decl);
tree *sc = NULL, *scp = NULL;
- if (GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c))
- || ptr
- || attach_detach)
+ if (n != NULL
+ && (GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c))
+ || ptr
+ || attach_detach))
n->value |= GOVD_SEEN;
sc = &OMP_CLAUSE_CHAIN (*osc);
if (*sc != c
@@ -9654,9 +9864,11 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
tree sc_decl = OMP_CLAUSE_DECL (*sc);
poly_offset_int offsetn;
poly_int64 bitposn;
+ tree tree_offsetn;
tree base
= extract_base_bit_offset (sc_decl, NULL,
- &bitposn, &offsetn);
+ &bitposn, &offsetn,
+ &tree_offsetn);
if (base != decl)
break;
if (scp)
@@ -9731,22 +9943,34 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
}
else if (*sc != c)
{
+ if (gimplify_expr (pd, pre_p, NULL, is_gimple_lvalue,
+ fb_lvalue)
+ == GS_ERROR)
+ {
+ remove = true;
+ break;
+ }
*list_p = OMP_CLAUSE_CHAIN (c);
OMP_CLAUSE_CHAIN (c) = *sc;
*sc = c;
continue;
}
}
+ skip_map_struct:
+ ;
}
else if ((code == OACC_ENTER_DATA
|| code == OACC_EXIT_DATA
|| code == OACC_DATA
|| code == OACC_PARALLEL
|| code == OACC_KERNELS
- || code == OACC_SERIAL)
+ || code == OACC_SERIAL
+ || code == OMP_TARGET_ENTER_DATA
+ || code == OMP_TARGET_EXIT_DATA)
&& OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
{
- gomp_map_kind k = (code == OACC_EXIT_DATA
+ gomp_map_kind k = ((code == OACC_EXIT_DATA
+ || code == OMP_TARGET_EXIT_DATA)
? GOMP_MAP_DETACH : GOMP_MAP_ATTACH);
OMP_CLAUSE_SET_MAP_KIND (c, k);
}
@@ -9866,6 +10090,24 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
break;
}
+ /* If this was of the form map(*pointer_to_struct), then the
+ 'pointer_to_struct' DECL should be considered deref'ed. */
+ if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALLOC
+ || GOMP_MAP_COPY_TO_P (OMP_CLAUSE_MAP_KIND (c))
+ || GOMP_MAP_COPY_FROM_P (OMP_CLAUSE_MAP_KIND (c)))
+ && INDIRECT_REF_P (orig_decl)
+ && DECL_P (TREE_OPERAND (orig_decl, 0))
+ && TREE_CODE (TREE_TYPE (orig_decl)) == RECORD_TYPE)
+ {
+ tree ptr = TREE_OPERAND (orig_decl, 0);
+ if (!struct_deref_set || !struct_deref_set->contains (ptr))
+ {
+ if (!struct_deref_set)
+ struct_deref_set = new hash_set<tree> ();
+ struct_deref_set->add (ptr);
+ }
+ }
+
if (!remove
&& OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_POINTER
&& OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH_DETACH
@@ -10560,6 +10802,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
ctx->clauses = *orig_list_p;
gimplify_omp_ctxp = ctx;
+ if (struct_seen_clause)
+ delete struct_seen_clause;
if (struct_map_to_clause)
delete struct_map_to_clause;
if (struct_deref_set)
@@ -11215,6 +11459,12 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
}
}
}
+ if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
+ && (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA))
+ {
+ remove = true;
+ break;
+ }
if (!DECL_P (decl))
{
if ((ctx->region_type & ORT_TARGET) != 0
@@ -11261,10 +11511,6 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
= OMP_CLAUSE_CHAIN (OMP_CLAUSE_CHAIN (c));
}
}
- else if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
- && (code == OMP_TARGET_EXIT_DATA
- || code == OACC_EXIT_DATA))
- remove = true;
else if (DECL_SIZE (decl)
&& TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST
&& OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_POINTER
diff --git a/gcc/hash-map.h b/gcc/hash-map.h
index dd039f1..c4fe26c 100644
--- a/gcc/hash-map.h
+++ b/gcc/hash-map.h
@@ -217,7 +217,8 @@ public:
}
/* Call the call back on each pair of key and value with the passed in
- arg. */
+ arg until either the call back returns false or all pairs have been seen.
+ The traversal is unordered. */
template<typename Arg, bool (*f)(const typename Traits::key_type &,
const Value &, Arg)>
@@ -225,7 +226,8 @@ public:
{
for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
iter != m_table.end (); ++iter)
- f ((*iter).m_key, (*iter).m_value, a);
+ if (!f ((*iter).m_key, (*iter).m_value, a))
+ break;
}
template<typename Arg, bool (*f)(const typename Traits::key_type &,
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 017944f..b0052f6 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -4726,7 +4726,9 @@ find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge)
/* If that results in an invalid insn, back out. */
for (rtx_insn *x = seq; x; x = NEXT_INSN (x))
- if (recog_memoized (x) < 0)
+ if (reload_completed
+ ? !valid_insn_p (x)
+ : recog_memoized (x) < 0)
return FALSE;
/* Emit the new insns before cond_earliest. */
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 6ac3460..08f94b7 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -3050,6 +3050,23 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt)
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 this expands to a register and the underlying decl is wrapped in
+ a MEM_REF that just serves as an access type change expose the decl
+ if it is of correct size. This avoids a situation as in PR103271
+ if the target does not support a direct move to the registers mode. */
+ if (reg_lhs
+ && TREE_CODE (lhs_base) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (lhs_base, 0)) == ADDR_EXPR
+ && DECL_P (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))
+ && integer_zerop (TREE_OPERAND (lhs_base, 1))
+ && tree_fits_uhwi_p (var_size)
+ && tree_int_cst_equal
+ (var_size,
+ DECL_SIZE_UNIT (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))))
+ {
+ lhs = TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0);
+ var_type = TREE_TYPE (lhs);
+ }
}
if (!reg_lhs)
diff --git a/gcc/ipa-modref-tree.c b/gcc/ipa-modref-tree.c
index 0671fa7..a868e3e 100644
--- a/gcc/ipa-modref-tree.c
+++ b/gcc/ipa-modref-tree.c
@@ -297,7 +297,7 @@ modref_access_node::closer_pair_p (const modref_access_node &a1,
dist2 = offseta2 - offsetb2 - b2.max_size;
}
/* It may happen that intervals overlap in case size
- is different. Preffer the overlap to non-overlap. */
+ is different. Prefer the overlap to non-overlap. */
if (known_lt (dist1, 0) && known_ge (dist2, 0))
return true;
if (known_lt (dist2, 0) && known_ge (dist1, 0))
diff --git a/gcc/ira-color.c b/gcc/ira-color.c
index 3d01c60..a1b0277 100644
--- a/gcc/ira-color.c
+++ b/gcc/ira-color.c
@@ -2796,7 +2796,7 @@ static int *allocno_priorities;
static void
setup_allocno_priorities (ira_allocno_t *consideration_allocnos, int n)
{
- int i, length, nrefs, priority, max_priority, mult;
+ int i, length, nrefs, priority, max_priority, mult, diff;
ira_allocno_t a;
max_priority = 0;
@@ -2807,11 +2807,30 @@ setup_allocno_priorities (ira_allocno_t *consideration_allocnos, int n)
ira_assert (nrefs >= 0);
mult = floor_log2 (ALLOCNO_NREFS (a)) + 1;
ira_assert (mult >= 0);
- allocno_priorities[ALLOCNO_NUM (a)]
- = priority
- = (mult
- * (ALLOCNO_MEMORY_COST (a) - ALLOCNO_CLASS_COST (a))
- * ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]);
+ mult *= ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)];
+ diff = ALLOCNO_MEMORY_COST (a) - ALLOCNO_CLASS_COST (a);
+#ifdef __has_builtin
+#if __has_builtin(__builtin_smul_overflow)
+#define HAS_SMUL_OVERFLOW
+#endif
+#endif
+ /* Multiplication can overflow for very large functions.
+ Check the overflow and constrain the result if necessary: */
+#ifdef HAS_SMUL_OVERFLOW
+ if (__builtin_smul_overflow (mult, diff, &priority)
+ || priority < -INT_MAX)
+ priority = diff >= 0 ? INT_MAX : -INT_MAX;
+#else
+ static_assert
+ (sizeof (long long) >= 2 * sizeof (int),
+ "overflow code does not work for such int and long long sizes");
+ long long priorityll = (long long) mult * diff;
+ if (priorityll < -INT_MAX || priorityll > INT_MAX)
+ priority = diff >= 0 ? INT_MAX : -INT_MAX;
+ else
+ priority = priorityll;
+#endif
+ allocno_priorities[ALLOCNO_NUM (a)] = priority;
if (priority < 0)
priority = -priority;
if (max_priority < priority)
diff --git a/gcc/lto-opts.c b/gcc/lto-opts.c
index 7b2ad74..30c1013 100644
--- a/gcc/lto-opts.c
+++ b/gcc/lto-opts.c
@@ -149,6 +149,7 @@ lto_write_options (void)
case OPT_fdebug_prefix_map_:
case OPT_ffile_prefix_map_:
case OPT_fmacro_prefix_map_:
+ case OPT_fprofile_prefix_map_:
continue;
default:
diff --git a/gcc/match.pd b/gcc/match.pd
index 0a00b08..0d7b8dd 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4403,6 +4403,28 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(op (min @X { wide_int_to_tree (from_type, real_c1); })
{ wide_int_to_tree (from_type, c2); })))))))))
+/* X != C1 ? -X : C2 simplifies to -X when -C1 == C2. */
+(simplify
+ (cond (ne @0 INTEGER_CST@1) (negate@3 @0) INTEGER_CST@2)
+ (if (!TYPE_SATURATING (type)
+ && (TYPE_OVERFLOW_WRAPS (type)
+ || !wi::only_sign_bit_p (wi::to_wide (@1)))
+ && wi::eq_p (wi::neg (wi::to_wide (@1)), wi::to_wide (@2)))
+ @3))
+
+/* X != C1 ? ~X : C2 simplifies to ~X when ~C1 == C2. */
+(simplify
+ (cond (ne @0 INTEGER_CST@1) (bit_not@3 @0) INTEGER_CST@2)
+ (if (wi::eq_p (wi::bit_not (wi::to_wide (@1)), wi::to_wide (@2)))
+ @3))
+
+/* (X + 1) > Y ? -X : 1 simplifies to X >= Y ? -X : 1 when
+ X is unsigned, as when X + 1 overflows, X is -1, so -X == 1. */
+(simplify
+ (cond (gt (plus @0 integer_onep) @1) (negate @0) integer_onep@2)
+ (if (TYPE_UNSIGNED (type))
+ (cond (ge @0 @1) (negate @0) @2)))
+
(for cnd (cond vec_cond)
/* A ? B : (A ? X : C) -> A ? B : C. */
(simplify
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 8a1cb9f..811bb49 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,11 @@
+2021-12-05 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-next-metadata-tags.h (objc_rt_trees): Declare here.
+ * objc-next-runtime-abi-01.c: Remove from here.
+ * objc-next-runtime-abi-02.c: Likewise.
+ * objc-runtime-shared-support.c: Reorder headers, provide
+ a GTY declaration the definition of objc_rt_trees.
+
2021-11-30 Richard Biener <rguenther@suse.de>
* objc-act.c (objc_build_setter_call): Remove unreachable
diff --git a/gcc/objc/objc-next-metadata-tags.h b/gcc/objc/objc-next-metadata-tags.h
index ceb8783..aea1455 100644
--- a/gcc/objc/objc-next-metadata-tags.h
+++ b/gcc/objc/objc-next-metadata-tags.h
@@ -79,6 +79,8 @@ enum objc_runtime_tree_index
OCTI_RT_META_MAX
};
+extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
+
/* Tags for the META data so that the backend can put them in the correct
sections for targets/runtimes (Darwin/NeXT) that require this.
This information also survives LTO - which might produce mixed language
diff --git a/gcc/objc/objc-next-runtime-abi-01.c b/gcc/objc/objc-next-runtime-abi-01.c
index 12f8bdc..0f76162 100644
--- a/gcc/objc/objc-next-runtime-abi-01.c
+++ b/gcc/objc/objc-next-runtime-abi-01.c
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see
#include "objc-runtime-hooks.h"
#include "objc-runtime-shared-support.h"
+#include "objc-next-metadata-tags.h"
#include "objc-encoding.h"
/* NeXT ABI 0 and 1 private definitions. */
@@ -99,14 +100,6 @@ along with GCC; see the file COPYING3. If not see
#define CLS_HAS_CXX_STRUCTORS 0x2000L
-/* rt_trees identifiers - shared between NeXT implementations. These
- allow the FE to tag meta-data in a manner that survives LTO and can
- be used when the runtime requires that certain meta-data items
- appear in particular named sections. */
-
-#include "objc-next-metadata-tags.h"
-extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
-
static void next_runtime_01_initialize (void);
static tree next_runtime_abi_01_super_superclassfield_id (void);
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index 7ca0fd7..913ed643 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see
#include "objc-runtime-hooks.h"
#include "objc-runtime-shared-support.h"
+#include "objc-next-metadata-tags.h"
#include "objc-encoding.h"
/* ABI 2 Private definitions. */
@@ -180,14 +181,6 @@ enum objc_v2_tree_index
#define objc_rethrow_exception_decl \
objc_v2_global_trees[OCTI_V2_RETHROW_DECL]
-/* rt_trees identifiers - shared between NeXT implementations. These allow
- the FE to tag meta-data in a manner that survives LTO and can be used when
- the runtime requires that certain meta-data items appear in particular
- named sections. */
-
-#include "objc-next-metadata-tags.h"
-extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
-
/* The OCTI_V2_... enumeration itself is in above. */
static GTY(()) tree objc_v2_global_trees[OCTI_V2_MAX];
diff --git a/gcc/objc/objc-runtime-shared-support.c b/gcc/objc/objc-runtime-shared-support.c
index 40f506c..0d3036f 100644
--- a/gcc/objc/objc-runtime-shared-support.c
+++ b/gcc/objc/objc-runtime-shared-support.c
@@ -44,16 +44,11 @@ along with GCC; see the file COPYING3. If not see
#include "objc-runtime-hooks.h"
#include "objc-runtime-shared-support.h"
-#include "objc-encoding.h"
-
-/* rt_trees identifiers - shared between NeXT implementations. These allow
- the FE to tag meta-data in a manner that survives LTO and can be used when
- the runtime requires that certain meta-data items appear in particular
- named sections. */
#include "objc-next-metadata-tags.h"
-extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
+#include "objc-encoding.h"
/* Rather than repeatedly looking up the identifiers, we save them here. */
+extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
tree objc_rt_trees[OCTI_RT_META_MAX];
/* For building an objc struct. These might not be used when this file
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index de3a26e..2a07beb 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -12635,6 +12635,8 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
case GOMP_MAP_ALWAYS_POINTER:
case GOMP_MAP_ATTACH:
case GOMP_MAP_DETACH:
+ case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
+ case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
break;
case GOMP_MAP_IF_PRESENT:
case GOMP_MAP_FORCE_ALLOC:
diff --git a/gcc/opt-functions.awk b/gcc/opt-functions.awk
index 9bc8560..ffe4eb9 100644
--- a/gcc/opt-functions.awk
+++ b/gcc/opt-functions.awk
@@ -303,7 +303,7 @@ function var_set(flags)
return "0, CLVC_STRING, 0"
if (flag_set_p("ByteSize", flags))
return "0, CLVC_SIZE, 0"
- return "0, CLVC_BOOLEAN, 0"
+ return "0, CLVC_INTEGER, 0"
}
# Given that an option called NAME has flags FLAGS, return an initializer
diff --git a/gcc/opts-common.c b/gcc/opts-common.c
index 9d1914f..ef2130e 100644
--- a/gcc/opts-common.c
+++ b/gcc/opts-common.c
@@ -1458,7 +1458,7 @@ set_option (struct gcc_options *opts, struct gcc_options *opts_set,
switch (option->var_type)
{
- case CLVC_BOOLEAN:
+ case CLVC_INTEGER:
if (option->cl_host_wide_int)
{
*(HOST_WIDE_INT *) flag_var = value;
@@ -1586,7 +1586,8 @@ option_flag_var (int opt_index, struct gcc_options *opts)
}
/* Return 1 if option OPT_IDX is enabled in OPTS, 0 if it is disabled,
- or -1 if it isn't a simple on-off switch. */
+ or -1 if it isn't a simple on-off switch
+ (or if the value is unknown, typically set later in target). */
int
option_enabled (int opt_idx, unsigned lang_mask, void *opts)
@@ -1606,11 +1607,17 @@ option_enabled (int opt_idx, unsigned lang_mask, void *opts)
if (flag_var)
switch (option->var_type)
{
- case CLVC_BOOLEAN:
+ case CLVC_INTEGER:
if (option->cl_host_wide_int)
- return *(HOST_WIDE_INT *) flag_var != 0;
+ {
+ HOST_WIDE_INT v = *(HOST_WIDE_INT *) flag_var;
+ return v != 0 ? (v < 0 ? -1 : 1) : 0;
+ }
else
- return *(int *) flag_var != 0;
+ {
+ int v = *(int *) flag_var;
+ return v != 0 ? (v < 0 ? -1 : 1) : 0;
+ }
case CLVC_EQUAL:
if (option->cl_host_wide_int)
@@ -1658,7 +1665,7 @@ get_option_state (struct gcc_options *opts, int option,
switch (cl_options[option].var_type)
{
- case CLVC_BOOLEAN:
+ case CLVC_INTEGER:
case CLVC_EQUAL:
case CLVC_SIZE:
state->data = flag_var;
@@ -1725,7 +1732,7 @@ control_warning_option (unsigned int opt_index, int kind, const char *arg,
const struct cl_option *option = &cl_options[opt_index];
/* -Werror=foo implies -Wfoo. */
- if (option->var_type == CLVC_BOOLEAN
+ if (option->var_type == CLVC_INTEGER
|| option->var_type == CLVC_ENUM
|| option->var_type == CLVC_SIZE)
{
diff --git a/gcc/opts-global.c b/gcc/opts-global.c
index 5527382..d4fde39 100644
--- a/gcc/opts-global.c
+++ b/gcc/opts-global.c
@@ -386,6 +386,10 @@ handle_common_deferred_options (void)
add_file_prefix_map (opt->arg);
break;
+ case OPT_fprofile_prefix_map_:
+ add_profile_prefix_map (opt->arg);
+ break;
+
case OPT_fdump_:
g->get_dumps ()->dump_switch_p (opt->arg);
break;
diff --git a/gcc/opts.c b/gcc/opts.c
index b16497e..870ccec 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -2685,6 +2685,7 @@ common_handle_option (struct gcc_options *opts,
case OPT_fdebug_prefix_map_:
case OPT_ffile_prefix_map_:
+ case OPT_fprofile_prefix_map_:
/* Deferred. */
break;
@@ -3598,6 +3599,7 @@ gen_command_line_string (cl_decoded_option *options,
case OPT_fdebug_prefix_map_:
case OPT_fmacro_prefix_map_:
case OPT_ffile_prefix_map_:
+ case OPT_fprofile_prefix_map_:
case OPT_fcompare_debug:
case OPT_fchecking:
case OPT_fchecking_:
diff --git a/gcc/opts.h b/gcc/opts.h
index f5bc9a3..4c2b77e 100644
--- a/gcc/opts.h
+++ b/gcc/opts.h
@@ -24,8 +24,8 @@ along with GCC; see the file COPYING3. If not see
/* Specifies how a switch's VAR_VALUE relates to its FLAG_VAR. */
enum cl_var_type {
- /* The switch is enabled when FLAG_VAR is nonzero. */
- CLVC_BOOLEAN,
+ /* The switch is an integer value. */
+ CLVC_INTEGER,
/* The switch is enabled when FLAG_VAR == VAR_VALUE. */
CLVC_EQUAL,
diff --git a/gcc/output.h b/gcc/output.h
index 8f6f153..4a23795 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -470,7 +470,7 @@ struct GTY(()) named_section {
/* A callback that writes the assembly code for switching to an unnamed
section. The argument provides callback-specific data. */
-typedef void (*unnamed_section_callback) (const void *);
+typedef void (*unnamed_section_callback) (const char *);
/* Information about a SECTION_UNNAMED section. */
struct GTY(()) unnamed_section {
@@ -478,8 +478,8 @@ struct GTY(()) unnamed_section {
/* The callback used to switch to the section, and the data that
should be passed to the callback. */
- unnamed_section_callback GTY ((skip)) callback;
- const void *GTY ((skip)) data;
+ unnamed_section_callback GTY ((callback)) callback;
+ const char *data;
/* The next entry in the chain of unnamed sections. */
section *next;
@@ -503,7 +503,7 @@ struct GTY(()) noswitch_section {
struct section_common common;
/* The callback used to assemble decls in this section. */
- noswitch_section_callback GTY ((skip)) callback;
+ noswitch_section_callback GTY ((callback)) callback;
};
/* Information about a section, which may be named or unnamed. */
@@ -538,8 +538,8 @@ extern GTY(()) section *bss_noswitch_section;
extern GTY(()) section *in_section;
extern GTY(()) bool in_cold_section_p;
-extern section *get_unnamed_section (unsigned int, void (*) (const void *),
- const void *);
+extern section *get_unnamed_section (unsigned int, void (*) (const char *),
+ const char *);
extern section *get_section (const char *, unsigned int, tree,
bool not_existing = false);
extern section *get_named_section (tree, const char *, int);
@@ -561,7 +561,7 @@ extern section *get_cdtor_priority_section (int, bool);
extern bool unlikely_text_section_p (section *);
extern void switch_to_section (section *, tree = nullptr);
-extern void output_section_asm_op (const void *);
+extern void output_section_asm_op (const char *);
extern void record_tm_clone_pair (tree, tree);
extern void finish_tm_clone_pairs (void);
diff --git a/gcc/predict.c b/gcc/predict.c
index 3cb4e3c..1a1da7e 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -3044,7 +3044,7 @@ assert_is_empty (const_basic_block const &, edge_prediction *const &value,
void *)
{
gcc_assert (!value);
- return false;
+ return true;
}
/* Predict branch probabilities and estimate profile for basic block BB.
diff --git a/gcc/profile-count.c b/gcc/profile-count.c
index f7f4dff..c04b4fe 100644
--- a/gcc/profile-count.c
+++ b/gcc/profile-count.c
@@ -84,18 +84,28 @@ const char *profile_quality_display_names[] =
"precise"
};
-/* Dump THIS to F. */
+/* Dump THIS to BUFFER. */
void
-profile_count::dump (FILE *f) const
+profile_count::dump (char *buffer) const
{
if (!initialized_p ())
- fprintf (f, "uninitialized");
+ sprintf (buffer, "uninitialized");
else
- fprintf (f, "%" PRId64 " (%s)", m_val,
+ sprintf (buffer, "%" PRId64 " (%s)", m_val,
profile_quality_display_names[m_quality]);
}
+/* Dump THIS to F. */
+
+void
+profile_count::dump (FILE *f) const
+{
+ char buffer[64];
+ dump (buffer);
+ fputs (buffer, f);
+}
+
/* Dump THIS to stderr. */
void
@@ -151,32 +161,44 @@ profile_count::stream_out (struct lto_output_stream *ob)
streamer_write_uhwi_stream (ob, m_quality);
}
-/* Dump THIS to F. */
+
+/* Output THIS to BUFFER. */
void
-profile_probability::dump (FILE *f) const
+profile_probability::dump (char *buffer) const
{
if (!initialized_p ())
- fprintf (f, "uninitialized");
+ sprintf (buffer, "uninitialized");
else
{
/* Make difference between 0.00 as a roundoff error and actual 0.
Similarly for 1. */
if (m_val == 0)
- fprintf (f, "never");
+ buffer += sprintf (buffer, "never");
else if (m_val == max_probability)
- fprintf (f, "always");
+ buffer += sprintf (buffer, "always");
else
- fprintf (f, "%3.1f%%", (double)m_val * 100 / max_probability);
+ buffer += sprintf (buffer, "%3.1f%%", (double)m_val * 100 / max_probability);
+
if (m_quality == ADJUSTED)
- fprintf (f, " (adjusted)");
+ sprintf (buffer, " (adjusted)");
else if (m_quality == AFDO)
- fprintf (f, " (auto FDO)");
+ sprintf (buffer, " (auto FDO)");
else if (m_quality == GUESSED)
- fprintf (f, " (guessed)");
+ sprintf (buffer, " (guessed)");
}
}
+/* Dump THIS to F. */
+
+void
+profile_probability::dump (FILE *f) const
+{
+ char buffer[64];
+ dump (buffer);
+ fputs (buffer, f);
+}
+
/* Dump THIS to stderr. */
void
diff --git a/gcc/profile-count.h b/gcc/profile-count.h
index c7a45ac..f86091f 100644
--- a/gcc/profile-count.h
+++ b/gcc/profile-count.h
@@ -609,6 +609,9 @@ public:
/* Output THIS to F. */
void dump (FILE *f) const;
+ /* Output THIS to BUFFER. */
+ void dump (char *buffer) const;
+
/* Print THIS to stderr. */
void debug () const;
@@ -1208,6 +1211,9 @@ public:
/* Output THIS to F. */
void dump (FILE *f) const;
+ /* Output THIS to BUFFER. */
+ void dump (char *buffer) const;
+
/* Print THIS to stderr. */
void debug () const;
diff --git a/gcc/profile.c b/gcc/profile.c
index dbf42ff..d410305 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -65,6 +65,7 @@ along with GCC; see the file COPYING3. If not see
#include "dumpfile.h"
#include "cfgloop.h"
#include "sreal.h"
+#include "file-prefix-map.h"
#include "profile.h"
@@ -1060,6 +1061,9 @@ output_location (hash_set<location_triplet_hash> *streamed_locations,
static int prev_line;
bool name_differs, line_differs;
+ if (file_name != NULL)
+ file_name = remap_profile_filename (file_name);
+
location_triplet triplet;
triplet.filename = file_name;
triplet.lineno = line;
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index 1d9ea03..cc369f0 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -453,7 +453,7 @@ get_true_reg (rtx *pat)
}
}
-/* Set if we find any malformed asms in a block. */
+/* Set if we find any malformed asms in a function. */
static bool any_malformed_asm;
/* There are many rules that an asm statement for stack-like regs must
@@ -3014,8 +3014,6 @@ convert_regs_1 (basic_block block)
bool cfg_altered = false;
int debug_insns_with_starting_stack = 0;
- any_malformed_asm = false;
-
/* Choose an initial stack layout, if one hasn't already been chosen. */
if (bi->stack_in.top == -2)
{
@@ -3385,6 +3383,7 @@ reg_to_stack (void)
0, sizeof (char) * (max_uid + 1));
convert_regs ();
+ any_malformed_asm = false;
free_aux_for_blocks ();
return true;
diff --git a/gcc/target.def b/gcc/target.def
index 6bc39d2..0631ac8 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -2965,6 +2965,14 @@ The default value of this hook is based on target's libc.",
bool, (void),
default_has_ifunc_p)
+/* True if it is OK to reference indirect function resolvers locally. */
+DEFHOOK
+(ifunc_ref_local_ok,
+ "Return true if it is OK to reference indirect function resolvers\n\
+locally. The default is to return false.",
+ bool, (void),
+ hook_bool_void_false)
+
/* True if it is OK to do sibling call optimization for the specified
call expression EXP. DECL will be the called function, or NULL if
this is an indirect call. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f6d0e96..e02c0c8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,453 @@
+2021-12-08 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/103609
+ * gfortran.dg/pr103609.f90: New test.
+
+2021-12-08 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * gcc.target/pru/pru_irq_map.c: New test.
+
+2021-12-08 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/103610
+ * gfortran.dg/shape_11.f90: New test.
+
+2021-12-08 Martin Liska <mliska@suse.cz>
+
+ * gcc.dg/loop-unswitch-1.c: Adjust test-case based on
+ dump_printf_loc.
+ * gcc.dg/loop-unswitch-2.c: Likewise.
+ * gcc.dg/loop-unswitch-3.c: Likewise.
+ * gcc.dg/loop-unswitch-4.c: Likewise.
+ * gcc.dg/loop-unswitch-5.c: Likewise.
+
+2021-12-08 Hans-Peter Nilsson <hp@axis.com>
+
+ * gcc.dg/sibcall-1.c, gcc.dg/sibcall-10.c,
+ gcc.dg/sibcall-2.c, gcc.dg/sibcall-3.c,
+ gcc.dg/sibcall-4.c, gcc.dg/sibcall-9.c: Replace
+ attribute "noinline" with "noipa".
+
+2021-12-08 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * c-c++-common/goacc/deep-copy-arrayofstruct.c: Adjust testcase.
+ * c-c++-common/gomp/target-enter-data-1.c: New testcase.
+ * c-c++-common/gomp/target-implicit-map-2.c: New testcase.
+
+2021-12-08 Roger Sayle <roger@nextmovesoftware.com>
+
+ * gcc.target/nvptx/exttrunc-2.c: New test case.
+ * gcc.target/nvptx/exttrunc-3.c: New test case.
+ * gcc.target/nvptx/exttrunc-4.c: New test case.
+ * gcc.target/nvptx/exttrunc-5.c: New test case.
+ * gcc.target/nvptx/exttrunc-6.c: New test case.
+
+2021-12-08 Roger Sayle <roger@nextmovesoftware.com>
+
+ * gcc.target/nvptx/exttrunc-1.c: New test case.
+
+2021-12-08 Chung-Lin Tang <cltang@codesourcery.com>
+
+ PR middle-end/92120
+ * gcc.dg/gomp/target-3.c: New testcase.
+ * g++.dg/gomp/target-3.C: New testcase.
+ * g++.dg/gomp/target-lambda-1.C: New testcase.
+ * g++.dg/gomp/target-lambda-2.C: New testcase.
+ * g++.dg/gomp/target-this-1.C: New testcase.
+ * g++.dg/gomp/target-this-2.C: New testcase.
+ * g++.dg/gomp/target-this-3.C: New testcase.
+ * g++.dg/gomp/target-this-4.C: New testcase.
+ * g++.dg/gomp/target-this-5.C: New testcase.
+ * g++.dg/gomp/this-2.C: Adjust testcase.
+
+2021-12-08 Haochen Jiang <haochen.jiang@intel.com>
+
+ PR target/100738
+ * g++.target/i386/pr100738-1.C: New test.
+
+2021-12-08 Alexandre Oliva <oliva@adacore.com>
+
+ PR middle-end/103149
+ * gcc.target/aarch64/pr103149.c: New.
+
+2021-12-07 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/103607
+ * gfortran.dg/pr103607.f90: New test.
+
+2021-12-07 Marek Polacek <polacek@redhat.com>
+
+ * g++.dg/cpp0x/decltype-bitfield1.C: Change a type to unsigned
+ long long. Only run on longlong64 targets.
+
+2021-12-07 Peter Bergner <bergner@linux.ibm.com>
+
+ PR testsuite/103556
+ PR testsuite/103586
+ * lib/target-supports.exp (check_effective_target_rop_ok): Remove '\n'.
+
+2021-12-07 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/103588
+ * gfortran.dg/pr103588.f90: New test.
+
+2021-12-07 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/103591
+ * gfortran.dg/select_9.f90: New test.
+
+2021-12-07 Marek Polacek <polacek@redhat.com>
+
+ PR c++/95009
+ * g++.dg/cpp0x/decltype-bitfield1.C: New test.
+ * g++.dg/cpp0x/decltype-bitfield2.C: New test.
+
+2021-12-07 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/103594
+ * gcc.dg/pr103594.c: New test.
+
+2021-12-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/103596
+ * gcc.dg/torture/pr103596.c: New testcase.
+
+2021-12-07 YunQiang Su <yunqiang.su@cipunited.com>
+
+ * gcc.target/mips/mips.exp: add unaligned-access
+ * gcc.target/mips/unaligned-2.c: New test.
+ * gcc.target/mips/unaligned-3.c: New test.
+
+2021-12-07 Eugene Rozenfeld <erozen@microsoft.com>
+
+ * gcc.dg/tree-prof/init-array.c: New test for unrolling inner loops.
+
+2021-12-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/103581
+ * gcc.dg/vect/pr103581.c: New testcase.
+
+2021-12-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/103544
+ * gcc.dg/vect/pr103544.c: New testcase.
+
+2021-12-06 Tamar Christina <tamar.christina@arm.com>
+
+ PR rtl-optimization/103404
+ * gcc.target/i386/pr103404.c: New test.
+
+2021-12-06 Hongtao Liu <Hongtao.liu@intel.com>
+ Uroš Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/pr95740.c: New test.
+
+2021-12-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/93614
+ * g++.dg/template/lookup18.C: New test.
+
+2021-12-04 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/gomp/atomic-2.f90: Move now supported code to ...
+ * gfortran.dg/gomp/atomic.f90: here.
+ * gfortran.dg/gomp/atomic-10.f90: New test.
+ * gfortran.dg/gomp/atomic-12.f90: New test.
+ * gfortran.dg/gomp/atomic-15.f90: New test.
+ * gfortran.dg/gomp/atomic-16.f90: New test.
+ * gfortran.dg/gomp/atomic-17.f90: New test.
+ * gfortran.dg/gomp/atomic-18.f90: New test.
+ * gfortran.dg/gomp/atomic-19.f90: New test.
+ * gfortran.dg/gomp/atomic-20.f90: New test.
+ * gfortran.dg/gomp/atomic-22.f90: New test.
+ * gfortran.dg/gomp/atomic-24.f90: New test.
+ * gfortran.dg/gomp/atomic-25.f90: New test.
+ * gfortran.dg/gomp/atomic-26.f90: New test.
+
+2021-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/cpp2a/bit-cast11.C: New test.
+ * g++.dg/cpp2a/bit-cast12.C: New test.
+ * g++.dg/cpp2a/bit-cast13.C: New test.
+ * g++.dg/cpp2a/bit-cast14.C: New test.
+
+2021-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR preprocessor/102432
+ * c-c++-common/gomp/pr102432.c: New test.
+ * c-c++-common/goacc/pr102432.c: New test.
+
+2021-12-04 Alexandre Oliva <oliva@adacore.com>
+
+ PR rtl-optimization/103028
+ * gcc.dg/pr103028.c: New.
+
+2021-12-04 David Edelsohn <dje.gcc@gmail.com>
+
+ * gcc.target/powerpc/vec_reve_1.c: Require VSX.
+
+2021-12-03 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/diagnostic/scope1.C: New test.
+
+2021-12-03 Martin Liska <mliska@suse.cz>
+
+ PR target/101324
+ * gcc.target/powerpc/pr101324.c: New test.
+
+2021-12-03 Peter Bergner <bergner@linux.ibm.com>
+
+ * lib/target-supports.exp (check_effective_target_rop_ok): New function.
+ * gcc.target/powerpc/rop-1.c: Use it.
+ * gcc.target/powerpc/rop-2.c: Likewise.
+ * gcc.target/powerpc/rop-3.c: Likewise.
+ * gcc.target/powerpc/rop-4.c: Likewise.
+ * gcc.target/powerpc/rop-5.c: Likewise.
+
+2021-12-03 Harald Anlauf <anlauf@gmx.de>
+ Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/103505
+ * gfortran.dg/pr103505.f90: New test.
+
+2021-12-03 Marek Polacek <polacek@redhat.com>
+
+ PR c++/103403
+ * g++.dg/cpp1y/decltype-auto2.C: New test.
+ * g++.dg/cpp1y/decltype-auto3.C: New test.
+ * g++.dg/cpp1y/decltype-auto4.C: New test.
+ * g++.dg/cpp1z/decomp-decltype1.C: New test.
+
+2021-12-03 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/103269
+ * gcc.target/i386/pieces-memcpy-17.c: New test.
+ * gcc.target/i386/pieces-memcpy-18.c: Likewise.
+ * gcc.target/i386/pieces-memcpy-19.c: Likewise.
+ * gcc.target/i386/pieces-memcpy-20.c: Likewise.
+ * gcc.target/i386/pieces-memcpy-21.c: Likewise.
+ * gcc.target/i386/pieces-memset-45.c: Likewise.
+ * gcc.target/i386/pieces-memset-46.c: Likewise.
+ * gcc.target/i386/pieces-memset-47.c: Likewise.
+ * gcc.target/i386/pieces-memset-48.c: Likewise.
+ * gcc.target/i386/pieces-memset-49.c: Likewise.
+
+2021-12-03 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/83782
+ * gcc.target/i386/pr83782-1.c: Also scan leal x32.
+ * gcc.target/i386/pr83782-2.c: Likewise.
+
+2021-12-03 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.target/aarch64/sve/pred-combine-and.c: New test.
+
+2021-12-03 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/51469
+ PR target/83782
+ * gcc.target/i386/pr83782-1.c: New test.
+ * gcc.target/i386/pr83782-2.c: Likewise.
+
+2021-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/103456
+ * gcc.dg/ubsan/pr103456.c: Add -ffat-lto-objects to dg-options.
+
+2021-12-03 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/allocate_with_source_26.f90: Adjust testcase.
+ * gfortran.dg/allocate_with_mold_4.f90: New testcase.
+
+2021-12-03 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR testsuite/102735
+ * lib/gcc-dg.exp (process-message): Make sure that we get unique
+ test names.
+
+2021-12-03 Andrew Pinski <apinski@marvell.com>
+
+ PR c++/71792
+ * g++.dg/torture/pr71792.C: New test.
+
+2021-12-02 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/103526
+ * gcc.dg/analyzer/pr103526.c: New test.
+
+2021-12-02 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * gcc.target/powerpc/bfp/scalar-extract-exp-2.c: Adjust expected error
+ message.
+ * gcc.target/powerpc/bfp/scalar-extract-sig-2.c: Likewise.
+ * gcc.target/powerpc/bfp/scalar-insert-exp-2.c: Likewise.
+ * gcc.target/powerpc/bfp/scalar-insert-exp-5.c: Likewise.
+ * gcc.target/powerpc/bfp/scalar-insert-exp-8.c: Likewise.
+ * gcc.target/powerpc/bfp/scalar-test-neg-2.c: Likewise.
+ * gcc.target/powerpc/bfp/scalar-test-neg-3.c: Likewise.
+ * gcc.target/powerpc/bfp/scalar-test-neg-5.c: Likewise.
+ * gcc.target/powerpc/byte-in-set-2.c: Likewise.
+ * gcc.target/powerpc/cmpb-2.c: Likewise.
+ * gcc.target/powerpc/cmpb-3.c: Likewise.
+ * gcc.target/powerpc/cmpb32-2.c: Likewise.
+ * gcc.target/powerpc/crypto-builtin-2.c: Likewise.
+ * gcc.target/powerpc/fold-vec-splat-floatdouble.c: Remove invalid
+ test and adjust xxpermdi count.
+ * gcc.target/powerpc/fold-vec-splat-longlong.c: Remove invalid
+ tests and adjust instruction counts.
+ * gcc.target/powerpc/fold-vec-splat-misc-invalid.c: Adjust expected
+ error messages.
+ * gcc.target/powerpc/int_128bit-runnable.c: Adjust instruction counts.
+ * gcc.target/powerpc/pr80315-1.c: Adjust expected error message.
+ * gcc.target/powerpc/pr80315-2.c: Likewise.
+ * gcc.target/powerpc/pr80315-3.c: Likewise.
+ * gcc.target/powerpc/pr80315-4.c: Likewise.
+ * gcc.target/powerpc/pr88100.c: Likewise.
+ * gcc.target/powerpc/pragma_misc9.c: Likewise.
+ * gcc.target/powerpc/pragma_power8.c: Undef _RS6000_VECDEFINES_H.
+ * gcc.target/powerpc/pragma_power9.c: Likewise.
+ * gcc.target/powerpc/test_fpscr_drn_builtin_error.c: Adjust expected
+ error messages.
+ * gcc.target/powerpc/test_fpscr_rn_builtin_error.c: Likewise.
+ * gcc.target/powerpc/vec-gnb-2.c: Likewise.
+ * gcc.target/powerpc/vsu/vec-all-nez-7.c: Likewise.
+ * gcc.target/powerpc/vsu/vec-any-eqz-7.c: Likewise.
+ * gcc.target/powerpc/vsu/vec-cmpnez-7.c: Likewise.
+ * gcc.target/powerpc/vsu/vec-cntlz-lsbb-2.c: Likewise.
+ * gcc.target/powerpc/vsu/vec-cnttz-lsbb-2.c: Likewise.
+ * gcc.target/powerpc/vsu/vec-xl-len-13.c: Likewise.
+ * gcc.target/powerpc/vsu/vec-xst-len-12.c: Likewise.
+
+2021-12-02 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.target/aarch64/advsimd-intrinsics/shrn-1.c: New test.
+ * gcc.target/aarch64/advsimd-intrinsics/shrn-2.c: New test.
+ * gcc.target/aarch64/advsimd-intrinsics/shrn-3.c: New test.
+ * gcc.target/aarch64/advsimd-intrinsics/shrn-4.c: New test.
+
+2021-12-02 Tamar Christina <tamar.christina@arm.com>
+
+ PR testsuite/103479
+ * gcc.dg/bic-bitmask-18.c: Update regexpr to expect = 0;.
+
+2021-12-02 Marek Polacek <polacek@redhat.com>
+
+ PR c++/94490
+ * g++.dg/ext/integer-pack5.C: New test.
+
+2021-12-02 Marek Polacek <polacek@redhat.com>
+
+ PR c++/103408
+ * g++.dg/cpp23/concepts-err1.C: New test.
+
+2021-12-02 Chung-Lin Tang <cltang@codesourcery.com>
+
+ PR fortran/90030
+ * gfortran.dg/goacc/finalize-1.f: Adjust scan test.
+ * gfortran.dg/gomp/affinity-clause-1.f90: Likewise.
+ * gfortran.dg/gomp/affinity-clause-5.f90: Likewise.
+ * gfortran.dg/gomp/defaultmap-4.f90: Likewise.
+ * gfortran.dg/gomp/defaultmap-5.f90: Likewise.
+ * gfortran.dg/gomp/defaultmap-6.f90: Likewise.
+ * gfortran.dg/gomp/map-3.f90: Likewise.
+ * gfortran.dg/gomp/pr78260-2.f90: Likewise.
+ * gfortran.dg/gomp/pr78260-3.f90: Likewise.
+
+2021-12-01 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/102471
+ * gcc.dg/analyzer/leak-3.c: New test.
+
+2021-12-01 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/102881
+ * gcc.target/i386/pr102811-1.c: New test.
+ * gcc.target/i386/avx512fp16-1c.c (dg-final): Update
+ scan-assembler-times scan strings for ia32 targets.
+ * gcc.target/i386/pr102327-1.c (dg-final): Ditto.
+ * gcc.target/i386/pr102811.c: Rename from ...
+ * gcc.target/i386/avx512vl-vcvtps2ph-pr102811.c: ... this.
+
+2021-12-01 Roger Sayle <roger@nextmovesoftware.com>
+ Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/fold-condneg-1.c: New test case.
+ * gcc.dg/fold-condneg-2.c: New test case.
+ * gcc.dg/fold-condnot-1.c: New test case.
+ * gcc.dg/pr101145-1.c: New test case.
+ * gcc.dg/pr101145-2.c: New test case.
+
+2021-12-01 Peter Bergner <bergner@linux.ibm.com>
+
+ PR middle-end/103127
+ * gcc.target/powerpc/pr103127.c: New test.
+
+2021-12-01 Jason Merrill <jason@redhat.com>
+
+ PR c++/103310
+ * g++.dg/cpp0x/constexpr-fp-except1.C: New test.
+ * g++.dg/cpp1z/constexpr-if36.C: New test.
+ * gcc.dg/tree-ssa/nonzero-1.c: Now well-formed.
+ * gcc.dg/tree-ssa/nonzero-1a.c: New test.
+
+2021-12-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/103517
+ * gcc.dg/vect/pr103517.c: New test.
+
+2021-12-01 Alex Coplan <alex.coplan@arm.com>
+
+ * gcc.target/aarch64/aapcs64/macro-def.h (PTR): Fix typo in
+ comment.
+
+2021-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/100977
+ * g++.dg/cpp/ucnid-1.C: Adjust expected diagnostics.
+ * g++.dg/cpp/ucnid-1-utf8.C: Likewise.
+
+2021-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/102356
+ * gcc.dg/pr102356.c: New test.
+
+2021-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR preprocessor/103415
+ * c-c++-common/cpp/va-opt-8.c: New test.
+ * c-c++-common/Wimplicit-fallthrough-38.c: New test.
+
+2021-12-01 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.dg/bic-bitmask-10.c: Moved to gcc.dg/vect/vect-bic-bitmask-10.c.
+ * gcc.dg/bic-bitmask-11.c: Moved to gcc.dg/vect/vect-bic-bitmask-11.c.
+ * gcc.dg/bic-bitmask-12.c: Moved to gcc.dg/vect/vect-bic-bitmask-12.c.
+ * gcc.dg/bic-bitmask-3.c: Moved to gcc.dg/vect/vect-bic-bitmask-3.c.
+ * gcc.dg/bic-bitmask-23.c: Moved to gcc.dg/vect/vect-bic-bitmask-23.c.
+ * gcc.dg/bic-bitmask-2.c: Moved to gcc.dg/vect/vect-bic-bitmask-2.c.
+ * gcc.dg/bic-bitmask-4.c: Moved to gcc.dg/vect/vect-bic-bitmask-4.c.
+ * gcc.dg/bic-bitmask-5.c: Moved to gcc.dg/vect/vect-bic-bitmask-5.c.
+ * gcc.dg/bic-bitmask-6.c: Moved to gcc.dg/vect/vect-bic-bitmask-6.c.
+ * gcc.dg/bic-bitmask-8.c: Moved to gcc.dg/vect/vect-bic-bitmask-8.c.
+ * gcc.dg/bic-bitmask-9.c: Moved to gcc.dg/vect/vect-bic-bitmask-9.c.
+ * gcc.dg/vect/vect-bic-bitmask-10.c: New file.
+ * gcc.dg/vect/vect-bic-bitmask-11.c: New file.
+ * gcc.dg/vect/vect-bic-bitmask-12.c: New file.
+ * gcc.dg/vect/vect-bic-bitmask-2.c: New file.
+ * gcc.dg/vect/vect-bic-bitmask-23.c: New file.
+ * gcc.dg/vect/vect-bic-bitmask-3.c: New file.
+ * gcc.dg/vect/vect-bic-bitmask-4.c: New file.
+ * gcc.dg/vect/vect-bic-bitmask-5.c: New file.
+ * gcc.dg/vect/vect-bic-bitmask-6.c: New file.
+ * gcc.dg/vect/vect-bic-bitmask-8.c: New file.
+ * gcc.dg/vect/vect-bic-bitmask-9.c: New file.
+
+2021-12-01 Siddhesh Poyarekar <siddhesh@gotplt.org>
+ Martin Liška <mliska@suse.cz>
+
+ PR tree-optimization/103456
+ * gcc.dg/ubsan/pr103456.c: New test.
+
2021-11-30 liuhongt <hongtao.liu@intel.com>
* gcc.target/i386/pr103463.c: New test.
diff --git a/gcc/testsuite/c-c++-common/goacc/deep-copy-arrayofstruct.c b/gcc/testsuite/c-c++-common/goacc/deep-copy-arrayofstruct.c
index d411bcf..4247607 100644
--- a/gcc/testsuite/c-c++-common/goacc/deep-copy-arrayofstruct.c
+++ b/gcc/testsuite/c-c++-common/goacc/deep-copy-arrayofstruct.c
@@ -37,13 +37,12 @@ int main(int argc, char* argv[])
{
int j, k;
for (k = 0; k < S; k++)
-#pragma acc parallel loop copy(m[k].a[0:N]) /* { dg-error "expected .\\\). before .\\\.. token" } */
+#pragma acc parallel loop copy(m[k].a[0:N])
for (j = 0; j < N; j++)
m[k].a[j]++;
for (k = 0; k < S; k++)
-#pragma acc parallel loop copy(m[k].b[0:N], m[k].c[5:N-10]) /* { dg-error "expected .\\\). before .\\\.. token" } */
- /* { dg-error ".m. appears more than once in data clauses" "" { target c++ } .-1 } */
+#pragma acc parallel loop copy(m[k].b[0:N], m[k].c[5:N-10])
for (j = 0; j < N; j++)
{
m[k].b[j]++;
diff --git a/gcc/testsuite/c-c++-common/goacc/pr102432.c b/gcc/testsuite/c-c++-common/goacc/pr102432.c
new file mode 100644
index 0000000..97450f3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/pr102432.c
@@ -0,0 +1,23 @@
+/* PR preprocessor/102432 */
+
+#define loop(x)
+
+void
+foo (void)
+{
+ int i;
+#pragma acc parallel
+#pragma acc loop
+ for (i = 0; i < 64; i++)
+ ;
+}
+
+void
+bar (void)
+{
+ int i;
+ _Pragma ("acc parallel")
+ _Pragma ("acc loop")
+ for (i = 0; i < 64; i++)
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/pr102432.c b/gcc/testsuite/c-c++-common/gomp/pr102432.c
new file mode 100644
index 0000000..89b0f6d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr102432.c
@@ -0,0 +1,23 @@
+/* PR preprocessor/102432 */
+
+#define loop(x)
+
+void
+foo (void)
+{
+ int i;
+#pragma omp parallel
+#pragma omp loop
+ for (i = 0; i < 64; i++)
+ ;
+}
+
+void
+bar (void)
+{
+ int i;
+ _Pragma ("omp parallel")
+ _Pragma ("omp loop")
+ for (i = 0; i < 64; i++)
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/target-enter-data-1.c b/gcc/testsuite/c-c++-common/gomp/target-enter-data-1.c
new file mode 100644
index 0000000..ce766d2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-enter-data-1.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fopenmp -fdump-tree-gimple" } */
+
+struct bar
+{
+ int num_vectors;
+ double *vectors;
+};
+
+struct foo
+{
+ int num_vectors;
+ struct bar *bars;
+ double **vectors;
+};
+
+void func (struct foo *f, int n, int m)
+{
+ #pragma omp target enter data map (to: f->vectors[m][:n])
+ #pragma omp target enter data map (to: f->bars[n].vectors[:m])
+ #pragma omp target enter data map (to: f->bars[n].vectors[:f->bars[n].num_vectors])
+}
+
+/* { dg-final { scan-tree-dump-times "map\\(to:\\*_\[0-9\]+ \\\[len: _\[0-9\]+\\\]\\) map\\(attach:\[^-\]+->vectors \\\[bias: \[^\]\]+\\\]\\)" 3 "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/target-implicit-map-2.c b/gcc/testsuite/c-c++-common/gomp/target-implicit-map-2.c
new file mode 100644
index 0000000..3aa1a8f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-implicit-map-2.c
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-gimple" } */
+#include <stdlib.h>
+
+#define N 10
+
+struct S
+{
+ int a, b;
+ int *ptr;
+ int c, d;
+};
+
+int
+main (void)
+{
+ struct S a;
+ a.ptr = (int *) malloc (sizeof (int) * N);
+
+ for (int i = 0; i < N; i++)
+ a.ptr[i] = 0;
+
+ #pragma omp target enter data map(to: a.ptr, a.ptr[:N])
+
+ #pragma omp target
+ for (int i = 0; i < N; i++)
+ a.ptr[i] += 1;
+
+ #pragma omp target update from(a.ptr[:N])
+
+ for (int i = 0; i < N; i++)
+ if (a.ptr[i] != 1)
+ abort ();
+
+ #pragma omp target map(a.ptr[:N])
+ for (int i = 0; i < N; i++)
+ a.ptr[i] += 1;
+
+ #pragma omp target update from(a.ptr[:N])
+
+ for (int i = 0; i < N; i++)
+ if (a.ptr[i] != 2)
+ abort ();
+
+ #pragma omp target exit data map(from:a.ptr, a.ptr[:N])
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* map\(tofrom:a \[len: [0-9]+\]\[implicit\]\)} "gimple" } } */
+
+/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* map\(tofrom:a \[len: [0-9]+\]\[implicit\]\) map\(tofrom:\*_[0-9]+ \[len: [0-9]+\]\) map\(attach:a\.ptr \[bias: 0\]\)} "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-fp-except1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-fp-except1.C
new file mode 100644
index 0000000..3887a5b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-fp-except1.C
@@ -0,0 +1,4 @@
+// { dg-do compile { target c++11 } }
+// { dg-additional-options -fconstexpr-fp-except }
+
+constexpr double inf = 1./0.;
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-bitfield1.C b/gcc/testsuite/g++.dg/cpp0x/decltype-bitfield1.C
new file mode 100644
index 0000000..27289fb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-bitfield1.C
@@ -0,0 +1,65 @@
+// PR c++/95009
+// { dg-do compile { target { c++11 && longlong64 } } }
+
+struct false_type { static constexpr bool value = false; };
+struct true_type { static constexpr bool value = true; };
+template<class T, class U>
+struct is_same : false_type {};
+template<class T>
+struct is_same<T, T> : true_type {};
+
+struct A {
+ int i : 31;
+ unsigned long long l : 37;
+} a;
+
+void
+g ()
+{
+ // Careful: pre{in,de}crements are lvalues -> deduce T&. */
+ static_assert (is_same<decltype(a.i), int>::value, "");
+ static_assert (is_same<decltype((a.i)), int&>::value, "");
+ static_assert (is_same<decltype(++a.i), int&>::value, "");
+ static_assert (is_same<decltype((++a.i)), int&>::value, "");
+ static_assert (is_same<decltype(a.i++), int>::value, "");
+ static_assert (is_same<decltype((a.i++)), int>::value, "");
+ static_assert (is_same<decltype(--a.i), int&>::value, "");
+ static_assert (is_same<decltype((--a.i)), int&>::value, "");
+ static_assert (is_same<decltype(a.i--), int>::value, "");
+ static_assert (is_same<decltype((a.i--)), int>::value, "");
+ static_assert (is_same<decltype(a.i += 1), int&>::value, "");
+ static_assert (is_same<decltype((a.i += 1)), int&>::value, "");
+ static_assert (is_same<decltype(a.i -= 1), int&>::value, "");
+ static_assert (is_same<decltype((a.i -= 1)), int&>::value, "");
+ static_assert (is_same<decltype(a.i *= 1), int&>::value, "");
+ static_assert (is_same<decltype((a.i *= 1)), int&>::value, "");
+ static_assert (is_same<decltype(+a.i), int>::value, "");
+ static_assert (is_same<decltype((+a.i)), int>::value, "");
+ static_assert (is_same<decltype(-a.i), int>::value, "");
+ static_assert (is_same<decltype((-a.i)), int>::value, "");
+ static_assert (is_same<decltype(~a.i), int>::value, "");
+ static_assert (is_same<decltype((~a.i)), int>::value, "");
+
+ static_assert (is_same<decltype(a.l), unsigned long long>::value, "");
+ static_assert (is_same<decltype((a.l)), unsigned long long&>::value, "");
+ static_assert (is_same<decltype(++a.l), unsigned long long&>::value, "");
+ static_assert (is_same<decltype((++a.l)), unsigned long long&>::value, "");
+ static_assert (is_same<decltype(a.l++), unsigned long long>::value, "");
+ static_assert (is_same<decltype((a.l++)), unsigned long long>::value, "");
+ static_assert (is_same<decltype(--a.l), unsigned long long&>::value, "");
+ static_assert (is_same<decltype((--a.l)), unsigned long long&>::value, "");
+ static_assert (is_same<decltype(a.l--), unsigned long long>::value, "");
+ static_assert (is_same<decltype((a.l--)), unsigned long long>::value, "");
+ static_assert (is_same<decltype(a.l += 1), unsigned long long&>::value, "");
+ static_assert (is_same<decltype((a.l += 1)), unsigned long long&>::value, "");
+ static_assert (is_same<decltype(a.l -= 1), unsigned long long&>::value, "");
+ static_assert (is_same<decltype((a.l -= 1)), unsigned long long&>::value, "");
+ static_assert (is_same<decltype(a.l *= 1), unsigned long long&>::value, "");
+ static_assert (is_same<decltype((a.l *= 1)), unsigned long long&>::value, "");
+ static_assert (is_same<decltype(+a.l), unsigned long long>::value, "");
+ static_assert (is_same<decltype((+a.l)), unsigned long long>::value, "");
+ static_assert (is_same<decltype(-a.l), unsigned long long>::value, "");
+ static_assert (is_same<decltype((-a.l)), unsigned long long>::value, "");
+ static_assert (is_same<decltype(~a.l), unsigned long long>::value, "");
+ static_assert (is_same<decltype((~a.l)), unsigned long long>::value, "");
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-bitfield2.C b/gcc/testsuite/g++.dg/cpp0x/decltype-bitfield2.C
new file mode 100644
index 0000000..4bf9c76
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-bitfield2.C
@@ -0,0 +1,18 @@
+// PR c++/95009
+// { dg-do compile { target c++11 } }
+
+struct A {
+ int i:31;
+};
+
+template<typename>
+void f ()
+{
+}
+
+int main ()
+{
+ A a;
+ f<decltype(a.i += 1)>();
+ f<decltype(++a.i)>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto2.C b/gcc/testsuite/g++.dg/cpp1y/decltype-auto2.C
new file mode 100644
index 0000000..56e011e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto2.C
@@ -0,0 +1,12 @@
+// PR c++/103403
+// { dg-do compile { target c++14 } }
+
+template<typename T>
+auto constexpr RtoL1(T&& r) -> decltype(auto) {
+ return (r);
+};
+int main() {
+ int t;
+ int x{3};
+ decltype (RtoL1(x+0)) y = t;
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto3.C b/gcc/testsuite/g++.dg/cpp1y/decltype-auto3.C
new file mode 100644
index 0000000..914e87f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto3.C
@@ -0,0 +1,12 @@
+// PR c++/103403
+// { dg-do compile { target c++14 } }
+
+int main()
+{
+ int i = 1;
+ int&& r = 1;
+
+ decltype(auto) ri = (i);
+ decltype(auto) rr = (r);
+ decltype((r)) rr2 = (r);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto4.C b/gcc/testsuite/g++.dg/cpp1y/decltype-auto4.C
new file mode 100644
index 0000000..9765857
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto4.C
@@ -0,0 +1,65 @@
+// PR c++/103403
+// { dg-do compile { target c++14 } }
+
+struct false_type { static constexpr bool value = false; };
+struct true_type { static constexpr bool value = true; };
+template<class T, class U>
+struct is_same : false_type {};
+template<class T>
+struct is_same<T, T> : true_type {};
+
+int fn ();
+int &ref ();
+int &&rref ();
+
+struct S {
+ int i;
+ int &r = i;
+};
+
+void
+ids ()
+{
+ const S *s = new S();
+ int i;
+ int &ir = i;
+ decltype(auto) r1 = s->i;
+ static_assert (is_same<decltype(r1), int>::value, "");
+ decltype(auto) r2 = s->r;
+ static_assert (is_same<decltype(r2), int&>::value, "");
+ decltype(auto) r3 = i;
+ static_assert (is_same<decltype(r3), int>::value, "");
+ decltype(auto) r4 = ir;
+ static_assert (is_same<decltype(r4), int&>::value, "");
+}
+
+void
+nonids ()
+{
+ const S *s = new S();
+ int i;
+ int &ir = i;
+ int &&irr = 42;
+ decltype(auto) r1 = fn ();
+ static_assert (is_same<decltype(r1), int>::value, "");
+ decltype(auto) r2 = (fn ());
+ static_assert (is_same<decltype(r2), int>::value, "");
+ decltype(auto) r3 = ref ();
+ static_assert (is_same<decltype(r3), int&>::value, "");
+ decltype(auto) r4 = (ref ());
+ static_assert (is_same<decltype(r4), int&>::value, "");
+ decltype(auto) r5 = rref ();
+ static_assert (is_same<decltype(r5), int&&>::value, "");
+ decltype(auto) r6 = (rref ());
+ static_assert (is_same<decltype(r6), int&&>::value, "");
+ decltype(auto) r8 = (s->i);
+ static_assert (is_same<decltype(r8), const int&>::value, "");
+ decltype(auto) r9 = (s->r);
+ static_assert (is_same<decltype(r9), int&>::value, "");
+ decltype(auto) r10 = (i);
+ static_assert (is_same<decltype(r10), int&>::value, "");
+ decltype(auto) r11 = (ir);
+ static_assert (is_same<decltype(r11), int&>::value, "");
+ decltype(auto) r12 = (irr);
+ static_assert (is_same<decltype(r12), int&>::value, "");
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if36.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if36.C
new file mode 100644
index 0000000..4a1b134
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if36.C
@@ -0,0 +1,19 @@
+// PR c++/103310
+// Test that only manifestly-constant-evaluated comparisons lock a symbol's
+// weakness.
+
+// { dg-do compile { target c++17 } }
+
+extern void weakfn1 (void);
+extern void weakfn2 (void);
+
+void call_weakfn (void)
+{
+ if (weakfn1)
+ weakfn1 ();
+ if constexpr (weakfn2)
+ weakfn2 ();
+}
+
+extern void weakfn1 (void) __attribute__((weak));
+extern void weakfn2 (void) __attribute__((weak)); // { dg-error "declared weak after being used" }
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp-decltype1.C b/gcc/testsuite/g++.dg/cpp1z/decomp-decltype1.C
new file mode 100644
index 0000000..e8ca0fc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp-decltype1.C
@@ -0,0 +1,28 @@
+// PR c++/81176
+// { dg-do compile { target c++17 } }
+
+namespace std {
+ template<typename T> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+struct A {
+ int i;
+ template <int I> int& get() { return i; }
+};
+
+template<> struct std::tuple_size<A> { static const int value = 2; };
+template<int I> struct std::tuple_element<I,A> { using type = int; };
+
+template <class,class> struct same_type;
+template <class T> struct same_type<T,T> {};
+
+void
+foo (A x)
+{
+ auto [ a, b ] = x;
+ decltype(auto) c = a;
+ same_type<decltype(a), int>{};
+ same_type<decltype(c), int>{};
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp23/concepts-err1.C b/gcc/testsuite/g++.dg/cpp23/concepts-err1.C
new file mode 100644
index 0000000..e5bdc54
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/concepts-err1.C
@@ -0,0 +1,6 @@
+// PR c++/103408
+// { dg-do compile { target c++23 } }
+
+template<int>
+concept C = auto([]{}); // { dg-error "constraint" }
+static_assert(C<0>); // { dg-error "non-constant condition for static assertion" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast11.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast11.C
new file mode 100644
index 0000000..a3eb31b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast11.C
@@ -0,0 +1,63 @@
+// P1272R4
+// { dg-do compile { target c++14 } }
+
+struct S { unsigned char a[2]; alignas(sizeof 0) int b; };
+struct T { char a; alignas(sizeof 0) int b; };
+struct U { char a : 1; char : 6; char b : 1; };
+struct V { int a; S b; };
+struct W { unsigned a; T b; };
+
+constexpr bool
+f1 ()
+{
+ T t = { 1, 2 };
+ S s = __builtin_bit_cast (S, t);
+ return s.a[0] == 1;
+}
+
+constexpr bool
+f2 ()
+{
+ U u = { 0, 0 };
+ unsigned char a = __builtin_bit_cast (unsigned char, u);
+ return true;
+}
+
+constexpr bool
+f3 ()
+{
+ T t = { 1, 2 };
+ S s = __builtin_bit_cast (S, t);
+ return s.a[1] == 0;
+}
+
+constexpr bool
+f4 ()
+{
+ U u = { 0, 0 };
+ unsigned char a = __builtin_bit_cast (unsigned char, u);
+ return a == 0; // { dg-error "is not a constant expression" }
+}
+
+constexpr bool
+f5 ()
+{
+ W t = { 1, 2 };
+ V s = __builtin_bit_cast (V, t);
+ return s.b.a[0] == 1;
+}
+
+constexpr bool
+f6 ()
+{
+ W t = { 1, 2 };
+ V s = __builtin_bit_cast (V, t);
+ return s.b.a[1] == 1;
+}
+
+constexpr bool a = f1 ();
+constexpr bool b = f2 ();
+constexpr bool c = f3 (); // { dg-error "accessing uninitialized array element" }
+constexpr bool d = f4 ();
+constexpr bool e = f5 ();
+constexpr bool f = f6 (); // { dg-error "accessing uninitialized array element" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast12.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast12.C
new file mode 100644
index 0000000..9c699dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast12.C
@@ -0,0 +1,68 @@
+// P1272R4
+// { dg-do compile { target c++14 } }
+
+namespace std
+{
+ enum class byte : unsigned char {};
+}
+
+struct S { unsigned char a[2]; alignas(sizeof 0) int b; };
+struct T { char a; alignas(sizeof 0) int b; };
+struct U { char a : 1; char : 6; char b : 1; };
+struct V { int a; S b; };
+struct W { unsigned a; T b; };
+
+constexpr bool
+f1 ()
+{
+ T t = { 1, 2 };
+ S s = __builtin_bit_cast (S, t);
+ return s.a[0] == 1;
+}
+
+constexpr bool
+f2 ()
+{
+ U u = { 0, 0 };
+ unsigned char a = __builtin_bit_cast (unsigned char, u);
+ return true;
+}
+
+constexpr bool
+f3 ()
+{
+ T t = { 1, 2 };
+ S s = __builtin_bit_cast (S, t);
+ return s.a[1] == 0;
+}
+
+constexpr bool
+f4 ()
+{
+ U u = { 0, 0 };
+ unsigned char a = __builtin_bit_cast (unsigned char, u);
+ return a == 0; // { dg-error "is not a constant expression" }
+}
+
+constexpr bool
+f5 ()
+{
+ W t = { 1, 2 };
+ V s = __builtin_bit_cast (V, t);
+ return s.b.a[0] == 1;
+}
+
+constexpr bool
+f6 ()
+{
+ W t = { 1, 2 };
+ V s = __builtin_bit_cast (V, t);
+ return s.b.a[1] == 1;
+}
+
+constexpr bool a = f1 ();
+constexpr bool b = f2 ();
+constexpr bool c = f3 (); // { dg-error "accessing uninitialized array element" }
+constexpr bool d = f4 ();
+constexpr bool e = f5 ();
+constexpr bool f = f6 (); // { dg-error "accessing uninitialized array element" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast13.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast13.C
new file mode 100644
index 0000000..f3bae59
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast13.C
@@ -0,0 +1,63 @@
+// P1272R4
+// { dg-do compile { target c++14 } }
+
+struct S { char a[2]; alignas(sizeof 0) int b; };
+struct T { char a; alignas(sizeof 0) int b; };
+struct U { char a : 1; char : 6; char b : 1; };
+struct V { int a; S b; };
+struct W { unsigned a; T b; };
+
+constexpr bool
+f1 ()
+{
+ T t = { 1, 2 };
+ S s = __builtin_bit_cast (S, t); // { dg-error "accessing uninitialized byte" }
+ return s.a[0] == 1;
+}
+
+constexpr bool
+f2 ()
+{
+ U u = { 0, 0 };
+ char a = __builtin_bit_cast (char, u); // { dg-error "accessing uninitialized byte" }
+ return true;
+}
+
+constexpr bool
+f3 ()
+{
+ T t = { 1, 2 };
+ S s = __builtin_bit_cast (S, t); // { dg-error "accessing uninitialized byte" }
+ return s.a[1] == 0;
+}
+
+constexpr bool
+f4 ()
+{
+ U u = { 0, 0 };
+ char a = __builtin_bit_cast (char, u); // { dg-error "accessing uninitialized byte" }
+ return a == 0;
+}
+
+constexpr bool
+f5 ()
+{
+ W t = { 1, 2 };
+ V s = __builtin_bit_cast (V, t); // { dg-error "accessing uninitialized byte" }
+ return s.b.a[0] == 1;
+}
+
+constexpr bool
+f6 ()
+{
+ W t = { 1, 2 };
+ V s = __builtin_bit_cast (V, t); // { dg-error "accessing uninitialized byte" }
+ return s.b.a[1] == 1;
+}
+
+constexpr bool a = f1 ();
+constexpr bool b = f2 ();
+constexpr bool c = f3 ();
+constexpr bool d = f4 ();
+constexpr bool e = f5 ();
+constexpr bool f = f6 ();
diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast14.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast14.C
new file mode 100644
index 0000000..5e18591
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast14.C
@@ -0,0 +1,75 @@
+// P1272R4
+// { dg-do compile { target c++14 } }
+
+struct S { unsigned char a : 8, b : 5, c : 3, d, e; unsigned int f : 8, g : 24; };
+struct T1 { unsigned char a : 1, : 7, b : 5, c : 3, d, e; unsigned int f : 8, g : 24; };
+struct T2 { unsigned char a : 8, b : 1, : 4, c : 3, d, e; unsigned int f : 8, g : 24; };
+struct T3 { unsigned char a : 8, b : 5, c : 1, : 2, d, e; unsigned int f : 8, g : 24; };
+struct T4 { unsigned char a : 8, b : 5, c : 3, d, e; unsigned int f : 1, : 7, g : 24; };
+
+constexpr bool
+f1 ()
+{
+ T1 t = { 0, 0, 0, 0, 0, 0, 0 };
+ S s = __builtin_bit_cast (S, t);
+ return true;
+}
+
+constexpr bool
+f2 ()
+{
+ T2 t = { 0, 0, 0, 0, 0, 0, 0 };
+ S s = __builtin_bit_cast (S, t);
+ return true;
+}
+
+constexpr bool
+f3 ()
+{
+ T3 t = { 0, 0, 0, 0, 0, 0, 0 };
+ S s = __builtin_bit_cast (S, t);
+ return true;
+}
+
+constexpr bool
+f4 ()
+{
+ T4 t = { 0, 0, 0, 0, 0, 0, 0 };
+ S s = __builtin_bit_cast (S, t); // { dg-error "accessing uninitialized byte" }
+ return true;
+}
+
+constexpr bool
+f5 ()
+{
+ T1 t = { 0, 0, 0, 0, 0, 0, 0 };
+ S s = __builtin_bit_cast (S, t);
+ unsigned char a = s.a;
+ return true;
+}
+
+constexpr bool
+f6 ()
+{
+ T2 t = { 0, 0, 0, 0, 0, 0, 0 };
+ S s = __builtin_bit_cast (S, t);
+ unsigned char b = s.b;
+ return true;
+}
+
+constexpr bool
+f7 ()
+{
+ T3 t = { 0, 0, 0, 0, 0, 0, 0 };
+ S s = __builtin_bit_cast (S, t);
+ unsigned char c = s.c;
+ return true;
+}
+
+constexpr bool a = f1 ();
+constexpr bool b = f2 ();
+constexpr bool c = f3 ();
+constexpr bool d = f4 ();
+constexpr bool e = f5 (); // { dg-error "accessing uninitialized member" }
+constexpr bool f = f6 (); // { dg-error "accessing uninitialized member" }
+constexpr bool g = f7 (); // { dg-error "accessing uninitialized member" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/scope1.C b/gcc/testsuite/g++.dg/diagnostic/scope1.C
new file mode 100644
index 0000000..14d0a1b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/scope1.C
@@ -0,0 +1,12 @@
+// Test for avoiding redundant scope qualifiers.
+
+struct A
+{
+ struct B { };
+ static void f(B,B); // { dg-message {A::f\(B, B\)} }
+};
+
+int main()
+{
+ A::f(42); // { dg-error "no match" }
+}
diff --git a/gcc/testsuite/g++.dg/ext/integer-pack5.C b/gcc/testsuite/g++.dg/ext/integer-pack5.C
new file mode 100644
index 0000000..8493864
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/integer-pack5.C
@@ -0,0 +1,29 @@
+// PR c++/94490
+// { dg-do compile { target c++14 } }
+
+template<class T>
+constexpr int fake_tuple_size_v = 3;
+template<int...> struct intseq {};
+
+// So that it compiles with clang++.
+#if __has_builtin(__make_integer_seq)
+using size_t = decltype(sizeof(1));
+template<typename, size_t... _Indices>
+using _IdxTuple = intseq<_Indices...>;
+
+template<int N> using genseq = __make_integer_seq<_IdxTuple, size_t, N>;
+#else
+template<int N> using genseq = intseq<__integer_pack(N)...>;
+#endif
+
+template<int A, class S = genseq<0 ? A : A>>
+struct arith_result
+{ };
+
+template<typename T>
+auto Mul(const T&)
+{
+ return [](auto) { return arith_result<fake_tuple_size_v<T>> { }; }(0);
+}
+
+auto x = Mul(0);
diff --git a/gcc/testsuite/g++.dg/gomp/target-3.C b/gcc/testsuite/g++.dg/gomp/target-3.C
new file mode 100644
index 0000000..f4d40ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/target-3.C
@@ -0,0 +1,36 @@
+// { dg-do compile }
+// { dg-options "-fopenmp -fdump-tree-gimple" }
+
+struct S
+{
+ int a, b;
+ void bar (int);
+};
+
+void
+S::bar (int x)
+{
+ #pragma omp target map (alloc: a, b)
+ ;
+ #pragma omp target enter data map (alloc: a, b)
+}
+
+template <int N>
+struct T
+{
+ int a, b;
+ void bar (int);
+};
+
+template <int N>
+void
+T<N>::bar (int x)
+{
+ #pragma omp target map (alloc: a, b)
+ ;
+ #pragma omp target enter data map (alloc: a, b)
+}
+
+template struct T<0>;
+
+/* { dg-final { scan-tree-dump-times "map\\(struct:\\*this \\\[len: 2\\\]\\) map\\(alloc:this->a \\\[len: \[0-9\]+\\\]\\) map\\(alloc:this->b \\\[len: \[0-9\]+\\\]\\)" 4 "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/target-lambda-1.C b/gcc/testsuite/g++.dg/gomp/target-lambda-1.C
new file mode 100644
index 0000000..7f83f92
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/target-lambda-1.C
@@ -0,0 +1,94 @@
+// We use 'auto' without a function return type, so specify dialect here
+// { dg-additional-options "-std=c++14 -fdump-tree-gimple" }
+#include <cstdlib>
+#include <cstring>
+
+template <typename L>
+void
+omp_target_loop (int begin, int end, L loop)
+{
+ #pragma omp target teams distribute parallel for
+ for (int i = begin; i < end; i++)
+ loop (i);
+}
+
+struct S
+{
+ int a, len;
+ int *ptr;
+
+ auto merge_data_func (int *iptr, int &b)
+ {
+ auto fn = [=](void) -> bool
+ {
+ bool mapped;
+ #pragma omp target map(from:mapped)
+ {
+ mapped = (ptr != NULL && iptr != NULL);
+ if (mapped)
+ {
+ for (int i = 0; i < len; i++)
+ ptr[i] += a + b + iptr[i];
+ }
+ }
+ return mapped;
+ };
+ return fn;
+ }
+};
+
+int x = 1;
+
+int main (void)
+{
+ const int N = 10;
+ int *data1 = new int[N];
+ int *data2 = new int[N];
+ memset (data1, 0xab, sizeof (int) * N);
+ memset (data1, 0xcd, sizeof (int) * N);
+
+ int val = 1;
+ int &valref = val;
+ #pragma omp target enter data map(alloc: data1[:N], data2[:N])
+
+ omp_target_loop (0, N, [=](int i) { data1[i] = val; });
+ omp_target_loop (0, N, [=](int i) { data2[i] = valref + 1; });
+
+ #pragma omp target update from(data1[:N], data2[:N])
+
+ for (int i = 0; i < N; i++)
+ {
+ if (data1[i] != 1) abort ();
+ if (data2[i] != 2) abort ();
+ }
+
+ #pragma omp target exit data map(delete: data1[:N], data2[:N])
+
+ int b = 8;
+ S s = { 4, N, data1 };
+ auto f = s.merge_data_func (data2, b);
+
+ if (f ()) abort ();
+
+ #pragma omp target enter data map(to: data1[:N])
+ if (f ()) abort ();
+
+ #pragma omp target enter data map(to: data2[:N])
+ if (!f ()) abort ();
+
+ #pragma omp target exit data map(from: data1[:N], data2[:N])
+
+ for (int i = 0; i < N; i++)
+ {
+ if (data1[i] != 0xf) abort ();
+ if (data2[i] != 2) abort ();
+ }
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* firstprivate\(b\) map\(alloc:MEM.* \[len: 0\]\) map\(firstprivate:iptr \[pointer assign, bias: 0\]\) map\(alloc:MEM.* \[len: 0\]\) map\(firstprivate:this \[pointer assign, bias: 0\]\) map\(to:\*__closure \[len: [0-9]+\]\) map\(firstprivate:__closure \[pointer assign, bias: 0\]\) map\(tofrom:\*_[0-9]+ \[len: [0-9]+\]\) map\(always_pointer:__closure->__this \[pointer assign, bias: 0\]\) map\(attach_zero_length_array_section:__closure->__iptr \[bias: 0\]\) map\(attach_zero_length_array_section:_[0-9]+->ptr \[bias: 0\]\) map\(from:mapped \[len: [0-9]+\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\)} "gimple" } } */
+
+/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* firstprivate\(end\) firstprivate\(begin\) map\(to:loop \[len: [0-9]+\]\) map\(attach_zero_length_array_section:loop\.__data1 \[bias: 0\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\)} "gimple" } } */
+
+/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* firstprivate\(end\) firstprivate\(begin\) map\(to:loop \[len: [0-9]+\]\) map\(attach_zero_length_array_section:loop\.__data2 \[bias: 0\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\)} "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/target-lambda-2.C b/gcc/testsuite/g++.dg/gomp/target-lambda-2.C
new file mode 100644
index 0000000..bdf2564
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/target-lambda-2.C
@@ -0,0 +1,35 @@
+// We use 'auto' without a function return type, so specify dialect here
+// { dg-additional-options "-std=c++14 -fdump-tree-gimple" }
+#include <cstdlib>
+
+#define N 10
+int main (void)
+{
+ int X, Y;
+ #pragma omp target map(from: X, Y)
+ {
+ int x = 0, y = 0;
+
+ for (int i = 0; i < N; i++)
+ [&] (int v) { x += v; } (i);
+
+ auto yinc = [&y] { y++; };
+ for (int i = 0; i < N; i++)
+ yinc ();
+
+ X = x;
+ Y = y;
+ }
+
+ int Xs = 0;
+ for (int i = 0; i < N; i++)
+ Xs += i;
+ if (X != Xs)
+ abort ();
+
+ if (Y != N)
+ abort ();
+}
+
+/* Make sure lambda objects do NOT appear in target maps. */
+/* { dg-final { scan-tree-dump {(?n)#pragma omp target num_teams.* map\(from:Y \[len: [0-9]+\]\) map\(from:X \[len: [0-9]+\]\)$} "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/target-this-1.C b/gcc/testsuite/g++.dg/gomp/target-this-1.C
new file mode 100644
index 0000000..de93a3e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/target-this-1.C
@@ -0,0 +1,33 @@
+// { dg-do compile }
+// { dg-additional-options "-fdump-tree-gimple" }
+extern "C" void abort ();
+
+struct S
+{
+ int a, b, c, d;
+
+ int sum (void)
+ {
+ int val = 0;
+ val += a + b + this->c + this->d;
+ return val;
+ }
+
+ int sum_offload (void)
+ {
+ int val = 0;
+ #pragma omp target map(val)
+ val += a + b + this->c + this->d;
+ return val;
+ }
+};
+
+int main (void)
+{
+ S s = { 1, 2, 3, 4 };
+ if (s.sum () != s.sum_offload ())
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump {map\(tofrom:\*this \[len: [0-9]+\]\) map\(firstprivate:this \[pointer assign, bias: 0\]\)} "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/target-this-2.C b/gcc/testsuite/g++.dg/gomp/target-this-2.C
new file mode 100644
index 0000000..8a76bb8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/target-this-2.C
@@ -0,0 +1,49 @@
+// We use 'auto' without a function return type, so specify dialect here
+// { dg-do compile }
+// { dg-additional-options "-std=c++14 -fdump-tree-gimple" }
+
+extern "C" void abort ();
+
+struct T
+{
+ int x, y;
+
+ auto sum_func (int n)
+ {
+ auto fn = [=](int m) -> int
+ {
+ int v;
+ v = (x + y) * n + m;
+ return v;
+ };
+ return fn;
+ }
+
+ auto sum_func_offload (int n)
+ {
+ auto fn = [=](int m) -> int
+ {
+ int v;
+ #pragma omp target map(from:v)
+ v = (x + y) * n + m;
+ return v;
+ };
+ return fn;
+ }
+
+};
+
+int main (void)
+{
+ T a = { 1, 2 };
+
+ auto s1 = a.sum_func (3);
+ auto s2 = a.sum_func_offload (3);
+
+ if (s1 (1) != s2 (1))
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* firstprivate\(n\) map\(alloc:MEM.* \[len: 0\]\) map\(firstprivate:this \[pointer assign, bias: 0\]\) firstprivate\(m\) map\(to:\*__closure \[len: [0-9]+\]\) map\(firstprivate:__closure \[pointer assign, bias: 0\]\) map\(tofrom:\*_[0-9]+ \[len: [0-9]+\]\) map\(always_pointer:__closure->__this \[pointer assign, bias: 0\]\) map\(from:v \[len: [0-9]+\]\)} "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/target-this-3.C b/gcc/testsuite/g++.dg/gomp/target-this-3.C
new file mode 100644
index 0000000..91cfbd6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/target-this-3.C
@@ -0,0 +1,105 @@
+// { dg-do compile }
+// { dg-additional-options "-fdump-tree-gimple" }
+#include <cstdlib>
+#include <cstring>
+extern "C" void abort ();
+
+struct S
+{
+ int * ptr;
+ int ptr_len;
+
+ int *&refptr;
+ int refptr_len;
+
+ bool set_ptr (int n)
+ {
+ bool mapped;
+ #pragma omp target map(from:mapped)
+ {
+ if (ptr != NULL)
+ for (int i = 0; i < ptr_len; i++)
+ ptr[i] = n;
+ mapped = (ptr != NULL);
+ }
+ return mapped;
+ }
+
+ bool set_refptr (int n)
+ {
+ bool mapped;
+ #pragma omp target map(from:mapped)
+ {
+ if (refptr != NULL)
+ for (int i = 0; i < refptr_len; i++)
+ refptr[i] = n;
+ mapped = (refptr != NULL);
+ }
+ return mapped;
+ }
+};
+
+int main (void)
+{
+ #define N 10
+ int *ptr1 = new int[N];
+ int *ptr2 = new int[N];
+
+ memset (ptr1, 0, sizeof (int) * N);
+ memset (ptr2, 0, sizeof (int) * N);
+
+ S s = { ptr1, N, ptr2, N };
+
+ bool mapped;
+ int val = 123;
+
+ mapped = s.set_ptr (val);
+ if (mapped)
+ abort ();
+ if (s.ptr != ptr1)
+ abort ();
+ for (int i = 0; i < N; i++)
+ if (ptr1[i] != 0)
+ abort ();
+
+ mapped = s.set_refptr (val);
+ if (mapped)
+ abort ();
+ if (s.refptr != ptr2)
+ abort ();
+ for (int i = 0; i < N; i++)
+ if (ptr2[i] != 0)
+ abort ();
+
+ #pragma omp target data map(ptr1[:N])
+ mapped = s.set_ptr (val);
+
+ if (!mapped)
+ abort ();
+ if (s.set_refptr (0))
+ abort ();
+ if (s.ptr != ptr1 || s.refptr != ptr2)
+ abort ();
+ for (int i = 0; i < N; i++)
+ if (ptr1[i] != val)
+ abort ();
+
+ #pragma omp target data map(ptr2[:N])
+ mapped = s.set_refptr (val);
+
+ if (!mapped)
+ abort ();
+ if (s.set_ptr (0))
+ abort ();
+ if (s.ptr != ptr1 || s.refptr != ptr2)
+ abort ();
+ for (int i = 0; i < N; i++)
+ if (ptr2[i] != val)
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* map\(alloc:MEM.* \[len: 0\]\) map\(firstprivate:this \[pointer assign, bias: 0\]\) firstprivate\(n\) map\(tofrom:\*this \[len: [0-9]+\]\) map\(firstprivate:this \[pointer assign, bias: 0\]\) map\(alloc:\*_[0-9]+ \[pointer assign, zero-length array section, bias: 0\]\) map\(attach:this->refptr \[bias: 0\]\) map\(from:mapped \[len: [0-9]+\]\)} "gimple" } } */
+
+/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* map\(alloc:MEM.* \[len: 0\]\) map\(firstprivate:this \[pointer assign, bias: 0\]\) firstprivate\(n\) map\(tofrom:\*this \[len: [0-9]+\]\) map\(firstprivate:this \[pointer assign, bias: 0\]\) map\(attach_zero_length_array_section:this->ptr \[bias: 0\]\) map\(from:mapped \[len: [0-9]+\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\)} "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/target-this-4.C b/gcc/testsuite/g++.dg/gomp/target-this-4.C
new file mode 100644
index 0000000..e4b2a71
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/target-this-4.C
@@ -0,0 +1,107 @@
+// We use 'auto' without a function return type, so specify dialect here
+// { dg-additional-options "-std=c++14 -fdump-tree-gimple" }
+#include <cstdlib>
+#include <cstring>
+
+struct T
+{
+ int *ptr;
+ int ptr_len;
+
+ int *&refptr;
+ int refptr_len;
+
+ auto set_ptr_func (int n)
+ {
+ auto fn = [=](void) -> bool
+ {
+ bool mapped;
+ #pragma omp target map(from:mapped)
+ {
+ if (ptr)
+ for (int i = 0; i < ptr_len; i++)
+ ptr[i] = n;
+ mapped = (ptr != NULL);
+ }
+ return mapped;
+ };
+ return fn;
+ }
+
+ auto set_refptr_func (int n)
+ {
+ auto fn = [=](void) -> bool
+ {
+ bool mapped;
+ #pragma omp target map(from:mapped)
+ {
+ if (refptr)
+ for (int i = 0; i < refptr_len; i++)
+ refptr[i] = n;
+ mapped = (refptr != NULL);
+ }
+ return mapped;
+ };
+ return fn;
+ }
+};
+
+int main (void)
+{
+ #define N 10
+ int *ptr1 = new int[N];
+ int *ptr2 = new int[N];
+
+ memset (ptr1, 0, sizeof (int) * N);
+ memset (ptr2, 0, sizeof (int) * N);
+
+ T a = { ptr1, N, ptr2, N };
+
+ auto p1 = a.set_ptr_func (1);
+ auto r2 = a.set_refptr_func (2);
+
+ if (p1 ())
+ abort ();
+ if (r2 ())
+ abort ();
+
+ if (a.ptr != ptr1)
+ abort ();
+ if (a.refptr != ptr2)
+ abort ();
+
+ for (int i = 0; i < N; i++)
+ if (ptr1[i] != 0)
+ abort ();
+
+ for (int i = 0; i < N; i++)
+ if (ptr2[i] != 0)
+ abort ();
+
+ #pragma omp target data map(ptr1[:N], ptr2[:N])
+ {
+ if (!p1 ())
+ abort ();
+ if (!r2 ())
+ abort ();
+ }
+
+ if (a.ptr != ptr1)
+ abort ();
+ if (a.refptr != ptr2)
+ abort ();
+
+ for (int i = 0; i < N; i++)
+ if (ptr1[i] != 1)
+ abort ();
+
+ for (int i = 0; i < N; i++)
+ if (ptr2[i] != 2)
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* firstprivate\(n\) map\(alloc:MEM.* \[len: 0\]\) map\(firstprivate:this \[pointer assign, bias: 0\]\) map\(to:\*__closure \[len: [0-9]+\]\) map\(firstprivate:__closure \[pointer assign, bias: 0\]\) map\(tofrom:\*_[0-9]+ \[len: [0-9]+\]\) map\(always_pointer:__closure->__this \[pointer assign, bias: 0\]\) map\(attach_zero_length_array_section:_[0-9]+->ptr \[bias: 0\]\) map\(from:mapped \[len: [0-9]+\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\)} "gimple" } } */
+
+/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* firstprivate\(n\) map\(alloc:MEM.* \[len: 0\]\) map\(firstprivate:this \[pointer assign, bias: 0\]\) map\(to:\*__closure \[len: [0-9]+\]\) map\(firstprivate:__closure \[pointer assign, bias: 0\]\) map\(tofrom:\*_[0-9]+ \[len: [0-9]+\]\) map\(always_pointer:__closure->__this \[pointer assign, bias: 0\]\) map\(alloc:\*_[0-9]+ \[pointer assign, zero-length array section, bias: 0\]\) map\(attach:_[0-9]+->refptr \[bias: 0\]\) map\(from:mapped \[len: [0-9]+\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\)} "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/target-this-5.C b/gcc/testsuite/g++.dg/gomp/target-this-5.C
new file mode 100644
index 0000000..a9ac74b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/target-this-5.C
@@ -0,0 +1,34 @@
+// { dg-do compile }
+// { dg-additional-options "-fdump-tree-gimple" }
+extern "C" void abort ();
+
+template<typename T>
+struct S
+{
+ T a, b, c, d;
+
+ T sum (void)
+ {
+ T val = 0;
+ val += a + b + this->c + this->d;
+ return val;
+ }
+
+ T sum_offload (void)
+ {
+ T val = 0;
+ #pragma omp target map(val)
+ val += a + b + this->c + this->d;
+ return val;
+ }
+};
+
+int main (void)
+{
+ S<int> s = { 1, 2, 3, 4 };
+ if (s.sum () != s.sum_offload ())
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump {map\(tofrom:\*this \[len: [0-9]+\]\) map\(firstprivate:this \[pointer assign, bias: 0\]\)} "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/this-2.C b/gcc/testsuite/g++.dg/gomp/this-2.C
index d03b8a0..b521a4f 100644
--- a/gcc/testsuite/g++.dg/gomp/this-2.C
+++ b/gcc/testsuite/g++.dg/gomp/this-2.C
@@ -9,14 +9,14 @@ struct S
void
S::bar (int x)
{
- #pragma omp target map (this, x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ #pragma omp target map (this, x) // { dg-error "cannot take the address of .this., which is an rvalue expression" }
;
- #pragma omp target map (this[0], x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ #pragma omp target map (this[0], x)
;
- #pragma omp target update to (this, x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
- #pragma omp target update to (this[0], x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
- #pragma omp target update from (this, x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
- #pragma omp target update from (this[1], x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ #pragma omp target update to (this, x) // { dg-error "cannot take the address of .this., which is an rvalue expression" }
+ #pragma omp target update to (this[0], x)
+ #pragma omp target update from (this, x) // { dg-error "cannot take the address of .this., which is an rvalue expression" }
+ #pragma omp target update from (this[1], x)
}
template <int N>
@@ -29,14 +29,14 @@ template <int N>
void
T<N>::bar (int x)
{
- #pragma omp target map (this, x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ #pragma omp target map (this, x) // { dg-error "cannot take the address of .this., which is an rvalue expression" }
;
- #pragma omp target map (this[0], x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ #pragma omp target map (this[0], x)
;
- #pragma omp target update to (this, x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
- #pragma omp target update to (this[0], x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
- #pragma omp target update from (this, x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
- #pragma omp target update from (this[1], x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ #pragma omp target update to (this, x) // { dg-error "cannot take the address of .this., which is an rvalue expression" }
+ #pragma omp target update to (this[0], x)
+ #pragma omp target update from (this, x) // { dg-error "cannot take the address of .this., which is an rvalue expression" }
+ #pragma omp target update from (this[1], x)
}
template struct T<0>;
diff --git a/gcc/testsuite/g++.dg/pr103024.C b/gcc/testsuite/g++.dg/pr103024.C
new file mode 100644
index 0000000..15e68d4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr103024.C
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fnon-call-exceptions -fharden-compares -fsignaling-nans" } */
+
+struct G4ErrorMatrix {
+ G4ErrorMatrix(int);
+ ~G4ErrorMatrix();
+};
+double PropagateError_charge;
+void PropagateError() {
+ G4ErrorMatrix transf(0);
+ int field(PropagateError_charge && field);
+}
diff --git a/gcc/testsuite/g++.dg/pr103530.C b/gcc/testsuite/g++.dg/pr103530.C
new file mode 100644
index 0000000..c1d2059
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr103530.C
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fharden-compares -Wno-c++11-extensions" } */
+
+enum E:bool
+{ E0, E1 };
+
+int x;
+
+E
+baz (E rtt)
+{
+ return rtt == E0 ? E1 : E0;
+}
+
+bool bar ();
+
+void
+foo (E)
+{
+ E a = x ? E1 : E0;
+ if (bar ())
+ if (bar ())
+ {
+ E b = baz (a);
+ foo (b);
+ }
+}
diff --git a/gcc/testsuite/g++.dg/template/lookup18.C b/gcc/testsuite/g++.dg/template/lookup18.C
new file mode 100644
index 0000000..38f7347
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/lookup18.C
@@ -0,0 +1,17 @@
+// PR c++/93614
+
+template<class T>
+class foo{};
+
+template<class T>
+class template_class_with_struct
+{
+ void my_method() {
+ if(this->b.foo < 1);
+ };
+
+ struct bar
+ {
+ long foo;
+ } b;
+};
diff --git a/gcc/testsuite/g++.dg/torture/pr71792.C b/gcc/testsuite/g++.dg/torture/pr71792.C
new file mode 100644
index 0000000..607774d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr71792.C
@@ -0,0 +1,42 @@
+// { dg-do run { target c++11 } }
+// PR C++/71792
+
+class some_class
+{
+public:
+ unsigned int np : 4;
+ unsigned int nc : 8;
+ unsigned int nc0 : 1;
+};
+
+template<bool what>
+static void test_bug (const some_class &mp) {
+ if (what) {
+ int t = 0;
+ for (auto i = mp.nc0; i < mp.nc; i++) {
+ if (t != i) __builtin_abort ();
+ t++;
+ }
+ }
+}
+
+static void test_ok (const some_class &mp) {
+ int t = 0;
+ for (auto i = mp.nc0; i < mp.nc; i++) {
+ if (t != i) __builtin_abort ();
+ t++;
+ }
+}
+
+int main ()
+{
+ some_class mp;
+ mp.nc0 = 0;
+ mp.nc = 9;
+ mp.np = 3;
+
+ test_bug<true> (mp);
+ test_ok (mp);
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.target/i386/pr100738-1.C b/gcc/testsuite/g++.target/i386/pr100738-1.C
new file mode 100755
index 0000000..ace1866
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr100738-1.C
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx2" } */
+/* { dg-final {scan-assembler-times "vblendvps\[ \\t\]" 2 } } */
+/* { dg-final {scan-assembler-not "vpcmpeqd\[ \\t\]" } } */
+/* { dg-final {scan-assembler-not "vpxor\[ \\t\]" } } */
+
+typedef int v4si __attribute__((vector_size(16)));
+typedef char v16qi __attribute__((vector_size(16)));
+v4si
+foo_1 (v16qi a, v4si b, v4si c, v4si d)
+{
+ return ((v4si)~a) < 0 ? c : d;
+}
+
+v4si
+foo_2 (v16qi a, v4si b, v4si c, v4si d)
+{
+ return ((v4si)~a) >= 0 ? c : d;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/leak-3.c b/gcc/testsuite/gcc.dg/analyzer/leak-3.c
new file mode 100644
index 0000000..d11cc03
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/leak-3.c
@@ -0,0 +1,41 @@
+#include <stdlib.h>
+
+/* Reduced from Juliet 1.3's CWE415_Double_Free__malloc_free_char_67a.c
+ goodG2B which was showing a false leak report in a non-LTO build. */
+
+struct s1
+{
+ char * structFirst;
+};
+void external_fn_1(struct s1 myStruct);
+void test_1()
+{
+ char * data;
+ struct s1 myStruct;
+ data = (char *)malloc(100*sizeof(char));
+ if (data == NULL)
+ exit(-1);
+ myStruct.structFirst = data;
+ external_fn_1(myStruct);
+} /* { dg-bogus "leak of 'data'" } */
+
+/* As above, but with padding before the field. */
+
+struct s2
+{
+ void *padding;
+ char *ptr;
+};
+void external_fn_2(struct s2 myStruct);
+void test_2()
+{
+ char * data;
+ struct s2 myStruct;
+ data = (char *)malloc(100*sizeof(char));
+ if (data == NULL)
+ exit(-1);
+ myStruct.padding = NULL;
+ myStruct.ptr = data;
+ external_fn_2(myStruct);
+} /* { dg-bogus "leak of 'data'" } */
+
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr103526.c b/gcc/testsuite/gcc.dg/analyzer/pr103526.c
new file mode 100644
index 0000000..39d60fd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr103526.c
@@ -0,0 +1,50 @@
+#include <stdlib.h>
+#include <string.h>
+
+struct game_state {
+ const char *word;
+ char *word_state;
+};
+
+const char *const teststr = "test string";
+
+static struct game_state *
+game_new(void)
+{
+ struct game_state tmp = {0};
+ struct game_state *rval = NULL;
+ size_t wordlen;
+
+ tmp.word = teststr;
+ wordlen = strlen(tmp.word);
+ if ((tmp.word_state = malloc(wordlen+1)) == NULL)
+ goto err;
+ if ((rval = malloc(sizeof(*rval))) == NULL)
+ goto err;
+ memcpy(rval, &tmp, sizeof(*rval));
+
+ return (rval);
+err:
+ free(tmp.word_state);
+ free(rval);
+ return (NULL);
+} /* { dg-bogus "leak" } */
+
+static void
+game_free(struct game_state *game)
+{
+ if (game == NULL)
+ return;
+ free(game->word_state);
+ free(game);
+}
+
+int
+main(void)
+{
+ struct game_state *game;
+ if ((game = game_new()) == NULL)
+ exit(1);
+ game_free(game);
+ exit(0);
+}
diff --git a/gcc/testsuite/gcc.dg/bic-bitmask-18.c b/gcc/testsuite/gcc.dg/bic-bitmask-18.c
index 9d11b3b..70bab0c 100644
--- a/gcc/testsuite/gcc.dg/bic-bitmask-18.c
+++ b/gcc/testsuite/gcc.dg/bic-bitmask-18.c
@@ -19,6 +19,6 @@ void fun2(uint32_t *x, int n)
#include "bic-bitmask.h"
-/* { dg-final { scan-tree-dump-times {= 0} 1 dce7 { target vect_int } } } */
+/* { dg-final { scan-tree-dump-times { = 0;} 1 dce7 { target vect_int } } } */
/* { dg-final { scan-tree-dump-not {\s+bic\s+} dce7 { target { aarch64*-*-* } } } } */
diff --git a/gcc/testsuite/gcc.dg/fold-condneg-1.c b/gcc/testsuite/gcc.dg/fold-condneg-1.c
new file mode 100644
index 0000000..c4edd74
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-condneg-1.c
@@ -0,0 +1,59 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int test_i0(int x)
+{
+ return x != 0 ? -x : 0;
+}
+
+int test_i1(int x)
+{
+ return x != 1 ? -x : -1;
+}
+
+int test_im1(int x)
+{
+ return x != -1 ? -x : 1;
+}
+
+unsigned int test_u0(unsigned int x)
+{
+ return x != 0 ? -x : 0;
+}
+
+unsigned int test_u1(unsigned int x)
+{
+ return x != 1 ? -x : ~0u;
+}
+
+unsigned int test_um1(unsigned int x)
+{
+ return x != ~0u ? -x : 1;
+}
+
+unsigned char test_uc0(unsigned char x)
+{
+ return x != 0 ? -x : 0;
+}
+
+unsigned char test_uc1(unsigned char x)
+{
+ return x != 1 ? -x : 255;
+}
+
+unsigned char test_uc127(unsigned char x)
+{
+ return x != 127 ? -x : 129;
+}
+
+unsigned char test_uc128(unsigned char x)
+{
+ return x != 128 ? -x : 128;
+}
+
+unsigned char test_uc255(unsigned char x)
+{
+ return x != 255 ? -x : 1;
+}
+
+/* { dg-final { scan-tree-dump-not "goto" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/fold-condneg-2.c b/gcc/testsuite/gcc.dg/fold-condneg-2.c
new file mode 100644
index 0000000..1af2463
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-condneg-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftrapv -fdump-tree-optimized" } */
+
+#define INT_MIN (-__INT_MAX__ - 1)
+
+int test(int x)
+{
+ return x != INT_MIN ? -x : INT_MIN;
+}
+
+/* { dg-final { scan-tree-dump "goto" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/fold-condnot-1.c b/gcc/testsuite/gcc.dg/fold-condnot-1.c
new file mode 100644
index 0000000..75d558c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-condnot-1.c
@@ -0,0 +1,84 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int test_i0(int x)
+{
+ return x != 0 ? ~x : ~0;
+}
+
+int test_i1(int x)
+{
+ return x != 1 ? ~x : -2;
+}
+
+int test_im1(int x)
+{
+ return x != ~0 ? ~x : 0;
+}
+
+unsigned int test_u0(unsigned int x)
+{
+ return x != 0 ? ~x : ~0;
+}
+
+unsigned int test_u1(unsigned int x)
+{
+ return x != 1 ? ~x : ~1u;
+}
+
+unsigned int test_um1(unsigned int x)
+{
+ return x != ~0u ? ~x : 0;
+}
+
+signed char test_c0(signed char x)
+{
+ return x != 0 ? ~x : -1;
+}
+
+signed char test_c1(signed char x)
+{
+ return x != 1 ? ~x : -2;
+}
+
+signed char test_cm1(signed char x)
+{
+ return x != -1 ? ~x : 0;
+}
+
+signed char test_cm128(signed char x)
+{
+ return x != -128 ? ~x : 127;
+}
+
+signed char test_c127(signed char x)
+{
+ return x != 127 ? ~x : -128;
+}
+
+unsigned char test_uc0(unsigned char x)
+{
+ return x != 0 ? ~x : 255;
+}
+
+unsigned char test_uc1(unsigned char x)
+{
+ return x != 1 ? ~x : 254;
+}
+
+unsigned char test_uc127(unsigned char x)
+{
+ return x != 127 ? ~x : 128;
+}
+
+unsigned char test_uc128(unsigned char x)
+{
+ return x != 128 ? ~x : 127;
+}
+
+unsigned char test_ucm1(unsigned char x)
+{
+ return x != 255 ? ~x : 0;
+}
+
+/* { dg-final { scan-tree-dump-not "goto" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/gomp/target-3.c b/gcc/testsuite/gcc.dg/gomp/target-3.c
new file mode 100644
index 0000000..3e79212
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/target-3.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-gimple" } */
+
+struct S
+{
+ int a, b;
+};
+
+void foo (struct S *s)
+{
+ #pragma omp target map (alloc: s->a, s->b)
+ ;
+ #pragma omp target enter data map (alloc: s->a, s->b)
+}
+
+/* { dg-final { scan-tree-dump-times "map\\(struct:\\*s \\\[len: 2\\\]\\) map\\(alloc:s->a \\\[len: \[0-9\]+\\\]\\) map\\(alloc:s->b \\\[len: \[0-9\]+\\\]\\)" 2 "gimple" } } */
diff --git a/gcc/testsuite/gcc.dg/loop-unswitch-1.c b/gcc/testsuite/gcc.dg/loop-unswitch-1.c
index de2fb2c..f9d628d 100644
--- a/gcc/testsuite/gcc.dg/loop-unswitch-1.c
+++ b/gcc/testsuite/gcc.dg/loop-unswitch-1.c
@@ -1,6 +1,6 @@
/* For PR rtl-optimization/27735 */
/* { dg-do compile } */
-/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-details -fno-finite-loops" } */
+/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-all -fno-finite-loops" } */
void set_color(void);
void xml_colorize_line(unsigned int *p, int state)
@@ -33,4 +33,4 @@ parse_tag: ;
}
/* Test that we actually unswitched something. */
-/* { dg-final { scan-tree-dump ";; Unswitching loop" "unswitch" } } */
+/* { dg-final { scan-tree-dump "Unswitching loop" "unswitch" } } */
diff --git a/gcc/testsuite/gcc.dg/loop-unswitch-2.c b/gcc/testsuite/gcc.dg/loop-unswitch-2.c
index f8e99bd..e92ae553 100644
--- a/gcc/testsuite/gcc.dg/loop-unswitch-2.c
+++ b/gcc/testsuite/gcc.dg/loop-unswitch-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-details -fno-thread-jumps" } */
+/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-all -fno-thread-jumps" } */
void foo (float **a, float **b, float *c, int n, int m, int l)
{
@@ -11,6 +11,5 @@ void foo (float **a, float **b, float *c, int n, int m, int l)
c[i] += a[i][k] * b[k][j];
}
-/* { dg-final { scan-tree-dump-times "guard hoisted" 3 "unswitch" } } */
+/* { dg-final { scan-tree-dump-times "Guard hoisted" 3 "unswitch" } } */
/* { dg-final { scan-tree-dump-not "Invalid sum" "unswitch" } } */
-
diff --git a/gcc/testsuite/gcc.dg/loop-unswitch-3.c b/gcc/testsuite/gcc.dg/loop-unswitch-3.c
index 089b610..31a90ef 100644
--- a/gcc/testsuite/gcc.dg/loop-unswitch-3.c
+++ b/gcc/testsuite/gcc.dg/loop-unswitch-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-details" } */
+/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-all" } */
#include <stdlib.h>
#define N 32
@@ -21,7 +21,4 @@ float *foo(int ustride, int size, float *src)
return buffer;
}
-/* { dg-final { scan-tree-dump-times "guard hoisted" 1 "unswitch" } } */
-/* { dg-final { scan-tree-dump-not "Invalid sum" "unswitch" } } */
-
-
+/* { dg-final { scan-tree-dump-times "Guard hoisted" 1 "unswitch" } } */
diff --git a/gcc/testsuite/gcc.dg/loop-unswitch-4.c b/gcc/testsuite/gcc.dg/loop-unswitch-4.c
index 320a1cd..05d0fe8 100644
--- a/gcc/testsuite/gcc.dg/loop-unswitch-4.c
+++ b/gcc/testsuite/gcc.dg/loop-unswitch-4.c
@@ -49,4 +49,3 @@ int main()
return 0;
}
-
diff --git a/gcc/testsuite/gcc.dg/loop-unswitch-5.c b/gcc/testsuite/gcc.dg/loop-unswitch-5.c
index b41e853..7788000 100644
--- a/gcc/testsuite/gcc.dg/loop-unswitch-5.c
+++ b/gcc/testsuite/gcc.dg/loop-unswitch-5.c
@@ -1,6 +1,6 @@
/* PR middle-end/71691 */
/* { dg-do run } */
-/* { dg-options "-fno-tree-vrp -O2 -funswitch-loops -fdump-tree-unswitch-details" } */
+/* { dg-options "-fno-tree-vrp -O2 -funswitch-loops" } */
/* Note: The -fno-tree-vrp above is only there to avoid VRP papering
over the problem. */
diff --git a/gcc/testsuite/gcc.dg/pr101145-1.c b/gcc/testsuite/gcc.dg/pr101145-1.c
new file mode 100644
index 0000000..e6f7923
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr101145-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+unsigned foo(unsigned val, unsigned start)
+{
+ unsigned cnt = 0;
+ for (unsigned i = start; i > val; ++i)
+ cnt++;
+ return cnt;
+}
+
+/* { dg-final { scan-tree-dump "cnt_\[0-9\] = -start_\[0-9\]\\(D\\);" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr101145-2.c b/gcc/testsuite/gcc.dg/pr101145-2.c
new file mode 100644
index 0000000..6ecfeb2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr101145-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+unsigned foo(unsigned val, unsigned start)
+{
+ unsigned cnt = 0;
+ unsigned i = start;
+ do {
+ cnt++;
+ i++;
+ } while (i > val);
+ return cnt;
+}
+
+/* { dg-final { scan-tree-dump "cnt_\[0-9\] = start_\[0-9\]\\(D\\) >= val_\[0-9\]\\(D\\) \\? _\[0-9\] : 1;" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr103028.c b/gcc/testsuite/gcc.dg/pr103028.c
new file mode 100644
index 0000000..df96c62
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr103028.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-fif-conversion2 -Og" } */
+/* { dg-options "-fif-conversion2 -Og -march=z9-ec" { target { s390x-*-* } } } */
+
+unsigned char x;
+int foo(void)
+{
+ unsigned long long i = x;
+ i = i + 0x80000000;
+ unsigned long long t = 0xffffffff;
+
+ if (i > t) {
+ unsigned long long ii;
+ asm("":"=g"(ii):"0"(i));
+ if ((ii <= t))
+ __builtin_trap();
+ return x;
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr103594.c b/gcc/testsuite/gcc.dg/pr103594.c
new file mode 100644
index 0000000..0eae239
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr103594.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target fpic } } */
+/* { dg-options "-O1 -fpic" } */
+
+int regex_subst(void)
+{
+ const void *subst = "";
+ return (*(int (*)(int))subst) (0);
+}
+
+int foobar (void)
+{
+ int x;
+ return (*(int (*)(void))&x) ();
+}
diff --git a/gcc/testsuite/gcc.dg/sibcall-1.c b/gcc/testsuite/gcc.dg/sibcall-1.c
index 367ee43..f2bd3ad 100644
--- a/gcc/testsuite/gcc.dg/sibcall-1.c
+++ b/gcc/testsuite/gcc.dg/sibcall-1.c
@@ -47,7 +47,7 @@ recurser_void (int n)
void *trackpoint;
-void __attribute__ ((noinline))
+void __attribute__ ((noipa))
track (int n)
{
char stackpos[1];
diff --git a/gcc/testsuite/gcc.dg/sibcall-10.c b/gcc/testsuite/gcc.dg/sibcall-10.c
index 4ac2ee4..dcb3e6a 100644
--- a/gcc/testsuite/gcc.dg/sibcall-10.c
+++ b/gcc/testsuite/gcc.dg/sibcall-10.c
@@ -46,7 +46,7 @@ int main ()
reasonably sure is to make them have the same contents (regarding the
n tests). */
-static void __attribute__((noinline)) ATTR
+static void __attribute__((noipa)) ATTR
recurser_void1 (void)
{
if (n == 0 || n == 7 || n == 8)
@@ -58,7 +58,7 @@ recurser_void1 (void)
recurser_void2 ();
}
-static void __attribute__((noinline)) ATTR
+static void __attribute__((noipa)) ATTR
recurser_void2 (void)
{
if (n == 0 || n == 7 || n == 8)
@@ -73,7 +73,7 @@ recurser_void2 (void)
void *trackpoint;
-void __attribute__ ((noinline))
+void __attribute__ ((noipa))
track ()
{
char stackpos[1];
diff --git a/gcc/testsuite/gcc.dg/sibcall-2.c b/gcc/testsuite/gcc.dg/sibcall-2.c
index a626273..0d4df82 100644
--- a/gcc/testsuite/gcc.dg/sibcall-2.c
+++ b/gcc/testsuite/gcc.dg/sibcall-2.c
@@ -38,7 +38,7 @@ recurser_void (void)
void *trackpoint;
-void __attribute__ ((noinline))
+void __attribute__ ((noipa))
track ()
{
char stackpos[1];
diff --git a/gcc/testsuite/gcc.dg/sibcall-3.c b/gcc/testsuite/gcc.dg/sibcall-3.c
index 9962b64..80555cf 100644
--- a/gcc/testsuite/gcc.dg/sibcall-3.c
+++ b/gcc/testsuite/gcc.dg/sibcall-3.c
@@ -40,7 +40,7 @@ int main ()
reasonably sure is to make them have the same contents (regarding the
n tests). */
-static void __attribute__((noinline)) ATTR
+static void __attribute__((noipa)) ATTR
recurser_void1 (int n)
{
if (n == 0 || n == 7 || n == 8)
@@ -52,7 +52,7 @@ recurser_void1 (int n)
recurser_void2 (n + 1);
}
-static void __attribute__((noinline)) ATTR
+static void __attribute__((noipa)) ATTR
recurser_void2 (int n)
{
if (n == 0 || n == 7 || n == 8)
@@ -66,7 +66,7 @@ recurser_void2 (int n)
void *trackpoint;
-void __attribute__ ((noinline))
+void __attribute__ ((noipa))
track (int n)
{
char stackpos[1];
diff --git a/gcc/testsuite/gcc.dg/sibcall-4.c b/gcc/testsuite/gcc.dg/sibcall-4.c
index 9ba1d16..97086bb 100644
--- a/gcc/testsuite/gcc.dg/sibcall-4.c
+++ b/gcc/testsuite/gcc.dg/sibcall-4.c
@@ -41,7 +41,7 @@ int main ()
reasonably sure is to make them have the same contents (regarding the
n tests). */
-static void __attribute__((noinline)) ATTR
+static void __attribute__((noipa)) ATTR
recurser_void1 (void)
{
if (n == 0 || n == 7 || n == 8)
@@ -53,7 +53,7 @@ recurser_void1 (void)
recurser_void2 ();
}
-static void __attribute__((noinline)) ATTR
+static void __attribute__((noipa)) ATTR
recurser_void2 (void)
{
if (n == 0 || n == 7 || n == 8)
@@ -67,7 +67,7 @@ recurser_void2 (void)
void *trackpoint;
-void __attribute__ ((noinline))
+void __attribute__ ((noipa))
track ()
{
char stackpos[1];
diff --git a/gcc/testsuite/gcc.dg/sibcall-9.c b/gcc/testsuite/gcc.dg/sibcall-9.c
index c06acdb..006dc0d 100644
--- a/gcc/testsuite/gcc.dg/sibcall-9.c
+++ b/gcc/testsuite/gcc.dg/sibcall-9.c
@@ -45,7 +45,7 @@ int main ()
reasonably sure is to make them have the same contents (regarding the
n tests). */
-static void __attribute__((noinline)) ATTR
+static void __attribute__((noipa)) ATTR
recurser_void1 (int n)
{
if (n == 0 || n == 7 || n == 8)
@@ -57,7 +57,7 @@ recurser_void1 (int n)
recurser_void2 (n + 1);
}
-static void __attribute__((noinline)) ATTR
+static void __attribute__((noipa)) ATTR
recurser_void2 (int n)
{
if (n == 0 || n == 7 || n == 8)
@@ -72,7 +72,7 @@ recurser_void2 (int n)
void *trackpoint;
-void __attribute__ ((noinline))
+void __attribute__ ((noipa))
track (int n)
{
char stackpos[1];
diff --git a/gcc/testsuite/gcc.dg/torture/pr103596.c b/gcc/testsuite/gcc.dg/torture/pr103596.c
new file mode 100644
index 0000000..4f65c36
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr103596.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-additional-options "--param case-values-threshold=1" } */
+
+int n;
+
+void
+qux (int a)
+{
+}
+
+int
+baz (void)
+{
+ return -1;
+}
+
+__attribute__ ((returns_twice)) int
+bar (int b)
+{
+ if (n != 0)
+ {
+ if (b != 2)
+ if (b != 0)
+ return n + b;
+
+ if (n == 2)
+ return 0;
+ }
+}
+
+void
+foo (void)
+{
+ qux (n);
+ bar (baz ());
+}
diff --git a/gcc/testsuite/gcc.dg/tree-prof/init-array.c b/gcc/testsuite/gcc.dg/tree-prof/init-array.c
new file mode 100644
index 0000000..0f7a5c8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-prof/init-array.c
@@ -0,0 +1,43 @@
+/* { dg-options "-O3 -fdump-tree-cunrolli-details" } */
+
+static int s[10][10][10];
+static int d[10][10][10];
+
+__attribute__((noipa))
+int array()
+{
+ int i;
+ register int j, k;
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ d[i][j][k] = s[i][j][k];
+
+ return(0);
+}
+
+__attribute__((noipa))
+void TestBench()
+{
+ for (int i = 0; i < 150000; ++i)
+ {
+ array();
+ }
+}
+
+int main(int argc, char *argv[])
+{
+
+ TestBench();
+
+ if (d[9][9][9] == 0 && s[9][9][9] == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+/* { dg-final-use { scan-tree-dump-times "loop with 10 iterations completely unrolled" 2 "cunrolli"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c b/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c
index c9d438e..aa21b71 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c
@@ -1,12 +1,13 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fdelete-null-pointer-checks -fdump-tree-optimized" } */
/* { dg-require-weak "" } */
/* { dg-skip-if "" keeps_null_pointer_checks } */
-extern int a; /* { dg-error "declared weak after being used" } */
+extern int a;
int
t()
{
+ /* { dg-final { scan-tree-dump "&a != 0" "optimized" } } */
return &a!=0;
}
extern int a __attribute__ ((weak));
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1a.c b/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1a.c
new file mode 100644
index 0000000..3d1eb97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1a.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdelete-null-pointer-checks -fdump-tree-optimized" } */
+
+/* { dg-skip-if "" keeps_null_pointer_checks } */
+extern int a;
+int
+t()
+{
+ /* { dg-final { scan-tree-dump-not "&a != 0" "optimized" } } */
+ return &a!=0;
+}
diff --git a/gcc/testsuite/gcc.dg/ubsan/pr103456.c b/gcc/testsuite/gcc.dg/ubsan/pr103456.c
index 20322fb..7624fa8 100644
--- a/gcc/testsuite/gcc.dg/ubsan/pr103456.c
+++ b/gcc/testsuite/gcc.dg/ubsan/pr103456.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/103456 */
/* { dg-do compile } */
-/* { dg-options "-fsanitize=undefined -O -fdump-tree-objsz" } */
+/* { dg-options "-fsanitize=undefined -O -fdump-tree-objsz -ffat-lto-objects" } */
static char *multilib_options = "m64/m32";
diff --git a/gcc/testsuite/gcc.dg/vect/pr103517.c b/gcc/testsuite/gcc.dg/vect/pr103517.c
new file mode 100644
index 0000000..de87fc4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr103517.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=skylake-avx512" { target x86_64-*-* i?86-*-* } } */
+
+int a;
+short b, c;
+extern short d[];
+void e() {
+ for (short f = 1; f < (short)a; f += 2)
+ if (d[f + 1]) {
+ b = d[f];
+ c = d[f + 1];
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr103544.c b/gcc/testsuite/gcc.dg/vect/pr103544.c
new file mode 100644
index 0000000..c8bdee8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr103544.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3" } */
+/* { dg-additional-options "-march=haswell" { target x86_64-*-* i?86-*-* } } */
+
+int crash_me(char* ptr, unsigned long size)
+{
+ short result[16] = {0};
+
+ unsigned long no_iters = 0;
+ for(unsigned long i = 0; i < size - 12; i+= 13){
+ for(unsigned long j = 0; j < 12; j++){
+ result[j] += ptr[i + j] - '0';
+ }
+ no_iters++;
+ }
+
+ int result_int = 0;
+ for(int j = 0; j < 12; j++){
+ int bit_value = result[j] > no_iters/2 ? 1 : 0;
+ result_int |= bit_value;
+ }
+
+ return result_int;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr103581.c b/gcc/testsuite/gcc.dg/vect/pr103581.c
new file mode 100644
index 0000000..d072748
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr103581.c
@@ -0,0 +1,59 @@
+/* { dg-additional-options "-mavx2 -mtune-ctrl=use_gather" { target avx2_runtime } } */
+
+#include "tree-vect.h"
+
+#define MASKGATHER(SUFF, TYPE1, TYPE2) \
+TYPE1 * __attribute__((noipa)) \
+maskgather ## SUFF (int n, TYPE2 *indices, TYPE1 *data) \
+{ \
+ TYPE1 *out = __builtin_malloc (sizeof (TYPE1) * n); \
+ for (int i = 0; i < n; ++i) \
+ { \
+ TYPE2 d = indices[i]; \
+ if (d > 1) \
+ out[i] = data[d]; \
+ } \
+ return out; \
+}
+
+MASKGATHER(udiusi, unsigned long long, unsigned int)
+MASKGATHER(usiusi, unsigned int, unsigned int)
+MASKGATHER(udiudi, unsigned long long, unsigned long long)
+MASKGATHER(usiudi, unsigned int, unsigned long long)
+
+int
+main()
+{
+ check_vect ();
+
+ unsigned int idx4[32], data4[32];
+ unsigned long long idx8[32], data8[32];
+ for (int i = 0; i < 32; ++i)
+ {
+ idx4[i] = i;
+ idx8[i] = i;
+ data4[i] = i;
+ data8[i] = i;
+ }
+ unsigned long long *resudiusi = maskgatherudiusi (16, idx4, data8);
+ unsigned int *resusiusi = maskgatherusiusi (16, idx4, data4);
+ unsigned long long *resudiudi = maskgatherudiudi (16, idx8, data8);
+ unsigned int *resusiudi = maskgatherusiudi (16, idx8, data4);
+ for (int i = 0; i < 16; ++i)
+ {
+ unsigned int d = idx4[i];
+ if (d > 1)
+ {
+ if (resudiusi[i] != data4[d])
+ __builtin_abort ();
+ if (resudiudi[i] != data4[d])
+ __builtin_abort ();
+ if (resusiudi[i] != data4[d])
+ __builtin_abort ();
+ if (resusiusi[i] != data4[d])
+ __builtin_abort ();
+ }
+ }
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/macro-def.h b/gcc/testsuite/gcc.target/aarch64/aapcs64/macro-def.h
index 72a4706..e681de6 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/macro-def.h
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/macro-def.h
@@ -63,7 +63,7 @@
#define ANON_PROMOTED(type,val,type_promoted, val_promoted, offset,...) \
ANON(type_promoted, val_promoted, offset, __VA_ARGS__)
/* Composite larger than 16 bytes is replaced by a pointer to a copy prepared
- by the caller, so here we extrat the pointer, deref it and compare the
+ by the caller, so here we extract the pointer, deref it and compare the
content with that of the original one. */
#define PTR(type, val, offset, ...) { \
type * ptr; \
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-1.c
new file mode 100644
index 0000000..4bc3aa9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+#include <arm_neon.h>
+
+uint8x16_t foo (uint32x4_t a, uint32x4_t b)
+{
+ uint16x4_t a1 = vrshrn_n_u32 (a, 16);
+ uint16x8_t b1 = vrshrn_high_n_u32 (a1, b, 16);
+ return vrshrn_high_n_u16 (vrshrn_n_u16 (b1, 8), b1, 8);
+}
+
+/* { dg-final { scan-assembler-times {\tmovi\t} 1 } } */
+/* { dg-final { scan-assembler-times {\traddhn\t} 2 } } */
+/* { dg-final { scan-assembler-times {\traddhn2\t} 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-2.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-2.c
new file mode 100644
index 0000000..09d913e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target { aarch64*-*-* } } } */
+
+#include <arm_neon.h>
+
+uint32x4_t foo (uint64x2_t a, uint64x2_t b)
+{
+ return vrshrn_high_n_u64 (vrshrn_n_u64 (a, 32), b, 32);
+}
+
+/* { dg-final { scan-assembler-times {\traddhn\t} 1 } } */
+/* { dg-final { scan-assembler-times {\traddhn2\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-3.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-3.c
new file mode 100644
index 0000000..bdccbb3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-3.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target { aarch64*-*-* } } } */
+
+#include <arm_neon.h>
+
+uint16x8_t foo (uint32x4_t a, uint32x4_t b)
+{
+ return vrshrn_high_n_u32 (vrshrn_n_u32 (a, 16), b, 16);
+}
+
+/* { dg-final { scan-assembler-times {\traddhn\t} 1 } } */
+/* { dg-final { scan-assembler-times {\traddhn2\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-4.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-4.c
new file mode 100644
index 0000000..4b23edd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/shrn-4.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target { aarch64*-*-* } } } */
+
+#include <arm_neon.h>
+
+uint8x16_t foo (uint16x8_t a, uint16x8_t b)
+{
+ return vrshrn_high_n_u16 (vrshrn_n_u16 (a, 8), b, 8);
+}
+
+/* { dg-final { scan-assembler-times {\traddhn\t} 1 } } */
+/* { dg-final { scan-assembler-times {\traddhn2\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/pr103149.c b/gcc/testsuite/gcc.target/aarch64/pr103149.c
new file mode 100644
index 0000000..906bc9a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr103149.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+sve -O2 -fharden-conditional-branches -fno-tree-scev-cprop" } */
+
+/* -fharden-conditional-branches prevents optimization of its redundant
+ compares by detaching values from the operands with asm statements. They
+ used to require GENERAL_REGS, but the vectorized booleans, generated while
+ vectorizing this function, can't be held in GENERAL_REGS. */
+
+void
+foo (int *p)
+{
+ while (*p < 1)
+ ++*p;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pred-combine-and.c b/gcc/testsuite/gcc.target/aarch64/sve/pred-combine-and.c
new file mode 100644
index 0000000..ee92734
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pred-combine-and.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+void f5(float * restrict z0, float * restrict z1, float *restrict x, float * restrict y, float c, int n)
+{
+ for (int i = 0; i < n; i++) {
+ float a = x[i];
+ float b = y[i];
+ if (a > b) {
+ z0[i] = a + b;
+ if (a > c) {
+ z1[i] = a - b;
+ }
+ }
+ }
+}
+
+/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.s, p[0-9]+/z, z[0-9]+\.s, z[0-9]+\.s} 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-1c.c b/gcc/testsuite/gcc.target/i386/avx512fp16-1c.c
index b41a90b..0966886 100644
--- a/gcc/testsuite/gcc.target/i386/avx512fp16-1c.c
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-1c.c
@@ -1,8 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-mavx512fp16 -O2" } */
-/* { dg-final { scan-assembler-times "vmovsh" 1 } } */
-/* { dg-final { scan-assembler-times "vpblendw" 1 } } */
-/* { dg-final { scan-assembler "vpbroadcastw" } } */
+
+/* { dg-final { scan-assembler-times "vpbroadcastw" 1 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vpblendw" 1 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vmovsh" 1 { target { ! ia32 } } } } */
+
+/* { dg-final { scan-assembler-times "vpinsrw" 2 { target ia32 } } } */
typedef _Float16 __v8hf __attribute__ ((__vector_size__ (16)));
typedef _Float16 __m128h __attribute__ ((__vector_size__ (16), __may_alias__));
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memcpy-17.c b/gcc/testsuite/gcc.target/i386/pieces-memcpy-17.c
new file mode 100644
index 0000000..28ab7a6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pieces-memcpy-17.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64 -mprefer-vector-width=256 -mavx512f -mmove-max=512" } */
+
+extern char *dst, *src;
+
+void
+foo (void)
+{
+ __builtin_memcpy (dst, src, 66);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu64\[ \\t\]+\[^\n\]*%zmm" 2 } } */
+/* No need to dynamically realign the stack here. */
+/* { dg-final { scan-assembler-not "and\[^\n\r]*%\[re\]sp" } } */
+/* Nor use a frame pointer. */
+/* { dg-final { scan-assembler-not "%\[re\]bp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memcpy-18.c b/gcc/testsuite/gcc.target/i386/pieces-memcpy-18.c
new file mode 100644
index 0000000..b15a0db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pieces-memcpy-18.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=sapphirerapids" } */
+
+extern char *dst, *src;
+
+void
+foo (void)
+{
+ __builtin_memcpy (dst, src, 66);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu64\[ \\t\]+\[^\n\]*%zmm" 2 } } */
+/* No need to dynamically realign the stack here. */
+/* { dg-final { scan-assembler-not "and\[^\n\r]*%\[re\]sp" } } */
+/* Nor use a frame pointer. */
+/* { dg-final { scan-assembler-not "%\[re\]bp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memcpy-19.c b/gcc/testsuite/gcc.target/i386/pieces-memcpy-19.c
new file mode 100644
index 0000000..a5b5b61
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pieces-memcpy-19.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=sapphirerapids -mmove-max=128 -mstore-max=128" } */
+
+extern char *dst, *src;
+
+void
+foo (void)
+{
+ __builtin_memcpy (dst, src, 66);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu\[ \\t\]+\[^\n\]*%xmm" 8 } } */
+/* No need to dynamically realign the stack here. */
+/* { dg-final { scan-assembler-not "and\[^\n\r]*%\[re\]sp" } } */
+/* Nor use a frame pointer. */
+/* { dg-final { scan-assembler-not "%\[re\]bp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memcpy-20.c b/gcc/testsuite/gcc.target/i386/pieces-memcpy-20.c
new file mode 100644
index 0000000..1feff48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pieces-memcpy-20.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=sapphirerapids -mmove-max=256 -mstore-max=256" } */
+
+extern char *dst, *src;
+
+void
+foo (void)
+{
+ __builtin_memcpy (dst, src, 66);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu(?:64|)\[ \\t\]+\[^\n\]*%ymm" 4 } } */
+/* No need to dynamically realign the stack here. */
+/* { dg-final { scan-assembler-not "and\[^\n\r]*%\[re\]sp" } } */
+/* Nor use a frame pointer. */
+/* { dg-final { scan-assembler-not "%\[re\]bp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memcpy-21.c b/gcc/testsuite/gcc.target/i386/pieces-memcpy-21.c
new file mode 100644
index 0000000..ef439f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pieces-memcpy-21.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=sapphirerapids -march=x86-64 -mavx2" } */
+
+extern char *dst, *src;
+
+void
+foo (void)
+{
+ __builtin_memcpy (dst, src, 66);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu(?:64|)\[ \\t\]+\[^\n\]*%ymm" 4 } } */
+/* No need to dynamically realign the stack here. */
+/* { dg-final { scan-assembler-not "and\[^\n\r]*%\[re\]sp" } } */
+/* Nor use a frame pointer. */
+/* { dg-final { scan-assembler-not "%\[re\]bp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-45.c b/gcc/testsuite/gcc.target/i386/pieces-memset-45.c
new file mode 100644
index 0000000..70c80e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-45.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64 -mprefer-vector-width=256 -mavx512f -mtune-ctrl=avx512_store_by_pieces" } */
+
+extern char *dst;
+
+void
+foo (void)
+{
+ __builtin_memset (dst, 3, 66);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu64\[ \\t\]+\[^\n\]*%zmm" 1 } } */
+/* No need to dynamically realign the stack here. */
+/* { dg-final { scan-assembler-not "and\[^\n\r]*%\[re\]sp" } } */
+/* Nor use a frame pointer. */
+/* { dg-final { scan-assembler-not "%\[re\]bp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-46.c b/gcc/testsuite/gcc.target/i386/pieces-memset-46.c
new file mode 100644
index 0000000..ab7894a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-46.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=sapphirerapids" } */
+
+extern char *dst;
+
+void
+foo (void)
+{
+ __builtin_memset (dst, 3, 66);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu8\[ \\t\]+\[^\n\]*%zmm" 1 } } */
+/* { dg-final { scan-assembler-times "vmovw\[ \\t\]+\[^\n\]*%xmm" 1 } } */
+/* No need to dynamically realign the stack here. */
+/* { dg-final { scan-assembler-not "and\[^\n\r]*%\[re\]sp" } } */
+/* Nor use a frame pointer. */
+/* { dg-final { scan-assembler-not "%\[re\]bp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-47.c b/gcc/testsuite/gcc.target/i386/pieces-memset-47.c
new file mode 100644
index 0000000..8f2c254a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-47.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=sapphirerapids -mstore-max=128" } */
+
+extern char *dst;
+
+void
+foo (void)
+{
+ __builtin_memset (dst, 3, 66);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu(?:8|)\[ \\t\]+\[^\n\]*%xmm" 4 } } */
+/* { dg-final { scan-assembler-times "vmovw\[ \\t\]+\[^\n\]*%xmm" 1 } } */
+/* No need to dynamically realign the stack here. */
+/* { dg-final { scan-assembler-not "and\[^\n\r]*%\[re\]sp" } } */
+/* Nor use a frame pointer. */
+/* { dg-final { scan-assembler-not "%\[re\]bp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-48.c b/gcc/testsuite/gcc.target/i386/pieces-memset-48.c
new file mode 100644
index 0000000..9a7da96
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-48.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=sapphirerapids -mstore-max=256" } */
+
+extern char *dst;
+
+void
+foo (void)
+{
+ __builtin_memset (dst, 3, 66);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu(?:8|)\[ \\t\]+\[^\n\]*%ymm" 2 } } */
+/* { dg-final { scan-assembler-times "vmovw\[ \\t\]+\[^\n\]*%xmm" 1 } } */
+/* No need to dynamically realign the stack here. */
+/* { dg-final { scan-assembler-not "and\[^\n\r]*%\[re\]sp" } } */
+/* Nor use a frame pointer. */
+/* { dg-final { scan-assembler-not "%\[re\]bp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-49.c b/gcc/testsuite/gcc.target/i386/pieces-memset-49.c
new file mode 100644
index 0000000..ad43f89
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-49.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=sapphirerapids -march=x86-64 -mavx2" } */
+
+extern char *dst;
+
+void
+foo (void)
+{
+ __builtin_memset (dst, 3, 66);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu(?:8|)\[ \\t\]+\[^\n\]*%ymm" 2 } } */
+/* No need to dynamically realign the stack here. */
+/* { dg-final { scan-assembler-not "and\[^\n\r]*%\[re\]sp" } } */
+/* Nor use a frame pointer. */
+/* { dg-final { scan-assembler-not "%\[re\]bp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr102327-1.c b/gcc/testsuite/gcc.target/i386/pr102327-1.c
index 4743926..bd02f53 100644
--- a/gcc/testsuite/gcc.target/i386/pr102327-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr102327-1.c
@@ -60,6 +60,11 @@ VEC_SET (v32hf, _Float16, 14);
VEC_SET (v32hf, _Float16, 16);
VEC_SET (v32hf, _Float16, 24);
VEC_SET (v32hf, _Float16, 28);
-/* { dg-final { scan-assembler-times "vpbroadcastw" 10 } } */
-/* { dg-final { scan-assembler-times "vpblendw" 4 } } */
+/* { dg-final { scan-assembler-times "vpbroadcastw" 10 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vpblendw" 4 { target { ! ia32 } } } } */
+
+/* { dg-final { scan-assembler-times "vpbroadcastw" 9 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "vpblendw" 3 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "vpinsrw" 1 { target ia32 } } } */
+
/* { dg-final { scan-assembler-times "vpblendd" 3 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr102811-1.c b/gcc/testsuite/gcc.target/i386/pr102811-1.c
new file mode 100644
index 0000000..a1952d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr102811-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mf16c -mno-avx512fp16" } */
+/* { dg-final { scan-assembler-times "vpxor" 1 } } */
+/* { dg-final { scan-assembler-times "vpblendw" 2 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vpinsrw" 2 { target ia32 } } } */
+/* { dg-final { scan-assembler-not "vpextrw"} } */
+/* { dg-final { scan-assembler-not "vpbroadcastw"} } */
+_Float16 test (_Float16 a, _Float16 b)
+{
+ return a + b;
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vcvtps2ph-pr102811.c b/gcc/testsuite/gcc.target/i386/pr102811.c
index 9a6c432..9a6c432 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-vcvtps2ph-pr102811.c
+++ b/gcc/testsuite/gcc.target/i386/pr102811.c
diff --git a/gcc/testsuite/gcc.target/i386/pr103097.c b/gcc/testsuite/gcc.target/i386/pr103097.c
new file mode 100644
index 0000000..2b7a307
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr103097.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fharden-conditional-branches" } */
+
+/* This is a slightly simplified version of
+ gcc.target/s390/vector/long-double-asm-earlyclobber.c. On x86, the f
+ constraints in asm statements imposes some requirements that the testcase
+ doesn't meet. What's unusual is that -fharden-conditional-branches extends
+ the effects of the malformed asm onto a different basic blocks, which
+ reg-stack did not expect. */
+
+#include <assert.h>
+#include <stdint.h>
+
+void
+f (void)
+{
+ long double res, x = 0;
+ asm("" : "=f"(res) /* { dg-error "must specify a single register" } */
+ : "0"(x));
+ assert (res == x);
+}
+
+void
+g (void)
+{
+ long double res, x = 0;
+ asm("" : "=g"(res) /* this is ok. */
+ : "0"(x));
+ assert (res == x);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr103404.c b/gcc/testsuite/gcc.target/i386/pr103404.c
new file mode 100644
index 0000000..66f3364
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr103404.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Og -fcse-follow-jumps -fno-dce -fno-early-inlining -fgcse -fharden-conditional-branches -frerun-cse-after-loop -fno-tree-ccp -mavx5124fmaps -std=c99 -w" } */
+
+typedef unsigned __attribute__((__vector_size__ (4))) U;
+typedef unsigned __attribute__((__vector_size__ (16))) V;
+typedef unsigned __attribute__((__vector_size__ (64))) W;
+
+int x, y;
+
+V v;
+W w;
+
+inline
+int bar (U a)
+{
+ a |= x;
+ W k =
+ __builtin_shufflevector (v, 5 / a,
+ 2, 4, 0, 2, 4, 1, 0, 1,
+ 1, 2, 1, 3, 0, 4, 4, 0);
+ w = k;
+ y = 0;
+}
+
+int
+foo ()
+{
+ bar ((U){0xffffffff});
+ for (unsigned i; i < sizeof (foo);)
+ ;
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/pr83782-1.c b/gcc/testsuite/gcc.target/i386/pr83782-1.c
new file mode 100644
index 0000000..ce97b12
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr83782-1.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O2 -fpic" } */
+
+static void
+my_foo (void)
+{
+}
+
+static void (*resolve_foo (void)) (void)
+{
+ return my_foo;
+}
+
+extern void foo (void) __attribute__((ifunc("resolve_foo"), visibility("hidden")));
+
+void *
+bar(void)
+{
+ return foo;
+}
+
+/* { dg-final { scan-assembler {leal[ \t]foo@GOTOFF\(%[^,]*\),[ \t]%eax} { target ia32 } } } */
+/* { dg-final { scan-assembler {lea(?:l|q)[ \t]foo\(%rip\),[ \t]%(?:e|r)ax} { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "foo@GOT\\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "foo@GOTPCREL\\\(" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr83782-2.c b/gcc/testsuite/gcc.target/i386/pr83782-2.c
new file mode 100644
index 0000000..e25d258
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr83782-2.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O2 -fpic" } */
+
+static void
+my_foo (void)
+{
+}
+
+static void (*resolve_foo (void)) (void)
+{
+ return my_foo;
+}
+
+static void foo (void) __attribute__((ifunc("resolve_foo")));
+
+void *
+bar(void)
+{
+ return foo;
+}
+
+/* { dg-final { scan-assembler {leal[ \t]foo@GOTOFF\(%[^,]*\),[ \t]%eax} { target ia32 } } } */
+/* { dg-final { scan-assembler {lea(?:l|q)[ \t]foo\(%rip\),[ \t]%(?:e|r)ax} { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "foo@GOT\\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "foo@GOTPCREL\\\(" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr95740.c b/gcc/testsuite/gcc.target/i386/pr95740.c
new file mode 100644
index 0000000..7ecd71b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr95740.c
@@ -0,0 +1,26 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-msse2 -O2 -mtune=generic -mtune-ctrl=use_incdec -masm=att -mfpmath=sse" } */
+/* { dg-final { scan-assembler-times {(?n)movd[\t ]*%xmm0.*%eax} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)incl[\t ]*%eax} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)movq[\t ]*%xmm0.*%rax} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)incq[\t ]*%rax} 1 } } */
+
+int
+foo (float a)
+{
+ union{
+ int b;
+ float a;}u;
+ u.a = a;
+ return u.b + 1;
+}
+
+long long
+foo1 (double a)
+{
+ union{
+ long long b;
+ double a;}u;
+ u.a = a;
+ return u.b + 1;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp
index d4d4b90..f76ab7a 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -264,6 +264,7 @@ set mips_option_groups {
frame-header "-mframe-header-opt|-mno-frame-header-opt"
stack-protector "-fstack-protector"
stdlib "REQUIRES_STDLIB"
+ unaligned-access "-m(no-|)unaligned-access"
}
for { set option 0 } { $option < 32 } { incr option } {
diff --git a/gcc/testsuite/gcc.target/mips/unaligned-2.c b/gcc/testsuite/gcc.target/mips/unaligned-2.c
new file mode 100644
index 0000000..8679afa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/unaligned-2.c
@@ -0,0 +1,53 @@
+/* { dg-options "isa_rev>=6 -mgp64" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-not "\tsb\t" } } */
+/* { dg-final { scan-assembler-not "\tsh\t" } } */
+/* { dg-final { scan-assembler-not "\tlb\t" } } */
+/* { dg-final { scan-assembler-not "\tlh\t" } } */
+/* { dg-final { scan-assembler-not "\tswl\t" } } */
+/* { dg-final { scan-assembler-not "\tswr\t" } } */
+/* { dg-final { scan-assembler-not "\tlwl\t" } } */
+/* { dg-final { scan-assembler-not "\tlwr\t" } } */
+/* { dg-final { scan-assembler-not "\tsdl\t" } } */
+/* { dg-final { scan-assembler-not "\tsdr\t" } } */
+/* { dg-final { scan-assembler-not "\tldl\t" } } */
+/* { dg-final { scan-assembler-not "\tldr\t" } } */
+/* { dg-final { scan-assembler-times "\tsw\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tlw\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tsd\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tld\t" 1 } } */
+/* { dg-final { scan-assembler-not "\tnop" } } */
+
+/* Test to make sure we produce the unaligned load/store for
+ both 64bit and 32bits sized accesses. */
+
+struct s
+{
+ char c;
+ int i;
+ long long l;
+} __attribute__ ((packed)) s __attribute__((aligned(1) ));
+
+NOMIPS16 void
+sd (long long l)
+{
+ s.l = l;
+}
+
+NOMIPS16 long long
+ld ()
+{
+ return s.l;
+}
+
+NOMIPS16 void
+sw (int i)
+{
+ s.i = i;
+}
+
+NOMIPS16 int
+lw ()
+{
+ return s.i;
+}
diff --git a/gcc/testsuite/gcc.target/mips/unaligned-3.c b/gcc/testsuite/gcc.target/mips/unaligned-3.c
new file mode 100644
index 0000000..d0fbe19
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/unaligned-3.c
@@ -0,0 +1,53 @@
+/* { dg-options "isa_rev>=6 -mgp64 -mno-unaligned-access" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-times "\tsb\t" 12 } } */
+/* { dg-final { scan-assembler-times "\tlbu\t" 12 } } */
+/* { dg-final { scan-assembler-not "\tsh\t" } } */
+/* { dg-final { scan-assembler-not "\tlh\t" } } */
+/* { dg-final { scan-assembler-not "\tsw\t" } } */
+/* { dg-final { scan-assembler-not "\tlw\t" } } */
+/* { dg-final { scan-assembler-not "\tsd\t" } } */
+/* { dg-final { scan-assembler-not "\tld\t" } } */
+/* { dg-final { scan-assembler-not "\tswl\t" } } */
+/* { dg-final { scan-assembler-not "\tswr\t" } } */
+/* { dg-final { scan-assembler-not "\tlwl\t" } } */
+/* { dg-final { scan-assembler-not "\tlwr\t" } } */
+/* { dg-final { scan-assembler-not "\tsdl\t" } } */
+/* { dg-final { scan-assembler-not "\tsdr\t" } } */
+/* { dg-final { scan-assembler-not "\tldl\t" } } */
+/* { dg-final { scan-assembler-not "\tldr\t" } } */
+/* { dg-final { scan-assembler-not "\tnop" } } */
+
+/* Test to make sure we produce the unaligned load/store for
+ both 64bit and 32bits sized accesses. */
+
+struct s
+{
+ char c;
+ int i;
+ long long l;
+} __attribute__ ((packed)) s __attribute__((aligned(1) ));
+
+NOMIPS16 void
+sd (long long l)
+{
+ s.l = l;
+}
+
+NOMIPS16 long long
+ld ()
+{
+ return s.l;
+}
+
+NOMIPS16 void
+sw (int i)
+{
+ s.i = i;
+}
+
+NOMIPS16 int
+lw ()
+{
+ return s.i;
+}
diff --git a/gcc/testsuite/gcc.target/nvptx/exttrunc-1.c b/gcc/testsuite/gcc.target/nvptx/exttrunc-1.c
new file mode 100644
index 0000000..ed9ceee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/exttrunc-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+short exttrunc_hi2_qi(short x)
+{
+ return (char)x;
+}
+
+/* Match:
+ mov.u32 %r24, %ar0;
+ cvt.u32.u32 %r26, %r24;
+ cvt.s32.s8 %value, %r26;
+ Todo: Remove cvt.u32.u32. */
+
+/* { dg-final { scan-assembler-times "mov\.u32\t%r\[0-9\]*, %ar0" 1 } } */
+/* { dg-final { scan-assembler-times "mov\." 1 } } */
+
+/* { dg-final { scan-assembler-times "cvt\.u32\.u32" 1 } } */
+/* { dg-final { scan-assembler-times "cvt\.s32\.s8" 1 } } */
+/* { dg-final { scan-assembler-times "cvt\." 2 } } */
diff --git a/gcc/testsuite/gcc.target/nvptx/exttrunc-2.c b/gcc/testsuite/gcc.target/nvptx/exttrunc-2.c
new file mode 100644
index 0000000..b108b55
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/exttrunc-2.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int exttrunc_si2_qi(int x)
+{
+ return (char)x;
+}
+
+/* Match:
+ mov.u32 %r24, %ar0;
+ cvt.s32.s8 %value, %r24; */
+
+/* { dg-final { scan-assembler-times "mov\.u32\t%r\[0-9\]*, %ar0" 1 } } */
+/* { dg-final { scan-assembler-times "mov\." 1 } } */
+
+/* { dg-final { scan-assembler-times "cvt\.s32\.s8" 1 } } */
+/* { dg-final { scan-assembler-times "cvt\." 1 } } */
diff --git a/gcc/testsuite/gcc.target/nvptx/exttrunc-3.c b/gcc/testsuite/gcc.target/nvptx/exttrunc-3.c
new file mode 100644
index 0000000..69e42fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/exttrunc-3.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+long exttrunc_di2_qi(long x)
+{
+ return (char)x;
+}
+
+/* Match:
+ mov.u64 %r24, %ar0;
+ cvt.s64.s8 %value, %r24; */
+
+/* { dg-final { scan-assembler-times "mov\.u64\t%r\[0-9\]*, %ar0" 1 } } */
+/* { dg-final { scan-assembler-times "mov\." 1 } } */
+
+/* { dg-final { scan-assembler-times "cvt\.s64\.s8" 1 } } */
+/* { dg-final { scan-assembler-times "cvt\." 1 } } */
diff --git a/gcc/testsuite/gcc.target/nvptx/exttrunc-4.c b/gcc/testsuite/gcc.target/nvptx/exttrunc-4.c
new file mode 100644
index 0000000..09009db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/exttrunc-4.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int exttrunc_si2_hi(int x)
+{
+ return (short)x;
+}
+
+/* Match:
+ mov.u32 %r24, %ar0;
+ cvt.s32.s16 %value, %r24;
+
+/* { dg-final { scan-assembler-times "mov\.u32\t%r\[0-9\]*, %ar0" 1 } } */
+/* { dg-final { scan-assembler-times "mov\." 1 } } */
+
+/* { dg-final { scan-assembler-times "cvt\.s32\.s16" 1 } } */
+/* { dg-final { scan-assembler-times "cvt\." 1 } } */
diff --git a/gcc/testsuite/gcc.target/nvptx/exttrunc-5.c b/gcc/testsuite/gcc.target/nvptx/exttrunc-5.c
new file mode 100644
index 0000000..5445850
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/exttrunc-5.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+long exttrunc_di2_hi(long x)
+{
+ return (short)x;
+}
+
+/* Match:
+ mov.u64 %r24, %ar0;
+ cvt.s64.s16 %value, %r24; */
+
+/* { dg-final { scan-assembler-times "mov\.u64\t%r\[0-9\]*, %ar0" 1 } } */
+/* { dg-final { scan-assembler-times "mov\." 1 } } */
+
+/* { dg-final { scan-assembler-times "cvt\.s64\.s16" 1 } } */
+/* { dg-final { scan-assembler-times "cvt\." 1 } } */
diff --git a/gcc/testsuite/gcc.target/nvptx/exttrunc-6.c b/gcc/testsuite/gcc.target/nvptx/exttrunc-6.c
new file mode 100644
index 0000000..74f050f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/exttrunc-6.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+long exttrunc_di2_si(long x)
+{
+ return (int)x;
+}
+
+/* Match:
+ mov.u64 %r24, %ar0;
+ cvt.s64.s32 %value, %r24; */
+
+/* { dg-final { scan-assembler-times "mov\.u64\t%r\[0-9\]*, %ar0" 1 } } */
+/* { dg-final { scan-assembler-times "mov\." 1 } } */
+
+/* { dg-final { scan-assembler-times "cvt\.s64\.s32" 1 } } */
+/* { dg-final { scan-assembler-times "cvt\." 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-2.c
index 9221806..53b67c9 100644
--- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-2.c
@@ -14,7 +14,7 @@ get_exponent (double *p)
{
double source = *p;
- return scalar_extract_exp (source); /* { dg-error "'__builtin_vec_scalar_extract_exp' is not supported in this compiler configuration" } */
+ return scalar_extract_exp (source); /* { dg-error "'__builtin_vsx_scalar_extract_exp' requires the" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c
index e24d4bd..39ee74c 100644
--- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c
@@ -12,5 +12,5 @@ get_significand (double *p)
{
double source = *p;
- return __builtin_vec_scalar_extract_sig (source); /* { dg-error "'__builtin_vec_scalar_extract_sig' is not supported in this compiler configuration" } */
+ return __builtin_vec_scalar_extract_sig (source); /* { dg-error "'__builtin_vsx_scalar_extract_sig' requires the" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-2.c
index feb9431..efd6972 100644
--- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-2.c
@@ -16,5 +16,5 @@ insert_exponent (unsigned long long int *significand_p,
unsigned long long int significand = *significand_p;
unsigned long long int exponent = *exponent_p;
- return scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vec_scalar_insert_exp' is not supported in this compiler configuration" } */
+ return scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vsx_scalar_insert_exp' requires the" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-5.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-5.c
index 0e5683d..f85966a 100644
--- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-5.c
@@ -16,5 +16,5 @@ insert_exponent (double *significand_p,
double significand = *significand_p;
unsigned long long int exponent = *exponent_p;
- return scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vec_scalar_insert_exp' is not supported in this compiler configuration" } */
+ return scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vsx_scalar_insert_exp_dp' requires the" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c
index bd68f77..b1be828 100644
--- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c
@@ -16,5 +16,5 @@ insert_exponent (unsigned __int128 *significand_p, /* { dg-error "'__int128' is
unsigned __int128 significand = *significand_p; /* { dg-error "'__int128' is not supported on this target" } */
unsigned long long int exponent = *exponent_p;
- return scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vec_scalar_insert_exp' is not supported in this compiler configuration" } */
+ return scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vsx_scalar_insert_exp' requires the" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-2.c
index 7d2b4de..46d743a 100644
--- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-2.c
@@ -10,5 +10,5 @@ test_neg (float *p)
{
float source = *p;
- return __builtin_vec_scalar_test_neg_sp (source); /* { dg-error "'__builtin_vsx_scalar_test_neg_sp' requires" } */
+ return __builtin_vec_scalar_test_neg (source); /* { dg-error "'__builtin_vsx_scalar_test_neg_sp' requires" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-3.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-3.c
index b503dfa..bfc892b 100644
--- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-3.c
@@ -10,5 +10,5 @@ test_neg (double *p)
{
double source = *p;
- return __builtin_vec_scalar_test_neg_dp (source); /* { dg-error "'__builtin_vsx_scalar_test_neg_dp' requires" } */
+ return __builtin_vec_scalar_test_neg (source); /* { dg-error "'__builtin_vsx_scalar_test_neg_dp' requires" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-5.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-5.c
index bab8604..8c55c1c 100644
--- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-5.c
@@ -10,5 +10,5 @@ test_neg (__ieee128 *p)
{
__ieee128 source = *p;
- return __builtin_vec_scalar_test_neg_qp (source); /* { dg-error "'__builtin_vsx_scalar_test_neg_qp' requires" } */
+ return __builtin_vec_scalar_test_neg (source); /* { dg-error "'__builtin_vsx_scalar_test_neg_qp' requires" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c b/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c
index 44cc778..4c676ba 100644
--- a/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c
@@ -10,5 +10,5 @@
int
test_byte_in_set (unsigned char b, unsigned long long set_members)
{
- return __builtin_byte_in_set (b, set_members); /* { dg-warning "implicit declaration of function" } */
+ return __builtin_byte_in_set (b, set_members); /* { dg-error "'__builtin_scalar_byte_in_set' requires the" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/cmpb-2.c b/gcc/testsuite/gcc.target/powerpc/cmpb-2.c
index 113ab6a..02b84d0 100644
--- a/gcc/testsuite/gcc.target/powerpc/cmpb-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/cmpb-2.c
@@ -8,7 +8,7 @@ void abort ();
unsigned long long int
do_compare (unsigned long long int a, unsigned long long int b)
{
- return __builtin_cmpb (a, b); /* { dg-warning "implicit declaration of function '__builtin_cmpb'" } */
+ return __builtin_cmpb (a, b); /* { dg-error "'__builtin_p6_cmpb' requires the '-mcpu=power6' option" } */
}
void
diff --git a/gcc/testsuite/gcc.target/powerpc/cmpb-3.c b/gcc/testsuite/gcc.target/powerpc/cmpb-3.c
index de111a8..75641bd 100644
--- a/gcc/testsuite/gcc.target/powerpc/cmpb-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/cmpb-3.c
@@ -8,7 +8,7 @@ void abort ();
long long int
do_compare (long long int a, long long int b)
{
- return __builtin_cmpb (a, b); /* { dg-error "'__builtin_cmpb' is not supported in this compiler configuration" } */
+ return __builtin_cmpb (a, b); /* { dg-error "'__builtin_p6_cmpb' requires the '-mcpu=power6' option and either the '-m64' or '-mpowerpc64' option" } */
}
void expect (long long int pattern, long long int value)
diff --git a/gcc/testsuite/gcc.target/powerpc/cmpb32-2.c b/gcc/testsuite/gcc.target/powerpc/cmpb32-2.c
index 37b5474..d4264ab 100644
--- a/gcc/testsuite/gcc.target/powerpc/cmpb32-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/cmpb32-2.c
@@ -7,7 +7,7 @@ void abort ();
unsigned int
do_compare (unsigned int a, unsigned int b)
{
- return __builtin_cmpb (a, b); /* { dg-warning "implicit declaration of function '__builtin_cmpb'" } */
+ return __builtin_cmpb (a, b); /* { dg-error "'__builtin_p6_cmpb_32' requires the '-mcpu=power6' option" } */
}
void
diff --git a/gcc/testsuite/gcc.target/powerpc/crypto-builtin-2.c b/gcc/testsuite/gcc.target/powerpc/crypto-builtin-2.c
index 4066b12..b3a6c73 100644
--- a/gcc/testsuite/gcc.target/powerpc/crypto-builtin-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/crypto-builtin-2.c
@@ -5,21 +5,21 @@
void use_builtins_d (__vector unsigned long long *p, __vector unsigned long long *q, __vector unsigned long long *r, __vector unsigned long long *s)
{
- p[0] = __builtin_crypto_vcipher (q[0], r[0]); /* { dg-error "'__builtin_crypto_vcipher' is not supported with the current options" } */
- p[1] = __builtin_crypto_vcipherlast (q[1], r[1]); /* { dg-error "'__builtin_crypto_vcipherlast' is not supported with the current options" } */
- p[2] = __builtin_crypto_vncipher (q[2], r[2]); /* { dg-error "'__builtin_crypto_vncipher' is not supported with the current options" } */
- p[3] = __builtin_crypto_vncipherlast (q[3], r[3]); /* { dg-error "'__builtin_crypto_vncipherlast' is not supported with the current options" } */
+ p[0] = __builtin_crypto_vcipher (q[0], r[0]); /* { dg-error "'__builtin_crypto_vcipher' requires the '-mcrypto' option" } */
+ p[1] = __builtin_crypto_vcipherlast (q[1], r[1]); /* { dg-error "'__builtin_crypto_vcipherlast' requires the '-mcrypto' option" } */
+ p[2] = __builtin_crypto_vncipher (q[2], r[2]); /* { dg-error "'__builtin_crypto_vncipher' requires the '-mcrypto' option" } */
+ p[3] = __builtin_crypto_vncipherlast (q[3], r[3]); /* { dg-error "'__builtin_crypto_vncipherlast' requires the '-mcrypto' option" } */
p[4] = __builtin_crypto_vpermxor (q[4], r[4], s[4]);
p[5] = __builtin_crypto_vpmsumd (q[5], r[5]);
- p[6] = __builtin_crypto_vshasigmad (q[6], 1, 15); /* { dg-error "'__builtin_crypto_vshasigmad' is not supported with the current options" } */
- p[7] = __builtin_crypto_vsbox (q[7]); /* { dg-error "'__builtin_crypto_vsbox' is not supported with the current options" } */
+ p[6] = __builtin_crypto_vshasigmad (q[6], 1, 15); /* { dg-error "'__builtin_crypto_vshasigmad' requires the '-mcrypto' option" } */
+ p[7] = __builtin_crypto_vsbox (q[7]); /* { dg-error "'__builtin_crypto_vsbox' requires the '-mcrypto' option" } */
}
void use_builtins_w (__vector unsigned int *p, __vector unsigned int *q, __vector unsigned int *r, __vector unsigned int *s)
{
p[0] = __builtin_crypto_vpermxor (q[0], r[0], s[0]);
p[1] = __builtin_crypto_vpmsumw (q[1], r[1]);
- p[2] = __builtin_crypto_vshasigmaw (q[2], 1, 15); /* { dg-error "'__builtin_crypto_vshasigmaw' is not supported with the current options" } */
+ p[2] = __builtin_crypto_vshasigmaw (q[2], 1, 15); /* { dg-error "'__builtin_crypto_vshasigmaw' requires the '-mcrypto' option" } */
}
void use_builtins_h (__vector unsigned short *p, __vector unsigned short *q, __vector unsigned short *r, __vector unsigned short *s)
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-floatdouble.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-floatdouble.c
index 7661917..b95fa32 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-floatdouble.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-floatdouble.c
@@ -18,7 +18,7 @@ vector float test_fc ()
vector double testd_00 (vector double x) { return vec_splat (x, 0b00000); }
vector double testd_01 (vector double x) { return vec_splat (x, 0b00001); }
vector double test_dc ()
-{ const vector double y = { 3.0, 5.0 }; return vec_splat (y, 0b00010); }
+{ const vector double y = { 3.0, 5.0 }; return vec_splat (y, 0b00001); }
/* If the source vector is a known constant, we will generate a load or possibly
XXSPLTIW. */
@@ -28,5 +28,5 @@ vector double test_dc ()
/* { dg-final { scan-assembler-times {\mvspltw\M|\mxxspltw\M} 3 } } */
/* For double types, we will generate xxpermdi instructions. */
-/* { dg-final { scan-assembler-times "xxpermdi" 3 } } */
+/* { dg-final { scan-assembler-times "xxpermdi" 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-longlong.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-longlong.c
index b95b987..3fa1f05 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-longlong.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-longlong.c
@@ -9,23 +9,19 @@
vector bool long long testb_00 (vector bool long long x) { return vec_splat (x, 0b00000); }
vector bool long long testb_01 (vector bool long long x) { return vec_splat (x, 0b00001); }
-vector bool long long testb_02 (vector bool long long x) { return vec_splat (x, 0b00010); }
vector signed long long tests_00 (vector signed long long x) { return vec_splat (x, 0b00000); }
vector signed long long tests_01 (vector signed long long x) { return vec_splat (x, 0b00001); }
-vector signed long long tests_02 (vector signed long long x) { return vec_splat (x, 0b00010); }
vector unsigned long long testu_00 (vector unsigned long long x) { return vec_splat (x, 0b00000); }
vector unsigned long long testu_01 (vector unsigned long long x) { return vec_splat (x, 0b00001); }
-vector unsigned long long testu_02 (vector unsigned long long x) { return vec_splat (x, 0b00010); }
/* Similar test as above, but the source vector is a known constant. */
-vector bool long long test_bll () { const vector bool long long y = {12, 23}; return vec_splat (y, 0b00010); }
-vector signed long long test_sll () { const vector signed long long y = {34, 45}; return vec_splat (y, 0b00010); }
-vector unsigned long long test_ull () { const vector unsigned long long y = {56, 67}; return vec_splat (y, 0b00010); }
+vector bool long long test_bll () { const vector bool long long y = {12, 23}; return vec_splat (y, 0b00001); }
+vector signed long long test_sll () { const vector signed long long y = {34, 45}; return vec_splat (y, 0b00001); }
/* Assorted load instructions for the initialization with known constants. */
-/* { dg-final { scan-assembler-times {\mlvx\M|\mlxvd2x\M|\mlxv\M|\mplxv\M} 3 } } */
+/* { dg-final { scan-assembler-times {\mlvx\M|\mlxvd2x\M|\mlxv\M|\mplxv\M|\mxxspltib\M} 2 } } */
/* xxpermdi for vec_splat of long long vectors.
At the time of this writing, the number of xxpermdi instructions
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-misc-invalid.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-misc-invalid.c
index 20f5b05..263a172 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-misc-invalid.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-misc-invalid.c
@@ -10,24 +10,24 @@
vector signed short
testss_1 (unsigned int ui)
{
- return vec_splat_s16 (ui);/* { dg-error "argument 1 must be a 5-bit signed literal" } */
+ return vec_splat_s16 (ui);/* { dg-error "argument 1 must be a literal between -16 and 15, inclusive" } */
}
vector unsigned short
testss_2 (signed int si)
{
- return vec_splat_u16 (si);/* { dg-error "argument 1 must be a 5-bit signed literal" } */
+ return vec_splat_u16 (si);/* { dg-error "argument 1 must be a literal between -16 and 15, inclusive" } */
}
vector signed char
testsc_1 (unsigned int ui)
{
- return vec_splat_s8 (ui); /* { dg-error "argument 1 must be a 5-bit signed literal" } */
+ return vec_splat_s8 (ui); /* { dg-error "argument 1 must be a literal between -16 and 15, inclusive" } */
}
vector unsigned char
testsc_2 (signed int si)
{
- return vec_splat_u8 (si);/* { dg-error "argument 1 must be a 5-bit signed literal" } */
+ return vec_splat_u8 (si);/* { dg-error "argument 1 must be a literal between -16 and 15, inclusive" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c b/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c
index 1255ee9..1356793 100644
--- a/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c
@@ -11,9 +11,9 @@
/* { dg-final { scan-assembler-times {\mvrlq\M} 2 } } */
/* { dg-final { scan-assembler-times {\mvrlqnm\M} 2 } } */
/* { dg-final { scan-assembler-times {\mvrlqmi\M} 2 } } */
-/* { dg-final { scan-assembler-times {\mvcmpequq\M} 16 } } */
-/* { dg-final { scan-assembler-times {\mvcmpgtsq\M} 16 } } */
-/* { dg-final { scan-assembler-times {\mvcmpgtuq\M} 16 } } */
+/* { dg-final { scan-assembler-times {\mvcmpequq\M} 24 } } */
+/* { dg-final { scan-assembler-times {\mvcmpgtsq\M} 26 } } */
+/* { dg-final { scan-assembler-times {\mvcmpgtuq\M} 26 } } */
/* { dg-final { scan-assembler-times {\mvmuloud\M} 1 } } */
/* { dg-final { scan-assembler-times {\mvmulesd\M} 1 } } */
/* { dg-final { scan-assembler-times {\mvmulosd\M} 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr101324.c b/gcc/testsuite/gcc.target/powerpc/pr101324.c
new file mode 100644
index 0000000..ca0fca8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr101324.c
@@ -0,0 +1,17 @@
+/* { dg-require-effective-target rop_ok } */
+/* { dg-options "-O1 -mrop-protect -mdejagnu-cpu=power10" } */
+
+extern void foo (void);
+
+long int
+__attribute__ ((__optimize__ ("no-inline")))
+func (long int cond)
+{
+ if (cond)
+ foo ();
+ return cond;
+}
+
+/* Ensure hashst comes after mflr and hashchk comes after ld 0,16(1). */
+/* { dg-final { scan-assembler {(?p)\mmflr 0.*\n.*\n.*\mhashst 0,} } } */
+/* { dg-final { scan-assembler {(?p)ld 0,.*\n.*\n.*\n.*\mhashchk 0,} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr103127.c b/gcc/testsuite/gcc.target/powerpc/pr103127.c
new file mode 100644
index 0000000..801fc0a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr103127.c
@@ -0,0 +1,19 @@
+/* PR target/103127 */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-O2 -mdejagnu-cpu=power10 -ftrivial-auto-var-init=zero" } */
+
+/* Verify we do not ICE on the following tests. */
+
+void
+foo (__vector_quad *dst)
+{
+ __vector_quad acc;
+ *dst = acc;
+}
+
+void
+bar (__vector_pair *dst)
+{
+ __vector_pair pair;
+ *dst = pair;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80315-1.c b/gcc/testsuite/gcc.target/powerpc/pr80315-1.c
index e2db0ff..f37f1f1 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr80315-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr80315-1.c
@@ -10,6 +10,6 @@ main()
int mask;
/* Argument 2 must be 0 or 1. Argument 3 must be in range 0..15. */
- res = __builtin_crypto_vshasigmaw (test, 1, 0xff); /* { dg-error {argument 3 must be in the range \[0, 15\]} } */
+ res = __builtin_crypto_vshasigmaw (test, 1, 0xff); /* { dg-error {argument 3 must be a 4-bit unsigned literal} } */
return 0;
}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80315-2.c b/gcc/testsuite/gcc.target/powerpc/pr80315-2.c
index 144b705..0819a05 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr80315-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr80315-2.c
@@ -10,6 +10,6 @@ main ()
int mask;
/* Argument 2 must be 0 or 1. Argument 3 must be in range 0..15. */
- res = __builtin_crypto_vshasigmad (test, 1, 0xff); /* { dg-error {argument 3 must be in the range \[0, 15\]} } */
+ res = __builtin_crypto_vshasigmad (test, 1, 0xff); /* { dg-error {argument 3 must be a 4-bit unsigned literal} } */
return 0;
}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80315-3.c b/gcc/testsuite/gcc.target/powerpc/pr80315-3.c
index 99a3e24..cc2e46c 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr80315-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr80315-3.c
@@ -12,6 +12,6 @@ main ()
int mask;
/* Argument 2 must be 0 or 1. Argument 3 must be in range 0..15. */
- res = vec_shasigma_be (test, 1, 0xff); /* { dg-error {argument 3 must be in the range \[0, 15\]} } */
+ res = vec_shasigma_be (test, 1, 0xff); /* { dg-error {argument 3 must be a 4-bit unsigned literal} } */
return res;
}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80315-4.c b/gcc/testsuite/gcc.target/powerpc/pr80315-4.c
index 7f5f6f7..ac12910 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr80315-4.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr80315-4.c
@@ -12,6 +12,6 @@ main ()
int mask;
/* Argument 2 must be 0 or 1. Argument 3 must be in range 0..15. */
- res = vec_shasigma_be (test, 1, 0xff); /* { dg-error {argument 3 must be in the range \[0, 15\]} } */
+ res = vec_shasigma_be (test, 1, 0xff); /* { dg-error {argument 3 must be a 4-bit unsigned literal} } */
return res;
}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr88100.c b/gcc/testsuite/gcc.target/powerpc/pr88100.c
index 4452145..764c897 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr88100.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr88100.c
@@ -10,35 +10,35 @@
vector unsigned char
splatu1 (void)
{
- return vec_splat_u8(0x100);/* { dg-error "argument 1 must be a 5-bit signed literal" } */
+ return vec_splat_u8(0x100);/* { dg-error "argument 1 must be a literal between -16 and 15, inclusive" } */
}
vector unsigned short
splatu2 (void)
{
- return vec_splat_u16(0x10000);/* { dg-error "argument 1 must be a 5-bit signed literal" } */
+ return vec_splat_u16(0x10000);/* { dg-error "argument 1 must be a literal between -16 and 15, inclusive" } */
}
vector unsigned int
splatu3 (void)
{
- return vec_splat_u32(0x10000000);/* { dg-error "argument 1 must be a 5-bit signed literal" } */
+ return vec_splat_u32(0x10000000);/* { dg-error "argument 1 must be a literal between -16 and 15, inclusive" } */
}
vector signed char
splats1 (void)
{
- return vec_splat_s8(0x100);/* { dg-error "argument 1 must be a 5-bit signed literal" } */
+ return vec_splat_s8(0x100);/* { dg-error "argument 1 must be a literal between -16 and 15, inclusive" } */
}
vector signed short
splats2 (void)
{
- return vec_splat_s16(0x10000);/* { dg-error "argument 1 must be a 5-bit signed literal" } */
+ return vec_splat_s16(0x10000);/* { dg-error "argument 1 must be a literal between -16 and 15, inclusive" } */
}
vector signed int
splats3 (void)
{
- return vec_splat_s32(0x10000000);/* { dg-error "argument 1 must be a 5-bit signed literal" } */
+ return vec_splat_s32(0x10000000);/* { dg-error "argument 1 must be a literal between -16 and 15, inclusive" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/pragma_misc9.c b/gcc/testsuite/gcc.target/powerpc/pragma_misc9.c
index e03099b..c1667d9 100644
--- a/gcc/testsuite/gcc.target/powerpc/pragma_misc9.c
+++ b/gcc/testsuite/gcc.target/powerpc/pragma_misc9.c
@@ -20,7 +20,7 @@ vector bool int
test2 (vector signed int a, vector signed int b)
{
return vec_cmpnez (a, b);
- /* { dg-error "'__builtin_altivec_vcmpnezw' requires the '-mcpu=power9' option" "" { target *-*-* } .-1 } */
+ /* { dg-error "'__builtin_altivec_vcmpnezw' requires the '-mcpu=power9' and '-mvsx' options" "" { target *-*-* } .-1 } */
}
#pragma GCC target ("cpu=power7")
@@ -28,7 +28,7 @@ vector signed int
test3 (vector signed int a, vector signed int b)
{
return vec_mergee (a, b);
- /* { dg-error "'__builtin_altivec_vmrgew_v4si' requires the '-mpower8-vector' option" "" { target *-*-* } .-1 } */
+ /* { dg-error "'__builtin_altivec_vmrgew_v4si' requires the '-mcpu=power8' and '-mvsx' options" "" { target *-*-* } .-1 } */
}
#pragma GCC target ("cpu=power6")
diff --git a/gcc/testsuite/gcc.target/powerpc/pragma_power8.c b/gcc/testsuite/gcc.target/powerpc/pragma_power8.c
index c8d2cdd..cb0f308 100644
--- a/gcc/testsuite/gcc.target/powerpc/pragma_power8.c
+++ b/gcc/testsuite/gcc.target/powerpc/pragma_power8.c
@@ -19,6 +19,7 @@ test1 (vector int a, vector int b)
#pragma GCC target ("cpu=power7")
/* Force a re-read of altivec.h with new cpu target. */
#undef _ALTIVEC_H
+#undef _RS6000_VECDEFINES_H
#include <altivec.h>
#ifdef _ARCH_PWR7
vector signed int
@@ -33,6 +34,7 @@ test2 (vector signed int a, vector signed int b)
#pragma GCC target ("cpu=power8")
/* Force a re-read of altivec.h with new cpu target. */
#undef _ALTIVEC_H
+#undef _RS6000_VECDEFINES_H
#include <altivec.h>
#ifdef _ARCH_PWR8
vector int
diff --git a/gcc/testsuite/gcc.target/powerpc/pragma_power9.c b/gcc/testsuite/gcc.target/powerpc/pragma_power9.c
index e33aad1..e05f1f4 100644
--- a/gcc/testsuite/gcc.target/powerpc/pragma_power9.c
+++ b/gcc/testsuite/gcc.target/powerpc/pragma_power9.c
@@ -17,6 +17,7 @@ test1 (vector int a, vector int b)
#pragma GCC target ("cpu=power7")
#undef _ALTIVEC_H
+#undef _RS6000_VECDEFINES_H
#include <altivec.h>
#ifdef _ARCH_PWR7
vector signed int
@@ -30,6 +31,7 @@ test2 (vector signed int a, vector signed int b)
#pragma GCC target ("cpu=power8")
#undef _ALTIVEC_H
+#undef _RS6000_VECDEFINES_H
#include <altivec.h>
#ifdef _ARCH_PWR8
vector int
@@ -50,6 +52,7 @@ test3b (vec_t a, vec_t b)
#pragma GCC target ("cpu=power9,power9-vector")
#undef _ALTIVEC_H
+#undef _RS6000_VECDEFINES_H
#include <altivec.h>
#ifdef _ARCH_PWR9
vector bool int
diff --git a/gcc/testsuite/gcc.target/powerpc/rop-1.c b/gcc/testsuite/gcc.target/powerpc/rop-1.c
index 8cedcb6..12893de 100644
--- a/gcc/testsuite/gcc.target/powerpc/rop-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/rop-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mdejagnu-cpu=power10 -mrop-protect" } */
-/* { dg-require-effective-target powerpc_elfv2 } */
+/* { dg-require-effective-target rop_ok } */
/* Verify that ROP-protect instructions are inserted when a
call is present. */
diff --git a/gcc/testsuite/gcc.target/powerpc/rop-2.c b/gcc/testsuite/gcc.target/powerpc/rop-2.c
index c556952..5f1d7c3 100644
--- a/gcc/testsuite/gcc.target/powerpc/rop-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/rop-2.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mdejagnu-cpu=power10 -mrop-protect -mprivileged" } */
-/* { dg-require-effective-target powerpc_elfv2 } */
+/* { dg-require-effective-target rop_ok } */
/* Verify that privileged ROP-protect instructions are inserted when a
call is present. */
diff --git a/gcc/testsuite/gcc.target/powerpc/rop-3.c b/gcc/testsuite/gcc.target/powerpc/rop-3.c
index 8d03792..d2ef3bf 100644
--- a/gcc/testsuite/gcc.target/powerpc/rop-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/rop-3.c
@@ -1,5 +1,5 @@
/* { dg-do run { target { power10_hw } } } */
-/* { dg-require-effective-target powerpc_elfv2 } */
+/* { dg-require-effective-target rop_ok } */
/* { dg-options "-O2 -mdejagnu-cpu=power10 -mrop-protect" } */
/* Verify that ROP-protect instructions execute correctly when a
diff --git a/gcc/testsuite/gcc.target/powerpc/rop-4.c b/gcc/testsuite/gcc.target/powerpc/rop-4.c
index dcf47c6..80faa9b 100644
--- a/gcc/testsuite/gcc.target/powerpc/rop-4.c
+++ b/gcc/testsuite/gcc.target/powerpc/rop-4.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mdejagnu-cpu=power10 -mrop-protect" } */
-/* { dg-require-effective-target powerpc_elfv2 } */
+/* { dg-require-effective-target rop_ok } */
/* Verify that no ROP-protect instructions are inserted when no
call is present. */
diff --git a/gcc/testsuite/gcc.target/powerpc/rop-5.c b/gcc/testsuite/gcc.target/powerpc/rop-5.c
index f2594df..f7970f1 100644
--- a/gcc/testsuite/gcc.target/powerpc/rop-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/rop-5.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-require-effective-target powerpc_elfv2 } */
+/* { dg-require-effective-target rop_ok } */
/* { dg-options "-O2 -mdejagnu-cpu=power10 -mrop-protect" } */
/* Verify that __ROP_PROTECT__ is predefined for -mrop-protect. */
diff --git a/gcc/testsuite/gcc.target/powerpc/test_fpscr_drn_builtin_error.c b/gcc/testsuite/gcc.target/powerpc/test_fpscr_drn_builtin_error.c
index 028ab0b..4f9d9e0 100644
--- a/gcc/testsuite/gcc.target/powerpc/test_fpscr_drn_builtin_error.c
+++ b/gcc/testsuite/gcc.target/powerpc/test_fpscr_drn_builtin_error.c
@@ -9,8 +9,8 @@ int main ()
__builtin_set_fpscr_drn() also support a variable as an argument but
can't test variable value at compile time. */
- __builtin_set_fpscr_drn(-1); /* { dg-error "Argument must be a value between 0 and 7" } */
- __builtin_set_fpscr_drn(8); /* { dg-error "Argument must be a value between 0 and 7" } */
+ __builtin_set_fpscr_drn(-1); /* { dg-error "argument 1 must be a variable or a literal between 0 and 7, inclusive" } */
+ __builtin_set_fpscr_drn(8); /* { dg-error "argument 1 must be a variable or a literal between 0 and 7, inclusive" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/test_fpscr_rn_builtin_error.c b/gcc/testsuite/gcc.target/powerpc/test_fpscr_rn_builtin_error.c
index aea6509..10391b7 100644
--- a/gcc/testsuite/gcc.target/powerpc/test_fpscr_rn_builtin_error.c
+++ b/gcc/testsuite/gcc.target/powerpc/test_fpscr_rn_builtin_error.c
@@ -8,13 +8,13 @@ int main ()
int arguments. The builtins __builtin_set_fpscr_rn() also supports a
variable as an argument but can't test variable value at compile time. */
- __builtin_mtfsb0(-1); /* { dg-error "Argument must be a constant between 0 and 31" } */
- __builtin_mtfsb0(32); /* { dg-error "Argument must be a constant between 0 and 31" } */
+ __builtin_mtfsb0(-1); /* { dg-error "argument 1 must be a 5-bit unsigned literal" } */
+ __builtin_mtfsb0(32); /* { dg-error "argument 1 must be a 5-bit unsigned literal" } */
- __builtin_mtfsb1(-1); /* { dg-error "Argument must be a constant between 0 and 31" } */
- __builtin_mtfsb1(32); /* { dg-error "Argument must be a constant between 0 and 31" } */
+ __builtin_mtfsb1(-1); /* { dg-error "argument 1 must be a 5-bit unsigned literal" } */
+ __builtin_mtfsb1(32); /* { dg-error "argument 1 must be a 5-bit unsigned literal" } */
- __builtin_set_fpscr_rn(-1); /* { dg-error "Argument must be a value between 0 and 3" } */
- __builtin_set_fpscr_rn(4); /* { dg-error "Argument must be a value between 0 and 3" } */
+ __builtin_set_fpscr_rn(-1); /* { dg-error "argument 1 must be a variable or a literal between 0 and 3, inclusive" } */
+ __builtin_set_fpscr_rn(4); /* { dg-error "argument 1 must be a variable or a literal between 0 and 3, inclusive" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-gnb-2.c b/gcc/testsuite/gcc.target/powerpc/vec-gnb-2.c
index 895bb95..4e59cbf 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-gnb-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-gnb-2.c
@@ -20,7 +20,7 @@ do_vec_gnb (vector unsigned __int128 source, int stride)
case 5:
return vec_gnb (source, 1); /* { dg-error "between 2 and 7" } */
case 6:
- return vec_gnb (source, stride); /* { dg-error "unsigned literal" } */
+ return vec_gnb (source, stride); /* { dg-error "literal" } */
case 7:
return vec_gnb (source, 7);
diff --git a/gcc/testsuite/gcc.target/powerpc/vec_reve_1.c b/gcc/testsuite/gcc.target/powerpc/vec_reve_1.c
index 120c318..95751d5 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec_reve_1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec_reve_1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
-/* { dg-require-effective-target powerpc_altivec_ok } */
-/* { dg-options "-O2 -maltivec" } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mvsx" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-all-nez-7.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-all-nez-7.c
index f53c6dc..a41e82e 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-all-nez-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-all-nez-7.c
@@ -12,5 +12,5 @@ test_all_not_equal_and_not_zero (vector unsigned short *arg1_p,
vector unsigned short arg_2 = *arg2_p;
return __builtin_vec_vcmpnez_p (__CR6_LT, arg_1, arg_2);
- /* { dg-error "'__builtin_altivec_vcmpnezh_p' requires the '-mcpu=power9' option" "" { target *-*-* } .-1 } */
+ /* { dg-error "'__builtin_altivec_vcmpnezh_p' requires the '-mcpu=power9' and '-mvsx' options" "" { target *-*-* } .-1 } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-any-eqz-7.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-any-eqz-7.c
index 757acd9..3bf8a32 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-any-eqz-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-any-eqz-7.c
@@ -11,5 +11,5 @@ test_any_equal (vector unsigned int *arg1_p, vector unsigned int *arg2_p)
vector unsigned int arg_2 = *arg2_p;
return __builtin_vec_vcmpnez_p (__CR6_LT_REV, arg_1, arg_2);
- /* { dg-error "'__builtin_altivec_vcmpnezw_p' requires the '-mcpu=power9' option" "" { target *-*-* } .-1 } */
+ /* { dg-error "'__builtin_altivec_vcmpnezw_p' requires the '-mcpu=power9' and '-mvsx' options" "" { target *-*-* } .-1 } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-cmpnez-7.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-cmpnez-7.c
index 811b32f..52110af 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-cmpnez-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-cmpnez-7.c
@@ -10,5 +10,5 @@ fetch_data (vector unsigned int *arg1_p, vector unsigned int *arg2_p)
vector unsigned int arg_1 = *arg1_p;
vector unsigned int arg_2 = *arg2_p;
- return __builtin_vec_vcmpnez (arg_1, arg_2); /* { dg-error "'__builtin_altivec_vcmpnezw' requires the '-mcpu=power9' option" } */
+ return __builtin_vec_vcmpnez (arg_1, arg_2); /* { dg-error "'__builtin_altivec_vcmpnezw' requires the '-mcpu=power9' and '-mvsx' options" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-cntlz-lsbb-2.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-cntlz-lsbb-2.c
index 6ee066d..dd0d337 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-cntlz-lsbb-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-cntlz-lsbb-2.c
@@ -9,5 +9,5 @@ count_leading_zero_byte_bits (vector unsigned char *arg1_p)
{
vector unsigned char arg_1 = *arg1_p;
- return __builtin_vec_vclzlsbb (arg_1); /* { dg-error "'__builtin_altivec_vclzlsbb_v16qi' requires the '-mcpu=power9' option" } */
+ return __builtin_vec_vclzlsbb (arg_1); /* { dg-error "'__builtin_altivec_vclzlsbb_v16qi' requires the '-mcpu=power9' and '-mvsx' options" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-cnttz-lsbb-2.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-cnttz-lsbb-2.c
index ecd0add..22c55ef 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-cnttz-lsbb-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-cnttz-lsbb-2.c
@@ -9,5 +9,5 @@ count_trailing_zero_byte_bits (vector unsigned char *arg1_p)
{
vector unsigned char arg_1 = *arg1_p;
- return __builtin_vec_vctzlsbb (arg_1); /* { dg-error "'__builtin_altivec_vctzlsbb_v16qi' requires the '-mcpu=power9' option" } */
+ return __builtin_vec_vctzlsbb (arg_1); /* { dg-error "'__builtin_altivec_vctzlsbb_v16qi' requires the '-mcpu=power9' and '-mvsx' options" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-13.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-13.c
index 1cfed57..0f601fb 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-13.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-13.c
@@ -13,5 +13,5 @@
int
fetch_data (float *address, size_t length)
{
- return __builtin_vec_lxvl (address, length); /* { dg-warning "'__builtin_vec_lxvl'" } */
+ return __builtin_vec_lxvl (address, length); /* { dg-error "'__builtin_vsx_lxvl' requires the" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-12.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-12.c
index 3a51132..f30d49c 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-12.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-12.c
@@ -13,5 +13,5 @@ store_data (vector double *datap, double *address, size_t length)
{
vector double data = *datap;
- __builtin_vec_stxvl (data, address, length); /* { dg-error "'__builtin_vec_stxvl' is not supported in this compiler configuration" } */
+ __builtin_vec_stxvl (data, address, length); /* { dg-error "'__builtin_altivec_stxvl' requires the" } */
}
diff --git a/gcc/testsuite/gcc.target/pru/pru_irq_map.c b/gcc/testsuite/gcc.target/pru/pru_irq_map.c
new file mode 100644
index 0000000..4f9a5e7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/pru_irq_map.c
@@ -0,0 +1,8 @@
+/* Test the special handling of .pru_irq_map section. */
+
+/* { dg-do compile } */
+
+int my_int_map __attribute__((section(".pru_irq_map")));
+
+/* Section must not have the allocated flag. */
+/* { dg-final { scan-assembler "\.section\[ \t\]+.pru_irq_map,\[ \]*\"\",[ ]*@progbits" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/pr103302.c b/gcc/testsuite/gcc.target/riscv/pr103302.c
new file mode 100644
index 0000000..822c408
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr103302.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-options "-Og -fharden-compares -fno-tree-dce -fno-tree-fre " } */
+
+typedef unsigned char u8;
+typedef unsigned char __attribute__((__vector_size__ (32))) v256u8;
+typedef unsigned short __attribute__((__vector_size__ (32))) v256u16;
+typedef unsigned short __attribute__((__vector_size__ (64))) v512u16;
+typedef unsigned int u32;
+typedef unsigned int __attribute__((__vector_size__ (4))) v512u32;
+typedef unsigned long long __attribute__((__vector_size__ (32))) v256u64;
+typedef unsigned long long __attribute__((__vector_size__ (64))) v512u64;
+typedef unsigned __int128 __attribute__((__vector_size__ (32))) v256u128;
+typedef unsigned __int128 __attribute__((__vector_size__ (64))) v512u128;
+
+v512u16 g;
+
+void
+foo0 (u8 u8_0, v256u16 v256u16_0, v512u16 v512u16_0, u32 u32_0, v512u32,
+ v256u64 v256u64_0, v512u64 v512u64_0, v256u128 v256u128_0,
+ v512u128 v512u128_0)
+{
+ u32_0 <= (v512u128) (v512u128_0 != u8_0);
+ v512u64 v512u64_1 =
+ __builtin_shufflevector (v256u64_0, v512u64_0, 7, 8, 0, 9, 5, 0, 3, 1);
+ g = v512u16_0;
+ (v256u8) v256u16_0 + (v256u8) v256u128_0;
+}
+
+int
+main (void)
+{
+ foo0 (40, (v256u16)
+ {
+ }, (v512u16)
+ {
+ }, 0, (v512u32)
+ {
+ }, (v256u64)
+ {
+ }, (v512u64)
+ {
+ }, (v256u128)
+ {
+ }, (v512u128)
+ {
+ });
+}
diff --git a/gcc/testsuite/gdc.test/compilable/b19294.d b/gcc/testsuite/gdc.test/compilable/b19294.d
new file mode 100644
index 0000000..063a9df
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/b19294.d
@@ -0,0 +1,69 @@
+alias MT = MyStruct!int;
+
+struct MyStruct(T)
+{
+ T x;
+
+ this(T y)
+ {
+ x = y;
+ }
+
+ MyStruct!T opBinary(string op)(MyStruct!T y) const
+ {
+ alias C = typeof(return);
+ auto w = C(this.x);
+ return w.opOpAssign!(op)(y);
+ }
+
+ MyStruct!T opBinaryRight(string op)(MyStruct!T y) const
+ {
+ return opBinary!(op)(y);
+ }
+
+ ref MyStruct opOpAssign(string op, T)(const MyStruct!T z)
+ {
+ mixin ("x "~op~"= z.x;");
+ return this;
+ }
+
+ MyStruct!T opBinary(string op)(T y) const
+ {
+ alias C = typeof(return);
+ auto w = C(this.x);
+ return w.opOpAssign!(op)(y);
+ }
+
+ MyStruct!T opBinaryRight(string op)(T y) const
+ {
+ return opBinary!(op)(y);
+ }
+
+ ref MyStruct opOpAssign(string op, T)(const T z)
+ {
+ mixin ("x "~op~"= z;");
+ return this;
+ }
+}
+
+void test()
+{
+ MT s = MyStruct!int(1);
+ MT[] arr = [s, 2 * s, 3 * s, 4 * s, 5 * s, 6 * s];
+ MT[] result = new MT[arr.length];
+
+ result[] = arr[] + s;
+ result[] = s + arr[];
+
+ result[] = arr[] - s;
+ result[] = s - arr[];
+
+ result[] = arr[] * s;
+ result[] = s * arr[];
+
+ result[] = arr[] / s;
+ result[] = s / arr[];
+
+ result[] = arr[] ^^ s;
+ result[] = s ^^ arr[];
+}
diff --git a/gcc/testsuite/gdc.test/compilable/cdcmp.d b/gcc/testsuite/gdc.test/compilable/cdcmp.d
index 614bdc8..4248818 100644
--- a/gcc/testsuite/gdc.test/compilable/cdcmp.d
+++ b/gcc/testsuite/gdc.test/compilable/cdcmp.d
@@ -2,7 +2,7 @@
// REQUIRED_ARGS: -O
// POST_SCRIPT: compilable/extra-files/objdump-postscript.sh
// only testing on SYSV-ABI, but backend code is identical across platforms
-// DISABLED: win32 win64 osx linux32 freebsd32 freebsd64
+// DISABLED: win32 win64 osx linux32 freebsd32 freebsd64 openbsd32 openbsd64
bool test_ltz(ubyte x) { return x < 0; }
bool test_lez(ubyte x) { return x <= 0; }
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables_22285.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables_22285.d
new file mode 100644
index 0000000..5e8836d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables_22285.d
@@ -0,0 +1,15 @@
+// PERMUTE_ARGS:
+// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o-
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_tables_22285.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_tables_22285.html
+
+module test.compilable.ddoc_markdown_tables_22285;
+
+/**
+| A | B | C |
+|---|---|---|
+| a | 0 | |
+| b | 1 1 1 | |
+| c | 2 | |
+*/
+enum _ = 0;
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_ignored.d b/gcc/testsuite/gdc.test/compilable/dtoh_ignored.d
index 54bbc79..47c0172 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_ignored.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_ignored.d
@@ -144,4 +144,7 @@ __gshared void function(ifloat) onVariableFunctionParam;
__gshared ifloat delegate() onVariableDelegate;
-noreturn myExit() {}
+noreturn myExit()
+{
+ assert(false);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c b/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c
deleted file mode 100644
index f6aaf3b..0000000
--- a/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// check bugs in importing C files
-
-int squared(int a)
-{
- return a * a;
-}
diff --git a/gcc/testsuite/gdc.test/compilable/mixintype2.d b/gcc/testsuite/gdc.test/compilable/mixintype2.d
index 43803df..d160bd4 100644
--- a/gcc/testsuite/gdc.test/compilable/mixintype2.d
+++ b/gcc/testsuite/gdc.test/compilable/mixintype2.d
@@ -66,3 +66,52 @@ static assert(is(T8 == const(ubyte*)));
alias T8 = mixin(q{immutable(__traits(getMember, S, "T"))})*;
static assert(is(T8 == immutable(float*)*));
*/
+
+/**************************************************/
+// https://issues.dlang.org/show_bug.cgi?id=22356
+
+mixin("void") func22356(int) { }
+static assert(is(typeof(&func22356) == void function(int)));
+
+static mixin("void") func22356_s(char) { }
+static assert(is(typeof(&func22356_s) == void function(char)));
+
+mixin("int")[2] func22356_2(int) { return [1, 2]; }
+static assert(is(typeof(&func22356_2) == int[2] function(int)));
+
+mixin("int") func22356tp(S, T)(S, T) { return 1; }
+static assert(is(typeof(&func22356tp!(char, float)) == int function(char, float) pure nothrow @nogc @safe));
+
+mixin("int") x22356;
+static assert(is(typeof(x22356) == int));
+
+mixin("int")** xpp22356;
+static assert(is(typeof(xpp22356) == int**));
+
+mixin("int") y22356, z22356;
+static assert(is(typeof(y22356) == int) && is(typeof(z22356) == int));
+
+// Already working but for completeness
+void test_statements_22356()
+{
+ mixin("void") func22356(int) { }
+ static assert(is(typeof(&func22356) == void delegate(int) pure nothrow @nogc @safe));
+
+ static mixin("void") func22356_s(char) { }
+ static assert(is(typeof(&func22356_s) == void function(char) pure nothrow @nogc @safe));
+
+ mixin("int")[2] func22356_2(int) { return [1, 2]; }
+ static assert(is(typeof(&func22356_2) == int[2] delegate(int) pure nothrow @nogc @safe));
+
+ mixin("int") func22356tp(S, T)(S, T) { return 1; }
+ static assert(is(typeof(&func22356tp!(char, float)) == int delegate(char, float) pure nothrow @nogc @safe));
+
+ mixin("int") x22356;
+ static assert(is(typeof(x22356) == int));
+
+ mixin("int")** xpp22356;
+ static assert(is(typeof(xpp22356) == int**));
+
+ mixin("int") y22356, z22356;
+ static assert(is(typeof(y22356) == int) && is(typeof(z22356) == int));
+}
diff --git a/gcc/testsuite/gdc.test/compilable/noreturn1.d b/gcc/testsuite/gdc.test/compilable/noreturn1.d
index 7517bb2..b041e07 100644
--- a/gcc/testsuite/gdc.test/compilable/noreturn1.d
+++ b/gcc/testsuite/gdc.test/compilable/noreturn1.d
@@ -49,8 +49,17 @@ static assert(noreturn.alignof == 0);
static assert((noreturn*).sizeof == (int*).sizeof);
static assert((noreturn[]).sizeof == (int[]).sizeof);
+static assert(is(typeof(noreturn.init) == noreturn));
+static assert(is(typeof((const noreturn).init) == const noreturn));
+static assert(is(typeof((immutable noreturn).init) == immutable noreturn));
+static assert(is(typeof((shared noreturn).init) == shared noreturn));
+
version (DigitalMars)
- noreturn exits(int* p) { *p = 3; }
+ noreturn exits(int* p)
+ {
+ *p = 3;
+ assert(false); // *p could be valid
+ }
noreturn exit();
@@ -58,9 +67,47 @@ noreturn pureexits() @nogc nothrow pure @safe { assert(0); }
noreturn callpureexits() { pureexits(); }
+noreturn returnExits()
+{
+ return pureexits();
+}
+
+void alsoExits()
+{
+ return assert(0);
+}
+
+int thisAlsoExits()
+{
+ return assert(0);
+}
+
+void cast_()
+{
+ noreturn n;
+ int i = n;
+}
+
int test1(int i)
{
if (exit())
return i + 1;
return i - 1;
}
+
+noreturn tlsNoreturn;
+__gshared noreturn globalNoreturn;
+
+template CreateTLS(A)
+{
+ A a;
+}
+
+void* useTls()
+{
+ alias Tnr = CreateTLS!noreturn;
+ void* a1 = &Tnr.a;
+ void* a2 = &tlsNoreturn;
+ void* a3 = &globalNoreturn;
+ return a1 < a2 ? a2 : a3;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/previewall.d b/gcc/testsuite/gdc.test/compilable/previewall.d
deleted file mode 100644
index e5ed7a8..0000000
--- a/gcc/testsuite/gdc.test/compilable/previewall.d
+++ /dev/null
@@ -1,10 +0,0 @@
-// ARG_SETS: -preview=all
-// ARG_SETS: -transition=all
-// ARG_SETS: -revert=all
-import core.stdc.stdio;
-
-void main (string[] args)
-{
- if (args.length == 42)
- printf("Hello World\n");
-}
diff --git a/gcc/testsuite/gdc.test/compilable/reinterpretctfe.d b/gcc/testsuite/gdc.test/compilable/reinterpretctfe.d
index 1d6fd4f..9a4db35 100644
--- a/gcc/testsuite/gdc.test/compilable/reinterpretctfe.d
+++ b/gcc/testsuite/gdc.test/compilable/reinterpretctfe.d
@@ -1,5 +1,11 @@
// https://issues.dlang.org/show_bug.cgi?id=21997
+struct Strukt
+{
+ int i;
+ string s;
+}
+
int nonPureFunc(int i)
{
return 2 * i;
@@ -28,6 +34,14 @@ int mainCtfe()
auto baseDel = cast(int delegate(int)) pureDel;
assert(baseDel(4) == 20);
*/
+
+ {
+ shared Strukt shStr;
+ Strukt str = *cast(Strukt*) &shStr;
+
+ shared(Strukt)* ptr = cast(shared(Strukt)*) &str;
+ }
+
return 0;
}
diff --git a/gcc/testsuite/gdc.test/compilable/sroa.d b/gcc/testsuite/gdc.test/compilable/sroa.d
new file mode 100644
index 0000000..8ea515c
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/sroa.d
@@ -0,0 +1,55 @@
+/* REQUIRED_ARGS: -O -release -inline
+This compares two different ways to do a for loop. The range
+version should SROA the VecRange struct into two register variables.
+*/
+
+extern (C):
+
+nothrow:
+@nogc:
+@safe:
+
+alias vec_base_t = size_t; // base type of vector
+alias vec_t = vec_base_t*;
+
+@trusted
+pure
+size_t vec_index(size_t b, const vec_t vec);
+
+@trusted
+pure ref inout(vec_base_t) vec_numbits(inout vec_t v) { return v[-1]; }
+@trusted
+pure ref inout(vec_base_t) vec_dim(inout vec_t v) { return v[-2]; }
+
+struct VecRange
+{
+ size_t i;
+ const vec_t v;
+
+ @nogc @safe nothrow pure:
+ this(const vec_t v) { this.v = v; i = vec_index(0, v); }
+ bool empty() const { return i == vec_numbits(v); }
+ size_t front() const { return i; }
+ void popFront() { i = vec_index(i + 1, v); }
+}
+
+@safe
+pure
+uint vec_numBitsSet(const vec_t vec)
+{
+ uint n = 0;
+ size_t length = vec_numbits(vec);
+ for (size_t i = 0; (i = vec_index(i, vec)) < length; ++i)
+ ++n;
+ return n;
+}
+
+@safe
+pure
+uint vec_numBitsSet2(const vec_t vec)
+{
+ uint n = 0;
+ foreach (j; VecRange(vec))
+ ++n;
+ return n;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/stc_traits.d b/gcc/testsuite/gdc.test/compilable/stc_traits.d
new file mode 100644
index 0000000..c5c4e5f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/stc_traits.d
@@ -0,0 +1,172 @@
+// REQUIRED_ARGS: -preview=dip1000 -preview=in
+/*
+TEST_OUTPUT:
+---
+100 tuple()
+101 tuple("return", "ref")
+102 tuple("ref")
+103 tuple()
+104 tuple("ref")
+105 tuple()
+106 tuple()
+107 tuple("ref")
+108 tuple("ref")
+109 tuple("ref")
+110 tuple("ref")
+111 tuple()
+112 tuple("ref")
+113 tuple("ref")
+114 tuple("ref")
+115 tuple("ref")
+116 tuple()
+117 tuple("ref")
+118 tuple("ref")
+119 tuple()
+120 tuple("ref")
+121 tuple()
+122 tuple("ref")
+123 tuple("in")
+124 tuple("in")
+m tuple("ref")
+m-mixin tuple("ref")
+m tuple("ref")
+m-mixin tuple("ref")
+m tuple("ref")
+m-mixin tuple("ref")
+m tuple("return", "ref")
+m-mixin tuple("return", "ref")
+m tuple("ref")
+m-mixin tuple("ref")
+m tuple("ref")
+m-mixin tuple("ref")
+m tuple()
+m-mixin tuple()
+m tuple("ref")
+m-mixin tuple("ref")
+m tuple("ref")
+m-mixin tuple("ref")
+m tuple("ref")
+m-mixin tuple("ref")
+m tuple("ref")
+m-mixin tuple("ref")
+m tuple("ref")
+m-mixin tuple("ref")
+m tuple("ref")
+m-mixin tuple("ref")
+m tuple("in")
+m-mixin tuple("in")
+---
+*/
+
+void func(int i) {}
+void func(return ref bool i) {}
+void func(ref float a, int b) {}
+void get(T : int)(ref T t) {}
+void get()(float t) {}
+void get(T)(ref T[] t) {}
+void funcautoi()(auto ref int i) {}
+void funcauto(T)(auto ref T a) {}
+void funcin(in int i) {}
+
+struct Foo {
+ void foo(int i) {}
+ void foo(ref bool i) {}
+ static void sfoo(ref int i) {}
+}
+
+struct FooT(T) {
+ void foo(ref T i) {}
+ static void sfoo(ref T i) {}
+}
+
+class Bar {
+ void bar(int i) {}
+ void bar(ref bool i) {}
+ static void sbar(ref int i) {}
+}
+
+class BarT(T) {
+ void bar(ref T i) {}
+ static void sbar(ref T i) {}
+}
+
+int i;
+
+template match(handlers...)
+{
+ static foreach(h; handlers)
+ {
+ // should give the same result
+ pragma(msg, "m ", __traits(getParameterStorageClasses, h(i), 0));
+ pragma(msg, "m-mixin ", __traits(getParameterStorageClasses, mixin("h(i)"), 0));
+ }
+
+ enum match = (){};
+}
+
+void funcT(T)(ref T t) {}
+
+void main() {
+ int i;
+ bool b;
+ float f;
+ int[] ia;
+ Foo foo;
+ FooT!int foot;
+ Bar bar = new Bar;
+ BarT!int bart = new BarT!int;
+
+ ref int _foo(return ref const int* p, scope int* a, out int b, lazy int c);
+
+ // From SPEC_RUNNABLE_EXAMPLE_COMPILE:
+ int* p, a;
+ int _b, c;
+
+ static assert(__traits(getParameterStorageClasses, _foo(p, a, _b, c), 1)[0] == "scope");
+ static assert(__traits(getParameterStorageClasses, _foo(p, a, _b, c), 2)[0] == "out");
+ static assert(__traits(getParameterStorageClasses, _foo(p, a, _b, c), 3)[0] == "lazy");
+
+#line 100
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, func(0), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, func(b), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, func(f, i), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, func(f, i), 1));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, get(i), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, get(0.0), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, get(f), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, get(ia), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, mixin("get(i)"), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, Foo.sfoo(i), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, FooT!int.sfoo(i), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, foo.foo(0), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, foo.foo(b), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, foot.foo(i), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, Bar.sbar(i), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, BarT!int.sbar(i), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, bar.bar(0), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, bar.bar(b), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, bart.bar(i), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, funcautoi(10), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, funcautoi(i), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, funcauto(10), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, funcauto(i), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, funcin(1), 0));
+ pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, funcin(i), 0));
+
+ cast(void) match!(
+ function(ref int i) => true,
+ delegate(ref int i) => true,
+ (ref int i) => true,
+ (return ref int i) => &i,
+ get,
+ funcT,
+ (int i) => true,
+ FooT!int.sfoo,
+ Foo.sfoo,
+ BarT!int.sbar,
+ Bar.sbar,
+ funcautoi,
+ funcauto,
+ funcin,
+ );
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test15711.d b/gcc/testsuite/gdc.test/compilable/test15711.d
new file mode 100644
index 0000000..ba7a93d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test15711.d
@@ -0,0 +1,31 @@
+// https://issues.dlang.org/show_bug.cgi?id=15711
+
+struct Quu {
+ string val;
+}
+
+string[] result = foo!(0, [Quu(['z']), Quu("")]);
+
+template foo(size_t i, Quu[] data, string[] results = []) {
+ static if (i < data.length) {
+ enum def = data[i];
+ enum foo = foo!(i+1, data, results ~ def.val);
+ }
+ else {
+ enum foo = results;
+ }
+}
+
+// Run-time version already works
+
+string[] result_rt = foo_rt(0, [Quu(['z']), Quu("")]);
+
+string[] foo_rt(size_t i, Quu[] data, string[] results = []) {
+ if (i < data.length) {
+ auto def = data[i];
+ return foo_rt(i+1, data, results ~ def.val);
+ }
+ else {
+ return results;
+ }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test16492.d b/gcc/testsuite/gdc.test/compilable/test16492.d
deleted file mode 100644
index 833be1d..0000000
--- a/gcc/testsuite/gdc.test/compilable/test16492.d
+++ /dev/null
@@ -1,87 +0,0 @@
-// ARG_SETS: -debug; -o-; -debug -preview=dip1000
-// https://issues.dlang.org/show_bug.cgi?id=16492
-
-void mayCallGC();
-
-void test() @nogc pure
-{
- debug new int(1);
- debug
- {
- mayCallGC();
- auto b = [1, 2, 3];
- b ~= 4;
- }
-}
-
-void debugSafe() @safe
-{
- debug unsafeSystem();
- debug unsafeTemplated();
-}
-
-void unsafeSystem() @system {}
-void unsafeTemplated()() {
- int[] arr;
- auto b = arr.ptr;
-}
-
-void debugSafe2() @safe
-{
- char[] arr1, arr2;
- debug unsafeDIP1000Lifetime(arr1, arr2);
-
- char* ptr;
- char[] arr;
- debug ptr = arr.ptr;
-}
-
-void unsafeDIP1000Lifetime()(ref char[] p, scope char[] s)
-{
- p = s;
-}
-
-
-void test2() nothrow
-{
- debug throw new Exception("");
-}
-
-void test3() nothrow
-{
- debug {
- foreach (_; 0 .. 10) {
- if (1) {
- throw new Exception("");
- }
- }
- }
-}
-
-void test4() nothrow
-{
- debug throwException();
-}
-
-void test5() nothrow
-{
- debug willThrowException();
-}
-
-void willThrowException()()
-{
- throwException();
-}
-
-void throwException()
-{
- throw new Exception("");
-}
-
-void test6() nothrow
-{
- debug
- {
- () {throw new Exception("");}();
- }
-}
diff --git a/gcc/testsuite/gdc.test/compilable/test19482.d b/gcc/testsuite/gdc.test/compilable/test19482.d
new file mode 100644
index 0000000..09485a3
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test19482.d
@@ -0,0 +1,68 @@
+// https://issues.dlang.org/show_bug.cgi?id=19482
+
+alias AliasSeq(T...) = T;
+
+extern (C++, "cppns")
+@("asd", 123)
+private
+deprecated
+immutable
+static foreach (i; 0 .. 1)
+{
+ static assert(is(typeof(i) == int));
+ static assert(__traits(getLinkage, i) == "D");
+ static assert(__traits(isDeprecated, i) == false);
+ static assert(__traits(getAttributes, i).length == 0);
+ static assert(__traits(getCppNamespaces, i).length == 0);
+ static assert(__traits(getVisibility, i) == "public");
+
+ extern int x;
+ static assert(is(typeof(x) == immutable int));
+ static assert(__traits(getLinkage, x) == "C++");
+ static assert(__traits(isDeprecated, x) == true);
+ static assert(__traits(getAttributes, x) == AliasSeq!("asd", 123));
+ static assert(__traits(getCppNamespaces, x) == AliasSeq!("cppns"));
+ static assert(__traits(getVisibility, x) == "private");
+}
+
+struct S
+{
+ @disable static foreach (j; 0 .. 1)
+ {
+ int y;
+ static assert(__traits(isDisabled, j) == false);
+ static assert(__traits(isDisabled, S.y) == true);
+ }
+}
+
+const
+static foreach (i, v; ['a'])
+{
+ static assert(is(typeof(i) == size_t));
+ static assert(is(typeof(v) == char));
+}
+
+const
+static foreach (i, s, f; Range())
+{
+ static assert(is(typeof(i) == int));
+ static assert(is(typeof(s) == string));
+ static assert(is(typeof(f) == float));
+}
+
+struct Range
+{
+ int i;
+ auto front()
+ {
+ return Tup!(int, string, float)(123, "asd", 3.14f);
+ }
+ bool empty() { return i > 0; }
+ void popFront() { ++i; }
+}
+
+struct Tup(T...)
+{
+ T fields;
+ alias fields this;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test21438.d b/gcc/testsuite/gdc.test/compilable/test21438.d
new file mode 100644
index 0000000..02e2d8d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test21438.d
@@ -0,0 +1,15 @@
+// https://issues.dlang.org/show_bug.cgi?id=21438
+
+int genGBPLookup() {
+ static struct Table {
+ int[1] entries;
+ }
+
+ auto table = new Table;
+ auto x = table.entries[0];
+
+ static assert(is(typeof(x) == int));
+ return 0;
+}
+
+enum x = genGBPLookup;
diff --git a/gcc/testsuite/gdc.test/compilable/test21794.d b/gcc/testsuite/gdc.test/compilable/test21794.d
new file mode 100644
index 0000000..68e504b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test21794.d
@@ -0,0 +1,52 @@
+// https://issues.dlang.org/show_bug.cgi?id=21794
+/*
+TEST_OUTPUT:
+---
+0
+0u
+0L
+0LU
+0.0F
+0.0
+0.0L
+---
+*/
+
+bool fun(void* p) {
+ const x = cast(ulong)p;
+ return 1;
+}
+
+static assert(fun(null));
+
+T fun2(T)(void* p) {
+ const x = cast(T)p;
+ return x;
+}
+
+// These were an error before, they were returning a NullExp instead of IntegerExp/RealExp
+
+static assert(fun2!int(null) == 0);
+static assert(fun2!uint(null) == 0);
+static assert(fun2!long(null) == 0);
+static assert(fun2!ulong(null) == 0);
+static assert(fun2!float(null) == 0);
+static assert(fun2!double(null) == 0);
+static assert(fun2!real(null) == 0);
+
+// These were printing 'null' instead of the corresponding number
+
+const i = cast(int)null;
+const ui = cast(uint)null;
+const l = cast(long)null;
+const ul = cast(ulong)null;
+const f = cast(float)null;
+const d = cast(double)null;
+const r = cast(real)null;
+pragma(msg, i);
+pragma(msg, ui);
+pragma(msg, l);
+pragma(msg, ul);
+pragma(msg, f);
+pragma(msg, d);
+pragma(msg, r);
diff --git a/gcc/testsuite/gdc.test/compilable/test21850.d b/gcc/testsuite/gdc.test/compilable/test21850.d
new file mode 100644
index 0000000..e7fe2d4
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test21850.d
@@ -0,0 +1,35 @@
+// https://issues.dlang.org/show_bug.cgi?id=21850
+
+struct Strukt2 {
+ this(int* _block) { }
+}
+
+struct Strukt {
+ int* block;
+ Strukt2 foo() { return Strukt2(null); }
+ alias foo this;
+}
+
+bool wrapper(T)(ref T a, ref T b)
+{
+ return doesPointTo(a, b);
+}
+
+void johan() pure {
+ Strukt a;
+ Strukt b;
+ assert(wrapper(a, b)); // error wrapper is not pure
+ assert(doesPointTo(a, b)); // fine
+}
+
+bool doesPointTo(S, T)(S , T) {
+ return false;
+}
+
+bool doesPointTo(S)(shared S) {
+ return false;
+}
+
+bool mayPointTo(){
+ return false;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test22214.d b/gcc/testsuite/gdc.test/compilable/test22214.d
new file mode 100644
index 0000000..d218125
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22214.d
@@ -0,0 +1,16 @@
+// https://issues.dlang.org/show_bug.cgi?id=22214
+
+struct S
+{
+ struct T
+ {
+ }
+}
+
+void main() {
+ const S s;
+ static if (__traits(compiles, { auto t = s.T; }))
+ {
+ auto t = s.T;
+ }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test22224.d b/gcc/testsuite/gdc.test/compilable/test22224.d
new file mode 100644
index 0000000..d16b2f40
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22224.d
@@ -0,0 +1,4 @@
+// REQUIRED_ARGS: -profile -c
+
+import core.stdc.stdarg;
+void error(...) { }
diff --git a/gcc/testsuite/gdc.test/compilable/test22228.d b/gcc/testsuite/gdc.test/compilable/test22228.d
new file mode 100644
index 0000000..ef31b4b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22228.d
@@ -0,0 +1,11 @@
+// https://issues.dlang.org/show_bug.cgi?id=22228
+// Note: fixed by reverting pull #11545
+
+auto f()
+{ immutable int i;
+ auto p = (() => &i)();
+
+ return 0;
+}
+
+enum ctfeInvocation = f;
diff --git a/gcc/testsuite/gdc.test/compilable/test22292.d b/gcc/testsuite/gdc.test/compilable/test22292.d
new file mode 100644
index 0000000..945dffb
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22292.d
@@ -0,0 +1,155 @@
+// https://issues.dlang.org/show_bug.cgi?id=22292
+
+// Original case
+
+class C1
+{
+ C1 c1;
+ this () pure
+ {
+ c1 = this;
+ }
+}
+immutable x = cast(immutable)r;
+
+auto r()
+{
+ C1 c1 = new C1;
+ return c1;
+}
+
+// Reference stored in another class
+
+template Test2()
+{
+ class C1
+ {
+ C2 c2;
+ this () pure
+ {
+ C1 a = this;
+ c2 = new C2(a);
+ }
+ }
+ class C2
+ {
+ C1 c1;
+ this (C1 c) pure
+ {
+ c1 = c;
+ }
+ }
+ immutable x = cast(immutable)r;
+
+ auto r()
+ {
+ C1 c1 = new C1();
+ return c1;
+ }
+}
+
+alias test2 = Test2!();
+
+// Ditto but using a struct in the middle
+
+template Test3()
+{
+ class C0
+ {
+ S1 s1;
+
+ this()
+ {
+ s1 = S1(this);
+ }
+ }
+ struct S1
+ {
+ C1 c1;
+ this (C0 c)
+ {
+ c1 = new C1(c);
+ }
+ }
+ class C1
+ {
+ C0 c0;
+ this(C0 c)
+ {
+ c0 = c;
+ }
+ }
+ immutable x = cast(immutable)r;
+
+ auto r()
+ {
+ C0 c0 = new C0();
+ return c0;
+ }
+}
+
+alias test3 = Test3!();
+
+// From https://issues.dlang.org/show_bug.cgi?id=22114
+
+template Test4()
+{
+ public class Test1(T)
+ {
+ private Test2!T val;
+
+ this()
+ {
+ val = new Test2!T(this);
+ }
+
+ private class Test2(T)
+ {
+ private Test1!(T) m_source;
+
+ this(Test1!T source)
+ {
+ m_source = source;
+ }
+ }
+ }
+
+ public class Demo
+ {
+ auto val = new Test1!int();
+ }
+}
+
+alias test4 = Test4!();
+
+// ditto
+
+template Test5()
+{
+ public @nogc class TestA(T)
+ {
+ private TestB!T valA;
+ private TestB!T valB;
+ this()
+ {
+ valB = valA = new TestB!T(this);
+ }
+
+ private @nogc class TestB(T)
+ {
+ private TestA!(T) m_source;
+
+ this(TestA!T source)
+ {
+ m_source = source;
+ }
+ }
+ }
+
+ public class Demo
+ {
+ auto val = new TestA!int();
+ }
+}
+
+alias test5 = Test5!();
diff --git a/gcc/testsuite/gdc.test/compilable/test22388.d b/gcc/testsuite/gdc.test/compilable/test22388.d
new file mode 100644
index 0000000..cf8c3fc
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22388.d
@@ -0,0 +1,22 @@
+// https://issues.dlang.org/show_bug.cgi?id=22388
+
+void setTimer(void delegate()) @system;
+void setTimer(void delegate() @safe) @safe;
+
+void setTimer2(void delegate() @safe) @safe;
+void setTimer2(void delegate()) @system;
+
+void main() @safe
+{
+ setTimer(() => assert(false));
+
+ alias lambda = () => assert(false);
+ setTimer(lambda);
+
+ // Reversed order
+
+ setTimer2(() => assert(false));
+
+ alias lambda2 = () => assert(false);
+ setTimer2(lambda2);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test22410.d b/gcc/testsuite/gdc.test/compilable/test22410.d
new file mode 100644
index 0000000..7e631b7
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22410.d
@@ -0,0 +1,59 @@
+// https://issues.dlang.org/show_bug.cgi?id=22410
+
+alias A(T...) = T;
+
+void fun0(const A!(int, string) x = A!(1, "asdf"))
+{
+ static assert(is(typeof(x) == A!(const int, const string)));
+}
+
+void fun1(const A!(immutable int, string) x = A!(1, "asdf"))
+{
+ static assert(is(typeof(x) == A!(immutable int, const string)));
+}
+
+void fun2(shared A!(int, string) x = A!(1, "asdf"))
+{
+ static assert(is(typeof(x) == A!(shared int, shared string)));
+}
+
+void fun3(shared const A!(int, string) x = A!(1, "asdf"))
+{
+ static assert(is(typeof(x) == A!(shared const int, shared const string)));
+}
+
+void fun4(inout A!(int, const string) x = A!(1, "asdf"))
+{
+ static assert(is(typeof(x) == A!(inout int, inout const string)));
+}
+
+void fun5(ref const A!(int, string) x = A!(1, "asdf"))
+{
+ static assert(is(typeof(x) == A!(const int, const string)));
+ static assert(__traits(isRef, x[0]) && __traits(isRef, x[1]));
+}
+
+// Implicitly conversion is also fixed, for example:
+// from (ulong, double) to (int, float)
+
+// Integral narrowing here, ulong(uint.max + 1UL) would fail.
+void fun10(A!(uint, float) x = A!(ulong(uint.max), 3.14))
+{
+ static assert(is(typeof(x) == A!(uint, float)));
+}
+
+void fun11(A!(int, double) x = A!(byte(1), 2.5f))
+{
+ static assert(is(typeof(x) == A!(int, double)));
+}
+
+void fun12(A!(byte, float) x = A!(1, 'a'))
+{
+ static assert(is(typeof(x) == A!(byte, float)));
+}
+
+A!(const int, shared char) tup = A!(1, 'a');
+void fun13(A!(byte, float) x = tup)
+{
+ static assert(is(typeof(x) == A!(byte, float)));
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test22420.d b/gcc/testsuite/gdc.test/compilable/test22420.d
new file mode 100644
index 0000000..c18d0a9
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22420.d
@@ -0,0 +1,88 @@
+// https://issues.dlang.org/show_bug.cgi?id=22420
+
+struct File
+{
+ ~this()
+ {
+ }
+ File impl()
+ {
+ return File.init;
+ }
+ alias impl this;
+}
+struct Variable
+{
+ this(File)(File) { }
+ this(File)(File[]) { }
+}
+Variable wrapFunctionReturn(alias handler)(Variable params)
+{
+ return Variable(handler(params));
+}
+void registerFile()
+{
+ wrapFunctionReturn!((Variable) {
+ return File.init;
+ })(Variable.init);
+}
+
+// Reduction from an 'automem' test
+
+struct Issue156 {}
+
+void test2()
+{
+ RefCounted!Issue156 s;
+ auto r1 = repeat(s);
+ zip(r1);
+}
+
+struct RefCounted(RefCountedType)
+{
+ ~this() {}
+ alias _impl this;
+
+ struct Impl {}
+ alias ImplType = Impl;
+
+ private ImplType* _impl;
+
+}
+template Tuple(Specs)
+{
+ struct Tuple
+ {
+ this(U)(U) {}
+ this()(int) {}
+ }
+}
+
+template ElementType(R)
+{
+ static if (is(typeof(R.init) T))
+ alias ElementType = T;
+}
+
+struct Repeat(T)
+{
+ inout(T) front() inout {assert(0);}
+}
+
+Repeat!T repeat(T)(T ) {assert(0);}
+
+auto zip(Ranges)(Ranges )
+{
+ return ZipShortest!Ranges();
+}
+
+struct ZipShortest(Ranges...)
+{
+ Ranges ranges;
+ alias ElementType = Tuple!(.ElementType!(Ranges[0]));
+
+ ElementType front()
+ {
+ return typeof(return)(ranges[0].front);
+ }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test22421.d b/gcc/testsuite/gdc.test/compilable/test22421.d
new file mode 100644
index 0000000..902646d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22421.d
@@ -0,0 +1,19 @@
+// https://issues.dlang.org/show_bug.cgi?id=22421
+
+alias AliasSeq(T...) = T;
+
+template staticMap(alias fun, args...)
+{
+ alias staticMap = AliasSeq!();
+ static foreach(arg; args)
+ staticMap = AliasSeq!(staticMap, fun!arg);
+}
+
+template id(alias what)
+{
+ enum id = __traits(identifier, what);
+}
+
+enum A { a }
+
+static assert(staticMap!(id, A.a) == AliasSeq!("a"));
diff --git a/gcc/testsuite/gdc.test/compilable/test318.d b/gcc/testsuite/gdc.test/compilable/test318.d
new file mode 100644
index 0000000..fd3cabe
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test318.d
@@ -0,0 +1,19 @@
+// LINK:
+// PERMUTE_ARGS: -version=C_Main
+
+version (C_Main)
+{
+ // Fine, infers int
+ extern(C) auto main(int argc, const char** argv)
+ {
+ return argc;
+ }
+}
+else
+{
+ // Fine, infers void
+ auto main()
+ {
+
+ }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test4090.d b/gcc/testsuite/gdc.test/compilable/test4090.d
index 8f8f7c9..0e785cf 100644
--- a/gcc/testsuite/gdc.test/compilable/test4090.d
+++ b/gcc/testsuite/gdc.test/compilable/test4090.d
@@ -12,9 +12,6 @@ void test4090a()
// inference + qualifier + ref
foreach ( ref x; arr) static assert(is(typeof(x) == int));
foreach ( const ref x; arr) static assert(is(typeof(x) == const int));
- static assert(!__traits(compiles, {
- foreach (immutable ref x; arr) {}
- }));
// with exact type + qualifier
foreach ( int x; arr) static assert(is(typeof(x) == int));
@@ -24,25 +21,11 @@ void test4090a()
// with exact type + qualifier + ref
foreach ( ref int x; arr) static assert(is(typeof(x) == int));
foreach ( const ref int x; arr) static assert(is(typeof(x) == const int));
- static assert(!__traits(compiles, {
- foreach (immutable ref int x; arr) {}
- }));
// convertible type + qualifier
foreach ( double x; arr) static assert(is(typeof(x) == double));
foreach ( const double x; arr) static assert(is(typeof(x) == const double));
foreach (immutable double x; arr) static assert(is(typeof(x) == immutable double));
-
- // convertible type + qualifier + ref
- static assert(!__traits(compiles, {
- foreach ( ref double x; arr) {}
- }));
- static assert(!__traits(compiles, {
- foreach ( const ref double x; arr) {}
- }));
- static assert(!__traits(compiles, {
- foreach (immutable ref double x; arr) {}
- }));
}
// for the immutable elements
{
diff --git a/gcc/testsuite/gdc.test/compilable/test9766.d b/gcc/testsuite/gdc.test/compilable/test9766.d
index 3cfc22f..aaceb7d 100644
--- a/gcc/testsuite/gdc.test/compilable/test9766.d
+++ b/gcc/testsuite/gdc.test/compilable/test9766.d
@@ -69,9 +69,9 @@ static assert(U9766.var4.offsetof == 40);
struct TestMaxAlign
{
-align(1u << 31):
+align(1u << 15):
ubyte a;
ubyte b;
}
-static assert(TestMaxAlign.b.offsetof == 2147483648u);
+static assert(TestMaxAlign.b.offsetof == (1 << 15));
diff --git a/gcc/testsuite/gdc.test/compilable/testcstuff3.d b/gcc/testsuite/gdc.test/compilable/testcstuff3.d
deleted file mode 100644
index 89228a9..0000000
--- a/gcc/testsuite/gdc.test/compilable/testcstuff3.d
+++ /dev/null
@@ -1,4 +0,0 @@
-// EXTRA_FILES: imports/cstuff3.c
-import imports.cstuff3;
-
-static assert(squared(4) == 16);
diff --git a/gcc/testsuite/gdc.test/compilable/transition_in.d b/gcc/testsuite/gdc.test/compilable/transition_in.d
new file mode 100644
index 0000000..cc492a7
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/transition_in.d
@@ -0,0 +1,26 @@
+// REQUIRED_ARGS: -transition=in
+/*
+TRANSFORM_OUTPUT: remove_lines(druntime)
+TEST_OUTPUT:
+---
+compilable/transition_in.d(3): Usage of 'in' on parameter
+compilable/transition_in.d(3): Usage of 'in' on parameter
+compilable/transition_in.d(8): Usage of 'in' on parameter
+compilable/transition_in.d(13): Usage of 'in' on parameter
+---
+*/
+#line 1
+struct Foobar
+{
+ void bar (in int a, in Object c);
+}
+
+version (none)
+{
+ void barfoo (in string arg);
+}
+
+void main ()
+{
+ void nested (in char c) {}
+}
diff --git a/gcc/testsuite/gdc.test/compilable/zerosize.d b/gcc/testsuite/gdc.test/compilable/zerosize.d
index 3c0062e..6e26deb 100644
--- a/gcc/testsuite/gdc.test/compilable/zerosize.d
+++ b/gcc/testsuite/gdc.test/compilable/zerosize.d
@@ -1,12 +1,17 @@
extern (C) struct S { }
-static assert(S.sizeof == 0);
-static assert(S.alignof == 1);
+version (CRuntime_Microsoft)
+ static assert(S.sizeof == 4);
+else
+ static assert(S.sizeof == 0);
+
+version (CRuntime_DigitalMars)
+ static assert(S.alignof == 0);
+else
+ static assert(S.alignof == 1);
extern (C++) struct T { }
static assert(T.sizeof == 1);
static assert(T.alignof == 1);
-
-
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10327.d b/gcc/testsuite/gdc.test/fail_compilation/diag10327.d
index 38f9ccb..1366882 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag10327.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag10327.d
@@ -1,7 +1,8 @@
/*
TEST_OUTPUT:
---
-fail_compilation/diag10327.d(11): Error: module `test10327` is in file 'imports/test10327.d' which cannot be read
+fail_compilation/diag10327.d(12): Error: unable to read module `test10327`
+fail_compilation/diag10327.d(12): Expected 'imports/test10327.d' or 'imports/test10327/package.d' in one of the following import paths:
import path[0] = fail_compilation
import path[1] = $p:druntime/import$
import path[2] = $p:phobos$
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag20059.d b/gcc/testsuite/gdc.test/fail_compilation/diag20059.d
index a7a5914..2c8063a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag20059.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag20059.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/diag20059.d(15): Error: Expected return type of `string`, not `string[]`:
+fail_compilation/diag20059.d(15): Error: expected return type of `string`, not `string[]`:
fail_compilation/diag20059.d(13): Return type of `string` inferred here.
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail20618.d b/gcc/testsuite/gdc.test/fail_compilation/fail20618.d
new file mode 100644
index 0000000..ac6b33a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail20618.d
@@ -0,0 +1,16 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail20618.d(13): Error: in slice `a[1 .. 12]`, upper bound is greater than array length `10`
+fail_compilation/fail20618.d(14): Error: in slice `a[4 .. 3]`, lower bound is greater than upper bound
+fail_compilation/fail20618.d(15): Error: in slice `a[0 .. 11]`, upper bound is greater than array length `10`
+---
+*/
+
+void main()
+{
+ int[10] a;
+ auto b = a[1..12];
+ auto c = a[4..3];
+ auto d = a[0..$ + 1];
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21091a.d b/gcc/testsuite/gdc.test/fail_compilation/fail21091a.d
index 74f40c2..c2bbe4d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail21091a.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21091a.d
@@ -3,7 +3,8 @@
/*
TEST_OUTPUT:
----
-fail_compilation/fail21091a.d(15): Error: module `Ternary` is in file 'Ternary.d' which cannot be read
+fail_compilation/fail21091a.d(16): Error: unable to read module `Ternary`
+fail_compilation/fail21091a.d(16): Expected 'Ternary.d' or 'Ternary/package.d' in one of the following import paths:
import path[0] = fail_compilation
import path[1] = $p:druntime/import$
import path[2] = $p:phobos$
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21091b.d b/gcc/testsuite/gdc.test/fail_compilation/fail21091b.d
index d9467aa..3d7d600 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail21091b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21091b.d
@@ -3,7 +3,8 @@
/*
TEST_OUTPUT:
----
-fail_compilation/fail21091b.d(15): Error: module `Tid` is in file 'Tid.d' which cannot be read
+fail_compilation/fail21091b.d(16): Error: unable to read module `Tid`
+fail_compilation/fail21091b.d(16): Expected 'Tid.d' or 'Tid/package.d' in one of the following import paths:
import path[0] = fail_compilation
import path[1] = $p:druntime/import$
import path[2] = $p:phobos$
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22084.d b/gcc/testsuite/gdc.test/fail_compilation/fail22084.d
index 02fff2f..bd11832 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail22084.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22084.d
@@ -18,6 +18,6 @@ struct Destructor
void test()
{
- auto a0 = Destructor;
+ auto a0 = Destructor();
testVariadic(1, a0);
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22151.d b/gcc/testsuite/gdc.test/fail_compilation/fail22151.d
new file mode 100644
index 0000000..c6c3b1b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22151.d
@@ -0,0 +1,24 @@
+// https://issues.dlang.org/show_bug.cgi?id=22151
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail22151.d(14): Error: function `test` is not an lvalue and cannot be modified
+fail_compilation/fail22151.d(15): Error: function `test2` is not an lvalue and cannot be modified
+fail_compilation/fail22151.d(18): Error: function pointed to by `fp` is not an lvalue and cannot be modified
+fail_compilation/fail22151.d(21): Error: function pointed to by `ff` is not an lvalue and cannot be modified
+---
+*/
+
+void test()
+{
+ *&test = *&test;
+ *&test2 = *&test;
+
+ void function() fp;
+ *fp = *fp;
+
+ auto ff = &test2;
+ *ff = *&test2;
+}
+
+void test2();
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22366.d b/gcc/testsuite/gdc.test/fail_compilation/fail22366.d
new file mode 100644
index 0000000..3a2469f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22366.d
@@ -0,0 +1,15 @@
+// REQUIRED_ARGS: -dip1000
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail22366.d(13): Error: scope variable `__aaval2` assigned to non-scope `aa[0]`
+---
+*/
+
+int* fun(scope int* x) @safe
+{
+ int*[int] aa;
+ aa[0] = x; // should give an error
+ return aa[0];
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail225.d b/gcc/testsuite/gdc.test/fail_compilation/fail225.d
deleted file mode 100644
index dee9a54..0000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail225.d
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail225.d(15): Error: cannot implicitly convert expression `1` of type `int` to `immutable(char*)`
-fail_compilation/fail225.d(15): Error: cannot implicitly convert expression `& ch` of type `char*` to `immutable(char*)`
----
-*/
-struct Struct {
- char* chptr;
-}
-
-void main()
-{
- char ch = 'd';
- immutable Struct iStruct = {1, &ch};
-}
-
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail287.d b/gcc/testsuite/gdc.test/fail_compilation/fail287.d
index 7ed8f13..e5b1a79 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail287.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail287.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail287.d(14): Error: had 299 cases which is more than 256 cases in case range
+fail_compilation/fail287.d(14): Error: had 300 cases which is more than 257 cases in case range
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail318.d b/gcc/testsuite/gdc.test/fail_compilation/fail318.d
deleted file mode 100644
index d99175e..0000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail318.d
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail318.d(8): Error: function `D main` must return `int` or `void`
----
-*/
-
-auto main() { }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail318_b.d b/gcc/testsuite/gdc.test/fail_compilation/fail318_b.d
new file mode 100644
index 0000000..efbf45b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail318_b.d
@@ -0,0 +1,11 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail318_b.d(8): Error: function `D main` must return `int`, `void` or `noreturn`, not `string`
+---
+*/
+
+auto main()
+{
+ return "";
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7173.d b/gcc/testsuite/gdc.test/fail_compilation/fail7173.d
index 2a2e46b..05ba7f9 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail7173.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail7173.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail7173.d(23): Error: cannot implicitly convert expression `b1._a.opBinary(b2._a).fun()` of type `void` to `B`
+fail_compilation/fail7173.d(23): Error: expression `b1._a.opBinary(b2._a).fun()` is `void` and has no value
---
*/
struct A{
diff --git a/gcc/testsuite/gdc.test/fail_compilation/foreach.d b/gcc/testsuite/gdc.test/fail_compilation/foreach.d
new file mode 100644
index 0000000..9a1c7c8
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/foreach.d
@@ -0,0 +1,14 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/foreach.d(12): Error: cannot declare `out` loop variable, use `ref` instead
+fail_compilation/foreach.d(13): Error: cannot declare `out` loop variable, use `ref` instead
+fail_compilation/foreach.d(13): Error: cannot declare `out` loop variable, use `ref` instead
+---
+*/
+void main ()
+{
+ int[] array;
+ foreach (out val; array) {}
+ foreach (out idx, out val; array) {}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/foreach2.d b/gcc/testsuite/gdc.test/fail_compilation/foreach2.d
new file mode 100644
index 0000000..8bd4893
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/foreach2.d
@@ -0,0 +1,22 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/foreach2.d(15): Error: argument type mismatch, `int` to `ref immutable(int)`
+fail_compilation/foreach2.d(16): Error: argument type mismatch, `int` to `ref immutable(int)`
+fail_compilation/foreach2.d(19): Error: argument type mismatch, `int` to `ref double`
+fail_compilation/foreach2.d(20): Error: argument type mismatch, `int` to `ref const(double)`
+fail_compilation/foreach2.d(21): Error: argument type mismatch, `int` to `ref immutable(double)`
+---
+*/
+void test4090 ()
+{
+ // From https://issues.dlang.org/show_bug.cgi?id=4090
+ int[] arr = [1,2,3];
+ foreach (immutable ref x; arr) {}
+ foreach (immutable ref int x; arr) {}
+
+ // convertible type + qualifier + ref
+ foreach ( ref double x; arr) {}
+ foreach ( const ref double x; arr) {}
+ foreach (immutable ref double x; arr) {}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10212.d b/gcc/testsuite/gdc.test/fail_compilation/ice10212.d
index b9fe2aa..99fe1ed 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice10212.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice10212.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice10212.d(13): Error: Expected return type of `int`, not `int function() pure nothrow @nogc @safe`:
+fail_compilation/ice10212.d(13): Error: expected return type of `int`, not `int function() pure nothrow @nogc @safe`:
fail_compilation/ice10212.d(13): Return type of `int` inferred here.
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice22377.d b/gcc/testsuite/gdc.test/fail_compilation/ice22377.d
new file mode 100644
index 0000000..4616f99
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice22377.d
@@ -0,0 +1,8 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/ice22377.d(8): Error: Internal Compiler Error: type `string` cannot be mapped to C++
+---
+*/
+
+extern(C++) void foo(string a) {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice7782.d b/gcc/testsuite/gdc.test/fail_compilation/ice7782.d
index d42011a..551933b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice7782.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice7782.d
@@ -2,7 +2,8 @@
EXTRA_FILES: imports/ice7782algorithm.d imports/ice7782range.d
TEST_OUTPUT:
----
-fail_compilation/ice7782.d(13): Error: module `ice7782math` is in file 'imports/ice7782range/imports/ice7782math.d' which cannot be read
+fail_compilation/ice7782.d(14): Error: unable to read module `ice7782math`
+fail_compilation/ice7782.d(14): Expected 'imports/ice7782range/imports/ice7782math.d' or 'imports/ice7782range/imports/ice7782math/package.d' in one of the following import paths:
import path[0] = fail_compilation
import path[1] = $p:druntime/import$
import path[2] = $p:phobos$
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/imp22329.d b/gcc/testsuite/gdc.test/fail_compilation/imports/imp22329.d
new file mode 100644
index 0000000..9dc3c8e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/imp22329.d
@@ -0,0 +1,4 @@
+void func(T)(T arg)
+{
+ auto a = arg + 1;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/noreturn.d b/gcc/testsuite/gdc.test/fail_compilation/noreturn.d
index 3b340e8..4a588b4 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/noreturn.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/noreturn.d
@@ -72,7 +72,7 @@ noreturn casting(int i)
return cast() n;
}
}
-
+ assert(false);
}
enum forceCasting0 = casting(0);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d b/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d
new file mode 100644
index 0000000..e7d28dc
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d
@@ -0,0 +1,90 @@
+/*
+REQUIRED_ARGS: -w -o-
+
+TEST_OUTPUT:
+---
+fail_compilation/noreturn2.d(18): Error: expected return type of `noreturn`, not `void`
+---
+
+https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1034.md
+*/
+
+alias noreturn = typeof(*null);
+
+void doStuff();
+
+noreturn returnVoid()
+{
+ return doStuff();
+}
+
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/noreturn2.d(37): Error: expected return type of `int`, not `string`:
+fail_compilation/noreturn2.d(35): Return type of `int` inferred here.
+---
++/
+
+auto missmatch(int i)
+{
+ if (i < 0)
+ return assert(false);
+ if (i == 0)
+ return i;
+ if (i > 0)
+ return "";
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/noreturn2.d(50): Error: function `noreturn2.returns` is typed as `NR` but does return
+fail_compilation/noreturn2.d(50): `noreturn` functions must either throw, abort or loop indefinitely
+---
++/
+
+enum NR : noreturn;
+
+NR returns()
+{
+ // Fallthrough despite noreturn
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/noreturn2.d(64): Error: cannot implicitly convert expression `1` of type `int` to `noreturn`
+---
++/
+
+noreturn returnsValue()
+{
+ return 1;
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/noreturn2.d(75): Error: expected return type of `int`, not `void`
+---
++/
+int returnVoid2()
+{
+ return doStuff();
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/noreturn2.d(89): Error: mismatched function return type inference of `void` and `int`
+---
++/
+auto returnVoid3(int i)
+{
+ if (i > 0)
+ return i;
+ else
+ return doStuff();
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d b/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d
index 034fa54..43998b9 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d
@@ -113,6 +113,8 @@ fail_compilation/reserved_version.d(214): Error: version identifier `CppRuntime_
fail_compilation/reserved_version.d(215): Error: version identifier `CppRuntime_Sun` is reserved and cannot be set
fail_compilation/reserved_version.d(216): Error: version identifier `D_PIE` is reserved and cannot be set
fail_compilation/reserved_version.d(217): Error: version identifier `AVR` is reserved and cannot be set
+fail_compilation/reserved_version.d(218): Error: version identifier `D_PreConditions` is reserved and cannot be set
+fail_compilation/reserved_version.d(219): Error: version identifier `D_PostConditions` is reserved and cannot be set
---
*/
@@ -232,6 +234,8 @@ version = CppRuntime_Microsoft;
version = CppRuntime_Sun;
version = D_PIE;
version = AVR;
+version = D_PreConditions;
+version = D_PostConditions;
// This should work though
debug = DigitalMars;
@@ -340,3 +344,5 @@ debug = none;
debug = D_P16;
debug = MSP430;
debug = AVR;
+debug = D_PreConditions;
+debug = D_PostConditions;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d b/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d
index b8b6fa4..6333309 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d
@@ -103,6 +103,8 @@
// REQUIRED_ARGS: -version=assert
// REQUIRED_ARGS: -version=all
// REQUIRED_ARGS: -version=none
+// REQUIRED_ARGS: -version=D_PreConditions
+// REQUIRED_ARGS: -version=D_PostConditions
// REQUIRED_ARGS: -debug=DigitalMars
// REQUIRED_ARGS: -debug=GNU
// REQUIRED_ARGS: -debug=LDC
@@ -203,6 +205,8 @@
// REQUIRED_ARGS: -debug=assert
// REQUIRED_ARGS: -debug=all
// REQUIRED_ARGS: -debug=none
+// REQUIRED_ARGS: -debug=D_PreConditions
+// REQUIRED_ARGS: -debug=D_PostConditions
/*
TEST_OUTPUT:
---
@@ -309,5 +313,7 @@ Error: version identifier `unittest` is reserved and cannot be set
Error: version identifier `assert` is reserved and cannot be set
Error: version identifier `all` is reserved and cannot be set
Error: version identifier `none` is reserved and cannot be set
+Error: version identifier `D_PreConditions` is reserved and cannot be set
+Error: version identifier `D_PostConditions` is reserved and cannot be set
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17425.d b/gcc/testsuite/gdc.test/fail_compilation/test17425.d
index f7628b8..77c4956 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test17425.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test17425.d
@@ -1,7 +1,7 @@
/* TEST_OUTPUT:
---
fail_compilation/test17425.d(24): Error: parameter index must be in range 0..4 not 4
-fail_compilation/test17425.d(27): Error: first argument to `__traits(getParameterStorageClasses, i, 4)` is not a function
+fail_compilation/test17425.d(27): Error: first argument to `__traits(getParameterStorageClasses, i, 4)` is not a function or a function call
fail_compilation/test17425.d(29): Error: expression expected as second argument of `__traits(getParameterStorageClasses, foo, int)`
fail_compilation/test17425.d(31): Error: expected 2 arguments for `getParameterStorageClasses` but had 3
---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17868b.d b/gcc/testsuite/gdc.test/fail_compilation/test17868b.d
index 5bfff5c..7833b61 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test17868b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test17868b.d
@@ -1,9 +1,9 @@
/*
TEST_OUTPUT:
----
+fail_compilation/test17868b.d(9): Error: pragma `crt_constructor` can only apply to a single declaration
fail_compilation/test17868b.d(10): Error: function `test17868b.foo` must be `extern(C)` for `pragma(crt_constructor)`
fail_compilation/test17868b.d(14): Error: function `test17868b.bar` must be `extern(C)` for `pragma(crt_constructor)`
-fail_compilation/test17868b.d(9): Error: pragma `crt_constructor` can only apply to a single declaration
----
*/
pragma(crt_constructor):
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20998.d b/gcc/testsuite/gdc.test/fail_compilation/test20998.d
new file mode 100644
index 0000000..16eb026
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test20998.d
@@ -0,0 +1,120 @@
+// https://issues.dlang.org/show_bug.cgi?id=20998
+/*
+REQUIRED_ARGS: -verrors=context
+TEST_OUTPUT:
+---
+fail_compilation/test20998.d(76): Error: undefined identifier `invalid`
+X x = { invalid, 2, "asd" };
+ ^
+fail_compilation/test20998.d(76): Error: too many initializers for `X`
+X x = { invalid, 2, "asd" };
+ ^
+fail_compilation/test20998.d(83): Error: cannot implicitly convert expression `"a"` of type `string` to `int`
+X2 x2 = { ptr: null, "a", ptr: 2, 444 };
+ ^
+fail_compilation/test20998.d(83): Error: duplicate initializer for field `ptr`
+X2 x2 = { ptr: null, "a", ptr: 2, 444 };
+ ^
+fail_compilation/test20998.d(83): Error: too many initializers for `X2`
+X2 x2 = { ptr: null, "a", ptr: 2, 444 };
+ ^
+fail_compilation/test20998.d(90): Error: overlapping initialization for field `ptr` and `x`
+X3 x3 = { ptr: null, "a", ptr: 2, 444 };
+ ^
+fail_compilation/test20998.d(90): Error: cannot implicitly convert expression `"a"` of type `string` to `int`
+X3 x3 = { ptr: null, "a", ptr: 2, 444 };
+ ^
+fail_compilation/test20998.d(90): Error: duplicate initializer for field `ptr`
+X3 x3 = { ptr: null, "a", ptr: 2, 444 };
+ ^
+fail_compilation/test20998.d(90): Error: too many initializers for `X3`
+X3 x3 = { ptr: null, "a", ptr: 2, 444 };
+ ^
+fail_compilation/test20998.d(98): Error: field `X4.ptr` cannot assign to misaligned pointers in `@safe` code
+ X4 x4 = { ptr: null, "a", 444, ptr: 2, true };
+ ^
+fail_compilation/test20998.d(98): Error: cannot implicitly convert expression `"a"` of type `string` to `int`
+ X4 x4 = { ptr: null, "a", 444, ptr: 2, true };
+ ^
+fail_compilation/test20998.d(98): Error: too many initializers for `X4`
+ X4 x4 = { ptr: null, "a", 444, ptr: 2, true };
+ ^
+fail_compilation/test20998.d(102): called from here: `test()`
+auto e = test();
+ ^
+fail_compilation/test20998.d(104): Error: cannot implicitly convert expression `1` of type `int` to `void*`
+X2 a5 = { ptr: 1, ptr: 2, ptr: 444, ptr: 555 };
+ ^
+fail_compilation/test20998.d(104): Error: duplicate initializer for field `ptr`
+X2 a5 = { ptr: 1, ptr: 2, ptr: 444, ptr: 555 };
+ ^
+fail_compilation/test20998.d(104): Error: duplicate initializer for field `ptr`
+X2 a5 = { ptr: 1, ptr: 2, ptr: 444, ptr: 555 };
+ ^
+fail_compilation/test20998.d(104): Error: too many initializers for `X2`
+X2 a5 = { ptr: 1, ptr: 2, ptr: 444, ptr: 555 };
+ ^
+fail_compilation/test20998.d(107): Error: too many initializers for `X2`
+X2 c6 = { null, 2, true, null };
+ ^
+fail_compilation/test20998.d(116): Error: cannot implicitly convert expression `1` of type `int` to `immutable(char*)`
+ immutable Struct iStruct = {1, &ch};
+ ^
+fail_compilation/test20998.d(116): Error: too many initializers for `Struct`
+ immutable Struct iStruct = {1, &ch};
+ ^
+fail_compilation/test20998.d(120): called from here: `test2()`
+auto t = test2();
+ ^
+---
+*/
+
+struct X {
+ void* ptr;
+ int x;
+}
+X x = { invalid, 2, "asd" };
+
+struct X2 {
+ void* ptr;
+ int x;
+ bool y;
+}
+X2 x2 = { ptr: null, "a", ptr: 2, 444 };
+
+union X3 {
+ void* ptr;
+ int x;
+ bool y;
+}
+X3 x3 = { ptr: null, "a", ptr: 2, 444 };
+
+int test() @safe
+{
+ align (1) struct X4 {
+ void* ptr;
+ int x;
+ }
+ X4 x4 = { ptr: null, "a", 444, ptr: 2, true };
+ return 0;
+}
+
+auto e = test();
+
+X2 a5 = { ptr: 1, ptr: 2, ptr: 444, ptr: 555 };
+X2 b5 = { ptr: null, y: true };
+X2 c5 = { x: 2, true, ptr: null };
+X2 c6 = { null, 2, true, null };
+
+struct Struct {
+ char* chptr;
+}
+
+int test2()
+{
+ char ch = 'd';
+ immutable Struct iStruct = {1, &ch};
+ return 0;
+}
+
+auto t = test2();
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21093.d b/gcc/testsuite/gdc.test/fail_compilation/test21093.d
new file mode 100644
index 0000000..b85d0c3
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21093.d
@@ -0,0 +1,56 @@
+// https://issues.dlang.org/show_bug.cgi?id=21093
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test21093.d(24): Error: function `test21093.LocalTime.hasDST` does not override any function
+fail_compilation/test21093.d(32): Error: class `test21093.LocalTime2` cannot implicitly generate a default constructor when base class `test21093.TimeZone2` is missing a default constructor
+fail_compilation/test21093.d(44): Error: function `test21093.LocalTime3.string` does not override any function
+fail_compilation/test21093.d(55): Error: cannot implicitly override base class method `test21093.TimeZone4.hasDST` with `test21093.LocalTime4.hasDST`; add `override` attribute
+---
+*/
+
+void fromUnixTime(immutable TimeZone tz = LocalTime()) { }
+void fromUnixTime(immutable TimeZone2 tz = LocalTime2()) { }
+void fromUnixTime(immutable TimeZone3 tz = LocalTime3()) { }
+void fromUnixTime(immutable TimeZone4 tz = LocalTime4()) { }
+
+class TimeZone
+{
+}
+
+class LocalTime : TimeZone
+{
+ static immutable(LocalTime) opCall() { }
+ override hasDST() { }
+}
+
+class TimeZone2
+{
+ this(string) { }
+}
+
+class LocalTime2 : TimeZone2
+{
+ static immutable(LocalTime2) opCall() { }
+}
+
+class TimeZone3
+{
+}
+
+class LocalTime3 : TimeZone3
+{
+ static immutable(LocalTime3) opCall() { }
+ override string () { }
+}
+
+class TimeZone4
+{
+ bool hasDST();
+}
+
+class LocalTime4 : TimeZone4
+{
+ static immutable(LocalTime4) opCall() { }
+ bool hasDST() { }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21380.d b/gcc/testsuite/gdc.test/fail_compilation/test21380.d
new file mode 100644
index 0000000..6a2da1b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21380.d
@@ -0,0 +1,46 @@
+// https://issues.dlang.org/show_bug.cgi?id=21380
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test21380.d(39): Error: partial template instance `MySerializer().serializeSinkType!int` has no value
+fail_compilation/test21380.d(44): Error: template instance `test21380.SupportSinkTypeSer!(MySerializer!int)` error instantiating
+---
+*/
+
+template isSomeFunction(T...)
+if (T.length == 1)
+{
+ static if (is(typeof(& T[0]) U : U*) && is(U == function) || is(typeof(& T[0]) U == delegate))
+ {
+ // T is a (nested) function symbol.
+ enum bool isSomeFunction = true;
+ }
+ else static if (is(T[0] W) || is(typeof(T[0]) W))
+ {
+ // T is an expression or a type. Take the type of it and examine.
+ static if (is(W F : F*) && is(F == function))
+ enum bool isSomeFunction = true; // function pointer
+ else
+ enum bool isSomeFunction = is(W == function) || is(W == delegate);
+ }
+ else
+ enum bool isSomeFunction = false;
+}
+
+struct MySerializer (T)
+{
+ void serializeSinkType(T2) (scope auto ref T2 record) {}
+}
+
+template SupportSinkTypeSer(SerT)
+{
+ /* Note: Partial template instance because it needs inference, in this case
+ it cannot infer 'auto ref' parameter */
+ enum SupportSinkTypeSer = isSomeFunction!(SerT.init.serializeSinkType!int);
+}
+
+int main()
+{
+ enum x = SupportSinkTypeSer!(MySerializer!int);
+ return 0;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21930.d b/gcc/testsuite/gdc.test/fail_compilation/test21930.d
new file mode 100644
index 0000000..6c93243
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21930.d
@@ -0,0 +1,27 @@
+// https://issues.dlang.org/show_bug.cgi?id=21930
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test21930.d(21): Error: variable `string` is used as a type
+fail_compilation/test21930.d(15): variable `string` is declared here
+fail_compilation/test21930.d(26): Error: constructor `test21930.R.this(string)` is not callable using argument types `()`
+---
+*/
+
+alias AliasSeq(T...) = T;
+
+alias TP(alias name) = AliasSeq!name;
+
+int string; // 'string' declared as a variable
+
+alias a = TP!(main);
+
+class R
+{
+ this(string) { } // so constructor have errors
+}
+
+@system main()
+{
+ new R;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22329.d b/gcc/testsuite/gdc.test/fail_compilation/test22329.d
new file mode 100644
index 0000000..237f9c7
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test22329.d
@@ -0,0 +1,21 @@
+// https://issues.dlang.org/show_bug.cgi?id=22329
+// EXTRA_FILES: imports/imp22329.d
+/*
+TEST_OUTPUT:
+---
+fail_compilation/imports/imp22329.d(3): Error: no property `values` for type `test22329.Foo`
+fail_compilation/imports/imp22329.d(3): Error: incompatible types for `(arg) + (1)`: `Foo` and `int`
+fail_compilation/test22329.d(20): Error: template instance `imp22329.func!(Foo)` error instantiating
+---
+*/
+
+public struct Foo {
+ private int values;
+ alias values this;
+}
+
+void main()
+{
+ import imports.imp22329 : func;
+ func(Foo());
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22361.d b/gcc/testsuite/gdc.test/fail_compilation/test22361.d
new file mode 100644
index 0000000..11255ff
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test22361.d
@@ -0,0 +1,11 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test22361.d(11): Error: unable to read module `this_module_does_not_exist`
+fail_compilation/test22361.d(11): Expected 'this_module_does_not_exist.d' or 'this_module_does_not_exist/package.d' in one of the following import paths:
+import path[0] = fail_compilation
+import path[1] = $p:druntime/import$
+import path[2] = $p:phobos$
+---
+*/
+import this_module_does_not_exist;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/testOpApply.d b/gcc/testsuite/gdc.test/fail_compilation/testOpApply.d
new file mode 100644
index 0000000..9203685
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/testOpApply.d
@@ -0,0 +1,161 @@
+/+
+TEST_OUTPUT:
+---
+fail_compilation/testOpApply.d(27): Error: `testOpApply.SameAttr.opApply` called with argument types `(int delegate(int i) pure nothrow @nogc @safe)` matches both:
+fail_compilation/testOpApply.d(13): `testOpApply.SameAttr.opApply(int delegate(int) @system dg)`
+and:
+fail_compilation/testOpApply.d(18): `testOpApply.SameAttr.opApply(int delegate(int) @system dg)`
+---
++/
+
+struct SameAttr
+{
+ int opApply(int delegate(int) @system dg) @system
+ {
+ return 0;
+ }
+
+ int opApply(int delegate(int) @system dg) @safe
+ {
+ return 0;
+ }
+}
+
+void testSameAttr() @safe
+{
+ SameAttr sa;
+ foreach (int i; sa) {}
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/testOpApply.d(104): Error: `testOpApply.SameAttr.opApply` called with argument types `(int delegate(int i) pure nothrow @nogc @system)` matches both:
+fail_compilation/testOpApply.d(13): `testOpApply.SameAttr.opApply(int delegate(int) @system dg)`
+and:
+fail_compilation/testOpApply.d(18): `testOpApply.SameAttr.opApply(int delegate(int) @system dg)`
+---
++/
+#line 100
+
+void testSameAttr() @system
+{
+ SameAttr sa;
+ foreach (int i; sa) {}
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/testOpApply.d(217): Error: `sa.opApply` matches more than one declaration:
+`fail_compilation/testOpApply.d(203)`: `int(int delegate(int) dg)`
+and:
+`fail_compilation/testOpApply.d(208)`: `int(int delegate(string) dg)`
+fail_compilation/testOpApply.d(217): Error: cannot uniquely infer `foreach` argument types
+---
++/
+#line 200
+
+struct DifferentTypes
+{
+ int opApply(int delegate(int) dg)
+ {
+ return 0;
+ }
+
+ int opApply(int delegate(string) dg)
+ {
+ return 0;
+ }
+}
+
+void testDifferentTypes()
+{
+ DifferentTypes sa;
+ foreach (i; sa) {}
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/testOpApply.d(317): Error: `sa.opApply` matches more than one declaration:
+`fail_compilation/testOpApply.d(303)`: `int(int delegate(int) dg)`
+and:
+`fail_compilation/testOpApply.d(308)`: `int(int delegate(long) dg)`
+fail_compilation/testOpApply.d(317): Error: cannot uniquely infer `foreach` argument types
+---
++/
+#line 300
+
+struct CovariantTypes
+{
+ int opApply(int delegate(int) dg)
+ {
+ return 0;
+ }
+
+ int opApply(int delegate(long) dg)
+ {
+ return 0;
+ }
+}
+
+void testCovariantTypes()
+{
+ CovariantTypes sa;
+ foreach (i; sa) {}
+}
+
+/+
+See https://issues.dlang.org/show_bug.cgi?id=21683
+
+TEST_OUTPUT:
+---
+fail_compilation/testOpApply.d(420): Error: `sa.opApply` matches more than one declaration:
+`fail_compilation/testOpApply.d(404)`: `int(int delegate(int) dg)`
+and:
+`fail_compilation/testOpApply.d(410)`: `int(int delegate(ref int) dg)`
+fail_compilation/testOpApply.d(420): Error: cannot uniquely infer `foreach` argument types
+---
++/
+#line 400
+
+struct DifferentQualifiers
+{
+ int x;
+ int opApply(int delegate(int) dg)
+ {
+ x = 1;
+ return 0;
+ }
+
+ int opApply(int delegate(ref int) dg)
+ {
+ x = 2;
+ return 0;
+ }
+}
+
+void testDifferentQualifiers()
+{
+ DifferentQualifiers sa;
+ foreach (i; sa) {}
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/testOpApply.d(504): Error: `sa.opApply` matches more than one declaration:
+`fail_compilation/testOpApply.d(404)`: `int(int delegate(int) dg)`
+and:
+`fail_compilation/testOpApply.d(410)`: `int(int delegate(ref int) dg)`
+fail_compilation/testOpApply.d(504): Error: cannot uniquely infer `foreach` argument types
+---
++/
+#line 500
+
+void testDifferentQualifiersRef()
+{
+ DifferentQualifiers sa;
+ foreach (ref i; sa) {}
+}
diff --git a/gcc/testsuite/gdc.test/runnable/aliasthis.d b/gcc/testsuite/gdc.test/runnable/aliasthis.d
index cc12f55..db5913c 100644
--- a/gcc/testsuite/gdc.test/runnable/aliasthis.d
+++ b/gcc/testsuite/gdc.test/runnable/aliasthis.d
@@ -2102,6 +2102,42 @@ void test16633()
root.populate;
}
+/***************************************************/
+// https://issues.dlang.org/show_bug.cgi?id=13009
+
+struct RefCounted13009_2(T)
+{
+ ref T refCountedPayload()
+ {
+ assert(false);
+ }
+
+ ref inout(T) refCountedPayload() inout
+ {
+ assert(false);
+ }
+
+ alias refCountedPayload this;
+}
+
+struct S13009_2
+{
+ struct Payload
+ {
+ int[] data;
+ }
+
+ RefCounted13009_2!Payload payload;
+ alias X = typeof(payload.data[0]);
+
+ void foo()
+ {
+ payload.data[0] = 0;
+ }
+}
+
+/***************************************************/
+
int main()
{
test1();
diff --git a/gcc/testsuite/gdc.test/runnable/dhry.d b/gcc/testsuite/gdc.test/runnable/dhry.d
index f772d61..1eb463c 100644
--- a/gcc/testsuite/gdc.test/runnable/dhry.d
+++ b/gcc/testsuite/gdc.test/runnable/dhry.d
@@ -929,3 +929,19 @@ version (NetBSD)
return q;
}
}
+
+version (OpenBSD)
+{
+ import core.sys.posix.sys.time;
+
+ double dtime()
+ {
+ double q;
+ timeval tv;
+
+ gettimeofday(&tv,null);
+ q = cast(double)tv.tv_sec + cast(double)tv.tv_usec * 1.0e-6;
+
+ return q;
+ }
+}
diff --git a/gcc/testsuite/gdc.test/runnable/fix22372.d b/gcc/testsuite/gdc.test/runnable/fix22372.d
new file mode 100644
index 0000000..55864a0
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/fix22372.d
@@ -0,0 +1,38 @@
+/* PERMUTE_ARGS: -O
+ */
+
+// https://issues.dlang.org/show_bug.cgi?id=22104
+
+struct S { int a1, a2, a3; }
+
+version (none)
+void throws2ndCall(ref S x);
+else
+{
+void throws2ndCall(ref S x)
+{
+ __gshared bool b;
+ if (b)
+ throw new Exception("n == 1");
+ b = true;
+}
+}
+
+void main() { foo(); }
+
+void foo()
+{
+ S[] arr = [S(), S()];
+ size_t i;
+ try
+ {
+ for (i = 0; i < 2; i++)
+ throws2ndCall(arr[i]);
+ }
+ catch (Exception o)
+ {
+ //printf("Exception: i = %lu\n", i);
+ assert(i == 1); // this fails
+ }
+}
+
diff --git a/gcc/testsuite/gdc.test/runnable/interpret.d b/gcc/testsuite/gdc.test/runnable/interpret.d
index a626749..989fb2e 100644
--- a/gcc/testsuite/gdc.test/runnable/interpret.d
+++ b/gcc/testsuite/gdc.test/runnable/interpret.d
@@ -3605,6 +3605,62 @@ void test21878()
}
/************************************************/
+// https://issues.dlang.org/show_bug.cgi?id=20133
+
+void bar20133(ref string text)
+{
+ text = text[1 .. $];
+ assert(text.length < 3);
+ if (text.length == 2) assert(text == "oo");
+ if (text.length == 1) assert(text == "o");
+ if (text.length == 0) assert(text == "");
+ string tcopy = text;
+ if (tcopy.length > 0)
+ bar20133(tcopy);
+ assert(tcopy.length < 2);
+ if (tcopy.length == 1) assert(tcopy == "o");
+ if (tcopy.length == 0) assert(tcopy == "");
+}
+
+void bar20133_2(ref string text)
+{
+ auto ptext = &text;
+ *ptext = text[1 .. $];
+ assert(text.length < 3);
+ if (text.length == 2) assert(text == "oo");
+ if (text.length == 1) assert(text == "o");
+ if (text.length == 0) assert(text == "");
+ string tcopy = text;
+ if (tcopy.length > 0)
+ bar20133_2(tcopy);
+ assert(tcopy.length < 2);
+ if (tcopy.length == 1) assert(tcopy == "o");
+ if (tcopy.length == 0) assert(tcopy == "");
+}
+
+alias fun20133 = {
+ string input = "foo";
+ bar20133(input);
+ assert(input == "oo");
+ return input;
+};
+
+alias fun20133_2 = {
+ string input = "foo";
+ bar20133_2(input);
+ assert(input == "oo");
+ return input;
+};
+
+void test20133()
+{
+ enum ctest = fun20133();
+ enum ctest2 = fun20133_2();
+ auto rtest = fun20133();
+ auto rtest2 = fun20133_2();
+}
+
+/************************************************/
int main()
{
@@ -3732,6 +3788,7 @@ int main()
test20366();
test20400();
test21878();
+ test20133();
printf("Success\n");
return 0;
diff --git a/gcc/testsuite/gdc.test/runnable/noreturn1.d b/gcc/testsuite/gdc.test/runnable/noreturn1.d
index 447ea28..1da0479 100644
--- a/gcc/testsuite/gdc.test/runnable/noreturn1.d
+++ b/gcc/testsuite/gdc.test/runnable/noreturn1.d
@@ -66,9 +66,56 @@ void test2()
/*****************************************/
+struct BasicStruct
+{
+ int firstInt;
+ noreturn noRet;
+ long lastLong;
+}
+
+struct AlignedStruct
+{
+ int firstInt;
+ align(16) noreturn noRet;
+ long lastLong;
+}
+
+void takeBasic(BasicStruct bs)
+{
+ assert(bs.firstInt == 13);
+ assert(bs.lastLong == 42);
+
+ assert(&bs.noRet == (&bs.firstInt + 1));
+}
+
+void takeAligned(AlignedStruct as)
+{
+ assert(as.firstInt == 99);
+ assert(as.lastLong == 0xDEADBEEF);
+
+ assert(&as.noRet == &as.lastLong);
+}
+
+void test3()
+{
+ {
+ BasicStruct bs;
+ bs.firstInt = 13;
+ bs.lastLong = 42;
+ takeBasic(bs);
+ }
+ {
+ AlignedStruct as;
+ as.firstInt = 99;
+ as.lastLong = 0xDEADBEEF;
+ takeAligned(as);
+ }
+}
+
int main()
{
test1();
test2();
+ test3();
return 0;
}
diff --git a/gcc/testsuite/gdc.test/runnable/noreturn2.d b/gcc/testsuite/gdc.test/runnable/noreturn2.d
new file mode 100644
index 0000000..1d3d362
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/noreturn2.d
@@ -0,0 +1,220 @@
+/*
+PERMUTE_ARGS: -O -inline
+RUN_OUTPUT:
+---
+getAndPrintS
+---
+*/
+
+import core.stdc.stdio;
+import core.exception : AssertError;
+
+/*****************************************/
+
+// noreturn is inferred for functions that always throw
+// The code must not strip the destructor when calling a noreturn function
+
+struct WithDtor
+{
+ __gshared int destroyed;
+
+ int num;
+
+ int acceptNoreturn(int a, int b, int c)
+ {
+ puts("unreachable");
+ return num + a + b + c;
+ }
+
+ ~this()
+ {
+ destroyed += num;
+ }
+}
+
+noreturn doesThrow()
+{
+ WithDtor wd = WithDtor(1);
+ throw new Exception("");
+}
+
+noreturn callDoesThrow()
+{
+ WithDtor wd = WithDtor(2);
+ doesThrow();
+}
+
+
+void testDtors()
+{
+ try
+ {
+ callDoesThrow();
+ assert(0);
+ } catch (Exception e) {}
+
+ assert(WithDtor.destroyed == 3);
+}
+
+/*****************************************************************************/
+
+/// Verifies that `func` throws a `Throwable` with `message` at `line`
+void testAssertFailure(size_t expLine, string expMsg, void function() func, size_t callLine = __LINE__)
+{
+ void enforce(bool check, string error)
+ {
+ if (!check)
+ throw new AssertError(error, __FILE__, callLine);
+ }
+
+ bool caught;
+ try
+ {
+ func();
+ }
+ catch (Throwable t)
+ {
+ // Save members because t might be overwritten by an Assertion failure below
+ string actFile = t.file;
+ size_t actLine = t.line;
+ string actMsg = t.msg;
+ caught = true;
+
+ scope (failure)
+ {
+ printf("\nfile = \"%.*s\"\nline = %zu\nmsg = \"%.*s\"\n\n",
+ cast(int) actFile.length, actFile.ptr,
+ actLine,
+ cast(int) actMsg.length, actMsg.ptr
+ );
+ fflush(stdout);
+ }
+
+ enforce(actFile == __FILE__, "Wrong file");
+ enforce(actLine == expLine, "Wrong line");
+ enforce(actMsg == expMsg, "Wrong message");
+ }
+
+ enforce(caught, "No Throwable was thrown!");
+}
+
+void testAccess()
+{
+ enum msg = "Accessed expression of type `noreturn`";
+
+ // FIXME: Another assertion failure in the backend trying to generate noreturn.sizeof = 0 byte assignment
+ version (FIXME)
+ testAssertFailure(__LINE__ + 3, msg, function noreturn()
+ {
+ noreturn a;
+ noreturn b = a;
+ });
+
+ if (false) // read does not assert!
+ testAssertFailure(__LINE__ + 3, msg, function noreturn()
+ {
+ noreturn a;
+ int b = a;
+ assert(false, "Unreachable!"); // Statement above not detected as noreturn
+ });
+
+ testAssertFailure(__LINE__ + 2, msg, function noreturn()
+ {
+ cast(noreturn) 1;
+ });
+
+ version (FIXME)
+ testAssertFailure(__LINE__ + 3, msg, function noreturn()
+ {
+ noreturn a;
+ noreturn b = cast(noreturn) 1;
+ });
+
+ if (false) // Read does not assert
+ testAssertFailure(__LINE__ + 3, msg, function noreturn()
+ {
+ noreturn a;
+ return a;
+ });
+
+ if (false) // Read does not assert
+ testAssertFailure(__LINE__ + 4, msg, function noreturn()
+ {
+ static void foo(noreturn) {}
+ noreturn a;
+ foo(a);
+ assert(false, "Unreachable!"); // Ditto
+ });
+}
+
+/*****************************************/
+
+void testFuncCall()
+{
+ enum msg = "Called abort()";
+ enum line = __LINE__ + 1;
+ static noreturn abort() { assert(0, msg); }
+
+ // Canaries to check for side effects
+ __gshared int countLeft, countRight;
+
+ scope (failure) printf("countLeft = %d\ncountRight = %d\n", countLeft, countRight);
+
+
+ // D function arguments are evaluated left to right
+ testAssertFailure(line, msg, function()
+ {
+ static void acceptNoreturnD(int, int, int) { puts("unreachable"); }
+
+ acceptNoreturnD(countLeft++, abort(), countRight++);
+ });
+
+ assert(countLeft == 1);
+ assert(countRight == 0);
+
+// // C function arguments are still evaluated left to right
+// // Despite them being push in reverse order
+ testAssertFailure(line, msg, function()
+ {
+ static extern(C) void acceptNoreturnC(int, int, int) { puts("unreachable"); }
+
+ acceptNoreturnC(countLeft++, abort(), countRight++);
+
+ assert(false);
+ });
+
+ assert(countLeft == 2);
+ assert(countRight == 0);
+
+ WithDtor.destroyed = 0;
+
+ testAssertFailure(__LINE__ + 2, "Error", function()
+ {
+ static WithDtor getS() { assert(false, "Error"); }
+
+ getS().acceptNoreturn(countLeft++, abort(), countRight++);
+ });
+
+ assert(countLeft == 2); // No changes
+ assert(countRight == 0);
+ assert(WithDtor.destroyed == 0); // No temporary to destruct
+
+ testAssertFailure(line, msg, function()
+ {
+ static WithDtor getAndPrintS() { puts("getAndPrintS"); return WithDtor(1); }
+
+ getAndPrintS().acceptNoreturn(countLeft++, abort(), countRight++);
+ });
+
+ assert(countLeft == 3);
+ assert(countRight == 0);
+ assert(WithDtor.destroyed == 1);
+}
+
+int main()
+{
+ testDtors();
+ testAccess();
+ testFuncCall();
+ return 0;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/sroa13220.d b/gcc/testsuite/gdc.test/runnable/sroa13220.d
new file mode 100644
index 0000000..2cec666
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/sroa13220.d
@@ -0,0 +1,103 @@
+/* REQUIRED_ARGS: -O -inline -noboundscheck
+ */
+// https://github.com/dlang/pull/13220
+
+version (D_SIMD)
+{
+
+mixin template VectorOps(VectorType, ArrayType: BaseType[N], BaseType, size_t N)
+{
+ enum Count = N;
+ alias Base = BaseType;
+
+ BaseType* ptr() return pure nothrow @nogc
+ {
+ return array.ptr;
+ }
+
+ // Unary operators
+ VectorType opUnary(string op)() pure nothrow @safe @nogc
+ {
+ VectorType res = void;
+ mixin("res.array[] = " ~ op ~ "array[];");
+ return res;
+ }
+
+ // Binary operators
+ VectorType opBinary(string op)(VectorType other) pure const nothrow @safe @nogc
+ {
+ VectorType res = void;
+ mixin("res.array[] = array[] " ~ op ~ " other.array[];");
+ return res;
+ }
+
+ // Assigning a BaseType value
+ void opAssign(BaseType e) pure nothrow @safe @nogc
+ {
+ array[] = e;
+ }
+
+ // Assigning a static array
+ void opAssign(ArrayType v) pure nothrow @safe @nogc
+ {
+ array[] = v[];
+ }
+
+ void opOpAssign(string op)(VectorType other) pure nothrow @safe @nogc
+ {
+ mixin("array[] " ~ op ~ "= other.array[];");
+ }
+
+ // Assigning a dyn array
+ this(ArrayType v) pure nothrow @safe @nogc
+ {
+ array[] = v[];
+ }
+
+ // Broadcast constructor
+ this(BaseType x) pure nothrow @safe @nogc
+ {
+ array[] = x;
+ }
+
+ ref inout(BaseType) opIndex(size_t i) inout pure nothrow @safe @nogc
+ {
+ return array[i];
+ }
+}
+
+// Note: can't be @safe with this signature
+Vec loadUnaligned(Vec)(const(BaseType!Vec)* pvec) @trusted
+{
+ // Since this vector is emulated, it doesn't have alignement constraints
+ // and as such we can just cast it.
+ return *cast(Vec*)(pvec);
+}
+
+private template BaseType(V)
+{
+ alias typeof( ( { V v; return v; }()).array[0]) BaseType;
+}
+
+struct int4
+{
+ int[4] array;
+ mixin VectorOps!(int4, int[4]);
+}
+
+alias __m128i = int4;
+}
+
+int main()
+{
+ version (D_SIMD)
+ {
+ int4 A = [1, 2, 3, 4];
+ int4 ia = A;
+ ia.ptr[2] = 5;
+ int4 C = ia;
+ int[4] result = [1, 2, 5, 4];
+ assert(C.array == result);
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test15624.d b/gcc/testsuite/gdc.test/runnable/test15624.d
deleted file mode 100644
index 7927579..0000000
--- a/gcc/testsuite/gdc.test/runnable/test15624.d
+++ /dev/null
@@ -1,51 +0,0 @@
-/* PERMUTE_ARGS:
- */
-
-// https://issues.dlang.org/show_bug.cgi?id=15624
-
-struct Foo {
- int x;
- int opApply(int delegate(int, string, string) @safe dg) @safe {
- x = 1;
- return 0;
- }
- int opApply(int delegate(int, string, string) @system dg) @system {
- x = 2;
- return 0;
- }
-}
-
-void testSafe() @safe {
- Foo foo;
- foreach (i, k, v; foo) {
- }
- assert(foo.x == 1);
-}
-
-void testSystem() @system {
- Foo foo;
- foreach (i, k, v; foo) {
- }
- assert(foo.x == 2);
-}
-
-void test() @system
-{
- Foo f;
-
- int dgsafe (int x, string s, string t) @safe { return 1; }
- int dgsystem(int x, string s, string t) @system { return 1; }
-
- f.opApply(&dgsafe);
- assert(f.x == 1);
- f.opApply(&dgsystem);
- assert(f.x == 2);
-}
-
-int main()
-{
- testSafe();
- testSystem();
- test();
- return 0;
-}
diff --git a/gcc/testsuite/gdc.test/runnable/test21039.d b/gcc/testsuite/gdc.test/runnable/test21039.d
new file mode 100644
index 0000000..c58600f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test21039.d
@@ -0,0 +1,27 @@
+// https://issues.dlang.org/show_bug.cgi?id=21039
+
+class Inner {}
+
+class Outer {
+ Inner inner;
+ alias inner this;
+ this(Inner i) { inner = i; }
+}
+
+void main() {
+ auto inner = new Inner;
+ auto outer = new Outer(new Inner);
+
+ // implicit cast goes through 'alias this'
+
+ Inner inner1 = outer; // Already does it
+ assert(inner1);
+
+ Inner[] inners = [inner, outer]; // Fixed
+
+ assert(inners[0], "first element is null");
+ assert(inners[1], "second element is null");
+
+ Inner inner2 = 1 ? outer : inner; // Fixed
+ assert(inner2);
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test22205.d b/gcc/testsuite/gdc.test/runnable/test22205.d
new file mode 100644
index 0000000..78abf2f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test22205.d
@@ -0,0 +1,17 @@
+// REQUIRED_ARGS: -debug
+
+void main() nothrow
+{
+ debug
+ {
+ try
+ {
+ throw new Exception("2");
+ }
+ catch (Exception) {}
+ catch (Throwable)
+ {
+ assert(0);
+ }
+ }
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test22278.d b/gcc/testsuite/gdc.test/runnable/test22278.d
new file mode 100644
index 0000000..72332a4
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test22278.d
@@ -0,0 +1,24 @@
+/*
+REQUIRED_ARGS: -release
+PERMUTE_ARGS: -check=in=on -check=out=on
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=22278
+
+bool resultIn;
+bool resultOut;
+
+void foo22278()
+ in { resultIn = true; }
+ out { resultOut = true; }
+do {}
+
+int main()
+{
+ foo22278();
+
+ version(D_PreConditions) assert(resultIn); else assert(!resultIn);
+ version(D_PostConditions) assert(resultOut); else assert(!resultOut);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/testOpApply.d b/gcc/testsuite/gdc.test/runnable/testOpApply.d
new file mode 100644
index 0000000..7b884e5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/testOpApply.d
@@ -0,0 +1,142 @@
+/* PERMUTE_ARGS:
+ */
+
+// https://issues.dlang.org/show_bug.cgi?id=15624
+
+struct Foo {
+ int x;
+ int opApply(int delegate(int, string, string) @safe dg) @safe {
+ x = 1;
+ return 0;
+ }
+ int opApply(int delegate(int, string, string) @system dg) @system {
+ x = 2;
+ return 0;
+ }
+}
+
+void testSafe() @safe {
+ Foo foo;
+ foreach (i, k, v; foo) {
+ }
+ assert(foo.x == 1);
+}
+
+void testSystem() @system {
+ Foo foo;
+ foreach (i, k, v; foo) {
+ }
+ assert(foo.x == 2);
+}
+
+void test() @system
+{
+ Foo f;
+
+ int dgsafe (int x, string s, string t) @safe { return 1; }
+ int dgsystem(int x, string s, string t) @system { return 1; }
+
+ f.opApply(&dgsafe);
+ assert(f.x == 1);
+ f.opApply(&dgsystem);
+ assert(f.x == 2);
+}
+
+int main()
+{
+ testSafe();
+ testSystem();
+ test();
+ testDifferentTypes();
+ testSameAttributes();
+ testInverseAttributes();
+ return 0;
+}
+
+void testDifferentTypes()
+{
+ static struct DifferentTypes
+ {
+ int x;
+ int opApply(int delegate(int) dg) @safe {
+ x = 1;
+ return 0;
+ }
+ int opApply(int delegate(long) dg) @safe {
+ x = 2;
+ return 0;
+ }
+ }
+
+ DifferentTypes dt;
+ foreach (int i; dt) {}
+ assert(dt.x == 1);
+
+ foreach (long i; dt) {}
+ assert(dt.x == 2);
+}
+
+void testSameAttributes()
+{
+ static struct SameAttributes
+ {
+ int x;
+ int opApply(int delegate(int) @system dg) @safe {
+ x = 1;
+ return 0;
+ }
+ int opApply(int delegate(int) @safe dg) @safe {
+ x = 2;
+ return 0;
+ }
+ }
+
+ static void safe() @safe
+ {
+ SameAttributes sa;
+ foreach (i; sa) {}
+ assert(sa.x == 2);
+ }
+ safe();
+
+ static void system() @system
+ {
+ SameAttributes sa;
+ foreach (i; sa) {}
+ assert(sa.x == 1);
+ }
+ system();
+}
+
+// Not useful but enabled by the associated patch
+void testInverseAttributes()
+{
+ static struct InverseAttributes
+ {
+ int x;
+ int opApply(int delegate(int) @system dg) @safe {
+ x = 1;
+ return 0;
+ }
+ int opApply(int delegate(int) @safe dg) @system {
+ x = 2;
+ return 0;
+ }
+ }
+
+ static void system() @system
+ {
+ InverseAttributes sa;
+ foreach (i; sa) {}
+ assert(sa.x == 1);
+ }
+ system();
+
+ static void safe() @safe
+ {
+ InverseAttributes sa;
+ (() @trusted { foreach (i; sa) {} })();
+ assert(sa.x == 2);
+ }
+ safe();
+}
diff --git a/gcc/testsuite/gdc.test/runnable/testmainb.d b/gcc/testsuite/gdc.test/runnable/testmainb.d
new file mode 100644
index 0000000..d6452ec
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/testmainb.d
@@ -0,0 +1,15 @@
+/*
+Test that -main does nothing when main is already defined
+
+REQUIRED_ARGS: -main
+RUN_OUTPUT:
+---
+Success
+---
+*/
+extern(C) int printf(const char*, ...);
+
+void main()
+{
+ printf("Success\n");
+}
diff --git a/gcc/testsuite/gdc.test/runnable/uda.d b/gcc/testsuite/gdc.test/runnable/uda.d
index cdb9aa6..1d01098 100644
--- a/gcc/testsuite/gdc.test/runnable/uda.d
+++ b/gcc/testsuite/gdc.test/runnable/uda.d
@@ -697,6 +697,54 @@ static if(is(typeof(foo20831) Params20831 == __parameters))
/************************************************/
+/************************************************/
+// https://issues.dlang.org/show_bug.cgi?id=15804
+
+template test15804()
+{
+ alias AliasSeq(T...) = T;
+
+ @(42) struct Foo(D) {}
+ auto fooFac(T)()
+ {
+ static assert(__traits(getAttributes, Foo) == AliasSeq!42);
+ static assert(__traits(getAttributes, Foo!int) == AliasSeq!42);
+ return Foo!T();
+ }
+
+ auto booFac(T)()
+ {
+ @(43) struct Boo {}
+ static assert(__traits(getAttributes, Boo) == AliasSeq!43);
+ return Boo();
+ }
+
+ auto barFac(T)()
+ {
+ @(44) struct Bar(D) {}
+ static assert(__traits(getAttributes, Bar) == AliasSeq!44); // Fixed
+ static assert(__traits(getAttributes, Bar!int) == AliasSeq!44);
+ return Bar!T();
+ }
+
+ auto bazFac(T)()
+ {
+ @(45) static struct Baz(D) {}
+ static assert(__traits(getAttributes, Baz) == AliasSeq!45); // Fixed
+ static assert(__traits(getAttributes, Baz!int) == AliasSeq!45);
+ return Baz!T();
+ }
+
+ auto foo = fooFac!int;
+ auto boo = booFac!int;
+ auto bar = barFac!int;
+ auto baz = bazFac!int;
+}
+
+alias a15804 = test15804!();
+
+/************************************************/
+
int main()
{
test1();
diff --git a/gcc/testsuite/gdc.test/runnable/ufcs.d b/gcc/testsuite/gdc.test/runnable/ufcs.d
index 2d9bf15..8fd7bb2 100644
--- a/gcc/testsuite/gdc.test/runnable/ufcs.d
+++ b/gcc/testsuite/gdc.test/runnable/ufcs.d
@@ -196,6 +196,7 @@ void test5()
{
// f5_1 .. f5_5 are symbols which declared in module scope
assert(100.f5_1() == 1);
+ assert(001.f5_1() == 1); // https://issues.dlang.org/show_bug.cgi?id=8346
assert("s".f5_2() == 2);
assert(1.4.f5_3() == 3);
assert(100.f5_4() == 1);
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cpp22287.cpp b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cpp22287.cpp
new file mode 100644
index 0000000..ba7b25a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cpp22287.cpp
@@ -0,0 +1,337 @@
+#include <assert.h>
+
+class X
+{
+public:
+ virtual ~X();
+ int i;
+};
+
+X::~X()
+{
+}
+
+class Y : public X
+{
+};
+
+class A
+{
+public:
+ virtual ~A();
+ virtual int f1() const;
+
+ int i;
+};
+
+class I
+{
+public:
+ virtual int f2() const = 0;
+ virtual X *f4() = 0;
+};
+
+class B : public A, public I
+{
+public:
+ virtual int f1() const;
+ virtual int f2() const;
+ virtual int f3() const;
+ virtual X *f4();
+};
+
+class C : public B
+{
+public:
+ virtual int f1() const;
+ virtual int f2() const;
+ virtual int f3() const;
+ virtual Y *f4();
+};
+
+#ifdef _WIN32
+class D : public B
+{
+public:
+ virtual int f1() const;
+ virtual int f2() const;
+ virtual int f3() const;
+ virtual Y *f4();
+};
+
+class E : public B
+{
+public:
+ virtual int f1() const;
+ virtual int f2() const;
+ virtual int f3() const;
+ virtual Y *f4();
+};
+#endif
+
+A::~A()
+{
+}
+
+int A::f1() const
+{
+ return i + 11;
+}
+
+int B::f1() const
+{
+ return i + 21;
+}
+
+int B::f2() const
+{
+ return i + 22;
+}
+
+int B::f3() const
+{
+ return i + 23;
+}
+
+X *B::f4()
+{
+ X *r = new X;
+ r->i = i + 24;
+ return r;
+}
+
+int C::f1() const
+{
+ return i + 31;
+}
+
+int C::f2() const
+{
+ return i + 32;
+}
+
+int C::f3() const
+{
+ return i + 33;
+}
+
+Y *C::f4()
+{
+ Y *r = new Y;
+ r->i = i + 34;
+ return r;
+}
+
+I *createIFromCPP(char type, int i)
+{
+ switch (type)
+ {
+ case 'B':
+ {
+ B *b = new B();
+ b->i = i;
+ return b;
+ }
+ case 'C':
+ {
+ C *c = new C();
+ c->i = i;
+ return c;
+ }
+#ifdef _WIN32
+ case 'D':
+ {
+ D *d = new D();
+ d->i = i;
+ return d;
+ }
+ case 'E':
+ {
+ E *e = new E();
+ e->i = i;
+ return e;
+ }
+#endif
+ default:
+ return 0;
+ }
+}
+
+B *createBFromCPP(char type, int i)
+{
+ switch (type)
+ {
+ case 'B':
+ {
+ B *b = new B();
+ b->i = i;
+ return b;
+ }
+ case 'C':
+ {
+ C *c = new C();
+ c->i = i;
+ return c;
+ }
+#ifdef _WIN32
+ case 'D':
+ {
+ D *d = new D();
+ d->i = i;
+ return d;
+ }
+ case 'E':
+ {
+ E *e = new E();
+ e->i = i;
+ return e;
+ }
+#endif
+ default:
+ return 0;
+ }
+}
+
+C *createCFromCPP(int i)
+{
+ C *c = new C();
+ c->i = i;
+ return c;
+}
+
+#ifdef _WIN32
+D *createDFromCPP(int i)
+{
+ D *d = new D();
+ d->i = i;
+ return d;
+}
+
+E *createEFromCPP(int i)
+{
+ E *e = new E();
+ e->i = i;
+ return e;
+}
+#endif
+
+I *createIFromD(char type, int i);
+B *createBFromD(char type, int i);
+C *createCFromD(int i);
+#ifdef _WIN32
+D *createDFromD(int i);
+E *createEFromD(int i);
+#endif
+
+void runCPPTests()
+{
+ {
+ B *b = new B();
+ b->i = 100;
+ assert(b->f1() == 121);
+ assert(b->f2() == 122);
+ assert(b->f3() == 123);
+ assert(b->f4()->i == 124);
+ }
+ {
+ C *c = new C();
+ c->i = 100;
+ assert(c->f1() == 131);
+ assert(c->f2() == 132);
+ assert(c->f3() == 133);
+ assert(c->f4()->i == 134);
+ }
+#ifdef _WIN32
+ {
+ D *d = new D();
+ d->i = 100;
+ assert(d->f1() == 141);
+ assert(d->f2() == 142);
+ assert(d->f3() == 143);
+ assert(d->f4()->i == 144);
+ }
+ {
+ E *e = new E();
+ e->i = 100;
+ assert(e->f1() == 151);
+ assert(e->f2() == 152);
+ assert(e->f3() == 153);
+ assert(e->f4()->i == 154);
+ }
+#endif
+ {
+ I *i = createIFromD('B', 100);
+ assert(i->f2() == 122);
+ assert(i->f4()->i == 124);
+ }
+ {
+ I *i = createIFromD('C', 100);
+ assert(i->f2() == 132);
+ assert(i->f4()->i == 134);
+ }
+#ifdef _WIN32
+ {
+ I *i = createIFromD('D', 100);
+ assert(i->f2() == 142);
+ assert(i->f4()->i == 144);
+ }
+ {
+ I *i = createIFromD('E', 100);
+ assert(i->f2() == 152);
+ assert(i->f4()->i == 154);
+ }
+#endif
+ {
+ B *b = createBFromD('B', 100);
+ assert(b->f1() == 121);
+ assert(b->f2() == 122);
+ assert(b->f3() == 123);
+ assert(b->f4()->i == 124);
+ }
+ {
+ B *b = createBFromD('C', 100);
+ assert(b->f1() == 131);
+ assert(b->f2() == 132);
+ assert(b->f3() == 133);
+ assert(b->f4()->i == 134);
+ }
+#ifdef _WIN32
+ {
+ B *b = createBFromD('D', 100);
+ assert(b->f1() == 141);
+ assert(b->f2() == 142);
+ assert(b->f3() == 143);
+ assert(b->f4()->i == 144);
+ }
+ {
+ B *b = createBFromD('E', 100);
+ assert(b->f1() == 151);
+ assert(b->f2() == 152);
+ assert(b->f3() == 153);
+ assert(b->f4()->i == 154);
+ }
+#endif
+ {
+ C *c = createCFromD(100);
+ assert(c->f1() == 131);
+ assert(c->f2() == 132);
+ assert(c->f3() == 133);
+ assert(c->f4()->i == 134);
+ }
+#ifdef _WIN32
+ {
+ D *d = createDFromD(100);
+ assert(d->f1() == 141);
+ assert(d->f2() == 142);
+ assert(d->f3() == 143);
+ assert(d->f4()->i == 144);
+ }
+ {
+ E *e = createEFromD(100);
+ assert(e->f1() == 151);
+ assert(e->f2() == 152);
+ assert(e->f3() == 153);
+ assert(e->f4()->i == 154);
+ }
+#endif
+}
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/test22287.d b/gcc/testsuite/gdc.test/runnable_cxx/test22287.d
new file mode 100644
index 0000000..a0c7475
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable_cxx/test22287.d
@@ -0,0 +1,327 @@
+// EXTRA_CPP_SOURCES: cpp22287.cpp
+
+extern(C++):
+
+class X
+{
+public:
+ ~this();
+ int i;
+}
+
+class Y : X
+{
+}
+
+class A
+{
+ ~this();
+ int f1() const;
+
+ int i;
+}
+
+interface I
+{
+ int f2() const;
+ X f4();
+}
+
+class B : A, I
+{
+ override int f1() const;
+ override int f2() const;
+ int f3() const;
+ override X f4();
+}
+
+class C : B
+{
+ override int f1() const;
+ override int f2() const;
+ override int f3() const;
+ override Y f4();
+}
+
+version(Windows)
+{
+class D : B
+{
+ override int f1() const
+ {
+ return i + 41;
+ }
+
+ override int f2() const
+ {
+ return i + 42;
+ }
+
+ override int f3() const
+ {
+ return i + 43;
+ }
+
+ override Y f4()
+ {
+ Y r = new Y;
+ r.i = i + 44;
+ return r;
+ }
+}
+
+mixin template MixinE()
+{
+ override int f1() const
+ {
+ return i + 51;
+ }
+
+ override int f2() const
+ {
+ return i + 52;
+ }
+
+ override int f3() const
+ {
+ return i + 53;
+ }
+
+ override Y f4()
+ {
+ Y r = new Y;
+ r.i = i + 54;
+ return r;
+ }
+}
+
+class E : B
+{
+ mixin MixinE;
+}
+}
+
+I createIFromCPP(char type, int i);
+B createBFromCPP(char type, int i);
+C createCFromCPP(int i);
+version(Windows)
+{
+D createDFromCPP(int i);
+E createEFromCPP(int i);
+}
+
+I createIFromD(char type, int i)
+{
+ switch (type)
+ {
+ case 'B':
+ {
+ B b = new B();
+ b.i = i;
+ return b;
+ }
+ case 'C':
+ {
+ C c = new C();
+ c.i = i;
+ return c;
+ }
+ version(Windows)
+ {
+ case 'D':
+ {
+ D d = new D();
+ d.i = i;
+ return d;
+ }
+ case 'E':
+ {
+ E e = new E();
+ e.i = i;
+ return e;
+ }
+ }
+ default:
+ return null;
+ }
+}
+
+B createBFromD(char type, int i)
+{
+ switch (type)
+ {
+ case 'B':
+ {
+ B b = new B();
+ b.i = i;
+ return b;
+ }
+ case 'C':
+ {
+ C c = new C();
+ c.i = i;
+ return c;
+ }
+ version(Windows)
+ {
+ case 'D':
+ {
+ D d = new D();
+ d.i = i;
+ return d;
+ }
+ case 'E':
+ {
+ E e = new E();
+ e.i = i;
+ return e;
+ }
+ }
+ default:
+ return null;
+ }
+}
+
+C createCFromD(int i)
+{
+ C c = new C();
+ c.i = i;
+ return c;
+}
+
+version(Windows)
+{
+D createDFromD(int i)
+{
+ D d = new D();
+ d.i = i;
+ return d;
+}
+
+E createEFromD(int i)
+{
+ E e = new E();
+ e.i = i;
+ return e;
+}
+}
+
+void runCPPTests();
+
+extern(D) void main()
+{
+ {
+ B b = new B();
+ b.i = 100;
+ assert(b.f1() == 121);
+ assert(b.f2() == 122);
+ assert(b.f3() == 123);
+ assert(b.f4().i == 124);
+ }
+ {
+ C c = new C();
+ c.i = 100;
+ assert(c.f1() == 131);
+ assert(c.f2() == 132);
+ assert(c.f3() == 133);
+ assert(c.f4().i == 134);
+ }
+ version(Windows)
+ {
+ {
+ D d = new D();
+ d.i = 100;
+ assert(d.f1() == 141);
+ assert(d.f2() == 142);
+ assert(d.f3() == 143);
+ assert(d.f4().i == 144);
+ }
+ {
+ E e = new E();
+ e.i = 100;
+ assert(e.f1() == 151);
+ assert(e.f2() == 152);
+ assert(e.f3() == 153);
+ assert(e.f4().i == 154);
+ }
+ }
+ {
+ I i = createIFromCPP('B', 100);
+ assert(i.f2() == 122);
+ assert(i.f4().i == 124);
+ }
+ {
+ I i = createIFromCPP('C', 100);
+ assert(i.f2() == 132);
+ assert(i.f4().i == 134);
+ }
+ version(Windows)
+ {
+ {
+ I i = createIFromCPP('D', 100);
+ assert(i.f2() == 142);
+ assert(i.f4().i == 144);
+ }
+ {
+ I i = createIFromCPP('E', 100);
+ assert(i.f2() == 152);
+ assert(i.f4().i == 154);
+ }
+ }
+ {
+ B b = createBFromCPP('B', 100);
+ assert(b.f1() == 121);
+ assert(b.f2() == 122);
+ assert(b.f3() == 123);
+ assert(b.f4().i == 124);
+ }
+ {
+ B b = createBFromCPP('C', 100);
+ assert(b.f1() == 131);
+ assert(b.f2() == 132);
+ assert(b.f3() == 133);
+ assert(b.f4().i == 134);
+ }
+ version(Windows)
+ {
+ {
+ B b = createBFromCPP('D', 100);
+ assert(b.f1() == 141);
+ assert(b.f2() == 142);
+ assert(b.f3() == 143);
+ assert(b.f4().i == 144);
+ }
+ {
+ B b = createBFromCPP('E', 100);
+ assert(b.f1() == 151);
+ assert(b.f2() == 152);
+ assert(b.f3() == 153);
+ assert(b.f4().i == 154);
+ }
+ }
+ {
+ C c = createCFromCPP(100);
+ assert(c.f1() == 131);
+ assert(c.f2() == 132);
+ assert(c.f3() == 133);
+ assert(c.f4().i == 134);
+ }
+ version(Windows)
+ {
+ {
+ D d = createDFromCPP(100);
+ assert(d.f1() == 141);
+ assert(d.f2() == 142);
+ assert(d.f3() == 143);
+ assert(d.f4().i == 144);
+ }
+ {
+ E e = createEFromCPP(100);
+ assert(e.f1() == 151);
+ assert(e.f2() == 152);
+ assert(e.f3() == 153);
+ assert(e.f4().i == 154);
+ }
+ }
+ runCPPTests();
+}
diff --git a/gcc/testsuite/gfortran.dg/allocate_with_mold_4.f90 b/gcc/testsuite/gfortran.dg/allocate_with_mold_4.f90
new file mode 100644
index 0000000..d545fe1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/allocate_with_mold_4.f90
@@ -0,0 +1,24 @@
+program A_M
+ implicit none
+ real, parameter :: C(5:10) = 5.0
+ real, dimension (:), allocatable :: A, B
+ allocate (A(6))
+ call Init (A)
+contains
+ subroutine Init ( A )
+ real, dimension ( -1 : ), intent ( in ) :: A
+ integer, dimension ( 1 ) :: lb_B
+
+ allocate (B, mold = A)
+ if (any (lbound (B) /= lbound (A))) stop 1
+ if (any (ubound (B) /= ubound (A))) stop 2
+ if (any (shape (B) /= shape (A))) stop 3
+ if (size (B) /= size (A)) stop 4
+ deallocate (B)
+ allocate (B, mold = C)
+ if (any (lbound (B) /= lbound (C))) stop 5
+ if (any (ubound (B) /= ubound (C))) stop 6
+ if (any (shape (B) /= shape (C))) stop 7
+ if (size (B) /= size (C)) stop 8
+end
+end
diff --git a/gcc/testsuite/gfortran.dg/allocate_with_source_26.f90 b/gcc/testsuite/gfortran.dg/allocate_with_source_26.f90
index 28f24fc..323c8a3 100644
--- a/gcc/testsuite/gfortran.dg/allocate_with_source_26.f90
+++ b/gcc/testsuite/gfortran.dg/allocate_with_source_26.f90
@@ -34,23 +34,23 @@ program p
if (lbound(p1, 1) /= 3 .or. ubound(p1, 1) /= 4 &
.or. lbound(p2, 1) /= 3 .or. ubound(p2, 1) /= 4 &
.or. lbound(p3, 1) /= 1 .or. ubound(p3, 1) /= 2 &
- .or. lbound(p4, 1) /= 7 .or. ubound(p4, 1) /= 8 &
+ .or. lbound(p4, 1) /= 1 .or. ubound(p4, 1) /= 2 &
.or. p1(3)%i /= 43 .or. p1(4)%i /= 56 &
.or. p2(3)%i /= 43 .or. p2(4)%i /= 56 &
.or. p3(1)%i /= 43 .or. p3(2)%i /= 56 &
- .or. p4(7)%i /= 11 .or. p4(8)%i /= 12) then
+ .or. p4(1)%i /= 11 .or. p4(2)%i /= 12) then
call abort()
endif
!write(*,*) lbound(a,1), ubound(a,1) ! prints 1 3
!write(*,*) lbound(b,1), ubound(b,1) ! prints 1 3
- !write(*,*) lbound(c,1), ubound(c,1) ! prints 3 5
+ !write(*,*) lbound(c,1), ubound(c,1) ! prints 1 3
!write(*,*) lbound(d,1), ubound(d,1) ! prints 1 5
!write(*,*) lbound(e,1), ubound(e,1) ! prints 1 6
if (lbound(a,1) /= 1 .or. ubound(a,1) /= 3 &
.or. lbound(b,1) /= 1 .or. ubound(b,1) /= 3 &
- .or. lbound(c,1) /= 3 .or. ubound(c,1) /= 5 &
+ .or. lbound(c,1) /= 1 .or. ubound(c,1) /= 3 &
.or. lbound(d,1) /= 1 .or. ubound(d,1) /= 5 &
.or. lbound(e,1) /= 1 .or. ubound(e,1) /= 6) then
call abort()
diff --git a/gcc/testsuite/gfortran.dg/goacc/finalize-1.f b/gcc/testsuite/gfortran.dg/goacc/finalize-1.f
index b706b38..1e5bf0b 100644
--- a/gcc/testsuite/gfortran.dg/goacc/finalize-1.f
+++ b/gcc/testsuite/gfortran.dg/goacc/finalize-1.f
@@ -20,8 +20,8 @@
! { dg-final { scan-tree-dump-times "(?n)#pragma omp target oacc_exit_data map\\(delete:del_f \\\[len: \[0-9\]+\\\]\\) finalize$" 1 "gimple" } }
!$ACC EXIT DATA FINALIZE DELETE (del_f_p(2:5))
-! { dg-final { scan-tree-dump-times "(?n)#pragma acc exit data map\\(release:\\*\\(c_char \\*\\) parm\\.0\\.data \\\[len: \[^\\\]\]+\\\]\\) map\\(to:del_f_p \\\[pointer set, len: \[0-9\]+\\\]\\) map\\(alloc:\\(integer\\(kind=1\\)\\\[0:\\\] \\* restrict\\) del_f_p\\.data \\\[pointer assign, bias: \\(.*int.*\\) parm\\.0\\.data - \\(.*int.*\\) del_f_p\\.data\\\]\\) finalize;$" 1 "original" } }
-! { dg-final { scan-tree-dump-times "(?n)#pragma omp target oacc_exit_data map\\(delete:MEM\\\[\\(c_char \\*\\)\[^\\\]\]+\\\] \\\[len: \[^\\\]\]+\\\]\\) map\\(to:del_f_p \\\[pointer set, len: \[0-9\]+\\\]\\) map\\(alloc:del_f_p\\.data \\\[pointer assign, bias: \[^\\\]\]+\\\]\\) finalize$" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "(?n)#pragma acc exit data map\\(release:\\*\\(integer\\(kind=.\\)\\\[0:\\\] \\*\\) parm\\.0\\.data \\\[len: \[^\\\]\]+\\\]\\) map\\(to:del_f_p \\\[pointer set, len: \[0-9\]+\\\]\\) map\\(alloc:\\(integer\\(kind=1\\)\\\[0:\\\] \\* restrict\\) del_f_p\\.data \\\[pointer assign, bias: \\(.*int.*\\) parm\\.0\\.data - \\(.*int.*\\) del_f_p\\.data\\\]\\) finalize;$" 1 "original" } }
+! { dg-final { scan-tree-dump-times "(?n)#pragma omp target oacc_exit_data map\\(delete:MEM <\[^>\]+> \\\[\\(integer\\(kind=.\\)\\\[0:\\\] \\*\\)_\[0-9\]+\\\] \\\[len: \[^\\\]\]+\\\]\\) map\\(to:del_f_p \\\[pointer set, len: \[0-9\]+\\\]\\) map\\(alloc:del_f_p\\.data \\\[pointer assign, bias: \[^\\\]\]+\\\]\\) finalize$" 1 "gimple" } }
!$ACC EXIT DATA COPYOUT (cpo_r)
! { dg-final { scan-tree-dump-times "(?n)#pragma acc exit data map\\(from:cpo_r\\);$" 1 "original" } }
@@ -32,6 +32,6 @@
! { dg-final { scan-tree-dump-times "(?n)#pragma omp target oacc_exit_data map\\(force_from:cpo_f \\\[len: \[0-9\]+\\\]\\) finalize$" 1 "gimple" } }
!$ACC EXIT DATA COPYOUT (cpo_f_p(4:10)) FINALIZE
-! { dg-final { scan-tree-dump-times "(?n)#pragma acc exit data map\\(from:\\*\\(c_char \\*\\) parm\\.1\\.data \\\[len: \[^\\\]\]+\\\]\\) map\\(to:cpo_f_p \\\[pointer set, len: \[0-9\]+\\\]\\) map\\(alloc:\\(integer\\(kind=1\\)\\\[0:\\\] \\* restrict\\) cpo_f_p\\.data \\\[pointer assign, bias: \\(.*int.*\\) parm\\.1\\.data - \\(.*int.*\\) cpo_f_p\\.data\\\]\\) finalize;$" 1 "original" } }
-! { dg-final { scan-tree-dump-times "(?n)#pragma omp target oacc_exit_data map\\(force_from:MEM\\\[\\(c_char \\*\\)\[^\\\]\]+\\\] \\\[len: \[^\\\]\]+\\\]\\) map\\(to:cpo_f_p \\\[pointer set, len: \[0-9\]+\\\]\\) map\\(alloc:cpo_f_p\\.data \\\[pointer assign, bias: \[^\\\]\]+\\\]\\) finalize$" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "(?n)#pragma acc exit data map\\(from:\\*\\(integer\\(kind=.\\)\\\[0:\\\] \\*\\) parm\\.1\\.data \\\[len: \[^\\\]\]+\\\]\\) map\\(to:cpo_f_p \\\[pointer set, len: \[0-9\]+\\\]\\) map\\(alloc:\\(integer\\(kind=1\\)\\\[0:\\\] \\* restrict\\) cpo_f_p\\.data \\\[pointer assign, bias: \\(.*int.*\\) parm\\.1\\.data - \\(.*int.*\\) cpo_f_p\\.data\\\]\\) finalize;$" 1 "original" } }
+! { dg-final { scan-tree-dump-times "(?n)#pragma omp target oacc_exit_data map\\(force_from:MEM <\[^>\]+> \\\[\\(integer\\(kind=.\\)\\\[0:\\\] \\*\\)_\[0-9\]+\\\] \\\[len: \[^\\\]\]+\\\]\\) map\\(to:cpo_f_p \\\[pointer set, len: \[0-9\]+\\\]\\) map\\(alloc:cpo_f_p\\.data \\\[pointer assign, bias: \[^\\\]\]+\\\]\\) finalize$" 1 "gimple" } }
END SUBROUTINE f
diff --git a/gcc/testsuite/gfortran.dg/gomp/affinity-clause-1.f90 b/gcc/testsuite/gfortran.dg/gomp/affinity-clause-1.f90
index 13bdd36..08c7740 100644
--- a/gcc/testsuite/gfortran.dg/gomp/affinity-clause-1.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/affinity-clause-1.f90
@@ -22,12 +22,12 @@ end
! { dg-final { scan-tree-dump-times "D\\.\[0-9\]+ = .integer.kind=4.. __builtin_cosf ..real.kind=4.. a \\+ 1.0e\\+0\\);" 2 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp task affinity\\(iterator\\(integer\\(kind=4\\) jj=2:5:2, integer\\(kind=4\\) i=D\\.\[0-9\]+:5:1\\):\\*\\(c_char \\*\\) &b\\\[.* <?i>? \\+ -1\\\]\\) affinity\\(iterator\\(integer\\(kind=4\\) jj=2:5:2, integer\\(kind=4\\) i=D\\.\[0-9\]+:5:1\\):\\*\\(c_char \\*\\) &d\\\[\\(.*jj \\* 5 \\+ .* <?i>?\\) \\+ -6\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task affinity\\(iterator\\(integer\\(kind=4\\) jj=2:5:2, integer\\(kind=4\\) i=D\\.\[0-9\]+:5:1\\):b\\\[.* <?i>? \\+ -1\\\]\\) affinity\\(iterator\\(integer\\(kind=4\\) jj=2:5:2, integer\\(kind=4\\) i=D\\.\[0-9\]+:5:1\\):d\\\[\\(.*jj \\* 5 \\+ .* <?i>?\\) \\+ -6\\\]\\)" 1 "original" } }
-! { dg final { scan-tree-dump-times "#pragma omp task affinity\\(iterator\\(integer\\(kind=4\\) i=D.3938:5:1\\):\\*\\(c_char \\*\\) &b\\\[\\(.* <?i>? \\+ -1\\\]\\) affinity\\(iterator\\(integer\\(kind=4\\) i=D\\.\[0-9\]+:5:1\\):\\*\\(c_char \\*\\) &d\\\[\\(\\(integer\\(kind=8\\)\\) i \\+ -1\\) \\* 6\\\]\\)" 1 "original" } }
+! { dg final { scan-tree-dump-times "#pragma omp task affinity\\(iterator\\(integer\\(kind=4\\) i=D\\.\[0-9\]+:5:1\\):b\\\[\\(.* <?i>? \\+ -1\\\]\\) affinity\\(iterator\\(integer\\(kind=4\\) i=D\\.\[0-9\]+:5:1\\):d\\\[\\(\\(integer\\(kind=8\\)\\) i \\+ -1\\) \\* 6\\\]\\)" 1 "original" } }
! { dg-final { scan-tree-dump-times "#pragma omp task affinity\\(iterator\\(integer\\(kind=4\\) i=1:5:1\\):a\\)\[^ \]" 1 "original" } }
! { dg-final { scan-tree-dump-times "#pragma omp task affinity\\(iterator\\(integer\\(kind=4\\) i=1:5:1\\):a\\) affinity\\(iterator\\(integer\\(kind=4\\) i=1:5:1\\):\\*x\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp task affinity\\(iterator\\(integer\\(kind=4\\) k=7:4:-1, integer\\(kind=8\\) j=1:5:1\\):\\*\\(c_char \\*\\) &b\\\[\\(?\\(integer\\(kind=.\\).* \[jk\] \\+ .*\[kj\]\\) \\+ -1\\\]\\) affinity\\(iterator\\(integer\\(kind=4\\) k=7:4:-1, integer\\(kind=8\\) j=1:5:1\\):a\\) affinity\\(cc\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task affinity\\(iterator\\(integer\\(kind=4\\) k=7:4:-1, integer\\(kind=8\\) j=1:5:1\\):b\\\[\\(?\\(integer\\(kind=.\\).* \[jk\] \\+ .*\[kj\]\\) \\+ -1\\\]\\) affinity\\(iterator\\(integer\\(kind=4\\) k=7:4:-1, integer\\(kind=8\\) j=1:5:1\\):a\\) affinity\\(cc\\)" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/affinity-clause-5.f90 b/gcc/testsuite/gfortran.dg/gomp/affinity-clause-5.f90
index 538b5a5..c23fee0 100644
--- a/gcc/testsuite/gfortran.dg/gomp/affinity-clause-5.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/affinity-clause-5.f90
@@ -18,6 +18,6 @@ end
! { dg-final { scan-tree-dump-times "pragma omp task affinity\\(iterator\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp task affinity\\(\\*\\(c_char \\*\\) &iterator\\\[2\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task affinity\\(iterator\\\[2\\\]\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp task affinity\\(iterator\\(integer\\(kind=4\\) i=1:10:1\\):\\*\\(c_char \\*\\) &iterator\\\[.* <?i>? \\+ -1\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task affinity\\(iterator\\(integer\\(kind=4\\) i=1:10:1\\):iterator\\\[.* <?i>? \\+ -1\\\]\\)" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic-10.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic-10.f90
new file mode 100644
index 0000000..bafc88b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic-10.f90
@@ -0,0 +1,32 @@
+! PR middle-end/28046 for the original C tet.
+! { dg-do compile }
+! { dg-options "-fopenmp -fdump-tree-ompexp" }
+! { dg-require-effective-target cas_int }
+
+module m
+ implicit none
+ integer a(3), b
+ type t_C
+ integer :: x, y
+ end type
+ type(t_C) :: c
+
+ interface
+ integer function bar(); end
+ integer function baz(); end
+ end interface
+ pointer :: baz
+contains
+subroutine foo
+!$omp atomic
+ a(2) = a(2) + bar ()
+!$omp atomic
+ b = b + bar ()
+!$omp atomic
+ c%y = c%y + bar ()
+!$omp atomic
+ b = b + baz ()
+end
+end module
+
+! { dg-final { scan-tree-dump-times "__atomic_fetch_add" 4 "ompexp" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic-12.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic-12.f90
new file mode 100644
index 0000000..a097076
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic-12.f90
@@ -0,0 +1,364 @@
+! PR middle-end/45423 - for the original C/C++ testcase
+! { dg-do compile }
+! { dg-options "-fopenmp -fdump-tree-gimple -g0 -Wno-deprecated" }
+! atomicvar should never be referenced in between the barrier and
+! following #pragma omp atomic_load.
+! { dg-final { scan-tree-dump-not "barrier\[^#\]*atomicvar" "gimple" } }
+
+module m
+ implicit none
+ logical :: atomicvar, c
+ integer :: i, atomicvar2, c2
+contains
+integer function foo ()
+ !$omp barrier
+ !$omp atomic
+ atomicvar = atomicvar .or. .true.
+ !$omp barrier
+ !$omp atomic
+ atomicvar = atomicvar .or. .false.
+ !$omp barrier
+ !$omp atomic
+ atomicvar = atomicvar .or. c
+ !$omp barrier
+ !$omp atomic
+ atomicvar = atomicvar .and. .true.
+ !$omp barrier
+ !$omp atomic
+ atomicvar = atomicvar .and. .false.
+ !$omp barrier
+ !$omp atomic
+ atomicvar = atomicvar .and. c
+ !$omp barrier
+ !$omp atomic
+ atomicvar = atomicvar .neqv. .true.
+ !$omp barrier
+ !$omp atomic
+ atomicvar = atomicvar .neqv. .false.
+ !$omp barrier
+ !$omp atomic
+ atomicvar = atomicvar .neqv. c
+ !$omp barrier
+ !$omp atomic
+ atomicvar = atomicvar .eqv. .true.
+ !$omp barrier
+ !$omp atomic
+ atomicvar = atomicvar .eqv. .false.
+ !$omp barrier
+ !$omp atomic
+ atomicvar = atomicvar .eqv. c
+ !$omp barrier
+ !$omp atomic
+ atomicvar = .true. .or. atomicvar
+ !$omp barrier
+ !$omp atomic
+ atomicvar = .false. .or. atomicvar
+ !$omp barrier
+ !$omp atomic
+ atomicvar = c .or. atomicvar
+ !$omp barrier
+ !$omp atomic
+ atomicvar = .true. .and. atomicvar
+ !$omp barrier
+ !$omp atomic
+ atomicvar = .false. .and. atomicvar
+ !$omp barrier
+ !$omp atomic
+ atomicvar = c .and. atomicvar
+ !$omp barrier
+ !$omp atomic
+ atomicvar = .true. .neqv. atomicvar
+ !$omp barrier
+ !$omp atomic
+ atomicvar = .false. .neqv. atomicvar
+ !$omp barrier
+ !$omp atomic
+ atomicvar = c .neqv. atomicvar
+ !$omp barrier
+ !$omp atomic
+ atomicvar = .true. .eqv. atomicvar
+ !$omp barrier
+ !$omp atomic
+ atomicvar = .false. .eqv. atomicvar
+ !$omp barrier
+ !$omp atomic
+ atomicvar = c .eqv. atomicvar
+ !$omp barrier
+ foo = 0
+end
+
+integer function bar ()
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ior (atomicvar2, -1)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ior (atomicvar2, 0)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ior (atomicvar2, 1)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ior (atomicvar2, 2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ior (atomicvar2, c2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ior (-1, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ior (0, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ior (1, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ior (2, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ior (c2, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ieor (atomicvar2, -1)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ieor (atomicvar2, 0)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ieor (atomicvar2, 1)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ieor (atomicvar2, 2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ieor (atomicvar2, c2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ieor (-1, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ieor (0, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ieor (1, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ior (2, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = ior (c2, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = iand (atomicvar2, -1)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = iand (atomicvar2, 0)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = iand (atomicvar2, 1)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = iand (atomicvar2, 2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = iand (atomicvar2, c2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = iand (-1, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = iand (0, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = iand (1, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = iand (2, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = iand (c2, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = min (atomicvar2, -1)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = min (atomicvar2, 0)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = min (atomicvar2, 1)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = min (atomicvar2, 2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = min (atomicvar2, c2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = min (-1, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = min (0, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = min (1, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = min (2, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = min (c2, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = max (atomicvar2, -1)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = max (atomicvar2, 0)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = max (atomicvar2, 1)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = max (atomicvar2, 2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = max (atomicvar2, c2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = max (-1, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = max (0, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = max (1, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = max (2, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = max (c2, atomicvar2)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 + (-1)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 + 0
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 + 1
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 + 2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 + c2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = -1 + atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = 0 + atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = 1 + atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = 2 + atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = c2 + atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 - (-1)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 - 0
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 - 1
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 - 2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 - c2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = -1 - atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = 0 - atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = 1 - atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = 2 - atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = c2 - atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 * (-1)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 * 0
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 * 1
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 * 2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 * c2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = (-1) * atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = 0 * atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = 1 * atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = 2 * atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = c2 * atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 / (-1)
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 / 0
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 / 1
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 / 2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = atomicvar2 / c2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = (-1) / atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = 0 / atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = 1 / atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = 2 / atomicvar2
+ !$omp barrier
+ !$omp atomic
+ atomicvar2 = c2 / atomicvar2
+ !$omp barrier
+ bar = 0
+end
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic-15.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic-15.f90
new file mode 100644
index 0000000..4c81791
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic-15.f90
@@ -0,0 +1,44 @@
+! { dg-do compile }
+! { dg-options "-fopenmp" }
+module m
+ implicit none
+ integer :: x = 6
+end module m
+
+program main
+ use m
+ implicit none
+ integer v
+ !$omp atomic
+ x = x * 7 + 6 ! { dg-error "assignment must be var = var op expr or var = expr op var" }
+ !$omp atomic
+ x = ieor (x * 7, 6) ! { dg-error "intrinsic arguments except one must not reference 'x'" }
+ !$omp atomic update
+ x = x - 8 + 6 ! { dg-error "var = var op expr not mathematically equivalent to var = var op \\(expr\\)" }
+ !$omp atomic
+ x = ior (ieor (x, 7), 2) ! { dg-error "intrinsic arguments except one must not reference 'x'" }
+ !$omp atomic
+ x = x / 7 * 2 ! { dg-error "var = var op expr not mathematically equivalent to var = var op \\(expr\\)" }
+ !$omp atomic
+ x = x / 7 / 2 ! { dg-error "var = var op expr not mathematically equivalent to var = var op \\(expr\\)" }
+ !$omp atomic capture
+ v = x; x = x * 7 + 6 ! { dg-error "assignment must be var = var op expr or var = expr op var" }
+ !$omp atomic capture
+ v = x; x = ieor(x * 7, 6) ! { dg-error "intrinsic arguments except one must not reference 'x'" }
+ !$omp atomic capture
+ v = x; x = x - 8 + 6 ! { dg-error "var = var op expr not mathematically equivalent to var = var op \\(expr\\)" }
+ !$omp atomic capture
+ v = x; x = ior (ieor(x, 7), 2) ! { dg-error "intrinsic arguments except one must not reference 'x'" }
+ !$omp atomic capture
+ v = x; x = x / 7 * 2 ! { dg-error "var = var op expr not mathematically equivalent to var = var op \\(expr\\)" }
+ !$omp atomic capture
+ v = x; x = x / 7 / 2 ! { dg-error "var = var op expr not mathematically equivalent to var = var op \\(expr\\)" }
+ !$omp atomic capture
+ x = x * 7 + 6; v = x ! { dg-error "assignment must be var = var op expr or var = expr op var" }
+ !$omp atomic capture
+ x = ieor(x * 7, 6); v = x ! { dg-error "intrinsic arguments except one must not reference 'x'" }
+ !$omp atomic capture
+ x = x - 8 + 6; v = x ! { dg-error "var = var op expr not mathematically equivalent to var = var op \\(expr\\)" }
+ !$omp atomic capture
+ x = ior(ieor(x, 7), 2); v = x ! { dg-error "intrinsic arguments except one must not reference 'x'" }
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic-16.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic-16.f90
new file mode 100644
index 0000000..7660858
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic-16.f90
@@ -0,0 +1,36 @@
+! { dg-do compile }
+! { dg-options "-fopenmp" }
+
+module m
+ implicit none
+ integer :: x = 6
+contains
+
+subroutine foo ()
+ integer v
+ !$omp atomic seq_cst read
+ v = x
+ !$omp atomic seq_cst, read
+ v = x
+ !$omp atomic seq_cst write
+ x = v
+ !$omp atomic seq_cst ,write
+ x = v
+ !$omp atomic seq_cst update
+ x = x + v;
+ !$omp atomic seq_cst , update
+ x = v + x;
+ !$omp atomic seq_cst capture
+ v = x; x = x + 2;
+ !$omp atomic seq_cst, capture
+ v = x; x = 2 + x;
+ !$omp atomic read , seq_cst
+ v = x
+ !$omp atomic write ,seq_cst
+ x = v
+ !$omp atomic update, seq_cst
+ x = x + v
+ !$omp atomic capture, seq_cst
+ x = x + 2; v = x
+end
+end module m
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic-17.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic-17.f90
new file mode 100644
index 0000000..d6864f5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic-17.f90
@@ -0,0 +1,41 @@
+module m
+implicit none
+integer i, v
+real f
+contains
+
+subroutine foo ()
+ !$omp atomic release, hint (0), update
+ i = i + 1
+ !$omp atomic hint(0)seq_cst
+ i = i + 1
+ !$omp atomic relaxed,update,hint (0)
+ i = i + 1
+ !$omp atomic release
+ i = i + 1
+ !$omp atomic relaxed
+ i = i + 1
+ !$omp atomic acq_rel capture
+ i = i + 1; v = i
+ !$omp atomic capture,acq_rel , hint (1)
+ i = i + 1; v = i
+ !$omp atomic hint(0),acquire capture
+ i = i + 1; v = i
+ !$omp atomic read acquire
+ v = i
+ !$omp atomic acq_rel read
+ v = i
+ !$omp atomic release,write
+ i = v
+ !$omp atomic write,acq_rel
+ i = v
+ !$omp atomic hint(1),update,release
+ f = f + 2.0
+ !$omp atomic update ,acquire
+ i = i + 1
+ !$omp atomic acq_rel update
+ i = i + 1
+ !$omp atomic acq_rel,hint(0)
+ i = i + 1
+end
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic-18.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic-18.f90
new file mode 100644
index 0000000..9bc6f63
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic-18.f90
@@ -0,0 +1,27 @@
+module m
+implicit none
+integer i, v
+real f
+contains
+subroutine foo (j)
+integer, value :: j
+ !$omp atomic update,update ! { dg-error "Duplicated atomic clause: unexpected update clause" }
+ i = i + 1
+ !$omp atomic seq_cst release ! { dg-error "Duplicated memory-order clause: unexpected release clause" }
+ i = i + 1
+ !$omp atomic read,release ! { dg-error "ATOMIC READ at .1. incompatible with RELEASE clause" }
+ v = i
+ !$omp atomic acquire , write ! { dg-error "ATOMIC WRITE at .1. incompatible with ACQUIRE clause" }
+ i = v
+ !$omp atomic capture hint (0) capture ! { dg-error "Duplicated 'capture' clause" }
+ v = i = i + 1
+ !$omp atomic hint(j + 2) ! { dg-error "Value of HINT clause at .1. shall be a valid constant hint expression" }
+ i = i + 1
+ !$omp atomic hint(f)
+ ! { dg-error "HINT clause at .1. requires a scalar INTEGER expression" "" { target *-*-* } .-1 }
+ ! { dg-error "Value of HINT clause at .1. shall be a valid constant hint expression" "" { target *-*-* } .-2 }
+ i = i + 1
+ !$omp atomic foobar ! { dg-error "Failed to match clause" }
+ i = i + 1
+end
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic-19.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic-19.f90
new file mode 100644
index 0000000..ade4c94
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic-19.f90
@@ -0,0 +1,39 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+! { dg-final { scan-tree-dump-times "omp atomic release" 1 "original" } }
+! { dg-final { scan-tree-dump-times "omp atomic relaxed" 3 "original" } }
+! { dg-final { scan-tree-dump-times "omp atomic read relaxed" 1 "original" } }
+! { dg-final { scan-tree-dump-times "omp atomic capture relaxed" 1 "original" } }
+
+module mod
+ implicit none
+ integer i, j, k, l, m, n
+
+contains
+
+subroutine foo ()
+ !$omp atomic release
+ i = i + 1;
+end
+end
+
+module m2
+use mod
+implicit none
+!$omp requires atomic_default_mem_order (relaxed)
+
+contains
+subroutine bar ()
+ integer v;
+ !$omp atomic
+ j = j + 1
+ !$omp atomic update
+ k = k + 1
+ !$omp atomic read
+ v = l
+ !$omp atomic write
+ m = v
+ !$omp atomic capture
+ n = n + 1; v = n
+end
+end module m2
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic-2.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic-2.f90
index 1de418d..b6c1b6a 100644
--- a/gcc/testsuite/gfortran.dg/gomp/atomic-2.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic-2.f90
@@ -3,13 +3,13 @@
subroutine bar
integer :: i, v
real :: f
- !$omp atomic update acq_rel hint("abc") ! { dg-error "OMP ATOMIC UPDATE at .1. incompatible with ACQ_REL or ACQUIRE clauses" }
+ !$omp atomic update acq_rel hint("abc")
! { dg-error "HINT clause at .1. requires a scalar INTEGER expression" "" { target *-*-* } .-1 }
! { dg-error "Value of HINT clause at .1. shall be a valid constant hint expression" "" { target *-*-* } .-2 }
i = i + 1
!$omp end atomic
- !$omp atomic acq_rel ! { dg-error "OMP ATOMIC UPDATE at .1. incompatible with ACQ_REL or ACQUIRE clauses" }
+ !$omp atomic acq_rel
i = i + 1
!$omp end atomic
@@ -18,7 +18,7 @@ subroutine bar
v = i
!$omp end atomic
- !$omp atomic acq_rel , hint (1), update ! { dg-error "OMP ATOMIC UPDATE at .1. incompatible with ACQ_REL or ACQUIRE clauses" }
+ !$omp atomic acq_rel , hint (1), update
i = i + 1
!$omp end atomic
@@ -27,44 +27,10 @@ subroutine bar
v = i
!$omp end atomic
- !$omp atomic write capture ! { dg-error "multiple atomic clauses" }
+ !$omp atomic write capture ! { dg-error "with CAPTURE clause is incompatible with READ or WRITE" }
i = 2
v = i
!$omp end atomic
!$omp atomic foobar ! { dg-error "Failed to match clause" }
end
-
-! moved here from atomic.f90
-subroutine openmp51_foo
- integer :: x, v
- !$omp atomic update seq_cst capture ! { dg-error "multiple atomic clauses" }
- x = x + 2
- v = x
- !$omp end atomic
- !$omp atomic seq_cst, capture, update ! { dg-error "multiple atomic clauses" }
- x = x + 2
- v = x
- !$omp end atomic
- !$omp atomic capture, seq_cst ,update ! { dg-error "multiple atomic clauses" }
- x = x + 2
- v = x
- !$omp end atomic
-end
-
-subroutine openmp51_bar
- integer :: i, v
- real :: f
- !$omp atomic relaxed capture update ! { dg-error "multiple atomic clauses" }
- i = i + 1
- v = i
- !$omp end atomic
- !$omp atomic update capture,release , hint (1) ! { dg-error "multiple atomic clauses" }
- i = i + 1
- v = i
- !$omp end atomic
- !$omp atomic hint(0),update relaxed capture ! { dg-error "multiple atomic clauses" }
- i = i + 1
- v = i
- !$omp end atomic
-end
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic-20.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic-20.f90
new file mode 100644
index 0000000..29193e1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic-20.f90
@@ -0,0 +1,39 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+! { dg-final { scan-tree-dump-times "omp atomic release" 1 "original" } }
+! { dg-final { scan-tree-dump-times "omp atomic seq_cst" 3 "original" } }
+! { dg-final { scan-tree-dump-times "omp atomic read seq_cst" 1 "original" } }
+! { dg-final { scan-tree-dump-times "omp atomic capture seq_cst" 1 "original" } }
+
+module mod
+implicit none
+integer i, j, k, l, m, n
+
+contains
+subroutine foo ()
+ !$omp atomic release
+ i = i + 1
+end
+end module
+
+module m2
+use mod
+implicit none
+!$omp requires atomic_default_mem_order (seq_cst)
+
+contains
+
+subroutine bar ()
+ integer v
+ !$omp atomic
+ j = j + 1
+ !$omp atomic update
+ k = k + 1
+ !$omp atomic read
+ v = l
+ !$omp atomic write
+ m = v
+ !$omp atomic capture
+ n = n + 1; v = n
+end
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic-22.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic-22.f90
new file mode 100644
index 0000000..584c0d3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic-22.f90
@@ -0,0 +1,24 @@
+module mod
+integer i, j
+
+contains
+subroutine foo ()
+ integer v
+ !$omp atomic release
+ i = i + 1
+ !$omp atomic read
+ v = j
+end
+end module
+
+module m2
+!$omp requires atomic_default_mem_order (acq_rel) ! OK
+contains
+subroutine bar
+ !$omp atomic release
+ i = i + 1
+!$omp requires atomic_default_mem_order (acq_rel) ! { dg-error "must appear in the specification part of a program unit" }
+ !$omp atomic read
+ v = j
+end subroutine
+end module m2
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic-24.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic-24.f90
new file mode 100644
index 0000000..235826e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic-24.f90
@@ -0,0 +1,13 @@
+! PR c/101297
+
+module m
+implicit none
+integer :: i
+contains
+subroutine foo ()
+ !$omp atomic update, ! { dg-error "Clause expected at .1. after trailing comma" }
+ i = i + 1
+ !$omp atomic update,, ! { dg-error "Failed to match clause" }
+ i = i + 1
+end
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic-25.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic-25.f90
new file mode 100644
index 0000000..598ff4e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic-25.f90
@@ -0,0 +1,53 @@
+! { dg-do compile }
+
+module m
+use iso_fortran_env
+implicit none
+integer, parameter :: mrk = maxval(real_kinds)
+integer x, r, z
+real(kind(4.0d0)) d, v
+real(mrk) ld
+
+contains
+subroutine foo (y, e, f)
+ integer :: y
+ real(kind(4.0d0)) :: e
+ real(mrk) :: f
+ !$omp atomic update seq_cst fail(acquire)
+ x = min(x, y)
+ !$omp atomic relaxed fail(relaxed)
+ d = max (e, d)
+ !$omp atomic fail(SEQ_CST)
+ d = min (d, f)
+ !$omp atomic seq_cst compare fail(relaxed) ! { dg-error "Sorry, COMPARE clause in ATOMIC at .1. is not yet supported" }
+ if (x == 7) x = 24
+ !$omp atomic compare ! { dg-error "Sorry, COMPARE clause in ATOMIC at .1. is not yet supported" }
+ if (x == 7) x = 24
+ !$omp atomic compare ! { dg-error "Sorry, COMPARE clause in ATOMIC at .1. is not yet supported" }
+ if (x == 123) x = 256
+ !$omp atomic compare ! { dg-error "Sorry, COMPARE clause in ATOMIC at .1. is not yet supported" }
+ if (ld == f) ld = f + 5.0_mrk
+ !$omp atomic compare ! { dg-error "Sorry, COMPARE clause in ATOMIC at .1. is not yet supported" }
+ if (x == 9) then
+ x = 5
+ endif
+ !$omp atomic compare update capture seq_cst fail(acquire) ! { dg-error "Sorry, COMPARE clause in ATOMIC at .1. is not yet supported" }
+ if (x == 42) then
+ x = f
+ else
+ v = x
+ endif
+ !$omp atomic capture compare weak ! { dg-error "Sorry, COMPARE clause in ATOMIC at .1. is not yet supported" }
+ if (x == 42) then
+ x = f
+ else
+ v = x
+ endif
+ !$omp atomic capture compare fail(seq_cst) ! { dg-error "Sorry, COMPARE clause in ATOMIC at .1. is not yet supported" }
+ if (d == 8.0) then
+ d = 16.0
+ else
+ v = d
+ end if
+end
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic-26.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic-26.f90
new file mode 100644
index 0000000..5f21d3b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic-26.f90
@@ -0,0 +1,75 @@
+! { dg-do compile }
+
+module m
+implicit none
+integer x
+real d
+
+contains
+
+real function foo (y, e, f)
+ integer :: y
+ real v, e
+ real(8) :: f
+ !$omp atomic compare compare ! { dg-error "Duplicated 'compare' clause" }
+ if (x == y) x = d
+ !$omp atomic compare fail(seq_cst) fail(seq_cst) ! { dg-error "Duplicated 'fail' clause" }
+ if (x == y) x = d
+ !$omp atomic compare,fail(seq_cst),fail(relaxed) ! { dg-error "Duplicated 'fail' clause" }
+ if (x == y) x = d
+ !$omp atomic compare weak weak ! { dg-error "Duplicated 'weak' clause" }
+ if (x == y) x = d
+ !$omp atomic read capture ! { dg-error "CAPTURE clause is incompatible with READ or WRITE" }
+ v = d
+ !$omp atomic capture, write ! { dg-error "CAPTURE clause is incompatible with READ or WRITE" }
+ d = v; v = v + 1 ! { dg-error "Unexpected ..OMP ATOMIC statement" "" { target *-*-* } .-1 }
+ foo = v
+end
+
+real function bar (y, e, f)
+ integer :: y
+ real v, e
+ real(8) :: f
+ !$omp atomic read compare ! { dg-error "COMPARE clause is incompatible with READ or WRITE" }
+ if (x == y) x = d
+ !$omp atomic compare, write ! { dg-error "COMPARE clause is incompatible with READ or WRITE" }
+ if (x == y) x = d
+ !$omp atomic read fail(seq_cst) ! { dg-error "FAIL clause is incompatible with READ or WRITE" }
+ v = d
+ !$omp atomic fail(relaxed), write ! { dg-error "FAIL clause is incompatible with READ or WRITE" }
+ d = v
+ !$omp atomic fail(relaxed) update ! { dg-error "FAIL clause requiries either the COMPARE clause or using the intrinsic MIN/MAX procedure" }
+ d = d + 3.0
+ !$omp atomic fail(relaxed) ! { dg-error "FAIL clause requiries either the COMPARE clause or using the intrinsic MIN/MAX procedure" }
+ d = d + 3.0
+ !$omp atomic capture fail(relaxed) ! { dg-error "FAIL clause requiries either the COMPARE clause or using the intrinsic MIN/MAX procedure" }
+ v = d; d = d + 3.0
+ !$omp atomic read weak ! { dg-error "WEAK clause requires COMPARE clause" }
+ v = d
+ !$omp atomic weak, write ! { dg-error "WEAK clause requires COMPARE clause" }
+ d = v
+ !$omp atomic weak update ! { dg-error "WEAK clause requires COMPARE clause" }
+ d = d + 3.0
+ !$omp atomic weak ! { dg-error "WEAK clause requires COMPARE clause" }
+ d = d + 3.0
+ !$omp atomic capture weak ! { dg-error "WEAK clause requires COMPARE clause" }
+ d = d + 3.0; v = d
+ !$omp atomic capture
+ d = d + 3.0; v = x ! { dg-error "capture statement reads from different variable than update statement writes" }
+ !$omp atomic compare fail ! { dg-error "Expected '\\\(' after 'fail'" }
+ if (x == y) x = d
+ !$omp atomic compare fail( ! { dg-error "Expected SEQ_CST, ACQUIRE or RELAXED" }
+ if (x == y) x = d ! { dg-error "Sorry, COMPARE clause in ATOMIC at .1. is not yet supported" "" { target *-*-* } .-1 }
+ !$omp atomic compare fail() ! { dg-error "Expected SEQ_CST, ACQUIRE or RELAXED" }
+ if (x == y) x = d
+ !$omp atomic compare fail(foobar) ! { dg-error "Expected SEQ_CST, ACQUIRE or RELAXED" }
+ if (x == y) x = d
+ !$omp atomic compare fail(acq_rel) ! { dg-error "Expected SEQ_CST, ACQUIRE or RELAXED" }
+ if (x == y) x = d
+ !$omp atomic compare fail(release) ! { dg-error "Expected SEQ_CST, ACQUIRE or RELAXED" }
+ if (x == y) x = d
+ !$omp atomic compare fail(seq_cst ! { dg-error "Failed to match clause" }
+ if (x == y) x = d
+ bar = v
+end
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic.f90
index b4caf03..ca12796 100644
--- a/gcc/testsuite/gfortran.dg/gomp/atomic.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic.f90
@@ -3,14 +3,13 @@
! { dg-final { scan-tree-dump-times "#pragma omp atomic relaxed" 4 "original" } }
! { dg-final { scan-tree-dump-times "#pragma omp atomic release" 4 "original" } }
-! { dg-final { scan-tree-dump-times "v = #pragma omp atomic capture relaxed" 2 "original" } }
-! { dg-final { scan-tree-dump-times "v = #pragma omp atomic capture release" 1 "original" } }
+! { dg-final { scan-tree-dump-times "v = #pragma omp atomic capture relaxed" 4 "original" } }
+! { dg-final { scan-tree-dump-times "v = #pragma omp atomic capture release" 2 "original" } }
! { dg-final { scan-tree-dump-times "v = #pragma omp atomic read acquire" 1 "original" } }
! { dg-final { scan-tree-dump-times "#pragma omp atomic seq_cst" 7 "original" } }
! { dg-final { scan-tree-dump-times "v = #pragma omp atomic read seq_cst" 3 "original" } }
-! { dg-final { scan-tree-dump-times "v = #pragma omp atomic capture seq_cst" 3 "original" } }
-
+! { dg-final { scan-tree-dump-times "v = #pragma omp atomic capture seq_cst" 6 "original" } }
subroutine foo ()
integer :: x, v
@@ -85,3 +84,36 @@ subroutine bar
!$omp atomic hint(1),update,release
f = f + 2.0
end
+
+subroutine openmp51_foo
+ integer :: x, v
+ !$omp atomic update seq_cst capture
+ x = x + 2
+ v = x
+ !$omp end atomic
+ !$omp atomic seq_cst, capture, update
+ x = x + 2
+ v = x
+ !$omp end atomic
+ !$omp atomic capture, seq_cst ,update
+ x = x + 2
+ v = x
+ !$omp end atomic
+end
+
+subroutine openmp51_bar
+ integer :: i, v
+ real :: f
+ !$omp atomic relaxed capture update
+ i = i + 1
+ v = i
+ !$omp end atomic
+ !$omp atomic update capture,release , hint (1)
+ i = i + 1
+ v = i
+ !$omp end atomic
+ !$omp atomic hint(0),update relaxed capture
+ i = i + 1
+ v = i
+ !$omp end atomic
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/defaultmap-4.f90 b/gcc/testsuite/gfortran.dg/gomp/defaultmap-4.f90
index 89bbe87..7b182b5 100644
--- a/gcc/testsuite/gfortran.dg/gomp/defaultmap-4.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/defaultmap-4.f90
@@ -56,16 +56,18 @@ end
! { dg-final { scan-tree-dump-times "map\\(alloc:\\*aii \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(alloc:aii \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(alloc:arr \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) aarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) dtaarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) dtparr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) parr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) str1aarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) str1parr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) str5aarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) str5parr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) strxaarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) strxparr\\.data \\\[len:" 1 "gimple" } }
+
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxparr\\\] \\*\\) strxparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxaarr\\\] \\* restrict\\) strxaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\*\\) str5parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\* restrict\\) str5aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\*\\) str1parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\* restrict\\) str1aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(struct t\\\[0:\\\] \\*\\) dtparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(struct t\\\[0:\\\] \\* restrict\\) dtaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) aarr\\.data \\\[len:" 1 "gimple" } }
+
! { dg-final { scan-tree-dump-times "map\\(alloc:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\* restrict\\) str1aarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(alloc:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\* restrict\\) str5aarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(alloc:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxaarr\\\] \\* restrict\\) strxaarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
@@ -103,21 +105,23 @@ end
! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(struct t\\\[0:\\\] \\*\\) dtparr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(to:aarr \\\[pointer set, len:" 2 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(to:arr \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) dtparr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) parr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) str1parr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) str5parr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) strxparr\\.data \\\[len:" 1 "gimple" } }
+
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxparr\\\] \\*\\) strxparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\*\\) str5parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\*\\) str1parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(struct t\\\[0:\\\] \\*\\) dtparr\\.data \\\[len:" 1 "gimple" } }
+
! { dg-final { scan-tree-dump-times "map\\(to:dtaarr \\\[pointer set, len:" 2 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(to:dtarr \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(to:dt \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(to:dtparr \\\[pointer set, len:" 2 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*aii \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) aarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) dtaarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str1aarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str5aarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) strxaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxaarr\\\] \\* restrict\\) strxaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\* restrict\\) str5aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\* restrict\\) str1aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(struct t\\\[0:\\\] \\* restrict\\) dtaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) aarr\\.data \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*dta \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*str1a \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*str5a \\\[len:" 1 "gimple" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/defaultmap-5.f90 b/gcc/testsuite/gfortran.dg/gomp/defaultmap-5.f90
index d6b32dc..1391274 100644
--- a/gcc/testsuite/gfortran.dg/gomp/defaultmap-5.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/defaultmap-5.f90
@@ -86,16 +86,16 @@ end
! { dg-final { scan-tree-dump-times "map\\(to:aarr \\\[pointer set, len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(to:\\*aii \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(to:arr \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) aarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) dtaarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) dtparr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) parr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) str1aarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) str1parr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) str5aarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) str5parr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) strxaarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) strxparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxparr\\\] \\*\\) strxparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxaarr\\\] \\* restrict\\) strxaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\*\\) str5parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\* restrict\\) str5aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\*\\) str1parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\* restrict\\) str1aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(struct t\\\[0:\\\] \\*\\) dtparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(struct t\\\[0:\\\] \\* restrict\\) dtaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) aarr\\.data \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(to:dtaarr \\\[pointer set, len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(to:\\*dta \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(to:dtarr \\\[len:" 1 "gimple" } }
@@ -103,11 +103,11 @@ end
! { dg-final { scan-tree-dump-times "map\\(to:dtparr \\\[pointer set, len:" 2 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(to:\\*dtp \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(tofrom:arr \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) dtparr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) parr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str1parr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str5parr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) strxparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxparr\\\] \\*\\) strxparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\*\\) str5parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\*\\) str1parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(struct t\\\[0:\\\] \\*\\) dtparr\\.data \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(tofrom:dtarr \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(tofrom:dt \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*dtp \\\[len:" 1 "gimple" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/defaultmap-6.f90 b/gcc/testsuite/gfortran.dg/gomp/defaultmap-6.f90
index fabf771..9a81d0f 100644
--- a/gcc/testsuite/gfortran.dg/gomp/defaultmap-6.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/defaultmap-6.f90
@@ -65,16 +65,16 @@ end
! { dg-final { scan-tree-dump-times "map\\(to:dtparr \\\[pointer set, len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*aii \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(tofrom:arr \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) aarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) dtaarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) dtparr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) parr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str1aarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str1parr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str5aarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str5parr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) strxaarr\\.data \\\[len:" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) strxparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxparr\\\] \\*\\) strxparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxaarr\\\] \\* restrict\\) strxaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\*\\) str5parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\* restrict\\) str5aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\*\\) str1parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\* restrict\\) str1aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(struct t\\\[0:\\\] \\*\\) dtparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(struct t\\\[0:\\\] \\* restrict\\) dtaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) aarr\\.data \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*dta \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(tofrom:dtarr \\\[len:" 1 "gimple" } }
! { dg-final { scan-tree-dump-times "map\\(tofrom:dt \\\[len:" 1 "gimple" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/map-3.f90 b/gcc/testsuite/gfortran.dg/gomp/map-3.f90
index bdd2890..2f0a792 100644
--- a/gcc/testsuite/gfortran.dg/gomp/map-3.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/map-3.f90
@@ -34,5 +34,5 @@ end
! { dg-final { scan-tree-dump-times "#pragma omp target data use_device_addr\\(x\\)" 1 "original" } }
! { dg-final { scan-tree-dump-times "#pragma omp target data use_device_addr\\(x2\\)" 1 "original" } }
! { dg-final { scan-tree-dump-times "#pragma omp target exit data map\\(release:x\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp target data map\\(tofrom:\\*\\(c_char \\*\\) y.data \\\[len: .*\\) map\\(to:y \\\[pointer set, len: .*\\) map\\(alloc:.*y.data \\\[pointer assign, bias: 0\\\]\\) use_device_addr\\(y\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp target data map\\(tofrom:\\*\\(c_char \\*\\) z.data \\\[len: .*\\) map\\(to:z \\\[pointer set, len: .*\\) map\\(alloc:.*z.data \\\[pointer assign, bias: 0\\\]\\) use_device_addr\\(z\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target data map\\(tofrom:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) y.data \\\[len: .*\\) map\\(to:y \\\[pointer set, len: .*\\) map\\(alloc:.*y.data \\\[pointer assign, bias: 0\\\]\\) use_device_addr\\(y\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target data map\\(tofrom:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) z.data \\\[len: .*\\) map\\(to:z \\\[pointer set, len: .*\\) map\\(alloc:.*z.data \\\[pointer assign, bias: 0\\\]\\) use_device_addr\\(z\\)" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr78260-2.f90 b/gcc/testsuite/gfortran.dg/gomp/pr78260-2.f90
index c58ad93..f5d8885 100644
--- a/gcc/testsuite/gfortran.dg/gomp/pr78260-2.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr78260-2.f90
@@ -48,10 +48,10 @@ contains
end subroutine sub
end module m
-! { dg-final { scan-tree-dump-times "#pragma omp target data map\\(tofrom:\\*\\(c_char \\*\\) arr.data \\\[len: D.\[0-9\]+ \\* 4\\\]\\) map\\(to:arr \\\[pointer set, len: ..\\\]\\) map\\(alloc:\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) arr.data \\\[pointer assign, bias: 0\\\]\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp target update to\\(\\*\\(c_char \\*\\) arr.data \\\[len: D.\[0-9\]+ \\* 4\\\]\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp target data map\\(tofrom:\\*\\(c_char \\*\\) __result->data \\\[len: D.\[0-9\]+ \\* 4\\\]\\) map\\(to:\\*__result \\\[pointer set, len: ..\\\]\\) map\\(alloc:\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) __result->data \\\[pointer assign, bias: 0\\\]\\) map\\(alloc:__result \\\[pointer assign, bias: 0\\\]\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp target update to\\(\\*\\(c_char \\*\\) __result->data \\\[len: D.\[0-9\]+ \\* 4\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target data map\\(tofrom:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) arr.data \\\[len: D.\[0-9\]+ \\* 4\\\]\\) map\\(to:arr \\\[pointer set, len: ..\\\]\\) map\\(alloc:\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) arr.data \\\[pointer assign, bias: 0\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target update to\\(\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) arr.data \\\[len: D.\[0-9\]+ \\* 4\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target data map\\(tofrom:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) __result->data \\\[len: D.\[0-9\]+ \\* 4\\\]\\) map\\(to:\\*__result \\\[pointer set, len: ..\\\]\\) map\\(alloc:\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) __result->data \\\[pointer assign, bias: 0\\\]\\) map\\(alloc:__result \\\[pointer assign, bias: 0\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target update to\\(\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) __result->data \\\[len: D.\[0-9\]+ \\* 4\\\]\\)" 1 "original" } }
! { dg-final { scan-tree-dump-times "#pragma omp target data map\\(tofrom:\\*__result.0\\) map\\(alloc:__result.0 \\\[pointer assign, bias: 0\\\]\\)" 2 "original" } }
! { dg-final { scan-tree-dump-times "#pragma omp target update to\\(\\*__result.0\\)" 2 "original" } }
! { dg-final { scan-tree-dump-times "#pragma omp target data map\\(tofrom:__result_f1\\)" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr78260-3.f90 b/gcc/testsuite/gfortran.dg/gomp/pr78260-3.f90
index 4ca3e36..64851b3 100644
--- a/gcc/testsuite/gfortran.dg/gomp/pr78260-3.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr78260-3.f90
@@ -70,5 +70,5 @@ end subroutine sub
! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(inout:__result_f1\\)" 2 "original" } }
! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(inout:\\*__result.0\\)" 4 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(inout:\\*\\(c_char \\*\\) __result->data\\)" 2 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(inout:\\*\\(c_char \\*\\) arr.data\\)" 2 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(inout:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) __result->data\\)" 2 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(inout:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) arr.data\\)" 2 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/pr103505.f90 b/gcc/testsuite/gfortran.dg/pr103505.f90
new file mode 100644
index 0000000..522e53e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr103505.f90
@@ -0,0 +1,9 @@
+! { dg-do compile }
+! PR fortran/103505 - this used to ICE in compare_bound_mpz_t
+! Testcase by G.Steinmetz
+
+program p
+ integer, parameter :: a((2.)) = [4,8] ! { dg-error "scalar INTEGER" }
+ integer, parameter :: z(1:(2.)) = [4,8] ! { dg-error "scalar INTEGER" }
+ print *, a(1:1) ! { dg-error "Syntax error" }
+end
diff --git a/gcc/testsuite/gfortran.dg/pr103588.f90 b/gcc/testsuite/gfortran.dg/pr103588.f90
new file mode 100644
index 0000000..198e176
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr103588.f90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+! PR fortran/103588 - ICE: Simplification error in gfc_ref_dimen_size
+! Contributed by G.Steinmetz
+
+program p
+ integer, parameter :: a(:) = [1,2] ! { dg-error "cannot be automatic or of deferred shape" }
+ integer :: b(2) = a(::a(1)) ! { dg-error "Invalid" }
+end
diff --git a/gcc/testsuite/gfortran.dg/pr103607.f90 b/gcc/testsuite/gfortran.dg/pr103607.f90
new file mode 100644
index 0000000..a6a2c4f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr103607.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! PR fortran/103607 - ICE in do_subscript, at fortran/frontend-passes.c:2927
+! Contributed by G.Steinmetz
+
+program p
+ integer :: i, x(abs(2.)) ! { dg-error "must be of INTEGER type" }
+ do i = 1, 2
+ x(i) = 0
+ end do
+end
+
+! { dg-prune-output "must have constant shape" }
diff --git a/gcc/testsuite/gfortran.dg/pr103609.f90 b/gcc/testsuite/gfortran.dg/pr103609.f90
new file mode 100644
index 0000000..57f6a3b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr103609.f90
@@ -0,0 +1,15 @@
+! { dg-do compile }
+! PR fortran/103609 - ICE in gfc_sym_get_dummy_args
+! Contributed by G.Steinmetz
+
+program p
+ implicit none
+ integer :: i
+ do i = 1, 2
+ call s
+ end do
+contains
+ subroutine s
+ call sub(x) ! { dg-error "has no IMPLICIT type" }
+ end
+end
diff --git a/gcc/testsuite/gfortran.dg/select_9.f90 b/gcc/testsuite/gfortran.dg/select_9.f90
new file mode 100644
index 0000000..c580e81
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/select_9.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+! PR fortran/103591 - ICE in gfc_compare_string
+! Contributed by G.Steinmetz
+
+program p
+ integer :: n
+ select case (n)
+ case ('1':2.) ! { dg-error "cannot be REAL" }
+ end select
+end
diff --git a/gcc/testsuite/gfortran.dg/shape_11.f90 b/gcc/testsuite/gfortran.dg/shape_11.f90
new file mode 100644
index 0000000..127d221
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/shape_11.f90
@@ -0,0 +1,16 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original" }
+! PR fortran/103610 - ICE while simplifying SHAPE
+! Contributed by G.Steinmetz
+
+program p
+ integer, parameter :: a(-1) = 1
+ integer, parameter :: b(1) = maskl(shape(a))
+ integer, parameter :: c(1) = shape(a)
+ integer, parameter :: d(1) = maskr(shape(a))
+ if (b(1) /= 0) stop 1
+ if (c(1) /= 0) stop 2
+ if (d(1) /= 0) stop 3
+end
+
+! { dg-final { scan-tree-dump-not "_gfortran_stop_numeric" "original" } }
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index 7edd070..78a6c36 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -1191,8 +1191,18 @@ proc process-message { msgproc msgprefix dgargs } {
upvar dg-messages dg-messages
if { [llength $dgargs] == 5 } {
- set num [get-absolute-line [lindex $dgargs 0] [lindex $dgargs 4]]
- set dgargs [lreplace $dgargs 4 4 $num]
+ set useline [lindex $dgargs 0]
+
+ # Resolve absolute line number.
+ set line [get-absolute-line $useline [lindex $dgargs 4]]
+ set dgargs [lreplace $dgargs 4 4 $line]
+
+ if { $line != $useline } {
+ # Make sure that we get unique test names if different USELINEs
+ # refer to the same LINE.
+ set comment "[lindex $dgargs 2] at line $useline"
+ set dgargs [lreplace $dgargs 2 2 $comment]
+ }
}
# Process the dg- directive, including adding the regular expression
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index caa8ab9..039125c 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -6628,6 +6628,12 @@ proc check_effective_target_powerpc_elfv2 { } {
}
}
+# Return 1 if this is a PowerPC target supporting -mrop-protect
+
+proc check_effective_target_rop_ok { } {
+ return [check_effective_target_power10_ok] && [check_effective_target_powerpc_elfv2]
+}
+
# The VxWorks SPARC simulator accepts only EM_SPARC executables and
# chokes on EM_SPARC32PLUS or EM_SPARCV9 executables. Return 1 if the
# test environment appears to run executables on such a simulator.
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 8ab119d..91ae523 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1961,7 +1961,7 @@ struct GTY(()) tree_function_decl {
struct GTY(()) tree_translation_unit_decl {
struct tree_decl_common common;
/* Source language of this translation unit. Used for DWARF output. */
- const char * GTY((skip(""))) language;
+ const char *language;
/* TODO: Non-optimization used to build this translation unit. */
/* TODO: Root of a partial DWARF tree for global types and decls. */
};
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index fcc0796..a81ba40 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -858,6 +858,7 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
{
case GOMP_MAP_ALLOC:
case GOMP_MAP_POINTER:
+ case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
pp_string (pp, "alloc");
break;
case GOMP_MAP_IF_PRESENT:
@@ -936,6 +937,9 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
case GOMP_MAP_ATTACH_DETACH:
pp_string (pp, "attach_detach");
break;
+ case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
+ pp_string (pp, "attach_zero_length_array_section");
+ break;
default:
gcc_unreachable ();
}
@@ -954,6 +958,9 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
case GOMP_MAP_ALWAYS_POINTER:
pp_string (pp, " [pointer assign, bias: ");
break;
+ case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
+ pp_string (pp, " [pointer assign, zero-length array section, bias: ");
+ break;
case GOMP_MAP_TO_PSET:
pp_string (pp, " [pointer set, len: ");
break;
@@ -961,6 +968,7 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
case GOMP_MAP_DETACH:
case GOMP_MAP_FORCE_DETACH:
case GOMP_MAP_ATTACH_DETACH:
+ case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
pp_string (pp, " [bias: ");
break;
default:
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 7510940..06954e4 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -1478,7 +1478,7 @@ assert_loop_rolls_lt (tree type, affine_iv *iv0, affine_iv *iv1,
The number of iterations is stored to NITER. */
static bool
-number_of_iterations_until_wrap (class loop *, tree type, affine_iv *iv0,
+number_of_iterations_until_wrap (class loop *loop, tree type, affine_iv *iv0,
affine_iv *iv1, class tree_niter_desc *niter)
{
tree niter_type = unsigned_type_for (type);
@@ -1506,6 +1506,23 @@ number_of_iterations_until_wrap (class loop *, tree type, affine_iv *iv0,
num = fold_build2 (MINUS_EXPR, niter_type, wide_int_to_tree (type, max),
iv1->base);
+
+ /* When base has the form iv + 1, if we know iv >= n, then iv + 1 < n
+ only when iv + 1 overflows, i.e. when iv == TYPE_VALUE_MAX. */
+ if (sgn == UNSIGNED
+ && integer_onep (step)
+ && TREE_CODE (iv1->base) == PLUS_EXPR
+ && integer_onep (TREE_OPERAND (iv1->base, 1)))
+ {
+ tree cond = fold_build2 (GE_EXPR, boolean_type_node,
+ TREE_OPERAND (iv1->base, 0), iv0->base);
+ cond = simplify_using_initial_conditions (loop, cond);
+ if (integer_onep (cond))
+ may_be_zero = fold_build2 (EQ_EXPR, boolean_type_node,
+ TREE_OPERAND (iv1->base, 0),
+ TYPE_MAX_VALUE (type));
+ }
+
high = max;
if (TREE_CODE (iv1->base) == INTEGER_CST)
low = wi::to_wide (iv1->base) - 1;
diff --git a/gcc/tree-ssa-loop-unswitch.c b/gcc/tree-ssa-loop-unswitch.c
index fe4dacc..9fae549 100644
--- a/gcc/tree-ssa-loop-unswitch.c
+++ b/gcc/tree-ssa-loop-unswitch.c
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-iterator.h"
#include "cfghooks.h"
#include "tree-ssa-loop-manip.h"
+#include "tree-vectorizer.h"
/* This file implements the loop unswitching, i.e. transformation of loops like
@@ -273,14 +274,17 @@ tree_unswitch_single_loop (class loop *loop, int num)
bool changed = false;
HOST_WIDE_INT iterations;
+ dump_user_location_t loc = find_loop_location (loop);
+
/* Perform initial tests if unswitch is eligible. */
if (num == 0)
{
/* Do not unswitch in cold regions. */
if (optimize_loop_for_size_p (loop))
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, ";; Not unswitching cold loops\n");
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, loc,
+ "Not unswitching cold loops\n");
return false;
}
@@ -288,8 +292,9 @@ tree_unswitch_single_loop (class loop *loop, int num)
if (tree_num_loop_insns (loop, &eni_size_weights)
> (unsigned) param_max_unswitch_insns)
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, ";; Not unswitching, loop too big\n");
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, loc,
+ "Not unswitching, loop too big\n");
return false;
}
@@ -300,9 +305,10 @@ tree_unswitch_single_loop (class loop *loop, int num)
iterations = likely_max_loop_iterations_int (loop);
if (iterations >= 0 && iterations <= 1)
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, ";; Not unswitching, loop is not expected"
- " to iterate\n");
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, loc,
+ "Not unswitching, loop is not expected"
+ " to iterate\n");
return false;
}
}
@@ -320,10 +326,10 @@ tree_unswitch_single_loop (class loop *loop, int num)
if (i == loop->num_nodes)
{
- if (dump_file
- && num > param_max_unswitch_level
- && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, ";; Not unswitching anymore, hit max level\n");
+ if (dump_enabled_p ()
+ && num > param_max_unswitch_level)
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
+ "Not unswitching anymore, hit max level\n");
if (found == loop->num_nodes)
{
@@ -445,8 +451,10 @@ tree_unswitch_single_loop (class loop *loop, int num)
}
}
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, ";; Unswitching loop\n");
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+ "Unswitching loop on condition: %G\n",
+ last_stmt (bbs[found]));
initialize_original_copy_tables ();
/* Unswitch the loop on this condition. */
@@ -520,9 +528,10 @@ tree_unswitch_outer_loop (class loop *loop)
iterations = likely_max_loop_iterations_int (loop);
if (iterations >= 0 && iterations <= 1)
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, ";; Not unswitching, loop is not expected"
- " to iterate\n");
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, find_loop_location (loop),
+ "Not unswitching, loop is not expected"
+ " to iterate\n");
return false;
}
@@ -623,26 +632,31 @@ find_loop_guard (class loop *loop)
else
return NULL;
+ dump_user_location_t loc = find_loop_location (loop);
+
/* Guard edge must skip inner loop. */
if (!dominated_by_p (CDI_DOMINATORS, loop->inner->header,
guard_edge == fe ? te->dest : fe->dest))
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Guard edge %d --> %d is not around the loop!\n",
- guard_edge->src->index, guard_edge->dest->index);
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
+ "Guard edge %d --> %d is not around the loop!\n",
+ guard_edge->src->index, guard_edge->dest->index);
return NULL;
}
if (guard_edge->dest == loop->latch)
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Guard edge destination is loop latch.\n");
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
+ "Guard edge destination is loop latch.\n");
return NULL;
}
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file,
- "Considering guard %d -> %d in loop %d\n",
- guard_edge->src->index, guard_edge->dest->index, loop->num);
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, loc,
+ "Considering guard %d -> %d in loop %d\n",
+ guard_edge->src->index, guard_edge->dest->index,
+ loop->num);
/* Check if condition operands do not have definitions inside loop since
any bb copying is not performed. */
FOR_EACH_SSA_TREE_OPERAND (use, cond, iter, SSA_OP_USE)
@@ -652,9 +666,9 @@ find_loop_guard (class loop *loop)
if (def_bb
&& flow_bb_inside_loop_p (loop, def_bb))
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " guard operands have definitions"
- " inside loop\n");
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, loc, "guard operands have definitions"
+ " inside loop\n");
return NULL;
}
}
@@ -667,23 +681,26 @@ find_loop_guard (class loop *loop)
continue;
if (bb->flags & BB_IRREDUCIBLE_LOOP)
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Block %d is marked as irreducible in loop\n",
- bb->index);
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
+ "Block %d is marked as irreducible in loop\n",
+ bb->index);
guard_edge = NULL;
goto end;
}
if (!empty_bb_without_guard_p (loop, bb))
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " block %d has side effects\n", bb->index);
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
+ "Block %d has side effects\n", bb->index);
guard_edge = NULL;
goto end;
}
}
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " suitable to hoist\n");
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+ "suitable to hoist\n");
end:
if (body)
free (body);
@@ -822,13 +839,19 @@ hoist_guard (class loop *loop, edge guard)
update_stmt (cond_stmt);
/* Create new loop pre-header. */
e = split_block (pre_header, last_stmt (pre_header));
- if (dump_file && (dump_flags & TDF_DETAILS))
+
+ dump_user_location_t loc = find_loop_location (loop);
+
+ if (dump_enabled_p ())
{
- fprintf (dump_file, " Moving guard %i->%i (prob ",
- guard->src->index, guard->dest->index);
- guard->probability.dump (dump_file);
- fprintf (dump_file, ") to bb %i, new preheader is %i\n",
- e->src->index, e->dest->index);
+ char buffer[64];
+ guard->probability.dump (buffer);
+
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+ "Moving guard %i->%i (prob %s) to bb %i, "
+ "new preheader is %i\n",
+ guard->src->index, guard->dest->index,
+ buffer, e->src->index, e->dest->index);
}
gcc_assert (loop_preheader_edge (loop)->src == e->dest);
@@ -860,11 +883,14 @@ hoist_guard (class loop *loop, edge guard)
fprintf (dump_file, " Capping count; expect profile inconsistency\n");
skip_count = e->count ();
}
- if (dump_file && (dump_flags & TDF_DETAILS))
+ if (dump_enabled_p ())
{
- fprintf (dump_file, " Estimated probability of skipping loop is ");
- new_edge->probability.dump (dump_file);
- fprintf (dump_file, "\n");
+ char buffer[64];
+ new_edge->probability.dump (buffer);
+
+ dump_printf_loc (MSG_NOTE, loc,
+ "Estimated probability of skipping loop is %s\n",
+ buffer);
}
/* Update profile after the transform:
@@ -883,15 +909,15 @@ hoist_guard (class loop *loop, edge guard)
where profile does not change. */
basic_block *body = get_loop_body (loop);
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " Scaling nonguarded BBs in loop:");
for (unsigned int i = 0; i < loop->num_nodes; i++)
{
basic_block bb = body[i];
if (!dominated_by_p (CDI_DOMINATORS, bb, not_guard->dest))
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " %i", bb->index);
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, loc,
+ "Scaling nonguarded BBs in loop: %i\n",
+ bb->index);
if (e->probability.initialized_p ())
scale_bbs_frequencies (&bb, 1, e->probability);
}
@@ -922,8 +948,9 @@ hoist_guard (class loop *loop, edge guard)
}
}
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "\n guard hoisted.\n");
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
+ "Guard hoisted\n");
free (body);
}
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 6d19410..1f2a17f 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -1042,10 +1042,12 @@ substitute_and_fold_engine::substitute_and_fold (basic_block block)
}
-/* Return true if we may propagate ORIG into DEST, false otherwise. */
+/* Return true if we may propagate ORIG into DEST, false otherwise.
+ If DEST_NOT_PHI_ARG_P is true then assume the propagation does
+ not happen into a PHI argument which relaxes some constraints. */
bool
-may_propagate_copy (tree dest, tree orig)
+may_propagate_copy (tree dest, tree orig, bool dest_not_phi_arg_p)
{
tree type_d = TREE_TYPE (dest);
tree type_o = TREE_TYPE (orig);
@@ -1065,8 +1067,10 @@ may_propagate_copy (tree dest, tree orig)
&& SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig))
return false;
/* Similarly if DEST flows in from an abnormal edge then the copy cannot be
- propagated. */
- else if (TREE_CODE (dest) == SSA_NAME
+ propagated. If we know we do not propagate into a PHI argument this
+ does not apply. */
+ else if (!dest_not_phi_arg_p
+ && TREE_CODE (dest) == SSA_NAME
&& SSA_NAME_OCCURS_IN_ABNORMAL_PHI (dest))
return false;
@@ -1100,9 +1104,9 @@ may_propagate_copy_into_stmt (gimple *dest, tree orig)
for the expression, so we delegate to may_propagate_copy. */
if (gimple_assign_single_p (dest))
- return may_propagate_copy (gimple_assign_rhs1 (dest), orig);
+ return may_propagate_copy (gimple_assign_rhs1 (dest), orig, true);
else if (gswitch *dest_swtch = dyn_cast <gswitch *> (dest))
- return may_propagate_copy (gimple_switch_index (dest_swtch), orig);
+ return may_propagate_copy (gimple_switch_index (dest_swtch), orig, true);
/* In other cases, the expression is not materialized, so there
is no destination to pass to may_propagate_copy. On the other
@@ -1140,25 +1144,19 @@ may_propagate_copy_into_asm (tree dest ATTRIBUTE_UNUSED)
}
-/* Common code for propagate_value and replace_exp.
+/* Replace *OP_P with value VAL (assumed to be a constant or another SSA_NAME).
- Replace use operand OP_P with VAL. FOR_PROPAGATION indicates if the
- replacement is done to propagate a value or not. */
+ Use this version when not const/copy propagating values. For example,
+ PRE uses this version when building expressions as they would appear
+ in specific blocks taking into account actions of PHI nodes.
-static void
-replace_exp_1 (use_operand_p op_p, tree val,
- bool for_propagation ATTRIBUTE_UNUSED)
-{
- if (flag_checking)
- {
- tree op = USE_FROM_PTR (op_p);
- gcc_assert (!(for_propagation
- && TREE_CODE (op) == SSA_NAME
- && TREE_CODE (val) == SSA_NAME
- && !may_propagate_copy (op, val)));
- }
+ The statement in which an expression has been replaced should be
+ folded using fold_stmt_inplace. */
- if (TREE_CODE (val) == SSA_NAME)
+void
+replace_exp (use_operand_p op_p, tree val)
+{
+ if (TREE_CODE (val) == SSA_NAME || CONSTANT_CLASS_P (val))
SET_USE (op_p, val);
else
SET_USE (op_p, unshare_expr (val));
@@ -1174,22 +1172,10 @@ replace_exp_1 (use_operand_p op_p, tree val,
void
propagate_value (use_operand_p op_p, tree val)
{
- replace_exp_1 (op_p, val, true);
-}
-
-/* Replace *OP_P with value VAL (assumed to be a constant or another SSA_NAME).
-
- Use this version when not const/copy propagating values. For example,
- PRE uses this version when building expressions as they would appear
- in specific blocks taking into account actions of PHI nodes.
-
- The statement in which an expression has been replaced should be
- folded using fold_stmt_inplace. */
-
-void
-replace_exp (use_operand_p op_p, tree val)
-{
- replace_exp_1 (op_p, val, false);
+ if (flag_checking)
+ gcc_assert (may_propagate_copy (USE_FROM_PTR (op_p), val,
+ !is_a <gphi *> (USE_STMT (op_p))));
+ replace_exp (op_p, val);
}
diff --git a/gcc/tree-ssa-propagate.h b/gcc/tree-ssa-propagate.h
index 5257fbb..87a94ad 100644
--- a/gcc/tree-ssa-propagate.h
+++ b/gcc/tree-ssa-propagate.h
@@ -65,7 +65,7 @@ enum ssa_prop_result {
extern void move_ssa_defining_stmt_for_defs (gimple *, gimple *);
extern bool stmt_makes_single_store (gimple *);
-extern bool may_propagate_copy (tree, tree);
+extern bool may_propagate_copy (tree, tree, bool = false);
extern bool may_propagate_copy_into_stmt (gimple *, tree);
extern bool may_propagate_copy_into_asm (tree);
extern void propagate_value (use_operand_p, tree);
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index d31bf32..16c93d1 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -6607,7 +6607,7 @@ eliminate_dom_walker::eliminate_stmt (basic_block b, gimple_stmt_iterator *gsi)
at the definition are also available at uses. */
sprime = eliminate_avail (gimple_bb (SSA_NAME_DEF_STMT (use)), use);
if (sprime && sprime != use
- && may_propagate_copy (use, sprime)
+ && may_propagate_copy (use, sprime, true)
/* We substitute into debug stmts to avoid excessive
debug temporaries created by removed stmts, but we need
to avoid doing so for inserted sprimes as we never want
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 7bff511..b912c35 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -1121,7 +1121,12 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
|| first_stmt_code == BIT_FIELD_REF
|| first_stmt_code == INDIRECT_REF
|| first_stmt_code == COMPONENT_REF
- || first_stmt_code == MEM_REF)))
+ || first_stmt_code == MEM_REF)
+ && (rhs_code == ARRAY_REF
+ || rhs_code == BIT_FIELD_REF
+ || rhs_code == INDIRECT_REF
+ || rhs_code == COMPONENT_REF
+ || rhs_code == MEM_REF)))
|| first_stmt_load_p != load_p
|| first_stmt_phi_p != phi_p)
{
@@ -2532,7 +2537,8 @@ dot_slp_tree (FILE *f, slp_tree node, hash_set<slp_tree> &visited)
fprintf (f, "\"%p\" -> \"%p\";", (void *)node, (void *)child);
for (slp_tree child : SLP_TREE_CHILDREN (node))
- dot_slp_tree (f, child, visited);
+ if (child)
+ dot_slp_tree (f, child, visited);
}
DEBUG_FUNCTION void
@@ -3413,8 +3419,13 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size)
vinfo = next;
}
STMT_VINFO_DEF_TYPE (first_element) = vect_internal_def;
- /* It can be still vectorized as part of an SLP reduction. */
- loop_vinfo->reductions.safe_push (last);
+ /* It can be still vectorized as part of an SLP reduction.
+ ??? But only if we didn't skip a conversion around the group.
+ In that case we'd have to reverse engineer that conversion
+ stmt following the chain using reduc_idx and from the PHI
+ using reduc_def. */
+ if (STMT_VINFO_DEF_TYPE (last) == vect_reduction_def)
+ loop_vinfo->reductions.safe_push (last);
}
/* Find SLP sequences starting from groups of reductions. */
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 9726450..8c42717 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1795,23 +1795,29 @@ check_load_store_for_partial_vectors (loop_vec_info loop_vinfo, tree vectype,
/* Return the mask input to a masked load or store. VEC_MASK is the vectorized
form of the scalar mask condition and LOOP_MASK, if nonnull, is the mask
that needs to be applied to all loads and stores in a vectorized loop.
- Return VEC_MASK if LOOP_MASK is null, otherwise return VEC_MASK & LOOP_MASK.
+ Return VEC_MASK if LOOP_MASK is null or if VEC_MASK is already masked,
+ otherwise return VEC_MASK & LOOP_MASK.
MASK_TYPE is the type of both masks. If new statements are needed,
insert them before GSI. */
static tree
-prepare_load_store_mask (tree mask_type, tree loop_mask, tree vec_mask,
- gimple_stmt_iterator *gsi)
+prepare_vec_mask (loop_vec_info loop_vinfo, tree mask_type, tree loop_mask,
+ tree vec_mask, gimple_stmt_iterator *gsi)
{
gcc_assert (useless_type_conversion_p (mask_type, TREE_TYPE (vec_mask)));
if (!loop_mask)
return vec_mask;
gcc_assert (TREE_TYPE (loop_mask) == mask_type);
+
+ if (loop_vinfo->vec_cond_masked_set.contains ({ vec_mask, loop_mask }))
+ return vec_mask;
+
tree and_res = make_temp_ssa_name (mask_type, NULL, "vec_mask_and");
gimple *and_stmt = gimple_build_assign (and_res, BIT_AND_EXPR,
vec_mask, loop_mask);
+
gsi_insert_before (gsi, and_stmt, GSI_SAME_STMT);
return and_res;
}
@@ -2740,7 +2746,7 @@ vect_build_gather_load_calls (vec_info *vinfo, stmt_vec_info stmt_info,
&& (!mask
|| TREE_CODE (masktype) == INTEGER_TYPE
|| types_compatible_p (srctype, masktype)));
- if (mask && TREE_CODE (masktype) == INTEGER_TYPE)
+ if (mask)
masktype = truth_type_for (srctype);
tree mask_halftype = masktype;
@@ -2779,7 +2785,7 @@ vect_build_gather_load_calls (vec_info *vinfo, stmt_vec_info stmt_info,
ncopies *= 2;
- if (mask && masktype == real_masktype)
+ if (mask && VECTOR_TYPE_P (real_masktype))
{
for (int i = 0; i < count; ++i)
sel[i] = i | (count / 2);
@@ -2876,7 +2882,7 @@ vect_build_gather_load_calls (vec_info *vinfo, stmt_vec_info stmt_info,
mask_op = var;
}
}
- if (modifier == NARROW && masktype != real_masktype)
+ if (modifier == NARROW && !VECTOR_TYPE_P (real_masktype))
{
var = vect_get_new_ssa_name (mask_halftype, vect_simple_var);
gassign *new_stmt
@@ -2893,7 +2899,8 @@ vect_build_gather_load_calls (vec_info *vinfo, stmt_vec_info stmt_info,
if (masktype != real_masktype)
{
tree utype, optype = TREE_TYPE (mask_op);
- if (TYPE_MODE (real_masktype) == TYPE_MODE (optype))
+ if (VECTOR_TYPE_P (real_masktype)
+ || TYPE_MODE (real_masktype) == TYPE_MODE (optype))
utype = real_masktype;
else
utype = lang_hooks.types.type_for_mode (TYPE_MODE (optype), 1);
@@ -3567,8 +3574,9 @@ vectorizable_call (vec_info *vinfo,
gcc_assert (ncopies == 1);
tree mask = vect_get_loop_mask (gsi, masks, vec_num,
vectype_out, i);
- vargs[mask_opno] = prepare_load_store_mask
- (TREE_TYPE (mask), mask, vargs[mask_opno], gsi);
+ vargs[mask_opno] = prepare_vec_mask
+ (loop_vinfo, TREE_TYPE (mask), mask,
+ vargs[mask_opno], gsi);
}
gcall *call;
@@ -3611,8 +3619,8 @@ vectorizable_call (vec_info *vinfo,
tree mask = vect_get_loop_mask (gsi, masks, ncopies,
vectype_out, j);
vargs[mask_opno]
- = prepare_load_store_mask (TREE_TYPE (mask), mask,
- vargs[mask_opno], gsi);
+ = prepare_vec_mask (loop_vinfo, TREE_TYPE (mask), mask,
+ vargs[mask_opno], gsi);
}
gimple *new_stmt;
@@ -6349,10 +6357,43 @@ vectorizable_operation (vec_info *vinfo,
}
else
{
+ tree mask = NULL_TREE;
+ /* When combining two masks check if either of them is elsewhere
+ combined with a loop mask, if that's the case we can mark that the
+ new combined mask doesn't need to be combined with a loop mask. */
+ if (masked_loop_p && code == BIT_AND_EXPR)
+ {
+ if (loop_vinfo->scalar_cond_masked_set.contains ({ op0,
+ ncopies}))
+ {
+ mask = vect_get_loop_mask (gsi, masks, vec_num * ncopies,
+ vectype, i);
+
+ vop0 = prepare_vec_mask (loop_vinfo, TREE_TYPE (mask), mask,
+ vop0, gsi);
+ }
+
+ if (loop_vinfo->scalar_cond_masked_set.contains ({ op1,
+ ncopies }))
+ {
+ mask = vect_get_loop_mask (gsi, masks, vec_num * ncopies,
+ vectype, i);
+
+ vop1 = prepare_vec_mask (loop_vinfo, TREE_TYPE (mask), mask,
+ vop1, gsi);
+ }
+ }
+
new_stmt = gimple_build_assign (vec_dest, code, vop0, vop1, vop2);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);
vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
+
+ /* Enter the combined value into the vector cond hash so we don't
+ AND it with a loop mask again. */
+ if (mask)
+ loop_vinfo->vec_cond_masked_set.add ({ new_temp, mask });
+
if (vec_cvt_dest)
{
new_temp = build1 (VIEW_CONVERT_EXPR, vectype_out, new_temp);
@@ -8213,8 +8254,8 @@ vectorizable_store (vec_info *vinfo,
final_mask = vect_get_loop_mask (gsi, loop_masks, ncopies,
vectype, j);
if (vec_mask)
- final_mask = prepare_load_store_mask (mask_vectype, final_mask,
- vec_mask, gsi);
+ final_mask = prepare_vec_mask (loop_vinfo, mask_vectype,
+ final_mask, vec_mask, gsi);
gcall *call;
if (final_mask)
@@ -8268,8 +8309,8 @@ vectorizable_store (vec_info *vinfo,
vec_num * ncopies,
vectype, vec_num * j + i);
if (vec_mask)
- final_mask = prepare_load_store_mask (mask_vectype, final_mask,
- vec_mask, gsi);
+ final_mask = prepare_vec_mask (loop_vinfo, mask_vectype,
+ final_mask, vec_mask, gsi);
if (memory_access_type == VMAT_GATHER_SCATTER)
{
@@ -9496,8 +9537,8 @@ vectorizable_load (vec_info *vinfo,
final_mask = vect_get_loop_mask (gsi, loop_masks, ncopies,
vectype, j);
if (vec_mask)
- final_mask = prepare_load_store_mask (mask_vectype, final_mask,
- vec_mask, gsi);
+ final_mask = prepare_vec_mask (loop_vinfo, mask_vectype,
+ final_mask, vec_mask, gsi);
gcall *call;
if (final_mask)
@@ -9548,8 +9589,8 @@ vectorizable_load (vec_info *vinfo,
vec_num * ncopies,
vectype, vec_num * j + i);
if (vec_mask)
- final_mask = prepare_load_store_mask (mask_vectype, final_mask,
- vec_mask, gsi);
+ final_mask = prepare_vec_mask (loop_vinfo, mask_vectype,
+ final_mask, vec_mask, gsi);
if (i > 0)
dataref_ptr = bump_vector_ptr (vinfo, dataref_ptr, ptr_incr,
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 76e81ea..2f6e1e2 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -328,6 +328,12 @@ struct default_hash_traits<scalar_cond_masked_key>
typedef hash_set<scalar_cond_masked_key> scalar_cond_masked_set_type;
+/* Key and map that records association between vector conditions and
+ corresponding loop mask, and is populated by prepare_vec_mask. */
+
+typedef pair_hash<tree_operand_hash, tree_operand_hash> tree_cond_mask_hash;
+typedef hash_set<tree_cond_mask_hash> vec_cond_masked_set_type;
+
/* Describes two objects whose addresses must be unequal for the vectorized
loop to be valid. */
typedef std::pair<tree, tree> vec_object_pair;
@@ -647,6 +653,9 @@ public:
/* Set of scalar conditions that have loop mask applied. */
scalar_cond_masked_set_type scalar_cond_masked_set;
+ /* Set of vector conditions that have loop mask applied. */
+ vec_cond_masked_set_type vec_cond_masked_set;
+
/* If we are using a loop mask to align memory addresses, this variable
contains the number of vector elements that we should skip in the
first iteration of the vector loop (i.e. the number of leading
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 82509fa..d38d078 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -1550,70 +1550,50 @@ irange::irange_union (const irange &r)
// the merge is performed.
//
// [Xi,Yi]..[Xn,Yn] U [Xj,Yj]..[Xm,Ym] --> [Xk,Yk]..[Xp,Yp]
- tree ttype = r.type ();
- signop sign = TYPE_SIGN (ttype);
-
- auto_vec<tree, 20> res;
- wide_int u1 ;
- wi::overflow_type ovf;
+ auto_vec<tree, 20> res (m_num_ranges * 2 + r.m_num_ranges * 2);
unsigned i = 0, j = 0, k = 0;
while (i < m_num_ranges * 2 && j < r.m_num_ranges * 2)
{
// lower of Xi and Xj is the lowest point.
- if (wi::le_p (wi::to_wide (m_base[i]), wi::to_wide (r.m_base[j]), sign))
+ if (wi::to_widest (m_base[i]) <= wi::to_widest (r.m_base[j]))
{
- res.safe_push (m_base[i]);
- res.safe_push (m_base[i + 1]);
+ res.quick_push (m_base[i]);
+ res.quick_push (m_base[i + 1]);
k += 2;
i += 2;
}
else
{
- res.safe_push (r.m_base[j]);
- res.safe_push (r.m_base[j + 1]);
+ res.quick_push (r.m_base[j]);
+ res.quick_push (r.m_base[j + 1]);
k += 2;
j += 2;
}
}
for ( ; i < m_num_ranges * 2; i += 2)
{
- res.safe_push (m_base[i]);
- res.safe_push (m_base[i + 1]);
+ res.quick_push (m_base[i]);
+ res.quick_push (m_base[i + 1]);
k += 2;
}
for ( ; j < r.m_num_ranges * 2; j += 2)
{
- res.safe_push (r.m_base[j]);
- res.safe_push (r.m_base[j + 1]);
+ res.quick_push (r.m_base[j]);
+ res.quick_push (r.m_base[j + 1]);
k += 2;
}
// Now normalize the vector removing any overlaps.
i = 2;
- int prec = TYPE_PRECISION (ttype);
- wide_int max_val = wi::max_value (prec, sign);
for (j = 2; j < k ; j += 2)
{
- wide_int val_im1 = wi::to_wide (res[i - 1]);
- if (val_im1 == max_val)
- break;
- u1 = wi::add (val_im1, 1, sign, &ovf);
-
- // Overflow indicates we are at MAX already.
- // A wide int bug requires the previous max_val check
- // trigger: gcc.c-torture/compile/pr80443.c with -O3
- if (ovf == wi::OVF_OVERFLOW)
- break;
-
- wide_int val_j = wi::to_wide (res[j]);
- wide_int val_jp1 = wi::to_wide (res[j+1]);
// Current upper+1 is >= lower bound next pair, then we merge ranges.
- if (wi::ge_p (u1, val_j, sign))
+ if (wi::to_widest (res[i - 1]) + 1 >= wi::to_widest (res[j]))
{
// New upper bounds is greater of current or the next one.
- if (wi::gt_p (val_jp1, val_im1, sign))
- res [i - 1] = res[j + 1];
+ if (wi::to_widest (res[j + 1]) > wi::to_widest (res[i - 1]))
+ res[i - 1] = res[j + 1];
}
else
{
diff --git a/gcc/varasm.c b/gcc/varasm.c
index d6031d6..5da3b8f 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -250,8 +250,8 @@ object_block_hasher::hash (object_block *old)
/* Return a new unnamed section with the given fields. */
section *
-get_unnamed_section (unsigned int flags, void (*callback) (const void *),
- const void *data)
+get_unnamed_section (unsigned int flags, void (*callback) (const char *),
+ const char *data)
{
section *sect;
@@ -5869,7 +5869,7 @@ mark_weak (tree decl)
struct symtab_node *n = symtab_node::get (decl);
if (n && n->refuse_visibility_changes)
- error ("%+qD declared weak after being used", decl);
+ error ("%qD declared weak after being used", decl);
DECL_WEAK (decl) = 1;
if (DECL_RTL_SET_P (decl)
@@ -7474,7 +7474,8 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
FIXME: We can resolve the weakref case more curefuly by looking at the
weakref alias. */
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))
- || (TREE_CODE (exp) == FUNCTION_DECL
+ || (!targetm.ifunc_ref_local_ok ()
+ && TREE_CODE (exp) == FUNCTION_DECL
&& cgraph_node::get (exp)
&& cgraph_node::get (exp)->ifunc_resolver))
return false;
@@ -7778,9 +7779,9 @@ file_end_indicate_split_stack (void)
a get_unnamed_section callback. */
void
-output_section_asm_op (const void *directive)
+output_section_asm_op (const char *directive)
{
- fprintf (asm_out_file, "%s\n", (const char *) directive);
+ fprintf (asm_out_file, "%s\n", directive);
}
/* Emit assembly code to switch to section NEW_SECTION. Do nothing if