aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2022-09-29 10:41:04 +0200
committerMartin Liska <mliska@suse.cz>2022-09-29 10:41:04 +0200
commit54f3cfaf3a6f50958c71d79c85206a6c722e1a22 (patch)
tree5f33297a30acc0df71baa0566cffa701eb97ab4e /gcc
parent3c527a35fa428b727807c81f1225a5e0025446c1 (diff)
parenta1cd4d52d6ef90b977fb2d80c1cf17f3efa5b01d (diff)
downloadgcc-54f3cfaf3a6f50958c71d79c85206a6c722e1a22.zip
gcc-54f3cfaf3a6f50958c71d79c85206a6c722e1a22.tar.gz
gcc-54f3cfaf3a6f50958c71d79c85206a6c722e1a22.tar.bz2
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog276
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/ChangeLog99
-rw-r--r--gcc/basic-block.h5
-rw-r--r--gcc/builtins.def5
-rw-r--r--gcc/c-family/ChangeLog58
-rw-r--r--gcc/c-family/c-common.cc37
-rw-r--r--gcc/c-family/c-common.h1
-rw-r--r--gcc/c-family/c-cppbuiltin.cc10
-rw-r--r--gcc/c-family/c-format.cc3
-rw-r--r--gcc/c-family/c-lex.cc20
-rw-r--r--gcc/c-family/c-omp.cc42
-rw-r--r--gcc/c-family/c-pragma.cc5
-rw-r--r--gcc/c-family/c-pragma.h5
-rw-r--r--gcc/c/ChangeLog18
-rw-r--r--gcc/c/c-decl.cc4
-rw-r--r--gcc/c/c-lang.h3
-rw-r--r--gcc/c/c-parser.cc308
-rw-r--r--gcc/calls.cc6
-rw-r--r--gcc/cfghooks.cc1
-rw-r--r--gcc/cfgrtl.cc3
-rw-r--r--gcc/config.gcc1
-rw-r--r--gcc/config/arm/arm-c.cc2
-rw-r--r--gcc/config/i386/avx512fp16intrin.h11
-rw-r--r--gcc/config/i386/i386-builtins.cc15
-rw-r--r--gcc/config/i386/i386.cc5
-rw-r--r--gcc/config/i386/predicates.md20
-rw-r--r--gcc/config/i386/sse.md4
-rw-r--r--gcc/config/ia64/ia64.cc24
-rw-r--r--gcc/config/loongarch/loongarch.cc2
-rw-r--r--gcc/config/loongarch/loongarch.md12
-rw-r--r--gcc/config/riscv/riscv-builtins.cc2
-rw-r--r--gcc/config/riscv/riscv-protos.h1
-rw-r--r--gcc/config/riscv/riscv-vector-builtins.cc279
-rw-r--r--gcc/config/riscv/riscv-vector-builtins.def199
-rw-r--r--gcc/config/riscv/riscv-vector-builtins.h79
-rw-r--r--gcc/config/riscv/riscv-vector-switch.def164
-rw-r--r--gcc/config/riscv/riscv.cc95
-rw-r--r--gcc/config/riscv/t-riscv10
-rw-r--r--gcc/config/rs6000/rs6000-builtin.cc17
-rw-r--r--gcc/config/rs6000/rs6000-c.cc1
-rw-r--r--gcc/config/rs6000/rs6000.cc6
-rw-r--r--gcc/cp/ChangeLog156
-rw-r--r--gcc/cp/call.cc159
-rw-r--r--gcc/cp/constraint.cc14
-rw-r--r--gcc/cp/cp-tree.h31
-rw-r--r--gcc/cp/cxx-pretty-print.cc2
-rw-r--r--gcc/cp/decl.cc26
-rw-r--r--gcc/cp/error.cc10
-rw-r--r--gcc/cp/lambda.cc89
-rw-r--r--gcc/cp/mangle.cc69
-rw-r--r--gcc/cp/method.cc1
-rw-r--r--gcc/cp/module.cc5
-rw-r--r--gcc/cp/parser.cc471
-rw-r--r--gcc/cp/pt.cc86
-rw-r--r--gcc/cp/semantics.cc7
-rw-r--r--gcc/cp/tree.cc2
-rw-r--r--gcc/cp/typeck.cc182
-rw-r--r--gcc/cp/typeck2.cc25
-rw-r--r--gcc/cselib.cc20
-rw-r--r--gcc/d/ChangeLog12
-rw-r--r--gcc/d/decl.cc2
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/aggregate.d13
-rw-r--r--gcc/d/dmd/aggregate.h2
-rw-r--r--gcc/d/dmd/apply.d25
-rw-r--r--gcc/d/dmd/arrayop.d12
-rw-r--r--gcc/d/dmd/attrib.d4
-rw-r--r--gcc/d/dmd/canthrow.d6
-rw-r--r--gcc/d/dmd/chkformat.d600
-rw-r--r--gcc/d/dmd/clone.d6
-rw-r--r--gcc/d/dmd/cparse.d19
-rw-r--r--gcc/d/dmd/dcast.d4
-rw-r--r--gcc/d/dmd/declaration.h4
-rw-r--r--gcc/d/dmd/dimport.d7
-rw-r--r--gcc/d/dmd/dinterpret.d12
-rw-r--r--gcc/d/dmd/dmangle.d17
-rw-r--r--gcc/d/dmd/doc.d4
-rw-r--r--gcc/d/dmd/dsymbol.d6
-rw-r--r--gcc/d/dmd/dsymbol.h2
-rw-r--r--gcc/d/dmd/dsymbolsem.d48
-rw-r--r--gcc/d/dmd/dtemplate.d71
-rw-r--r--gcc/d/dmd/escape.d5
-rw-r--r--gcc/d/dmd/expression.d20
-rw-r--r--gcc/d/dmd/expression.h22
-rw-r--r--gcc/d/dmd/expressionsem.d92
-rw-r--r--gcc/d/dmd/func.d19
-rw-r--r--gcc/d/dmd/iasmgcc.d8
-rw-r--r--gcc/d/dmd/id.d2
-rw-r--r--gcc/d/dmd/init.d1
-rw-r--r--gcc/d/dmd/init.h1
-rw-r--r--gcc/d/dmd/initsem.d553
-rw-r--r--gcc/d/dmd/lexer.d9
-rw-r--r--gcc/d/dmd/module.h2
-rw-r--r--gcc/d/dmd/mtype.d649
-rw-r--r--gcc/d/dmd/mtype.h4
-rw-r--r--gcc/d/dmd/opover.d9
-rw-r--r--gcc/d/dmd/parse.d102
-rw-r--r--gcc/d/dmd/root/object.h2
-rw-r--r--gcc/d/dmd/semantic3.d40
-rw-r--r--gcc/d/dmd/transitivevisitor.d73
-rw-r--r--gcc/d/dmd/typesem.d18
-rw-r--r--gcc/d/expr.cc33
-rw-r--r--gcc/d/runtime.def5
-rw-r--r--gcc/doc/invoke.texi11
-rw-r--r--gcc/final.cc26
-rw-r--r--gcc/fortran/ChangeLog7
-rw-r--r--gcc/fortran/simplify.cc13
-rw-r--r--gcc/gimple-pretty-print.cc2
-rw-r--r--gcc/gimple-range-op.cc8
-rw-r--r--gcc/gimple-streamer-in.cc1
-rw-r--r--gcc/gimple-streamer-out.cc1
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/input.cc36
-rw-r--r--gcc/input.h4
-rw-r--r--gcc/ipa-cp.cc4
-rw-r--r--gcc/lto-streamer-in.cc19
-rw-r--r--gcc/lto-streamer-out.cc7
-rw-r--r--gcc/lto-streamer.h3
-rw-r--r--gcc/print-rtl.cc4
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/testsuite/ChangeLog230
-rw-r--r--gcc/testsuite/c-c++-common/gomp/assume-1.c29
-rw-r--r--gcc/testsuite/c-c++-common/gomp/assume-2.c46
-rw-r--r--gcc/testsuite/c-c++-common/gomp/assume-3.c27
-rw-r--r--gcc/testsuite/c-c++-common/gomp/assumes-1.c26
-rw-r--r--gcc/testsuite/c-c++-common/gomp/assumes-2.c23
-rw-r--r--gcc/testsuite/c-c++-common/gomp/assumes-3.c15
-rw-r--r--gcc/testsuite/c-c++-common/gomp/assumes-4.c6
-rw-r--r--gcc/testsuite/c-c++-common/gomp/begin-assumes-1.c46
-rw-r--r--gcc/testsuite/c-c++-common/gomp/begin-assumes-2.c63
-rw-r--r--gcc/testsuite/c-c++-common/gomp/begin-assumes-3.c2
-rw-r--r--gcc/testsuite/c-c++-common/gomp/begin-assumes-4.c2
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-target-6.c2
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/pr85213.c7
-rw-r--r--gcc/testsuite/g++.dg/conversion/pr41426.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/elision_weak.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/move-return3.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/decltype-auto2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/decltype-auto6.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-89419.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/constexpr-lambda13.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp23/decltype1.C113
-rw-r--r--gcc/testsuite/g++.dg/cpp23/decltype2.C49
-rw-r--r--gcc/testsuite/g++.dg/cpp23/elision1.C114
-rw-r--r--gcc/testsuite/g++.dg/cpp23/elision2.C46
-rw-r--r--gcc/testsuite/g++.dg/cpp23/elision3.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp23/elision4.C38
-rw-r--r--gcc/testsuite/g++.dg/cpp23/elision5.C53
-rw-r--r--gcc/testsuite/g++.dg/cpp23/elision6.C20
-rw-r--r--gcc/testsuite/g++.dg/cpp23/elision7.C72
-rw-r--r--gcc/testsuite/g++.dg/cpp23/ext-floating.h30
-rw-r--r--gcc/testsuite/g++.dg/cpp23/ext-floating1.C447
-rw-r--r--gcc/testsuite/g++.dg/cpp23/ext-floating10.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp23/ext-floating2.C157
-rw-r--r--gcc/testsuite/g++.dg/cpp23/ext-floating3.C134
-rw-r--r--gcc/testsuite/g++.dg/cpp23/ext-floating4.C126
-rw-r--r--gcc/testsuite/g++.dg/cpp23/ext-floating5.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp23/ext-floating6.C30
-rw-r--r--gcc/testsuite/g++.dg/cpp23/ext-floating7.C119
-rw-r--r--gcc/testsuite/g++.dg/cpp23/ext-floating8.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp23/ext-floating9.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp23/static-operator-call1.C41
-rw-r--r--gcc/testsuite/g++.dg/cpp23/static-operator-call2.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp23/static-operator-call3.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-traits3.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constinit3.C2
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/is_convertible4.C33
-rw-r--r--gcc/testsuite/g++.dg/ext/is_nothrow_convertible4.C33
-rw-r--r--gcc/testsuite/g++.dg/fstack-protector-strong.C2
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-1.C15
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-15.C41
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-16.C26
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-17.C17
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-2.C15
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-9.C20
-rw-r--r--gcc/testsuite/g++.dg/gomp/pr56217.C4
-rw-r--r--gcc/testsuite/g++.dg/other/mult-stor1.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/crash39.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/typedef8.C10
-rw-r--r--gcc/testsuite/g++.dg/pr58245-1.C10
-rw-r--r--gcc/testsuite/g++.dg/template/error30.C2
-rw-r--r--gcc/testsuite/g++.dg/torture/pr107029.C19
-rw-r--r--gcc/testsuite/g++.dg/uninit-pr105646.C17
-rw-r--r--gcc/testsuite/g++.dg/warn/Wno-return-local-addr.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/Wreturn-local-addr.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/crash55.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/operator.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/temporary2.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/p2846b.C2
-rw-r--r--gcc/testsuite/g++.target/i386/float16-1.C4
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/cold_partition_label.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/popcount6.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/popcount6b.c6
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x2.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x3.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x4.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst1x2.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst1x3.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst1x4.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/attr-crypto.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/keylocker-encodekey128.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/keylocker-encodekey256.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr107055.c4
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/base/abi-1.c63
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/base/abi-2.c63
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/base/abi-3.c63
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/base/abi-4.c63
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/base/abi-5.c63
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/base/abi-6.c63
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/base/abi-7.c63
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/rvv.exp47
-rw-r--r--gcc/testsuite/gdc.test/compilable/commontype.d20
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/cimports2a.i4
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/cimports2b.i4
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/format23327.d7
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/format23327/write.d0
-rw-r--r--gcc/testsuite/gdc.test/compilable/segfaultgolf.d50
-rw-r--r--gcc/testsuite/gdc.test/compilable/statictemplatethis.d45
-rw-r--r--gcc/testsuite/gdc.test/compilable/test13123.d38
-rw-r--r--gcc/testsuite/gdc.test/compilable/test21243.d21
-rw-r--r--gcc/testsuite/gdc.test/compilable/test21956.d16
-rw-r--r--gcc/testsuite/gdc.test/compilable/test22674.d10
-rw-r--r--gcc/testsuite/gdc.test/compilable/test23173.d6
-rw-r--r--gcc/testsuite/gdc.test/compilable/test23258.d21
-rw-r--r--gcc/testsuite/gdc.test/compilable/test23306.d7
-rw-r--r--gcc/testsuite/gdc.test/compilable/test23327.d3
-rw-r--r--gcc/testsuite/gdc.test/compilable/vararg.d20
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag10169.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag10783.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag13528.d6
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag14145.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag15713.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag23355.d16
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag3438.d5
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag3438b.d9
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag8894.d8
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/dip22a.d8
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/e15876_1.d15
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/e15876_3.d30
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/e15876_4.d26
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail10968.d31
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail121.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail13123.d21
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail17646.d5
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail18892.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail18970.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail18979.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19103.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19687.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19913.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail21243.d19
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail23109.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail7372.d13
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/failoffset.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice10938.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice12174.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice15855.d24
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice18469.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice19755.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/fail7372.d9
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d1
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/mixinprop.d13
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test15785.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test15897.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test16188.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test17380spec.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test21096.d6
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test22680.d17
-rw-r--r--gcc/testsuite/gdc.test/runnable/newaa.d23
-rw-r--r--gcc/testsuite/gdc.test/runnable/test23234.d22
-rw-r--r--gcc/testsuite/gdc.test/runnable/testassign.d16
-rw-r--r--gcc/testsuite/gfortran.dg/pr107054.f9013
-rw-r--r--gcc/tree-cfg.cc49
-rw-r--r--gcc/tree-core.h4
-rw-r--r--gcc/tree-pretty-print.cc6
-rw-r--r--gcc/tree-ssa-reassoc.cc21
-rw-r--r--gcc/tree-ssa-uninit.cc10
-rw-r--r--gcc/tree-vect-loop-manip.cc10
-rw-r--r--gcc/tree-vect-loop.cc82
-rw-r--r--gcc/tree-vectorizer.h3
-rw-r--r--gcc/tree.cc11
-rw-r--r--gcc/tree.h4
-rw-r--r--gcc/value-range.cc13
-rw-r--r--gcc/value-range.h9
-rw-r--r--gcc/var-tracking.cc17
292 files changed, 8132 insertions, 1816 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6890dd1..25721e8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,279 @@
+2022-09-28 Eugene Rozenfeld <erozen@microsoft.com>
+
+ * basic-block.h: Remove discriminator from basic blocks.
+ * cfghooks.cc (split_block_1): Remove discriminator from basic blocks.
+ * final.cc (final_start_function_1): Switch from per-bb to per statement
+ discriminator.
+ (final_scan_insn_1): Don't keep track of basic block discriminators.
+ (compute_discriminator): Switch from basic block discriminators to
+ instruction discriminators.
+ (insn_discriminator): New function to return instruction discriminator.
+ (notice_source_line): Use insn_discriminator.
+ * gimple-pretty-print.cc (dump_gimple_bb_header): Remove dumping of
+ basic block discriminators.
+ * gimple-streamer-in.cc (input_bb): Remove reading of basic block
+ discriminators.
+ * gimple-streamer-out.cc (output_bb): Remove writing of basic block
+ discriminators.
+ * input.cc (make_location): Pass 0 discriminator to COMBINE_LOCATION_DATA.
+ (location_with_discriminator): New function to combine locus with
+ a discriminator.
+ (has_discriminator): New function to check if a location has a discriminator.
+ (get_discriminator_from_loc): New function to get the discriminator
+ from a location.
+ * input.h: Declarations of new functions.
+ * lto-streamer-in.cc (cmp_loc): Use discriminators in location comparison.
+ (apply_location_cache): Keep track of current discriminator.
+ (input_location_and_block): Read discriminator from stream.
+ * lto-streamer-out.cc (clear_line_info): Set current discriminator to
+ UINT_MAX.
+ (lto_output_location_1): Write discriminator to stream.
+ * lto-streamer.h: Add discriminator to cached_location.
+ Add current_discr to lto_location_cache.
+ Add current_discr to output_block.
+ * print-rtl.cc (print_rtx_operand_code_i): Print discriminator.
+ * rtl.h: Add extern declaration of insn_discriminator.
+ * tree-cfg.cc (assign_discriminator): New function to assign a unique
+ discriminator value to all statements in a basic block that have the given
+ line number.
+ (assign_discriminators): Assign discriminators to statement locations.
+ * tree-pretty-print.cc (dump_location): Dump discriminators.
+ * tree.cc (set_block): Preserve discriminator when setting block.
+ (set_source_range): Preserve discriminator when setting source range.
+
+2022-09-28 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/107061
+ * config/i386/predicates.md (encodekey128_operation): Check
+ XMM4-XMM6 as clobbered.
+ (encodekey256_operation): Likewise.
+ * config/i386/sse.md (encodekey128u32): Clobber XMM4-XMM6.
+ (encodekey256u32): Likewise.
+
+2022-09-28 Ju-Zhe Zhong <juzhe.zhong@rivai.ai>
+
+ * config.gcc: Add riscv-vector-builtins.o.
+ * config/riscv/riscv-builtins.cc (riscv_init_builtins): Add RVV builtin function.
+ * config/riscv/riscv-protos.h (riscv_v_ext_enabled_vector_mode_p): New function.
+ * config/riscv/riscv.cc (ENTRY): New macro.
+ (riscv_v_ext_enabled_vector_mode_p): New function.
+ (riscv_mangle_type): Add RVV mangle.
+ (riscv_vector_mode_supported_p): Adjust RVV machine mode.
+ (riscv_verify_type_context): Add context check for RVV.
+ (riscv_vector_alignment): Add RVV alignment target hook support.
+ (TARGET_VECTOR_MODE_SUPPORTED_P): New target hook support.
+ (TARGET_VERIFY_TYPE_CONTEXT): Ditto.
+ (TARGET_VECTOR_ALIGNMENT): Ditto.
+ * config/riscv/t-riscv: Add riscv-vector-builtins.o
+ * config/riscv/riscv-vector-builtins.cc: New file.
+ * config/riscv/riscv-vector-builtins.def: New file.
+ * config/riscv/riscv-vector-builtins.h: New file.
+ * config/riscv/riscv-vector-switch.def: New file.
+
+2022-09-28 Stefan Schulze Frielinghaus <stefansf@linux.ibm.com>
+
+ * var-tracking.cc (vt_add_function_parameter): Add entry values
+ up to maximal register mode.
+
+2022-09-28 Stefan Schulze Frielinghaus <stefansf@linux.ibm.com>
+
+ * cselib.cc (new_cselib_val): Keep track of further subvalue
+ relations.
+
+2022-09-28 Andrea Corallo <andrea.corallo@arm.com>
+
+ * config/arm/arm-c.cc (arm_cpu_builtins): Define
+ __ARM_FEATURE_AES and __ARM_FEATURE_SHA2.
+
+2022-09-28 Xi Ruoyao <xry111@xry111.site>
+
+ PR tree-optimization/105414
+ * config/loongarch/loongarch.md (UNSPEC_FMAX): New unspec.
+ (UNSPEC_FMIN): Likewise.
+ (fmax<mode>3): Use UNSPEC_FMAX instead of smax.
+ (fmin<mode>3): Use UNSPEC_FMIN instead of smin.
+
+2022-09-28 Lulu Cheng <chenglulu@loongson.cn>
+
+ * config/loongarch/loongarch.cc (loongarch_asan_shadow_offset):
+ Fixed typo in "asan_mapping.h".
+
+2022-09-28 H.J. Lu <hjl.tools@gmail.com>
+
+ PR middle-end/58245
+ * calls.cc: Include "tree-eh.h".
+ (expand_call): Check stack canary before throwing exception.
+
+2022-09-27 Eugene Rozenfeld <erozen@microsoft.com>
+
+ * ipa-cp.cc (good_cloning_opportunity_p): Fix profile count comparison.
+
+2022-09-27 Kim Kuparinen <kim.kuparinen@rightware.com>
+
+ * doc/invoke.texi: Update ABI version info.
+
+2022-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-op.cc (cfn_popcount): Calculate the popcount of a
+ singleton.
+
+2022-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * value-range.cc (irange::set_nonzero_bits): Set range when known.
+
+2022-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * value-range.h (irange::set): New version taking wide_int_ref.
+
+2022-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/107029
+ * tree-ssa-reassoc.cc (optimize_range_tests_cmp_bitwise): Treat
+ OFFSET_TYPE like POINTER_TYPE, except that OFFSET_TYPE may be
+ signed and so can trigger even the (b % 4) == 3 case.
+
+2022-09-27 Jeff Law <jeffreyalaw@gmail.com>
+
+ * cfgrtl.cc (fixup_reorder_chain): Verify that simple_return
+ and return are available before trying to use them.
+
+2022-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/106652
+ PR c++/85518
+ * tree-core.h (enum tree_index): Add TI_FLOAT128T_TYPE
+ enumerator.
+ * tree.h (float128t_type_node): Define.
+ * tree.cc (build_common_tree_nodes): Initialize float128t_type_node.
+ * builtins.def (DEF_FLOATN_BUILTIN): Adjust comment now that
+ _Float<N> is supported in C++ too.
+ * config/i386/i386.cc (ix86_mangle_type): Only mangle as "g"
+ float128t_type_node.
+ * config/i386/i386-builtins.cc (ix86_init_builtin_types): Use
+ float128t_type_node for __float128 instead of float128_type_node
+ and create it if NULL.
+ * config/i386/avx512fp16intrin.h (_mm_setzero_ph, _mm256_setzero_ph,
+ _mm512_setzero_ph, _mm_set_sh, _mm_load_sh): Use 0.0f16 instead of
+ 0.0f.
+ * config/ia64/ia64.cc (ia64_init_builtins): Use
+ float128t_type_node for __float128 instead of float128_type_node
+ and create it if NULL.
+ * config/rs6000/rs6000-c.cc (is_float128_p): Also return true
+ for float128t_type_node if non-NULL.
+ * config/rs6000/rs6000.cc (rs6000_mangle_type): Don't mangle
+ float128_type_node as "u9__ieee128".
+ * config/rs6000/rs6000-builtin.cc (rs6000_init_builtins): Use
+ float128t_type_node for __float128 instead of float128_type_node
+ and create it if NULL.
+
+2022-09-26 Martin Liska <mliska@suse.cz>
+
+ * doc/invoke.texi: Add missing dash for
+ Wanalyzer-exposure-through-uninit-copy.
+
+2022-09-26 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/107009
+ * range-op.cc (operator_bitwise_and::op1_range): Optimize 0 = x & MASK.
+ (range_op_bitwise_and_tests): New test.
+
+2022-09-26 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/107009
+ * tree-ssa-dom.cc
+ (dom_opt_dom_walker::set_global_ranges_from_unreachable_edges):
+ Iterate over exports.
+
+2022-09-26 Thomas Schwinge <thomas@codesourcery.com>
+
+ * config.gcc (with_arch) [nvptx]: Allow '--with-arch' to override
+ the default.
+ * config/nvptx/gen-multilib-matches.sh: New.
+ * config/nvptx/t-nvptx (MULTILIB_OPTIONS, MULTILIB_MATCHES)
+ (MULTILIB_EXCEPTIONS): Handle this.
+ * doc/install.texi (Specific) <nvptx-*-none>: Document this.
+ * doc/invoke.texi (Nvidia PTX Options): Likewise.
+
+2022-09-26 Thomas Schwinge <thomas@codesourcery.com>
+
+ * config.gcc (TM_MULTILIB_CONFIG) [nvptx]: Set to '$with_arch'.
+ * config/nvptx/t-nvptx (MULTILIB_OPTIONS, MULTILIB_MATCHES)
+ (MULTILIB_EXCEPTIONS): Handle it.
+
+2022-09-26 Thomas Schwinge <thomas@codesourcery.com>
+
+ * config.gcc (with_arch) [nvptx]: Set to 'sm_30'.
+ * config/nvptx/nvptx.cc (nvptx_option_override): Assert that
+ '-misa' appeared.
+ * config/nvptx/nvptx.h (OPTION_DEFAULT_SPECS): Define.
+ * config/nvptx/nvptx.opt (misa=): Remove 'Init'.
+
+2022-09-26 Thomas Schwinge <thomas@codesourcery.com>
+
+ * config/nvptx/nvptx.h (ASM_SPEC): Define.
+
+2022-09-26 Jeff Law <jeffreyalaw@gmail.com>
+
+ * cfgcleanup.cc (bb_is_just_return): No longer static.
+ * cfgcleanup.h (bb_is_just_return): Add prototype.
+ * cfgrtl.cc (fixup_reorder_chain): Do not create an
+ unconditional jump to a return block. Conditionally
+ remove unreachable blocks.
+
+2022-09-26 Tobias Burnus <tobias@codesourcery.com>
+
+ PR middle-end/106982
+ * omp-low.cc (lower_oacc_reductions): Add some unshare_expr.
+
+2022-09-26 Martin Liska <mliska@suse.cz>
+
+ * config/s390/s390.cc (s390_rtx_costs): Remove dest variable
+ and use only dst.
+
+2022-09-26 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64-arches.def (armv9.1-a): Define.
+ (armv9.2-a): Likewise.
+ (armv9.3-a): Likewise.
+ * config/aarch64/aarch64.h (AARCH64_FL_V9_1): Likewise.
+ (AARCH64_FL_V9_2): Likewise.
+ (AARCH64_FL_V9_3): Likewise.
+ (AARCH64_FL_FOR_ARCH9_1): Likewise.
+ (AARCH64_FL_FOR_ARCH9_2): Likewise.
+ (AARCH64_FL_FOR_ARCH9_3): Likewise.
+ (AARCH64_ISA_V9_1): Likewise.
+ (AARCH64_ISA_V9_2): Likewise.
+ (AARCH64_ISA_V9_3): Likewise.
+ * doc/invoke.texi (AArch64 Options): Document armv9.1-a, armv9.2-a,
+ armv9.3-a values to -march.
+
+2022-09-26 Martin Liska <mliska@suse.cz>
+
+ * value-range.cc (tree_compare): Remove unused function.
+
+2022-09-26 Kewen Lin <linkw@linux.ibm.com>
+
+ PR target/96072
+ * config/rs6000/rs6000-logue.cc (rs6000_emit_epilogue): Update the
+ condition for adding REG_CFA_DEF_CFA reg note with
+ frame_pointer_needed_indeed.
+
+2022-09-26 Kewen Lin <linkw@linux.ibm.com>
+
+ PR target/100645
+ * config/rs6000/vector.md (vec_shr_<mode>): Replace condition
+ TARGET_ALTIVEC with VECTOR_UNIT_ALTIVEC_OR_VSX_P.
+
+2022-09-26 Hongtao Liu <hongtao.liu@intel.com>
+ Liwei Xu <liwei.xu@intel.com>
+
+ PR target/53346
+ * config/i386/i386-expand.cc (expand_vec_perm_shufps_shufps):
+ New function.
+ (ix86_expand_vec_perm_const_1): Insert
+ expand_vec_perm_shufps_shufps at the end of 2-instruction
+ expand sequence.
+
2022-09-25 Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
* doc/sourcebuild.texi: Fix chapter level.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 7764f7e..ea4b4d1 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20220926
+20220929
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index c48bbdf..db4ac0d 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,102 @@
+2022-09-26 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_attributes.rst: Rename Valid_Image.
+ * gnat_rm.texi: Regenerate.
+ * gnat_ugn.texi: Regenerate.
+
+2022-09-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch12.adb (Build_Instance_Compilation_Unit_Nodes): Relocate
+ auxiliary declarations from the original compilation unit to the
+ newly created compilation unit for the spec.
+
+2022-09-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * rtsfind.ads
+ (RTU_Id): Remove unreferenced packages; fix whitespace.
+ (RE_Id): Remove unreferenced entities; add comment about entity
+ that is only used by GNATprove and not by GNAT.
+
+2022-09-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * s-oscons-tmplt.c (STR, STR1): Remove.
+
+2022-09-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_ugn/building_executable_programs_with_gnat.rst
+ (-gnateT): Document new parameter Long_Long_Long_Size.
+ * gnat_ugn.texi: Regenerate.
+
+2022-09-26 Steve Baird <baird@adacore.com>
+
+ * bindgen.adb: When the binder is invoked for the device, specify
+ the CUDA_Global aspect for the adainit and adafinal procedures via
+ a pragma instead of via an aspect_specification.
+
+2022-09-26 Kévin Le Gouguec <legouguec@adacore.com>
+
+ * doc/gnat_ugn/building_executable_programs_with_gnat.rst
+ (Linker Switches): Document support for mold along with gold; add some
+ advice regarding OpenSSL in the Pro version.
+ * gnat_ugn.texi: Regenerate.
+
+2022-09-26 Tucker Taft <taft@adacore.com>
+
+ * sem_util.adb (Original_Aspect_Pragma_Name): Check for Check
+ pragmas.
+
+2022-09-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch5.adb (Analyze_Iterator_Specification): Delay expansion
+ based on Full_Analysis flag.
+
+2022-09-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch5.adb (Analyze_Iterator_Specification): Delay expansion of
+ for iterated component association just like it is done within
+ quantified expression.
+
+2022-09-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * contracts.adb (Analyze_Object_Contract): Check SPARK_Mode before
+ applying SPARK rule.
+
+2022-09-26 Justin Squirek <squirek@adacore.com>
+
+ * sem_util.adb
+ (Accessibility_Level): Modify indexed and selected components case
+ by reducing the scope where Original_Node gets used.
+
+2022-09-26 Boris Yakobowski <yakobowski@adacore.com>
+
+ * doc/gnat_ugn/gnat_utility_programs.rst: Remove documentation for
+ gnatmetric.
+
+2022-09-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * gsocket.h: Remove redefinition of _WIN32_WINNT.
+ * mingw32.h: Remove conditional definition of _WIN32_WINNT.
+
+2022-09-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * mingw32.h: Remove condition definition of MAXPATHLEN; the include
+ directive for stdlib.h was most likely intended to provide the
+ MAX_PATH.
+
+2022-09-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * adaint.c: Remove conditional #include directives for old MinGW.
+ * cal.c: Always include winsock.h, since it is part of modern
+ MinGW.
+ * cstreams.c: Remove workaround for old MinGW.
+ * expect.c: Remove conditional #include directive for old MinGW.
+ * mingw32.h: Remove STD_MINGW and OLD_MINGW declarations.
+ * sysdep.c: Remove conditional #include directive for old MinGW.
+
+2022-09-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_warn.ads (Has_Junk_Name): Reword comment.
+
2022-09-20 Martin Liska <mliska@suse.cz>
* exp_ch6.adb: Replace "the the" with "the".
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index c9d1fc9..1eae03d 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -148,11 +148,6 @@ struct GTY((chain_next ("%h.next_bb"), chain_prev ("%h.prev_bb"))) basic_block_d
/* Expected number of executions: calculated in profile.cc. */
profile_count count;
-
- /* The discriminator for this block. The discriminator distinguishes
- among several basic blocks that share a common locus, allowing for
- more accurate sample-based profiling. */
- int discriminator;
};
/* This ensures that struct gimple_bb_info is smaller than
diff --git a/gcc/builtins.def b/gcc/builtins.def
index f023631..109b387 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -114,9 +114,8 @@ along with GCC; see the file COPYING3. If not see
with an argument such as FLOAT32 to produce the enum value for the type. If
we are compiling for the C language with GNU extensions, we enable the name
without the __builtin_ prefix as well as the name with the __builtin_
- prefix. C++ does not enable these names by default because they don't have
- the _Float<N> and _Float<N>X keywords, and a class based library should use
- the __builtin_ names. */
+ prefix. C++ does not enable these names by default because a class based
+ library should use the __builtin_ names. */
#undef DEF_FLOATN_BUILTIN
#define DEF_FLOATN_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 415c4cf..a9ed2f0 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,61 @@
+2022-09-27 Marek Polacek <polacek@redhat.com>
+
+ PR c++/101165
+ PR c++/106882
+ * c-cppbuiltin.cc (c_cpp_builtins): Define __cpp_implicit_move.
+
+2022-09-27 Marek Polacek <polacek@redhat.com>
+
+ * c-format.cc (c_keywords): Drop nothrow.
+
+2022-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/106651
+ * c-cppbuiltin.cc (c_cpp_builtins): Predefine
+ __cpp_static_call_operator=202207L for C++23.
+
+2022-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_ASSUME,
+ PRAGMA_OMP_ASSUMES and PRAGMA_OMP_BEGIN. Rename
+ PRAGMA_OMP_END_DECLARE_TARGET to PRAGMA_OMP_END.
+ * c-pragma.cc (omp_pragmas): Add assumes and begin.
+ For end rename PRAGMA_OMP_END_DECLARE_TARGET to PRAGMA_OMP_END.
+ (omp_pragmas_simd): Add assume.
+ * c-common.h (c_omp_directives): Declare.
+ * c-omp.cc (omp_directives): Rename to ...
+ (c_omp_directives): ... this. No longer static. Uncomment
+ assume, assumes, begin assumes and end assumes entries.
+ In end declare target entry rename PRAGMA_OMP_END_DECLARE_TARGET
+ to PRAGMA_OMP_END.
+ (c_omp_categorize_directive): Adjust for omp_directives to
+ c_omp_directives renaming.
+
+2022-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/106652
+ PR c++/85518
+ * c-common.cc (c_common_reswords): Change _Float{16,32,64,128} and
+ _Float{32,64,128}x flags from D_CONLY to 0.
+ (shorten_binary_op): Punt if common_type returns error_mark_node.
+ (shorten_compare): Likewise.
+ (c_common_nodes_and_builtins): For C++ record _Float{16,32,64,128}
+ and _Float{32,64,128}x builtin types if available. For C++
+ clear float128t_type_node.
+ * c-cppbuiltin.cc (c_cpp_builtins): Predefine
+ __STDCPP_FLOAT{16,32,64,128}_T__ for C++23 if supported.
+ * c-lex.cc (interpret_float): For q/Q suffixes prefer
+ float128t_type_node over float128_type_node. Allow
+ {f,F}{16,32,64,128} suffixes for C++ if supported with pedwarn
+ for C++20 and older. Allow {f,F}{32,64,128}x suffixes for C++
+ with pedwarn. Don't call excess_precision_type for C++.
+
+2022-09-26 Marek Polacek <polacek@redhat.com>
+
+ PR c++/106656
+ * c-cppbuiltin.cc (c_cpp_builtins): Update value of __cpp_char8_t
+ for C++20.
+
2022-09-23 Marek Polacek <polacek@redhat.com>
PR c++/106784
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index dce3045..cda6910 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -352,13 +352,13 @@ const struct c_common_resword c_common_reswords[] =
{ "_Bool", RID_BOOL, D_CONLY },
{ "_Complex", RID_COMPLEX, 0 },
{ "_Imaginary", RID_IMAGINARY, D_CONLY },
- { "_Float16", RID_FLOAT16, D_CONLY },
- { "_Float32", RID_FLOAT32, D_CONLY },
- { "_Float64", RID_FLOAT64, D_CONLY },
- { "_Float128", RID_FLOAT128, D_CONLY },
- { "_Float32x", RID_FLOAT32X, D_CONLY },
- { "_Float64x", RID_FLOAT64X, D_CONLY },
- { "_Float128x", RID_FLOAT128X, D_CONLY },
+ { "_Float16", RID_FLOAT16, 0 },
+ { "_Float32", RID_FLOAT32, 0 },
+ { "_Float64", RID_FLOAT64, 0 },
+ { "_Float128", RID_FLOAT128, 0 },
+ { "_Float32x", RID_FLOAT32X, 0 },
+ { "_Float64x", RID_FLOAT64X, 0 },
+ { "_Float128x", RID_FLOAT128X, 0 },
{ "_Decimal32", RID_DFLOAT32, D_CONLY },
{ "_Decimal64", RID_DFLOAT64, D_CONLY },
{ "_Decimal128", RID_DFLOAT128, D_CONLY },
@@ -1431,8 +1431,11 @@ shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
== TYPE_PRECISION (TREE_TYPE (arg0)))
&& unsigned0 == unsigned1
&& (unsigned0 || !uns))
- return c_common_signed_or_unsigned_type
- (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
+ {
+ tree ctype = common_type (TREE_TYPE (arg0), TREE_TYPE (arg1));
+ if (ctype != error_mark_node)
+ return c_common_signed_or_unsigned_type (unsigned0, ctype);
+ }
else if (TREE_CODE (arg0) == INTEGER_CST
&& (unsigned1 || !uns)
@@ -3204,9 +3207,10 @@ shorten_compare (location_t loc, tree *op0_ptr, tree *op1_ptr,
else if (unsignedp0 == unsignedp1 && real1 == real2
&& TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (*restype_ptr)
- && TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (*restype_ptr))
+ && TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (*restype_ptr)
+ && (type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1)))
+ != error_mark_node)
{
- type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1));
type = c_common_signed_or_unsigned_type (unsignedp0
|| TYPE_UNSIGNED (*restype_ptr),
type);
@@ -4380,11 +4384,18 @@ c_common_nodes_and_builtins (void)
record_builtin_type (RID_DOUBLE, NULL, double_type_node);
record_builtin_type (RID_MAX, "long double", long_double_type_node);
- if (!c_dialect_cxx ())
- for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ {
if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE)
record_builtin_type ((enum rid) (RID_FLOATN_NX_FIRST + i), NULL,
FLOATN_NX_TYPE_NODE (i));
+ }
+
+ /* For C, let float128t_type_node (__float128 in some backends) be the
+ same type as float128_type_node (_Float128), for C++ let those
+ be distinct types that mangle and behave differently. */
+ if (c_dialect_cxx ())
+ float128t_type_node = NULL_TREE;
/* Only supported decimal floating point extension if the target
actually supports underlying modes. */
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 31397d8..50a4691 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1286,6 +1286,7 @@ struct c_omp_directive {
bool simd;
};
+extern const struct c_omp_directive c_omp_directives[];
extern const struct c_omp_directive *c_omp_categorize_directive (const char *,
const char *,
const char *);
diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc
index b709f84..d4de5a0 100644
--- a/gcc/c-family/c-cppbuiltin.cc
+++ b/gcc/c-family/c-cppbuiltin.cc
@@ -1081,6 +1081,8 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__cpp_constexpr=202110L");
cpp_define (pfile, "__cpp_multidimensional_subscript=202110L");
cpp_define (pfile, "__cpp_named_character_escapes=202207L");
+ cpp_define (pfile, "__cpp_static_call_operator=202207L");
+ cpp_define (pfile, "__cpp_implicit_move=202207L");
}
if (flag_concepts)
{
@@ -1246,6 +1248,14 @@ c_cpp_builtins (cpp_reader *pfile)
{
if (FLOATN_NX_TYPE_NODE (i) == NULL_TREE)
continue;
+ if (c_dialect_cxx ()
+ && cxx_dialect > cxx20
+ && !floatn_nx_types[i].extended)
+ {
+ char name[sizeof ("__STDCPP_FLOAT128_T__=1")];
+ sprintf (name, "__STDCPP_FLOAT%d_T__=1", floatn_nx_types[i].n);
+ cpp_define (pfile, name);
+ }
char prefix[20], csuffix[20];
sprintf (prefix, "FLT%d%s", floatn_nx_types[i].n,
floatn_nx_types[i].extended ? "X" : "");
diff --git a/gcc/c-family/c-format.cc b/gcc/c-family/c-format.cc
index a6c380b..a202659 100644
--- a/gcc/c-family/c-format.cc
+++ b/gcc/c-family/c-format.cc
@@ -2900,7 +2900,7 @@ static const token_t cxx_opers[] =
};
/* Common C/C++ keywords that are expected to be quoted within the format
- string. Keywords like auto, inline, or volatile are exccluded because
+ string. Keywords like auto, inline, or volatile are excluded because
they are sometimes used in common terms like /auto variables/, /inline
function/, or /volatile access/ where they should not be quoted. */
@@ -2927,7 +2927,6 @@ static const token_t c_keywords[] =
NAME ("noinline", NULL),
NAME ("nonnull", NULL),
NAME ("noreturn", NULL),
- NAME ("nothrow", NULL),
NAME ("offsetof", NULL),
NAME ("readonly", "read-only"),
NAME ("readwrite", "read-write"),
diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc
index 110d029..4d2252f 100644
--- a/gcc/c-family/c-lex.cc
+++ b/gcc/c-family/c-lex.cc
@@ -960,6 +960,10 @@ interpret_float (const cpp_token *token, unsigned int flags,
pedwarn (input_location, OPT_Wpedantic, "non-standard suffix on floating constant");
type = c_common_type_for_mode (mode, 0);
+ /* For Q suffix, prefer float128t_type_node (__float128) type
+ over float128_type_node (_Float128) type if they are distinct. */
+ if (type == float128_type_node && float128t_type_node)
+ type = float128t_type_node;
gcc_assert (type);
}
else if ((flags & (CPP_N_FLOATN | CPP_N_FLOATNX)) != 0)
@@ -979,8 +983,17 @@ interpret_float (const cpp_token *token, unsigned int flags,
error ("unsupported non-standard suffix on floating constant");
return error_mark_node;
}
+ else if (c_dialect_cxx () && !extended)
+ {
+ if (cxx_dialect < cxx23)
+ pedwarn (input_location, OPT_Wpedantic,
+ "%<f%d%> or %<F%d%> suffix on floating constant only "
+ "available with %<-std=c++2b%> or %<-std=gnu++2b%>",
+ n, n);
+ }
else
- pedwarn (input_location, OPT_Wpedantic, "non-standard suffix on floating constant");
+ pedwarn (input_location, OPT_Wpedantic,
+ "non-standard suffix on floating constant");
}
else if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
type = long_double_type_node;
@@ -990,7 +1003,10 @@ interpret_float (const cpp_token *token, unsigned int flags,
else
type = double_type_node;
- const_type = excess_precision_type (type);
+ if (c_dialect_cxx ())
+ const_type = NULL_TREE;
+ else
+ const_type = excess_precision_type (type);
if (!const_type)
const_type = type;
diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc
index 1b086d8..7a97c40 100644
--- a/gcc/c-family/c-omp.cc
+++ b/gcc/c-family/c-omp.cc
@@ -3097,21 +3097,21 @@ c_omp_adjust_map_clauses (tree clauses, bool is_target)
}
}
-static const struct c_omp_directive omp_directives[] = {
+const struct c_omp_directive c_omp_directives[] = {
/* Keep this alphabetically sorted by the first word. Non-null second/third
if any should precede null ones. */
{ "allocate", nullptr, nullptr, PRAGMA_OMP_ALLOCATE,
C_OMP_DIR_DECLARATIVE, false },
- /* { "assume", nullptr, nullptr, PRAGMA_OMP_ASSUME,
- C_OMP_DIR_INFORMATIONAL, false }, */
- /* { "assumes", nullptr, nullptr, PRAGMA_OMP_ASSUMES,
- C_OMP_DIR_INFORMATIONAL, false }, */
+ { "assume", nullptr, nullptr, PRAGMA_OMP_ASSUME,
+ C_OMP_DIR_INFORMATIONAL, false },
+ { "assumes", nullptr, nullptr, PRAGMA_OMP_ASSUMES,
+ C_OMP_DIR_INFORMATIONAL, false },
{ "atomic", nullptr, nullptr, PRAGMA_OMP_ATOMIC,
C_OMP_DIR_CONSTRUCT, false },
{ "barrier", nullptr, nullptr, PRAGMA_OMP_BARRIER,
C_OMP_DIR_STANDALONE, false },
- /* { "begin", "assumes", nullptr, PRAGMA_OMP_BEGIN,
- C_OMP_DIR_INFORMATIONAL, false }, */
+ { "begin", "assumes", nullptr, PRAGMA_OMP_BEGIN,
+ C_OMP_DIR_INFORMATIONAL, false },
/* { "begin", "declare", "target", PRAGMA_OMP_BEGIN,
C_OMP_DIR_DECLARATIVE, false }, */
/* { "begin", "declare", "variant", PRAGMA_OMP_BEGIN,
@@ -3140,9 +3140,9 @@ static const struct c_omp_directive omp_directives[] = {
C_OMP_DIR_CONSTRUCT, false }, */
{ "distribute", nullptr, nullptr, PRAGMA_OMP_DISTRIBUTE,
C_OMP_DIR_CONSTRUCT, true },
- /* { "end", "assumes", nullptr, PRAGMA_OMP_END,
- C_OMP_DIR_INFORMATIONAL, false }, */
- { "end", "declare", "target", PRAGMA_OMP_END_DECLARE_TARGET,
+ { "end", "assumes", nullptr, PRAGMA_OMP_END,
+ C_OMP_DIR_INFORMATIONAL, false },
+ { "end", "declare", "target", PRAGMA_OMP_END,
C_OMP_DIR_DECLARATIVE, false },
/* { "end", "declare", "variant", PRAGMA_OMP_END,
C_OMP_DIR_DECLARATIVE, false }, */
@@ -3224,26 +3224,26 @@ const struct c_omp_directive *
c_omp_categorize_directive (const char *first, const char *second,
const char *third)
{
- const size_t n_omp_directives = ARRAY_SIZE (omp_directives);
+ const size_t n_omp_directives = ARRAY_SIZE (c_omp_directives);
for (size_t i = 0; i < n_omp_directives; i++)
{
- if ((unsigned char) omp_directives[i].first[0]
+ if ((unsigned char) c_omp_directives[i].first[0]
< (unsigned char) first[0])
continue;
- if ((unsigned char) omp_directives[i].first[0]
+ if ((unsigned char) c_omp_directives[i].first[0]
> (unsigned char) first[0])
break;
- if (strcmp (omp_directives[i].first, first))
+ if (strcmp (c_omp_directives[i].first, first))
continue;
- if (!omp_directives[i].second)
- return &omp_directives[i];
- if (!second || strcmp (omp_directives[i].second, second))
+ if (!c_omp_directives[i].second)
+ return &c_omp_directives[i];
+ if (!second || strcmp (c_omp_directives[i].second, second))
continue;
- if (!omp_directives[i].third)
- return &omp_directives[i];
- if (!third || strcmp (omp_directives[i].third, third))
+ if (!c_omp_directives[i].third)
+ return &c_omp_directives[i];
+ if (!third || strcmp (c_omp_directives[i].third, third))
continue;
- return &omp_directives[i];
+ return &c_omp_directives[i];
}
return NULL;
}
diff --git a/gcc/c-family/c-pragma.cc b/gcc/c-family/c-pragma.cc
index 789719e..b5a4b3c 100644
--- a/gcc/c-family/c-pragma.cc
+++ b/gcc/c-family/c-pragma.cc
@@ -1546,14 +1546,16 @@ static const struct omp_pragma_def oacc_pragmas[] = {
};
static const struct omp_pragma_def omp_pragmas[] = {
{ "allocate", PRAGMA_OMP_ALLOCATE },
+ { "assumes", PRAGMA_OMP_ASSUMES },
{ "atomic", PRAGMA_OMP_ATOMIC },
{ "barrier", PRAGMA_OMP_BARRIER },
+ { "begin", PRAGMA_OMP_BEGIN },
{ "cancel", PRAGMA_OMP_CANCEL },
{ "cancellation", PRAGMA_OMP_CANCELLATION_POINT },
{ "critical", PRAGMA_OMP_CRITICAL },
{ "depobj", PRAGMA_OMP_DEPOBJ },
{ "error", PRAGMA_OMP_ERROR },
- { "end", PRAGMA_OMP_END_DECLARE_TARGET },
+ { "end", PRAGMA_OMP_END },
{ "flush", PRAGMA_OMP_FLUSH },
{ "nothing", PRAGMA_OMP_NOTHING },
{ "requires", PRAGMA_OMP_REQUIRES },
@@ -1568,6 +1570,7 @@ static const struct omp_pragma_def omp_pragmas[] = {
{ "threadprivate", PRAGMA_OMP_THREADPRIVATE }
};
static const struct omp_pragma_def omp_pragmas_simd[] = {
+ { "assume", PRAGMA_OMP_ASSUME },
{ "declare", PRAGMA_OMP_DECLARE },
{ "distribute", PRAGMA_OMP_DISTRIBUTE },
{ "for", PRAGMA_OMP_FOR },
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index c894a25..10a4053 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -45,8 +45,11 @@ enum pragma_kind {
/* PRAGMA_OMP__START_ should be equal to the first PRAGMA_OMP_* code. */
PRAGMA_OMP_ALLOCATE,
PRAGMA_OMP__START_ = PRAGMA_OMP_ALLOCATE,
+ PRAGMA_OMP_ASSUME,
+ PRAGMA_OMP_ASSUMES,
PRAGMA_OMP_ATOMIC,
PRAGMA_OMP_BARRIER,
+ PRAGMA_OMP_BEGIN,
PRAGMA_OMP_CANCEL,
PRAGMA_OMP_CANCELLATION_POINT,
PRAGMA_OMP_CRITICAL,
@@ -54,7 +57,7 @@ enum pragma_kind {
PRAGMA_OMP_DEPOBJ,
PRAGMA_OMP_DISTRIBUTE,
PRAGMA_OMP_ERROR,
- PRAGMA_OMP_END_DECLARE_TARGET,
+ PRAGMA_OMP_END,
PRAGMA_OMP_FLUSH,
PRAGMA_OMP_FOR,
PRAGMA_OMP_LOOP,
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 4b852b8..7b29d78 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,21 @@
+2022-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ * c-lang.h (current_omp_begin_assumes): Declare.
+ * c-parser.cc: Include bitmap.h.
+ (c_parser_omp_end_declare_target): Rename to ...
+ (c_parser_omp_end): ... this. Handle also end assumes.
+ (c_parser_omp_begin, c_parser_omp_assumption_clauses,
+ c_parser_omp_assumes, c_parser_omp_assume): New functions.
+ (c_parser_translation_unit): Also diagnose #pragma omp begin assumes
+ without corresponding #pragma omp end assumes.
+ (c_parser_pragma): Use %s in may only be used at file scope
+ diagnostics to decrease number of translatable messages. Handle
+ PRAGMA_OMP_BEGIN and PRAGMA_OMP_ASSUMES. Handle PRAGMA_OMP_END
+ rather than PRAGMA_OMP_END_DECLARE_TARGET and call c_parser_omp_end
+ for it rather than c_parser_omp_end_declare_target.
+ (c_parser_omp_construct): Handle PRAGMA_OMP_ASSUME.
+ * c-decl.cc (current_omp_begin_assumes): Define.
+
2022-09-24 Jakub Jelinek <jakub@redhat.com>
PR c/106981
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index b09c639..740982e 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -156,6 +156,10 @@ static bool undef_nested_function;
/* If non-zero, implicit "omp declare target" attribute is added into the
attribute lists. */
int current_omp_declare_target_attribute;
+
+/* If non-zero, we are inside of
+ #pragma omp begin assumes ... #pragma omp end assumes region. */
+int current_omp_begin_assumes;
/* Each c_binding structure describes one binding of an identifier to
a decl. All the decls in a scope - irrespective of namespace - are
diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h
index 7bdab47..861abe8 100644
--- a/gcc/c/c-lang.h
+++ b/gcc/c/c-lang.h
@@ -63,5 +63,8 @@ struct GTY(()) language_function {
/* If non-zero, implicit "omp declare target" attribute is added into the
attribute lists. */
extern GTY(()) int current_omp_declare_target_attribute;
+/* Similarly whether we are in between #pragma omp begin assumes and
+ #pragma omp end assumes (and how many times when nested). */
+extern GTY(()) int current_omp_begin_assumes;
#endif /* ! GCC_C_LANG_H */
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index bce79d3..f2498dc 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -71,6 +71,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pretty-print.h"
#include "memmodel.h"
#include "c-family/known-headers.h"
+#include "bitmap.h"
/* We need to walk over decls with incomplete struct/union/enum types
after parsing the whole translation unit.
@@ -1594,10 +1595,13 @@ enum pragma_context { pragma_external, pragma_struct, pragma_param,
static bool c_parser_pragma (c_parser *, enum pragma_context, bool *);
static bool c_parser_omp_cancellation_point (c_parser *, enum pragma_context);
static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *);
-static void c_parser_omp_end_declare_target (c_parser *);
+static void c_parser_omp_begin (c_parser *);
+static void c_parser_omp_end (c_parser *);
static bool c_parser_omp_declare (c_parser *, enum pragma_context);
static void c_parser_omp_requires (c_parser *);
static bool c_parser_omp_error (c_parser *, enum pragma_context);
+static void c_parser_omp_assumption_clauses (c_parser *, bool);
+static void c_parser_omp_assumes (c_parser *);
static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
static void c_parser_oacc_routine (c_parser *, enum pragma_context);
@@ -1678,6 +1682,13 @@ c_parser_translation_unit (c_parser *parser)
"%<#pragma omp end declare target%>");
current_omp_declare_target_attribute = 0;
}
+ if (current_omp_begin_assumes)
+ {
+ if (!errorcount)
+ error ("%<#pragma omp begin assumes%> without corresponding "
+ "%<#pragma omp end assumes%>");
+ current_omp_begin_assumes = 0;
+ }
}
/* Parse an external declaration (C90 6.7, C99 6.9, C11 6.9).
@@ -12594,8 +12605,12 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
case PRAGMA_OMP_TARGET:
return c_parser_omp_target (parser, context, if_p);
- case PRAGMA_OMP_END_DECLARE_TARGET:
- c_parser_omp_end_declare_target (parser);
+ case PRAGMA_OMP_BEGIN:
+ c_parser_omp_begin (parser);
+ return false;
+
+ case PRAGMA_OMP_END:
+ c_parser_omp_end (parser);
return false;
case PRAGMA_OMP_SCAN:
@@ -12619,13 +12634,26 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
if (context != pragma_external)
{
error_at (c_parser_peek_token (parser)->location,
- "%<#pragma omp requires%> may only be used at file scope");
+ "%<#pragma %s%> may only be used at file scope",
+ "omp requires");
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
return false;
}
c_parser_omp_requires (parser);
return false;
+ case PRAGMA_OMP_ASSUMES:
+ if (context != pragma_external)
+ {
+ error_at (c_parser_peek_token (parser)->location,
+ "%<#pragma %s%> may only be used at file scope",
+ "omp assumes");
+ c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+ return false;
+ }
+ c_parser_omp_assumes (parser);
+ return false;
+
case PRAGMA_OMP_NOTHING:
c_parser_omp_nothing (parser);
return false;
@@ -22405,14 +22433,44 @@ c_parser_omp_declare_target (c_parser *parser)
"directive with only %<device_type%> clauses ignored");
}
+/* OpenMP 5.1
+ #pragma omp begin assumes clauses[optseq] new-line */
+
+static void
+c_parser_omp_begin (c_parser *parser)
+{
+ const char *p = "";
+ c_parser_consume_pragma (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "assumes") == 0)
+ {
+ c_parser_consume_token (parser);
+ c_parser_omp_assumption_clauses (parser, false);
+ current_omp_begin_assumes++;
+ }
+ else
+ {
+ c_parser_error (parser, "expected %<assumes%>");
+ c_parser_skip_to_pragma_eol (parser);
+ }
+}
+
+/* OpenMP 4.0
+ #pragma omp end declare target
+
+ OpenMP 5.1
+ #pragma omp end assumes */
+
static void
-c_parser_omp_end_declare_target (c_parser *parser)
+c_parser_omp_end (c_parser *parser)
{
location_t loc = c_parser_peek_token (parser)->location;
+ const char *p = "";
c_parser_consume_pragma (parser);
- if (c_parser_next_token_is (parser, CPP_NAME)
- && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
- "declare") == 0)
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "declare") == 0)
{
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_NAME)
@@ -22425,22 +22483,30 @@ c_parser_omp_end_declare_target (c_parser *parser)
c_parser_skip_to_pragma_eol (parser);
return;
}
+ c_parser_skip_to_pragma_eol (parser);
+ if (!current_omp_declare_target_attribute)
+ error_at (loc, "%<#pragma omp end declare target%> without "
+ "corresponding %<#pragma omp declare target%>");
+ else
+ current_omp_declare_target_attribute--;
}
- else
+ else if (strcmp (p, "assumes") == 0)
{
- c_parser_error (parser, "expected %<declare%>");
+ c_parser_consume_token (parser);
c_parser_skip_to_pragma_eol (parser);
- return;
+ if (!current_omp_begin_assumes)
+ error_at (loc, "%<#pragma omp end assumes%> without "
+ "corresponding %<#pragma omp begin assumes%>");
+ else
+ current_omp_begin_assumes--;
}
- c_parser_skip_to_pragma_eol (parser);
- if (!current_omp_declare_target_attribute)
- error_at (loc, "%<#pragma omp end declare target%> without corresponding "
- "%<#pragma omp declare target%>");
else
- current_omp_declare_target_attribute--;
+ {
+ c_parser_error (parser, "expected %<declare%> or %<assumes%>");
+ c_parser_skip_to_pragma_eol (parser);
+ }
}
-
/* OpenMP 4.0
#pragma omp declare reduction (reduction-id : typename-list : expression) \
initializer-clause[opt] new-line
@@ -23299,6 +23365,211 @@ c_parser_omp_error (c_parser *parser, enum pragma_context context)
return false;
}
+/* Assumption clauses:
+ OpenMP 5.1
+ absent (directive-name-list)
+ contains (directive-name-list)
+ holds (expression)
+ no_openmp
+ no_openmp_routines
+ no_parallelism */
+
+static void
+c_parser_omp_assumption_clauses (c_parser *parser, bool is_assume)
+{
+ bool first = true;
+ bool no_openmp = false;
+ bool no_openmp_routines = false;
+ bool no_parallelism = false;
+ bitmap_head absent_head, contains_head;
+
+ bitmap_obstack_initialize (NULL);
+ bitmap_initialize (&absent_head, &bitmap_default_obstack);
+ bitmap_initialize (&contains_head, &bitmap_default_obstack);
+
+ if (c_parser_next_token_is (parser, CPP_PRAGMA_EOL))
+ error_at (c_parser_peek_token (parser)->location,
+ "expected at least one assumption clause");
+
+ while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+ {
+ if (!first
+ && c_parser_next_token_is (parser, CPP_COMMA)
+ && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
+ c_parser_consume_token (parser);
+
+ first = false;
+
+ if (!c_parser_next_token_is (parser, CPP_NAME))
+ break;
+
+ const char *p
+ = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ location_t cloc = c_parser_peek_token (parser)->location;
+
+ if (!strcmp (p, "no_openmp"))
+ {
+ c_parser_consume_token (parser);
+ if (no_openmp)
+ error_at (cloc, "too many %qs clauses", "no_openmp");
+ no_openmp = true;
+ }
+ else if (!strcmp (p, "no_openmp_routines"))
+ {
+ c_parser_consume_token (parser);
+ if (no_openmp_routines)
+ error_at (cloc, "too many %qs clauses", "no_openmp_routines");
+ no_openmp_routines = true;
+ }
+ else if (!strcmp (p, "no_parallelism"))
+ {
+ c_parser_consume_token (parser);
+ if (no_parallelism)
+ error_at (cloc, "too many %qs clauses", "no_parallelism");
+ no_parallelism = true;
+ }
+ else if (!strcmp (p, "holds"))
+ {
+ c_parser_consume_token (parser);
+ matching_parens parens;
+ if (parens.require_open (parser))
+ {
+ location_t eloc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ tree t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
+ t = c_objc_common_truthvalue_conversion (eloc, t);
+ t = c_fully_fold (t, false, NULL);
+ if (is_assume)
+ {
+ /* FIXME: Emit .ASSUME (t) call here. */
+ (void) t;
+ }
+ parens.skip_until_found_close (parser);
+ }
+ }
+ else if (!strcmp (p, "absent") || !strcmp (p, "contains"))
+ {
+ c_parser_consume_token (parser);
+ matching_parens parens;
+ if (parens.require_open (parser))
+ {
+ do
+ {
+ const char *directive[3] = {};
+ int i;
+ location_t dloc = c_parser_peek_token (parser)->location;
+ for (i = 0; i < 3; i++)
+ {
+ tree id;
+ if (c_parser_peek_nth_token (parser, i + 1)->type
+ == CPP_NAME)
+ id = c_parser_peek_nth_token (parser, i + 1)->value;
+ else if (c_parser_peek_nth_token (parser, i + 1)->keyword
+ != RID_MAX)
+ {
+ enum rid rid
+ = c_parser_peek_nth_token (parser, i + 1)->keyword;
+ id = ridpointers[rid];
+ }
+ else
+ break;
+ directive[i] = IDENTIFIER_POINTER (id);
+ }
+ if (i == 0)
+ error_at (dloc, "expected directive name");
+ else
+ {
+ const struct c_omp_directive *dir
+ = c_omp_categorize_directive (directive[0],
+ directive[1],
+ directive[2]);
+ if (dir == NULL
+ || dir->kind == C_OMP_DIR_DECLARATIVE
+ || dir->kind == C_OMP_DIR_INFORMATIONAL
+ || dir->id == PRAGMA_OMP_END
+ || (!dir->second && directive[1])
+ || (!dir->third && directive[2]))
+ error_at (dloc, "unknown OpenMP directive name in "
+ "%qs clause argument", p);
+ else
+ {
+ int id = dir - c_omp_directives;
+ if (bitmap_bit_p (p[0] == 'a' ? &contains_head
+ : &absent_head, id))
+ error_at (dloc, "%<%s%s%s%s%s%> directive "
+ "mentioned in both %<absent%> and "
+ "%<contains%> clauses",
+ directive[0],
+ directive[1] ? " " : "",
+ directive[1] ? directive[1] : "",
+ directive[2] ? " " : "",
+ directive[2] ? directive[2] : "");
+ else if (!bitmap_set_bit (p[0] == 'a'
+ ? &absent_head
+ : &contains_head, id))
+ error_at (dloc, "%<%s%s%s%s%s%> directive "
+ "mentioned multiple times in %qs "
+ "clauses",
+ directive[0],
+ directive[1] ? " " : "",
+ directive[1] ? directive[1] : "",
+ directive[2] ? " " : "",
+ directive[2] ? directive[2] : "", p);
+ }
+ for (; i; --i)
+ c_parser_consume_token (parser);
+ }
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else
+ break;
+ }
+ while (1);
+ parens.skip_until_found_close (parser);
+ }
+ }
+ else if (startswith (p, "ext_"))
+ {
+ warning_at (cloc, 0, "unknown assumption clause %qs", p);
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ {
+ matching_parens parens;
+ parens.consume_open (parser);
+ c_parser_balanced_token_sequence (parser);
+ parens.require_close (parser);
+ }
+ }
+ else
+ {
+ c_parser_consume_token (parser);
+ error_at (cloc, "expected assumption clause");
+ break;
+ }
+ }
+ c_parser_skip_to_pragma_eol (parser);
+}
+
+/* OpenMP 5.1
+ #pragma omp assume clauses[optseq] new-line */
+
+static void
+c_parser_omp_assume (c_parser *parser, bool *if_p)
+{
+ c_parser_omp_assumption_clauses (parser, true);
+ add_stmt (c_parser_omp_structured_block (parser, if_p));
+}
+
+/* OpenMP 5.1
+ #pragma omp assumes clauses[optseq] new-line */
+
+static void
+c_parser_omp_assumes (c_parser *parser)
+{
+ c_parser_consume_pragma (parser);
+ c_parser_omp_assumption_clauses (parser, false);
+}
+
/* Main entry point to parsing most OpenMP pragmas. */
static void
@@ -23404,6 +23675,9 @@ c_parser_omp_construct (c_parser *parser, bool *if_p)
strcpy (p_name, "#pragma omp");
stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL, if_p);
break;
+ case PRAGMA_OMP_ASSUME:
+ c_parser_omp_assume (parser, if_p);
+ return;
default:
gcc_unreachable ();
}
diff --git a/gcc/calls.cc b/gcc/calls.cc
index bc96aff..6dd6f73 100644
--- a/gcc/calls.cc
+++ b/gcc/calls.cc
@@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not see
#include "attr-fnspec.h"
#include "value-query.h"
#include "tree-pretty-print.h"
+#include "tree-eh.h"
/* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits. */
#define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
@@ -3154,7 +3155,10 @@ expand_call (tree exp, rtx target, int ignore)
if (pass && (flags & ECF_MALLOC))
start_sequence ();
- if (pass == 0
+ /* Check the canary value for sibcall or function which doesn't
+ return and could throw. */
+ if ((pass == 0
+ || ((flags & ECF_NORETURN) != 0 && tree_could_throw_p (exp)))
&& crtl->stack_protect_guard
&& targetm.stack_protect_runtime_enabled_p ())
stack_protect_epilogue ();
diff --git a/gcc/cfghooks.cc b/gcc/cfghooks.cc
index c6ac953..29ded57 100644
--- a/gcc/cfghooks.cc
+++ b/gcc/cfghooks.cc
@@ -541,7 +541,6 @@ split_block_1 (basic_block bb, void *i)
return NULL;
new_bb->count = bb->count;
- new_bb->discriminator = bb->discriminator;
if (dom_info_available_p (CDI_DOMINATORS))
{
diff --git a/gcc/cfgrtl.cc b/gcc/cfgrtl.cc
index 90cd6ee..281a432 100644
--- a/gcc/cfgrtl.cc
+++ b/gcc/cfgrtl.cc
@@ -4049,7 +4049,8 @@ fixup_reorder_chain (void)
rtx_insn *ret, *use;
basic_block dest;
if (bb_is_just_return (e_fall->dest, &ret, &use)
- && (PATTERN (ret) == simple_return_rtx || PATTERN (ret) == ret_rtx))
+ && ((PATTERN (ret) == simple_return_rtx && targetm.have_simple_return ())
+ || (PATTERN (ret) == ret_rtx && targetm.have_return ())))
{
ret_label = PATTERN (ret);
dest = EXIT_BLOCK_PTR_FOR_FN (cfun);
diff --git a/gcc/config.gcc b/gcc/config.gcc
index c1b1215..7eb0787 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -516,6 +516,7 @@ pru-*-*)
riscv*)
cpu_type=riscv
extra_objs="riscv-builtins.o riscv-c.o riscv-sr.o riscv-shorten-memrefs.o riscv-selftests.o"
+ extra_objs="${extra_objs} riscv-vector-builtins.o"
d_target_objs="riscv-d.o"
;;
rs6000*-*-*)
diff --git a/gcc/config/arm/arm-c.cc b/gcc/config/arm/arm-c.cc
index a8697b8..86c56bf 100644
--- a/gcc/config/arm/arm-c.cc
+++ b/gcc/config/arm/arm-c.cc
@@ -202,6 +202,8 @@ arm_cpu_builtins (struct cpp_reader* pfile)
def_or_undef_macro (pfile, "__ARM_FEATURE_QBIT", TARGET_ARM_QBIT);
def_or_undef_macro (pfile, "__ARM_FEATURE_SAT", TARGET_ARM_SAT);
def_or_undef_macro (pfile, "__ARM_FEATURE_CRYPTO", TARGET_CRYPTO);
+ def_or_undef_macro (pfile, "__ARM_FEATURE_AES", TARGET_CRYPTO);
+ def_or_undef_macro (pfile, "__ARM_FEATURE_SHA2", TARGET_CRYPTO);
def_or_undef_macro (pfile, "__ARM_FEATURE_UNALIGNED", unaligned_access);
diff --git a/gcc/config/i386/avx512fp16intrin.h b/gcc/config/i386/avx512fp16intrin.h
index 2804151..75f7475 100644
--- a/gcc/config/i386/avx512fp16intrin.h
+++ b/gcc/config/i386/avx512fp16intrin.h
@@ -183,21 +183,21 @@ extern __inline __m128h
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm_setzero_ph (void)
{
- return _mm_set1_ph (0.0f);
+ return _mm_set1_ph (0.0f16);
}
extern __inline __m256h
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm256_setzero_ph (void)
{
- return _mm256_set1_ph (0.0f);
+ return _mm256_set1_ph (0.0f16);
}
extern __inline __m512h
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm512_setzero_ph (void)
{
- return _mm512_set1_ph (0.0f);
+ return _mm512_set1_ph (0.0f16);
}
extern __inline __m128h
@@ -358,7 +358,8 @@ extern __inline __m128h
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm_set_sh (_Float16 __F)
{
- return _mm_set_ph (0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, __F);
+ return _mm_set_ph (0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16,
+ __F);
}
/* Create a vector with element 0 as *P and the rest zero. */
@@ -366,7 +367,7 @@ extern __inline __m128h
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm_load_sh (void const *__P)
{
- return _mm_set_ph (0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ return _mm_set_ph (0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16,
*(_Float16 const *) __P);
}
diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc
index af2faee..b91aba1 100644
--- a/gcc/config/i386/i386-builtins.cc
+++ b/gcc/config/i386/i386-builtins.cc
@@ -1409,9 +1409,18 @@ ix86_init_builtin_types (void)
lang_hooks.types.register_builtin_type (float80_type_node, "__float80");
/* The __float128 type. The node has already been created as
- _Float128, so we only need to register the __float128 name for
- it. */
- lang_hooks.types.register_builtin_type (float128_type_node, "__float128");
+ _Float128, so for C we only need to register the __float128 name for
+ it. For C++, we create a distinct type which will mangle differently
+ (g) vs. _Float128 (DF128_) and behave backwards compatibly. */
+ if (float128t_type_node == NULL_TREE)
+ {
+ float128t_type_node = make_node (REAL_TYPE);
+ TYPE_PRECISION (float128t_type_node)
+ = TYPE_PRECISION (float128_type_node);
+ SET_TYPE_MODE (float128t_type_node, TYPE_MODE (float128_type_node));
+ layout_type (float128t_type_node);
+ }
+ lang_hooks.types.register_builtin_type (float128t_type_node, "__float128");
ix86_register_float16_builtin_type ();
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index ca799da..4386caf 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -22735,7 +22735,10 @@ ix86_mangle_type (const_tree type)
return "DF16_";
case E_TFmode:
/* __float128 is "g". */
- return "g";
+ if (type == float128t_type_node)
+ return "g";
+ /* _Float128 should mangle as "DF128_" done in generic code. */
+ return NULL;
case E_XFmode:
/* "long double" or __float80 is "e". */
return "e";
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 655eabf..c4141a9 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -2107,11 +2107,11 @@
for(i = 4; i < 7; i++)
{
elt = XVECEXP (op, 0, i);
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_DEST (elt)) != REG
- || GET_MODE (SET_DEST (elt)) != V2DImode
- || REGNO (SET_DEST (elt)) != GET_SSE_REGNO (i)
- || SET_SRC (elt) != CONST0_RTX (V2DImode))
+ if (GET_CODE (elt) != CLOBBER
+ || GET_MODE (elt) != VOIDmode
+ || GET_CODE (XEXP (elt, 0)) != REG
+ || GET_MODE (XEXP (elt, 0)) != V2DImode
+ || REGNO (XEXP (elt, 0)) != GET_SSE_REGNO (i))
return false;
}
@@ -2157,11 +2157,11 @@
for(i = 4; i < 7; i++)
{
elt = XVECEXP (op, 0, i + 1);
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_DEST (elt)) != REG
- || GET_MODE (SET_DEST (elt)) != V2DImode
- || REGNO (SET_DEST (elt)) != GET_SSE_REGNO (i)
- || SET_SRC (elt) != CONST0_RTX (V2DImode))
+ if (GET_CODE (elt) != CLOBBER
+ || GET_MODE (elt) != VOIDmode
+ || GET_CODE (XEXP (elt, 0)) != REG
+ || GET_MODE (XEXP (elt, 0)) != V2DImode
+ || REGNO (XEXP (elt, 0)) != GET_SSE_REGNO (i))
return false;
}
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 5c18963..076064f 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -29015,7 +29015,7 @@
for (i = 4; i < 7; i++)
XVECEXP (operands[2], 0, i)
- = gen_rtx_SET (xmm_regs[i], CONST0_RTX (V2DImode));
+ = gen_rtx_CLOBBER (VOIDmode, xmm_regs[i]);
XVECEXP (operands[2], 0, 7)
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
@@ -29072,7 +29072,7 @@
for (i = 4; i < 7; i++)
XVECEXP (operands[2], 0, i + 1)
- = gen_rtx_SET (xmm_regs[i], CONST0_RTX (V2DImode));
+ = gen_rtx_CLOBBER (VOIDmode, xmm_regs[i]);
XVECEXP (operands[2], 0, 8)
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
diff --git a/gcc/config/ia64/ia64.cc b/gcc/config/ia64/ia64.cc
index 50ae7aa..d510573 100644
--- a/gcc/config/ia64/ia64.cc
+++ b/gcc/config/ia64/ia64.cc
@@ -10466,11 +10466,19 @@ ia64_init_builtins (void)
= build_pointer_type (build_qualified_type
(char_type_node, TYPE_QUAL_CONST));
- (*lang_hooks.types.register_builtin_type) (float128_type_node,
+ if (float128t_type_node == NULL_TREE)
+ {
+ float128t_type_node = make_node (REAL_TYPE);
+ TYPE_PRECISION (float128t_type_node)
+ = TYPE_PRECISION (float128_type_node);
+ layout_type (float128t_type_node);
+ SET_TYPE_MODE (float128t_type_node, TYPE_MODE (float128_type_node));
+ }
+ (*lang_hooks.types.register_builtin_type) (float128t_type_node,
"__float128");
/* TFmode support builtins. */
- ftype = build_function_type_list (float128_type_node, NULL_TREE);
+ ftype = build_function_type_list (float128t_type_node, NULL_TREE);
decl = add_builtin_function ("__builtin_infq", ftype,
IA64_BUILTIN_INFQ, BUILT_IN_MD,
NULL, NULL_TREE);
@@ -10481,7 +10489,7 @@ ia64_init_builtins (void)
NULL, NULL_TREE);
ia64_builtins[IA64_BUILTIN_HUGE_VALQ] = decl;
- ftype = build_function_type_list (float128_type_node,
+ ftype = build_function_type_list (float128t_type_node,
const_string_type,
NULL_TREE);
decl = add_builtin_function ("__builtin_nanq", ftype,
@@ -10496,8 +10504,8 @@ ia64_init_builtins (void)
TREE_READONLY (decl) = 1;
ia64_builtins[IA64_BUILTIN_NANSQ] = decl;
- ftype = build_function_type_list (float128_type_node,
- float128_type_node,
+ ftype = build_function_type_list (float128t_type_node,
+ float128t_type_node,
NULL_TREE);
decl = add_builtin_function ("__builtin_fabsq", ftype,
IA64_BUILTIN_FABSQ, BUILT_IN_MD,
@@ -10505,9 +10513,9 @@ ia64_init_builtins (void)
TREE_READONLY (decl) = 1;
ia64_builtins[IA64_BUILTIN_FABSQ] = decl;
- ftype = build_function_type_list (float128_type_node,
- float128_type_node,
- float128_type_node,
+ ftype = build_function_type_list (float128t_type_node,
+ float128t_type_node,
+ float128t_type_node,
NULL_TREE);
decl = add_builtin_function ("__builtin_copysignq", ftype,
IA64_BUILTIN_COPYSIGNQ, BUILT_IN_MD,
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index 98c0e26..e9ba337 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -6472,7 +6472,7 @@ static unsigned HOST_WIDE_INT
loongarch_asan_shadow_offset (void)
{
/* We only have libsanitizer support for LOONGARCH64 at present.
- This value is taken from the file libsanitizer/asan/asan_mappint.h. */
+ This value is taken from the file libsanitizer/asan/asan_mapping.h. */
return TARGET_64BIT ? (HOST_WIDE_INT_1 << 46) : 0;
}
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
index 3787fd8..214b14b 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -35,6 +35,8 @@
;; Floating point unspecs.
UNSPEC_FRINT
UNSPEC_FCLASS
+ UNSPEC_FMAX
+ UNSPEC_FMIN
;; Override return address for exception handling.
UNSPEC_EH_RETURN
@@ -1032,8 +1034,9 @@
(define_insn "fmax<mode>3"
[(set (match_operand:ANYF 0 "register_operand" "=f")
- (smax:ANYF (match_operand:ANYF 1 "register_operand" "f")
- (match_operand:ANYF 2 "register_operand" "f")))]
+ (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" "f"))
+ (use (match_operand:ANYF 2 "register_operand" "f"))]
+ UNSPEC_FMAX))]
""
"fmax.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmove")
@@ -1041,8 +1044,9 @@
(define_insn "fmin<mode>3"
[(set (match_operand:ANYF 0 "register_operand" "=f")
- (smin:ANYF (match_operand:ANYF 1 "register_operand" "f")
- (match_operand:ANYF 2 "register_operand" "f")))]
+ (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" "f"))
+ (use (match_operand:ANYF 2 "register_operand" "f"))]
+ UNSPEC_FMIN))]
""
"fmin.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmove")
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index 3009311..a51037a 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "stringpool.h"
#include "expr.h"
#include "langhooks.h"
+#include "riscv-vector-builtins.h"
/* Macros to create an enumeration identifier for a function prototype. */
#define RISCV_FTYPE_NAME0(A) RISCV_##A##_FTYPE
@@ -213,6 +214,7 @@ void
riscv_init_builtins (void)
{
riscv_init_builtin_types ();
+ riscv_vector::init_builtins ();
for (size_t i = 0; i < ARRAY_SIZE (riscv_builtins); i++)
{
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index f9a2baa..101361a 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -75,6 +75,7 @@ extern bool riscv_store_data_bypass_p (rtx_insn *, rtx_insn *);
extern rtx riscv_gen_gpr_save_insn (struct riscv_frame_info *);
extern bool riscv_gpr_save_operation_p (rtx);
extern void riscv_reinit (void);
+extern bool riscv_v_ext_enabled_vector_mode_p (machine_mode);
/* Routines implemented in riscv-c.cc. */
void riscv_cpu_cpp_builtins (cpp_reader *);
diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
new file mode 100644
index 0000000..019a40d
--- /dev/null
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -0,0 +1,279 @@
+/* Builtins implementation for RISC-V 'V' Extension for GNU compiler.
+ Copyright (C) 2022-2022 Free Software Foundation, Inc.
+ Contributed by Ju-Zhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#define IN_TARGET_CODE 1
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "memmodel.h"
+#include "insn-codes.h"
+#include "optabs.h"
+#include "recog.h"
+#include "diagnostic.h"
+#include "expr.h"
+#include "function.h"
+#include "fold-const.h"
+#include "gimplify.h"
+#include "explow.h"
+#include "stor-layout.h"
+#include "alias.h"
+#include "langhooks.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "targhooks.h"
+#include "regs.h"
+#include "riscv-vector-builtins.h"
+
+namespace riscv_vector {
+
+/* Information about each RVV type. */
+static CONSTEXPR const vector_type_info vector_types[] = {
+#define DEF_RVV_TYPE(USER_NAME, NCHARS, ABI_NAME, ARGS...) \
+ {#USER_NAME, #ABI_NAME, "u" #NCHARS #ABI_NAME},
+#include "riscv-vector-builtins.def"
+};
+
+/* The scalar type associated with each vector type. */
+static GTY (()) tree scalar_types[NUM_VECTOR_TYPES];
+/* The machine mode associated with each vector type. */
+static GTY (()) machine_mode vector_modes[NUM_VECTOR_TYPES];
+/* The RVV types, with their built-in
+ "__rvv..._t" name. Allow an index of NUM_VECTOR_TYPES, which always
+ yields a null tree. */
+static GTY(()) tree abi_vector_types[NUM_VECTOR_TYPES + 1];
+
+rvv_switcher::rvv_switcher ()
+{
+ /* Set have_regs_of_mode before targetm.init_builtins (). */
+ memcpy (m_old_have_regs_of_mode, have_regs_of_mode,
+ sizeof (have_regs_of_mode));
+ for (int i = 0; i < NUM_MACHINE_MODES; ++i)
+ if (riscv_v_ext_enabled_vector_mode_p ((machine_mode) i))
+ have_regs_of_mode[i] = true;
+}
+
+rvv_switcher::~rvv_switcher ()
+{
+ /* Recover back have_regs_of_mode. */
+ memcpy (have_regs_of_mode, m_old_have_regs_of_mode,
+ sizeof (have_regs_of_mode));
+}
+
+/* Add type attributes to builtin type tree, currently only the mangled name. */
+static void
+add_vector_type_attribute (tree type, const char *mangled_name)
+{
+ tree mangled_name_tree = get_identifier (mangled_name);
+ tree value = tree_cons (NULL_TREE, mangled_name_tree, NULL_TREE);
+ TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("RVV type"), value,
+ TYPE_ATTRIBUTES (type));
+}
+
+/* Force TYPE to be a sizeless type. */
+static void
+make_type_sizeless (tree type)
+{
+ TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("RVV sizeless type"),
+ NULL_TREE, TYPE_ATTRIBUTES (type));
+}
+
+/* Return true if TYPE is a sizeless type. */
+static bool
+sizeless_type_p (const_tree type)
+{
+ if (type == error_mark_node)
+ return NULL_TREE;
+ return lookup_attribute ("RVV sizeless type", TYPE_ATTRIBUTES (type));
+}
+
+/* If TYPE is an ABI-defined RVV type, return its attribute descriptor,
+ otherwise return null. */
+static tree
+lookup_vector_type_attribute (const_tree type)
+{
+ if (type == error_mark_node)
+ return NULL_TREE;
+ return lookup_attribute ("RVV type", TYPE_ATTRIBUTES (type));
+}
+
+/* If TYPE is a built-in type defined by the RVV ABI, return the mangled name,
+ otherwise return NULL. */
+const char *
+mangle_builtin_type (const_tree type)
+{
+ if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
+ type = TREE_TYPE (TYPE_NAME (type));
+ if (tree attr = lookup_vector_type_attribute (type))
+ if (tree id = TREE_VALUE (chain_index (0, TREE_VALUE (attr))))
+ return IDENTIFIER_POINTER (id);
+ return NULL;
+}
+
+/* Register the built-in RVV ABI types, such as __rvv_int32m1_t. */
+static void
+register_builtin_types ()
+{
+ /* int32_t/uint32_t defined as `long`/`unsigned long` in RV32,
+ but intSI_type_node/unsigned_intSI_type_node is
+ `int` and `unsigned int`, so use long_integer_type_node and
+ long_unsigned_type_node here for type consistent. */
+ tree int32_type_node
+ = TARGET_64BIT ? intSI_type_node : long_integer_type_node;
+ tree unsigned_int32_type_node
+ = TARGET_64BIT ? unsigned_intSI_type_node : long_unsigned_type_node;
+
+ machine_mode mode;
+#define DEF_RVV_TYPE(USER_NAME, NCHARS, ABI_NAME, SCALAR_TYPE, VECTOR_MODE, \
+ VECTOR_MODE_MIN_VLEN_32) \
+ mode = TARGET_MIN_VLEN > 32 ? VECTOR_MODE##mode \
+ : VECTOR_MODE_MIN_VLEN_32##mode; \
+ scalar_types[VECTOR_TYPE_##USER_NAME] \
+ = riscv_v_ext_enabled_vector_mode_p (mode) ? SCALAR_TYPE##_type_node \
+ : NULL_TREE; \
+ vector_modes[VECTOR_TYPE_##USER_NAME] \
+ = riscv_v_ext_enabled_vector_mode_p (mode) ? mode : VOIDmode;
+#include "riscv-vector-builtins.def"
+
+ for (unsigned int i = 0; i < NUM_VECTOR_TYPES; ++i)
+ {
+ tree eltype = scalar_types[i];
+ mode = vector_modes[i];
+ /* We disabled the datatypes according '-march'. */
+ if (!eltype)
+ continue;
+
+ tree vectype = build_vector_type_for_mode (eltype, mode);
+ gcc_assert (
+ VECTOR_MODE_P (TYPE_MODE (vectype)) && TYPE_MODE (vectype) == mode
+ && TYPE_MODE_RAW (vectype) == mode && TYPE_ALIGN (vectype) <= 128
+ && known_eq (tree_to_poly_uint64 (TYPE_SIZE (vectype)),
+ GET_MODE_BITSIZE (mode)));
+ vectype = build_distinct_type_copy (vectype);
+ gcc_assert (vectype == TYPE_MAIN_VARIANT (vectype));
+ SET_TYPE_STRUCTURAL_EQUALITY (vectype);
+ TYPE_ARTIFICIAL (vectype) = 1;
+ TYPE_INDIVISIBLE_P (vectype) = 1;
+ add_vector_type_attribute (vectype, vector_types[i].mangled_name);
+ make_type_sizeless (vectype);
+ abi_vector_types[i] = vectype;
+ lang_hooks.types.register_builtin_type (vectype,
+ vector_types[i].abi_name);
+ }
+}
+
+/* Initialize all compiler built-ins related to RVV that should be
+ defined at start-up. */
+void
+init_builtins ()
+{
+ rvv_switcher rvv;
+ if (!TARGET_VECTOR)
+ return;
+ register_builtin_types ();
+}
+
+/* Implement TARGET_VERIFY_TYPE_CONTEXT for RVV types. */
+bool
+verify_type_context (location_t loc, type_context_kind context, const_tree type,
+ bool silent_p)
+{
+ if (!sizeless_type_p (type))
+ return true;
+
+ switch (context)
+ {
+ case TCTX_SIZEOF:
+ case TCTX_STATIC_STORAGE:
+ if (!silent_p)
+ error_at (loc, "RVV type %qT does not have a fixed size", type);
+
+ return false;
+
+ case TCTX_ALIGNOF:
+ if (!silent_p)
+ error_at (loc, "RVV type %qT does not have a defined alignment", type);
+
+ return false;
+
+ case TCTX_THREAD_STORAGE:
+ if (!silent_p)
+ error_at (loc,
+ "variables of type %qT cannot have thread-local"
+ " storage duration",
+ type);
+
+ return false;
+
+ case TCTX_POINTER_ARITH:
+ if (!silent_p)
+ error_at (loc, "arithmetic on pointer to RVV type %qT", type);
+
+ return false;
+
+ case TCTX_FIELD:
+ if (silent_p)
+ ;
+ else if (lang_GNU_CXX ())
+ error_at (loc, "member variables cannot have RVV type %qT", type);
+ else
+ error_at (loc, "fields cannot have RVV type %qT", type);
+
+ return false;
+
+ case TCTX_ARRAY_ELEMENT:
+ if (!silent_p)
+ error_at (loc, "array elements cannot have RVV type %qT", type);
+
+ return false;
+
+ case TCTX_ALLOCATION:
+ if (!silent_p)
+ error_at (loc, "cannot allocate objects with RVV type %qT", type);
+
+ return false;
+
+ case TCTX_DEALLOCATION:
+ if (!silent_p)
+ error_at (loc, "cannot delete objects with RVV type %qT", type);
+
+ return false;
+
+ case TCTX_EXCEPTIONS:
+ if (!silent_p)
+ error_at (loc, "cannot throw or catch RVV type %qT", type);
+
+ return false;
+
+ case TCTX_CAPTURE_BY_COPY:
+ if (!silent_p)
+ error_at (loc, "capture by copy of RVV type %qT", type);
+
+ return false;
+ }
+
+ gcc_unreachable ();
+}
+
+} // end namespace riscv_vector
diff --git a/gcc/config/riscv/riscv-vector-builtins.def b/gcc/config/riscv/riscv-vector-builtins.def
new file mode 100644
index 0000000..a9001b3
--- /dev/null
+++ b/gcc/config/riscv/riscv-vector-builtins.def
@@ -0,0 +1,199 @@
+/* Builtins macros for RISC-V 'V' Extension for GNU compiler.
+ Copyright (C) 2022-2022 Free Software Foundation, Inc.
+ Contributed by Ju-Zhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* Use "DEF_RVV_TYPE" macro to define RVV datatype builtins.
+ 1.The 1 argument is the name exposed to users.
+ For example, "vint32m1_t".
+ 2.The 2 argument is the length of ABI-name.
+ For example, length of "__rvv_int32m1_t" is 15.
+ 3.The 3 argument is the ABI-name. For example, "__rvv_int32m1_t".
+ 4.The 4 argument is associated scalar type which is used in
+ "build_vector_type_for_mode". For "vint32m1_t", we use "intSI_type_node" in
+ RV64. Otherwise, we use "long_integer_type_node".
+ 5.The 5 and 6 argument are the machine modes of corresponding RVV type used
+ in "build_vector_type_for_mode". For "vint32m1_t", we use VNx2SImode when
+ TARGET_MIN_VLEN > 32. Otherwise the machine mode is VNx1SImode. */
+
+#ifndef DEF_RVV_TYPE
+#define DEF_RVV_TYPE(USER_NAME, NCHARS, ABI_NAME, SCALAR_TYPE, VECTOR_MODE, \
+ VECTOR_MODE_MIN_VLEN_32)
+#endif
+
+/* SEW/LMUL = 64:
+ Only enable when TARGET_MIN_VLEN > 32 and machine mode = VNx1BImode. */
+DEF_RVV_TYPE (vbool64_t, 14, __rvv_bool64_t, boolean, VNx1BI, VOID)
+/* SEW/LMUL = 32:
+ Machine mode = VNx2BImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx1BImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vbool32_t, 14, __rvv_bool32_t, boolean, VNx2BI, VNx1BI)
+/* SEW/LMUL = 16:
+ Machine mode = VNx2BImode when TARGET_MIN_VLEN = 32.
+ Machine mode = VNx4BImode when TARGET_MIN_VLEN > 32. */
+DEF_RVV_TYPE (vbool16_t, 14, __rvv_bool16_t, boolean, VNx4BI, VNx2BI)
+/* SEW/LMUL = 8:
+ Machine mode = VNx8BImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx4BImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vbool8_t, 13, __rvv_bool8_t, boolean, VNx8BI, VNx4BI)
+/* SEW/LMUL = 4:
+ Machine mode = VNx16BImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx8BImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vbool4_t, 13, __rvv_bool4_t, boolean, VNx16BI, VNx8BI)
+/* SEW/LMUL = 2:
+ Machine mode = VNx32BImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx16BImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vbool2_t, 13, __rvv_bool2_t, boolean, VNx32BI, VNx16BI)
+/* SEW/LMUL = 1:
+ Machine mode = VNx64BImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx32BImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vbool1_t, 13, __rvv_bool1_t, boolean, VNx64BI, VNx32BI)
+
+/* LMUL = 1/8:
+ Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1QImode. */
+DEF_RVV_TYPE (vint8mf8_t, 15, __rvv_int8mf8_t, intQI, VNx1QI, VOID)
+DEF_RVV_TYPE (vuint8mf8_t, 16, __rvv_uint8mf8_t, unsigned_intQI, VNx1QI, VOID)
+/* LMUL = 1/4:
+ Machine mode = VNx2QImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx1QImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vint8mf4_t, 15, __rvv_int8mf4_t, intQI, VNx2QI, VNx1QI)
+DEF_RVV_TYPE (vuint8mf4_t, 16, __rvv_uint8mf4_t, unsigned_intQI, VNx2QI, VNx1QI)
+/* LMUL = 1/2:
+ Machine mode = VNx4QImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx2QImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vint8mf2_t, 15, __rvv_int8mf2_t, intQI, VNx4QI, VNx2QI)
+DEF_RVV_TYPE (vuint8mf2_t, 16, __rvv_uint8mf2_t, unsigned_intQI, VNx4QI, VNx2QI)
+/* LMUL = 1:
+ Machine mode = VNx8QImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx4QImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vint8m1_t, 14, __rvv_int8m1_t, intQI, VNx8QI, VNx4QI)
+DEF_RVV_TYPE (vuint8m1_t, 15, __rvv_uint8m1_t, unsigned_intQI, VNx8QI, VNx4QI)
+/* LMUL = 2:
+ Machine mode = VNx16QImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx8QImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vint8m2_t, 14, __rvv_int8m2_t, intQI, VNx16QI, VNx8QI)
+DEF_RVV_TYPE (vuint8m2_t, 15, __rvv_uint8m2_t, unsigned_intQI, VNx16QI, VNx8QI)
+/* LMUL = 4:
+ Machine mode = VNx32QImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx16QImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vint8m4_t, 14, __rvv_int8m4_t, intQI, VNx32QI, VNx16QI)
+DEF_RVV_TYPE (vuint8m4_t, 15, __rvv_uint8m4_t, unsigned_intQI, VNx32QI, VNx16QI)
+/* LMUL = 8:
+ Machine mode = VNx64QImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx32QImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vint8m8_t, 14, __rvv_int8m8_t, intQI, VNx64QI, VNx32QI)
+DEF_RVV_TYPE (vuint8m8_t, 15, __rvv_uint8m8_t, unsigned_intQI, VNx64QI, VNx32QI)
+
+/* LMUL = 1/4:
+ Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1HImode. */
+DEF_RVV_TYPE (vint16mf4_t, 16, __rvv_int16mf4_t, intHI, VNx1HI, VOID)
+DEF_RVV_TYPE (vuint16mf4_t, 17, __rvv_uint16mf4_t, unsigned_intHI, VNx1HI, VOID)
+/* LMUL = 1/2:
+ Machine mode = VNx2HImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx1HImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vint16mf2_t, 16, __rvv_int16mf2_t, intHI, VNx2HI, VNx1HI)
+DEF_RVV_TYPE (vuint16mf2_t, 17, __rvv_uint16mf2_t, unsigned_intHI, VNx2HI,
+ VNx1HI)
+/* LMUL = 1:
+ Machine mode = VNx4HImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx2HImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vint16m1_t, 15, __rvv_int16m1_t, intHI, VNx4HI, VNx2HI)
+DEF_RVV_TYPE (vuint16m1_t, 16, __rvv_uint16m1_t, unsigned_intHI, VNx4HI, VNx2HI)
+/* LMUL = 2:
+ Machine mode = VNx8HImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx4HImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vint16m2_t, 15, __rvv_int16m2_t, intHI, VNx8HI, VNx4HI)
+DEF_RVV_TYPE (vuint16m2_t, 16, __rvv_uint16m2_t, unsigned_intHI, VNx8HI, VNx4HI)
+/* LMUL = 4:
+ Machine mode = VNx16HImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx8HImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vint16m4_t, 15, __rvv_int16m4_t, intHI, VNx16HI, VNx8HI)
+DEF_RVV_TYPE (vuint16m4_t, 16, __rvv_uint16m4_t, unsigned_intHI, VNx16HI,
+ VNx8HI)
+/* LMUL = 8:
+ Machine mode = VNx32HImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx16HImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vint16m8_t, 15, __rvv_int16m8_t, intHI, VNx32HI, VNx16HI)
+DEF_RVV_TYPE (vuint16m8_t, 16, __rvv_uint16m8_t, unsigned_intHI, VNx32HI,
+ VNx16HI)
+
+/* LMUL = 1/2:
+ Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1SImode. */
+DEF_RVV_TYPE (vint32mf2_t, 16, __rvv_int32mf2_t, int32, VNx1SI, VOID)
+DEF_RVV_TYPE (vuint32mf2_t, 17, __rvv_uint32mf2_t, unsigned_int32, VNx1SI, VOID)
+/* LMUL = 1:
+ Machine mode = VNx2SImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx1SImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vint32m1_t, 15, __rvv_int32m1_t, int32, VNx2SI, VNx1SI)
+DEF_RVV_TYPE (vuint32m1_t, 16, __rvv_uint32m1_t, unsigned_int32, VNx2SI, VNx1SI)
+/* LMUL = 2:
+ Machine mode = VNx4SImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx2SImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vint32m2_t, 15, __rvv_int32m2_t, int32, VNx4SI, VNx2SI)
+DEF_RVV_TYPE (vuint32m2_t, 16, __rvv_uint32m2_t, unsigned_int32, VNx4SI, VNx2SI)
+/* LMUL = 4:
+ Machine mode = VNx8SImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx4SImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vint32m4_t, 15, __rvv_int32m4_t, int32, VNx8SI, VNx4SI)
+DEF_RVV_TYPE (vuint32m4_t, 16, __rvv_uint32m4_t, unsigned_int32, VNx8SI, VNx4SI)
+/* LMUL = 8:
+ Machine mode = VNx16SImode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx8SImode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vint32m8_t, 15, __rvv_int32m8_t, int32, VNx16SI, VNx8SI)
+DEF_RVV_TYPE (vuint32m8_t, 16, __rvv_uint32m8_t, unsigned_int32, VNx16SI,
+ VNx8SI)
+
+/* SEW = 64:
+ Disable when TARGET_MIN_VLEN > 32. */
+DEF_RVV_TYPE (vint64m1_t, 15, __rvv_int64m1_t, intDI, VNx1DI, VOID)
+DEF_RVV_TYPE (vuint64m1_t, 16, __rvv_uint64m1_t, unsigned_intDI, VNx1DI, VOID)
+DEF_RVV_TYPE (vint64m2_t, 15, __rvv_int64m2_t, intDI, VNx2DI, VOID)
+DEF_RVV_TYPE (vuint64m2_t, 16, __rvv_uint64m2_t, unsigned_intDI, VNx2DI, VOID)
+DEF_RVV_TYPE (vint64m4_t, 15, __rvv_int64m4_t, intDI, VNx4DI, VOID)
+DEF_RVV_TYPE (vuint64m4_t, 16, __rvv_uint64m4_t, unsigned_intDI, VNx4DI, VOID)
+DEF_RVV_TYPE (vint64m8_t, 15, __rvv_int64m8_t, intDI, VNx8DI, VOID)
+DEF_RVV_TYPE (vuint64m8_t, 16, __rvv_uint64m8_t, unsigned_intDI, VNx8DI, VOID)
+
+/* LMUL = 1/2:
+ Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1SFmode. */
+DEF_RVV_TYPE (vfloat32mf2_t, 18, __rvv_float32mf2_t, float, VNx1SF, VOID)
+/* LMUL = 1:
+ Machine mode = VNx2SFmode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx1SFmode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vfloat32m1_t, 17, __rvv_float32m1_t, float, VNx2SF, VNx1SF)
+/* LMUL = 2:
+ Machine mode = VNx4SFmode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx2SFmode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vfloat32m2_t, 17, __rvv_float32m2_t, float, VNx4SF, VNx2SF)
+/* LMUL = 4:
+ Machine mode = VNx8SFmode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx4SFmode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vfloat32m4_t, 17, __rvv_float32m4_t, float, VNx8SF, VNx4SF)
+/* LMUL = 8:
+ Machine mode = VNx16SFmode when TARGET_MIN_VLEN > 32.
+ Machine mode = VNx8SFmode when TARGET_MIN_VLEN = 32. */
+DEF_RVV_TYPE (vfloat32m8_t, 17, __rvv_float32m8_t, float, VNx16SF, VNx8SF)
+
+/* SEW = 64:
+ Disable when TARGET_VECTOR_FP64. */
+DEF_RVV_TYPE (vfloat64m1_t, 17, __rvv_float64m1_t, double, VNx1DF, VOID)
+DEF_RVV_TYPE (vfloat64m2_t, 17, __rvv_float64m2_t, double, VNx2DF, VOID)
+DEF_RVV_TYPE (vfloat64m4_t, 17, __rvv_float64m4_t, double, VNx4DF, VOID)
+DEF_RVV_TYPE (vfloat64m8_t, 17, __rvv_float64m8_t, double, VNx8DF, VOID)
+
+#undef DEF_RVV_TYPE
diff --git a/gcc/config/riscv/riscv-vector-builtins.h b/gcc/config/riscv/riscv-vector-builtins.h
new file mode 100644
index 0000000..a4a8c11
--- /dev/null
+++ b/gcc/config/riscv/riscv-vector-builtins.h
@@ -0,0 +1,79 @@
+/* Builtins definitions for RISC-V 'V' Extension for GNU compiler.
+ Copyright (C) 2022-2022 Free Software Foundation, Inc.
+ Contributed by Ju-Zhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_RISCV_V_BUILTINS_H
+#define GCC_RISCV_V_BUILTINS_H
+
+namespace riscv_vector {
+
+/* Static information about each vector type. */
+struct vector_type_info
+{
+ /* The name of the type as declared by riscv_vector.h
+ which is recommend to use. For example: 'vint32m1_t'. */
+ const char *user_name;
+
+ /* ABI name of vector type. The type is always available
+ under this name, even when riscv_vector.h isn't included.
+ For example: '__rvv_int32m1_t'. */
+ const char *abi_name;
+
+ /* The C++ mangling of ABI_NAME. */
+ const char *mangled_name;
+};
+
+/* Enumerates the RVV types, together called
+ "vector types" for brevity. */
+enum vector_type_index
+{
+#define DEF_RVV_TYPE(USER_NAME, ABI_NAME, NCHARS, ARGS...) \
+ VECTOR_TYPE_##USER_NAME,
+#include "riscv-vector-builtins.def"
+ NUM_VECTOR_TYPES
+};
+
+/* RAII class for enabling enough RVV features to define the built-in
+ types and implement the riscv_vector.h pragma.
+
+ Note: According to 'TYPE_MODE' macro implementation, we need set
+ have_regs_of_mode[mode] to be true if we want to get the exact mode
+ from 'TYPE_MODE'. However, have_regs_of_mode has not been set yet in
+ targetm.init_builtins (). We need rvv_switcher to set have_regs_of_mode
+ before targetm.init_builtins () and recover back have_regs_of_mode
+ after targetm.init_builtins (). */
+class rvv_switcher
+{
+public:
+ rvv_switcher ();
+ ~rvv_switcher ();
+
+private:
+ bool m_old_have_regs_of_mode[MAX_MACHINE_MODE];
+};
+
+void init_builtins ();
+const char *mangle_builtin_type (const_tree);
+#ifdef GCC_TARGET_H
+bool verify_type_context (location_t, type_context_kind, const_tree, bool);
+#endif
+
+} // end namespace riscv_vector
+
+#endif
diff --git a/gcc/config/riscv/riscv-vector-switch.def b/gcc/config/riscv/riscv-vector-switch.def
new file mode 100644
index 0000000..cacfccb
--- /dev/null
+++ b/gcc/config/riscv/riscv-vector-switch.def
@@ -0,0 +1,164 @@
+/* Machine mode switch for RISC-V 'V' Extension for GNU compiler.
+ Copyright (C) 2022-2022 Free Software Foundation, Inc.
+ Contributed by Ju-Zhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* This file is enable or disable the RVV modes according '-march'. */
+
+/* According to rvv-intrinsic and RISC-V 'V' Extension ISA document:
+ https://github.com/riscv-non-isa/rvv-intrinsic-doc/blob/master/rvv-intrinsic-rfc.md.
+ https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc.
+
+ Data Types
+ Encode SEW and LMUL into data types.
+ We enforce the constraint LMUL ≥ SEW/ELEN in the implementation.
+ There are the following data types for MIN_VLEN > 32.
+
+Note: N/A means the corresponding vector type is disabled.
+
+|Types |LMUL=1|LMUL=2 |LMUL=4 |LMUL=8 |LMUL=1/2|LMUL=1/4|LMUL=1/8|
+|int64_t |VNx1DI|VNx2DI |VNx4DI |VNx8DI |N/A |N/A |N/A |
+|uint64_t|VNx1DI|VNx2DI |VNx4DI |VNx8DI |N/A |N/A |N/A |
+|int32_t |VNx2SI|VNx4SI |VNx8SI |VNx16SI|VNx1SI |N/A |N/A |
+|uint32_t|VNx2SI|VNx4SI |VNx8SI |VNx16SI|VNx1SI |N/A |N/A |
+|int16_t |VNx4HI|VNx8HI |VNx16HI|VNx32HI|VNx2HI |VNx1HI |N/A |
+|uint16_t|VNx4HI|VNx8HI |VNx16HI|VNx32HI|VNx2HI |VNx1HI |N/A |
+|int8_t |VNx8QI|VNx16QI|VNx32QI|VNx64QI|VNx4QI |VNx2QI |VNx1QI |
+|uint8_t |VNx8QI|VNx16QI|VNx32QI|VNx64QI|VNx4QI |VNx2QI |VNx1QI |
+|float64 |VNx1DF|VNx2DF |VNx4DF |VNx8DF |N/A |N/A |N/A |
+|float32 |VNx2SF|VNx4SF |VNx8SF |VNx16SF|VNx1SF |N/A |N/A |
+|float16 |VNx4HF|VNx8HF |VNx16HF|VNx32HF|VNx2HF |VNx1HF |N/A |
+
+Mask Types Encode the ratio of SEW/LMUL into the
+mask types. There are the following mask types.
+
+n = SEW/LMUL
+
+|Types|n=1 |n=2 |n=4 |n=8 |n=16 |n=32 |n=64 |
+|bool |VNx64BI|VNx32BI|VNx16BI|VNx8BI|VNx4BI|VNx2BI|VNx1BI|
+
+There are the following data types for MIN_VLEN = 32.
+
+|Types |LMUL=1|LMUL=2|LMUL=4 |LMUL=8 |LMUL=1/2|LMUL=1/4|LMUL=1/8|
+|int64_t |N/A |N/A |N/A |N/A |N/A |N/A |N/A |
+|uint64_t|N/A |N/A |N/A |N/A |N/A |N/A |N/A |
+|int32_t |VNx1SI|VNx2SI|VNx4SI |VNx8SI |N/A |N/A |N/A |
+|uint32_t|VNx1SI|VNx2SI|VNx4SI |VNx8SI |N/A |N/A |N/A |
+|int16_t |VNx2HI|VNx4HI|VNx8HI |VNx16HI|VNx1HI |N/A |N/A |
+|uint16_t|VNx2HI|VNx4HI|VNx8HI |VNx16HI|VNx1HI |N/A |N/A |
+|int8_t |VNx4QI|VNx8QI|VNx16QI|VNx32QI|VNx2QI |VNx1QI |N/A |
+|uint8_t |VNx4QI|VNx8QI|VNx16QI|VNx32QI|VNx2QI |VNx1QI |N/A |
+|float64 |N/A |N/A |N/A |N/A |N/A |N/A |N/A |
+|float32 |VNx1SF|VNx2SF|VNx4SF |VNx8SF |N/A |N/A |N/A |
+|float16 |VNx2HF|VNx4HF|VNx8HF |VNx16HF|VNx1HF |N/A |N/A |
+
+Mask Types Encode the ratio of SEW/LMUL into the
+mask types. There are the following mask types.
+
+n = SEW/LMUL
+
+|Types|n=1 |n=2 |n=4 |n=8 |n=16 |n=32 |n=64|
+|bool |VNx32BI|VNx16BI|VNx8BI|VNx4BI|VNx2BI|VNx1BI|N/A |
+
+TODO: FP16 vector needs support of 'zvfh', we don't support it yet. */
+
+/* Return 'REQUIREMENT' for machine_mode 'MODE'.
+ For example: 'MODE' = VNx64BImode needs TARGET_MIN_VLEN > 32. */
+#ifndef ENTRY
+#define ENTRY(MODE, REQUIREMENT)
+#endif
+/* Flag of FP32 vector. */
+#ifndef TARGET_VECTOR_FP32
+#define TARGET_VECTOR_FP32 \
+ (TARGET_HARD_FLOAT && (TARGET_VECTOR_ELEN_FP_32 || TARGET_VECTOR_ELEN_FP_64))
+#endif
+/* Flag of FP64 vector. */
+#ifndef TARGET_VECTOR_FP64
+#define TARGET_VECTOR_FP64 \
+ (TARGET_DOUBLE_FLOAT && TARGET_VECTOR_ELEN_FP_64 && (TARGET_MIN_VLEN > 32))
+#endif
+
+/* Mask modes. Disable VNx64BImode when TARGET_MIN_VLEN == 32. */
+ENTRY (VNx64BI, TARGET_MIN_VLEN > 32)
+ENTRY (VNx32BI, true)
+ENTRY (VNx16BI, true)
+ENTRY (VNx8BI, true)
+ENTRY (VNx4BI, true)
+ENTRY (VNx2BI, true)
+ENTRY (VNx1BI, true)
+
+/* SEW = 8. Disable VNx64QImode when TARGET_MIN_VLEN == 32. */
+ENTRY (VNx64QI, TARGET_MIN_VLEN > 32)
+ENTRY (VNx32QI, true)
+ENTRY (VNx16QI, true)
+ENTRY (VNx8QI, true)
+ENTRY (VNx4QI, true)
+ENTRY (VNx2QI, true)
+ENTRY (VNx1QI, true)
+
+/* SEW = 16. Disable VNx32HImode when TARGET_MIN_VLEN == 32. */
+ENTRY (VNx32HI, TARGET_MIN_VLEN > 32)
+ENTRY (VNx16HI, true)
+ENTRY (VNx8HI, true)
+ENTRY (VNx4HI, true)
+ENTRY (VNx2HI, true)
+ENTRY (VNx1HI, true)
+
+/* TODO:Disable all FP16 vector, enable them when 'zvfh' is supported. */
+ENTRY (VNx32HF, false)
+ENTRY (VNx16HF, false)
+ENTRY (VNx8HF, false)
+ENTRY (VNx4HF, false)
+ENTRY (VNx2HF, false)
+ENTRY (VNx1HF, false)
+
+/* SEW = 32. Disable VNx16SImode when TARGET_MIN_VLEN == 32.
+ For single-precision floating-point, we need TARGET_VECTOR_FP32 ==
+ RVV_ENABLE. */
+ENTRY (VNx16SI, TARGET_MIN_VLEN > 32)
+ENTRY (VNx8SI, true)
+ENTRY (VNx4SI, true)
+ENTRY (VNx2SI, true)
+ENTRY (VNx1SI, true)
+
+ENTRY (VNx16SF, TARGET_VECTOR_FP32 && (TARGET_MIN_VLEN > 32))
+ENTRY (VNx8SF, TARGET_VECTOR_FP32)
+ENTRY (VNx4SF, TARGET_VECTOR_FP32)
+ENTRY (VNx2SF, TARGET_VECTOR_FP32)
+ENTRY (VNx1SF, TARGET_VECTOR_FP32)
+
+/* SEW = 64. Enable when TARGET_MIN_VLEN > 32.
+ For double-precision floating-point, we need TARGET_VECTOR_FP64 ==
+ RVV_ENABLE. */
+ENTRY (VNx8DI, TARGET_MIN_VLEN > 32)
+ENTRY (VNx4DI, TARGET_MIN_VLEN > 32)
+ENTRY (VNx2DI, TARGET_MIN_VLEN > 32)
+ENTRY (VNx1DI, TARGET_MIN_VLEN > 32)
+
+ENTRY (VNx8DF, TARGET_VECTOR_FP64 && (TARGET_MIN_VLEN > 32))
+ENTRY (VNx4DF, TARGET_VECTOR_FP64)
+ENTRY (VNx2DF, TARGET_VECTOR_FP64)
+ENTRY (VNx1DF, TARGET_VECTOR_FP64)
+
+/* SEW = 128. Disable all of them. */
+ENTRY (VNx2TI, false)
+ENTRY (VNx2TF, false)
+
+#undef TARGET_VECTOR_FP32
+#undef TARGET_VECTOR_FP64
+#undef ENTRY
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 4d5d887..0d61831 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -59,6 +59,7 @@ along with GCC; see the file COPYING3. If not see
#include "opts.h"
#include "tm-constrs.h"
#include "rtl-iter.h"
+#include "riscv-vector-builtins.h"
/* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */
#define UNSPEC_ADDRESS_P(X) \
@@ -375,6 +376,11 @@ static const struct attribute_spec riscv_attribute_table[] =
{ "interrupt", 0, 1, false, true, true, false,
riscv_handle_type_attribute, NULL },
+ /* The following two are used for the built-in properties of the Vector type
+ and are not used externally */
+ {"RVV sizeless type", 4, 4, false, true, false, true, NULL, NULL},
+ {"RVV type", 0, 0, false, true, false, true, NULL, NULL},
+
/* The last attribute spec is set to be NULL. */
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
@@ -942,7 +948,37 @@ riscv_valid_lo_sum_p (enum riscv_symbol_type sym_type, machine_mode mode,
static bool
riscv_v_ext_vector_mode_p (machine_mode mode)
{
- return VECTOR_MODE_P (mode);
+#define ENTRY(MODE, REQUIREMENT) \
+ case MODE##mode: \
+ return true;
+ switch (mode)
+ {
+#include "riscv-vector-switch.def"
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+/* Return true if mode is the RVV enabled mode.
+ For example: 'VNx1DI' mode is disabled if MIN_VLEN == 32.
+ 'VNx1SI' mode is enabled if MIN_VLEN == 32. */
+
+bool
+riscv_v_ext_enabled_vector_mode_p (machine_mode mode)
+{
+#define ENTRY(MODE, REQUIREMENT) \
+ case MODE##mode: \
+ return REQUIREMENT;
+ switch (mode)
+ {
+#include "riscv-vector-switch.def"
+ default:
+ return false;
+ }
+
+ return false;
}
/* Return true if X is a valid address for machine mode MODE. If it is,
@@ -6180,6 +6216,16 @@ riscv_mangle_type (const_tree type)
if (TREE_CODE (type) == REAL_TYPE && TYPE_PRECISION (type) == 16)
return "DF16_";
+ /* Mangle all vector type for vector extension. */
+ /* The mangle name follows the rule of RVV LLVM
+ that is "u" + length of (abi_name) + abi_name. */
+ if (TYPE_NAME (type) != NULL)
+ {
+ const char *res = riscv_vector::mangle_builtin_type (type);
+ if (res)
+ return res;
+ }
+
/* Use the default mangling. */
return NULL;
}
@@ -6290,6 +6336,44 @@ riscv_reinit (void)
#define TARGET_RUN_TARGET_SELFTESTS selftest::riscv_run_selftests
#endif /* #if CHECKING_P */
+/* Implement TARGET_VECTOR_MODE_SUPPORTED_P. */
+
+static bool
+riscv_vector_mode_supported_p (machine_mode mode)
+{
+ if (TARGET_VECTOR)
+ return riscv_v_ext_enabled_vector_mode_p (mode);
+
+ return false;
+}
+
+/* Implement TARGET_VERIFY_TYPE_CONTEXT. */
+
+static bool
+riscv_verify_type_context (location_t loc, type_context_kind context,
+ const_tree type, bool silent_p)
+{
+ return riscv_vector::verify_type_context (loc, context, type, silent_p);
+}
+
+/* Implement TARGET_VECTOR_ALIGNMENT. */
+
+static HOST_WIDE_INT
+riscv_vector_alignment (const_tree type)
+{
+ /* ??? Checking the mode isn't ideal, but VECTOR_BOOLEAN_TYPE_P can
+ be set for non-predicate vectors of booleans. Modes are the most
+ direct way we have of identifying real RVV predicate types. */
+ /* FIXME: RVV didn't mention the alignment of bool, we uses
+ one byte align. */
+ if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_VECTOR_BOOL)
+ return 8;
+
+ widest_int min_size
+ = constant_lower_bound (wi::to_poly_widest (TYPE_SIZE (type)));
+ return wi::umin (min_size, 128).to_uhwi ();
+}
+
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@@ -6502,6 +6586,15 @@ riscv_reinit (void)
#define TARGET_DEFAULT_TARGET_FLAGS (MASK_BIG_ENDIAN)
#endif
+#undef TARGET_VECTOR_MODE_SUPPORTED_P
+#define TARGET_VECTOR_MODE_SUPPORTED_P riscv_vector_mode_supported_p
+
+#undef TARGET_VERIFY_TYPE_CONTEXT
+#define TARGET_VERIFY_TYPE_CONTEXT riscv_verify_type_context
+
+#undef TARGET_VECTOR_ALIGNMENT
+#define TARGET_VECTOR_ALIGNMENT riscv_vector_alignment
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-riscv.h"
diff --git a/gcc/config/riscv/t-riscv b/gcc/config/riscv/t-riscv
index 2b82e5f..ad9be09 100644
--- a/gcc/config/riscv/t-riscv
+++ b/gcc/config/riscv/t-riscv
@@ -5,6 +5,16 @@ riscv-builtins.o: $(srcdir)/config/riscv/riscv-builtins.cc $(CONFIG_H) \
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/riscv/riscv-builtins.cc
+riscv-vector-builtins.o: $(srcdir)/config/riscv/riscv-vector-builtins.cc \
+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) $(TM_P_H) \
+ memmodel.h insn-codes.h $(OPTABS_H) $(RECOG_H) $(DIAGNOSTIC_H) $(EXPR_H) \
+ $(FUNCTION_H) fold-const.h gimplify.h explow.h stor-layout.h $(REGS_H) \
+ alias.h langhooks.h attribs.h stringpool.h $(REGS_H) \
+ $(srcdir)/config/riscv/riscv-vector-builtins.h \
+ $(srcdir)/config/riscv/riscv-vector-builtins.def
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/riscv/riscv-vector-builtins.cc
+
riscv-sr.o: $(srcdir)/config/riscv/riscv-sr.cc $(CONFIG_H) \
$(SYSTEM_H) $(TM_H)
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
diff --git a/gcc/config/rs6000/rs6000-builtin.cc b/gcc/config/rs6000/rs6000-builtin.cc
index 3ce729c..90ab39d 100644
--- a/gcc/config/rs6000/rs6000-builtin.cc
+++ b/gcc/config/rs6000/rs6000-builtin.cc
@@ -733,7 +733,22 @@ rs6000_init_builtins (void)
if (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128)
ieee128_float_type_node = long_double_type_node;
else
- ieee128_float_type_node = float128_type_node;
+ {
+ /* For C we only need to register the __ieee128 name for
+ it. For C++, we create a distinct type which will mangle
+ differently (u9__ieee128) vs. _Float128 (DF128_) and behave
+ backwards compatibly. */
+ if (float128t_type_node == NULL_TREE)
+ {
+ float128t_type_node = make_node (REAL_TYPE);
+ TYPE_PRECISION (float128t_type_node)
+ = TYPE_PRECISION (float128_type_node);
+ layout_type (float128t_type_node);
+ SET_TYPE_MODE (float128t_type_node,
+ TYPE_MODE (float128_type_node));
+ }
+ ieee128_float_type_node = float128t_type_node;
+ }
t = build_qualified_type (ieee128_float_type_node, TYPE_QUAL_CONST);
lang_hooks.types.register_builtin_type (ieee128_float_type_node,
"__ieee128");
diff --git a/gcc/config/rs6000/rs6000-c.cc b/gcc/config/rs6000/rs6000-c.cc
index ca9cc42..5660946 100644
--- a/gcc/config/rs6000/rs6000-c.cc
+++ b/gcc/config/rs6000/rs6000-c.cc
@@ -808,6 +808,7 @@ static inline bool
is_float128_p (tree t)
{
return (t == float128_type_node
+ || (t && t == float128t_type_node)
|| (TARGET_IEEEQUAD
&& TARGET_LONG_DOUBLE_128
&& t == long_double_type_node));
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 5f347e9..bbe21ea 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -20272,7 +20272,11 @@ rs6000_mangle_type (const_tree type)
if (SCALAR_FLOAT_TYPE_P (type) && FLOAT128_IBM_P (TYPE_MODE (type)))
return "g";
- if (SCALAR_FLOAT_TYPE_P (type) && FLOAT128_IEEE_P (TYPE_MODE (type)))
+ if (SCALAR_FLOAT_TYPE_P (type)
+ && FLOAT128_IEEE_P (TYPE_MODE (type))
+ /* _Float128 should mangle as DF128_ (done in generic code)
+ rather than u9__ieee128 (used for __ieee128 and __float128). */
+ && type != float128_type_node)
return "u9__ieee128";
if (type == vector_pair_type_node)
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b9b2729..3f512c6 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,159 @@
+2022-09-28 Eugene Rozenfeld <erozen@microsoft.com>
+
+ * module.cc (write_location): Write discriminator.
+ (read_location): Read discriminator.
+
+2022-09-28 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (DECL_NTTP_OBJECT_P): New.
+ (template_parm_object_p): Delete.
+ (build_template_parm_object): Declare.
+ * cxx-pretty-print.cc (pp_cx_template_argument_list): Use DECL_NTTP_OBJECT_P.
+ * error.cc (dump_simple_decl): Likewise.
+ * mangle.cc (write_template_arg): Likewise.
+ * pt.cc (template_parm_object_p): Delete.
+ (create_template_parm_object): Separated out checking from ...
+ (get_template_parm_object): ... this, new external entry point.
+
+2022-09-27 Marek Polacek <polacek@redhat.com>
+
+ PR c++/101165
+ PR c++/106882
+ * call.cc (reference_binding): Check clk_implicit_rval in C++20 only.
+ * cp-tree.h (unparenthesized_id_or_class_member_access_p): Declare.
+ * pt.cc (unparenthesized_id_or_class_member_access_p): New function,
+ broken out of...
+ (do_auto_deduction): ...here. Use it. In C++23, maybe call
+ treat_lvalue_as_rvalue_p.
+ * tree.cc (xvalue_p): Check & clk_rvalueref, not == clk_rvalueref.
+ * typeck.cc (check_return_expr): Allow implicit move for functions
+ returning a reference as well, or when the return value type is not
+ a scalar type.
+
+2022-09-27 Marek Polacek <polacek@redhat.com>
+
+ * constraint.cc (diagnose_trait_expr): Say "nothrow" without quotes
+ rather than in quotes.
+
+2022-09-27 Jonathan Wakely <jwakely@redhat.com>
+
+ PR c++/107049
+ * method.cc (is_convertible_helper): Use access check sentinel.
+
+2022-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/106651
+ * cp-tree.h (LAMBDA_EXPR_STATIC_P): Implement C++23
+ P1169R4 - static operator(). Define.
+ * parser.cc (CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR): Document
+ that it also allows static.
+ (cp_parser_lambda_declarator_opt): Handle static lambda specifier.
+ (cp_parser_decl_specifier_seq): Allow RID_STATIC for
+ CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR.
+ * decl.cc (grok_op_properties): If operator() isn't a method,
+ use a different error wording, if it is static member function,
+ allow it (for C++20 and older with a pedwarn unless it is
+ a lambda function or template instantiation).
+ * call.cc (joust): Don't ICE if one candidate is static member
+ function and the other is an indirect call. If the parameter
+ conversion on the other candidate is user defined conversion,
+ ellipsis or bad conversion, make static member function candidate
+ a winner for that parameter.
+ * lambda.cc (maybe_add_lambda_conv_op): Handle static lambdas.
+ * error.cc (dump_lambda_function): Print static for static lambdas.
+
+2022-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ * cp-tree.h (struct omp_begin_assumes_data): New type.
+ (struct saved_scope): Add omp_begin_assumes member.
+ * parser.cc: Include bitmap.h.
+ (cp_parser_omp_assumption_clauses, cp_parser_omp_assume,
+ cp_parser_omp_assumes, cp_parser_omp_begin): New functions.
+ (cp_parser_omp_end_declare_target): Rename to ...
+ (cp_parser_omp_end): ... this. Handle also end assumes.
+ (cp_parser_omp_construct): Handle PRAGMA_OMP_ASSUME.
+ (cp_parser_pragma): Handle PRAGMA_OMP_ASSUME, PRAGMA_OMP_ASSUMES
+ and PRAGMA_OMP_BEGIN. Handle PRAGMA_OMP_END rather than
+ PRAGMA_OMP_END_DECLARE_TARGET and call cp_parser_omp_end
+ for it rather than cp_parser_omp_end_declare_target.
+ * pt.cc (apply_late_template_attributes): Also temporarily clear
+ omp_begin_assumes.
+ * semantics.cc (finish_translation_unit): Also diagnose
+ #pragma omp begin assumes without corresponding
+ #pragma omp end assumes.
+
+2022-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.cc (cp_parser_lambda_declarator_opt): Don't diagnose
+ conflicting specifiers here.
+ (cp_storage_class_name): New variable.
+ (cp_parser_decl_specifier_seq): When setting conflicting_specifiers_p
+ for the first time, diagnose which exact specifiers conflict.
+ (cp_parser_set_storage_class): Likewise. Move storage_class
+ computation earlier.
+ * decl.cc (grokdeclarator): Don't diagnose conflicting specifiers
+ here, just return error_mark_node.
+
+2022-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/106652
+ PR c++/85518
+ * cp-tree.h (cp_compare_floating_point_conversion_ranks): Implement
+ P1467R9 - Extended floating-point types and standard names except
+ for std::bfloat16_t for now. Declare.
+ (extended_float_type_p): New inline function.
+ * mangle.cc (write_builtin_type): Mangle float{16,32,64,128}_type_node
+ as DF{16,32,64,128}_. Mangle float{32,64,128}x_type_node as
+ DF{32,64,128}x. Remove FIXED_POINT_TYPE mangling that conflicts
+ with that.
+ * typeck2.cc (check_narrowing): If one of ftype or type is extended
+ floating-point type, compare floating-point conversion ranks.
+ * parser.cc (cp_keyword_starts_decl_specifier_p): Handle
+ CASE_RID_FLOATN_NX.
+ (cp_parser_simple_type_specifier): Likewise and diagnose missing
+ _Float<N> or _Float<N>x support if not supported by target.
+ * typeck.cc (cp_compare_floating_point_conversion_ranks): New function.
+ (cp_common_type): If both types are REAL_TYPE and one or both are
+ extended floating-point types, select common type based on comparison
+ of floating-point conversion ranks and subranks.
+ (cp_build_binary_op): Diagnose operation with floating point arguments
+ with unordered conversion ranks.
+ * call.cc (standard_conversion): For floating-point conversion, if
+ either from or to are extended floating-point types, set conv->bad_p
+ for implicit conversion from larger to smaller conversion rank or
+ with unordered conversion ranks.
+ (convert_like_internal): Emit a pedwarn on such conversions.
+ (build_conditional_expr): Diagnose operation with floating point
+ arguments with unordered conversion ranks.
+ (convert_arg_to_ellipsis): Don't promote extended floating-point types
+ narrower than double to double.
+ (compare_ics): Implement P1467R9 [over.ics.rank]/4 changes.
+
+2022-09-26 Marek Polacek <polacek@redhat.com>
+
+ PR c++/106656
+ * typeck2.cc (array_string_literal_compatible_p): Allow
+ initializing arrays of char or unsigned char by a UTF-8 string literal.
+
+2022-09-26 Marek Polacek <polacek@redhat.com>
+
+ PR c++/106784
+ * method.cc (is_convertible_helper): New.
+ (is_convertible): Use it.
+ (is_nothrow_convertible): Likewise.
+
+2022-09-26 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/107033
+ * module.cc (trees_in::decl_value): In the MK_partial case for
+ a variable template partial specialization, pass decl_p=true to
+ add_mergeable_specialization, and set spec to the VAR_DECL not
+ the TEMPLATE_DECL.
+ * pt.cc (add_mergeable_specialization): For a variable template
+ partial specialization, set the TREE_TYPE of the new
+ DECL_TEMPLATE_SPECIALIZATIONS node to the TREE_TYPE of the
+ VAR_DECL not the VAR_DECL itself.
+
2022-09-23 Marek Polacek <polacek@redhat.com>
PR c++/106784
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 7e9289f..3506b0f 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -1541,6 +1541,22 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
|| (underlying_type && same_type_p (to, underlying_type)))
&& next_conversion (conv)->rank <= cr_promotion)
conv->rank = cr_promotion;
+
+ /* A prvalue of floating-point type can be converted to a prvalue of
+ another floating-point type with a greater or equal conversion
+ rank ([conv.rank]). A prvalue of standard floating-point type can
+ be converted to a prvalue of another standard floating-point type.
+ For backwards compatibility with handling __float128 and other
+ non-standard floating point types, allow all implicit floating
+ point conversions if neither type is extended floating-point
+ type and if at least one of them is, fail if they have unordered
+ conversion rank or from has higher conversion rank. */
+ if (fcode == REAL_TYPE
+ && tcode == REAL_TYPE
+ && (extended_float_type_p (from)
+ || extended_float_type_p (to))
+ && cp_compare_floating_point_conversion_ranks (from, to) >= 2)
+ conv->bad_p = true;
}
else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE
&& vector_types_convertible_p (from, to, false))
@@ -1864,8 +1880,10 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
/* Nor the reverse. */
if (!is_lvalue && !TYPE_REF_IS_RVALUE (rto)
- /* Unless it's really an lvalue. */
- && !(cxx_dialect >= cxx20
+ /* Unless it's really a C++20 lvalue being treated as an xvalue.
+ But in C++23, such an expression is just an xvalue, not a special
+ lvalue, so the binding is once again ill-formed. */
+ && !(cxx_dialect == cxx20
&& (gl_kind & clk_implicit_rval))
&& (!CP_TYPE_CONST_NON_VOLATILE_P (to)
|| (flags & LOOKUP_NO_RVAL_BIND))
@@ -5842,6 +5860,21 @@ build_conditional_expr (const op_location_t &loc,
/* In this case, there is always a common type. */
result_type = type_after_usual_arithmetic_conversions (arg2_type,
arg3_type);
+ if (result_type == error_mark_node
+ && TREE_CODE (arg2_type) == REAL_TYPE
+ && TREE_CODE (arg3_type) == REAL_TYPE
+ && (extended_float_type_p (arg2_type)
+ || extended_float_type_p (arg3_type))
+ && cp_compare_floating_point_conversion_ranks (arg2_type,
+ arg3_type) == 3)
+ {
+ if (complain & tf_error)
+ error_at (loc, "operands to %<?:%> of types %qT and %qT "
+ "have unordered conversion rank",
+ arg2_type, arg3_type);
+ return error_mark_node;
+ }
+
if (complain & tf_warning)
do_warn_double_promotion (result_type, arg2_type, arg3_type,
"implicit conversion from %qH to %qI to "
@@ -7906,6 +7939,27 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
"direct-initialization",
totype, TREE_TYPE (expr));
+ if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+ && TREE_CODE (totype) == REAL_TYPE
+ && (extended_float_type_p (TREE_TYPE (expr))
+ || extended_float_type_p (totype)))
+ switch (cp_compare_floating_point_conversion_ranks (TREE_TYPE (expr),
+ totype))
+ {
+ case 2:
+ pedwarn (loc, 0, "converting to %qH from %qI with greater "
+ "conversion rank", totype, TREE_TYPE (expr));
+ complained = true;
+ break;
+ case 3:
+ pedwarn (loc, 0, "converting to %qH from %qI with unordered "
+ "conversion ranks", totype, TREE_TYPE (expr));
+ complained = true;
+ break;
+ default:
+ break;
+ }
+
for (; t ; t = next_conversion (t))
{
if (t->kind == ck_user && t->cand->reason)
@@ -8531,7 +8585,8 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
if (TREE_CODE (arg_type) == REAL_TYPE
&& (TYPE_PRECISION (arg_type)
< TYPE_PRECISION (double_type_node))
- && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (arg_type)))
+ && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (arg_type))
+ && !extended_float_type_p (arg_type))
{
if ((complain & tf_warning)
&& warn_double_promotion && !c_inhibit_evaluation_warnings)
@@ -11719,6 +11774,81 @@ compare_ics (conversion *ics1, conversion *ics2)
return 1;
}
+ {
+ /* A conversion in either direction between floating-point type FP1 and
+ floating-point type FP2 is better than a conversion in the same
+ direction between FP1 and arithmetic type T3 if
+ - the floating-point conversion rank of FP1 is equal to the rank of
+ FP2, and
+ - T3 is not a floating-point type, or T3 is a floating-point type
+ whose rank is not equal to the rank of FP1, or the floating-point
+ conversion subrank of FP2 is greater than the subrank of T3. */
+ tree fp1 = from_type1;
+ tree fp2 = to_type1;
+ tree fp3 = from_type2;
+ tree t3 = to_type2;
+ int ret = 1;
+ if (TYPE_MAIN_VARIANT (fp2) == TYPE_MAIN_VARIANT (t3))
+ {
+ std::swap (fp1, fp2);
+ std::swap (fp3, t3);
+ }
+ if (TYPE_MAIN_VARIANT (fp1) == TYPE_MAIN_VARIANT (fp3)
+ && TREE_CODE (fp1) == REAL_TYPE
+ /* Only apply this rule if at least one of the 3 types is
+ extended floating-point type, otherwise keep them as
+ before for compatibility reasons with types like __float128.
+ float, double and long double alone have different conversion
+ ranks and so when just those 3 types are involved, this
+ rule doesn't trigger. */
+ && (extended_float_type_p (fp1)
+ || (TREE_CODE (fp2) == REAL_TYPE && extended_float_type_p (fp2))
+ || (TREE_CODE (t3) == REAL_TYPE && extended_float_type_p (t3))))
+ {
+ if (TREE_CODE (fp2) != REAL_TYPE)
+ {
+ ret = -ret;
+ std::swap (fp2, t3);
+ }
+ if (TREE_CODE (fp2) == REAL_TYPE)
+ {
+ /* cp_compare_floating_point_conversion_ranks returns -1, 0 or 1
+ if the conversion rank is equal (-1 or 1 if the subrank is
+ different). */
+ if (IN_RANGE (cp_compare_floating_point_conversion_ranks (fp1,
+ fp2),
+ -1, 1))
+ {
+ /* Conversion ranks of FP1 and FP2 are equal. */
+ if (TREE_CODE (t3) != REAL_TYPE
+ || !IN_RANGE (cp_compare_floating_point_conversion_ranks
+ (fp1, t3),
+ -1, 1))
+ /* FP1 <-> FP2 conversion is better. */
+ return ret;
+ int c = cp_compare_floating_point_conversion_ranks (fp2, t3);
+ gcc_assert (IN_RANGE (c, -1, 1));
+ if (c == 1)
+ /* Conversion subrank of FP2 is greater than subrank of T3.
+ FP1 <-> FP2 conversion is better. */
+ return ret;
+ else if (c == -1)
+ /* Conversion subrank of FP2 is less than subrank of T3.
+ FP1 <-> T3 conversion is better. */
+ return -ret;
+ }
+ else if (TREE_CODE (t3) == REAL_TYPE
+ && IN_RANGE (cp_compare_floating_point_conversion_ranks
+ (fp1, t3),
+ -1, 1))
+ /* Conversion ranks of FP1 and FP2 are not equal, conversion
+ ranks of FP1 and T3 are equal.
+ FP1 <-> T3 conversion is better. */
+ return -ret;
+ }
+ }
+ }
+
if (TYPE_PTR_P (from_type1)
&& TYPE_PTR_P (from_type2)
&& TYPE_PTR_P (to_type1)
@@ -12133,10 +12263,14 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
len = cand1->num_convs;
if (len != cand2->num_convs)
{
- int static_1 = DECL_STATIC_FUNCTION_P (cand1->fn);
- int static_2 = DECL_STATIC_FUNCTION_P (cand2->fn);
+ int static_1 = (TREE_CODE (cand1->fn) == FUNCTION_DECL
+ && DECL_STATIC_FUNCTION_P (cand1->fn));
+ int static_2 = (TREE_CODE (cand2->fn) == FUNCTION_DECL
+ && DECL_STATIC_FUNCTION_P (cand2->fn));
- if (DECL_CONSTRUCTOR_P (cand1->fn)
+ if (TREE_CODE (cand1->fn) == FUNCTION_DECL
+ && TREE_CODE (cand2->fn) == FUNCTION_DECL
+ && DECL_CONSTRUCTOR_P (cand1->fn)
&& is_list_ctor (cand1->fn) != is_list_ctor (cand2->fn))
/* We're comparing a near-match list constructor and a near-match
non-list constructor. Just treat them as unordered. */
@@ -12145,9 +12279,20 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
gcc_assert (static_1 != static_2);
if (static_1)
- off2 = 1;
+ {
+ /* C++23 [over.best.ics.general] says:
+ When the parameter is the implicit object parameter of a static
+ member function, the implicit conversion sequence is a standard
+ conversion sequence that is neither better nor worse than any
+ other standard conversion sequence. */
+ if (CONVERSION_RANK (cand2->convs[0]) >= cr_user)
+ winner = 1;
+ off2 = 1;
+ }
else
{
+ if (CONVERSION_RANK (cand1->convs[0]) >= cr_user)
+ winner = -1;
off1 = 1;
--len;
}
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 5839bfb..266ec58 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3592,13 +3592,13 @@ diagnose_trait_expr (tree expr, tree args)
switch (TRAIT_EXPR_KIND (expr))
{
case CPTK_HAS_NOTHROW_ASSIGN:
- inform (loc, " %qT is not %<nothrow%> copy assignable", t1);
+ inform (loc, " %qT is not nothrow copy assignable", t1);
break;
case CPTK_HAS_NOTHROW_CONSTRUCTOR:
- inform (loc, " %qT is not %<nothrow%> default constructible", t1);
+ inform (loc, " %qT is not nothrow default constructible", t1);
break;
case CPTK_HAS_NOTHROW_COPY:
- inform (loc, " %qT is not %<nothrow%> copy constructible", t1);
+ inform (loc, " %qT is not nothrow copy constructible", t1);
break;
case CPTK_HAS_TRIVIAL_ASSIGN:
inform (loc, " %qT is not trivially copy assignable", t1);
@@ -3674,7 +3674,7 @@ diagnose_trait_expr (tree expr, tree args)
inform (loc, " %qT is not trivially assignable from %qT", t1, t2);
break;
case CPTK_IS_NOTHROW_ASSIGNABLE:
- inform (loc, " %qT is not %<nothrow%> assignable from %qT", t1, t2);
+ inform (loc, " %qT is not nothrow assignable from %qT", t1, t2);
break;
case CPTK_IS_CONSTRUCTIBLE:
if (!t2)
@@ -3690,9 +3690,9 @@ diagnose_trait_expr (tree expr, tree args)
break;
case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
if (!t2)
- inform (loc, " %qT is not %<nothrow%> default constructible", t1);
+ inform (loc, " %qT is not nothrow default constructible", t1);
else
- inform (loc, " %qT is not %<nothrow%> constructible from %qE", t1, t2);
+ inform (loc, " %qT is not nothrow constructible from %qE", t1, t2);
break;
case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
inform (loc, " %qT does not have unique object representations", t1);
@@ -3701,7 +3701,7 @@ diagnose_trait_expr (tree expr, tree args)
inform (loc, " %qT is not convertible from %qE", t2, t1);
break;
case CPTK_IS_NOTHROW_CONVERTIBLE:
- inform (loc, " %qT is not %<nothrow%> convertible from %qE", t2, t1);
+ inform (loc, " %qT is not nothrow convertible from %qE", t2, t1);
break;
case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY:
inform (loc, " %qT is not a reference that binds to a temporary "
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e4d8920..d0f1b18 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -504,6 +504,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
OVL_NESTED_P (in OVERLOAD)
DECL_MODULE_EXPORT_P (in _DECL)
PACK_EXPANSION_FORCE_EXTRA_ARGS_P (in *_PACK_EXPANSION)
+ LAMBDA_EXPR_STATIC_P (in LAMBDA_EXPR)
4: IDENTIFIER_MARKED (IDENTIFIER_NODEs)
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
CALL_EXPR, or FIELD_DECL).
@@ -517,6 +518,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
CALL_EXPR_REVERSE_ARGS (in CALL_EXPR, AGGR_INIT_EXPR)
CONSTRUCTOR_PLACEHOLDER_BOUNDARY (in CONSTRUCTOR)
OVL_EXPORT_P (in OVERLOAD)
+ DECL_NTTP_OBJECT_P (in VAR_DECL)
6: TYPE_MARKED_P (in _TYPE)
DECL_NONTRIVIALLY_INITIALIZED_P (in VAR_DECL)
RANGE_FOR_IVDEP (in RANGE_FOR_STMT)
@@ -1490,6 +1492,10 @@ enum cp_lambda_default_capture_mode_type {
#define LAMBDA_EXPR_CAPTURE_OPTIMIZED(NODE) \
TREE_LANG_FLAG_2 (LAMBDA_EXPR_CHECK (NODE))
+/* Predicate tracking whether the lambda was declared 'static'. */
+#define LAMBDA_EXPR_STATIC_P(NODE) \
+ TREE_LANG_FLAG_3 (LAMBDA_EXPR_CHECK (NODE))
+
/* True if this TREE_LIST in LAMBDA_EXPR_CAPTURE_LIST is for an explicit
capture. */
#define LAMBDA_CAPTURE_EXPLICIT_P(NODE) \
@@ -1834,6 +1840,10 @@ struct GTY(()) omp_declare_target_attr {
bool attr_syntax;
};
+struct GTY(()) omp_begin_assumes_data {
+ bool attr_syntax;
+};
+
/* Global state. */
struct GTY(()) saved_scope {
@@ -1881,6 +1891,7 @@ struct GTY(()) saved_scope {
hash_map<tree, tree> *GTY((skip)) x_local_specializations;
vec<omp_declare_target_attr, va_gc> *omp_declare_target_attribute;
+ vec<omp_begin_assumes_data, va_gc> *omp_begin_assumes;
struct saved_scope *prev;
};
@@ -3538,6 +3549,10 @@ struct GTY(()) lang_decl {
#define DECL_TINFO_P(NODE) \
TREE_LANG_FLAG_4 (TREE_CHECK2 (NODE,VAR_DECL,TYPE_DECL))
+/* true iff VAR_DECL node NODE is a NTTP object decl. */
+#define DECL_NTTP_OBJECT_P(NODE) \
+ TREE_LANG_FLAG_5 (TREE_CHECK (NODE,VAR_DECL))
+
/* 1 iff VAR_DECL node NODE is virtual table or VTT. We forward to
DECL_VIRTUAL_P from the common code, as that has the semantics we
need. But we want a more descriptive name. */
@@ -7282,6 +7297,7 @@ extern tree make_constrained_decltype_auto (tree, tree);
extern tree make_template_placeholder (tree);
extern bool template_placeholder_p (tree);
extern bool ctad_template_p (tree);
+extern bool unparenthesized_id_or_class_member_access_p (tree);
extern tree do_auto_deduction (tree, tree, tree,
tsubst_flags_t
= tf_warning_or_error,
@@ -7403,7 +7419,7 @@ extern bool alias_type_or_template_p (tree);
enum { nt_opaque = false, nt_transparent = true };
extern tree alias_template_specialization_p (const_tree, bool);
extern tree dependent_alias_template_spec_p (const_tree, bool);
-extern bool template_parm_object_p (const_tree);
+extern tree get_template_parm_object (tree expr, tree mangle);
extern tree tparm_object_argument (tree);
extern bool explicit_class_specialization_p (tree);
extern bool push_tinst_level (tree);
@@ -7946,6 +7962,7 @@ extern tree require_complete_type (tree,
extern tree complete_type (tree);
extern tree complete_type_or_else (tree, tree);
extern tree complete_type_or_maybe_complain (tree, tree, tsubst_flags_t);
+extern int cp_compare_floating_point_conversion_ranks (tree, tree);
inline bool type_unknown_p (const_tree);
enum { ce_derived, ce_type, ce_normal, ce_exact };
extern bool comp_except_specs (const_tree, const_tree, int);
@@ -8688,6 +8705,18 @@ struct push_access_scope_guard
}
};
+/* True if TYPE is an extended floating-point type. */
+
+inline bool
+extended_float_type_p (tree type)
+{
+ type = TYPE_MAIN_VARIANT (type);
+ for (int i = 0; i < NUM_FLOATN_NX_TYPES; ++i)
+ if (type == FLOATN_TYPE_NODE (i))
+ return true;
+ return false;
+}
+
#if CHECKING_P
namespace selftest {
extern void run_cp_tests (void);
diff --git a/gcc/cp/cxx-pretty-print.cc b/gcc/cp/cxx-pretty-print.cc
index e18143e3..bbd51bb 100644
--- a/gcc/cp/cxx-pretty-print.cc
+++ b/gcc/cp/cxx-pretty-print.cc
@@ -1956,7 +1956,7 @@ pp_cxx_template_argument_list (cxx_pretty_printer *pp, tree t)
if (TYPE_P (arg) || (TREE_CODE (arg) == TEMPLATE_DECL
&& TYPE_P (DECL_TEMPLATE_RESULT (arg))))
pp->type_id (arg);
- else if (template_parm_object_p (arg))
+ else if (TREE_CODE (arg) == VAR_DECL && DECL_NTTP_OBJECT_P (arg))
pp->expression (DECL_INITIAL (arg));
else
pp->expression (arg);
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 80467c1..fb85564 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -12095,12 +12095,7 @@ grokdeclarator (const cp_declarator *declarator,
}
if (declspecs->conflicting_specifiers_p)
- {
- error_at (min_location (declspecs->locations[ds_typedef],
- declspecs->locations[ds_storage_class]),
- "conflicting specifiers in declaration of %qs", name);
- return error_mark_node;
- }
+ return error_mark_node;
/* Extract the basic type from the decl-specifier-seq. */
type = declspecs->type;
@@ -15305,8 +15300,25 @@ grok_op_properties (tree decl, bool complain)
an enumeration, or a reference to an enumeration. 13.4.0.6 */
if (! methodp || DECL_STATIC_FUNCTION_P (decl))
{
+ if (operator_code == CALL_EXPR)
+ {
+ if (! DECL_STATIC_FUNCTION_P (decl))
+ {
+ error_at (loc, "%qD must be a member function", decl);
+ return false;
+ }
+ if (cxx_dialect < cxx23
+ /* For lambdas we diagnose static lambda specifier elsewhere. */
+ && ! LAMBDA_FUNCTION_P (decl)
+ /* For instantiations, we have diagnosed this already. */
+ && ! DECL_USE_TEMPLATE (decl))
+ pedwarn (loc, OPT_Wc__23_extensions, "%qD may be a static member "
+ "function only with %<-std=c++23%> or %<-std=gnu++23%>", decl);
+ /* There are no further restrictions on the arguments to an
+ overloaded "operator ()". */
+ return true;
+ }
if (operator_code == TYPE_EXPR
- || operator_code == CALL_EXPR
|| operator_code == COMPONENT_REF
|| operator_code == ARRAY_REF
|| operator_code == NOP_EXPR)
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 94181e7..53904e3 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -1129,7 +1129,7 @@ dump_global_iord (cxx_pretty_printer *pp, tree t)
static void
dump_simple_decl (cxx_pretty_printer *pp, tree t, tree type, int flags)
{
- if (template_parm_object_p (t))
+ if (TREE_CODE (t) == VAR_DECL && DECL_NTTP_OBJECT_P (t))
return dump_expr (pp, DECL_INITIAL (t), flags);
if (flags & TFF_DECL_SPECIFIERS)
@@ -1692,7 +1692,13 @@ dump_lambda_function (cxx_pretty_printer *pp,
{
/* A lambda's signature is essentially its "type". */
dump_type (pp, DECL_CONTEXT (fn), flags);
- if (!(TYPE_QUALS (class_of_this_parm (TREE_TYPE (fn))) & TYPE_QUAL_CONST))
+ if (TREE_CODE (TREE_TYPE (fn)) == FUNCTION_TYPE)
+ {
+ pp->padding = pp_before;
+ pp_c_ws_string (pp, "static");
+ }
+ else if (!(TYPE_QUALS (class_of_this_parm (TREE_TYPE (fn)))
+ & TYPE_QUAL_CONST))
{
pp->padding = pp_before;
pp_c_ws_string (pp, "mutable");
diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index 3ee1fe9..e9d5d4d 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -1099,7 +1099,9 @@ maybe_add_lambda_conv_op (tree type)
tree optype = TREE_TYPE (callop);
tree fn_result = TREE_TYPE (optype);
- tree thisarg = build_int_cst (TREE_TYPE (DECL_ARGUMENTS (callop)), 0);
+ tree thisarg = NULL_TREE;
+ if (TREE_CODE (optype) == METHOD_TYPE)
+ thisarg = build_int_cst (TREE_TYPE (DECL_ARGUMENTS (callop)), 0);
if (generic_lambda_p)
{
++processing_template_decl;
@@ -1109,18 +1111,25 @@ maybe_add_lambda_conv_op (tree type)
return expression for a deduced return call op to allow for simple
implementation of the conversion operator. */
- tree instance = cp_build_fold_indirect_ref (thisarg);
- tree objfn = lookup_template_function (DECL_NAME (callop),
- DECL_TI_ARGS (callop));
- objfn = build_min (COMPONENT_REF, NULL_TREE,
- instance, objfn, NULL_TREE);
- int nargs = list_length (DECL_ARGUMENTS (callop)) - 1;
+ tree objfn;
+ int nargs = list_length (DECL_ARGUMENTS (callop));
+ if (thisarg)
+ {
+ tree instance = cp_build_fold_indirect_ref (thisarg);
+ objfn = lookup_template_function (DECL_NAME (callop),
+ DECL_TI_ARGS (callop));
+ objfn = build_min (COMPONENT_REF, NULL_TREE,
+ instance, objfn, NULL_TREE);
+ --nargs;
+ call = prepare_op_call (objfn, nargs);
+ }
+ else
+ objfn = callop;
- call = prepare_op_call (objfn, nargs);
if (type_uses_auto (fn_result))
decltype_call = prepare_op_call (objfn, nargs);
}
- else
+ else if (thisarg)
{
direct_argvec = make_tree_vector ();
direct_argvec->quick_push (thisarg);
@@ -1135,9 +1144,11 @@ maybe_add_lambda_conv_op (tree type)
tree fn_args = NULL_TREE;
{
int ix = 0;
- tree src = DECL_CHAIN (DECL_ARGUMENTS (callop));
+ tree src = FUNCTION_FIRST_USER_PARM (callop);
tree tgt = NULL;
+ if (!thisarg && !decltype_call)
+ src = NULL_TREE;
while (src)
{
tree new_node = copy_node (src);
@@ -1160,12 +1171,15 @@ maybe_add_lambda_conv_op (tree type)
if (generic_lambda_p)
{
tree a = tgt;
- if (DECL_PACK_P (tgt))
+ if (thisarg)
{
- a = make_pack_expansion (a);
- PACK_EXPANSION_LOCAL_P (a) = true;
+ if (DECL_PACK_P (tgt))
+ {
+ a = make_pack_expansion (a);
+ PACK_EXPANSION_LOCAL_P (a) = true;
+ }
+ CALL_EXPR_ARG (call, ix) = a;
}
- CALL_EXPR_ARG (call, ix) = a;
if (decltype_call)
{
@@ -1193,7 +1207,7 @@ maybe_add_lambda_conv_op (tree type)
tf_warning_or_error);
}
}
- else
+ else if (thisarg)
{
/* Don't warn on deprecated or unavailable lambda declarations, unless
the lambda is actually called. */
@@ -1203,10 +1217,14 @@ maybe_add_lambda_conv_op (tree type)
direct_argvec->address ());
}
- CALL_FROM_THUNK_P (call) = 1;
- SET_EXPR_LOCATION (call, UNKNOWN_LOCATION);
+ if (thisarg)
+ {
+ CALL_FROM_THUNK_P (call) = 1;
+ SET_EXPR_LOCATION (call, UNKNOWN_LOCATION);
+ }
- tree stattype = build_function_type (fn_result, FUNCTION_ARG_CHAIN (callop));
+ tree stattype
+ = build_function_type (fn_result, FUNCTION_FIRST_USER_PARMTYPE (callop));
stattype = (cp_build_type_attribute_variant
(stattype, TYPE_ATTRIBUTES (optype)));
if (flag_noexcept_type
@@ -1249,6 +1267,41 @@ maybe_add_lambda_conv_op (tree type)
add_method (type, fn, false);
+ if (thisarg == NULL_TREE)
+ {
+ /* For static lambda, just return operator(). */
+ if (nested)
+ push_function_context ();
+ else
+ /* Still increment function_depth so that we don't GC in the
+ middle of an expression. */
+ ++function_depth;
+
+ /* Generate the body of the conversion op. */
+
+ start_preparsed_function (convfn, NULL_TREE,
+ SF_PRE_PARSED | SF_INCLASS_INLINE);
+ tree body = begin_function_body ();
+ tree compound_stmt = begin_compound_stmt (0);
+
+ /* decl_needed_p needs to see that it's used. */
+ TREE_USED (callop) = 1;
+ finish_return_stmt (decay_conversion (callop, tf_warning_or_error));
+
+ finish_compound_stmt (compound_stmt);
+ finish_function_body (body);
+
+ fn = finish_function (/*inline_p=*/true);
+ if (!generic_lambda_p)
+ expand_or_defer_fn (fn);
+
+ if (nested)
+ pop_function_context ();
+ else
+ --function_depth;
+ return;
+ }
+
/* Generic thunk code fails for varargs; we'll complain in mark_used if
the conversion op is used. */
if (varargs_function_p (callop))
diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 75388e9..1a45585 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -2648,63 +2648,24 @@ write_builtin_type (tree type)
write_string ("Dd");
else if (type == dfloat128_type_node || type == fallback_dfloat128_type)
write_string ("De");
+ else if (type == float16_type_node)
+ write_string ("DF16_");
+ else if (type == float32_type_node)
+ write_string ("DF32_");
+ else if (type == float64_type_node)
+ write_string ("DF64_");
+ else if (type == float128_type_node)
+ write_string ("DF128_");
+ else if (type == float32x_type_node)
+ write_string ("DF32x");
+ else if (type == float64x_type_node)
+ write_string ("DF64x");
+ else if (type == float128x_type_node)
+ write_string ("DF128x");
else
gcc_unreachable ();
break;
- case FIXED_POINT_TYPE:
- write_string ("DF");
- if (GET_MODE_IBIT (TYPE_MODE (type)) > 0)
- write_unsigned_number (GET_MODE_IBIT (TYPE_MODE (type)));
- if (type == fract_type_node
- || type == sat_fract_type_node
- || type == accum_type_node
- || type == sat_accum_type_node)
- write_char ('i');
- else if (type == unsigned_fract_type_node
- || type == sat_unsigned_fract_type_node
- || type == unsigned_accum_type_node
- || type == sat_unsigned_accum_type_node)
- write_char ('j');
- else if (type == short_fract_type_node
- || type == sat_short_fract_type_node
- || type == short_accum_type_node
- || type == sat_short_accum_type_node)
- write_char ('s');
- else if (type == unsigned_short_fract_type_node
- || type == sat_unsigned_short_fract_type_node
- || type == unsigned_short_accum_type_node
- || type == sat_unsigned_short_accum_type_node)
- write_char ('t');
- else if (type == long_fract_type_node
- || type == sat_long_fract_type_node
- || type == long_accum_type_node
- || type == sat_long_accum_type_node)
- write_char ('l');
- else if (type == unsigned_long_fract_type_node
- || type == sat_unsigned_long_fract_type_node
- || type == unsigned_long_accum_type_node
- || type == sat_unsigned_long_accum_type_node)
- write_char ('m');
- else if (type == long_long_fract_type_node
- || type == sat_long_long_fract_type_node
- || type == long_long_accum_type_node
- || type == sat_long_long_accum_type_node)
- write_char ('x');
- else if (type == unsigned_long_long_fract_type_node
- || type == sat_unsigned_long_long_fract_type_node
- || type == unsigned_long_long_accum_type_node
- || type == sat_unsigned_long_long_accum_type_node)
- write_char ('y');
- else
- sorry ("mangling unknown fixed point type");
- write_unsigned_number (GET_MODE_FBIT (TYPE_MODE (type)));
- if (TYPE_SATURATING (type))
- write_char ('s');
- else
- write_char ('n');
- break;
-
default:
gcc_unreachable ();
}
@@ -3711,7 +3672,7 @@ write_template_arg (tree node)
}
}
- if (template_parm_object_p (node))
+ if (TREE_CODE (node) == VAR_DECL && DECL_NTTP_OBJECT_P (node))
/* We want to mangle the argument, not the var we stored it in. */
node = tparm_object_argument (node);
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index 9f917f1..55af5c4 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -2246,6 +2246,7 @@ is_convertible_helper (tree from, tree to)
return integer_one_node;
cp_unevaluated u;
tree expr = build_stub_object (from);
+ deferring_access_check_sentinel acs (dk_no_deferred);
return perform_implicit_conversion (to, expr, tf_none);
}
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 7496df5..d965017 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -15777,6 +15777,8 @@ module_state::write_location (bytes_out &sec, location_t loc)
range.m_start = UNKNOWN_LOCATION;
write_location (sec, range.m_start);
write_location (sec, range.m_finish);
+ unsigned discriminator = get_discriminator_from_adhoc_loc (line_table, loc);
+ sec.u (discriminator);
}
else if (loc >= LINEMAPS_MACRO_LOWEST_LOCATION (line_table))
{
@@ -15902,8 +15904,9 @@ module_state::read_location (bytes_in &sec) const
if (range.m_start == UNKNOWN_LOCATION)
range.m_start = locus;
range.m_finish = read_location (sec);
+ unsigned discriminator = sec.u ();
if (locus != loc && range.m_start != loc && range.m_finish != loc)
- locus = get_combined_adhoc_loc (line_table, locus, range, NULL);
+ locus = get_combined_adhoc_loc (line_table, locus, range, NULL, discriminator);
}
break;
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index bb83d1c..d501178 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see
#include "cp-name-hint.h"
#include "memmodel.h"
#include "c-family/known-headers.h"
+#include "bitmap.h"
/* The lexer. */
@@ -1129,6 +1130,7 @@ cp_keyword_starts_decl_specifier_p (enum rid keyword)
case RID_UNSIGNED:
case RID_FLOAT:
case RID_DOUBLE:
+ CASE_RID_FLOATN_NX:
case RID_VOID:
/* CV qualifiers. */
case RID_CONST:
@@ -1994,7 +1996,7 @@ enum
constexpr. */
CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR = 0x8,
/* When parsing a decl-specifier-seq, only allow mutable, constexpr or
- for C++20 consteval. */
+ for C++20 consteval or for C++23 static. */
CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR = 0x10,
/* When parsing a decl-specifier-seq, allow missing typename. */
CP_PARSER_FLAGS_TYPENAME_OPTIONAL = 0x20,
@@ -11728,9 +11730,18 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
{
LAMBDA_EXPR_MUTABLE_P (lambda_expr) = 1;
quals = TYPE_UNQUALIFIED;
- if (lambda_specs.conflicting_specifiers_p)
+ }
+ else if (lambda_specs.storage_class == sc_static)
+ {
+ if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE
+ || LAMBDA_EXPR_CAPTURE_LIST (lambda_expr))
error_at (lambda_specs.locations[ds_storage_class],
- "duplicate %<mutable%>");
+ "%<static%> lambda specifier with lambda capture");
+ else
+ {
+ LAMBDA_EXPR_STATIC_P (lambda_expr) = 1;
+ quals = TYPE_UNQUALIFIED;
+ }
}
tx_qual = cp_parser_tx_qualifier_opt (parser);
@@ -11817,6 +11828,12 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
if (lambda_specs.locations[ds_consteval])
return_type_specs.locations[ds_consteval]
= lambda_specs.locations[ds_consteval];
+ if (LAMBDA_EXPR_STATIC_P (lambda_expr))
+ {
+ return_type_specs.storage_class = sc_static;
+ return_type_specs.locations[ds_storage_class]
+ = lambda_specs.locations[ds_storage_class];
+ }
p = obstack_alloc (&declarator_obstack, 0);
@@ -11840,8 +11857,9 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
{
DECL_INITIALIZED_IN_CLASS_P (fco) = 1;
DECL_ARTIFICIAL (fco) = 1;
- /* Give the object parameter a different name. */
- DECL_NAME (DECL_ARGUMENTS (fco)) = closure_identifier;
+ if (!LAMBDA_EXPR_STATIC_P (lambda_expr))
+ /* Give the object parameter a different name. */
+ DECL_NAME (DECL_ARGUMENTS (fco)) = closure_identifier;
DECL_SET_LAMBDA_FUNCTION (fco, true);
}
if (template_param_list)
@@ -15730,6 +15748,13 @@ cp_parser_decomposition_declaration (cp_parser *parser,
return decl;
}
+/* Names of storage classes. */
+
+static const char *const
+cp_storage_class_name[] = {
+ "", "auto", "register", "static", "extern", "mutable"
+};
+
/* Parse a decl-specifier-seq.
decl-specifier-seq:
@@ -15951,8 +15976,18 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
may as well commit at this point. */
cp_parser_commit_to_tentative_parse (parser);
- if (decl_specs->storage_class != sc_none)
- decl_specs->conflicting_specifiers_p = true;
+ if (decl_specs->storage_class != sc_none)
+ {
+ if (decl_specs->conflicting_specifiers_p)
+ break;
+ gcc_rich_location richloc (token->location);
+ location_t oloc = decl_specs->locations[ds_storage_class];
+ richloc.add_location_if_nearby (oloc);
+ error_at (&richloc,
+ "%<typedef%> specifier conflicts with %qs",
+ cp_storage_class_name[decl_specs->storage_class]);
+ decl_specs->conflicting_specifiers_p = true;
+ }
break;
/* storage-class-specifier:
@@ -16018,8 +16053,15 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
&& token->keyword != RID_MUTABLE
&& token->keyword != RID_CONSTEXPR
&& token->keyword != RID_CONSTEVAL)
- error_at (token->location, "%qD invalid in lambda",
- ridpointers[token->keyword]);
+ {
+ if (token->keyword != RID_STATIC)
+ error_at (token->location, "%qD invalid in lambda",
+ ridpointers[token->keyword]);
+ else if (cxx_dialect < cxx23)
+ pedwarn (token->location, OPT_Wc__23_extensions,
+ "%qD only valid in lambda with %<-std=c++23%> or "
+ "%<-std=gnu++23%>", ridpointers[token->keyword]);
+ }
if (ds != ds_last)
set_and_check_decl_spec_loc (decl_specs, ds, token);
@@ -19716,6 +19758,14 @@ cp_parser_simple_type_specifier (cp_parser* parser,
case RID_DOUBLE:
type = double_type_node;
break;
+ CASE_RID_FLOATN_NX:
+ type = FLOATN_NX_TYPE_NODE (token->keyword - RID_FLOATN_NX_FIRST);
+ if (type == NULL_TREE)
+ error ("%<_Float%d%s%> is not supported on this target",
+ floatn_nx_types[token->keyword - RID_FLOATN_NX_FIRST].n,
+ floatn_nx_types[token->keyword - RID_FLOATN_NX_FIRST].extended
+ ? "x" : "");
+ break;
case RID_VOID:
type = void_type_node;
break;
@@ -32836,26 +32886,6 @@ cp_parser_set_storage_class (cp_parser *parser,
{
cp_storage_class storage_class;
- if (parser->in_unbraced_linkage_specification_p)
- {
- error_at (token->location, "invalid use of %qD in linkage specification",
- ridpointers[keyword]);
- return;
- }
- else if (decl_specs->storage_class != sc_none)
- {
- decl_specs->conflicting_specifiers_p = true;
- return;
- }
-
- if ((keyword == RID_EXTERN || keyword == RID_STATIC)
- && decl_spec_seq_has_spec_p (decl_specs, ds_thread)
- && decl_specs->gnu_thread_keyword_p)
- {
- pedwarn (decl_specs->locations[ds_thread], 0,
- "%<__thread%> before %qD", ridpointers[keyword]);
- }
-
switch (keyword)
{
case RID_AUTO:
@@ -32876,6 +32906,38 @@ cp_parser_set_storage_class (cp_parser *parser,
default:
gcc_unreachable ();
}
+
+ if (parser->in_unbraced_linkage_specification_p)
+ {
+ error_at (token->location, "invalid use of %qD in linkage specification",
+ ridpointers[keyword]);
+ return;
+ }
+ else if (decl_specs->storage_class != sc_none)
+ {
+ if (decl_specs->conflicting_specifiers_p)
+ return;
+ gcc_rich_location richloc (token->location);
+ richloc.add_location_if_nearby (decl_specs->locations[ds_storage_class]);
+ if (decl_specs->storage_class == storage_class)
+ error_at (&richloc, "duplicate %qD specifier", ridpointers[keyword]);
+ else
+ error_at (&richloc,
+ "%qD specifier conflicts with %qs",
+ ridpointers[keyword],
+ cp_storage_class_name[decl_specs->storage_class]);
+ decl_specs->conflicting_specifiers_p = true;
+ return;
+ }
+
+ if ((keyword == RID_EXTERN || keyword == RID_STATIC)
+ && decl_spec_seq_has_spec_p (decl_specs, ds_thread)
+ && decl_specs->gnu_thread_keyword_p)
+ {
+ pedwarn (decl_specs->locations[ds_thread], 0,
+ "%<__thread%> before %qD", ridpointers[keyword]);
+ }
+
decl_specs->storage_class = storage_class;
set_and_check_decl_spec_loc (decl_specs, ds_storage_class, token);
@@ -32883,8 +32945,16 @@ cp_parser_set_storage_class (cp_parser *parser,
specifier. If there is a typedef specifier present then set
conflicting_specifiers_p which will trigger an error later
on in grokdeclarator. */
- if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef))
- decl_specs->conflicting_specifiers_p = true;
+ if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef)
+ && !decl_specs->conflicting_specifiers_p)
+ {
+ gcc_rich_location richloc (token->location);
+ richloc.add_location_if_nearby (decl_specs->locations[ds_typedef]);
+ error_at (&richloc,
+ "%qD specifier conflicts with %<typedef%>",
+ ridpointers[keyword]);
+ decl_specs->conflicting_specifiers_p = true;
+ }
}
/* Update the DECL_SPECS to reflect the TYPE_SPEC. If TYPE_DEFINITION_P
@@ -46018,6 +46088,218 @@ cp_parser_omp_context_selector_specification (cp_parser *parser,
return nreverse (ret);
}
+/* Assumption clauses:
+ OpenMP 5.1
+ absent (directive-name-list)
+ contains (directive-name-list)
+ holds (expression)
+ no_openmp
+ no_openmp_routines
+ no_parallelism */
+
+static void
+cp_parser_omp_assumption_clauses (cp_parser *parser, cp_token *pragma_tok,
+ bool is_assume)
+{
+ bool first = true;
+ bool no_openmp = false;
+ bool no_openmp_routines = false;
+ bool no_parallelism = false;
+ bitmap_head absent_head, contains_head;
+
+ bitmap_obstack_initialize (NULL);
+ bitmap_initialize (&absent_head, &bitmap_default_obstack);
+ bitmap_initialize (&contains_head, &bitmap_default_obstack);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA_EOL))
+ error_at (cp_lexer_peek_token (parser->lexer)->location,
+ "expected at least one assumption clause");
+
+ while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
+ {
+ /* For now only in C++ attributes, do it always for OpenMP 5.1. */
+ if ((!first || parser->lexer->in_omp_attribute_pragma)
+ && cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME))
+ cp_lexer_consume_token (parser->lexer);
+
+ first = false;
+
+ if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ break;
+
+ const char *p
+ = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value);
+ location_t cloc = cp_lexer_peek_token (parser->lexer)->location;
+
+ if (!strcmp (p, "no_openmp"))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ if (no_openmp)
+ error_at (cloc, "too many %qs clauses", "no_openmp");
+ no_openmp = true;
+ }
+ else if (!strcmp (p, "no_openmp_routines"))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ if (no_openmp_routines)
+ error_at (cloc, "too many %qs clauses", "no_openmp_routines");
+ no_openmp_routines = true;
+ }
+ else if (!strcmp (p, "no_parallelism"))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ if (no_parallelism)
+ error_at (cloc, "too many %qs clauses", "no_parallelism");
+ no_parallelism = true;
+ }
+ else if (!strcmp (p, "holds"))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ matching_parens parens;
+ if (parens.require_open (parser))
+ {
+ tree t = cp_parser_assignment_expression (parser);
+ if (!type_dependent_expression_p (t))
+ t = contextual_conv_bool (t, tf_warning_or_error);
+ if (is_assume)
+ {
+ /* FIXME: Emit .ASSUME (t) call here. */
+ (void) t;
+ }
+ if (!parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ }
+ }
+ else if (!strcmp (p, "absent") || !strcmp (p, "contains"))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ matching_parens parens;
+ if (parens.require_open (parser))
+ {
+ do
+ {
+ const char *directive[3] = {};
+ int i;
+ location_t dloc
+ = cp_lexer_peek_token (parser->lexer)->location;
+ for (i = 0; i < 3; i++)
+ {
+ tree id;
+ if (cp_lexer_nth_token_is (parser->lexer, i + 1, CPP_NAME))
+ id = cp_lexer_peek_nth_token (parser->lexer,
+ i + 1)->u.value;
+ else if (cp_lexer_nth_token_is (parser->lexer, i + 1,
+ CPP_KEYWORD))
+ {
+ enum rid rid
+ = cp_lexer_peek_nth_token (parser->lexer,
+ i + 1)->keyword;
+ id = ridpointers[rid];
+ }
+ else
+ break;
+ directive[i] = IDENTIFIER_POINTER (id);
+ }
+ if (i == 0)
+ error_at (dloc, "expected directive name");
+ else
+ {
+ const struct c_omp_directive *dir
+ = c_omp_categorize_directive (directive[0],
+ directive[1],
+ directive[2]);
+ if (dir == NULL
+ || dir->kind == C_OMP_DIR_DECLARATIVE
+ || dir->kind == C_OMP_DIR_INFORMATIONAL
+ || dir->id == PRAGMA_OMP_END
+ || (!dir->second && directive[1])
+ || (!dir->third && directive[2]))
+ error_at (dloc, "unknown OpenMP directive name in "
+ "%qs clause argument", p);
+ else
+ {
+ int id = dir - c_omp_directives;
+ if (bitmap_bit_p (p[0] == 'a' ? &contains_head
+ : &absent_head, id))
+ error_at (dloc, "%<%s%s%s%s%s%> directive "
+ "mentioned in both %<absent%> and "
+ "%<contains%> clauses",
+ directive[0],
+ directive[1] ? " " : "",
+ directive[1] ? directive[1] : "",
+ directive[2] ? " " : "",
+ directive[2] ? directive[2] : "");
+ else if (!bitmap_set_bit (p[0] == 'a'
+ ? &absent_head
+ : &contains_head, id))
+ error_at (dloc, "%<%s%s%s%s%s%> directive "
+ "mentioned multiple times in %qs "
+ "clauses",
+ directive[0],
+ directive[1] ? " " : "",
+ directive[1] ? directive[1] : "",
+ directive[2] ? " " : "",
+ directive[2] ? directive[2] : "", p);
+ }
+ for (; i; --i)
+ cp_lexer_consume_token (parser->lexer);
+ }
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ else
+ break;
+ }
+ while (1);
+ if (!parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ }
+ }
+ else if (startswith (p, "ext_"))
+ {
+ warning_at (cloc, 0, "unknown assumption clause %qs", p);
+ cp_lexer_consume_token (parser->lexer);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+ for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1;
+ n; --n)
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else
+ {
+ cp_lexer_consume_token (parser->lexer);
+ error_at (cloc, "expected assumption clause");
+ break;
+ }
+ }
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+}
+
+/* OpenMP 5.1
+ # pragma omp assume clauses[optseq] new-line */
+
+static void
+cp_parser_omp_assume (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
+{
+ cp_parser_omp_assumption_clauses (parser, pragma_tok, true);
+ add_stmt (cp_parser_omp_structured_block (parser, if_p));
+}
+
+/* OpenMP 5.1
+ # pragma omp assumes clauses[optseq] new-line */
+
+static bool
+cp_parser_omp_assumes (cp_parser *parser, cp_token *pragma_tok)
+{
+ cp_parser_omp_assumption_clauses (parser, pragma_tok, false);
+ return false;
+}
+
/* Finalize #pragma omp declare variant after a fndecl has been parsed, and put
that into "omp declare variant base" attribute. */
@@ -46467,8 +46749,41 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok)
"directive with only %<device_type%> clauses ignored");
}
+/* OpenMP 5.1
+ #pragma omp begin assumes clauses[optseq] new-line */
+
static void
-cp_parser_omp_end_declare_target (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_begin (cp_parser *parser, cp_token *pragma_tok)
+{
+ const char *p = "";
+ bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ p = IDENTIFIER_POINTER (id);
+ }
+ if (strcmp (p, "assumes") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_omp_assumption_clauses (parser, pragma_tok, false);
+ struct omp_begin_assumes_data a = { in_omp_attribute_pragma };
+ vec_safe_push (scope_chain->omp_begin_assumes, a);
+ }
+ else
+ {
+ cp_parser_error (parser, "expected %<assumes%>");
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ }
+}
+
+/* OpenMP 4.0:
+ # pragma omp end declare target new-line
+
+ OpenMP 5.1:
+ # pragma omp end assumes new-line */
+
+static void
+cp_parser_omp_end (cp_parser *parser, cp_token *pragma_tok)
{
const char *p = "";
bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
@@ -46494,33 +46809,58 @@ cp_parser_omp_end_declare_target (cp_parser *parser, cp_token *pragma_tok)
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
return;
}
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ if (!vec_safe_length (scope_chain->omp_declare_target_attribute))
+ error_at (pragma_tok->location,
+ "%<#pragma omp end declare target%> without corresponding "
+ "%<#pragma omp declare target%>");
+ else
+ {
+ omp_declare_target_attr
+ a = scope_chain->omp_declare_target_attribute->pop ();
+ if (a.attr_syntax != in_omp_attribute_pragma)
+ {
+ if (a.attr_syntax)
+ error_at (pragma_tok->location,
+ "%<declare target%> in attribute syntax terminated "
+ "with %<end declare target%> in pragma syntax");
+ else
+ error_at (pragma_tok->location,
+ "%<declare target%> in pragma syntax terminated "
+ "with %<end declare target%> in attribute syntax");
+ }
+ }
}
- else
+ else if (strcmp (p, "assumes") == 0)
{
- cp_parser_error (parser, "expected %<declare%>");
- cp_parser_skip_to_pragma_eol (parser, pragma_tok);
- return;
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ if (!vec_safe_length (scope_chain->omp_begin_assumes))
+ error_at (pragma_tok->location,
+ "%<#pragma omp end assumes%> without corresponding "
+ "%<#pragma omp begin assumes%>");
+ else
+ {
+ omp_begin_assumes_data
+ a = scope_chain->omp_begin_assumes->pop ();
+ if (a.attr_syntax != in_omp_attribute_pragma)
+ {
+ if (a.attr_syntax)
+ error_at (pragma_tok->location,
+ "%<begin assumes%> in attribute syntax terminated "
+ "with %<end assumes%> in pragma syntax");
+ else
+ error_at (pragma_tok->location,
+ "%<begin assumes%> in pragma syntax terminated "
+ "with %<end assumes%> in attribute syntax");
+ }
+ }
}
- cp_parser_require_pragma_eol (parser, pragma_tok);
- if (!vec_safe_length (scope_chain->omp_declare_target_attribute))
- error_at (pragma_tok->location,
- "%<#pragma omp end declare target%> without corresponding "
- "%<#pragma omp declare target%>");
else
{
- omp_declare_target_attr
- a = scope_chain->omp_declare_target_attribute->pop ();
- if (a.attr_syntax != in_omp_attribute_pragma)
- {
- if (a.attr_syntax)
- error_at (pragma_tok->location,
- "%<declare target%> in attribute syntax terminated "
- "with %<end declare target%> in pragma syntax");
- else
- error_at (pragma_tok->location,
- "%<declare target%> in pragma syntax terminated "
- "with %<end declare target%> in attribute syntax");
- }
+ cp_parser_error (parser, "expected %<declare%> or %<assumes%>");
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return;
}
}
@@ -47803,6 +48143,9 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
stmt = cp_parser_omp_teams (parser, pragma_tok, p_name, mask, NULL,
if_p);
break;
+ case PRAGMA_OMP_ASSUME:
+ cp_parser_omp_assume (parser, pragma_tok, if_p);
+ return;
default:
gcc_unreachable ();
}
@@ -48406,6 +48749,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
case PRAGMA_OACC_LOOP:
case PRAGMA_OACC_PARALLEL:
case PRAGMA_OACC_SERIAL:
+ case PRAGMA_OMP_ASSUME:
case PRAGMA_OMP_ATOMIC:
case PRAGMA_OMP_CRITICAL:
case PRAGMA_OMP_DISTRIBUTE:
@@ -48440,6 +48784,17 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
}
return cp_parser_omp_requires (parser, pragma_tok);
+ case PRAGMA_OMP_ASSUMES:
+ if (context != pragma_external)
+ {
+ error_at (pragma_tok->location,
+ "%<#pragma omp assumes%> may only be used at file or "
+ "namespace scope");
+ ret = true;
+ break;
+ }
+ return cp_parser_omp_assumes (parser, pragma_tok);
+
case PRAGMA_OMP_NOTHING:
cp_parser_omp_nothing (parser, pragma_tok);
return false;
@@ -48463,8 +48818,12 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
pop_omp_privatization_clauses (stmt);
return ret;
- case PRAGMA_OMP_END_DECLARE_TARGET:
- cp_parser_omp_end_declare_target (parser, pragma_tok);
+ case PRAGMA_OMP_BEGIN:
+ cp_parser_omp_begin (parser, pragma_tok);
+ return false;
+
+ case PRAGMA_OMP_END:
+ cp_parser_omp_end (parser, pragma_tok);
return false;
case PRAGMA_OMP_SCAN:
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 1f088fe..c7adaef 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -7112,16 +7112,6 @@ unify_template_argument_mismatch (bool explain_p, tree parm, tree arg)
return unify_invalid (explain_p);
}
-/* True if T is a C++20 template parameter object to store the argument for a
- template parameter of class type. */
-
-bool
-template_parm_object_p (const_tree t)
-{
- return (TREE_CODE (t) == VAR_DECL && DECL_ARTIFICIAL (t) && DECL_NAME (t)
- && startswith (IDENTIFIER_POINTER (DECL_NAME (t)), "_ZTA"));
-}
-
/* Subroutine of convert_nontype_argument, to check whether EXPR, as an
argument for TYPE, points to an unsuitable object.
@@ -7256,16 +7246,11 @@ invalid_tparm_referent_p (tree type, tree expr, tsubst_flags_t complain)
}
-/* The template arguments corresponding to template parameter objects of types
- that contain pointers to members. */
-
-static GTY(()) hash_map<tree, tree> *tparm_obj_values;
-
/* Return a VAR_DECL for the C++20 template parameter object corresponding to
template argument EXPR. */
static tree
-get_template_parm_object (tree expr, tsubst_flags_t complain)
+create_template_parm_object (tree expr, tsubst_flags_t complain)
{
if (TREE_CODE (expr) == TARGET_EXPR)
expr = TARGET_EXPR_INITIAL (expr);
@@ -7283,13 +7268,27 @@ get_template_parm_object (tree expr, tsubst_flags_t complain)
/* This is no longer a compound literal. */
gcc_assert (!TREE_HAS_CONSTRUCTOR (expr));
- tree name = mangle_template_parm_object (expr);
+ return get_template_parm_object (expr, mangle_template_parm_object (expr));
+}
+
+/* The template arguments corresponding to template parameter objects of types
+ that contain pointers to members. */
+
+static GTY(()) hash_map<tree, tree> *tparm_obj_values;
+
+/* Find or build an nttp object for (already-validated) EXPR with name
+ NAME. */
+
+tree
+get_template_parm_object (tree expr, tree name)
+{
tree decl = get_global_binding (name);
if (decl)
return decl;
tree type = cp_build_qualified_type (TREE_TYPE (expr), TYPE_QUAL_CONST);
decl = create_temporary_var (type);
+ DECL_NTTP_OBJECT_P (decl) = true;
DECL_CONTEXT (decl) = NULL_TREE;
TREE_STATIC (decl) = true;
DECL_DECLARED_CONSTEXPR_P (decl) = true;
@@ -7776,7 +7775,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
/* Replace the argument with a reference to the corresponding template
parameter object. */
if (!val_dep_p)
- expr = get_template_parm_object (expr, complain);
+ expr = create_template_parm_object (expr, complain);
if (expr == error_mark_node)
return NULL_TREE;
}
@@ -11945,6 +11944,7 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
auto o3 = make_temp_override (current_target_pragma, NULL_TREE);
auto o4 = make_temp_override (scope_chain->omp_declare_target_attribute,
NULL);
+ auto o5 = make_temp_override (scope_chain->omp_begin_assumes, NULL);
cplus_decl_attributes (decl_p, late_attrs, attr_flags);
@@ -30407,6 +30407,26 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
cp_type_quals (ptype));
}
+/* Return true if INIT is an unparenthesized id-expression or an
+ unparenthesized class member access. Used for the argument of
+ decltype(auto). */
+
+bool
+unparenthesized_id_or_class_member_access_p (tree init)
+{
+ STRIP_ANY_LOCATION_WRAPPER (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 (init)
+ && !REF_PARENTHESIZED_P (init))
+ init = TREE_OPERAND (init, 0);
+ return (DECL_P (init)
+ || ((TREE_CODE (init) == COMPONENT_REF
+ || TREE_CODE (init) == SCOPE_REF)
+ && !REF_PARENTHESIZED_P (init)));
+}
+
/* Replace occurrences of 'auto' in TYPE with the appropriate type deduced
from INIT. AUTO_NODE is the TEMPLATE_TYPE_PARM used for 'auto' in TYPE.
The CONTEXT determines the context in which auto deduction is performed
@@ -30442,6 +30462,23 @@ do_auto_deduction (tree type, tree init, tree auto_node,
auto_node. */
complain &= ~tf_partial;
+ /* In C++23, we must deduce the type to int&& for code like
+ decltype(auto) f(int&& x) { return (x); }
+ or
+ auto&& f(int x) { return x; }
+ so we use treat_lvalue_as_rvalue_p. But don't do it for
+ decltype(auto) f(int x) { return x; }
+ where we should deduce 'int' rather than 'int&&'; transmogrifying
+ INIT to an rvalue would break that. */
+ tree r;
+ if (cxx_dialect >= cxx23
+ && context == adc_return_type
+ && (!AUTO_IS_DECLTYPE (auto_node)
+ || !unparenthesized_id_or_class_member_access_p (init))
+ && (r = treat_lvalue_as_rvalue_p (maybe_undo_parenthesized_ref (init),
+ /*return*/true)))
+ init = r;
+
if (tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node))
/* C++17 class template argument deduction. */
return do_class_deduction (type, tmpl, init, flags, complain);
@@ -30503,18 +30540,7 @@ 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);
- /* 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);
- const bool id = (DECL_P (stripped_init)
- || ((TREE_CODE (stripped_init) == COMPONENT_REF
- || TREE_CODE (stripped_init) == SCOPE_REF)
- && !REF_PARENTHESIZED_P (stripped_init)));
+ const bool id = unparenthesized_id_or_class_member_access_p (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.cc b/gcc/cp/semantics.cc
index 92fc795..e8cd505 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -3363,6 +3363,13 @@ finish_translation_unit (void)
"%<#pragma omp end declare target%>");
vec_safe_truncate (scope_chain->omp_declare_target_attribute, 0);
}
+ if (vec_safe_length (scope_chain->omp_begin_assumes))
+ {
+ if (!errorcount)
+ error ("%<#pragma omp begin assumes%> without corresponding "
+ "%<#pragma omp end assumes%>");
+ vec_safe_truncate (scope_chain->omp_begin_assumes, 0);
+ }
}
/* Finish a template type parameter, specified as AGGR IDENTIFIER.
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index d0bd41a..ea4dfc6 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -382,7 +382,7 @@ obvalue_p (const_tree ref)
bool
xvalue_p (const_tree ref)
{
- return (lvalue_kind (ref) == clk_rvalueref);
+ return (lvalue_kind (ref) & clk_rvalueref);
}
/* True if REF is a bit-field. */
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 22d834d..5f16c4d 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -267,6 +267,133 @@ merge_type_attributes_from (tree type, tree other_type)
return cp_build_type_attribute_variant (type, attrs);
}
+/* Compare floating point conversion ranks and subranks of T1 and T2
+ types. If T1 and T2 have unordered conversion ranks, return 3.
+ If T1 has greater conversion rank than T2, return 2.
+ If T2 has greater conversion rank than T1, return -2.
+ If T1 has equal conversion rank as T2, return -1, 0 or 1 depending
+ on if T1 has smaller, equal or greater conversion subrank than
+ T2. */
+
+int
+cp_compare_floating_point_conversion_ranks (tree t1, tree t2)
+{
+ tree mv1 = TYPE_MAIN_VARIANT (t1);
+ tree mv2 = TYPE_MAIN_VARIANT (t2);
+ int extended1 = 0;
+ int extended2 = 0;
+
+ if (mv1 == mv2)
+ return 0;
+
+ for (int i = 0; i < NUM_FLOATN_NX_TYPES; ++i)
+ {
+ if (mv1 == FLOATN_NX_TYPE_NODE (i))
+ extended1 = i + 1;
+ if (mv2 == FLOATN_NX_TYPE_NODE (i))
+ extended2 = i + 1;
+ }
+ if (extended2 && !extended1)
+ {
+ int ret = cp_compare_floating_point_conversion_ranks (t2, t1);
+ return ret == 3 ? 3 : -ret;
+ }
+
+ const struct real_format *fmt1 = REAL_MODE_FORMAT (TYPE_MODE (t1));
+ const struct real_format *fmt2 = REAL_MODE_FORMAT (TYPE_MODE (t2));
+ gcc_assert (fmt1->b == 2 && fmt2->b == 2);
+ /* For {ibm,mips}_extended_format formats, the type has variable
+ precision up to ~2150 bits when the first double is around maximum
+ representable double and second double is subnormal minimum.
+ So, e.g. for __ibm128 vs. std::float128_t, they have unordered
+ ranks. */
+ int p1 = (MODE_COMPOSITE_P (TYPE_MODE (t1))
+ ? fmt1->emax - fmt1->emin + fmt1->p - 1 : fmt1->p);
+ int p2 = (MODE_COMPOSITE_P (TYPE_MODE (t2))
+ ? fmt2->emax - fmt2->emin + fmt2->p - 1 : fmt2->p);
+ /* The rank of a floating point type T is greater than the rank of
+ any floating-point type whose set of values is a proper subset
+ of the set of values of T. */
+ if ((p1 > p2 && fmt1->emax >= fmt2->emax)
+ || (p1 == p2 && fmt1->emax > fmt2->emax))
+ return 2;
+ if ((p1 < p2 && fmt1->emax <= fmt2->emax)
+ || (p1 == p2 && fmt1->emax < fmt2->emax))
+ return -2;
+ if ((p1 > p2 && fmt1->emax < fmt2->emax)
+ || (p1 < p2 && fmt1->emax > fmt2->emax))
+ return 3;
+ if (!extended1 && !extended2)
+ {
+ /* The rank of long double is greater than the rank of double, which
+ is greater than the rank of float. */
+ if (t1 == long_double_type_node)
+ return 2;
+ else if (t2 == long_double_type_node)
+ return -2;
+ if (t1 == double_type_node)
+ return 2;
+ else if (t2 == double_type_node)
+ return -2;
+ if (t1 == float_type_node)
+ return 2;
+ else if (t2 == float_type_node)
+ return -2;
+ return 0;
+ }
+ /* Two extended floating-point types with the same set of values have equal
+ ranks. */
+ if (extended1 && extended2)
+ {
+ if ((extended1 <= NUM_FLOATN_TYPES) == (extended2 <= NUM_FLOATN_TYPES))
+ {
+ /* Prefer higher extendedN value. */
+ if (extended1 > extended2)
+ return 1;
+ else if (extended1 < extended2)
+ return -1;
+ else
+ return 0;
+ }
+ else if (extended1 <= NUM_FLOATN_TYPES)
+ /* Prefer _FloatN type over _FloatMx type. */
+ return 1;
+ else if (extended2 <= NUM_FLOATN_TYPES)
+ return -1;
+ else
+ return 0;
+ }
+
+ /* gcc_assert (extended1 && !extended2); */
+ tree *p;
+ int cnt = 0;
+ for (p = &float_type_node; p <= &long_double_type_node; ++p)
+ {
+ const struct real_format *fmt3 = REAL_MODE_FORMAT (TYPE_MODE (*p));
+ gcc_assert (fmt3->b == 2);
+ int p3 = (MODE_COMPOSITE_P (TYPE_MODE (*p))
+ ? fmt3->emax - fmt3->emin + fmt3->p - 1 : fmt3->p);
+ if (p1 == p3 && fmt1->emax == fmt3->emax)
+ ++cnt;
+ }
+ /* An extended floating-point type with the same set of values
+ as exactly one cv-unqualified standard floating-point type
+ has a rank equal to the rank of that standard floating-point
+ type.
+
+ An extended floating-point type with the same set of values
+ as more than one cv-unqualified standard floating-point type
+ has a rank equal to the rank of double.
+
+ Thus, if the latter is true and t2 is long double, t2
+ has higher rank. */
+ if (cnt > 1 && mv2 == long_double_type_node)
+ return -2;
+ /* Otherwise, they have equal rank, but extended types
+ (other than std::bfloat16_t) have higher subrank. */
+ return 1;
+}
+
/* Return the common type for two arithmetic types T1 and T2 under the
usual arithmetic conversions. The default conversions have already
been applied, and enumerated types converted to their compatible
@@ -337,6 +464,23 @@ cp_common_type (tree t1, tree t2)
if (code2 == REAL_TYPE && code1 != REAL_TYPE)
return build_type_attribute_variant (t2, attributes);
+ if (code1 == REAL_TYPE
+ && (extended_float_type_p (t1) || extended_float_type_p (t2)))
+ {
+ tree mv1 = TYPE_MAIN_VARIANT (t1);
+ tree mv2 = TYPE_MAIN_VARIANT (t2);
+ if (mv1 == mv2)
+ return build_type_attribute_variant (t1, attributes);
+
+ int cmpret = cp_compare_floating_point_conversion_ranks (mv1, mv2);
+ if (cmpret == 3)
+ return error_mark_node;
+ else if (cmpret >= 0)
+ return build_type_attribute_variant (t1, attributes);
+ else
+ return build_type_attribute_variant (t2, attributes);
+ }
+
/* Both real or both integers; use the one with greater precision. */
if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
return build_type_attribute_variant (t1, attributes);
@@ -5037,7 +5181,20 @@ cp_build_binary_op (const op_location_t &location,
= targetm.invalid_binary_op (code, type0, type1)))
{
if (complain & tf_error)
- error (invalid_op_diag);
+ {
+ if (code0 == REAL_TYPE
+ && code1 == REAL_TYPE
+ && (extended_float_type_p (type0)
+ || extended_float_type_p (type1))
+ && cp_compare_floating_point_conversion_ranks (type0,
+ type1) == 3)
+ {
+ rich_location richloc (line_table, location);
+ binary_op_error (&richloc, code, type0, type1);
+ }
+ else
+ error (invalid_op_diag);
+ }
return error_mark_node;
}
@@ -5907,6 +6064,19 @@ cp_build_binary_op (const op_location_t &location,
&& (shorten || common || short_compare))
{
result_type = cp_common_type (type0, type1);
+ if (result_type == error_mark_node
+ && code0 == REAL_TYPE
+ && code1 == REAL_TYPE
+ && (extended_float_type_p (type0) || extended_float_type_p (type1))
+ && cp_compare_floating_point_conversion_ranks (type0, type1) == 3)
+ {
+ if (complain & tf_error)
+ {
+ rich_location richloc (line_table, location);
+ binary_op_error (&richloc, code, type0, type1);
+ }
+ return error_mark_node;
+ }
if (complain & tf_warning)
{
do_warn_double_promotion (result_type, type0, type1,
@@ -10872,9 +11042,13 @@ check_return_expr (tree retval, bool *no_warning)
the conditions for the named return value optimization. */
bool converted = false;
tree moved;
- /* This is only interesting for class type. */
- if (CLASS_TYPE_P (functype)
- && (moved = treat_lvalue_as_rvalue_p (retval, /*return*/true)))
+ /* Until C++23, this was only interesting for class type, but in C++23,
+ we should do the below when we're converting rom/to a class/reference
+ (a non-scalar type). */
+ if ((cxx_dialect < cxx23
+ ? CLASS_TYPE_P (functype)
+ : !SCALAR_TYPE_P (functype) || !SCALAR_TYPE_P (TREE_TYPE (retval)))
+ && (moved = treat_lvalue_as_rvalue_p (retval, /*return*/true)))
{
if (cxx_dialect < cxx20)
{
diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 739097a..d5236d1 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -997,12 +997,25 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain,
else if (TREE_CODE (ftype) == REAL_TYPE
&& TREE_CODE (type) == REAL_TYPE)
{
- if ((same_type_p (ftype, long_double_type_node)
- && (same_type_p (type, double_type_node)
- || same_type_p (type, float_type_node)))
- || (same_type_p (ftype, double_type_node)
- && same_type_p (type, float_type_node))
- || (TYPE_PRECISION (type) < TYPE_PRECISION (ftype)))
+ if ((extended_float_type_p (ftype) || extended_float_type_p (type))
+ ? /* "from a floating-point type T to another floating-point type
+ whose floating-point conversion rank is neither greater than
+ nor equal to that of T".
+ So, it is ok if
+ cp_compare_floating_point_conversion_ranks (ftype, type)
+ returns -2 (type has greater conversion rank than ftype)
+ or [-1..1] (type has equal conversion rank as ftype, possibly
+ different subrank. Only do this if at least one of the
+ types is extended floating-point type, otherwise keep doing
+ what we did before (for the sake of non-standard
+ backend types). */
+ cp_compare_floating_point_conversion_ranks (ftype, type) >= 2
+ : ((same_type_p (ftype, long_double_type_node)
+ && (same_type_p (type, double_type_node)
+ || same_type_p (type, float_type_node)))
+ || (same_type_p (ftype, double_type_node)
+ && same_type_p (type, float_type_node))
+ || (TYPE_PRECISION (type) < TYPE_PRECISION (ftype))))
{
if (TREE_CODE (init) == REAL_CST)
{
diff --git a/gcc/cselib.cc b/gcc/cselib.cc
index 6a56097..9b582e5 100644
--- a/gcc/cselib.cc
+++ b/gcc/cselib.cc
@@ -1569,6 +1569,26 @@ new_cselib_val (unsigned int hash, machine_mode mode, rtx x)
e->locs = 0;
e->next_containing_mem = 0;
+ scalar_int_mode int_mode;
+ if (REG_P (x) && is_int_mode (mode, &int_mode)
+ && REG_VALUES (REGNO (x)) != NULL
+ && (!cselib_current_insn || !DEBUG_INSN_P (cselib_current_insn)))
+ {
+ rtx copy = shallow_copy_rtx (x);
+ scalar_int_mode narrow_mode_iter;
+ FOR_EACH_MODE_UNTIL (narrow_mode_iter, int_mode)
+ {
+ PUT_MODE_RAW (copy, narrow_mode_iter);
+ cselib_val *v = cselib_lookup (copy, narrow_mode_iter, 0, VOIDmode);
+ if (v)
+ {
+ rtx sub = lowpart_subreg (narrow_mode_iter, e->val_rtx, int_mode);
+ if (sub)
+ new_elt_loc_list (v, sub);
+ }
+ }
+ }
+
if (dump_file && (dump_flags & TDF_CSELIB))
{
fprintf (dump_file, "cselib value %u:%u ", e->uid, hash);
diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog
index 9bb29d3..434c1c6 100644
--- a/gcc/d/ChangeLog
+++ b/gcc/d/ChangeLog
@@ -1,3 +1,15 @@
+2022-09-27 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * dmd/MERGE: Merge upstream dmd d579c467c1.
+ * decl.cc (layout_struct_initializer): Update for new front-end
+ interface.
+ * expr.cc (ExprVisitor::visit (AssignExp *)): Remove lowering of array
+ assignments.
+ (ExprVisitor::visit (NewExp *)): Add new lowering of new'ing
+ associative arrays to an _aaNew() library call.
+ * runtime.def (ARRAYSETASSIGN): Remove.
+ (AANEW): Define.
+
2022-09-15 Richard Biener <rguenther@suse.de>
* d-builtins.cc (d_build_c_type_nodes): Do not initialize
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index e91aee3..dcfca64 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -2335,7 +2335,7 @@ layout_struct_initializer (StructDeclaration *sd)
{
StructLiteralExp *sle = StructLiteralExp::create (sd->loc, sd, NULL);
- if (!sd->fill (sd->loc, sle->elements, true))
+ if (!sd->fill (sd->loc, *sle->elements, true))
gcc_unreachable ();
sle->type = sd->type;
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 85fc49d..a4c46f3 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-817610b16d0f0f469b9fbb28c000956fb910c43f
+4219ba670ce9ff92f3e874f0f048f2c28134c008
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/aggregate.d b/gcc/d/dmd/aggregate.d
index f4b5e8a..edca17f 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/dmd/aggregate.d
@@ -355,23 +355,22 @@ 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(const ref Loc loc, Expressions* elements, bool ctorinit)
+ final bool fill(const ref Loc loc, ref Expressions elements, bool ctorinit)
{
//printf("AggregateDeclaration::fill() %s\n", toChars());
assert(sizeok == Sizeok.done);
- assert(elements);
const nfields = nonHiddenFields();
bool errors = false;
size_t dim = elements.dim;
elements.setDim(nfields);
foreach (size_t i; dim .. nfields)
- (*elements)[i] = null;
+ elements[i] = null;
// Fill in missing any elements with default initializers
foreach (i; 0 .. nfields)
{
- if ((*elements)[i])
+ if (elements[i])
continue;
auto vd = fields[i];
@@ -389,7 +388,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
if (!vd.isOverlappedWith(v2))
continue;
- if ((*elements)[j])
+ if (elements[j])
{
vx = null;
break;
@@ -489,10 +488,10 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
else
e = telem.defaultInitLiteral(loc);
}
- (*elements)[fieldi] = e;
+ elements[fieldi] = e;
}
}
- foreach (e; *elements)
+ foreach (e; elements)
{
if (e && e.op == EXP.error)
return false;
diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h
index d91e35e..f0909e3 100644
--- a/gcc/d/dmd/aggregate.h
+++ b/gcc/d/dmd/aggregate.h
@@ -125,7 +125,7 @@ public:
bool determineSize(const Loc &loc);
virtual void finalizeSize() = 0;
uinteger_t size(const Loc &loc) override final;
- bool fill(const Loc &loc, Expressions *elements, bool ctorinit);
+ bool fill(const Loc &loc, Expressions &elements, bool ctorinit);
Type *getType() override final;
bool isDeprecated() const override final; // is aggregate deprecated?
void setDeprecated();
diff --git a/gcc/d/dmd/apply.d b/gcc/d/dmd/apply.d
index ac2c80e..3b73771 100644
--- a/gcc/d/dmd/apply.d
+++ b/gcc/d/dmd/apply.d
@@ -16,6 +16,7 @@ import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.expression;
+import dmd.root.array;
import dmd.visitor;
bool walkPostorder(Expression e, StoppableVisitor v)
@@ -86,12 +87,10 @@ public:
return stop;
}
- bool doCond(Expressions* e)
+ extern(D) bool doCond(Expression[] e)
{
- if (!e)
- return false;
- for (size_t i = 0; i < e.dim && !stop; i++)
- doCond((*e)[i]);
+ for (size_t i = 0; i < e.length && !stop; i++)
+ doCond(e[i]);
return stop;
}
@@ -110,13 +109,13 @@ public:
override void visit(NewExp e)
{
//printf("NewExp::apply(): %s\n", toChars());
- doCond(e.thisexp) || doCond(e.arguments) || applyTo(e);
+ doCond(e.thisexp) || doCond(e.arguments.peekSlice()) || applyTo(e);
}
override void visit(NewAnonClassExp e)
{
//printf("NewAnonClassExp::apply(): %s\n", toChars());
- doCond(e.thisexp) || doCond(e.arguments) || applyTo(e);
+ doCond(e.thisexp) || doCond(e.arguments.peekSlice()) || applyTo(e);
}
override void visit(TypeidExp e)
@@ -143,13 +142,13 @@ public:
override void visit(CallExp e)
{
//printf("CallExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
- doCond(e.e1) || doCond(e.arguments) || applyTo(e);
+ doCond(e.e1) || doCond(e.arguments.peekSlice()) || applyTo(e);
}
override void visit(ArrayExp e)
{
//printf("ArrayExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
- doCond(e.e1) || doCond(e.arguments) || applyTo(e);
+ doCond(e.e1) || doCond(e.arguments.peekSlice()) || applyTo(e);
}
override void visit(SliceExp e)
@@ -159,12 +158,12 @@ public:
override void visit(ArrayLiteralExp e)
{
- doCond(e.basis) || doCond(e.elements) || applyTo(e);
+ doCond(e.basis) || doCond(e.elements.peekSlice()) || applyTo(e);
}
override void visit(AssocArrayLiteralExp e)
{
- doCond(e.keys) || doCond(e.values) || applyTo(e);
+ doCond(e.keys.peekSlice()) || doCond(e.values.peekSlice()) || applyTo(e);
}
override void visit(StructLiteralExp e)
@@ -173,13 +172,13 @@ public:
return;
int old = e.stageflags;
e.stageflags |= stageApply;
- doCond(e.elements) || applyTo(e);
+ doCond(e.elements.peekSlice()) || applyTo(e);
e.stageflags = old;
}
override void visit(TupleExp e)
{
- doCond(e.e0) || doCond(e.exps) || applyTo(e);
+ doCond(e.e0) || doCond(e.exps.peekSlice()) || applyTo(e);
}
override void visit(CondExp e)
diff --git a/gcc/d/dmd/arrayop.d b/gcc/d/dmd/arrayop.d
index 272e751..f07a6f4 100644
--- a/gcc/d/dmd/arrayop.d
+++ b/gcc/d/dmd/arrayop.d
@@ -129,8 +129,7 @@ Expression arrayOp(BinExp e, Scope* sc)
return arrayOpInvalidError(e);
auto tiargs = new Objects();
- auto args = new Expressions();
- buildArrayOp(sc, e, tiargs, args);
+ auto args = buildArrayOp(sc, e, tiargs);
import dmd.dtemplate : TemplateDeclaration;
__gshared TemplateDeclaration arrayOp;
@@ -184,7 +183,7 @@ Expression arrayOp(BinAssignExp e, Scope* sc)
* using reverse polish notation (RPN) to encode order of operations.
* Encode operations as string arguments, using a "u" prefix for unary operations.
*/
-private void buildArrayOp(Scope* sc, Expression e, Objects* tiargs, Expressions* args)
+private Expressions* buildArrayOp(Scope* sc, Expression e, Objects* tiargs)
{
extern (C++) final class BuildArrayOpVisitor : Visitor
{
@@ -194,11 +193,11 @@ private void buildArrayOp(Scope* sc, Expression e, Objects* tiargs, Expressions*
Expressions* args;
public:
- extern (D) this(Scope* sc, Objects* tiargs, Expressions* args)
+ extern (D) this(Scope* sc, Objects* tiargs)
{
this.sc = sc;
this.tiargs = tiargs;
- this.args = args;
+ this.args = new Expressions();
}
override void visit(Expression e)
@@ -252,8 +251,9 @@ private void buildArrayOp(Scope* sc, Expression e, Objects* tiargs, Expressions*
}
}
- scope v = new BuildArrayOpVisitor(sc, tiargs, args);
+ scope v = new BuildArrayOpVisitor(sc, tiargs);
e.accept(v);
+ return v.args;
}
/***********************************************
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index b569a9c..3472d1c 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -1431,7 +1431,7 @@ extern (C++) final class UserAttributeDeclaration : AttribDeclaration
if (auto sc = _scope)
{
_scope = null;
- arrayExpressionSemantic(atts, sc);
+ arrayExpressionSemantic(atts.peekSlice(), sc);
}
auto exps = new Expressions();
if (userAttribDecl && userAttribDecl !is this)
@@ -1554,7 +1554,7 @@ int foreachUda(Dsymbol sym, Scope* sc, int delegate(Expression) dg)
return 0;
auto udas = sym.userAttribDecl.getAttributes();
- arrayExpressionSemantic(udas, sc, true);
+ arrayExpressionSemantic(udas.peekSlice(), sc, true);
return udas.each!((uda) {
if (!uda.isTupleExp())
diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d
index 088ca61..09e3833 100644
--- a/gcc/d/dmd/canthrow.d
+++ b/gcc/d/dmd/canthrow.d
@@ -111,13 +111,9 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN
auto ts = tbNext.baseElemOf().isTypeStruct();
if (ts)
{
- import dmd.id : Id;
-
auto sd = ts.sym;
const id = ce.f.ident;
- if (sd.postblit &&
- (id == Id._d_arrayctor || id == Id._d_arraysetctor ||
- id == Id._d_arrayassign_l || id == Id._d_arrayassign_r))
+ if (sd.postblit && isArrayConstructionOrAssign(id))
{
checkFuncThrows(ce, sd.postblit);
return;
diff --git a/gcc/d/dmd/chkformat.d b/gcc/d/dmd/chkformat.d
index e118d70..8204961 100644
--- a/gcc/d/dmd/chkformat.d
+++ b/gcc/d/dmd/chkformat.d
@@ -1079,386 +1079,210 @@ Format parseGenericFormatSpecifier(scope const char[] format,
return specifier; // success
}
-unittest
+@("parseGenericFormatSpecifier") unittest
{
- /* parseGenericFormatSpecifier
- */
-
char genSpecifier;
size_t idx;
- assert(parseGenericFormatSpecifier("hhd", idx, genSpecifier) == Format.hhd);
- assert(genSpecifier == 'd');
-
- idx = 0;
- assert(parseGenericFormatSpecifier("hn", idx, genSpecifier) == Format.hn);
- assert(genSpecifier == 'n');
-
- idx = 0;
- assert(parseGenericFormatSpecifier("ji", idx, genSpecifier) == Format.jd);
- assert(genSpecifier == 'i');
+ void testG(string fmtStr, Format expectedFormat, char expectedGenSpecifier)
+ {
+ idx = 0;
+ assert(parseGenericFormatSpecifier(fmtStr, idx, genSpecifier) == expectedFormat);
+ assert(genSpecifier == expectedGenSpecifier);
+ }
- idx = 0;
- assert(parseGenericFormatSpecifier("lu", idx, genSpecifier) == Format.lu);
- assert(genSpecifier == 'u');
+ testG("hhd", Format.hhd, 'd');
+ testG("hn", Format.hn, 'n');
+ testG("ji", Format.jd, 'i');
+ testG("lu", Format.lu, 'u');
idx = 0;
assert(parseGenericFormatSpecifier("k", idx, genSpecifier) == Format.error);
+}
- /* parsePrintfFormatSpecifier
- */
-
- bool widthStar;
- bool precisionStar;
-
- // one for each Format
- idx = 0;
- assert(parsePrintfFormatSpecifier("%d", idx, widthStar, precisionStar) == Format.d);
- assert(idx == 2);
- assert(!widthStar && !precisionStar);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%ld", idx, widthStar, precisionStar) == Format.ld);
- assert(idx == 3);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%lld", idx, widthStar, precisionStar) == Format.lld);
- assert(idx == 4);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%jd", idx, widthStar, precisionStar) == Format.jd);
- assert(idx == 3);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%zd", idx, widthStar, precisionStar) == Format.zd);
- assert(idx == 3);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%td", idx, widthStar, precisionStar) == Format.td);
- assert(idx == 3);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%g", idx, widthStar, precisionStar) == Format.g);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%Lg", idx, widthStar, precisionStar) == Format.Lg);
- assert(idx == 3);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%p", idx, widthStar, precisionStar) == Format.p);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%n", idx, widthStar, precisionStar) == Format.n);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%ln", idx, widthStar, precisionStar) == Format.ln);
- assert(idx == 3);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%lln", idx, widthStar, precisionStar) == Format.lln);
- assert(idx == 4);
+@("parsePrintfFormatSpecifier") unittest
+{
+ bool useGNUExts = false;
- idx = 0;
- assert(parsePrintfFormatSpecifier("%hn", idx, widthStar, precisionStar) == Format.hn);
- assert(idx == 3);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%hhn", idx, widthStar, precisionStar) == Format.hhn);
- assert(idx == 4);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%jn", idx, widthStar, precisionStar) == Format.jn);
- assert(idx == 3);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%zn", idx, widthStar, precisionStar) == Format.zn);
- assert(idx == 3);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%tn", idx, widthStar, precisionStar) == Format.tn);
- assert(idx == 3);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%c", idx, widthStar, precisionStar) == Format.c);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%lc", idx, widthStar, precisionStar) == Format.lc);
- assert(idx == 3);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%s", idx, widthStar, precisionStar) == Format.s);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%ls", idx, widthStar, precisionStar) == Format.ls);
- assert(idx == 3);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%%", idx, widthStar, precisionStar) == Format.percent);
- assert(idx == 2);
-
- // Synonyms
- idx = 0;
- assert(parsePrintfFormatSpecifier("%i", idx, widthStar, precisionStar) == Format.d);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%u", idx, widthStar, precisionStar) == Format.u);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%o", idx, widthStar, precisionStar) == Format.u);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%x", idx, widthStar, precisionStar) == Format.u);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%X", idx, widthStar, precisionStar) == Format.u);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%f", idx, widthStar, precisionStar) == Format.g);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%F", idx, widthStar, precisionStar) == Format.g);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%G", idx, widthStar, precisionStar) == Format.g);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%a", idx, widthStar, precisionStar) == Format.g);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%La", idx, widthStar, precisionStar) == Format.Lg);
- assert(idx == 3);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%A", idx, widthStar, precisionStar) == Format.g);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%lg", idx, widthStar, precisionStar) == Format.lg);
- assert(idx == 3);
-
- // width, precision
- idx = 0;
- assert(parsePrintfFormatSpecifier("%*d", idx, widthStar, precisionStar) == Format.d);
- assert(idx == 3);
- assert(widthStar && !precisionStar);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%.*d", idx, widthStar, precisionStar) == Format.d);
- assert(idx == 4);
- assert(!widthStar && precisionStar);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%*.*d", idx, widthStar, precisionStar) == Format.d);
- assert(idx == 5);
- assert(widthStar && precisionStar);
-
- // Too short formats
- {
- foreach (s; ["%", "%-", "%+", "% ", "%#", "%0", "%*", "%1", "%19", "%.", "%.*", "%.1", "%.12",
- "%j", "%z", "%t", "%l", "%h", "%ll", "%hh"])
- {
- idx = 0;
- assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar) == Format.error);
- assert(idx == s.length);
- }
- }
-
- // Undefined format combinations
- {
- foreach (s; ["%#d", "%llg", "%jg", "%zg", "%tg", "%hg", "%hhg",
- "%#c", "%0c", "%jc", "%zc", "%tc", "%Lc", "%hc", "%hhc", "%llc",
- "%#s", "%0s", "%js", "%zs", "%ts", "%Ls", "%hs", "%hhs", "%lls",
- "%jp", "%zp", "%tp", "%Lp", "%hp", "%lp", "%hhp", "%llp",
- "%-n", "%+n", "% n", "%#n", "%0n", "%*n", "%1n", "%19n", "%.n", "%.*n", "%.1n", "%.12n", "%Ln", "%K"])
- {
- idx = 0;
- assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar) == Format.error);
- assert(idx == s.length);
- }
- }
-
- /* parseScanfFormatSpecifier
- */
+ size_t idx = 0;
+ bool widthStar;
+ bool precisionStar;
- bool asterisk;
+ void testP(string fmtStr, Format expectedFormat, size_t expectedIdx)
+ {
+ idx = 0;
+ assert(parsePrintfFormatSpecifier(fmtStr, idx, widthStar, precisionStar, useGNUExts) == expectedFormat);
+ assert(idx == expectedIdx);
+ }
// one for each Format
- idx = 0;
- assert(parseScanfFormatSpecifier("%d", idx, asterisk) == Format.d);
- assert(idx == 2);
- assert(!asterisk);
+ testP("%d", Format.d, 2);
+ assert(!widthStar && !precisionStar);
+
+ testP("%ld", Format.ld, 3);
+ testP("%lld", Format.lld, 4);
+ testP("%jd", Format.jd, 3);
+ testP("%zd", Format.zd, 3);
+ testP("%td", Format.td, 3);
+ testP("%g", Format.g, 2);
+ testP("%Lg", Format.Lg, 3);
+ testP("%p", Format.p, 2);
+ testP("%n", Format.n, 2);
+ testP("%ln", Format.ln, 3);
+ testP("%lln", Format.lln, 4);
+ testP("%hn", Format.hn, 3);
+ testP("%hhn", Format.hhn, 4);
+ testP("%jn", Format.jn, 3);
+ testP("%zn", Format.zn, 3);
+ testP("%tn", Format.tn, 3);
+ testP("%c", Format.c, 2);
+ testP("%lc", Format.lc, 3);
+ testP("%s", Format.s, 2);
+ testP("%ls", Format.ls, 3);
+ testP("%%", Format.percent, 2);
- idx = 0;
- assert(parseScanfFormatSpecifier("%hhd", idx, asterisk) == Format.hhd);
- assert(idx == 4);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%hd", idx, asterisk) == Format.hd);
- assert(idx == 3);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%ld", idx, asterisk) == Format.ld);
- assert(idx == 3);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%lld", idx, asterisk) == Format.lld);
- assert(idx == 4);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%jd", idx, asterisk) == Format.jd);
- assert(idx == 3);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%zd", idx, asterisk) == Format.zd);
- assert(idx == 3);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%td", idx, asterisk,) == Format.td);
- assert(idx == 3);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%u", idx, asterisk) == Format.u);
- assert(idx == 2);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%hhu", idx, asterisk,) == Format.hhu);
- assert(idx == 4);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%hu", idx, asterisk) == Format.hu);
- assert(idx == 3);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%lu", idx, asterisk) == Format.lu);
- assert(idx == 3);
+ // Synonyms
+ testP("%i", Format.d, 2);
+ testP("%u", Format.u, 2);
+ testP("%o", Format.u, 2);
+ testP("%x", Format.u, 2);
+ testP("%X", Format.u, 2);
+ testP("%f", Format.g, 2);
+ testP("%F", Format.g, 2);
+ testP("%G", Format.g, 2);
+ testP("%a", Format.g, 2);
+ testP("%La", Format.Lg, 3);
+ testP("%A", Format.g, 2);
+ testP("%lg", Format.lg, 3);
+
+ // width, precision
+ testP("%*d", Format.d, 3);
+ assert(widthStar && !precisionStar);
+
+ testP("%.*d", Format.d, 4);
+ assert(!widthStar && precisionStar);
+
+ testP("%*.*d", Format.d, 5);
+ assert(widthStar && precisionStar);
- idx = 0;
- assert(parseScanfFormatSpecifier("%llu", idx, asterisk) == Format.llu);
- assert(idx == 4);
+ // Too short formats
+ foreach (s; ["%", "%-", "%+", "% ", "%#", "%0", "%*", "%1", "%19", "%.", "%.*", "%.1", "%.12",
+ "%j", "%z", "%t", "%l", "%h", "%ll", "%hh"])
+ {
+ testP(s, Format.error, s.length);
+ }
- idx = 0;
- assert(parseScanfFormatSpecifier("%ju", idx, asterisk) == Format.ju);
- assert(idx == 3);
+ // Undefined format combinations
+ foreach (s; ["%#d", "%llg", "%jg", "%zg", "%tg", "%hg", "%hhg",
+ "%#c", "%0c", "%jc", "%zc", "%tc", "%Lc", "%hc", "%hhc", "%llc",
+ "%#s", "%0s", "%js", "%zs", "%ts", "%Ls", "%hs", "%hhs", "%lls",
+ "%jp", "%zp", "%tp", "%Lp", "%hp", "%lp", "%hhp", "%llp",
+ "%-n", "%+n", "% n", "%#n", "%0n", "%*n", "%1n", "%19n", "%.n", "%.*n", "%.1n", "%.12n", "%Ln", "%K"])
+ {
+ testP(s, Format.error, s.length);
+ }
- idx = 0;
- assert(parseScanfFormatSpecifier("%g", idx, asterisk) == Format.g);
- assert(idx == 2);
+ testP("%C", Format.lc, 2);
+ testP("%S", Format.ls, 2);
- idx = 0;
- assert(parseScanfFormatSpecifier("%lg", idx, asterisk) == Format.lg);
- assert(idx == 3);
+ // GNU extensions: explicitly toggle ISO/GNU flag.
+ foreach (s; ["%jm", "%zm", "%tm", "%Lm", "%hm", "%hhm", "%lm", "%llm",
+ "%#m", "%+m", "%-m", "% m", "%0m"])
+ {
+ useGNUExts = false;
+ testP(s, Format.error, s.length);
+ useGNUExts = true;
+ testP(s, Format.error, s.length);
+ }
- idx = 0;
- assert(parseScanfFormatSpecifier("%Lg", idx, asterisk) == Format.Lg);
- assert(idx == 3);
+ foreach (s; ["%m", "%md", "%mz", "%mc", "%mm", "%msyz", "%ml", "%mlz", "%mlc", "%mlm"])
+ {
+ // valid cases, all parsed as `%m`
+ // GNU printf()
+ useGNUExts = true;
+ testP(s, Format.GNU_m, 2);
- idx = 0;
- assert(parseScanfFormatSpecifier("%p", idx, asterisk) == Format.p);
- assert(idx == 2);
+ // ISO printf()
+ useGNUExts = false;
+ testP(s, Format.error, 2);
+ }
+}
- idx = 0;
- assert(parseScanfFormatSpecifier("%s", idx, asterisk) == Format.s);
- assert(idx == 2);
+@("parseScanfFormatSpecifier") unittest
+{
+ size_t idx;
+ bool asterisk;
- idx = 0;
- assert(parseScanfFormatSpecifier("%ls", idx, asterisk,) == Format.ls);
- assert(idx == 3);
+ void testS(string fmtStr, Format expectedFormat, size_t expectedIdx)
+ {
+ idx = 0;
+ assert(parseScanfFormatSpecifier(fmtStr, idx, asterisk) == expectedFormat);
+ assert(idx == expectedIdx);
+ }
- idx = 0;
- assert(parseScanfFormatSpecifier("%%", idx, asterisk) == Format.percent);
- assert(idx == 2);
+ // one for each Format
+ testS("%d", Format.d, 2);
+ testS("%hhd", Format.hhd, 4);
+ testS("%hd", Format.hd, 3);
+ testS("%ld", Format.ld, 3);
+ testS("%lld", Format.lld, 4);
+ testS("%jd", Format.jd, 3);
+ testS("%zd", Format.zd, 3);
+ testS("%td", Format.td, 3);
+ testS("%u", Format.u, 2);
+ testS("%hhu", Format.hhu, 4);
+ testS("%hu", Format.hu, 3);
+ testS("%lu", Format.lu, 3);
+ testS("%llu", Format.llu, 4);
+ testS("%ju", Format.ju, 3);
+ testS("%g", Format.g, 2);
+ testS("%lg", Format.lg, 3);
+ testS("%Lg", Format.Lg, 3);
+ testS("%p", Format.p, 2);
+ testS("%s", Format.s, 2);
+ testS("%ls", Format.ls, 3);
+ testS("%%", Format.percent, 2);
// Synonyms
- idx = 0;
- assert(parseScanfFormatSpecifier("%i", idx, asterisk) == Format.d);
- assert(idx == 2);
+ testS("%i", Format.d, 2);
+ testS("%n", Format.n, 2);
- idx = 0;
- assert(parseScanfFormatSpecifier("%n", idx, asterisk) == Format.n);
- assert(idx == 2);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%o", idx, asterisk) == Format.u);
- assert(idx == 2);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%x", idx, asterisk) == Format.u);
- assert(idx == 2);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%f", idx, asterisk) == Format.g);
- assert(idx == 2);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%e", idx, asterisk) == Format.g);
- assert(idx == 2);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%a", idx, asterisk) == Format.g);
- assert(idx == 2);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%c", idx, asterisk) == Format.c);
- assert(idx == 2);
+ testS("%o", Format.u, 2);
+ testS("%x", Format.u, 2);
+ testS("%f", Format.g, 2);
+ testS("%e", Format.g, 2);
+ testS("%a", Format.g, 2);
+ testS("%c", Format.c, 2);
// asterisk
- idx = 0;
- assert(parseScanfFormatSpecifier("%*d", idx, asterisk) == Format.d);
- assert(idx == 3);
+ testS("%*d", Format.d, 3);
assert(asterisk);
- idx = 0;
- assert(parseScanfFormatSpecifier("%9ld", idx, asterisk) == Format.ld);
- assert(idx == 4);
+ testS("%9ld", Format.ld, 4);
assert(!asterisk);
- idx = 0;
- assert(parseScanfFormatSpecifier("%*25984hhd", idx, asterisk) == Format.hhd);
- assert(idx == 10);
+ testS("%*25984hhd", Format.hhd, 10);
assert(asterisk);
// scansets
- idx = 0;
- assert(parseScanfFormatSpecifier("%[a-zA-Z]", idx, asterisk) == Format.s);
- assert(idx == 9);
+ testS("%[a-zA-Z]", Format.s, 9);
assert(!asterisk);
- idx = 0;
- assert(parseScanfFormatSpecifier("%*25l[a-z]", idx, asterisk) == Format.ls);
- assert(idx == 10);
+ testS("%*25l[a-z]", Format.ls, 10);
assert(asterisk);
- idx = 0;
- assert(parseScanfFormatSpecifier("%[]]", idx, asterisk) == Format.s);
- assert(idx == 4);
+ testS("%[]]", Format.s, 4);
assert(!asterisk);
- idx = 0;
- assert(parseScanfFormatSpecifier("%[^]]", idx, asterisk) == Format.s);
- assert(idx == 5);
+ testS("%[^]]", Format.s, 5);
assert(!asterisk);
// Too short formats
foreach (s; ["%", "% ", "%#", "%0", "%*", "%1", "%19",
"%j", "%z", "%t", "%l", "%h", "%ll", "%hh", "%K"])
{
- idx = 0;
- assert(parseScanfFormatSpecifier(s, idx, asterisk) == Format.error);
- assert(idx == s.length);
+
+ testS(s, Format.error, s.length);
}
@@ -1468,18 +1292,16 @@ unittest
"%jp", "%zp", "%tp", "%Lp", "%hp", "%lp", "%hhp", "%llp",
"%-", "%+", "%#", "%0", "%.", "%Ln"])
{
- idx = 0;
- assert(parseScanfFormatSpecifier(s, idx, asterisk) == Format.error);
- assert(idx == s.length);
+
+ testS(s, Format.error, s.length);
}
// Invalid scansets
foreach (s; ["%[]", "%[^", "%[^]", "%[s", "%[0-9lld", "%[", "%l[^]"])
{
- idx = 0;
- assert(parseScanfFormatSpecifier(s, idx, asterisk) == Format.error);
- assert(idx == s.length);
+
+ testS(s, Format.error, s.length);
}
// Posix extensions
@@ -1488,95 +1310,19 @@ unittest
"%LC", "%lC", "%llC", "%jC", "%tC", "%hC", "%hhC", "%zC",
"%LS", "%lS", "%llS", "%jS", "%tS", "%hS", "%hhS", "%zS"])
{
- idx = 0;
- assert(parseScanfFormatSpecifier(s, idx, asterisk) == Format.error);
- assert(idx == s.length);
- }
- idx = 0;
- assert(parseScanfFormatSpecifier("%mc", idx, asterisk) == Format.POSIX_ms);
- assert(idx == 3);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%ms", idx, asterisk) == Format.POSIX_ms);
- assert(idx == 3);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%m[0-9]", idx, asterisk) == Format.POSIX_ms);
- assert(idx == 7);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%mlc", idx, asterisk) == Format.POSIX_mls);
- assert(idx == 4);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%mls", idx, asterisk) == Format.POSIX_mls);
- assert(idx == 4);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%ml[^0-9]", idx, asterisk) == Format.POSIX_mls);
- assert(idx == 9);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%mC", idx, asterisk) == Format.POSIX_mls);
- assert(idx == 3);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%mS", idx, asterisk) == Format.POSIX_mls);
- assert(idx == 3);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%C", idx, widthStar, precisionStar) == Format.lc);
- assert(idx == 2);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%C", idx, asterisk) == Format.lc);
- assert(idx == 2);
-
- idx = 0;
- assert(parsePrintfFormatSpecifier("%S", idx, widthStar, precisionStar) == Format.ls);
- assert(idx == 2);
-
- idx = 0;
- assert(parseScanfFormatSpecifier("%S", idx, asterisk) == Format.ls);
- assert(idx == 2);
-
- // GNU extensions: explicitly toggle ISO/GNU flag.
- // ISO printf()
- bool useGNUExts = false;
- {
- foreach (s; ["%jm", "%zm", "%tm", "%Lm", "%hm", "%hhm", "%lm", "%llm",
- "%#m", "%+m", "%-m", "% m", "%0m"])
- {
- idx = 0;
- assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.error);
- assert(idx == s.length);
- }
- foreach (s; ["%m", "%md", "%mz", "%mc", "%mm", "%msyz", "%ml", "%mlz", "%mlc", "%mlm"])
- {
- idx = 0;
- assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.error);
- assert(idx == 2);
- }
+ testS(s, Format.error, s.length);
}
- // GNU printf()
- useGNUExts = true;
- {
- foreach (s; ["%jm", "%zm", "%tm", "%Lm", "%hm", "%hhm", "%lm", "%llm",
- "%#m", "%+m", "%-m", "% m", "%0m"])
- {
- idx = 0;
- assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.error);
- assert(idx == s.length);
- }
-
- // valid cases, all parsed as `%m`
- foreach (s; ["%m", "%md", "%mz", "%mc", "%mm", "%msyz", "%ml", "%mlz", "%mlc", "%mlm"])
- {
- idx = 0;
- assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.GNU_m);
- assert(idx == 2);
- }
- }
+ testS("%mc", Format.POSIX_ms, 3);
+ testS("%ms", Format.POSIX_ms, 3);
+ testS("%m[0-9]", Format.POSIX_ms, 7);
+ testS("%mlc", Format.POSIX_mls, 4);
+ testS("%mls", Format.POSIX_mls, 4);
+ testS("%ml[^0-9]", Format.POSIX_mls, 9);
+ testS("%mC", Format.POSIX_mls, 3);
+ testS("%mS", Format.POSIX_mls, 3);
+
+ testS("%C", Format.lc, 2);
+ testS("%S", Format.ls, 2);
}
diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d
index 1a26eaa..ba7d590 100644
--- a/gcc/d/dmd/clone.d
+++ b/gcc/d/dmd/clone.d
@@ -105,8 +105,7 @@ FuncDeclaration hasIdentityOpAssign(AggregateDeclaration ad, Scope* sc)
scope er = new NullExp(ad.loc, ad.type); // dummy rvalue
scope el = new IdentifierExp(ad.loc, Id.p); // dummy lvalue
el.type = ad.type;
- Expressions a;
- a.setDim(1);
+ auto a = Expressions(1);
const errors = global.startGagging(); // Do not report errors, even if the template opAssign fbody makes it.
sc = sc.push();
sc.tinst = null;
@@ -465,8 +464,7 @@ private FuncDeclaration hasIdentityOpEquals(AggregateDeclaration ad, Scope* sc)
*/
scope er = new NullExp(ad.loc, null); // dummy rvalue
scope el = new IdentifierExp(ad.loc, Id.p); // dummy lvalue
- Expressions a;
- a.setDim(1);
+ auto a = Expressions(1);
bool hasIt(Type tthis)
{
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 2679a63..2c5a4f0 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -1886,15 +1886,6 @@ final class CParser(AST) : Parser!AST
}
if (s !is null)
{
- s = applySpecifier(s, specifier);
- if (level == LVL.local)
- {
- // Wrap the declaration in `extern (C) { declaration }`
- // Necessary for function pointers, but harmless to apply to all.
- auto decls = new AST.Dsymbols(1);
- (*decls)[0] = s;
- s = new AST.LinkDeclaration(s.loc, linkage, decls);
- }
// Saw `asm("name")` in the function, type, or variable definition.
// This is equivalent to `pragma(mangle, "name")` in D
if (asmName)
@@ -1917,6 +1908,15 @@ final class CParser(AST) : Parser!AST
p.mangleOverride = str;
}
}
+ s = applySpecifier(s, specifier);
+ if (level == LVL.local)
+ {
+ // Wrap the declaration in `extern (C) { declaration }`
+ // Necessary for function pointers, but harmless to apply to all.
+ auto decls = new AST.Dsymbols(1);
+ (*decls)[0] = s;
+ s = new AST.LinkDeclaration(s.loc, linkage, decls);
+ }
symbols.push(s);
}
first = false;
@@ -2603,7 +2603,6 @@ final class CParser(AST) : Parser!AST
{
//printf("cparseDeclarator(%d, %p)\n", declarator, t);
AST.Types constTypes; // all the Types that will need `const` applied to them
- constTypes.setDim(0);
AST.Type parseDecl(AST.Type t)
{
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index afd19f3..8ab3873 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -2979,10 +2979,10 @@ Lagain:
return Lret(t);
if (t1n.ty == Tvoid) // pointers to void are always compatible
- return Lret(t2);
+ return Lret(t1);
if (t2n.ty == Tvoid)
- return Lret(t);
+ return Lret(t2);
if (t1.implicitConvTo(t2))
return convert(e1, t2);
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index bc8db44..5bce6b0 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -210,7 +210,7 @@ public:
Dsymbol *aliassym;
const char *kind() const override;
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
bool overloadInsert(Dsymbol *s) override;
Dsymbol *toAlias() override;
@@ -625,7 +625,7 @@ public:
FuncDeclaration *syntaxCopy(Dsymbol *) override;
bool functionSemantic();
bool functionSemantic3();
- bool equals(const RootObject *o) const override final;
+ bool equals(const RootObject * const o) const override final;
int overrides(FuncDeclaration *fd);
int findVtblIndex(Dsymbols *vtbl, int dim);
diff --git a/gcc/d/dmd/dimport.d b/gcc/d/dmd/dimport.d
index 5cc3772..705acd1 100644
--- a/gcc/d/dmd/dimport.d
+++ b/gcc/d/dmd/dimport.d
@@ -265,11 +265,16 @@ extern (C++) final class Import : Dsymbol
scopesym.addAccessiblePackage(p, visibility);
foreach (id; packages[1 .. $]) // [b, c]
{
- p = cast(Package) p.symtab.lookup(id);
+ auto sym = p.symtab.lookup(id);
// https://issues.dlang.org/show_bug.cgi?id=17991
// An import of truly empty file/package can happen
// https://issues.dlang.org/show_bug.cgi?id=20151
// Package in the path conflicts with a module name
+ if (sym is null)
+ break;
+ // https://issues.dlang.org/show_bug.cgi?id=23327
+ // Package conflicts with symbol of the same name
+ p = sym.isPackage();
if (p is null)
break;
scopesym.addAccessiblePackage(p, visibility);
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index a9fd0f5..a95d9de 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -2830,7 +2830,7 @@ public:
(*exps)[i] = ex;
}
}
- sd.fill(e.loc, exps, false);
+ sd.fill(e.loc, *exps, false);
auto se = ctfeEmplaceExp!StructLiteralExp(e.loc, sd, exps, e.newtype);
se.origin = se;
@@ -4778,12 +4778,6 @@ public:
// If `_d_HookTraceImpl` is found, resolve the underlying hook and replace `e` and `fd` with it.
removeHookTraceImpl(e, fd);
- bool isArrayConstructionOrAssign(FuncDeclaration fd)
- {
- return fd.ident == Id._d_arrayctor || fd.ident == Id._d_arraysetctor ||
- fd.ident == Id._d_arrayassign_l || fd.ident == Id._d_arrayassign_r;
- }
-
if (fd.ident == Id.__ArrayPostblit || fd.ident == Id.__ArrayDtor)
{
assert(e.arguments.dim == 1);
@@ -4837,11 +4831,11 @@ public:
result = interpretRegion(ae, istate);
return;
}
- else if (isArrayConstructionOrAssign(fd))
+ else if (isArrayConstructionOrAssign(fd.ident))
{
// In expressionsem.d, the following lowerings were performed:
// * `T[x] ea = eb;` to `_d_array{,set}ctor(ea[], eb[]);`.
- // * `ea = eb` (ea and eb are arrays) to `_d_arrayassign_{l,r}(ea[], eb[])`.
+ // * `ea = eb` to `_d_array{,setassign,assign_l,assign_r}(ea[], eb)`.
// The following code will rewrite them back to `ea = eb` and
// then interpret that expression.
diff --git a/gcc/d/dmd/dmangle.d b/gcc/d/dmd/dmangle.d
index 25794e2..be0cbcc 100644
--- a/gcc/d/dmd/dmangle.d
+++ b/gcc/d/dmd/dmangle.d
@@ -833,6 +833,23 @@ public:
printf(" parent = %s %s", s.parent.kind(), s.parent.toChars());
printf("\n");
}
+ if (s.parent && s.ident)
+ {
+ if (auto m = s.parent.isModule())
+ {
+ if (m.filetype == FileType.c)
+ {
+ /* C types at global level get mangled into the __C global namespace
+ * to get the same mangling regardless of which module it
+ * is declared in. This works because types are the same if the mangling
+ * is the same.
+ */
+ mangleIdentifier(Id.ImportC, s); // parent
+ mangleIdentifier(s.ident, s);
+ return;
+ }
+ }
+ }
mangleParent(s);
if (s.ident)
mangleIdentifier(s.ident, s);
diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d
index ba83649..e1d5897 100644
--- a/gcc/d/dmd/doc.d
+++ b/gcc/d/dmd/doc.d
@@ -3294,7 +3294,7 @@ private struct MarkdownLink
* Params:
* buf = an OutBuffer containing the DDoc
* i = the index within `buf` that points to the first character of the URL.
- * If this function succeeds `i` will point just after the the end of the URL.
+ * If this function succeeds `i` will point just after the end of the URL.
* Returns: whether a URL was found and parsed
*/
private bool parseHref(ref OutBuffer buf, ref size_t i)
@@ -3362,7 +3362,7 @@ private struct MarkdownLink
* Params:
* buf = an OutBuffer containing the DDoc
* i = the index within `buf` that points to the first character of the title.
- * If this function succeeds `i` will point just after the the end of the title.
+ * If this function succeeds `i` will point just after the end of the title.
* Returns: whether a title was found and parsed
*/
private bool parseTitle(ref OutBuffer buf, ref size_t i)
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index c940ff0..7e2d02f 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -1544,6 +1544,12 @@ public:
if (flags & IgnoreAmbiguous) // if return NULL on ambiguity
return null;
+
+ /* If two imports from C import files, pick first one, as C has global name space
+ */
+ if (s.isCsymbol() && s2.isCsymbol())
+ continue;
+
if (!(flags & IgnoreErrors))
ScopeDsymbol.multiplyDefined(loc, s, s2);
break;
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index bea4b77..acf0004 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -189,7 +189,7 @@ public:
virtual const char *toPrettyCharsHelper(); // helper to print fully qualified (template) arguments
Loc getLoc();
const char *locToChars();
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
bool isAnonymous() const;
void error(const Loc &loc, const char *format, ...);
void error(const char *format, ...);
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index c3424dc..701f06a 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -58,6 +58,7 @@ import dmd.nspace;
import dmd.objc;
import dmd.opover;
import dmd.parse;
+import dmd.root.array;
import dmd.root.filename;
import dmd.common.outbuffer;
import dmd.root.rmem;
@@ -983,7 +984,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// possibilities.
if (fd && !(dsym.storage_class & (STC.manifest | STC.static_ | STC.gshared | STC.extern_)) && !dsym._init.isVoidInitializer())
{
- //printf("fd = '%s', var = '%s'\n", fd.toChars(), toChars());
+ //printf("fd = '%s', var = '%s'\n", fd.toChars(), dsym.toChars());
if (!ei)
{
ArrayInitializer ai = dsym._init.isArrayInitializer();
@@ -1014,24 +1015,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITinterpret);
}
- Expression exp = ei.exp;
- Expression e1 = new VarExp(dsym.loc, dsym);
- if (isBlit)
- exp = new BlitExp(dsym.loc, e1, exp);
- else
- exp = new ConstructExp(dsym.loc, e1, exp);
- dsym.canassign++;
- exp = exp.expressionSemantic(sc);
- dsym.canassign--;
- exp = exp.optimize(WANTvalue);
- if (exp.op == EXP.error)
- {
- dsym._init = new ErrorInitializer();
- ei = null;
- }
- else
- ei.exp = exp;
-
if (ei && dsym.isScope())
{
Expression ex = ei.exp.lastComma();
@@ -1054,6 +1037,24 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
f.tookAddressOf--;
}
}
+
+ Expression exp = ei.exp;
+ Expression e1 = new VarExp(dsym.loc, dsym);
+ if (isBlit)
+ exp = new BlitExp(dsym.loc, e1, exp);
+ else
+ exp = new ConstructExp(dsym.loc, e1, exp);
+ dsym.canassign++;
+ exp = exp.expressionSemantic(sc);
+ dsym.canassign--;
+ exp = exp.optimize(WANTvalue);
+ if (exp.op == EXP.error)
+ {
+ dsym._init = new ErrorInitializer();
+ ei = null;
+ }
+ else
+ ei.exp = exp;
}
else
{
@@ -1956,7 +1957,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
//printf("UserAttributeDeclaration::semantic() %p\n", this);
if (uad.decl && !uad._scope)
uad.Dsymbol.setScope(sc); // for function local symbols
- arrayExpressionSemantic(uad.atts, sc, true);
+ arrayExpressionSemantic(uad.atts.peekSlice(), sc, true);
return attribSemantic(uad);
}
@@ -4182,6 +4183,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
dd.errors = true;
return;
}
+
+ if (ad.isClassDeclaration() && ad.classKind == ClassKind.d)
+ {
+ // Class destructors are implicitly `scope`
+ dd.storage_class |= STC.scope_;
+ }
+
if (dd.ident == Id.dtor && dd.semanticRun < PASS.semantic)
ad.userDtors.push(dd);
if (!dd.type)
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index 34cae1d..13efc1c 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -1327,7 +1327,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
Loc instLoc = ti.loc;
Objects* tiargs = ti.tiargs;
- auto dedargs = new Objects();
+ auto dedargs = new Objects(parameters.dim);
Objects* dedtypes = &ti.tdtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
version (none)
@@ -1346,7 +1346,6 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
assert(_scope);
- dedargs.setDim(parameters.dim);
dedargs.zero();
dedtypes.setDim(parameters.dim);
@@ -1511,7 +1510,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
}
}
- if (toParent().isModule() || (_scope.stc & STC.static_))
+ if (toParent().isModule())
tthis = null;
if (tthis)
{
@@ -1534,7 +1533,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
}
// Match attributes of tthis against attributes of fd
- if (fd.type && !fd.isCtorDeclaration())
+ if (fd.type && !fd.isCtorDeclaration() && !(_scope.stc & STC.static_))
{
StorageClass stc = _scope.stc | fd.storage_class2;
// Propagate parent storage class, https://issues.dlang.org/show_bug.cgi?id=5504
@@ -2716,14 +2715,27 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
if (mfa == MATCH.nomatch)
return 0;
- if (mfa > m.last) goto LfIsBetter;
- if (mfa < m.last) goto LlastIsBetter;
+ int firstIsBetter()
+ {
+ td_best = null;
+ ti_best = null;
+ ta_last = MATCH.exact;
+ m.last = mfa;
+ m.lastf = fd;
+ tthis_best = tthis_fd;
+ ov_index = 0;
+ m.count = 1;
+ return 0;
+ }
+
+ if (mfa > m.last) return firstIsBetter();
+ if (mfa < m.last) return 0;
/* See if one of the matches overrides the other.
*/
assert(m.lastf);
- if (m.lastf.overrides(fd)) goto LlastIsBetter;
- if (fd.overrides(m.lastf)) goto LfIsBetter;
+ if (m.lastf.overrides(fd)) return 0;
+ if (fd.overrides(m.lastf)) return firstIsBetter();
/* Try to disambiguate using template-style partial ordering rules.
* In essence, if f() and g() are ambiguous, if f() can call g(),
@@ -2734,8 +2746,8 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
MATCH c1 = fd.leastAsSpecialized(m.lastf);
MATCH c2 = m.lastf.leastAsSpecialized(fd);
//printf("c1 = %d, c2 = %d\n", c1, c2);
- if (c1 > c2) goto LfIsBetter;
- if (c1 < c2) goto LlastIsBetter;
+ if (c1 > c2) return firstIsBetter();
+ if (c1 < c2) return 0;
}
/* The 'overrides' check above does covariant checking only
@@ -2756,12 +2768,12 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
{
if (firstCovariant != Covariant.yes && firstCovariant != Covariant.no)
{
- goto LlastIsBetter;
+ return 0;
}
}
else if (firstCovariant == Covariant.yes || firstCovariant == Covariant.no)
{
- goto LfIsBetter;
+ return firstIsBetter();
}
}
@@ -2780,37 +2792,22 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
fd._linkage == m.lastf._linkage)
{
if (fd.fbody && !m.lastf.fbody)
- goto LfIsBetter;
+ return firstIsBetter();
if (!fd.fbody)
- goto LlastIsBetter;
+ return 0;
}
// https://issues.dlang.org/show_bug.cgi?id=14450
// Prefer exact qualified constructor for the creating object type
if (isCtorCall && tf.mod != m.lastf.type.mod)
{
- if (tthis.mod == tf.mod) goto LfIsBetter;
- if (tthis.mod == m.lastf.type.mod) goto LlastIsBetter;
+ if (tthis.mod == tf.mod) return firstIsBetter();
+ if (tthis.mod == m.lastf.type.mod) return 0;
}
m.nextf = fd;
m.count++;
return 0;
-
- LlastIsBetter:
- return 0;
-
- LfIsBetter:
- td_best = null;
- ti_best = null;
- ta_last = MATCH.exact;
- m.last = mfa;
- m.lastf = fd;
- tthis_best = tthis_fd;
- ov_index = 0;
- m.count = 1;
- return 0;
-
}
int applyTemplate(TemplateDeclaration td)
@@ -3844,10 +3841,20 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
tp = (*parameters)[i];
else
{
+ Loc loc;
+ // The "type" (it hasn't been resolved yet) of the function parameter
+ // does not have a location but the parameter it is related to does,
+ // so we use that for the resolution (better error message).
+ if (inferStart < parameters.dim)
+ {
+ TemplateParameter loctp = (*parameters)[inferStart];
+ loc = loctp.loc;
+ }
+
Expression e;
Type tx;
Dsymbol s;
- taa.index.resolve(Loc.initial, sc, e, tx, s);
+ taa.index.resolve(loc, sc, e, tx, s);
edim = s ? getValue(s) : getValue(e);
}
}
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index 4f06bac..7ba0a96 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -1423,10 +1423,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
* auto dg = () return { return &x; }
* Because dg.ptr points to x, this is returning dt.ptr+offset
*/
- if (global.params.useDIP1000 == FeatureState.enabled)
- {
- sc.func.storage_class |= STC.return_ | STC.returninferred;
- }
+ sc.func.storage_class |= STC.return_ | STC.returninferred;
}
}
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index f871fade..42b4dd4 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -7197,6 +7197,26 @@ extern(D) Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag
}
}
+/**
+ * Verify if the given identifier is any of
+ * _d_array{ctor,setctor,setassign,assign_l, assign_r}.
+ *
+ * Params:
+ * id = the identifier to verify
+ *
+ * Returns:
+ * `true` if the identifier corresponds to a construction of assignement
+ * runtime hook, `false` otherwise.
+ */
+bool isArrayConstructionOrAssign(const Identifier id)
+{
+ import dmd.id : Id;
+
+ return id == Id._d_arrayctor || id == Id._d_arraysetctor ||
+ id == Id._d_arrayassign_l || id == Id._d_arrayassign_r ||
+ id == Id._d_arraysetassign;
+}
+
/******************************
* Provide efficient way to implement isUnaExp(), isBinExp(), isBinAssignExp()
*/
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index 9ab1cab..c9e3978 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -250,7 +250,7 @@ public:
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 override;
+ bool equals(const RootObject * const o) const override;
dinteger_t toInteger() override;
real_t toReal() override;
real_t toImaginary() override;
@@ -280,7 +280,7 @@ public:
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 override;
+ bool equals(const RootObject * const o) const override;
dinteger_t toInteger() override;
uinteger_t toUInteger() override;
real_t toReal() override;
@@ -297,7 +297,7 @@ public:
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 override;
+ bool equals(const RootObject * const o) const override;
dinteger_t toInteger() override;
uinteger_t toUInteger() override;
real_t toReal() override;
@@ -358,7 +358,7 @@ public:
class NullExp final : public Expression
{
public:
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
Optional<bool> toBool() override;
StringExp *toStringExp() override;
void accept(Visitor *v) override { v->visit(this); }
@@ -377,7 +377,7 @@ public:
static StringExp *create(const Loc &loc, const char *s);
static StringExp *create(const Loc &loc, const void *s, d_size_t len);
static void emplace(UnionExp *pue, const Loc &loc, const char *s);
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
char32_t getCodeUnit(d_size_t i) const;
void setCodeUnit(d_size_t i, char32_t c);
StringExp *toStringExp() override;
@@ -408,7 +408,7 @@ public:
static TupleExp *create(const Loc &loc, Expressions *exps);
TupleExp *syntaxCopy() override;
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -423,7 +423,7 @@ public:
static ArrayLiteralExp *create(const Loc &loc, Expressions *elements);
static void emplace(UnionExp *pue, const Loc &loc, Expressions *elements);
ArrayLiteralExp *syntaxCopy() override;
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
Expression *getElement(d_size_t i); // use opIndex instead
Expression *opIndex(d_size_t i);
Optional<bool> toBool() override;
@@ -439,7 +439,7 @@ public:
Expressions *values;
OwnedBy ownedByCtfe;
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
AssocArrayLiteralExp *syntaxCopy() override;
Optional<bool> toBool() override;
@@ -477,7 +477,7 @@ public:
OwnedBy ownedByCtfe;
static StructLiteralExp *create(const Loc &loc, StructDeclaration *sd, void *elements, Type *stype = NULL);
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
StructLiteralExp *syntaxCopy() override;
Expression *getField(Type *type, unsigned offset);
int getFieldIndex(Type *type, unsigned offset);
@@ -583,7 +583,7 @@ class VarExp final : public SymbolExp
public:
bool delegateWasExtracted;
static VarExp *create(const Loc &loc, Declaration *var, bool hasOverloads = true);
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
Expression *modifiableLvalue(Scope *sc, Expression *e) override;
@@ -612,7 +612,7 @@ public:
TemplateDeclaration *td;
TOK tok;
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
FuncExp *syntaxCopy() override;
const char *toChars() const override;
bool checkType() override;
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 3114100..8a4a13c 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -62,6 +62,7 @@ import dmd.opover;
import dmd.optimize;
import dmd.parse;
import dmd.printast;
+import dmd.root.array;
import dmd.root.ctfloat;
import dmd.root.file;
import dmd.root.filename;
@@ -336,22 +337,18 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* p
/******************************
* Perform semantic() on an array of Expressions.
*/
-bool arrayExpressionSemantic(Expressions* exps, Scope* sc, bool preserveErrors = false)
+extern(D) bool arrayExpressionSemantic(
+ Expression[] exps, Scope* sc, bool preserveErrors = false)
{
bool err = false;
- if (exps)
+ foreach (ref e; exps)
{
- foreach (ref e; *exps)
- {
- if (e)
- {
- auto e2 = e.expressionSemantic(sc);
- if (e2.op == EXP.error)
- err = true;
- if (preserveErrors || e2.op != EXP.error)
- e = e2;
- }
- }
+ if (e is null) continue;
+ auto e2 = e.expressionSemantic(sc);
+ if (e2.op == EXP.error)
+ err = true;
+ if (preserveErrors || e2.op != EXP.error)
+ e = e2;
}
return err;
}
@@ -443,7 +440,7 @@ private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
}
if (!s)
- return ue.e1.type.getProperty(sc, loc, ident, 0);
+ return ue.e1.type.getProperty(sc, loc, ident, 0, ue.e1);
FuncDeclaration f = s.isFuncDeclaration();
if (f)
@@ -550,7 +547,7 @@ private Expression resolveUFCS(Scope* sc, CallExp ce)
if (!global.endGagging(errors))
return e;
- if (arrayExpressionSemantic(originalArguments, sc))
+ if (arrayExpressionSemantic(originalArguments.peekSlice(), sc))
return ErrorExp.get();
/* fall down to UFCS */
@@ -3111,7 +3108,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (e.basis)
e.basis = e.basis.expressionSemantic(sc);
- if (arrayExpressionSemantic(e.elements, sc) || (e.basis && e.basis.op == EXP.error))
+ if (arrayExpressionSemantic(e.elements.peekSlice(), sc) || (e.basis && e.basis.op == EXP.error))
return setError();
expandTuples(e.elements);
@@ -3154,8 +3151,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
// Run semantic() on each element
- bool err_keys = arrayExpressionSemantic(e.keys, sc);
- bool err_vals = arrayExpressionSemantic(e.values, sc);
+ bool err_keys = arrayExpressionSemantic(e.keys.peekSlice(), sc);
+ bool err_vals = arrayExpressionSemantic(e.values.peekSlice(), sc);
if (err_keys || err_vals)
return setError();
@@ -3201,7 +3198,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
// run semantic() on each element
- if (arrayExpressionSemantic(e.elements, sc))
+ if (arrayExpressionSemantic(e.elements.peekSlice(), sc))
return setError();
expandTuples(e.elements);
@@ -3213,7 +3210,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* Fill out remainder of elements[] with default initializers for fields[]
*/
- if (!e.sd.fill(e.loc, e.elements, false))
+ if (!e.sd.fill(e.loc, *e.elements, false))
{
/* An error in the initializer needs to be recorded as an error
* in the enclosing function or template, since the initializer
@@ -3524,7 +3521,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.newtype = exp.type; // in case type gets cast to something else
Type tb = exp.type.toBasetype();
//printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco);
- if (arrayExpressionSemantic(exp.arguments, sc))
+ if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc))
{
return setError();
}
@@ -3672,7 +3669,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
- if (cd.disableNew)
+ if (cd.disableNew && !exp.onstack)
{
exp.error("cannot allocate `class %s` with `new` because it is annotated with `@disable new()`",
originalNewtype.toChars());
@@ -3807,7 +3804,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (!sd.fit(exp.loc, sc, exp.arguments, tb))
return setError();
- if (!sd.fill(exp.loc, exp.arguments, false))
+ if (!sd.fill(exp.loc, *exp.arguments, false))
return setError();
if (checkFrameAccess(exp.loc, sc, sd, exp.arguments ? exp.arguments.dim : 0))
@@ -4259,7 +4256,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
if (FuncExp fe = exp.e1.isFuncExp())
{
- if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
+ if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc) ||
+ preFunctionParameters(sc, exp.arguments))
return setError();
// Run e1 semantic even if arguments have any errors
@@ -4497,7 +4495,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = exp.e1;
return;
}
- if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
+ if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc) ||
+ preFunctionParameters(sc, exp.arguments))
return setError();
// Check for call operator overload
@@ -4543,7 +4542,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
goto Lx;
auto sle = new StructLiteralExp(exp.loc, sd, null, exp.e1.type);
- if (!sd.fill(exp.loc, sle.elements, true))
+ if (!sd.fill(exp.loc, *sle.elements, true))
return setError();
if (checkFrameAccess(exp.loc, sc, sd, sle.elements.dim))
return setError();
@@ -4614,7 +4613,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
Expression e;
- // Make sure to use the the enum type itself rather than its
+ // Make sure to use the enum type itself rather than its
// base type
// https://issues.dlang.org/show_bug.cgi?id=16346
if (exp.e1.type.ty == Tenum)
@@ -8661,7 +8660,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (sd.isNested())
{
auto sle = new StructLiteralExp(loc, sd, null, t);
- if (!sd.fill(loc, sle.elements, true))
+ if (!sd.fill(loc, *sle.elements, true))
return ErrorExp.get();
if (checkFrameAccess(loc, sc, sd, sle.elements.dim))
return ErrorExp.get();
@@ -9991,15 +9990,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
/***************************************
- * Lower AssignExp to `_d_arrayassign_{l,r}` if needed.
+ * Lower AssignExp to `_d_array{setassign,assign_l,assign_r}` if needed.
*
* Params:
* ae = the AssignExp to be lowered
* fromCommaExp = indicates whether `ae` is part of a CommaExp or not,
* so no unnecessary temporay variable is created.
* Returns:
- * a CommaExp contiaining call a to `_d_arrayassign_{l,r}` if needed or
- * `ae` otherwise
+ * a CommaExp contiaining call a to `_d_array{setassign,assign_l,assign_r}`
+ * if needed or `ae` otherwise
*/
private Expression lowerArrayAssign(AssignExp ae, bool fromCommaExp = false)
{
@@ -10007,12 +10006,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (t1b.ty != Tsarray && t1b.ty != Tarray)
return ae;
- const isArrayAssign =
- (ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) &&
+ const isArrayAssign = (ae.e1.isSliceExp() || ae.e1.type.ty == Tsarray) &&
(ae.e2.type.ty == Tsarray || ae.e2.type.ty == Tarray) &&
- (ae.e1.type.nextOf && ae.e2.type.nextOf && ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf));
+ (ae.e1.type.nextOf() && ae.e2.type.nextOf() && ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf()));
- if (!isArrayAssign)
+ const isArraySetAssign = (ae.e1.isSliceExp() || ae.e1.type.ty == Tsarray) &&
+ (ae.e1.type.nextOf() && ae.e2.type.implicitConvTo(ae.e1.type.nextOf()));
+
+ if (!isArrayAssign && !isArraySetAssign)
return ae;
const ts = t1b.nextOf().baseElemOf().isTypeStruct();
@@ -10020,9 +10021,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return ae;
Expression res;
- auto func = ae.e2.isLvalue || ae.e2.isSliceExp ? Id._d_arrayassign_l : Id._d_arrayassign_r;
+ Identifier func = isArraySetAssign ? Id._d_arraysetassign :
+ ae.e2.isLvalue() || ae.e2.isSliceExp() ? Id._d_arrayassign_l : Id._d_arrayassign_r;
- // Lower to `.object._d_arrayassign_l{r}(e1, e2)``
+ // Lower to `.object._d_array{setassign,assign_l,assign_r}(e1, e2)``
Expression id = new IdentifierExp(ae.loc, Id.empty);
id = new DotIdExp(ae.loc, id, Id.object);
id = new DotIdExp(ae.loc, id, func);
@@ -10032,10 +10034,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
.expressionSemantic(sc));
Expression eValue2, value2 = ae.e2;
- if (ae.e2.isLvalue)
- value2 = new CastExp(ae.loc, ae.e2, ae.e2.type.nextOf.arrayOf)
+ if (isArrayAssign && value2.isLvalue())
+ value2 = new CastExp(ae.loc, ae.e2, ae.e2.type.nextOf.arrayOf())
.expressionSemantic(sc);
- else if (!fromCommaExp)
+ else if (!fromCommaExp &&
+ (isArrayAssign || (isArraySetAssign && !value2.isLvalue())))
{
// Rvalues from CommaExps were introduced in `visit(AssignExp)`
// and are temporary variables themselves. Rvalues from trivial
@@ -10044,7 +10047,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// `__assigntmp` will be destroyed together with the array `ae.e1`.
// When `ae.e2` is a variadic arg array, it is also `scope`, so
// `__assigntmp` may also be scope.
- auto vd = copyToTemp(STC.rvalue | STC.nodtor | STC.scope_, "__assigntmp", ae.e2);
+ StorageClass stc = STC.nodtor;
+ if (isArrayAssign)
+ stc |= STC.rvalue | STC.scope_;
+
+ auto vd = copyToTemp(stc, "__assigntmp", ae.e2);
eValue2 = new DeclarationExp(vd.loc, vd).expressionSemantic(sc);
value2 = new VarExp(vd.loc, vd).expressionSemantic(sc);
}
@@ -10052,7 +10059,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Expression ce = new CallExp(ae.loc, id, arguments);
res = Expression.combine(eValue2, ce).expressionSemantic(sc);
- res = Expression.combine(res, ae.e1).expressionSemantic(sc);
+ if (isArrayAssign)
+ res = Expression.combine(res, ae.e1).expressionSemantic(sc);
if (global.params.verbose)
message("lowered %s =>\n %s", ae.toChars(), res.toChars());
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 4c09474..bcae282 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -3216,11 +3216,12 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
}
}
- if (tiargs && arrayObjectIsError(tiargs) ||
- fargs && arrayObjectIsError(cast(Objects*)fargs))
- {
+ if (tiargs && arrayObjectIsError(tiargs))
return null;
- }
+ if (fargs !is null)
+ foreach (arg; *fargs)
+ if (isError(arg))
+ return null;
MatchAccumulator m;
functionResolve(m, s, loc, sc, tiargs, tthis, fargs, null);
@@ -3758,9 +3759,9 @@ extern (C++) final class FuncLiteralDeclaration : FuncDeclaration
// backend
bool deferToObj;
- extern (D) this(const ref Loc loc, const ref Loc endloc, Type type, TOK tok, ForeachStatement fes, Identifier id = null)
+ extern (D) this(const ref Loc loc, const ref Loc endloc, Type type, TOK tok, ForeachStatement fes, Identifier id = null, StorageClass storage_class = STC.undefined_)
{
- super(loc, endloc, null, STC.undefined_, type);
+ super(loc, endloc, null, storage_class, type);
this.ident = id ? id : Id.empty;
this.tok = tok;
this.fes = fes;
@@ -3774,7 +3775,7 @@ extern (C++) final class FuncLiteralDeclaration : FuncDeclaration
{
//printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
assert(!s);
- auto f = new FuncLiteralDeclaration(loc, endloc, type.syntaxCopy(), tok, fes, ident);
+ auto f = new FuncLiteralDeclaration(loc, endloc, type.syntaxCopy(), tok, fes, ident, storage_class & STC.auto_);
f.treq = treq; // don't need to copy
FuncDeclaration.syntaxCopy(f);
return f;
@@ -3833,9 +3834,7 @@ extern (C++) final class FuncLiteralDeclaration : FuncDeclaration
{
Expression exp = s.exp;
if (exp && !exp.type.equals(tret))
- {
- s.exp = exp.castTo(sc, tret);
- }
+ s.exp = exp.implicitCastTo(sc, tret);
}
}
diff --git a/gcc/d/dmd/iasmgcc.d b/gcc/d/dmd/iasmgcc.d
index 7d4fbc3..7a840ff 100644
--- a/gcc/d/dmd/iasmgcc.d
+++ b/gcc/d/dmd/iasmgcc.d
@@ -84,13 +84,10 @@ int parseExtAsmOperands(Parser)(Parser p, GccAsmStatement s)
case TOK.string_:
constraint = p.parsePrimaryExp();
- // @@@DEPRECATED_2.101@@@
- // Old parser allowed omitting parentheses around the expression.
- // Deprecated in 2.091. Can be made permanent error after 2.100
if (p.token.value != TOK.leftParenthesis)
{
arg = p.parseAssignExp();
- deprecation(arg.loc, "`%s` must be surrounded by parentheses", arg.toChars());
+ error(arg.loc, "`%s` must be surrounded by parentheses", arg.toChars());
}
else
{
@@ -527,6 +524,9 @@ unittest
// Found ',' when expecting ':'
q{ asm { "", "";
} },
+
+ // https://issues.dlang.org/show_bug.cgi?id=20593
+ q{ asm { "instruction" : : "operand" 123; } },
];
foreach (test; passAsmTests)
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index 6695faa..48ca766 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -319,6 +319,7 @@ immutable Msgtable[] msgtable =
{ "_aaApply2" },
{ "_d_arrayctor" },
{ "_d_arraysetctor" },
+ { "_d_arraysetassign" },
{ "_d_arrayassign_l" },
{ "_d_arrayassign_r" },
@@ -511,6 +512,7 @@ immutable Msgtable[] msgtable =
{ "wchar_t" },
// for C compiler
+ { "ImportC", "__C" },
{ "__tag" },
{ "dllimport" },
{ "dllexport" },
diff --git a/gcc/d/dmd/init.d b/gcc/d/dmd/init.d
index 164a5f3..523b5b8 100644
--- a/gcc/d/dmd/init.d
+++ b/gcc/d/dmd/init.d
@@ -167,6 +167,7 @@ extern (C++) final class ArrayInitializer : Initializer
uint dim; // length of array being initialized
Type type; // type that array will be used to initialize
bool sem; // true if semantic() is run
+ bool isCarray; // C array semantics
extern (D) this(const ref Loc loc)
{
diff --git a/gcc/d/dmd/init.h b/gcc/d/dmd/init.h
index 296c31d..977157f 100644
--- a/gcc/d/dmd/init.h
+++ b/gcc/d/dmd/init.h
@@ -78,6 +78,7 @@ public:
unsigned dim; // length of array being initialized
Type *type; // type that array will be used to initialize
bool sem; // true if semantic() is run
+ bool isCarray; // C array semantics
bool isAssociativeArray() const;
Expression *toAssocArrayLiteral();
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index a576712..ef39f59 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -225,7 +225,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
assert(sc);
auto tm = vd.type.addMod(t.mod);
auto iz = i.value[j].initializerSemantic(sc, tm, needInterpret);
- auto ex = iz.initializerToExpression();
+ auto ex = iz.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0);
if (ex.op == EXP.error)
{
errors = true;
@@ -243,7 +243,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
// Make a StructLiteralExp out of elements[]
auto sle = new StructLiteralExp(i.loc, sd, elements, t);
- if (!sd.fill(i.loc, elements, false))
+ if (!sd.fill(i.loc, *elements, false))
return err();
sle.type = t;
auto ie = new ExpInitializer(i.loc, sle);
@@ -272,7 +272,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
uint length;
const(uint) amax = 0x80000000;
bool errors = false;
- //printf("ArrayInitializer::semantic(%s)\n", t.toChars());
+ //printf("ArrayInitializer::semantic(%s), ai: %s %p\n", t.toChars(), i.toChars(), i);
if (i.sem) // if semantic() already run
{
return i;
@@ -374,11 +374,22 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
}
if (auto tsa = t.isTypeSArray())
{
- uinteger_t edim = tsa.dim.toInteger();
- if (i.dim > edim && !(tsa.isIncomplete() && (sc.flags & SCOPE.Cfile)))
+ if (sc.flags & SCOPE.Cfile && tsa.isIncomplete())
{
- error(i.loc, "array initializer has %u elements, but array length is %llu", i.dim, edim);
- return err();
+ // Change to array of known length
+ auto tn = tsa.next.toBasetype();
+ tsa = new TypeSArray(tn, new IntegerExp(Loc.initial, i.dim, Type.tsize_t));
+ tx = tsa; // rewrite caller's type
+ i.type = tsa; // remember for later passes
+ }
+ else
+ {
+ uinteger_t edim = tsa.dim.toInteger();
+ if (i.dim > edim)
+ {
+ error(i.loc, "array initializer has %u elements, but array length is %llu", i.dim, edim);
+ return err();
+ }
}
}
if (errors)
@@ -394,6 +405,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
error(i.loc, "array dimension %llu exceeds max of %llu", ulong(i.dim), ulong(amax / sz));
return err();
}
+ //printf("returns ai: %s\n", i.toChars());
return i;
}
@@ -661,295 +673,380 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
Initializer visitC(CInitializer ci)
{
- if (ci.sem) // if semantic() already run
- return ci;
//printf("CInitializer::semantic() (%s) %s\n", t.toChars(), ci.toChars());
- ci.sem = true;
+ /* Rewrite CInitializer into ExpInitializer, ArrayInitializer, or StructInitializer
+ */
t = t.toBasetype();
- ci.type = t; // later passes will need this
-
- auto dil = ci.initializerList[];
- size_t i = 0; // index into dil[]
- const uint amax = 0x8000_0000;
- bool errors;
/* If `{ expression }` return the expression initializer
*/
ExpInitializer isBraceExpression()
{
+ auto dil = ci.initializerList[];
return (dil.length == 1 && !dil[0].designatorList)
? dil[0].initializer.isExpInitializer()
: null;
}
- /* Convert struct initializer into ExpInitializer
+ /********************************
*/
- Initializer structs(TypeStruct ts)
+ bool overlaps(VarDeclaration field, VarDeclaration[] fields, StructInitializer si)
{
- //printf("structs %s\n", ts.toChars());
+ foreach (fld; fields)
+ {
+ if (field.isOverlappedWith(fld))
+ {
+ // look for initializer corresponding with fld
+ foreach (i, ident; si.field[])
+ {
+ if (ident == fld.ident && si.value[i])
+ return true; // already an initializer for `field`
+ }
+ }
+ }
+ return false;
+ }
+
+ /* Run semantic on ExpInitializer, see if it represents entire struct ts
+ */
+ bool representsStruct(ExpInitializer ei, TypeStruct ts)
+ {
+ if (needInterpret)
+ sc = sc.startCTFE();
+ ei.exp = ei.exp.expressionSemantic(sc);
+ ei.exp = resolveProperties(sc, ei.exp);
+ if (needInterpret)
+ sc = sc.endCTFE();
+ return ei.exp.implicitConvTo(ts) != MATCH.nomatch; // initializer represents the entire struct
+ }
+
+ /* If { } are omitted from substructs, use recursion to reconstruct where
+ * brackets go
+ * Params:
+ * ts = substruct to initialize
+ * index = index into ci.initializer, updated
+ * Returns: struct initializer for this substruct
+ */
+ Initializer subStruct()(TypeStruct ts, ref size_t index)
+ {
+ //printf("subStruct(ts: %s, index %d)\n", ts.toChars(), cast(int)index);
+
+ auto si = new StructInitializer(ci.loc);
StructDeclaration sd = ts.sym;
sd.size(ci.loc);
if (sd.sizeok != Sizeok.done)
{
- errors = true;
+ index = ci.initializerList.length;
return err();
}
- const nfields = sd.nonHiddenFields();
- auto elements = new Expressions(nfields);
- auto elems = (*elements)[];
- foreach (ref elem; elems)
- elem = null;
+ const nfields = sd.fields.length;
- FieldLoop:
- for (size_t fieldi = 0; fieldi < nfields; ++fieldi)
+ foreach (fieldi; 0 .. nfields)
{
- if (i == dil.length)
- break;
-
- auto di = dil[i];
- if (di.designatorList)
+ if (index >= ci.initializerList.length)
+ break; // ran out of initializers
+ auto di = ci.initializerList[index];
+ if (di.designatorList && fieldi != 0)
+ break; // back to top level
+ else
{
- error(ci.loc, "C designator-list not supported yet");
- errors = true;
- break;
+ VarDeclaration field;
+ while (1) // skip field if it overlaps with previously seen fields
+ {
+ field = sd.fields[fieldi];
+ ++fieldi;
+ if (!overlaps(field, sd.fields[], si))
+ break;
+ if (fieldi == nfields)
+ break;
+ }
+ auto tn = field.type.toBasetype();
+ auto tnsa = tn.isTypeSArray();
+ auto tns = tn.isTypeStruct();
+ auto ix = di.initializer;
+ if (tnsa && ix.isExpInitializer())
+ {
+ ExpInitializer ei = ix.isExpInitializer();
+ if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
+ {
+ si.addInit(field.ident, ei);
+ ++index;
+ }
+ else
+ si.addInit(field.ident, subArray(tnsa, index)); // fwd ref of subArray is why subStruct is a template
+ }
+ else if (tns && ix.isExpInitializer())
+ {
+ /* Disambiguate between an exp representing the entire
+ * struct, and an exp representing the first field of the struct
+ */
+ if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
+ {
+ si.addInit(field.ident, initializerSemantic(ix, sc, tn, needInterpret));
+ ++index;
+ }
+ else // field initializers for struct
+ si.addInit(field.ident, subStruct(tns, index)); // the first field
+ }
+ else
+ {
+ si.addInit(field.ident, ix);
+ ++index;
+ }
}
+ }
+ //printf("subStruct() returns ai: %s, index: %d\n", si.toChars(), cast(int)index);
+ return si;
+ }
- VarDeclaration vd = sd.fields[fieldi];
+ /* If { } are omitted from subarrays, use recursion to reconstruct where
+ * brackets go
+ * Params:
+ * tsa = subarray to initialize
+ * index = index into ci.initializer, updated
+ * Returns: array initializer for this subarray
+ */
+ Initializer subArray(TypeSArray tsa, ref size_t index)
+ {
+ //printf("array(tsa: %s, index %d)\n", tsa.toChars(), cast(int)index);
+ if (tsa.isIncomplete())
+ {
+ // C11 6.2.5-20 "element type shall be complete whenever the array type is specified"
+ assert(0); // should have been detected by parser
+ }
- // Check for overlapping initializations (can happen with unions)
- foreach (k, v2; sd.fields[0 .. nfields])
+ auto tnsa = tsa.nextOf().toBasetype().isTypeSArray();
+
+ auto ai = new ArrayInitializer(ci.loc);
+ ai.isCarray = true;
+
+ foreach (n; 0 .. cast(size_t)tsa.dim.toInteger())
+ {
+ if (index >= ci.initializerList.length)
+ break; // ran out of initializers
+ auto di = ci.initializerList[index];
+ if (di.designatorList)
+ break; // back to top level
+ else if (tnsa && di.initializer.isExpInitializer())
{
- if (vd.isOverlappedWith(v2) && elems[k])
+ ExpInitializer ei = di.initializer.isExpInitializer();
+ if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
{
- continue FieldLoop; // skip it
+ ai.addInit(null, ei);
+ ++index;
}
+ else
+ ai.addInit(null, subArray(tnsa, index));
}
-
- ++i;
-
- // Convert initializer to Expression `ex`
- assert(sc);
- auto tm = vd.type.addMod(ts.mod);
- auto iz = di.initializer.initializerSemantic(sc, tm, needInterpret);
- auto ex = iz.initializerToExpression(null, true);
- if (ex.op == EXP.error)
+ else
{
- errors = true;
- continue;
+ ai.addInit(null, di.initializer);
+ ++index;
}
-
- elems[fieldi] = ex;
}
- if (errors)
- return err();
-
- // Make a StructLiteralExp out of elements[]
- Type tx = ts;
- auto sle = new StructLiteralExp(ci.loc, sd, elements, tx);
- if (!sd.fill(ci.loc, elements, false))
- return err();
- sle.type = tx;
- auto ie = new ExpInitializer(ci.loc, sle);
- return ie.initializerSemantic(sc, tx, needInterpret);
+ //printf("array() returns ai: %s, index: %d\n", ai.toChars(), cast(int)index);
+ return ai;
}
if (auto ts = t.isTypeStruct())
{
- auto ei = structs(ts);
- if (errors)
- return err();
- if (i < dil.length)
+ auto si = new StructInitializer(ci.loc);
+ StructDeclaration sd = ts.sym;
+ sd.size(ci.loc); // run semantic() on sd to get fields
+ if (sd.sizeok != Sizeok.done)
{
- error(ci.loc, "%d extra initializer(s) for `struct %s`", cast(int)(dil.length - i), ts.toChars());
return err();
}
- return ei;
- }
+ const nfields = sd.fields.length;
- auto tsa = t.isTypeSArray();
- if (!tsa)
- {
- /* Not an array. See if it is `{ exp }` which can be
- * converted to an ExpInitializer
- */
- if (ExpInitializer ei = isBraceExpression())
- {
- return ei.initializerSemantic(sc, t, needInterpret);
- }
-
- error(ci.loc, "C non-array initializer (%s) %s not supported yet", t.toChars(), ci.toChars());
- return err();
- }
+ size_t fieldi = 0;
- /* If it's an array of integral being initialized by `{ string }`
- * replace with `string`
- */
- auto tn = t.nextOf();
- if (tn.isintegral())
- {
- if (ExpInitializer ei = isBraceExpression())
+ for (size_t index = 0; index < ci.initializerList.length; )
{
- if (ei.exp.isStringExp())
- return ei.initializerSemantic(sc, t, needInterpret);
+ auto di = ci.initializerList[index];
+ auto dlist = di.designatorList;
+ if (dlist)
+ {
+ const length = (*dlist).length;
+ if (length == 0 || !(*dlist)[0].ident)
+ {
+ error(ci.loc, "`.identifier` expected for C struct field initializer `%s`", ci.toChars());
+ return err();
+ }
+ if (length > 1)
+ {
+ error(ci.loc, "only 1 designator currently allowed for C struct field initializer `%s`", ci.toChars());
+ return err();
+ }
+ auto id = (*dlist)[0].ident;
+ foreach (k, f; sd.fields[]) // linear search for now
+ {
+ if (f.ident == id)
+ {
+ fieldi = k;
+ si.addInit(id, di.initializer);
+ ++fieldi;
+ ++index;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (fieldi == nfields)
+ break;
+ VarDeclaration field;
+ while (1) // skip field if it overlaps with previously seen fields
+ {
+ field = sd.fields[fieldi];
+ ++fieldi;
+ if (!overlaps(field, sd.fields[], si))
+ break;
+ if (fieldi == nfields)
+ break;
+ }
+ auto tn = field.type.toBasetype();
+ auto tnsa = tn.isTypeSArray();
+ auto tns = tn.isTypeStruct();
+ auto ix = di.initializer;
+ if (tnsa && ix.isExpInitializer())
+ {
+ ExpInitializer ei = ix.isExpInitializer();
+ if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
+ {
+ si.addInit(field.ident, ei);
+ ++index;
+ }
+ else
+ si.addInit(field.ident, subArray(tnsa, index));
+ }
+ else if (tns && ix.isExpInitializer())
+ {
+ /* Disambiguate between an exp representing the entire
+ * struct, and an exp representing the first field of the struct
+ */
+ if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
+ {
+ si.addInit(field.ident, initializerSemantic(ix, sc, tn, needInterpret));
+ ++index;
+ }
+ else // field initializers for struct
+ si.addInit(field.ident, subStruct(tns, index)); // the first field
+ }
+ else
+ {
+ si.addInit(field.ident, di.initializer);
+ ++index;
+ }
+ }
}
+ return initializerSemantic(si, sc, t, needInterpret);
}
-
- /* Support recursion to handle un-braced array initializers
- * Params:
- * t = element type
- * dim = max number of elements
- * simple = true if array of simple elements
- * Returns:
- * # of elements in array
- */
- size_t array(Type t, size_t dim, ref bool simple)
+ else if (auto ta = t.isTypeSArray())
{
- //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();
- 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", tnsa.toChars());
- errors = true;
- return 1;
- }
- if (i == dil.length)
- return 0;
- size_t n;
- const nelems = tnsa ? cast(size_t)tnsa.dim.toInteger() : 0;
+ auto tn = t.nextOf().toBasetype(); // element type of array
- /* Run initializerSemantic on a single element.
+ /* If it's an array of integral being initialized by `{ string }`
+ * replace with `string`
*/
- Initializer elem(Initializer ie)
+ if (tn.isintegral())
{
- ++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;
+ if (ExpInitializer ei = isBraceExpression())
+ {
+ if (ei.exp.isStringExp())
+ return ei.initializerSemantic(sc, t, needInterpret);
+ }
}
- foreach (j; 0 .. dim)
+ auto tnsa = tn.isTypeSArray(); // array of array
+ auto tns = tn.isTypeStruct(); // array of struct
+
+ auto ai = new ArrayInitializer(ci.loc);
+ ai.isCarray = true;
+ for (size_t index = 0; index < ci.initializerList.length; )
{
- auto di = dil[i];
- if (di.designatorList)
- {
- error(ci.loc, "C designator-list not supported yet");
- errors = true;
- break;
- }
- if (tnsa && di.initializer.isExpInitializer())
+ auto di = ci.initializerList[index];
+ if (auto dlist = di.designatorList)
{
- // no braces enclosing array initializer, so recurse
- array(tnsa, nelems, simple);
- }
- else if (auto tns = tn.isTypeStruct())
- {
- if (auto ei = di.initializer.isExpInitializer())
+ const length = (*dlist).length;
+ if (length == 0 || !(*dlist)[0].exp)
+ {
+ error(ci.loc, "`[ constant-expression ]` expected for C array element initializer `%s`", ci.toChars());
+ return err();
+ }
+ if (length > 1)
+ {
+ error(ci.loc, "only 1 designator currently allowed for C array element initializer `%s`", ci.toChars());
+ return err();
+ }
+ //printf("tn: %s, di.initializer: %s\n", tn.toChars(), di.initializer.toChars());
+ auto ix = di.initializer;
+ if (tnsa && ix.isExpInitializer())
+ {
+ // Wrap initializer in [ ]
+ auto ain = new ArrayInitializer(ci.loc);
+ ain.addInit(null, di.initializer);
+ ix = ain;
+ ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret));
+ ++index;
+ }
+ else if (tns && ix.isExpInitializer())
{
- // no braces enclosing struct initializer
-
/* Disambiguate between an exp representing the entire
* struct, and an exp representing the first field of the struct
- */
- if (needInterpret)
- sc = sc.startCTFE();
- ei.exp = ei.exp.expressionSemantic(sc);
- ei.exp = resolveProperties(sc, ei.exp);
- if (needInterpret)
- sc = sc.endCTFE();
- if (ei.exp.implicitConvTo(tn))
- di.initializer = elem(di.initializer); // the whole struct
- else
+ */
+ if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
{
- simple = false;
- dil[n].initializer = structs(tns); // the first field
+ ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret));
+ ++index;
}
+ else // field initializers for struct
+ ai.addInit((*dlist)[0].exp, subStruct(tns, index)); // the first field
+ }
+ else
+ {
+ ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret));
+ ++index;
+ }
+ }
+ else if (tnsa && di.initializer.isExpInitializer())
+ {
+ ExpInitializer ei = di.initializer.isExpInitializer();
+ if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
+ {
+ ai.addInit(null, ei);
+ ++index;
}
else
- dil[n].initializer = elem(di.initializer);
+ ai.addInit(null, subArray(tnsa, index));
+ }
+ else if (tns && di.initializer.isExpInitializer())
+ {
+ /* Disambiguate between an exp representing the entire
+ * struct, and an exp representing the first field of the struct
+ */
+ if (representsStruct(di.initializer.isExpInitializer(), tns)) // initializer represents the entire struct
+ {
+ ai.addInit(null, initializerSemantic(di.initializer, sc, tn, needInterpret));
+ ++index;
+ }
+ else // field initializers for struct
+ ai.addInit(null, subStruct(tns, index)); // the first field
}
else
{
- di.initializer = elem(di.initializer);
+ ai.addInit(null, initializerSemantic(di.initializer, sc, tn, needInterpret));
+ ++index;
}
- ++n;
- if (i == dil.length)
- break;
- }
- //printf(" n: %d i: %d\n", cast(int)n, cast(int)i);
- return n;
- }
-
- size_t dim = tsa.isIncomplete() ? dil.length : cast(size_t)tsa.dim.toInteger();
- bool simple = true;
- auto newdim = array(t, dim, simple);
-
- if (errors)
- return err();
-
- if (tsa.isIncomplete()) // array of unknown length
- {
- // Change to array of known length
- 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
- }
- const uinteger_t edim = tsa.dim.toInteger();
- if (i < dil.length)
- {
- error(ci.loc, "%d extra initializer(s) for static array length of %d", cast(int)(dil.length - i), cast(int)edim);
- return err();
- }
-
- const sz = tn.size(); // element size
- if (sz == SIZE_INVALID)
- return err();
- bool overflow;
- const max = mulu(edim, sz, overflow);
- if (overflow || max >= amax)
- {
- error(ci.loc, "array dimension %llu exceeds max of %llu", ulong(edim), ulong(amax / sz));
- return err();
- }
-
- /* If an array of simple elements, replace with an ArrayInitializer
- */
- auto tnb = tn.toBasetype();
- if (!tnb.isTypeSArray() && (!tnb.isTypeStruct() || simple))
- {
- 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);
+ return initializerSemantic(ai, sc, tx, needInterpret);
}
-
- if (newdim < ci.initializerList.length && tnb.isTypeStruct())
+ else if (ExpInitializer ei = isBraceExpression())
+ return visitExp(ei);
+ else
{
- // 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;
+ assert(0);
}
-
- return ci;
}
final switch (init.kind)
diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d
index 21bbde8..1de89d4 100644
--- a/gcc/d/dmd/lexer.d
+++ b/gcc/d/dmd/lexer.d
@@ -2582,8 +2582,13 @@ class Lexer
{
/* C11 6.4.4.2 doesn't actually care if it is not representable if it is not hex
*/
- const char* suffix = (result == TOK.float32Literal || result == TOK.imaginary32Literal) ? "f" : "";
- error(scanloc, "number `%s%s` is not representable", sbufptr, suffix);
+ const char* suffix = result == TOK.float32Literal ? "f" : result == TOK.float80Literal ? "L" : "";
+ const char* type = [TOK.float32Literal: "`float`".ptr,
+ TOK.float64Literal: "`double`".ptr,
+ TOK.float80Literal: "`real` for the current target".ptr][result];
+ error(scanloc, "number `%s%s` is not representable as a %s", sbufptr, suffix, type);
+ const char* extra = result == TOK.float64Literal ? "`real` literals can be written using the `L` suffix. " : "";
+ errorSupplemental(scanloc, "%shttps://dlang.org/spec/lex.html#floatliteral", extra);
}
debug
{
diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h
index 6bfb729..341ce36 100644
--- a/gcc/d/dmd/module.h
+++ b/gcc/d/dmd/module.h
@@ -37,7 +37,7 @@ public:
const char *kind() const override;
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
Package *isPackage() override final { return this; }
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index f2da41b..1240f5a 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -936,7 +936,7 @@ extern (C++) abstract class Type : ASTNode
else
{
// If `typeSemantic` succeeded, there may have been deprecations that
- // were gagged due the the `startGagging` above. Run again to display
+ // were gagged due the `startGagging` above. Run again to display
// those deprecations. https://issues.dlang.org/show_bug.cgi?id=19107
if (global.gaggedWarnings > 0)
typeSemantic(tcopy, loc, sc);
@@ -4656,7 +4656,7 @@ extern (C++) final class TypeFunction : TypeNext
// suppress early exit if an error message is wanted,
// so we can check any matching args are valid
if (!pMessage)
- goto Nomatch;
+ return MATCH.nomatch;
}
// too many args; no match
match = MATCH.convert; // match ... with a "conversion" match level
@@ -4669,7 +4669,7 @@ extern (C++) final class TypeFunction : TypeNext
buf.printf("too few arguments, expected `%d`, got `%d`", cast(int)nparams, cast(int)nargs);
if (pMessage)
*pMessage = buf.extractChars();
- goto Nomatch;
+ return MATCH.nomatch;
}
foreach (u, p; parameterList)
@@ -4710,226 +4710,16 @@ extern (C++) final class TypeFunction : TypeNext
MATCH m;
assert(p);
- if (u >= nargs)
- {
- if (p.defaultArg)
- continue;
- // try typesafe variadics
- goto L1;
- }
+
+ // One or more arguments remain
+ if (u < nargs)
{
Expression arg = args[u];
assert(arg);
- //printf("arg: %s, type: %s\n", arg.toChars(), arg.type.toChars());
-
- Type targ = arg.type;
- Type tprm = wildmatch ? p.type.substWildTo(wildmatch) : p.type;
-
- if (p.isLazy() && tprm.ty == Tvoid && targ.ty != Tvoid)
- m = MATCH.convert;
- else
- {
- //printf("%s of type %s implicitConvTo %s\n", arg.toChars(), targ.toChars(), tprm.toChars());
- if (flag)
- {
- // for partial ordering, value is an irrelevant mockup, just look at the type
- m = targ.implicitConvTo(tprm);
- }
- else
- {
- const isRef = p.isReference();
-
- StructDeclaration argStruct, prmStruct;
-
- // first look for a copy constructor
- if (arg.isLvalue() && !isRef && targ.ty == Tstruct && tprm.ty == Tstruct)
- {
- // if the argument and the parameter are of the same unqualified struct type
- argStruct = (cast(TypeStruct)targ).sym;
- prmStruct = (cast(TypeStruct)tprm).sym;
- }
-
- // check if the copy constructor may be called to copy the argument
- if (argStruct && argStruct == prmStruct && argStruct.hasCopyCtor)
- {
- /* this is done by seeing if a call to the copy constructor can be made:
- *
- * typeof(tprm) __copytmp;
- * copytmp.__copyCtor(arg);
- */
- auto tmp = new VarDeclaration(arg.loc, tprm, Identifier.generateId("__copytmp"), null);
- tmp.storage_class = STC.rvalue | STC.temp | STC.ctfe;
- tmp.dsymbolSemantic(sc);
- Expression ve = new VarExp(arg.loc, tmp);
- Expression e = new DotIdExp(arg.loc, ve, Id.ctor);
- e = new CallExp(arg.loc, e, arg);
- //printf("e = %s\n", e.toChars());
- if(.trySemantic(e, sc))
- m = MATCH.exact;
- else
- {
- if (pMessage)
- {
- /* https://issues.dlang.org/show_bug.cgi?id=22202
- *
- * If a function was deduced by semantic on the CallExp,
- * it means that resolveFuncCall completed succesfully.
- * Therefore, there exists a callable copy constructor,
- * however, it cannot be called because scope constraints
- * such as purity, safety or nogc.
- */
- OutBuffer buf;
- auto callExp = e.isCallExp();
- if (auto f = callExp.f)
- {
- char[] s;
- if (!f.isPure && sc.func.setImpure())
- s ~= "pure ";
- if (!f.isSafe() && !f.isTrusted() && sc.setUnsafe())
- s ~= "@safe ";
- if (!f.isNogc && sc.func.setGC())
- s ~= "nogc ";
- if (s)
- {
- s[$-1] = '\0';
- buf.printf("`%s` copy constructor cannot be called from a `%s` context", f.type.toChars(), s.ptr);
- }
- else if (f.isGenerated() && f.isDisabled())
- {
- /* https://issues.dlang.org/show_bug.cgi?id=23097
- * Compiler generated copy constructor failed.
- */
- buf.printf("generating a copy constructor for `struct %s` failed, therefore instances of it are uncopyable",
- argStruct.toChars());
- }
- else
- {
- /* Although a copy constructor may exist, no suitable match was found.
- * i.e: `inout` constructor creates `const` object, not mutable.
- * Fallback to using the original generic error before bugzilla 22202.
- */
- goto Lnocpctor;
- }
- }
- else
- {
- Lnocpctor:
- buf.printf("`struct %s` does not define a copy constructor for `%s` to `%s` copies",
- argStruct.toChars(), targ.toChars(), tprm.toChars());
- }
-
- *pMessage = buf.extractChars();
- }
- m = MATCH.nomatch;
- goto Nomatch;
- }
- }
- else
- {
- import dmd.dcast : cimplicitConvTo;
- m = (sc && sc.flags & SCOPE.Cfile) ? arg.cimplicitConvTo(tprm) : arg.implicitConvTo(tprm);
- }
- }
- //printf("match %d\n", m);
- }
-
- // Non-lvalues do not match ref or out parameters
- if (p.isReference())
- {
- // https://issues.dlang.org/show_bug.cgi?id=13783
- // Don't use toBasetype() to handle enum types.
- Type ta = targ;
- Type tp = tprm;
- //printf("fparam[%d] ta = %s, tp = %s\n", u, ta.toChars(), tp.toChars());
-
- if (m && !arg.isLvalue())
- {
- if (p.storageClass & STC.out_)
- {
- if (pMessage) *pMessage = getParamError(arg, p);
- goto Nomatch;
- }
-
- if (arg.op == EXP.string_ && tp.ty == Tsarray)
- {
- if (ta.ty != Tsarray)
- {
- Type tn = tp.nextOf().castMod(ta.nextOf().mod);
- dinteger_t dim = (cast(StringExp)arg).len;
- ta = tn.sarrayOf(dim);
- }
- }
- else if (arg.op == EXP.slice && tp.ty == Tsarray)
- {
- // Allow conversion from T[lwr .. upr] to ref T[upr-lwr]
- if (ta.ty != Tsarray)
- {
- Type tn = ta.nextOf();
- dinteger_t dim = (cast(TypeSArray)tp).dim.toUInteger();
- ta = tn.sarrayOf(dim);
- }
- }
- else if ((p.storageClass & STC.in_) && global.params.previewIn)
- {
- // Allow converting a literal to an `in` which is `ref`
- if (arg.op == EXP.arrayLiteral && tp.ty == Tsarray)
- {
- Type tn = tp.nextOf();
- dinteger_t dim = (cast(TypeSArray)tp).dim.toUInteger();
- ta = tn.sarrayOf(dim);
- }
-
- // Need to make this a rvalue through a temporary
- m = MATCH.convert;
- }
- else if (global.params.rvalueRefParam != FeatureState.enabled ||
- p.storageClass & STC.out_ ||
- !arg.type.isCopyable()) // can't copy to temp for ref parameter
- {
- if (pMessage) *pMessage = getParamError(arg, p);
- goto Nomatch;
- }
- else
- {
- /* in functionParameters() we'll convert this
- * rvalue into a temporary
- */
- m = MATCH.convert;
- }
- }
-
- /* If the match is not already perfect or if the arg
- is not a lvalue then try the `alias this` chain
- see https://issues.dlang.org/show_bug.cgi?id=15674
- and https://issues.dlang.org/show_bug.cgi?id=21905
- */
- if (ta != tp || !arg.isLvalue())
- {
- Type firsttab = ta.toBasetype();
- while (1)
- {
- Type tab = ta.toBasetype();
- Type tat = tab.aliasthisOf();
- if (!tat || !tat.implicitConvTo(tprm))
- break;
- if (tat == tab || tat == firsttab)
- break;
- ta = tat;
- }
- }
-
- /* A ref variable should work like a head-const reference.
- * e.g. disallows:
- * ref T <- an lvalue of const(T) argument
- * ref T[dim] <- an lvalue of const(T[dim]) argument
- */
- if (!ta.constConv(tp))
- {
- if (pMessage) *pMessage = getParamError(arg, p);
- goto Nomatch;
- }
- }
+ m = argumentMatchParameter(this, p, arg, wildmatch, flag, sc, pMessage);
}
+ else if (p.defaultArg)
+ continue;
/* prefer matching the element type rather than the array
* type when more arguments are present with T[]...
@@ -4943,100 +4733,33 @@ extern (C++) final class TypeFunction : TypeNext
L1:
if (parameterList.varargs == VarArg.typesafe && u + 1 == nparams) // if last varargs param
{
- Type tb = p.type.toBasetype();
- TypeSArray tsa;
- dinteger_t sz;
-
- switch (tb.ty)
- {
- case Tsarray:
- tsa = cast(TypeSArray)tb;
- sz = tsa.dim.toInteger();
- if (sz != nargs - u)
- {
- if (pMessage)
- // Windows (Vista) OutBuffer.vprintf issue? 2nd argument always zero
- //*pMessage = getMatchError("expected %d variadic argument(s), not %d", sz, nargs - u);
- if (!global.gag || global.params.showGaggedErrors)
- {
- OutBuffer buf;
- buf.printf("expected %llu variadic argument(s)", sz);
- buf.printf(", not %zu", nargs - u);
- *pMessage = buf.extractChars();
- }
- goto Nomatch;
- }
- goto case Tarray;
- case Tarray:
- {
- TypeArray ta = cast(TypeArray)tb;
- foreach (arg; args[u .. nargs])
- {
- assert(arg);
-
- /* If lazy array of delegates,
- * convert arg(s) to delegate(s)
- */
- Type tret = p.isLazyArray();
- if (tret)
- {
- if (ta.next.equals(arg.type))
- m = MATCH.exact;
- else if (tret.toBasetype().ty == Tvoid)
- m = MATCH.convert;
- else
- {
- m = arg.implicitConvTo(tret);
- if (m == MATCH.nomatch)
- m = arg.implicitConvTo(ta.next);
- }
- }
- else
- m = arg.implicitConvTo(ta.next);
-
- if (m == MATCH.nomatch)
- {
- if (pMessage) *pMessage = getParamError(arg, p);
- goto Nomatch;
- }
- if (m < match)
- match = m;
- }
- goto Ldone;
- }
- case Tclass:
- // Should see if there's a constructor match?
- // Or just leave it ambiguous?
- goto Ldone;
-
- default:
- break;
- }
+ auto trailingArgs = args[u .. $];
+ if (auto vmatch = matchTypeSafeVarArgs(this, p, trailingArgs, pMessage))
+ return vmatch < match ? vmatch : match;
+ // Error message was already generated in `matchTypeSafeVarArgs`
+ return MATCH.nomatch;
}
- if (pMessage && u < nargs)
- *pMessage = getParamError(args[u], p);
- else if (pMessage)
+ if (pMessage && u >= nargs)
*pMessage = getMatchError("missing argument for parameter #%d: `%s`",
u + 1, parameterToChars(p, this, false));
- goto Nomatch;
+ // If an error happened previously, `pMessage` was already filled
+ else if (pMessage && !*pMessage)
+ *pMessage = getParamError(args[u], p);
+
+ return MATCH.nomatch;
}
if (m < match)
match = m; // pick worst match
}
- Ldone:
if (pMessage && !parameterList.varargs && nargs > nparams)
{
// all parameters had a match, but there are surplus args
*pMessage = getMatchError("expected %d argument(s), not %d", nparams, nargs);
- goto Nomatch;
+ return MATCH.nomatch;
}
//printf("match = %d\n", match);
return match;
-
- Nomatch:
- //printf("no match\n");
- return MATCH.nomatch;
}
/+
@@ -6194,6 +5917,11 @@ extern (C++) final class TypeClass : Type
if (t && t.ty == Tclass)
{
ClassDeclaration cd = (cast(TypeClass)t).sym;
+ if (cd.semanticRun < PASS.semanticdone && !cd.isBaseInfoComplete())
+ cd.dsymbolSemantic(null);
+ if (sym.semanticRun < PASS.semanticdone && !sym.isBaseInfoComplete())
+ sym.dsymbolSemantic(null);
+
if (sym.isBaseOf(cd, poffset))
return true;
}
@@ -6355,10 +6083,9 @@ extern (C++) final class TypeTuple : Type
extern (D) this(Expressions* exps)
{
super(Ttuple);
- auto arguments = new Parameters();
+ auto arguments = new Parameters(exps ? exps.dim : 0);
if (exps)
{
- arguments.setDim(exps.dim);
for (size_t i = 0; i < exps.dim; i++)
{
Expression e = (*exps)[i];
@@ -7330,3 +7057,325 @@ const(char)* toChars(ScopeRef sr) pure nothrow @nogc @safe
return names[sr];
}
}
+
+/**
+ * Used by `callMatch` to check if the copy constructor may be called to
+ * copy the argument
+ *
+ * This is done by seeing if a call to the copy constructor can be made:
+ * ```
+ * typeof(tprm) __copytmp;
+ * copytmp.__copyCtor(arg);
+ * ```
+ */
+private extern(D) bool isCopyConstructorCallable (StructDeclaration argStruct,
+ Expression arg, Type tprm, Scope* sc, const(char)** pMessage)
+{
+ auto tmp = new VarDeclaration(arg.loc, tprm, Identifier.generateId("__copytmp"), null);
+ tmp.storage_class = STC.rvalue | STC.temp | STC.ctfe;
+ tmp.dsymbolSemantic(sc);
+ Expression ve = new VarExp(arg.loc, tmp);
+ Expression e = new DotIdExp(arg.loc, ve, Id.ctor);
+ e = new CallExp(arg.loc, e, arg);
+ //printf("e = %s\n", e.toChars());
+ if (.trySemantic(e, sc))
+ return true;
+
+ if (pMessage)
+ {
+ /* https://issues.dlang.org/show_bug.cgi?id=22202
+ *
+ * If a function was deduced by semantic on the CallExp,
+ * it means that resolveFuncCall completed succesfully.
+ * Therefore, there exists a callable copy constructor,
+ * however, it cannot be called because scope constraints
+ * such as purity, safety or nogc.
+ */
+ OutBuffer buf;
+ auto callExp = e.isCallExp();
+ if (auto f = callExp.f)
+ {
+ char[] s;
+ if (!f.isPure && sc.func.setImpure())
+ s ~= "pure ";
+ if (!f.isSafe() && !f.isTrusted() && sc.setUnsafe())
+ s ~= "@safe ";
+ if (!f.isNogc && sc.func.setGC())
+ s ~= "nogc ";
+ if (s)
+ {
+ s[$-1] = '\0';
+ buf.printf("`%s` copy constructor cannot be called from a `%s` context", f.type.toChars(), s.ptr);
+ }
+ else if (f.isGenerated() && f.isDisabled())
+ {
+ /* https://issues.dlang.org/show_bug.cgi?id=23097
+ * Compiler generated copy constructor failed.
+ */
+ buf.printf("generating a copy constructor for `struct %s` failed, therefore instances of it are uncopyable",
+ argStruct.toChars());
+ }
+ else
+ {
+ /* Although a copy constructor may exist, no suitable match was found.
+ * i.e: `inout` constructor creates `const` object, not mutable.
+ * Fallback to using the original generic error before bugzilla 22202.
+ */
+ goto Lnocpctor;
+ }
+ }
+ else
+ {
+ Lnocpctor:
+ buf.printf("`struct %s` does not define a copy constructor for `%s` to `%s` copies",
+ argStruct.toChars(), arg.type.toChars(), tprm.toChars());
+ }
+
+ *pMessage = buf.extractChars();
+ }
+ return false;
+}
+
+/**
+ * Match a single parameter to an argument.
+ *
+ * This function is called by `TypeFunction.callMatch` while iterating over
+ * the list of parameter. Here we check if `arg` is a match for `p`,
+ * which is mostly about checking if `arg.type` converts to `p`'s type
+ * and some check about value reference.
+ *
+ * Params:
+ * tf = The `TypeFunction`, only used for error reporting
+ * p = The parameter of `tf` being matched
+ * arg = Argument being passed (bound) to `p`
+ * wildmatch = Wild (`inout`) matching level, derived from the full argument list
+ * flag = A non-zero value means we're doing a partial ordering check
+ * (no value semantic check)
+ * sc = Scope we are in
+ * pMessage = A buffer to write the error in, or `null`
+ *
+ * Returns: Whether `trailingArgs` match `p`.
+ */
+private extern(D) MATCH argumentMatchParameter (TypeFunction tf, Parameter p,
+ Expression arg, ubyte wildmatch, int flag, Scope* sc, const(char)** pMessage)
+{
+ //printf("arg: %s, type: %s\n", arg.toChars(), arg.type.toChars());
+ MATCH m;
+ Type targ = arg.type;
+ Type tprm = wildmatch ? p.type.substWildTo(wildmatch) : p.type;
+
+ if (p.isLazy() && tprm.ty == Tvoid && targ.ty != Tvoid)
+ m = MATCH.convert;
+ else if (flag)
+ {
+ // for partial ordering, value is an irrelevant mockup, just look at the type
+ m = targ.implicitConvTo(tprm);
+ }
+ else
+ {
+ const isRef = p.isReference();
+ StructDeclaration argStruct, prmStruct;
+
+ // first look for a copy constructor
+ if (arg.isLvalue() && !isRef && targ.ty == Tstruct && tprm.ty == Tstruct)
+ {
+ // if the argument and the parameter are of the same unqualified struct type
+ argStruct = (cast(TypeStruct)targ).sym;
+ prmStruct = (cast(TypeStruct)tprm).sym;
+ }
+
+ // check if the copy constructor may be called to copy the argument
+ if (argStruct && argStruct == prmStruct && argStruct.hasCopyCtor)
+ {
+ if (!isCopyConstructorCallable(argStruct, arg, tprm, sc, pMessage))
+ return MATCH.nomatch;
+ m = MATCH.exact;
+ }
+ else
+ {
+ import dmd.dcast : cimplicitConvTo;
+ m = (sc && sc.flags & SCOPE.Cfile) ? arg.cimplicitConvTo(tprm) : arg.implicitConvTo(tprm);
+ }
+ }
+
+ // Non-lvalues do not match ref or out parameters
+ if (p.isReference())
+ {
+ // https://issues.dlang.org/show_bug.cgi?id=13783
+ // Don't use toBasetype() to handle enum types.
+ Type ta = targ;
+ Type tp = tprm;
+ //printf("fparam[%d] ta = %s, tp = %s\n", u, ta.toChars(), tp.toChars());
+
+ if (m && !arg.isLvalue())
+ {
+ if (p.storageClass & STC.out_)
+ {
+ if (pMessage) *pMessage = tf.getParamError(arg, p);
+ return MATCH.nomatch;
+ }
+
+ if (arg.op == EXP.string_ && tp.ty == Tsarray)
+ {
+ if (ta.ty != Tsarray)
+ {
+ Type tn = tp.nextOf().castMod(ta.nextOf().mod);
+ dinteger_t dim = (cast(StringExp)arg).len;
+ ta = tn.sarrayOf(dim);
+ }
+ }
+ else if (arg.op == EXP.slice && tp.ty == Tsarray)
+ {
+ // Allow conversion from T[lwr .. upr] to ref T[upr-lwr]
+ if (ta.ty != Tsarray)
+ {
+ Type tn = ta.nextOf();
+ dinteger_t dim = (cast(TypeSArray)tp).dim.toUInteger();
+ ta = tn.sarrayOf(dim);
+ }
+ }
+ else if ((p.storageClass & STC.in_) && global.params.previewIn)
+ {
+ // Allow converting a literal to an `in` which is `ref`
+ if (arg.op == EXP.arrayLiteral && tp.ty == Tsarray)
+ {
+ Type tn = tp.nextOf();
+ dinteger_t dim = (cast(TypeSArray)tp).dim.toUInteger();
+ ta = tn.sarrayOf(dim);
+ }
+
+ // Need to make this a rvalue through a temporary
+ m = MATCH.convert;
+ }
+ else if (global.params.rvalueRefParam != FeatureState.enabled ||
+ p.storageClass & STC.out_ ||
+ !arg.type.isCopyable()) // can't copy to temp for ref parameter
+ {
+ if (pMessage) *pMessage = tf.getParamError(arg, p);
+ return MATCH.nomatch;
+ }
+ else
+ {
+ /* in functionParameters() we'll convert this
+ * rvalue into a temporary
+ */
+ m = MATCH.convert;
+ }
+ }
+
+ /* If the match is not already perfect or if the arg
+ is not a lvalue then try the `alias this` chain
+ see https://issues.dlang.org/show_bug.cgi?id=15674
+ and https://issues.dlang.org/show_bug.cgi?id=21905
+ */
+ if (ta != tp || !arg.isLvalue())
+ {
+ Type firsttab = ta.toBasetype();
+ while (1)
+ {
+ Type tab = ta.toBasetype();
+ Type tat = tab.aliasthisOf();
+ if (!tat || !tat.implicitConvTo(tprm))
+ break;
+ if (tat == tab || tat == firsttab)
+ break;
+ ta = tat;
+ }
+ }
+
+ /* A ref variable should work like a head-const reference.
+ * e.g. disallows:
+ * ref T <- an lvalue of const(T) argument
+ * ref T[dim] <- an lvalue of const(T[dim]) argument
+ */
+ if (!ta.constConv(tp))
+ {
+ if (pMessage) *pMessage = tf.getParamError(arg, p);
+ return MATCH.nomatch;
+ }
+ }
+ return m;
+}
+
+/**
+ * Match the remaining arguments `trailingArgs` with parameter `p`.
+ *
+ * Assume we already checked that `p` is the last parameter of `tf`,
+ * and we want to know whether the arguments would match `p`.
+ *
+ * Params:
+ * tf = The `TypeFunction`, only used for error reporting
+ * p = The last parameter of `tf` which is variadic
+ * trailingArgs = The remaining arguments that should match `p`
+ * pMessage = A buffer to write the error in, or `null`
+ *
+ * Returns: Whether `trailingArgs` match `p`.
+ */
+private extern(D) MATCH matchTypeSafeVarArgs(TypeFunction tf, Parameter p,
+ Expression[] trailingArgs, const(char)** pMessage)
+{
+ Type tb = p.type.toBasetype();
+
+ switch (tb.ty)
+ {
+ case Tsarray:
+ TypeSArray tsa = cast(TypeSArray)tb;
+ dinteger_t sz = tsa.dim.toInteger();
+ if (sz != trailingArgs.length)
+ {
+ if (pMessage)
+ *pMessage = tf.getMatchError("expected %llu variadic argument(s), not %zu",
+ sz, trailingArgs.length);
+ return MATCH.nomatch;
+ }
+ goto case Tarray;
+ case Tarray:
+ {
+ MATCH match = MATCH.exact;
+ TypeArray ta = cast(TypeArray)tb;
+ foreach (arg; trailingArgs)
+ {
+ MATCH m;
+ assert(arg);
+
+ /* If lazy array of delegates,
+ * convert arg(s) to delegate(s)
+ */
+ Type tret = p.isLazyArray();
+ if (tret)
+ {
+ if (ta.next.equals(arg.type))
+ m = MATCH.exact;
+ else if (tret.toBasetype().ty == Tvoid)
+ m = MATCH.convert;
+ else
+ {
+ m = arg.implicitConvTo(tret);
+ if (m == MATCH.nomatch)
+ m = arg.implicitConvTo(ta.next);
+ }
+ }
+ else
+ m = arg.implicitConvTo(ta.next);
+
+ if (m == MATCH.nomatch)
+ {
+ if (pMessage) *pMessage = tf.getParamError(arg, p);
+ return MATCH.nomatch;
+ }
+ if (m < match)
+ match = m;
+ }
+ return match;
+ }
+ case Tclass:
+ // We leave it up to the actual constructor call to do the matching.
+ return MATCH.exact;
+
+ default:
+ // We can have things as `foo(int[int] wat...)` but they only match
+ // with an associative array proper.
+ if (pMessage && trailingArgs.length) *pMessage = tf.getParamError(trailingArgs[0], p);
+ return MATCH.nomatch;
+ }
+}
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index 3e614d8..2b9c94c 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -221,7 +221,7 @@ public:
virtual const char *kind();
Type *copy() const;
virtual Type *syntaxCopy();
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
bool equivalent(Type *t);
// kludge for template.isType()
DYNCAST dyncast() const override final { return DYNCAST_TYPE; }
@@ -877,7 +877,7 @@ public:
static TypeTuple *create(Type *t1, Type *t2);
const char *kind() override;
TypeTuple *syntaxCopy() override;
- bool equals(const RootObject *o) const override;
+ bool equals(const RootObject * const o) const override;
void accept(Visitor *v) override { v->visit(this); }
};
diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d
index 4f6903c..ca99b8b 100644
--- a/gcc/d/dmd/opover.d
+++ b/gcc/d/dmd/opover.d
@@ -1247,13 +1247,10 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
args2[0] = e.e2;
expandTuples(&args2);
MatchAccumulator m;
- if (s)
+ functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2);
+ if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
{
- functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2);
- if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
- {
- return ErrorExp.get();
- }
+ return ErrorExp.get();
}
if (m.count > 1)
{
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index ce2769d..ed85a5d 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -2756,7 +2756,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
{
auto parameters = new AST.Parameters();
VarArg varargs = VarArg.none;
- int hasdefault = 0;
StorageClass varargsStc;
// Attributes allowed for ...
@@ -2921,27 +2920,23 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
//if ((storageClass & STC.scope_) && (storageClass & (STC.ref_ | STC.out_)))
//error("scope cannot be ref or out");
- if (tpl && token.value == TOK.identifier)
+ const tv = peekNext();
+ if (tpl && token.value == TOK.identifier &&
+ (tv == TOK.comma || tv == TOK.rightParenthesis || tv == TOK.dotDotDot))
{
- const tv = peekNext();
- if (tv == TOK.comma || tv == TOK.rightParenthesis || tv == TOK.dotDotDot)
- {
- Identifier id = Identifier.generateId("__T");
- const loc = token.loc;
- at = new AST.TypeIdentifier(loc, id);
- if (!*tpl)
- *tpl = new AST.TemplateParameters();
- AST.TemplateParameter tp = new AST.TemplateTypeParameter(loc, id, null, null);
- (*tpl).push(tp);
-
- ai = token.ident;
- nextToken();
- }
- else goto _else;
+ Identifier id = Identifier.generateId("__T");
+ const loc = token.loc;
+ at = new AST.TypeIdentifier(loc, id);
+ if (!*tpl)
+ *tpl = new AST.TemplateParameters();
+ AST.TemplateParameter tp = new AST.TemplateTypeParameter(loc, id, null, null);
+ (*tpl).push(tp);
+
+ ai = token.ident;
+ nextToken();
}
else
{
- _else:
at = parseType(&ai);
}
ae = null;
@@ -2949,12 +2944,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
{
nextToken();
ae = parseDefaultInitExp();
- hasdefault = 1;
- }
- else
- {
- if (hasdefault)
- error("default argument expected for `%s`", ai ? ai.toChars() : at.toChars());
}
auto param = new AST.Parameter(storageClass | STC.parameter, at, ai, ae, null);
if (udas)
@@ -4484,7 +4473,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
const loc = token.loc;
Identifier ident;
-
auto t = parseDeclarator(ts, alt, &ident, &tpl, storage_class, &disable, &udas);
assert(t);
if (!tfirst)
@@ -4868,6 +4856,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
token.value == TOK.identifier && peekNext() == TOK.goesTo ||
token.value == TOK.ref_ && peekNext() == TOK.leftParenthesis &&
skipAttributes(peekPastParen(peek(&token)), &tk) &&
+ (tk.value == TOK.goesTo || tk.value == TOK.leftCurly) ||
+ token.value == TOK.auto_ && peekNext() == TOK.ref_ &&
+ peekNext2() == TOK.leftParenthesis &&
+ skipAttributes(peekPastParen(peek(peek(&token))), &tk) &&
(tk.value == TOK.goesTo || tk.value == TOK.leftCurly)
)
{
@@ -4879,6 +4871,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
// identifier => expression
// ref (parameters) { statements... }
// ref (parameters) => expression
+ // auto ref (parameters) { statements... }
+ // auto ref (parameters) => expression
s = parseFunctionLiteral();
@@ -5006,7 +5000,20 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.delegate_:
save = token.value;
nextToken();
- if (token.value == TOK.ref_)
+ if (token.value == TOK.auto_)
+ {
+ nextToken();
+ if (token.value == TOK.ref_)
+ {
+ // function auto ref (parameters) { statements... }
+ // delegate auto ref (parameters) { statements... }
+ stc = STC.auto_ | STC.ref_;
+ nextToken();
+ }
+ else
+ error("`auto` can only be used as part of `auto ref` for function literal return values");
+ }
+ else if (token.value == TOK.ref_)
{
// function ref (parameters) { statements... }
// delegate ref (parameters) { statements... }
@@ -5034,6 +5041,20 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
}
goto case TOK.leftParenthesis;
+ case TOK.auto_:
+ {
+ nextToken();
+ if (token.value == TOK.ref_)
+ {
+ // auto ref (parameters) => expression
+ // auto ref (parameters) { statements... }
+ stc = STC.auto_ | STC.ref_;
+ nextToken();
+ }
+ else
+ error("`auto` can only be used as part of `auto ref` for function literal return values");
+ goto case TOK.leftParenthesis;
+ }
case TOK.ref_:
{
// ref (parameters) => expression
@@ -5086,7 +5107,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
auto tf = new AST.TypeFunction(parameterList, tret, linkage, stc);
tf = cast(AST.TypeFunction)tf.addSTC(stc);
- auto fd = new AST.FuncLiteralDeclaration(loc, Loc.initial, tf, save, null);
+ auto fd = new AST.FuncLiteralDeclaration(loc, Loc.initial, tf, save, null, null, stc & STC.auto_);
if (token.value == TOK.goesTo)
{
@@ -5209,7 +5230,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
}
else
{
- f.frequires.push(parseStatement(ParseStatementFlags.curly | ParseStatementFlags.scope_));
+ auto ret = parseStatement(ParseStatementFlags.curly | ParseStatementFlags.scope_);
+ assert(ret);
+ f.frequires.push(ret);
requireDo = true;
}
goto L1;
@@ -6550,7 +6573,7 @@ LagainStc:
nextToken();
if (token.value == TOK.semicolon)
nextToken();
- s = null;
+ s = new AST.ErrorStatement;
break;
}
if (pEndloc)
@@ -8394,6 +8417,22 @@ LagainStc:
e = parseNewExp(null);
break;
+ case TOK.auto_:
+ {
+ if (peekNext() == TOK.ref_ && peekNext2() == TOK.leftParenthesis)
+ {
+ Token* tk = peekPastParen(peek(peek(&token)));
+ if (skipAttributes(tk, &tk) && (tk.value == TOK.goesTo || tk.value == TOK.leftCurly))
+ {
+ // auto ref (arguments) => expression
+ // auto ref (arguments) { statements... }
+ goto case_delegate;
+ }
+ }
+ nextToken();
+ error("found `%s` when expecting `ref` and function literal following `auto`", token.toChars());
+ goto Lerr;
+ }
case TOK.ref_:
{
if (peekNext() == TOK.leftParenthesis)
@@ -8630,7 +8669,7 @@ LagainStc:
if (token.value != TOK.identifier)
{
error("identifier expected following `(type)`.");
- return null;
+ return AST.ErrorExp.get();
}
e = new AST.DotIdExp(loc, new AST.TypeExp(loc, t), token.ident);
nextToken();
@@ -8749,7 +8788,8 @@ LagainStc:
if (peekNext() != TOK.identifier && peekNext() != TOK.new_)
{
error("identifier or new keyword expected following `(...)`.");
- return null;
+ nextToken();
+ return AST.ErrorExp.get();
}
e = new AST.TypeExp(loc, t);
e.parens = true;
diff --git a/gcc/d/dmd/root/object.h b/gcc/d/dmd/root/object.h
index 0c92a9a..b735dd9 100644
--- a/gcc/d/dmd/root/object.h
+++ b/gcc/d/dmd/root/object.h
@@ -39,7 +39,7 @@ class RootObject
public:
RootObject() { }
- virtual bool equals(const RootObject *o) const;
+ virtual bool equals(const RootObject * const o) const;
/**
* Pretty-print an Object. Useful for debugging the old-fashioned way.
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index ad4487f..d2f9c0a 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -167,11 +167,18 @@ private extern(C++) final class Semantic3Visitor : Visitor
sc = sc.push(tmix.argsym);
sc = sc.push(tmix);
+
+ uint olderrors = global.errors;
+
for (size_t i = 0; i < tmix.members.dim; i++)
{
Dsymbol s = (*tmix.members)[i];
s.semantic3(sc);
}
+
+ if (global.errors != olderrors)
+ errorSupplemental(tmix.loc, "parent scope from here: `mixin %s`", tmix.toChars());
+
sc = sc.pop();
sc.pop();
}
@@ -969,6 +976,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
/* Do the semantic analysis on the [in] preconditions and
* [out] postconditions.
*/
+ immutable bool isnothrow = f.isnothrow && !(funcdecl.flags & FUNCFLAG.nothrowInprocess);
if (freq)
{
/* frequire is composed of the [in] contracts
@@ -980,10 +988,22 @@ private extern(C++) final class Semantic3Visitor : Visitor
sc2.flags = (sc2.flags & ~SCOPE.contract) | SCOPE.require;
// BUG: need to error if accessing out parameters
- // BUG: need to disallow returns and throws
+ // BUG: need to disallow returns
// BUG: verify that all in and ref parameters are read
freq = freq.statementSemantic(sc2);
- freq.blockExit(funcdecl, false);
+
+ // @@@DEPRECATED_2.111@@@ - pass `isnothrow` instead of `false` to print a more detailed error msg`
+ const blockExit = freq.blockExit(funcdecl, false);
+ if (blockExit & BE.throw_)
+ {
+ if (isnothrow)
+ // @@@DEPRECATED_2.111@@@
+ // Deprecated in 2.101, can be made an error in 2.111
+ deprecation(funcdecl.loc, "`%s`: `in` contract may throw but function is marked as `nothrow`",
+ funcdecl.toPrettyChars());
+ else if (funcdecl.flags & FUNCFLAG.nothrowInprocess)
+ f.isnothrow = false;
+ }
funcdecl.flags &= ~FUNCFLAG.noEH;
@@ -992,6 +1012,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
if (global.params.useIn == CHECKENABLE.off)
freq = null;
}
+
if (fens)
{
/* fensure is composed of the [out] contracts
@@ -1017,7 +1038,19 @@ private extern(C++) final class Semantic3Visitor : Visitor
funcdecl.buildResultVar(scout, f.next);
fens = fens.statementSemantic(sc2);
- fens.blockExit(funcdecl, false);
+
+ // @@@DEPRECATED_2.111@@@ - pass `isnothrow` instead of `false` to print a more detailed error msg`
+ const blockExit = fens.blockExit(funcdecl, false);
+ if (blockExit & BE.throw_)
+ {
+ if (isnothrow)
+ // @@@DEPRECATED_2.111@@@
+ // Deprecated in 2.101, can be made an error in 2.111
+ deprecation(funcdecl.loc, "`%s`: `out` contract may throw but function is marked as `nothrow`",
+ funcdecl.toPrettyChars());
+ else if (funcdecl.flags & FUNCFLAG.nothrowInprocess)
+ f.isnothrow = false;
+ }
funcdecl.flags &= ~FUNCFLAG.noEH;
@@ -1144,7 +1177,6 @@ private extern(C++) final class Semantic3Visitor : Visitor
s = s.statementSemantic(sc2);
- immutable bool isnothrow = f.isnothrow && !(funcdecl.flags & FUNCFLAG.nothrowInprocess);
const blockexit = s.blockExit(funcdecl, isnothrow);
if (blockexit & BE.throw_)
{
diff --git a/gcc/d/dmd/transitivevisitor.d b/gcc/d/dmd/transitivevisitor.d
index 5791a88..0d7240f 100644
--- a/gcc/d/dmd/transitivevisitor.d
+++ b/gcc/d/dmd/transitivevisitor.d
@@ -28,6 +28,7 @@ extern(C++) class ParseTimeTransitiveVisitor(AST) : PermissiveVisitor!AST
*/
package mixin template ParseVisitMethods(AST)
{
+ import dmd.root.array;
// Statement Nodes
//===========================================================
@@ -46,7 +47,7 @@ package mixin template ParseVisitMethods(AST)
override void visit(AST.CompileStatement s)
{
//printf("Visiting CompileStatement\n");
- visitArgs(s.exps);
+ visitArgs(s.exps.peekSlice());
}
override void visit(AST.CompoundStatement s)
@@ -181,11 +182,9 @@ package mixin template ParseVisitMethods(AST)
s.elsebody.accept(this);
}
- void visitArgs(AST.Expressions* expressions, AST.Expression basis = null)
+ private extern(D) void visitArgs(AST.Expression[] expressions, AST.Expression basis = null)
{
- if (!expressions || !expressions.dim)
- return;
- foreach (el; *expressions)
+ foreach (el; expressions)
{
if (!el)
el = basis;
@@ -197,8 +196,7 @@ package mixin template ParseVisitMethods(AST)
override void visit(AST.PragmaStatement s)
{
//printf("Visiting PragmaStatement\n");
- if (s.args && s.args.dim)
- visitArgs(s.args);
+ visitArgs(s.args.peekSlice());
if (s._body)
s._body.accept(this);
}
@@ -346,19 +344,14 @@ package mixin template ParseVisitMethods(AST)
foreach (p; *td.origParameters)
p.accept(this);
}
- visitParameters(t.parameterList.parameters);
+ visitParameters(t.parameterList.parameters.peekSlice());
}
- void visitParameters(AST.Parameters* parameters)
+ private extern(D) final void visitParameters(AST.Parameter[] parameters)
{
- if (parameters)
+ foreach (i; 0 .. parameters.length)
{
- size_t dim = AST.Parameter.dim(parameters);
- foreach(i; 0..dim)
- {
- AST.Parameter fparam = AST.Parameter.getNth(parameters, i);
- fparam.accept(this);
- }
+ parameters[i].accept(this);
}
}
@@ -469,7 +462,7 @@ package mixin template ParseVisitMethods(AST)
override void visit(AST.TypeTuple t)
{
//printf("Visiting TypeTuple\n");
- visitParameters(t.arguments);
+ visitParameters(t.arguments.peekSlice());
}
override void visit(AST.TypeSlice t)
@@ -487,7 +480,7 @@ package mixin template ParseVisitMethods(AST)
override void visit(AST.TypeMixin t)
{
- visitArgs(t.exps);
+ visitArgs(t.exps.peekSlice());
}
// Miscellaneous
@@ -571,8 +564,7 @@ package mixin template ParseVisitMethods(AST)
override void visit(AST.PragmaDeclaration d)
{
//printf("Visiting PragmaDeclaration\n");
- if (d.args && d.args.dim)
- visitArgs(d.args);
+ visitArgs(d.args.peekSlice());
visitAttribDeclaration(cast(AST.AttribDeclaration)d);
}
@@ -580,24 +572,22 @@ package mixin template ParseVisitMethods(AST)
{
//printf("Visiting ConditionalDeclaration\n");
d.condition.accept(this);
- if (d.decl)
- foreach (de; *d.decl)
- de.accept(this);
- if (d.elsedecl)
- foreach (de; *d.elsedecl)
- de.accept(this);
+ foreach (de; d.decl.peekSlice())
+ de.accept(this);
+ foreach (de; d.elsedecl.peekSlice())
+ de.accept(this);
}
override void visit(AST.CompileDeclaration d)
{
//printf("Visiting compileDeclaration\n");
- visitArgs(d.exps);
+ visitArgs(d.exps.peekSlice());
}
override void visit(AST.UserAttributeDeclaration d)
{
//printf("Visiting UserAttributeDeclaration\n");
- visitArgs(d.atts);
+ visitArgs(d.atts.peekSlice());
visitAttribDeclaration(cast(AST.AttribDeclaration)d);
}
@@ -791,6 +781,15 @@ package mixin template ParseVisitMethods(AST)
s.accept(this);
}
+ override void visit(AST.UnionDeclaration d)
+ {
+ //printf("Visiting UnionDeclaration\n");
+ if (!d.members)
+ return;
+ foreach (s; *d.members)
+ s.accept(this);
+ }
+
override void visit(AST.ClassDeclaration d)
{
//printf("Visiting ClassDeclaration\n");
@@ -840,7 +839,7 @@ package mixin template ParseVisitMethods(AST)
auto tf = f.type.isTypeFunction();
if (!f.inferRetType && tf.next)
visitType(tf.next);
- visitParameters(tf.parameterList.parameters);
+ visitParameters(tf.parameterList.parameters.peekSlice());
AST.CompoundStatement cs = f.fbody.isCompoundStatement();
AST.Statement s = !cs ? f.fbody : null;
AST.ReturnStatement rs = s ? s.isReturnStatement() : null;
@@ -946,7 +945,7 @@ package mixin template ParseVisitMethods(AST)
override void visit(AST.ArrayLiteralExp e)
{
//printf("Visiting ArrayLiteralExp\n");
- visitArgs(e.elements, e.basis);
+ visitArgs(e.elements.peekSlice(), e.basis);
}
override void visit(AST.AssocArrayLiteralExp e)
@@ -978,8 +977,7 @@ package mixin template ParseVisitMethods(AST)
if (e.thisexp)
e.thisexp.accept(this);
visitType(e.newtype);
- if (e.arguments && e.arguments.dim)
- visitArgs(e.arguments);
+ visitArgs(e.arguments.peekSlice());
}
override void visit(AST.NewAnonClassExp e)
@@ -987,8 +985,7 @@ package mixin template ParseVisitMethods(AST)
//printf("Visiting NewAnonClassExp\n");
if (e.thisexp)
e.thisexp.accept(this);
- if (e.arguments && e.arguments.dim)
- visitArgs(e.arguments);
+ visitArgs(e.arguments.peekSlice());
if (e.cd)
e.cd.accept(this);
}
@@ -998,7 +995,7 @@ package mixin template ParseVisitMethods(AST)
//printf("Visiting TupleExp\n");
if (e.e0)
e.e0.accept(this);
- visitArgs(e.exps);
+ visitArgs(e.exps.peekSlice());
}
override void visit(AST.FuncExp e)
@@ -1056,7 +1053,7 @@ package mixin template ParseVisitMethods(AST)
override void visit(AST.MixinExp e)
{
//printf("Visiting MixinExp\n");
- visitArgs(e.exps);
+ visitArgs(e.exps.peekSlice());
}
override void visit(AST.ImportExp e)
@@ -1090,7 +1087,7 @@ package mixin template ParseVisitMethods(AST)
{
//printf("Visiting CallExp\n");
e.e1.accept(this);
- visitArgs(e.arguments);
+ visitArgs(e.arguments.peekSlice());
}
override void visit(AST.PtrExp e)
@@ -1124,7 +1121,7 @@ package mixin template ParseVisitMethods(AST)
{
//printf("Visiting ArrayExp\n");
e.e1.accept(this);
- visitArgs(e.arguments);
+ visitArgs(e.arguments.peekSlice());
}
override void visit(AST.PostExp e)
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index b21ff79..0ef7705 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -1388,6 +1388,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
// extended index), as we need to run semantic when `oidx` changes.
size_t tupleOrigIdx = size_t.max;
size_t tupleExtIdx = size_t.max;
+ bool hasDefault;
foreach (oidx, oparam, eidx, eparam; tf.parameterList)
{
// oparam (original param) will always have the default arg
@@ -1396,6 +1397,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
// position to get the offset in it later on.
if (oparam.defaultArg)
{
+ hasDefault = true;
// Get the obvious case out of the way
if (oparam is eparam)
errors |= !defaultArgSemantic(eparam, argsc);
@@ -1422,6 +1424,11 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
eparam.defaultArg = (*te.exps)[eidx - tupleExtIdx];
}
}
+ else if (hasDefault)
+ {
+ .error(loc, "default argument expected for `%s`", oparam.toChars());
+ errors = true;
+ }
// We need to know the default argument to resolve `auto ref`,
// hence why this has to take place as the very last step.
@@ -2089,10 +2096,12 @@ extern (C++) Type merge(Type type)
* loc = the location where the property is encountered
* ident = the identifier of the property
* flag = if flag & 1, don't report "not a property" error and just return NULL.
+ * src = expression for type `t` or null.
* Returns:
* expression representing the property, or null if not a property and (flag & 1)
*/
-Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier ident, int flag)
+Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier ident, int flag,
+ Expression src = null)
{
Expression visitType(Type mt)
{
@@ -2169,7 +2178,10 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden
error(loc, "no property `%s` for type `%s`, perhaps `import %.*s;` is needed?", ident.toChars(), mt.toChars(), cast(int)n.length, n.ptr);
else
{
- error(loc, "no property `%s` for type `%s`", ident.toChars(), mt.toPrettyChars(true));
+ if (src)
+ error(loc, "no property `%s` for `%s` of type `%s`", ident.toChars(), src.toChars(), mt.toPrettyChars(true));
+ else
+ error(loc, "no property `%s` for type `%s`", ident.toChars(), mt.toPrettyChars(true));
if (auto dsym = mt.toDsymbol(scope_))
if (auto sym = dsym.isAggregateDeclaration())
{
@@ -4457,7 +4469,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
/************************
- * Get the the default initialization expression for a type.
+ * Get the default initialization expression for a type.
* Params:
* mt = the type for which the init expression is returned
* loc = the location where the expression needs to be evaluated
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index b0ce870..fa5ec90 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -908,21 +908,12 @@ public:
if ((postblit || destructor) && e->op != EXP::blit)
{
- /* Need to call postblit/destructor as part of assignment.
- Construction has already been handled by the front-end. */
- gcc_assert (e->op != EXP::construct);
-
- /* So we can call postblits on const/immutable objects. */
- Type *tm = etype->unSharedOf ()->mutableOf ();
- tree ti = build_typeinfo (e, tm);
-
- /* Generate: _d_arraysetassign (t1.ptr, &t2, t1.length, ti); */
- result = build_libcall (LIBCALL_ARRAYSETASSIGN, Type::tvoid, 4,
- d_array_ptr (t1),
- build_address (t2),
- d_array_length (t1), ti);
+ /* This case should have been rewritten to `_d_arraysetassign`
+ in the semantic phase. */
+ gcc_unreachable ();
}
- else if (integer_zerop (t2))
+
+ if (integer_zerop (t2))
{
tree size = size_mult_expr (d_array_length (t1),
size_int (etype->size ()));
@@ -2473,6 +2464,20 @@ public:
if (e->argprefix)
result = compound_expr (build_expr (e->argprefix), result);
}
+ else if (tb->ty == TY::Taarray)
+ {
+ /* Allocating memory for a new associative array. */
+ tree arg = build_typeinfo (e, e->newtype);
+ tree mem = build_libcall (LIBCALL_AANEW, Type::tvoidptr, 1, arg);
+
+ /* Return an associative array pointed to by MEM. */
+ tree aatype = build_ctype (tb);
+ vec <constructor_elt, va_gc> *ce = NULL;
+ CONSTRUCTOR_APPEND_ELT (ce, TYPE_FIELDS (aatype), mem);
+
+ result = build_nop (build_ctype (e->type),
+ build_constructor (aatype, ce));
+ }
else
gcc_unreachable ();
diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def
index 282f22c..f576bef 100644
--- a/gcc/d/runtime.def
+++ b/gcc/d/runtime.def
@@ -115,10 +115,6 @@ DEF_D_RUNTIME (ALLOCMEMORY, "_d_allocmemory", RT(VOIDPTR), P1(SIZE_T),
DEF_D_RUNTIME (ARRAYCOPY, "_d_arraycopy", RT(ARRAY_VOID),
P3(SIZE_T, ARRAY_VOID, ARRAY_VOID), 0)
-/* Used for array assignments from a single element. */
-DEF_D_RUNTIME (ARRAYSETASSIGN, "_d_arraysetassign", RT(VOIDPTR),
- P4(VOIDPTR, VOIDPTR, SIZE_T, CONST_TYPEINFO), 0)
-
/* Used for concatenating two or more arrays together. Then `n' variant is
for when there is more than two arrays to handle. */
DEF_D_RUNTIME (ARRAYCATT, "_d_arraycatT", RT(ARRAY_BYTE),
@@ -140,6 +136,7 @@ DEF_D_RUNTIME (ARRAYAPPENDWD, "_d_arrayappendwd", RT(ARRAY_VOID),
/* Used for allocating a new associative array. */
DEF_D_RUNTIME (ASSOCARRAYLITERALTX, "_d_assocarrayliteralTX", RT(VOIDPTR),
P3(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID), 0)
+DEF_D_RUNTIME (AANEW, "_aaNew", RT(VOIDPTR), P1(CONST_TYPEINFO), 0)
/* Used for value equality of two associative arrays. */
DEF_D_RUNTIME (AAEQUAL, "_aaEqual", RT(INT),
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 4a01cfb..d39dd82 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -2890,10 +2890,17 @@ change in version 12.
Version 14, which first appeared in G++ 10, corrects the mangling of
the nullptr expression.
-Version 15, which first appeared in G++ 11, changes the mangling of
+Version 15, which first appeared in G++ 10.3, corrects G++ 10 ABI
+tag regression.
+
+Version 16, which first appeared in G++ 11, changes the mangling of
@code{__alignof__} to be distinct from that of @code{alignof}, and
dependent operator names.
+Version 17, which first appeared in G++ 12, fixes layout of classes
+that inherit from aggregate classes with default member initializers
+in C++14 and up.
+
See also @option{-Wabi}.
@item -fabi-compat-version=@var{n}
@@ -2903,7 +2910,7 @@ works around mangling changes by creating an alias with the correct
mangled name when defining a symbol with an incorrect mangled name.
This switch specifies which ABI version to use for the alias.
-With @option{-fabi-version=0} (the default), this defaults to 11 (GCC 7
+With @option{-fabi-version=0} (the default), this defaults to 13 (GCC 8.2
compatibility). If another ABI version is explicitly selected, this
defaults to 0. For compatibility with GCC versions 3.2 through 4.9,
use @option{-fabi-compat-version=2}.
diff --git a/gcc/final.cc b/gcc/final.cc
index c0bfdf6..eea5722 100644
--- a/gcc/final.cc
+++ b/gcc/final.cc
@@ -118,18 +118,10 @@ static int last_columnnum;
/* Discriminator written to assembly. */
static int last_discriminator;
-/* Discriminator to be written to assembly for current instruction.
+/* Compute discriminator to be written to assembly for current instruction.
Note: actual usage depends on loc_discriminator_kind setting. */
-static int discriminator;
static inline int compute_discriminator (location_t loc);
-/* Discriminator identifying current basic block among others sharing
- the same locus. */
-static int bb_discriminator;
-
-/* Basic block discriminator for previous instruction. */
-static int last_bb_discriminator;
-
/* Highest line number in current block. */
static int high_block_linenum;
@@ -1688,8 +1680,7 @@ final_start_function_1 (rtx_insn **firstp, FILE *file, int *seen,
last_filename = LOCATION_FILE (prologue_location);
last_linenum = LOCATION_LINE (prologue_location);
last_columnnum = LOCATION_COLUMN (prologue_location);
- last_discriminator = discriminator = 0;
- last_bb_discriminator = bb_discriminator = 0;
+ last_discriminator = 0;
force_source_line = false;
high_block_linenum = high_function_linenum = last_linenum;
@@ -2234,7 +2225,6 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
if (targetm.asm_out.unwind_emit)
targetm.asm_out.unwind_emit (asm_out_file, insn);
- bb_discriminator = NOTE_BASIC_BLOCK (insn)->discriminator;
break;
case NOTE_INSN_EH_REGION_BEG:
@@ -2939,7 +2929,7 @@ compute_discriminator (location_t loc)
int discriminator;
if (!decl_to_instance_map)
- discriminator = bb_discriminator;
+ discriminator = get_discriminator_from_loc (loc);
else
{
tree block = LOCATION_BLOCK (loc);
@@ -2963,6 +2953,13 @@ compute_discriminator (location_t loc)
return discriminator;
}
+/* Return discriminator of the statement that produced this insn. */
+int
+insn_discriminator (const rtx_insn *insn)
+{
+ return compute_discriminator (INSN_LOCATION (insn));
+}
+
/* Return whether a source line note needs to be emitted before INSN.
Sets IS_STMT to TRUE if the line should be marked as a possible
breakpoint location. */
@@ -2972,6 +2969,7 @@ notice_source_line (rtx_insn *insn, bool *is_stmt)
{
const char *filename;
int linenum, columnnum;
+ int discriminator;
if (NOTE_MARKER_P (insn))
{
@@ -3001,7 +2999,7 @@ notice_source_line (rtx_insn *insn, bool *is_stmt)
filename = xloc.file;
linenum = xloc.line;
columnnum = xloc.column;
- discriminator = compute_discriminator (INSN_LOCATION (insn));
+ discriminator = insn_discriminator (insn);
}
else
{
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 6985e62..dcbfd54 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,10 @@
+2022-09-27 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/107054
+ * simplify.cc (gfc_simplify_unpack): Replace assert by condition
+ that terminates simplification when there are not enough elements
+ in the constructor of argument VECTOR.
+
2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/41453
diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc
index c0fbd0e..6ac92cf 100644
--- a/gcc/fortran/simplify.cc
+++ b/gcc/fortran/simplify.cc
@@ -8458,9 +8458,16 @@ gfc_simplify_unpack (gfc_expr *vector, gfc_expr *mask, gfc_expr *field)
{
if (mask_ctor->expr->value.logical)
{
- gcc_assert (vector_ctor);
- e = gfc_copy_expr (vector_ctor->expr);
- vector_ctor = gfc_constructor_next (vector_ctor);
+ if (vector_ctor)
+ {
+ e = gfc_copy_expr (vector_ctor->expr);
+ vector_ctor = gfc_constructor_next (vector_ctor);
+ }
+ else
+ {
+ gfc_free_expr (result);
+ return NULL;
+ }
}
else if (field->expr_type == EXPR_ARRAY)
e = gfc_copy_expr (field_ctor->expr);
diff --git a/gcc/gimple-pretty-print.cc b/gcc/gimple-pretty-print.cc
index f18baec..a87e2ae 100644
--- a/gcc/gimple-pretty-print.cc
+++ b/gcc/gimple-pretty-print.cc
@@ -2875,8 +2875,6 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, int indent,
indent, "", get_lineno (gsi_stmt (gsi)));
break;
}
- if (bb->discriminator)
- fprintf (outf, ", discriminator %i", bb->discriminator);
fputc ('\n', outf);
}
}
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index d7c6dfa..3f5e585 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -397,6 +397,14 @@ public:
{
if (lh.undefined_p ())
return false;
+ // Calculating the popcount of a singleton is trivial.
+ if (lh.singleton_p ())
+ {
+ wide_int nz = lh.get_nonzero_bits ();
+ wide_int pop = wi::shwi (wi::popcount (nz), TYPE_PRECISION (type));
+ r.set (type, pop, pop);
+ return true;
+ }
// __builtin_ffs* and __builtin_popcount* return [0, prec].
int prec = TYPE_PRECISION (lh.type ());
// If arg is non-zero, then ffs or popcount are non-zero.
diff --git a/gcc/gimple-streamer-in.cc b/gcc/gimple-streamer-in.cc
index e7f3256..ea8891e 100644
--- a/gcc/gimple-streamer-in.cc
+++ b/gcc/gimple-streamer-in.cc
@@ -267,7 +267,6 @@ input_bb (class lto_input_block *ib, enum LTO_tags tag,
bb->count
= bb->count.apply_scale (count_materialization_scale, REG_BR_PROB_BASE);
bb->flags = streamer_read_hwi (ib);
- bb->discriminator = streamer_read_hwi (ib);
/* LTO_bb1 has statements. LTO_bb0 does not. */
if (tag == LTO_bb0)
diff --git a/gcc/gimple-streamer-out.cc b/gcc/gimple-streamer-out.cc
index 3336525..4583254 100644
--- a/gcc/gimple-streamer-out.cc
+++ b/gcc/gimple-streamer-out.cc
@@ -208,7 +208,6 @@ output_bb (struct output_block *ob, basic_block bb, struct function *fn)
streamer_write_uhwi (ob, bb->index);
bb->count.stream_out (ob);
streamer_write_hwi (ob, bb->flags);
- streamer_write_hwi (ob, bb->discriminator);
if (!gsi_end_p (bsi) || phi_nodes (bb))
{
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index f7a7985..4793c82 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-42efec8c126cf3787bc7c89d9c7f224eff7c5a21
+8f1a91aeff400d572857895b7f5e863ec5a4d93e
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/input.cc b/gcc/input.cc
index 060ca16..a28abfa 100644
--- a/gcc/input.cc
+++ b/gcc/input.cc
@@ -1082,7 +1082,8 @@ make_location (location_t caret, location_t start, location_t finish)
location_t combined_loc = COMBINE_LOCATION_DATA (line_table,
pure_loc,
src_range,
- NULL);
+ NULL,
+ 0);
return combined_loc;
}
@@ -1092,7 +1093,7 @@ location_t
make_location (location_t caret, source_range src_range)
{
location_t pure_loc = get_pure_location (caret);
- return COMBINE_LOCATION_DATA (line_table, pure_loc, src_range, NULL);
+ return COMBINE_LOCATION_DATA (line_table, pure_loc, src_range, NULL, 0);
}
/* An expanded_location stores the column in byte units. This function
@@ -1766,6 +1767,37 @@ get_location_within_string (cpp_reader *pfile,
return NULL;
}
+/* Associate the DISCRIMINATOR with LOCUS, and return a new locus. */
+
+location_t
+location_with_discriminator (location_t locus, int discriminator)
+{
+ tree block = LOCATION_BLOCK (locus);
+ source_range src_range = get_range_from_loc (line_table, locus);
+ locus = get_pure_location (locus);
+
+ if (locus == UNKNOWN_LOCATION)
+ return locus;
+
+ return COMBINE_LOCATION_DATA (line_table, locus, src_range, block, discriminator);
+}
+
+/* Return TRUE if LOCUS represents a location with a discriminator. */
+
+bool
+has_discriminator (location_t locus)
+{
+ return get_discriminator_from_loc (locus) != 0;
+}
+
+/* Return the discriminator for LOCUS. */
+
+int
+get_discriminator_from_loc (location_t locus)
+{
+ return get_discriminator_from_loc (line_table, locus);
+}
+
#if CHECKING_P
namespace selftest {
diff --git a/gcc/input.h b/gcc/input.h
index f1ae3ae..11c571d 100644
--- a/gcc/input.h
+++ b/gcc/input.h
@@ -165,6 +165,10 @@ extern location_t expansion_point_location (location_t);
extern location_t input_location;
+extern location_t location_with_discriminator (location_t, int);
+extern bool has_discriminator (location_t);
+extern int get_discriminator_from_loc (location_t);
+
#define LOCATION_FILE(LOC) ((expand_location (LOC)).file)
#define LOCATION_LINE(LOC) ((expand_location (LOC)).line)
#define LOCATION_COLUMN(LOC)((expand_location (LOC)).column)
diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index 543a933..66bba71 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -3338,9 +3338,9 @@ good_cloning_opportunity_p (struct cgraph_node *node, sreal time_benefit,
ipa_node_params *info = ipa_node_params_sum->get (node);
int eval_threshold = opt_for_fn (node->decl, param_ipa_cp_eval_threshold);
- if (count_sum > profile_count::zero ())
+ if (count_sum.nonzero_p ())
{
- gcc_assert (base_count > profile_count::zero ());
+ gcc_assert (base_count.nonzero_p ());
sreal factor = count_sum.probability_in (base_count).to_sreal ();
sreal evaluation = (time_benefit * factor) / size_cost;
evaluation = incorporate_penalties (node, info, evaluation);
diff --git a/gcc/lto-streamer-in.cc b/gcc/lto-streamer-in.cc
index a7dad70..fa89634 100644
--- a/gcc/lto-streamer-in.cc
+++ b/gcc/lto-streamer-in.cc
@@ -409,6 +409,8 @@ lto_location_cache::cmp_loc (const void *pa, const void *pb)
return a->line - b->line;
if (a->col != b->col)
return a->col - b->col;
+ if (a->discr != b->discr)
+ return a->discr - b->discr;
if ((a->block == NULL_TREE) != (b->block == NULL_TREE))
return a->block ? 1 : -1;
if (a->block)
@@ -460,6 +462,8 @@ lto_location_cache::apply_location_cache ()
current_loc = linemap_position_for_column (line_table, loc.col);
if (loc.block)
current_loc = set_block (current_loc, loc.block);
+ if (loc.discr)
+ current_loc = location_with_discriminator (current_loc, loc.discr);
}
else if (current_block != loc.block)
{
@@ -467,12 +471,17 @@ lto_location_cache::apply_location_cache ()
current_loc = set_block (current_loc, loc.block);
else
current_loc = LOCATION_LOCUS (current_loc);
+ if (loc.discr)
+ current_loc = location_with_discriminator (current_loc, loc.discr);
}
+ else if (current_discr != loc.discr)
+ current_loc = location_with_discriminator (current_loc, loc.discr);
*loc.loc = current_loc;
current_line = loc.line;
prev_file = current_file = loc.file;
current_col = loc.col;
current_block = loc.block;
+ current_discr = loc.discr;
}
loc_cache.truncate (0);
accepted_length = 0;
@@ -512,6 +521,7 @@ lto_location_cache::input_location_and_block (location_t *loc,
static int stream_col;
static bool stream_sysp;
static tree stream_block;
+ static unsigned stream_discr;
static const char *stream_relative_path_prefix;
gcc_assert (current_cache == this);
@@ -538,6 +548,7 @@ lto_location_cache::input_location_and_block (location_t *loc,
*loc = RESERVED_LOCATION_COUNT;
bool line_change = bp_unpack_value (bp, 1);
bool column_change = bp_unpack_value (bp, 1);
+ bool discr_change = bp_unpack_value (bp, 1);
if (file_change)
{
@@ -563,6 +574,9 @@ lto_location_cache::input_location_and_block (location_t *loc,
if (column_change)
stream_col = bp_unpack_var_len_unsigned (bp);
+ if (discr_change)
+ stream_discr = bp_unpack_var_len_unsigned (bp);
+
tree block = NULL_TREE;
if (ib)
{
@@ -578,7 +592,8 @@ lto_location_cache::input_location_and_block (location_t *loc,
if (current_file == stream_file
&& current_line == stream_line
&& current_col == stream_col
- && current_sysp == stream_sysp)
+ && current_sysp == stream_sysp
+ && current_discr == stream_discr)
{
if (current_block == block)
*loc = current_loc;
@@ -590,7 +605,7 @@ lto_location_cache::input_location_and_block (location_t *loc,
}
struct cached_location entry
- = {stream_file, loc, stream_line, stream_col, stream_sysp, block};
+ = {stream_file, loc, stream_line, stream_col, stream_sysp, block, stream_discr};
loc_cache.safe_push (entry);
}
diff --git a/gcc/lto-streamer-out.cc b/gcc/lto-streamer-out.cc
index 1bc3f55..2e7af03 100644
--- a/gcc/lto-streamer-out.cc
+++ b/gcc/lto-streamer-out.cc
@@ -67,6 +67,7 @@ clear_line_info (struct output_block *ob)
so that the first location with block in a function etc.
always streams a change_block bit and the first block. */
ob->current_block = void_node;
+ ob->current_discr = UINT_MAX;
}
@@ -194,6 +195,7 @@ lto_output_location_1 (struct output_block *ob, struct bitpack_d *bp,
if (loc >= RESERVED_LOCATION_COUNT)
{
expanded_location xloc = expand_location (loc);
+ unsigned discr = get_discriminator_from_loc (orig_loc);
if (ob->reset_locus)
{
@@ -216,6 +218,7 @@ lto_output_location_1 (struct output_block *ob, struct bitpack_d *bp,
bp_pack_value (bp, ob->current_line != xloc.line, 1);
bp_pack_value (bp, ob->current_col != xloc.column, 1);
+ bp_pack_value (bp, ob->current_discr != discr, 1);
if (ob->current_file != xloc.file)
{
@@ -242,6 +245,10 @@ lto_output_location_1 (struct output_block *ob, struct bitpack_d *bp,
if (ob->current_col != xloc.column)
bp_pack_var_len_unsigned (bp, xloc.column);
ob->current_col = xloc.column;
+
+ if (ob->current_discr != discr)
+ bp_pack_var_len_unsigned (bp, discr);
+ ob->current_discr = discr;
}
else
bp_pack_int_in_range (bp, 0, RESERVED_LOCATION_COUNT + 1, loc);
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index 597e9e4..2e3abd9 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -311,6 +311,7 @@ private:
int line, col;
bool sysp;
tree block;
+ unsigned discr;
};
/* The location cache. */
@@ -333,6 +334,7 @@ private:
bool current_sysp;
location_t current_loc;
tree current_block;
+ unsigned current_discr;
};
/* Structure used as buffer for reading an LTO file. */
@@ -723,6 +725,7 @@ struct output_block
bool reset_locus;
bool emit_pwd;
tree current_block;
+ unsigned current_discr;
/* Cache of nodes written in this section. */
struct streamer_tree_cache_d *writer_cache;
diff --git a/gcc/print-rtl.cc b/gcc/print-rtl.cc
index 60c8454..e115f98 100644
--- a/gcc/print-rtl.cc
+++ b/gcc/print-rtl.cc
@@ -453,6 +453,10 @@ rtx_writer::print_rtx_operand_code_i (const_rtx in_rtx, int idx)
expanded_location xloc = insn_location (in_insn);
fprintf (m_outfile, " \"%s\":%i:%i", xloc.file, xloc.line,
xloc.column);
+ int discriminator = insn_discriminator (in_insn);
+ if (discriminator)
+ fprintf (m_outfile, " discrim %d", discriminator);
+
}
#endif
}
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 645c009..7a8c470 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -3369,6 +3369,7 @@ extern int insn_line (const rtx_insn *);
extern const char * insn_file (const rtx_insn *);
extern tree insn_scope (const rtx_insn *);
extern expanded_location insn_location (const rtx_insn *);
+extern int insn_discriminator (const rtx_insn *);
extern location_t prologue_location, epilogue_location;
/* In jump.cc */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0e7cd64e..9007c43 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,233 @@
+2022-09-28 Eugene Rozenfeld <erozen@microsoft.com>
+
+ * c-c++-common/ubsan/pr85213.c: Pass -gno-statement-frontiers.
+
+2022-09-28 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/107061
+ * gcc.target/i386/keylocker-encodekey128.c: Don't check
+ XMM4-XMM6.
+ * gcc.target/i386/keylocker-encodekey256.c: Likewise.
+
+2022-09-28 Ju-Zhe Zhong <juzhe.zhong@rivai.ai>
+
+ * gcc.target/riscv/rvv/base/abi-1.c: New test.
+ * gcc.target/riscv/rvv/base/abi-2.c: New test.
+ * gcc.target/riscv/rvv/base/abi-3.c: New test.
+ * gcc.target/riscv/rvv/base/abi-4.c: New test.
+ * gcc.target/riscv/rvv/base/abi-5.c: New test.
+ * gcc.target/riscv/rvv/base/abi-6.c: New test.
+ * gcc.target/riscv/rvv/base/abi-7.c: New test.
+ * gcc.target/riscv/rvv/rvv.exp: New test.
+
+2022-09-28 Andrea Corallo <andrea.corallo@arm.com>
+
+ * gcc.target/arm/attr-crypto.c: Update test.
+
+2022-09-28 Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
+ Yvan ROUX <yvan.roux@foss.st.com>
+
+ * gcc.target/aarch64/advsimd-intrinsics/vld1x2.c: Rephrase
+ to unimplemented.
+ * gcc.target/aarch64/advsimd-intrinsics/vld1x3.c: Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vld1x4.c: Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vst1x2.c: Replace
+ dg-xfail-if with dg-skip-if.
+ * gcc.target/aarch64/advsimd-intrinsics/vst1x3.c: Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vst1x4.c: Likewise.
+
+2022-09-28 H.J. Lu <hjl.tools@gmail.com>
+
+ PR middle-end/58245
+ * g++.dg/fstack-protector-strong.C: Adjusted.
+ * g++.dg/pr58245-1.C: New test.
+
+2022-09-28 Eugene Rozenfeld <erozen@microsoft.com>
+
+ * gcc.dg/tree-prof/cold_partition_label.c: Don't check for hot/cold splitting with AutoFDO.
+ * gcc.dg/tree-prof/section-attr-1.c: Don't check for hot/cold splitting with AutoFDO.
+ * gcc.dg/tree-prof/section-attr-2.c: Don't check for hot/cold splitting with AutoFDO.
+ * gcc.dg/tree-prof/section-attr-3.c: Don't check for hot/cold splitting with AutoFDO.
+
+2022-09-27 Marek Polacek <polacek@redhat.com>
+
+ PR c++/101165
+ PR c++/106882
+ * g++.dg/conversion/pr41426.C: Add dg-error for C++23.
+ * g++.dg/cpp0x/elision_weak.C: Likewise.
+ * g++.dg/cpp0x/move-return3.C: Only link in c++20_down.
+ * g++.dg/cpp1y/decltype-auto2.C: Add dg-error for C++23.
+ * g++.dg/cpp1y/lambda-generic-89419.C: Likewise.
+ * g++.dg/cpp23/feat-cxx2b.C: Test __cpp_implicit_move.
+ * g++.dg/gomp/pr56217.C: Only compile in c++20_down.
+ * g++.dg/warn/Wno-return-local-addr.C: Add dg-error for C++23.
+ * g++.dg/warn/Wreturn-local-addr.C: Adjust dg-error.
+ * g++.old-deja/g++.brendan/crash55.C: Add dg-error for C++23.
+ * g++.old-deja/g++.jason/temporary2.C: Likewise.
+ * g++.old-deja/g++.mike/p2846b.C: Adjust.
+ * g++.dg/cpp1y/decltype-auto6.C: New test.
+ * g++.dg/cpp23/decltype1.C: New test.
+ * g++.dg/cpp23/decltype2.C: New test.
+ * g++.dg/cpp23/elision1.C: New test.
+ * g++.dg/cpp23/elision2.C: New test.
+ * g++.dg/cpp23/elision3.C: New test.
+ * g++.dg/cpp23/elision4.C: New test.
+ * g++.dg/cpp23/elision5.C: New test.
+ * g++.dg/cpp23/elision6.C: New test.
+ * g++.dg/cpp23/elision7.C: New test.
+
+2022-09-27 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/107054
+ * gfortran.dg/pr107054.f90: New test.
+
+2022-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/tree-ssa/popcount6b.c: New test.
+
+2022-09-27 Marek Polacek <polacek@redhat.com>
+
+ * g++.dg/cpp2a/concepts-traits3.C: Adjust expected diagnostics.
+
+2022-09-27 Jonathan Wakely <jwakely@redhat.com>
+
+ PR c++/107049
+ * g++.dg/ext/is_convertible4.C: New test.
+ * g++.dg/ext/is_nothrow_convertible4.C: New test.
+
+2022-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/tree-ssa/popcount6.c: New test.
+
+2022-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/106651
+ * g++.dg/template/error30.C: Adjust expected diagnostics.
+ * g++.dg/cpp1z/constexpr-lambda13.C: Likewise.
+ * g++.dg/cpp23/feat-cxx2b.C: Test __cpp_static_call_operator.
+ * g++.dg/cpp23/static-operator-call1.C: New test.
+ * g++.dg/cpp23/static-operator-call2.C: New test.
+ * g++.old-deja/g++.jason/operator.C: Adjust expected diagnostics.
+ * g++.dg/cpp23/static-operator-call3.C: New file.
+
+2022-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/107029
+ * g++.dg/torture/pr107029.C: New test.
+
+2022-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/assume-1.c: New test.
+ * c-c++-common/gomp/assume-2.c: New test.
+ * c-c++-common/gomp/assume-3.c: New test.
+ * c-c++-common/gomp/assumes-1.c: New test.
+ * c-c++-common/gomp/assumes-2.c: New test.
+ * c-c++-common/gomp/assumes-3.c: New test.
+ * c-c++-common/gomp/assumes-4.c: New test.
+ * c-c++-common/gomp/begin-assumes-1.c: New test.
+ * c-c++-common/gomp/begin-assumes-2.c: New test.
+ * c-c++-common/gomp/begin-assumes-3.c: New test.
+ * c-c++-common/gomp/begin-assumes-4.c: New test.
+ * c-c++-common/gomp/declare-target-6.c: New test.
+ * g++.dg/gomp/attrs-1.C (bar): Add n1 and n2 arguments, add
+ tests for assume directive.
+ * g++.dg/gomp/attrs-2.C (bar): Likewise.
+ * g++.dg/gomp/attrs-9.C: Add n1 and n2 variables, add tests for
+ begin assumes directive.
+ * g++.dg/gomp/attrs-15.C: New test.
+ * g++.dg/gomp/attrs-16.C: New test.
+ * g++.dg/gomp/attrs-17.C: New test.
+
+2022-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/diagnostic/conflicting-specifiers-1.C: Adjust expected
+ diagnostics.
+ * g++.dg/parse/typedef8.C: Likewise.
+ * g++.dg/parse/crash39.C: Likewise.
+ * g++.dg/other/mult-stor1.C: Likewise.
+ * g++.dg/cpp2a/constinit3.C: Likewise.
+
+2022-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/106652
+ PR c++/85518
+ * g++.dg/cpp23/ext-floating1.C: New test.
+ * g++.dg/cpp23/ext-floating2.C: New test.
+ * g++.dg/cpp23/ext-floating3.C: New test.
+ * g++.dg/cpp23/ext-floating4.C: New test.
+ * g++.dg/cpp23/ext-floating5.C: New test.
+ * g++.dg/cpp23/ext-floating6.C: New test.
+ * g++.dg/cpp23/ext-floating7.C: New test.
+ * g++.dg/cpp23/ext-floating8.C: New test.
+ * g++.dg/cpp23/ext-floating9.C: New test.
+ * g++.dg/cpp23/ext-floating10.C: New test.
+ * g++.dg/cpp23/ext-floating.h: New file.
+ * g++.target/i386/float16-1.C: Adjust expected diagnostics.
+
+2022-09-26 Marek Polacek <polacek@redhat.com>
+
+ PR c++/106656
+ * g++.dg/cpp23/feat-cxx2b.C: Adjust.
+ * g++.dg/cpp2a/feat-cxx2a.C: Likewise.
+ * g++.dg/ext/char8_t-feature-test-macro-2.C: Likewise.
+ * g++.dg/ext/char8_t-init-2.C: Likewise.
+ * g++.dg/cpp2a/char8_t3.C: New test.
+ * g++.dg/cpp2a/char8_t4.C: New test.
+
+2022-09-26 Marek Polacek <polacek@redhat.com>
+
+ PR c++/106784
+ * g++.dg/ext/is_convertible3.C: New test.
+ * g++.dg/ext/is_nothrow_convertible3.C: New test.
+
+2022-09-26 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/107033
+ * g++.dg/modules/partial-2.cc, g++.dg/modules/partial-2.h: New
+ files, factored out from ...
+ * g++.dg/modules/partial-2_a.C, g++.dg/modules/partial-2_b.C: ...
+ these.
+ * g++.dg/modules/partial-2_c.H: New test.
+ * g++.dg/modules/partial-2_d.C: New test.
+
+2022-09-26 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/107009
+ * gcc.dg/tree-ssa/pr107009.c: New test.
+
+2022-09-26 Jeff Law <jeffreyalaw@gmail.com>
+
+ * gcc.target/riscv/ret-1.c: New test.
+
+2022-09-26 Tobias Burnus <tobias@codesourcery.com>
+
+ PR middle-end/106982
+ * c-c++-common/goacc/reduction-7.c: New test.
+ * c-c++-common/goacc/reduction-8.c: New test.
+
+2022-09-26 Kewen Lin <linkw@linux.ibm.com>
+
+ PR target/96072
+ * gcc.target/powerpc/pr96072.c: New test.
+
+2022-09-26 Hu, Lin1 <lin1.hu@intel.com>
+
+ PR target/94962
+ * gcc.target/i386/avx256-unaligned-store-3.c: Add -mno-avx512f
+
+2022-09-26 Kewen Lin <linkw@linux.ibm.com>
+
+ PR target/100645
+ * gcc.target/powerpc/pr100645.c: New test.
+
+2022-09-26 Hongtao Liu <hongtao.liu@intel.com>
+ Liwei Xu <liwei.xu@intel.com>
+
+ * gcc.target/i386/pr53346-1.c: New test.
+ * gcc.target/i386/pr53346-2.c: New test.
+ * gcc.target/i386/pr53346-3.c: New test.
+ * gcc.target/i386/pr53346-4.c: New test.
+
2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/41453
diff --git a/gcc/testsuite/c-c++-common/gomp/assume-1.c b/gcc/testsuite/c-c++-common/gomp/assume-1.c
new file mode 100644
index 0000000..05c64a8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/assume-1.c
@@ -0,0 +1,29 @@
+void
+foo (int i, int *a)
+{
+ #pragma omp assume no_openmp, absent (target, teams) holds (i < 32U) holds (i < 32U)
+ ;
+ #pragma omp assume no_openmp_routines, contains (simd)
+ {
+ #pragma omp simd
+ for (int j = 0; j < i; j++)
+ a[j] = j;
+ }
+ #pragma omp assume no_parallelism, contains (error)
+ {
+ if (i >= 32)
+ {
+ #pragma omp error at (execution) message ("Should not happen")
+ }
+ }
+ #pragma omp assume absent (for)
+ ;
+ #pragma omp assume absent (atomic, barrier, cancel, cancellation point) absent (critical, depobj)
+ ;
+ #pragma omp assume absent (distribute, flush, loop, masked, master, nothing, ordered)
+ ;
+ #pragma omp assume absent (parallel, scan, scope, section, sections, simd, single, task)
+ ;
+ #pragma omp assume absent (taskgroup, taskloop, taskwait, taskyield)
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/assume-2.c b/gcc/testsuite/c-c++-common/gomp/assume-2.c
new file mode 100644
index 0000000..4739605
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/assume-2.c
@@ -0,0 +1,46 @@
+void
+foo (int i, int *a)
+{
+ #pragma omp assume no_openmp no_openmp /* { dg-error "too many 'no_openmp' clauses" } */
+ ;
+ #pragma omp assume no_openmp_routines, no_openmp_routines /* { dg-error "too many 'no_openmp_routines' clauses" } */
+ ;
+ #pragma omp assume no_parallelism, no_parallelism /* { dg-error "too many 'no_parallelism' clauses" } */
+ ;
+ #pragma omp assume absent (target, target) /* { dg-error "'target' directive mentioned multiple times in 'absent' clauses" } */
+ ;
+ #pragma omp assume absent (target, teams) absent (teams, parallel) /* { dg-error "'teams' directive mentioned multiple times in 'absent' clauses" } */
+ ;
+ #pragma omp assume contains (cancellation point, cancellation point) /* { dg-error "'cancellation point' directive mentioned multiple times in 'contains' clauses" } */
+ ;
+ #pragma omp assume contains (target enter data, target exit data) contains (target exit data, parallel) /* { dg-error "target exit data' directive mentioned multiple times in 'contains' clauses" } */
+ ;
+ #pragma omp assume absent (target enter data, target exit data) contains (target exit data, parallel) /* { dg-error "'target exit data' directive mentioned in both 'absent' and 'contains' clauses" } */
+ ;
+ #pragma omp assume contains (target enter data, target exit data) absent (target enter data, parallel) /* { dg-error "'target enter data' directive mentioned in both 'absent' and 'contains' clauses" } */
+ ;
+ #pragma omp assume contains (declare target) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */
+ ;
+ #pragma omp assume absent (parallel for simd) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */
+ ;
+ #pragma omp assume contains (target parallel) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */
+ ;
+ #pragma omp assume absent (assume) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */
+ ;
+ #pragma omp assume absent (assumes) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */
+ ;
+ #pragma omp assume contains (begin assumes) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */
+ ;
+ #pragma omp assume contains (end assumes) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */
+ ;
+ #pragma omp assume contains (foo) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */
+ ;
+ #pragma omp assume absent (target enter something) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */
+ ;
+ #pragma omp assume foobar /* { dg-error "expected assumption clause" } */
+ ;
+ #pragma omp assume ext_GCC_foobarbaz, ext_GCC_baz (1, 12, 1 < 17), no_parallelism /* { dg-warning "unknown assumption clause 'ext_GCC_foobarbaz'" } */
+ ; /* { dg-warning "unknown assumption clause 'ext_GCC_baz'" "" { target *-*-* } .-1 } */
+ #pragma omp assume /* { dg-error "expected at least one assumption clause" } */
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/assume-3.c b/gcc/testsuite/c-c++-common/gomp/assume-3.c
new file mode 100644
index 0000000..ce38359
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/assume-3.c
@@ -0,0 +1,27 @@
+/* { dg-do run } */
+/* { dg-options "-fno-openmp -fopenmp-simd" } */
+
+int i, j;
+
+int
+foo (void)
+{
+ j = 1;
+ return 1;
+}
+
+int
+main ()
+{
+ #pragma omp assume holds (i < 42)
+ ;
+ #pragma omp assume holds (++i == 1)
+ ;
+ if (i != 0)
+ __builtin_abort ();
+ #pragma omp assume holds (foo () == 1)
+ ;
+ if (j != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/assumes-1.c b/gcc/testsuite/c-c++-common/gomp/assumes-1.c
new file mode 100644
index 0000000..8b3fb37
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/assumes-1.c
@@ -0,0 +1,26 @@
+int i;
+
+#pragma omp assumes no_openmp, absent (target, teams) holds (i < 32U) holds (i < 32U)
+void
+bar (void)
+{
+}
+
+#pragma omp assumes no_openmp_routines
+
+#pragma omp assumes no_parallelism
+
+#pragma omp assumes absent (for)
+void
+fred (void)
+{
+}
+
+#pragma omp assumes absent (atomic, barrier, cancel, cancellation point) absent (critical, depobj) \
+ absent (distribute, flush, loop, masked, master, nothing, ordered) \
+ absent (parallel, scan, scope, section, sections, simd, single, task) \
+ absent (taskgroup, taskloop, taskwait, taskyield)
+void
+foo (void)
+{
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/assumes-2.c b/gcc/testsuite/c-c++-common/gomp/assumes-2.c
new file mode 100644
index 0000000..924f323
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/assumes-2.c
@@ -0,0 +1,23 @@
+#pragma omp assumes no_openmp no_openmp /* { dg-error "too many 'no_openmp' clauses" } */
+#pragma omp assumes no_openmp_routines, no_openmp_routines /* { dg-error "too many 'no_openmp_routines' clauses" } */
+#pragma omp assumes no_parallelism, no_parallelism /* { dg-error "too many 'no_parallelism' clauses" } */
+#pragma omp assumes absent (target, target) /* { dg-error "'target' directive mentioned multiple times in 'absent' clauses" } */
+#pragma omp assumes absent (target, teams) absent (teams, parallel) /* { dg-error "'teams' directive mentioned multiple times in 'absent' clauses" } */
+#pragma omp assumes contains (cancellation point, cancellation point) /* { dg-error "'cancellation point' directive mentioned multiple times in 'contains' clauses" } */
+#pragma omp assumes contains (target enter data, target exit data) contains (target exit data, parallel) /* { dg-error "target exit data' directive mentioned multiple times in 'contains' clauses" } */
+#pragma omp assumes absent (target enter data, target exit data) contains (target exit data, parallel) /* { dg-error "'target exit data' directive mentioned in both 'absent' and 'contains' clauses" } */
+#pragma omp assumes contains (target enter data, target exit data) absent (target enter data, parallel) /* { dg-error "'target enter data' directive mentioned in both 'absent' and 'contains' clauses" } */
+#pragma omp assumes contains (declare target) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */
+#pragma omp assumes absent (parallel for simd) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */
+#pragma omp assumes contains (target parallel) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */
+#pragma omp assumes absent (assume) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */
+#pragma omp assumes absent (assumes) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */
+#pragma omp assumes contains (begin assumes) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */
+#pragma omp assumes contains (end assumes) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */
+#pragma omp assumes contains (foo) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */
+#pragma omp assumes absent (target enter something) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */
+#pragma omp assumes foobar /* { dg-error "expected assumption clause" } */
+#pragma omp assumes ext_GCC_foobarbaz, ext_GCC_baz (1, 12, 1 < 17), no_parallelism /* { dg-warning "unknown assumption clause 'ext_GCC_foobarbaz'" } */
+ /* { dg-warning "unknown assumption clause 'ext_GCC_baz'" "" { target *-*-* } .-1 } */
+#pragma omp assumes /* { dg-error "expected at least one assumption clause" } */
+int i;
diff --git a/gcc/testsuite/c-c++-common/gomp/assumes-3.c b/gcc/testsuite/c-c++-common/gomp/assumes-3.c
new file mode 100644
index 0000000..0bfadac
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/assumes-3.c
@@ -0,0 +1,15 @@
+#pragma omp assumes contains (simd)
+#pragma omp assumes contains (error)
+#pragma omp assumes contains (simd)
+
+void
+foo (int i, int *a)
+{
+ #pragma omp simd
+ for (int j = 0; j < i; j++)
+ a[j] = j;
+ if (i >= 32)
+ {
+ #pragma omp error at (execution) message ("Should not happen")
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/assumes-4.c b/gcc/testsuite/c-c++-common/gomp/assumes-4.c
new file mode 100644
index 0000000..6e77adb
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/assumes-4.c
@@ -0,0 +1,6 @@
+void
+foo (void)
+{
+ #pragma omp assumes no_openmp /* { dg-error "'#pragma omp assumes' may only be used at file scope" "" { target c } } */
+ ; /* { dg-error "'#pragma omp assumes' may only be used at file or namespace scope" "" { target c++ } .-1 } */
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/begin-assumes-1.c b/gcc/testsuite/c-c++-common/gomp/begin-assumes-1.c
new file mode 100644
index 0000000..c3332b1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/begin-assumes-1.c
@@ -0,0 +1,46 @@
+int i;
+
+#pragma omp begin assumes no_openmp, absent (target, teams) holds (i < 32U) holds (i < 32U)
+void
+bar (void)
+{
+}
+#pragma omp end assumes
+
+#pragma omp begin assumes no_openmp_routines, contains (simd)
+void
+baz (int *a)
+{
+ #pragma omp simd
+ for (int j = 0; j < i; j++)
+ a[j] = j;
+}
+#pragma omp end assumes
+
+#pragma omp begin assumes no_parallelism, contains (error)
+void
+qux (void)
+{
+ if (i >= 32)
+ {
+ #pragma omp error at (execution) message ("Should not happen")
+ }
+}
+#pragma omp end assumes
+
+#pragma omp begin assumes absent (for)
+void
+fred (void)
+{
+}
+#pragma omp end assumes
+
+#pragma omp begin assumes absent (atomic, barrier, cancel, cancellation point) absent (critical, depobj) \
+ absent (distribute, flush, loop, masked, master, nothing, ordered) \
+ absent (parallel, scan, scope, section, sections, simd, single, task) \
+ absent (taskgroup, taskloop, taskwait, taskyield)
+void
+foo (void)
+{
+}
+#pragma omp end assumes
diff --git a/gcc/testsuite/c-c++-common/gomp/begin-assumes-2.c b/gcc/testsuite/c-c++-common/gomp/begin-assumes-2.c
new file mode 100644
index 0000000..15dae64
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/begin-assumes-2.c
@@ -0,0 +1,63 @@
+#pragma omp begin assumes no_openmp no_openmp /* { dg-error "too many 'no_openmp' clauses" } */
+void f1 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes no_openmp_routines, no_openmp_routines /* { dg-error "too many 'no_openmp_routines' clauses" } */
+void f2 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes no_parallelism, no_parallelism /* { dg-error "too many 'no_parallelism' clauses" } */
+void f3 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes absent (target, target) /* { dg-error "'target' directive mentioned multiple times in 'absent' clauses" } */
+void f4 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes absent (target, teams) absent (teams, parallel) /* { dg-error "'teams' directive mentioned multiple times in 'absent' clauses" } */
+void f5 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes contains (cancellation point, cancellation point) /* { dg-error "'cancellation point' directive mentioned multiple times in 'contains' clauses" } */
+void f6 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes contains (target enter data, target exit data) contains (target exit data, parallel) /* { dg-error "target exit data' directive mentioned multiple times in 'contains' clauses" } */
+void f7 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes absent (target enter data, target exit data) contains (target exit data, parallel) /* { dg-error "'target exit data' directive mentioned in both 'absent' and 'contains' clauses" } */
+void f8 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes contains (target enter data, target exit data) absent (target enter data, parallel) /* { dg-error "'target enter data' directive mentioned in both 'absent' and 'contains' clauses" } */
+void f9 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes contains (declare target) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */
+void f10 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes absent (parallel for simd) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */
+void f11 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes contains (target parallel) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */
+void f12 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes absent (assume) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */
+void f13 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes absent (assumes) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */
+void f14 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes contains (begin assumes) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */
+void f15 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes contains (end assumes) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */
+void f16 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes contains (foo) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */
+void f17 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes absent (target enter something) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */
+void f18 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes foobar /* { dg-error "expected assumption clause" } */
+void f19 (void) {}
+#pragma omp end assumes
+#pragma omp begin assumes ext_GCC_foobarbaz, ext_GCC_baz (1, 12, 1 < 17), no_parallelism /* { dg-warning "unknown assumption clause 'ext_GCC_foobarbaz'" } */
+void f20 (void) {} /* { dg-warning "unknown assumption clause 'ext_GCC_baz'" "" { target *-*-* } .-1 } */
+#pragma omp end assumes
+#pragma omp begin assumes /* { dg-error "expected at least one assumption clause" } */
+void f21 (void) {}
+#pragma omp end assumes
diff --git a/gcc/testsuite/c-c++-common/gomp/begin-assumes-3.c b/gcc/testsuite/c-c++-common/gomp/begin-assumes-3.c
new file mode 100644
index 0000000..202d5c7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/begin-assumes-3.c
@@ -0,0 +1,2 @@
+#pragma omp begin assumes no_openmp_routines
+void foo (void); /* { dg-error "'#pragma omp begin assumes' without corresponding '#pragma omp end assumes'" } */
diff --git a/gcc/testsuite/c-c++-common/gomp/begin-assumes-4.c b/gcc/testsuite/c-c++-common/gomp/begin-assumes-4.c
new file mode 100644
index 0000000..eea6f90
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/begin-assumes-4.c
@@ -0,0 +1,2 @@
+#pragma omp end assumes /* { dg-error "'#pragma omp end assumes' without corresponding '#pragma omp begin assumes'" } */
+void foo (void);
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-target-6.c b/gcc/testsuite/c-c++-common/gomp/declare-target-6.c
new file mode 100644
index 0000000..586eb50
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/declare-target-6.c
@@ -0,0 +1,2 @@
+#pragma omp end declare target /* { dg-error "'#pragma omp end declare target' without corresponding '#pragma omp declare target'" } */
+void foo (void);
diff --git a/gcc/testsuite/c-c++-common/ubsan/pr85213.c b/gcc/testsuite/c-c++-common/ubsan/pr85213.c
index 8a6be81..e903e97 100644
--- a/gcc/testsuite/c-c++-common/ubsan/pr85213.c
+++ b/gcc/testsuite/c-c++-common/ubsan/pr85213.c
@@ -1,6 +1,11 @@
/* PR sanitizer/85213 */
/* { dg-do compile } */
-/* { dg-options "-O1 -fsanitize=undefined -fcompare-debug" } */
+/* Pass -gno-statement-frontiers to work around
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100733 :
+ without it the IR coming from the front end may be different with and without
+ debug information turned on. That may cause e.g., different discriminator values
+ and -fcompare-debug failures. */
+/* { dg-options "-O1 -fsanitize=undefined -fcompare-debug -gno-statement-frontiers" } */
int
foo (int x)
diff --git a/gcc/testsuite/g++.dg/conversion/pr41426.C b/gcc/testsuite/g++.dg/conversion/pr41426.C
index 5493a91..b4ecbca 100644
--- a/gcc/testsuite/g++.dg/conversion/pr41426.C
+++ b/gcc/testsuite/g++.dg/conversion/pr41426.C
@@ -11,19 +11,20 @@ struct A
A<float> g1()
{
float f[] = {1.1f, 2.3f};
- return f;
+ return f; // { dg-error "cannot bind non-const" "" { target c++23 } }
}
const A<float> &g3()
{
float f[] = {1.1f, 2.3f};
- return f; // { dg-warning "returning reference to temporary" }
+ return f; // { dg-warning "returning reference to temporary" "" { target c++20_down } }
+// { dg-error "non-const lvalue|invalid user-defined conversion" "" { target c++23 } .-1 }
}
A<float> &g4()
{
float f[] = {1.1f, 2.3f};
- return f; // { dg-error "cannot bind non-const lvalue ref" }
+ return f; // { dg-error "cannot bind non-const lvalue ref|invalid user-defined conversion" }
}
struct B
@@ -35,6 +36,5 @@ struct B
B g2()
{
int c[10];
- return c;
+ return c; // { dg-error "non-const lvalue" "" { target c++23 } }
}
-
diff --git a/gcc/testsuite/g++.dg/cpp0x/elision_weak.C b/gcc/testsuite/g++.dg/cpp0x/elision_weak.C
index e8ba755..ddd1274 100644
--- a/gcc/testsuite/g++.dg/cpp0x/elision_weak.C
+++ b/gcc/testsuite/g++.dg/cpp0x/elision_weak.C
@@ -9,11 +9,11 @@ struct S
S f()
{
S s;
- return s;
+ return s; // { dg-error "cannot bind non-const lvalue reference" "" { target c++23 } }
}
void g()
{
S s;
- throw s;
+ throw s; // { dg-error "cannot bind non-const lvalue reference" "" { target c++23 } }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/move-return3.C b/gcc/testsuite/g++.dg/cpp0x/move-return3.C
index c79f059..30a936f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/move-return3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/move-return3.C
@@ -1,6 +1,7 @@
// PR c++/91212
// Test that C++11 implicit move semantics don't call the const copy.
-// { dg-do link }
+// In C++23, we call #2.
+// { dg-do link { target c++20_down } }
struct T { int i; };
diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto2.C b/gcc/testsuite/g++.dg/cpp1y/decltype-auto2.C
index 56e011e..24b32ed 100644
--- a/gcc/testsuite/g++.dg/cpp1y/decltype-auto2.C
+++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto2.C
@@ -8,5 +8,5 @@ auto constexpr RtoL1(T&& r) -> decltype(auto) {
int main() {
int t;
int x{3};
- decltype (RtoL1(x+0)) y = t;
+ decltype (RtoL1(x+0)) y = t; // { dg-error "cannot bind rvalue reference" "" { target c++23 } }
}
diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto6.C b/gcc/testsuite/g++.dg/cpp1y/decltype-auto6.C
new file mode 100644
index 0000000..da53278
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto6.C
@@ -0,0 +1,19 @@
+// PR c++/101165 - P2266R1 - Simpler implicit move
+// { dg-do compile { target c++14 } }
+// A variant of cxx23/elision1.C:eight, just with ().
+
+struct Widget {
+ Widget(Widget&&);
+};
+
+Widget val();
+
+decltype(auto)
+foo ()
+{
+ decltype(auto) x = val(); // OK, x is Widget
+ // We deduce the return type to int&&, therefore we're doing something
+ // we ought not to be doing -- returning a reference to a local variable!
+ // In C++20, we deduce to int&, but that has the same problem!
+ return (x); // { dg-warning "reference to local variable" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-89419.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-89419.C
index 46ce909..8e64d4e 100644
--- a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-89419.C
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-89419.C
@@ -2,7 +2,7 @@
// { dg-do compile { target c++14 } }
struct A;
-struct B {
+struct B { // { dg-error "cannot bind" "" { target c++23 } }
struct C { C (); C (C &); } b;
};
struct D { A operator* (); };
@@ -13,12 +13,12 @@ struct E {
auto bar () { return e; }
D e;
};
-struct F { B f; int g; };
+struct F { B f; int g; }; // { dg-error "use of deleted function" "" { target c++23 } }
int
main ()
{
E e;
auto f = *e.bar ();
- auto i = [&] { F g; g.g = 1; auto h = [&](auto) { g.g = 0; }; f.foo (h); return g; };
+ auto i = [&] { F g; g.g = 1; auto h = [&](auto) { g.g = 0; }; f.foo (h); return g; }; // { dg-error "use of deleted function" "" { target c++23 } }
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda13.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda13.C
index 962ec8d..0323a0d 100644
--- a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda13.C
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda13.C
@@ -2,4 +2,4 @@
auto l1 = []() constexpr constexpr { }; // { dg-error "duplicate" }
auto l2 = []() mutable mutable { }; // { dg-error "duplicate" }
-auto l3 = []() static { }; // { dg-error "static" }
+auto l3 = []() static { }; // { dg-error "static' only valid in lambda with" "" { target c++20_down } }
diff --git a/gcc/testsuite/g++.dg/cpp23/decltype1.C b/gcc/testsuite/g++.dg/cpp23/decltype1.C
new file mode 100644
index 0000000..6f3cd0d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/decltype1.C
@@ -0,0 +1,113 @@
+// PR c++/101165 - P2266R1 - Simpler implicit move
+// { dg-do compile { target c++23 } }
+// Tests from P2266R1, decltype-related changes in
+// $ 3.2.1. Interaction with decltype and decltype(auto)
+
+template<typename T, typename U>
+struct same_type { static const bool value = false; };
+
+template<typename T>
+struct same_type<T, T> { static const bool value = true; };
+
+auto f1(int x) -> decltype(x) { return (x); }
+static_assert(same_type<decltype(f1), int (int)>::value);
+auto f2(int x) -> decltype((x)) { return (x); } // { dg-error "cannot bind" }
+static_assert(same_type<decltype(f2), int& (int)>::value);
+auto f3(int x) -> decltype(auto) { return (x); } // { dg-warning "reference to local variable" }
+static_assert(same_type<decltype(f3), int&& (int)>::value);
+auto g1(int x) -> decltype(x) { return x; }
+static_assert(same_type<decltype(g1), int (int)>::value);
+auto g2(int x) -> decltype((x)) { return x; } // { dg-error "cannot bind" }
+static_assert(same_type<decltype(g2), int& (int)>::value);
+auto g3(int x) -> decltype(auto) { return x; }
+static_assert(same_type<decltype(g3), int (int)>::value);
+
+// Note that f2 and g2 are well-formed in C++20, but we propose to make
+// f2 and g2 ill-formed, because they attempt to bind an lvalue reference
+// to a move-eligible xvalue expression.
+
+struct X { };
+
+auto
+f4 (X x)
+{
+ return x;
+}
+static_assert(same_type<decltype(f4), X(X)>::value);
+
+auto&
+f5 (X x)
+{
+ return x; // { dg-error "cannot bind non-const lvalue reference" }
+}
+static_assert(same_type<decltype(f5), X&(X)>::value);
+
+auto&&
+f6 (X x)
+{
+ return x; // { dg-warning "reference to local variable" }
+}
+static_assert(same_type<decltype(f6), X&&(X)>::value);
+
+auto
+f7 (X x)
+{
+ return (x);
+}
+static_assert(same_type<decltype(f7), X(X)>::value);
+
+auto&
+f8 (X x)
+{
+ return (x); // { dg-error "cannot bind non-const lvalue reference" }
+}
+static_assert(same_type<decltype(f8), X&(X)>::value);
+
+auto&&
+f9 (X x)
+{
+ return (x); // { dg-warning "reference to local variable" }
+}
+static_assert(same_type<decltype(f9), X&&(X)>::value);
+
+decltype(auto)
+f10 (X x)
+{
+ return x;
+}
+static_assert(same_type<decltype(f10), X(X)>::value);
+
+decltype(auto)
+f11 (X x)
+{
+ return (x); // { dg-warning "reference to local variable" }
+}
+static_assert(same_type<decltype(f11), X&&(X)>::value);
+
+decltype(auto)
+f12 (X& x)
+{
+ return x;
+}
+static_assert(same_type<decltype(f12), X&(X&)>::value);
+
+decltype(auto)
+f13 (X& x)
+{
+ return (x);
+}
+static_assert(same_type<decltype(f13), X&(X&)>::value);
+
+decltype(auto)
+f14 (X&& x)
+{
+ return x;
+}
+static_assert(same_type<decltype(f14), X&&(X&&)>::value);
+
+decltype(auto)
+f15 (X&& x)
+{
+ return (x);
+}
+static_assert(same_type<decltype(f15), X&&(X&&)>::value);
diff --git a/gcc/testsuite/g++.dg/cpp23/decltype2.C b/gcc/testsuite/g++.dg/cpp23/decltype2.C
new file mode 100644
index 0000000..84679c4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/decltype2.C
@@ -0,0 +1,49 @@
+// PR c++/101165 - P2266R1 - Simpler implicit move
+// { dg-do compile { target c++23 } }
+// Test decltype(auto) more.
+
+template<typename T, typename U>
+struct same_type { static const bool value = false; };
+
+template<typename T>
+struct same_type<T, T> { static const bool value = true; };
+
+struct Widget {
+ int x;
+};
+
+Widget wg;
+
+decltype(auto) fn0(Widget&& x) {
+ return (::wg);
+}
+static_assert(same_type<decltype(fn0), Widget& (Widget&&)>::value);
+
+decltype(auto) fn1(Widget&& x) {
+ return ::wg;
+}
+static_assert(same_type<decltype(fn1), Widget (Widget&&)>::value);
+
+decltype(auto) fn2() {
+ Widget w;
+ return w;
+}
+static_assert(same_type<decltype(fn2), Widget ()>::value);
+
+decltype(auto) fn3() {
+ Widget w;
+ return (w); // { dg-warning "reference to local variable" }
+}
+static_assert(same_type<decltype(fn3), Widget&& ()>::value);
+
+decltype(auto) fn4() {
+ Widget w;
+ return w.x;
+}
+static_assert(same_type<decltype(fn4), int ()>::value);
+
+decltype(auto) fn5() {
+ Widget w;
+ return (w.x); // { dg-warning "reference to local variable" }
+}
+static_assert(same_type<decltype(fn5), int& ()>::value);
diff --git a/gcc/testsuite/g++.dg/cpp23/elision1.C b/gcc/testsuite/g++.dg/cpp23/elision1.C
new file mode 100644
index 0000000..f44fd2a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/elision1.C
@@ -0,0 +1,114 @@
+// PR c++/101165 - P2266R1 - Simpler implicit move
+// { dg-do compile { target c++23 } }
+// Tests from P2266R1.
+
+namespace std {
+ template<typename _Tp>
+ struct remove_reference
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ constexpr typename std::remove_reference<_Tp>::type&&
+ move(_Tp&& __t) noexcept
+ { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
+}
+
+template<typename T, typename U>
+struct same_type { static const bool value = false; };
+
+template<typename T>
+struct same_type<T, T> { static const bool value = true; };
+
+struct Widget {
+ Widget(Widget&&);
+};
+
+struct RRefTaker {
+ RRefTaker(Widget&&);
+};
+
+struct Mutt {
+ operator int*() &&;
+};
+
+struct Jeff {
+ operator int&() &&;
+};
+
+struct Ella {
+ operator int() &&;
+};
+
+Widget one(Widget w) {
+ return w; // OK since C++11
+}
+
+RRefTaker two(Widget w) {
+ return w; // OK since C++11 + CWG1579
+}
+
+RRefTaker three(Widget&& w) {
+ return w; // OK since C++20 because P0527
+}
+
+// Tests that implicit move applies even to functions that return references.
+Widget&& four(Widget&& w) {
+ return w; // OK since C++23
+}
+
+// ... or pointers.
+int* five(Mutt x) {
+ return x; // OK since C++20 because P1155
+}
+
+int& six(Jeff x) {
+ return x;
+}
+
+int test_ella(Ella e) {
+ return e;
+}
+
+template<class T>
+T&& seven(T&& x) { return x; }
+
+void test_seven(Widget w) {
+ Widget& r = seven(w);
+ Widget&& rr = seven(std::move(w));
+}
+
+Widget val();
+Widget& lref();
+Widget&& rref();
+
+decltype(auto) eight() {
+ decltype(auto) x = val(); // OK, x is Widget
+ return x; // OK, return type is Widget, we get copy elision
+}
+
+decltype(auto) nine() {
+ decltype(auto) x = lref(); // OK, x is Widget&
+ return x; // OK, return type is Widget&
+}
+
+decltype(auto) ten() {
+ decltype(auto) x = rref(); // OK, x is Widget&&
+ // This was an error: return type is Widget&&, cannot bind to x.
+ // But in C++23, x is treated as an rvalue.
+ return x;
+}
+
+// Now returns Widget&&, not Widget&.
+// This is from $ 3.2.1. Interaction with decltype and decltype(auto).
+decltype(auto) eleven(Widget&& x) {
+ return (x);
+}
+static_assert(same_type<decltype(eleven), Widget&& (Widget&&)>::value);
diff --git a/gcc/testsuite/g++.dg/cpp23/elision2.C b/gcc/testsuite/g++.dg/cpp23/elision2.C
new file mode 100644
index 0000000..a698fc9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/elision2.C
@@ -0,0 +1,46 @@
+// PR c++/101165 - P2266R1 - Simpler implicit move
+// { dg-do compile { target c++20 } }
+// Test from P2266R1, $ 3.3. Two overload resolutions are overly confusing.
+
+struct Widget {
+ Widget();
+ Widget(Widget&&);
+};
+
+struct Frodo {
+ Frodo(Widget&);
+ Frodo(Widget&&) = delete;
+};
+
+struct Sam {
+ Sam(Widget&) = delete; // #1
+ Sam(const Widget&); // #2
+};
+
+Sam twelve() {
+ Widget w;
+ // This is supposed to call #2 since C++20 because P1155.
+ // But we actually choose #1 since r11-2411 (in C++20 only).
+ return w; // { dg-error "deleted" "" { target c++20_only } }
+}
+
+Frodo thirteen() {
+ Widget w;
+ // This is a correct error in both C++20 and C++23.
+ return w; // { dg-error "use of deleted function" }
+}
+
+struct Merry {};
+struct Pippin {};
+struct Together : Merry, Pippin {};
+struct Quest {
+ Quest(Merry&&);
+ Quest(Pippin&&);
+ Quest(Together&);
+};
+
+Quest fourteen() {
+ Together t;
+ // C++20: calls Quest(Together&). Proposed: ill-formed.
+ return t; // { dg-error "ambiguous" "" { target c++23 } }
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/elision3.C b/gcc/testsuite/g++.dg/cpp23/elision3.C
new file mode 100644
index 0000000..246342e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/elision3.C
@@ -0,0 +1,16 @@
+// PR c++/101165 - P2266R1 - Simpler implicit move
+// { dg-do compile { target c++23 } }
+// Test from P2266R1, $ 3.4. A specific case involving reference_wrapper.
+
+#include <functional>
+
+struct Widget {
+ Widget();
+ Widget(Widget&&);
+};
+
+std::reference_wrapper<Widget> fifteen() {
+ Widget w;
+ // OK until CWG1579; OK after LWG2993. Proposed: ill-formed
+ return w; // { dg-error "could not convert" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/elision4.C b/gcc/testsuite/g++.dg/cpp23/elision4.C
new file mode 100644
index 0000000..c19b86b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/elision4.C
@@ -0,0 +1,38 @@
+// PR c++/101165 - P2266R1 - Simpler implicit move
+// { dg-do compile { target c++23 } }
+// Test from P2266R1, $ 5.2. LibreOffice OString constructor.
+
+struct X {
+ X(auto&);
+};
+
+// The following compiles in C++20 (deducing X(char (&)[10])) but not
+// after P2266 (because the returned expression now has type char (&&)[10],
+// which cannot bind to auto&).
+X f() {
+ char a[10];
+ return a; // { dg-error "cannot bind non-const lvalue reference" }
+}
+
+// The solution was to change it by making the return convert explicitly
+// rather than implicitly:
+X fixed() {
+ char a[10];
+ return X(a);
+}
+
+// $ 5.3. LibreOffice o3tl::temporary
+
+template<class T>
+T& temporary1(T&& x) { return x; } // { dg-error "cannot bind non-const lvalue reference" }
+
+// Fixed by:
+template<class T>
+T& temporary2(T&& x) { return static_cast<T&>(x); }
+
+void
+test ()
+{
+ int& r1 = temporary1 (42);
+ int& r2 = temporary2 (42);
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/elision5.C b/gcc/testsuite/g++.dg/cpp23/elision5.C
new file mode 100644
index 0000000..a7d3e7c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/elision5.C
@@ -0,0 +1,53 @@
+// PR c++/101165 - P2266R1 - Simpler implicit move
+// { dg-do compile { target c++23 } }
+// Test from [class.copy.elision]/4.
+
+class Thing {
+public:
+ Thing();
+ ~Thing();
+ Thing(Thing&&);
+private:
+ Thing(const Thing&);
+};
+
+Thing f(bool b) {
+ Thing t;
+ if (b)
+ throw t; // OK, Thing(Thing&&) used (or elided) to throw t
+ return t; // OK, Thing(Thing&&) used (or elided) to return t
+}
+
+Thing t2 = f(false); // OK, no extra copy/move performed, t2 constructed by call to f
+
+struct Weird {
+ Weird();
+ Weird(Weird&);
+};
+
+Weird g(bool b) {
+ static Weird w1;
+ Weird w2;
+ if (b) {
+ return w1; // OK: Weird(Weird&)
+ } else {
+ return w2; // { dg-error "cannot bind non-const lvalue reference" }
+ }
+}
+
+int& h(bool b, int i) {
+ static int s;
+ if (b)
+ return s; // OK
+ else
+ return i; // { dg-error "cannot bind non-const lvalue reference" }
+}
+
+decltype(auto) h2(Thing t) {
+ return t; // OK, t is an xvalue and h2's return type is Thing
+}
+
+decltype(auto) h3(Thing t) {
+ // OK, (t) is an xvalue and h3's return type is Thing&&
+ return (t); // { dg-warning "reference to local variable" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/elision6.C b/gcc/testsuite/g++.dg/cpp23/elision6.C
new file mode 100644
index 0000000..5d58da9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/elision6.C
@@ -0,0 +1,20 @@
+// PR c++/101165 - P2266R1 - Simpler implicit move
+// { dg-do compile { target c++23 } }
+// From [diff.cpp20.expr].
+
+template<typename T, typename U>
+struct same_type { static const bool value = false; };
+
+template<typename T>
+struct same_type<T, T> { static const bool value = true; };
+
+// In C++23, returns int&&; previously returned int&.
+decltype(auto) f(int&& x) { return (x); }
+static_assert(same_type<decltype(f), int&& (int&&)>::value);
+
+// This used to work in C++20.
+int& g(int&& x) { return x; } // { dg-error "cannot bind non-const lvalue reference" }
+
+template<typename T>
+decltype(auto) h(T&& x) { return (x); }
+static_assert(same_type<decltype(h(42)), int&&>::value);
diff --git a/gcc/testsuite/g++.dg/cpp23/elision7.C b/gcc/testsuite/g++.dg/cpp23/elision7.C
new file mode 100644
index 0000000..19fa89a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/elision7.C
@@ -0,0 +1,72 @@
+// PR c++/101165 - P2266R1 - Simpler implicit move
+// { dg-do compile { target c++23 } }
+
+struct X {
+ X ();
+ X(X&&);
+};
+
+X&& rref ();
+
+X&&
+f1 (X&& x)
+{
+ return x;
+}
+
+template<typename T> T&&
+f2 (T&& x)
+{
+ return x;
+}
+template X& f2<X&>(X&);
+template X&& f2<X>(X&&);
+
+X&&
+f3 ()
+{
+ X&& x = rref ();
+ return x;
+}
+
+void
+f4 ()
+try {
+ X x;
+ throw x;
+} catch (...) { }
+
+void
+f5 ()
+{
+ auto l1 = [](auto x) -> auto { return x; };
+ auto &&x1 = l1(X{});
+ auto l2 = [](auto x) -> auto& { return x; }; // { dg-error "cannot bind non-const lvalue reference" }
+ auto &&x2 = l2(X{});
+ auto l3 = [](auto x) -> auto&& { return x; }; // { dg-warning "reference to local" }
+ auto &&x3 = l3(X{});
+}
+
+constexpr int &
+f6 (int &&n)
+{
+ return n; // { dg-error "cannot bind non-const lvalue reference" }
+}
+
+void
+do_f6 ()
+{
+ auto x = f6 (42);
+}
+
+template<typename T> auto &
+f7 (T &&t)
+{
+ return t; // { dg-error "cannot bind non-const lvalue reference" }
+}
+
+void
+do_f7 ()
+{
+ const int &x = f7 (0);
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/ext-floating.h b/gcc/testsuite/g++.dg/cpp23/ext-floating.h
new file mode 100644
index 0000000..ffd9e63
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/ext-floating.h
@@ -0,0 +1,30 @@
+// P1467R9 - Extended floating-point types and standard names.
+
+namespace std
+{
+ #ifdef __STDCPP_FLOAT16_T__
+ using float16_t = _Float16;
+ #endif
+ #ifdef __STDCPP_FLOAT32_T__
+ using float32_t = _Float32;
+ #endif
+ #ifdef __STDCPP_FLOAT64_T__
+ using float64_t = _Float64;
+ #endif
+ #ifdef __STDCPP_FLOAT128_T__
+ using float128_t = _Float128;
+ #endif
+ #undef __STDCPP_BFLOAT16_T__
+ #ifdef __STDCPP_BFLOAT16_T__
+ using bfloat16_t = __bf16; // ???
+ #endif
+ template<typename T, T v> struct integral_constant {
+ static constexpr T value = v;
+ };
+ typedef integral_constant<bool, false> false_type;
+ typedef integral_constant<bool, true> true_type;
+ template<class T, class U>
+ struct is_same : std::false_type {};
+ template <class T>
+ struct is_same<T, T> : std::true_type {};
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/ext-floating1.C b/gcc/testsuite/g++.dg/cpp23/ext-floating1.C
new file mode 100644
index 0000000..63232af
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/ext-floating1.C
@@ -0,0 +1,447 @@
+// P1467R9 - Extended floating-point types and standard names.
+// { dg-do compile { target c++23 } }
+// { dg-options "" }
+
+#include "ext-floating.h"
+
+#ifdef __STRICT_ANSI__
+#undef __SIZEOF_FLOAT128__
+#endif
+
+using namespace std;
+
+static_assert (!is_same<float, double>::value);
+static_assert (!is_same<float, long double>::value);
+static_assert (!is_same<double, long double>::value);
+static_assert (is_same<decltype (0.0f), float>::value);
+static_assert (is_same<decltype (0.0F), float>::value);
+static_assert (is_same<decltype (0.0), double>::value);
+static_assert (is_same<decltype (0.0l), long double>::value);
+static_assert (is_same<decltype (0.0L), long double>::value);
+static_assert (is_same<decltype (0.0f + 0.0F), float>::value);
+static_assert (is_same<decltype (0.0F + 0.0f), float>::value);
+static_assert (is_same<decltype (0.0 + 0.0), double>::value);
+static_assert (is_same<decltype (0.0l + 0.0L), long double>::value);
+static_assert (is_same<decltype (0.0L + 0.0l), long double>::value);
+#ifdef __SIZEOF_FLOAT128__
+static_assert (is_same<decltype (0.0q), __float128>::value);
+static_assert (is_same<decltype (0.0Q), __float128>::value);
+static_assert (is_same<decltype (0.0q + 0.0q), __float128>::value);
+static_assert (is_same<decltype (0.0Q + 0.0Q), __float128>::value);
+#endif
+#ifdef __STDCPP_FLOAT16_T__
+static_assert (!is_same<float, float16_t>::value);
+static_assert (!is_same<double, float16_t>::value);
+static_assert (!is_same<long double, float16_t>::value);
+static_assert (is_same<decltype (0.0f16), float16_t>::value);
+static_assert (is_same<decltype (0.0F16), float16_t>::value);
+static_assert (is_same<decltype (0.0f16 + 0.0f16), float16_t>::value);
+static_assert (is_same<decltype (0.0F16 + 0.0F16), float16_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+static_assert (!is_same<float, float32_t>::value);
+static_assert (!is_same<double, float32_t>::value);
+static_assert (!is_same<long double, float32_t>::value);
+static_assert (!is_same<decltype (0.0f), float32_t>::value);
+static_assert (!is_same<decltype (0.0F), float32_t>::value);
+static_assert (is_same<decltype (0.0f32), float32_t>::value);
+static_assert (is_same<decltype (0.0F32), float32_t>::value);
+static_assert (!is_same<decltype (0.0f32), float>::value);
+static_assert (!is_same<decltype (0.0F32), float>::value);
+static_assert (is_same<decltype (0.0f32 + 0.0f32), float32_t>::value);
+static_assert (is_same<decltype (0.0F32 + 0.0F32), float32_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+static_assert (!is_same<float, float64_t>::value);
+static_assert (!is_same<double, float64_t>::value);
+static_assert (!is_same<long double, float64_t>::value);
+static_assert (!is_same<decltype (0.0), float64_t>::value);
+static_assert (is_same<decltype (0.0f64), float64_t>::value);
+static_assert (is_same<decltype (0.0F64), float64_t>::value);
+static_assert (!is_same<decltype (0.0f64), double>::value);
+static_assert (!is_same<decltype (0.0F64), double>::value);
+static_assert (is_same<decltype (0.0f64 + 0.0f64), float64_t>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0F64), float64_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+static_assert (!is_same<float, float128_t>::value);
+static_assert (!is_same<double, float128_t>::value);
+static_assert (!is_same<long double, float128_t>::value);
+static_assert (!is_same<decltype (0.0l), float128_t>::value);
+static_assert (!is_same<decltype (0.0L), float128_t>::value);
+static_assert (is_same<decltype (0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128), float128_t>::value);
+static_assert (!is_same<decltype (0.0f128), long double>::value);
+static_assert (!is_same<decltype (0.0F128), long double>::value);
+static_assert (is_same<decltype (0.0f128 + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0F128), float128_t>::value);
+#ifdef __SIZEOF_FLOAT128__
+static_assert (!is_same<float128_t, __float128>::value);
+static_assert (!is_same<decltype (0.0q), float128_t>::value);
+static_assert (!is_same<decltype (0.0Q), float128_t>::value);
+static_assert (!is_same<decltype (0.0f128), __float128>::value);
+static_assert (!is_same<decltype (0.0F128), __float128>::value);
+#endif
+#endif
+#ifdef __STDCPP_BFLOAT16_T__
+static_assert (!is_same<float, bfloat16_t>::value);
+static_assert (!is_same<double, bfloat16_t>::value);
+static_assert (!is_same<long double, bfloat16_t>::value);
+static_assert (is_same<decltype (0.0bf16), bfloat16_t>::value);
+static_assert (is_same<decltype (0.0BF16), bfloat16_t>::value);
+static_assert (is_same<decltype (0.0bf16 + 0.0bf16), bfloat16_t>::value);
+static_assert (is_same<decltype (0.0BF16 + 0.0BF16), bfloat16_t>::value);
+#endif
+#ifdef __FLT32X_MANT_DIG__
+static_assert (!is_same<float, _Float32x>::value);
+static_assert (!is_same<double, _Float32x>::value);
+static_assert (!is_same<long double, _Float32x>::value);
+static_assert (!is_same<decltype (0.0f), _Float32x>::value);
+static_assert (!is_same<decltype (0.0F), _Float32x>::value);
+static_assert (is_same<decltype (0.0f32x), _Float32x>::value);
+static_assert (is_same<decltype (0.0F32x), _Float32x>::value);
+static_assert (!is_same<decltype (0.0f32x), float>::value);
+static_assert (!is_same<decltype (0.0F32x), float>::value);
+static_assert (is_same<decltype (0.0f32x + 0.0f32x), _Float32x>::value);
+static_assert (is_same<decltype (0.0F32x + 0.0F32x), _Float32x>::value);
+#ifdef __STDCPP_FLOAT16_T__
+static_assert (!is_same<float16_t, _Float32x>::value);
+static_assert (!is_same<decltype (0.0f16), _Float32x>::value);
+static_assert (!is_same<decltype (0.0F16), _Float32x>::value);
+static_assert (!is_same<decltype (0.0f32x), float16_t>::value);
+static_assert (!is_same<decltype (0.0F32x), float16_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+static_assert (!is_same<float32_t, _Float32x>::value);
+static_assert (!is_same<decltype (0.0f32), _Float32x>::value);
+static_assert (!is_same<decltype (0.0F32), _Float32x>::value);
+static_assert (!is_same<decltype (0.0f32x), float32_t>::value);
+static_assert (!is_same<decltype (0.0F32x), float32_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+static_assert (!is_same<float64_t, _Float32x>::value);
+static_assert (!is_same<decltype (0.0f64), _Float32x>::value);
+static_assert (!is_same<decltype (0.0F64), _Float32x>::value);
+static_assert (!is_same<decltype (0.0f32x), float64_t>::value);
+static_assert (!is_same<decltype (0.0F32x), float64_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+static_assert (!is_same<float128_t, _Float32x>::value);
+static_assert (!is_same<decltype (0.0f128), _Float32x>::value);
+static_assert (!is_same<decltype (0.0F128), _Float32x>::value);
+static_assert (!is_same<decltype (0.0f32x), float128_t>::value);
+static_assert (!is_same<decltype (0.0F32x), float128_t>::value);
+#endif
+#endif
+#ifdef __FLT64X_MANT_DIG__
+static_assert (!is_same<float, _Float64x>::value);
+static_assert (!is_same<double, _Float64x>::value);
+static_assert (!is_same<long double, _Float64x>::value);
+static_assert (!is_same<decltype (0.0), _Float64x>::value);
+static_assert (is_same<decltype (0.0f64x), _Float64x>::value);
+static_assert (is_same<decltype (0.0F64x), _Float64x>::value);
+static_assert (!is_same<decltype (0.0f64x), double>::value);
+static_assert (!is_same<decltype (0.0F64x), double>::value);
+static_assert (is_same<decltype (0.0f64x + 0.0f64x), _Float64x>::value);
+static_assert (is_same<decltype (0.0F64x + 0.0F64x), _Float64x>::value);
+#ifdef __STDCPP_FLOAT16_T__
+static_assert (!is_same<float16_t, _Float64x>::value);
+static_assert (!is_same<decltype (0.0f16), _Float64x>::value);
+static_assert (!is_same<decltype (0.0F16), _Float64x>::value);
+static_assert (!is_same<decltype (0.0f64x), float16_t>::value);
+static_assert (!is_same<decltype (0.0F64x), float16_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+static_assert (!is_same<float32_t, _Float64x>::value);
+static_assert (!is_same<decltype (0.0f32), _Float64x>::value);
+static_assert (!is_same<decltype (0.0F32), _Float64x>::value);
+static_assert (!is_same<decltype (0.0f64x), float32_t>::value);
+static_assert (!is_same<decltype (0.0F64x), float32_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+static_assert (!is_same<float64_t, _Float64x>::value);
+static_assert (!is_same<decltype (0.0f64), _Float64x>::value);
+static_assert (!is_same<decltype (0.0F64), _Float64x>::value);
+static_assert (!is_same<decltype (0.0f64x), float64_t>::value);
+static_assert (!is_same<decltype (0.0F64x), float64_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+static_assert (!is_same<float128_t, _Float64x>::value);
+static_assert (!is_same<decltype (0.0f128), _Float64x>::value);
+static_assert (!is_same<decltype (0.0F128), _Float64x>::value);
+static_assert (!is_same<decltype (0.0f64x), float128_t>::value);
+static_assert (!is_same<decltype (0.0F64x), float128_t>::value);
+#endif
+#ifdef __SIZEOF_FLOAT128__
+static_assert (!is_same<_Float64x, __float128>::value);
+static_assert (!is_same<decltype (0.0q), _Float64x>::value);
+static_assert (!is_same<decltype (0.0Q), _Float64x>::value);
+static_assert (!is_same<decltype (0.0f64x), __float128>::value);
+static_assert (!is_same<decltype (0.0F64x), __float128>::value);
+#endif
+#endif
+#ifdef __FLT128X_MANT_DIG__
+static_assert (!is_same<float, _Float128x>::value);
+static_assert (!is_same<double, _Float128x>::value);
+static_assert (!is_same<long double, _Float128x>::value);
+static_assert (!is_same<decltype (0.0l), _Float128x>::value);
+static_assert (!is_same<decltype (0.0L), _Float128x>::value);
+static_assert (is_same<decltype (0.0f128x), _Float128x>::value);
+static_assert (is_same<decltype (0.0F128x), _Float128x>::value);
+static_assert (!is_same<decltype (0.0f128x), long double>::value);
+static_assert (!is_same<decltype (0.0F128x), long double>::value);
+static_assert (is_same<decltype (0.0f128x + 0.0f128x), _Float128x>::value);
+static_assert (is_same<decltype (0.0F128x + 0.0F128x), _Float128x>::value);
+#ifdef __STDCPP_FLOAT16_T__
+static_assert (!is_same<float16_t, _Float128x>::value);
+static_assert (!is_same<decltype (0.0f16), _Float128x>::value);
+static_assert (!is_same<decltype (0.0F16), _Float128x>::value);
+static_assert (!is_same<decltype (0.0f128x), float16_t>::value);
+static_assert (!is_same<decltype (0.0F128x), float16_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+static_assert (!is_same<float32_t, _Float128x>::value);
+static_assert (!is_same<decltype (0.0f32), _Float128x>::value);
+static_assert (!is_same<decltype (0.0F32), _Float128x>::value);
+static_assert (!is_same<decltype (0.0f128x), float32_t>::value);
+static_assert (!is_same<decltype (0.0F128x), float32_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+static_assert (!is_same<float64_t, _Float128x>::value);
+static_assert (!is_same<decltype (0.0f64), _Float128x>::value);
+static_assert (!is_same<decltype (0.0F64), _Float128x>::value);
+static_assert (!is_same<decltype (0.0f128x), float64_t>::value);
+static_assert (!is_same<decltype (0.0F128x), float64_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+static_assert (!is_same<float128_t, _Float128x>::value);
+static_assert (!is_same<decltype (0.0f128), _Float128x>::value);
+static_assert (!is_same<decltype (0.0F128), _Float128x>::value);
+static_assert (!is_same<decltype (0.0f128x), float128_t>::value);
+static_assert (!is_same<decltype (0.0F128x), float128_t>::value);
+#endif
+#ifdef __SIZEOF_FLOAT128__
+static_assert (!is_same<_Float128x, __float128>::value);
+static_assert (!is_same<decltype (0.0q), _Float128x>::value);
+static_assert (!is_same<decltype (0.0Q), _Float128x>::value);
+static_assert (!is_same<decltype (0.0f128x), __float128>::value);
+static_assert (!is_same<decltype (0.0F128x), __float128>::value);
+#endif
+#endif
+static_assert (is_same<decltype (0.0f + 0.0), double>::value);
+static_assert (is_same<decltype (0.0 + 0.0F), double>::value);
+static_assert (is_same<decltype (0.0L + 0.0), long double>::value);
+static_assert (is_same<decltype (0.0 + 0.0L), long double>::value);
+static_assert (is_same<decltype (0.0L + 0.0f), long double>::value);
+static_assert (is_same<decltype (0.0F + 0.0l), long double>::value);
+#if defined(__STDCPP_FLOAT16_T__) && defined(__STDCPP_FLOAT32_T__)
+static_assert (!is_same<float16_t, float32_t>::value);
+static_assert (is_same<decltype (0.0f16 + 0.0f32), float32_t>::value);
+static_assert (is_same<decltype (0.0F32 + 0.0F16), float32_t>::value);
+#endif
+#if defined(__STDCPP_FLOAT16_T__) && defined(__STDCPP_FLOAT64_T__)
+static_assert (!is_same<float16_t, float64_t>::value);
+static_assert (is_same<decltype (0.0f16 + 0.0f64), float64_t>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0F16), float64_t>::value);
+#endif
+#if defined(__STDCPP_FLOAT16_T__) && defined(__STDCPP_FLOAT128_T__)
+static_assert (!is_same<float16_t, float128_t>::value);
+static_assert (is_same<decltype (0.0f16 + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0F16), float128_t>::value);
+#endif
+#if defined(__STDCPP_FLOAT16_T__) && defined(__FLT32X_MANT_DIG__)
+static_assert (is_same<decltype (0.0f16 + 0.0f32x), _Float32x>::value);
+static_assert (is_same<decltype (0.0F32x + 0.0F16), _Float32x>::value);
+#endif
+#if defined(__STDCPP_FLOAT16_T__) && defined(__FLT64X_MANT_DIG__)
+static_assert (is_same<decltype (0.0f16 + 0.0f64x), _Float64x>::value);
+static_assert (is_same<decltype (0.0F64x + 0.0F16), _Float64x>::value);
+#endif
+#if defined(__STDCPP_FLOAT16_T__) && defined(__FLT128X_MANT_DIG__)
+static_assert (is_same<decltype (0.0f16 + 0.0f128x), _Float128x>::value);
+static_assert (is_same<decltype (0.0F128x + 0.0F16), _Float128x>::value);
+#endif
+#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__)
+static_assert (!is_same<float32_t, float64_t>::value);
+static_assert (is_same<decltype (0.0f32 + 0.0f64), float64_t>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0F32), float64_t>::value);
+#endif
+#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT128_T__)
+static_assert (!is_same<float32_t, float128_t>::value);
+static_assert (is_same<decltype (0.0f32 + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0F32), float128_t>::value);
+#endif
+#if defined(__STDCPP_FLOAT32_T__) && defined(__FLT32X_MANT_DIG__)
+static_assert (is_same<decltype (0.0f32 + 0.0f32x), _Float32x>::value);
+static_assert (is_same<decltype (0.0F32x + 0.0F32), _Float32x>::value);
+#endif
+#if defined(__STDCPP_FLOAT32_T__) && defined(__FLT64X_MANT_DIG__)
+static_assert (is_same<decltype (0.0f32 + 0.0f64x), _Float64x>::value);
+static_assert (is_same<decltype (0.0F64x + 0.0F32), _Float64x>::value);
+#endif
+#if defined(__STDCPP_FLOAT32_T__) && defined(__FLT128X_MANT_DIG__)
+static_assert (is_same<decltype (0.0f32 + 0.0f128x), _Float128x>::value);
+static_assert (is_same<decltype (0.0F128x + 0.0F32), _Float128x>::value);
+#endif
+#if defined(__STDCPP_FLOAT64_T__) && defined(__STDCPP_FLOAT128_T__)
+static_assert (!is_same<float64_t, float128_t>::value);
+static_assert (is_same<decltype (0.0f64 + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0F64), float128_t>::value);
+#endif
+#if defined(__STDCPP_FLOAT64_T__) && defined(__FLT32X_MANT_DIG__) \
+ && __FLT64_MAX_EXP__ == __FLT32X_MAX_EXP__ \
+ && __FLT64_MANT_DIG__ == __FLT32X_MANT_DIG__
+static_assert (is_same<decltype (0.0f64 + 0.0f32x), float64_t>::value);
+static_assert (is_same<decltype (0.0F32x + 0.0F64), float64_t>::value);
+#endif
+#if defined(__STDCPP_FLOAT64_T__) && defined(__FLT64X_MANT_DIG__)
+static_assert (is_same<decltype (0.0f64 + 0.0f64x), _Float64x>::value);
+static_assert (is_same<decltype (0.0F64x + 0.0F64), _Float64x>::value);
+#endif
+#if defined(__STDCPP_FLOAT64_T__) && defined(__FLT128X_MANT_DIG__)
+static_assert (is_same<decltype (0.0f64 + 0.0f128x), _Float128x>::value);
+static_assert (is_same<decltype (0.0F128x + 0.0F64), _Float128x>::value);
+#endif
+#if defined(__STDCPP_FLOAT128_T__) && defined(__FLT32X_MANT_DIG__) \
+ && __FLT128_MAX_EXP__ >= __FLT32X_MAX_EXP__ \
+ && __FLT128_MANT_DIG__ >= __FLT32X_MANT_DIG__
+static_assert (is_same<decltype (0.0f128 + 0.0f32x), float128_t>::value);
+static_assert (is_same<decltype (0.0F32x + 0.0F128), float128_t>::value);
+#endif
+#if defined(__STDCPP_FLOAT128_T__) && defined(__FLT64X_MANT_DIG__) \
+ && __FLT128_MAX_EXP__ >= __FLT64X_MAX_EXP__ \
+ && __FLT128_MANT_DIG__ >= __FLT64X_MANT_DIG__
+static_assert (is_same<decltype (0.0f128 + 0.0f64x), float128_t>::value);
+static_assert (is_same<decltype (0.0F64x + 0.0F128), float128_t>::value);
+#endif
+#if defined(__STDCPP_FLOAT128_T__) && defined(__FLT128X_MANT_DIG__)
+static_assert (is_same<decltype (0.0f128 + 0.0f128x), _Float128>::value);
+static_assert (is_same<decltype (0.0F128x + 0.0F128), _Float128>::value);
+#endif
+#if defined(__STDCPP_BFLOAT16_T__) && defined(__STDCPP_FLOAT32_T__)
+static_assert (!is_same<bfloat16_t, float32_t>::value);
+static_assert (is_same<decltype (0.0bf16 + 0.0f32), float32_t>::value);
+static_assert (is_same<decltype (0.0F32 + 0.0BF16), float32_t>::value);
+#endif
+#if defined(__STDCPP_BFLOAT16_T__) && defined(__STDCPP_FLOAT64_T__)
+static_assert (!is_same<bfloat16_t, float64_t>::value);
+static_assert (is_same<decltype (0.0bf16 + 0.0f64), float64_t>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0BF16), float64_t>::value);
+#endif
+#if defined(__STDCPP_BFLOAT16_T__) && defined(__STDCPP_FLOAT128_T__)
+static_assert (!is_same<bfloat16_t, float128_t>::value);
+static_assert (is_same<decltype (0.0bf16 + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0BF16), float128_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT16_T__
+#if __FLT_MAX_EXP__ > __FLT16_MAX_EXP__ && __FLT_MANT_DIG__ > __FLT16_MANT_DIG__
+static_assert (is_same<decltype (0.0f + 0.0f16), float>::value);
+static_assert (is_same<decltype (0.0F16 + 0.0F), float>::value);
+#endif
+#if __DBL_MAX_EXP__ > __FLT16_MAX_EXP__ && __DBL_MANT_DIG__ > __FLT16_MANT_DIG__
+static_assert (is_same<decltype (0.0 + 0.0f16), double>::value);
+static_assert (is_same<decltype (0.0F16 + 0.0), double>::value);
+#endif
+#if __LDBL_MAX_EXP__ > __FLT16_MAX_EXP__ && __LDBL_MANT_DIG__ > __FLT16_MANT_DIG__
+static_assert (is_same<decltype (0.0L + 0.0f16), long double>::value);
+static_assert (is_same<decltype (0.0F16 + 0.0l), long double>::value);
+#endif
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+#if __FLT_MAX_EXP__ == __FLT32_MAX_EXP__ && __FLT_MANT_DIG__ == __FLT32_MANT_DIG__
+static_assert (is_same<decltype (0.0f + 0.0f32), float32_t>::value);
+static_assert (is_same<decltype (0.0F32 + 0.0F), float32_t>::value);
+#endif
+#if __DBL_MAX_EXP__ > __FLT32_MAX_EXP__ && __DBL_MANT_DIG__ > __FLT32_MANT_DIG__
+static_assert (is_same<decltype (0.0 + 0.0f32), double>::value);
+static_assert (is_same<decltype (0.0F32 + 0.0), double>::value);
+#endif
+#if __LDBL_MAX_EXP__ > __FLT32_MAX_EXP__ && __LDBL_MANT_DIG__ > __FLT32_MANT_DIG__
+static_assert (is_same<decltype (0.0L + 0.0f32), long double>::value);
+static_assert (is_same<decltype (0.0F32 + 0.0l), long double>::value);
+#endif
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+#if __FLT_MAX_EXP__ < __FLT64_MAX_EXP__ && __FLT_MANT_DIG__ < __FLT64_MANT_DIG__
+static_assert (is_same<decltype (0.0f + 0.0f64), float64_t>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0F), float64_t>::value);
+#endif
+#if __DBL_MAX_EXP__ == __FLT64_MAX_EXP__ && __DBL_MANT_DIG__ == __FLT64_MANT_DIG__
+static_assert (is_same<decltype (0.0 + 0.0f64), float64_t>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0), float64_t>::value);
+#endif
+#if __LDBL_MAX_EXP__ > __FLT64_MAX_EXP__ && __LDBL_MANT_DIG__ > __FLT64_MANT_DIG__
+static_assert (is_same<decltype (0.0L + 0.0f64), long double>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0l), long double>::value);
+#endif
+#if __LDBL_MAX_EXP__ == __FLT64_MAX_EXP__ && __LDBL_MANT_DIG__ == __FLT64_MANT_DIG__ \
+ && __DBL_MAX_EXP__ == __FLT64_MAX_EXP__ && __DBL_MANT_DIG__ == __FLT64_MANT_DIG__
+// An extended floating-point type with the same set of values as more than one
+// cv-unqualified standard floating-point type has a rank equal to the rank of
+// double.
+// Then long double will have higher rank than float64_t.
+static_assert (is_same<decltype (0.0L + 0.0f64), long double>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0l), long double>::value);
+#endif
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+#if __FLT_MAX_EXP__ < __FLT128_MAX_EXP__ && __FLT_MANT_DIG__ < __FLT128_MANT_DIG__
+static_assert (is_same<decltype (0.0f + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0F), float128_t>::value);
+#endif
+#if __DBL_MAX_EXP__ < __FLT128_MAX_EXP__ && __DBL_MANT_DIG__ < __FLT128_MANT_DIG__
+static_assert (is_same<decltype (0.0 + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0), float128_t>::value);
+#endif
+#if __LDBL_MAX_EXP__ <= __FLT128_MAX_EXP__ && __LDBL_MANT_DIG__ <= __FLT128_MANT_DIG__ \
+ && __LDBL_MANT_DIG__ != 106 // IBM extended long double and IEEE quad are unordered.
+static_assert (is_same<decltype (0.0L + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0l), float128_t>::value);
+#endif
+#ifdef __SIZEOF_FLOAT128__
+static_assert (is_same<decltype (0.0Q + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0q), float128_t>::value);
+#endif
+#endif
+#ifdef __STDCPP_BFLOAT16_T__
+#if __FLT_MAX_EXP__ > __BFLT16_MAX_EXP__ && __FLT_MANT_DIG__ > __BFLT16_MANT_DIG__
+static_assert (is_same<decltype (0.0f + 0.0bf16), float>::value);
+static_assert (is_same<decltype (0.0BF16 + 0.0F), float>::value);
+#endif
+#if __DBL_MAX_EXP__ > __BFLT16_MAX_EXP__ && __DBL_MANT_DIG__ > __BFLT16_MANT_DIG__
+static_assert (is_same<decltype (0.0 + 0.0bf16), double>::value);
+static_assert (is_same<decltype (0.0BF16 + 0.0), double>::value);
+#endif
+#if __LDBL_MAX_EXP__ > __BFLT16_MAX_EXP__ && __LDBL_MANT_DIG__ > __BFLT16_MANT_DIG__
+static_assert (is_same<decltype (0.0L + 0.0bf16), long double>::value);
+static_assert (is_same<decltype (0.0BF16 + 0.0l), long double>::value);
+#endif
+#endif
+
+void foo (float) {}
+void foo (double) {}
+void foo (long double) {}
+#ifdef __STDCPP_FLOAT16_T__
+void foo (float16_t) {}
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+void foo (float32_t) {}
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+void foo (float64_t) {}
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+void foo (float128_t) {}
+#endif
+#ifdef __STDCPP_BFLOAT16_T__
+void foo (bfloat16_t) {}
+#endif
+#ifdef __FLT32X_MANT_DIG__
+void foo (_Float32x) {}
+#endif
+#ifdef __FLT64X_MANT_DIG__
+void foo (_Float64x) {}
+#endif
+#ifdef __FLT128X_MANT_DIG__
+void foo (_Float128x) {}
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp23/ext-floating10.C b/gcc/testsuite/g++.dg/cpp23/ext-floating10.C
new file mode 100644
index 0000000..f5563fe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/ext-floating10.C
@@ -0,0 +1,13 @@
+// P1467R9 - Extended floating-point types and standard names.
+// { dg-do run { target { c++23 && float128_runtime } } }
+// { dg-options "" }
+// { dg-add-options float128 }
+
+#ifndef WIDTH
+#ifndef __STDCPP_FLOAT128_T__
+#error Unexpected
+#endif
+#define WIDTH 128
+#endif
+
+#include "ext-floating7.C"
diff --git a/gcc/testsuite/g++.dg/cpp23/ext-floating2.C b/gcc/testsuite/g++.dg/cpp23/ext-floating2.C
new file mode 100644
index 0000000..41e9a54
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/ext-floating2.C
@@ -0,0 +1,157 @@
+// P1467R9 - Extended floating-point types and standard names.
+// { dg-do compile { target c++23 } }
+// { dg-options "" }
+
+#include "ext-floating.h"
+
+#ifdef __STRICT_ANSI__
+#undef __SIZEOF_FLOAT128__
+#endif
+
+using namespace std;
+
+float fa = 1.0f;
+float fb = (float) 1.0f;
+float fc = 1.0;
+float fd = (float) 1.0;
+float fe = 1.0L;
+float ff = (float) 1.0L;
+#ifdef __SIZEOF_FLOAT128__
+float fg = 1.0Q;
+float fh = (float) 1.0Q;
+#endif
+double da = 1.0f;
+double db = (double) 1.0f;
+double dc = 1.0;
+double dd = (double) 1.0;
+double de = 1.0L;
+double df = (double) 1.0L;
+#ifdef __SIZEOF_FLOAT128__
+double dg = 1.0Q;
+double dh = (double) 1.0Q;
+#endif
+long double lda = 1.0f;
+long double ldb = (long double) 1.0f;
+long double ldc = 1.0;
+long double ldd = (long double) 1.0;
+long double lde = 1.0L;
+long double ldf = (long double) 1.0L;
+#ifdef __SIZEOF_FLOAT128__
+long double ldg = 1.0Q;
+long double ldh = (long double) 1.0Q;
+__float128 qa = 1.0f;
+__float128 qb = (__float128) 1.0f;
+__float128 qc = 1.0;
+__float128 qd = (__float128) 1.0;
+__float128 qe = 1.0L;
+__float128 qf = (__float128) 1.0L;
+__float128 qg = 1.0Q;
+__float128 qh = (__float128) 1.0Q;
+#endif
+#ifdef __STDCPP_FLOAT16_T__
+float16_t f16a = 1.0F16;
+float16_t f16b = (float16_t) 1.0F16;
+#ifdef __STDCPP_FLOAT32_T__
+float16_t f16c = 1.0F32; // { dg-warning "converting to 'std::float16_t' \\\{aka '_Float16'\\\} from '_Float32' with greater conversion rank" "" { target { float16 && float32 } } }
+float16_t f16d = (float16_t) 1.0F32;
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+float16_t f16e = 1.0F64; // { dg-warning "converting to 'std::float16_t' \\\{aka '_Float16'\\\} from '_Float64' with greater conversion rank" "" { target { float16 && float64 } } }
+float16_t f16f = (float16_t) 1.0F64;
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+float16_t f16g = 1.0F128; // { dg-warning "converting to 'std::float16_t' \\\{aka '_Float16'\\\} from '_Float128' with greater conversion rank" "" { target { float16 && float128 } } }
+float16_t f16h = (float16_t) 1.0F128;
+#endif
+float16_t f16j = (float16_t) 1.0f;
+float16_t f16l = (float16_t) 1.0;
+float16_t f16n = (float16_t) 1.0L;
+#ifdef __SIZEOF_FLOAT128__
+float16_t f16p = (float16_t) 1.0Q;
+#endif
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+#ifdef __STDCPP_FLOAT16_T__
+float32_t f32a = 1.0F16;
+float32_t f32b = (float32_t) 1.0F16;
+#endif
+float32_t f32c = 1.0F32;
+float32_t f32d = (float32_t) 1.0F32;
+#ifdef __STDCPP_FLOAT64_T__
+float32_t f32e = 1.0F64; // { dg-warning "converting to 'std::float32_t' \\\{aka '_Float32'\\\} from '_Float64' with greater conversion rank" "" { target { float32 && float64 } } }
+float32_t f32f = (float32_t) 1.0F64;
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+float32_t f32g = 1.0F128; // { dg-warning "converting to 'std::float32_t' \\\{aka '_Float32'\\\} from '_Float128' with greater conversion rank" "" { target { float32 && float128 } } }
+float32_t f32h = (float32_t) 1.0F128;
+#endif
+#if __FLT_MAX_EXP__ <= __FLT32_MAX_EXP__ && __FLT_MANT_DIG__ <= __FLT32_MANT_DIG__
+float32_t f32i = 1.0f;
+#endif
+float32_t f32j = (float32_t) 1.0f;
+float32_t f32l = (float32_t) 1.0;
+float32_t f32n = (float32_t) 1.0L;
+#ifdef __SIZEOF_FLOAT128__
+float32_t f32p = (float32_t) 1.0Q;
+#endif
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+#ifdef __STDCPP_FLOAT16_T__
+float64_t f64a = 1.0F16;
+float64_t f64b = (float64_t) 1.0F16;
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+float64_t f64c = 1.0F32;
+float64_t f64d = (float64_t) 1.0F32;
+#endif
+float64_t f64e = 1.0F64;
+float64_t f64f = (float64_t) 1.0F64;
+#ifdef __STDCPP_FLOAT128_T__
+float64_t f64g = 1.0F128; // { dg-warning "converting to 'std::float64_t' \\\{aka '_Float64'\\\} from '_Float128' with greater conversion rank" "" { target { float64 && float128 } } }
+float64_t f64h = (float64_t) 1.0F128;
+#endif
+#if __FLT_MAX_EXP__ <= __FLT64_MAX_EXP__ && __FLT_MANT_DIG__ <= __FLT64_MANT_DIG__
+float64_t f64i = 1.0f;
+#endif
+float64_t f64j = (float64_t) 1.0f;
+#if __DBL_MAX_EXP__ <= __FLT64_MAX_EXP__ && __DBL_MANT_DIG__ <= __FLT64_MANT_DIG__
+float64_t f64k = 1.0;
+#endif
+float64_t f64l = (float64_t) 1.0;
+float64_t f64n = (float64_t) 1.0L;
+#ifdef __SIZEOF_FLOAT128__
+float64_t f64p = (float64_t) 1.0Q;
+#endif
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+#ifdef __STDCPP_FLOAT16_T__
+float128_t f128a = 1.0F16;
+float128_t f128b = (float128_t) 1.0F16;
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+float128_t f128c = 1.0F32;
+float128_t f128d = (float128_t) 1.0F32;
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+float128_t f128e = 1.0F64;
+float128_t f128f = (float128_t) 1.0F64;
+#endif
+float128_t f128g = 1.0F128;
+float128_t f128h = (float128_t) 1.0F128;
+#if __FLT_MAX_EXP__ <= __FLT128_MAX_EXP__ && __FLT_MANT_DIG__ <= __FLT128_MANT_DIG__
+float128_t f128i = 1.0f;
+#endif
+float128_t f128j = (float128_t) 1.0f;
+#if __DBL_MAX_EXP__ <= __FLT128_MAX_EXP__ && __DBL_MANT_DIG__ <= __FLT128_MANT_DIG__
+float128_t f128k = 1.0;
+#endif
+float128_t f128l = (float128_t) 1.0;
+#if __LDBL_MAX_EXP__ <= __FLT128_MAX_EXP__ && __LDBL_MANT_DIG__ <= __FLT128_MANT_DIG__ && __LDBL_MANT_DIG__ != 106
+float128_t f128m = 1.0L;
+#endif
+float128_t f128n = (float128_t) 1.0L;
+#ifdef __SIZEOF_FLOAT128__
+float128_t f128o = 1.0Q;
+float128_t f128p = (float128_t) 1.0Q;
+#endif
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp23/ext-floating3.C b/gcc/testsuite/g++.dg/cpp23/ext-floating3.C
new file mode 100644
index 0000000..ca9399f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/ext-floating3.C
@@ -0,0 +1,134 @@
+// P1467R9 - Extended floating-point types and standard names.
+// Variant of ext-floating2.C test with x86 specific assumptions
+// about float, double, long double and existence of __float128.
+// And some further tests.
+// { dg-do compile { target { c++23 && { i?86-*-linux* x86_64-*-linux* } } } }
+// { dg-options "" }
+
+#include "ext-floating.h"
+
+#if !defined(__STDCPP_FLOAT32_T__) \
+ || !defined(__STDCPP_FLOAT64_T__) || !defined(__STDCPP_FLOAT128_T__) \
+ || __FLT_MAX_EXP__ != __FLT32_MAX_EXP__ || __FLT_MANT_DIG__ != __FLT32_MANT_DIG__ \
+ || __DBL_MAX_EXP__ != __FLT64_MAX_EXP__ || __DBL_MANT_DIG__ != __FLT64_MANT_DIG__ \
+ || __LDBL_MAX_EXP__ != __FLT128_MAX_EXP__ || __LDBL_MANT_DIG__ >= __FLT128_MANT_DIG__ \
+ || !defined(__SIZEOF_FLOAT128__)
+#error Unexpected set of floating point types
+#endif
+
+using namespace std;
+
+#ifdef __STDCPP_FLOAT16_T__
+float16_t f16i = 1.0f; // { dg-warning "converting to 'std::float16_t' \\\{aka '_Float16'\\\} from 'float' with greater conversion rank" "" { target float16 } }
+float16_t f16k = 1.0; // { dg-warning "converting to 'std::float16_t' \\\{aka '_Float16'\\\} from 'double' with greater conversion rank" "" { target float16 } }
+float16_t f16m = 1.0L; // { dg-warning "converting to 'std::float16_t' \\\{aka '_Float16'\\\} from 'long double' with greater conversion rank" "" { target float16 } }
+float16_t f16o = 1.0Q; // { dg-warning "converting to 'std::float16_t' \\\{aka '_Float16'\\\} from '__float128' with greater conversion rank" "" { target float16 } }
+#endif
+float32_t f32i = 1.0f;
+float32_t f32k = 1.0; // { dg-warning "converting to 'std::float32_t' \\\{aka '_Float32'\\\} from 'double' with greater conversion rank" }
+float32_t f32m = 1.0L; // { dg-warning "converting to 'std::float32_t' \\\{aka '_Float32'\\\} from 'long double' with greater conversion rank" }
+float32_t f32o = 1.0Q; // { dg-warning "converting to 'std::float32_t' \\\{aka '_Float32'\\\} from '__float128' with greater conversion rank" }
+float64_t f64i = 1.0f;
+float64_t f64k = 1.0;
+float64_t f64m = 1.0L; // { dg-warning "converting to 'std::float64_t' \\\{aka '_Float64'\\\} from 'long double' with greater conversion rank" }
+float64_t f64o = 1.0Q; // { dg-warning "converting to 'std::float64_t' \\\{aka '_Float64'\\\} from '__float128' with greater conversion rank" }
+float128_t f128i = 1.0f;
+float128_t f128k = 1.0;
+float128_t f128m = 1.0L;
+float128_t f128o = 1.0Q;
+
+#ifdef __STDCPP_FLOAT16_T__
+constexpr float16_t f16x = 1.0F16;
+#endif
+constexpr float32_t f32x = 2.0F32;
+constexpr float64_t f64x = 3.0F64;
+constexpr float128_t f128x = 4.0F128;
+constexpr float fx = 5.0f;
+constexpr double dx = 6.0;
+constexpr long double ldx = 7.0L;
+
+constexpr int foo (float32_t) { return 1; }
+constexpr int foo (float64_t) { return 2; }
+constexpr int bar (float) { return 3; }
+constexpr int bar (double) { return 4; }
+constexpr int bar (long double) { return 5; }
+constexpr int baz (float32_t) { return 6; }
+constexpr int baz (float64_t) { return 7; }
+constexpr int baz (float128_t) { return 8; }
+constexpr int qux (float64_t) { return 9; }
+constexpr int qux (float32_t) { return 10; }
+constexpr int fred (long double) { return 11; }
+constexpr int fred (double) { return 12; }
+constexpr int fred (float) { return 13; }
+constexpr int thud (float128_t) { return 14; }
+constexpr int thud (float64_t) { return 15; }
+constexpr int thud (float32_t) { return 16; }
+struct S {
+ constexpr operator float32_t () const { return 1.0f32; }
+ constexpr operator float64_t () const { return 2.0f64; }
+};
+struct T {
+ constexpr operator float64_t () const { return 3.0f64; }
+ constexpr operator float32_t () const { return 4.0f32; }
+};
+
+void
+test (S s, T t)
+{
+#ifdef __STDCPP_FLOAT16_T__
+ foo (float16_t (1.0)); // { dg-error "call of overloaded 'foo\\\(std::float16_t\\\)' is ambiguous" "" { target float16 } }
+#endif
+ static_assert (foo (float (2.0)) == 1);
+ static_assert (foo (double (3.0)) == 2);
+ constexpr double x (s);
+ static_assert (x == 2.0);
+#ifdef __STDCPP_FLOAT16_T__
+ bar (f16x); // { dg-error "call of overloaded 'bar\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+ static_assert (bar (f32x) == 3);
+ static_assert (bar (f64x) == 4);
+ bar (f128x); // { dg-error "no matching function for call to 'bar\\\(const std::float128_t\\\&\\\)'" }
+ // { dg-warning "converting to 'float' from 'const std::float128_t' \\\{aka 'const _Float128'\\\} with greater conversion rank" "" { target *-*-* } .-1 }
+ // { dg-warning "converting to 'double' from 'const std::float128_t' \\\{aka 'const _Float128'\\\} with greater conversion rank" "" { target *-*-* } .-2 }
+ // { dg-warning "converting to 'long double' from 'const std::float128_t' \\\{aka 'const _Float128'\\\} with greater conversion rank" "" { target *-*-* } .-3 }
+ static_assert (bar (fx) == 3);
+ static_assert (bar (dx) == 4);
+ static_assert (bar (ldx) == 5);
+#ifdef __STDCPP_FLOAT16_T__
+ baz (f16x); // { dg-error "call of overloaded 'baz\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+ static_assert (baz (f32x) == 6);
+ static_assert (baz (f64x) == 7);
+ static_assert (baz (f128x) == 8);
+ static_assert (baz (fx) == 6);
+ static_assert (baz (dx) == 7);
+ static_assert (baz (ldx) == 8);
+#ifdef __STDCPP_FLOAT16_T__
+ qux (float16_t (1.0)); // { dg-error "call of overloaded 'qux\\\(std::float16_t\\\)' is ambiguous" "" { target float16 } }
+#endif
+ static_assert (qux (float (2.0)) == 10);
+ static_assert (qux (double (3.0)) == 9);
+ constexpr double y (t);
+ static_assert (y == 3.0);
+#ifdef __STDCPP_FLOAT16_T__
+ fred (f16x); // { dg-error "call of overloaded 'fred\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+ static_assert (fred (f32x) == 13);
+ static_assert (fred (f64x) == 12);
+ fred (f128x); // { dg-error "no matching function for call to 'fred\\\(const std::float128_t\\\&\\\)'" }
+ // { dg-warning "converting to 'float' from 'const std::float128_t' \\\{aka 'const _Float128'\\\} with greater conversion rank" "" { target *-*-* } .-1 }
+ // { dg-warning "converting to 'double' from 'const std::float128_t' \\\{aka 'const _Float128'\\\} with greater conversion rank" "" { target *-*-* } .-2 }
+ // { dg-warning "converting to 'long double' from 'const std::float128_t' \\\{aka 'const _Float128'\\\} with greater conversion rank" "" { target *-*-* } .-3 }
+ static_assert (fred (fx) == 13);
+ static_assert (fred (dx) == 12);
+ static_assert (fred (ldx) == 11);
+#ifdef __STDCPP_FLOAT16_T__
+ thud (f16x); // { dg-error "call of overloaded 'thud\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+ static_assert (thud (f32x) == 16);
+ static_assert (thud (f64x) == 15);
+ static_assert (thud (f128x) == 14);
+ static_assert (thud (fx) == 16);
+ static_assert (thud (dx) == 15);
+ static_assert (thud (ldx) == 14);
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/ext-floating4.C b/gcc/testsuite/g++.dg/cpp23/ext-floating4.C
new file mode 100644
index 0000000..1bac105
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/ext-floating4.C
@@ -0,0 +1,126 @@
+// P1467R9 - Extended floating-point types and standard names.
+// Variant of ext-floating3.C test with different specific assumptions
+// about float, double, long double.
+// float, double and long double are assumed to be IEEE 754 single, double
+// and quad.
+// { dg-do compile { target { c++23 && { aarch64*-*-* powerpc64le*-*-linux* riscv*-*-* s390*-*-* sparc*-*-linux* } } } }
+// { dg-options "" }
+// { dg-additional-options "-mlong-double-128" { target s390*-*-* sparc*-*-linux* } }
+// { dg-additional-options "-mvsx -mfloat128 -mlong-double-128 -mabi=ieeelongdouble -Wno-psabi" { target powerpc64le*-*-linux* } }
+
+#include "ext-floating.h"
+
+#if !defined(__STDCPP_FLOAT32_T__) \
+ || !defined(__STDCPP_FLOAT64_T__) || !defined(__STDCPP_FLOAT128_T__) \
+ || __FLT_MAX_EXP__ != __FLT32_MAX_EXP__ || __FLT_MANT_DIG__ != __FLT32_MANT_DIG__ \
+ || __DBL_MAX_EXP__ != __FLT64_MAX_EXP__ || __DBL_MANT_DIG__ != __FLT64_MANT_DIG__ \
+ || __LDBL_MAX_EXP__ != __FLT128_MAX_EXP__ || __LDBL_MANT_DIG__ != __FLT128_MANT_DIG__
+#error Unexpected set of floating point types
+#endif
+
+using namespace std;
+
+#ifdef __STDCPP_FLOAT16_T__
+float16_t f16i = 1.0f; // { dg-warning "converting to 'std::float16_t' \\\{aka '_Float16'\\\} from 'float' with greater conversion rank" "" { target float16 } }
+float16_t f16k = 1.0; // { dg-warning "converting to 'std::float16_t' \\\{aka '_Float16'\\\} from 'double' with greater conversion rank" "" { target float16 } }
+float16_t f16m = 1.0L; // { dg-warning "converting to 'std::float16_t' \\\{aka '_Float16'\\\} from 'long double' with greater conversion rank" "" { target float16 } }
+#endif
+float32_t f32i = 1.0f;
+float32_t f32k = 1.0; // { dg-warning "converting to 'std::float32_t' \\\{aka '_Float32'\\\} from 'double' with greater conversion rank" }
+float32_t f32m = 1.0L; // { dg-warning "converting to 'std::float32_t' \\\{aka '_Float32'\\\} from 'long double' with greater conversion rank" }
+float64_t f64i = 1.0f;
+float64_t f64k = 1.0;
+float64_t f64m = 1.0L; // { dg-warning "converting to 'std::float64_t' \\\{aka '_Float64'\\\} from 'long double' with greater conversion rank" }
+float128_t f128i = 1.0f;
+float128_t f128k = 1.0;
+float128_t f128m = 1.0L;
+
+#ifdef __STDCPP_FLOAT16_T__
+constexpr float16_t f16x = 1.0F16;
+#endif
+constexpr float32_t f32x = 2.0F32;
+constexpr float64_t f64x = 3.0F64;
+constexpr float128_t f128x = 4.0F128;
+constexpr float fx = 5.0f;
+constexpr double dx = 6.0;
+constexpr long double ldx = 7.0L;
+
+constexpr int foo (float32_t) { return 1; }
+constexpr int foo (float64_t) { return 2; }
+constexpr int bar (float) { return 3; }
+constexpr int bar (double) { return 4; }
+constexpr int bar (long double) { return 5; }
+constexpr int baz (float32_t) { return 6; }
+constexpr int baz (float64_t) { return 7; }
+constexpr int baz (float128_t) { return 8; }
+constexpr int qux (float64_t) { return 9; }
+constexpr int qux (float32_t) { return 10; }
+constexpr int fred (long double) { return 11; }
+constexpr int fred (double) { return 12; }
+constexpr int fred (float) { return 13; }
+constexpr int thud (float128_t) { return 14; }
+constexpr int thud (float64_t) { return 15; }
+constexpr int thud (float32_t) { return 16; }
+struct S {
+ constexpr operator float32_t () const { return 1.0f32; }
+ constexpr operator float64_t () const { return 2.0f64; }
+};
+struct T {
+ constexpr operator float64_t () const { return 3.0f64; }
+ constexpr operator float32_t () const { return 4.0f32; }
+};
+
+void
+test (S s, T t)
+{
+#ifdef __STDCPP_FLOAT16_T__
+ foo (float16_t (1.0)); // { dg-error "call of overloaded 'foo\\\(std::float16_t\\\)' is ambiguous" "" { target float16 } }
+#endif
+ static_assert (foo (float (2.0)) == 1);
+ static_assert (foo (double (3.0)) == 2);
+ constexpr double x (s);
+ static_assert (x == 2.0);
+#ifdef __STDCPP_FLOAT16_T__
+ bar (f16x); // { dg-error "call of overloaded 'bar\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+ static_assert (bar (f32x) == 3);
+ static_assert (bar (f64x) == 4);
+ static_assert (bar (f128x) == 5);
+ static_assert (bar (fx) == 3);
+ static_assert (bar (dx) == 4);
+ static_assert (bar (ldx) == 5);
+#ifdef __STDCPP_FLOAT16_T__
+ baz (f16x); // { dg-error "call of overloaded 'baz\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+ static_assert (baz (f32x) == 6);
+ static_assert (baz (f64x) == 7);
+ static_assert (baz (f128x) == 8);
+ static_assert (baz (fx) == 6);
+ static_assert (baz (dx) == 7);
+ static_assert (baz (ldx) == 8);
+#ifdef __STDCPP_FLOAT16_T__
+ qux (float16_t (1.0)); // { dg-error "call of overloaded 'qux\\\(std::float16_t\\\)' is ambiguous" "" { target float16 } }
+#endif
+ static_assert (qux (float (2.0)) == 10);
+ static_assert (qux (double (3.0)) == 9);
+ constexpr double y (t);
+ static_assert (y == 3.0);
+#ifdef __STDCPP_FLOAT16_T__
+ fred (f16x); // { dg-error "call of overloaded 'fred\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+ static_assert (fred (f32x) == 13);
+ static_assert (fred (f64x) == 12);
+ static_assert (fred (f128x) == 11);
+ static_assert (fred (fx) == 13);
+ static_assert (fred (dx) == 12);
+ static_assert (fred (ldx) == 11);
+#ifdef __STDCPP_FLOAT16_T__
+ thud (f16x); // { dg-error "call of overloaded 'thud\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+ static_assert (thud (f32x) == 16);
+ static_assert (thud (f64x) == 15);
+ static_assert (thud (f128x) == 14);
+ static_assert (thud (fx) == 16);
+ static_assert (thud (dx) == 15);
+ static_assert (thud (ldx) == 14);
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/ext-floating5.C b/gcc/testsuite/g++.dg/cpp23/ext-floating5.C
new file mode 100644
index 0000000..7c8bf6a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/ext-floating5.C
@@ -0,0 +1,13 @@
+// P1467R9 - Extended floating-point types and standard names.
+// IBM extended long double and _Float128 should have unordered conversion
+// ranks as IBM extended long double has variable precision from 53 bits
+// for denormals to more than 2150 bits for certain numbers.
+// { dg-do compile { target { c++23 && { powerpc*-*-linux* } } } }
+// { dg-require-effective-target ppc_float128_sw }
+// { dg-options "-mvsx -mfloat128 -mlong-double-128 -mabi=ibmlongdouble" }
+
+auto a = 1.0F128 + 1.0L; // { dg-error "invalid operands to binary \\\+ \\\(have '_Float128' and 'long double'\\\)" }
+auto b = 1.0L + 1.0F128; // { dg-error "invalid operands to binary \\\+ \\\(have 'long double' and '_Float128'\\\)" }
+bool c;
+auto d = c ? 1.0F128 : 1.0L; // { dg-error "operands to '\\\?:' of types '_Float128' and 'long double' have unordered conversion rank" }
+auto e = c ? 1.0L : 1.0F128; // { dg-error "operands to '\\\?:' of types 'long double' and '_Float128' have unordered conversion rank" }
diff --git a/gcc/testsuite/g++.dg/cpp23/ext-floating6.C b/gcc/testsuite/g++.dg/cpp23/ext-floating6.C
new file mode 100644
index 0000000..70272a1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/ext-floating6.C
@@ -0,0 +1,30 @@
+// P1467R9 - Extended floating-point types and standard names.
+// { dg-do compile { target c++23 } }
+// { dg-options "" }
+
+#include "ext-floating.h"
+
+#ifdef __STRICT_ANSI__
+#undef __SIZEOF_FLOAT128__
+#endif
+
+using namespace std;
+
+float foo (float x, float y, float z) { return x * y + z; }
+double foo (double x, double y, double z) { return x * y + z; }
+long double foo (long double x, long double y, long double z) { return x * y + z; }
+#ifdef __STDCPP_FLOAT16_T__
+float16_t foo (float16_t x, float16_t y, float16_t z) { return x * y + z; }
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+float32_t foo (float32_t x, float32_t y, float32_t z) { return x * y + z; }
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+float64_t foo (float64_t x, float64_t y, float64_t z) { return x * y + z; }
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+float128_t foo (float128_t x, float128_t y, float128_t z) { return x * y + z; }
+#endif
+#ifdef __STDCPP_BFLOAT16_T__
+bfloat16_t foo (bfloat16_t x, bfloat16_t y, bfloat16_t z) { return x * y + z; }
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp23/ext-floating7.C b/gcc/testsuite/g++.dg/cpp23/ext-floating7.C
new file mode 100644
index 0000000..5c30a59
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/ext-floating7.C
@@ -0,0 +1,119 @@
+// P1467R9 - Extended floating-point types and standard names.
+// { dg-do run { target { c++23 && float16_runtime } } }
+// { dg-options "" }
+// { dg-add-options float16 }
+
+#ifndef WIDTH
+#ifndef __STDCPP_FLOAT16_T__
+#error Unexpected
+#endif
+#define WIDTH 16
+#endif
+
+#include <stdarg.h>
+#include "ext-floating.h"
+
+#define CONCATX(X, Y) X ## Y
+#define CONCAT(X, Y) CONCATX (X, Y)
+#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z)
+#define TYPE CONCAT (_Float, WIDTH)
+#define CST(C) CONCAT3 (C, f, WIDTH)
+#define CSTU(C) CONCAT3 (C, F, WIDTH)
+
+extern "C" void abort ();
+
+volatile TYPE a = CST (1.0), b = CSTU (2.5), c = -CST (2.5);
+volatile TYPE a2 = CST (1.0), z = CST (0.0), nz = -CST (0.0);
+
+// These types are not subject to default argument promotions.
+
+TYPE
+vafn (TYPE arg1, ...)
+{
+ va_list ap;
+ TYPE ret;
+ va_start (ap, arg1);
+ ret = arg1 + va_arg (ap, TYPE);
+ va_end (ap);
+ return ret;
+}
+
+TYPE
+fn (TYPE arg)
+{
+ return arg / 4;
+}
+
+int
+main (void)
+{
+ volatile TYPE r;
+ r = -b;
+ if (r != c)
+ abort ();
+ r = a + b;
+ if (r != CST (3.5))
+ abort ();
+ r = a - b;
+ if (r != -CST (1.5))
+ abort ();
+ r = 2 * c;
+ if (r != -5)
+ abort ();
+ r = b * c;
+ if (r != -CST (6.25))
+ abort ();
+ r = b / (a + a);
+ if (r != CST (1.25))
+ abort ();
+ r = c * 3;
+ if (r != -CST (7.5))
+ abort ();
+ volatile int i = r;
+ if (i != -7)
+ abort ();
+ r = vafn (a, c);
+ if (r != -CST (1.5))
+ abort ();
+ r = fn (a);
+ if (r != CST (0.25))
+ abort ();
+ if ((a < b) != 1)
+ abort ();
+ if ((b < a) != 0)
+ abort ();
+ if ((a < a2) != 0)
+ abort ();
+ if ((nz < z) != 0)
+ abort ();
+ if ((a <= b) != 1)
+ abort ();
+ if ((b <= a) != 0)
+ abort ();
+ if ((a <= a2) != 1)
+ abort ();
+ if ((nz <= z) != 1)
+ abort ();
+ if ((a > b) != 0)
+ abort ();
+ if ((b > a) != 1)
+ abort ();
+ if ((a > a2) != 0)
+ abort ();
+ if ((nz > z) != 0)
+ abort ();
+ if ((a >= b) != 0)
+ abort ();
+ if ((b >= a) != 1)
+ abort ();
+ if ((a >= a2) != 1)
+ abort ();
+ if ((nz >= z) != 1)
+ abort ();
+ i = (nz == z);
+ if (i != 1)
+ abort ();
+ i = (a == b);
+ if (i != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/ext-floating8.C b/gcc/testsuite/g++.dg/cpp23/ext-floating8.C
new file mode 100644
index 0000000..afb74a3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/ext-floating8.C
@@ -0,0 +1,13 @@
+// P1467R9 - Extended floating-point types and standard names.
+// { dg-do run { target { c++23 && float32_runtime } } }
+// { dg-options "" }
+// { dg-add-options float32 }
+
+#ifndef WIDTH
+#ifndef __STDCPP_FLOAT32_T__
+#error Unexpected
+#endif
+#define WIDTH 32
+#endif
+
+#include "ext-floating7.C"
diff --git a/gcc/testsuite/g++.dg/cpp23/ext-floating9.C b/gcc/testsuite/g++.dg/cpp23/ext-floating9.C
new file mode 100644
index 0000000..f0118da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/ext-floating9.C
@@ -0,0 +1,13 @@
+// P1467R9 - Extended floating-point types and standard names.
+// { dg-do run { target { c++23 && float64_runtime } } }
+// { dg-options "" }
+// { dg-add-options float64 }
+
+#ifndef WIDTH
+#ifndef __STDCPP_FLOAT64_T__
+#error Unexpected
+#endif
+#define WIDTH 64
+#endif
+
+#include "ext-floating7.C"
diff --git a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
index 0537e1d..b52cf37 100644
--- a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
+++ b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
@@ -563,3 +563,15 @@
#elif __cpp_named_character_escapes != 202207
# error "__cpp_named_character_escapes != 202207"
#endif
+
+#ifndef __cpp_static_call_operator
+# error "__cpp_static_call_operator"
+#elif __cpp_static_call_operator != 202207
+# error "__cpp_static_call_operator != 202207"
+#endif
+
+#ifndef __cpp_implicit_move
+# error "__cpp_implicit_move"
+#elif __cpp_implicit_move != 202207
+# error "__cpp_implicit_move != 202207"
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp23/static-operator-call1.C b/gcc/testsuite/g++.dg/cpp23/static-operator-call1.C
new file mode 100644
index 0000000..42219bf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/static-operator-call1.C
@@ -0,0 +1,41 @@
+// P1169R4 - static operator()
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+template <typename T>
+struct S
+{
+ static constexpr bool operator () (T const &x, T const &y) { return x < y; }; // { dg-warning "may be a static member function only with" "" { target c++20_down } }
+ using P = bool (*) (T const &, T const &);
+ operator P () const { return operator (); }
+};
+
+static_assert (S<int> {} (1, 2), "");
+
+template <typename T>
+void
+bar (T &x)
+{
+ x (1, 2);
+}
+
+void
+foo ()
+{
+#if __cpp_constexpr >= 201603L
+ auto a = [](int x, int y) static constexpr { return x + y; }; // { dg-warning "'static' only valid in lambda with" "" { target { c++17 && c++20_down } } }
+ static_assert (a (1, 2) == 3, "");
+ bar (*a);
+#endif
+ auto b = []() static { return 1; }; // { dg-warning "'static' only valid in lambda with" "" { target c++20_down } }
+ b ();
+ auto c = [](int x, int y) static { return x + y; }; // { dg-warning "'static' only valid in lambda with" "" { target c++20_down } }
+ c (1, 2);
+ bar (*c);
+#if __cpp_generic_lambdas >= 201707L
+ auto d = []<typename T, typename U>(T x, U y) static { return x + y; }; // { dg-warning "'static' only valid in lambda with" "" { target c++20_only } }
+ d (1, 2L);
+#endif
+ S<long> s;
+ s(1L, 2L);
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/static-operator-call2.C b/gcc/testsuite/g++.dg/cpp23/static-operator-call2.C
new file mode 100644
index 0000000..21f3d44
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/static-operator-call2.C
@@ -0,0 +1,22 @@
+// P1169R4 - static operator()
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+void
+foo ()
+{
+ int u = 0;
+ auto a = [](int x, int y) mutable mutable { return x + y; }; // { dg-error "duplicate 'mutable' specifier" }
+ auto b = [](int x, int y) static static { return x + y; }; // { dg-error "duplicate 'static' specifier" }
+ // { dg-warning "'static' only valid in lambda with" "" { target c++20_down } .-1 }
+ auto c = [](int x, int y) static mutable { return x + y; }; // { dg-error "'mutable' specifier conflicts with 'static'" }
+ // { dg-warning "'static' only valid in lambda with" "" { target c++20_down } .-1 }
+ auto d = [](int x, int y) mutable static { return x + y; }; // { dg-error "'static' specifier conflicts with 'mutable'" }
+ // { dg-warning "'static' only valid in lambda with" "" { target c++20_down } .-1 }
+ auto e = [=](int x, int y) static { return x + y; }; // { dg-error "lambda specifier with lambda capture" }
+ // { dg-warning "'static' only valid in lambda with" "" { target c++20_down } .-1 }
+ auto f = [&](int x, int y) static { return x + y; }; // { dg-error "lambda specifier with lambda capture" }
+ // { dg-warning "'static' only valid in lambda with" "" { target c++20_down } .-1 }
+ auto g = [u](int x, int y) static { return x + y; }; // { dg-error "lambda specifier with lambda capture" }
+ // { dg-warning "'static' only valid in lambda with" "" { target c++20_down } .-1 }
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/static-operator-call3.C b/gcc/testsuite/g++.dg/cpp23/static-operator-call3.C
new file mode 100644
index 0000000..9c84db6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/static-operator-call3.C
@@ -0,0 +1,10 @@
+// P1169R4 - static operator()
+// { dg-do compile { target c++14 } }
+// { dg-options "" }
+
+void
+foo ()
+{
+ auto a = [] (auto x) static { return x; }; // { dg-warning "'static' only valid in lambda with" "" { target c++20_down } }
+ int (*b) (int) = a;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-traits3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-traits3.C
index f20608b6..3e87da4 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-traits3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-traits3.C
@@ -21,7 +21,7 @@ concept TriviallyAssignable = __is_trivially_assignable(T, U);
template<class T, class U>
concept NothrowAssignable = __is_nothrow_assignable(T, U);
-// { dg-message "'S' is not 'nothrow' assignable from 'int'" "" { target *-*-* } .-1 }
+// { dg-message "'S' is not nothrow assignable from 'int'" "" { target *-*-* } .-1 }
template<class T, class... Args>
concept Constructible = __is_constructible(T, Args...);
@@ -37,9 +37,9 @@ concept TriviallyConstructible = __is_trivially_constructible(T, Args...);
template<class T, class... Args>
concept NothrowConstructible = __is_nothrow_constructible(T, Args...);
-// { dg-message "'S' is not 'nothrow' default constructible" "" { target *-*-* } .-1 }
-// { dg-message "'S' is not 'nothrow' constructible from 'int'" "" { target *-*-* } .-2 }
-// { dg-message "'S' is not 'nothrow' constructible from 'int, char'" "" { target *-*-* } .-3 }
+// { dg-message "'S' is not nothrow default constructible" "" { target *-*-* } .-1 }
+// { dg-message "'S' is not nothrow constructible from 'int'" "" { target *-*-* } .-2 }
+// { dg-message "'S' is not nothrow constructible from 'int, char'" "" { target *-*-* } .-3 }
template<class T>
concept UniqueObjReps = __has_unique_object_representations(T);
diff --git a/gcc/testsuite/g++.dg/cpp2a/constinit3.C b/gcc/testsuite/g++.dg/cpp2a/constinit3.C
index a29c594..ffa6184 100644
--- a/gcc/testsuite/g++.dg/cpp2a/constinit3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/constinit3.C
@@ -5,7 +5,7 @@ constinit constinit int v1; // { dg-error "duplicate .constinit." }
constexpr constinit int v2 = 1; // { dg-error "can use at most one of the .constinit. and .constexpr. specifiers" }
constinit constexpr int v3 = 1; // { dg-error "an use at most one of the .constinit. and .constexpr. specifiers" }
-extern static constinit int v4; // { dg-error "conflicting specifiers" }
+extern static constinit int v4; // { dg-error "'static' specifier conflicts with 'extern'" }
extern thread_local constinit int v5;
extern constinit int v6;
diff --git a/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C b/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C
index 1a8ac02..89e2ebd 100644
--- a/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C
+++ b/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C
@@ -1 +1 @@
-static typedef int i __attribute__((unused)); // { dg-error "1:conflicting specifiers" }
+static typedef int i __attribute__((unused)); // { dg-error "8:'typedef' specifier conflicts with 'static'" }
diff --git a/gcc/testsuite/g++.dg/ext/is_convertible4.C b/gcc/testsuite/g++.dg/ext/is_convertible4.C
new file mode 100644
index 0000000..8a7724c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_convertible4.C
@@ -0,0 +1,33 @@
+// PR c++/107049
+// { dg-do compile { target c++11 } }
+// Failed access check should be a substitution failure, not an error.
+
+template<bool B>
+struct bool_constant { static constexpr bool value = B; };
+
+template<typename From, typename To>
+struct is_convertible
+: public bool_constant<__is_convertible(From, To)>
+{ };
+
+#if __cpp_variable_templates
+template<typename From, typename To>
+constexpr bool is_convertible_v = __is_convertible(From, To);
+#endif
+
+class Private
+{
+ operator int() const
+ {
+ static_assert( not is_convertible<Private, int>::value, "" );
+#if __cpp_variable_templates
+ static_assert( not is_convertible_v<Private, int>, "" );
+#endif
+ return 0;
+ }
+};
+
+static_assert( not is_convertible<Private, int>::value, "" );
+#if __cpp_variable_templates
+static_assert( not is_convertible_v<Private, int>, "" );
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_nothrow_convertible4.C b/gcc/testsuite/g++.dg/ext/is_nothrow_convertible4.C
new file mode 100644
index 0000000..f81b594
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_nothrow_convertible4.C
@@ -0,0 +1,33 @@
+// PR c++/107049
+// { dg-do compile { target c++11 } }
+// Failed access check should be a substitution failure, not an error.
+
+template<bool B>
+struct bool_constant { static constexpr bool value = B; };
+
+template<typename From, typename To>
+struct is_nt_convertible
+: public bool_constant<__is_nothrow_convertible(From, To)>
+{ };
+
+#if __cpp_variable_templates
+template<typename From, typename To>
+constexpr bool is_nt_convertible_v = __is_nothrow_convertible(From, To);
+#endif
+
+class Private
+{
+ operator int() const
+ {
+ static_assert( not is_nt_convertible<Private, int>::value, "" );
+#if __cpp_variable_templates
+ static_assert( not is_nt_convertible_v<Private, int>, "" );
+#endif
+ return 0;
+ }
+};
+
+static_assert( not is_nt_convertible<Private, int>::value, "" );
+#if __cpp_variable_templates
+static_assert( not is_nt_convertible_v<Private, int>, "" );
+#endif
diff --git a/gcc/testsuite/g++.dg/fstack-protector-strong.C b/gcc/testsuite/g++.dg/fstack-protector-strong.C
index ae6d2fd..034af2c 100644
--- a/gcc/testsuite/g++.dg/fstack-protector-strong.C
+++ b/gcc/testsuite/g++.dg/fstack-protector-strong.C
@@ -85,4 +85,4 @@ int foo7 (B *p)
return p->return_slot ().a1;
}
-/* { dg-final { scan-assembler-times "stack_chk_fail" 7 } } */
+/* { dg-final { scan-assembler-times "stack_chk_fail" 8 } } */
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-1.C b/gcc/testsuite/g++.dg/gomp/attrs-1.C
index 3f366ae..dd33b07 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-1.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-1.C
@@ -123,7 +123,7 @@ baz (int d, int m, int i1, int i2, int p, int *idp, int s,
void
bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int hda, int s,
int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm,
- const char *msg)
+ const char *msg, int n1, int n2)
{
[[omp::directive (nothing)]];
[[omp::directive (error at (execution) severity (warning) message (msg))]];
@@ -612,6 +612,19 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int hda, int s,
;
[[omp::directive (parallel)]]
switch (0) { case 1: break; default: break; }
+ [[omp::directive (assume no_openmp no_openmp_routines no_parallelism
+ absent (atomic, barrier, cancel, cancellation point)
+ absent (critical, depobj)
+ absent (distribute, flush, loop, masked, master, nothing, ordered)
+ absent (parallel, scan, scope, section, sections, simd, single, task)
+ absent (taskgroup, taskloop, taskwait, taskyield)
+ absent (target, teams, for, error) holds (n1 < n2))]]
+ if (0)
+ ;
+ [[omp::sequence (omp::directive (assume contains (simd)),
+ omp::directive (for simd))]]
+ for (int i = 0; i < 64; i++)
+ ;
}
void corge1 ();
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-15.C b/gcc/testsuite/g++.dg/gomp/attrs-15.C
new file mode 100644
index 0000000..d0598f4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/attrs-15.C
@@ -0,0 +1,41 @@
+// { dg-do compile { target c++11 } }
+
+#pragma omp begin assumes absent (target)
+#pragma omp begin assumes absent (target)
+[[omp::directive (begin assumes absent (target))]];
+int a;
+[[omp::directive (end assumes)]];
+#pragma omp end assumes
+#pragma omp end assumes
+[[omp::directive (begin assumes absent (target))]];
+int b;
+#pragma omp end assumes // { dg-error "'begin assumes' in attribute syntax terminated with 'end assumes' in pragma syntax" }
+#pragma omp begin assumes absent (target)
+int c;
+[[omp::directive (end assumes)]];// { dg-error "'begin assumes' in pragma syntax terminated with 'end assumes' in attribute syntax" }
+#pragma omp begin assumes absent (target)
+[[omp::directive (begin assumes absent (target))]];
+int d;
+#pragma omp end assumes // { dg-error "'begin assumes' in attribute syntax terminated with 'end assumes' in pragma syntax" }
+#pragma omp begin assumes absent (target)
+int e;
+[[omp::directive (end assumes)]];// { dg-error "'begin assumes' in pragma syntax terminated with 'end assumes' in attribute syntax" }
+#pragma omp end assumes
+[[omp::directive (begin assumes absent (target))]];
+[[omp::directive (begin assumes absent (target))]];
+int f;
+#pragma omp end assumes // { dg-error "'begin assumes' in attribute syntax terminated with 'end assumes' in pragma syntax" }
+#pragma omp begin assumes absent (target)
+int g;
+[[omp::directive (end assumes)]];// { dg-error "'begin assumes' in pragma syntax terminated with 'end assumes' in attribute syntax" }
+[[omp::directive (end assumes)]];
+[[omp::directive (begin assumes absent (target))]];
+#pragma omp begin assumes absent (target)
+int h;
+#pragma omp end assumes
+#pragma omp end assumes // { dg-error "'begin assumes' in attribute syntax terminated with 'end assumes' in pragma syntax" }
+#pragma omp begin assumes absent (target)
+[[omp::directive (begin assumes absent (target))]];
+int i;
+[[omp::directive (end assumes)]];
+[[omp::directive (end assumes)]];// { dg-error "'begin assumes' in pragma syntax terminated with 'end assumes' in attribute syntax" }
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-16.C b/gcc/testsuite/g++.dg/gomp/attrs-16.C
new file mode 100644
index 0000000..5c1dcc5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/attrs-16.C
@@ -0,0 +1,26 @@
+// { dg-do compile { target c++11 } }
+
+int i;
+
+[[omp::directive (assumes no_openmp, absent (target, teams) holds (i < 32U) holds (i < 32U))]];
+void
+bar (void)
+{
+}
+
+[[omp::directive (assumes no_openmp_routines)]];
+[[omp::directive (assumes no_parallelism)]];
+[[omp::directive (assumes absent (for))]];
+void
+fred (void)
+{
+}
+
+[[omp::directive (assumes absent (atomic, barrier, cancel, cancellation point) absent (critical, depobj)
+ absent (distribute, flush, loop, masked, master, nothing, ordered)
+ absent (parallel, scan, scope, section, sections, simd, single, task)
+ absent (taskgroup, taskloop, taskwait, taskyield))]];
+void
+foo (void)
+{
+}
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-17.C b/gcc/testsuite/g++.dg/gomp/attrs-17.C
new file mode 100644
index 0000000..fe36146
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/attrs-17.C
@@ -0,0 +1,17 @@
+// { dg-do compile { target c++11 } }
+
+[[omp::directive (assumes contains (simd))]];
+[[omp::directive (assumes contains (error))]];
+[[omp::directive (assumes, contains (simd))]];
+
+void
+foo (int i, int *a)
+{
+ [[omp::directive (simd)]]
+ for (int j = 0; j < i; j++)
+ a[j] = j;
+ if (i >= 32)
+ {
+ [[omp::directive (error at (execution) message ("Should not happen"))]];
+ }
+}
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-2.C b/gcc/testsuite/g++.dg/gomp/attrs-2.C
index cb80415..7258d38 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-2.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-2.C
@@ -123,7 +123,7 @@ baz (int d, int m, int i1, int i2, int p, int *idp, int s,
void
bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int hda, int s,
int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm,
- const char *msg)
+ const char *msg, int n1, int n2)
{
[[omp::directive (nothing)]];
[[omp::directive (error, at (execution), severity (warning), message (msg))]];
@@ -604,6 +604,19 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int hda, int s,
extern int t2;
[[omp::directive (declare reduction (dr: int: omp_out += omp_in),initializer (omp_priv = 0))]]
;
+ [[omp::directive (assume, no_openmp, no_openmp_routines, no_parallelism,
+ absent (atomic, barrier, cancel, cancellation point),
+ absent (critical, depobj),
+ absent (distribute, flush, loop, masked, master, nothing, ordered),
+ absent (parallel, scan, scope, section, sections, simd, single, task),
+ absent (taskgroup, taskloop, taskwait, taskyield),
+ absent (target, teams, for, error), holds (n1 < n2))]]
+ if (0)
+ ;
+ [[omp::sequence (omp::directive (assume, contains (simd)),
+ omp::directive (for simd))]]
+ for (int i = 0; i < 64; i++)
+ ;
}
void corge1 ();
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-9.C b/gcc/testsuite/g++.dg/gomp/attrs-9.C
index 19a3b0a..fa02299 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-9.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-9.C
@@ -1,5 +1,6 @@
// { dg-do compile { target c++11 } }
+int n1 = 0, n2 = 42;
[[omp::sequence (directive (requires, atomic_default_mem_order (seq_cst)))]];
[[omp::directive (declare reduction (plus: int: omp_out += omp_in) initializer (omp_priv = 0))]];
int a;
@@ -14,3 +15,22 @@ int d;
[[omp::directive (end declare target)]];
[[omp::directive (end declare target)]];
[[omp::directive (nothing)]];
+[[omp::directive (begin assumes no_openmp no_openmp_routines no_parallelism
+ absent (atomic, barrier, cancel, cancellation point)
+ absent (critical, depobj)
+ absent (distribute, flush, loop, masked, master, nothing, ordered)
+ absent (parallel, scan, scope, section, sections, simd, single, task)
+ absent (taskgroup, taskloop, taskwait, taskyield)
+ absent (target, teams, for, error) holds (n1 < n2))]];
+void foo (void) {}
+[[omp::directive (end assumes)]];
+[[omp::directive (begin assumes, no_openmp, no_openmp_routines, no_parallelism,
+ absent (atomic, barrier, cancel, cancellation point),
+ absent (critical, depobj),
+ absent (distribute, flush, loop, masked, master, nothing, ordered),
+ absent (parallel, scan, scope, section, sections, simd, single, task),
+ absent (taskgroup, taskloop, taskwait, taskyield),
+ absent (target, teams, for, error), holds (n1 < n2))]];
+[[omp::directive (begin assumes no_openmp)]];
+void bar (void) {}
+[[omp::sequence (omp::directive (end assumes), omp::directive (end assumes))]];
diff --git a/gcc/testsuite/g++.dg/gomp/pr56217.C b/gcc/testsuite/g++.dg/gomp/pr56217.C
index 03dfc5f..731c0c0 100644
--- a/gcc/testsuite/g++.dg/gomp/pr56217.C
+++ b/gcc/testsuite/g++.dg/gomp/pr56217.C
@@ -1,5 +1,5 @@
// PR middle-end/56217
-// { dg-do compile }
+// { dg-do compile { target c++20_down } }
// { dg-options "-fopenmp" }
struct S { int *p; S (); S (S &); };
@@ -10,5 +10,7 @@ foo ()
S s;
#pragma omp task shared (s)
s.p = 0;
+ // This fails in C++23, because "cannot bind non-const lvalue reference of
+ // type 'S&' to an rvalue of type 'S'".
return s;
}
diff --git a/gcc/testsuite/g++.dg/other/mult-stor1.C b/gcc/testsuite/g++.dg/other/mult-stor1.C
index 1eaec4f1..e582b03 100644
--- a/gcc/testsuite/g++.dg/other/mult-stor1.C
+++ b/gcc/testsuite/g++.dg/other/mult-stor1.C
@@ -4,5 +4,5 @@
struct A
{
- extern static int i; // { dg-error "conflicting specifiers" }
+ extern static int i; // { dg-error "'static' specifier conflicts with 'extern'" }
};
diff --git a/gcc/testsuite/g++.dg/parse/crash39.C b/gcc/testsuite/g++.dg/parse/crash39.C
index 2f39c10..5d4e02d 100644
--- a/gcc/testsuite/g++.dg/parse/crash39.C
+++ b/gcc/testsuite/g++.dg/parse/crash39.C
@@ -1,3 +1,3 @@
// PR c++/31747
-static extern int i; // { dg-error "conflicting specifiers" }
+static extern int i; // { dg-error "'extern' specifier conflicts with 'static'" }
diff --git a/gcc/testsuite/g++.dg/parse/typedef8.C b/gcc/testsuite/g++.dg/parse/typedef8.C
index 60b8f39..e21bdb9 100644
--- a/gcc/testsuite/g++.dg/parse/typedef8.C
+++ b/gcc/testsuite/g++.dg/parse/typedef8.C
@@ -1,11 +1,11 @@
//PR c++ 29024
-typedef static int a; // { dg-error "conflicting" }
-typedef register int b; // { dg-error "conflicting" }
-typedef extern int c; // { dg-error "conflicting" }
-static typedef int a; // { dg-error "conflicting" }
+typedef static int a; // { dg-error "'static' specifier conflicts with 'typedef'" }
+typedef register int b; // { dg-error "'register' specifier conflicts with 'typedef'" }
+typedef extern int c; // { dg-error "'extern' specifier conflicts with 'typedef'" }
+static typedef int a; // { dg-error "'typedef' specifier conflicts with 'static'" }
void foo()
{
- typedef auto int bar; // { dg-error "conflicting|two or more data types" }
+ typedef auto int bar; // { dg-error "'auto' specifier conflicts with 'typedef'|two or more data types" }
}
diff --git a/gcc/testsuite/g++.dg/pr58245-1.C b/gcc/testsuite/g++.dg/pr58245-1.C
new file mode 100644
index 0000000..1439bc6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr58245-1.C
@@ -0,0 +1,10 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* rs6000-*-* s390x-*-* } } */
+/* { dg-options "-O2 -fstack-protector-all" } */
+
+void
+bar (void)
+{
+ throw 1;
+}
+
+/* { dg-final { scan-assembler-times "stack_chk_fail" 1 } } */
diff --git a/gcc/testsuite/g++.dg/template/error30.C b/gcc/testsuite/g++.dg/template/error30.C
index 3a87872..5a3047c 100644
--- a/gcc/testsuite/g++.dg/template/error30.C
+++ b/gcc/testsuite/g++.dg/template/error30.C
@@ -2,4 +2,4 @@
template<int> struct A;
-template<template<typename> class B> A<B<int>::x> operator() (); // { dg-error "51:.A<B<int>::x> operator\\(\\)\\(\\). must be a non-static member function" }
+template<template<typename> class B> A<B<int>::x> operator() (); // { dg-error "51:.A<B<int>::x> operator\\(\\)\\(\\). must be a member function" }
diff --git a/gcc/testsuite/g++.dg/torture/pr107029.C b/gcc/testsuite/g++.dg/torture/pr107029.C
new file mode 100644
index 0000000..93c7f28
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr107029.C
@@ -0,0 +1,19 @@
+// PR tree-optimization/107029
+// { dg-do compile }
+
+struct S { long long a; int b; };
+long long S::*a;
+int S::*b;
+struct A { void foo (bool, bool); void bar (); int c; };
+
+void
+A::foo (bool a, bool b)
+{
+ c = a || b;
+}
+
+void
+A::bar()
+{
+ foo (a, b);
+}
diff --git a/gcc/testsuite/g++.dg/uninit-pr105646.C b/gcc/testsuite/g++.dg/uninit-pr105646.C
new file mode 100644
index 0000000..48ceb98
--- /dev/null
+++ b/gcc/testsuite/g++.dg/uninit-pr105646.C
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-require-effective-target c++11 }
+// { dg-options "-O2 -Wuninitialized" }
+
+int f1();
+int f2(){
+ bool v2{v2}; // { dg-warning "is used uninitialized" }
+ auto const & a = f1();
+ return a;
+}
+int f3(){
+ auto const & a = f1();
+ // Diagnose the following when optimizing and as unconditional
+ // uninitialized use despite f1 possibly throwing
+ bool v3{v3}; // { dg-warning "is used uninitialized" }
+ return a;
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wno-return-local-addr.C b/gcc/testsuite/g++.dg/warn/Wno-return-local-addr.C
index e15bfa2..cc9bb59 100644
--- a/gcc/testsuite/g++.dg/warn/Wno-return-local-addr.C
+++ b/gcc/testsuite/g++.dg/warn/Wno-return-local-addr.C
@@ -4,7 +4,7 @@
int& bad1()
{
int x = 0;
- return x;
+ return x; // { dg-error "cannot bind non-const lvalue reference" "" { target c++23 } }
}
int* bad2()
diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr.C b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr.C
index 642a576..4c18c2f 100644
--- a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr.C
+++ b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr.C
@@ -5,7 +5,7 @@
int& bad1()
{
int x = 0;
- return x; // { dg-error "reference to local variable" }
+ return x; // { dg-error "reference to local variable|cannot bind non-const lvalue reference" }
}
int* bad2()
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash55.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash55.C
index fd4d4b6..b93e6e0 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/crash55.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash55.C
@@ -8,5 +8,6 @@
local = x+2;
- return local; // { dg-warning "reference to local" }
+ return local; // { dg-warning "reference to local" "" { target c++20_down } }
+// { dg-error "non-const lvalue" "" { target c++23 } .-1 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/operator.C b/gcc/testsuite/g++.old-deja/g++.jason/operator.C
index 79c1932..c187901 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/operator.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/operator.C
@@ -6,7 +6,7 @@ typedef __SIZE_TYPE__ size_t;
struct A {
int operator?:(int a, int b); // { dg-error "prohibits overloading" }
- static int operator()(int a); // { dg-error "14:.static int A::operator\\(\\)\\(int\\). must be a non-static member function" }
+ static int operator()(int a); // { dg-warning "14:.static int A::operator\\(\\)\\(int\\). may be a static member function only with" "" { target c++20_down } }
static int operator+(A,A); // { dg-error "14:.static int A::operator\\+\\(A, A\\). must be either a non-static member function or a non-member function" }
int operator+(int a, int b = 1); // { dg-error "7:.int A::operator\\+\\(int, int\\). must have either zero or one argument" }
int operator++(char); // { dg-error "7:postfix .int A::operator\\+\\+\\(char\\). must have .int. as its argument" }
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/temporary2.C b/gcc/testsuite/g++.old-deja/g++.jason/temporary2.C
index c855f8f..2709b50 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/temporary2.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/temporary2.C
@@ -8,7 +8,7 @@ public:
int i;
};
-X foo() { X x; return x; }
+X foo() { X x; return x; } // { dg-error "cannot bind non-const lvalue reference" "" { target c++23 } }
int main()
{
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p2846b.C b/gcc/testsuite/g++.old-deja/g++.mike/p2846b.C
index 57422fe..5bcf9e3 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p2846b.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p2846b.C
@@ -42,7 +42,7 @@ public:
B A::compute(void) const
{
B sub(*this, 1);
- return sub;
+ return static_cast<B&>(sub);
}
int main ()
diff --git a/gcc/testsuite/g++.target/i386/float16-1.C b/gcc/testsuite/g++.target/i386/float16-1.C
index 95d1ac2..f96b932 100644
--- a/gcc/testsuite/g++.target/i386/float16-1.C
+++ b/gcc/testsuite/g++.target/i386/float16-1.C
@@ -1,8 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mno-sse2" } */
-_Float16/* { dg-error "does not name a type" } */
+_Float16 /* { dg-error "expected unqualified-id before '_Float16'" } */
foo (_Float16 x)
{
return x;
-}
+} /* { dg-error "'_Float16' is not supported on this target" } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/cold_partition_label.c b/gcc/testsuite/gcc.dg/tree-prof/cold_partition_label.c
index 511b610..b85e6c1 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/cold_partition_label.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/cold_partition_label.c
@@ -43,6 +43,6 @@ main (int argc, char *argv[])
return 0;
}
-/* { dg-final-use { scan-assembler "foo\[._\]+cold" { target *-*-linux* *-*-gnu* } } } */
-/* { dg-final-use { scan-assembler "size\[ \ta-zA-Z0-0\]+foo\[._\]+cold" { target *-*-linux* *-*-gnu* } } } */
+/* { dg-final-use-not-autofdo { scan-assembler "foo\[._\]+cold" { target *-*-linux* *-*-gnu* } } } */
+/* { dg-final-use-not-autofdo { scan-assembler "size\[ \ta-zA-Z0-0\]+foo\[._\]+cold" { target *-*-linux* *-*-gnu* } } } */
/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c b/gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c
index 2087d0d..5376de1 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c
@@ -52,5 +52,5 @@ foo (int path)
}
}
-/* { dg-final-use { scan-assembler "\.section\[\t \]*\.text\.unlikely\[\\n\\r\]+\[\t \]*\.size\[\t \]*foo\.cold" { target *-*-linux* *-*-gnu* } } } */
-/* { dg-final-use { scan-assembler {.section[\t ]*__TEXT,__text_cold[^\n]*[\n\r]+_foo.cold:} { target *-*-darwin* } } } */
+/* { dg-final-use-not-autofdo { scan-assembler "\.section\[\t \]*\.text\.unlikely\[\\n\\r\]+\[\t \]*\.size\[\t \]*foo\.cold" { target *-*-linux* *-*-gnu* } } } */
+/* { dg-final-use-not-autofdo { scan-assembler {.section[\t ]*__TEXT,__text_cold[^\n]*[\n\r]+_foo.cold:} { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c b/gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c
index b02526b..90de2c0 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c
@@ -51,5 +51,5 @@ foo (int path)
}
}
-/* { dg-final-use { scan-assembler "\.section\[\t \]*\.text\.unlikely\[\\n\\r\]+\[\t \]*\.size\[\t \]*foo\.cold" { target *-*-linux* *-*-gnu* } } } */
-/* { dg-final-use { scan-assembler {.section[\t ]*__TEXT,__text_cold[^\n]*[\n\r]+_foo.cold:} { target *-*-darwin* } } } */
+/* { dg-final-use-not-autofdo { scan-assembler "\.section\[\t \]*\.text\.unlikely\[\\n\\r\]+\[\t \]*\.size\[\t \]*foo\.cold" { target *-*-linux* *-*-gnu* } } } */
+/* { dg-final-use-not-autofdo { scan-assembler {.section[\t ]*__TEXT,__text_cold[^\n]*[\n\r]+_foo.cold:} { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c b/gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c
index da06407..29a48f0 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c
@@ -52,5 +52,5 @@ foo (int path)
}
}
-/* { dg-final-use { scan-assembler "\.section\[\t \]*\.text\.unlikely\[\\n\\r\]+\[\t \]*\.size\[\t \]*foo\.cold" { target *-*-linux* *-*-gnu* } } } */
-/* { dg-final-use { scan-assembler {.section[\t ]*__TEXT,__text_cold[^\n]*[\n\r]+_foo.cold:} { target *-*-darwin* } } } */
+/* { dg-final-use-not-autofdo { scan-assembler "\.section\[\t \]*\.text\.unlikely\[\\n\\r\]+\[\t \]*\.size\[\t \]*foo\.cold" { target *-*-linux* *-*-gnu* } } } */
+/* { dg-final-use-not-autofdo { scan-assembler {.section[\t ]*__TEXT,__text_cold[^\n]*[\n\r]+_foo.cold:} { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/popcount6.c b/gcc/testsuite/gcc.dg/tree-ssa/popcount6.c
new file mode 100644
index 0000000..1406ad9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/popcount6.c
@@ -0,0 +1,12 @@
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-evrp" }
+
+int g(int n)
+{
+ n &= 0x8000;
+ if (n == 0)
+ return 1;
+ return __builtin_popcount(n);
+}
+
+// { dg-final { scan-tree-dump "return 1;" "evrp" } }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/popcount6b.c b/gcc/testsuite/gcc.dg/tree-ssa/popcount6b.c
new file mode 100644
index 0000000..90336ec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/popcount6b.c
@@ -0,0 +1,6 @@
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-evrp -fno-tree-ccp" }
+
+#include "popcount6.c"
+
+// { dg-final { scan-tree-dump "return 1;" "evrp" } }
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x2.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x2.c
index f933102..0c45a2b 100644
--- a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x2.c
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x2.c
@@ -1,6 +1,6 @@
/* We haven't implemented these intrinsics for arm yet. */
/* { dg-do run } */
-/* { dg-skip-if "unsupported" { arm*-*-* } } */
+/* { dg-skip-if "unimplemented" { arm*-*-* } } */
/* { dg-options "-O3" } */
#include <arm_neon.h>
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x3.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x3.c
index b20dec0..4174dcd 100644
--- a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x3.c
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x3.c
@@ -1,6 +1,6 @@
/* We haven't implemented these intrinsics for arm yet. */
/* { dg-do run } */
-/* { dg-skip-if "unsupported" { arm*-*-* } } */
+/* { dg-skip-if "unimplemented" { arm*-*-* } } */
/* { dg-options "-O3" } */
#include <arm_neon.h>
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x4.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x4.c
index e59f845..89b289b 100644
--- a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x4.c
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x4.c
@@ -1,6 +1,6 @@
/* We haven't implemented these intrinsics for arm yet. */
/* { dg-do run } */
-/* { dg-skip-if "unsupported" { arm*-*-* } } */
+/* { dg-skip-if "unimplemented" { arm*-*-* } } */
/* { dg-options "-O3" } */
#include <arm_neon.h>
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst1x2.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst1x2.c
index cb13da0..6d20a46 100644
--- a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst1x2.c
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst1x2.c
@@ -1,6 +1,6 @@
/* We haven't implemented these intrinsics for arm yet. */
-/* { dg-xfail-if "" { arm*-*-* } } */
/* { dg-do run } */
+/* { dg-skip-if "unimplemented" { arm*-*-* } } */
/* { dg-options "-O3" } */
#include <arm_neon.h>
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst1x3.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst1x3.c
index 3ce272a..87eae4d 100644
--- a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst1x3.c
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst1x3.c
@@ -1,6 +1,6 @@
/* We haven't implemented these intrinsics for arm yet. */
-/* { dg-xfail-if "" { arm*-*-* } } */
/* { dg-do run } */
+/* { dg-skip-if "unimplemented" { arm*-*-* } } */
/* { dg-options "-O3" } */
#include <arm_neon.h>
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst1x4.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst1x4.c
index 1f17b53..829a18d 100644
--- a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst1x4.c
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst1x4.c
@@ -1,6 +1,6 @@
/* We haven't implemented these intrinsics for arm yet. */
-/* { dg-xfail-if "" { arm*-*-* } } */
/* { dg-do run } */
+/* { dg-skip-if "unimplemented" { arm*-*-* } } */
/* { dg-options "-O3" } */
#include <arm_neon.h>
diff --git a/gcc/testsuite/gcc.target/arm/attr-crypto.c b/gcc/testsuite/gcc.target/arm/attr-crypto.c
index cbd13a7..05e458f 100644
--- a/gcc/testsuite/gcc.target/arm/attr-crypto.c
+++ b/gcc/testsuite/gcc.target/arm/attr-crypto.c
@@ -16,6 +16,14 @@
#error __ARM_FEATURE_CRYPTO not defined.
#endif
+#ifndef __ARM_FEATURE_AES
+#error __ARM_FEATURE_AES not defined.
+#endif
+
+#ifndef __ARM_FEATURE_SHA2
+#error __ARM_FEATURE_SHA2 not defined.
+#endif
+
#ifndef __ARM_NEON
#error __ARM_NEON not defined.
#endif
diff --git a/gcc/testsuite/gcc.target/i386/keylocker-encodekey128.c b/gcc/testsuite/gcc.target/i386/keylocker-encodekey128.c
index 805e062..57fa9bd 100644
--- a/gcc/testsuite/gcc.target/i386/keylocker-encodekey128.c
+++ b/gcc/testsuite/gcc.target/i386/keylocker-encodekey128.c
@@ -6,7 +6,6 @@
/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\]*%xmm0,\[^\\n\\r\]*" } } */
/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\]*%xmm1,\[^\\n\\r\]*16\[^\\n\\r\]*" } } */
/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\]*%xmm2,\[^\\n\\r\]*32\[^\\n\\r\]*" } } */
-/* { dg-final { scan-assembler "(?:movdqa|movaps)\[ \\t\]+\[^\\n\]*%xmm\[4-6\],\[^\\n\\r\]*" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/keylocker-encodekey256.c b/gcc/testsuite/gcc.target/i386/keylocker-encodekey256.c
index 26f04dc..a9398b4 100644
--- a/gcc/testsuite/gcc.target/i386/keylocker-encodekey256.c
+++ b/gcc/testsuite/gcc.target/i386/keylocker-encodekey256.c
@@ -8,7 +8,6 @@
/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\]*%xmm1,\[^\\n\\r\]*16\[^\\n\\r\]*" } } */
/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\]*%xmm2,\[^\\n\\r\]*32\[^\\n\\r\]*" } } */
/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\]*%xmm3,\[^\\n\\r\]*48\[^\\n\\r\]*" } } */
-/* { dg-final { scan-assembler "(?:movdqa|movaps)\[ \\t\]+\[^\\n\]*%xmm\[4-6\],\[^\\n\\r\]*" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/pr107055.c b/gcc/testsuite/gcc.target/i386/pr107055.c
new file mode 100644
index 0000000..63bcb3d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr107055.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fno-tree-dce -fno-vect-cost-model -ftree-vectorize -fprofile-arcs" } */
+
+#include "../../gcc.dg/torture/pr24257.c"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/abi-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-1.c
new file mode 100644
index 0000000..2e0e12a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-1.c
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-skip-if "test rvv intrinsic" { *-*-* } { "*" } { "-march=rv*v*" } } */
+
+void foo0 () {__rvv_bool64_t t;}
+void foo1 () {__rvv_bool32_t t;}
+void foo2 () {__rvv_bool16_t t;}
+void foo3 () {__rvv_bool8_t t;}
+void foo4 () {__rvv_bool4_t t;}
+void foo5 () {__rvv_bool2_t t;}
+void foo6 () {__rvv_bool1_t t;}
+void foo7 () {__rvv_int8mf8_t t;}
+void foo8 () {__rvv_uint8mf8_t t;}
+void foo9 () {__rvv_int8mf4_t t;}
+void foo10 () {__rvv_uint8mf4_t t;}
+void foo11 () {__rvv_int8mf2_t t;}
+void foo12 () {__rvv_uint8mf2_t t;}
+void foo13 () {__rvv_int8m1_t t;}
+void foo14 () {__rvv_uint8m1_t t;}
+void foo15 () {__rvv_int8m2_t t;}
+void foo16 () {__rvv_uint8m2_t t;}
+void foo17 () {__rvv_int8m4_t t;}
+void foo18 () {__rvv_uint8m4_t t;}
+void foo19 () {__rvv_int8m8_t t;}
+void foo20 () {__rvv_uint8m8_t t;}
+void foo21 () {__rvv_int16mf4_t t;}
+void foo22 () {__rvv_uint16mf4_t t;}
+void foo23 () {__rvv_int16mf2_t t;}
+void foo24 () {__rvv_uint16mf2_t t;}
+void foo25 () {__rvv_int16m1_t t;}
+void foo26 () {__rvv_uint16m1_t t;}
+void foo27 () {__rvv_int16m2_t t;}
+void foo28 () {__rvv_uint16m2_t t;}
+void foo29 () {__rvv_int16m4_t t;}
+void foo30 () {__rvv_uint16m4_t t;}
+void foo31 () {__rvv_int16m8_t t;}
+void foo32 () {__rvv_uint16m8_t t;}
+void foo33 () {__rvv_int32mf2_t t;}
+void foo34 () {__rvv_uint32mf2_t t;}
+void foo35 () {__rvv_int32m1_t t;}
+void foo36 () {__rvv_uint32m1_t t;}
+void foo37 () {__rvv_int32m2_t t;}
+void foo38 () {__rvv_uint32m2_t t;}
+void foo39 () {__rvv_int32m4_t t;}
+void foo40 () {__rvv_uint32m4_t t;}
+void foo41 () {__rvv_int32m8_t t;}
+void foo42 () {__rvv_uint32m8_t t;}
+void foo43 () {__rvv_int64m1_t t;}
+void foo44 () {__rvv_uint64m1_t t;}
+void foo45 () {__rvv_int64m2_t t;}
+void foo46 () {__rvv_uint64m2_t t;}
+void foo47 () {__rvv_int64m4_t t;}
+void foo48 () {__rvv_uint64m4_t t;}
+void foo49 () {__rvv_int64m8_t t;}
+void foo50 () {__rvv_uint64m8_t t;}
+void foo57 () {__rvv_float32mf2_t t;}
+void foo58 () {__rvv_float32m1_t t;}
+void foo59 () {__rvv_float32m2_t t;}
+void foo60 () {__rvv_float32m4_t t;}
+void foo61 () {__rvv_float32m8_t t;}
+void foo62 () {__rvv_float64m1_t t;}
+void foo63 () {__rvv_float64m2_t t;}
+void foo64 () {__rvv_float64m4_t t;}
+void foo65 () {__rvv_float64m8_t t;}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/abi-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-2.c
new file mode 100644
index 0000000..92e61c2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-2.c
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=rv32gc -mabi=ilp32d" } */
+
+void foo0 () {__rvv_bool64_t t;} /* { dg-error {unknown type name '__rvv_bool64_t'} } */
+void foo1 () {__rvv_bool32_t t;} /* { dg-error {unknown type name '__rvv_bool32_t'} } */
+void foo2 () {__rvv_bool16_t t;} /* { dg-error {unknown type name '__rvv_bool16_t'} } */
+void foo3 () {__rvv_bool8_t t;} /* { dg-error {unknown type name '__rvv_bool8_t'} } */
+void foo4 () {__rvv_bool4_t t;} /* { dg-error {unknown type name '__rvv_bool4_t'} } */
+void foo5 () {__rvv_bool2_t t;} /* { dg-error {unknown type name '__rvv_bool2_t'} } */
+void foo6 () {__rvv_bool1_t t;} /* { dg-error {unknown type name '__rvv_bool1_t'} } */
+void foo7 () {__rvv_int8mf8_t t;} /* { dg-error {unknown type name '__rvv_int8mf8_t'} } */
+void foo8 () {__rvv_uint8mf8_t t;} /* { dg-error {unknown type name '__rvv_uint8mf8_t'} } */
+void foo9 () {__rvv_int8mf4_t t;} /* { dg-error {unknown type name '__rvv_int8mf4_t'} } */
+void foo10 () {__rvv_uint8mf4_t t;} /* { dg-error {unknown type name '__rvv_uint8mf4_t'} } */
+void foo11 () {__rvv_int8mf2_t t;} /* { dg-error {unknown type name '__rvv_int8mf2_t'} } */
+void foo12 () {__rvv_uint8mf2_t t;} /* { dg-error {unknown type name '__rvv_uint8mf2_t'} } */
+void foo13 () {__rvv_int8m1_t t;} /* { dg-error {unknown type name '__rvv_int8m1_t'} } */
+void foo14 () {__rvv_uint8m1_t t;} /* { dg-error {unknown type name '__rvv_uint8m1_t'} } */
+void foo15 () {__rvv_int8m2_t t;} /* { dg-error {unknown type name '__rvv_int8m2_t'} } */
+void foo16 () {__rvv_uint8m2_t t;} /* { dg-error {unknown type name '__rvv_uint8m2_t'} } */
+void foo17 () {__rvv_int8m4_t t;} /* { dg-error {unknown type name '__rvv_int8m4_t'} } */
+void foo18 () {__rvv_uint8m4_t t;} /* { dg-error {unknown type name '__rvv_uint8m4_t'} } */
+void foo19 () {__rvv_int8m8_t t;} /* { dg-error {unknown type name '__rvv_int8m8_t'} } */
+void foo20 () {__rvv_uint8m8_t t;} /* { dg-error {unknown type name '__rvv_uint8m8_t'} } */
+void foo21 () {__rvv_int16mf4_t t;} /* { dg-error {unknown type name '__rvv_int16mf4_t'} } */
+void foo22 () {__rvv_uint16mf4_t t;} /* { dg-error {unknown type name '__rvv_uint16mf4_t'} } */
+void foo23 () {__rvv_int16mf2_t t;} /* { dg-error {unknown type name '__rvv_int16mf2_t'} } */
+void foo24 () {__rvv_uint16mf2_t t;} /* { dg-error {unknown type name '__rvv_uint16mf2_t'} } */
+void foo25 () {__rvv_int16m1_t t;} /* { dg-error {unknown type name '__rvv_int16m1_t'} } */
+void foo26 () {__rvv_uint16m1_t t;} /* { dg-error {unknown type name '__rvv_uint16m1_t'} } */
+void foo27 () {__rvv_int16m2_t t;} /* { dg-error {unknown type name '__rvv_int16m2_t'} } */
+void foo28 () {__rvv_uint16m2_t t;} /* { dg-error {unknown type name '__rvv_uint16m2_t'} } */
+void foo29 () {__rvv_int16m4_t t;} /* { dg-error {unknown type name '__rvv_int16m4_t'} } */
+void foo30 () {__rvv_uint16m4_t t;} /* { dg-error {unknown type name '__rvv_uint16m4_t'} } */
+void foo31 () {__rvv_int16m8_t t;} /* { dg-error {unknown type name '__rvv_int16m8_t'} } */
+void foo32 () {__rvv_uint16m8_t t;} /* { dg-error {unknown type name '__rvv_uint16m8_t'} } */
+void foo33 () {__rvv_int32mf2_t t;} /* { dg-error {unknown type name '__rvv_int32mf2_t'} } */
+void foo34 () {__rvv_uint32mf2_t t;} /* { dg-error {unknown type name '__rvv_uint32mf2_t'} } */
+void foo35 () {__rvv_int32m1_t t;} /* { dg-error {unknown type name '__rvv_int32m1_t'} } */
+void foo36 () {__rvv_uint32m1_t t;} /* { dg-error {unknown type name '__rvv_uint32m1_t'} } */
+void foo37 () {__rvv_int32m2_t t;} /* { dg-error {unknown type name '__rvv_int32m2_t'} } */
+void foo38 () {__rvv_uint32m2_t t;} /* { dg-error {unknown type name '__rvv_uint32m2_t'} } */
+void foo39 () {__rvv_int32m4_t t;} /* { dg-error {unknown type name '__rvv_int32m4_t'} } */
+void foo40 () {__rvv_uint32m4_t t;} /* { dg-error {unknown type name '__rvv_uint32m4_t'} } */
+void foo41 () {__rvv_int32m8_t t;} /* { dg-error {unknown type name '__rvv_int32m8_t'} } */
+void foo42 () {__rvv_uint32m8_t t;} /* { dg-error {unknown type name '__rvv_uint32m8_t'} } */
+void foo43 () {__rvv_int64m1_t t;} /* { dg-error {unknown type name '__rvv_int64m1_t'} } */
+void foo44 () {__rvv_uint64m1_t t;} /* { dg-error {unknown type name '__rvv_uint64m1_t'} } */
+void foo45 () {__rvv_int64m2_t t;} /* { dg-error {unknown type name '__rvv_int64m2_t'} } */
+void foo46 () {__rvv_uint64m2_t t;} /* { dg-error {unknown type name '__rvv_uint64m2_t'} } */
+void foo47 () {__rvv_int64m4_t t;} /* { dg-error {unknown type name '__rvv_int64m4_t'} } */
+void foo48 () {__rvv_uint64m4_t t;} /* { dg-error {unknown type name '__rvv_uint64m4_t'} } */
+void foo49 () {__rvv_int64m8_t t;} /* { dg-error {unknown type name '__rvv_int64m8_t'} } */
+void foo50 () {__rvv_uint64m8_t t;} /* { dg-error {unknown type name '__rvv_uint64m8_t'} } */
+void foo57 () {__rvv_float32mf2_t t;} /* { dg-error {unknown type name '__rvv_float32mf2_t'} } */
+void foo58 () {__rvv_float32m1_t t;} /* { dg-error {unknown type name '__rvv_float32m1_t'} } */
+void foo59 () {__rvv_float32m2_t t;} /* { dg-error {unknown type name '__rvv_float32m2_t'} } */
+void foo60 () {__rvv_float32m4_t t;} /* { dg-error {unknown type name '__rvv_float32m4_t'} } */
+void foo61 () {__rvv_float32m8_t t;} /* { dg-error {unknown type name '__rvv_float32m8_t'} } */
+void foo62 () {__rvv_float64m1_t t;} /* { dg-error {unknown type name '__rvv_float64m1_t'} } */
+void foo63 () {__rvv_float64m2_t t;} /* { dg-error {unknown type name '__rvv_float64m2_t'} } */
+void foo64 () {__rvv_float64m4_t t;} /* { dg-error {unknown type name '__rvv_float64m4_t'} } */
+void foo65 () {__rvv_float64m8_t t;} /* { dg-error {unknown type name '__rvv_float64m8_t'} } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/abi-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-3.c
new file mode 100644
index 0000000..b9adb30
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-3.c
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=rv32gc_zve64x -mabi=ilp32d" } */
+
+void foo0 () {__rvv_bool64_t t;}
+void foo1 () {__rvv_bool32_t t;}
+void foo2 () {__rvv_bool16_t t;}
+void foo3 () {__rvv_bool8_t t;}
+void foo4 () {__rvv_bool4_t t;}
+void foo5 () {__rvv_bool2_t t;}
+void foo6 () {__rvv_bool1_t t;}
+void foo7 () {__rvv_int8mf8_t t;}
+void foo8 () {__rvv_uint8mf8_t t;}
+void foo9 () {__rvv_int8mf4_t t;}
+void foo10 () {__rvv_uint8mf4_t t;}
+void foo11 () {__rvv_int8mf2_t t;}
+void foo12 () {__rvv_uint8mf2_t t;}
+void foo13 () {__rvv_int8m1_t t;}
+void foo14 () {__rvv_uint8m1_t t;}
+void foo15 () {__rvv_int8m2_t t;}
+void foo16 () {__rvv_uint8m2_t t;}
+void foo17 () {__rvv_int8m4_t t;}
+void foo18 () {__rvv_uint8m4_t t;}
+void foo19 () {__rvv_int8m8_t t;}
+void foo20 () {__rvv_uint8m8_t t;}
+void foo21 () {__rvv_int16mf4_t t;}
+void foo22 () {__rvv_uint16mf4_t t;}
+void foo23 () {__rvv_int16mf2_t t;}
+void foo24 () {__rvv_uint16mf2_t t;}
+void foo25 () {__rvv_int16m1_t t;}
+void foo26 () {__rvv_uint16m1_t t;}
+void foo27 () {__rvv_int16m2_t t;}
+void foo28 () {__rvv_uint16m2_t t;}
+void foo29 () {__rvv_int16m4_t t;}
+void foo30 () {__rvv_uint16m4_t t;}
+void foo31 () {__rvv_int16m8_t t;}
+void foo32 () {__rvv_uint16m8_t t;}
+void foo33 () {__rvv_int32mf2_t t;}
+void foo34 () {__rvv_uint32mf2_t t;}
+void foo35 () {__rvv_int32m1_t t;}
+void foo36 () {__rvv_uint32m1_t t;}
+void foo37 () {__rvv_int32m2_t t;}
+void foo38 () {__rvv_uint32m2_t t;}
+void foo39 () {__rvv_int32m4_t t;}
+void foo40 () {__rvv_uint32m4_t t;}
+void foo41 () {__rvv_int32m8_t t;}
+void foo42 () {__rvv_uint32m8_t t;}
+void foo43 () {__rvv_int64m1_t t;}
+void foo44 () {__rvv_uint64m1_t t;}
+void foo45 () {__rvv_int64m2_t t;}
+void foo46 () {__rvv_uint64m2_t t;}
+void foo47 () {__rvv_int64m4_t t;}
+void foo48 () {__rvv_uint64m4_t t;}
+void foo49 () {__rvv_int64m8_t t;}
+void foo50 () {__rvv_uint64m8_t t;}
+void foo57 () {__rvv_float32mf2_t t;} /* { dg-error {unknown type name '__rvv_float32mf2_t'} } */
+void foo58 () {__rvv_float32m1_t t;} /* { dg-error {unknown type name '__rvv_float32m1_t'} } */
+void foo59 () {__rvv_float32m2_t t;} /* { dg-error {unknown type name '__rvv_float32m2_t'} } */
+void foo60 () {__rvv_float32m4_t t;} /* { dg-error {unknown type name '__rvv_float32m4_t'} } */
+void foo61 () {__rvv_float32m8_t t;} /* { dg-error {unknown type name '__rvv_float32m8_t'} } */
+void foo62 () {__rvv_float64m1_t t;} /* { dg-error {unknown type name '__rvv_float64m1_t'} } */
+void foo63 () {__rvv_float64m2_t t;} /* { dg-error {unknown type name '__rvv_float64m2_t'} } */
+void foo64 () {__rvv_float64m4_t t;} /* { dg-error {unknown type name '__rvv_float64m4_t'} } */
+void foo65 () {__rvv_float64m8_t t;} /* { dg-error {unknown type name '__rvv_float64m8_t'} } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/abi-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-4.c
new file mode 100644
index 0000000..56a0ebe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-4.c
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=rv32gc_zve64f -mabi=ilp32d" } */
+
+void foo0 () {__rvv_bool64_t t;}
+void foo1 () {__rvv_bool32_t t;}
+void foo2 () {__rvv_bool16_t t;}
+void foo3 () {__rvv_bool8_t t;}
+void foo4 () {__rvv_bool4_t t;}
+void foo5 () {__rvv_bool2_t t;}
+void foo6 () {__rvv_bool1_t t;}
+void foo7 () {__rvv_int8mf8_t t;}
+void foo8 () {__rvv_uint8mf8_t t;}
+void foo9 () {__rvv_int8mf4_t t;}
+void foo10 () {__rvv_uint8mf4_t t;}
+void foo11 () {__rvv_int8mf2_t t;}
+void foo12 () {__rvv_uint8mf2_t t;}
+void foo13 () {__rvv_int8m1_t t;}
+void foo14 () {__rvv_uint8m1_t t;}
+void foo15 () {__rvv_int8m2_t t;}
+void foo16 () {__rvv_uint8m2_t t;}
+void foo17 () {__rvv_int8m4_t t;}
+void foo18 () {__rvv_uint8m4_t t;}
+void foo19 () {__rvv_int8m8_t t;}
+void foo20 () {__rvv_uint8m8_t t;}
+void foo21 () {__rvv_int16mf4_t t;}
+void foo22 () {__rvv_uint16mf4_t t;}
+void foo23 () {__rvv_int16mf2_t t;}
+void foo24 () {__rvv_uint16mf2_t t;}
+void foo25 () {__rvv_int16m1_t t;}
+void foo26 () {__rvv_uint16m1_t t;}
+void foo27 () {__rvv_int16m2_t t;}
+void foo28 () {__rvv_uint16m2_t t;}
+void foo29 () {__rvv_int16m4_t t;}
+void foo30 () {__rvv_uint16m4_t t;}
+void foo31 () {__rvv_int16m8_t t;}
+void foo32 () {__rvv_uint16m8_t t;}
+void foo33 () {__rvv_int32mf2_t t;}
+void foo34 () {__rvv_uint32mf2_t t;}
+void foo35 () {__rvv_int32m1_t t;}
+void foo36 () {__rvv_uint32m1_t t;}
+void foo37 () {__rvv_int32m2_t t;}
+void foo38 () {__rvv_uint32m2_t t;}
+void foo39 () {__rvv_int32m4_t t;}
+void foo40 () {__rvv_uint32m4_t t;}
+void foo41 () {__rvv_int32m8_t t;}
+void foo42 () {__rvv_uint32m8_t t;}
+void foo43 () {__rvv_int64m1_t t;}
+void foo44 () {__rvv_uint64m1_t t;}
+void foo45 () {__rvv_int64m2_t t;}
+void foo46 () {__rvv_uint64m2_t t;}
+void foo47 () {__rvv_int64m4_t t;}
+void foo48 () {__rvv_uint64m4_t t;}
+void foo49 () {__rvv_int64m8_t t;}
+void foo50 () {__rvv_uint64m8_t t;}
+void foo57 () {__rvv_float32mf2_t t;}
+void foo58 () {__rvv_float32m1_t t;}
+void foo59 () {__rvv_float32m2_t t;}
+void foo60 () {__rvv_float32m4_t t;}
+void foo61 () {__rvv_float32m8_t t;}
+void foo62 () {__rvv_float64m1_t t;} /* { dg-error {unknown type name '__rvv_float64m1_t'} } */
+void foo63 () {__rvv_float64m2_t t;} /* { dg-error {unknown type name '__rvv_float64m2_t'} } */
+void foo64 () {__rvv_float64m4_t t;} /* { dg-error {unknown type name '__rvv_float64m4_t'} } */
+void foo65 () {__rvv_float64m8_t t;} /* { dg-error {unknown type name '__rvv_float64m8_t'} } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/abi-5.c b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-5.c
new file mode 100644
index 0000000..af71609
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-5.c
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=rv32gc_zve64d -mabi=ilp32d" } */
+
+void foo0 () {__rvv_bool64_t t;}
+void foo1 () {__rvv_bool32_t t;}
+void foo2 () {__rvv_bool16_t t;}
+void foo3 () {__rvv_bool8_t t;}
+void foo4 () {__rvv_bool4_t t;}
+void foo5 () {__rvv_bool2_t t;}
+void foo6 () {__rvv_bool1_t t;}
+void foo7 () {__rvv_int8mf8_t t;}
+void foo8 () {__rvv_uint8mf8_t t;}
+void foo9 () {__rvv_int8mf4_t t;}
+void foo10 () {__rvv_uint8mf4_t t;}
+void foo11 () {__rvv_int8mf2_t t;}
+void foo12 () {__rvv_uint8mf2_t t;}
+void foo13 () {__rvv_int8m1_t t;}
+void foo14 () {__rvv_uint8m1_t t;}
+void foo15 () {__rvv_int8m2_t t;}
+void foo16 () {__rvv_uint8m2_t t;}
+void foo17 () {__rvv_int8m4_t t;}
+void foo18 () {__rvv_uint8m4_t t;}
+void foo19 () {__rvv_int8m8_t t;}
+void foo20 () {__rvv_uint8m8_t t;}
+void foo21 () {__rvv_int16mf4_t t;}
+void foo22 () {__rvv_uint16mf4_t t;}
+void foo23 () {__rvv_int16mf2_t t;}
+void foo24 () {__rvv_uint16mf2_t t;}
+void foo25 () {__rvv_int16m1_t t;}
+void foo26 () {__rvv_uint16m1_t t;}
+void foo27 () {__rvv_int16m2_t t;}
+void foo28 () {__rvv_uint16m2_t t;}
+void foo29 () {__rvv_int16m4_t t;}
+void foo30 () {__rvv_uint16m4_t t;}
+void foo31 () {__rvv_int16m8_t t;}
+void foo32 () {__rvv_uint16m8_t t;}
+void foo33 () {__rvv_int32mf2_t t;}
+void foo34 () {__rvv_uint32mf2_t t;}
+void foo35 () {__rvv_int32m1_t t;}
+void foo36 () {__rvv_uint32m1_t t;}
+void foo37 () {__rvv_int32m2_t t;}
+void foo38 () {__rvv_uint32m2_t t;}
+void foo39 () {__rvv_int32m4_t t;}
+void foo40 () {__rvv_uint32m4_t t;}
+void foo41 () {__rvv_int32m8_t t;}
+void foo42 () {__rvv_uint32m8_t t;}
+void foo43 () {__rvv_int64m1_t t;}
+void foo44 () {__rvv_uint64m1_t t;}
+void foo45 () {__rvv_int64m2_t t;}
+void foo46 () {__rvv_uint64m2_t t;}
+void foo47 () {__rvv_int64m4_t t;}
+void foo48 () {__rvv_uint64m4_t t;}
+void foo49 () {__rvv_int64m8_t t;}
+void foo50 () {__rvv_uint64m8_t t;}
+void foo57 () {__rvv_float32mf2_t t;}
+void foo58 () {__rvv_float32m1_t t;}
+void foo59 () {__rvv_float32m2_t t;}
+void foo60 () {__rvv_float32m4_t t;}
+void foo61 () {__rvv_float32m8_t t;}
+void foo62 () {__rvv_float64m1_t t;}
+void foo63 () {__rvv_float64m2_t t;}
+void foo64 () {__rvv_float64m4_t t;}
+void foo65 () {__rvv_float64m8_t t;}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/abi-6.c b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-6.c
new file mode 100644
index 0000000..e866c06
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-6.c
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=rv32gc_zve32x -mabi=ilp32d" } */
+
+void foo0 () {__rvv_bool64_t t;} /* { dg-error {unknown type name '__rvv_bool64_t'} } */
+void foo1 () {__rvv_bool32_t t;}
+void foo2 () {__rvv_bool16_t t;}
+void foo3 () {__rvv_bool8_t t;}
+void foo4 () {__rvv_bool4_t t;}
+void foo5 () {__rvv_bool2_t t;}
+void foo6 () {__rvv_bool1_t t;}
+void foo7 () {__rvv_int8mf8_t t;} /* { dg-error {unknown type name '__rvv_int8mf8_t'} } */
+void foo8 () {__rvv_uint8mf8_t t;} /* { dg-error {unknown type name '__rvv_uint8mf8_t'} } */
+void foo9 () {__rvv_int8mf4_t t;}
+void foo10 () {__rvv_uint8mf4_t t;}
+void foo11 () {__rvv_int8mf2_t t;}
+void foo12 () {__rvv_uint8mf2_t t;}
+void foo13 () {__rvv_int8m1_t t;}
+void foo14 () {__rvv_uint8m1_t t;}
+void foo15 () {__rvv_int8m2_t t;}
+void foo16 () {__rvv_uint8m2_t t;}
+void foo17 () {__rvv_int8m4_t t;}
+void foo18 () {__rvv_uint8m4_t t;}
+void foo19 () {__rvv_int8m8_t t;}
+void foo20 () {__rvv_uint8m8_t t;}
+void foo21 () {__rvv_int16mf4_t t;} /* { dg-error {unknown type name '__rvv_int16mf4_t'} } */
+void foo22 () {__rvv_uint16mf4_t t;} /* { dg-error {unknown type name '__rvv_uint16mf4_t'} } */
+void foo23 () {__rvv_int16mf2_t t;}
+void foo24 () {__rvv_uint16mf2_t t;}
+void foo25 () {__rvv_int16m1_t t;}
+void foo26 () {__rvv_uint16m1_t t;}
+void foo27 () {__rvv_int16m2_t t;}
+void foo28 () {__rvv_uint16m2_t t;}
+void foo29 () {__rvv_int16m4_t t;}
+void foo30 () {__rvv_uint16m4_t t;}
+void foo31 () {__rvv_int16m8_t t;}
+void foo32 () {__rvv_uint16m8_t t;}
+void foo33 () {__rvv_int32mf2_t t;} /* { dg-error {unknown type name '__rvv_int32mf2_t'} } */
+void foo34 () {__rvv_uint32mf2_t t;} /* { dg-error {unknown type name '__rvv_uint32mf2_t'} } */
+void foo35 () {__rvv_int32m1_t t;}
+void foo36 () {__rvv_uint32m1_t t;}
+void foo37 () {__rvv_int32m2_t t;}
+void foo38 () {__rvv_uint32m2_t t;}
+void foo39 () {__rvv_int32m4_t t;}
+void foo40 () {__rvv_uint32m4_t t;}
+void foo41 () {__rvv_int32m8_t t;}
+void foo42 () {__rvv_uint32m8_t t;}
+void foo43 () {__rvv_int64m1_t t;} /* { dg-error {unknown type name '__rvv_int64m1_t'} } */
+void foo44 () {__rvv_uint64m1_t t;} /* { dg-error {unknown type name '__rvv_uint64m1_t'} } */
+void foo45 () {__rvv_int64m2_t t;} /* { dg-error {unknown type name '__rvv_int64m2_t'} } */
+void foo46 () {__rvv_uint64m2_t t;} /* { dg-error {unknown type name '__rvv_uint64m2_t'} } */
+void foo47 () {__rvv_int64m4_t t;} /* { dg-error {unknown type name '__rvv_int64m4_t'} } */
+void foo48 () {__rvv_uint64m4_t t;} /* { dg-error {unknown type name '__rvv_uint64m4_t'} } */
+void foo49 () {__rvv_int64m8_t t;} /* { dg-error {unknown type name '__rvv_int64m8_t'} } */
+void foo50 () {__rvv_uint64m8_t t;} /* { dg-error {unknown type name '__rvv_uint64m8_t'} } */
+void foo57 () {__rvv_float32mf2_t t;} /* { dg-error {unknown type name '__rvv_float32mf2_t'} } */
+void foo58 () {__rvv_float32m1_t t;} /* { dg-error {unknown type name '__rvv_float32m1_t'} } */
+void foo59 () {__rvv_float32m2_t t;} /* { dg-error {unknown type name '__rvv_float32m2_t'} } */
+void foo60 () {__rvv_float32m4_t t;} /* { dg-error {unknown type name '__rvv_float32m4_t'} } */
+void foo61 () {__rvv_float32m8_t t;} /* { dg-error {unknown type name '__rvv_float32m8_t'} } */
+void foo62 () {__rvv_float64m1_t t;} /* { dg-error {unknown type name '__rvv_float64m1_t'} } */
+void foo63 () {__rvv_float64m2_t t;} /* { dg-error {unknown type name '__rvv_float64m2_t'} } */
+void foo64 () {__rvv_float64m4_t t;} /* { dg-error {unknown type name '__rvv_float64m4_t'} } */
+void foo65 () {__rvv_float64m8_t t;} /* { dg-error {unknown type name '__rvv_float64m8_t'} } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/abi-7.c b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-7.c
new file mode 100644
index 0000000..407756d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-7.c
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=rv32gc_zve32f -mabi=ilp32d" } */
+
+void foo0 () {__rvv_bool64_t t;} /* { dg-error {unknown type name '__rvv_bool64_t'} } */
+void foo1 () {__rvv_bool32_t t;}
+void foo2 () {__rvv_bool16_t t;}
+void foo3 () {__rvv_bool8_t t;}
+void foo4 () {__rvv_bool4_t t;}
+void foo5 () {__rvv_bool2_t t;}
+void foo6 () {__rvv_bool1_t t;}
+void foo7 () {__rvv_int8mf8_t t;} /* { dg-error {unknown type name '__rvv_int8mf8_t'} } */
+void foo8 () {__rvv_uint8mf8_t t;} /* { dg-error {unknown type name '__rvv_uint8mf8_t'} } */
+void foo9 () {__rvv_int8mf4_t t;}
+void foo10 () {__rvv_uint8mf4_t t;}
+void foo11 () {__rvv_int8mf2_t t;}
+void foo12 () {__rvv_uint8mf2_t t;}
+void foo13 () {__rvv_int8m1_t t;}
+void foo14 () {__rvv_uint8m1_t t;}
+void foo15 () {__rvv_int8m2_t t;}
+void foo16 () {__rvv_uint8m2_t t;}
+void foo17 () {__rvv_int8m4_t t;}
+void foo18 () {__rvv_uint8m4_t t;}
+void foo19 () {__rvv_int8m8_t t;}
+void foo20 () {__rvv_uint8m8_t t;}
+void foo21 () {__rvv_int16mf4_t t;} /* { dg-error {unknown type name '__rvv_int16mf4_t'} } */
+void foo22 () {__rvv_uint16mf4_t t;} /* { dg-error {unknown type name '__rvv_uint16mf4_t'} } */
+void foo23 () {__rvv_int16mf2_t t;}
+void foo24 () {__rvv_uint16mf2_t t;}
+void foo25 () {__rvv_int16m1_t t;}
+void foo26 () {__rvv_uint16m1_t t;}
+void foo27 () {__rvv_int16m2_t t;}
+void foo28 () {__rvv_uint16m2_t t;}
+void foo29 () {__rvv_int16m4_t t;}
+void foo30 () {__rvv_uint16m4_t t;}
+void foo31 () {__rvv_int16m8_t t;}
+void foo32 () {__rvv_uint16m8_t t;}
+void foo33 () {__rvv_int32mf2_t t;} /* { dg-error {unknown type name '__rvv_int32mf2_t'} } */
+void foo34 () {__rvv_uint32mf2_t t;} /* { dg-error {unknown type name '__rvv_uint32mf2_t'} } */
+void foo35 () {__rvv_int32m1_t t;}
+void foo36 () {__rvv_uint32m1_t t;}
+void foo37 () {__rvv_int32m2_t t;}
+void foo38 () {__rvv_uint32m2_t t;}
+void foo39 () {__rvv_int32m4_t t;}
+void foo40 () {__rvv_uint32m4_t t;}
+void foo41 () {__rvv_int32m8_t t;}
+void foo42 () {__rvv_uint32m8_t t;}
+void foo43 () {__rvv_int64m1_t t;} /* { dg-error {unknown type name '__rvv_int64m1_t'} } */
+void foo44 () {__rvv_uint64m1_t t;} /* { dg-error {unknown type name '__rvv_uint64m1_t'} } */
+void foo45 () {__rvv_int64m2_t t;} /* { dg-error {unknown type name '__rvv_int64m2_t'} } */
+void foo46 () {__rvv_uint64m2_t t;} /* { dg-error {unknown type name '__rvv_uint64m2_t'} } */
+void foo47 () {__rvv_int64m4_t t;} /* { dg-error {unknown type name '__rvv_int64m4_t'} } */
+void foo48 () {__rvv_uint64m4_t t;} /* { dg-error {unknown type name '__rvv_uint64m4_t'} } */
+void foo49 () {__rvv_int64m8_t t;} /* { dg-error {unknown type name '__rvv_int64m8_t'} } */
+void foo50 () {__rvv_uint64m8_t t;} /* { dg-error {unknown type name '__rvv_uint64m8_t'} } */
+void foo57 () {__rvv_float32mf2_t t;} /* { dg-error {unknown type name '__rvv_float32mf2_t'} } */
+void foo58 () {__rvv_float32m1_t t;}
+void foo59 () {__rvv_float32m2_t t;}
+void foo60 () {__rvv_float32m4_t t;}
+void foo61 () {__rvv_float32m8_t t;}
+void foo62 () {__rvv_float64m1_t t;} /* { dg-error {unknown type name '__rvv_float64m1_t'} } */
+void foo63 () {__rvv_float64m2_t t;} /* { dg-error {unknown type name '__rvv_float64m2_t'} } */
+void foo64 () {__rvv_float64m4_t t;} /* { dg-error {unknown type name '__rvv_float64m4_t'} } */
+void foo65 () {__rvv_float64m8_t t;} /* { dg-error {unknown type name '__rvv_float64m8_t'} } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
new file mode 100644
index 0000000..25e09f4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
@@ -0,0 +1,47 @@
+# Copyright (C) 2022-2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't a RISC-V target.
+if ![istarget riscv*-*-*] then {
+ return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+ set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+}
+
+set gcc_march "rv64gcv_zfh"
+if [istarget riscv32-*-*] then {
+ set gcc_march "rv32gcv_zfh"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+set CFLAGS "$DEFAULT_CFLAGS -march=$gcc_march -O3"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/base/*.\[cS\]]] \
+ "" $CFLAGS
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gdc.test/compilable/commontype.d b/gcc/testsuite/gdc.test/compilable/commontype.d
index 076e29b..abe956c 100644
--- a/gcc/testsuite/gdc.test/compilable/commontype.d
+++ b/gcc/testsuite/gdc.test/compilable/commontype.d
@@ -151,19 +151,19 @@ static assert(Error!( uint*, int* ));
static assert(is( X!( int function(), int function() ) == int function() ));
// void pointer
-static assert(is( X!( void*, int* ) == int* ));
-static assert(is( X!( int*, void* ) == int* ));
-static assert(is( X!( const(int)*, void* ) == const(int)* ));
-static assert(is( X!( const(int*), void* ) == const(int*) ));
-static assert(is( X!( int*, const(void)* ) == int* )); // `const`
-static assert(is( X!( int*, const(void*) ) == int* )); // `const`
-static assert(is( X!( int*, shared(void*) ) == int* )); // should fail
-static assert(is( X!( int*, shared(void)* ) == int* )); // should fail
+static assert(is( X!( void*, int* ) == void* ));
+static assert(is( X!( int*, void* ) == void* ));
+static assert(is( X!( const(int)*, void* ) == void* ));
+static assert(is( X!( const(int*), void* ) == void* ));
+static assert(is( X!( int*, const(void)* ) == const(void)* )); // `const`
+static assert(is( X!( int*, const(void*) ) == const(void*) )); // `const`
+static assert(is( X!( int*, shared(void*) ) == shared(void*) )); // should fail
+static assert(is( X!( int*, shared(void)* ) == shared(void)* )); // should fail
static assert(Error!( int**, void** )); // should work
-static assert(is( X!( void*, int function() ) == int function() ));
-static assert(is( X!( immutable(void*), int function() ) == int function() )); // `const`
+static assert(is( X!( void*, int function() ) == void* ));
+static assert(is( X!( immutable(void*), int function() ) == immutable(void*) )); // `const`
// implicit conversion
static assert(is( X!( int*, const(int*) ) == const(int*) ));
diff --git a/gcc/testsuite/gdc.test/compilable/imports/cimports2a.i b/gcc/testsuite/gdc.test/compilable/imports/cimports2a.i
new file mode 100644
index 0000000..c8ff976
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/cimports2a.i
@@ -0,0 +1,4 @@
+extern int xx;
+
+typedef struct Foo *FooRef;
+FooRef make_foo(void);
diff --git a/gcc/testsuite/gdc.test/compilable/imports/cimports2b.i b/gcc/testsuite/gdc.test/compilable/imports/cimports2b.i
new file mode 100644
index 0000000..03b22b2
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/cimports2b.i
@@ -0,0 +1,4 @@
+extern int xx;
+
+typedef struct Foo *FooRef;
+void free_foo(FooRef foo);
diff --git a/gcc/testsuite/gdc.test/compilable/imports/format23327.d b/gcc/testsuite/gdc.test/compilable/imports/format23327.d
new file mode 100644
index 0000000..de9b957
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/format23327.d
@@ -0,0 +1,7 @@
+module imports.format23327;
+
+import imports.format23327.write;
+
+immutable(string) format23327() { }
+
+import imports.format23327.internal.write;
diff --git a/gcc/testsuite/gdc.test/compilable/imports/format23327/write.d b/gcc/testsuite/gdc.test/compilable/imports/format23327/write.d
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/format23327/write.d
diff --git a/gcc/testsuite/gdc.test/compilable/segfaultgolf.d b/gcc/testsuite/gdc.test/compilable/segfaultgolf.d
new file mode 100644
index 0000000..2ea125f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/segfaultgolf.d
@@ -0,0 +1,50 @@
+// https://issues.dlang.org/show_bug.cgi?id=23351
+enum strings =
+[
+"a[(b).",
+"[(a)(b).",
+"a(={@.()(",
+"a[b,[(c).",
+"a[b#([(c).",
+"[a@b[(c).",
+"[((a).",
+"[a)b[(c).",
+"a[b)[(c).",
+"a(b[(c).",
+"a[b()c[(d).",
+"a[(b[(c).",
+"a(b[(c).",
+"[(@@a b[(c).",
+"a[(!b)c[(d).",
+"[(^a)b[(c).",
+"a(b[(c).",
+"~[a.b[(c).",
+"[a).[(b c d(e[(f).",
+"[((a).",
+"[a}b[(c).",
+"a[b[c..(d).",
+"[1a.[(b).",
+"a[({in){,",
+"a[^in(b[c=])S....,",
+"a[({in[({)){,"
+];
+template KidNamedFinger(T)
+{
+
+}
+void dummy()
+{
+ static foreach(str; strings)
+ {
+ /*
+ The above strings are all gibberish, they should
+ fail to parse but not segfault the compiler.
+ */
+ {
+ enum exp = __traits(compiles, mixin(str));
+ static assert(!exp);
+ enum t = __traits(compiles, KidNamedFinger!(mixin(str)));
+ static assert(!t);
+ }
+ }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/statictemplatethis.d b/gcc/testsuite/gdc.test/compilable/statictemplatethis.d
new file mode 100644
index 0000000..0236f2d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/statictemplatethis.d
@@ -0,0 +1,45 @@
+mixin template Constructors(){
+ this(){ }
+ this()immutable{ }
+ this()shared{ }
+}
+
+class A {
+public:
+ static T getInstance(this T)() {
+ return new T();
+ }
+private:
+ mixin Constructors;
+}
+
+class B : A {
+private:
+ mixin Constructors;
+}
+
+void f(){
+ auto a = (new A).getInstance;
+ auto b = (new B).getInstance;
+ static assert(is(typeof(a) == A));
+ static assert(is(typeof(b) == B));
+
+ auto ca = (new immutable A).getInstance;
+ auto sb = (new shared B).getInstance;
+ static assert(is(typeof(ca) == immutable A));
+ static assert(is(typeof(sb) == shared B));
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=10488
+version(none)
+void g(){
+ auto a = A.getInstance();
+ auto b = B.getInstance();
+ static assert(is(typeof(a)==A));
+ static assert(is(typeof(b)==B));
+
+ auto ai = (immutable(A)).getInstance();
+ auto bs = (shared(B)).getInstance();
+ static assert(is(typeof(ai)==immutable(A)));
+ static assert(is(typeof(bs)==shared(B)));
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test13123.d b/gcc/testsuite/gdc.test/compilable/test13123.d
new file mode 100644
index 0000000..881eb1b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test13123.d
@@ -0,0 +1,38 @@
+auto inferNothrow()
+in
+{
+}
+out
+{
+}
+do
+{
+ return 1;
+}
+
+auto dontInferNothrowIn()
+in
+{
+ throw new Exception(null);
+}
+do
+{
+ return 1;
+}
+
+auto dontInferNothrowOut()
+out
+{
+ throw new Exception(null);
+}
+do
+{
+ return 1;
+}
+
+enum isNothrow(Attr...) = (Attr.length >= 1)
+ && (Attr[0] == "nothrow" || isNothrow!(Attr[1 .. $]));
+
+static assert(isNothrow!(__traits(getFunctionAttributes, inferNothrow)));
+static assert(!isNothrow!(__traits(getFunctionAttributes, dontInferNothrowIn)));
+static assert(!isNothrow!(__traits(getFunctionAttributes, dontInferNothrowOut)));
diff --git a/gcc/testsuite/gdc.test/compilable/test21243.d b/gcc/testsuite/gdc.test/compilable/test21243.d
new file mode 100644
index 0000000..20838dc
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test21243.d
@@ -0,0 +1,21 @@
+// Parsing - expressions
+auto a = auto ref (int x) => x;
+auto b = auto ref (int x) { return x; };
+auto c = function auto ref (int x) { return x; };
+auto d = delegate auto ref (int x) { return x; };
+
+// Parsing - aliases
+alias e = auto ref (int x) => x;
+alias f = auto ref (int x) { return x; };
+alias g = function auto ref (int x) { return x; };
+alias h = delegate auto ref (int x) { return x; };
+
+// Semantic
+void test()
+{
+ alias fun(alias x) = auto ref () => x;
+ int n = 123;
+ auto _ = fun!123();
+ static assert(!__traits(compiles, &fun!123())); // rvalue
+ fun!n() = 456; // lvalue
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test21956.d b/gcc/testsuite/gdc.test/compilable/test21956.d
new file mode 100644
index 0000000..64ebc55
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test21956.d
@@ -0,0 +1,16 @@
+// https://issues.dlang.org/show_bug.cgi?id=21956
+
+noreturn[noreturn] nrnr;
+
+void gun()
+{
+ foreach (a; nrnr){}
+}
+
+int main()
+{
+ noreturn[] empty;
+ int val;
+ foreach(el; empty) val++;
+ return val;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test22674.d b/gcc/testsuite/gdc.test/compilable/test22674.d
new file mode 100644
index 0000000..cc6e3bb
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22674.d
@@ -0,0 +1,10 @@
+// https://issues.dlang.org/show_bug.cgi?id=22674
+// EXTRA_FILES: imports/cimports2a.i imports/cimports2b.i
+
+import imports.cimports2a;
+import imports.cimports2b;
+
+void do_foo(){
+ FooRef f = make_foo(); // use_foo.d(5)
+ free_foo(f); // use_foo.d(6)
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23173.d b/gcc/testsuite/gdc.test/compilable/test23173.d
new file mode 100644
index 0000000..6b16132
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23173.d
@@ -0,0 +1,6 @@
+// REQUIRED_ARGS: -o-
+// https://issues.dlang.org/show_bug.cgi?id=23173
+
+mixin("long l = ", long.min, ";");
+static assert(mixin(long.min) == long.min);
+static assert(is(typeof(mixin(long.min)) == long));
diff --git a/gcc/testsuite/gdc.test/compilable/test23258.d b/gcc/testsuite/gdc.test/compilable/test23258.d
new file mode 100644
index 0000000..1e8e91b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23258.d
@@ -0,0 +1,21 @@
+// https://issues.dlang.org/show_bug.cgi?id=23258
+
+struct SumType(Types...)
+{
+ this(Types[0])
+ {
+ }
+ this(Types[1])
+ {
+ }
+}
+
+alias A2 = SumType!(C1[], C2[]);
+
+class C1
+{
+}
+
+class C2
+{
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23306.d b/gcc/testsuite/gdc.test/compilable/test23306.d
new file mode 100644
index 0000000..81b51f6
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23306.d
@@ -0,0 +1,7 @@
+class A {
+ @disable new();
+}
+
+void main() {
+ scope A a = new A();
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23327.d b/gcc/testsuite/gdc.test/compilable/test23327.d
new file mode 100644
index 0000000..bbb6346
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23327.d
@@ -0,0 +1,3 @@
+// https://issues.dlang.org/show_bug.cgi?id=23327
+// EXTRA_FILES: imports/format23327.d imports/format23327/write.d
+import imports.format23327;
diff --git a/gcc/testsuite/gdc.test/compilable/vararg.d b/gcc/testsuite/gdc.test/compilable/vararg.d
new file mode 100644
index 0000000..79826a0
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/vararg.d
@@ -0,0 +1,20 @@
+void main ()
+{
+ variance([1.0, 2, 3]);
+}
+
+alias meanType(T) = T;
+
+template variance(bool stable = true)
+{
+ void variance(Range)(Range r, bool isPopulation = false)
+ {
+ .variance!(double, stable)(r, isPopulation);
+ }
+}
+
+template variance(F, bool stable = true)
+{
+ void variance(Range)(Range r, bool isPopulation = false) {}
+ void variance(scope const F[] ar...) {}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10169.d b/gcc/testsuite/gdc.test/fail_compilation/diag10169.d
index 72becf2..84d0ad4 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag10169.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag10169.d
@@ -2,7 +2,7 @@
EXTRA_FILES: imports/a10169.d
TEST_OUTPUT:
---
-fail_compilation/diag10169.d(12): Error: no property `x` for type `imports.a10169.B`
+fail_compilation/diag10169.d(12): Error: no property `x` for `B(0)` of type `imports.a10169.B`
---
*/
import imports.a10169;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10783.d b/gcc/testsuite/gdc.test/fail_compilation/diag10783.d
index f18341f..80c7f5e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag10783.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag10783.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/diag10783.d(14): Error: no property `type` for type `diag10783.Event`
+fail_compilation/diag10783.d(14): Error: no property `type` for `event` of type `diag10783.Event`
fail_compilation/diag10783.d(14): Error: undefined identifier `En`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag13528.d b/gcc/testsuite/gdc.test/fail_compilation/diag13528.d
index 5d908f7..9b5761f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag13528.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag13528.d
@@ -1,10 +1,12 @@
/*
TEST_OUTPUT:
---
-fail_compilation/diag13528.d(13): Error: value of `this` is not known at compile time
-fail_compilation/diag13528.d(13): while evaluating `pragma(msg, __traits(getMember, A, "foo"))`
+fail_compilation/diag13528.d(6): Error: value of `this` is not known at compile time
+fail_compilation/diag13528.d(6): while evaluating `pragma(msg, __traits(getMember, A, "foo"))`
+fail_compilation/diag13528.d(12): parent scope from here: `mixin MyTemplate!()`
---
*/
+#line 1
mixin template MyTemplate()
{
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag14145.d b/gcc/testsuite/gdc.test/fail_compilation/diag14145.d
index 6447f5e..fa7c611 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag14145.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag14145.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/diag14145.d(15): Error: no property `i` for type `diag14145.main.Capture!(i)`
+fail_compilation/diag14145.d(15): Error: no property `i` for `_` of type `diag14145.main.Capture!(i)`
fail_compilation/diag14145.d(15): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
fail_compilation/diag14145.d(34): Error: expression `*this.ptr` of type `shared(int)` is not implicitly convertible to return type `ref int`
fail_compilation/diag14145.d(16): Error: template instance `diag14145.main.Capture!(i).Capture.opDispatch!"i"` error instantiating
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag15713.d b/gcc/testsuite/gdc.test/fail_compilation/diag15713.d
index 1c61408..e4cb2a7 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag15713.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag15713.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/diag15713.d(19): Error: no property `widthSign` for type `diag15713.WrData.Data`
+fail_compilation/diag15713.d(19): Error: no property `widthSign` for `this` of type `diag15713.WrData.Data`
fail_compilation/diag15713.d(39): Error: template instance `diag15713.conwritefImpl!("parse-int", "width", "\n", Data(null))` error instantiating
fail_compilation/diag15713.d(44): instantiated from here: `conwritefImpl!("main", "\n", Data(null))`
fail_compilation/diag15713.d(49): instantiated from here: `fdwritef!()`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag23355.d b/gcc/testsuite/gdc.test/fail_compilation/diag23355.d
new file mode 100644
index 0000000..586cbb0
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag23355.d
@@ -0,0 +1,16 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/diag23355.d(1): Error: undefined identifier `n`
+fail_compilation/diag23355.d(4): Error: none of the overloads of template `diag23355.ffi1` are callable using argument types `!()(int[4])`
+fail_compilation/diag23355.d(1): Candidate is: `ffi1(T)(T[n] s)`
+fail_compilation/diag23355.d(2): Error: undefined identifier `n`
+fail_compilation/diag23355.d(4): Error: none of the overloads of template `diag23355.ffi2` are callable using argument types `!()(int[4])`
+fail_compilation/diag23355.d(2): Candidate is: `ffi2()(T[n] s)`
+---
+*/
+#line 1
+void ffi1(T)(T[n] s) { }
+void ffi2()(T[n] s) { }
+
+void main() { int[4] x; ffi1(x); ffi2(x); }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag3438.d b/gcc/testsuite/gdc.test/fail_compilation/diag3438.d
index 445f6d5..c4cbc72 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag3438.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag3438.d
@@ -1,4 +1,3 @@
-// REQUIRED_ARGS: -de
/*
TEST_OUTPUT:
---
@@ -8,6 +7,7 @@ fail_compilation/diag3438.d(20): Error: constructor `diag3438.F5.this` is marked
fail_compilation/diag3438.d(20): Use `@disable this();` if you want to disable default initialization.
fail_compilation/diag3438.d(21): Error: constructor `diag3438.F6.this` is marked `@disable`, so it cannot have default arguments for all parameters.
fail_compilation/diag3438.d(21): Use `@disable this();` if you want to disable default initialization.
+fail_compilation/diag3438.d(24): Error: default argument expected for `y`
---
*/
@@ -19,3 +19,6 @@ struct F3 { this(...) { } } // ok
struct F4 { this(int[] x...) { } } // ok
struct F5 { @disable this(int x = 1); }
struct F6 { @disable this(int x = 1) { } }
+
+// Make sure the deprecation doesn't interfere w/ the check for default arguments
+struct S { this(int x = 1, int y) { } }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag3438b.d b/gcc/testsuite/gdc.test/fail_compilation/diag3438b.d
deleted file mode 100644
index 46a197d..0000000
--- a/gcc/testsuite/gdc.test/fail_compilation/diag3438b.d
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/diag3438b.d(9): Error: default argument expected for `y`
----
-*/
-
-// Make sure the deprecation doesn't interfere w/ the check for default arguments
-struct S { this(int x = 1, int y) { } }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8894.d b/gcc/testsuite/gdc.test/fail_compilation/diag8894.d
index 9e0dadd..7cf3023 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag8894.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag8894.d
@@ -1,10 +1,10 @@
/*
TEST_OUTPUT:
---
-fail_compilation/diag8894.d(16): Error: no property `x` for type `diag8894.Foo`
-fail_compilation/diag8894.d(17): Error: no property `y` for type `diag8894.Foo`
-fail_compilation/diag8894.d(18): Error: no property `x` for type `diag8894.Foo`
-fail_compilation/diag8894.d(19): Error: no property `x` for type `diag8894.Foo`
+fail_compilation/diag8894.d(16): Error: no property `x` for `f` of type `diag8894.Foo`
+fail_compilation/diag8894.d(17): Error: no property `y` for `f` of type `diag8894.Foo`
+fail_compilation/diag8894.d(18): Error: no property `x` for `f` of type `diag8894.Foo`
+fail_compilation/diag8894.d(19): Error: no property `x` for `f` of type `diag8894.Foo`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/dip22a.d b/gcc/testsuite/gdc.test/fail_compilation/dip22a.d
index bf04a51..324d217 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/dip22a.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/dip22a.d
@@ -2,11 +2,11 @@
EXTRA_FILES: imports/dip22a.d
TEST_OUTPUT:
---
-fail_compilation/dip22a.d(16): Error: no property `bar` for type `imports.dip22a.Klass`
-fail_compilation/dip22a.d(17): Error: no property `bar` for type `imports.dip22a.Struct`
+fail_compilation/dip22a.d(16): Error: no property `bar` for `new Klass` of type `imports.dip22a.Klass`
+fail_compilation/dip22a.d(17): Error: no property `bar` for `Struct()` of type `imports.dip22a.Struct`
fail_compilation/dip22a.d(18): Error: undefined identifier `bar` in module `imports.dip22a`
-fail_compilation/dip22a.d(19): Error: no property `bar` for type `void`
-fail_compilation/dip22a.d(20): Error: no property `bar` for type `int`
+fail_compilation/dip22a.d(19): Error: no property `bar` for `Template!int` of type `void`
+fail_compilation/dip22a.d(20): Error: no property `bar` for `12` of type `int`
---
*/
import imports.dip22a;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d
index 33bee25..92e0734 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d
@@ -1,14 +1,15 @@
/*
TEST_OUTPUT:
---
-fail_compilation/e15876_1.d(15): Error: valid scope identifiers are `exit`, `failure`, or `success`, not `x`
-fail_compilation/e15876_1.d(16): Error: found `End of File` when expecting `)`
-fail_compilation/e15876_1.d(16): Error: found `End of File` instead of statement
-fail_compilation/e15876_1.d(16): Error: found `End of File` when expecting `}` following compound statement
-fail_compilation/e15876_1.d(16): Error: found `End of File` when expecting `]`
-fail_compilation/e15876_1.d(16): Error: no identifier for declarator `o[()
+fail_compilation/e15876_1.d(16): Error: valid scope identifiers are `exit`, `failure`, or `success`, not `x`
+fail_compilation/e15876_1.d(17): Error: found `End of File` when expecting `)`
+fail_compilation/e15876_1.d(17): Error: found `End of File` instead of statement
+fail_compilation/e15876_1.d(17): Error: found `End of File` when expecting `}` following compound statement
+fail_compilation/e15876_1.d(17): Error: found `End of File` when expecting `]`
+fail_compilation/e15876_1.d(17): Error: no identifier for declarator `o[()
{
-scope(exit) }
+scope(exit) __error__
+}
]`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d
index ae5f77a..fe7d546 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d
@@ -1,25 +1,27 @@
/*
TEST_OUTPUT:
---
-fail_compilation/e15876_3.d(25): Error: unexpected `(` in declarator
-fail_compilation/e15876_3.d(25): Error: basic type expected, not `=`
-fail_compilation/e15876_3.d(26): Error: found `End of File` when expecting `(`
-fail_compilation/e15876_3.d(26): Error: found `End of File` instead of statement
-fail_compilation/e15876_3.d(26): Error: expression expected, not `End of File`
-fail_compilation/e15876_3.d(26): Error: found `End of File` when expecting `;` following `for` condition
-fail_compilation/e15876_3.d(26): Error: expression expected, not `End of File`
-fail_compilation/e15876_3.d(26): Error: found `End of File` when expecting `)`
-fail_compilation/e15876_3.d(26): Error: found `End of File` instead of statement
-fail_compilation/e15876_3.d(26): Error: found `End of File` when expecting `}` following compound statement
-fail_compilation/e15876_3.d(26): Error: found `End of File` when expecting `)`
-fail_compilation/e15876_3.d(26): Error: no identifier for declarator `d(_error_ = ()
+fail_compilation/e15876_3.d(27): Error: unexpected `(` in declarator
+fail_compilation/e15876_3.d(27): Error: basic type expected, not `=`
+fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `(`
+fail_compilation/e15876_3.d(28): Error: found `End of File` instead of statement
+fail_compilation/e15876_3.d(28): Error: expression expected, not `End of File`
+fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `;` following `for` condition
+fail_compilation/e15876_3.d(28): Error: expression expected, not `End of File`
+fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `)`
+fail_compilation/e15876_3.d(28): Error: found `End of File` instead of statement
+fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `}` following compound statement
+fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `)`
+fail_compilation/e15876_3.d(28): Error: no identifier for declarator `d(_error_ = ()
{
-for (; 0; 0)
+for (__error__
+ 0; 0)
{
+__error__
}
}
)`
-fail_compilation/e15876_3.d(26): Error: semicolon expected following function declaration
+fail_compilation/e15876_3.d(28): Error: semicolon expected following function declaration
---
*/
d(={for
diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d
index 6f46633..f4bd407 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d
@@ -1,20 +1,22 @@
/*
TEST_OUTPUT:
---
-fail_compilation/e15876_4.d(23): Error: found `)` when expecting `(`
-fail_compilation/e15876_4.d(24): Error: found `End of File` when expecting `(`
-fail_compilation/e15876_4.d(24): Error: found `End of File` instead of statement
-fail_compilation/e15876_4.d(24): Error: expression expected, not `End of File`
-fail_compilation/e15876_4.d(24): Error: found `End of File` when expecting `;` following `for` condition
-fail_compilation/e15876_4.d(24): Error: expression expected, not `End of File`
-fail_compilation/e15876_4.d(24): Error: found `End of File` when expecting `)`
-fail_compilation/e15876_4.d(24): Error: found `End of File` instead of statement
-fail_compilation/e15876_4.d(24): Error: found `End of File` when expecting `}` following compound statement
-fail_compilation/e15876_4.d(24): Error: found `End of File` when expecting `)`
-fail_compilation/e15876_4.d(24): Error: no identifier for declarator `typeof(()
+fail_compilation/e15876_4.d(25): Error: found `)` when expecting `(`
+fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `(`
+fail_compilation/e15876_4.d(26): Error: found `End of File` instead of statement
+fail_compilation/e15876_4.d(26): Error: expression expected, not `End of File`
+fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `;` following `for` condition
+fail_compilation/e15876_4.d(26): Error: expression expected, not `End of File`
+fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `)`
+fail_compilation/e15876_4.d(26): Error: found `End of File` instead of statement
+fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `}` following compound statement
+fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `)`
+fail_compilation/e15876_4.d(26): Error: no identifier for declarator `typeof(()
{
-for (; 0; 0)
+for (__error__
+ 0; 0)
{
+__error__
}
}
)`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail10968.d b/gcc/testsuite/gdc.test/fail_compilation/fail10968.d
index e969b24..cfda8f4 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail10968.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail10968.d
@@ -1,27 +1,28 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail10968.d(42): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(42): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(43): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(43): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here
+fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(44): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(44): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here
-fail_compilation/fail10968.d(44): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.arrayassign._d_arrayassign_l!(SA[], SA)._d_arrayassign_l`
-fail_compilation/fail10968.d(47): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(47): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here
+fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
+fail_compilation/fail10968.d(44): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.arrayassign._d_arraysetassign!(SA[], SA)._d_arraysetassign`
+fail_compilation/fail10968.d(45): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
+fail_compilation/fail10968.d(45): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
+fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
+fail_compilation/fail10968.d(45): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.arrayassign._d_arrayassign_l!(SA[], SA)._d_arrayassign_l`
fail_compilation/fail10968.d(48): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(48): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here
-fail_compilation/fail10968.d(48): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arraysetctor!(SA[], SA)._d_arraysetctor`
+fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(49): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(49): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here
-fail_compilation/fail10968.d(49): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arrayctor!(SA[], SA)._d_arrayctor`
+fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
+fail_compilation/fail10968.d(49): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arraysetctor!(SA[], SA)._d_arraysetctor`
+fail_compilation/fail10968.d(50): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
+fail_compilation/fail10968.d(50): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
+fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
+fail_compilation/fail10968.d(50): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arrayctor!(SA[], SA)._d_arrayctor`
---
*/
@@ -52,12 +53,12 @@ void bar() pure @safe
/*
TEST_OUTPUT:
---
-fail_compilation/fail10968.d(75): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
fail_compilation/fail10968.d(76): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
fail_compilation/fail10968.d(77): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
-fail_compilation/fail10968.d(80): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
+fail_compilation/fail10968.d(78): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
fail_compilation/fail10968.d(81): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
fail_compilation/fail10968.d(82): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
+fail_compilation/fail10968.d(83): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail121.d b/gcc/testsuite/gdc.test/fail_compilation/fail121.d
index 70e9d0c..8d5af74 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail121.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail121.d
@@ -3,8 +3,8 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail121.d(23): Error: no property `typeinfo` for type `fail121.myobject`
-fail_compilation/fail121.d(23): Error: no property `typeinfo` for type `int`
+fail_compilation/fail121.d(23): Error: no property `typeinfo` for `list[1]` of type `fail121.myobject`
+fail_compilation/fail121.d(23): Error: no property `typeinfo` for `i` of type `int`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail13123.d b/gcc/testsuite/gdc.test/fail_compilation/fail13123.d
new file mode 100644
index 0000000..7784cba
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail13123.d
@@ -0,0 +1,21 @@
+// REQUIRED_ARGS: -de
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail13123.d(10): Deprecation: `fail13123.test`: `in` contract may throw but function is marked as `nothrow`
+fail_compilation/fail13123.d(10): Deprecation: `fail13123.test`: `out` contract may throw but function is marked as `nothrow`
+---
+*/
+
+void test() nothrow
+in
+{
+ throw new Exception(null);
+}
+out
+{
+ throw new Exception(null);
+}
+do
+{
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail17646.d b/gcc/testsuite/gdc.test/fail_compilation/fail17646.d
index 3571e38..39e7cb9 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail17646.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail17646.d
@@ -4,9 +4,8 @@ EXTRA_FILES: imports/fail17646.d
TEST_OUTPUT:
---
fail_compilation/imports/fail17646.d(10): Error: found `}` instead of statement
-fail_compilation/imports/fail17646.d(7): Error: function `imports.fail17646.allTestData!"".allTestData` has no `return` statement, but is expected to return a value of type `const(TestData)[]`
-fail_compilation/fail17646.d(16): Error: template instance `imports.fail17646.allTestData!""` error instantiating
-fail_compilation/fail17646.d(19): instantiated from here: `runTests!""`
+fail_compilation/fail17646.d(11): Error: function `fail17646.runTests!"".runTests` has no `return` statement, but is expected to return a value of type `int`
+fail_compilation/fail17646.d(18): Error: template instance `fail17646.runTests!""` error instantiating
---
*/
int runTests(Modules...)()
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18892.d b/gcc/testsuite/gdc.test/fail_compilation/fail18892.d
index 531d1ed..0fb56d3 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail18892.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail18892.d
@@ -1,8 +1,8 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail18892.d(20): Error: no property `foo` for type `fail18892.MT`
-fail_compilation/fail18892.d(21): Error: no property `foo` for type `fail18892.MT`
+fail_compilation/fail18892.d(20): Error: no property `foo` for `a` of type `fail18892.MT`
+fail_compilation/fail18892.d(21): Error: no property `foo` for `MT` of type `fail18892.MT`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18970.d b/gcc/testsuite/gdc.test/fail_compilation/fail18970.d
index 0973217..a8156fe 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail18970.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail18970.d
@@ -1,9 +1,9 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail18970.d(24): Error: no property `y` for type `fail18970.S`
+fail_compilation/fail18970.d(24): Error: no property `y` for `S()` of type `fail18970.S`
fail_compilation/fail18970.d(24): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
-fail_compilation/fail18970.d(31): Error: no property `yyy` for type `fail18970.S2`
+fail_compilation/fail18970.d(31): Error: no property `yyy` for `this` of type `fail18970.S2`
fail_compilation/fail18970.d(31): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18979.d b/gcc/testsuite/gdc.test/fail_compilation/fail18979.d
index 9756570..04e36f6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail18979.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail18979.d
@@ -2,7 +2,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail18979.d(13): Error: no property `__ctor` for type `imports.imp18979.Foo`
+fail_compilation/fail18979.d(13): Error: no property `__ctor` for `Foo()` of type `imports.imp18979.Foo`
----
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19103.d b/gcc/testsuite/gdc.test/fail_compilation/fail19103.d
index 6b740ac..40fafcd 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19103.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19103.d
@@ -1,8 +1,8 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail19103.d(12): Error: no property `puts` for type `fail19103.C`
-fail_compilation/fail19103.d(14): Error: no property `puts` for type `fail19103.S1`
+fail_compilation/fail19103.d(12): Error: no property `puts` for `new C` of type `fail19103.C`
+fail_compilation/fail19103.d(14): Error: no property `puts` for `s1` of type `fail19103.S1`
fail_compilation/fail19103.d(16): Error: no property `puts` for type `S2`, did you mean `core.stdc.stdio.puts`?
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19687.d b/gcc/testsuite/gdc.test/fail_compilation/fail19687.d
index 7d1c6e5..0076091 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19687.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19687.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail19687.d(17): Error: no property `nonexisting` for type `string`
+fail_compilation/fail19687.d(17): Error: no property `nonexisting` for `""` of type `string`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19913.d b/gcc/testsuite/gdc.test/fail_compilation/fail19913.d
index fe2655e..c880923 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19913.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19913.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail19913.d(11): Error: no property `b` for type `int`
+fail_compilation/fail19913.d(11): Error: no property `b` for `a` of type `int`
fail_compilation/fail19913.d(11): Error: mixin `fail19913.S.b!()` is not defined
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21243.d b/gcc/testsuite/gdc.test/fail_compilation/fail21243.d
new file mode 100644
index 0000000..25df235
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21243.d
@@ -0,0 +1,19 @@
+/+ TEST_OUTPUT:
+---
+fail_compilation/fail21243.d(16): Error: found `(` when expecting `ref` and function literal following `auto`
+fail_compilation/fail21243.d(16): Error: semicolon expected following auto declaration, not `int`
+fail_compilation/fail21243.d(16): Error: semicolon needed to end declaration of `x` instead of `)`
+fail_compilation/fail21243.d(16): Error: declaration expected, not `)`
+fail_compilation/fail21243.d(17): Error: `auto` can only be used as part of `auto ref` for function literal return values
+fail_compilation/fail21243.d(18): Error: basic type expected, not `(`
+fail_compilation/fail21243.d(18): Error: function declaration without return type. (Note that constructors are always named `this`)
+fail_compilation/fail21243.d(18): Deprecation: storage class `auto` has no effect in type aliases
+fail_compilation/fail21243.d(18): Error: semicolon expected to close `alias` declaration
+fail_compilation/fail21243.d(18): Error: declaration expected, not `=>`
+fail_compilation/fail21243.d(19): Error: `auto` can only be used as part of `auto ref` for function literal return values
+---
++/
+auto a = auto (int x) => x;
+auto b = function auto (int x) { return x; };
+alias c = auto (int x) => x;
+alias d = function auto (int x) { return x; };
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23109.d b/gcc/testsuite/gdc.test/fail_compilation/fail23109.d
index 91b4e79..5c5c11b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail23109.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail23109.d
@@ -4,8 +4,8 @@ EXTRA_FILES: imports/test23109a.d imports/test23109b.d imports/test23109c.d
EXTRA_SOURCES: extra-files/test23109/object.d
TEST_OUTPUT:
---
-Error: no property `getHash` for type `object.TypeInfo_Const`
-Error: no property `getHash` for type `object.TypeInfo_Const`
+Error: no property `getHash` for `typeid(const(Ensure[]))` of type `object.TypeInfo_Const`
+Error: no property `getHash` for `typeid(const(Ensure[1]))` of type `object.TypeInfo_Const`
fail_compilation/imports/test23109a.d(10): Error: template instance `imports.test23109a.Array!(Ensure)` error instantiating
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7372.d b/gcc/testsuite/gdc.test/fail_compilation/fail7372.d
new file mode 100644
index 0000000..2d56e09
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail7372.d
@@ -0,0 +1,13 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/imports/fail7372.d(7): Error: undefined identifier `X`
+fail_compilation/fail7372.d(4): parent scope from here: `mixin Issue7372!()`
+---
+*/
+#line 1
+import imports.fail7372;
+interface I {}
+class C : I {
+ mixin Issue7372!();
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d b/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d
index d7853e6..c44b289 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/faildottypeinfo.d(11): Error: no property `typeinfo` for type `int`
+fail_compilation/faildottypeinfo.d(11): Error: no property `typeinfo` for `0` of type `int`
fail_compilation/faildottypeinfo.d(12): Error: no property `typeinfo` for type `object.Object`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/failoffset.d b/gcc/testsuite/gdc.test/fail_compilation/failoffset.d
index bbec698..ff0d26b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/failoffset.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/failoffset.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/failoffset.d(12): Error: no property `offset` for type `int`
+fail_compilation/failoffset.d(12): Error: no property `offset` for `b` of type `int`
fail_compilation/failoffset.d(12): while evaluating: `static assert(b.offset == 4)`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10938.d b/gcc/testsuite/gdc.test/fail_compilation/ice10938.d
index 2084e32..d21ee47 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice10938.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice10938.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice10938.d(13): Error: no property `opts` for type `ice10938.C`
+fail_compilation/ice10938.d(13): Error: no property `opts` for `this` of type `ice10938.C`
fail_compilation/ice10938.d(13): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice12174.d b/gcc/testsuite/gdc.test/fail_compilation/ice12174.d
index 019722a..dbe386e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice12174.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice12174.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice12174.d(12): Error: no property `sum` for type `int[]`
+fail_compilation/ice12174.d(12): Error: no property `sum` for `[1, 2, 3]` of type `int[]`
fail_compilation/ice12174.d(20): Error: CTFE failed because of previous errors in `this`
fail_compilation/ice12174.d(13): called from here: `filter([1, 2, 3])`
---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice15855.d b/gcc/testsuite/gdc.test/fail_compilation/ice15855.d
index e800838..b26fe4c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice15855.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice15855.d
@@ -2,19 +2,21 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice15855.d(25): Error: found `End of File` when expecting `(`
-fail_compilation/ice15855.d(25): Error: found `End of File` instead of statement
-fail_compilation/ice15855.d(25): Error: expression expected, not `End of File`
-fail_compilation/ice15855.d(25): Error: found `End of File` when expecting `;` following `for` condition
-fail_compilation/ice15855.d(25): Error: expression expected, not `End of File`
-fail_compilation/ice15855.d(25): Error: found `End of File` when expecting `)`
-fail_compilation/ice15855.d(25): Error: found `End of File` instead of statement
-fail_compilation/ice15855.d(25): Error: found `End of File` when expecting `}` following compound statement
-fail_compilation/ice15855.d(25): Error: found `End of File` when expecting `]`
-fail_compilation/ice15855.d(25): Error: no identifier for declarator `a[()
+fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `(`
+fail_compilation/ice15855.d(27): Error: found `End of File` instead of statement
+fail_compilation/ice15855.d(27): Error: expression expected, not `End of File`
+fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `;` following `for` condition
+fail_compilation/ice15855.d(27): Error: expression expected, not `End of File`
+fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `)`
+fail_compilation/ice15855.d(27): Error: found `End of File` instead of statement
+fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `}` following compound statement
+fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `]`
+fail_compilation/ice15855.d(27): Error: no identifier for declarator `a[()
{
-for (; 0; 0)
+for (__error__
+ 0; 0)
{
+__error__
}
}
]`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice18469.d b/gcc/testsuite/gdc.test/fail_compilation/ice18469.d
index 8803956..796dd3d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice18469.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice18469.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice18469.d(10): Error: no property `opCall` for type `void`
+fail_compilation/ice18469.d(10): Error: no property `opCall` for `this.~this()` of type `void`
---
*/
class Bar
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice19755.d b/gcc/testsuite/gdc.test/fail_compilation/ice19755.d
index f948477..6d60fc4 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice19755.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice19755.d
@@ -1,6 +1,6 @@
/* TEST_OUTPUT:
---
-fail_compilation/ice19755.d(11): Error: no property `x` for type `ice19755.Thunk!int*`
+fail_compilation/ice19755.d(11): Error: no property `x` for `self` of type `ice19755.Thunk!int*`
fail_compilation/ice19755.d(16): Error: template instance `ice19755.Thunk!int` error instantiating
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/fail7372.d b/gcc/testsuite/gdc.test/fail_compilation/imports/fail7372.d
new file mode 100644
index 0000000..f71c736
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/fail7372.d
@@ -0,0 +1,9 @@
+module imports.fail7372;
+import imports.imp1;
+mixin template Issue7372()
+{
+ public void f()
+ {
+ int foo = X;
+ }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d b/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d
index b50a616..11fddf0 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d
@@ -22,7 +22,6 @@ fail_compilation/misc_parser_err_cov1.d(39): Error: expression expected, not `;`
fail_compilation/misc_parser_err_cov1.d(40): Error: semicolon expected following auto declaration, not `auto`
fail_compilation/misc_parser_err_cov1.d(40): Error: identifier or `new` expected following `.`, not `+`
fail_compilation/misc_parser_err_cov1.d(41): Error: identifier or new keyword expected following `(...)`.
-fail_compilation/misc_parser_err_cov1.d(41): Error: found `.` when expecting `;` following statement
fail_compilation/misc_parser_err_cov1.d(41): Error: expression expected, not `;`
fail_compilation/misc_parser_err_cov1.d(42): Error: found `}` when expecting `;` following statement
fail_compilation/misc_parser_err_cov1.d(43): Error: found `End of File` when expecting `}` following compound statement
diff --git a/gcc/testsuite/gdc.test/fail_compilation/mixinprop.d b/gcc/testsuite/gdc.test/fail_compilation/mixinprop.d
new file mode 100644
index 0000000..db8bf59
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/mixinprop.d
@@ -0,0 +1,13 @@
+/* TEST_OUTPUT:
+---
+fail_compilation/mixinprop.d(12): Error: no property `x` for `mixin Foo!() F;
+` of type `void`
+---
+*/
+mixin template Foo() { }
+
+void main()
+{
+ mixin Foo F;
+ F.x;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15785.d b/gcc/testsuite/gdc.test/fail_compilation/test15785.d
index 23a3660..594b5d3 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test15785.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test15785.d
@@ -2,7 +2,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/test15785.d(16): Error: no property `foo` for type `imports.test15785.Base`
+fail_compilation/test15785.d(16): Error: no property `foo` for `super` of type `imports.test15785.Base`
fail_compilation/test15785.d(17): Error: undefined identifier `bar`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15897.d b/gcc/testsuite/gdc.test/fail_compilation/test15897.d
index e4ade7d..db554cb 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test15897.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test15897.d
@@ -3,7 +3,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/test15897.d(19): Error: no property `create` for type `imports.test15897.Cat`
+fail_compilation/test15897.d(19): Error: no property `create` for `cat` of type `imports.test15897.Cat`
---
*/
module test15897;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16188.d b/gcc/testsuite/gdc.test/fail_compilation/test16188.d
index c4a0fa6..bdaae94 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test16188.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test16188.d
@@ -1,7 +1,7 @@
/* REQUIRED_ARGS: -preview=bitfields
* TEST_OUTPUT:
---
-fail_compilation/test16188.d(101): Error: no property `name` for type `test16188.Where`
+fail_compilation/test16188.d(101): Error: no property `name` for `Where()` of type `test16188.Where`
fail_compilation/test16188.d(101): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d b/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d
index 2456a59..f523337 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d
@@ -2,7 +2,7 @@
TEST_OUTPUT:
---
(spec:1) fail_compilation/test17380spec.d(14): Error: cannot resolve identifier `ThisTypeDoesNotExistAndCrashesTheCompiler`
-(spec:1) fail_compilation/test17380spec.d(14): Error: no property `ThisTypeDoesNotExistAndCrashesTheCompiler` for type `test17380spec.Uint128`
+(spec:1) fail_compilation/test17380spec.d(14): Error: no property `ThisTypeDoesNotExistAndCrashesTheCompiler` for `this.opCast()` of type `test17380spec.Uint128`
fail_compilation/test17380spec.d(14): Error: undefined identifier `ThisTypeDoesNotExistAndCrashesTheCompiler`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21096.d b/gcc/testsuite/gdc.test/fail_compilation/test21096.d
index e32ad9c..302eb3d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test21096.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21096.d
@@ -3,10 +3,8 @@
/*
TEST_OUTPUT:
---
-fail_compilation/test21096.d(13): Error: identifier or new keyword expected following `(...)`.
-fail_compilation/test21096.d(13): Error: found `.` when expecting `]`
-fail_compilation/test21096.d(13): Error: no identifier for declarator `char`
-fail_compilation/test21096.d(13): Error: declaration expected, not `]`
+fail_compilation/test21096.d(11): Error: identifier or new keyword expected following `(...)`.
+fail_compilation/test21096.d(11): Error: no identifier for declarator `char[(__error)]`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22680.d b/gcc/testsuite/gdc.test/fail_compilation/test22680.d
new file mode 100644
index 0000000..caf0f4a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test22680.d
@@ -0,0 +1,17 @@
+/* REQUIRED_ARGS: -preview=dip1000
+TEST_OUTPUT:
+---
+fail_compilation/test22680.d(104): Error: scope variable `this` assigned to non-scope `c`
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=22680
+
+#line 100
+
+C c;
+class C {
+ ~this() @safe {
+ c = this;
+ }
+}
diff --git a/gcc/testsuite/gdc.test/runnable/newaa.d b/gcc/testsuite/gdc.test/runnable/newaa.d
new file mode 100644
index 0000000..94e79d5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/newaa.d
@@ -0,0 +1,23 @@
+void main()
+{
+ alias AA = int[string];
+ // aa is not ref
+ static void test(AA aa)
+ {
+ aa[""] = 0;
+ }
+ auto aa = new AA();
+ auto ab = new int[string];
+ auto ac = new typeof(aa);
+ test(aa);
+ test(ab);
+ test(ac);
+ assert(aa.length);
+ assert(ab.length);
+ assert(ac.length);
+
+ int[string] a = new int[string];
+ auto b = a;
+ a["seven"] = 7;
+ assert(b["seven"] == 7);
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test23234.d b/gcc/testsuite/gdc.test/runnable/test23234.d
new file mode 100644
index 0000000..7872aa7
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test23234.d
@@ -0,0 +1,22 @@
+// https://issues.dlang.org/show_bug.cgi?id=23234
+
+class Bar
+{
+}
+
+class Foo
+{
+ Bar get() { return new Bar; }
+ alias get this;
+}
+
+void main()
+{
+ auto foo = new Foo;
+ void test(Bar delegate() dg)
+ {
+ assert(dg() !is null);
+ }
+
+ test(() => foo);
+}
diff --git a/gcc/testsuite/gdc.test/runnable/testassign.d b/gcc/testsuite/gdc.test/runnable/testassign.d
index f47d2b2..586aea8 100644
--- a/gcc/testsuite/gdc.test/runnable/testassign.d
+++ b/gcc/testsuite/gdc.test/runnable/testassign.d
@@ -230,6 +230,21 @@ void test5()
static assert(!__traits(compiles, s.err += 1));
}
+void test6()
+{
+ int dtors;
+ struct S6
+ {
+ @disable this(this);
+ ~this() { dtors++; }
+ }
+
+ S6[2] arr;
+ arr = S6();
+
+ assert(dtors == 2);
+}
+
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=4424
@@ -1192,6 +1207,7 @@ int main()
test3();
test4();
test5();
+ test6();
test4424();
test6174a();
test6174b();
diff --git a/gcc/testsuite/gfortran.dg/pr107054.f90 b/gcc/testsuite/gfortran.dg/pr107054.f90
new file mode 100644
index 0000000..bbfe646
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr107054.f90
@@ -0,0 +1,13 @@
+! { dg-do compile }
+! PR fortran/107054 - ICE in gfc_simplify_unpack
+! Contributed by G.Steinmetz
+
+program p
+ type t
+ integer :: n = 0
+ end type
+ type(t), parameter :: a(4) = t(2)
+ type(t), parameter :: b(4) = reshape(a,[2]) ! { dg-error "Different shape" }
+ type(t), parameter :: c(2) = pack(b,[.false.,.true.,.false.,.true.]) ! { dg-error "Different shape" }
+ type(t), parameter :: d(4) = unpack(c,[.false.,.true.,.false.,.true.],a)
+end
diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
index 53be0c2..ade66c5 100644
--- a/gcc/tree-cfg.cc
+++ b/gcc/tree-cfg.cc
@@ -1166,7 +1166,33 @@ same_line_p (location_t locus1, expanded_location *from, location_t locus2)
&& filename_cmp (from->file, to.file) == 0);
}
-/* Assign discriminators to each basic block. */
+/* Assign a unique discriminator value to all statements in block bb that
+ have the same line number as locus. */
+
+static void
+assign_discriminator (location_t locus, basic_block bb)
+{
+ gimple_stmt_iterator gsi;
+ int discriminator;
+
+ if (locus == UNKNOWN_LOCATION)
+ return;
+
+ expanded_location locus_e = expand_location (locus);
+
+ discriminator = next_discriminator_for_locus (locus_e.line);
+
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ location_t stmt_locus = gimple_location (stmt);
+ if (same_line_p (locus, &locus_e, stmt_locus))
+ gimple_set_location (stmt,
+ location_with_discriminator (stmt_locus, discriminator));
+ }
+}
+
+/* Assign discriminators to statement locations. */
static void
assign_discriminators (void)
@@ -1189,17 +1215,22 @@ assign_discriminators (void)
{
gimple *first = first_non_label_stmt (e->dest);
gimple *last = last_stmt (e->dest);
- if ((first && same_line_p (locus, &locus_e,
+
+ gimple *stmt_on_same_line = NULL;
+ if (first && same_line_p (locus, &locus_e,
gimple_location (first)))
- || (last && same_line_p (locus, &locus_e,
- gimple_location (last))))
+ stmt_on_same_line = first;
+ else if (last && same_line_p (locus, &locus_e,
+ gimple_location (last)))
+ stmt_on_same_line = last;
+
+ if (stmt_on_same_line)
{
- if (e->dest->discriminator != 0 && bb->discriminator == 0)
- bb->discriminator
- = next_discriminator_for_locus (locus_e.line);
+ if (has_discriminator (gimple_location (stmt_on_same_line))
+ && !has_discriminator (locus))
+ assign_discriminator (locus, bb);
else
- e->dest->discriminator
- = next_discriminator_for_locus (locus_e.line);
+ assign_discriminator (locus, e->dest);
}
}
}
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 80c2bcb..55807fe 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -690,6 +690,10 @@ enum tree_index {
- TI_FLOATN_NX_TYPE_FIRST \
+ 1)
+ /* Type used by certain backends for __float128, which in C++ should be
+ distinct type from _Float128 for backwards compatibility reasons. */
+ TI_FLOAT128T_TYPE,
+
/* Put the complex types after their component types, so that in (sequential)
tree streaming we can assert that their component types have already been
handled (see tree-streamer.cc:record_common_node). */
diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc
index 33b12c7..e7a8c94 100644
--- a/gcc/tree-pretty-print.cc
+++ b/gcc/tree-pretty-print.cc
@@ -1455,6 +1455,7 @@ void
dump_location (pretty_printer *pp, location_t loc)
{
expanded_location xloc = expand_location (loc);
+ int discriminator = get_discriminator_from_loc (loc);
pp_left_bracket (pp);
if (xloc.file)
@@ -1465,6 +1466,11 @@ dump_location (pretty_printer *pp, location_t loc)
pp_decimal_int (pp, xloc.line);
pp_colon (pp);
pp_decimal_int (pp, xloc.column);
+ if (discriminator)
+ {
+ pp_string (pp, " discrim ");
+ pp_decimal_int (pp, discriminator);
+ }
pp_string (pp, "] ");
}
diff --git a/gcc/tree-ssa-reassoc.cc b/gcc/tree-ssa-reassoc.cc
index c5c8b68..b39c3c8 100644
--- a/gcc/tree-ssa-reassoc.cc
+++ b/gcc/tree-ssa-reassoc.cc
@@ -3608,13 +3608,13 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
tree type2 = NULL_TREE;
bool strict_overflow_p = false;
candidates.truncate (0);
- if (POINTER_TYPE_P (type1))
+ if (POINTER_TYPE_P (type1) || TREE_CODE (type1) == OFFSET_TYPE)
type1 = pointer_sized_int_node;
for (j = i; j; j = chains[j - 1])
{
tree type = TREE_TYPE (ranges[j - 1].exp);
strict_overflow_p |= ranges[j - 1].strict_overflow_p;
- if (POINTER_TYPE_P (type))
+ if (POINTER_TYPE_P (type) || TREE_CODE (type) == OFFSET_TYPE)
type = pointer_sized_int_node;
if ((b % 4) == 3)
{
@@ -3646,7 +3646,7 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
tree type = TREE_TYPE (ranges[j - 1].exp);
if (j == k)
continue;
- if (POINTER_TYPE_P (type))
+ if (POINTER_TYPE_P (type) || TREE_CODE (type) == OFFSET_TYPE)
type = pointer_sized_int_node;
if ((b % 4) == 3)
{
@@ -3677,10 +3677,20 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
op = r->exp;
continue;
}
- if (id == l || POINTER_TYPE_P (TREE_TYPE (op)))
+ if (id == l
+ || POINTER_TYPE_P (TREE_TYPE (op))
+ || TREE_CODE (TREE_TYPE (op)) == OFFSET_TYPE)
{
code = (b % 4) == 3 ? BIT_NOT_EXPR : NOP_EXPR;
tree type3 = id >= l ? type1 : pointer_sized_int_node;
+ if (code == BIT_NOT_EXPR
+ && TREE_CODE (TREE_TYPE (op)) == OFFSET_TYPE)
+ {
+ g = gimple_build_assign (make_ssa_name (type3),
+ NOP_EXPR, op);
+ gimple_seq_add_stmt_without_update (&seq, g);
+ op = gimple_assign_lhs (g);
+ }
g = gimple_build_assign (make_ssa_name (type3), code, op);
gimple_seq_add_stmt_without_update (&seq, g);
op = gimple_assign_lhs (g);
@@ -3688,6 +3698,7 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
tree type = TREE_TYPE (r->exp);
tree exp = r->exp;
if (POINTER_TYPE_P (type)
+ || TREE_CODE (type) == OFFSET_TYPE
|| (id >= l && !useless_type_conversion_p (type1, type)))
{
tree type3 = id >= l ? type1 : pointer_sized_int_node;
@@ -3705,7 +3716,7 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
op = gimple_assign_lhs (g);
}
type1 = TREE_TYPE (ranges[k - 1].exp);
- if (POINTER_TYPE_P (type1))
+ if (POINTER_TYPE_P (type1) || TREE_CODE (type1) == OFFSET_TYPE)
{
gimple *g
= gimple_build_assign (make_ssa_name (type1), NOP_EXPR, op);
diff --git a/gcc/tree-ssa-uninit.cc b/gcc/tree-ssa-uninit.cc
index eae29f8..bde2399 100644
--- a/gcc/tree-ssa-uninit.cc
+++ b/gcc/tree-ssa-uninit.cc
@@ -991,14 +991,20 @@ warn_uninitialized_vars (bool wmaybe_uninit)
auto_bb_flag ft_reachable (cfun);
/* Mark blocks that are always executed when we ignore provably
- not executed edges. */
+ not executed and EH and abnormal edges. */
basic_block bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
while (!(bb->flags & ft_reachable))
{
bb->flags |= ft_reachable;
+ edge e = find_fallthru_edge (bb->succs);
+ if (e && e->flags & EDGE_EXECUTABLE)
+ {
+ bb = e->dest;
+ continue;
+ }
/* Find a single executable edge. */
edge_iterator ei;
- edge e, ee = NULL;
+ edge ee = NULL;
FOR_EACH_EDGE (e, ei, bb->succs)
if (e->flags & EDGE_EXECUTABLE)
{
diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
index 74b221a..1d96130 100644
--- a/gcc/tree-vect-loop-manip.cc
+++ b/gcc/tree-vect-loop-manip.cc
@@ -1413,6 +1413,7 @@ vect_can_advance_ivs_p (loop_vec_info loop_vinfo)
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
tree evolution_part;
+ enum vect_induction_op_type induction_type;
gphi *phi = gsi.phi ();
stmt_vec_info phi_info = loop_vinfo->lookup_stmt (phi);
@@ -1432,6 +1433,15 @@ vect_can_advance_ivs_p (loop_vec_info loop_vinfo)
continue;
}
+ induction_type = STMT_VINFO_LOOP_PHI_EVOLUTION_TYPE (phi_info);
+ if (induction_type != vect_step_op_add)
+ {
+ if (!vect_can_peel_nonlinear_iv_p (loop_vinfo, induction_type))
+ return false;
+
+ continue;
+ }
+
/* Analyze the evolution function. */
evolution_part = STMT_VINFO_LOOP_PHI_EVOLUTION_PART (phi_info);
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index aabdc6f..2536cc3 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -8558,6 +8558,50 @@ vect_update_nonlinear_iv (gimple_seq* stmts, tree vectype,
return vec_def;
}
+
+/* Return true if vectorizer can peel for nonlinear iv. */
+bool
+vect_can_peel_nonlinear_iv_p (loop_vec_info loop_vinfo,
+ enum vect_induction_op_type induction_type)
+{
+ tree niters_skip;
+ /* Init_expr will be update by vect_update_ivs_after_vectorizer,
+ if niters is unkown:
+ For shift, when shift mount >= precision, there would be UD.
+ For mult, don't known how to generate
+ init_expr * pow (step, niters) for variable niters.
+ For neg, it should be ok, since niters of vectorized main loop
+ will always be multiple of 2. */
+ if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
+ && induction_type != vect_step_op_neg)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Peeling for epilogue is not supported"
+ " for nonlinear induction except neg"
+ " when iteration count is unknown.\n");
+ return false;
+ }
+
+ /* Also doens't support peel for neg when niter is variable.
+ ??? generate something like niter_expr & 1 ? init_expr : -init_expr? */
+ niters_skip = LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo);
+ if ((niters_skip != NULL_TREE
+ && TREE_CODE (niters_skip) != INTEGER_CST)
+ || (!vect_use_loop_mask_for_alignment_p (loop_vinfo)
+ && LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) < 0))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Peeling for alignement is not supported"
+ " for nonlinear induction when niters_skip"
+ " is not constant.\n");
+ return false;
+ }
+
+ return true;
+}
+
/* Function vectorizable_induction
Check if STMT_INFO performs an nonlinear induction computation that can be
@@ -8628,42 +8672,9 @@ vectorizable_nonlinear_induction (loop_vec_info loop_vinfo,
return false;
}
- /* Init_expr will be update by vect_update_ivs_after_vectorizer,
- if niters is unkown:
- For shift, when shift mount >= precision, there would be UD.
- For mult, don't known how to generate
- init_expr * pow (step, niters) for variable niters.
- For neg, it should be ok, since niters of vectorized main loop
- will always be multiple of 2. */
- if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
- && induction_type != vect_step_op_neg)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Peeling for epilogue is not supported"
- " for nonlinear induction except neg"
- " when iteration count is unknown.\n");
- return false;
- }
-
- /* Also doens't support peel for neg when niter is variable.
- ??? generate something like niter_expr & 1 ? init_expr : -init_expr? */
- niters_skip = LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo);
- if ((niters_skip != NULL_TREE
- && TREE_CODE (niters_skip) != INTEGER_CST)
- || (!vect_use_loop_mask_for_alignment_p (loop_vinfo)
- && LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) < 0))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Peeling for alignement is not supported"
- " for nonlinear induction when niters_skip"
- " is not constant.\n");
- return false;
- }
+ if (!vect_can_peel_nonlinear_iv_p (loop_vinfo, induction_type))
+ return false;
- if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
- && induction_type == vect_step_op_mul)
if (!INTEGRAL_TYPE_P (TREE_TYPE (vectype)))
{
if (dump_enabled_p ())
@@ -8799,6 +8810,7 @@ vectorizable_nonlinear_induction (loop_vec_info loop_vinfo,
gimple_seq stmts = NULL;
+ niters_skip = LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo);
/* If we are using the loop mask to "peel" for alignment then we need
to adjust the start value here. */
if (niters_skip != NULL_TREE)
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 5e75ed1..4870c75 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -2343,6 +2343,9 @@ extern tree cse_and_gimplify_to_preheader (loop_vec_info, tree);
/* Nonlinear induction. */
extern tree vect_peel_nonlinear_iv_init (gimple_seq*, tree, tree,
tree, enum vect_induction_op_type);
+extern bool
+vect_can_peel_nonlinear_iv_p (loop_vec_info loop_vinfo,
+ enum vect_induction_op_type induction_type);
/* In tree-vect-slp.cc. */
extern void vect_slp_init (void);
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 4165cbd..f8d24b5 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -9461,6 +9461,7 @@ build_common_tree_nodes (bool signed_char)
layout_type (FLOATN_NX_TYPE_NODE (i));
SET_TYPE_MODE (FLOATN_NX_TYPE_NODE (i), mode);
}
+ float128t_type_node = float128_type_node;
float_ptr_type_node = build_pointer_type (float_type_node);
double_ptr_type_node = build_pointer_type (double_type_node);
@@ -14252,7 +14253,8 @@ set_block (location_t loc, tree block)
{
location_t pure_loc = get_pure_location (loc);
source_range src_range = get_range_from_loc (line_table, loc);
- return COMBINE_LOCATION_DATA (line_table, pure_loc, src_range, block);
+ unsigned discriminator = get_discriminator_from_loc (line_table, loc);
+ return COMBINE_LOCATION_DATA (line_table, pure_loc, src_range, block, discriminator);
}
location_t
@@ -14270,11 +14272,14 @@ set_source_range (tree expr, source_range src_range)
if (!EXPR_P (expr))
return UNKNOWN_LOCATION;
- location_t pure_loc = get_pure_location (EXPR_LOCATION (expr));
+ location_t expr_location = EXPR_LOCATION (expr);
+ location_t pure_loc = get_pure_location (expr_location);
+ unsigned discriminator = get_discriminator_from_loc (expr_location);
location_t adhoc = COMBINE_LOCATION_DATA (line_table,
pure_loc,
src_range,
- NULL);
+ NULL,
+ discriminator);
SET_EXPR_LOCATION (expr, adhoc);
return adhoc;
}
diff --git a/gcc/tree.h b/gcc/tree.h
index 266e24a..95285e4 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4302,6 +4302,10 @@ tree_strip_any_location_wrapper (tree exp)
#define float64x_type_node global_trees[TI_FLOAT64X_TYPE]
#define float128x_type_node global_trees[TI_FLOAT128X_TYPE]
+/* Type used by certain backends for __float128, which in C++ should be
+ distinct type from _Float128 for backwards compatibility reasons. */
+#define float128t_type_node global_trees[TI_FLOAT128T_TYPE]
+
#define float_ptr_type_node global_trees[TI_FLOAT_PTR_TYPE]
#define double_ptr_type_node global_trees[TI_DOUBLE_PTR_TYPE]
#define long_double_ptr_type_node global_trees[TI_LONG_DOUBLE_PTR_TYPE]
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 754379a..6154d73 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -2930,6 +2930,19 @@ irange::set_nonzero_bits (const wide_int_ref &bits)
set_nonzero_bits (NULL);
return;
}
+ // If we have only one bit set in the mask, we can figure out the
+ // range immediately.
+ if (wi::popcount (bits) == 1)
+ {
+ bool has_zero = contains_p (build_zero_cst (type ()));
+ set (type (), bits, bits);
+ if (has_zero)
+ {
+ int_range<2> zero;
+ zero.set_zero (type ());
+ union_ (zero);
+ }
+ }
set_nonzero_bits (wide_int_to_tree (type (), bits));
}
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 413e54b..556e31a 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -117,6 +117,8 @@ class GTY((user)) irange : public vrange
public:
// In-place setters.
virtual void set (tree, tree, value_range_kind = VR_RANGE) override;
+ void set (tree type, const wide_int_ref &, const wide_int_ref &,
+ value_range_kind = VR_RANGE);
virtual void set_nonzero (tree type) override;
virtual void set_zero (tree type) override;
virtual void set_nonnegative (tree type) override;
@@ -687,6 +689,13 @@ irange::varying_compatible_p () const
return true;
}
+inline void
+irange::set (tree type, const wide_int_ref &min, const wide_int_ref &max,
+ value_range_kind kind)
+{
+ set (wide_int_to_tree (type, min), wide_int_to_tree (type, max), kind);
+}
+
inline bool
vrange::varying_p () const
{
diff --git a/gcc/var-tracking.cc b/gcc/var-tracking.cc
index 235981d..9c40ec4 100644
--- a/gcc/var-tracking.cc
+++ b/gcc/var-tracking.cc
@@ -9906,6 +9906,23 @@ vt_add_function_parameter (tree parm)
VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
}
}
+
+ if (GET_MODE_CLASS (mode) == MODE_INT)
+ {
+ machine_mode wider_mode_iter;
+ FOR_EACH_WIDER_MODE (wider_mode_iter, mode)
+ {
+ if (!HWI_COMPUTABLE_MODE_P (wider_mode_iter))
+ break;
+ rtx wider_reg
+ = gen_rtx_REG (wider_mode_iter, REGNO (incoming));
+ cselib_val *wider_val
+ = cselib_lookup_from_insn (wider_reg, wider_mode_iter, 1,
+ VOIDmode, get_insns ());
+ preserve_value (wider_val);
+ record_entry_value (wider_val, wider_reg);
+ }
+ }
}
}
else if (GET_CODE (incoming) == PARALLEL && !dv_onepart_p (dv))