aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2022-09-27 13:40:33 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2022-09-27 13:40:33 +0200
commit76425e19243cc310566fe7fd2f772039f9b8ec9f (patch)
tree96c1066811af285f2e0d4c8bf68351f7c0442280
parentcecd314884a285957a110560bbd141a5f39ad7d3 (diff)
parent614e5696d730a65998ff5b0373f905795a758dd6 (diff)
downloadgcc-76425e19243cc310566fe7fd2f772039f9b8ec9f.zip
gcc-76425e19243cc310566fe7fd2f772039f9b8ec9f.tar.gz
gcc-76425e19243cc310566fe7fd2f772039f9b8ec9f.tar.bz2
Merge remote-tracking branch 'mainline/master' into ibuclaw/merge_mainline
Fixes: #1544
-rw-r--r--ChangeLog4
-rw-r--r--MAINTAINERS3
-rw-r--r--fixincludes/fixincl.x154
-rw-r--r--fixincludes/inclhack.def96
-rw-r--r--fixincludes/tests/base/bits/floatn.h74
-rw-r--r--gcc/ChangeLog123
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/ChangeLog111
-rw-r--r--gcc/ada/adaint.c13
-rw-r--r--gcc/ada/bindgen.adb9
-rw-r--r--gcc/ada/cal.c2
-rw-r--r--gcc/ada/contracts.adb2
-rw-r--r--gcc/ada/cstreams.c8
-rw-r--r--gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst8
-rw-r--r--gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst30
-rw-r--r--gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst1120
-rw-r--r--gcc/ada/expect.c8
-rw-r--r--gcc/ada/gnat_rm.texi22
-rw-r--r--gcc/ada/gnat_ugn.texi12
-rw-r--r--gcc/ada/gsocket.h6
-rw-r--r--gcc/ada/mingw32.h28
-rw-r--r--gcc/ada/rtsfind.ads111
-rw-r--r--gcc/ada/s-oscons-tmplt.c3
-rw-r--r--gcc/ada/sem_ch12.adb7
-rw-r--r--gcc/ada/sem_ch5.adb8
-rw-r--r--gcc/ada/sem_util.adb24
-rw-r--r--gcc/ada/sem_warn.ads9
-rw-r--r--gcc/ada/sysdep.c6
-rw-r--r--gcc/builtins.def5
-rw-r--r--gcc/c-family/ChangeLog6
-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.cc11
-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/ChangeLog7
-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/cfgcleanup.cc2
-rw-r--r--gcc/cfgcleanup.h1
-rw-r--r--gcc/cfgrtl.cc30
-rw-r--r--gcc/config.gcc22
-rw-r--r--gcc/config/aarch64/aarch64-arches.def3
-rw-r--r--gcc/config/aarch64/aarch64.h18
-rw-r--r--gcc/config/i386/avx512fp16intrin.h11
-rw-r--r--gcc/config/i386/i386-builtins.cc15
-rw-r--r--gcc/config/i386/i386-expand.cc116
-rw-r--r--gcc/config/i386/i386.cc5
-rw-r--r--gcc/config/ia64/ia64.cc24
-rwxr-xr-xgcc/config/nvptx/gen-multilib-matches.sh60
-rw-r--r--gcc/config/nvptx/nvptx.cc4
-rw-r--r--gcc/config/nvptx/nvptx.h8
-rw-r--r--gcc/config/nvptx/nvptx.opt2
-rw-r--r--gcc/config/nvptx/t-nvptx31
-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-logue.cc2
-rw-r--r--gcc/config/rs6000/rs6000.cc6
-rw-r--r--gcc/config/rs6000/vector.md2
-rw-r--r--gcc/config/s390/s390.cc15
-rw-r--r--gcc/cp/ChangeLog25
-rw-r--r--gcc/cp/call.cc153
-rw-r--r--gcc/cp/cp-tree.h23
-rw-r--r--gcc/cp/decl.cc26
-rw-r--r--gcc/cp/error.cc8
-rw-r--r--gcc/cp/lambda.cc89
-rw-r--r--gcc/cp/mangle.cc67
-rw-r--r--gcc/cp/method.cc23
-rw-r--r--gcc/cp/module.cc17
-rw-r--r--gcc/cp/parser.cc471
-rw-r--r--gcc/cp/pt.cc3
-rw-r--r--gcc/cp/semantics.cc7
-rw-r--r--gcc/cp/typeck.cc172
-rw-r--r--gcc/cp/typeck2.cc34
-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/install.texi9
-rw-r--r--gcc/doc/invoke.texi9
-rw-r--r--gcc/doc/sourcebuild.texi2
-rw-r--r--gcc/fortran/ChangeLog66
-rw-r--r--gcc/fortran/trans-expr.cc83
-rw-r--r--gcc/fortran/trans.h3
-rw-r--r--gcc/omp-low.cc19
-rw-r--r--gcc/range-op.cc18
-rw-r--r--gcc/testsuite/ChangeLog119
-rw-r--r--gcc/testsuite/c-c++-common/goacc/reduction-7.c22
-rw-r--r--gcc/testsuite/c-c++-common/goacc/reduction-8.c12
-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/g++.dg/cpp1z/constexpr-lambda13.C2
-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.C10
-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/char8_t3.C37
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/char8_t4.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constinit3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C4
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/char8_t-feature-test-macro-2.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/char8_t-init-2.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/is_convertible3.C9
-rw-r--r--gcc/testsuite/g++.dg/ext/is_nothrow_convertible3.C9
-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/modules/partial-2.cc17
-rw-r--r--gcc/testsuite/g++.dg/modules/partial-2.h38
-rw-r--r--gcc/testsuite/g++.dg/modules/partial-2_a.C39
-rw-r--r--gcc/testsuite/g++.dg/modules/partial-2_b.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/partial-2_c.H5
-rw-r--r--gcc/testsuite/g++.dg/modules/partial-2_d.C8
-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/template/error30.C2
-rw-r--r--gcc/testsuite/g++.dg/torture/pr107029.C19
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/operator.C2
-rw-r--r--gcc/testsuite/g++.target/i386/float16-1.C4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/popcount6.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr107009.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr53346-1.c70
-rw-r--r--gcc/testsuite/gcc.target/i386/pr53346-2.c59
-rw-r--r--gcc/testsuite/gcc.target/i386/pr53346-3.c69
-rw-r--r--gcc/testsuite/gcc.target/i386/pr53346-4.c59
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr100645.c13
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr96072.c14
-rw-r--r--gcc/testsuite/gcc.target/riscv/ret-1.c41
-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/intent_optimize_10.f9066
-rw-r--r--gcc/testsuite/gfortran.dg/intent_optimize_4.f9043
-rw-r--r--gcc/testsuite/gfortran.dg/intent_optimize_5.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/intent_optimize_6.f9034
-rw-r--r--gcc/testsuite/gfortran.dg/intent_optimize_7.f9045
-rw-r--r--gcc/testsuite/gfortran.dg/intent_optimize_8.f9045
-rw-r--r--gcc/testsuite/gfortran.dg/intent_optimize_9.f9042
-rw-r--r--gcc/testsuite/gfortran.dg/intent_out_15.f9027
-rw-r--r--gcc/tree-core.h4
-rw-r--r--gcc/tree-ssa-dom.cc35
-rw-r--r--gcc/tree-ssa-reassoc.cc21
-rw-r--r--gcc/tree.cc1
-rw-r--r--gcc/tree.h4
-rw-r--r--gcc/value-range.cc22
-rw-r--r--gcc/value-range.h9
-rw-r--r--include/demangle.h14
-rw-r--r--include/dwarf2.h10
-rw-r--r--libcpp/expr.cc1
-rw-r--r--libgcc/ChangeLog5
-rw-r--r--libgcc/unwind-dw2-fde.c4
-rw-r--r--libgomp/ChangeLog5
-rw-r--r--libiberty/cp-demangle.c100
-rw-r--r--libiberty/cp-demangle.h2
-rw-r--r--libiberty/testsuite/demangle-expected8
-rw-r--r--libphobos/libdruntime/MERGE2
-rw-r--r--libphobos/libdruntime/Makefile.am10
-rw-r--r--libphobos/libdruntime/Makefile.in21
-rw-r--r--libphobos/libdruntime/__builtins.di2
-rw-r--r--libphobos/libdruntime/core/demangle.d250
-rw-r--r--libphobos/libdruntime/core/internal/array/arrayassign.d148
-rw-r--r--libphobos/libdruntime/core/internal/dassert.d2
-rw-r--r--libphobos/libdruntime/core/internal/utf.d21
-rw-r--r--libphobos/libdruntime/core/simd.d2
-rw-r--r--libphobos/libdruntime/core/stdc/fenv.d2
-rw-r--r--libphobos/libdruntime/core/stdc/math.d11
-rw-r--r--libphobos/libdruntime/core/sys/darwin/mach/loader.d2
-rw-r--r--libphobos/libdruntime/core/sys/linux/fcntl.d2
-rw-r--r--libphobos/libdruntime/core/sys/posix/dlfcn.d4
-rw-r--r--libphobos/libdruntime/core/sys/posix/mqueue.d4
-rw-r--r--libphobos/libdruntime/core/sys/posix/setjmp.d16
-rw-r--r--libphobos/libdruntime/core/sys/posix/stdlib.d20
-rw-r--r--libphobos/libdruntime/core/sys/posix/sys/types.d12
-rw-r--r--libphobos/libdruntime/core/sys/windows/stacktrace.d3
-rw-r--r--libphobos/libdruntime/core/time.d2
-rw-r--r--libphobos/libdruntime/object.d3
-rw-r--r--libphobos/libdruntime/rt/arrayassign.d60
-rw-r--r--libphobos/libdruntime/rt/lifetime.d60
-rw-r--r--libphobos/src/MERGE2
-rw-r--r--libphobos/src/Makefile.am8
-rw-r--r--libphobos/src/Makefile.in14
-rw-r--r--libphobos/src/index.dd4
-rw-r--r--libphobos/src/std/algorithm/comparison.d20
-rw-r--r--libphobos/src/std/algorithm/iteration.d17
-rw-r--r--libphobos/src/std/algorithm/searching.d76
-rw-r--r--libphobos/src/std/algorithm/sorting.d4
-rw-r--r--libphobos/src/std/compiler.d2
-rw-r--r--libphobos/src/std/concurrency.d7
-rw-r--r--libphobos/src/std/container/array.d31
-rw-r--r--libphobos/src/std/container/dlist.d2
-rw-r--r--libphobos/src/std/conv.d15
-rw-r--r--libphobos/src/std/datetime/stopwatch.d2
-rw-r--r--libphobos/src/std/datetime/timezone.d3
-rw-r--r--libphobos/src/std/digest/crc.d8
-rw-r--r--libphobos/src/std/digest/digest.d3
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/affix_allocator.d4
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/aligned_block_list.d10
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/allocator_list.d20
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/fallback_allocator.d14
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/free_list.d4
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/free_tree.d4
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/quantizer.d8
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/region.d867
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/scoped_allocator.d6
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/segregator.d8
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/stats_collector.d8
-rw-r--r--libphobos/src/std/experimental/allocator/package.d14
-rw-r--r--libphobos/src/std/file.d2
-rw-r--r--libphobos/src/std/format/package.d2
-rw-r--r--libphobos/src/std/internal/math/gammafunction.d2
-rw-r--r--libphobos/src/std/logger/core.d21
-rw-r--r--libphobos/src/std/net/curl.d8
-rw-r--r--libphobos/src/std/numeric.d4
-rw-r--r--libphobos/src/std/path.d29
-rw-r--r--libphobos/src/std/range/primitives.d13
-rw-r--r--libphobos/src/std/socket.d4
-rw-r--r--libphobos/src/std/stdio.d5
-rw-r--r--libphobos/src/std/sumtype.d47
-rw-r--r--libphobos/src/std/typecons.d40
-rw-r--r--libphobos/src/std/uni/package.d2
-rw-r--r--libphobos/src/std/utf.d2
-rw-r--r--libphobos/src/std/xml.d3113
-rw-r--r--libstdc++-v3/ChangeLog39
-rw-r--r--libstdc++-v3/include/bits/alloc_traits.h4
-rw-r--r--libstdc++-v3/include/bits/ptr_traits.h47
-rw-r--r--libstdc++-v3/include/bits/std_function.h25
-rw-r--r--libstdc++-v3/include/experimental/type_traits24
-rw-r--r--libstdc++-v3/include/std/bitset5
-rw-r--r--libstdc++-v3/include/std/future4
-rw-r--r--libstdc++-v3/include/std/type_traits54
-rw-r--r--libstdc++-v3/testsuite/17_intro/names.cc1
-rw-r--r--libstdc++-v3/testsuite/20_util/bitset/107037.cc7
-rw-r--r--libstdc++-v3/testsuite/20_util/function/cons/deduction_c++23.cc23
-rw-r--r--libstdc++-v3/testsuite/20_util/pointer_traits/lwg3545.cc17
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/cons/deduction_c++23.cc23
362 files changed, 8675 insertions, 7052 deletions
diff --git a/ChangeLog b/ChangeLog
index 652b069..9aee34d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2022-09-26 Jeff Law <jlaw@ventanamicro.com>
+
+ * MAINTAINERS: Update my email address and DCO entry.
+
2022-09-23 Paul-Antoine Arras <pa@codesourcery.com>
* MAINTAINERS (Write After Approval): Add myself.
diff --git a/MAINTAINERS b/MAINTAINERS
index f63de22..11fa8bc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -30,7 +30,7 @@ Richard Biener <rguenther@suse.de>
Richard Earnshaw <richard.earnshaw@arm.com>
Jakub Jelinek <jakub@redhat.com>
Richard Kenner <kenner@nyu.edu>
-Jeff Law <jeffreyalaw@gmail.com>
+Jeff Law <jlaw@ventanamicro.com>
Michael Meissner <gnu@the-meissners.org>
Jason Merrill <jason@redhat.com>
David S. Miller <davem@redhat.com>
@@ -725,6 +725,7 @@ Matthias Kretz <m.kretz@gsi.de>
Tim Lange <mail@tim-lange.me>
Jeff Law <jeffreyalaw@gmail.com>
Jeff Law <jlaw@tachyum.com>
+Jeff Law <jlaw@ventanamicro.com>
Immad Mir <mir@sourceware.org>
Gaius Mulley <gaiusmod2@gmail.com>
Siddhesh Poyarekar <siddhesh@gotplt.org>
diff --git a/fixincludes/fixincl.x b/fixincludes/fixincl.x
index bad4904..6309723 100644
--- a/fixincludes/fixincl.x
+++ b/fixincludes/fixincl.x
@@ -2,11 +2,11 @@
*
* DO NOT EDIT THIS FILE (fixincl.x)
*
- * It has been AutoGen-ed February 27, 2022 at 07:47:03 PM by AutoGen 5.18.16
+ * It has been AutoGen-ed September 27, 2022 at 12:21:44 PM by AutoGen 5.18.16
* From the definitions inclhack.def
* and the template file fixincl
*/
-/* DO NOT SVN-MERGE THIS FILE, EITHER Sun Feb 27 19:47:03 UTC 2022
+/* DO NOT SVN-MERGE THIS FILE, EITHER Tue Sep 27 12:21:44 CEST 2022
*
* You must regenerate it. Use the ./genfixes script.
*
@@ -15,7 +15,7 @@
* certain ANSI-incompatible system header files which are fixed to work
* correctly with ANSI C and placed in a directory that GNU C will search.
*
- * This file contains 267 fixup descriptions.
+ * This file contains 270 fixup descriptions.
*
* See README for more information.
*
@@ -4107,6 +4107,132 @@ static const char* apzGlibc_C99_Inline_4Patch[] = {
/* * * * * * * * * * * * * * * * * * * * * * * * * *
*
+ * Description of Glibc_Cxx_Floatn_1 fix
+ */
+tSCC zGlibc_Cxx_Floatn_1Name[] =
+ "glibc_cxx_floatn_1";
+
+/*
+ * File name selection pattern
+ */
+tSCC zGlibc_Cxx_Floatn_1List[] =
+ "bits/floatn.h\0bits/floatn-common.h\0*/bits/floatn.h\0*/bits/floatn-common.h\0";
+/*
+ * Machine/OS name selection pattern
+ */
+#define apzGlibc_Cxx_Floatn_1Machs (const char**)NULL
+
+/*
+ * content selection pattern - do fix if pattern found
+ */
+tSCC zGlibc_Cxx_Floatn_1Select0[] =
+ "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n\
+(([ \t]*/\\*[^\n\
+]*\\*/\n\
+)?([ \t]*#[ \t]*if[^\n\
+]*\n\
+)?[ \t]*#[ \t]*define __f(16|32|64|128)x?\\()";
+
+#define GLIBC_CXX_FLOATN_1_TEST_CT 1
+static tTestDesc aGlibc_Cxx_Floatn_1Tests[] = {
+ { TT_EGREP, zGlibc_Cxx_Floatn_1Select0, (regex_t*)NULL }, };
+
+/*
+ * Fix Command Arguments for Glibc_Cxx_Floatn_1
+ */
+static const char* apzGlibc_Cxx_Floatn_1Patch[] = {
+ "format",
+ "%1(defined __cplusplus && !__GNUC_PREREQ (13, 0))\n\
+%2",
+ (char*)NULL };
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Description of Glibc_Cxx_Floatn_2 fix
+ */
+tSCC zGlibc_Cxx_Floatn_2Name[] =
+ "glibc_cxx_floatn_2";
+
+/*
+ * File name selection pattern
+ */
+tSCC zGlibc_Cxx_Floatn_2List[] =
+ "bits/floatn.h\0bits/floatn-common.h\0*/bits/floatn.h\0*/bits/floatn-common.h\0";
+/*
+ * Machine/OS name selection pattern
+ */
+#define apzGlibc_Cxx_Floatn_2Machs (const char**)NULL
+
+/*
+ * content selection pattern - do fix if pattern found
+ */
+tSCC zGlibc_Cxx_Floatn_2Select0[] =
+ "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n\
+(([ \t]*/\\*[^\n\
+]*\\*/\n\
+)?[ \t]*typedef[ \t]+[^\n\
+]*[ \t]+_Float(16|32|64|128)x?([ \t]+__attribute__ \\(\\(__mode__ \\(__HF__\\)\\)\\))?;)";
+
+#define GLIBC_CXX_FLOATN_2_TEST_CT 1
+static tTestDesc aGlibc_Cxx_Floatn_2Tests[] = {
+ { TT_EGREP, zGlibc_Cxx_Floatn_2Select0, (regex_t*)NULL }, };
+
+/*
+ * Fix Command Arguments for Glibc_Cxx_Floatn_2
+ */
+static const char* apzGlibc_Cxx_Floatn_2Patch[] = {
+ "format",
+ "%1(defined __cplusplus && !__GNUC_PREREQ (13, 0))\n\
+%2",
+ (char*)NULL };
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Description of Glibc_Cxx_Floatn_3 fix
+ */
+tSCC zGlibc_Cxx_Floatn_3Name[] =
+ "glibc_cxx_floatn_3";
+
+/*
+ * File name selection pattern
+ */
+tSCC zGlibc_Cxx_Floatn_3List[] =
+ "bits/floatn.h\0bits/floatn-common.h\0*/bits/floatn.h\0*/bits/floatn-common.h\0";
+/*
+ * Machine/OS name selection pattern
+ */
+#define apzGlibc_Cxx_Floatn_3Machs (const char**)NULL
+
+/*
+ * content selection pattern - do fix if pattern found
+ */
+tSCC zGlibc_Cxx_Floatn_3Select0[] =
+ "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n\
+(([ \t]*/\\*[^\n\
+]*\n\
+?[^\n\
+]*\\*/\n\
+)?([ \t]*#[ \t]*if[^\n\
+]*\n\
+)?([ \t]*typedef[ \t]+[^\n\
+]*;\n\
+)?[ \t]*#[ \t]*define __CFLOAT(16|32|64|128)X?[ \t]+)";
+
+#define GLIBC_CXX_FLOATN_3_TEST_CT 1
+static tTestDesc aGlibc_Cxx_Floatn_3Tests[] = {
+ { TT_EGREP, zGlibc_Cxx_Floatn_3Select0, (regex_t*)NULL }, };
+
+/*
+ * Fix Command Arguments for Glibc_Cxx_Floatn_3
+ */
+static const char* apzGlibc_Cxx_Floatn_3Patch[] = {
+ "format",
+ "%1(defined __cplusplus && !__GNUC_PREREQ (13, 0))\n\
+%2",
+ (char*)NULL };
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
* Description of Glibc_Mutex_Init fix
*/
tSCC zGlibc_Mutex_InitName[] =
@@ -10872,9 +10998,9 @@ static const char* apzX11_SprintfPatch[] = {
*
* List of all fixes
*/
-#define REGEX_COUNT 305
+#define REGEX_COUNT 308
#define MACH_LIST_SIZE_LIMIT 187
-#define FIX_COUNT 267
+#define FIX_COUNT 270
/*
* Enumerate the fixes
@@ -10977,6 +11103,9 @@ typedef enum {
GLIBC_C99_INLINE_2_FIXIDX,
GLIBC_C99_INLINE_3_FIXIDX,
GLIBC_C99_INLINE_4_FIXIDX,
+ GLIBC_CXX_FLOATN_1_FIXIDX,
+ GLIBC_CXX_FLOATN_2_FIXIDX,
+ GLIBC_CXX_FLOATN_3_FIXIDX,
GLIBC_MUTEX_INIT_FIXIDX,
GLIBC_STDINT_FIXIDX,
GLIBC_STRNCPY_FIXIDX,
@@ -11635,6 +11764,21 @@ tFixDesc fixDescList[ FIX_COUNT ] = {
GLIBC_C99_INLINE_4_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
aGlibc_C99_Inline_4Tests, apzGlibc_C99_Inline_4Patch, 0 },
+ { zGlibc_Cxx_Floatn_1Name, zGlibc_Cxx_Floatn_1List,
+ apzGlibc_Cxx_Floatn_1Machs,
+ GLIBC_CXX_FLOATN_1_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
+ aGlibc_Cxx_Floatn_1Tests, apzGlibc_Cxx_Floatn_1Patch, 0 },
+
+ { zGlibc_Cxx_Floatn_2Name, zGlibc_Cxx_Floatn_2List,
+ apzGlibc_Cxx_Floatn_2Machs,
+ GLIBC_CXX_FLOATN_2_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
+ aGlibc_Cxx_Floatn_2Tests, apzGlibc_Cxx_Floatn_2Patch, 0 },
+
+ { zGlibc_Cxx_Floatn_3Name, zGlibc_Cxx_Floatn_3List,
+ apzGlibc_Cxx_Floatn_3Machs,
+ GLIBC_CXX_FLOATN_3_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
+ aGlibc_Cxx_Floatn_3Tests, apzGlibc_Cxx_Floatn_3Patch, 0 },
+
{ zGlibc_Mutex_InitName, zGlibc_Mutex_InitList,
apzGlibc_Mutex_InitMachs,
GLIBC_MUTEX_INIT_TEST_CT, FD_MACH_ONLY,
diff --git a/fixincludes/inclhack.def b/fixincludes/inclhack.def
index 7605ac8..88bf28f 100644
--- a/fixincludes/inclhack.def
+++ b/fixincludes/inclhack.def
@@ -2015,6 +2015,102 @@ fix = {
EOT;
};
+/* glibc-2.27 to 2.36 assume GCC 7 or later supports some or all
+ * of _Float{16,32,64,128} and _Float{32,64,128}x keywords for C,
+ * but doesn't for C++.
+ */
+fix = {
+ hackname = glibc_cxx_floatn_1;
+ files = bits/floatn.h, bits/floatn-common.h, "*/bits/floatn.h", "*/bits/floatn-common.h";
+ select = "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n"
+ "(([ \t]*/\\*[^\n]*\\*/\n)?"
+ "([ \t]*#[ \t]*if[^\n]*\n)?"
+ "[ \t]*#[ \t]*define __f(16|32|64|128)x?\\()";
+ c_fix = format;
+ c_fix_arg = "%1(defined __cplusplus && !__GNUC_PREREQ (13, 0))\n%2";
+ test_text = <<-EOT
+ # if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+ /* The literal suffix f128 exists only since GCC 7.0. */
+ # define __f128(x) x##l
+ # else
+ # define __f128(x) x##f128
+ # endif
+ # if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+ /* The literal suffix (f128) exist for powerpc only since GCC 7.0. */
+ # if __LDBL_MANT_DIG__ == 113
+ # define __f128(x) x##l
+ # else
+ # define __f128(x) x##q
+ # endif
+ # else
+ # define __f128(x) x##f128
+ # endif
+ # if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+ # ifdef __NO_LONG_DOUBLE_MATH
+ # define __f64(x) x##l
+ # else
+ # define __f64(x) x
+ # endif
+ # else
+ # define __f64(x) x##f64
+ # endif
+ EOT;
+};
+
+fix = {
+ hackname = glibc_cxx_floatn_2;
+ files = bits/floatn.h, bits/floatn-common.h, "*/bits/floatn.h", "*/bits/floatn-common.h";
+ select = "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n"
+ "(([ \t]*/\\*[^\n]*\\*/\n)?"
+ "[ \t]*typedef[ \t]+[^\n]*[ \t]+_Float(16|32|64|128)x?([ \t]+__attribute__ \\(\\(__mode__ \\(__HF__\\)\\)\\))?;)";
+ c_fix = format;
+ c_fix_arg = "%1(defined __cplusplus && !__GNUC_PREREQ (13, 0))\n%2";
+ test_text = <<-EOT
+ # if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+ typedef float _Float16 __attribute__ ((__mode__ (__HF__)));
+ # endif
+ # if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+ typedef __float128 _Float128;
+ # endif
+ EOT;
+};
+
+fix = {
+ hackname = glibc_cxx_floatn_3;
+ files = bits/floatn.h, bits/floatn-common.h, "*/bits/floatn.h", "*/bits/floatn-common.h";
+ select = "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n"
+ "(([ \t]*/\\*[^\n]*\n?[^\n]*\\*/\n)?"
+ "([ \t]*#[ \t]*if[^\n]*\n)?"
+ "([ \t]*typedef[ \t]+[^\n]*;\n)?"
+ "[ \t]*#[ \t]*define __CFLOAT(16|32|64|128)X?[ \t]+)";
+ c_fix = format;
+ c_fix_arg = "%1(defined __cplusplus && !__GNUC_PREREQ (13, 0))\n%2";
+ test_text = <<-EOT
+ # if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+ # define __CFLOAT128 _Complex long double
+ # else
+ # define __CFLOAT128 _Complex _Float128
+ # endif
+ # if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+ /* Add a typedef for older GCC compilers which don't natively support
+ _Complex _Float128. */
+ typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__)));
+ # define __CFLOAT128 __cfloat128
+ # else
+ # define __CFLOAT128 _Complex _Float128
+ # endif
+ # if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+ # ifdef __NO_LONG_DOUBLE_MATH
+ # define __CFLOAT64 _Complex long double
+ # else
+ # define __CFLOAT64 _Complex double
+ # endif
+ # else
+ # define __CFLOAT64 _Complex _Float64
+ # endif
+ EOT;
+};
+
/* glibc-2.3.5 defines pthread mutex initializers incorrectly,
* so we replace them with versions that correspond to the
* definition.
diff --git a/fixincludes/tests/base/bits/floatn.h b/fixincludes/tests/base/bits/floatn.h
new file mode 100644
index 0000000..f09528b
--- /dev/null
+++ b/fixincludes/tests/base/bits/floatn.h
@@ -0,0 +1,74 @@
+/* DO NOT EDIT THIS FILE.
+
+ It has been auto-edited by fixincludes from:
+
+ "fixinc/tests/inc/bits/floatn.h"
+
+ This had to be done to correct non-standard usages in the
+ original, manufacturer supplied header file. */
+
+
+
+#if defined( GLIBC_CXX_FLOATN_1_CHECK )
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
+/* The literal suffix f128 exists only since GCC 7.0. */
+# define __f128(x) x##l
+# else
+# define __f128(x) x##f128
+# endif
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
+/* The literal suffix (f128) exist for powerpc only since GCC 7.0. */
+# if __LDBL_MANT_DIG__ == 113
+# define __f128(x) x##l
+# else
+# define __f128(x) x##q
+# endif
+# else
+# define __f128(x) x##f128
+# endif
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
+# ifdef __NO_LONG_DOUBLE_MATH
+# define __f64(x) x##l
+# else
+# define __f64(x) x
+# endif
+# else
+# define __f64(x) x##f64
+# endif
+#endif /* GLIBC_CXX_FLOATN_1_CHECK */
+
+
+#if defined( GLIBC_CXX_FLOATN_2_CHECK )
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
+typedef float _Float16 __attribute__ ((__mode__ (__HF__)));
+# endif
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
+typedef __float128 _Float128;
+# endif
+#endif /* GLIBC_CXX_FLOATN_2_CHECK */
+
+
+#if defined( GLIBC_CXX_FLOATN_3_CHECK )
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
+# define __CFLOAT128 _Complex long double
+# else
+# define __CFLOAT128 _Complex _Float128
+# endif
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
+/* Add a typedef for older GCC compilers which don't natively support
+ _Complex _Float128. */
+typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__)));
+# define __CFLOAT128 __cfloat128
+# else
+# define __CFLOAT128 _Complex _Float128
+# endif
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
+# ifdef __NO_LONG_DOUBLE_MATH
+# define __CFLOAT64 _Complex long double
+# else
+# define __CFLOAT64 _Complex double
+# endif
+# else
+# define __CFLOAT64 _Complex _Float64
+# endif
+#endif /* GLIBC_CXX_FLOATN_3_CHECK */
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4ff50c3..4bd177d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,126 @@
+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.
+
+2022-09-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/107001
+ * omp-low.cc (lower_omp_taskgroup): Don't add GOMP_RETURN statement
+ at the end.
+ * omp-expand.cc (build_omp_regions_1): Clarify GF_OMP_TARGET_KIND_DATA
+ is not stand-alone directive. For GIMPLE_OMP_TASKGROUP, also don't
+ update parent.
+ (omp_make_gimple_edges) <case GIMPLE_OMP_TASKGROUP>: Reset
+ cur_region back after new_omp_region.
+
2022-09-23 Vineet Gupta <vineetg@rivosinc.com>
* config/riscv/riscv.h (LOCAL_SYM_P): New.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index c0c32de..38c805d 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20220924
+20220927
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index fe048b8..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".
@@ -66,7 +165,7 @@
2022-09-12 Eric Botcazou <ebotcazou@adacore.com>
- * contracts.adb (uild_Subprogram_Contract_Wrapper): Remove useless
+ * contracts.adb (Build_Subprogram_Contract_Wrapper): Remove useless
local variable. In the case of a function, replace the extended
return statement by a block statement declaring a renaming of the
call to the local subprogram after removing side effects manually.
@@ -1179,14 +1278,14 @@
2022-09-02 Eric Botcazou <ebotcazou@adacore.com>
- * exp_util.adb (Expand_Subtype_From_Expr): Be prepared for
- rewritten aggregates as expressions.
+ * exp_util.adb (Expand_Subtype_From_Expr): Be prepared for rewritten
+ aggregates as expressions.
2022-09-02 Gary Dismukes <dismukes@adacore.com>
- * exp_ch6.adb (Expand_Simple_Function_Return) Bypass creation of an actual
- subtype and unchecked conversion to that subtype when the underlying type
- of the expression has discriminants without defaults.
+ * exp_ch6.adb (Expand_Simple_Function_Return) Bypass creation of an
+ actual subtype and unchecked conversion to that subtype when the
+ underlying type of the expression has discriminants without defaults.
2022-09-02 Eric Botcazou <ebotcazou@adacore.com>
diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c
index 2ae4ded..199dbe0 100644
--- a/gcc/ada/adaint.c
+++ b/gcc/ada/adaint.c
@@ -200,11 +200,7 @@ UINT __gnat_current_ccs_encoding;
#endif
/* wait.h processing */
-#ifdef __MINGW32__
-# if OLD_MINGW
-# include <sys/wait.h>
-# endif
-#elif defined (__vxworks) && defined (__RTP__)
+#if defined (__vxworks) && defined (__RTP__)
# include <wait.h>
#elif defined (__Lynx__)
/* ??? We really need wait.h and it includes resource.h on Lynx. GCC
@@ -214,7 +210,7 @@ UINT __gnat_current_ccs_encoding;
preventing the inclusion of the GCC header from doing anything. */
# define GCC_RESOURCE_H
# include <sys/wait.h>
-#elif defined (__PikeOS__)
+#elif defined (__PikeOS__) || defined (__MINGW32__)
/* No wait() or waitpid() calls available. */
#else
/* Default case. */
@@ -335,11 +331,6 @@ const char *__gnat_library_template = GNAT_LIBRARY_TEMPLATE;
#if defined (__MINGW32__)
#include "mingw32.h"
-
-#if OLD_MINGW
-#include <sys/param.h>
-#endif
-
#else
#include <sys/param.h>
#endif
diff --git a/gcc/ada/bindgen.adb b/gcc/ada/bindgen.adb
index b2fa44d..f2aaa2d 100644
--- a/gcc/ada/bindgen.adb
+++ b/gcc/ada/bindgen.adb
@@ -134,9 +134,6 @@ package body Bindgen is
-- Text for aspect specifications (if any) given as part of the
-- Adainit and Adafinal spec declarations.
- function Aspect_Text return String is
- (if Enable_CUDA_Device_Expansion then " with CUDA_Global" else "");
-
----------------------------------
-- Interface_State Pragma Table --
----------------------------------
@@ -2644,10 +2641,11 @@ package body Bindgen is
end if;
WBI ("");
- WBI (" procedure " & Ada_Init_Name.all & Aspect_Text & ";");
+ WBI (" procedure " & Ada_Init_Name.all & ";");
if Enable_CUDA_Device_Expansion then
WBI (" pragma Export (C, " & Ada_Init_Name.all &
", Link_Name => """ & Device_Ada_Init_Link_Name & """);");
+ WBI (" pragma CUDA_Global (" & Ada_Init_Name.all & ");");
else
WBI (" pragma Export (C, " & Ada_Init_Name.all & ", """ &
Ada_Init_Name.all & """);");
@@ -2662,11 +2660,12 @@ package body Bindgen is
if not Cumulative_Restrictions.Set (No_Finalization) then
WBI ("");
- WBI (" procedure " & Ada_Final_Name.all & Aspect_Text & ";");
+ WBI (" procedure " & Ada_Final_Name.all & ";");
if Enable_CUDA_Device_Expansion then
WBI (" pragma Export (C, " & Ada_Final_Name.all &
", Link_Name => """ & Device_Ada_Final_Link_Name & """);");
+ WBI (" pragma CUDA_Global (" & Ada_Final_Name.all & ");");
else
WBI (" pragma Export (C, " & Ada_Final_Name.all & ", """ &
Ada_Final_Name.all & """);");
diff --git a/gcc/ada/cal.c b/gcc/ada/cal.c
index e1ab692..09bcc15 100644
--- a/gcc/ada/cal.c
+++ b/gcc/ada/cal.c
@@ -53,10 +53,8 @@
#ifdef __MINGW32__
#include "mingw32.h"
-#if STD_MINGW
#include <winsock.h>
#endif
-#endif
void
__gnat_timeval_to_duration (struct timeval *t, long long *sec, long *usec)
diff --git a/gcc/ada/contracts.adb b/gcc/ada/contracts.adb
index 34db67a..dd573d3 100644
--- a/gcc/ada/contracts.adb
+++ b/gcc/ada/contracts.adb
@@ -1207,7 +1207,7 @@ package body Contracts is
-- A Ghost object cannot be effectively volatile (SPARK RM 6.9(7) and
-- SPARK RM 6.9(19)).
- elsif Is_Effectively_Volatile (Obj_Id) then
+ elsif SPARK_Mode = On and then Is_Effectively_Volatile (Obj_Id) then
Error_Msg_N ("ghost object & cannot be volatile", Obj_Id);
-- A Ghost object cannot be imported or exported (SPARK RM 6.9(7)).
diff --git a/gcc/ada/cstreams.c b/gcc/ada/cstreams.c
index 10cc3a6..fc583e1 100644
--- a/gcc/ada/cstreams.c
+++ b/gcc/ada/cstreams.c
@@ -97,14 +97,6 @@ extern "C" {
#undef fileno
#endif
-/* The _IONBF value in MINGW32 stdio.h is wrong. */
-#if defined (WINNT) || defined (_WINNT)
-#if OLD_MINGW
-#undef _IONBF
-#define _IONBF 0004
-#endif
-#endif
-
int
__gnat_feof (FILE *stream)
{
diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst b/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst
index c25e3d4..d839b1f 100644
--- a/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst
+++ b/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst
@@ -1623,13 +1623,13 @@ Multi-dimensional arrays can be modified, as shown by this example:
which changes element (1,2) to 20 and (3,4) to 30.
-Attribute Valid_Image
+Attribute Valid_Value
=======================
-.. index:: Valid_Image
+.. index:: Valid_Value
-The ``'Valid_Image`` attribute is defined for enumeration types other than
+The ``'Valid_Value`` attribute is defined for enumeration types other than
those in package Standard. This attribute is a function that takes
-a String, and returns Boolean. ``T'Valid_Image (S)`` returns True
+a String, and returns Boolean. ``T'Valid_Value (S)`` returns True
if and only if ``T'Value (S)`` would not raise Constraint_Error.
Attribute Valid_Scalars
diff --git a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
index 6a47809..d4bddff 100644
--- a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
+++ b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
@@ -1719,6 +1719,7 @@ Alphabetical List of All Switches
Float_Words_BE : Nat; -- Float words stored big-endian?
Int_Size : Pos; -- Standard.Integer'Size
Long_Double_Size : Pos; -- Standard.Long_Long_Float'Size
+ Long_Long_Long_Size : Pos; -- Standard.Long_Long_Long_Integer'Size
Long_Long_Size : Pos; -- Standard.Long_Long_Integer'Size
Long_Size : Pos; -- Standard.Long_Integer'Size
Maximum_Alignment : Pos; -- Maximum permitted alignment
@@ -1816,6 +1817,7 @@ Alphabetical List of All Switches
Float_Words_BE 0
Int_Size 64
Long_Double_Size 128
+ Long_Long_Long_Size 128
Long_Long_Size 64
Long_Size 64
Maximum_Alignment 16
@@ -6229,11 +6231,33 @@ Linker switches can be specified after :switch:`-largs` builder switch.
.. index:: -fuse-ld=name
:switch:`-fuse-ld={name}`
- Linker to be used. The default is ``bfd`` for :file:`ld.bfd`,
- the alternative being ``gold`` for :file:`ld.gold`. The later is
- a more recent and faster linker, but only available on GNU/Linux
+ Linker to be used. The default is ``bfd`` for :file:`ld.bfd`; ``gold``
+ (for :file:`ld.gold`) and ``mold`` (for :file:`ld.mold`) are more
+ recent and faster alternatives, but only available on GNU/Linux
platforms.
+ .. only:: PRO
+
+ The GNAT distribution for native Linux platforms includes ``mold``,
+ compiled against OpenSSL version 1.1; however, the distribution does
+ not include OpenSSL. In order to use this linker, you may either:
+
+ * use your system's OpenSSL library, if the version matches: in this
+ situation, you need not do anything beside using the
+ :switch:`-fuse-ld=mold` switch,
+
+ * obtain a source distribution for OpenSSL 1.1, compile the
+ :file:`libcrypto.so` library and install it in the directory of
+ your choice, then include this directory in the
+ :envvar:`LD_LIBRARY_PATH` environment variable,
+
+ * install another copy of ``mold`` by other means in the directory
+ of your choice, and include this directory in the :envvar:`PATH`
+ environment variable; you may find this alternative preferable if
+ the copy of ``mold`` included in GNAT does not suit your needs
+ (e.g. being able to link against your system's OpenSSL, or using
+ another version of ``mold``).
+
.. _Binding_with_gnatbind:
Binding with ``gnatbind``
diff --git a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst
index d670839..92877a2 100644
--- a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst
+++ b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst
@@ -15,7 +15,6 @@ This chapter describes a number of utility programs:
* :ref:`The_File_Cleanup_Utility_gnatclean`
* :ref:`The_GNAT_Library_Browser_gnatls`
* :ref:`The_Coding_Standard_Verifier_gnatcheck`
- * :ref:`The_GNAT_Metrics_Tool_gnatmetric`
* :ref:`The_GNAT_Pretty_Printer_gnatpp`
* :ref:`The_Body_Stub_Generator_gnatstub`
* :ref:`The_Backtrace_Symbolizer_gnatsymbolize`
@@ -487,1123 +486,6 @@ building specialized scripts.
For full details, plese refer to :title:`GNATcheck Reference Manual`.
-
-.. only:: PRO or GPL
-
- .. _The_GNAT_Metrics_Tool_gnatmetric:
-
- The GNAT Metrics Tool ``gnatmetric``
- ====================================
-
- .. index:: ! gnatmetric
- .. index:: Metric tool
-
- The ``gnatmetric`` tool is a utility
- for computing various program metrics.
- It takes an Ada source file as input and generates a file containing the
- metrics data as output. Various switches control which
- metrics are reported.
-
- ``gnatmetric`` is a project-aware tool
- (see :ref:`Using_Project_Files_with_GNAT_Tools` for a description of
- the project-related switches). The project file package that can specify
- ``gnatmetric`` switches is named ``Metrics``.
-
- The ``gnatmetric`` command has the form
-
- ::
-
- $ gnatmetric [ switches ] { filename }
-
- where:
-
- * ``switches`` specify the metrics to compute and define the destination for
- the output
-
- * Each ``filename`` is the name of a source file to process. 'Wildcards' are
- allowed, and the file name may contain path information. If no
- ``filename`` is supplied, then the ``switches`` list must contain at least
- one :switch:`--files` switch (see :ref:`Other_gnatmetric_Switches`).
- Including both a :switch:`--files` switch and one or more ``filename``
- arguments is permitted.
-
- Note that it is no longer necessary to specify the Ada language version;
- ``gnatmetric`` can process Ada source code written in any version from
- Ada 83 onward without specifying any language version switch.
-
- The following subsections describe the various switches accepted by
- ``gnatmetric``, organized by category.
-
- .. _Output_File_Control-gnatmetric:
-
- Output File Control
- -------------------
-
- .. index:: Output file control in gnatmetric
-
- ``gnatmetric`` has two output formats. It can generate a
- textual (human-readable) form, and also XML. By default only textual
- output is generated.
-
- When generating the output in textual form, ``gnatmetric`` creates
- for each Ada source file a corresponding text file
- containing the computed metrics, except for the case when the set of metrics
- specified by gnatmetric parameters consists only of metrics that are computed
- for the whole set of analyzed sources, but not for each Ada source.
- By default, the name of the file containing metric information for a source
- is obtained by appending the :file:`.metrix` suffix to the
- name of the input source file. If not otherwise specified and no project file
- is specified as ``gnatmetric`` option this file is placed in the same
- directory as where the source file is located. If ``gnatmetric`` has a
- project file as its parameter, it places all the generated files in the
- object directory of the project (or in the project source directory if the
- project does not define an object directory). If :switch:`--subdirs` option
- is specified, the files are placed in the subrirectory of this directory
- specified by this option.
-
- All the output information generated in XML format is placed in a single
- file. By default the name of this file is :file:`metrix.xml`.
- If not otherwise specified and if no project file is specified
- as ``gnatmetric`` option this file is placed in the
- current directory.
-
- Some of the computed metrics are summed over the units passed to
- ``gnatmetric``; for example, the total number of lines of code.
- By default this information is sent to :file:`stdout`, but a file
- can be specified with the :switch:`--global-file-name` switch.
-
- The following switches control the ``gnatmetric`` output:
-
- .. index:: --generate-xml-output (gnatmetric)
-
- :switch:`--generate-xml-output`
- Generate XML output.
-
- .. index:: --generate-xml-schema (gnatmetric)
-
- :switch:`--generate-xml-schema`
- Generate XML output and an XML schema file that describes the structure
- of the XML metric report. This schema is assigned to the XML file. The schema
- file has the same name as the XML output file with :file:`.xml` suffix replaced
- with :file:`.xsd`.
-
- .. index:: --no-text-output (gnatmetric)
-
-
- :switch:`--no-text-output`
- Do not generate the output in text form (implies :switch:`-x`).
-
- .. index:: --output-dir (gnatmetric)
-
-
- :switch:`--output-dir={output_dir}`
- Put text files with detailed metrics into ``output_dir``.
-
- .. index:: --output-suffix (gnatmetric)
-
-
- :switch:`--output-suffix={file_suffix}`
- Use ``file_suffix``, instead of :file:`.metrix`
- in the name of the output file.
-
- .. index:: --global-file-name (gnatmetric)
-
- :switch:`--global-file-name={file_name}`
- Put global metrics into ``file_name``.
-
- .. index:: --xml-file-name (gnatmetric)
-
-
- :switch:`--xml-file-name={file_name}`
- Put the XML output into ``file_name``
- (also implies :switch:`--generate-xml-output`).
-
- .. index:: --short-file-names (gnatmetric)
-
- :switch:`--short-file-names`
- Use 'short' source file names in the output. (The ``gnatmetric``
- output includes the name(s) of the Ada source file(s) from which the
- metrics are computed. By default each name includes the absolute
- path. The :switch:`--short-file-names` switch causes ``gnatmetric``
- to exclude all directory information from the file names that are
- output.)
-
- .. index:: --wide-character-encoding (gnatmetric)
-
- :switch:`--wide-character-encoding={e}`
- Specify the wide character encoding method for the input and output
- files. ``e`` is one of the following:
-
- * *8* - UTF-8 encoding
-
- * *b* - Brackets encoding (default value)
-
-
- .. index:: Disable Metrics For Local Units in gnatmetric
-
- .. _Disable_Metrics_For_Local_Units:
-
- Disable Metrics For Local Units
- -------------------------------
-
- ``gnatmetric`` relies on the GNAT compilation model --
- one compilation
- unit per one source file. It computes line metrics for the whole source
- file, and it also computes syntax
- and complexity metrics for the file's outermost unit.
-
- By default, ``gnatmetric`` will also compute all metrics for certain
- kinds of locally declared program units:
-
- * subprogram (and generic subprogram) bodies;
-
- * package (and generic package) specs and bodies;
-
- * task object and type specifications and bodies;
-
- * protected object and type specifications and bodies.
-
- .. index:: Eligible local unit (for gnatmetric)
-
- These kinds of entities will be referred to as
- *eligible local program units*, or simply *eligible local units*,
- in the discussion below.
-
- Note that a subprogram declaration, generic instantiation,
- or renaming declaration only receives metrics
- computation when it appear as the outermost entity
- in a source file.
-
- Suppression of metrics computation for eligible local units can be
- obtained via the following switch:
-
-
- .. index:: --no-local-metrics (gnatmetric)
-
-
- :switch:`--no-local-metrics`
- Do not compute detailed metrics for eligible local program units.
-
-
- .. _Specifying_a_set_of_metrics_to_compute:
-
- Specifying a set of metrics to compute
- --------------------------------------
-
- By default all the metrics are reported. The switches described in this
- subsection allow you to control, on an individual basis, whether metrics are
- reported. If at least one positive metric switch is specified (that is, a
- switch that defines that a given metric or set of metrics is to be computed),
- then only explicitly specified metrics are reported.
-
- .. _Line_Metrics_Control:
-
- Line Metrics Control
- ^^^^^^^^^^^^^^^^^^^^
-
- .. index:: Line metrics control in gnatmetric
-
- For each source file, and for each of its eligible local program
- units, ``gnatmetric`` computes the following metrics:
-
- * the total number of lines;
-
- * the total number of code lines (i.e., non-blank lines that are not
- comments)
-
- * the number of comment lines
-
- * the number of code lines containing end-of-line comments;
-
- * the comment percentage: the ratio between the number of lines that
- contain comments and the number of all non-blank lines, expressed as
- a percentage
-
- * the number of empty lines and lines containing only space characters
- and/or format effectors (blank lines)
-
- * the average number of code lines in subprogram bodies, task bodies,
- entry bodies and statement sequences in package bodies
-
- ``gnatmetric`` sums the values of the line metrics for all the files
- being processed and then generates the cumulative results. The tool
- also computes for all the files being processed the average number of
- code lines in bodies.
-
- You can use the following switches to select the specific line metrics
- to be reported.
-
-
- .. index:: --lines (gnatmetric)
- .. index:: --no-lines (gnatmetric)
-
-
- :switch:`--lines-all`
- Report all the line metrics
-
-
- :switch:`--no-lines-all`
- Do not report any of line metrics
-
-
- :switch:`--lines`
- Report the number of all lines
-
-
- :switch:`--no-lines`
- Do not report the number of all lines
-
-
- :switch:`--lines-code`
- Report the number of code lines
-
-
- :switch:`--no-lines-code`
- Do not report the number of code lines
-
-
- :switch:`--lines-comment`
- Report the number of comment lines
-
-
- :switch:`--no-lines-comment`
- Do not report the number of comment lines
-
-
- :switch:`--lines-eol-comment`
- Report the number of code lines containing
- end-of-line comments
-
-
- :switch:`--no-lines-eol-comment`
- Do not report the number of code lines containing
- end-of-line comments
-
-
- :switch:`--lines-ratio`
- Report the comment percentage in the program text
-
-
- :switch:`--no-lines-ratio`
- Do not report the comment percentage in the program text
-
-
- :switch:`--lines-blank`
- Report the number of blank lines
-
-
- :switch:`--no-lines-blank`
- Do not report the number of blank lines
-
-
- :switch:`--lines-average`
- Report the average number of code lines in subprogram bodies, task bodies,
- entry bodies and statement sequences in package bodies.
-
-
- :switch:`--no-lines-average`
- Do not report the average number of code lines in subprogram bodies,
- task bodies, entry bodies and statement sequences in package bodies.
-
-
- :switch:`--lines-spark`
- Report the number of lines written in SPARK.
-
-
- :switch:`--no-lines-spark`
- Do not report the number of lines written in SPARK.
-
-
- .. _Syntax_Metrics_Control:
-
- Syntax Metrics Control
- ^^^^^^^^^^^^^^^^^^^^^^
-
- .. index:: Syntax metrics control in gnatmetric
-
- ``gnatmetric`` computes various syntactic metrics for the
- outermost unit and for each eligible local unit:
-
- * *LSLOC ('Logical Source Lines Of Code')*
- The total number of declarations and the total number of
- statements. Note that the definition of declarations is the one
- given in the reference manual:
-
- "Each of the following is defined to be a declaration: any
- basic_declaration; an enumeration_literal_specification; a
- discriminant_specification; a component_declaration; a
- loop_parameter_specification; a parameter_specification; a
- subprogram_body; an entry_declaration; an
- entry_index_specification; a choice_parameter_specification; a
- generic_formal_parameter_declaration."
-
- This means for example that each enumeration literal adds one to
- the count, as well as each subprogram parameter.
-
- * *Maximal static nesting level of inner program units*
- According to :title:`Ada Reference Manual`, 10.1(1):
-
- "A program unit is either a package, a task unit, a protected
- unit, a protected entry, a generic unit, or an explicitly
- declared subprogram other than an enumeration literal."
-
- * *Maximal nesting level of composite syntactic constructs*
- This corresponds to the notion of the maximum nesting level in the
- GNAT built-in style checks (see :ref:`Style_Checking`).
-
- * *Number of formal parameters*
- Number of formal parameters of a subprogram; if a subprogram does
- have parameters, then numbers of "in", "out" and "in out"
- parameters are also reported. This metric is reported for
- subprogram specifications and for subprogram instantiations. For
- subprogram bodies, expression functions and null procedures this
- metric is reported if the construct acts as a subprogram
- declaration but is not a completion of previous declaration. This
- metric is not reported for generic and formal subprograms.
-
- For the outermost unit in the file, ``gnatmetric`` additionally
- computes the following metrics:
-
- * *Public subprograms*
- This metric is computed for package specs. It is the number of
- subprograms and generic subprograms declared in the visible part
- (including the visible part of nested packages, protected objects,
- and protected types).
-
-
- * *All subprograms*
- This metric is computed for bodies and subunits. The metric is
- equal to a total number of subprogram bodies in the compilation
- unit.
- Neither generic instantiations nor renamings-as-a-body nor body
- stubs are counted. Any subprogram body is counted, independently
- of its nesting level and enclosing constructs. Generic bodies and
- bodies of protected subprograms are counted in the same way as
- 'usual' subprogram bodies.
-
-
- * *Public types*
- This metric is computed for package specs and generic package
- declarations. It is the total number of types that can be
- referenced from outside this compilation unit, plus the number of
- types from all the visible parts of all the visible generic
- packages. Generic formal types are not counted. Only types, not
- subtypes, are included.
-
- Along with the total number of public types, the following
- types are counted and reported separately:
-
- * *Abstract types*
-
- * *Root tagged types^ (abstract, non-abstract, private,
- non-private). Type extensions are *not* counted
-
- * *Private types* (including private extensions)
-
- * *Task types*
-
- * *Protected types*
-
- * *All types*
- This metric is computed for any compilation unit. It is equal to
- the total number of the declarations of different types given in
- the compilation unit. The private and the corresponding full type
- declaration are counted as one type declaration. Incomplete type
- declarations and generic formal types are not counted.
- No distinction is made among different kinds of types (abstract,
- private etc.); the total number of types is reported.
-
- By default, all the syntax metrics are reported. You can use the following
- switches to select specific syntax metrics.
-
-
- .. index:: --syntax (gnatmetric)
- .. index:: --no-syntax (gnatmetric)
-
-
- :switch:`--syntax-all`
- Report all the syntax metrics
-
-
- :switch:`--no-syntax-all`
- Do not report any of syntax metrics
-
-
- :switch:`--declarations`
- Report the total number of declarations
-
-
- :switch:`--no-declarations`
- Do not report the total number of declarations
-
-
- :switch:`--statements`
- Report the total number of statements
-
-
- :switch:`--no-statements`
- Do not report the total number of statements
-
-
- :switch:`--public-subprograms`
- Report the number of public subprograms in a compilation unit
-
-
- :switch:`--no-public-subprograms`
- Do not report the number of public subprograms in a compilation unit
-
-
- :switch:`--all-subprograms`
- Report the number of all the subprograms in a compilation unit
-
-
- :switch:`--no-all-subprograms`
- Do not report the number of all the subprograms in a compilation unit
-
-
- :switch:`--public-types`
- Report the number of public types in a compilation unit
-
-
- :switch:`--no-public-types`
- Do not report the number of public types in a compilation unit
-
-
- :switch:`--all-types`
- Report the number of all the types in a compilation unit
-
-
- :switch:`--no-all-types`
- Do not report the number of all the types in a compilation unit
-
-
- :switch:`--unit-nesting`
- Report the maximal program unit nesting level
-
-
- :switch:`--no-unit-nesting`
- Do not report the maximal program unit nesting level
-
-
- :switch:`--construct-nesting`
- Report the maximal construct nesting level
-
-
- :switch:`--no-construct-nesting`
- Do not report the maximal construct nesting level
-
- :switch:`--param-number`
- Report the number of subprogram parameters
-
-
- :switch:`--no-param-number`
- Do not report the number of subprogram parameters
-
-
- .. _Contract_Metrics_Control:
-
- Contract Metrics Control
- ^^^^^^^^^^^^^^^^^^^^^^^^
-
- .. index:: Contract metrics control in gnatmetric
-
- :switch:`--contract-all`
- Report all the contract metrics
-
-
- :switch:`--no-contract-all`
- Do not report any of the contract metrics
-
-
- :switch:`--contract`
- Report the number of public subprograms with contracts
-
-
- :switch:`--no-contract`
- Do not report the number of public subprograms with contracts
-
-
- :switch:`--post`
- Report the number of public subprograms with postconditions
-
-
- :switch:`--no-post`
- Do not report the number of public subprograms with postconditions
-
-
- :switch:`--contract-complete`
- Report the number of public subprograms with complete contracts
-
-
- :switch:`--no-contract-complete`
- Do not report the number of public subprograms with complete contracts
-
-
- :switch:`--contract-cyclomatic`
- Report the McCabe complexity of public subprograms
-
-
- :switch:`--no-contract-cyclomatic`
- Do not report the McCabe complexity of public subprograms
-
-
- .. _Complexity_Metrics_Control:
-
- Complexity Metrics Control
- ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- .. index:: Complexity metrics control in gnatmetric
-
- For a program unit that is an executable body (a subprogram body
- (including generic bodies), task body, entry body or a package body
- containing its own statement sequence) ``gnatmetric`` computes the
- following complexity metrics:
-
- * McCabe cyclomatic complexity;
-
- * McCabe essential complexity;
-
- * maximal loop nesting level;
-
- * extra exit points (for subprograms);
-
- The McCabe cyclomatic complexity metric is defined
- in `http://www.mccabe.com/pdf/mccabe-nist235r.pdf <http://www.mccabe.com/pdf/mccabe-nist235r.pdf>`_
-
- According to McCabe, both control statements and short-circuit control
- forms should be taken into account when computing cyclomatic
- complexity. For Ada 2012 we have also take into account conditional
- expressions and quantified expressions. For each body, we compute
- three metric values:
-
- * the complexity introduced by control
- statements only, without taking into account short-circuit forms
- (referred as ``statement complexity`` in ``gnatmetric`` output),
-
- * the complexity introduced by short-circuit control forms only
- (referred as ``expression complexity`` in ``gnatmetric`` output),
- and
-
- * the total
- cyclomatic complexity, which is the sum of these two values
- (referred as ``cyclomatic complexity`` in ``gnatmetric`` output).
-
- The cyclomatic complexity is also computed for Ada 2012 expression functions.
- An expression function cannot have statements as its components, so only one
- metric value is computed as a cyclomatic complexity of an expression function.
-
- The origin of cyclomatic complexity metric is the need to estimate the number
- of independent paths in the control flow graph that in turn gives the number
- of tests needed to satisfy paths coverage testing completeness criterion.
- Considered from the testing point of view, a static Ada ``loop`` (that is,
- the ``loop`` statement having static subtype in loop parameter
- specification) does not add to cyclomatic complexity. By providing
- :switch:`--no-static-loop` option a user
- may specify that such loops should not be counted when computing the
- cyclomatic complexity metric
-
- The Ada essential complexity metric is a McCabe cyclomatic complexity metric
- counted for the code that is reduced by excluding all the pure structural Ada
- control statements. An compound statement is considered as a non-structural
- if it contains a ``raise`` or ``return`` statement as it subcomponent,
- or if it contains a ``goto`` statement that transfers the control outside
- the operator. A selective ``accept`` statement with a ``terminate`` alternative
- is considered a non-structural statement. When computing this metric,
- ``exit`` statements are treated in the same way as ``goto``
- statements unless the :switch:`-ne` option is specified.
-
- The Ada essential complexity metric defined here is intended to quantify
- the extent to which the software is unstructured. It is adapted from
- the McCabe essential complexity metric defined in
- http://www.mccabe.com/pdf/mccabe-nist235r.pdf
- but is modified to be more
- suitable for typical Ada usage. For example, short circuit forms
- are not penalized as unstructured in the Ada essential complexity metric.
-
- When computing cyclomatic and essential complexity, ``gnatmetric`` skips
- the code in the exception handlers and in all the nested program units. The
- code of assertions and predicates (that is, subprogram preconditions and
- postconditions, subtype predicates and type invariants) is also skipped.
-
- By default, all the complexity metrics are reported. For more fine-grained
- control you can use the following switches:
-
-
- .. index:: --complexity (gnatmetric)
- .. index:: --no-complexity (gnatmetric)
-
-
- :switch:`--complexity-all`
- Report all the complexity metrics
-
-
- :switch:`--no-complexity-all`
- Do not report any of the complexity metrics
-
-
- :switch:`--complexity-cyclomatic`
- Report the McCabe Cyclomatic Complexity
-
-
- :switch:`--no-complexity-cyclomatic`
- Do not report the McCabe Cyclomatic Complexity
-
-
- :switch:`--complexity-essential`
- Report the Essential Complexity
-
-
- :switch:`--no-complexity-essential`
- Do not report the Essential Complexity
-
-
- :switch:`--loop-nesting`
- Report maximal loop nesting level
-
-
- :switch:`--no-loop-nesting`
- Do not report maximal loop nesting level
-
-
- :switch:`--complexity-average`
- Report the average McCabe Cyclomatic Complexity for all the subprogram bodies,
- task bodies, entry bodies and statement sequences in package bodies.
- The metric is reported for whole set of processed Ada sources only.
-
-
- :switch:`--no-complexity-average`
- Do not report the average McCabe Cyclomatic Complexity for all the subprogram
- bodies, task bodies, entry bodies and statement sequences in package bodies
-
- .. index:: --no-treat-exit-as-goto (gnatmetric)
-
-
- :switch:`--no-treat-exit-as-goto`
- Do not consider ``exit`` statements as ``goto``\ s when
- computing Essential Complexity
-
- .. index:: --no-static-loop (gnatmetric)
-
-
- :switch:`--no-static-loop`
- Do not consider static loops when computing cyclomatic complexity
-
-
- :switch:`--extra-exit-points`
- Report the extra exit points for subprogram bodies. As an exit point, this
- metric counts ``return`` statements and raise statements in case when the
- raised exception is not handled in the same body. In case of a function this
- metric subtracts 1 from the number of exit points, because a function body
- must contain at least one ``return`` statement.
-
-
- :switch:`--no-extra-exit-points`
- Do not report the extra exit points for subprogram bodies
-
-
- .. _Coupling_Metrics_Control:
-
- Coupling Metrics Control
- ^^^^^^^^^^^^^^^^^^^^^^^^
-
- .. index:: Coupling metrics control in gnatmetric
-
- .. index:: Coupling metrics (in gnatmetric)
-
- Coupling metrics measure the dependencies between a given entity and other
- entities in the program. This information is useful since high coupling
- may signal potential issues with maintainability as the program evolves.
-
- ``gnatmetric`` computes the following coupling metrics:
-
-
- * *object-oriented coupling*, for classes in traditional object-oriented
- sense;
-
- * *unit coupling*, for all the program units making up a program;
-
- * *control coupling*, reflecting dependencies between a unit and
- other units that contain subprograms.
-
- .. index:: fan-out coupling
- .. index:: efferent coupling
-
- Two kinds of coupling metrics are computed:
-
- * fan-out coupling ('efferent coupling'):
- the number of entities the given entity depends upon. This metric
- reflects how the given entity depends on the changes in the
- 'external world'.
-
- .. index:: fan-in coupling
- .. index:: afferent coupling
-
- * fan-in coupling ('afferent' coupling):
- the number of entities that depend on a given entity.
- This metric reflects how the 'external world' depends on the changes in a
- given entity.
-
- Object-oriented coupling metrics measure the dependencies
- between a given class (or a group of classes) and the other classes in the
- program. In this subsection the term 'class' is used in its traditional
- object-oriented programming sense (an instantiable module that contains data
- and/or method members). A *category* (of classes) is a group of closely
- related classes that are reused and/or modified together.
-
- A class ``K``\ 's fan-out coupling is the number of classes
- that ``K`` depends upon.
- A category's fan-out coupling is the number of classes outside the
- category that the classes inside the category depend upon.
-
- A class ``K``\ 's fan-in coupling is the number of classes
- that depend upon ``K``.
- A category's fan-in coupling is the number of classes outside the
- category that depend on classes belonging to the category.
-
- Ada's object-oriented paradigm separates the instantiable entity
- (type) from the module (package), so the definition of the coupling
- metrics for Ada maps the class and class category notions
- onto Ada constructs.
-
- For the coupling metrics, several kinds of modules that define a tagged type
- or an interface type -- library packages, library generic packages, and
- library generic package instantiations -- are considered to be classes.
- A category consists of a library package (or
- a library generic package) that defines a tagged or an interface type,
- together with all its descendant (generic) packages that define tagged
- or interface types. Thus a
- category is an Ada hierarchy of library-level program units. Class
- coupling in Ada is referred to as 'tagged coupling', and category coupling
- is referred to as 'hierarchy coupling'.
-
- For any package serving as a class, its body and subunits (if any) are
- considered together with its spec when computing dependencies, and coupling
- metrics are reported for spec units only. Dependencies between classes
- mean Ada semantic dependencies. For object-oriented coupling
- metrics, only dependencies on units treated as classes are
- considered.
-
- Similarly, for unit and control coupling an entity is considered to be the
- conceptual construct consisting of the entity's specification, body, and
- any subunits (transitively).
- ``gnatmetric`` computes
- the dependencies of all these units as a whole, but
- metrics are only reported for spec
- units (or for a subprogram body unit in case if there is no
- separate spec for the given subprogram).
-
- For unit coupling, dependencies are computed between all kinds of program
- units. For control coupling, the dependencies of a given unit are limited to
- those units that define subprograms. Thus control fan-out coupling is reported
- for all units, but control fan-in coupling is only reported for units
- that define subprograms.
-
- The following simple example illustrates the difference between unit coupling
- and control coupling metrics:
-
- .. code-block:: ada
-
- package Lib_1 is
- function F_1 (I : Integer) return Integer;
- end Lib_1;
-
- package Lib_2 is
- type T_2 is new Integer;
- end Lib_2;
-
- package body Lib_1 is
- function F_1 (I : Integer) return Integer is
- begin
- return I + 1;
- end F_1;
- end Lib_1;
-
- with Lib_2; use Lib_2;
- package Pack is
- Var : T_2;
- function Fun (I : Integer) return Integer;
- end Pack;
-
- with Lib_1; use Lib_1;
- package body Pack is
- function Fun (I : Integer) return Integer is
- begin
- return F_1 (I);
- end Fun;
- end Pack;
-
- If we apply ``gnatmetric`` with the :switch:`--coupling-all` option to
- these units, the result will be:
-
- ::
-
- Coupling metrics:
- =================
- Unit Lib_1 (C:\\customers\\662\\L406-007\\lib_1.ads)
- control fan-out coupling : 0
- control fan-in coupling : 1
- unit fan-out coupling : 0
- unit fan-in coupling : 1
-
- Unit Pack (C:\\customers\\662\\L406-007\\pack.ads)
- control fan-out coupling : 1
- control fan-in coupling : 0
- unit fan-out coupling : 2
- unit fan-in coupling : 0
-
- Unit Lib_2 (C:\\customers\\662\\L406-007\\lib_2.ads)
- control fan-out coupling : 0
- unit fan-out coupling : 0
- unit fan-in coupling : 1
-
- The result does not contain values for object-oriented
- coupling because none of the argument units contains a tagged type and
- therefore none of these units can be treated as a class.
-
- The ``Pack`` package (spec and body) depends on two
- units -- ``Lib_1`` and ``Lib_2`` -- and so its unit fan-out coupling
- is 2. Since nothing depends on it, its unit fan-in coupling is 0, as
- is its control fan-in coupling. Only one of the units ``Pack`` depends
- upon defines a subprogram, so its control fan-out coupling is 1.
-
- ``Lib_2`` depends on nothing, so its fan-out metrics are 0. It does
- not define any subprograms, so it has no control fan-in metric.
- One unit (``Pack``) depends on it , so its unit fan-in coupling is 1.
-
- ``Lib_1`` is similar to ``Lib_2``, but it does define a subprogram.
- Its control fan-in coupling is 1 (because there is one unit
- depending on it).
-
- When computing coupling metrics, ``gnatmetric`` counts only
- dependencies between units that are arguments of the ``gnatmetric``
- invocation. Coupling metrics are program-wide (or project-wide) metrics, so
- you should invoke ``gnatmetric`` for
- the complete set of sources comprising your program. This can be done
- by invoking ``gnatmetric`` with the corresponding project file
- and with the :switch:`-U` option.
-
- By default, all the coupling metrics are reported. You can use the following
- switches to select specific syntax metrics.
-
- .. index:: --tagged-coupling (gnatmetric)
- .. index:: --hierarchy-coupling (gnatmetric)
- .. index:: --unit-coupling (gnatmetric)
- .. index:: --control-coupling (gnatmetric)
-
- :switch:`--coupling-all`
- Report all the coupling metrics
-
-
- :switch:`--tagged-coupling-out`
- Report tagged (class) fan-out coupling
-
-
- :switch:`--tagged-coupling-in`
- Report tagged (class) fan-in coupling
-
-
- :switch:`--hierarchy-coupling-out`
- Report hierarchy (category) fan-out coupling
-
-
- :switch:`--hierarchy-coupling-in`
- Report hierarchy (category) fan-in coupling
-
-
- :switch:`--unit-coupling-out`
- Report unit fan-out coupling
-
-
- :switch:`--unit-coupling-in`
- Report unit fan-in coupling
-
-
- :switch:`--control-coupling-out`
- Report control fan-out coupling
-
-
- :switch:`--control-coupling-in`
- Report control fan-in coupling
-
-
- .. _Other_gnatmetric_Switches:
-
- Other ``gnatmetric`` Switches
- -----------------------------
-
- Additional ``gnatmetric`` switches are as follows:
-
-
- .. index:: --version (gnatmetric)
-
- :switch:`--version`
- Display copyright and version, then exit disregarding all other options.
-
-
- .. index:: --help (gnatmetric)
-
- :switch:`--help`
- Display usage, then exit disregarding all other options.
-
-
- .. index:: -P (gnatmetric)
-
- :switch:`-P {file}`
- Indicates the name of the project file that describes the set of sources
- to be processed. The exact set of argument sources depends on other options
- specified, see below. An aggregate project is allowed as the file parameter
- only if it has exactly one non-aggregate project being aggregated.
-
-
- .. index:: -U (gnatmetric)
-
- :switch:`-U`
- If a project file is specified and no argument source is explicitly
- specified (either directly or by means of :switch:`-files` option), process
- all the units of the closure of the argument project. Otherwise this option
- has no effect.
-
-
- :switch:`-U {main_unit}`
- If a project file is specified and no argument source is explicitly
- specified (either directly or by means of :switch:`-files` option), process
- the closure of units rooted at ``main_unit``. Otherwise this option
- has no effect.
-
-
- .. index:: -X (gnatmetric)
-
- :switch:`-X{name}={value}`
- Indicates that external variable ``name`` in the argument project
- has the value ``value``. Has no effect if no project is specified.
-
-
- .. index:: --RTS (gnatmetric)
-
- :switch:`--RTS={rts-path}`
- Specifies the default location of the runtime library. Same meaning as the
- equivalent ``gnatmake`` flag (see :ref:`Switches_for_gnatmake`).
-
-
- .. index:: --subdirs=dir (gnatmetric)
-
- :switch:`--subdirs={dir}`
- Use the specified subdirectory of the project objects file (or of the
- project file directory if the project does not specify an object directory)
- for tool output files. Has no effect if no project is specified as
- tool argument r if :switch:`--no-objects-dir` is specified.
-
-
- .. index:: --files (gnatmetric)
-
- :switch:`--files={file}`
- Take as arguments the files listed in text file ``file``.
- Text file ``file`` may contain empty lines that are ignored.
- Each nonempty line should contain the name of an existing file.
- Several such switches may be specified simultaneously.
-
-
- .. index:: --ignore (gnatmetric)
-
- :switch:`--ignore={filename}`
- Do not process the sources listed in a specified file.
-
-
- .. index:: --verbose (gnatmetric)
-
- :switch:`--verbose`
- Verbose mode;
- ``gnatmetric`` generates version information and then
- a trace of sources being processed.
-
-
- .. index:: --quiet (gnatmetric)
-
- :switch:`--quiet`
- Quiet mode.
-
- If a project file is specified and no argument source is explicitly
- specified (either directly or by means of :switch:`-files` option), and no
- :switch:`-U` is specified, then the set of processed sources is
- all the immediate units of the argument project.
-
-
- Legacy Switches
- ^^^^^^^^^^^^^^^
-
- Some switches have a short form, mostly for legacy reasons,
- as shown below.
-
- .. index:: -x (gnatmetric)
-
- :switch:`-x`
- :switch:`--generate-xml-output`
-
- .. index:: -xs (gnatmetric)
-
- :switch:`-xs`
- :switch:`--generate-xml-schema`
-
- .. index:: -nt (gnatmetric)
-
- :switch:`-nt`
- :switch:`--no-text-output`
-
- .. index:: -d (gnatmetric)
-
- :switch:`-d {output-dir}`
- :switch:`--output-dir`
-
- .. index:: -o (gnatmetric)
-
- :switch:`-o {file-suffix}`
- :switch:`--output-suffix`
-
- .. index:: -og (gnatmetric)
-
- :switch:`-og {file-name}`
- :switch:`--global-file-name`
-
- .. index:: -ox (gnatmetric)
-
- :switch:`-ox {file-name}`
- :switch:`--xml-file-name`
-
- .. index:: -sfn (gnatmetric)
-
- :switch:`-sfn`
- :switch:`--short-file-names`
-
- .. index:: -W (gnatsmetric)
-
- :switch:`-W{e}`
- :switch:`--wide-character-encoding={e}`
-
- .. index:: -nolocal (gnatmetric)
-
- :switch:`-nolocal`
- :switch:`--no-local-metrics`
-
- .. index:: -ne (gnatmetric)
-
- :switch:`-ne`
- :switch:`--no-treat-exit-as-goto`
-
- .. index:: -files (gnatmetric)
-
- :switch:`-files {filename}`
- :switch:`--files`
-
- .. index:: -v (gnatmetric)
-
- :switch:`-v`
- :switch:`--verbose`
-
- .. index:: -q (gnatmetric)
-
- :switch:`-q`
- :switch:`--quiet`
-
.. only:: PRO or GPL
.. _The_GNAT_Pretty_Printer_gnatpp:
@@ -3026,7 +1908,7 @@ building specialized scripts.
naming conventions.
Note that it is no longer necessary to specify the Ada language version;
- ``gnatmetric`` can process Ada source code written in any version from
+ ``gnatstub`` can process Ada source code written in any version from
Ada 83 onward without specifying any language version switch.
* *switches*
diff --git a/gcc/ada/expect.c b/gcc/ada/expect.c
index b1889fe..48fb107 100644
--- a/gcc/ada/expect.c
+++ b/gcc/ada/expect.c
@@ -42,17 +42,13 @@
#include "adaint.h"
#include <sys/types.h>
-#ifdef __MINGW32__
-# if OLD_MINGW
-# include <sys/wait.h>
-# endif
-#elif defined (__vxworks) && defined (__RTP__)
+#if defined (__vxworks) && defined (__RTP__)
# include <wait.h>
#elif defined (__Lynx__)
/* ??? See comment in adaint.c. */
# define GCC_RESOURCE_H
# include <sys/wait.h>
-#elif defined (__PikeOS__)
+#elif defined (__PikeOS__) || defined (__MINGW32__)
/* No wait.h available */
#else
#include <sys/wait.h>
diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi
index cdf8605..64f2e79 100644
--- a/gcc/ada/gnat_rm.texi
+++ b/gcc/ada/gnat_rm.texi
@@ -19,7 +19,7 @@
@copying
@quotation
-GNAT Reference Manual , Sep 09, 2022
+GNAT Reference Manual , Sep 23, 2022
AdaCore
@@ -433,7 +433,7 @@ Implementation Defined Attributes
* Attribute Universal_Literal_String::
* Attribute Unrestricted_Access::
* Attribute Update::
-* Attribute Valid_Image::
+* Attribute Valid_Value::
* Attribute Valid_Scalars::
* Attribute VADS_Size::
* Attribute Value_Size::
@@ -10295,7 +10295,7 @@ consideration, you should minimize the use of these attributes.
* Attribute Universal_Literal_String::
* Attribute Unrestricted_Access::
* Attribute Update::
-* Attribute Valid_Image::
+* Attribute Valid_Value::
* Attribute Valid_Scalars::
* Attribute VADS_Size::
* Attribute Value_Size::
@@ -12040,7 +12040,7 @@ In general this is a risky approach. It may appear to “work” but such uses o
@code{Unrestricted_Access} are potentially non-portable, even from one version
of GNAT to another, so are best avoided if possible.
-@node Attribute Update,Attribute Valid_Image,Attribute Unrestricted_Access,Implementation Defined Attributes
+@node Attribute Update,Attribute Valid_Value,Attribute Unrestricted_Access,Implementation Defined Attributes
@anchor{gnat_rm/implementation_defined_attributes attribute-update}@anchor{1ac}
@section Attribute Update
@@ -12121,19 +12121,19 @@ A := A'Update ((1, 2) => 20, (3, 4) => 30);
which changes element (1,2) to 20 and (3,4) to 30.
-@node Attribute Valid_Image,Attribute Valid_Scalars,Attribute Update,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-valid-image}@anchor{1ad}
-@section Attribute Valid_Image
+@node Attribute Valid_Value,Attribute Valid_Scalars,Attribute Update,Implementation Defined Attributes
+@anchor{gnat_rm/implementation_defined_attributes attribute-valid-value}@anchor{1ad}
+@section Attribute Valid_Value
-@geindex Valid_Image
+@geindex Valid_Value
-The @code{'Valid_Image} attribute is defined for enumeration types other than
+The @code{'Valid_Value} attribute is defined for enumeration types other than
those in package Standard. This attribute is a function that takes
-a String, and returns Boolean. @code{T'Valid_Image (S)} returns True
+a String, and returns Boolean. @code{T'Valid_Value (S)} returns True
if and only if @code{T'Value (S)} would not raise Constraint_Error.
-@node Attribute Valid_Scalars,Attribute VADS_Size,Attribute Valid_Image,Implementation Defined Attributes
+@node Attribute Valid_Scalars,Attribute VADS_Size,Attribute Valid_Value,Implementation Defined Attributes
@anchor{gnat_rm/implementation_defined_attributes attribute-valid-scalars}@anchor{1ae}
@section Attribute Valid_Scalars
diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi
index f2cb1ed..7d96dbe 100644
--- a/gcc/ada/gnat_ugn.texi
+++ b/gcc/ada/gnat_ugn.texi
@@ -19,7 +19,7 @@
@copying
@quotation
-GNAT User's Guide for Native Platforms , Sep 09, 2022
+GNAT User's Guide for Native Platforms , Sep 26, 2022
AdaCore
@@ -9220,6 +9220,7 @@ Float_Size : Pos; -- Standard.Float'Size
Float_Words_BE : Nat; -- Float words stored big-endian?
Int_Size : Pos; -- Standard.Integer'Size
Long_Double_Size : Pos; -- Standard.Long_Long_Float'Size
+Long_Long_Long_Size : Pos; -- Standard.Long_Long_Long_Integer'Size
Long_Long_Size : Pos; -- Standard.Long_Long_Integer'Size
Long_Size : Pos; -- Standard.Long_Integer'Size
Maximum_Alignment : Pos; -- Maximum permitted alignment
@@ -9307,6 +9308,7 @@ Float_Size 32
Float_Words_BE 0
Int_Size 64
Long_Double_Size 128
+Long_Long_Long_Size 128
Long_Long_Size 64
Long_Size 64
Maximum_Alignment 16
@@ -15317,10 +15319,11 @@ Linker switches can be specified after @code{-largs} builder switch.
@item @code{-fuse-ld=`name'}
-Linker to be used. The default is @code{bfd} for @code{ld.bfd},
-the alternative being @code{gold} for @code{ld.gold}. The later is
-a more recent and faster linker, but only available on GNU/Linux
+Linker to be used. The default is @code{bfd} for @code{ld.bfd}; @code{gold}
+(for @code{ld.gold}) and @code{mold} (for @code{ld.mold}) are more
+recent and faster alternatives, but only available on GNU/Linux
platforms.
+
@end table
@node Binding with gnatbind,Linking with gnatlink,Linker Switches,Building Executable Programs with GNAT
@@ -17932,7 +17935,6 @@ instr.ads
-
@c -- Example: A |withing| unit has a |with| clause, it |withs| a |withed| unit
@node GNAT and Program Execution,Platform-Specific Information,GNAT Utility Programs,Top
diff --git a/gcc/ada/gsocket.h b/gcc/ada/gsocket.h
index e7284a1..561f2ff 100644
--- a/gcc/ada/gsocket.h
+++ b/gcc/ada/gsocket.h
@@ -80,12 +80,6 @@
#define FD_SETSIZE 1024
#ifdef __MINGW32__
-/* winsock2.h allows WSAPoll related definitions only when
- * _WIN32_WINNT >= 0x0600 */
-#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600
-#define _WIN32_WINNT 0x0600
-#endif
-
#include <winsock2.h>
#include <ws2tcpip.h>
#include <versionhelpers.h>
diff --git a/gcc/ada/mingw32.h b/gcc/ada/mingw32.h
index 1157fc6..d038211 100644
--- a/gcc/ada/mingw32.h
+++ b/gcc/ada/mingw32.h
@@ -44,11 +44,6 @@
#define UNICODE /* For Win32 API */
#endif
-/* We need functionality available only starting with Windows XP */
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
-
#ifndef __CYGWIN__
#include <tchar.h>
#endif
@@ -99,27 +94,4 @@ extern UINT __gnat_current_ccs_encoding;
#define WS2S(str,wstr,len) strncpy(str,wstr,len)
#endif
-#include <stdlib.h>
-
-/* STD_MINGW: standard if MINGW32 version > 1.3, we have switched to this
- version instead of the previous enhanced version to ease building GNAT on
- Windows platforms. By using STD_MINGW or OLD_MINGW it is possible to build
- GNAT using both MingW include files (Old MingW + ACT changes and standard
- MingW starting with version 1.3.
- For w64 Mingw the define STD_MINGW is always set to value 1, because
- there is no old header set present. */
-#ifdef _WIN64
-#define STD_MINGW 1
-#else
-#define STD_MINGW ((__MINGW32_MAJOR_VERSION == 1 \
- && __MINGW32_MINOR_VERSION >= 3) \
- || (__MINGW32_MAJOR_VERSION >= 2))
-#endif
-
-#define OLD_MINGW (!(STD_MINGW))
-
-#ifndef MAXPATHLEN
-#define MAXPATHLEN MAX_PATH
-#endif
-
#endif /* _MINGW32_H */
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index 65c6409..24aca2c 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -189,7 +189,6 @@ package Rtsfind is
-- Children of Interfaces
Interfaces_C,
- Interfaces_Packed_Decimal,
-- Children of Interfaces.C
@@ -205,7 +204,6 @@ package Rtsfind is
System_Address_To_Access_Conversions,
System_Arith_64,
System_Arith_128,
- System_AST_Handling,
System_Assertions,
System_Atomic_Operations,
System_Atomic_Primitives,
@@ -257,9 +255,6 @@ package Rtsfind is
System_Fat_LFlt,
System_Fat_LLF,
System_Fat_SFlt,
- System_Fat_VAX_D_Float,
- System_Fat_VAX_F_Float,
- System_Fat_VAX_G_Float,
System_Finalization_Masters,
System_Finalization_Root,
System_Fore_Decimal_32,
@@ -288,14 +283,12 @@ package Rtsfind is
System_Img_LLLI,
System_Img_LLU,
System_Img_LLLU,
- System_Img_Name,
System_Img_Uns,
System_Img_WChar,
System_Interrupts,
System_Long_Long_Float_Expon,
System_Machine_Code,
System_Mantissa,
- System_Memcop,
System_Memory,
System_Multiprocessors,
System_Pack_03,
@@ -420,10 +413,7 @@ package Rtsfind is
System_Pack_127,
System_Parameters,
System_Partition_Interface,
- System_Pool_32_Global,
System_Pool_Global,
- System_Pool_Empty,
- System_Pool_Local,
System_Pool_Size,
System_Put_Images,
System_Put_Task_Images,
@@ -440,7 +430,6 @@ package Rtsfind is
System_Stream_Attributes,
System_Task_Info,
System_Tasking,
- System_Threads,
System_Unsigned_Types,
System_Val_Bool,
System_Val_Char,
@@ -461,7 +450,6 @@ package Rtsfind is
System_Val_LLLI,
System_Val_LLU,
System_Val_LLLU,
- System_Val_Name,
System_Val_Uns,
System_Val_WChar,
System_Version_Control,
@@ -475,7 +463,6 @@ package Rtsfind is
System_Wid_LLLI,
System_Wid_LLU,
System_Wid_LLLU,
- System_Wid_Name,
System_Wid_Uns,
System_Wid_WChar,
System_WWd_Char,
@@ -484,7 +471,7 @@ package Rtsfind is
-- Children of System.Atomic_Operations
- System_Atomic_Operations_Test_And_Set,
+ System_Atomic_Operations_Test_And_Set,
-- Children of System.Dim
@@ -561,17 +548,13 @@ package Rtsfind is
RE_Set_Deadline, -- Ada.Dispatching.EDF
- RE_Code_Loc, -- Ada.Exceptions
RE_Exception_Id, -- Ada.Exceptions
- RE_Exception_Identity, -- Ada.Exceptions
RE_Exception_Information, -- Ada.Exceptions
RE_Exception_Message, -- Ada.Exceptions
RE_Exception_Name_Simple, -- Ada.Exceptions
RE_Exception_Occurrence, -- Ada.Exceptions
- RE_Exception_Occurrence_Access, -- Ada.Exceptions
RE_Null_Id, -- Ada.Exceptions
RE_Null_Occurrence, -- Ada.Exceptions
- RE_Poll, -- Ada.Exceptions
RE_Raise_Exception, -- Ada.Exceptions
RE_Raise_Exception_Always, -- Ada.Exceptions
RE_Raise_From_Controlled_Operation, -- Ada.Exceptions
@@ -596,7 +579,7 @@ package Rtsfind is
RE_Names, -- Ada.Interrupts.Names
RE_Clock, -- Ada.Real_Time
- RE_Clock_Time, -- Ada.Real_Time
+ RE_Clock_Time, -- Ada.Real_Time [used by GNATprove]
RE_Time_Span, -- Ada.Real_Time
RE_Time_Span_Zero, -- Ada.Real_Time
RO_RT_Time, -- Ada.Real_Time
@@ -612,8 +595,6 @@ package Rtsfind is
RE_Stream_Element_Array, -- Ada.Streams
RE_Stream_Element_Offset, -- Ada.Streams
- RE_Stream_Access, -- Ada.Streams.Stream_IO
-
RO_SU_Super_String, -- Ada.Strings.Superbounded
RO_WI_Super_String, -- Ada.Strings.Wide_Superbounded
@@ -628,8 +609,6 @@ package Rtsfind is
RE_Buffer_Type, -- Ada.Strings.Text_Buffers.Unbounded
RE_Get, -- Ada.Strings.Text_Buffers.Unbounded
- RE_Wide_Get, -- Ada.Strings.Text_Buffers.Unbounded
- RE_Wide_Wide_Get, -- Ada.Strings.Text_Buffers.Unbounded
RE_Wait_For_Release, -- Ada.Synchronous_Barriers
@@ -641,7 +620,6 @@ package Rtsfind is
RE_Address_Array, -- Ada.Tags
RE_Addr_Ptr, -- Ada.Tags
RE_Base_Address, -- Ada.Tags
- RE_Check_Interface_Conversion, -- Ada.Tags
RE_Check_TSD, -- Ada.Tags
RE_Cstring_Ptr, -- Ada.Tags
RE_CW_Membership, -- Ada.Tags
@@ -656,13 +634,11 @@ package Rtsfind is
RE_External_Tag, -- Ada.Tags
RO_TA_External_Tag, -- Ada.Tags
RE_Get_Access_Level, -- Ada.Tags
- RE_Get_Alignment, -- Ada.Tags
RE_Get_Entry_Index, -- Ada.Tags
RE_Get_Offset_Index, -- Ada.Tags
RE_Get_Prim_Op_Kind, -- Ada.Tags
RE_Get_Tagged_Kind, -- Ada.Tags
RE_HT_Link, -- Ada.Tags
- RE_Idepth, -- Ada.Tags
RE_Interfaces_Array, -- Ada.Tags
RE_Interfaces_Table, -- Ada.Tags
RE_Interface_Data, -- Ada.Tags
@@ -675,8 +651,6 @@ package Rtsfind is
RE_No_Dispatch_Table_Wrapper, -- Ada.Tags
RE_No_Tag, -- Ada.Tags
RE_NDT_Prims_Ptr, -- Ada.Tags
- RE_NDT_TSD, -- Ada.Tags
- RE_Num_Prims, -- Ada.Tags
RE_Object_Specific_Data, -- Ada.Tags
RE_Offset_To_Top, -- Ada.Tags
RE_Offset_To_Top_Ptr, -- Ada.Tags
@@ -699,11 +673,9 @@ package Rtsfind is
RE_Primary_DT, -- Ada.Tags
RE_Signature, -- Ada.Tags
RE_SSD, -- Ada.Tags
- RE_TSD, -- Ada.Tags
RE_Type_Specific_Data, -- Ada.Tags
RE_Register_Interface_Offset, -- Ada.Tags
RE_Register_Tag, -- Ada.Tags
- RE_Register_TSD, -- Ada.Tags
RE_Transportable, -- Ada.Tags
RE_Secondary_DT, -- Ada.Tags
RE_Secondary_Tag, -- Ada.Tags
@@ -749,7 +721,6 @@ package Rtsfind is
RE_Stream_T, -- CUDA.Driver_Types
- RE_Fatbin_Wrapper, -- CUDA.Internal
RE_Launch_Kernel, -- CUDA.Internal
RE_Pop_Call_Configuration, -- CUDA.Internal
RE_Push_Call_Configuration, -- CUDA.Internal
@@ -772,19 +743,14 @@ package Rtsfind is
RO_IC_Unsigned, -- Interfaces.C
- RE_Chars_Ptr, -- Interfaces.C.Strings
- RE_New_Char_Array, -- Interfaces.C.Strings
-
RE_Address, -- System
RE_Any_Priority, -- System
RE_Bit_Order, -- System
RE_Default_Priority, -- System
RE_High_Order_First, -- System
RE_Interrupt_Priority, -- System
- RE_Lib_Stop, -- System
RE_Low_Order_First, -- System
RE_Max_Base_Digits, -- System
- RE_Max_Priority, -- System
RE_Null_Address, -- System
RE_Priority, -- System
@@ -802,8 +768,6 @@ package Rtsfind is
RE_Subtract_With_Ovflo_Check128, -- System.Arith_128
RE_Scaled_Divide128, -- System.Arith_128
- RE_Create_AST_Handler, -- System.AST_Handling
-
RE_Assert_Failure, -- System.Assertions
RE_Raise_Assert_Failure, -- System.Assertions
@@ -824,9 +788,6 @@ package Rtsfind is
RE_Atomic_Test_And_Set, -- System.Atomic_Operations.Test_And_Set
RE_AST_Handler, -- System.Aux_DEC
- RE_Import_Address, -- System.Aux_DEC
- RE_Import_Value, -- System.Aux_DEC
- RE_No_AST_Handler, -- System.Aux_DEC
RE_Type_Class, -- System.Aux_DEC
RE_Type_Class_Enumeration, -- System.Aux_DEC
RE_Type_Class_Integer, -- System.Aux_DEC
@@ -954,15 +915,6 @@ package Rtsfind is
RE_Attr_Long_Long_Float, -- System.Fat_LLF
- RE_Attr_VAX_D_Float, -- System.Fat_VAX_D_Float
- RE_Fat_VAX_D, -- System.Fat_VAX_D_Float
-
- RE_Attr_VAX_F_Float, -- System.Fat_VAX_F_Float
- RE_Fat_VAX_F, -- System.Fat_VAX_F_Float
-
- RE_Attr_VAX_G_Float, -- System.Fat_VAX_G_Float
- RE_Fat_VAX_G, -- System.Fat_VAX_G_Float
-
RE_Add_Offset_To_Address, -- System.Finalization_Masters
RE_Attach, -- System.Finalization_Masters
RE_Base_Pool, -- System.Finalization_Masters
@@ -970,10 +922,8 @@ package Rtsfind is
RE_Finalization_Master_Ptr, -- System.Finalization_Masters
RE_Set_Base_Pool, -- System.Finalization_Masters
RE_Set_Finalize_Address, -- System.Finalization_Masters
- RE_Set_Is_Heterogeneous, -- System.Finalization_Masters
RE_Root_Controlled, -- System.Finalization_Root
- RE_Root_Controlled_Ptr, -- System.Finalization_Root
RE_Fore_Decimal32, -- System.Fore_Decimal_32
@@ -1649,9 +1599,7 @@ package Rtsfind is
RE_Set_127, -- System.Pack_127
RE_Adjust_Storage_Size, -- System.Parameters
- RE_Default_Secondary_Stack_Size, -- System.Parameters
RE_Default_Stack_Size, -- System.Parameters
- RE_Garbage_Collected, -- System.Parameters
RE_Size_Type, -- System.Parameters
RE_Unspecified_Size, -- System.Parameters
@@ -1677,8 +1625,6 @@ package Rtsfind is
RE_Global_Pool_Object, -- System.Pool_Global
- RE_Global_Pool_32_Object, -- System.Pool_32_Global
-
RE_Stack_Bounded_Pool, -- System.Pool_Size
RE_Put_Image_Integer, -- System.Put_Images
@@ -1744,11 +1690,8 @@ package Rtsfind is
RE_Set_Result, -- System.Partition_Interface
RE_Register_Obj_Receiving_Stub, -- System.Partition_Interface
RE_Register_Pkg_Receiving_Stub, -- System.Partition_Interface
- RE_Is_Nil, -- System.Partition_Interface
- RE_Entity_Ptr, -- System.Partition_Interface
RE_Entity_Of, -- System.Partition_Interface
RE_Inc_Usage, -- System.Partition_Interface
- RE_Set_Ref, -- System.Partition_Interface
RE_Make_Ref, -- System.Partition_Interface
RE_Get_Local_Address, -- System.Partition_Interface
RE_Get_Reference, -- System.Partition_Interface
@@ -1881,8 +1824,6 @@ package Rtsfind is
RE_Deallocate_Any_Controlled, -- System.Storage_Pools.Subpools
RE_Header_Size_With_Padding, -- System.Storage_Pools.Subpools
RE_Root_Storage_Pool_With_Subpools, -- System.Storage_Pools.Subpools
- RE_Root_Subpool, -- System.Storage_Pools.Subpools
- RE_Subpool_Handle, -- System.Storage_Pools.Subpools
RE_I_AD, -- System.Stream_Attributes
RE_I_AS, -- System.Stream_Attributes
@@ -2006,7 +1947,6 @@ package Rtsfind is
RE_Simple_Mode, -- System.Tasking
RE_Terminate_Mode, -- System.Tasking
RE_Delay_Mode, -- System.Tasking
- RE_Entry_Index, -- System.Tasking
RE_Task_Entry_Index, -- System.Tasking
RE_Self, -- System.Tasking
@@ -2244,17 +2184,13 @@ package Rtsfind is
RE_Set_Deadline => Ada_Dispatching_EDF,
- RE_Code_Loc => Ada_Exceptions,
RE_Exception_Id => Ada_Exceptions,
- RE_Exception_Identity => Ada_Exceptions,
RE_Exception_Information => Ada_Exceptions,
RE_Exception_Message => Ada_Exceptions,
RE_Exception_Name_Simple => Ada_Exceptions,
RE_Exception_Occurrence => Ada_Exceptions,
- RE_Exception_Occurrence_Access => Ada_Exceptions,
RE_Null_Id => Ada_Exceptions,
RE_Null_Occurrence => Ada_Exceptions,
- RE_Poll => Ada_Exceptions,
RE_Raise_Exception => Ada_Exceptions,
RE_Raise_Exception_Always => Ada_Exceptions,
RE_Raise_From_Controlled_Operation => Ada_Exceptions,
@@ -2295,8 +2231,6 @@ package Rtsfind is
RE_Stream_Element_Array => Ada_Streams,
RE_Stream_Element_Offset => Ada_Streams,
- RE_Stream_Access => Ada_Streams_Stream_IO,
-
RO_SU_Super_String => Ada_Strings_Superbounded,
RO_WI_Super_String => Ada_Strings_Wide_Superbounded,
@@ -2311,8 +2245,6 @@ package Rtsfind is
RE_Buffer_Type => Ada_Strings_Text_Buffers_Unbounded,
RE_Get => Ada_Strings_Text_Buffers_Unbounded,
- RE_Wide_Get => Ada_Strings_Text_Buffers_Unbounded,
- RE_Wide_Wide_Get => Ada_Strings_Text_Buffers_Unbounded,
RE_Wait_For_Release => Ada_Synchronous_Barriers,
@@ -2324,7 +2256,6 @@ package Rtsfind is
RE_Address_Array => Ada_Tags,
RE_Addr_Ptr => Ada_Tags,
RE_Base_Address => Ada_Tags,
- RE_Check_Interface_Conversion => Ada_Tags,
RE_Check_TSD => Ada_Tags,
RE_Cstring_Ptr => Ada_Tags,
RE_CW_Membership => Ada_Tags,
@@ -2339,13 +2270,11 @@ package Rtsfind is
RE_External_Tag => Ada_Tags,
RO_TA_External_Tag => Ada_Tags,
RE_Get_Access_Level => Ada_Tags,
- RE_Get_Alignment => Ada_Tags,
RE_Get_Entry_Index => Ada_Tags,
RE_Get_Offset_Index => Ada_Tags,
RE_Get_Prim_Op_Kind => Ada_Tags,
RE_Get_Tagged_Kind => Ada_Tags,
RE_HT_Link => Ada_Tags,
- RE_Idepth => Ada_Tags,
RE_Interfaces_Array => Ada_Tags,
RE_Interfaces_Table => Ada_Tags,
RE_Interface_Data => Ada_Tags,
@@ -2358,8 +2287,6 @@ package Rtsfind is
RE_No_Dispatch_Table_Wrapper => Ada_Tags,
RE_No_Tag => Ada_Tags,
RE_NDT_Prims_Ptr => Ada_Tags,
- RE_NDT_TSD => Ada_Tags,
- RE_Num_Prims => Ada_Tags,
RE_Object_Specific_Data => Ada_Tags,
RE_Offset_To_Top => Ada_Tags,
RE_Offset_To_Top_Ptr => Ada_Tags,
@@ -2382,11 +2309,9 @@ package Rtsfind is
RE_Primary_DT => Ada_Tags,
RE_Signature => Ada_Tags,
RE_SSD => Ada_Tags,
- RE_TSD => Ada_Tags,
RE_Type_Specific_Data => Ada_Tags,
RE_Register_Interface_Offset => Ada_Tags,
RE_Register_Tag => Ada_Tags,
- RE_Register_TSD => Ada_Tags,
RE_Transportable => Ada_Tags,
RE_Secondary_DT => Ada_Tags,
RE_Secondary_Tag => Ada_Tags,
@@ -2432,7 +2357,6 @@ package Rtsfind is
RE_Stream_T => CUDA_Driver_Types,
- RE_Fatbin_Wrapper => CUDA_Internal,
RE_Launch_Kernel => CUDA_Internal,
RE_Pop_Call_Configuration => CUDA_Internal,
RE_Push_Call_Configuration => CUDA_Internal,
@@ -2455,19 +2379,14 @@ package Rtsfind is
RO_IC_Unsigned => Interfaces_C,
- RE_Chars_Ptr => Interfaces_C_Strings,
- RE_New_Char_Array => Interfaces_C_Strings,
-
RE_Address => System,
RE_Any_Priority => System,
RE_Bit_Order => System,
RE_Default_Priority => System,
RE_High_Order_First => System,
RE_Interrupt_Priority => System,
- RE_Lib_Stop => System,
RE_Low_Order_First => System,
RE_Max_Base_Digits => System,
- RE_Max_Priority => System,
RE_Null_Address => System,
RE_Priority => System,
@@ -2485,8 +2404,6 @@ package Rtsfind is
RE_Subtract_With_Ovflo_Check128 => System_Arith_128,
RE_Scaled_Divide128 => System_Arith_128,
- RE_Create_AST_Handler => System_AST_Handling,
-
RE_Assert_Failure => System_Assertions,
RE_Raise_Assert_Failure => System_Assertions,
@@ -2507,9 +2424,6 @@ package Rtsfind is
RE_Atomic_Test_And_Set => System_Atomic_Operations_Test_And_Set,
RE_AST_Handler => System_Aux_DEC,
- RE_Import_Address => System_Aux_DEC,
- RE_Import_Value => System_Aux_DEC,
- RE_No_AST_Handler => System_Aux_DEC,
RE_Type_Class => System_Aux_DEC,
RE_Type_Class_Enumeration => System_Aux_DEC,
RE_Type_Class_Integer => System_Aux_DEC,
@@ -2643,15 +2557,6 @@ package Rtsfind is
RE_Attr_Long_Long_Float => System_Fat_LLF,
- RE_Attr_VAX_D_Float => System_Fat_VAX_D_Float,
- RE_Fat_VAX_D => System_Fat_VAX_D_Float,
-
- RE_Attr_VAX_F_Float => System_Fat_VAX_F_Float,
- RE_Fat_VAX_F => System_Fat_VAX_F_Float,
-
- RE_Attr_VAX_G_Float => System_Fat_VAX_G_Float,
- RE_Fat_VAX_G => System_Fat_VAX_G_Float,
-
RE_Add_Offset_To_Address => System_Finalization_Masters,
RE_Attach => System_Finalization_Masters,
RE_Base_Pool => System_Finalization_Masters,
@@ -2659,10 +2564,8 @@ package Rtsfind is
RE_Finalization_Master_Ptr => System_Finalization_Masters,
RE_Set_Base_Pool => System_Finalization_Masters,
RE_Set_Finalize_Address => System_Finalization_Masters,
- RE_Set_Is_Heterogeneous => System_Finalization_Masters,
RE_Root_Controlled => System_Finalization_Root,
- RE_Root_Controlled_Ptr => System_Finalization_Root,
RE_Fore_Decimal32 => System_Fore_Decimal_32,
@@ -3340,9 +3243,7 @@ package Rtsfind is
RE_Set_127 => System_Pack_127,
RE_Adjust_Storage_Size => System_Parameters,
- RE_Default_Secondary_Stack_Size => System_Parameters,
RE_Default_Stack_Size => System_Parameters,
- RE_Garbage_Collected => System_Parameters,
RE_Size_Type => System_Parameters,
RE_Unspecified_Size => System_Parameters,
@@ -3399,11 +3300,8 @@ package Rtsfind is
RE_Set_Result => System_Partition_Interface,
RE_Register_Obj_Receiving_Stub => System_Partition_Interface,
RE_Register_Pkg_Receiving_Stub => System_Partition_Interface,
- RE_Is_Nil => System_Partition_Interface,
- RE_Entity_Ptr => System_Partition_Interface,
RE_Entity_Of => System_Partition_Interface,
RE_Inc_Usage => System_Partition_Interface,
- RE_Set_Ref => System_Partition_Interface,
RE_Make_Ref => System_Partition_Interface,
RE_Get_Local_Address => System_Partition_Interface,
RE_Get_Reference => System_Partition_Interface,
@@ -3488,8 +3386,6 @@ package Rtsfind is
RE_Global_Pool_Object => System_Pool_Global,
- RE_Global_Pool_32_Object => System_Pool_32_Global,
-
RE_Stack_Bounded_Pool => System_Pool_Size,
RE_Put_Image_Integer => System_Put_Images,
@@ -3572,8 +3468,6 @@ package Rtsfind is
RE_Deallocate_Any_Controlled => System_Storage_Pools_Subpools,
RE_Header_Size_With_Padding => System_Storage_Pools_Subpools,
RE_Root_Storage_Pool_With_Subpools => System_Storage_Pools_Subpools,
- RE_Root_Subpool => System_Storage_Pools_Subpools,
- RE_Subpool_Handle => System_Storage_Pools_Subpools,
RE_I_AD => System_Stream_Attributes,
RE_I_AS => System_Stream_Attributes,
@@ -3697,7 +3591,6 @@ package Rtsfind is
RE_Simple_Mode => System_Tasking,
RE_Terminate_Mode => System_Tasking,
RE_Delay_Mode => System_Tasking,
- RE_Entry_Index => System_Tasking,
RE_Task_Entry_Index => System_Tasking,
RE_Self => System_Tasking,
diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c
index af69190..5394122 100644
--- a/gcc/ada/s-oscons-tmplt.c
+++ b/gcc/ada/s-oscons-tmplt.c
@@ -237,9 +237,6 @@ int counter = 0;
#define CST(name,comment) C(#name,String,name,comment)
/* String constant */
-#define STR(x) STR1(x)
-#define STR1(x) #x
-
#ifdef __MINGW32__
unsigned int _CRT_fmode = _O_BINARY;
#endif
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index 9525140..ab2e182 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -6296,13 +6296,16 @@ package body Sem_Ch12 is
Old_Main : constant Entity_Id := Cunit_Entity (Main_Unit);
begin
- -- A new compilation unit node is built for the instance declaration
+ -- A new compilation unit node is built for the instance declaration.
+ -- It relocates the auxiliary declaration node from the compilation unit
+ -- where the instance appeared, so that declarations that originally
+ -- followed the instance will be attached to the spec compilation unit.
Decl_Cunit :=
Make_Compilation_Unit (Sloc (N),
Context_Items => Empty_List,
Unit => Act_Decl,
- Aux_Decls_Node => Make_Compilation_Unit_Aux (Sloc (N)));
+ Aux_Decls_Node => Relocate_Node (Aux_Decls_Node (Parent (N))));
Set_Parent_Spec (Act_Decl, Parent_Spec (N));
diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb
index 17bf6d9..d0f00b3 100644
--- a/gcc/ada/sem_ch5.adb
+++ b/gcc/ada/sem_ch5.adb
@@ -2429,13 +2429,9 @@ package body Sem_Ch5 is
if not Is_Entity_Name (Iter_Name)
- -- When the context is a quantified expression, the renaming
- -- declaration is delayed until the expansion phase if we are
- -- doing expansion.
+ -- Do not perform this expansion in preanalysis
- and then (Nkind (Parent (N)) /= N_Quantified_Expression
- or else (Operating_Mode = Check_Semantics
- and then not GNATprove_Mode))
+ and then Full_Analysis
-- Do not perform this expansion when expansion is disabled, where the
-- temporary may hide the transformation of a selected component into
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index b0babeb..9ae082c 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -531,7 +531,7 @@ package body Sem_Util is
-- Local variables
- E : Entity_Id := Original_Node (Expr);
+ E : Node_Id := Original_Node (Expr);
Pre : Node_Id;
-- Start of processing for Accessibility_Level
@@ -777,8 +777,18 @@ package body Sem_Util is
-- We don't handle function calls in prefix notation correctly ???
- when N_Indexed_Component | N_Selected_Component =>
- Pre := Original_Node (Prefix (E));
+ when N_Indexed_Component | N_Selected_Component | N_Slice =>
+ Pre := Prefix (E);
+
+ -- Fetch the original node when the prefix comes from the result
+ -- of expanding a function call since we want to find the level
+ -- of the original source call.
+
+ if not Comes_From_Source (Pre)
+ and then Nkind (Original_Node (Pre)) = N_Function_Call
+ then
+ Pre := Original_Node (Pre);
+ end if;
-- When E is an indexed component or selected component and
-- the current Expr is a function call, we know that we are
@@ -26549,6 +26559,14 @@ package body Sem_Util is
Item_Nam :=
Chars (Original_Node (Pragma_Identifier (Original_Node (Item))));
+ if Item_Nam = Name_Check then
+ -- Pragma "Check" preserves the original pragma name as its first
+ -- argument.
+ Item_Nam :=
+ Chars (Expression (First (Pragma_Argument_Associations
+ (Original_Node (Item)))));
+ end if;
+
else
pragma Assert (Nkind (Item) = N_Aspect_Specification);
Item_Nam := Chars (Identifier (Item));
diff --git a/gcc/ada/sem_warn.ads b/gcc/ada/sem_warn.ads
index 1894f36..6681e54 100644
--- a/gcc/ada/sem_warn.ads
+++ b/gcc/ada/sem_warn.ads
@@ -257,12 +257,9 @@ package Sem_Warn is
----------------------
function Has_Junk_Name (E : Entity_Id) return Boolean;
- -- Return True if the entity name contains any of the following substrings:
- -- discard
- -- dummy
- -- ignore
- -- junk
- -- unused
+ -- Return True if the entity name contains substrings like "junk" or
+ -- "dummy" (see the body for the complete list).
+ --
-- Used to suppress warnings on names matching these patterns. The contents
-- of Name_Buffer and Name_Len are destroyed by this call.
diff --git a/gcc/ada/sysdep.c b/gcc/ada/sysdep.c
index 5e9cf70..7bdfcbc 100644
--- a/gcc/ada/sysdep.c
+++ b/gcc/ada/sysdep.c
@@ -323,11 +323,7 @@ __gnat_ttyname (int filedes ATTRIBUTE_UNUSED)
|| defined (__QNX__)
# ifdef __MINGW32__
-# if OLD_MINGW
-# include <termios.h>
-# else
-# include <conio.h> /* for getch(), kbhit() */
-# endif
+# include <conio.h> /* for getch(), kbhit() */
# else
# include <termios.h>
# endif
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..4e99c43 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+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 a1557eb..ca5f500 100644
--- a/gcc/c-family/c-cppbuiltin.cc
+++ b/gcc/c-family/c-cppbuiltin.cc
@@ -1081,6 +1081,7 @@ 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");
}
if (flag_concepts)
{
@@ -1112,7 +1113,7 @@ c_cpp_builtins (cpp_reader *pfile)
if (flag_threadsafe_statics)
cpp_define (pfile, "__cpp_threadsafe_static_init=200806L");
if (flag_char8_t)
- cpp_define (pfile, "__cpp_char8_t=201811L");
+ cpp_define (pfile, "__cpp_char8_t=202207L");
#ifndef THREAD_MODEL_SPEC
/* Targets that define THREAD_MODEL_SPEC need to define
__STDCPP_THREADS__ in their config/XXX/XXX-c.c themselves. */
@@ -1246,6 +1247,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-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 21248d3..4b852b8 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,10 @@
+2022-09-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/106981
+ * c-typeck.cc (c_tree_equal): Only strip NON_LVALUE_EXPRs at the
+ start. For CONSTANT_CLASS_P or CASE_CONVERT: return false if t1 and
+ t2 have different types.
+
2022-09-22 David Malcolm <dmalcolm@redhat.com>
PR c/106830
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/cfgcleanup.cc b/gcc/cfgcleanup.cc
index a8b0139..a363e0b 100644
--- a/gcc/cfgcleanup.cc
+++ b/gcc/cfgcleanup.cc
@@ -2599,7 +2599,7 @@ trivially_empty_bb_p (basic_block bb)
return value. Fill in *RET and *USE with the return and use insns
if any found, otherwise NULL. All CLOBBERs are ignored. */
-static bool
+bool
bb_is_just_return (basic_block bb, rtx_insn **ret, rtx_insn **use)
{
*ret = *use = NULL;
diff --git a/gcc/cfgcleanup.h b/gcc/cfgcleanup.h
index a6d882f..f1021ca 100644
--- a/gcc/cfgcleanup.h
+++ b/gcc/cfgcleanup.h
@@ -30,5 +30,6 @@ extern int flow_find_head_matching_sequence (basic_block, basic_block,
extern bool delete_unreachable_blocks (void);
extern void delete_dead_jumptables (void);
extern bool cleanup_cfg (int);
+extern bool bb_is_just_return (basic_block, rtx_insn **, rtx_insn **);
#endif /* GCC_CFGCLEANUP_H */
diff --git a/gcc/cfgrtl.cc b/gcc/cfgrtl.cc
index a05c338..281a432 100644
--- a/gcc/cfgrtl.cc
+++ b/gcc/cfgrtl.cc
@@ -3901,6 +3901,7 @@ fixup_reorder_chain (void)
/* Now add jumps and labels as needed to match the blocks new
outgoing edges. */
+ bool remove_unreachable_blocks = false;
for (bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; bb ; bb = (basic_block)
bb->aux)
{
@@ -4043,10 +4044,31 @@ fixup_reorder_chain (void)
continue;
}
+ /* If E_FALL->dest is just a return block, then we can emit a
+ return rather than a jump to the return block. */
+ rtx_insn *ret, *use;
+ basic_block dest;
+ if (bb_is_just_return (e_fall->dest, &ret, &use)
+ && ((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);
+
+ /* E_FALL->dest might become unreachable as a result of
+ replacing the jump with a return. So arrange to remove
+ unreachable blocks. */
+ remove_unreachable_blocks = true;
+ }
+ else
+ {
+ dest = e_fall->dest;
+ }
+
/* We got here if we need to add a new jump insn.
Note force_nonfallthru can delete E_FALL and thus we have to
save E_FALL->src prior to the call to force_nonfallthru. */
- nb = force_nonfallthru_and_redirect (e_fall, e_fall->dest, ret_label);
+ nb = force_nonfallthru_and_redirect (e_fall, dest, ret_label);
if (nb)
{
nb->aux = bb->aux;
@@ -4134,6 +4156,12 @@ fixup_reorder_chain (void)
ei_next (&ei2);
}
}
+
+ /* Replacing a jump with a return may have exposed an unreachable
+ block. Conditionally remove them if such transformations were
+ made. */
+ if (remove_unreachable_blocks)
+ delete_unreachable_blocks ();
}
/* Perform sanity checks on the insn chain.
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 27ffce3..c1b1215 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -3941,6 +3941,9 @@ if test x$with_arch = x ; then
mips*-*-vxworks)
with_arch=mips2
;;
+ nvptx-*)
+ with_arch=sm_30
+ ;;
esac
# Avoid overriding --with-arch-32 and --with-arch-64 values.
@@ -5293,6 +5296,25 @@ case "${target}" in
esac
;;
+ nvptx-*)
+ supported_defaults=arch
+ TM_MULTILIB_CONFIG=$with_arch
+ #TODO 'sm_[...]' list per 'nvptx-sm.def'.
+ case $with_arch in
+ sm_30 )
+ # OK; default.
+ ;;
+ sm_35 | sm_53 | sm_70 | sm_75 | sm_80 )
+ # OK, but we'd like 'sm_30', too.
+ TM_MULTILIB_CONFIG="$TM_MULTILIB_CONFIG sm_30"
+ ;;
+ * )
+ echo "Unknown arch used in --with-arch=$with_arch" 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+
powerpc*-*-* | rs6000-*-*)
supported_defaults="abi cpu cpu_32 cpu_64 float tune tune_32 tune_64 advance_toolchain"
diff --git a/gcc/config/aarch64/aarch64-arches.def b/gcc/config/aarch64/aarch64-arches.def
index 3c2b165..6150448 100644
--- a/gcc/config/aarch64/aarch64-arches.def
+++ b/gcc/config/aarch64/aarch64-arches.def
@@ -41,5 +41,8 @@ AARCH64_ARCH("armv8.7-a", generic, 8_7A, 8, AARCH64_FL_FOR_ARCH8
AARCH64_ARCH("armv8.8-a", generic, 8_8A, 8, AARCH64_FL_FOR_ARCH8_8)
AARCH64_ARCH("armv8-r", generic, 8R , 8, AARCH64_FL_FOR_ARCH8_R)
AARCH64_ARCH("armv9-a", generic, 9A , 9, AARCH64_FL_FOR_ARCH9)
+AARCH64_ARCH("armv9.1-a", generic, 9_1A, 9, AARCH64_FL_FOR_ARCH9_1)
+AARCH64_ARCH("armv9.2-a", generic, 9_2A, 9, AARCH64_FL_FOR_ARCH9_2)
+AARCH64_ARCH("armv9.3-a", generic, 9_3A, 9, AARCH64_FL_FOR_ARCH9_3)
#undef AARCH64_ARCH
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 6f6bb70..f790de1 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -239,6 +239,15 @@
/* Armv8.8-a architecture extensions. */
#define AARCH64_FL_V8_8 (1ULL << 45)
+/* Armv9.1-A. */
+#define AARCH64_FL_V9_1 (1ULL << 46)
+
+/* Armv9.2-A. */
+#define AARCH64_FL_V9_2 (1ULL << 47)
+
+/* Armv9.3-A. */
+#define AARCH64_FL_V9_3 (1ULL << 48)
+
/* Has FP and SIMD. */
#define AARCH64_FL_FPSIMD (AARCH64_FL_FP | AARCH64_FL_SIMD)
@@ -273,6 +282,12 @@
#define AARCH64_FL_FOR_ARCH9 \
(AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_V9 \
| AARCH64_FL_F16)
+#define AARCH64_FL_FOR_ARCH9_1 \
+ (AARCH64_FL_FOR_ARCH9 | AARCH64_FL_FOR_ARCH8_6 | AARCH64_FL_V9_1)
+#define AARCH64_FL_FOR_ARCH9_2 \
+ (AARCH64_FL_FOR_ARCH9_1 | AARCH64_FL_FOR_ARCH8_7 | AARCH64_FL_V9_2)
+#define AARCH64_FL_FOR_ARCH9_3 \
+ (AARCH64_FL_FOR_ARCH9_2 | AARCH64_FL_FOR_ARCH8_8 | AARCH64_FL_V9_3)
/* Macros to test ISA flags. */
@@ -312,6 +327,9 @@
#define AARCH64_ISA_V8_R (aarch64_isa_flags & AARCH64_FL_V8_R)
#define AARCH64_ISA_PAUTH (aarch64_isa_flags & AARCH64_FL_PAUTH)
#define AARCH64_ISA_V9 (aarch64_isa_flags & AARCH64_FL_V9)
+#define AARCH64_ISA_V9_1 (aarch64_isa_flags & AARCH64_FL_V9_1)
+#define AARCH64_ISA_V9_2 (aarch64_isa_flags & AARCH64_FL_V9_2)
+#define AARCH64_ISA_V9_3 (aarch64_isa_flags & AARCH64_FL_V9_3)
#define AARCH64_ISA_MOPS (aarch64_isa_flags & AARCH64_FL_MOPS)
#define AARCH64_ISA_LS64 (aarch64_isa_flags & AARCH64_FL_LS64)
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-expand.cc b/gcc/config/i386/i386-expand.cc
index 5334363..6baff6d 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -19604,6 +19604,119 @@ expand_vec_perm_1 (struct expand_vec_perm_d *d)
return false;
}
+/* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
+ in terms of a pair of shufps+ shufps/pshufd instructions. */
+static bool
+expand_vec_perm_shufps_shufps (struct expand_vec_perm_d *d)
+{
+ unsigned char perm1[4];
+ machine_mode vmode = d->vmode;
+ bool ok;
+ unsigned i, j, k, count = 0;
+
+ if (d->one_operand_p
+ || (vmode != V4SImode && vmode != V4SFmode))
+ return false;
+
+ if (d->testing_p)
+ return true;
+
+ for (i = 0; i < 4; ++i)
+ count += d->perm[i] > 3 ? 1 : 0;
+
+ gcc_assert (count & 3);
+
+ rtx tmp = gen_reg_rtx (vmode);
+ /* 2 from op0 and 2 from op1. */
+ if (count == 2)
+ {
+ unsigned char perm2[4];
+ for (i = 0, j = 0, k = 2; i < 4; ++i)
+ if (d->perm[i] & 4)
+ {
+ perm1[k++] = d->perm[i];
+ perm2[i] = k - 1;
+ }
+ else
+ {
+ perm1[j++] = d->perm[i];
+ perm2[i] = j - 1;
+ }
+
+ /* shufps. */
+ ok = expand_vselect_vconcat (tmp, d->op0, d->op1,
+ perm1, d->nelt, false);
+ gcc_assert (ok);
+ if (vmode == V4SImode && TARGET_SSE2)
+ /* pshufd. */
+ ok = expand_vselect (d->target, tmp,
+ perm2, d->nelt, false);
+ else
+ {
+ /* shufps. */
+ perm2[2] += 4;
+ perm2[3] += 4;
+ ok = expand_vselect_vconcat (d->target, tmp, tmp,
+ perm2, d->nelt, false);
+ }
+ gcc_assert (ok);
+ }
+ /* 3 from one op and 1 from another. */
+ else
+ {
+ unsigned pair_idx = 8, lone_idx = 8, shift;
+
+ /* Find the lone index. */
+ for (i = 0; i < 4; ++i)
+ if ((d->perm[i] > 3 && count == 1)
+ || (d->perm[i] < 4 && count == 3))
+ lone_idx = i;
+
+ /* When lone_idx is not 0, it must from second op(count == 1). */
+ gcc_assert (count == (lone_idx ? 1 : 3));
+
+ /* Find the pair index that sits in the same half as the lone index. */
+ shift = lone_idx & 2;
+ pair_idx = 1 - lone_idx + 2 * shift;
+
+ /* First permutate lone index and pair index into the same vector as
+ [ lone, lone, pair, pair ]. */
+ perm1[1] = perm1[0]
+ = (count == 3) ? d->perm[lone_idx] : d->perm[lone_idx] - 4;
+ perm1[3] = perm1[2]
+ = (count == 3) ? d->perm[pair_idx] : d->perm[pair_idx] + 4;
+
+ /* Alway put the vector contains lone indx at the first. */
+ if (count == 1)
+ std::swap (d->op0, d->op1);
+
+ /* shufps. */
+ ok = expand_vselect_vconcat (tmp, d->op0, d->op1,
+ perm1, d->nelt, false);
+ gcc_assert (ok);
+
+ /* Refine lone and pair index to original order. */
+ perm1[shift] = lone_idx << 1;
+ perm1[shift + 1] = pair_idx << 1;
+
+ /* Select the remaining 2 elements in another vector. */
+ for (i = 2 - shift; i < 4 - shift; ++i)
+ perm1[i] = lone_idx == 1 ? d->perm[i] + 4 : d->perm[i];
+
+ /* Adjust to original selector. */
+ if (lone_idx > 1)
+ std::swap (tmp, d->op1);
+
+ /* shufps. */
+ ok = expand_vselect_vconcat (d->target, tmp, d->op1,
+ perm1, d->nelt, false);
+
+ gcc_assert (ok);
+ }
+
+ return true;
+}
+
/* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
in terms of a pair of pshuflw + pshufhw instructions. */
@@ -22152,6 +22265,9 @@ ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *d)
if (expand_vec_perm_2perm_pblendv (d, true))
return true;
+ if (expand_vec_perm_shufps_shufps (d))
+ return true;
+
/* Try sequences of three instructions. */
if (expand_vec_perm_even_odd_pack (d))
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/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/nvptx/gen-multilib-matches.sh b/gcc/config/nvptx/gen-multilib-matches.sh
new file mode 100755
index 0000000..9a5878e
--- /dev/null
+++ b/gcc/config/nvptx/gen-multilib-matches.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+# Print nvptx 'MULTILIB_MATCHES'
+
+# Copyright (C) 2022 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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/>.
+
+set -e
+
+nvptx_sm_def="$1/nvptx-sm.def"
+multilib_options_isa_default=$2
+multilib_options_isa_list=$3
+
+sms=$(grep ^NVPTX_SM $nvptx_sm_def | sed 's/.*(//;s/,.*//')
+
+# Every variant in 'sms' has to either be remapped to the default variant
+# ('.', which is always built), or does get built as non-default variant
+# ('misa=sm_SM'; thus not remapped), or has to be remapped to the "next lower"
+# variant that does get built.
+
+# The "lowest" variant has to be built.
+sm_next_lower=INVALID
+
+for sm in $sms; do
+ if [ x"sm_$sm" = x"$multilib_options_isa_default" ]; then
+ sm_map=.
+ elif expr " $multilib_options_isa_list " : ".* sm_$sm " > /dev/null; then
+ sm_map=
+ else
+ sm_map=$sm_next_lower
+ fi
+
+ if [ x"$sm_map" = x ]; then
+ sm_next_lower=$sm
+ else
+ # Output format as required for 'MULTILIB_MATCHES'.
+ if [ x"$sm_map" = x. ]; then
+ echo ".=misa?sm_$sm"
+ else
+ echo "misa?sm_$sm_map=misa?sm_$sm"
+ fi
+
+ sm_next_lower=$sm_map
+ fi
+done
diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc
index 49cc681..2fe120b 100644
--- a/gcc/config/nvptx/nvptx.cc
+++ b/gcc/config/nvptx/nvptx.cc
@@ -334,6 +334,10 @@ nvptx_option_override (void)
{
init_machine_status = nvptx_init_machine_status;
+ /* Via nvptx 'OPTION_DEFAULT_SPECS', '-misa' always appears on the command
+ line. */
+ gcc_checking_assert (OPTION_SET_P (ptx_isa_option));
+
handle_ptx_version_option ();
/* Set toplevel_reorder, unless explicitly disabled. We need
diff --git a/gcc/config/nvptx/nvptx.h b/gcc/config/nvptx/nvptx.h
index dc9cad1..0afc83b 100644
--- a/gcc/config/nvptx/nvptx.h
+++ b/gcc/config/nvptx/nvptx.h
@@ -27,6 +27,14 @@
/* Run-time Target. */
+/* Use '--with-arch' for default '-misa'. */
+#define OPTION_DEFAULT_SPECS \
+ { "arch", "%{!misa=*:-misa=%(VALUE)}" }, \
+
+/* Assembler supports '-v' option; handle similar to
+ '../../gcc.cc:asm_options', 'HAVE_GNU_AS'. */
+#define ASM_SPEC "%{v}"
+
#define STARTFILE_SPEC "%{mmainkernel:crt0.o}"
#define TARGET_CPU_CPP_BUILTINS() nvptx_cpu_cpp_builtins ()
diff --git a/gcc/config/nvptx/nvptx.opt b/gcc/config/nvptx/nvptx.opt
index c5a5668..71d3b68 100644
--- a/gcc/config/nvptx/nvptx.opt
+++ b/gcc/config/nvptx/nvptx.opt
@@ -53,7 +53,7 @@ Target Mask(GOMP)
Generate code for OpenMP offloading: enables -msoft-stack and -muniform-simt.
misa=
-Target RejectNegative ToLower Joined Enum(ptx_isa) Var(ptx_isa_option) Init(PTX_ISA_SM30)
+Target RejectNegative ToLower Joined Enum(ptx_isa) Var(ptx_isa_option)
Specify the PTX ISA target architecture to use.
march=
diff --git a/gcc/config/nvptx/t-nvptx b/gcc/config/nvptx/t-nvptx
index 2b68149..9c5cbda 100644
--- a/gcc/config/nvptx/t-nvptx
+++ b/gcc/config/nvptx/t-nvptx
@@ -31,4 +31,33 @@ s-nvptx-gen-opt: $(srcdir)/config/nvptx/nvptx-sm.def \
tmp-nvptx-gen.opt $(srcdir)/config/nvptx/nvptx-gen.opt
$(STAMP) s-nvptx-gen-opt
-MULTILIB_OPTIONS = mgomp mptx=3.1
+
+# Multilib setup.
+
+MULTILIB_OPTIONS =
+MULTILIB_MATCHES =
+MULTILIB_EXCEPTIONS =
+
+MULTILIB_OPTIONS += mgomp
+
+multilib_options_isa_list := $(TM_MULTILIB_CONFIG)
+multilib_options_isa_default := $(word 1,$(multilib_options_isa_list))
+multilib_options_misa_list := $(addprefix misa=,$(multilib_options_isa_list))
+# Add the requested '-misa' variants as a multilib option ('misa=VAR1/misa=VAR2/misa=VAR3' etc.):
+empty :=
+space := $(empty) $(empty)
+MULTILIB_OPTIONS += $(subst $(space),/,$(multilib_options_misa_list))
+# ..., and remap '-misa' variants as appropriate:
+multilib_matches := $(shell $(srcdir)/config/nvptx/gen-multilib-matches.sh $(srcdir)/config/nvptx $(multilib_options_isa_default) "$(multilib_options_isa_list)")
+MULTILIB_MATCHES += $(multilib_matches)
+# ..., and don't actually build what's the default '-misa':
+MULTILIB_EXCEPTIONS += *misa=$(multilib_options_isa_default)*
+
+MULTILIB_OPTIONS += mptx=3.1
+# Filter out invalid '-misa'/'-mptx=3.1' combinations; per 'nvptx-sm.def',
+# 'nvptx.opt:ptx_version', 'nvptx.cc:first_ptx_version_supporting_sm'
+# (that is, '-mptx=3.1' only for sm_30, sm_35 variants):
+MULTILIB_EXCEPTIONS += $(foreach misa,$(filter-out %=sm_30 %=sm_35,$(multilib_options_misa_list)),*$(misa)/mptx=3.1)
+# ..., and special care has to be taken if '-mptx=3.1' is invalid for the
+# default variant:
+MULTILIB_EXCEPTIONS += $(if $(filter-out sm_30 sm_35,$(multilib_options_isa_default)),mgomp/mptx=3.1 mptx=3.1)
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-logue.cc b/gcc/config/rs6000/rs6000-logue.cc
index 80a2e0d..f575e69 100644
--- a/gcc/config/rs6000/rs6000-logue.cc
+++ b/gcc/config/rs6000/rs6000-logue.cc
@@ -4920,7 +4920,7 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type)
a REG_CFA_DEF_CFA note, but that's OK; A duplicate is
discarded by dwarf2cfi.cc/dwarf2out.cc, and in any case would
be harmless if emitted. */
- if (frame_pointer_needed)
+ if (frame_pointer_needed_indeed)
{
insn = get_last_insn ();
add_reg_note (insn, REG_CFA_DEF_CFA,
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/config/rs6000/vector.md b/gcc/config/rs6000/vector.md
index a0d33d2..0171705 100644
--- a/gcc/config/rs6000/vector.md
+++ b/gcc/config/rs6000/vector.md
@@ -1475,7 +1475,7 @@
[(match_operand:VEC_L 0 "vlogical_operand")
(match_operand:VEC_L 1 "vlogical_operand")
(match_operand:QI 2 "reg_or_short_operand")]
- "TARGET_ALTIVEC"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
{
rtx bitshift = operands[2];
rtx shift;
diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index 3ae586c..9861913 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -3648,7 +3648,7 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code,
*total = 0;
return true;
case SET: {
- rtx dest = SET_DEST (x);
+ rtx dst = SET_DEST (x);
rtx src = SET_SRC (x);
switch (GET_CODE (src))
@@ -3669,7 +3669,6 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code,
slightly more expensive than a normal load. */
*total = COSTS_N_INSNS (1) + 2;
- rtx dst = SET_DEST (src);
rtx then = XEXP (src, 1);
rtx els = XEXP (src, 2);
@@ -3696,25 +3695,25 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code,
break;
}
- switch (GET_CODE (dest))
+ switch (GET_CODE (dst))
{
case SUBREG:
- if (!REG_P (SUBREG_REG (dest)))
+ if (!REG_P (SUBREG_REG (dst)))
*total += rtx_cost (SUBREG_REG (src), VOIDmode, SET, 0, speed);
/* fallthrough */
case REG:
/* If this is a VR -> VR copy, count the number of
registers. */
- if (VECTOR_MODE_P (GET_MODE (dest)) && REG_P (src))
+ if (VECTOR_MODE_P (GET_MODE (dst)) && REG_P (src))
{
- int nregs = s390_hard_regno_nregs (VR0_REGNUM, GET_MODE (dest));
+ int nregs = s390_hard_regno_nregs (VR0_REGNUM, GET_MODE (dst));
*total = COSTS_N_INSNS (nregs);
}
/* Same for GPRs. */
else if (REG_P (src))
{
int nregs
- = s390_hard_regno_nregs (GPR0_REGNUM, GET_MODE (dest));
+ = s390_hard_regno_nregs (GPR0_REGNUM, GET_MODE (dst));
*total = COSTS_N_INSNS (nregs);
}
else
@@ -3722,7 +3721,7 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code,
*total += rtx_cost (src, mode, SET, 1, speed);
return true;
case MEM: {
- rtx address = XEXP (dest, 0);
+ rtx address = XEXP (dst, 0);
rtx tmp;
HOST_WIDE_INT tmp2;
if (s390_loadrelative_operand_p (address, &tmp, &tmp2))
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b9b2729..ca5015e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,28 @@
+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..fc86b74 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))
@@ -5842,6 +5858,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 +7937,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 +8583,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 +11772,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 +12261,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 +12277,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/cp-tree.h b/gcc/cp/cp-tree.h
index e4d8920..99b486b8 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).
@@ -1490,6 +1491,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 +1839,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 +1890,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;
};
@@ -7946,6 +7956,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 +8699,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/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..0389f35 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -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..00d283f 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 ();
}
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index c35a59f..9f917f1 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -2236,6 +2236,19 @@ ref_xes_from_temporary (tree to, tree from, bool direct_init_p)
return ref_conv_binds_directly (to, val, direct_init_p).is_false ();
}
+/* Worker for is_{,nothrow_}convertible. Attempt to perform an implicit
+ conversion from FROM to TO and return the result. */
+
+static tree
+is_convertible_helper (tree from, tree to)
+{
+ if (VOID_TYPE_P (from) && VOID_TYPE_P (to))
+ return integer_one_node;
+ cp_unevaluated u;
+ tree expr = build_stub_object (from);
+ return perform_implicit_conversion (to, expr, tf_none);
+}
+
/* Return true if FROM can be converted to TO using implicit conversions,
or both FROM and TO are possibly cv-qualified void. NB: This doesn't
implement the "Access checks are performed as if from a context unrelated
@@ -2244,10 +2257,7 @@ ref_xes_from_temporary (tree to, tree from, bool direct_init_p)
bool
is_convertible (tree from, tree to)
{
- if (VOID_TYPE_P (from) && VOID_TYPE_P (to))
- return true;
- tree expr = build_stub_object (from);
- expr = perform_implicit_conversion (to, expr, tf_none);
+ tree expr = is_convertible_helper (from, to);
if (expr == error_mark_node)
return false;
return !!expr;
@@ -2258,10 +2268,7 @@ is_convertible (tree from, tree to)
bool
is_nothrow_convertible (tree from, tree to)
{
- if (VOID_TYPE_P (from) && VOID_TYPE_P (to))
- return true;
- tree expr = build_stub_object (from);
- expr = perform_implicit_conversion (to, expr, tf_none);
+ tree expr = is_convertible_helper (from, to);
if (expr == NULL_TREE || expr == error_mark_node)
return false;
return expr_noexcept_p (expr, tf_none);
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index f23832c..7496df5 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -8185,13 +8185,18 @@ trees_in::decl_value ()
/* Set the TEMPLATE_DECL's type. */
TREE_TYPE (decl) = TREE_TYPE (inner);
- if (mk & MK_template_mask
- || mk == MK_partial)
+ /* Add to specialization tables now that constraints etc are
+ added. */
+ if (mk == MK_partial)
{
- /* Add to specialization tables now that constraints etc are
- added. */
- bool is_type = mk == MK_partial || !(mk & MK_tmpl_decl_mask);
-
+ bool is_type = TREE_CODE (inner) == TYPE_DECL;
+ spec.spec = is_type ? type : inner;
+ add_mergeable_specialization (!is_type, false,
+ &spec, decl, spec_flags);
+ }
+ else if (mk & MK_template_mask)
+ {
+ bool is_type = !(mk & MK_tmpl_decl_mask);
spec.spec = is_type ? type : mk & MK_tmpl_tmpl_mask ? inner : decl;
add_mergeable_specialization (!is_type,
!is_type && mk & MK_tmpl_alias_mask,
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 db4e808..1c1e573 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -11945,6 +11945,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);
@@ -31010,7 +31011,7 @@ add_mergeable_specialization (bool decl_p, bool alias_p, spec_entry *elt,
/* A partial specialization. */
tree cons = tree_cons (elt->args, decl,
DECL_TEMPLATE_SPECIALIZATIONS (elt->tmpl));
- TREE_TYPE (cons) = elt->spec;
+ TREE_TYPE (cons) = decl_p ? TREE_TYPE (elt->spec) : elt->spec;
DECL_TEMPLATE_SPECIALIZATIONS (elt->tmpl) = cons;
}
}
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/typeck.cc b/gcc/cp/typeck.cc
index 22d834d..4854b98 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,
diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 75fd0e2..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)
{
@@ -1118,6 +1131,15 @@ array_string_literal_compatible_p (tree type, tree init)
if (ordinary_char_type_p (to_char_type)
&& ordinary_char_type_p (from_char_type))
return true;
+
+ /* P2513 (C++20/C++23): "an array of char or unsigned char may
+ be initialized by a UTF-8 string literal, or by such a string
+ literal enclosed in braces." */
+ if (from_char_type == char8_type_node
+ && (to_char_type == char_type_node
+ || to_char_type == unsigned_char_type_node))
+ return true;
+
return false;
}
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/install.texi b/gcc/doc/install.texi
index 7df6345..cc01c69 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -4598,6 +4598,15 @@ the GCC sources.
Use the @option{--disable-sjlj-exceptions} and
@option{--enable-newlib-io-long-long} options when configuring.
+The @option{--with-arch} option may be specified to override the
+default value for the @option{-march} option, and to also build
+corresponding target libraries.
+The default is @option{--with-arch=sm_30}.
+
+For example, if @option{--with-arch=sm_70} is specified,
+@option{-march=sm_30} and @option{-march=sm_70} target libraries are
+built, and code generation defaults to @option{-march=sm_70}.
+
@html
<hr />
@end html
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 928ab0f..383d22a 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -9901,7 +9901,7 @@ security-sensitive value is written to an output file
See @uref{https://cwe.mitre.org/data/definitions/532.html, CWE-532: Information Exposure Through Log Files}.
-@item Wanalyzer-exposure-through-uninit-copy
+@item -Wanalyzer-exposure-through-uninit-copy
@opindex Wanalyzer-exposure-through-uninit-copy
@opindex Wno-analyzer-exposure-through-uninit-copy
This warning requires both @option{-fanalyzer} and the use of a plugin
@@ -19681,6 +19681,9 @@ and the features that they enable by default:
@item @samp{armv8.7-a} @tab Armv8.7-A @tab @samp{armv8.6-a}, @samp{+ls64}
@item @samp{armv8.8-a} @tab Armv8.8-a @tab @samp{armv8.7-a}, @samp{+mops}
@item @samp{armv9-a} @tab Armv9-A @tab @samp{armv8.5-a}, @samp{+sve}, @samp{+sve2}
+@item @samp{armv9.1-a} @tab Armv9.1-A @tab @samp{armv9-a}, @samp{+bf16}, @samp{+i8mm}
+@item @samp{armv9.2-a} @tab Armv9.2-A @tab @samp{armv9.1-a}, @samp{+ls64}
+@item @samp{armv9.3-a} @tab Armv9.3-A @tab @samp{armv9.2-a}, @samp{+mops}
@item @samp{armv8-r} @tab Armv8-R @tab @samp{armv8-r}
@end multitable
@@ -28055,7 +28058,9 @@ supported.
Generate code for the specified PTX ISA target architecture
(e.g.@: @samp{sm_35}). Valid architecture strings are @samp{sm_30},
@samp{sm_35}, @samp{sm_53}, @samp{sm_70}, @samp{sm_75} and
-@samp{sm_80}. The default target architecture is sm_30.
+@samp{sm_80}.
+The default depends on how the compiler has been configured, see
+@option{--with-arch}.
This option sets the value of the preprocessor macro
@code{__PTX_SM__}; for instance, for @samp{sm_35}, it has the value
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 760ff95..52357cc 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -2447,7 +2447,7 @@ PowerPC target pre-defines macro _ARCH_PWR9 which means the @code{-mcpu}
setting is Power9 or later.
@end table
-@subsection RISC-V specific attributes
+@subsubsection RISC-V specific attributes
@table @code
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 998fb1b..6985e62 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,69 @@
+2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/41453
+ * trans-expr.cc (gfc_conv_procedure_call): Allow strictly
+ matching derived types.
+
+2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/41453
+ PR fortran/99169
+ * trans-expr.cc (gfc_conv_procedure_call): Remove conditions
+ on ALLOCATABLE and POINTER attributes guarding clobber
+ generation.
+
+2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/41453
+ PR fortran/87401
+ * trans-expr.cc (gfc_conv_procedure_call): Remove condition
+ disabling clobber generation for ASSOCIATE variables.
+
+2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/41453
+ PR fortran/87395
+ * trans-expr.cc (gfc_conv_procedure_call): Remove condition
+ on SAVE attribute guarding clobber generation.
+
+2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/41453
+ PR fortran/87395
+ * trans-expr.cc (gfc_conv_procedure_call): Remove condition
+ disabling clobber generation for dummy variables. Remove
+ obsolete comment.
+
+2022-09-25 Harald Anlauf <anlauf@gmx.de>
+ Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/105012
+ * trans-expr.cc (gfc_conv_procedure_call): Use dummy
+ information from associated_dummy if there is no information
+ from the procedure interface.
+
+2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/106817
+ * trans-expr.cc (gfc_conv_procedure_call): Collect all clobbers
+ to their own separate block. Append the block of clobbers to
+ the procedure preliminary block after the argument evaluation
+ codes for all the arguments.
+
+2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/105012
+ * trans-expr.cc (gfc_conv_procedure_call): Retrieve variable
+ from the just calculated variable reference.
+
+2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ * trans.h (gfc_conv_expr_reference): Remove add_clobber
+ argument.
+ * trans-expr.cc (gfc_conv_expr_reference): Ditto. Inline code
+ depending on add_clobber and conditions controlling it ...
+ (gfc_conv_procedure_call): ... to here.
+
2022-09-22 José Rui Faustino de Sousa <jrfsousa@gmail.com>
PR fortran/100103
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 7895d03..4f3ae82 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -6018,7 +6018,6 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
gfc_charlen cl;
gfc_expr *e;
gfc_symbol *fsym;
- stmtblock_t post;
enum {MISSING = 0, ELEMENTAL, SCALAR, SCALAR_POINTER, ARRAY};
gfc_component *comp = NULL;
int arglen;
@@ -6062,7 +6061,9 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
else
info = NULL;
+ stmtblock_t post, clobbers;
gfc_init_block (&post);
+ gfc_init_block (&clobbers);
gfc_init_interface_mapping (&mapping);
if (!comp)
{
@@ -6395,7 +6396,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
&& e->symtree->n.sym->attr.pointer))
&& fsym && fsym->attr.target)
/* Make sure the function only gets called once. */
- gfc_conv_expr_reference (&parmse, e, false);
+ gfc_conv_expr_reference (&parmse, e);
else if (e->expr_type == EXPR_FUNCTION
&& e->symtree->n.sym->result
&& e->symtree->n.sym->result != e->symtree->n.sym
@@ -6502,22 +6503,55 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
}
else
{
- bool add_clobber;
- add_clobber = fsym && fsym->attr.intent == INTENT_OUT
- && !fsym->attr.allocatable && !fsym->attr.pointer
- && e->symtree && e->symtree->n.sym
- && !e->symtree->n.sym->attr.dimension
- && !e->symtree->n.sym->attr.pointer
- && !e->symtree->n.sym->attr.allocatable
- /* See PR 41453. */
- && !e->symtree->n.sym->attr.dummy
- /* FIXME - PR 87395 and PR 41453 */
- && e->symtree->n.sym->attr.save == SAVE_NONE
- && !e->symtree->n.sym->attr.associate_var
- && e->ts.type != BT_CHARACTER && e->ts.type != BT_DERIVED
- && e->ts.type != BT_CLASS && !sym->attr.elemental;
-
- gfc_conv_expr_reference (&parmse, e, add_clobber);
+ gfc_conv_expr_reference (&parmse, e);
+
+ gfc_symbol *dsym = fsym;
+ gfc_dummy_arg *dummy;
+
+ /* Use associated dummy as fallback for formal
+ argument if there is no explicit interface. */
+ if (dsym == NULL
+ && (dummy = arg->associated_dummy)
+ && dummy->intrinsicness == GFC_NON_INTRINSIC_DUMMY_ARG
+ && dummy->u.non_intrinsic->sym)
+ dsym = dummy->u.non_intrinsic->sym;
+
+ if (dsym
+ && dsym->attr.intent == INTENT_OUT
+ && !dsym->attr.allocatable
+ && !dsym->attr.pointer
+ && e->expr_type == EXPR_VARIABLE
+ && e->ref == NULL
+ && e->symtree
+ && e->symtree->n.sym
+ && !e->symtree->n.sym->attr.dimension
+ && e->ts.type != BT_CHARACTER
+ && e->ts.type != BT_CLASS
+ && (e->ts.type != BT_DERIVED
+ || (dsym->ts.type == BT_DERIVED
+ && e->ts.u.derived == dsym->ts.u.derived
+ /* Types with allocatable components are
+ excluded from clobbering because we need
+ the unclobbered pointers to free the
+ allocatable components in the callee.
+ Same goes for finalizable types or types
+ with finalizable components, we need to
+ pass the unclobbered values to the
+ finalization routines.
+ For parameterized types, it's less clear
+ but they may not have a constant size
+ so better exclude them in any case. */
+ && !e->ts.u.derived->attr.alloc_comp
+ && !e->ts.u.derived->attr.pdt_type
+ && !gfc_is_finalizable (e->ts.u.derived, NULL)))
+ && !sym->attr.elemental)
+ {
+ tree var;
+ var = build_fold_indirect_ref_loc (input_location,
+ parmse.expr);
+ tree clobber = build_clobber (TREE_TYPE (var));
+ gfc_add_modify (&clobbers, var, clobber);
+ }
}
/* Catch base objects that are not variables. */
if (e->ts.type == BT_CLASS
@@ -7384,6 +7418,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
vec_safe_push (arglist, parmse.expr);
}
+ gfc_add_block_to_block (&se->pre, &clobbers);
gfc_finish_interface_mapping (&mapping, &se->pre, &se->post);
if (comp)
@@ -9484,7 +9519,7 @@ gfc_conv_expr_type (gfc_se * se, gfc_expr * expr, tree type)
values only. */
void
-gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr, bool add_clobber)
+gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr)
{
gfc_ss *ss;
tree var;
@@ -9524,16 +9559,6 @@ gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr, bool add_clobber)
gfc_add_block_to_block (&se->pre, &se->post);
se->expr = var;
}
- else if (add_clobber && expr->ref == NULL)
- {
- tree clobber;
- tree var;
- /* FIXME: This fails if var is passed by reference, see PR
- 41453. */
- var = expr->symtree->n.sym->backend_decl;
- clobber = build_clobber (TREE_TYPE (var));
- gfc_add_modify (&se->pre, var, clobber);
- }
return;
}
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 03d5288..bc9035c 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -499,8 +499,7 @@ tree gfc_build_compare_string (tree, tree, tree, tree, int, enum tree_code);
void gfc_conv_expr (gfc_se * se, gfc_expr * expr);
void gfc_conv_expr_val (gfc_se * se, gfc_expr * expr);
void gfc_conv_expr_lhs (gfc_se * se, gfc_expr * expr);
-void gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr,
- bool add_clobber = false);
+void gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr);
void gfc_conv_expr_type (gfc_se * se, gfc_expr *, tree);
diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc
index d9f9aae..dc42c75 100644
--- a/gcc/omp-low.cc
+++ b/gcc/omp-low.cc
@@ -7631,6 +7631,7 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
incoming = build_simple_mem_ref (incoming);
}
else
+ /* Note that 'var' might be a mem ref. */
v1 = v2 = v3 = var;
/* Determine position in reduction buffer, which may be used
@@ -7659,26 +7660,28 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
= build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
TREE_TYPE (var), 6, setup_code,
unshare_expr (ref_to_res),
- incoming, level, op, off);
+ unshare_expr (incoming),
+ level, op, off);
tree init_call
= build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
TREE_TYPE (var), 6, init_code,
unshare_expr (ref_to_res),
- v1, level, op, off);
+ unshare_expr (v1), level, op, off);
tree fini_call
= build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
TREE_TYPE (var), 6, fini_code,
unshare_expr (ref_to_res),
- v2, level, op, off);
+ unshare_expr (v2), level, op, off);
tree teardown_call
= build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
TREE_TYPE (var), 6, teardown_code,
- ref_to_res, v3, level, op, off);
+ ref_to_res, unshare_expr (v3),
+ level, op, off);
- gimplify_assign (v1, setup_call, &before_fork);
- gimplify_assign (v2, init_call, &after_fork);
- gimplify_assign (v3, fini_call, &before_join);
- gimplify_assign (outgoing, teardown_call, &after_join);
+ gimplify_assign (unshare_expr (v1), setup_call, &before_fork);
+ gimplify_assign (unshare_expr (v2), init_call, &after_fork);
+ gimplify_assign (unshare_expr (v3), fini_call, &before_join);
+ gimplify_assign (unshare_expr (outgoing), teardown_call, &after_join);
}
/* Now stitch things together. */
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 072ebd3..fc930f4 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -2951,6 +2951,15 @@ operator_bitwise_and::op1_range (irange &r, tree type,
}
if (r.undefined_p ())
set_nonzero_range_from_mask (r, type, lhs);
+
+ // For 0 = op1 & MASK, op1 is ~MASK.
+ if (lhs.zero_p () && op2.singleton_p ())
+ {
+ wide_int nz = wi::bit_not (op2.get_nonzero_bits ());
+ int_range<2> tmp (type);
+ tmp.set_nonzero_bits (nz);
+ r.intersect (tmp);
+ }
return true;
}
@@ -4612,6 +4621,15 @@ range_op_bitwise_and_tests ()
op_bitwise_and.op1_range (res, integer_type_node, i1, i2);
ASSERT_TRUE (res == int_range<1> (integer_type_node));
+ // For 0 = x & MASK, x is ~MASK.
+ {
+ int_range<2> zero (integer_zero_node, integer_zero_node);
+ int_range<2> mask = int_range<2> (INT (7), INT (7));
+ op_bitwise_and.op1_range (res, integer_type_node, zero, mask);
+ wide_int inv = wi::shwi (~7U, TYPE_PRECISION (integer_type_node));
+ ASSERT_TRUE (res.get_nonzero_bits () == inv);
+ }
+
// (NONZERO | X) is nonzero.
i1.set_nonzero (integer_type_node);
i2.set_varying (integer_type_node);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d37e199..24f4ac5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,122 @@
+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
+ * gfortran.dg/intent_optimize_10.f90: New test.
+
+2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/41453
+ PR fortran/99169
+ * gfortran.dg/intent_optimize_9.f90: New test.
+
+2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/41453
+ PR fortran/87401
+ * gfortran.dg/intent_optimize_8.f90: New test.
+
+2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/41453
+ PR fortran/87395
+ * gfortran.dg/intent_optimize_7.f90: New test.
+
+2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/41453
+ PR fortran/87395
+ * gfortran.dg/intent_optimize_6.f90: New test.
+
+2022-09-25 Harald Anlauf <anlauf@gmx.de>
+ Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/105012
+ * gfortran.dg/intent_optimize_5.f90: New test.
+
+2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/106817
+ * gfortran.dg/intent_optimize_4.f90: New test.
+
+2022-09-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/105012
+ * gfortran.dg/intent_out_15.f90: New test.
+
+2022-09-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/107001
+ * c-c++-common/gomp/pr107001.c: New test.
+
+2022-09-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/106981
+ * c-c++-common/gomp/pr106981.c: New test.
+
2022-09-23 Joseph Myers <joseph@codesourcery.com>
* gcc.dg/c2x-complit-1.c, gcc.dg/c2x-concat-1.c,
diff --git a/gcc/testsuite/c-c++-common/goacc/reduction-7.c b/gcc/testsuite/c-c++-common/goacc/reduction-7.c
new file mode 100644
index 0000000..482b0ab
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/reduction-7.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+
+/* PR middle-end/106982 */
+
+long long n = 100;
+int multiplicitive_n = 128;
+
+void test1(double *rand, double *a, double *b, double *c)
+{
+#pragma acc data copyin(a[0:10*multiplicitive_n], b[0:10*multiplicitive_n]) copyout(c[0:10])
+ {
+#pragma acc parallel loop
+ for (int i = 0; i < 10; ++i)
+ {
+ double temp = 1.0;
+#pragma acc loop vector reduction(*:temp)
+ for (int j = 0; j < multiplicitive_n; ++j)
+ temp *= a[(i * multiplicitive_n) + j] + b[(i * multiplicitive_n) + j];
+ c[i] = temp;
+ }
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/reduction-8.c b/gcc/testsuite/c-c++-common/goacc/reduction-8.c
new file mode 100644
index 0000000..2c3ed49
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/reduction-8.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+/* PR middle-end/106982 */
+
+void test1(double *c)
+{
+ double reduced[5];
+#pragma acc parallel loop gang private(reduced)
+ for (int x = 0; x < 5; ++x)
+#pragma acc loop worker reduction(*:reduced)
+ for (int y = 0; y < 5; ++y) { }
+}
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/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/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 d3e4072..2f6b21e 100644
--- a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
+++ b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
@@ -504,8 +504,8 @@
#ifndef __cpp_char8_t
# error "__cpp_char8_t"
-#elif __cpp_char8_t != 201811
-# error "__cpp_char8_t != 201811"
+#elif __cpp_char8_t != 202207
+# error "__cpp_char8_t != 202207"
#endif
#ifndef __cpp_designated_initializers
@@ -563,3 +563,9 @@
#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
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/char8_t3.C b/gcc/testsuite/g++.dg/cpp2a/char8_t3.C
new file mode 100644
index 0000000..071a718
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/char8_t3.C
@@ -0,0 +1,37 @@
+// PR c++/106656 - P2513 - char8_t Compatibility and Portability Fixes
+// { dg-do compile { target c++20 } }
+
+const char *p1 = u8""; // { dg-error "invalid conversion" }
+const unsigned char *p2 = u8""; // { dg-error "invalid conversion" }
+const signed char *p3 = u8""; // { dg-error "invalid conversion" }
+const char *p4 = { u8"" }; // { dg-error "invalid conversion" }
+const unsigned char *p5 = { u8"" }; // { dg-error "invalid conversion" }
+const signed char *p6 = { u8"" }; // { dg-error "invalid conversion" }
+const char *p7 = static_cast<const char *>(u8""); // { dg-error "invalid" }
+const char a1[] = u8"text";
+const unsigned char a2[] = u8"";
+const signed char a3[] = u8""; // { dg-error "cannot initialize array" }
+const char a4[] = { u8"text" };
+const unsigned char a5[] = { u8"" };
+const signed char a6[] = { u8"" }; // { dg-error "cannot initialize array" }
+
+const char *
+resource_id ()
+{
+ static const char res_id[] = u8"";
+ return res_id;
+}
+
+const char8_t x[] = "fail"; // { dg-error "cannot initialize array" }
+
+void fn (const char a[]);
+void
+g ()
+{
+ fn (u8"z"); // { dg-error "invalid conversion" }
+}
+
+char c = u8'c';
+unsigned char uc = u8'c';
+signed char sc = u8'c';
+char8_t c8 = 'c';
diff --git a/gcc/testsuite/g++.dg/cpp2a/char8_t4.C b/gcc/testsuite/g++.dg/cpp2a/char8_t4.C
new file mode 100644
index 0000000..c18081b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/char8_t4.C
@@ -0,0 +1,17 @@
+// PR c++/106656 - P2513 - char8_t Compatibility and Portability Fixes
+// { dg-do compile { target c++20 } }
+// [diff.cpp20.dcl]
+
+struct A {
+ char8_t s[10];
+};
+struct B {
+ char s[10];
+};
+
+void f(A);
+void f(B);
+
+int main() {
+ f({u8""}); // { dg-error "ambiguous" }
+}
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/cpp2a/feat-cxx2a.C b/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
index c65ea6b..02f3a37 100644
--- a/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
+++ b/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
@@ -504,8 +504,8 @@
#ifndef __cpp_char8_t
# error "__cpp_char8_t"
-#elif __cpp_char8_t != 201811
-# error "__cpp_char8_t != 201811"
+#elif __cpp_char8_t != 202207
+# error "__cpp_char8_t != 202207"
#endif
#ifndef __cpp_designated_initializers
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/char8_t-feature-test-macro-2.C b/gcc/testsuite/g++.dg/ext/char8_t-feature-test-macro-2.C
index df1063f..2d0f904 100644
--- a/gcc/testsuite/g++.dg/ext/char8_t-feature-test-macro-2.C
+++ b/gcc/testsuite/g++.dg/ext/char8_t-feature-test-macro-2.C
@@ -5,6 +5,6 @@
#if !defined(__cpp_char8_t)
# error __cpp_char8_t is not defined!
-#elif __cpp_char8_t != 201811
-# error __cpp_char8_t != 201811
+#elif __cpp_char8_t != 202207
+# error __cpp_char8_t != 202207
#endif
diff --git a/gcc/testsuite/g++.dg/ext/char8_t-init-2.C b/gcc/testsuite/g++.dg/ext/char8_t-init-2.C
index c713bc1..02a96ff 100644
--- a/gcc/testsuite/g++.dg/ext/char8_t-init-2.C
+++ b/gcc/testsuite/g++.dg/ext/char8_t-init-2.C
@@ -21,7 +21,7 @@ const char8_t (&rca4)[2] = u8"x";
const char8_t (&rca5)[2] = u"x"; // { dg-error "invalid initialization of reference of type .const char8_t ....... from expression of type .const char16_t ...." "char8_t" }
char ca1[] = "x";
-char ca2[] = u8"x"; // { dg-error "from a string literal with type array of .char8_t." "char8_t" }
+char ca2[] = u8"x";
char8_t ca3[] = "x"; // { dg-error "from a string literal with type array of .char." "char8_t" }
char8_t ca4[] = u8"x";
char8_t ca5[] = u"x"; // { dg-error "from a string literal with type array of .char16_t." "char8_t" }
@@ -30,4 +30,4 @@ signed char sca1[] = "x";
signed char sca2[] = u8"x"; // { dg-error "from a string literal with type array of .char8_t." "char8_t" }
unsigned char uca1[] = "x";
-unsigned char uca2[] = u8"x"; // { dg-error "from a string literal with type array of .char8_t." "char8_t" }
+unsigned char uca2[] = u8"x";
diff --git a/gcc/testsuite/g++.dg/ext/is_convertible3.C b/gcc/testsuite/g++.dg/ext/is_convertible3.C
new file mode 100644
index 0000000..7a986d0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_convertible3.C
@@ -0,0 +1,9 @@
+// PR c++/106784
+// { dg-do compile { target c++11 } }
+// Make sure we don't reject this at runtime by trying to instantiate
+// something that would be ill-formed.
+
+struct A;
+struct B { template<class T> B(const T&) noexcept { T::nonexistent; } };
+
+static_assert(__is_convertible(const A&, B), "");
diff --git a/gcc/testsuite/g++.dg/ext/is_nothrow_convertible3.C b/gcc/testsuite/g++.dg/ext/is_nothrow_convertible3.C
new file mode 100644
index 0000000..05b1e1d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_nothrow_convertible3.C
@@ -0,0 +1,9 @@
+// PR c++/106784
+// { dg-do compile { target c++11 } }
+// Make sure we don't reject this at runtime by trying to instantiate
+// something that would be ill-formed.
+
+struct A;
+struct B { template<class T> B(const T&) noexcept { T::nonexistent; } };
+
+static_assert(__is_nothrow_convertible(const A&, B), "");
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/modules/partial-2.cc b/gcc/testsuite/g++.dg/modules/partial-2.cc
new file mode 100644
index 0000000..1316bf5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/partial-2.cc
@@ -0,0 +1,17 @@
+static_assert(is_reference_v<int&>);
+static_assert(is_reference_v<int&&>);
+static_assert(!is_reference_v<int>);
+
+static_assert(A::is_reference_v<long&>);
+static_assert(A::is_reference_v<long&&>);
+static_assert(!A::is_reference_v<long>);
+
+#if __cpp_concepts
+static_assert(concepts::is_reference_v<char&>);
+static_assert(concepts::is_reference_v<char&&>);
+static_assert(!concepts::is_reference_v<char>);
+
+static_assert(concepts::A::is_reference_v<bool&>);
+static_assert(concepts::A::is_reference_v<bool&&>);
+static_assert(!concepts::A::is_reference_v<bool>);
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/partial-2.h b/gcc/testsuite/g++.dg/modules/partial-2.h
new file mode 100644
index 0000000..afcfce7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/partial-2.h
@@ -0,0 +1,38 @@
+template<class T> constexpr bool is_reference_v = false;
+template<class T> constexpr bool is_reference_v<T&> = true;
+template<class T> constexpr bool is_reference_v<T&&> = true;
+
+struct A {
+ template<class T> static constexpr bool is_reference_v = false;
+};
+
+template<class T> constexpr bool A::is_reference_v<T&> = true;
+template<class T> constexpr bool A::is_reference_v<T&&> = true;
+
+#if __cpp_concepts
+namespace concepts {
+ template<class T> bool is_reference_v;
+
+ template<class T> requires __is_same(T, T&)
+ constexpr bool is_reference_v<T> = true;
+
+ template<class T> requires __is_same(T, T&&) && (!__is_same(T, T&))
+ constexpr bool is_reference_v<T> = true;
+
+ template<class T> requires (!__is_same(T, T&)) && (!__is_same(T, T&&))
+ constexpr bool is_reference_v<T> = false;
+
+ struct A {
+ template<class T> static bool is_reference_v;
+ };
+
+ template<class T> requires __is_same(T, T&)
+ constexpr bool A::is_reference_v<T> = true;
+
+ template<class T> requires __is_same(T, T&&) && (!__is_same(T, T&))
+ constexpr bool A::is_reference_v<T> = true;
+
+ template<class T> requires (!__is_same(T, T&)) && (!__is_same(T, T&&))
+ constexpr bool A::is_reference_v<T> = false;
+}
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/partial-2_a.C b/gcc/testsuite/g++.dg/modules/partial-2_a.C
index 2681bb5..1582f56 100644
--- a/gcc/testsuite/g++.dg/modules/partial-2_a.C
+++ b/gcc/testsuite/g++.dg/modules/partial-2_a.C
@@ -3,41 +3,4 @@
// { dg-module-cmi pr106826 }
export module pr106826;
-template<class T> constexpr bool is_reference_v = false;
-template<class T> constexpr bool is_reference_v<T&> = true;
-template<class T> constexpr bool is_reference_v<T&&> = true;
-
-struct A {
- template<class T> static constexpr bool is_reference_v = false;
-};
-
-template<class T> constexpr bool A::is_reference_v<T&> = true;
-template<class T> constexpr bool A::is_reference_v<T&&> = true;
-
-#if __cpp_concepts
-namespace concepts {
- template<class T> bool is_reference_v;
-
- template<class T> requires __is_same(T, T&)
- constexpr bool is_reference_v<T> = true;
-
- template<class T> requires __is_same(T, T&&) && (!__is_same(T, T&))
- constexpr bool is_reference_v<T> = true;
-
- template<class T> requires (!__is_same(T, T&)) && (!__is_same(T, T&&))
- constexpr bool is_reference_v<T> = false;
-
- struct A {
- template<class T> static bool is_reference_v;
- };
-
- template<class T> requires __is_same(T, T&)
- constexpr bool A::is_reference_v<T> = true;
-
- template<class T> requires __is_same(T, T&&) && (!__is_same(T, T&))
- constexpr bool A::is_reference_v<T> = true;
-
- template<class T> requires (!__is_same(T, T&)) && (!__is_same(T, T&&))
- constexpr bool A::is_reference_v<T> = false;
-}
-#endif
+#include "partial-2.h"
diff --git a/gcc/testsuite/g++.dg/modules/partial-2_b.C b/gcc/testsuite/g++.dg/modules/partial-2_b.C
index 0af41ef..1b0c7a5 100644
--- a/gcc/testsuite/g++.dg/modules/partial-2_b.C
+++ b/gcc/testsuite/g++.dg/modules/partial-2_b.C
@@ -2,20 +2,4 @@
// { dg-additional-options -fmodules-ts }
module pr106826;
-static_assert(is_reference_v<int&>);
-static_assert(is_reference_v<int&&>);
-static_assert(!is_reference_v<int>);
-
-static_assert(A::is_reference_v<long&>);
-static_assert(A::is_reference_v<long&&>);
-static_assert(!A::is_reference_v<long>);
-
-#if __cpp_concepts
-static_assert(concepts::is_reference_v<char&>);
-static_assert(concepts::is_reference_v<char&&>);
-static_assert(!concepts::is_reference_v<char>);
-
-static_assert(concepts::A::is_reference_v<bool&>);
-static_assert(concepts::A::is_reference_v<bool&&>);
-static_assert(!concepts::A::is_reference_v<bool>);
-#endif
+#include "partial-2.cc"
diff --git a/gcc/testsuite/g++.dg/modules/partial-2_c.H b/gcc/testsuite/g++.dg/modules/partial-2_c.H
new file mode 100644
index 0000000..bd83852
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/partial-2_c.H
@@ -0,0 +1,5 @@
+// PR c++/107033
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "partial-2.h"
diff --git a/gcc/testsuite/g++.dg/modules/partial-2_d.C b/gcc/testsuite/g++.dg/modules/partial-2_d.C
new file mode 100644
index 0000000..ed54d3c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/partial-2_d.C
@@ -0,0 +1,8 @@
+// PR c++/107033
+// { dg-additional-options -fmodules-ts }
+// { dg-module-cmi pr107033 }
+export module pr107033;
+
+import "partial-2_c.H";
+
+#include "partial-2.cc"
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/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++.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++.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-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/pr107009.c b/gcc/testsuite/gcc.dg/tree-ssa/pr107009.c
new file mode 100644
index 0000000..5010aed
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr107009.c
@@ -0,0 +1,15 @@
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-dom2-alias" }
+
+typedef __SIZE_TYPE__ size_t;
+
+void saxpy(size_t n)
+{
+ if (n == 0 || n % 8 != 0)
+ __builtin_unreachable();
+
+ extern void foobar (size_t n);
+ foobar (n);
+}
+
+// { dg-final { scan-tree-dump "NONZERO.*fff8" "dom2" } }
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c
index f909099..67635fb 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O3 -dp -mavx -mavx256-split-unaligned-store -mtune=generic -fno-common" } */
+/* { dg-options "-O3 -dp -mavx -mavx256-split-unaligned-store -mtune=generic -fno-common -mno-avx512f" } */
#define N 1024
diff --git a/gcc/testsuite/gcc.target/i386/pr53346-1.c b/gcc/testsuite/gcc.target/i386/pr53346-1.c
new file mode 100644
index 0000000..6d230da
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr53346-1.c
@@ -0,0 +1,70 @@
+/* { dg-do compile } */
+/* { dg-options "-msse2 -O2 -mno-sse3" } */
+/* { dg-final { scan-assembler-times "shufps" 15 } } */
+/* { dg-final { scan-assembler-times "pshufd" 2 } } */
+
+typedef int v4si __attribute__((vector_size(16)));
+
+v4si
+__attribute__((noipa))
+foo (v4si a, v4si b)
+{
+ return __builtin_shufflevector (a, b, 1, 2, 5, 3);
+}
+
+v4si
+__attribute__((noipa))
+foo1 (v4si a, v4si b)
+{
+ return __builtin_shufflevector (a, b, 1, 5, 2, 3);
+}
+
+v4si
+__attribute__((noipa))
+foo2 (v4si a, v4si b)
+{
+ return __builtin_shufflevector (a, b, 1, 2, 3, 5);
+}
+
+v4si
+__attribute__((noipa))
+foo3 (v4si a, v4si b)
+{
+ return __builtin_shufflevector (a, b, 1, 4, 5, 6);
+}
+
+v4si
+__attribute__((noipa))
+foo4 (v4si a, v4si b)
+{
+ return __builtin_shufflevector (a, b, 3, 6, 7, 5);
+}
+
+v4si
+__attribute__((noipa))
+foo5 (v4si a, v4si b)
+{
+ return __builtin_shufflevector (a, b, 2, 4, 7, 6);
+}
+
+v4si
+__attribute__((noipa))
+foo6 (v4si a, v4si b)
+{
+ return __builtin_shufflevector (a, b, 2, 4, 3, 6);
+}
+
+v4si
+__attribute__((noipa))
+foo7 (v4si a, v4si b)
+{
+ return __builtin_shufflevector (a, b, 2, 3, 4, 6);
+}
+
+v4si
+__attribute__((noipa))
+foo8 (v4si a, v4si b)
+{
+ return __builtin_shufflevector (a, b, 2, 4, 6, 3);
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/pr53346-2.c b/gcc/testsuite/gcc.target/i386/pr53346-2.c
new file mode 100644
index 0000000..0c6c7b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr53346-2.c
@@ -0,0 +1,59 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -msse2" } */
+/* { dg-require-effective-target sse2 } */
+
+#include "sse2-check.h"
+#include "pr53346-1.c"
+
+static void
+sse2_test ()
+{
+ v4si a = __extension__(v4si) { 0, 1, 2, 3 };
+ v4si b = __extension__(v4si) { 4, 5, 6, 7 };
+ v4si exp = __extension__(v4si) { 1, 2, 5, 3 };
+ v4si dest;
+ dest = foo (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4si) { 1, 5, 2, 3 };
+ dest = foo1 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4si) { 1, 2, 3, 5 };
+ dest = foo2 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4si) { 1, 4, 5, 6 };
+ dest = foo3 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4si) { 3, 6, 7, 5 };
+ dest = foo4 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4si) { 2, 4, 7, 6 };
+ dest = foo5 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4si) { 2, 4, 3, 6 };
+ dest = foo6 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4si) { 2, 3, 4, 6 };
+ dest = foo7 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4si) { 2, 4, 6, 3 };
+ dest = foo8 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr53346-3.c b/gcc/testsuite/gcc.target/i386/pr53346-3.c
new file mode 100644
index 0000000..0b204f6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr53346-3.c
@@ -0,0 +1,69 @@
+/* { dg-do compile } */
+/* { dg-options "-msse2 -O2 -mno-sse3" } */
+/* { dg-final { scan-assembler-times "shufps" 17 } } */
+
+typedef float v4sf __attribute__((vector_size(16)));
+
+v4sf
+__attribute__((noipa))
+foo (v4sf a, v4sf b)
+{
+ return __builtin_shufflevector (a, b, 1, 2, 5, 3);
+}
+
+v4sf
+__attribute__((noipa))
+foo1 (v4sf a, v4sf b)
+{
+ return __builtin_shufflevector (a, b, 1, 5, 2, 3);
+}
+
+v4sf
+__attribute__((noipa))
+foo2 (v4sf a, v4sf b)
+{
+ return __builtin_shufflevector (a, b, 1, 2, 3, 5);
+}
+
+v4sf
+__attribute__((noipa))
+foo3 (v4sf a, v4sf b)
+{
+ return __builtin_shufflevector (a, b, 1, 4, 5, 6);
+}
+
+v4sf
+__attribute__((noipa))
+foo4 (v4sf a, v4sf b)
+{
+ return __builtin_shufflevector (a, b, 3, 6, 7, 5);
+}
+
+v4sf
+__attribute__((noipa))
+foo5 (v4sf a, v4sf b)
+{
+ return __builtin_shufflevector (a, b, 2, 4, 7, 6);
+}
+
+v4sf
+__attribute__((noipa))
+foo6 (v4sf a, v4sf b)
+{
+ return __builtin_shufflevector (a, b, 2, 4, 3, 6);
+}
+
+v4sf
+__attribute__((noipa))
+foo7 (v4sf a, v4sf b)
+{
+ return __builtin_shufflevector (a, b, 2, 3, 4, 6);
+}
+
+v4sf
+__attribute__((noipa))
+foo8 (v4sf a, v4sf b)
+{
+ return __builtin_shufflevector (a, b, 2, 4, 6, 3);
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/pr53346-4.c b/gcc/testsuite/gcc.target/i386/pr53346-4.c
new file mode 100644
index 0000000..9e4e45b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr53346-4.c
@@ -0,0 +1,59 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -msse2" } */
+/* { dg-require-effective-target sse2 } */
+
+#include "sse2-check.h"
+#include "pr53346-3.c"
+
+static void
+sse2_test ()
+{
+ v4sf a = __extension__(v4sf) { 0, 1, 2, 3 };
+ v4sf b = __extension__(v4sf) { 4, 5, 6, 7 };
+ v4sf exp = __extension__(v4sf) { 1, 2, 5, 3 };
+ v4sf dest;
+ dest = foo (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4sf) { 1, 5, 2, 3 };
+ dest = foo1 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4sf) { 1, 2, 3, 5 };
+ dest = foo2 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4sf) { 1, 4, 5, 6 };
+ dest = foo3 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4sf) { 3, 6, 7, 5 };
+ dest = foo4 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4sf) { 2, 4, 7, 6 };
+ dest = foo5 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4sf) { 2, 4, 3, 6 };
+ dest = foo6 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4sf) { 2, 3, 4, 6 };
+ dest = foo7 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+ exp = __extension__ (v4sf) { 2, 4, 6, 3 };
+ dest = foo8 (a, b);
+ if (__builtin_memcmp (&dest, &exp, 16))
+ __builtin_abort ();
+
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr100645.c b/gcc/testsuite/gcc.target/powerpc/pr100645.c
new file mode 100644
index 0000000..c4e92cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr100645.c
@@ -0,0 +1,13 @@
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-mdejagnu-cpu=power6 -maltivec" } */
+
+/* This used to ICE. */
+
+typedef long long v2di __attribute__ ((vector_size (16)));
+
+v2di
+foo_v2di_l (v2di x)
+{
+ return __builtin_shuffle ((v2di){0, 0}, x, (v2di){3, 0});
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/pr96072.c b/gcc/testsuite/gcc.target/powerpc/pr96072.c
new file mode 100644
index 0000000..10341c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr96072.c
@@ -0,0 +1,14 @@
+/* { dg-options "-O2" } */
+
+/* This used to ICE with the SYSV ABI (PR96072). */
+
+void
+he (int jn)
+{
+ {
+ int bh[jn];
+ if (jn != 0)
+ goto wa;
+ }
+wa:;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/ret-1.c b/gcc/testsuite/gcc.target/riscv/ret-1.c
new file mode 100644
index 0000000..28133aa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/ret-1.c
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -dp" } */
+/* This was extracted from coremark. */
+
+
+typedef signed short ee_s16;
+typedef struct list_data_s
+{
+ ee_s16 data16;
+ ee_s16 idx;
+} list_data;
+
+typedef struct list_head_s
+{
+ struct list_head_s *next;
+ struct list_data_s *info;
+} list_head;
+
+
+list_head *
+core_list_find(list_head *list, list_data *info)
+{
+ if (info->idx >= 0)
+ {
+ while (list && (list->info->idx != info->idx))
+ list = list->next;
+ return list;
+ }
+ else
+ {
+ while (list && ((list->info->data16 & 0xff) != info->data16))
+ list = list->next;
+ return list;
+ }
+}
+
+/* There is only one legitimate unconditional jump, so test for that,
+ which will catch the case where bb-reorder leaves a jump to a ret
+ in the IL. */
+/* { dg-final { scan-assembler-times "jump" 1 } } */
+
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/intent_optimize_10.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_10.f90
new file mode 100644
index 0000000..d8bc1bb
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/intent_optimize_10.f90
@@ -0,0 +1,66 @@
+! { dg-do run }
+! { dg-additional-options "-fno-inline -fno-ipa-modref -fdump-tree-optimized -fdump-tree-original" }
+!
+! PR fortran/41453
+! Check that the INTENT(OUT) attribute causes in the case of non-polymorphic derived type arguments:
+! - one clobber to be emitted in the caller before calls to FOO in the *.original dump,
+! - no clobber to be emitted in the caller before calls to BAR in the *.original dump,
+! - the initialization constants to be optimized away in the *.optimized dump.
+
+module x
+ implicit none
+ type :: t
+ integer :: c
+ end type t
+ type, extends(t) :: u
+ integer :: d
+ end type u
+contains
+ subroutine foo(a)
+ type(t), intent(out) :: a
+ a = t(42)
+ end subroutine foo
+ subroutine bar(b)
+ class(t), intent(out) :: b
+ b%c = 24
+ end subroutine bar
+end module x
+
+program main
+ use x
+ implicit none
+ type(t) :: tc
+ type(u) :: uc, ud
+ class(t), allocatable :: te, tf
+
+ tc = t(123456789)
+ call foo(tc)
+ if (tc%c /= 42) stop 1
+
+ uc = u(987654321, 0)
+ call foo(uc%t)
+ if (uc%c /= 42) stop 2
+ if (uc%d /= 0) stop 3
+
+ ud = u(11223344, 0)
+ call bar(ud)
+ if (ud%c /= 24) stop 4
+
+ te = t(55667788)
+ call foo(te)
+ if (te%c /= 42) stop 5
+
+ tf = t(99887766)
+ call bar(tf)
+ if (tf%c /= 24) stop 6
+
+end program main
+
+! We don't support class descriptors, neither derived type components, so there is a clobber for tc only;
+! no clobber for uc, ud, te, tf.
+! { dg-final { scan-tree-dump-times "CLOBBER" 1 "original" } }
+! { dg-final { scan-tree-dump "tc = {CLOBBER};" "original" } }
+
+! There is a clobber for tc, so we should manage to optimize away the associated initialization constant (but not other
+! initialization constants).
+! { dg-final { scan-tree-dump-not "123456789" "optimized" { target __OPTIMIZE__ } } }
diff --git a/gcc/testsuite/gfortran.dg/intent_optimize_4.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_4.f90
new file mode 100644
index 0000000..effbaa1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/intent_optimize_4.f90
@@ -0,0 +1,43 @@
+! { dg-do run }
+! { dg-additional-options "-fdump-tree-original" }
+! { dg-final { scan-tree-dump-times "CLOBBER" 2 "original" } }
+!
+! PR fortran/106817
+! Check that for an actual argument whose dummy is INTENT(OUT),
+! the clobber that is emitted in the caller before a procedure call
+! happens after any expression depending on the argument value has been
+! evaluated.
+!
+
+module m
+ implicit none
+contains
+ subroutine copy1(out, in)
+ integer, intent(in) :: in
+ integer, intent(out) :: out
+ out = in
+ end subroutine copy1
+ subroutine copy2(in, out)
+ integer, intent(in) :: in
+ integer, intent(out) :: out
+ out = in
+ end subroutine copy2
+end module m
+
+program p
+ use m
+ implicit none
+ integer :: a, b
+
+ ! Clobbering of a should happen after a+1 has been evaluated.
+ a = 3
+ call copy1(a, a+1)
+ if (a /= 4) stop 1
+
+ ! Clobbering order does not depend on the order of arguments.
+ ! It should also come last with reversed arguments.
+ b = 12
+ call copy2(b+1, b)
+ if (b /= 13) stop 2
+
+end program p
diff --git a/gcc/testsuite/gfortran.dg/intent_optimize_5.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_5.f90
new file mode 100644
index 0000000..2f184bf
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/intent_optimize_5.f90
@@ -0,0 +1,24 @@
+! { dg-do run }
+! { dg-additional-options "-fno-inline -fno-ipa-modref -fdump-tree-optimized -fdump-tree-original" }
+!
+! PR fortran/105012
+! Check that the INTENT(OUT) attribute causes one clobber to be emitted in
+! the caller before the call to Y in the *.original dump, and the
+! initialization constant to be optimized away in the *.optimized dump,
+! despite the non-explicit interface if the subroutine with the INTENT(OUT)
+! is declared in the same file.
+
+SUBROUTINE Y (Z)
+ integer, intent(out) :: Z
+ Z = 42
+END SUBROUTINE Y
+PROGRAM TEST
+ integer :: X
+ X = 123456789
+ CALL Y (X)
+ if (X.ne.42) STOP 1
+END PROGRAM
+
+! { dg-final { scan-tree-dump-times "CLOBBER" 1 "original" } }
+! { dg-final { scan-tree-dump "x = {CLOBBER};" "original" } }
+! { dg-final { scan-tree-dump-not "123456789" "optimized" { target __OPTIMIZE__ } } }
diff --git a/gcc/testsuite/gfortran.dg/intent_optimize_6.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_6.f90
new file mode 100644
index 0000000..72fec3d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/intent_optimize_6.f90
@@ -0,0 +1,34 @@
+! { dg-do run }
+! { dg-additional-options "-fno-inline -fno-ipa-modref -fdump-tree-optimized -fdump-tree-original" }
+!
+! PR fortran/41453
+! Check that the INTENT(OUT) attribute causes one clobber to be emitted in
+! the caller before each call to FOO in the *.original dump, and the
+! initialization constant to be optimized away in the *.optimized dump,
+! in the case of an argument passed by reference to the caller.
+
+module x
+implicit none
+contains
+ subroutine foo(a)
+ integer(kind=4), intent(out) :: a
+ a = 42
+ end subroutine foo
+ subroutine bar(b)
+ integer(kind=4) :: b
+ b = 123456789
+ call foo(b)
+ end subroutine bar
+end module x
+
+program main
+ use x
+ implicit none
+ integer(kind=4) :: c
+ call bar(c)
+ if (c /= 42) stop 1
+end program main
+
+! { dg-final { scan-tree-dump-times "CLOBBER" 1 "original" } }
+! { dg-final { scan-tree-dump "\\*\\\(integer\\\(kind=4\\\) \\*\\\) b = {CLOBBER};" "original" } }
+! { dg-final { scan-tree-dump-not "123456789" "optimized" { target __OPTIMIZE__ } } }
diff --git a/gcc/testsuite/gfortran.dg/intent_optimize_7.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_7.f90
new file mode 100644
index 0000000..c2f2192
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/intent_optimize_7.f90
@@ -0,0 +1,45 @@
+! { dg-do run }
+! { dg-additional-options "-fno-inline -fno-ipa-modref -fdump-tree-optimized -fdump-tree-original" }
+!
+! PR fortran/41453
+! Check that the INTENT(OUT) attribute causes one clobber to be emitted in
+! the caller before each call to FOO in the *.original dump, and the
+! initialization constants to be optimized away in the *.optimized dump,
+! in the case of SAVE variables.
+
+module x
+implicit none
+contains
+ subroutine foo(a)
+ integer, intent(out) :: a
+ a = 42
+ end subroutine foo
+end module x
+
+program main
+ use x
+ implicit none
+ integer :: c = 0
+
+ ! implicit SAVE attribute
+ c = 123456789
+ call foo(c)
+ if (c /= 42) stop 1
+
+ ! explicit SAVE attribute
+ call check_save_explicit
+
+contains
+ subroutine check_save_explicit
+ integer, save :: d
+ d = 987654321
+ call foo(d)
+ if (d /= 42) stop 2
+ end subroutine check_save_explicit
+end program main
+
+! { dg-final { scan-tree-dump-times "CLOBBER" 2 "original" } }
+! { dg-final { scan-tree-dump "c = {CLOBBER};" "original" } }
+! { dg-final { scan-tree-dump "d = {CLOBBER};" "original" } }
+! { dg-final { scan-tree-dump-not "123456789" "optimized" { target __OPTIMIZE__ } } }
+! { dg-final { scan-tree-dump-not "987654321" "optimized" { target __OPTIMIZE__ } } }
diff --git a/gcc/testsuite/gfortran.dg/intent_optimize_8.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_8.f90
new file mode 100644
index 0000000..4336fce
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/intent_optimize_8.f90
@@ -0,0 +1,45 @@
+! { dg-do run }
+! { dg-additional-options "-fno-inline -fno-ipa-modref -fdump-tree-optimized -fdump-tree-original" }
+!
+! PR fortran/41453
+! Check that the INTENT(OUT) attribute causes one clobber to be emitted in
+! the caller before each call to FOO in the *.original dump, and the
+! initialization constants to be optimized away in the *.optimized dump,
+! in the case of associate variables.
+
+module x
+implicit none
+contains
+ subroutine foo(a)
+ integer, intent(out) :: a
+ a = 42
+ end subroutine foo
+end module x
+
+program main
+ use x
+ implicit none
+ integer :: c1, c2
+
+ c1 = 123456789
+ associate (d1 => c1)
+ call foo(d1)
+ if (d1 /= 42) stop 1
+ end associate
+ if (c1 /= 42) stop 2
+
+ c2 = 0
+ associate (d2 => c2)
+ d2 = 987654321
+ call foo(d2)
+ if (d2 /= 42) stop 3
+ end associate
+ if (c2 /= 42) stop 4
+
+end program main
+
+! { dg-final { scan-tree-dump-times "CLOBBER" 2 "original" } }
+! { dg-final { scan-tree-dump "d1 = {CLOBBER};" "original" } }
+! { dg-final { scan-tree-dump "\\*d2 = {CLOBBER};" "original" } }
+! { dg-final { scan-tree-dump-not "123456789" "optimized" { target __OPTIMIZE__ } } }
+! { dg-final { scan-tree-dump-not "987654321" "optimized" { target __OPTIMIZE__ } } }
diff --git a/gcc/testsuite/gfortran.dg/intent_optimize_9.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_9.f90
new file mode 100644
index 0000000..0146dff
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/intent_optimize_9.f90
@@ -0,0 +1,42 @@
+! { dg-do run }
+! { dg-additional-options "-fno-inline -fno-ipa-modref -fdump-tree-optimized -fdump-tree-original" }
+!
+! PR fortran/41453
+! Check that the INTENT(OUT) attribute causes one clobber to be emitted in
+! the caller before each call to FOO in the *.original dump, and the
+! initialization constants to be optimized away in the *.optimized dump,
+! in the case of scalar allocatables and pointers.
+
+module x
+implicit none
+contains
+ subroutine foo(a)
+ integer, intent(out) :: a
+ a = 42
+ end subroutine foo
+end module x
+
+program main
+ use x
+ implicit none
+ integer, allocatable :: ca
+ integer, target :: ct
+ integer, pointer :: cp
+
+ allocate(ca)
+ ca = 123456789
+ call foo(ca)
+ if (ca /= 42) stop 1
+ deallocate(ca)
+
+ ct = 987654321
+ cp => ct
+ call foo(cp)
+ if (ct /= 42) stop 2
+end program main
+
+! { dg-final { scan-tree-dump-times "CLOBBER" 2 "original" } }
+! { dg-final { scan-tree-dump "\\*ca = {CLOBBER};" "original" } }
+! { dg-final { scan-tree-dump "\\*cp = {CLOBBER};" "original" } }
+! { dg-final { scan-tree-dump-not "123456789" "optimized" { target __OPTIMIZE__ } } }
+! { dg-final { scan-tree-dump-not "987654321" "optimized" { target __OPTIMIZE__ } } }
diff --git a/gcc/testsuite/gfortran.dg/intent_out_15.f90 b/gcc/testsuite/gfortran.dg/intent_out_15.f90
new file mode 100644
index 0000000..64334e6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/intent_out_15.f90
@@ -0,0 +1,27 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+!
+! PR fortran/105012
+! The following case was triggering an ICE because of a clobber
+! on the DERFC function decl instead of its result.
+
+module error_function
+integer, parameter :: r8 = selected_real_kind(12) ! 8 byte real
+contains
+SUBROUTINE CALERF_r8(ARG, RESULT, JINT)
+ integer, parameter :: rk = r8
+ real(rk), intent(in) :: arg
+ real(rk), intent(out) :: result
+ IF (Y .LE. THRESH) THEN
+ END IF
+end SUBROUTINE CALERF_r8
+FUNCTION DERFC(X)
+ integer, parameter :: rk = r8 ! 8 byte real
+ real(rk), intent(in) :: X
+ real(rk) :: DERFC
+ CALL CALERF_r8(X, DERFC, JINT)
+END FUNCTION DERFC
+end module error_function
+
+! { dg-final { scan-tree-dump-times "CLOBBER" 1 "original" } }
+! { dg-final { scan-tree-dump "__result_derfc = {CLOBBER};" "original" } }
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-ssa-dom.cc b/gcc/tree-ssa-dom.cc
index 513e0c8..84bef79 100644
--- a/gcc/tree-ssa-dom.cc
+++ b/gcc/tree-ssa-dom.cc
@@ -1227,29 +1227,30 @@ void
dom_opt_dom_walker::set_global_ranges_from_unreachable_edges (basic_block bb)
{
edge pred_e = single_pred_edge_ignoring_loop_edges (bb, false);
-
if (!pred_e)
return;
gimple *stmt = last_stmt (pred_e->src);
+ if (!stmt
+ || gimple_code (stmt) != GIMPLE_COND
+ || !assert_unreachable_fallthru_edge_p (pred_e))
+ return;
+
tree name;
- if (stmt
- && gimple_code (stmt) == GIMPLE_COND
- && (name = gimple_cond_lhs (stmt))
- && TREE_CODE (name) == SSA_NAME
- && assert_unreachable_fallthru_edge_p (pred_e)
- && all_uses_feed_or_dominated_by_stmt (name, stmt))
- {
- Value_Range r (TREE_TYPE (name));
+ gori_compute &gori = m_ranger->gori ();
+ FOR_EACH_GORI_EXPORT_NAME (gori, pred_e->src, name)
+ if (all_uses_feed_or_dominated_by_stmt (name, stmt))
+ {
+ Value_Range r (TREE_TYPE (name));
- if (m_ranger->range_on_edge (r, pred_e, name)
- && !r.varying_p ()
- && !r.undefined_p ())
- {
- set_range_info (name, r);
- maybe_set_nonzero_bits (pred_e, name);
- }
- }
+ if (m_ranger->range_on_edge (r, pred_e, name)
+ && !r.varying_p ()
+ && !r.undefined_p ())
+ {
+ set_range_info (name, r);
+ maybe_set_nonzero_bits (pred_e, name);
+ }
+ }
}
/* Record any equivalences created by the incoming edge to BB into
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.cc b/gcc/tree.cc
index 4165cbd..756c14f 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);
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 9ca4424..6154d73 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -258,15 +258,6 @@ frange::accept (const vrange_visitor &v) const
v.visit (*this);
}
-// Helper function to compare floats. Returns TRUE if op1 .CODE. op2
-// is nonzero.
-
-static inline bool
-tree_compare (tree_code code, tree op1, tree op2)
-{
- return !integer_zerop (fold_build2 (code, integer_type_node, op1, op2));
-}
-
// Flush denormal endpoints to the appropriate 0.0.
void
@@ -2939,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/include/demangle.h b/include/demangle.h
index e2aa4a9..81d4353 100644
--- a/include/demangle.h
+++ b/include/demangle.h
@@ -457,6 +457,11 @@ enum demangle_component_type
DEMANGLE_COMPONENT_MODULE_PARTITION,
DEMANGLE_COMPONENT_MODULE_ENTITY,
DEMANGLE_COMPONENT_MODULE_INIT,
+
+ /* A builtin type with argument. This holds the builtin type
+ information. */
+ DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE
+
};
/* Types which are only used internally. */
@@ -543,6 +548,15 @@ struct demangle_component
const struct demangle_builtin_type_info *type;
} s_builtin;
+ /* For DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE. */
+ struct
+ {
+ /* Builtin type. */
+ const struct demangle_builtin_type_info *type;
+ short arg;
+ char suffix;
+ } s_extended_builtin;
+
/* For DEMANGLE_COMPONENT_SUB_STD. */
struct
{
diff --git a/include/dwarf2.h b/include/dwarf2.h
index 40aa5a5..87bf764 100644
--- a/include/dwarf2.h
+++ b/include/dwarf2.h
@@ -373,6 +373,16 @@ enum dwarf_source_language
DW_LANG_Fortran03 = 0x0022,
DW_LANG_Fortran08 = 0x0023,
DW_LANG_RenderScript = 0x0024,
+ DW_LANG_BLISS = 0x0025,
+ DW_LANG_Kotlin = 0x0026,
+ DW_LANG_Zig = 0x0027,
+ DW_LANG_Crystal = 0x0028,
+ DW_LANG_C_plus_plus_17 = 0x002a,
+ DW_LANG_C_plus_plus_20 = 0x002b,
+ DW_LANG_C17 = 0x002c,
+ DW_LANG_Fortran18 = 0x002d,
+ DW_LANG_Ada2005 = 0x002e,
+ DW_LANG_Ada2012 = 0x002f,
DW_LANG_lo_user = 0x8000, /* Implementation-defined range start. */
DW_LANG_hi_user = 0xffff, /* Implementation-defined range start. */
diff --git a/libcpp/expr.cc b/libcpp/expr.cc
index 4bb02c4..1d68064 100644
--- a/libcpp/expr.cc
+++ b/libcpp/expr.cc
@@ -215,7 +215,6 @@ interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
case 'f': case 'F':
f++;
if (len > 0
- && !CPP_OPTION (pfile, cplusplus)
&& s[1] >= '1'
&& s[1] <= '9'
&& fn_bits == 0)
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 9ebfaa0..24296185 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,8 @@
+2022-09-26 Thomas Neumann <tneumann@users.sourceforge.net>
+
+ * unwind-dw2-fde.c: Introduce a constant for in_shutdown
+ for the non-fast-path case. Drop destructor priority.
+
2022-09-22 Thomas Neumann <tneumann@users.sourceforge.net>
* unwind-dw2-fde.c: (release_register_frames) Remember
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
index d237179..3c0cc65 100644
--- a/libgcc/unwind-dw2-fde.c
+++ b/libgcc/unwind-dw2-fde.c
@@ -51,7 +51,7 @@ static struct btree registered_frames;
static bool in_shutdown;
static void
-release_registered_frames (void) __attribute__ ((destructor (110)));
+release_registered_frames (void) __attribute__ ((destructor));
static void
release_registered_frames (void)
{
@@ -67,6 +67,8 @@ static void
init_object (struct object *ob);
#else
+/* Without fast path frame deregistration must always succeed. */
+static const int in_shutdown = 0;
/* The unseen_objects list contains objects that have been registered
but not yet categorized in any way. The seen_objects list has had
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index d3b4758..a5830a4 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,8 @@
+2022-09-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/106981
+ * testsuite/libgomp.c-c++-common/pr106981.c: New test.
+
2022-09-14 Julian Brown <julian@codesourcery.com>
* testsuite/libgomp.oacc-c-c++-common/deep-copy-15.c: New test.
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index d06d80d..7ff225e 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -648,6 +648,13 @@ d_dump (struct demangle_component *dc, int indent)
case DEMANGLE_COMPONENT_BUILTIN_TYPE:
printf ("builtin type %s\n", dc->u.s_builtin.type->name);
return;
+ case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE:
+ {
+ char suffix[2] = { dc->u.s_extended_builtin.type->suffix, 0 };
+ printf ("builtin type %s%d%s\n", dc->u.s_extended_builtin.type->name,
+ dc->u.s_extended_builtin.type->arg, suffix);
+ }
+ return;
case DEMANGLE_COMPONENT_OPERATOR:
printf ("operator %s\n", dc->u.s_operator.op->name);
return;
@@ -771,11 +778,6 @@ d_dump (struct demangle_component *dc, int indent)
case DEMANGLE_COMPONENT_PTRMEM_TYPE:
printf ("pointer to member type\n");
break;
- case DEMANGLE_COMPONENT_FIXED_TYPE:
- printf ("fixed-point type, accum? %d, sat? %d\n",
- dc->u.s_fixed.accum, dc->u.s_fixed.sat);
- d_dump (dc->u.s_fixed.length, indent + 2);
- break;
case DEMANGLE_COMPONENT_ARGLIST:
printf ("argument list\n");
break;
@@ -1109,6 +1111,28 @@ d_make_builtin_type (struct d_info *di,
return p;
}
+/* Add a new extended builtin type component. */
+
+static struct demangle_component *
+d_make_extended_builtin_type (struct d_info *di,
+ const struct demangle_builtin_type_info *type,
+ short arg, char suffix)
+{
+ struct demangle_component *p;
+
+ if (type == NULL)
+ return NULL;
+ p = d_make_empty (di);
+ if (p != NULL)
+ {
+ p->type = DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE;
+ p->u.s_extended_builtin.type = type;
+ p->u.s_extended_builtin.arg = arg;
+ p->u.s_extended_builtin.suffix = suffix;
+ }
+ return p;
+}
+
/* Add a new operator component. */
static struct demangle_component *
@@ -2464,6 +2488,7 @@ cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] =
/* 32 */ { NL ("char32_t"), NL ("char32_t"), D_PRINT_DEFAULT },
/* 33 */ { NL ("decltype(nullptr)"), NL ("decltype(nullptr)"),
D_PRINT_DEFAULT },
+ /* 34 */ { NL ("_Float"), NL ("_Float"), D_PRINT_FLOAT },
};
CP_STATIC_IF_GLIBCPP_V3
@@ -2727,19 +2752,26 @@ cplus_demangle_type (struct d_info *di)
break;
case 'F':
- /* Fixed point types. DF<int bits><length><fract bits><sat> */
- ret = d_make_empty (di);
- ret->type = DEMANGLE_COMPONENT_FIXED_TYPE;
- if ((ret->u.s_fixed.accum = IS_DIGIT (d_peek_char (di))))
- /* For demangling we don't care about the bits. */
- d_number (di);
- ret->u.s_fixed.length = cplus_demangle_type (di);
- if (ret->u.s_fixed.length == NULL)
- return NULL;
- d_number (di);
- peek = d_next_char (di);
- ret->u.s_fixed.sat = (peek == 's');
- break;
+ /* DF<number>_ - _Float<number>.
+ DF<number>x - _Float<number>x. */
+ {
+ int arg = d_number (di);
+ char buf[12];
+ char suffix = 0;
+ if (d_peek_char (di) == 'x')
+ suffix = 'x';
+ if (!suffix && d_peek_char (di) != '_')
+ return NULL;
+ ret
+ = d_make_extended_builtin_type (di,
+ &cplus_demangle_builtin_types[34],
+ arg, suffix);
+ d_advance (di, 1);
+ sprintf (buf, "%d", arg);
+ di->expansion += ret->u.s_extended_builtin.type->len
+ + strlen (buf) + (suffix != 0);
+ break;
+ }
case 'v':
ret = d_vector_type (di);
@@ -4202,6 +4234,7 @@ d_count_templates_scopes (struct d_print_info *dpi,
case DEMANGLE_COMPONENT_FUNCTION_PARAM:
case DEMANGLE_COMPONENT_SUB_STD:
case DEMANGLE_COMPONENT_BUILTIN_TYPE:
+ case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE:
case DEMANGLE_COMPONENT_OPERATOR:
case DEMANGLE_COMPONENT_CHARACTER:
case DEMANGLE_COMPONENT_NUMBER:
@@ -4210,6 +4243,7 @@ d_count_templates_scopes (struct d_print_info *dpi,
case DEMANGLE_COMPONENT_MODULE_NAME:
case DEMANGLE_COMPONENT_MODULE_PARTITION:
case DEMANGLE_COMPONENT_MODULE_INIT:
+ case DEMANGLE_COMPONENT_FIXED_TYPE:
break;
case DEMANGLE_COMPONENT_TEMPLATE:
@@ -4309,10 +4343,6 @@ d_count_templates_scopes (struct d_print_info *dpi,
d_count_templates_scopes (dpi, dc->u.s_extended_operator.name);
break;
- case DEMANGLE_COMPONENT_FIXED_TYPE:
- d_count_templates_scopes (dpi, dc->u.s_fixed.length);
- break;
-
case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
case DEMANGLE_COMPONENT_MODULE_ENTITY:
@@ -4580,11 +4610,11 @@ d_find_pack (struct d_print_info *dpi,
case DEMANGLE_COMPONENT_TAGGED_NAME:
case DEMANGLE_COMPONENT_OPERATOR:
case DEMANGLE_COMPONENT_BUILTIN_TYPE:
+ case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE:
case DEMANGLE_COMPONENT_SUB_STD:
case DEMANGLE_COMPONENT_CHARACTER:
case DEMANGLE_COMPONENT_FUNCTION_PARAM:
case DEMANGLE_COMPONENT_UNNAMED_TYPE:
- case DEMANGLE_COMPONENT_FIXED_TYPE:
case DEMANGLE_COMPONENT_DEFAULT_ARG:
case DEMANGLE_COMPONENT_NUMBER:
return NULL;
@@ -5387,6 +5417,14 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
dc->u.s_builtin.type->java_len);
return;
+ case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE:
+ d_append_buffer (dpi, dc->u.s_extended_builtin.type->name,
+ dc->u.s_extended_builtin.type->len);
+ d_append_num (dpi, dc->u.s_extended_builtin.arg);
+ if (dc->u.s_extended_builtin.suffix)
+ d_append_buffer (dpi, &dc->u.s_extended_builtin.suffix, 1);
+ return;
+
case DEMANGLE_COMPONENT_VENDOR_TYPE:
d_print_comp (dpi, options, d_left (dc));
return;
@@ -5525,22 +5563,6 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
return;
}
- case DEMANGLE_COMPONENT_FIXED_TYPE:
- if (dc->u.s_fixed.sat)
- d_append_string (dpi, "_Sat ");
- /* Don't print "int _Accum". */
- if (dc->u.s_fixed.length->u.s_builtin.type
- != &cplus_demangle_builtin_types['i'-'a'])
- {
- d_print_comp (dpi, options, dc->u.s_fixed.length);
- d_append_char (dpi, ' ');
- }
- if (dc->u.s_fixed.accum)
- d_append_string (dpi, "_Accum");
- else
- d_append_string (dpi, "_Fract");
- return;
-
case DEMANGLE_COMPONENT_ARGLIST:
case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
if (d_left (dc) != NULL)
diff --git a/libiberty/cp-demangle.h b/libiberty/cp-demangle.h
index c644503..c5d046b 100644
--- a/libiberty/cp-demangle.h
+++ b/libiberty/cp-demangle.h
@@ -180,7 +180,7 @@ d_advance (struct d_info *di, int i)
extern const struct demangle_operator_info cplus_demangle_operators[];
#endif
-#define D_BUILTIN_TYPE_COUNT (34)
+#define D_BUILTIN_TYPE_COUNT (35)
CP_STATIC_IF_GLIBCPP_V3
const struct demangle_builtin_type_info
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 351af34..8fad689 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -1242,8 +1242,12 @@ _ZNSt9_Any_data9_M_accessIPZ4postISt8functionIFvvEEEvOT_EUlvE_EERS5_v
post<std::function<void ()> >(std::function<void ()>&&)::{lambda()#1}*& std::_Any_data::_M_access<post<std::function<void ()> >(post<std::function<void ()> >(std::function<void ()>&&)::{lambda()#1}*&&)::{lambda()#1}*>()
#
--format=auto --no-params
-_Z3xxxDFyuVb
-xxx(unsigned long long _Fract, bool volatile)
+_Z3xxxDF16_DF32_DF64_DF128_CDF16_Vb
+xxx(_Float16, _Float32, _Float64, _Float128, _Float16 _Complex, bool volatile)
+xxx
+--format=auto --no-params
+_Z3xxxDF32xDF64xDF128xCDF32xVb
+xxx(_Float32x, _Float64x, _Float128x, _Float32x _Complex, bool volatile)
xxx
# https://sourceware.org/bugzilla/show_bug.cgi?id=16817
--format=auto --no-params
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 85fc49d..a4c46f3 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/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/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index d828749..45749d7 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -211,11 +211,11 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
gcc/sections/package.d gcc/sections/pecoff.d gcc/simd.d \
gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
- rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \
- rt/arraycat.d rt/cast_.d rt/config.d rt/critical_.d rt/deh.d \
- rt/dmain2.d rt/ehalloc.d rt/invariant.d rt/lifetime.d rt/memory.d \
- rt/minfo.d rt/monitor_.d rt/profilegc.d rt/sections.d rt/tlsgc.d \
- rt/util/typeinfo.d rt/util/utility.d
+ rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arraycat.d rt/cast_.d \
+ rt/config.d rt/critical_.d rt/deh.d rt/dmain2.d rt/ehalloc.d \
+ rt/invariant.d rt/lifetime.d rt/memory.d rt/minfo.d rt/monitor_.d \
+ rt/profilegc.d rt/sections.d rt/tlsgc.d rt/util/typeinfo.d \
+ rt/util/utility.d
DRUNTIME_DSOURCES_STDCXX = core/stdcpp/allocator.d core/stdcpp/array.d \
core/stdcpp/exception.d core/stdcpp/memory.d core/stdcpp/new_.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 57660ee..e86721f 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -242,11 +242,11 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
gcc/unwind/generic.lo gcc/unwind/package.lo gcc/unwind/pe.lo \
object.lo rt/aApply.lo rt/aApplyR.lo rt/aaA.lo rt/adi.lo \
- rt/arrayassign.lo rt/arraycat.lo rt/cast_.lo rt/config.lo \
- rt/critical_.lo rt/deh.lo rt/dmain2.lo rt/ehalloc.lo \
- rt/invariant.lo rt/lifetime.lo rt/memory.lo rt/minfo.lo \
- rt/monitor_.lo rt/profilegc.lo rt/sections.lo rt/tlsgc.lo \
- rt/util/typeinfo.lo rt/util/utility.lo
+ rt/arraycat.lo rt/cast_.lo rt/config.lo rt/critical_.lo \
+ rt/deh.lo rt/dmain2.lo rt/ehalloc.lo rt/invariant.lo \
+ rt/lifetime.lo rt/memory.lo rt/minfo.lo rt/monitor_.lo \
+ rt/profilegc.lo rt/sections.lo rt/tlsgc.lo rt/util/typeinfo.lo \
+ rt/util/utility.lo
am__objects_2 = core/stdc/libgdruntime_la-errno_.lo
am__objects_3 = core/sys/elf/package.lo
am__objects_4 = core/stdcpp/allocator.lo core/stdcpp/array.lo \
@@ -880,11 +880,11 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
gcc/sections/package.d gcc/sections/pecoff.d gcc/simd.d \
gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
- rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \
- rt/arraycat.d rt/cast_.d rt/config.d rt/critical_.d rt/deh.d \
- rt/dmain2.d rt/ehalloc.d rt/invariant.d rt/lifetime.d rt/memory.d \
- rt/minfo.d rt/monitor_.d rt/profilegc.d rt/sections.d rt/tlsgc.d \
- rt/util/typeinfo.d rt/util/utility.d
+ rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arraycat.d rt/cast_.d \
+ rt/config.d rt/critical_.d rt/deh.d rt/dmain2.d rt/ehalloc.d \
+ rt/invariant.d rt/lifetime.d rt/memory.d rt/minfo.d rt/monitor_.d \
+ rt/profilegc.d rt/sections.d rt/tlsgc.d rt/util/typeinfo.d \
+ rt/util/utility.d
DRUNTIME_DSOURCES_STDCXX = core/stdcpp/allocator.d core/stdcpp/array.d \
core/stdcpp/exception.d core/stdcpp/memory.d core/stdcpp/new_.d \
@@ -1364,7 +1364,6 @@ rt/aApply.lo: rt/$(am__dirstamp)
rt/aApplyR.lo: rt/$(am__dirstamp)
rt/aaA.lo: rt/$(am__dirstamp)
rt/adi.lo: rt/$(am__dirstamp)
-rt/arrayassign.lo: rt/$(am__dirstamp)
rt/arraycat.lo: rt/$(am__dirstamp)
rt/cast_.lo: rt/$(am__dirstamp)
rt/config.lo: rt/$(am__dirstamp)
diff --git a/libphobos/libdruntime/__builtins.di b/libphobos/libdruntime/__builtins.di
index cf05333..1c49035 100644
--- a/libphobos/libdruntime/__builtins.di
+++ b/libphobos/libdruntime/__builtins.di
@@ -15,7 +15,7 @@ module __builtins;
/* gcc relies on internal __builtin_xxxx functions and templates to
* accomplish <stdarg.h>. D does the same thing with templates in core.stdc.stdarg.
* Here, we redirect the gcc builtin declarations to the equivalent
- * ones in core.stdc.stdarg, thereby avoiding having to hardware them
+ * ones in core.stdc.stdarg, thereby avoiding having to hardwire them
* into the D compiler.
*/
diff --git a/libphobos/libdruntime/core/demangle.d b/libphobos/libdruntime/core/demangle.d
index ca87f90..c2d4032 100644
--- a/libphobos/libdruntime/core/demangle.d
+++ b/libphobos/libdruntime/core/demangle.d
@@ -82,7 +82,7 @@ pure @safe:
static class ParseException : Exception
{
- @safe pure nothrow this( string msg )
+ this(string msg) @safe pure nothrow
{
super( msg );
}
@@ -91,14 +91,14 @@ pure @safe:
static class OverflowException : Exception
{
- @safe pure nothrow this( string msg )
+ this(string msg) @safe pure nothrow
{
super( msg );
}
}
- static void error( string msg = "Invalid symbol" ) @trusted /* exception only used in module */
+ static noreturn error( string msg = "Invalid symbol" ) @trusted /* exception only used in module */
{
pragma(inline, false); // tame dmd inliner
@@ -110,7 +110,7 @@ pure @safe:
}
- static void overflow( string msg = "Buffer overflow" ) @trusted /* exception only used in module */
+ static noreturn overflow( string msg = "Buffer overflow" ) @trusted /* exception only used in module */
{
pragma(inline, false); // tame dmd inliner
@@ -156,7 +156,6 @@ pure @safe:
if (val >= '0' && val <= '9')
return cast(ubyte)(val - '0');
error();
- return 0;
}
@@ -253,23 +252,22 @@ pure @safe:
put(", ");
}
- char[] put(char c) return scope
+ void put(char c) return scope
{
char[1] val = c;
- return put(val[]);
+ put(val[]);
}
- char[] put( scope const(char)[] val ) return scope
+ void put(scope const(char)[] val) return scope
{
pragma(inline, false); // tame dmd inliner
- if ( val.length )
- {
- if ( !contains( dst[0 .. len], val ) )
- return append( val );
- return shift( val );
- }
- return null;
+ if (!val.length) return;
+
+ if (!contains(dst[0 .. len], val))
+ append(val);
+ else
+ shift(val);
}
@@ -948,18 +946,19 @@ pure @safe:
return dst[beg .. len];
case 'D': // TypeDelegate (D TypeFunction)
popFront();
- auto modbeg = len;
- parseModifier();
- auto modend = len;
+ auto modifiers = parseModifier();
if ( front == 'Q' )
parseBackrefType( () => parseTypeFunction( name, IsDelegate.yes ) );
else
parseTypeFunction( name, IsDelegate.yes );
- if (modend > modbeg)
+ if (modifiers)
{
- // move modifiers behind the function arguments
- shift(dst[modend-1 .. modend]); // trailing space
- shift(dst[modbeg .. modend-1]);
+ // write modifiers behind the function arguments
+ while (auto str = typeCtors.toStringConsume(modifiers))
+ {
+ put(' ');
+ put(str);
+ }
}
return dst[beg .. len];
case 'n': // TypeNone (n)
@@ -1009,7 +1008,6 @@ pure @safe:
}
}
error();
- return null;
}
}
@@ -1110,43 +1108,44 @@ pure @safe:
}
}
- void parseModifier()
+ /// Returns: Flags of `TypeCtor`
+ ushort parseModifier()
{
+ TypeCtor res = TypeCtor.None;
switch ( front )
{
case 'y':
popFront();
- put( "immutable " );
- break;
+ return TypeCtor.Immutable;
case 'O':
popFront();
- put( "shared " );
- if ( front == 'x' )
+ res |= TypeCtor.Shared;
+ if (front == 'x')
goto case 'x';
- if ( front == 'N' )
+ if (front == 'N')
goto case 'N';
- break;
+ return TypeCtor.Shared;
case 'N':
- if ( peek( 1 ) != 'g' )
- break;
+ if (peek( 1 ) != 'g')
+ return res;
popFront();
popFront();
- put( "inout " );
+ res |= TypeCtor.InOut;
if ( front == 'x' )
goto case 'x';
- break;
+ return res;
case 'x':
popFront();
- put( "const " );
- break;
- default: break;
+ res |= TypeCtor.Const;
+ return res;
+ default: return TypeCtor.None;
}
}
- void parseFuncAttr()
+ ushort parseFuncAttr()
{
// FuncAttrs
- breakFuncAttrs:
+ ushort result;
while ('N' == front)
{
popFront();
@@ -1154,27 +1153,27 @@ pure @safe:
{
case 'a': // FuncAttrPure
popFront();
- put( "pure " );
+ result |= FuncAttributes.Pure;
continue;
case 'b': // FuncAttrNoThrow
popFront();
- put( "nothrow " );
+ result |= FuncAttributes.Nothrow;
continue;
case 'c': // FuncAttrRef
popFront();
- put( "ref " );
+ result |= FuncAttributes.Ref;
continue;
case 'd': // FuncAttrProperty
popFront();
- put( "@property " );
+ result |= FuncAttributes.Property;
continue;
case 'e': // FuncAttrTrusted
popFront();
- put( "@trusted " );
+ result |= FuncAttributes.Trusted;
continue;
case 'f': // FuncAttrSafe
popFront();
- put( "@safe " );
+ result |= FuncAttributes.Safe;
continue;
case 'g':
case 'h':
@@ -1188,27 +1187,42 @@ pure @safe:
// if we see these, then we know we're really in
// the parameter list. Rewind and break.
pos--;
- break breakFuncAttrs;
+ return result;
case 'i': // FuncAttrNogc
popFront();
- put( "@nogc " );
+ result |= FuncAttributes.NoGC;
continue;
case 'j': // FuncAttrReturn
popFront();
- put( "return " );
+ if (this.peek(0) == 'N' && this.peek(1) == 'l')
+ {
+ result |= FuncAttributes.ReturnScope;
+ popFront();
+ popFront();
+ } else {
+ result |= FuncAttributes.Return;
+ }
continue;
case 'l': // FuncAttrScope
popFront();
- put( "scope " );
+ if (this.peek(0) == 'N' && this.peek(1) == 'j')
+ {
+ result |= FuncAttributes.ScopeReturn;
+ popFront();
+ popFront();
+ } else {
+ result |= FuncAttributes.Scope;
+ }
continue;
case 'm': // FuncAttrLive
popFront();
- put( "@live " );
+ result |= FuncAttributes.Live;
continue;
default:
error();
}
}
+ return result;
}
void parseFuncArguments() scope
@@ -1346,19 +1360,20 @@ pure @safe:
auto beg = len;
parseCallConvention();
- auto attrbeg = len;
- parseFuncAttr();
+ auto attributes = parseFuncAttr();
auto argbeg = len;
put( '(' );
parseFuncArguments();
put( ')' );
- if (attrbeg < argbeg)
+ if (attributes)
{
- // move function attributes behind arguments
- shift( dst[argbeg - 1 .. argbeg] ); // trailing space
- shift( dst[attrbeg .. argbeg - 1] ); // attributes
- argbeg = attrbeg;
+ // write function attributes behind arguments
+ while (auto str = funcAttrs.toStringConsume(attributes))
+ {
+ put(' ');
+ put(str);
+ }
}
auto retbeg = len;
parseType();
@@ -1900,21 +1915,26 @@ pure @safe:
{
// do not emit "needs this"
popFront();
- parseModifier();
+ auto modifiers = parseModifier();
+ while (auto str = typeCtors.toStringConsume(modifiers))
+ {
+ put(str);
+ put(' ');
+ }
}
if ( isCallConvention( front ) )
{
// we don't want calling convention and attributes in the qualified name
parseCallConvention();
- parseFuncAttr();
- if ( keepAttr )
- {
+ auto attributes = parseFuncAttr();
+ if (keepAttr) {
+ while (auto str = funcAttrs.toStringConsume(attributes))
+ {
+ put(str);
+ put(' ');
+ }
attr = dst[prevlen .. len];
}
- else
- {
- len = prevlen;
- }
put( '(' );
parseFuncArguments();
@@ -2637,6 +2657,12 @@ else
["_D4test4rrs1FNkMJPiZv", "void test.rrs1(return scope out int*)"],
["_D4test4rrs1FNkMKPiZv", "void test.rrs1(return scope ref int*)"],
["_D4test4rrs1FNkMPiZv", "void test.rrs1(return scope int*)"],
+
+ // `scope` and `return` combinations
+ ["_D3foo3Foo3barMNgFNjNlNfZNgPv", "inout return scope @safe inout(void*) foo.Foo.bar()"],
+ ["_D3foo3FooQiMNgFNlNfZv", "inout scope @safe void foo.Foo.foo()"],
+ ["_D3foo3Foo4foorMNgFNjNfZv", "inout return @safe void foo.Foo.foor()"],
+ ["_D3foo3Foo3rabMNgFNlNjNfZv", "inout scope return @safe void foo.Foo.rab()"],
];
@@ -2720,7 +2746,12 @@ unittest
}
/*
+ * Expand an OMF, DMD-generated compressed identifier into its full form
*
+ * This function only has a visible effect for OMF binaries (Win32),
+ * as compression is otherwise not used.
+ *
+ * See_Also: `compiler/src/dmd/backend/compress.d`
*/
string decodeDmdString( const(char)[] ln, ref size_t p ) nothrow pure @safe
{
@@ -2781,3 +2812,92 @@ extern (C) private
errno = err;
}
}
+
+private struct ManglingFlagInfo
+{
+ /// The flag value to use
+ ushort flag;
+
+ /// Human-readable representation
+ string value;
+}
+
+private enum TypeCtor : ushort {
+ None = 0,
+ //// 'x'
+ Const = (1 << 1),
+ /// 'y'
+ Immutable = (1 << 2),
+ /// 'O'
+ Shared = (1 << 3),
+ ///
+ InOut = (1 << 4),
+}
+
+private immutable ManglingFlagInfo[] typeCtors = [
+ ManglingFlagInfo(TypeCtor.Immutable, "immutable"),
+ ManglingFlagInfo(TypeCtor.Shared, "shared"),
+ ManglingFlagInfo(TypeCtor.InOut, "inout"),
+ ManglingFlagInfo(TypeCtor.Const, "const"),
+];
+
+private enum FuncAttributes : ushort {
+ None = 0,
+ //// 'a'
+ Pure = (1 << 1),
+ //// 'b'
+ Nothrow = (1 << 2),
+ //// 'c'
+ Ref = (1 << 3),
+ //// 'd'
+ Property = (1 << 4),
+ //// 'e'
+ Trusted = (1 << 5),
+ //// 'f'
+ Safe = (1 << 6),
+ //// 'i'
+ NoGC = (1 << 7),
+ //// 'j'
+ Return = (1 << 8),
+ //// 'l'
+ Scope = (1 << 9),
+ //// 'm'
+ Live = (1 << 10),
+
+ /// Their order matter
+ ReturnScope = (1 << 11),
+ ScopeReturn = (1 << 12),
+}
+
+// The order in which we process is the same as in compiler/dmd/src/dmangle.d
+private immutable ManglingFlagInfo[] funcAttrs = [
+ ManglingFlagInfo(FuncAttributes.Pure, "pure"),
+ ManglingFlagInfo(FuncAttributes.Nothrow, "nothrow"),
+ ManglingFlagInfo(FuncAttributes.Ref, "ref"),
+ ManglingFlagInfo(FuncAttributes.Property, "@property"),
+ ManglingFlagInfo(FuncAttributes.NoGC, "@nogc"),
+
+ ManglingFlagInfo(FuncAttributes.ReturnScope, "return scope"),
+ ManglingFlagInfo(FuncAttributes.ScopeReturn, "scope return"),
+
+ ManglingFlagInfo(FuncAttributes.Return, "return"),
+ ManglingFlagInfo(FuncAttributes.Scope, "scope"),
+
+ ManglingFlagInfo(FuncAttributes.Live, "@live"),
+ ManglingFlagInfo(FuncAttributes.Trusted, "@trusted"),
+ ManglingFlagInfo(FuncAttributes.Safe, "@safe"),
+];
+
+private string toStringConsume (immutable ManglingFlagInfo[] infos, ref ushort base)
+ @safe pure nothrow @nogc
+{
+ foreach (const ref info; infos)
+ {
+ if ((base & info.flag) == info.flag)
+ {
+ base &= ~info.flag;
+ return info.value;
+ }
+ }
+ return null;
+}
diff --git a/libphobos/libdruntime/core/internal/array/arrayassign.d b/libphobos/libdruntime/core/internal/array/arrayassign.d
index 6132e68..6e3c1fd 100644
--- a/libphobos/libdruntime/core/internal/array/arrayassign.d
+++ b/libphobos/libdruntime/core/internal/array/arrayassign.d
@@ -302,3 +302,151 @@ Tarr _d_arrayassign_r(Tarr : T[], T)(return scope Tarr to, scope Tarr from) @tru
assert(!didThrow);
assert(counter == 0);
}
+
+/**
+ * Sets all elements of an array to a single value. Takes into account postblits,
+ * copy constructors and destructors. For Plain Old Data elements,`rt/memset.d`
+ * is used.
+ *
+ * ---
+ * struct S
+ * {
+ * ~this() {} // destructor, so not Plain Old Data
+ * }
+ *
+ * void main()
+ * {
+ * S[3] arr;
+ * S value;
+ *
+ * arr = value;
+ * // Generates:
+ * // _d_arraysetassign(arr[], value), arr;
+ * }
+ * ---
+ *
+ * Params:
+ * to = destination array
+ * value = the element to set
+ * Returns:
+ * `to`
+ */
+Tarr _d_arraysetassign(Tarr : T[], T)(return scope Tarr to, scope ref T value) @trusted
+{
+ import core.internal.traits : Unqual;
+ import core.lifetime : copyEmplace;
+ import core.stdc.string : memcpy;
+
+ enum elemSize = T.sizeof;
+ void[elemSize] tmp = void;
+
+ foreach (ref dst; to)
+ {
+ memcpy(&tmp, cast(void*) &dst, elemSize);
+ // Use `memcpy` if `T` has a `@disable`d postblit.
+ static if (__traits(isCopyable, T))
+ copyEmplace(value, dst);
+ else
+ memcpy(cast(void*) &value, cast(void*) &dst, elemSize);
+ auto elem = cast(Unqual!T*) &tmp;
+ destroy(*elem);
+ }
+
+ return to;
+}
+
+// postblit and destructor
+@safe unittest
+{
+ string ops;
+ struct S
+ {
+ int val;
+ this(this) { ops ~= "="; }
+ ~this() { ops ~= "~"; }
+ }
+
+ S[4] arr;
+ S s = S(1234);
+ _d_arraysetassign(arr[], s);
+ assert(ops == "=~=~=~=~");
+ assert(arr == [S(1234), S(1234), S(1234), S(1234)]);
+}
+
+// copy constructor
+@safe unittest
+{
+ string ops;
+ struct S
+ {
+ int val;
+ this(const scope ref S rhs)
+ {
+ val = rhs.val;
+ ops ~= "=";
+ }
+ ~this() { ops ~= "~"; }
+ }
+
+ S[4] arr;
+ S s = S(1234);
+ _d_arraysetassign(arr[], s);
+ assert(ops == "=~=~=~=~");
+ assert(arr == [S(1234), S(1234), S(1234), S(1234)]);
+}
+
+// throwing and `nothrow`
+@safe nothrow unittest
+{
+ // Test that throwing works
+ bool didThrow;
+ int counter;
+ struct Throw
+ {
+ int val;
+ this(this)
+ {
+ counter++;
+ if (counter == 2)
+ throw new Exception("Oh no.");
+ }
+ }
+
+ try
+ {
+ Throw[4] a;
+ Throw b = Throw(1);
+ _d_arraysetassign(a[], b);
+ }
+ catch (Exception)
+ {
+ didThrow = true;
+ }
+ assert(didThrow);
+ assert(counter == 2);
+
+ // Test that `nothrow` works
+ didThrow = false;
+ counter = 0;
+ struct NoThrow
+ {
+ int val;
+ this(this) { counter++; }
+ }
+
+ try
+ {
+ NoThrow[4] a;
+ NoThrow b = NoThrow(1);
+ _d_arraysetassign(a[], b);
+ foreach (ref e; a)
+ assert(e == NoThrow(1));
+ }
+ catch (Exception)
+ {
+ didThrow = true;
+ }
+ assert(!didThrow);
+ // The array `a` is destroyed when the `try` block ends.
+ assert(counter == 4);
+}
diff --git a/libphobos/libdruntime/core/internal/dassert.d b/libphobos/libdruntime/core/internal/dassert.d
index 07486c2..dbad0e6 100644
--- a/libphobos/libdruntime/core/internal/dassert.d
+++ b/libphobos/libdruntime/core/internal/dassert.d
@@ -518,7 +518,7 @@ private auto assumeFakeAttributes(T)(T t) @trusted
}
/// Wrapper for `miniFormat` which assumes that the implementation is `@safe`, `@nogc`, ...
-/// s.t. it does not violate the constraints of the the function containing the `assert`.
+/// s.t. it does not violate the constraints of the function containing the `assert`.
private string miniFormatFakeAttributes(T)(const scope ref T t)
{
alias miniT = miniFormat!T;
diff --git a/libphobos/libdruntime/core/internal/utf.d b/libphobos/libdruntime/core/internal/utf.d
index 27bf7f2b..9808b99 100644
--- a/libphobos/libdruntime/core/internal/utf.d
+++ b/libphobos/libdruntime/core/internal/utf.d
@@ -567,17 +567,22 @@ ubyte codeLength(C)(dchar c)
/***********************************
Checks to see if string is well formed or not. $(D S) can be an array
- of $(D char), $(D wchar), or $(D dchar). Throws a $(D UtfException)
- if it is not. Use to check all untrusted input for correctness.
+ of $(D char), $(D wchar), or $(D dchar). Returns $(D false) if it is not.
+ Use to check all untrusted input for correctness.
*/
-@safe pure
-void validate(S)(const scope S s)
+@safe pure nothrow
+bool isValidString(S)(const scope S s)
{
auto len = s.length;
for (size_t i = 0; i < len; )
{
- decode(s, i);
+ try
+ decode(s, i);
+ catch (Exception e)
+ return false;
}
+
+ return true;
}
/* =================== Conversion to UTF8 ======================= */
@@ -626,7 +631,7 @@ char[] toUTF8(return scope char[] buf, dchar c)
string toUTF8(return scope string s)
in
{
- validate(s);
+ assert(isValidString(s));
}
do
{
@@ -787,7 +792,7 @@ wptr toUTF16z(const scope char[] s)
wstring toUTF16(return scope wstring s)
in
{
- validate(s);
+ assert(isValidString(s));
}
do
{
@@ -867,7 +872,7 @@ dstring toUTF32(const scope wchar[] s)
dstring toUTF32(return scope dstring s)
in
{
- validate(s);
+ assert(isValidString(s));
}
do
{
diff --git a/libphobos/libdruntime/core/simd.d b/libphobos/libdruntime/core/simd.d
index f1bf59b..c2b343a 100644
--- a/libphobos/libdruntime/core/simd.d
+++ b/libphobos/libdruntime/core/simd.d
@@ -704,7 +704,7 @@ version (D_SIMD)
// store `v` to location pointed to by `d`
storeUnaligned(cast(T*)d, v);
- // check that the the data was stored correctly
+ // check that the data was stored correctly
foreach (j; 0..T.sizeof)
{
assert(ptrToV[j] == d[j]);
diff --git a/libphobos/libdruntime/core/stdc/fenv.d b/libphobos/libdruntime/core/stdc/fenv.d
index 88123fb..5242ba9 100644
--- a/libphobos/libdruntime/core/stdc/fenv.d
+++ b/libphobos/libdruntime/core/stdc/fenv.d
@@ -483,7 +483,7 @@ else version (CRuntime_UClibc)
alias fexcept_t = ushort;
}
- else version (MIPS32)
+ else version (MIPS_Any)
{
struct fenv_t
{
diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d
index 0393ea5..2666c95 100644
--- a/libphobos/libdruntime/core/stdc/math.d
+++ b/libphobos/libdruntime/core/stdc/math.d
@@ -106,21 +106,14 @@ else version (CRuntime_Bionic)
}
else version (CRuntime_UClibc)
{
- version (X86)
- {
- ///
- enum int FP_ILOGB0 = int.min;
- ///
- enum int FP_ILOGBNAN = int.min;
- }
- else version (X86_64)
+ version (X86_Any)
{
///
enum int FP_ILOGB0 = int.min;
///
enum int FP_ILOGBNAN = int.min;
}
- else version (MIPS32)
+ else version (MIPS_Any)
{
///
enum int FP_ILOGB0 = -int.max;
diff --git a/libphobos/libdruntime/core/sys/darwin/mach/loader.d b/libphobos/libdruntime/core/sys/darwin/mach/loader.d
index f46698c..7713eea 100644
--- a/libphobos/libdruntime/core/sys/darwin/mach/loader.d
+++ b/libphobos/libdruntime/core/sys/darwin/mach/loader.d
@@ -1803,7 +1803,7 @@ version (CoreDdoc)
* image. The isub_image field is an index into the sub-images
* (sub-frameworks and sub-umbrellas list) that made up the two-level image
* that the undefined symbol was found in when it was built by the static
- * link editor. If isub-image is 0 the the symbol is expected to be defined
+ * link editor. If isub-image is 0 the symbol is expected to be defined
* in library and not in the sub-images. If isub-image is non-zero it is an
* index into the array of sub-images for the umbrella with the first index
* in the sub-images being 1. The array of sub-images is the ordered list of
diff --git a/libphobos/libdruntime/core/sys/linux/fcntl.d b/libphobos/libdruntime/core/sys/linux/fcntl.d
index 11c3745..89dc019 100644
--- a/libphobos/libdruntime/core/sys/linux/fcntl.d
+++ b/libphobos/libdruntime/core/sys/linux/fcntl.d
@@ -42,7 +42,7 @@ These cmd values will set locks that conflict with process-associated
record locks, but are "owned" by the open file description, not the
process. This means that they are inherited across fork() like BSD (flock)
locks, and they are only released automatically when the last reference to
-the the open file against which they were acquired is put.
+the open file against which they were acquired is put.
*/
enum
diff --git a/libphobos/libdruntime/core/sys/posix/dlfcn.d b/libphobos/libdruntime/core/sys/posix/dlfcn.d
index a9519ca..04a8e8b 100644
--- a/libphobos/libdruntime/core/sys/posix/dlfcn.d
+++ b/libphobos/libdruntime/core/sys/posix/dlfcn.d
@@ -377,7 +377,7 @@ else version (CRuntime_Musl)
}
else version (CRuntime_UClibc)
{
- version (X86_64)
+ version (X86_Any)
{
enum RTLD_LAZY = 0x0001;
enum RTLD_NOW = 0x0002;
@@ -387,7 +387,7 @@ else version (CRuntime_UClibc)
enum RTLD_LOCAL = 0;
enum RTLD_NODELETE = 0x01000;
}
- else version (MIPS32)
+ else version (MIPS_Any)
{
enum RTLD_LAZY = 0x0001;
enum RTLD_NOW = 0x0002;
diff --git a/libphobos/libdruntime/core/sys/posix/mqueue.d b/libphobos/libdruntime/core/sys/posix/mqueue.d
index 2f1a8c6..7085fc4 100644
--- a/libphobos/libdruntime/core/sys/posix/mqueue.d
+++ b/libphobos/libdruntime/core/sys/posix/mqueue.d
@@ -147,7 +147,7 @@ int mq_notify (mqd_t mqdes, const(sigevent)* notification);
/**
- * Receive the oldest message with the highest priority the the message queue
+ * Receive the oldest message with the highest priority the message queue
*
* Params:
* mqdes = Message queue descriptor.
@@ -164,7 +164,7 @@ ssize_t mq_receive (mqd_t mqdes, char* msg_ptr, size_t msg_len, uint* msg_prio);
/**
- * Receive the oldest message with the highest priority the the message queue,
+ * Receive the oldest message with the highest priority the message queue,
* wait up to a certain timeout.
*
* Params:
diff --git a/libphobos/libdruntime/core/sys/posix/setjmp.d b/libphobos/libdruntime/core/sys/posix/setjmp.d
index 91e3a19..5a15d82 100644
--- a/libphobos/libdruntime/core/sys/posix/setjmp.d
+++ b/libphobos/libdruntime/core/sys/posix/setjmp.d
@@ -370,6 +370,22 @@ else version (CRuntime_UClibc)
double[6] __fpregs;
}
}
+ else version (MIPS64)
+ {
+ struct __jmp_buf
+ {
+ long __pc;
+ long __sp;
+ long[8] __regs;
+ long __fp;
+ long __gp;
+ int __fpc_csr;
+ version (MIPS_N64)
+ double[8] __fpregs;
+ else
+ double[6] __fpregs;
+ }
+ }
else
static assert(0, "unimplemented");
diff --git a/libphobos/libdruntime/core/sys/posix/stdlib.d b/libphobos/libdruntime/core/sys/posix/stdlib.d
index 4c10d4e..df96a3d 100644
--- a/libphobos/libdruntime/core/sys/posix/stdlib.d
+++ b/libphobos/libdruntime/core/sys/posix/stdlib.d
@@ -95,44 +95,44 @@ int posix_memalign(void**, size_t, size_t);
version (CRuntime_Glibc)
{
- int posix_memalign(void**, size_t, size_t);
+ int posix_memalign(scope void**, size_t, size_t) pure;
}
else version (FreeBSD)
{
- int posix_memalign(void**, size_t, size_t);
+ int posix_memalign(scope void**, size_t, size_t) pure;
}
else version (NetBSD)
{
- int posix_memalign(void**, size_t, size_t);
+ int posix_memalign(scope void**, size_t, size_t) pure;
}
else version (OpenBSD)
{
- int posix_memalign(void**, size_t, size_t);
+ int posix_memalign(scope void**, size_t, size_t) pure;
}
else version (DragonFlyBSD)
{
- int posix_memalign(void**, size_t, size_t);
+ int posix_memalign(scope void**, size_t, size_t) pure;
}
else version (Solaris)
{
- int posix_memalign(void**, size_t, size_t);
+ int posix_memalign(scope void**, size_t, size_t) pure;
}
else version (Darwin)
{
- int posix_memalign(void**, size_t, size_t);
+ int posix_memalign(scope void**, size_t, size_t) pure;
}
else version (CRuntime_Bionic)
{
// Added since Lollipop
- int posix_memalign(void**, size_t, size_t);
+ int posix_memalign(scope void**, size_t, size_t) pure;
}
else version (CRuntime_Musl)
{
- int posix_memalign(void**, size_t, size_t);
+ int posix_memalign(scope void**, size_t, size_t) pure;
}
else version (CRuntime_UClibc)
{
- int posix_memalign(void**, size_t, size_t);
+ int posix_memalign(scope void**, size_t, size_t) pure;
}
//
diff --git a/libphobos/libdruntime/core/sys/posix/sys/types.d b/libphobos/libdruntime/core/sys/posix/sys/types.d
index ec229dd..3e515c4 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/types.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/types.d
@@ -1140,6 +1140,18 @@ else version (CRuntime_UClibc)
enum __SIZEOF_PTHREAD_BARRIER_T = 20;
enum __SIZEOF_PTHREAD_BARRIERATTR_T = 4;
}
+ else version (MIPS64)
+ {
+ enum __SIZEOF_PTHREAD_ATTR_T = 56;
+ enum __SIZEOF_PTHREAD_MUTEX_T = 40;
+ enum __SIZEOF_PTHREAD_MUTEXATTR_T = 4;
+ enum __SIZEOF_PTHREAD_COND_T = 48;
+ enum __SIZEOF_PTHREAD_CONDATTR_T = 4;
+ enum __SIZEOF_PTHREAD_RWLOCK_T = 56;
+ enum __SIZEOF_PTHREAD_RWLOCKATTR_T = 8;
+ enum __SIZEOF_PTHREAD_BARRIER_T = 32;
+ enum __SIZEOF_PTHREAD_BARRIERATTR_T = 4;
+ }
else version (ARM)
{
enum __SIZEOF_PTHREAD_ATTR_T = 36;
diff --git a/libphobos/libdruntime/core/sys/windows/stacktrace.d b/libphobos/libdruntime/core/sys/windows/stacktrace.d
index 2922e54..7982085 100644
--- a/libphobos/libdruntime/core/sys/windows/stacktrace.d
+++ b/libphobos/libdruntime/core/sys/windows/stacktrace.d
@@ -288,7 +288,8 @@ private:
auto res = formatStackFrame(pc);
res ~= " in ";
const(char)[] tempSymName = symName[0 .. strlen(symName)];
- //Deal with dmd mangling of long names
+ // Deal with dmd mangling of long names for OMF 32 bits builds
+ // Note that `target.d` only defines `CRuntime_DigitalMars` for OMF builds
version (CRuntime_DigitalMars)
{
size_t decodeIndex = 0;
diff --git a/libphobos/libdruntime/core/time.d b/libphobos/libdruntime/core/time.d
index 9b8391e..ea163a0 100644
--- a/libphobos/libdruntime/core/time.d
+++ b/libphobos/libdruntime/core/time.d
@@ -3362,7 +3362,7 @@ struct TickDuration
$(D gettimeofday) (the decision is made when $(D TickDuration) is
compiled), which unfortunately, is not monotonic, but if
$(D mach_absolute_time) and $(D clock_gettime) aren't available, then
- $(D gettimeofday) is the the best that there is.
+ $(D gettimeofday) is the best that there is.
$(RED Warning):
On some systems, the monotonic clock may stop counting when
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index d842499..83351f2 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -2700,7 +2700,7 @@ class Exception : Throwable
* Creates a new instance of Exception. The nextInChain parameter is used
* internally and should always be $(D null) when passed by user code.
* This constructor does not automatically throw the newly-created
- * Exception; the $(D throw) statement should be used for that purpose.
+ * Exception; the $(D throw) expression should be used for that purpose.
*/
@nogc @safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable nextInChain = null)
{
@@ -4617,6 +4617,7 @@ public import core.internal.array.construction : _d_arrayctor;
public import core.internal.array.construction : _d_arraysetctor;
public import core.internal.array.arrayassign : _d_arrayassign_l;
public import core.internal.array.arrayassign : _d_arrayassign_r;
+public import core.internal.array.arrayassign : _d_arraysetassign;
public import core.internal.array.capacity: _d_arraysetlengthTImpl;
public import core.internal.dassert: _d_assert_fail;
diff --git a/libphobos/libdruntime/rt/arrayassign.d b/libphobos/libdruntime/rt/arrayassign.d
deleted file mode 100644
index c9e2b15..0000000
--- a/libphobos/libdruntime/rt/arrayassign.d
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * Implementation of array assignment support routines.
- *
- *
- * Copyright: Copyright Digital Mars 2010 - 2016.
- * License: Distributed under the
- * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
- * Authors: Walter Bright, Kenji Hara
- * Source: $(DRUNTIMESRC rt/_arrayassign.d)
- */
-
-module rt.arrayassign;
-
-private
-{
- import core.internal.util.array;
- import core.stdc.string;
- import core.stdc.stdlib;
- debug(PRINTF) import core.stdc.stdio;
-}
-
-/**
-Set all elements of an array to a single value.
-
----
-p[0 .. count] = value;
----
-
-Takes into account postblits and destructors, for Plain Old Data elements,
-`rt/memset.d` is used.
-
-Params:
- p = pointer to start of array
- value = bytes of the element to set. Size is derived from `ti`.
- count = amount of array elements to set
- ti = type info of the array element type / `value`
-Returns: `p`
-*/
-extern (C) void* _d_arraysetassign(void* p, void* value, int count, TypeInfo ti)
-{
- void* pstart = p;
-
- auto element_size = ti.tsize;
-
- // Need a temporary buffer tmp[] big enough to hold one element
- immutable maxAllocaSize = 512;
- void *ptmp = (element_size > maxAllocaSize) ? malloc(element_size) : alloca(element_size);
-
- foreach (i; 0 .. count)
- {
- memcpy(ptmp, p, element_size);
- memcpy(p, value, element_size);
- ti.postblit(p);
- ti.destroy(ptmp);
- p += element_size;
- }
- if (element_size > maxAllocaSize)
- free(ptmp);
- return pstart;
-}
diff --git a/libphobos/libdruntime/rt/lifetime.d b/libphobos/libdruntime/rt/lifetime.d
index 026001f..f2515c3 100644
--- a/libphobos/libdruntime/rt/lifetime.d
+++ b/libphobos/libdruntime/rt/lifetime.d
@@ -1232,61 +1232,6 @@ debug(PRINTF)
/**
*
*/
-extern (C) void _d_delarray_t(void[]* p, const TypeInfo_Struct ti) @weak
-{
- if (p)
- {
- auto bic = __getBlkInfo(p.ptr);
- auto info = bic ? *bic : GC.query(p.ptr);
-
- if (info.base && (info.attr & BlkAttr.APPENDABLE))
- {
- if (ti) // ti non-null only if ti is a struct with dtor
- {
- void* start = __arrayStart(info);
- size_t length = __arrayAllocLength(info, ti);
- finalize_array(start, length, ti);
- }
-
- // if p is in the cache, clear it there as well
- if (bic)
- bic.base = null;
-
- GC.free(info.base);
- *p = null;
- }
- }
-}
-
-deprecated unittest
-{
- __gshared size_t countDtor = 0;
- struct S
- {
- int x;
- ~this() { countDtor++; }
- }
- // destroy large array with x.ptr not base address of allocation
- auto x = new S[10000];
- void* p = x.ptr;
- assert(GC.addrOf(p) != null);
- _d_delarray_t(cast(void[]*)&x, typeid(typeof(x[0]))); // delete x;
- assert(GC.addrOf(p) == null);
- assert(countDtor == 10000);
-
- // destroy full array even if only slice passed
- auto y = new S[400];
- auto z = y[200 .. 300];
- p = z.ptr;
- assert(GC.addrOf(p) != null);
- _d_delarray_t(cast(void[]*)&z, typeid(typeof(z[0]))); // delete z;
- assert(GC.addrOf(p) == null);
- assert(countDtor == 10000 + 400);
-}
-
-/**
- *
- */
extern (C) void _d_delmemory(void* *p) @weak
{
if (*p)
@@ -2755,11 +2700,6 @@ deprecated unittest
}
dtorCount = 0;
- S1[] arr1 = new S1[7];
- _d_delarray_t(cast(void[]*)&arr1, typeid(typeof(arr1[0]))); // delete arr1;
- assert(dtorCount == 7);
-
- dtorCount = 0;
S1* s2 = new S1;
GC.runFinalizers((cast(char*)(typeid(S1).xdtor))[0..1]);
assert(dtorCount == 1);
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index c8a3771..4d63826 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@
-b578dfad94770574d7e522557a77276c35943daa
+88aa69b14f8a28255a0ac7626f6509a13cfdb67a
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.
diff --git a/libphobos/src/Makefile.am b/libphobos/src/Makefile.am
index 2413024..655c02e 100644
--- a/libphobos/src/Makefile.am
+++ b/libphobos/src/Makefile.am
@@ -97,9 +97,9 @@ PHOBOS_DSOURCES = etc/c/curl.d etc/c/zlib.d std/algorithm/comparison.d \
std/datetime/interval.d std/datetime/package.d \
std/datetime/stopwatch.d std/datetime/systime.d \
std/datetime/timezone.d std/demangle.d std/digest/crc.d \
- std/digest/digest.d std/digest/hmac.d std/digest/md.d \
- std/digest/murmurhash.d std/digest/package.d std/digest/ripemd.d \
- std/digest/sha.d std/encoding.d std/exception.d \
+ std/digest/hmac.d std/digest/md.d std/digest/murmurhash.d \
+ std/digest/package.d std/digest/ripemd.d std/digest/sha.d \
+ std/encoding.d std/exception.d \
std/experimental/allocator/building_blocks/affix_allocator.d \
std/experimental/allocator/building_blocks/aligned_block_list.d \
std/experimental/allocator/building_blocks/allocator_list.d \
@@ -156,6 +156,6 @@ PHOBOS_DSOURCES = etc/c/curl.d etc/c/zlib.d std/algorithm/comparison.d \
std/stdio.d std/string.d std/sumtype.d std/system.d std/traits.d \
std/typecons.d std/typetuple.d std/uni/package.d std/uri.d std/utf.d \
std/uuid.d std/variant.d std/windows/charset.d std/windows/registry.d \
- std/windows/syserror.d std/xml.d std/zip.d std/zlib.d
+ std/windows/syserror.d std/zip.d std/zlib.d
endif
diff --git a/libphobos/src/Makefile.in b/libphobos/src/Makefile.in
index 562a428..a622958 100644
--- a/libphobos/src/Makefile.in
+++ b/libphobos/src/Makefile.in
@@ -179,7 +179,6 @@ am__dirstamp = $(am__leading_dot)dirstamp
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/datetime/timezone.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/demangle.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/digest/crc.lo \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/digest/digest.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/digest/hmac.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/digest/md.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/digest/murmurhash.lo \
@@ -291,8 +290,7 @@ am__dirstamp = $(am__leading_dot)dirstamp
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/windows/charset.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/windows/registry.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/windows/syserror.lo \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/xml.lo std/zip.lo \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/zlib.lo
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/zip.lo std/zlib.lo
am__objects_2 = $(am__objects_1)
am__objects_3 = $(am__objects_2)
am_libgphobos_la_OBJECTS = $(am__objects_3)
@@ -562,9 +560,9 @@ libgphobos_la_LINK = $(LIBTOOL) --tag=D $(libgphobos_la_LIBTOOLFLAGS) \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/datetime/interval.d std/datetime/package.d \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/datetime/stopwatch.d std/datetime/systime.d \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/datetime/timezone.d std/demangle.d std/digest/crc.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/digest/digest.d std/digest/hmac.d std/digest/md.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/digest/murmurhash.d std/digest/package.d std/digest/ripemd.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/digest/sha.d std/encoding.d std/exception.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/digest/hmac.d std/digest/md.d std/digest/murmurhash.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/digest/package.d std/digest/ripemd.d std/digest/sha.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/encoding.d std/exception.d \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/experimental/allocator/building_blocks/affix_allocator.d \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/experimental/allocator/building_blocks/aligned_block_list.d \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/experimental/allocator/building_blocks/allocator_list.d \
@@ -621,7 +619,7 @@ libgphobos_la_LINK = $(LIBTOOL) --tag=D $(libgphobos_la_LIBTOOLFLAGS) \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/stdio.d std/string.d std/sumtype.d std/system.d std/traits.d \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/typecons.d std/typetuple.d std/uni/package.d std/uri.d std/utf.d \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/uuid.d std/variant.d std/windows/charset.d std/windows/registry.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/windows/syserror.d std/xml.d std/zip.d std/zlib.d
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/windows/syserror.d std/zip.d std/zlib.d
# Source file definitions. Boring stuff, auto-generated with
@@ -754,7 +752,6 @@ std/digest/$(am__dirstamp):
@$(MKDIR_P) std/digest
@: > std/digest/$(am__dirstamp)
std/digest/crc.lo: std/digest/$(am__dirstamp)
-std/digest/digest.lo: std/digest/$(am__dirstamp)
std/digest/hmac.lo: std/digest/$(am__dirstamp)
std/digest/md.lo: std/digest/$(am__dirstamp)
std/digest/murmurhash.lo: std/digest/$(am__dirstamp)
@@ -964,7 +961,6 @@ std/windows/$(am__dirstamp):
std/windows/charset.lo: std/windows/$(am__dirstamp)
std/windows/registry.lo: std/windows/$(am__dirstamp)
std/windows/syserror.lo: std/windows/$(am__dirstamp)
-std/xml.lo: std/$(am__dirstamp)
std/zip.lo: std/$(am__dirstamp)
std/zlib.lo: std/$(am__dirstamp)
diff --git a/libphobos/src/index.dd b/libphobos/src/index.dd
index 45c248e..4812225 100644
--- a/libphobos/src/index.dd
+++ b/libphobos/src/index.dd
@@ -71,10 +71,6 @@ $(BOOKTABLE ,
$(TD Read/write data in JSON format.)
)
$(TR
- $(TDNW $(MREF std,xml))
- $(TD Read/write data in XML format.)
- )
- $(TR
$(TDNW $(MREF std,zip))
$(TD Read/write data in the ZIP archive format.)
)
diff --git a/libphobos/src/std/algorithm/comparison.d b/libphobos/src/std/algorithm/comparison.d
index b810fbb..5ecb4f6 100644
--- a/libphobos/src/std/algorithm/comparison.d
+++ b/libphobos/src/std/algorithm/comparison.d
@@ -577,14 +577,24 @@ Returns:
and `T3` are different.
*/
T1 clamp(T1, T2, T3)(T1 val, T2 lower, T3 upper)
-if (is(typeof(val.lessThan(lower) ? lower : val.greaterThan(upper) ? upper : val) : T1))
+if (is(typeof(val.lessThan(lower) ? lower : val.greaterThan(upper) ? upper : val))
+ && (is(T2 : T1) && is(T3 : T1)))
+// cannot use :
+// `if (is(typeof(val.lessThan(lower) ? lower : val.greaterThan(upper) ? upper : val) : T1))
+// because of https://issues.dlang.org/show_bug.cgi?id=16235.
+// Once that is fixed, we can simply use the ternary in both the template constraint
+// and the template body
in
{
assert(!lower.greaterThan(upper), "Lower can't be greater than upper.");
}
do
{
- return val.lessThan(lower) ? lower : val.greaterThan(upper) ? upper : val;
+ if (val.lessThan(lower))
+ return lower;
+ else if (val.greaterThan(upper))
+ return upper;
+ return val;
}
///
@@ -637,6 +647,12 @@ do
assert(x.clamp(lo, hi).y == 42);
}
+// https://issues.dlang.org/show_bug.cgi?id=23268
+@safe pure nothrow @nogc unittest
+{
+ static assert(__traits(compiles, clamp(short.init, short.init, cast(const) short.init)));
+}
+
// cmp
/**********************************
Performs a lexicographical comparison on two
diff --git a/libphobos/src/std/algorithm/iteration.d b/libphobos/src/std/algorithm/iteration.d
index 3e828ce..39eff0d 100644
--- a/libphobos/src/std/algorithm/iteration.d
+++ b/libphobos/src/std/algorithm/iteration.d
@@ -771,6 +771,23 @@ private struct MapResult(alias fun, Range)
assert(dd.length == 4);
}
+// Verify fix for: https://issues.dlang.org/show_bug.cgi?id=16034
+@safe unittest
+{
+ struct One
+ {
+ int entry = 1;
+ @disable this(this);
+ }
+
+ One[] ones = [One(), One()];
+
+ import std.algorithm.comparison : equal;
+
+ assert(ones.map!`a.entry + 1`.equal([2, 2]));
+}
+
+
@safe unittest
{
import std.algorithm.comparison : equal;
diff --git a/libphobos/src/std/algorithm/searching.d b/libphobos/src/std/algorithm/searching.d
index 870b1b4..15f7ca9 100644
--- a/libphobos/src/std/algorithm/searching.d
+++ b/libphobos/src/std/algorithm/searching.d
@@ -5002,7 +5002,7 @@ If set to `OpenRight.yes`, then the interval is open to the right
(last element is not included).
Otherwise if set to `OpenRight.no`, then the interval is closed to the right
-(last element included).
+including the entire sentinel.
*/
alias OpenRight = Flag!"openRight";
@@ -5052,6 +5052,7 @@ if (isInputRange!Range)
static if (!is(Sentinel == void))
private Sentinel _sentinel;
private OpenRight _openRight;
+ private bool _matchStarted;
private bool _done;
static if (!is(Sentinel == void))
@@ -5063,7 +5064,19 @@ if (isInputRange!Range)
_input = input;
_sentinel = sentinel;
_openRight = openRight;
- _done = _input.empty || openRight && predSatisfied();
+ static if (isInputRange!Sentinel)
+ {
+ _matchStarted = predSatisfied();
+ _done = _input.empty || _sentinel.empty || openRight && _matchStarted;
+ if (_matchStarted && !_done && !openRight)
+ {
+ _sentinel.popFront;
+ }
+ }
+ else
+ {
+ _done = _input.empty || openRight && predSatisfied();
+ }
}
private this(Range input, Sentinel sentinel, OpenRight openRight,
bool done)
@@ -5118,9 +5131,32 @@ if (isInputRange!Range)
assert(!empty, "Can not popFront of an empty Until");
if (!_openRight)
{
- _done = predSatisfied();
- _input.popFront();
- _done = _done || _input.empty;
+ static if (isInputRange!Sentinel)
+ {
+ _input.popFront();
+ _done = _input.empty || _sentinel.empty;
+ if (!_done)
+ {
+ if (_matchStarted)
+ {
+ _sentinel.popFront;
+ }
+ else
+ {
+ _matchStarted = predSatisfied();
+ if (_matchStarted)
+ {
+ _sentinel.popFront;
+ }
+ }
+ }
+ }
+ else
+ {
+ _done = predSatisfied();
+ _input.popFront();
+ _done = _done || _input.empty;
+ }
}
else
{
@@ -5212,3 +5248,33 @@ pure @safe unittest
assert(equal(r.save, "foo"));
}
}
+// https://issues.dlang.org/show_bug.cgi?id=14543
+pure @safe unittest
+{
+ import std.algorithm.comparison : equal;
+ import std.uni : toUpper;
+ assert("one two three".until("two").equal("one "));
+ assert("one two three".until("two", OpenRight.no).equal("one two"));
+
+ assert("one two three".until("two", No.openRight).equal("one two"));
+ assert("one two three".until("two", Yes.openRight).equal("one "));
+
+ assert("one two three".until('t', Yes.openRight).equal("one "));
+ assert("one two three".until("", Yes.openRight).equal(""));
+ assert("one two three".until("", No.openRight).equal(""));
+
+ assert("one two three".until("three", No.openRight).equal("one two three"));
+ assert("one two three".until("three", Yes.openRight).equal("one two "));
+
+ assert("one two three".until("one", No.openRight).equal("one"));
+ assert("one two three".until("one", Yes.openRight).equal(""));
+
+ assert("one two three".until("o", No.openRight).equal("o"));
+ assert("one two three".until("o", Yes.openRight).equal(""));
+
+ assert("one two three".until("", No.openRight).equal(""));
+ assert("one two three".until("", Yes.openRight).equal(""));
+
+ assert("one two three".until!((a,b)=>a.toUpper == b)("TWO", No.openRight).equal("one two"));
+}
+
diff --git a/libphobos/src/std/algorithm/sorting.d b/libphobos/src/std/algorithm/sorting.d
index ee68b23..4fc7ee9 100644
--- a/libphobos/src/std/algorithm/sorting.d
+++ b/libphobos/src/std/algorithm/sorting.d
@@ -1642,9 +1642,9 @@ private void multiSortImpl(Range, SwapStrategy ss, funs...)(Range r)
}
// https://issues.dlang.org/show_bug.cgi?id=16413 - @system comparison function
-@safe unittest
+@system unittest
{
- bool lt(int a, int b) { return a < b; } static @system
+ static @system bool lt(int a, int b) { return a < b; }
auto a = [2, 1];
a.multiSort!(lt, lt);
assert(a == [1, 2]);
diff --git a/libphobos/src/std/compiler.d b/libphobos/src/std/compiler.d
index 2f983c5..4ea5bd7 100644
--- a/libphobos/src/std/compiler.d
+++ b/libphobos/src/std/compiler.d
@@ -28,7 +28,7 @@ immutable
gnu = 2, /// GNU D Compiler (GDC)
llvm = 3, /// LLVM D Compiler (LDC)
dotNET = 4, /// D.NET
- sdc = 5, /// Stupid D Compiler (SDC)
+ sdc = 5, /// Snazzy D Compiler (SDC)
}
/// Which vendor produced this compiler.
diff --git a/libphobos/src/std/concurrency.d b/libphobos/src/std/concurrency.d
index fb383ae..bc53236 100644
--- a/libphobos/src/std/concurrency.d
+++ b/libphobos/src/std/concurrency.d
@@ -257,9 +257,12 @@ private
@property ref ThreadInfo thisInfo() nothrow
{
- if (scheduler is null)
+ import core.atomic : atomicLoad;
+
+ auto localScheduler = atomicLoad(scheduler);
+ if (localScheduler is null)
return ThreadInfo.thisInfo;
- return scheduler.thisInfo;
+ return localScheduler.thisInfo;
}
}
diff --git a/libphobos/src/std/container/array.d b/libphobos/src/std/container/array.d
index 08f9ead..ecc4599 100644
--- a/libphobos/src/std/container/array.d
+++ b/libphobos/src/std/container/array.d
@@ -412,9 +412,9 @@ if (!is(immutable T == immutable bool))
.destroy(e);
static if (hasIndirections!T)
- GC.removeRange(_payload.ptr);
+ GC.removeRange(cast(void*) _payload.ptr);
- free(_payload.ptr);
+ free(cast(void*) _payload.ptr);
}
this(this) @disable;
@@ -489,14 +489,14 @@ if (!is(immutable T == immutable bool))
auto newPayload = newPayloadPtr[0 .. oldLength];
// copy old data over to new array
- memcpy(newPayload.ptr, _payload.ptr, T.sizeof * oldLength);
+ memcpy(cast(void*) newPayload.ptr, cast(void*) _payload.ptr, T.sizeof * oldLength);
// Zero out unused capacity to prevent gc from seeing false pointers
- memset(newPayload.ptr + oldLength,
+ memset( cast(void*) (newPayload.ptr + oldLength),
0,
(elements - oldLength) * T.sizeof);
- GC.addRange(newPayload.ptr, sz);
- GC.removeRange(_payload.ptr);
- free(_payload.ptr);
+ GC.addRange(cast(void*) newPayload.ptr, sz);
+ GC.removeRange(cast(void*) _payload.ptr);
+ free(cast(void*) _payload.ptr);
_payload = newPayload;
}
else
@@ -611,12 +611,17 @@ if (!is(immutable T == immutable bool))
return opEquals(rhs);
}
+ // fix https://issues.dlang.org/show_bug.cgi?23140
+ private alias Unshared(T) = T;
+ private alias Unshared(T: shared U, U) = U;
+
/// ditto
bool opEquals(ref const Array rhs) const
{
if (empty) return rhs.empty;
if (rhs.empty) return false;
- return _data._payload == rhs._data._payload;
+
+ return cast(Unshared!(T)[]) _data._payload == cast(Unshared!(T)[]) rhs._data._payload;
}
/**
@@ -1740,6 +1745,16 @@ if (!is(immutable T == immutable bool))
assertThrown!AssertError(array.length = 5);
}
+// https://issues.dlang.org/show_bug.cgi?id=23140
+@system unittest
+{
+ shared class C
+ {
+ }
+
+ Array!C ac;
+ ac = Array!C([new C]);
+}
////////////////////////////////////////////////////////////////////////////////
// Array!bool
////////////////////////////////////////////////////////////////////////////////
diff --git a/libphobos/src/std/container/dlist.d b/libphobos/src/std/container/dlist.d
index 32d56ec..11e3883 100644
--- a/libphobos/src/std/container/dlist.d
+++ b/libphobos/src/std/container/dlist.d
@@ -111,7 +111,7 @@ private struct DRange
static assert(is(ElementType!DRange == BaseNode*));
}
-nothrow @safe pure:
+nothrow @safe @nogc pure:
private BaseNode* _first;
private BaseNode* _last;
diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d
index 9164e07..0f66065 100644
--- a/libphobos/src/std/conv.d
+++ b/libphobos/src/std/conv.d
@@ -4894,7 +4894,7 @@ if (isOctalLiteral(num))
template octal(alias decimalInteger)
if (is(typeof(decimalInteger)) && isIntegral!(typeof(decimalInteger)))
{
- enum octal = octal!(typeof(decimalInteger))(to!string(decimalInteger));
+ enum octal = convertToOctal(decimalInteger);
}
///
@@ -4910,6 +4910,19 @@ if (is(typeof(decimalInteger)) && isIntegral!(typeof(decimalInteger)))
auto d = octal!"0001_200_000";
}
+/*************************************
+ * Convert a decimal integer to an octal integer with the same digits.
+ * Params:
+ * i = integer to convert
+ * Returns:
+ * octal integer with the same type and same digits
+ */
+private T convertToOctal(T)(T i)
+{
+ assert((i % 10) < 8);
+ return i ? convertToOctal(i / 10) * 8 + i % 10 : 0;
+}
+
/*
Takes a string, num, which is an octal literal, and returns its
value, in the type T specified.
diff --git a/libphobos/src/std/datetime/stopwatch.d b/libphobos/src/std/datetime/stopwatch.d
index d8ecf7d..eedc0ea 100644
--- a/libphobos/src/std/datetime/stopwatch.d
+++ b/libphobos/src/std/datetime/stopwatch.d
@@ -234,7 +234,7 @@ public:
/++
- Peek at the amount of time that the the StopWatch has been running.
+ Peek at the amount of time that the StopWatch has been running.
This does not include any time during which the StopWatch was stopped but
does include $(I all) of the time that it was running and not just the
diff --git a/libphobos/src/std/datetime/timezone.d b/libphobos/src/std/datetime/timezone.d
index 28255f4..b238918 100644
--- a/libphobos/src/std/datetime/timezone.d
+++ b/libphobos/src/std/datetime/timezone.d
@@ -3397,8 +3397,7 @@ struct TZConversions
TZConversions parseTZConversions(string windowsZonesXMLText) @safe pure
{
// This is a bit hacky, since it doesn't properly read XML, but it avoids
- // needing to pull in std.xml (which we're theoretically replacing at some
- // point anyway).
+ // needing to pull in an xml parsing module.
import std.algorithm.iteration : uniq;
import std.algorithm.searching : find;
import std.algorithm.sorting : sort;
diff --git a/libphobos/src/std/digest/crc.d b/libphobos/src/std/digest/crc.d
index 38563b1..b7922bb 100644
--- a/libphobos/src/std/digest/crc.d
+++ b/libphobos/src/std/digest/crc.d
@@ -555,7 +555,7 @@ ubyte[8] crc64ECMAOf(T...)(T data)
}
/**
- * This is a convenience alias for $(REF digest, std,digest,digest) using the
+ * This is a convenience alias for $(REF digest, std,digest) using the
* CRC64-ISO implementation.
*
* Params:
@@ -611,7 +611,7 @@ alias CRC32Digest = WrapperDigest!CRC32;
* OOP API CRC64-ECMA implementation.
* See `std.digest` for differences between template and OOP API.
*
- * This is an alias for $(D $(REF WrapperDigest, std,digest,digest)!CRC64ECMA),
+ * This is an alias for $(D $(REF WrapperDigest, std,digest)!CRC64ECMA),
* see there for more information.
*/
alias CRC64ECMADigest = WrapperDigest!CRC64ECMA;
@@ -620,7 +620,7 @@ alias CRC64ECMADigest = WrapperDigest!CRC64ECMA;
* OOP API CRC64-ISO implementation.
* See `std.digest` for differences between template and OOP API.
*
- * This is an alias for $(D $(REF WrapperDigest, std,digest,digest)!CRC64ISO),
+ * This is an alias for $(D $(REF WrapperDigest, std,digest)!CRC64ISO),
* see there for more information.
*/
alias CRC64ISODigest = WrapperDigest!CRC64ISO;
@@ -628,7 +628,7 @@ alias CRC64ISODigest = WrapperDigest!CRC64ISO;
///
@safe unittest
{
- //Simple example, hashing a string using Digest.digest helper function
+ //Simple example, hashing a string using CRC32Digest.digest helper function
auto crc = new CRC32Digest();
ubyte[] hash = crc.digest("abc");
//Let's get a hash string
diff --git a/libphobos/src/std/digest/digest.d b/libphobos/src/std/digest/digest.d
deleted file mode 100644
index 01fdbd7..0000000
--- a/libphobos/src/std/digest/digest.d
+++ /dev/null
@@ -1,3 +0,0 @@
-// @@@DEPRECATED_2.101@@@
-deprecated("import std.digest instead of std.digest.digest. std.digest.digest will be removed in 2.101")
-module std.digest.digest;
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/affix_allocator.d b/libphobos/src/std/experimental/allocator/building_blocks/affix_allocator.d
index 1e3df91..d0d0b7c 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/affix_allocator.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/affix_allocator.d
@@ -521,9 +521,9 @@ version (StdUnittest)
@system unittest
{
- import std.experimental.allocator.building_blocks.region : Region;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
- auto a = AffixAllocator!(Region!(), uint)(Region!()(new ubyte[1024 * 64]));
+ auto a = AffixAllocator!(BorrowedRegion!(), uint)(BorrowedRegion!()(new ubyte[1024 * 64]));
auto b = a.allocate(42);
assert(b.length == 42);
// Test that expand infers from parent
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/aligned_block_list.d b/libphobos/src/std/experimental/allocator/building_blocks/aligned_block_list.d
index 14c6de4..99768bc 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/aligned_block_list.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/aligned_block_list.d
@@ -526,7 +526,7 @@ shared struct SharedAlignedBlockList(Allocator, ParentAllocator, ulong theAlignm
///
@system unittest
{
- import std.experimental.allocator.building_blocks.region : SharedRegion;
+ import std.experimental.allocator.building_blocks.region : SharedBorrowedRegion;
import std.experimental.allocator.building_blocks.ascending_page_allocator : SharedAscendingPageAllocator;
import std.experimental.allocator.building_blocks.null_allocator : NullAllocator;
import core.thread : ThreadGroup;
@@ -536,11 +536,11 @@ shared struct SharedAlignedBlockList(Allocator, ParentAllocator, ulong theAlignm
enum maxIter = 10;
/*
- In this example we use 'SharedAlignedBlockList' together with 'SharedRegion',
- in order to create a fast, thread-safe allocator.
+ In this example we use 'SharedAlignedBlockList' together with
+ 'SharedBorrowedRegion', in order to create a fast, thread-safe allocator.
*/
alias SuperAllocator = SharedAlignedBlockList!(
- SharedRegion!(NullAllocator, 1),
+ SharedBorrowedRegion!(1),
SharedAscendingPageAllocator,
4096);
@@ -597,7 +597,7 @@ version (StdUnittest)
SpinLock lock = SpinLock(SpinLock.Contention.brief);
alias SuperAllocator = SharedAlignedBlockList!(
- SharedRegion!(NullAllocator, 1),
+ SharedBorrowedRegion!(1),
SharedAscendingPageAllocator,
1 << 16);
void[][totalAllocs] buf;
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/allocator_list.d b/libphobos/src/std/experimental/allocator/building_blocks/allocator_list.d
index bcab16d..ca83785 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/allocator_list.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/allocator_list.d
@@ -679,8 +679,8 @@ version (Posix) @system unittest
{
// Create an allocator based upon 4MB regions, fetched from the GC heap.
import std.algorithm.comparison : max;
- import std.experimental.allocator.building_blocks.region : Region;
- AllocatorList!((n) => Region!()(new ubyte[max(n, 1024 * 4096)])) a;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
+ AllocatorList!((n) => BorrowedRegion!()(new ubyte[max(n, 1024 * 4096)])) a;
auto b1 = a.alignedAllocate(1024 * 8192, 1024);
assert(b1 !is null); // still works due to overdimensioning
assert(b1.length == 1024 * 8192);
@@ -707,8 +707,8 @@ version (Posix) @system unittest
// Create an allocator based upon 4MB regions, fetched from the GC heap.
import std.algorithm.comparison : max;
- import std.experimental.allocator.building_blocks.region : Region;
- AllocatorList!((n) => Region!()(new ubyte[max(n, 1024 * 4096)])) a;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
+ AllocatorList!((n) => BorrowedRegion!()(new ubyte[max(n, 1024 * 4096)])) a;
auto b1 = a.alignedAllocate(0, 1);
assert(b1 is null);
@@ -728,8 +728,8 @@ version (Posix) @system unittest
// Create an allocator based upon 4MB regions, fetched from the GC heap.
import std.algorithm.comparison : max;
- import std.experimental.allocator.building_blocks.region : Region;
- AllocatorList!((n) => Region!()(new ubyte[max(n, 1024 * 4096)])) a;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
+ AllocatorList!((n) => BorrowedRegion!()(new ubyte[max(n, 1024 * 4096)])) a;
auto b0 = a.alignedAllocate(1, 1024);
assert(b0.length == 1);
assert(b0.ptr.alignedAt(1024));
@@ -765,8 +765,8 @@ version (Posix) @system unittest
{
// Create an allocator based upon 4MB regions, fetched from the GC heap.
import std.algorithm.comparison : max;
- import std.experimental.allocator.building_blocks.region : Region;
- AllocatorList!((n) => Region!()(new ubyte[max(n, 1024 * 4096)])) a;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
+ AllocatorList!((n) => BorrowedRegion!()(new ubyte[max(n, 1024 * 4096)])) a;
auto b1 = a.allocate(1024 * 8192);
assert(b1 !is null); // still works due to overdimensioning
b1 = a.allocate(1024 * 10);
@@ -779,10 +779,10 @@ version (Posix) @system unittest
@system unittest
{
import std.algorithm.comparison : max;
- import std.experimental.allocator.building_blocks.region : Region;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
import std.experimental.allocator.mallocator : Mallocator;
import std.typecons : Ternary;
- AllocatorList!((n) => Region!()(new ubyte[max(n, 1024 * 4096)]), Mallocator) a;
+ AllocatorList!((n) => BorrowedRegion!()(new ubyte[max(n, 1024 * 4096)]), Mallocator) a;
auto b1 = a.allocate(1024 * 8192);
assert(b1 !is null);
b1 = a.allocate(1024 * 10);
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/fallback_allocator.d b/libphobos/src/std/experimental/allocator/building_blocks/fallback_allocator.d
index b413d73..3990418 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/fallback_allocator.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/fallback_allocator.d
@@ -342,12 +342,12 @@ struct FallbackAllocator(Primary, Fallback)
@system unittest
{
- import std.experimental.allocator.building_blocks.region : Region;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
import std.typecons : Ternary;
- auto a = FallbackAllocator!(Region!(), Region!())(
- Region!()(new ubyte[4096 * 1024]),
- Region!()(new ubyte[4096 * 1024]));
+ auto a = FallbackAllocator!(BorrowedRegion!(), BorrowedRegion!())(
+ BorrowedRegion!()(new ubyte[4096 * 1024]),
+ BorrowedRegion!()(new ubyte[4096 * 1024]));
auto b = a.alignedAllocate(42, 8);
assert(b.length == 42);
@@ -506,11 +506,11 @@ version (StdUnittest)
@system unittest
{
- import std.experimental.allocator.building_blocks.region : Region;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
import std.typecons : Ternary;
- alias A = FallbackAllocator!(Region!(), Region!());
- auto a = A(Region!()(new ubyte[16_384]), Region!()(new ubyte[16_384]));
+ alias A = FallbackAllocator!(BorrowedRegion!(), BorrowedRegion!());
+ auto a = A(BorrowedRegion!()(new ubyte[16_384]), BorrowedRegion!()(new ubyte[16_384]));
auto b = a.allocate(42);
assert(b.length == 42);
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/free_list.d b/libphobos/src/std/experimental/allocator/building_blocks/free_list.d
index 7055d66..d2b3209 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/free_list.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/free_list.d
@@ -486,9 +486,9 @@ struct FreeList(ParentAllocator,
// Test that deallocateAll infers from parent
@system unittest
{
- import std.experimental.allocator.building_blocks.region : Region;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
- auto fl = FreeList!(Region!(), 0, 16)(Region!()(new ubyte[1024 * 64]));
+ auto fl = FreeList!(BorrowedRegion!(), 0, 16)(BorrowedRegion!()(new ubyte[1024 * 64]));
auto b = fl.allocate(42);
assert(b.length == 42);
assert((() pure nothrow @safe @nogc => fl.expand(b, 48))());
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/free_tree.d b/libphobos/src/std/experimental/allocator/building_blocks/free_tree.d
index bd4bb95..fe59e26 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/free_tree.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/free_tree.d
@@ -502,9 +502,9 @@ version (StdUnittest)
@system unittest
{
- import std.experimental.allocator.building_blocks.region : Region;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
- auto a = FreeTree!(Region!())(Region!()(new ubyte[1024 * 64]));
+ auto a = FreeTree!(BorrowedRegion!())(BorrowedRegion!()(new ubyte[1024 * 64]));
auto b = a.allocate(42);
assert(b.length == 42);
assert((() pure nothrow @safe @nogc => a.expand(b, 22))());
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/quantizer.d b/libphobos/src/std/experimental/allocator/building_blocks/quantizer.d
index 762b379..3334a86 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/quantizer.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/quantizer.d
@@ -315,14 +315,14 @@ version (StdUnittest)
version (StdUnittest)
@system unittest
{
- import std.experimental.allocator.building_blocks.region : Region;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
import std.typecons : Ternary;
- alias MyAlloc = Quantizer!(Region!(),
+ alias MyAlloc = Quantizer!(BorrowedRegion!(),
(size_t n) => n.roundUpToMultipleOf(64));
- testAllocator!(() => MyAlloc(Region!()(new ubyte[1024 * 64])));
+ testAllocator!(() => MyAlloc(BorrowedRegion!()(new ubyte[1024 * 64])));
- auto a = MyAlloc(Region!()(new ubyte[1024 * 64]));
+ auto a = MyAlloc(BorrowedRegion!()(new ubyte[1024 * 64]));
// Check that empty inherits from parent
assert((() pure nothrow @safe @nogc => a.empty)() == Ternary.yes);
auto b = a.allocate(42);
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/region.d b/libphobos/src/std/experimental/allocator/building_blocks/region.d
index be0d274..8c39784 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/region.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/region.d
@@ -29,8 +29,7 @@ the store and the limits. One allocation entails rounding up the allocation
size for alignment purposes, bumping the current pointer, and comparing it
against the limit.
-If `ParentAllocator` is different from $(REF_ALTTEXT `NullAllocator`, NullAllocator, std,experimental,allocator,building_blocks,null_allocator), `Region`
-deallocates the chunk of memory during destruction.
+`Region` deallocates the chunk of memory during destruction.
The `minAlign` parameter establishes alignment. If $(D minAlign > 1), the
sizes of all allocation requests are rounded up to a multiple of `minAlign`.
@@ -38,7 +37,7 @@ Applications aiming at maximum speed may want to choose $(D minAlign = 1) and
control alignment externally.
*/
-struct Region(ParentAllocator = NullAllocator,
+struct Region(ParentAllocator,
uint minAlign = platformAlignment,
Flag!"growDownwards" growDownwards = No.growDownwards)
{
@@ -63,50 +62,42 @@ struct Region(ParentAllocator = NullAllocator,
alias parent = ParentAllocator.instance;
}
- private void* _current, _begin, _end;
+ private BorrowedRegion!(minAlign, growDownwards) _impl;
private void* roundedBegin() const pure nothrow @trusted @nogc
{
- return cast(void*) roundUpToAlignment(cast(size_t) _begin, alignment);
+ return _impl.roundedBegin;
}
private void* roundedEnd() const pure nothrow @trusted @nogc
{
- return cast(void*) roundDownToAlignment(cast(size_t) _end, alignment);
+ return _impl.roundedEnd;
}
/**
Constructs a region backed by a user-provided store.
- Assumes the memory was allocated with `ParentAllocator`
- (if different from $(REF_ALTTEXT `NullAllocator`, NullAllocator, std,experimental,allocator,building_blocks,null_allocator)).
+ Assumes the memory was allocated with `ParentAllocator`.
Params:
- store = User-provided store backing up the region. If $(D
- ParentAllocator) is different from $(REF_ALTTEXT `NullAllocator`, NullAllocator, std,experimental,allocator,building_blocks,null_allocator), memory is assumed to
- have been allocated with `ParentAllocator`.
- n = Bytes to allocate using `ParentAllocator`. This constructor is only
- defined If `ParentAllocator` is different from $(REF_ALTTEXT `NullAllocator`, NullAllocator, std,experimental,allocator,building_blocks,null_allocator). If
- `parent.allocate(n)` returns `null`, the region will be initialized
- as empty (correctly initialized but unable to allocate).
+ store = User-provided store backing up the region. Assumed to have been
+ allocated with `ParentAllocator`.
+ n = Bytes to allocate using `ParentAllocator`. If `parent.allocate(n)`
+ returns `null`, the region will be initialized as empty (correctly
+ initialized but unable to allocate).
*/
this(ubyte[] store) pure nothrow @nogc
{
- _begin = store.ptr;
- _end = store.ptr + store.length;
- static if (growDownwards)
- _current = roundedEnd();
- else
- _current = roundedBegin();
+ _impl = store;
}
/// Ditto
- static if (!is(ParentAllocator == NullAllocator) && !stateSize!ParentAllocator)
+ static if (!stateSize!ParentAllocator)
this(size_t n)
{
this(cast(ubyte[]) (parent.allocate(n.roundUpToAlignment(alignment))));
}
/// Ditto
- static if (!is(ParentAllocator == NullAllocator) && stateSize!ParentAllocator)
+ static if (stateSize!ParentAllocator)
this(ParentAllocator parent, size_t n)
{
this.parent = parent;
@@ -119,18 +110,299 @@ struct Region(ParentAllocator = NullAllocator,
*/
/**
- If `ParentAllocator` is not $(REF_ALTTEXT `NullAllocator`, NullAllocator, std,experimental,allocator,building_blocks,null_allocator) and defines `deallocate`,
- the region defines a destructor that uses `ParentAllocator.deallocate` to free the
- memory chunk.
+ If `ParentAllocator` defines `deallocate`, the region defines a destructor
+ that uses `ParentAllocator.deallocate` to free the memory chunk.
*/
- static if (!is(ParentAllocator == NullAllocator)
- && hasMember!(ParentAllocator, "deallocate"))
+ static if (hasMember!(ParentAllocator, "deallocate"))
~this()
{
- parent.deallocate(_begin[0 .. _end - _begin]);
+ with (_impl) parent.deallocate(_begin[0 .. _end - _begin]);
+ }
+
+ /**
+ Rounds the given size to a multiple of the `alignment`
+ */
+ size_t goodAllocSize(size_t n) const pure nothrow @safe @nogc
+ {
+ return _impl.goodAllocSize(n);
+ }
+
+ /**
+ Alignment offered.
+ */
+ alias alignment = minAlign;
+
+ /**
+ Allocates `n` bytes of memory. The shortest path involves an alignment
+ adjustment (if $(D alignment > 1)), an increment, and a comparison.
+
+ Params:
+ n = number of bytes to allocate
+
+ Returns:
+ A properly-aligned buffer of size `n` or `null` if request could not
+ be satisfied.
+ */
+ void[] allocate(size_t n) pure nothrow @trusted @nogc
+ {
+ return _impl.allocate(n);
+ }
+
+ /**
+ Allocates `n` bytes of memory aligned at alignment `a`.
+
+ Params:
+ n = number of bytes to allocate
+ a = alignment for the allocated block
+
+ Returns:
+ Either a suitable block of `n` bytes aligned at `a`, or `null`.
+ */
+ void[] alignedAllocate(size_t n, uint a) pure nothrow @trusted @nogc
+ {
+ return _impl.alignedAllocate(n, a);
+ }
+
+ /// Allocates and returns all memory available to this region.
+ void[] allocateAll() pure nothrow @trusted @nogc
+ {
+ return _impl.allocateAll;
+ }
+
+ /**
+ Expands an allocated block in place. Expansion will succeed only if the
+ block is the last allocated. Defined only if `growDownwards` is
+ `No.growDownwards`.
+ */
+ static if (growDownwards == No.growDownwards)
+ bool expand(ref void[] b, size_t delta) pure nothrow @safe @nogc
+ {
+ return _impl.expand(b, delta);
+ }
+
+ /**
+ Deallocates `b`. This works only if `b` was obtained as the last call
+ to `allocate`; otherwise (i.e. another allocation has occurred since) it
+ does nothing.
+
+ Params:
+ b = Block previously obtained by a call to `allocate` against this
+ allocator (`null` is allowed).
+ */
+ bool deallocate(void[] b) pure nothrow @nogc
+ {
+ return _impl.deallocate(b);
+ }
+
+ /**
+ Deallocates all memory allocated by this region, which can be subsequently
+ reused for new allocations.
+ */
+ bool deallocateAll() pure nothrow @nogc
+ {
+ return _impl.deallocateAll;
+ }
+
+ /**
+ Queries whether `b` has been allocated with this region.
+
+ Params:
+ b = Arbitrary block of memory (`null` is allowed; `owns(null)` returns
+ `false`).
+
+ Returns:
+ `true` if `b` has been allocated with this region, `false` otherwise.
+ */
+ Ternary owns(const void[] b) const pure nothrow @trusted @nogc
+ {
+ return _impl.owns(b);
+ }
+
+ /**
+ Returns `Ternary.yes` if no memory has been allocated in this region,
+ `Ternary.no` otherwise. (Never returns `Ternary.unknown`.)
+ */
+ Ternary empty() const pure nothrow @safe @nogc
+ {
+ return _impl.empty;
+ }
+
+ /// Nonstandard property that returns bytes available for allocation.
+ size_t available() const @safe pure nothrow @nogc
+ {
+ return _impl.available;
+ }
+}
+
+///
+@system nothrow unittest
+{
+ import std.algorithm.comparison : max;
+ import std.experimental.allocator.building_blocks.allocator_list
+ : AllocatorList;
+ import std.experimental.allocator.mallocator : Mallocator;
+ import std.typecons : Ternary;
+ // Create a scalable list of regions. Each gets at least 1MB at a time by
+ // using malloc.
+ auto batchAllocator = AllocatorList!(
+ (size_t n) => Region!Mallocator(max(n, 1024 * 1024))
+ )();
+ assert(batchAllocator.empty == Ternary.yes);
+ auto b = batchAllocator.allocate(101);
+ assert(b.length == 101);
+ assert(batchAllocator.empty == Ternary.no);
+ // This will cause a second allocation
+ b = batchAllocator.allocate(2 * 1024 * 1024);
+ assert(b.length == 2 * 1024 * 1024);
+ // Destructor will free the memory
+}
+
+@system nothrow @nogc unittest
+{
+ import std.experimental.allocator.mallocator : Mallocator;
+ import std.typecons : Ternary;
+
+ static void testAlloc(Allocator)(ref Allocator a)
+ {
+ assert((() pure nothrow @safe @nogc => a.empty)() == Ternary.yes);
+ const b = a.allocate(101);
+ assert(b.length == 101);
+ assert((() nothrow @safe @nogc => a.owns(b))() == Ternary.yes);
+
+ // Ensure deallocate inherits from parent allocators
+ auto c = a.allocate(42);
+ assert(c.length == 42);
+ assert((() nothrow @nogc => a.deallocate(c))());
+ assert((() pure nothrow @safe @nogc => a.empty)() == Ternary.no);
+ }
+
+ // Create a 64 KB region allocated with malloc
+ auto reg = Region!(Mallocator, Mallocator.alignment,
+ Yes.growDownwards)(1024 * 64);
+ testAlloc(reg);
+
+ // Create a 64 KB shared region allocated with malloc
+ auto sharedReg = SharedRegion!(Mallocator, Mallocator.alignment,
+ Yes.growDownwards)(1024 * 64);
+ testAlloc(sharedReg);
+}
+
+@system nothrow @nogc unittest
+{
+ // test 'this(ubyte[] store)' constructed regions properly clean up
+ // their inner storage after destruction
+ import std.experimental.allocator.mallocator : Mallocator;
+
+ static shared struct LocalAllocator
+ {
+ nothrow @nogc:
+ enum alignment = Mallocator.alignment;
+ void[] buf;
+ bool deallocate(void[] b)
+ {
+ assert(buf.ptr == b.ptr && buf.length == b.length);
+ return true;
+ }
+
+ void[] allocate(size_t n)
+ {
+ return null;
+ }
+
+ }
+
+ enum bufLen = 10 * Mallocator.alignment;
+ void[] tmp = Mallocator.instance.allocate(bufLen);
+
+ LocalAllocator a;
+ a.buf = cast(typeof(a.buf)) tmp[1 .. $];
+
+ auto reg = Region!(LocalAllocator, Mallocator.alignment,
+ Yes.growDownwards)(cast(ubyte[]) a.buf);
+ auto sharedReg = SharedRegion!(LocalAllocator, Mallocator.alignment,
+ Yes.growDownwards)(cast(ubyte[]) a.buf);
+ reg.parent = a;
+ sharedReg.parent = a;
+
+ Mallocator.instance.deallocate(tmp);
+}
+
+version (StdUnittest)
+@system unittest
+{
+ import std.experimental.allocator.mallocator : Mallocator;
+
+ testAllocator!(() => Region!(Mallocator)(1024 * 64));
+ testAllocator!(() => Region!(Mallocator, Mallocator.alignment, Yes.growDownwards)(1024 * 64));
+
+ testAllocator!(() => SharedRegion!(Mallocator)(1024 * 64));
+ testAllocator!(() => SharedRegion!(Mallocator, Mallocator.alignment, Yes.growDownwards)(1024 * 64));
+}
+
+@system nothrow @nogc unittest
+{
+ import std.experimental.allocator.mallocator : Mallocator;
+
+ auto reg = Region!(Mallocator)(1024 * 64);
+ auto b = reg.allocate(101);
+ assert(b.length == 101);
+ assert((() pure nothrow @safe @nogc => reg.expand(b, 20))());
+ assert((() pure nothrow @safe @nogc => reg.expand(b, 73))());
+ assert((() pure nothrow @safe @nogc => !reg.expand(b, 1024 * 64))());
+ assert((() nothrow @nogc => reg.deallocateAll())());
+}
+
+/**
+A `BorrowedRegion` allocates directly from a user-provided block of memory.
+
+Unlike a `Region`, a `BorrowedRegion` does not own the memory it allocates from
+and will not deallocate that memory upon destruction. Instead, it is the user's
+responsibility to ensure that the memory is properly disposed of.
+
+In all other respects, a `BorrowedRegion` behaves exactly like a `Region`.
+*/
+struct BorrowedRegion(uint minAlign = platformAlignment,
+ Flag!"growDownwards" growDownwards = No.growDownwards)
+{
+ static assert(minAlign.isGoodStaticAlignment);
+
+ import std.typecons : Ternary;
+
+ // state
+ private void* _current, _begin, _end;
+
+ private void* roundedBegin() const pure nothrow @trusted @nogc
+ {
+ return cast(void*) roundUpToAlignment(cast(size_t) _begin, alignment);
+ }
+
+ private void* roundedEnd() const pure nothrow @trusted @nogc
+ {
+ return cast(void*) roundDownToAlignment(cast(size_t) _end, alignment);
}
/**
+ Constructs a region backed by a user-provided store.
+
+ Params:
+ store = User-provided store backing up the region.
+ */
+ this(ubyte[] store) pure nothrow @nogc
+ {
+ _begin = store.ptr;
+ _end = store.ptr + store.length;
+ static if (growDownwards)
+ _current = roundedEnd();
+ else
+ _current = roundedBegin();
+ }
+
+ /*
+ TODO: The postblit of `BorrowedRegion` should be disabled because such objects
+ should not be copied around naively.
+ */
+
+ /**
Rounds the given size to a multiple of the `alignment`
*/
size_t goodAllocSize(size_t n) const pure nothrow @safe @nogc
@@ -362,56 +634,32 @@ struct Region(ParentAllocator = NullAllocator,
}
///
-@system nothrow unittest
-{
- import std.algorithm.comparison : max;
- import std.experimental.allocator.building_blocks.allocator_list
- : AllocatorList;
- import std.experimental.allocator.mallocator : Mallocator;
- import std.typecons : Ternary;
- // Create a scalable list of regions. Each gets at least 1MB at a time by
- // using malloc.
- auto batchAllocator = AllocatorList!(
- (size_t n) => Region!Mallocator(max(n, 1024 * 1024))
- )();
- assert(batchAllocator.empty == Ternary.yes);
- auto b = batchAllocator.allocate(101);
- assert(b.length == 101);
- assert(batchAllocator.empty == Ternary.no);
- // This will cause a second allocation
- b = batchAllocator.allocate(2 * 1024 * 1024);
- assert(b.length == 2 * 1024 * 1024);
- // Destructor will free the memory
-}
-
@system nothrow @nogc unittest
{
- import std.experimental.allocator.mallocator : Mallocator;
import std.typecons : Ternary;
- static void testAlloc(Allocator)(ref Allocator a)
- {
- assert((() pure nothrow @safe @nogc => a.empty)() == Ternary.yes);
- const b = a.allocate(101);
- assert(b.length == 101);
- assert((() nothrow @safe @nogc => a.owns(b))() == Ternary.yes);
+ ubyte[1024] store;
+ auto myRegion = BorrowedRegion!(1)(store[]);
- // Ensure deallocate inherits from parent allocators
- auto c = a.allocate(42);
- assert(c.length == 42);
- assert((() nothrow @nogc => a.deallocate(c))());
- assert((() pure nothrow @safe @nogc => a.empty)() == Ternary.no);
- }
+ assert(myRegion.empty == Ternary.yes);
+ assert(myRegion.available == store.length);
- // Create a 64 KB region allocated with malloc
- auto reg = Region!(Mallocator, Mallocator.alignment,
- Yes.growDownwards)(1024 * 64);
- testAlloc(reg);
+ void[] b = myRegion.allocate(101);
- // Create a 64 KB shared region allocated with malloc
- auto sharedReg = SharedRegion!(Mallocator, Mallocator.alignment,
- Yes.growDownwards)(1024 * 64);
- testAlloc(sharedReg);
+ assert(b.length == 101);
+ assert(myRegion.empty == Ternary.no);
+ assert(myRegion.owns(b) == Ternary.yes);
+ assert(myRegion.available == store.length - b.length);
+
+ void[] b2 = myRegion.allocate(256);
+
+ // Can only free the most recent allocation
+ assert(myRegion.deallocate(b) == false);
+ assert(myRegion.deallocate(b2) == true);
+
+ myRegion.deallocateAll();
+
+ assert(myRegion.empty == Ternary.yes);
}
@system nothrow @nogc unittest
@@ -420,76 +668,11 @@ struct Region(ParentAllocator = NullAllocator,
import std.typecons : Ternary;
ubyte[] buf = cast(ubyte[]) AlignedMallocator.instance.alignedAllocate(64, 64);
- auto reg = Region!(NullAllocator, 64, Yes.growDownwards)(buf);
+ auto reg = BorrowedRegion!(64, Yes.growDownwards)(buf);
assert(reg.alignedAllocate(10, 32).length == 10);
assert(!reg.available);
}
-@system nothrow @nogc unittest
-{
- // test 'this(ubyte[] store)' constructed regions properly clean up
- // their inner storage after destruction
- import std.experimental.allocator.mallocator : Mallocator;
-
- static shared struct LocalAllocator
- {
- nothrow @nogc:
- enum alignment = Mallocator.alignment;
- void[] buf;
- bool deallocate(void[] b)
- {
- assert(buf.ptr == b.ptr && buf.length == b.length);
- return true;
- }
-
- void[] allocate(size_t n)
- {
- return null;
- }
-
- }
-
- enum bufLen = 10 * Mallocator.alignment;
- void[] tmp = Mallocator.instance.allocate(bufLen);
-
- LocalAllocator a;
- a.buf = cast(typeof(a.buf)) tmp[1 .. $];
-
- auto reg = Region!(LocalAllocator, Mallocator.alignment,
- Yes.growDownwards)(cast(ubyte[]) a.buf);
- auto sharedReg = SharedRegion!(LocalAllocator, Mallocator.alignment,
- Yes.growDownwards)(cast(ubyte[]) a.buf);
- reg.parent = a;
- sharedReg.parent = a;
-
- Mallocator.instance.deallocate(tmp);
-}
-
-version (StdUnittest)
-@system unittest
-{
- import std.experimental.allocator.mallocator : Mallocator;
-
- testAllocator!(() => Region!(Mallocator)(1024 * 64));
- testAllocator!(() => Region!(Mallocator, Mallocator.alignment, Yes.growDownwards)(1024 * 64));
-
- testAllocator!(() => SharedRegion!(Mallocator)(1024 * 64));
- testAllocator!(() => SharedRegion!(Mallocator, Mallocator.alignment, Yes.growDownwards)(1024 * 64));
-}
-
-@system nothrow @nogc unittest
-{
- import std.experimental.allocator.mallocator : Mallocator;
-
- auto reg = Region!(Mallocator)(1024 * 64);
- auto b = reg.allocate(101);
- assert(b.length == 101);
- assert((() pure nothrow @safe @nogc => reg.expand(b, 20))());
- assert((() pure nothrow @safe @nogc => reg.expand(b, 73))());
- assert((() pure nothrow @safe @nogc => !reg.expand(b, 1024 * 64))());
- assert((() nothrow @nogc => reg.deallocateAll())());
-}
-
/**
`InSituRegion` is a convenient region that carries its storage within itself
@@ -535,7 +718,7 @@ struct InSituRegion(size_t size, size_t minAlign = platformAlignment)
@disable this(this);
// state {
- private Region!(NullAllocator, minAlign, growDownwards) _impl;
+ private BorrowedRegion!(minAlign, growDownwards) _impl;
union
{
private ubyte[size] _store = void;
@@ -992,7 +1175,7 @@ version (Posix) @system nothrow @nogc unittest
The threadsafe version of the `Region` allocator.
Allocations and deallocations are lock-free based using $(REF cas, core,atomic).
*/
-shared struct SharedRegion(ParentAllocator = NullAllocator,
+shared struct SharedRegion(ParentAllocator,
uint minAlign = platformAlignment,
Flag!"growDownwards" growDownwards = No.growDownwards)
{
@@ -1016,45 +1199,36 @@ shared struct SharedRegion(ParentAllocator = NullAllocator,
{
alias parent = ParentAllocator.instance;
}
- private shared void* _current, _begin, _end;
+ private shared SharedBorrowedRegion!(minAlign, growDownwards) _impl;
private void* roundedBegin() const pure nothrow @trusted @nogc
{
- return cast(void*) roundUpToAlignment(cast(size_t) _begin, alignment);
+ return _impl.roundedBegin;
}
private void* roundedEnd() const pure nothrow @trusted @nogc
{
- return cast(void*) roundDownToAlignment(cast(size_t) _end, alignment);
+ return _impl.roundedEnd;
}
/**
Constructs a region backed by a user-provided store.
- Assumes the memory was allocated with `ParentAllocator`
- (if different from $(REF_ALTTEXT `NullAllocator`, NullAllocator, std,experimental,allocator,building_blocks,null_allocator)).
+ Assumes the memory was allocated with `ParentAllocator`.
Params:
- store = User-provided store backing up the region. If `ParentAllocator`
- is different from $(REF_ALTTEXT `NullAllocator`, NullAllocator, std,experimental,allocator,building_blocks,null_allocator), memory is assumed to
- have been allocated with `ParentAllocator`.
- n = Bytes to allocate using `ParentAllocator`. This constructor is only
- defined If `ParentAllocator` is different from $(REF_ALTTEXT `NullAllocator`, NullAllocator, std,experimental,allocator,building_blocks,null_allocator). If
- `parent.allocate(n)` returns `null`, the region will be initialized
- as empty (correctly initialized but unable to allocate).
+ store = User-provided store backing up the region. Assumed to have been
+ allocated with `ParentAllocator`.
+ n = Bytes to allocate using `ParentAllocator`. If `parent.allocate(n)`
+ returns `null`, the region will be initialized as empty (correctly
+ initialized but unable to allocate).
*/
this(ubyte[] store) pure nothrow @nogc
{
- _begin = cast(typeof(_begin)) store.ptr;
- _end = cast(typeof(_end)) (store.ptr + store.length);
- static if (growDownwards)
- _current = cast(typeof(_current)) roundedEnd();
- else
- _current = cast(typeof(_current)) roundedBegin();
+ _impl = store;
}
/// Ditto
- static if (!is(ParentAllocator == NullAllocator))
this(size_t n)
{
this(cast(ubyte[]) (parent.allocate(n.roundUpToAlignment(alignment))));
@@ -1065,7 +1239,7 @@ shared struct SharedRegion(ParentAllocator = NullAllocator,
*/
size_t goodAllocSize(size_t n) const pure nothrow @safe @nogc
{
- return n.roundUpToAlignment(alignment);
+ return _impl.goodAllocSize(n);
}
/**
@@ -1086,38 +1260,7 @@ shared struct SharedRegion(ParentAllocator = NullAllocator,
*/
void[] allocate(size_t n) pure nothrow @trusted @nogc
{
- import core.atomic : cas, atomicLoad;
-
- if (n == 0) return null;
- const rounded = goodAllocSize(n);
-
- shared void* localCurrent, localNewCurrent;
- static if (growDownwards)
- {
- do
- {
- localCurrent = atomicLoad(_current);
- localNewCurrent = localCurrent - rounded;
- if (localNewCurrent > localCurrent || localNewCurrent < _begin)
- return null;
- } while (!cas(&_current, localCurrent, localNewCurrent));
-
- return cast(void[]) localNewCurrent[0 .. n];
- }
- else
- {
- do
- {
- localCurrent = atomicLoad(_current);
- localNewCurrent = localCurrent + rounded;
- if (localNewCurrent < localCurrent || localNewCurrent > _end)
- return null;
- } while (!cas(&_current, localCurrent, localNewCurrent));
-
- return cast(void[]) localCurrent[0 .. n];
- }
-
- assert(0, "Unexpected error in SharedRegion.allocate");
+ return _impl.allocate(n);
}
/**
@@ -1131,27 +1274,7 @@ shared struct SharedRegion(ParentAllocator = NullAllocator,
*/
bool deallocate(void[] b) pure nothrow @nogc
{
- import core.atomic : cas, atomicLoad;
-
- const rounded = goodAllocSize(b.length);
- shared void* localCurrent, localNewCurrent;
-
- // The cas is done only once, because only the last allocation can be reverted
- localCurrent = atomicLoad(_current);
- static if (growDownwards)
- {
- localNewCurrent = localCurrent + rounded;
- if (b.ptr == localCurrent)
- return cas(&_current, localCurrent, localNewCurrent);
- }
- else
- {
- localNewCurrent = localCurrent - rounded;
- if (b.ptr == localNewCurrent)
- return cas(&_current, localCurrent, localNewCurrent);
- }
-
- return false;
+ return _impl.deallocate(b);
}
/**
@@ -1160,16 +1283,7 @@ shared struct SharedRegion(ParentAllocator = NullAllocator,
*/
bool deallocateAll() pure nothrow @nogc
{
- import core.atomic : atomicStore;
- static if (growDownwards)
- {
- atomicStore(_current, cast(shared(void*)) roundedEnd());
- }
- else
- {
- atomicStore(_current, cast(shared(void*)) roundedBegin());
- }
- return true;
+ return _impl.deallocateAll;
}
/**
@@ -1183,45 +1297,7 @@ shared struct SharedRegion(ParentAllocator = NullAllocator,
*/
void[] alignedAllocate(size_t n, uint a) pure nothrow @trusted @nogc
{
- import core.atomic : cas, atomicLoad;
- import std.math.traits : isPowerOf2;
-
- assert(a.isPowerOf2);
- if (n == 0) return null;
-
- const rounded = goodAllocSize(n);
- shared void* localCurrent, localNewCurrent;
-
- static if (growDownwards)
- {
- do
- {
- localCurrent = atomicLoad(_current);
- auto alignedCurrent = cast(void*)(localCurrent - rounded);
- localNewCurrent = cast(shared(void*)) alignedCurrent.alignDownTo(a);
- if (alignedCurrent > localCurrent || localNewCurrent > alignedCurrent ||
- localNewCurrent < _begin)
- return null;
- } while (!cas(&_current, localCurrent, localNewCurrent));
-
- return cast(void[]) localNewCurrent[0 .. n];
- }
- else
- {
- do
- {
- localCurrent = atomicLoad(_current);
- auto alignedCurrent = alignUpTo(cast(void*) localCurrent, a);
- localNewCurrent = cast(shared(void*)) (alignedCurrent + rounded);
- if (alignedCurrent < localCurrent || localNewCurrent < alignedCurrent ||
- localNewCurrent > _end)
- return null;
- } while (!cas(&_current, localCurrent, localNewCurrent));
-
- return cast(void[]) (localNewCurrent - rounded)[0 .. n];
- }
-
- assert(0, "Unexpected error in SharedRegion.alignedAllocate");
+ return _impl.alignedAllocate(n, a);
}
/**
@@ -1236,7 +1312,7 @@ shared struct SharedRegion(ParentAllocator = NullAllocator,
*/
Ternary owns(const void[] b) const pure nothrow @trusted @nogc
{
- return Ternary(b && (&b[0] >= _begin) && (&b[0] + b.length <= _end));
+ return _impl.owns(b);
}
/**
@@ -1245,25 +1321,17 @@ shared struct SharedRegion(ParentAllocator = NullAllocator,
*/
Ternary empty() const pure nothrow @safe @nogc
{
- import core.atomic : atomicLoad;
-
- auto localCurrent = atomicLoad(_current);
- static if (growDownwards)
- return Ternary(localCurrent == roundedEnd());
- else
- return Ternary(localCurrent == roundedBegin());
+ return _impl.empty;
}
/**
- If `ParentAllocator` is not $(REF_ALTTEXT `NullAllocator`, NullAllocator, std,experimental,allocator,building_blocks,null_allocator) and defines `deallocate`,
- the region defines a destructor that uses `ParentAllocator.deallocate` to free the
- memory chunk.
+ If `ParentAllocator` defines `deallocate`, the region defines a destructor
+ that uses `ParentAllocator.deallocate` to free the memory chunk.
*/
- static if (!is(ParentAllocator == NullAllocator)
- && hasMember!(ParentAllocator, "deallocate"))
+ static if (hasMember!(ParentAllocator, "deallocate"))
~this()
{
- parent.deallocate(cast(void[]) _begin[0 .. _end - _begin]);
+ with (_impl) parent.deallocate(cast(void[]) _begin[0 .. _end - _begin]);
}
}
@@ -1397,3 +1465,250 @@ shared struct SharedRegion(ParentAllocator = NullAllocator,
testAlloc(a1, true);
testAlloc(a2, false);
}
+
+/**
+A `SharedBorrowedRegion` allocates directly from a user-provided block of memory.
+
+Unlike a `SharedRegion`, a `SharedBorrowedRegion` does not own the memory it
+allocates from and will not deallocate that memory upon destruction. Instead,
+it is the user's responsibility to ensure that the memory is properly disposed
+of.
+
+In all other respects, a `SharedBorrowedRegion` behaves exactly like a `SharedRegion`.
+*/
+shared struct SharedBorrowedRegion(uint minAlign = platformAlignment,
+ Flag!"growDownwards" growDownwards = No.growDownwards)
+{
+ static assert(minAlign.isGoodStaticAlignment);
+
+ import std.typecons : Ternary;
+
+ // state
+ private void* _current, _begin, _end;
+
+ private void* roundedBegin() shared const pure nothrow @trusted @nogc
+ {
+ return cast(void*) roundUpToAlignment(cast(size_t) _begin, alignment);
+ }
+
+ private void* roundedEnd() shared const pure nothrow @trusted @nogc
+ {
+ return cast(void*) roundDownToAlignment(cast(size_t) _end, alignment);
+ }
+
+ /**
+ Constructs a region backed by a user-provided store.
+
+ Params:
+ store = User-provided store backing up the region. Must not be aliased.
+ */
+ this(ubyte[] store) shared pure nothrow @nogc
+ {
+ _begin = cast(typeof(_begin)) store.ptr;
+ _end = cast(typeof(_end)) (store.ptr + store.length);
+ static if (growDownwards)
+ _current = cast(typeof(_current)) roundedEnd();
+ else
+ _current = cast(typeof(_current)) roundedBegin();
+ }
+
+ /*
+ TODO: The postblit of `SharedBorrowedRegion` should be disabled because
+ such objects should not be copied around naively.
+ */
+
+ /**
+ Rounds the given size to a multiple of the `alignment`
+ */
+ size_t goodAllocSize(size_t n) shared const pure nothrow @safe @nogc
+ {
+ return n.roundUpToAlignment(alignment);
+ }
+
+ /**
+ Alignment offered.
+ */
+ alias alignment = minAlign;
+
+ /**
+ Allocates `n` bytes of memory. The allocation is served by atomically incrementing
+ a pointer which keeps track of the current used space.
+
+ Params:
+ n = number of bytes to allocate
+
+ Returns:
+ A properly-aligned buffer of size `n`, or `null` if request could not
+ be satisfied.
+ */
+ void[] allocate(size_t n) shared pure nothrow @trusted @nogc
+ {
+ import core.atomic : cas, atomicLoad;
+
+ if (n == 0) return null;
+ const rounded = goodAllocSize(n);
+
+ shared void* localCurrent, localNewCurrent;
+ static if (growDownwards)
+ {
+ do
+ {
+ localCurrent = atomicLoad(_current);
+ localNewCurrent = localCurrent - rounded;
+ if (localNewCurrent > localCurrent || localNewCurrent < _begin)
+ return null;
+ } while (!cas(&_current, localCurrent, localNewCurrent));
+
+ return cast(void[]) localNewCurrent[0 .. n];
+ }
+ else
+ {
+ do
+ {
+ localCurrent = atomicLoad(_current);
+ localNewCurrent = localCurrent + rounded;
+ if (localNewCurrent < localCurrent || localNewCurrent > _end)
+ return null;
+ } while (!cas(&_current, localCurrent, localNewCurrent));
+
+ return cast(void[]) localCurrent[0 .. n];
+ }
+
+ assert(0, "Unexpected error in SharedBorrowedRegion.allocate");
+ }
+
+ /**
+ Allocates `n` bytes of memory aligned at alignment `a`.
+
+ Params:
+ n = number of bytes to allocate
+ a = alignment for the allocated block
+
+ Returns:
+ Either a suitable block of `n` bytes aligned at `a`, or `null`.
+ */
+ void[] alignedAllocate(size_t n, uint a) shared pure nothrow @trusted @nogc
+ {
+ import core.atomic : cas, atomicLoad;
+ import std.math.traits : isPowerOf2;
+
+ assert(a.isPowerOf2);
+ if (n == 0) return null;
+
+ const rounded = goodAllocSize(n);
+ shared void* localCurrent, localNewCurrent;
+
+ static if (growDownwards)
+ {
+ do
+ {
+ localCurrent = atomicLoad(_current);
+ auto alignedCurrent = cast(void*)(localCurrent - rounded);
+ localNewCurrent = cast(shared(void*)) alignedCurrent.alignDownTo(a);
+ if (alignedCurrent > localCurrent || localNewCurrent > alignedCurrent ||
+ localNewCurrent < _begin)
+ return null;
+ } while (!cas(&_current, localCurrent, localNewCurrent));
+
+ return cast(void[]) localNewCurrent[0 .. n];
+ }
+ else
+ {
+ do
+ {
+ localCurrent = atomicLoad(_current);
+ auto alignedCurrent = alignUpTo(cast(void*) localCurrent, a);
+ localNewCurrent = cast(shared(void*)) (alignedCurrent + rounded);
+ if (alignedCurrent < localCurrent || localNewCurrent < alignedCurrent ||
+ localNewCurrent > _end)
+ return null;
+ } while (!cas(&_current, localCurrent, localNewCurrent));
+
+ return cast(void[]) (localNewCurrent - rounded)[0 .. n];
+ }
+
+ assert(0, "Unexpected error in SharedBorrowedRegion.alignedAllocate");
+ }
+
+ /**
+ Deallocates `b`. This works only if `b` was obtained as the last call
+ to `allocate`; otherwise (i.e. another allocation has occurred since) it
+ does nothing.
+
+ Params:
+ b = Block previously obtained by a call to `allocate` against this
+ allocator (`null` is allowed).
+ */
+ bool deallocate(void[] b) shared pure nothrow @nogc
+ {
+ import core.atomic : cas, atomicLoad;
+
+ const rounded = goodAllocSize(b.length);
+ shared void* localCurrent, localNewCurrent;
+
+ // The cas is done only once, because only the last allocation can be reverted
+ localCurrent = atomicLoad(_current);
+ static if (growDownwards)
+ {
+ localNewCurrent = localCurrent + rounded;
+ if (b.ptr == localCurrent)
+ return cas(&_current, localCurrent, localNewCurrent);
+ }
+ else
+ {
+ localNewCurrent = localCurrent - rounded;
+ if (b.ptr == localNewCurrent)
+ return cas(&_current, localCurrent, localNewCurrent);
+ }
+
+ return false;
+ }
+
+ /**
+ Deallocates all memory allocated by this region, which can be subsequently
+ reused for new allocations.
+ */
+ bool deallocateAll() shared pure nothrow @nogc
+ {
+ import core.atomic : atomicStore;
+ static if (growDownwards)
+ {
+ atomicStore(_current, cast(shared(void*)) roundedEnd());
+ }
+ else
+ {
+ atomicStore(_current, cast(shared(void*)) roundedBegin());
+ }
+ return true;
+ }
+
+ /**
+ Queries whether `b` has been allocated with this region.
+
+ Params:
+ b = Arbitrary block of memory (`null` is allowed; `owns(null)` returns
+ `false`).
+
+ Returns:
+ `true` if `b` has been allocated with this region, `false` otherwise.
+ */
+ Ternary owns(const void[] b) shared const pure nothrow @trusted @nogc
+ {
+ return Ternary(b && (&b[0] >= _begin) && (&b[0] + b.length <= _end));
+ }
+
+ /**
+ Returns `Ternary.yes` if no memory has been allocated in this region,
+ `Ternary.no` otherwise. (Never returns `Ternary.unknown`.)
+ */
+ Ternary empty() shared const pure nothrow @safe @nogc
+ {
+ import core.atomic : atomicLoad;
+
+ auto localCurrent = atomicLoad(_current);
+ static if (growDownwards)
+ return Ternary(localCurrent == roundedEnd());
+ else
+ return Ternary(localCurrent == roundedBegin());
+ }
+}
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/scoped_allocator.d b/libphobos/src/std/experimental/allocator/building_blocks/scoped_allocator.d
index 8fc7584..96859b0 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/scoped_allocator.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/scoped_allocator.d
@@ -259,10 +259,10 @@ version (StdUnittest)
// Test that deallocateAll infers from parent
@system unittest
{
- import std.experimental.allocator.building_blocks.region : Region;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
- ScopedAllocator!(Region!()) a;
- a.parent.parent = Region!()(new ubyte[1024 * 64]);
+ ScopedAllocator!(BorrowedRegion!()) a;
+ a.parent.parent = BorrowedRegion!()(new ubyte[1024 * 64]);
auto b = a.allocate(42);
assert(b.length == 42);
assert((() pure nothrow @safe @nogc => a.expand(b, 22))());
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/segregator.d b/libphobos/src/std/experimental/allocator/building_blocks/segregator.d
index 655db456..ff089bd 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/segregator.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/segregator.d
@@ -503,12 +503,12 @@ if (Args.length > 3)
@system unittest
{
- import std.experimental.allocator.building_blocks.region : Region;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
import std.typecons : Ternary;
- auto a = Segregator!(10_240, Region!(), Region!())(
- Region!()(new ubyte[4096 * 1024]),
- Region!()(new ubyte[4096 * 1024]));
+ auto a = Segregator!(10_240, BorrowedRegion!(), BorrowedRegion!())(
+ BorrowedRegion!()(new ubyte[4096 * 1024]),
+ BorrowedRegion!()(new ubyte[4096 * 1024]));
assert((() nothrow @safe @nogc => a.empty)() == Ternary.yes);
auto b = a.alignedAllocate(42, 8);
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/stats_collector.d b/libphobos/src/std/experimental/allocator/building_blocks/stats_collector.d
index d57b3ed..3770af1 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/stats_collector.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/stats_collector.d
@@ -845,9 +845,9 @@ public:
@system unittest
{
- import std.experimental.allocator.building_blocks.region : Region;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
- auto a = StatsCollector!(Region!(), Options.all, Options.all)(Region!()(new ubyte[1024 * 64]));
+ auto a = StatsCollector!(BorrowedRegion!(), Options.all, Options.all)(BorrowedRegion!()(new ubyte[1024 * 64]));
auto b = a.allocate(42);
assert(b.length == 42);
// Test that reallocate infers from parent
@@ -859,9 +859,9 @@ public:
@system unittest
{
- import std.experimental.allocator.building_blocks.region : Region;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
- auto a = StatsCollector!(Region!(), Options.all)(Region!()(new ubyte[1024 * 64]));
+ auto a = StatsCollector!(BorrowedRegion!(), Options.all)(BorrowedRegion!()(new ubyte[1024 * 64]));
auto b = a.alignedAllocate(42, 128);
assert(b.length == 42);
assert(b.ptr.alignedAt(128));
diff --git a/libphobos/src/std/experimental/allocator/package.d b/libphobos/src/std/experimental/allocator/package.d
index 62f848f..2177926 100644
--- a/libphobos/src/std/experimental/allocator/package.d
+++ b/libphobos/src/std/experimental/allocator/package.d
@@ -547,24 +547,24 @@ nothrow:
@system unittest
{
- import std.experimental.allocator.building_blocks.region : Region;
+ import std.experimental.allocator.building_blocks.region : BorrowedRegion;
import std.conv : emplace;
- auto reg = Region!()(new ubyte[1024]);
- auto state = reg.allocate(stateSize!(CAllocatorImpl!(Region!(), Yes.indirect)));
- auto regObj = emplace!(CAllocatorImpl!(Region!(), Yes.indirect))(state, &reg);
+ auto reg = BorrowedRegion!()(new ubyte[1024]);
+ auto state = reg.allocate(stateSize!(CAllocatorImpl!(BorrowedRegion!(), Yes.indirect)));
+ auto regObj = emplace!(CAllocatorImpl!(BorrowedRegion!(), Yes.indirect))(state, &reg);
auto rcalloc = RCIAllocator(regObj);
auto b = rcalloc.allocate(10);
assert(b.length == 10);
// The reference counting is zero based
- assert((cast(CAllocatorImpl!(Region!(), Yes.indirect))(rcalloc._alloc)).rc == 1);
+ assert((cast(CAllocatorImpl!(BorrowedRegion!(), Yes.indirect))(rcalloc._alloc)).rc == 1);
{
auto rca2 = rcalloc;
- assert((cast(CAllocatorImpl!(Region!(), Yes.indirect))(rcalloc._alloc)).rc == 2);
+ assert((cast(CAllocatorImpl!(BorrowedRegion!(), Yes.indirect))(rcalloc._alloc)).rc == 2);
}
- assert((cast(CAllocatorImpl!(Region!(), Yes.indirect))(rcalloc._alloc)).rc == 1);
+ assert((cast(CAllocatorImpl!(BorrowedRegion!(), Yes.indirect))(rcalloc._alloc)).rc == 1);
}
@system unittest
diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d
index d6cac41..8957089 100644
--- a/libphobos/src/std/file.d
+++ b/libphobos/src/std/file.d
@@ -3714,7 +3714,7 @@ assert(!de2.isFile);
@property bool isSymlink() scope;
/++
- Returns the size of the the file represented by this `DirEntry`
+ Returns the size of the file represented by this `DirEntry`
in bytes.
+/
@property ulong size() scope;
diff --git a/libphobos/src/std/format/package.d b/libphobos/src/std/format/package.d
index 3f6f33a..d83f028 100644
--- a/libphobos/src/std/format/package.d
+++ b/libphobos/src/std/format/package.d
@@ -550,7 +550,7 @@ License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
Authors: $(HTTP walterbright.com, Walter Bright), $(HTTP erdani.com,
Andrei Alexandrescu), and Kenji Hara
-Source: $(PHOBOSSRC std/format.d)
+Source: $(PHOBOSSRC std/format/package.d)
*/
module std.format;
diff --git a/libphobos/src/std/internal/math/gammafunction.d b/libphobos/src/std/internal/math/gammafunction.d
index 7f72234..703ecb1 100644
--- a/libphobos/src/std/internal/math/gammafunction.d
+++ b/libphobos/src/std/internal/math/gammafunction.d
@@ -631,7 +631,7 @@ enum real BETA_BIGINV = 1.084202172485504434007e-19L;
* betaIncomplete(a, b, x) = &Gamma;(a+b)/(&Gamma;(a) &Gamma;(b)) *
* $(INTEGRATE 0, x) $(POWER t, a-1)$(POWER (1-t),b-1) dt
*
- * and is the same as the the cumulative distribution function.
+ * and is the same as the cumulative distribution function.
*
* The domain of definition is 0 <= x <= 1. In this
* implementation a and b are restricted to positive values.
diff --git a/libphobos/src/std/logger/core.d b/libphobos/src/std/logger/core.d
index be2bd8d..846f6ee 100644
--- a/libphobos/src/std/logger/core.d
+++ b/libphobos/src/std/logger/core.d
@@ -704,7 +704,7 @@ abstract class Logger
/** This template provides the log functions for the `Logger` `class`
with the `LogLevel` encoded in the function name.
- For further information see the the two functions defined inside of this
+ For further information see the two functions defined inside of this
template.
The aliases following this template create the public names of these log
@@ -1446,7 +1446,7 @@ that the returned reference is only a current snapshot and in the following
code, you must make sure no other thread reassigns to it between reading and
writing `sharedLog`.
-`sharedLog` is only thread-safe if the the used `Logger` is thread-safe.
+`sharedLog` is only thread-safe if the used `Logger` is thread-safe.
The default `Logger` is thread-safe.
-------------
if (sharedLog !is myLogger)
@@ -1559,10 +1559,21 @@ class StdForwardLogger : Logger
}
}
+ auto oldSharedLog = sharedLog;
+
sharedLog = new shared RaceLogger;
- scope(exit) { sharedLog = null; }
- () @trusted { new Thread(() { log("foo"); }).start(); }();
+ scope(exit)
+ {
+ sharedLog = oldSharedLog;
+ }
+ Thread toWaitFor;
+ () @trusted { toWaitFor = new Thread(() { log("foo"); }).start(); }();
log("bar");
+
+ () @trusted
+ {
+ toWaitFor.join();
+ }();
}
/** This `LogLevel` is unqiue to every thread.
@@ -1897,7 +1908,7 @@ version (StdUnittest) private void testFuncNames(Logger logger) @safe
assertThrown!Throwable(logf(LogLevel.fatal, msg, "Yet"));
} ();
lineNumber = __LINE__ - 2;
- assert(l.msg == msg.format("Yet"));
+ assert(l.msg == msg.format("Yet"), l.msg);
assert(l.line == lineNumber);
assert(l.logLevel == LogLevel.all);
diff --git a/libphobos/src/std/net/curl.d b/libphobos/src/std/net/curl.d
index 7ea2ceb..2318279 100644
--- a/libphobos/src/std/net/curl.d
+++ b/libphobos/src/std/net/curl.d
@@ -1973,7 +1973,7 @@ private mixin template Protocol()
}
/**
- * The network interface to use in form of the the IP of the interface.
+ * The network interface to use in form of the IP of the interface.
*
* Example:
* ----
@@ -2706,7 +2706,7 @@ struct HTTP
@property void dnsTimeout(Duration d);
/**
- * The network interface to use in form of the the IP of the interface.
+ * The network interface to use in form of the IP of the interface.
*
* Example:
* ----
@@ -3486,7 +3486,7 @@ struct FTP
@property void dnsTimeout(Duration d);
/**
- * The network interface to use in form of the the IP of the interface.
+ * The network interface to use in form of the IP of the interface.
*
* Example:
* ----
@@ -3912,7 +3912,7 @@ struct SMTP
@property void dnsTimeout(Duration d);
/**
- * The network interface to use in form of the the IP of the interface.
+ * The network interface to use in form of the IP of the interface.
*
* Example:
* ----
diff --git a/libphobos/src/std/numeric.d b/libphobos/src/std/numeric.d
index 96d20c2..df7ac39 100644
--- a/libphobos/src/std/numeric.d
+++ b/libphobos/src/std/numeric.d
@@ -1124,8 +1124,8 @@ public:
*
* References: "On Enclosing Simple Roots of Nonlinear Equations",
* G. Alefeld, F.A. Potra, Yixun Shi, Mathematics of Computation 61,
- * pp733-744 (1993). Fortran code available from $(HTTP
- * www.netlib.org,www.netlib.org) as algorithm TOMS478.
+ * pp733-744 (1993). Fortran code available from
+ * $(HTTP www.netlib.org,www.netlib.org) as algorithm TOMS478.
*
*/
T findRoot(T, DF, DT)(scope DF f, const T a, const T b,
diff --git a/libphobos/src/std/path.d b/libphobos/src/std/path.d
index de180fc..4b5a7ef 100644
--- a/libphobos/src/std/path.d
+++ b/libphobos/src/std/path.d
@@ -3357,8 +3357,10 @@ in
{
// Verify that pattern[] is valid
import std.algorithm.searching : balancedParens;
- assert(balancedParens(pattern, '[', ']', 0));
- assert(balancedParens(pattern, '{', '}', 0));
+ import std.utf : byUTF;
+
+ assert(balancedParens(pattern.byUTF!C, '[', ']', 0));
+ assert(balancedParens(pattern.byUTF!C, '{', '}', 0));
}
do
{
@@ -3959,7 +3961,7 @@ string expandTilde(string inputPath) @safe nothrow
version (Posix)
{
import core.exception : onOutOfMemoryError;
- import core.stdc.errno : errno, ERANGE;
+ import core.stdc.errno : errno, EBADF, ENOENT, EPERM, ERANGE, ESRCH;
import core.stdc.stdlib : malloc, free, realloc;
/* Joins a path from a C string to the remainder of path.
@@ -4065,7 +4067,7 @@ string expandTilde(string inputPath) @safe nothrow
char[] extra_memory;
passwd result;
- while (1)
+ loop: while (1)
{
extra_memory.length += extra_memory_size;
@@ -4088,10 +4090,23 @@ string expandTilde(string inputPath) @safe nothrow
break;
}
- if (errno != ERANGE &&
+ switch (errno)
+ {
+ case ERANGE:
// On BSD and OSX, errno can be left at 0 instead of set to ERANGE
- errno != 0)
- onOutOfMemoryError();
+ case 0:
+ break;
+
+ case ENOENT:
+ case ESRCH:
+ case EBADF:
+ case EPERM:
+ // The given name or uid was not found.
+ break loop;
+
+ default:
+ onOutOfMemoryError();
+ }
// extra_memory isn't large enough
import core.checkedint : mulu;
diff --git a/libphobos/src/std/range/primitives.d b/libphobos/src/std/range/primitives.d
index 31f58fa..cdab401 100644
--- a/libphobos/src/std/range/primitives.d
+++ b/libphobos/src/std/range/primitives.d
@@ -172,7 +172,7 @@ Returns:
enum bool isInputRange(R) =
is(typeof(R.init) == R)
&& is(ReturnType!((R r) => r.empty) == bool)
- && is(typeof((return ref R r) => r.front))
+ && (is(typeof((return ref R r) => r.front)) || is(typeof(ref (return ref R r) => r.front)))
&& !is(ReturnType!((R r) => r.front) == void)
&& is(typeof((R r) => r.popFront));
@@ -227,6 +227,17 @@ enum bool isInputRange(R) =
}
static assert(!isInputRange!VoidFront);
}
+// https://issues.dlang.org/show_bug.cgi?id=16034
+@safe unittest
+{
+ struct One
+ {
+ int entry = 1;
+ @disable this(this);
+ }
+
+ assert(isInputRange!(One[]));
+}
@safe unittest
{
diff --git a/libphobos/src/std/socket.d b/libphobos/src/std/socket.d
index 6ec7985..fb2c2d4 100644
--- a/libphobos/src/std/socket.d
+++ b/libphobos/src/std/socket.d
@@ -2942,7 +2942,7 @@ public:
* Calling `shutdown` before `close` is recommended
* for connection-oriented sockets.
*/
- void close() @trusted nothrow @nogc
+ void close() scope @trusted nothrow @nogc
{
_close(sock);
sock = socket_t.init;
@@ -3641,7 +3641,7 @@ class UdpSocket: Socket
{
checkAttributes!q{nothrow @nogc @trusted};
}
- nothrow @nogc @trusted void close()
+ nothrow @nogc @trusted scope void close()
{
checkAttributes!q{nothrow @nogc @trusted};
}
diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d
index a1fe962..cd1a356 100644
--- a/libphobos/src/std/stdio.d
+++ b/libphobos/src/std/stdio.d
@@ -85,8 +85,7 @@ else version (CRuntime_Musl)
}
else version (CRuntime_UClibc)
{
- // uClibc supports GCC IO
- version = GCC_IO;
+ version = GENERIC_IO;
}
else version (OSX)
{
@@ -589,7 +588,7 @@ Throws: `ErrnoException` if the file could not be opened.
detach();
}
- this(this) @safe nothrow
+ this(this) @safe pure nothrow @nogc
{
if (!_p) return;
assert(atomicLoad(_p.refs));
diff --git a/libphobos/src/std/sumtype.d b/libphobos/src/std/sumtype.d
index 160665c..ee2d73a 100644
--- a/libphobos/src/std/sumtype.d
+++ b/libphobos/src/std/sumtype.d
@@ -753,23 +753,6 @@ public:
}
}
- invariant
- {
- this.match!((ref value) {
- static if (is(typeof(value) == class))
- {
- if (value !is null)
- {
- assert(value);
- }
- }
- else static if (is(typeof(value) == struct))
- {
- assert(&value);
- }
- });
- }
-
// Workaround for https://issues.dlang.org/show_bug.cgi?id=21400
version (StdDdoc)
{
@@ -1330,36 +1313,6 @@ version (D_BetterC) {} else
}));
}
-// Types with invariants
-// Disabled in BetterC due to use of exceptions
-version (D_BetterC) {} else
-version (D_Invariants)
-@system unittest
-{
- import std.exception : assertThrown;
- import core.exception : AssertError;
-
- struct S
- {
- int i;
- invariant { assert(i >= 0); }
- }
-
- class C
- {
- int i;
- invariant { assert(i >= 0); }
- }
-
- SumType!S x;
- x.match!((ref v) { v.i = -1; });
- assertThrown!AssertError(assert(&x));
-
- SumType!C y = new C();
- y.match!((ref v) { v.i = -1; });
- assertThrown!AssertError(assert(&y));
-}
-
// Calls value postblit on self-assignment
@safe unittest
{
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index c7cdc24..094628b 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -3793,8 +3793,28 @@ Params:
sink.formatValue(_value, fmt);
}
}
+
+ void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt) const
+ {
+ if (isNull)
+ {
+ sink.formatValue("Nullable.null", fmt);
+ }
+ else
+ {
+ sink.formatValue(_value, fmt);
+ }
+ }
}
+@system unittest
+{
+ import std.conv : to;
+
+ const Nullable!(ulong, 0) x = 1;
+ assert(x.to!string == "1");
+}
+
/**
Check if `this` is in the null state.
@@ -4320,8 +4340,28 @@ Params:
sink.formatValue(*_value, fmt);
}
}
+
+ void toString()(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt) const
+ {
+ if (isNull)
+ {
+ sink.formatValue("Nullable.null", fmt);
+ }
+ else
+ {
+ sink.formatValue(*_value, fmt);
+ }
+ }
}
+@system unittest
+{
+ import std.conv : to;
+
+ const NullableRef!(ulong) x = new ulong(1);
+ assert(x.to!string == "1");
+}
+
/**
Binds the internal state to `value`.
diff --git a/libphobos/src/std/uni/package.d b/libphobos/src/std/uni/package.d
index e12a70c..8a032aa 100644
--- a/libphobos/src/std/uni/package.d
+++ b/libphobos/src/std/uni/package.d
@@ -426,7 +426,7 @@ $(TR $(TD Building blocks) $(TD
$(SECTION Construction of lookup tables)
$(P The Unicode standard describes a set of algorithms that
depend on having the ability to quickly look up various properties
- of a code point. Given the the codespace of about 1 million $(CODEPOINTS),
+ of a code point. Given the codespace of about 1 million $(CODEPOINTS),
it is not a trivial task to provide a space-efficient solution for
the multitude of properties.
)
diff --git a/libphobos/src/std/utf.d b/libphobos/src/std/utf.d
index d22dac8..8d94e12 100644
--- a/libphobos/src/std/utf.d
+++ b/libphobos/src/std/utf.d
@@ -3571,7 +3571,7 @@ enum dchar replacementDchar = '\uFFFD';
* of characters (including strings) or a type that implicitly converts to a string type.
* Returns:
* If `r` is not an auto-decodable string (i.e. a narrow string or a
- * user-defined type that implicits converts to a string type), then `r`
+ * user-defined type that implicitly converts to a string type), then `r`
* is returned.
*
* Otherwise, `r` is converted to its corresponding string type (if it's
diff --git a/libphobos/src/std/xml.d b/libphobos/src/std/xml.d
deleted file mode 100644
index fdfdc3f..0000000
--- a/libphobos/src/std/xml.d
+++ /dev/null
@@ -1,3113 +0,0 @@
-// Written in the D programming language.
-
-/**
-$(RED Warning: This module is considered out-dated and not up to Phobos'
- current standards. It will be removed from Phobos in 2.101.0.
- If you still need it, go to $(LINK https://github.com/DigitalMars/undeaD))
- */
-
-/*
-Classes and functions for creating and parsing XML
-
-The basic architecture of this module is that there are standalone functions,
-classes for constructing an XML document from scratch (Tag, Element and
-Document), and also classes for parsing a pre-existing XML file (ElementParser
-and DocumentParser). The parsing classes <i>may</i> be used to build a
-Document, but that is not their primary purpose. The handling capabilities of
-DocumentParser and ElementParser are sufficiently customizable that you can
-make them do pretty much whatever you want.
-
-Example: This example creates a DOM (Document Object Model) tree
- from an XML file.
-------------------------------------------------------------------------------
-import std.xml;
-import std.stdio;
-import std.string;
-import std.file;
-
-// books.xml is used in various samples throughout the Microsoft XML Core
-// Services (MSXML) SDK.
-//
-// See http://msdn2.microsoft.com/en-us/library/ms762271(VS.85).aspx
-
-void main()
-{
- string s = cast(string) std.file.read("books.xml");
-
- // Check for well-formedness
- check(s);
-
- // Make a DOM tree
- auto doc = new Document(s);
-
- // Plain-print it
- writeln(doc);
-}
-------------------------------------------------------------------------------
-
-Example: This example does much the same thing, except that the file is
- deconstructed and reconstructed by hand. This is more work, but the
- techniques involved offer vastly more power.
-------------------------------------------------------------------------------
-import std.xml;
-import std.stdio;
-import std.string;
-
-struct Book
-{
- string id;
- string author;
- string title;
- string genre;
- string price;
- string pubDate;
- string description;
-}
-
-void main()
-{
- string s = cast(string) std.file.read("books.xml");
-
- // Check for well-formedness
- check(s);
-
- // Take it apart
- Book[] books;
-
- auto xml = new DocumentParser(s);
- xml.onStartTag["book"] = (ElementParser xml)
- {
- Book book;
- book.id = xml.tag.attr["id"];
-
- xml.onEndTag["author"] = (in Element e) { book.author = e.text(); };
- xml.onEndTag["title"] = (in Element e) { book.title = e.text(); };
- xml.onEndTag["genre"] = (in Element e) { book.genre = e.text(); };
- xml.onEndTag["price"] = (in Element e) { book.price = e.text(); };
- xml.onEndTag["publish-date"] = (in Element e) { book.pubDate = e.text(); };
- xml.onEndTag["description"] = (in Element e) { book.description = e.text(); };
-
- xml.parse();
-
- books ~= book;
- };
- xml.parse();
-
- // Put it back together again;
- auto doc = new Document(new Tag("catalog"));
- foreach (book;books)
- {
- auto element = new Element("book");
- element.tag.attr["id"] = book.id;
-
- element ~= new Element("author", book.author);
- element ~= new Element("title", book.title);
- element ~= new Element("genre", book.genre);
- element ~= new Element("price", book.price);
- element ~= new Element("publish-date",book.pubDate);
- element ~= new Element("description", book.description);
-
- doc ~= element;
- }
-
- // Pretty-print it
- writefln(join(doc.pretty(3),"\n"));
-}
--------------------------------------------------------------------------------
-Copyright: Copyright Janice Caron 2008 - 2009.
-License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
-Authors: Janice Caron
-Source: $(PHOBOSSRC std/xml.d)
-*/
-/*
- Copyright Janice Caron 2008 - 2009.
-Distributed under the Boost Software License, Version 1.0.
- (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt)
-*/
-deprecated("Will be removed from Phobos in 2.101.0. If you still need it, go to https://github.com/DigitalMars/undeaD")
-module std.xml;
-
-enum cdata = "<![CDATA[";
-
-/*
- * Returns true if the character is a character according to the XML standard
- *
- * Standards: $(LINK2 http://www.w3.org/TR/1998/REC-xml-19980210, XML 1.0)
- *
- * Params:
- * c = the character to be tested
- */
-bool isChar(dchar c) @safe @nogc pure nothrow // rule 2
-{
- if (c <= 0xD7FF)
- {
- if (c >= 0x20)
- return true;
- switch (c)
- {
- case 0xA:
- case 0x9:
- case 0xD:
- return true;
- default:
- return false;
- }
- }
- else if (0xE000 <= c && c <= 0x10FFFF)
- {
- if ((c & 0x1FFFFE) != 0xFFFE) // U+FFFE and U+FFFF
- return true;
- }
- return false;
-}
-
-@safe @nogc nothrow pure unittest
-{
- assert(!isChar(cast(dchar) 0x8));
- assert( isChar(cast(dchar) 0x9));
- assert( isChar(cast(dchar) 0xA));
- assert(!isChar(cast(dchar) 0xB));
- assert(!isChar(cast(dchar) 0xC));
- assert( isChar(cast(dchar) 0xD));
- assert(!isChar(cast(dchar) 0xE));
- assert(!isChar(cast(dchar) 0x1F));
- assert( isChar(cast(dchar) 0x20));
- assert( isChar('J'));
- assert( isChar(cast(dchar) 0xD7FF));
- assert(!isChar(cast(dchar) 0xD800));
- assert(!isChar(cast(dchar) 0xDFFF));
- assert( isChar(cast(dchar) 0xE000));
- assert( isChar(cast(dchar) 0xFFFD));
- assert(!isChar(cast(dchar) 0xFFFE));
- assert(!isChar(cast(dchar) 0xFFFF));
- assert( isChar(cast(dchar) 0x10000));
- assert( isChar(cast(dchar) 0x10FFFF));
- assert(!isChar(cast(dchar) 0x110000));
-
- debug (stdxml_TestHardcodedChecks)
- {
- foreach (c; 0 .. dchar.max + 1)
- assert(isChar(c) == lookup(CharTable, c));
- }
-}
-
-/*
- * Returns true if the character is whitespace according to the XML standard
- *
- * Only the following characters are considered whitespace in XML - space, tab,
- * carriage return and linefeed
- *
- * Standards: $(LINK2 http://www.w3.org/TR/1998/REC-xml-19980210, XML 1.0)
- *
- * Params:
- * c = the character to be tested
- */
-bool isSpace(dchar c) @safe @nogc pure nothrow
-{
- return c == '\u0020' || c == '\u0009' || c == '\u000A' || c == '\u000D';
-}
-
-/*
- * Returns true if the character is a digit according to the XML standard
- *
- * Standards: $(LINK2 http://www.w3.org/TR/1998/REC-xml-19980210, XML 1.0)
- *
- * Params:
- * c = the character to be tested
- */
-bool isDigit(dchar c) @safe @nogc pure nothrow
-{
- if (c <= 0x0039 && c >= 0x0030)
- return true;
- else
- return lookup(DigitTable,c);
-}
-
-@safe @nogc nothrow pure unittest
-{
- debug (stdxml_TestHardcodedChecks)
- {
- foreach (c; 0 .. dchar.max + 1)
- assert(isDigit(c) == lookup(DigitTable, c));
- }
-}
-
-/*
- * Returns true if the character is a letter according to the XML standard
- *
- * Standards: $(LINK2 http://www.w3.org/TR/1998/REC-xml-19980210, XML 1.0)
- *
- * Params:
- * c = the character to be tested
- */
-bool isLetter(dchar c) @safe @nogc nothrow pure // rule 84
-{
- return isIdeographic(c) || isBaseChar(c);
-}
-
-/*
- * Returns true if the character is an ideographic character according to the
- * XML standard
- *
- * Standards: $(LINK2 http://www.w3.org/TR/1998/REC-xml-19980210, XML 1.0)
- *
- * Params:
- * c = the character to be tested
- */
-bool isIdeographic(dchar c) @safe @nogc nothrow pure
-{
- if (c == 0x3007)
- return true;
- if (c <= 0x3029 && c >= 0x3021 )
- return true;
- if (c <= 0x9FA5 && c >= 0x4E00)
- return true;
- return false;
-}
-
-@safe @nogc nothrow pure unittest
-{
- assert(isIdeographic('\u4E00'));
- assert(isIdeographic('\u9FA5'));
- assert(isIdeographic('\u3007'));
- assert(isIdeographic('\u3021'));
- assert(isIdeographic('\u3029'));
-
- debug (stdxml_TestHardcodedChecks)
- {
- foreach (c; 0 .. dchar.max + 1)
- assert(isIdeographic(c) == lookup(IdeographicTable, c));
- }
-}
-
-/*
- * Returns true if the character is a base character according to the XML
- * standard
- *
- * Standards: $(LINK2 http://www.w3.org/TR/1998/REC-xml-19980210, XML 1.0)
- *
- * Params:
- * c = the character to be tested
- */
-bool isBaseChar(dchar c) @safe @nogc nothrow pure
-{
- return lookup(BaseCharTable,c);
-}
-
-/*
- * Returns true if the character is a combining character according to the
- * XML standard
- *
- * Standards: $(LINK2 http://www.w3.org/TR/1998/REC-xml-19980210, XML 1.0)
- *
- * Params:
- * c = the character to be tested
- */
-bool isCombiningChar(dchar c) @safe @nogc nothrow pure
-{
- return lookup(CombiningCharTable,c);
-}
-
-/*
- * Returns true if the character is an extender according to the XML standard
- *
- * Standards: $(LINK2 http://www.w3.org/TR/1998/REC-xml-19980210, XML 1.0)
- *
- * Params:
- * c = the character to be tested
- */
-bool isExtender(dchar c) @safe @nogc nothrow pure
-{
- return lookup(ExtenderTable,c);
-}
-
-/*
- * Encodes a string by replacing all characters which need to be escaped with
- * appropriate predefined XML entities.
- *
- * encode() escapes certain characters (ampersand, quote, apostrophe, less-than
- * and greater-than), and similarly, decode() unescapes them. These functions
- * are provided for convenience only. You do not need to use them when using
- * the std.xml classes, because then all the encoding and decoding will be done
- * for you automatically.
- *
- * If the string is not modified, the original will be returned.
- *
- * Standards: $(LINK2 http://www.w3.org/TR/1998/REC-xml-19980210, XML 1.0)
- *
- * Params:
- * s = The string to be encoded
- *
- * Returns: The encoded string
- *
- * Example:
- * --------------
- * writefln(encode("a > b")); // writes "a &gt; b"
- * --------------
- */
-S encode(S)(S s)
-{
- import std.array : appender;
-
- string r;
- size_t lastI;
- auto result = appender!S();
-
- foreach (i, c; s)
- {
- switch (c)
- {
- case '&': r = "&amp;"; break;
- case '"': r = "&quot;"; break;
- case '\'': r = "&apos;"; break;
- case '<': r = "&lt;"; break;
- case '>': r = "&gt;"; break;
- default: continue;
- }
- // Replace with r
- result.put(s[lastI .. i]);
- result.put(r);
- lastI = i + 1;
- }
-
- if (!result.data.ptr) return s;
- result.put(s[lastI .. $]);
- return result.data;
-}
-
-@safe pure unittest
-{
- auto s = "hello";
- assert(encode(s) is s);
- assert(encode("a > b") == "a &gt; b", encode("a > b"));
- assert(encode("a < b") == "a &lt; b");
- assert(encode("don't") == "don&apos;t");
- assert(encode("\"hi\"") == "&quot;hi&quot;", encode("\"hi\""));
- assert(encode("cat & dog") == "cat &amp; dog");
-}
-
-/*
- * Mode to use for decoding.
- *
- * $(DDOC_ENUM_MEMBERS NONE) Do not decode
- * $(DDOC_ENUM_MEMBERS LOOSE) Decode, but ignore errors
- * $(DDOC_ENUM_MEMBERS STRICT) Decode, and throw exception on error
- */
-enum DecodeMode
-{
- NONE, LOOSE, STRICT
-}
-
-/*
- * Decodes a string by unescaping all predefined XML entities.
- *
- * encode() escapes certain characters (ampersand, quote, apostrophe, less-than
- * and greater-than), and similarly, decode() unescapes them. These functions
- * are provided for convenience only. You do not need to use them when using
- * the std.xml classes, because then all the encoding and decoding will be done
- * for you automatically.
- *
- * This function decodes the entities &amp;amp;, &amp;quot;, &amp;apos;,
- * &amp;lt; and &amp;gt,
- * as well as decimal and hexadecimal entities such as &amp;#x20AC;
- *
- * If the string does not contain an ampersand, the original will be returned.
- *
- * Note that the "mode" parameter can be one of DecodeMode.NONE (do not
- * decode), DecodeMode.LOOSE (decode, but ignore errors), or DecodeMode.STRICT
- * (decode, and throw a DecodeException in the event of an error).
- *
- * Standards: $(LINK2 http://www.w3.org/TR/1998/REC-xml-19980210, XML 1.0)
- *
- * Params:
- * s = The string to be decoded
- * mode = (optional) Mode to use for decoding. (Defaults to LOOSE).
- *
- * Throws: DecodeException if mode == DecodeMode.STRICT and decode fails
- *
- * Returns: The decoded string
- *
- * Example:
- * --------------
- * writefln(decode("a &gt; b")); // writes "a > b"
- * --------------
- */
-string decode(string s, DecodeMode mode=DecodeMode.LOOSE) @safe pure
-{
- import std.algorithm.searching : startsWith;
-
- if (mode == DecodeMode.NONE) return s;
-
- string buffer;
- foreach (ref i; 0 .. s.length)
- {
- char c = s[i];
- if (c != '&')
- {
- if (buffer.length != 0) buffer ~= c;
- }
- else
- {
- if (buffer.length == 0)
- {
- buffer = s[0 .. i].dup;
- }
- if (startsWith(s[i..$],"&#"))
- {
- try
- {
- dchar d;
- string t = s[i..$];
- checkCharRef(t, d);
- char[4] temp;
- import std.utf : encode;
- buffer ~= temp[0 .. encode(temp, d)];
- i = s.length - t.length - 1;
- }
- catch (Err e)
- {
- if (mode == DecodeMode.STRICT)
- throw new DecodeException("Unescaped &");
- buffer ~= '&';
- }
- }
- else if (startsWith(s[i..$],"&amp;" )) { buffer ~= '&'; i += 4; }
- else if (startsWith(s[i..$],"&quot;")) { buffer ~= '"'; i += 5; }
- else if (startsWith(s[i..$],"&apos;")) { buffer ~= '\''; i += 5; }
- else if (startsWith(s[i..$],"&lt;" )) { buffer ~= '<'; i += 3; }
- else if (startsWith(s[i..$],"&gt;" )) { buffer ~= '>'; i += 3; }
- else
- {
- if (mode == DecodeMode.STRICT)
- throw new DecodeException("Unescaped &");
- buffer ~= '&';
- }
- }
- }
- return (buffer.length == 0) ? s : buffer;
-}
-
-@safe pure unittest
-{
- void assertNot(string s) pure
- {
- bool b = false;
- try { decode(s,DecodeMode.STRICT); }
- catch (DecodeException e) { b = true; }
- assert(b,s);
- }
-
- // Assert that things that should work, do
- auto s = "hello";
- assert(decode(s, DecodeMode.STRICT) is s);
- assert(decode("a &gt; b", DecodeMode.STRICT) == "a > b");
- assert(decode("a &lt; b", DecodeMode.STRICT) == "a < b");
- assert(decode("don&apos;t", DecodeMode.STRICT) == "don't");
- assert(decode("&quot;hi&quot;", DecodeMode.STRICT) == "\"hi\"");
- assert(decode("cat &amp; dog", DecodeMode.STRICT) == "cat & dog");
- assert(decode("&#42;", DecodeMode.STRICT) == "*");
- assert(decode("&#x2A;", DecodeMode.STRICT) == "*");
- assert(decode("cat & dog", DecodeMode.LOOSE) == "cat & dog");
- assert(decode("a &gt b", DecodeMode.LOOSE) == "a &gt b");
- assert(decode("&#;", DecodeMode.LOOSE) == "&#;");
- assert(decode("&#x;", DecodeMode.LOOSE) == "&#x;");
- assert(decode("&#2G;", DecodeMode.LOOSE) == "&#2G;");
- assert(decode("&#x2G;", DecodeMode.LOOSE) == "&#x2G;");
-
- // Assert that things that shouldn't work, don't
- assertNot("cat & dog");
- assertNot("a &gt b");
- assertNot("&#;");
- assertNot("&#x;");
- assertNot("&#2G;");
- assertNot("&#x2G;");
-}
-
-/*
- * Class representing an XML document.
- *
- * Standards: $(LINK2 http://www.w3.org/TR/1998/REC-xml-19980210, XML 1.0)
- *
- */
-class Document : Element
-{
- /*
- * Contains all text which occurs before the root element.
- * Defaults to &lt;?xml version="1.0"?&gt;
- */
- string prolog = "<?xml version=\"1.0\"?>";
- /*
- * Contains all text which occurs after the root element.
- * Defaults to the empty string
- */
- string epilog;
-
- /*
- * Constructs a Document by parsing XML text.
- *
- * This function creates a complete DOM (Document Object Model) tree.
- *
- * The input to this function MUST be valid XML.
- * This is enforced by DocumentParser's in contract.
- *
- * Params:
- * s = the complete XML text.
- */
- this(string s)
- in
- {
- assert(s.length != 0);
- }
- do
- {
- auto xml = new DocumentParser(s);
- string tagString = xml.tag.tagString;
-
- this(xml.tag);
- prolog = s[0 .. tagString.ptr - s.ptr];
- parse(xml);
- epilog = *xml.s;
- }
-
- /*
- * Constructs a Document from a Tag.
- *
- * Params:
- * tag = the start tag of the document.
- */
- this(const(Tag) tag)
- {
- super(tag);
- }
-
- const
- {
- /*
- * Compares two Documents for equality
- *
- * Example:
- * --------------
- * Document d1,d2;
- * if (d1 == d2) { }
- * --------------
- */
- override bool opEquals(scope const Object o) const
- {
- const doc = toType!(const Document)(o);
- return prolog == doc.prolog
- && (cast(const) this).Element.opEquals(cast(const) doc)
- && epilog == doc.epilog;
- }
-
- /*
- * Compares two Documents
- *
- * You should rarely need to call this function. It exists so that
- * Documents can be used as associative array keys.
- *
- * Example:
- * --------------
- * Document d1,d2;
- * if (d1 < d2) { }
- * --------------
- */
- override int opCmp(scope const Object o) scope const
- {
- const doc = toType!(const Document)(o);
- if (prolog != doc.prolog)
- return prolog < doc.prolog ? -1 : 1;
- if (int cmp = this.Element.opCmp(doc))
- return cmp;
- if (epilog != doc.epilog)
- return epilog < doc.epilog ? -1 : 1;
- return 0;
- }
-
- /*
- * Returns the hash of a Document
- *
- * You should rarely need to call this function. It exists so that
- * Documents can be used as associative array keys.
- */
- override size_t toHash() scope const @trusted
- {
- return hash(prolog, hash(epilog, (cast() this).Element.toHash()));
- }
-
- /*
- * Returns the string representation of a Document. (That is, the
- * complete XML of a document).
- */
- override string toString() scope const @safe
- {
- return prolog ~ super.toString() ~ epilog;
- }
- }
-}
-
-@system unittest
-{
- // https://issues.dlang.org/show_bug.cgi?id=14966
- auto xml = `<?xml version="1.0" encoding="UTF-8"?><foo></foo>`;
-
- auto a = new Document(xml);
- auto b = new Document(xml);
- assert(a == b);
- assert(!(a < b));
- int[Document] aa;
- aa[a] = 1;
- assert(aa[b] == 1);
-
- b ~= new Element("b");
- assert(a < b);
- assert(b > a);
-}
-
-/*
- * Class representing an XML element.
- *
- * Standards: $(LINK2 http://www.w3.org/TR/1998/REC-xml-19980210, XML 1.0)
- */
-class Element : Item
-{
- Tag tag; // The start tag of the element
- Item[] items; // The element's items
- Text[] texts; // The element's text items
- CData[] cdatas; // The element's CData items
- Comment[] comments; // The element's comments
- ProcessingInstruction[] pis; // The element's processing instructions
- Element[] elements; // The element's child elements
-
- /*
- * Constructs an Element given a name and a string to be used as a Text
- * interior.
- *
- * Params:
- * name = the name of the element.
- * interior = (optional) the string interior.
- *
- * Example:
- * -------------------------------------------------------
- * auto element = new Element("title","Serenity")
- * // constructs the element <title>Serenity</title>
- * -------------------------------------------------------
- */
- this(string name, string interior=null) @safe pure
- {
- this(new Tag(name));
- if (interior.length != 0) opOpAssign!("~")(new Text(interior));
- }
-
- /*
- * Constructs an Element from a Tag.
- *
- * Params:
- * tag_ = the start or empty tag of the element.
- */
- this(const(Tag) tag_) @safe pure
- {
- this.tag = new Tag(tag_.name);
- tag.type = TagType.EMPTY;
- foreach (k,v;tag_.attr) tag.attr[k] = v;
- tag.tagString = tag_.tagString;
- }
-
- /*
- * Append a text item to the interior of this element
- *
- * Params:
- * item = the item you wish to append.
- *
- * Example:
- * --------------
- * Element element;
- * element ~= new Text("hello");
- * --------------
- */
- void opOpAssign(string op)(Text item) @safe pure
- if (op == "~")
- {
- texts ~= item;
- appendItem(item);
- }
-
- /*
- * Append a CData item to the interior of this element
- *
- * Params:
- * item = the item you wish to append.
- *
- * Example:
- * --------------
- * Element element;
- * element ~= new CData("hello");
- * --------------
- */
- void opOpAssign(string op)(CData item) @safe pure
- if (op == "~")
- {
- cdatas ~= item;
- appendItem(item);
- }
-
- /*
- * Append a comment to the interior of this element
- *
- * Params:
- * item = the item you wish to append.
- *
- * Example:
- * --------------
- * Element element;
- * element ~= new Comment("hello");
- * --------------
- */
- void opOpAssign(string op)(Comment item) @safe pure
- if (op == "~")
- {
- comments ~= item;
- appendItem(item);
- }
-
- /*
- * Append a processing instruction to the interior of this element
- *
- * Params:
- * item = the item you wish to append.
- *
- * Example:
- * --------------
- * Element element;
- * element ~= new ProcessingInstruction("hello");
- * --------------
- */
- void opOpAssign(string op)(ProcessingInstruction item) @safe pure
- if (op == "~")
- {
- pis ~= item;
- appendItem(item);
- }
-
- /*
- * Append a complete element to the interior of this element
- *
- * Params:
- * item = the item you wish to append.
- *
- * Example:
- * --------------
- * Element element;
- * Element other = new Element("br");
- * element ~= other;
- * // appends element representing <br />
- * --------------
- */
- void opOpAssign(string op)(Element item) @safe pure
- if (op == "~")
- {
- elements ~= item;
- appendItem(item);
- }
-
- private void appendItem(Item item) @safe pure
- {
- items ~= item;
- if (tag.type == TagType.EMPTY && !item.isEmptyXML)
- tag.type = TagType.START;
- }
-
- private void parse(ElementParser xml)
- {
- xml.onText = (string s) { opOpAssign!("~")(new Text(s)); };
- xml.onCData = (string s) { opOpAssign!("~")(new CData(s)); };
- xml.onComment = (string s) { opOpAssign!("~")(new Comment(s)); };
- xml.onPI = (string s) { opOpAssign!("~")(new ProcessingInstruction(s)); };
-
- xml.onStartTag[null] = (ElementParser xml)
- {
- auto e = new Element(xml.tag);
- e.parse(xml);
- opOpAssign!("~")(e);
- };
-
- xml.parse();
- }
-
- /*
- * Compares two Elements for equality
- *
- * Example:
- * --------------
- * Element e1,e2;
- * if (e1 == e2) { }
- * --------------
- */
- override bool opEquals(scope const Object o) const
- {
- const element = toType!(const Element)(o);
- immutable len = items.length;
- if (len != element.items.length) return false;
- foreach (i; 0 .. len)
- {
- if (!items[i].opEquals(element.items[i])) return false;
- }
- return true;
- }
-
- /*
- * Compares two Elements
- *
- * You should rarely need to call this function. It exists so that Elements
- * can be used as associative array keys.
- *
- * Example:
- * --------------
- * Element e1,e2;
- * if (e1 < e2) { }
- * --------------
- */
- override int opCmp(scope const Object o) @safe const
- {
- const element = toType!(const Element)(o);
- for (uint i=0; ; ++i)
- {
- if (i == items.length && i == element.items.length) return 0;
- if (i == items.length) return -1;
- if (i == element.items.length) return 1;
- if (!items[i].opEquals(element.items[i]))
- return items[i].opCmp(element.items[i]);
- }
- }
-
- /*
- * Returns the hash of an Element
- *
- * You should rarely need to call this function. It exists so that Elements
- * can be used as associative array keys.
- */
- override size_t toHash() scope const @safe
- {
- size_t hash = tag.toHash();
- foreach (item;items) hash += item.toHash();
- return hash;
- }
-
- const
- {
- /*
- * Returns the decoded interior of an element.
- *
- * The element is assumed to contain text <i>only</i>. So, for
- * example, given XML such as "&lt;title&gt;Good &amp;amp;
- * Bad&lt;/title&gt;", will return "Good &amp; Bad".
- *
- * Params:
- * mode = (optional) Mode to use for decoding. (Defaults to LOOSE).
- *
- * Throws: DecodeException if decode fails
- */
- string text(DecodeMode mode=DecodeMode.LOOSE)
- {
- string buffer;
- foreach (item;items)
- {
- Text t = cast(Text) item;
- if (t is null) throw new DecodeException(item.toString());
- buffer ~= decode(t.toString(),mode);
- }
- return buffer;
- }
-
- /*
- * Returns an indented string representation of this item
- *
- * Params:
- * indent = (optional) number of spaces by which to indent this
- * element. Defaults to 2.
- */
- override string[] pretty(uint indent=2) scope
- {
- import std.algorithm.searching : count;
- import std.string : rightJustify;
-
- if (isEmptyXML) return [ tag.toEmptyString() ];
-
- if (items.length == 1)
- {
- auto t = cast(const(Text))(items[0]);
- if (t !is null)
- {
- return [tag.toStartString() ~ t.toString() ~ tag.toEndString()];
- }
- }
-
- string[] a = [ tag.toStartString() ];
- foreach (item;items)
- {
- string[] b = item.pretty(indent);
- foreach (s;b)
- {
- a ~= rightJustify(s,count(s) + indent);
- }
- }
- a ~= tag.toEndString();
- return a;
- }
-
- /*
- * Returns the string representation of an Element
- *
- * Example:
- * --------------
- * auto element = new Element("br");
- * writefln(element.toString()); // writes "<br />"
- * --------------
- */
- override string toString() scope @safe
- {
- if (isEmptyXML) return tag.toEmptyString();
-
- string buffer = tag.toStartString();
- foreach (item;items) { buffer ~= item.toString(); }
- buffer ~= tag.toEndString();
- return buffer;
- }
-
- override @property @safe pure @nogc nothrow bool isEmptyXML() const scope { return items.length == 0; }
- }
-}
-
-/*
- * Tag types.
- *
- * $(DDOC_ENUM_MEMBERS START) Used for start tags
- * $(DDOC_ENUM_MEMBERS END) Used for end tags
- * $(DDOC_ENUM_MEMBERS EMPTY) Used for empty tags
- *
- */
-enum TagType { START, END, EMPTY }
-
-/*
- * Class representing an XML tag.
- *
- * Standards: $(LINK2 http://www.w3.org/TR/1998/REC-xml-19980210, XML 1.0)
- *
- * The class invariant guarantees
- * <ul>
- * <li> that $(B type) is a valid enum TagType value</li>
- * <li> that $(B name) consists of valid characters</li>
- * <li> that each attribute name consists of valid characters</li>
- * </ul>
- */
-class Tag
-{
- TagType type = TagType.START; // Type of tag
- string name; // Tag name
- string[string] attr; // Associative array of attributes
- private string tagString;
-
- invariant()
- {
- string s;
- string t;
-
- assert(type == TagType.START
- || type == TagType.END
- || type == TagType.EMPTY);
-
- s = name;
- try { checkName(s,t); }
- catch (Err e) { assert(false,"Invalid tag name:" ~ e.toString()); }
-
- foreach (k,v;attr)
- {
- s = k;
- try { checkName(s,t); }
- catch (Err e)
- { assert(false,"Invalid attribute name:" ~ e.toString()); }
- }
- }
-
- /*
- * Constructs an instance of Tag with a specified name and type
- *
- * The constructor does not initialize the attributes. To initialize the
- * attributes, you access the $(B attr) member variable.
- *
- * Params:
- * name = the Tag's name
- * type = (optional) the Tag's type. If omitted, defaults to
- * TagType.START.
- *
- * Example:
- * --------------
- * auto tag = new Tag("img",Tag.EMPTY);
- * tag.attr["src"] = "http://example.com/example.jpg";
- * --------------
- */
- this(string name, TagType type=TagType.START) @safe pure
- {
- this.name = name;
- this.type = type;
- }
-
- /* Private constructor (so don't ddoc this!)
- *
- * Constructs a Tag by parsing the string representation, e.g. "<html>".
- *
- * The string is passed by reference, and is advanced over all characters
- * consumed.
- *
- * The second parameter is a dummy parameter only, required solely to
- * distinguish this constructor from the public one.
- */
- private this(ref string s, bool dummy) @safe pure
- {
- import std.algorithm.searching : countUntil;
- import std.ascii : isWhite;
- import std.utf : byCodeUnit;
-
- tagString = s;
- try
- {
- reqc(s,'<');
- if (optc(s,'/')) type = TagType.END;
- ptrdiff_t i = s.byCodeUnit.countUntil(">", "/>", " ", "\t", "\v", "\r", "\n", "\f");
- name = s[0 .. i];
- s = s[i .. $];
-
- i = s.byCodeUnit.countUntil!(a => !isWhite(a));
- s = s[i .. $];
-
- while (s.length > 0 && s[0] != '>' && s[0] != '/')
- {
- i = s.byCodeUnit.countUntil("=", " ", "\t", "\v", "\r", "\n", "\f");
- string key = s[0 .. i];
- s = s[i .. $];
-
- i = s.byCodeUnit.countUntil!(a => !isWhite(a));
- s = s[i .. $];
- reqc(s,'=');
- i = s.byCodeUnit.countUntil!(a => !isWhite(a));
- s = s[i .. $];
-
- immutable char quote = requireOneOf(s,"'\"");
- i = s.byCodeUnit.countUntil(quote);
- string val = decode(s[0 .. i], DecodeMode.LOOSE);
- s = s[i .. $];
- reqc(s,quote);
-
- i = s.byCodeUnit.countUntil!(a => !isWhite(a));
- s = s[i .. $];
- attr[key] = val;
- }
- if (optc(s,'/'))
- {
- if (type == TagType.END) throw new TagException("");
- type = TagType.EMPTY;
- }
- reqc(s,'>');
- tagString.length = tagString.length - s.length;
- }
- catch (XMLException e)
- {
- tagString.length = tagString.length - s.length;
- throw new TagException(tagString);
- }
- }
-
- const
- {
- /*
- * Compares two Tags for equality
- *
- * You should rarely need to call this function. It exists so that Tags
- * can be used as associative array keys.
- *
- * Example:
- * --------------
- * Tag tag1,tag2
- * if (tag1 == tag2) { }
- * --------------
- */
- override bool opEquals(scope Object o)
- {
- const tag = toType!(const Tag)(o);
- return
- (name != tag.name) ? false : (
- (attr != tag.attr) ? false : (
- (type != tag.type) ? false : (
- true )));
- }
-
- /*
- * Compares two Tags
- *
- * Example:
- * --------------
- * Tag tag1,tag2
- * if (tag1 < tag2) { }
- * --------------
- */
- override int opCmp(Object o)
- {
- const tag = toType!(const Tag)(o);
- // Note that attr is an AA, so the comparison is nonsensical (bug 10381)
- return
- ((name != tag.name) ? ( name < tag.name ? -1 : 1 ) :
- ((attr != tag.attr) ? ( cast(void *) attr < cast(void*) tag.attr ? -1 : 1 ) :
- ((type != tag.type) ? ( type < tag.type ? -1 : 1 ) :
- 0 )));
- }
-
- /*
- * Returns the hash of a Tag
- *
- * You should rarely need to call this function. It exists so that Tags
- * can be used as associative array keys.
- */
- override size_t toHash()
- {
- return .hashOf(name);
- }
-
- /*
- * Returns the string representation of a Tag
- *
- * Example:
- * --------------
- * auto tag = new Tag("book",TagType.START);
- * writefln(tag.toString()); // writes "<book>"
- * --------------
- */
- override string toString() @safe
- {
- if (isEmpty) return toEmptyString();
- return (isEnd) ? toEndString() : toStartString();
- }
-
- private
- {
- string toNonEndString() @safe
- {
- import std.format : format;
-
- string s = "<" ~ name;
- foreach (key,val;attr)
- s ~= format(" %s=\"%s\"",key,encode(val));
- return s;
- }
-
- string toStartString() @safe { return toNonEndString() ~ ">"; }
-
- string toEndString() @safe { return "</" ~ name ~ ">"; }
-
- string toEmptyString() @safe { return toNonEndString() ~ " />"; }
- }
-
- /*
- * Returns true if the Tag is a start tag
- *
- * Example:
- * --------------
- * if (tag.isStart) { }
- * --------------
- */
- @property bool isStart() @safe @nogc pure nothrow { return type == TagType.START; }
-
- /*
- * Returns true if the Tag is an end tag
- *
- * Example:
- * --------------
- * if (tag.isEnd) { }
- * --------------
- */
- @property bool isEnd() @safe @nogc pure nothrow { return type == TagType.END; }
-
- /*
- * Returns true if the Tag is an empty tag
- *
- * Example:
- * --------------
- * if (tag.isEmpty) { }
- * --------------
- */
- @property bool isEmpty() @safe @nogc pure nothrow { return type == TagType.EMPTY; }
- }
-}
-
-/*
- * Class representing a comment
- */
-class Comment : Item
-{
- private string content;
-
- /*
- * Construct a comment
- *
- * Params:
- * content = the body of the comment
- *
- * Throws: CommentException if the comment body is illegal (contains "--"
- * or exactly equals "-")
- *
- * Example:
- * --------------
- * auto item = new Comment("This is a comment");
- * // constructs <!--This is a comment-->
- * --------------
- */
- this(string content) @safe pure
- {
- import std.string : indexOf;
-
- if (content == "-" || content.indexOf("--") != -1)
- throw new CommentException(content);
- this.content = content;
- }
-
- /*
- * Compares two comments for equality
- *
- * Example:
- * --------------
- * Comment item1,item2;
- * if (item1 == item2) { }
- * --------------
- */
- override bool opEquals(scope const Object o) const
- {
- const item = toType!(const Item)(o);
- const t = cast(const Comment) item;
- return t !is null && content == t.content;
- }
-
- /*
- * Compares two comments
- *
- * You should rarely need to call this function. It exists so that Comments
- * can be used as associative array keys.
- *
- * Example:
- * --------------
- * Comment item1,item2;
- * if (item1 < item2) { }
- * --------------
- */
- override int opCmp(scope const Object o) scope const
- {
- const item = toType!(const Item)(o);
- const t = cast(const Comment) item;
- return t !is null && (content != t.content
- ? (content < t.content ? -1 : 1 ) : 0 );
- }
-
- /*
- * Returns the hash of a Comment
- *
- * You should rarely need to call this function. It exists so that Comments
- * can be used as associative array keys.
- */
- override size_t toHash() scope const nothrow { return hash(content); }
-
- /*
- * Returns a string representation of this comment
- */
- override string toString() scope const @safe pure nothrow { return "<!--" ~ content ~ "-->"; }
-
- override @property @safe @nogc pure nothrow scope bool isEmptyXML() const { return false; } // Returns false always
-}
-
-// https://issues.dlang.org/show_bug.cgi?id=16241
-@safe unittest
-{
- import std.exception : assertThrown;
- auto c = new Comment("==");
- assert(c.content == "==");
- assertThrown!CommentException(new Comment("--"));
-}
-
-/*
- * Class representing a Character Data section
- */
-class CData : Item
-{
- private string content;
-
- /*
- * Construct a character data section
- *
- * Params:
- * content = the body of the character data segment
- *
- * Throws: CDataException if the segment body is illegal (contains "]]>")
- *
- * Example:
- * --------------
- * auto item = new CData("<b>hello</b>");
- * // constructs <![CDATA[<b>hello</b>]]>
- * --------------
- */
- this(string content) @safe pure
- {
- import std.string : indexOf;
- if (content.indexOf("]]>") != -1) throw new CDataException(content);
- this.content = content;
- }
-
- /*
- * Compares two CDatas for equality
- *
- * Example:
- * --------------
- * CData item1,item2;
- * if (item1 == item2) { }
- * --------------
- */
- override bool opEquals(scope const Object o) const
- {
- const item = toType!(const Item)(o);
- const t = cast(const CData) item;
- return t !is null && content == t.content;
- }
-
- /*
- * Compares two CDatas
- *
- * You should rarely need to call this function. It exists so that CDatas
- * can be used as associative array keys.
- *
- * Example:
- * --------------
- * CData item1,item2;
- * if (item1 < item2) { }
- * --------------
- */
- override int opCmp(scope const Object o) scope const
- {
- const item = toType!(const Item)(o);
- const t = cast(const CData) item;
- return t !is null && (content != t.content
- ? (content < t.content ? -1 : 1 ) : 0 );
- }
-
- /*
- * Returns the hash of a CData
- *
- * You should rarely need to call this function. It exists so that CDatas
- * can be used as associative array keys.
- */
- override size_t toHash() scope const nothrow { return hash(content); }
-
- /*
- * Returns a string representation of this CData section
- */
- override string toString() scope const @safe pure nothrow { return cdata ~ content ~ "]]>"; }
-
- override @property @safe @nogc pure nothrow scope bool isEmptyXML() const { return false; } // Returns false always
-}
-
-/*
- * Class representing a text (aka Parsed Character Data) section
- */
-class Text : Item
-{
- private string content;
-
- /*
- * Construct a text (aka PCData) section
- *
- * Params:
- * content = the text. This function encodes the text before
- * insertion, so it is safe to insert any text
- *
- * Example:
- * --------------
- * auto Text = new CData("a < b");
- * // constructs a &lt; b
- * --------------
- */
- this(string content) @safe pure
- {
- this.content = encode(content);
- }
-
- /*
- * Compares two text sections for equality
- *
- * Example:
- * --------------
- * Text item1,item2;
- * if (item1 == item2) { }
- * --------------
- */
- override bool opEquals(scope const Object o) const
- {
- const item = toType!(const Item)(o);
- const t = cast(const Text) item;
- return t !is null && content == t.content;
- }
-
- /*
- * Compares two text sections
- *
- * You should rarely need to call this function. It exists so that Texts
- * can be used as associative array keys.
- *
- * Example:
- * --------------
- * Text item1,item2;
- * if (item1 < item2) { }
- * --------------
- */
- override int opCmp(scope const Object o) scope const
- {
- const item = toType!(const Item)(o);
- const t = cast(const Text) item;
- return t !is null
- && (content != t.content ? (content < t.content ? -1 : 1 ) : 0 );
- }
-
- /*
- * Returns the hash of a text section
- *
- * You should rarely need to call this function. It exists so that Texts
- * can be used as associative array keys.
- */
- override size_t toHash() scope const nothrow { return hash(content); }
-
- /*
- * Returns a string representation of this Text section
- */
- override string toString() scope const @safe @nogc pure nothrow { return content; }
-
- /*
- * Returns true if the content is the empty string
- */
- override @property @safe @nogc pure nothrow scope bool isEmptyXML() const { return content.length == 0; }
-}
-
-/*
- * Class representing an XML Instruction section
- */
-class XMLInstruction : Item
-{
- private string content;
-
- /*
- * Construct an XML Instruction section
- *
- * Params:
- * content = the body of the instruction segment
- *
- * Throws: XIException if the segment body is illegal (contains ">")
- *
- * Example:
- * --------------
- * auto item = new XMLInstruction("ATTLIST");
- * // constructs <!ATTLIST>
- * --------------
- */
- this(string content) @safe pure
- {
- import std.string : indexOf;
- if (content.indexOf(">") != -1) throw new XIException(content);
- this.content = content;
- }
-
- /*
- * Compares two XML instructions for equality
- *
- * Example:
- * --------------
- * XMLInstruction item1,item2;
- * if (item1 == item2) { }
- * --------------
- */
- override bool opEquals(scope const Object o) const
- {
- const item = toType!(const Item)(o);
- const t = cast(const XMLInstruction) item;
- return t !is null && content == t.content;
- }
-
- /*
- * Compares two XML instructions
- *
- * You should rarely need to call this function. It exists so that
- * XmlInstructions can be used as associative array keys.
- *
- * Example:
- * --------------
- * XMLInstruction item1,item2;
- * if (item1 < item2) { }
- * --------------
- */
- override int opCmp(scope const Object o) scope const
- {
- const item = toType!(const Item)(o);
- const t = cast(const XMLInstruction) item;
- return t !is null
- && (content != t.content ? (content < t.content ? -1 : 1 ) : 0 );
- }
-
- /*
- * Returns the hash of an XMLInstruction
- *
- * You should rarely need to call this function. It exists so that
- * XmlInstructions can be used as associative array keys.
- */
- override size_t toHash() scope const nothrow { return hash(content); }
-
- /*
- * Returns a string representation of this XmlInstruction
- */
- override string toString() scope const @safe pure nothrow { return "<!" ~ content ~ ">"; }
-
- override @property @safe @nogc pure nothrow scope bool isEmptyXML() const { return false; } // Returns false always
-}
-
-/*
- * Class representing a Processing Instruction section
- */
-class ProcessingInstruction : Item
-{
- private string content;
-
- /*
- * Construct a Processing Instruction section
- *
- * Params:
- * content = the body of the instruction segment
- *
- * Throws: PIException if the segment body is illegal (contains "?>")
- *
- * Example:
- * --------------
- * auto item = new ProcessingInstruction("php");
- * // constructs <?php?>
- * --------------
- */
- this(string content) @safe pure
- {
- import std.string : indexOf;
- if (content.indexOf("?>") != -1) throw new PIException(content);
- this.content = content;
- }
-
- /*
- * Compares two processing instructions for equality
- *
- * Example:
- * --------------
- * ProcessingInstruction item1,item2;
- * if (item1 == item2) { }
- * --------------
- */
- override bool opEquals(scope const Object o) const
- {
- const item = toType!(const Item)(o);
- const t = cast(const ProcessingInstruction) item;
- return t !is null && content == t.content;
- }
-
- /*
- * Compares two processing instructions
- *
- * You should rarely need to call this function. It exists so that
- * ProcessingInstructions can be used as associative array keys.
- *
- * Example:
- * --------------
- * ProcessingInstruction item1,item2;
- * if (item1 < item2) { }
- * --------------
- */
- override int opCmp(scope const Object o) scope const
- {
- const item = toType!(const Item)(o);
- const t = cast(const ProcessingInstruction) item;
- return t !is null
- && (content != t.content ? (content < t.content ? -1 : 1 ) : 0 );
- }
-
- /*
- * Returns the hash of a ProcessingInstruction
- *
- * You should rarely need to call this function. It exists so that
- * ProcessingInstructions can be used as associative array keys.
- */
- override size_t toHash() scope const nothrow { return hash(content); }
-
- /*
- * Returns a string representation of this ProcessingInstruction
- */
- override string toString() scope const @safe pure nothrow { return "<?" ~ content ~ "?>"; }
-
- override @property @safe @nogc pure nothrow bool isEmptyXML() scope const { return false; } // Returns false always
-}
-
-/*
- * Abstract base class for XML items
- */
-abstract class Item
-{
- // Compares with another Item of same type for equality
- abstract override bool opEquals(scope const Object o) @safe const;
-
- // Compares with another Item of same type
- abstract override int opCmp(scope const Object o) @safe const;
-
- // Returns the hash of this item
- abstract override size_t toHash() @safe scope const;
-
- // Returns a string representation of this item
- abstract override string toString() @safe scope const;
-
- /*
- * Returns an indented string representation of this item
- *
- * Params:
- * indent = number of spaces by which to indent child elements
- */
- string[] pretty(uint indent) @safe scope const
- {
- import std.string : strip;
- string s = strip(toString());
- return s.length == 0 ? [] : [ s ];
- }
-
- // Returns true if the item represents empty XML text
- abstract @property @safe @nogc pure nothrow bool isEmptyXML() scope const;
-}
-
-/*
- * Class for parsing an XML Document.
- *
- * This is a subclass of ElementParser. Most of the useful functions are
- * documented there.
- *
- * Standards: $(LINK2 http://www.w3.org/TR/1998/REC-xml-19980210, XML 1.0)
- *
- * Bugs:
- * Currently only supports UTF documents.
- *
- * If there is an encoding attribute in the prolog, it is ignored.
- *
- */
-class DocumentParser : ElementParser
-{
- string xmlText;
-
- /*
- * Constructs a DocumentParser.
- *
- * The input to this function MUST be valid XML.
- * This is enforced by the function's in contract.
- *
- * Params:
- * xmlText_ = the entire XML document as text
- *
- */
- this(string xmlText_)
- in
- {
- assert(xmlText_.length != 0);
- try
- {
- // Confirm that the input is valid XML
- check(xmlText_);
- }
- catch (CheckException e)
- {
- // And if it's not, tell the user why not
- assert(false, "\n" ~ e.toString());
- }
- }
- do
- {
- xmlText = xmlText_;
- s = &xmlText;
- super(); // Initialize everything
- parse(); // Parse through the root tag (but not beyond)
- }
-}
-
-@system unittest
-{
- auto doc = new Document("<root><child><grandchild/></child></root>");
- assert(doc.elements.length == 1);
- assert(doc.elements[0].tag.name == "child");
- assert(doc.items == doc.elements);
-}
-
-/*
- * Class for parsing an XML element.
- *
- * Standards: $(LINK2 http://www.w3.org/TR/1998/REC-xml-19980210, XML 1.0)
- *
- * Note that you cannot construct instances of this class directly. You can
- * construct a DocumentParser (which is a subclass of ElementParser), but
- * otherwise, Instances of ElementParser will be created for you by the
- * library, and passed your way via onStartTag handlers.
- *
- */
-class ElementParser
-{
- alias Handler = void delegate(string);
- alias ElementHandler = void delegate(in Element element);
- alias ParserHandler = void delegate(ElementParser parser);
-
- private
- {
- Tag tag_;
- string elementStart;
- string* s;
-
- Handler commentHandler = null;
- Handler cdataHandler = null;
- Handler xiHandler = null;
- Handler piHandler = null;
- Handler rawTextHandler = null;
- Handler textHandler = null;
-
- // Private constructor for start tags
- this(ElementParser parent) @safe @nogc pure nothrow
- {
- s = parent.s;
- this();
- tag_ = parent.tag_;
- }
-
- // Private constructor for empty tags
- this(Tag tag, string* t) @safe @nogc pure nothrow
- {
- s = t;
- this();
- tag_ = tag;
- }
- }
-
- /*
- * The Tag at the start of the element being parsed. You can read this to
- * determine the tag's name and attributes.
- */
- @property @safe @nogc pure nothrow const(Tag) tag() const { return tag_; }
-
- /*
- * Register a handler which will be called whenever a start tag is
- * encountered which matches the specified name. You can also pass null as
- * the name, in which case the handler will be called for any unmatched
- * start tag.
- *
- * Example:
- * --------------
- * // Call this function whenever a <podcast> start tag is encountered
- * onStartTag["podcast"] = (ElementParser xml)
- * {
- * // Your code here
- * //
- * // This is a a closure, so code here may reference
- * // variables which are outside of this scope
- * };
- *
- * // call myEpisodeStartHandler (defined elsewhere) whenever an <episode>
- * // start tag is encountered
- * onStartTag["episode"] = &myEpisodeStartHandler;
- *
- * // call delegate dg for all other start tags
- * onStartTag[null] = dg;
- * --------------
- *
- * This library will supply your function with a new instance of
- * ElementHandler, which may be used to parse inside the element whose
- * start tag was just found, or to identify the tag attributes of the
- * element, etc.
- *
- * Note that your function will be called for both start tags and empty
- * tags. That is, we make no distinction between &lt;br&gt;&lt;/br&gt;
- * and &lt;br/&gt;.
- */
- ParserHandler[string] onStartTag;
-
- /*
- * Register a handler which will be called whenever an end tag is
- * encountered which matches the specified name. You can also pass null as
- * the name, in which case the handler will be called for any unmatched
- * end tag.
- *
- * Example:
- * --------------
- * // Call this function whenever a </podcast> end tag is encountered
- * onEndTag["podcast"] = (in Element e)
- * {
- * // Your code here
- * //
- * // This is a a closure, so code here may reference
- * // variables which are outside of this scope
- * };
- *
- * // call myEpisodeEndHandler (defined elsewhere) whenever an </episode>
- * // end tag is encountered
- * onEndTag["episode"] = &myEpisodeEndHandler;
- *
- * // call delegate dg for all other end tags
- * onEndTag[null] = dg;
- * --------------
- *
- * Note that your function will be called for both start tags and empty
- * tags. That is, we make no distinction between &lt;br&gt;&lt;/br&gt;
- * and &lt;br/&gt;.
- */
- ElementHandler[string] onEndTag;
-
- protected this() @safe @nogc pure nothrow
- {
- elementStart = *s;
- }
-
- /*
- * Register a handler which will be called whenever text is encountered.
- *
- * Example:
- * --------------
- * // Call this function whenever text is encountered
- * onText = (string s)
- * {
- * // Your code here
- *
- * // The passed parameter s will have been decoded by the time you see
- * // it, and so may contain any character.
- * //
- * // This is a a closure, so code here may reference
- * // variables which are outside of this scope
- * };
- * --------------
- */
- @property @safe @nogc pure nothrow void onText(Handler handler) { textHandler = handler; }
-
- /*
- * Register an alternative handler which will be called whenever text
- * is encountered. This differs from onText in that onText will decode
- * the text, whereas onTextRaw will not. This allows you to make design
- * choices, since onText will be more accurate, but slower, while
- * onTextRaw will be faster, but less accurate. Of course, you can
- * still call decode() within your handler, if you want, but you'd
- * probably want to use onTextRaw only in circumstances where you
- * know that decoding is unnecessary.
- *
- * Example:
- * --------------
- * // Call this function whenever text is encountered
- * onText = (string s)
- * {
- * // Your code here
- *
- * // The passed parameter s will NOT have been decoded.
- * //
- * // This is a a closure, so code here may reference
- * // variables which are outside of this scope
- * };
- * --------------
- */
- @safe @nogc pure nothrow void onTextRaw(Handler handler) { rawTextHandler = handler; }
-
- /*
- * Register a handler which will be called whenever a character data
- * segment is encountered.
- *
- * Example:
- * --------------
- * // Call this function whenever a CData section is encountered
- * onCData = (string s)
- * {
- * // Your code here
- *
- * // The passed parameter s does not include the opening <![CDATA[
- * // nor closing ]]>
- * //
- * // This is a a closure, so code here may reference
- * // variables which are outside of this scope
- * };
- * --------------
- */
- @property @safe @nogc pure nothrow void onCData(Handler handler) { cdataHandler = handler; }
-
- /*
- * Register a handler which will be called whenever a comment is
- * encountered.
- *
- * Example:
- * --------------
- * // Call this function whenever a comment is encountered
- * onComment = (string s)
- * {
- * // Your code here
- *
- * // The passed parameter s does not include the opening <!-- nor
- * // closing -->
- * //
- * // This is a a closure, so code here may reference
- * // variables which are outside of this scope
- * };
- * --------------
- */
- @property @safe @nogc pure nothrow void onComment(Handler handler) { commentHandler = handler; }
-
- /*
- * Register a handler which will be called whenever a processing
- * instruction is encountered.
- *
- * Example:
- * --------------
- * // Call this function whenever a processing instruction is encountered
- * onPI = (string s)
- * {
- * // Your code here
- *
- * // The passed parameter s does not include the opening <? nor
- * // closing ?>
- * //
- * // This is a a closure, so code here may reference
- * // variables which are outside of this scope
- * };
- * --------------
- */
- @property @safe @nogc pure nothrow void onPI(Handler handler) { piHandler = handler; }
-
- /*
- * Register a handler which will be called whenever an XML instruction is
- * encountered.
- *
- * Example:
- * --------------
- * // Call this function whenever an XML instruction is encountered
- * // (Note: XML instructions may only occur preceding the root tag of a
- * // document).
- * onPI = (string s)
- * {
- * // Your code here
- *
- * // The passed parameter s does not include the opening <! nor
- * // closing >
- * //
- * // This is a a closure, so code here may reference
- * // variables which are outside of this scope
- * };
- * --------------
- */
- @property @safe @nogc pure nothrow void onXI(Handler handler) { xiHandler = handler; }
-
- /*
- * Parse an XML element.
- *
- * Parsing will continue until the end of the current element. Any items
- * encountered for which a handler has been registered will invoke that
- * handler.
- *
- * Throws: various kinds of XMLException
- */
- void parse()
- {
- import std.algorithm.searching : startsWith;
- import std.string : indexOf;
-
- string t;
- const Tag root = tag_;
- Tag[string] startTags;
- if (tag_ !is null) startTags[tag_.name] = tag_;
-
- while (s.length != 0)
- {
- if (startsWith(*s,"<!--"))
- {
- chop(*s,4);
- t = chop(*s,indexOf(*s,"-->"));
- if (commentHandler.funcptr !is null) commentHandler(t);
- chop(*s,3);
- }
- else if (startsWith(*s,"<![CDATA["))
- {
- chop(*s,9);
- t = chop(*s,indexOf(*s,"]]>"));
- if (cdataHandler.funcptr !is null) cdataHandler(t);
- chop(*s,3);
- }
- else if (startsWith(*s,"<!"))
- {
- chop(*s,2);
- t = chop(*s,indexOf(*s,">"));
- if (xiHandler.funcptr !is null) xiHandler(t);
- chop(*s,1);
- }
- else if (startsWith(*s,"<?"))
- {
- chop(*s,2);
- t = chop(*s,indexOf(*s,"?>"));
- if (piHandler.funcptr !is null) piHandler(t);
- chop(*s,2);
- }
- else if (startsWith(*s,"<"))
- {
- tag_ = new Tag(*s,true);
- if (root is null)
- return; // Return to constructor of derived class
-
- if (tag_.isStart)
- {
- startTags[tag_.name] = tag_;
-
- auto parser = new ElementParser(this);
-
- auto handler = tag_.name in onStartTag;
- if (handler !is null) (*handler)(parser);
- else
- {
- handler = null in onStartTag;
- if (handler !is null) (*handler)(parser);
- }
- }
- else if (tag_.isEnd)
- {
- const startTag = startTags[tag_.name];
- string text;
-
- if (startTag.tagString.length == 0)
- assert(0);
-
- immutable(char)* p = startTag.tagString.ptr
- + startTag.tagString.length;
- immutable(char)* q = &tag_.tagString[0];
- text = decode(p[0..(q-p)], DecodeMode.LOOSE);
-
- auto element = new Element(startTag);
- if (text.length != 0) element ~= new Text(text);
-
- auto handler = tag_.name in onEndTag;
- if (handler !is null) (*handler)(element);
- else
- {
- handler = null in onEndTag;
- if (handler !is null) (*handler)(element);
- }
-
- if (tag_.name == root.name) return;
- }
- else if (tag_.isEmpty)
- {
- Tag startTag = new Tag(tag_.name);
-
- // FIX by hed010gy
- // https://issues.dlang.org/show_bug.cgi?id=2979
- if (tag_.attr.length > 0)
- foreach (tn,tv; tag_.attr) startTag.attr[tn]=tv;
- // END FIX
-
- // Handle the pretend start tag
- string s2;
- auto parser = new ElementParser(startTag,&s2);
- auto handler1 = startTag.name in onStartTag;
- if (handler1 !is null) (*handler1)(parser);
- else
- {
- handler1 = null in onStartTag;
- if (handler1 !is null) (*handler1)(parser);
- }
-
- // Handle the pretend end tag
- auto element = new Element(startTag);
- auto handler2 = tag_.name in onEndTag;
- if (handler2 !is null) (*handler2)(element);
- else
- {
- handler2 = null in onEndTag;
- if (handler2 !is null) (*handler2)(element);
- }
- }
- }
- else
- {
- t = chop(*s,indexOf(*s,"<"));
- if (rawTextHandler.funcptr !is null)
- rawTextHandler(t);
- else if (textHandler.funcptr !is null)
- textHandler(decode(t,DecodeMode.LOOSE));
- }
- }
- }
-
- /*
- * Returns that part of the element which has already been parsed
- */
- override string toString() const @nogc @safe pure nothrow
- {
- assert(elementStart.length >= s.length);
- return elementStart[0 .. elementStart.length - s.length];
- }
-
-}
-
-private
-{
- template Check(string msg)
- {
- string old = s;
-
- void fail() @safe pure
- {
- s = old;
- throw new Err(s,msg);
- }
-
- void fail(Err e) @safe pure
- {
- s = old;
- throw new Err(s,msg,e);
- }
-
- void fail(string msg2) @safe pure
- {
- fail(new Err(s,msg2));
- }
- }
-
- void checkMisc(ref string s) @safe pure // rule 27
- {
- import std.algorithm.searching : startsWith;
-
- mixin Check!("Misc");
-
- try
- {
- if (s.startsWith("<!--")) { checkComment(s); }
- else if (s.startsWith("<?")) { checkPI(s); }
- else { checkSpace(s); }
- }
- catch (Err e) { fail(e); }
- }
-
- void checkDocument(ref string s) @safe pure // rule 1
- {
- mixin Check!("Document");
- try
- {
- checkProlog(s);
- checkElement(s);
- star!(checkMisc)(s);
- }
- catch (Err e) { fail(e); }
- }
-
- void checkChars(ref string s) @safe pure // rule 2
- {
- // TO DO - Fix std.utf stride and decode functions, then use those
- // instead
- import std.format : format;
-
- mixin Check!("Chars");
-
- dchar c;
- ptrdiff_t n = -1;
- // 'i' must not be smaller than size_t because size_t is used internally in
- // aApply.d and it will be cast e.g to (int *) which fails on BigEndian targets.
- foreach (size_t i, dchar d; s)
- {
- if (!isChar(d))
- {
- c = d;
- n = i;
- break;
- }
- }
- if (n != -1)
- {
- s = s[n..$];
- fail(format("invalid character: U+%04X",c));
- }
- }
-
- void checkSpace(ref string s) @safe pure // rule 3
- {
- import std.algorithm.searching : countUntil;
- import std.ascii : isWhite;
- import std.utf : byCodeUnit;
-
- mixin Check!("Whitespace");
- ptrdiff_t i = s.byCodeUnit.countUntil!(a => !isWhite(a));
- if (i == -1 && s.length > 0 && isWhite(s[0]))
- s = s[$ .. $];
- else if (i > -1)
- s = s[i .. $];
- if (s is old) fail();
- }
-
- void checkName(ref string s, out string name) @safe pure // rule 5
- {
- mixin Check!("Name");
-
- if (s.length == 0) fail();
- ptrdiff_t n;
- // 'i' must not be smaller than size_t because size_t is used internally in
- // aApply.d and it will be cast e.g to (int *) which fails on BigEndian targets.
- foreach (size_t i, dchar c; s)
- {
- if (c == '_' || c == ':' || isLetter(c)) continue;
- if (i == 0) fail();
- if (c == '-' || c == '.' || isDigit(c)
- || isCombiningChar(c) || isExtender(c)) continue;
- n = i;
- break;
- }
- name = s[0 .. n];
- s = s[n..$];
- }
-
- void checkAttValue(ref string s) @safe pure // rule 10
- {
- import std.algorithm.searching : countUntil;
- import std.utf : byCodeUnit;
-
- mixin Check!("AttValue");
-
- if (s.length == 0) fail();
- char c = s[0];
- if (c != '\u0022' && c != '\u0027')
- fail("attribute value requires quotes");
- s = s[1..$];
- for (;;)
- {
- s = s[s.byCodeUnit.countUntil(c) .. $];
- if (s.length == 0) fail("unterminated attribute value");
- if (s[0] == '<') fail("< found in attribute value");
- if (s[0] == c) break;
- try { checkReference(s); } catch (Err e) { fail(e); }
- }
- s = s[1..$];
- }
-
- void checkCharData(ref string s) @safe pure // rule 14
- {
- import std.algorithm.searching : startsWith;
-
- mixin Check!("CharData");
-
- while (s.length != 0)
- {
- if (s.startsWith("&")) break;
- if (s.startsWith("<")) break;
- if (s.startsWith("]]>")) fail("]]> found within char data");
- s = s[1..$];
- }
- }
-
- void checkComment(ref string s) @safe pure // rule 15
- {
- import std.string : indexOf;
-
- mixin Check!("Comment");
-
- try { checkLiteral("<!--",s); } catch (Err e) { fail(e); }
- ptrdiff_t n = s.indexOf("--");
- if (n == -1) fail("unterminated comment");
- s = s[n..$];
- try { checkLiteral("-->",s); } catch (Err e) { fail(e); }
- }
-
- void checkPI(ref string s) @safe pure // rule 16
- {
- mixin Check!("PI");
-
- try
- {
- checkLiteral("<?",s);
- checkEnd("?>",s);
- }
- catch (Err e) { fail(e); }
- }
-
- void checkCDSect(ref string s) @safe pure // rule 18
- {
- mixin Check!("CDSect");
-
- try
- {
- checkLiteral(cdata,s);
- checkEnd("]]>",s);
- }
- catch (Err e) { fail(e); }
- }
-
- void checkProlog(ref string s) @safe pure // rule 22
- {
- mixin Check!("Prolog");
-
- try
- {
- /* The XML declaration is optional
- * http://www.w3.org/TR/2008/REC-xml-20081126/#NT-prolog
- */
- opt!(checkXMLDecl)(s);
-
- star!(checkMisc)(s);
- opt!(seq!(checkDocTypeDecl,star!(checkMisc)))(s);
- }
- catch (Err e) { fail(e); }
- }
-
- void checkXMLDecl(ref string s) @safe pure // rule 23
- {
- mixin Check!("XMLDecl");
-
- try
- {
- checkLiteral("<?xml",s);
- checkVersionInfo(s);
- opt!(checkEncodingDecl)(s);
- opt!(checkSDDecl)(s);
- opt!(checkSpace)(s);
- checkLiteral("?>",s);
- }
- catch (Err e) { fail(e); }
- }
-
- void checkVersionInfo(ref string s) @safe pure // rule 24
- {
- mixin Check!("VersionInfo");
-
- try
- {
- checkSpace(s);
- checkLiteral("version",s);
- checkEq(s);
- quoted!(checkVersionNum)(s);
- }
- catch (Err e) { fail(e); }
- }
-
- void checkEq(ref string s) @safe pure // rule 25
- {
- mixin Check!("Eq");
-
- try
- {
- opt!(checkSpace)(s);
- checkLiteral("=",s);
- opt!(checkSpace)(s);
- }
- catch (Err e) { fail(e); }
- }
-
- void checkVersionNum(ref string s) @safe pure // rule 26
- {
- import std.algorithm.searching : countUntil;
- import std.utf : byCodeUnit;
-
- mixin Check!("VersionNum");
-
- s = s[s.byCodeUnit.countUntil('\"') .. $];
- if (s is old) fail();
- }
-
- void checkDocTypeDecl(ref string s) @safe pure // rule 28
- {
- mixin Check!("DocTypeDecl");
-
- try
- {
- checkLiteral("<!DOCTYPE",s);
- //
- // TO DO -- ensure DOCTYPE is well formed
- // (But not yet. That's one of our "future directions")
- //
- checkEnd(">",s);
- }
- catch (Err e) { fail(e); }
- }
-
- void checkSDDecl(ref string s) @safe pure // rule 32
- {
- import std.algorithm.searching : startsWith;
-
- mixin Check!("SDDecl");
-
- try
- {
- checkSpace(s);
- checkLiteral("standalone",s);
- checkEq(s);
- }
- catch (Err e) { fail(e); }
-
- int n = 0;
- if (s.startsWith("'yes'") || s.startsWith("\"yes\"")) n = 5;
- else if (s.startsWith("'no'" ) || s.startsWith("\"no\"" )) n = 4;
- else fail("standalone attribute value must be 'yes', \"yes\","~
- " 'no' or \"no\"");
- s = s[n..$];
- }
-
- void checkElement(ref string s) @safe pure // rule 39
- {
- mixin Check!("Element");
-
- string sname,ename,t;
- try { checkTag(s,t,sname); } catch (Err e) { fail(e); }
-
- if (t == "STag")
- {
- try
- {
- checkContent(s);
- t = s;
- checkETag(s,ename);
- }
- catch (Err e) { fail(e); }
-
- if (sname != ename)
- {
- s = t;
- fail("end tag name \"" ~ ename
- ~ "\" differs from start tag name \""~sname~"\"");
- }
- }
- }
-
- // rules 40 and 44
- void checkTag(ref string s, out string type, out string name) @safe pure
- {
- mixin Check!("Tag");
-
- try
- {
- type = "STag";
- checkLiteral("<",s);
- checkName(s,name);
- star!(seq!(checkSpace,checkAttribute))(s);
- opt!(checkSpace)(s);
- if (s.length != 0 && s[0] == '/')
- {
- s = s[1..$];
- type = "ETag";
- }
- checkLiteral(">",s);
- }
- catch (Err e) { fail(e); }
- }
-
- void checkAttribute(ref string s) @safe pure // rule 41
- {
- mixin Check!("Attribute");
-
- try
- {
- string name;
- checkName(s,name);
- checkEq(s);
- checkAttValue(s);
- }
- catch (Err e) { fail(e); }
- }
-
- void checkETag(ref string s, out string name) @safe pure // rule 42
- {
- mixin Check!("ETag");
-
- try
- {
- checkLiteral("</",s);
- checkName(s,name);
- opt!(checkSpace)(s);
- checkLiteral(">",s);
- }
- catch (Err e) { fail(e); }
- }
-
- void checkContent(ref string s) @safe pure // rule 43
- {
- import std.algorithm.searching : startsWith;
-
- mixin Check!("Content");
-
- try
- {
- while (s.length != 0)
- {
- old = s;
- if (s.startsWith("&")) { checkReference(s); }
- else if (s.startsWith("<!--")) { checkComment(s); }
- else if (s.startsWith("<?")) { checkPI(s); }
- else if (s.startsWith(cdata)) { checkCDSect(s); }
- else if (s.startsWith("</")) { break; }
- else if (s.startsWith("<")) { checkElement(s); }
- else { checkCharData(s); }
- }
- }
- catch (Err e) { fail(e); }
- }
-
- void checkCharRef(ref string s, out dchar c) @safe pure // rule 66
- {
- import std.format : format;
-
- mixin Check!("CharRef");
-
- c = 0;
- try { checkLiteral("&#",s); } catch (Err e) { fail(e); }
- int radix = 10;
- if (s.length != 0 && s[0] == 'x')
- {
- s = s[1..$];
- radix = 16;
- }
- if (s.length == 0) fail("unterminated character reference");
- if (s[0] == ';')
- fail("character reference must have at least one digit");
- while (s.length != 0)
- {
- immutable char d = s[0];
- int n = 0;
- switch (d)
- {
- case 'F','f': ++n; goto case;
- case 'E','e': ++n; goto case;
- case 'D','d': ++n; goto case;
- case 'C','c': ++n; goto case;
- case 'B','b': ++n; goto case;
- case 'A','a': ++n; goto case;
- case '9': ++n; goto case;
- case '8': ++n; goto case;
- case '7': ++n; goto case;
- case '6': ++n; goto case;
- case '5': ++n; goto case;
- case '4': ++n; goto case;
- case '3': ++n; goto case;
- case '2': ++n; goto case;
- case '1': ++n; goto case;
- case '0': break;
- default: n = 100; break;
- }
- if (n >= radix) break;
- c *= radix;
- c += n;
- s = s[1..$];
- }
- if (!isChar(c)) fail(format("U+%04X is not a legal character",c));
- if (s.length == 0 || s[0] != ';') fail("expected ;");
- else s = s[1..$];
- }
-
- void checkReference(ref string s) @safe pure // rule 67
- {
- import std.algorithm.searching : startsWith;
-
- mixin Check!("Reference");
-
- try
- {
- dchar c;
- if (s.startsWith("&#")) checkCharRef(s,c);
- else checkEntityRef(s);
- }
- catch (Err e) { fail(e); }
- }
-
- void checkEntityRef(ref string s) @safe pure // rule 68
- {
- mixin Check!("EntityRef");
-
- try
- {
- string name;
- checkLiteral("&",s);
- checkName(s,name);
- checkLiteral(";",s);
- }
- catch (Err e) { fail(e); }
- }
-
- void checkEncName(ref string s) @safe pure // rule 81
- {
- import std.algorithm.searching : countUntil;
- import std.ascii : isAlpha;
- import std.utf : byCodeUnit;
-
- mixin Check!("EncName");
-
- s = s[s.byCodeUnit.countUntil!(a => !isAlpha(a)) .. $];
- if (s is old) fail();
- s = s[s.byCodeUnit.countUntil('\"', '\'') .. $];
- }
-
- void checkEncodingDecl(ref string s) @safe pure // rule 80
- {
- mixin Check!("EncodingDecl");
-
- try
- {
- checkSpace(s);
- checkLiteral("encoding",s);
- checkEq(s);
- quoted!(checkEncName)(s);
- }
- catch (Err e) { fail(e); }
- }
-
- // Helper functions
-
- void checkLiteral(string literal,ref string s) @safe pure
- {
- import std.string : startsWith;
-
- mixin Check!("Literal");
-
- if (!s.startsWith(literal)) fail("Expected literal \""~literal~"\"");
- s = s[literal.length..$];
- }
-
- void checkEnd(string end,ref string s) @safe pure
- {
- import std.string : indexOf;
- // Deliberately no mixin Check here.
-
- auto n = s.indexOf(end);
- if (n == -1) throw new Err(s,"Unable to find terminating \""~end~"\"");
- s = s[n..$];
- checkLiteral(end,s);
- }
-
- // Metafunctions -- none of these use mixin Check
-
- void opt(alias f)(ref string s)
- {
- try { f(s); } catch (Err e) {}
- }
-
- void plus(alias f)(ref string s)
- {
- f(s);
- star!(f)(s);
- }
-
- void star(alias f)(ref string s)
- {
- while (s.length != 0)
- {
- try { f(s); }
- catch (Err e) { return; }
- }
- }
-
- void quoted(alias f)(ref string s)
- {
- import std.string : startsWith;
-
- if (s.startsWith("'"))
- {
- checkLiteral("'",s);
- f(s);
- checkLiteral("'",s);
- }
- else
- {
- checkLiteral("\"",s);
- f(s);
- checkLiteral("\"",s);
- }
- }
-
- void seq(alias f,alias g)(ref string s)
- {
- f(s);
- g(s);
- }
-}
-
-/*
- * Check an entire XML document for well-formedness
- *
- * Params:
- * s = the document to be checked, passed as a string
- *
- * Throws: CheckException if the document is not well formed
- *
- * CheckException's toString() method will yield the complete hierarchy of
- * parse failure (the XML equivalent of a stack trace), giving the line and
- * column number of every failure at every level.
- */
-void check(string s) @safe pure
-{
- try
- {
- checkChars(s);
- checkDocument(s);
- if (s.length != 0) throw new Err(s,"Junk found after document");
- }
- catch (Err e)
- {
- e.complete(s);
- throw e;
- }
-}
-
-@system pure unittest
-{
- import std.string : indexOf;
-
- try
- {
- check(q"[<?xml version="1.0"?>
- <catalog>
- <book id="bk101">
- <author>Gambardella, Matthew</author>
- <title>XML Developer's Guide</title>
- <genre>Computer</genre>
- <price>44.95</price>
- <publish_date>2000-10-01</publish_date>
- <description>An in-depth look at creating applications
- with XML.</description>
- </book>
- <book id="bk102">
- <author>Ralls, Kim</author>
- <title>Midnight Rain</title>
- <genre>Fantasy</genres>
- <price>5.95</price>
- <publish_date>2000-12-16</publish_date>
- <description>A former architect battles corporate zombies,
- an evil sorceress, and her own childhood to become queen
- of the world.</description>
- </book>
- <book id="bk103">
- <author>Corets, Eva</author>
- <title>Maeve Ascendant</title>
- <genre>Fantasy</genre>
- <price>5.95</price>
- <publish_date>2000-11-17</publish_date>
- <description>After the collapse of a nanotechnology
- society in England, the young survivors lay the
- foundation for a new society.</description>
- </book>
- </catalog>
- ]");
- assert(false);
- }
- catch (CheckException e)
- {
- auto n = e.toString().indexOf("end tag name \"genres\" differs"~
- " from start tag name \"genre\"");
- assert(n != -1);
- }
-}
-
-@system unittest
-{
- string s = q"EOS
-<?xml version="1.0"?>
-<set>
- <one>A</one>
- <!-- comment -->
- <two>B</two>
-</set>
-EOS";
- try
- {
- check(s);
- }
- catch (CheckException e)
- {
- assert(0, e.toString());
- }
-}
-
-@system unittest
-{
- string test_xml = `<?xml version="1.0" encoding='UTF-8'?><r><stream:stream
- xmlns:stream="http://etherx.'jabber'.org/streams"
- xmlns="jabber:'client'" from='jid.pl' id="587a5767"
- xml:lang="en" version="1.0" attr='a"b"c'>
- </stream:stream></r>`;
-
- DocumentParser parser = new DocumentParser(test_xml);
- bool tested = false;
- parser.onStartTag["stream:stream"] = (ElementParser p) {
- assert(p.tag.attr["xmlns"] == "jabber:'client'");
- assert(p.tag.attr["from"] == "jid.pl");
- assert(p.tag.attr["attr"] == "a\"b\"c");
- tested = true;
- };
- parser.parse();
- assert(tested);
-}
-
-@system unittest
-{
- string s = q"EOS
-<?xml version="1.0" encoding="utf-8"?> <Tests>
- <Test thing="What &amp; Up">What &amp; Up Second</Test>
-</Tests>
-EOS";
- auto xml = new DocumentParser(s);
-
- xml.onStartTag["Test"] = (ElementParser xml) {
- assert(xml.tag.attr["thing"] == "What & Up");
- };
-
- xml.onEndTag["Test"] = (in Element e) {
- assert(e.text() == "What & Up Second");
- };
- xml.parse();
-}
-
-@system unittest
-{
- string s = `<tag attr="&quot;value&gt;" />`;
- auto doc = new Document(s);
- assert(doc.toString() == s);
-}
-
-/* The base class for exceptions thrown by this module */
-class XMLException : Exception { this(string msg) @safe pure { super(msg); } }
-
-// Other exceptions
-
-// Thrown during Comment constructor
-class CommentException : XMLException
-{ private this(string msg) @safe pure { super(msg); } }
-
-// Thrown during CData constructor
-class CDataException : XMLException
-{ private this(string msg) @safe pure { super(msg); } }
-
-// Thrown during XMLInstruction constructor
-class XIException : XMLException
-{ private this(string msg) @safe pure { super(msg); } }
-
-// Thrown during ProcessingInstruction constructor
-class PIException : XMLException
-{ private this(string msg) @safe pure { super(msg); } }
-
-// Thrown during Text constructor
-class TextException : XMLException
-{ private this(string msg) @safe pure { super(msg); } }
-
-// Thrown during decode()
-class DecodeException : XMLException
-{ private this(string msg) @safe pure { super(msg); } }
-
-// Thrown if comparing with wrong type
-class InvalidTypeException : XMLException
-{ private this(string msg) @safe pure { super(msg); } }
-
-// Thrown when parsing for Tags
-class TagException : XMLException
-{ private this(string msg) @safe pure { super(msg); } }
-
-/*
- * Thrown during check()
- */
-class CheckException : XMLException
-{
- CheckException err; // Parent in hierarchy
- private string tail;
- /*
- * Name of production rule which failed to parse,
- * or specific error message
- */
- string msg;
- size_t line = 0; // Line number at which parse failure occurred
- size_t column = 0; // Column number at which parse failure occurred
-
- private this(string tail,string msg,Err err=null) @safe pure
- {
- super(null);
- this.tail = tail;
- this.msg = msg;
- this.err = err;
- }
-
- private void complete(string entire) @safe pure
- {
- import std.string : count, lastIndexOf;
- import std.utf : toUTF32;
-
- string head = entire[0..$-tail.length];
- ptrdiff_t n = head.lastIndexOf('\n') + 1;
- line = head.count("\n") + 1;
- dstring t = toUTF32(head[n..$]);
- column = t.length + 1;
- if (err !is null) err.complete(entire);
- }
-
- override string toString() const @safe pure
- {
- import std.format : format;
-
- string s;
- if (line != 0) s = format("Line %d, column %d: ",line,column);
- s ~= msg;
- s ~= '\n';
- if (err !is null) s = err.toString() ~ s;
- return s;
- }
-}
-
-private alias Err = CheckException;
-
-// Private helper functions
-
-private
-{
- inout(T) toType(T)(inout return scope Object o)
- {
- T t = cast(T)(o);
- if (t is null)
- {
- throw new InvalidTypeException("Attempt to compare a "
- ~ T.stringof ~ " with an instance of another type");
- }
- return t;
- }
-
- string chop(ref string s, size_t n) @safe pure nothrow
- {
- if (n == -1) n = s.length;
- string t = s[0 .. n];
- s = s[n..$];
- return t;
- }
-
- bool optc(ref string s, char c) @safe pure nothrow
- {
- immutable bool b = s.length != 0 && s[0] == c;
- if (b) s = s[1..$];
- return b;
- }
-
- void reqc(ref string s, char c) @safe pure
- {
- if (s.length == 0 || s[0] != c) throw new TagException("");
- s = s[1..$];
- }
-
- char requireOneOf(ref string s, string chars) @safe pure
- {
- import std.string : indexOf;
-
- if (s.length == 0 || indexOf(chars,s[0]) == -1)
- throw new TagException("");
- immutable char ch = s[0];
- s = s[1..$];
- return ch;
- }
-
- alias hash = .hashOf;
-
- // Definitions from the XML specification
- immutable CharTable=[0x9,0x9,0xA,0xA,0xD,0xD,0x20,0xD7FF,0xE000,0xFFFD,
- 0x10000,0x10FFFF];
- immutable BaseCharTable=[0x0041,0x005A,0x0061,0x007A,0x00C0,0x00D6,0x00D8,
- 0x00F6,0x00F8,0x00FF,0x0100,0x0131,0x0134,0x013E,0x0141,0x0148,0x014A,
- 0x017E,0x0180,0x01C3,0x01CD,0x01F0,0x01F4,0x01F5,0x01FA,0x0217,0x0250,
- 0x02A8,0x02BB,0x02C1,0x0386,0x0386,0x0388,0x038A,0x038C,0x038C,0x038E,
- 0x03A1,0x03A3,0x03CE,0x03D0,0x03D6,0x03DA,0x03DA,0x03DC,0x03DC,0x03DE,
- 0x03DE,0x03E0,0x03E0,0x03E2,0x03F3,0x0401,0x040C,0x040E,0x044F,0x0451,
- 0x045C,0x045E,0x0481,0x0490,0x04C4,0x04C7,0x04C8,0x04CB,0x04CC,0x04D0,
- 0x04EB,0x04EE,0x04F5,0x04F8,0x04F9,0x0531,0x0556,0x0559,0x0559,0x0561,
- 0x0586,0x05D0,0x05EA,0x05F0,0x05F2,0x0621,0x063A,0x0641,0x064A,0x0671,
- 0x06B7,0x06BA,0x06BE,0x06C0,0x06CE,0x06D0,0x06D3,0x06D5,0x06D5,0x06E5,
- 0x06E6,0x0905,0x0939,0x093D,0x093D,0x0958,0x0961,0x0985,0x098C,0x098F,
- 0x0990,0x0993,0x09A8,0x09AA,0x09B0,0x09B2,0x09B2,0x09B6,0x09B9,0x09DC,
- 0x09DD,0x09DF,0x09E1,0x09F0,0x09F1,0x0A05,0x0A0A,0x0A0F,0x0A10,0x0A13,
- 0x0A28,0x0A2A,0x0A30,0x0A32,0x0A33,0x0A35,0x0A36,0x0A38,0x0A39,0x0A59,
- 0x0A5C,0x0A5E,0x0A5E,0x0A72,0x0A74,0x0A85,0x0A8B,0x0A8D,0x0A8D,0x0A8F,
- 0x0A91,0x0A93,0x0AA8,0x0AAA,0x0AB0,0x0AB2,0x0AB3,0x0AB5,0x0AB9,0x0ABD,
- 0x0ABD,0x0AE0,0x0AE0,0x0B05,0x0B0C,0x0B0F,0x0B10,0x0B13,0x0B28,0x0B2A,
- 0x0B30,0x0B32,0x0B33,0x0B36,0x0B39,0x0B3D,0x0B3D,0x0B5C,0x0B5D,0x0B5F,
- 0x0B61,0x0B85,0x0B8A,0x0B8E,0x0B90,0x0B92,0x0B95,0x0B99,0x0B9A,0x0B9C,
- 0x0B9C,0x0B9E,0x0B9F,0x0BA3,0x0BA4,0x0BA8,0x0BAA,0x0BAE,0x0BB5,0x0BB7,
- 0x0BB9,0x0C05,0x0C0C,0x0C0E,0x0C10,0x0C12,0x0C28,0x0C2A,0x0C33,0x0C35,
- 0x0C39,0x0C60,0x0C61,0x0C85,0x0C8C,0x0C8E,0x0C90,0x0C92,0x0CA8,0x0CAA,
- 0x0CB3,0x0CB5,0x0CB9,0x0CDE,0x0CDE,0x0CE0,0x0CE1,0x0D05,0x0D0C,0x0D0E,
- 0x0D10,0x0D12,0x0D28,0x0D2A,0x0D39,0x0D60,0x0D61,0x0E01,0x0E2E,0x0E30,
- 0x0E30,0x0E32,0x0E33,0x0E40,0x0E45,0x0E81,0x0E82,0x0E84,0x0E84,0x0E87,
- 0x0E88,0x0E8A,0x0E8A,0x0E8D,0x0E8D,0x0E94,0x0E97,0x0E99,0x0E9F,0x0EA1,
- 0x0EA3,0x0EA5,0x0EA5,0x0EA7,0x0EA7,0x0EAA,0x0EAB,0x0EAD,0x0EAE,0x0EB0,
- 0x0EB0,0x0EB2,0x0EB3,0x0EBD,0x0EBD,0x0EC0,0x0EC4,0x0F40,0x0F47,0x0F49,
- 0x0F69,0x10A0,0x10C5,0x10D0,0x10F6,0x1100,0x1100,0x1102,0x1103,0x1105,
- 0x1107,0x1109,0x1109,0x110B,0x110C,0x110E,0x1112,0x113C,0x113C,0x113E,
- 0x113E,0x1140,0x1140,0x114C,0x114C,0x114E,0x114E,0x1150,0x1150,0x1154,
- 0x1155,0x1159,0x1159,0x115F,0x1161,0x1163,0x1163,0x1165,0x1165,0x1167,
- 0x1167,0x1169,0x1169,0x116D,0x116E,0x1172,0x1173,0x1175,0x1175,0x119E,
- 0x119E,0x11A8,0x11A8,0x11AB,0x11AB,0x11AE,0x11AF,0x11B7,0x11B8,0x11BA,
- 0x11BA,0x11BC,0x11C2,0x11EB,0x11EB,0x11F0,0x11F0,0x11F9,0x11F9,0x1E00,
- 0x1E9B,0x1EA0,0x1EF9,0x1F00,0x1F15,0x1F18,0x1F1D,0x1F20,0x1F45,0x1F48,
- 0x1F4D,0x1F50,0x1F57,0x1F59,0x1F59,0x1F5B,0x1F5B,0x1F5D,0x1F5D,0x1F5F,
- 0x1F7D,0x1F80,0x1FB4,0x1FB6,0x1FBC,0x1FBE,0x1FBE,0x1FC2,0x1FC4,0x1FC6,
- 0x1FCC,0x1FD0,0x1FD3,0x1FD6,0x1FDB,0x1FE0,0x1FEC,0x1FF2,0x1FF4,0x1FF6,
- 0x1FFC,0x2126,0x2126,0x212A,0x212B,0x212E,0x212E,0x2180,0x2182,0x3041,
- 0x3094,0x30A1,0x30FA,0x3105,0x312C,0xAC00,0xD7A3];
- immutable IdeographicTable=[0x3007,0x3007,0x3021,0x3029,0x4E00,0x9FA5];
- immutable CombiningCharTable=[0x0300,0x0345,0x0360,0x0361,0x0483,0x0486,
- 0x0591,0x05A1,0x05A3,0x05B9,0x05BB,0x05BD,0x05BF,0x05BF,0x05C1,0x05C2,
- 0x05C4,0x05C4,0x064B,0x0652,0x0670,0x0670,0x06D6,0x06DC,0x06DD,0x06DF,
- 0x06E0,0x06E4,0x06E7,0x06E8,0x06EA,0x06ED,0x0901,0x0903,0x093C,0x093C,
- 0x093E,0x094C,0x094D,0x094D,0x0951,0x0954,0x0962,0x0963,0x0981,0x0983,
- 0x09BC,0x09BC,0x09BE,0x09BE,0x09BF,0x09BF,0x09C0,0x09C4,0x09C7,0x09C8,
- 0x09CB,0x09CD,0x09D7,0x09D7,0x09E2,0x09E3,0x0A02,0x0A02,0x0A3C,0x0A3C,
- 0x0A3E,0x0A3E,0x0A3F,0x0A3F,0x0A40,0x0A42,0x0A47,0x0A48,0x0A4B,0x0A4D,
- 0x0A70,0x0A71,0x0A81,0x0A83,0x0ABC,0x0ABC,0x0ABE,0x0AC5,0x0AC7,0x0AC9,
- 0x0ACB,0x0ACD,0x0B01,0x0B03,0x0B3C,0x0B3C,0x0B3E,0x0B43,0x0B47,0x0B48,
- 0x0B4B,0x0B4D,0x0B56,0x0B57,0x0B82,0x0B83,0x0BBE,0x0BC2,0x0BC6,0x0BC8,
- 0x0BCA,0x0BCD,0x0BD7,0x0BD7,0x0C01,0x0C03,0x0C3E,0x0C44,0x0C46,0x0C48,
- 0x0C4A,0x0C4D,0x0C55,0x0C56,0x0C82,0x0C83,0x0CBE,0x0CC4,0x0CC6,0x0CC8,
- 0x0CCA,0x0CCD,0x0CD5,0x0CD6,0x0D02,0x0D03,0x0D3E,0x0D43,0x0D46,0x0D48,
- 0x0D4A,0x0D4D,0x0D57,0x0D57,0x0E31,0x0E31,0x0E34,0x0E3A,0x0E47,0x0E4E,
- 0x0EB1,0x0EB1,0x0EB4,0x0EB9,0x0EBB,0x0EBC,0x0EC8,0x0ECD,0x0F18,0x0F19,
- 0x0F35,0x0F35,0x0F37,0x0F37,0x0F39,0x0F39,0x0F3E,0x0F3E,0x0F3F,0x0F3F,
- 0x0F71,0x0F84,0x0F86,0x0F8B,0x0F90,0x0F95,0x0F97,0x0F97,0x0F99,0x0FAD,
- 0x0FB1,0x0FB7,0x0FB9,0x0FB9,0x20D0,0x20DC,0x20E1,0x20E1,0x302A,0x302F,
- 0x3099,0x3099,0x309A,0x309A];
- immutable DigitTable=[0x0030,0x0039,0x0660,0x0669,0x06F0,0x06F9,0x0966,
- 0x096F,0x09E6,0x09EF,0x0A66,0x0A6F,0x0AE6,0x0AEF,0x0B66,0x0B6F,0x0BE7,
- 0x0BEF,0x0C66,0x0C6F,0x0CE6,0x0CEF,0x0D66,0x0D6F,0x0E50,0x0E59,0x0ED0,
- 0x0ED9,0x0F20,0x0F29];
- immutable ExtenderTable=[0x00B7,0x00B7,0x02D0,0x02D0,0x02D1,0x02D1,0x0387,
- 0x0387,0x0640,0x0640,0x0E46,0x0E46,0x0EC6,0x0EC6,0x3005,0x3005,0x3031,
- 0x3035,0x309D,0x309E,0x30FC,0x30FE];
-
- bool lookup(const(int)[] table, int c) @safe @nogc nothrow pure
- {
- while (table.length != 0)
- {
- auto m = (table.length >> 1) & ~1;
- if (c < table[m])
- {
- table = table[0 .. m];
- }
- else if (c > table[m+1])
- {
- table = table[m+2..$];
- }
- else return true;
- }
- return false;
- }
-
- string startOf(string s) @safe nothrow pure
- {
- string r;
- foreach (char c;s)
- {
- r ~= (c < 0x20 || c > 0x7F) ? '.' : c;
- if (r.length >= 40) { r ~= "___"; break; }
- }
- return r;
- }
-
- void exit(string s=null)
- {
- throw new XMLException(s);
- }
-}
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 7908837..ca7ab98 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,42 @@
+2022-09-26 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/ptr_traits.h (__ptr_traits_elem) [__cpp_concepts]:
+ Also define the __ptr_traits_elem class template for the
+ concepts case.
+ (pointer_traits<Ptr>): Remove constrained partial
+ specialization.
+ * testsuite/20_util/pointer_traits/lwg3545.cc: Check for
+ ambiguitiy with program-defined partial specialization.
+
+2022-09-26 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/type_traits (is_convertible, is_convertible_v):
+ Define using new built-in.
+ (is_nothrow_convertible is_nothrow_convertible_v): Likewise.
+
+2022-09-26 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/107037
+ * include/std/bitset (_Base_bitset::_M_do_reset): Use
+ preprocessor conditional around non-C++03 code.
+ * testsuite/20_util/bitset/107037.cc: New test.
+
+2022-09-24 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/alloc_traits.h (allocator_traits::is_always_equal):
+ Only instantiate is_empty if needed.
+ * include/bits/ptr_traits.h (__ptr_traits_impl::difference_type)
+ (__ptr_traits_impl::rebind): Use __detected_or.
+ * include/experimental/type_traits (is_same_v): Add a partial
+ specialization instead of instantiating the std::is_same class
+ template.
+ (detected_t): Redefine in terms of detected_or_t.
+ (is_detected, is_detected_v): Redefine in terms of detected_t.
+ * include/std/type_traits [__cpp_concepts] (__detected_or): Add
+ new definition using concepts.
+ (__detector::value_t): Rename to __is_detected.
+ * testsuite/17_intro/names.cc: Check value_t isn't used.
+
2022-09-23 Jonathan Wakely <jwakely@redhat.com>
* testsuite/20_util/is_assignable/requirements/access.cc:
diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h
index 507e8f1..8479bfd 100644
--- a/libstdc++-v3/include/bits/alloc_traits.h
+++ b/libstdc++-v3/include/bits/alloc_traits.h
@@ -74,7 +74,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
using __pocs = typename _Tp::propagate_on_container_swap;
template<typename _Tp>
- using __equal = typename _Tp::is_always_equal;
+ using __equal = __type_identity<typename _Tp::is_always_equal>;
};
template<typename _Alloc, typename _Up>
@@ -209,7 +209,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* otherwise @c is_empty<Alloc>::type
*/
using is_always_equal
- = __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>;
+ = typename __detected_or_t<is_empty<_Alloc>, __equal, _Alloc>::type;
template<typename _Tp>
using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h
index 8360c3b..71370ff 100644
--- a/libstdc++-v3/include/bits/ptr_traits.h
+++ b/libstdc++-v3/include/bits/ptr_traits.h
@@ -73,25 +73,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __replace_first_arg<_SomeTemplate<_Tp, _Types...>, _Up>
{ using type = _SomeTemplate<_Up, _Types...>; };
-#if __cpp_concepts
- // When concepts are supported detection of _Ptr::element_type is done
- // by a requires-clause, so __ptr_traits_elem_t only needs to do this:
- template<typename _Ptr>
- using __ptr_traits_elem_t = typename __get_first_arg<_Ptr>::type;
-#else
// Detect the element type of a pointer-like type.
template<typename _Ptr, typename = void>
struct __ptr_traits_elem : __get_first_arg<_Ptr>
{ };
// Use _Ptr::element_type if is a valid type.
+#if __cpp_concepts
+ template<typename _Ptr> requires requires { typename _Ptr::element_type; }
+ struct __ptr_traits_elem<_Ptr, void>
+ { using type = typename _Ptr::element_type; };
+#else
template<typename _Ptr>
struct __ptr_traits_elem<_Ptr, __void_t<typename _Ptr::element_type>>
{ using type = typename _Ptr::element_type; };
+#endif
template<typename _Ptr>
using __ptr_traits_elem_t = typename __ptr_traits_elem<_Ptr>::type;
-#endif
/// @endcond
@@ -144,29 +143,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __ptr_traits_impl : __ptr_traits_ptr_to<_Ptr, _Elt>
{
private:
- template<typename _Tp, typename = void>
- struct __difference { using type = ptrdiff_t; };
-
template<typename _Tp>
-#if __cpp_concepts
- requires requires { typename _Tp::difference_type; }
- struct __difference<_Tp>
-#else
- struct __difference<_Tp, __void_t<typename _Tp::difference_type>>
-#endif
- { using type = typename _Tp::difference_type; };
-
- template<typename _Tp, typename _Up, typename = void>
- struct __rebind : __replace_first_arg<_Tp, _Up> { };
+ using __diff_t = typename _Tp::difference_type;
template<typename _Tp, typename _Up>
-#if __cpp_concepts
- requires requires { typename _Tp::template rebind<_Up>; }
- struct __rebind<_Tp, _Up>
-#else
- struct __rebind<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up>>>
-#endif
- { using type = typename _Tp::template rebind<_Up>; };
+ using __rebind = __type_identity<typename _Tp::template rebind<_Up>>;
public:
/// The pointer type.
@@ -176,11 +157,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using element_type = _Elt;
/// The type used to represent the difference between two pointers.
- using difference_type = typename __difference<_Ptr>::type;
+ using difference_type = __detected_or_t<ptrdiff_t, __diff_t, _Ptr>;
/// A pointer to a different type.
template<typename _Up>
- using rebind = typename __rebind<_Ptr, _Up>::type;
+ using rebind = typename __detected_or_t<__replace_first_arg<_Ptr, _Up>,
+ __rebind, _Ptr, _Up>::type;
};
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@@ -199,13 +181,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct pointer_traits : __ptr_traits_impl<_Ptr, __ptr_traits_elem_t<_Ptr>>
{ };
-#if __cpp_concepts
- template<typename _Ptr> requires requires { typename _Ptr::element_type; }
- struct pointer_traits<_Ptr>
- : __ptr_traits_impl<_Ptr, typename _Ptr::element_type>
- { };
-#endif
-
/**
* @brief Partial specialization for built-in pointers.
* @headerfile memory
diff --git a/libstdc++-v3/include/bits/std_function.h b/libstdc++-v3/include/bits/std_function.h
index 96918a0..f5423a3 100644
--- a/libstdc++-v3/include/bits/std_function.h
+++ b/libstdc++-v3/include/bits/std_function.h
@@ -697,12 +697,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
{ using type = _Res(_Args...); };
+#if __cpp_static_call_operator >= 202207L && __cpp_concepts >= 202002L
+ template<typename _StaticCallOp>
+ struct __function_guide_static_helper
+ { };
+
+ template<typename _Res, bool _Nx, typename... _Args>
+ struct __function_guide_static_helper<_Res (*) (_Args...) noexcept(_Nx)>
+ { using type = _Res(_Args...); };
+
+ template<typename _Fn, typename _Op>
+ using __function_guide_t = typename __conditional_t<
+ requires (_Fn& __f) { (void) __f.operator(); },
+ __function_guide_static_helper<_Op>,
+ __function_guide_helper<_Op>>::type;
+#else
+ template<typename _Fn, typename _Op>
+ using __function_guide_t = typename __function_guide_helper<_Op>::type;
+#endif
+
template<typename _Res, typename... _ArgTypes>
function(_Res(*)(_ArgTypes...)) -> function<_Res(_ArgTypes...)>;
- template<typename _Functor, typename _Signature = typename
- __function_guide_helper<decltype(&_Functor::operator())>::type>
- function(_Functor) -> function<_Signature>;
+ template<typename _Fn, typename _Signature
+ = __function_guide_t<_Fn, decltype(&_Fn::operator())>>
+ function(_Fn) -> function<_Signature>;
#endif
// [20.7.15.2.6] null pointer comparisons
diff --git a/libstdc++-v3/include/experimental/type_traits b/libstdc++-v3/include/experimental/type_traits
index af5970e..fa25a1c 100644
--- a/libstdc++-v3/include/experimental/type_traits
+++ b/libstdc++-v3/include/experimental/type_traits
@@ -223,7 +223,9 @@ template <typename _Tp, unsigned _Idx = 0>
// See C++14 20.10.6, type relations
template <typename _Tp, typename _Up>
- constexpr bool is_same_v = is_same<_Tp, _Up>::value;
+ constexpr bool is_same_v = false;
+template <typename _Tp>
+ constexpr bool is_same_v<_Tp, _Tp> = true;
template <typename _Base, typename _Derived>
constexpr bool is_base_of_v = is_base_of<_Base, _Derived>::value;
template <typename _From, typename _To>
@@ -266,23 +268,21 @@ struct nonesuch : private __nonesuchbase
};
#pragma GCC diagnostic pop
-template<template<typename...> class _Op, typename... _Args>
- using is_detected
- = typename std::__detector<nonesuch, void, _Op, _Args...>::value_t;
-
-template<template<typename...> class _Op, typename... _Args>
- constexpr bool is_detected_v = is_detected<_Op, _Args...>::value;
-
-template<template<typename...> class _Op, typename... _Args>
- using detected_t
- = typename std::__detector<nonesuch, void, _Op, _Args...>::type;
-
template<typename _Default, template<typename...> class _Op, typename... _Args>
using detected_or = std::__detected_or<_Default, _Op, _Args...>;
template<typename _Default, template<typename...> class _Op, typename... _Args>
using detected_or_t = typename detected_or<_Default, _Op, _Args...>::type;
+template<template<typename...> class _Op, typename... _Args>
+ using detected_t = detected_or_t<nonesuch, _Op, _Args...>;
+
+template<template<typename...> class _Op, typename... _Args>
+ using is_detected = typename detected_or<void, _Op, _Args...>::__is_detected;
+
+template<template<typename...> class _Op, typename... _Args>
+ constexpr bool is_detected_v = is_detected<_Op, _Args...>::value;
+
template<typename _Expected, template<typename...> class _Op, typename... _Args>
using is_detected_exact = is_same<_Expected, detected_t<_Op, _Args...>>;
diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset
index 6dbc58c..1a551cf 100644
--- a/libstdc++-v3/include/std/bitset
+++ b/libstdc++-v3/include/std/bitset
@@ -182,13 +182,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX14_CONSTEXPR void
_M_do_reset() _GLIBCXX_NOEXCEPT
{
+#if __cplusplus >= 201402L
if (__builtin_is_constant_evaluated())
{
for (_WordT& __w : _M_w)
__w = 0;
return;
}
-
+#endif
__builtin_memset(_M_w, 0, _Nw * sizeof(_WordT));
}
@@ -1680,7 +1681,7 @@ _GLIBCXX_END_NAMESPACE_VERSION
#endif // C++11
-#ifdef _GLIBCXX_DEBUG && _GLIBCXX_HOSTED
+#if defined _GLIBCXX_DEBUG && _GLIBCXX_HOSTED
# include <debug/bitset>
#endif
diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future
index a1b2d7f..cf08c15 100644
--- a/libstdc++-v3/include/std/future
+++ b/libstdc++-v3/include/std/future
@@ -1649,8 +1649,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Res, typename... _ArgTypes>
packaged_task(_Res(*)(_ArgTypes...)) -> packaged_task<_Res(_ArgTypes...)>;
- template<typename _Fun, typename _Signature = typename
- __function_guide_helper<decltype(&_Fun::operator())>::type>
+ template<typename _Fun, typename _Signature
+ = __function_guide_t<_Fun, decltype(&_Fun::operator())>>
packaged_task(_Fun) -> packaged_task<_Signature>;
#endif
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 7c63531..1ac8051 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -1381,6 +1381,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public integral_constant<bool, __is_base_of(_Base, _Derived)>
{ };
+#if __has_builtin(__is_convertible)
+ template<typename _From, typename _To>
+ struct is_convertible
+ : public __bool_constant<__is_convertible(_From, _To)>
+ { };
+#else
template<typename _From, typename _To,
bool = __or_<is_void<_From>, is_function<_To>,
is_array<_To>>::value>
@@ -1416,12 +1422,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct is_convertible
: public __is_convertible_helper<_From, _To>::type
{ };
+#endif
// helper trait for unique_ptr<T[]>, shared_ptr<T[]>, and span<T, N>
template<typename _ToElementType, typename _FromElementType>
using __is_array_convertible
= is_convertible<_FromElementType(*)[], _ToElementType(*)[]>;
+#if __cplusplus >= 202002L
+#define __cpp_lib_is_nothrow_convertible 201806L
+
+#if __has_builtin(__is_nothrow_convertible)
+ /// is_nothrow_convertible_v
+ template<typename _From, typename _To>
+ inline constexpr bool is_nothrow_convertible_v
+ = __is_nothrow_convertible(_From, _To);
+
+ /// is_nothrow_convertible
+ template<typename _From, typename _To>
+ struct is_nothrow_convertible
+ : public bool_constant<is_nothrow_convertible_v<_From, _To>>
+ { };
+#else
template<typename _From, typename _To,
bool = __or_<is_void<_From>, is_function<_To>,
is_array<_To>>::value>
@@ -1451,8 +1473,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
#pragma GCC diagnostic pop
-#if __cplusplus > 201703L
-#define __cpp_lib_is_nothrow_convertible 201806L
/// is_nothrow_convertible
template<typename _From, typename _To>
struct is_nothrow_convertible
@@ -1463,6 +1483,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _From, typename _To>
inline constexpr bool is_nothrow_convertible_v
= is_nothrow_convertible<_From, _To>::value;
+#endif
#endif // C++2a
// Const-volatile modifications.
@@ -2551,13 +2572,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// @cond undocumented
+ // Detection idiom.
+ // Detect whether _Op<_Args...> is a valid type, use default _Def if not.
+
+#if __cpp_concepts
+ // Implementation of the detection idiom (negative case).
+ template<typename _Def, template<typename...> class _Op, typename... _Args>
+ struct __detected_or
+ {
+ using type = _Def;
+ using __is_detected = false_type;
+ };
+
+ // Implementation of the detection idiom (positive case).
+ template<typename _Def, template<typename...> class _Op, typename... _Args>
+ requires requires { typename _Op<_Args...>; }
+ struct __detected_or<_Def, _Op, _Args...>
+ {
+ using type = _Op<_Args...>;
+ using __is_detected = true_type;
+ };
+#else
/// Implementation of the detection idiom (negative case).
template<typename _Default, typename _AlwaysVoid,
template<typename...> class _Op, typename... _Args>
struct __detector
{
- using value_t = false_type;
using type = _Default;
+ using __is_detected = false_type;
};
/// Implementation of the detection idiom (positive case).
@@ -2565,14 +2607,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename... _Args>
struct __detector<_Default, __void_t<_Op<_Args...>>, _Op, _Args...>
{
- using value_t = true_type;
using type = _Op<_Args...>;
+ using __is_detected = true_type;
};
- // Detect whether _Op<_Args...> is a valid type, use _Default if not.
template<typename _Default, template<typename...> class _Op,
typename... _Args>
using __detected_or = __detector<_Default, void, _Op, _Args...>;
+#endif // __cpp_concepts
// _Op<_Args...> if that is a valid type, otherwise _Default.
template<typename _Default, template<typename...> class _Op,
@@ -3244,7 +3286,7 @@ template <typename _Tp>
template <typename _Base, typename _Derived>
inline constexpr bool is_base_of_v = __is_base_of(_Base, _Derived);
template <typename _From, typename _To>
- inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value;
+ inline constexpr bool is_convertible_v = __is_convertible(_From, _To);
template<typename _Fn, typename... _Args>
inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value;
template<typename _Fn, typename... _Args>
diff --git a/libstdc++-v3/testsuite/17_intro/names.cc b/libstdc++-v3/testsuite/17_intro/names.cc
index 82e201c..6490cd6 100644
--- a/libstdc++-v3/testsuite/17_intro/names.cc
+++ b/libstdc++-v3/testsuite/17_intro/names.cc
@@ -112,6 +112,7 @@
#define tmp (
#define sz (
#define token (
+#define value_t (
#if __cplusplus < 201103L
#define uses_allocator (
diff --git a/libstdc++-v3/testsuite/20_util/bitset/107037.cc b/libstdc++-v3/testsuite/20_util/bitset/107037.cc
new file mode 100644
index 0000000..b4560dd
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bitset/107037.cc
@@ -0,0 +1,7 @@
+// { dg-options "-std=c++03" }
+// { dg-do compile }
+// PR libstdc++/107037 bitset::_M_do_reset fails for strict -std=c++03 mode
+#include <bitset>
+template class std::bitset<0>;
+template class std::bitset<1>;
+template class std::bitset<100>;
diff --git a/libstdc++-v3/testsuite/20_util/function/cons/deduction_c++23.cc b/libstdc++-v3/testsuite/20_util/function/cons/deduction_c++23.cc
new file mode 100644
index 0000000..17454ea
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/function/cons/deduction_c++23.cc
@@ -0,0 +1,23 @@
+// { dg-options "-std=gnu++23" }
+// { dg-do compile { target c++23 } }
+
+#include <functional>
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+ typename require_same<T, U>::type
+ check_type(U&) { }
+
+void
+test_static_call_operator()
+{
+ struct F1 { static long operator()() { return 0; } };
+ std::function func1 = F1{};
+ check_type<std::function<long()>>(func1);
+
+ struct F2 { static float operator()(char, void*) noexcept { return 0; } };
+ std::function func2 = F2{};
+ check_type<std::function<float(char, void*)>>(func2);
+}
diff --git a/libstdc++-v3/testsuite/20_util/pointer_traits/lwg3545.cc b/libstdc++-v3/testsuite/20_util/pointer_traits/lwg3545.cc
index 08c3ed0..93c64a3 100644
--- a/libstdc++-v3/testsuite/20_util/pointer_traits/lwg3545.cc
+++ b/libstdc++-v3/testsuite/20_util/pointer_traits/lwg3545.cc
@@ -99,3 +99,20 @@ static_assert( is_same<pointer<Ctraits>, clever_ptr<char>>::value, "" );
static_assert( is_same<difference_type<Ctraits>, std::ptrdiff_t>::value, "" );
static_assert( is_same<rebind<Ctraits>, clever_ptr<short>>::value, "" );
static_assert( is_same<pointer_to<Ctraits>, clever_ptr<char>>::value, "" );
+
+#ifdef __cpp_concepts
+struct ptr_base { };
+
+// Program-defined specialization must not be ambiguous with primary template.
+template<typename P> requires std::derived_from<P, ptr_base>
+struct std::pointer_traits<P>
+{
+ using element_type = int;
+ using difference_type = long;
+ using pointer = P;
+};
+
+struct Ptr : ptr_base { using element_type = int; };
+
+using E = std::pointer_traits<Ptr>::element_type;
+#endif
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/deduction_c++23.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/deduction_c++23.cc
new file mode 100644
index 0000000..e36edfa0
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/deduction_c++23.cc
@@ -0,0 +1,23 @@
+// { dg-options "-std=gnu++23" }
+// { dg-do compile { target c++23 } }
+
+#include <future>
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+ typename require_same<T, U>::type
+ check_type(U&) { }
+
+void
+test_static_call_operator()
+{
+ struct F1 { static long operator()() { return 0; } };
+ std::packaged_task task1{ F1{} };
+ check_type<std::packaged_task<long()>>(task1);
+
+ struct F2 { static float operator()(char, void*) noexcept { return 0; } };
+ std::packaged_task task2{ F2{} };
+ check_type<std::packaged_task<float(char, void*)>>(task2);
+}