public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/ibuclaw/heads/gdc)] Import dmd v2.097.0: dmd 2a48c54ad, druntime c3a4c517, phobos 61c00065a
@ 2021-07-30 8:44 Iain Buclaw
0 siblings, 0 replies; only message in thread
From: Iain Buclaw @ 2021-07-30 8:44 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:7881f57cd49ca75ac8da796be150e65474a76e3c
commit 7881f57cd49ca75ac8da796be150e65474a76e3c
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date: Sat Apr 24 01:35:50 2021 +0200
Import dmd v2.097.0: dmd 2a48c54ad, druntime c3a4c517, phobos 61c00065a
Diff:
---
gcc/d/Make-lang.in | 4 +-
gcc/d/d-attribs.cc | 1 +
gcc/d/d-builtins.cc | 21 +-
gcc/d/d-codegen.cc | 42 +-
gcc/d/d-compiler.cc | 14 +-
gcc/d/d-convert.cc | 71 +-
gcc/d/d-frontend.cc | 2 +-
gcc/d/d-lang.cc | 59 +-
gcc/d/d-target.cc | 97 +-
gcc/d/d-target.def | 17 -
gcc/d/decl.cc | 67 +-
gcc/d/dmd/MERGE | 2 +-
gcc/d/dmd/README.md | 8 +-
gcc/d/dmd/VERSION | 2 +-
gcc/d/dmd/access.d | 79 +-
gcc/d/dmd/aggregate.d | 63 +-
gcc/d/dmd/aggregate.h | 74 +-
gcc/d/dmd/aliasthis.d | 53 +-
gcc/d/dmd/aliasthis.h | 2 +-
gcc/d/dmd/apply.d | 82 +-
gcc/d/dmd/arrayop.d | 3 +-
gcc/d/dmd/arraytypes.d | 5 +-
gcc/d/dmd/arraytypes.h | 5 +
gcc/d/dmd/ast_node.d | 2 +-
gcc/d/dmd/astcodegen.d | 17 +-
gcc/d/dmd/astenums.d | 347 +
gcc/d/dmd/attrib.d | 212 +-
gcc/d/dmd/attrib.h | 39 +-
gcc/d/dmd/blockexit.d | 5 +-
gcc/d/dmd/builtin.d | 2 +-
gcc/d/dmd/canthrow.d | 3 +-
gcc/d/dmd/chkformat.d | 210 +-
gcc/d/dmd/clone.d | 510 +-
gcc/d/dmd/compiler.d | 5 +-
gcc/d/dmd/compiler.h | 3 -
gcc/d/dmd/complex.d | 2 +-
gcc/d/dmd/cond.d | 63 +-
gcc/d/dmd/cond.h | 4 +-
gcc/d/dmd/constfold.d | 10 +-
gcc/d/dmd/cparse.d | 4052 +++++++
gcc/d/dmd/cppmangle.d | 598 +-
gcc/d/dmd/ctfeexpr.d | 11 +-
gcc/d/dmd/ctorflow.d | 2 +-
gcc/d/dmd/dcast.d | 599 +-
gcc/d/dmd/dclass.d | 38 +-
gcc/d/dmd/declaration.d | 300 +-
gcc/d/dmd/declaration.h | 76 +-
gcc/d/dmd/delegatize.d | 3 +-
gcc/d/dmd/denum.d | 81 +-
gcc/d/dmd/dimport.d | 73 +-
gcc/d/dmd/dinterpret.d | 235 +-
gcc/d/dmd/dmacro.d | 2 +-
gcc/d/dmd/dmangle.d | 292 +-
gcc/d/dmd/dmodule.d | 317 +-
gcc/d/dmd/doc.d | 67 +-
gcc/d/dmd/dscope.d | 127 +-
gcc/d/dmd/dstruct.d | 88 +-
gcc/d/dmd/dsymbol.d | 350 +-
gcc/d/dmd/dsymbol.h | 29 +-
gcc/d/dmd/dsymbolsem.d | 1709 ++-
gcc/d/dmd/dtemplate.d | 553 +-
gcc/d/dmd/dtoh.d | 2528 +++--
gcc/d/dmd/dversion.d | 6 +-
gcc/d/dmd/entity.d | 2 +-
gcc/d/dmd/enum.h | 8 +-
gcc/d/dmd/errors.d | 94 +-
gcc/d/dmd/errors.h | 4 +-
gcc/d/dmd/escape.d | 117 +-
gcc/d/dmd/expression.d | 179 +-
gcc/d/dmd/expression.h | 59 +-
gcc/d/dmd/expressionsem.d | 715 +-
gcc/d/dmd/foreachvar.d | 3 +-
gcc/d/dmd/func.d | 186 +-
gcc/d/dmd/globals.d | 341 +-
gcc/d/dmd/globals.h | 130 +-
gcc/d/dmd/gluelayer.d | 2 +-
gcc/d/dmd/hdrgen.d | 393 +-
gcc/d/dmd/iasm.d | 2 +-
gcc/d/dmd/iasmgcc.d | 35 +-
gcc/d/dmd/id.d | 21 +-
gcc/d/dmd/id.h | 2 +-
gcc/d/dmd/identifier.d | 2 +-
gcc/d/dmd/impcnvtab.d | 63 +-
gcc/d/dmd/imphint.d | 2 +-
gcc/d/dmd/import.h | 8 +-
gcc/d/dmd/init.d | 151 +-
gcc/d/dmd/init.h | 24 +
gcc/d/dmd/initsem.d | 615 +-
gcc/d/dmd/inline.d | 2 +-
gcc/d/dmd/intrange.d | 3 +-
gcc/d/dmd/json.d | 49 +-
gcc/d/dmd/lambdacomp.d | 3 +-
gcc/d/dmd/lexer.d | 585 +-
gcc/d/dmd/module.h | 6 +-
gcc/d/dmd/mtype.d | 564 +-
gcc/d/dmd/mtype.h | 82 +-
gcc/d/dmd/nogc.d | 3 +-
gcc/d/dmd/nspace.d | 12 +-
gcc/d/dmd/nspace.h | 2 +-
gcc/d/dmd/ob.d | 7 +-
gcc/d/dmd/objc.d | 155 +-
gcc/d/dmd/objc.h | 7 +-
gcc/d/dmd/opover.d | 53 +-
gcc/d/dmd/optimize.d | 53 +-
gcc/d/dmd/parse.d | 1815 ++--
gcc/d/dmd/parsetimevisitor.d | 6 +-
gcc/d/dmd/printast.d | 73 +-
gcc/d/dmd/root/aav.d | 2 +-
gcc/d/dmd/root/array.d | 37 +-
gcc/d/dmd/root/array.h | 28 +-
gcc/d/dmd/root/bitarray.d | 27 +-
gcc/d/dmd/root/bitarray.h | 4 +-
gcc/d/dmd/root/ctfloat.d | 6 +-
gcc/d/dmd/root/ctfloat.h | 2 +-
gcc/d/dmd/root/dcompat.h | 12 +
gcc/d/dmd/root/file.d | 564 +-
gcc/d/dmd/root/file.h | 2 +-
gcc/d/dmd/root/filename.d | 184 +-
gcc/d/dmd/root/filename.h | 3 +-
gcc/d/dmd/root/hash.d | 2 +-
gcc/d/dmd/root/longdouble.d | 2 +-
gcc/d/dmd/root/object.h | 2 +-
gcc/d/dmd/root/outbuffer.d | 145 +-
gcc/d/dmd/root/outbuffer.h | 6 +-
gcc/d/dmd/root/port.d | 2 +-
gcc/d/dmd/root/port.h | 2 +-
gcc/d/dmd/root/region.d | 10 +-
gcc/d/dmd/root/rmem.d | 246 +-
gcc/d/dmd/root/rmem.h | 4 +-
gcc/d/dmd/root/root.h | 2 +-
gcc/d/dmd/root/rootobject.d | 3 +-
gcc/d/dmd/root/speller.d | 273 +-
gcc/d/dmd/root/string.d | 4 +-
gcc/d/dmd/root/stringtable.d | 31 +-
gcc/d/dmd/safe.d | 15 +-
gcc/d/dmd/sapply.d | 17 +-
gcc/d/dmd/scope.h | 80 +-
gcc/d/dmd/semantic2.d | 411 +-
gcc/d/dmd/semantic3.d | 326 +-
gcc/d/dmd/sideeffect.d | 32 +-
gcc/d/dmd/statement.d | 156 +-
gcc/d/dmd/statement.h | 83 +-
gcc/d/dmd/statement_rewrite_walker.d | 2 +-
gcc/d/dmd/statementsem.d | 1382 +--
gcc/d/dmd/staticassert.d | 4 +-
gcc/d/dmd/staticassert.h | 2 +-
gcc/d/dmd/staticcond.d | 2 +-
gcc/d/dmd/stmtstate.d | 2 +-
gcc/d/dmd/target.d | 168 +-
gcc/d/dmd/target.h | 102 +-
gcc/d/dmd/template.h | 25 +-
gcc/d/dmd/templateparamsem.d | 56 +-
gcc/d/dmd/tokens.d | 157 +-
gcc/d/dmd/tokens.h | 33 +-
gcc/d/dmd/traits.d | 182 +-
gcc/d/dmd/transitivevisitor.d | 101 +-
gcc/d/dmd/typesem.d | 384 +-
gcc/d/dmd/typinf.d | 2 +-
gcc/d/dmd/utf.d | 2 +-
gcc/d/dmd/utils.d | 76 +-
gcc/d/dmd/version.h | 4 +-
gcc/d/dmd/visitor.d | 10 +-
gcc/d/dmd/visitor.h | 13 +-
gcc/d/expr.cc | 158 +-
gcc/d/imports.cc | 6 +-
gcc/d/intrinsics.def | 97 +-
gcc/d/lang.opt | 23 +-
gcc/d/modules.cc | 13 +-
gcc/d/toir.cc | 16 +-
gcc/d/typeinfo.cc | 36 +-
gcc/d/types.cc | 71 +-
gcc/doc/tm.texi.in | 4 -
gcc/testsuite/gdc.dg/Wcastresult2.d | 2 +-
gcc/testsuite/gdc.dg/imports/gdc170.d | 8 +-
gcc/testsuite/gdc.dg/intrinsics.d | 26 +-
gcc/testsuite/gdc.dg/pr98277.d | 2 +-
gcc/testsuite/gdc.dg/pr98457.d | 6 +-
gcc/testsuite/gdc.dg/torture/gdc309.d | 1 +
gcc/testsuite/gdc.dg/torture/pr94777b.d | 97 -
gcc/testsuite/gdc.test/compilable/aliasassign.d | 41 +
gcc/testsuite/gdc.test/compilable/b12504.d | 20 +
gcc/testsuite/gdc.test/compilable/b21285.d | 27 +
gcc/testsuite/gdc.test/compilable/callconv.d | 8 -
gcc/testsuite/gdc.test/compilable/checkimports3.d | 6 -
gcc/testsuite/gdc.test/compilable/compile1.d | 5 +
gcc/testsuite/gdc.test/compilable/cppmangle.d | 46 +-
gcc/testsuite/gdc.test/compilable/cppmangle3.d | 8 +-
gcc/testsuite/gdc.test/compilable/ctfe_math.d | 8 +-
gcc/testsuite/gdc.test/compilable/ddoc15475.d | 3 -
gcc/testsuite/gdc.test/compilable/depsOutput9948.d | 23 -
gcc/testsuite/gdc.test/compilable/diag12598.d | 3 -
gcc/testsuite/gdc.test/compilable/dip22d.d | 6 -
.../gdc.test/compilable/dtoh_AliasDeclaration.d | 127 +-
.../gdc.test/compilable/dtoh_AliasDeclaration_98.d | 56 +
.../gdc.test/compilable/dtoh_AnonDeclaration.d | 37 +-
.../compilable/dtoh_CPPNamespaceDeclaration.d | 28 +
.../gdc.test/compilable/dtoh_ClassDeclaration.d | 132 +-
.../gdc.test/compilable/dtoh_StructDeclaration.d | 86 +-
.../gdc.test/compilable/dtoh_TemplateDeclaration.d | 368 +-
.../gdc.test/compilable/dtoh_UnionDeclaration.d | 93 +
.../gdc.test/compilable/dtoh_VarDeclaration.d | 66 +-
.../gdc.test/compilable/dtoh_cpp98_compat.d | 142 +
gcc/testsuite/gdc.test/compilable/dtoh_enum.d | 104 +-
.../gdc.test/compilable/dtoh_enum_cpp98.d | 78 +-
.../gdc.test/compilable/dtoh_expressions.d | 127 +
.../gdc.test/compilable/dtoh_extern_type.d | 115 +-
.../gdc.test/compilable/dtoh_forwarding.d | 257 +
gcc/testsuite/gdc.test/compilable/dtoh_functions.d | 199 +-
gcc/testsuite/gdc.test/compilable/dtoh_ignored.d | 147 +
.../gdc.test/compilable/dtoh_invalid_identifiers.d | 170 +
gcc/testsuite/gdc.test/compilable/dtoh_names.d | 260 +
.../gdc.test/compilable/dtoh_protection.d | 218 +
.../gdc.test/compilable/dtoh_required_symbols.d | 225 +
.../gdc.test/compilable/dtoh_special_enum.d | 90 +
.../gdc.test/compilable/dtoh_unittest_block.d | 29 +
gcc/testsuite/gdc.test/compilable/dtoh_verbose.d | 141 +-
gcc/testsuite/gdc.test/compilable/dtorfields.d | 3 +
.../gdc.test/compilable/dtorfields_deprecation.d | 49 +
| 13 +
| 3 +
| 17 -
| 24 +-
gcc/testsuite/gdc.test/compilable/fix21647.d | 10 +-
gcc/testsuite/gdc.test/compilable/ice20415.d | 16 +
.../gdc.test/compilable/imports/cstuff3.c | 6 +
.../gdc.test/compilable/imports/depsOutput9948a.d | 6 -
.../gdc.test/compilable/imports/depsOutput9948b.d | 6 -
gcc/testsuite/gdc.test/compilable/interpret3.d | 46 -
gcc/testsuite/gdc.test/compilable/isZeroInit.d | 7 -
.../gdc.test/compilable/isreturnonstack.d | 1 +
gcc/testsuite/gdc.test/compilable/issue15478.d | 36 +-
gcc/testsuite/gdc.test/compilable/issue21726.d | 1 +
gcc/testsuite/gdc.test/compilable/json.d | 29 +-
gcc/testsuite/gdc.test/compilable/mixintype2.d | 9 -
gcc/testsuite/gdc.test/compilable/noreturn1.d | 49 +-
gcc/testsuite/gdc.test/compilable/ob1.d | 4 +-
gcc/testsuite/gdc.test/compilable/previewin.d | 53 +-
.../gdc.test/compilable/readmodify_structclass.d | 7 +-
gcc/testsuite/gdc.test/compilable/riia_ctor.d | 1 +
gcc/testsuite/gdc.test/compilable/scope.d | 139 +
gcc/testsuite/gdc.test/compilable/shared.d | 16 +
.../gdc.test/compilable/sw_transition_complex.d | 6 +-
gcc/testsuite/gdc.test/compilable/test11292.d | 5 -
gcc/testsuite/gdc.test/compilable/test1170.d | 6 -
gcc/testsuite/gdc.test/compilable/test15019.d | 4 +-
gcc/testsuite/gdc.test/compilable/test1537.d | 8 +-
gcc/testsuite/gdc.test/compilable/test15371.d | 10 -
gcc/testsuite/gdc.test/compilable/test1547.d | 5 -
gcc/testsuite/gdc.test/compilable/test15856.d | 6 -
gcc/testsuite/gdc.test/compilable/test16002.d | 3 -
gcc/testsuite/gdc.test/compilable/test17419.d | 5 -
gcc/testsuite/gdc.test/compilable/test17752.d | 5 -
gcc/testsuite/gdc.test/compilable/test17791.d | 9 -
gcc/testsuite/gdc.test/compilable/test19227.d | 8 +
gcc/testsuite/gdc.test/compilable/test19731.d | 78 +
gcc/testsuite/gdc.test/compilable/test19754.d | 2 +-
gcc/testsuite/gdc.test/compilable/test19809.d | 7 +-
gcc/testsuite/gdc.test/compilable/test20051.d | 7 -
gcc/testsuite/gdc.test/compilable/test20063.d | 15 -
gcc/testsuite/gdc.test/compilable/test20100.d | 13 +-
gcc/testsuite/gdc.test/compilable/test20136.d | 6 -
gcc/testsuite/gdc.test/compilable/test20406.d | 5 -
gcc/testsuite/gdc.test/compilable/test20835.d | 15 +
gcc/testsuite/gdc.test/compilable/test21217.d | 54 -
gcc/testsuite/gdc.test/compilable/test324.d | 11 -
gcc/testsuite/gdc.test/compilable/test9029.d | 7 -
gcc/testsuite/gdc.test/compilable/test9278a.d | 2 +-
gcc/testsuite/gdc.test/compilable/test9278b.d | 2 +-
gcc/testsuite/gdc.test/compilable/test930.d | 6 -
gcc/testsuite/gdc.test/compilable/test9613.d | 2 +-
gcc/testsuite/gdc.test/compilable/test9701.d | 6 -
gcc/testsuite/gdc.test/compilable/testCpCtor.d | 5 +-
gcc/testsuite/gdc.test/compilable/testInference.d | 6 -
.../gdc.test/compilable/testcheckimports.d | 8 -
gcc/testsuite/gdc.test/compilable/testcstuff1.c | 499 +
gcc/testsuite/gdc.test/compilable/testcstuff2.c | 313 +
gcc/testsuite/gdc.test/compilable/testcstuff3.d | 4 +
gcc/testsuite/gdc.test/compilable/testexpression.d | 24 -
| 4 -
gcc/testsuite/gdc.test/compilable/testparse.d | 12 +
gcc/testsuite/gdc.test/compilable/traits.d | 119 +-
gcc/testsuite/gdc.test/compilable/vcg-ast.d | 17 +
gcc/testsuite/gdc.test/compilable/vtemplates.d | 6 +-
.../gdc.test/compilable/vtemplates_list.d | 17 +-
.../gdc.test/fail_compilation/aliasassign.d | 21 +
.../gdc.test/fail_compilation/aliasassign1.d | 34 +
gcc/testsuite/gdc.test/fail_compilation/b15909.d | 15 +
gcc/testsuite/gdc.test/fail_compilation/b19523.d | 3 +-
gcc/testsuite/gdc.test/fail_compilation/b20780.d | 8 +-
gcc/testsuite/gdc.test/fail_compilation/b3841.d | 42 +-
gcc/testsuite/gdc.test/fail_compilation/b6227.d | 4 +-
gcc/testsuite/gdc.test/fail_compilation/bug15613.d | 3 -
gcc/testsuite/gdc.test/fail_compilation/bug16165.d | 6 -
gcc/testsuite/gdc.test/fail_compilation/bug18743.d | 6 +-
gcc/testsuite/gdc.test/fail_compilation/bug9631.d | 28 +-
gcc/testsuite/gdc.test/fail_compilation/cconst1.c | 21 +
.../gdc.test/fail_compilation/checkimports2a.d | 32 -
.../gdc.test/fail_compilation/checkimports2b.d | 29 -
.../gdc.test/fail_compilation/checkimports2c.d | 29 -
.../gdc.test/fail_compilation/chkformat.d | 7 -
.../gdc.test/fail_compilation/cppmangle.d | 12 +-
gcc/testsuite/gdc.test/fail_compilation/dassert.d | 43 +
.../gdc.test/fail_compilation/ddoc_18083.d | 6 +-
.../fail_compilation/debugCaseDeclaration.d | 39 +
.../fail_compilation/deprecate_objc_interface.d | 13 -
.../gdc.test/fail_compilation/deprecations.d | 11 +-
.../gdc.test/fail_compilation/diag10169.d | 4 -
.../gdc.test/fail_compilation/diag12380.d | 2 +-
.../gdc.test/fail_compilation/diag12829.d | 2 +-
.../gdc.test/fail_compilation/diag13215.d | 12 +
.../gdc.test/fail_compilation/diag14145.d | 38 +
.../gdc.test/fail_compilation/diag14875.d | 15 +-
.../gdc.test/fail_compilation/diag15411.d | 4 +-
gcc/testsuite/gdc.test/fail_compilation/diag1730.d | 26 +-
.../gdc.test/fail_compilation/diag21883.d | 16 +
gcc/testsuite/gdc.test/fail_compilation/diag4596.d | 4 +-
gcc/testsuite/gdc.test/fail_compilation/diag5385.d | 11 -
gcc/testsuite/gdc.test/fail_compilation/diag6707.d | 2 +-
gcc/testsuite/gdc.test/fail_compilation/diag8044.d | 19 +
gcc/testsuite/gdc.test/fail_compilation/diag8101.d | 13 -
.../gdc.test/fail_compilation/diag8101b.d | 14 +-
gcc/testsuite/gdc.test/fail_compilation/diag8178.d | 2 +-
gcc/testsuite/gdc.test/fail_compilation/diag8318.d | 27 +-
gcc/testsuite/gdc.test/fail_compilation/diag9831.d | 2 +-
.../fail_compilation/diag_debug_conditional.d | 11 +
.../fail_compilation/diag_template_alias.d | 11 +
.../gdc.test/fail_compilation/diag_template_this.d | 11 +
gcc/testsuite/gdc.test/fail_compilation/diagin.d | 8 +-
gcc/testsuite/gdc.test/fail_compilation/dip22a.d | 9 -
gcc/testsuite/gdc.test/fail_compilation/dip22b.d | 4 -
gcc/testsuite/gdc.test/fail_compilation/dip22e.d | 4 -
| 6 -
gcc/testsuite/gdc.test/fail_compilation/fail101.d | 3 +-
.../gdc.test/fail_compilation/fail10528.d | 11 -
gcc/testsuite/gdc.test/fail_compilation/fail109.d | 7 -
.../gdc.test/fail_compilation/fail10905.d | 3 -
.../gdc.test/fail_compilation/fail10968.d | 21 +-
.../gdc.test/fail_compilation/fail11355.d | 6 +-
.../gdc.test/fail_compilation/fail11445.d | 4 -
.../gdc.test/fail_compilation/fail11552.d | 2 +-
.../gdc.test/fail_compilation/fail11717.d | 14 -
.../gdc.test/fail_compilation/fail11720.d | 33 -
gcc/testsuite/gdc.test/fail_compilation/fail134.d | 5 +-
.../gdc.test/fail_compilation/fail15616b.d | 3 -
.../gdc.test/fail_compilation/fail16001.d | 13 +
.../gdc.test/fail_compilation/fail16206a.d | 12 -
.../gdc.test/fail_compilation/fail16206b.d | 12 -
.../gdc.test/fail_compilation/fail16689.d | 14 +
.../gdc.test/fail_compilation/fail17382.d | 9 -
.../gdc.test/fail_compilation/fail17602.d | 2 +-
.../gdc.test/fail_compilation/fail17955.d | 2 +-
.../gdc.test/fail_compilation/fail18143.d | 11 -
.../gdc.test/fail_compilation/fail18266.d | 28 -
.../gdc.test/fail_compilation/fail18719.d | 13 -
.../gdc.test/fail_compilation/fail18970.d | 11 +-
.../gdc.test/fail_compilation/fail18994.d | 2 +-
.../gdc.test/fail_compilation/fail19103.d | 16 +-
.../gdc.test/fail_compilation/fail19107.d | 21 -
gcc/testsuite/gdc.test/fail_compilation/fail196.d | 34 -
.../gdc.test/fail_compilation/fail20108.d | 14 +-
.../gdc.test/fail_compilation/fail20183.d | 18 +
.../gdc.test/fail_compilation/fail20714.d | 32 +
.../gdc.test/fail_compilation/fail20965.d | 27 +
.../gdc.test/fail_compilation/fail21092.d | 27 +
.../gdc.test/fail_compilation/fail21227.d | 20 -
.../gdc.test/fail_compilation/fail21508.d | 18 +
.../gdc.test/fail_compilation/fail21508_2.d | 11 +
.../gdc.test/fail_compilation/fail21547.d | 34 +
gcc/testsuite/gdc.test/fail_compilation/fail217.d | 4 -
.../gdc.test/fail_compilation/fail21830.d | 34 +
.../gdc.test/fail_compilation/fail21831.d | 29 +
.../gdc.test/fail_compilation/fail21832.d | 21 +
.../gdc.test/fail_compilation/fail21849.d | 36 +
.../gdc.test/fail_compilation/fail21885.d | 25 +
.../gdc.test/fail_compilation/fail21928.d | 19 +
.../gdc.test/fail_compilation/fail21928b.d | 19 +
.../gdc.test/fail_compilation/fail22035.d | 11 +
.../gdc.test/fail_compilation/fail22084.d | 23 +
gcc/testsuite/gdc.test/fail_compilation/fail222.d | 9 +-
gcc/testsuite/gdc.test/fail_compilation/fail241.d | 4 +-
gcc/testsuite/gdc.test/fail_compilation/fail2450.d | 7 +-
gcc/testsuite/gdc.test/fail_compilation/fail246.d | 2 +-
gcc/testsuite/gdc.test/fail_compilation/fail247.d | 2 +-
gcc/testsuite/gdc.test/fail_compilation/fail2789.d | 11 +-
gcc/testsuite/gdc.test/fail_compilation/fail3.d | 4 -
gcc/testsuite/gdc.test/fail_compilation/fail303.d | 15 +-
gcc/testsuite/gdc.test/fail_compilation/fail313.d | 6 -
gcc/testsuite/gdc.test/fail_compilation/fail324.d | 17 -
gcc/testsuite/gdc.test/fail_compilation/fail332.d | 4 -
gcc/testsuite/gdc.test/fail_compilation/fail341.d | 6 +-
gcc/testsuite/gdc.test/fail_compilation/fail347.d | 6 -
gcc/testsuite/gdc.test/fail_compilation/fail3753.d | 48 -
gcc/testsuite/gdc.test/fail_compilation/fail3882.d | 6 +-
.../gdc.test/fail_compilation/fail4375a.d | 4 +-
.../gdc.test/fail_compilation/fail4375b.d | 4 +-
.../gdc.test/fail_compilation/fail4375c.d | 4 +-
.../gdc.test/fail_compilation/fail4375d.d | 4 +-
.../gdc.test/fail_compilation/fail4375e.d | 4 +-
.../gdc.test/fail_compilation/fail4375f.d | 4 +-
.../gdc.test/fail_compilation/fail4375g.d | 4 +-
.../gdc.test/fail_compilation/fail4375h.d | 4 +-
.../gdc.test/fail_compilation/fail4375i.d | 4 +-
.../gdc.test/fail_compilation/fail4375j.d | 4 +-
.../gdc.test/fail_compilation/fail4375k.d | 4 +-
.../gdc.test/fail_compilation/fail4375l.d | 4 +-
.../gdc.test/fail_compilation/fail4375m.d | 4 +-
.../gdc.test/fail_compilation/fail4375o.d | 4 +-
.../gdc.test/fail_compilation/fail4375r.d | 4 +-
.../gdc.test/fail_compilation/fail4375s.d | 4 +-
.../gdc.test/fail_compilation/fail4375t.d | 4 +-
.../gdc.test/fail_compilation/fail4375u.d | 4 +-
.../gdc.test/fail_compilation/fail4375v.d | 4 +-
.../gdc.test/fail_compilation/fail4375w.d | 4 +-
.../gdc.test/fail_compilation/fail4375x.d | 4 +-
.../gdc.test/fail_compilation/fail4375y.d | 4 +-
gcc/testsuite/gdc.test/fail_compilation/fail47.d | 13 -
gcc/testsuite/gdc.test/fail_compilation/fail5435.d | 14 -
gcc/testsuite/gdc.test/fail_compilation/fail5634.d | 10 -
gcc/testsuite/gdc.test/fail_compilation/fail6334.d | 3 +-
gcc/testsuite/gdc.test/fail_compilation/fail6795.d | 35 +-
gcc/testsuite/gdc.test/fail_compilation/fail7173.d | 2 +-
gcc/testsuite/gdc.test/fail_compilation/fail7352.d | 52 +
gcc/testsuite/gdc.test/fail_compilation/fail79.d | 4 -
gcc/testsuite/gdc.test/fail_compilation/fail9346.d | 9 +-
gcc/testsuite/gdc.test/fail_compilation/fail9613.d | 2 +-
.../gdc.test/fail_compilation/fail_arrayop2.d | 6 +-
.../gdc.test/fail_compilation/fail_contracts3.d | 8 -
.../gdc.test/fail_compilation/fail_scope.d | 4 +-
.../gdc.test/fail_compilation/failcstuff1.c | 103 +
.../gdc.test/fail_compilation/failcstuff2.c | 86 +
gcc/testsuite/gdc.test/fail_compilation/failob2.d | 67 +
gcc/testsuite/gdc.test/fail_compilation/fob2.d | 15 +
gcc/testsuite/gdc.test/fail_compilation/goto2.d | 93 +
gcc/testsuite/gdc.test/fail_compilation/ice10212.d | 2 +-
gcc/testsuite/gdc.test/fail_compilation/ice10770.d | 13 -
gcc/testsuite/gdc.test/fail_compilation/ice10938.d | 3 +-
gcc/testsuite/gdc.test/fail_compilation/ice11552.d | 2 +-
gcc/testsuite/gdc.test/fail_compilation/ice11822.d | 7 +-
gcc/testsuite/gdc.test/fail_compilation/ice11967.d | 10 -
gcc/testsuite/gdc.test/fail_compilation/ice13385.d | 2 +-
gcc/testsuite/gdc.test/fail_compilation/ice14446.d | 13 -
gcc/testsuite/gdc.test/fail_compilation/ice14907.d | 10 -
gcc/testsuite/gdc.test/fail_compilation/ice20042.d | 2 +-
gcc/testsuite/gdc.test/fail_compilation/ice8255.d | 18 -
gcc/testsuite/gdc.test/fail_compilation/ice8511.d | 13 -
gcc/testsuite/gdc.test/fail_compilation/ice9759.d | 2 +-
.../gdc.test/fail_compilation/imports/imp21832.d | 24 +
.../fail_compilation/imports/import21508.d | 2 +
.../gdc.test/fail_compilation/issue20704.d | 39 +
.../gdc.test/fail_compilation/issue21203.d | 17 +
.../gdc.test/fail_compilation/issue21378.d | 16 +
.../gdc.test/fail_compilation/issue21936.d | 32 +
gcc/testsuite/gdc.test/fail_compilation/lookup.d | 7 -
.../gdc.test/fail_compilation/mixintype2.d | 7 -
.../gdc.test/fail_compilation/nestedtempl1.d | 4 +-
.../gdc.test/fail_compilation/nestedtempl2.d | 12 +-
gcc/testsuite/gdc.test/fail_compilation/noreturn.d | 118 +
.../gdc.test/fail_compilation/parseStc2.d | 4 +-
.../gdc.test/fail_compilation/pragmainline.d | 5 +-
gcc/testsuite/gdc.test/fail_compilation/pragmas.d | 3 +-
.../gdc.test/fail_compilation/previewin.d | 60 +-
.../gdc.test/fail_compilation/protattr1.d | 2 +-
.../gdc.test/fail_compilation/protattr2.d | 2 +-
.../gdc.test/fail_compilation/reserved_version.d | 57 +-
.../fail_compilation/reserved_version_switch.d | 3 +
gcc/testsuite/gdc.test/fail_compilation/retref2.d | 7 +-
gcc/testsuite/gdc.test/fail_compilation/retscope.d | 8 +-
.../gdc.test/fail_compilation/retscope6.d | 28 +
.../gdc.test/fail_compilation/test11176.d | 4 -
.../gdc.test/fail_compilation/test12385.d | 2 +-
.../gdc.test/fail_compilation/test12558.d | 49 +-
.../gdc.test/fail_compilation/test13667.d | 101 +
gcc/testsuite/gdc.test/fail_compilation/test143.d | 4 -
.../gdc.test/fail_compilation/test15117.d | 30 -
.../gdc.test/fail_compilation/test15306.d | 4 +-
.../gdc.test/fail_compilation/test15785.d | 4 -
.../gdc.test/fail_compilation/test15785b.d | 11 -
.../gdc.test/fail_compilation/test15897.d | 4 -
.../gdc.test/fail_compilation/test15925.d | 5 -
.../gdc.test/fail_compilation/test15989.d | 2 +-
.../gdc.test/fail_compilation/test16193.d | 2 +-
.../gdc.test/fail_compilation/test16228.d | 3 +-
.../gdc.test/fail_compilation/test17450.d | 2 +-
.../gdc.test/fail_compilation/test17451.d | 2 +-
.../gdc.test/fail_compilation/test18385.d | 2 +-
.../gdc.test/fail_compilation/test18385b.d | 47 +
.../gdc.test/fail_compilation/test19176.d | 3 +-
.../gdc.test/fail_compilation/test20324.d | 16 +
.../gdc.test/fail_compilation/test20549.d | 3 +-
.../gdc.test/fail_compilation/test20565.d | 19 +
.../gdc.test/fail_compilation/test21319.d | 12 +
.../gdc.test/fail_compilation/test21518.d | 38 +
.../gdc.test/fail_compilation/test21665.d | 31 +
.../gdc.test/fail_compilation/test21807.d | 54 +
.../gdc.test/fail_compilation/test22048.d | 10 +
gcc/testsuite/gdc.test/fail_compilation/test314.d | 4 -
gcc/testsuite/gdc.test/fail_compilation/test6883.d | 12 +-
.../gdc.test/fail_compilation/testpull1810.d | 4 +-
gcc/testsuite/gdc.test/fail_compilation/traits.d | 63 +-
.../gdc.test/fail_compilation/traits_child.d | 7 -
.../fail_compilation/union_initialization.d | 88 +
.../gdc.test/fail_compilation/warn13679.d | 4 +-
gcc/testsuite/gdc.test/runnable/aliasassign.d | 31 +
gcc/testsuite/gdc.test/runnable/b10562.d | 5 -
gcc/testsuite/gdc.test/runnable/builtin.d | 6 +-
gcc/testsuite/gdc.test/runnable/casting.d | 27 +-
gcc/testsuite/gdc.test/runnable/complex.d | 1165 +-
gcc/testsuite/gdc.test/runnable/constfold.d | 36 +-
gcc/testsuite/gdc.test/runnable/cppdtor.d | 143 +
gcc/testsuite/gdc.test/runnable/cstuff2.c | 254 +
gcc/testsuite/gdc.test/runnable/foreach4.d | 6 -
gcc/testsuite/gdc.test/runnable/foreach5.d | 40 +-
gcc/testsuite/gdc.test/runnable/funclit.d | 2 +-
gcc/testsuite/gdc.test/runnable/ice21696.d | 23 +
gcc/testsuite/gdc.test/runnable/ifti.d | 2 -
gcc/testsuite/gdc.test/runnable/imports/Other.d | 11 +-
.../gdc.test/runnable/imports/std15017variant.d | 2 +-
gcc/testsuite/gdc.test/runnable/interpret.d | 43 +-
gcc/testsuite/gdc.test/runnable/link15017.d | 1 +
gcc/testsuite/gdc.test/runnable/link6574.d | 16 -
gcc/testsuite/gdc.test/runnable/mangle.d | 15 +-
gcc/testsuite/gdc.test/runnable/mars1.d | 293 +-
gcc/testsuite/gdc.test/runnable/mixin1.d | 13 +-
gcc/testsuite/gdc.test/runnable/mixin2.d | 8 -
gcc/testsuite/gdc.test/runnable/nested.d | 4 -
gcc/testsuite/gdc.test/runnable/opover2.d | 5 +-
gcc/testsuite/gdc.test/runnable/overload.d | 36 +
gcc/testsuite/gdc.test/runnable/previewin.d | 41 +-
gcc/testsuite/gdc.test/runnable/property2.d | 8 -
gcc/testsuite/gdc.test/runnable/sdtor.d | 85 +-
gcc/testsuite/gdc.test/runnable/structlit.d | 14 +-
gcc/testsuite/gdc.test/runnable/template10.d | 754 --
gcc/testsuite/gdc.test/runnable/template4.d | 34 -
gcc/testsuite/gdc.test/runnable/template9.d | 22 +-
gcc/testsuite/gdc.test/runnable/test10619.d | 38 +
gcc/testsuite/gdc.test/runnable/test14874.d | 76 +-
gcc/testsuite/gdc.test/runnable/test15.d | 7 +-
gcc/testsuite/gdc.test/runnable/test16140.d | 32 +
gcc/testsuite/gdc.test/runnable/test17072.d | 2 +-
gcc/testsuite/gdc.test/runnable/test17373.d | 20 -
gcc/testsuite/gdc.test/runnable/test17965.d | 29 +
gcc/testsuite/gdc.test/runnable/test18772.d | 94 -
gcc/testsuite/gdc.test/runnable/test19122.d | 7 +-
gcc/testsuite/gdc.test/runnable/test19192.d | 18 +
gcc/testsuite/gdc.test/runnable/test19441.d | 6 +-
gcc/testsuite/gdc.test/runnable/test19774.d | 7 +-
gcc/testsuite/gdc.test/runnable/test19782.d | 5 +-
gcc/testsuite/gdc.test/runnable/test19822.d | 7 +-
gcc/testsuite/gdc.test/runnable/test20.d | 53 -
gcc/testsuite/gdc.test/runnable/test20025.d | 6 -
gcc/testsuite/gdc.test/runnable/test20565.d | 18 +
gcc/testsuite/gdc.test/runnable/test20855.d | 26 +
gcc/testsuite/gdc.test/runnable/test21357.d | 35 +
gcc/testsuite/gdc.test/runnable/test21403.d | 72 +
gcc/testsuite/gdc.test/runnable/test21424.d | 12 +
gcc/testsuite/gdc.test/runnable/test21479.d | 28 +
gcc/testsuite/gdc.test/runnable/test21515.d | 81 +
gcc/testsuite/gdc.test/runnable/test21586.d | 31 +
gcc/testsuite/gdc.test/runnable/test21822.d | 18 +
gcc/testsuite/gdc.test/runnable/test21833.d | 30 +
gcc/testsuite/gdc.test/runnable/test22.d | 294 -
gcc/testsuite/gdc.test/runnable/test23.d | 22 -
gcc/testsuite/gdc.test/runnable/test28.d | 27 -
gcc/testsuite/gdc.test/runnable/test34.d | 5 -
gcc/testsuite/gdc.test/runnable/test4.d | 44 +-
gcc/testsuite/gdc.test/runnable/test42.d | 39 -
gcc/testsuite/gdc.test/runnable/test6795.d | 26 +
gcc/testsuite/gdc.test/runnable/test711.d | 6 +-
gcc/testsuite/gdc.test/runnable/test8.d | 99 +-
gcc/testsuite/gdc.test/runnable/test809.d | 5 -
gcc/testsuite/gdc.test/runnable/testassert.d | 148 +
gcc/testsuite/gdc.test/runnable/testassign.d | 3 -
gcc/testsuite/gdc.test/runnable/testcgelem.d | 3 +-
gcc/testsuite/gdc.test/runnable/testclass.d | 40 +
gcc/testsuite/gdc.test/runnable/testconst.d | 2 +-
gcc/testsuite/gdc.test/runnable/testcontracts.d | 106 +-
gcc/testsuite/gdc.test/runnable/testdstress.d | 20 -
gcc/testsuite/gdc.test/runnable/testkeyword.d | 4 +-
gcc/testsuite/gdc.test/runnable/testsafe.d | 6 -
gcc/testsuite/gdc.test/runnable/testscope2.d | 6 +-
gcc/testsuite/gdc.test/runnable/testtypeid.d | 80 -
gcc/testsuite/gdc.test/runnable/traits.d | 55 -
.../gdc.test/runnable/traits_getPointerBitmap.d | 2 -
gcc/testsuite/gdc.test/runnable/uda.d | 4 -
gcc/testsuite/gdc.test/runnable/ufcs.d | 5 -
gcc/testsuite/gdc.test/runnable/uniformctor.d | 14 -
gcc/testsuite/gdc.test/runnable/xtest46.d | 12 -
.../gdc.test/runnable_cxx/cpp_abi_tests.d | 18 +
gcc/testsuite/gdc.test/runnable_cxx/cppa.d | 32 +-
gcc/testsuite/gdc.test/runnable_cxx/externmangle.d | 9 +
| 17 +
| 19 -
| 11 +
| 34 +
| 18 +-
gcc/testsuite/gdc.test/runnable_cxx/test20652.d | 23 +
gcc/testsuite/gdc.test/runnable_cxx/test21515.d | 1 +
gcc/testsuite/lib/gdc-utils.exp | 8 +-
libphobos/configure | 4 +-
libphobos/libdruntime/{LICENSE => LICENSE.txt} | 3 -
libphobos/libdruntime/MERGE | 2 +-
libphobos/libdruntime/Makefile.am | 180 +-
libphobos/libdruntime/Makefile.in | 584 +-
libphobos/libdruntime/__entrypoint.di | 56 -
libphobos/libdruntime/core/atomic.d | 76 +-
libphobos/libdruntime/core/attribute.d | 72 +
libphobos/libdruntime/core/bitop.d | 87 +-
libphobos/libdruntime/core/builtins.d | 19 +
libphobos/libdruntime/core/checkedint.d | 91 +-
libphobos/libdruntime/core/cpuid.d | 4 -
libphobos/libdruntime/core/demangle.d | 22 +-
libphobos/libdruntime/core/exception.d | 8 +-
libphobos/libdruntime/core/gc/gcinterface.d | 2 +-
.../libdruntime/core/internal/array/appending.d | 77 +-
.../libdruntime/core/internal/array/casting.d | 7 +-
.../libdruntime/core/internal/array/comparison.d | 10 +-
.../core/internal/array/concatenation.d | 2 +-
.../libdruntime/core/internal/array/construction.d | 109 +-
libphobos/libdruntime/core/internal/atomic.d | 8 +
.../{rt => core/internal}/backtrace/dwarf.d | 544 +-
.../{rt => core/internal}/backtrace/elf.d | 7 +-
.../libdruntime/core/internal/backtrace/handler.d | 133 +
.../core/internal/backtrace/libunwind.d | 157 +
.../{rt => core/internal}/backtrace/macho.d | 2 +-
.../libdruntime/core/internal/backtrace/unwind.d | 199 +
.../{rt/util => core/internal}/container/array.d | 4 +-
.../{rt/util => core/internal}/container/common.d | 11 +-
.../{rt/util => core/internal}/container/hashtab.d | 6 +-
.../{rt/util => core/internal}/container/treap.d | 37 +-
libphobos/libdruntime/core/internal/convert.d | 27 +-
libphobos/libdruntime/core/internal/dassert.d | 319 +-
libphobos/libdruntime/core/internal/elf/dl.d | 8 +-
libphobos/libdruntime/core/internal/elf/io.d | 5 +
.../libdruntime/{ => core/internal}/gc/bits.d | 10 +-
.../{ => core/internal}/gc/impl/conservative/gc.d | 140 +-
.../{ => core/internal}/gc/impl/manual/gc.d | 25 +-
.../{ => core/internal}/gc/impl/proto/gc.d | 26 +-
libphobos/libdruntime/{ => core/internal}/gc/os.d | 14 +-
.../libdruntime/{ => core/internal}/gc/pooltable.d | 4 +-
.../libdruntime/{ => core/internal}/gc/proxy.d | 31 +-
libphobos/libdruntime/core/internal/lifetime.d | 86 +-
.../libdruntime/{rt => core/internal}/qsort.d | 10 +-
libphobos/libdruntime/core/internal/string.d | 2 +-
libphobos/libdruntime/core/internal/traits.d | 237 +-
libphobos/libdruntime/core/internal/util/array.d | 14 +-
libphobos/libdruntime/core/internal/util/math.d | 53 +
libphobos/libdruntime/core/lifetime.d | 446 +-
libphobos/libdruntime/core/math.d | 12 -
libphobos/libdruntime/core/memory.d | 242 +-
libphobos/libdruntime/core/runtime.d | 140 +-
libphobos/libdruntime/core/simd.d | 209 -
libphobos/libdruntime/core/stdc/complex.d | 19 -
libphobos/libdruntime/core/stdc/math.d | 391 +-
libphobos/libdruntime/core/stdc/stdarg.d | 66 -
libphobos/libdruntime/core/stdc/stdint.d | 91 +-
libphobos/libdruntime/core/stdc/stdio.d | 4 -
libphobos/libdruntime/core/stdc/time.d | 4 -
libphobos/libdruntime/core/stdcpp/allocator.d | 26 +-
libphobos/libdruntime/core/stdcpp/exception.d | 32 +-
libphobos/libdruntime/core/stdcpp/new_.d | 5 +-
libphobos/libdruntime/core/stdcpp/string.d | 14 +
libphobos/libdruntime/core/stdcpp/typeinfo.d | 34 +-
libphobos/libdruntime/core/stdcpp/vector.d | 21 +-
libphobos/libdruntime/core/sync/barrier.d | 4 +-
libphobos/libdruntime/core/sync/condition.d | 18 +-
libphobos/libdruntime/core/sync/config.d | 8 +-
libphobos/libdruntime/core/sync/mutex.d | 14 +-
libphobos/libdruntime/core/sync/rwmutex.d | 40 +-
libphobos/libdruntime/core/sync/semaphore.d | 29 +-
libphobos/libdruntime/core/sys/darwin/dlfcn.d | 5 +
libphobos/libdruntime/core/sys/darwin/mach/dyld.d | 5 -
libphobos/libdruntime/core/sys/freebsd/sys/event.d | 7 -
libphobos/libdruntime/core/sys/freebsd/sys/mount.d | 17 -
libphobos/libdruntime/core/sys/linux/execinfo.d | 3 -
libphobos/libdruntime/core/sys/linux/sys/mman.d | 7 -
libphobos/libdruntime/core/sys/posix/arpa/inet.d | 60 +-
libphobos/libdruntime/core/sys/posix/dirent.d | 13 -
libphobos/libdruntime/core/sys/posix/dlfcn.d | 7 -
libphobos/libdruntime/core/sys/posix/locale.d | 58 -
libphobos/libdruntime/core/sys/posix/pthread.d | 4 -
libphobos/libdruntime/core/sys/posix/setjmp.d | 4 +
libphobos/libdruntime/core/sys/posix/signal.d | 28 -
libphobos/libdruntime/core/sys/posix/stdc/time.d | 4 -
libphobos/libdruntime/core/sys/posix/stdio.d | 21 +-
libphobos/libdruntime/core/sys/posix/sys/stat.d | 16 -
libphobos/libdruntime/core/sys/posix/sys/statvfs.d | 109 -
libphobos/libdruntime/core/sys/posix/ucontext.d | 7 -
libphobos/libdruntime/core/sys/windows/dll.d | 12 -
libphobos/libdruntime/core/sys/windows/stdc/time.d | 4 -
libphobos/libdruntime/core/thread/fiber.d | 38 -
libphobos/libdruntime/core/thread/osthread.d | 179 +-
libphobos/libdruntime/core/thread/threadbase.d | 55 +-
libphobos/libdruntime/core/time.d | 156 +-
libphobos/libdruntime/gcc/deh.d | 10 -
libphobos/libdruntime/gcc/emutls.d | 3 +-
libphobos/libdruntime/gcc/sections/elf.d | 6 +-
libphobos/libdruntime/gcc/sections/elf_shared.d | 1007 --
libphobos/libdruntime/gcc/sections/macho.d | 2 +-
libphobos/libdruntime/gcc/sections/pecoff.d | 2 +-
libphobos/libdruntime/gcc/sections/win32.d | 183 -
libphobos/libdruntime/gcc/sections/win64.d | 321 -
libphobos/libdruntime/object.d | 881 +-
libphobos/libdruntime/rt/aApplyR.d | 1 +
libphobos/libdruntime/rt/aaA.d | 58 +-
libphobos/libdruntime/rt/cast_.d | 1 +
libphobos/libdruntime/rt/critical_.d | 1 +
libphobos/libdruntime/rt/dmain2.d | 154 +-
libphobos/libdruntime/rt/ehalloc.d | 3 +-
libphobos/libdruntime/rt/invariant.d | 1 +
libphobos/libdruntime/rt/lifetime.d | 71 +-
libphobos/libdruntime/rt/minfo.d | 4 +-
libphobos/libdruntime/rt/monitor_.d | 1 +
libphobos/libdruntime/rt/profilegc.d | 2 +-
libphobos/libdruntime/rt/sections.d | 9 +
libphobos/libdruntime/rt/tlsgc.d | 1 +
libphobos/libdruntime/rt/util/random.d | 36 -
libphobos/libdruntime/rt/util/typeinfo.d | 294 +-
libphobos/libdruntime/rt/util/utility.d | 17 +
libphobos/src/MERGE | 2 +-
libphobos/src/Makefile.am | 26 +-
libphobos/src/Makefile.in | 93 +-
libphobos/src/index.d | 6 +-
libphobos/src/std/algorithm/comparison.d | 28 +-
libphobos/src/std/algorithm/iteration.d | 720 +-
libphobos/src/std/algorithm/mutation.d | 23 +-
libphobos/src/std/algorithm/package.d | 1 +
libphobos/src/std/algorithm/searching.d | 59 +-
libphobos/src/std/algorithm/sorting.d | 122 +-
libphobos/src/std/array.d | 135 +-
libphobos/src/std/base64.d | 131 +-
libphobos/src/std/bigint.d | 161 +-
libphobos/src/std/bitmanip.d | 545 +-
libphobos/src/std/complex.d | 483 +-
libphobos/src/std/concurrency.d | 103 +-
libphobos/src/std/container/array.d | 205 +-
libphobos/src/std/container/dlist.d | 12 +-
libphobos/src/std/container/package.d | 142 +-
libphobos/src/std/container/rbtree.d | 3 -
libphobos/src/std/conv.d | 2395 ++--
libphobos/src/std/csv.d | 37 +-
libphobos/src/std/datetime/date.d | 16 +-
libphobos/src/std/datetime/package.d | 581 -
libphobos/src/std/datetime/systime.d | 74 +-
libphobos/src/std/datetime/timezone.d | 42 +-
libphobos/src/std/digest/digest.d | 2 +-
libphobos/src/std/digest/hmac.d | 6 +-
libphobos/src/std/digest/md.d | 17 +-
libphobos/src/std/digest/package.d | 2 +-
libphobos/src/std/digest/ripemd.d | 49 +-
libphobos/src/std/encoding.d | 14 +-
libphobos/src/std/exception.d | 97 +-
.../allocator/building_blocks/affix_allocator.d | 4 +-
.../allocator/building_blocks/aligned_block_list.d | 4 +-
.../allocator/building_blocks/allocator_list.d | 26 +-
.../allocator/building_blocks/bitmapped_block.d | 8 +-
.../allocator/building_blocks/kernighan_ritchie.d | 3 +-
.../allocator/building_blocks/region.d | 7 +-
libphobos/src/std/experimental/allocator/common.d | 20 +-
libphobos/src/std/experimental/allocator/package.d | 57 +-
libphobos/src/std/experimental/allocator/typed.d | 2 +-
libphobos/src/std/experimental/checkedint.d | 189 +-
libphobos/src/std/experimental/logger/core.d | 20 +-
libphobos/src/std/experimental/logger/filelogger.d | 2 +-
libphobos/src/std/experimental/logger/nulllogger.d | 4 -
libphobos/src/std/experimental/typecons.d | 11 +-
libphobos/src/std/file.d | 254 +-
libphobos/src/std/format.d | 8476 ---------------
libphobos/src/std/format/internal/floats.d | 2930 +++++
libphobos/src/std/format/internal/read.d | 410 +
libphobos/src/std/format/internal/write.d | 3980 +++++++
libphobos/src/std/format/package.d | 1787 +++
libphobos/src/std/format/read.d | 721 ++
libphobos/src/std/format/spec.d | 949 ++
libphobos/src/std/format/write.d | 1289 +++
libphobos/src/std/functional.d | 196 +-
libphobos/src/std/getopt.d | 31 +-
libphobos/src/std/internal/cstring.d | 60 +-
libphobos/src/std/internal/math/biguintcore.d | 99 +-
libphobos/src/std/internal/math/errorfunction.d | 7 +-
libphobos/src/std/internal/math/gammafunction.d | 25 +-
libphobos/src/std/internal/memory.d | 4 +-
libphobos/src/std/internal/test/dummyrange.d | 6 +-
libphobos/src/std/json.d | 124 +-
libphobos/src/std/math.d | 10869 -------------------
libphobos/src/std/math/algebraic.d | 1079 ++
libphobos/src/std/math/constants.d | 38 +
libphobos/src/std/math/exponential.d | 3439 ++++++
libphobos/src/std/math/hardware.d | 1212 +++
libphobos/src/std/math/operations.d | 2010 ++++
libphobos/src/std/math/package.d | 494 +
libphobos/src/std/math/remainder.d | 155 +
libphobos/src/std/math/rounding.d | 1004 ++
libphobos/src/std/math/traits.d | 853 ++
libphobos/src/std/math/trigonometry.d | 1421 +++
libphobos/src/std/mathspecial.d | 6 +-
libphobos/src/std/meta.d | 103 +-
libphobos/src/std/mmfile.d | 7 +-
libphobos/src/std/net/isemail.d | 12 +-
libphobos/src/std/numeric.d | 507 +-
libphobos/src/std/outbuffer.d | 4 +-
libphobos/src/std/package.d | 1 +
libphobos/src/std/parallelism.d | 110 +-
libphobos/src/std/path.d | 22 +-
libphobos/src/std/process.d | 704 +-
libphobos/src/std/random.d | 62 +-
libphobos/src/std/range/package.d | 227 +-
libphobos/src/std/range/primitives.d | 42 +-
libphobos/src/std/regex/internal/backtracking.d | 24 +-
libphobos/src/std/regex/internal/generator.d | 2 +-
libphobos/src/std/regex/internal/ir.d | 117 +-
libphobos/src/std/regex/internal/parser.d | 2 +-
libphobos/src/std/regex/internal/tests.d | 4 -
libphobos/src/std/regex/internal/tests2.d | 216 +-
libphobos/src/std/regex/internal/thompson.d | 5 +-
libphobos/src/std/regex/package.d | 34 +-
libphobos/src/std/socket.d | 18 +-
libphobos/src/std/stdio.d | 729 +-
libphobos/src/std/string.d | 60 +-
libphobos/src/std/sumtype.d | 2477 +++++
libphobos/src/std/system.d | 5 +-
libphobos/src/std/traits.d | 574 +-
libphobos/src/std/typecons.d | 402 +-
libphobos/src/std/uni/package.d | 31 +-
libphobos/src/std/uri.d | 2 +-
libphobos/src/std/utf.d | 13 +-
libphobos/src/std/variant.d | 271 +-
libphobos/src/std/windows/syserror.d | 2 +-
libphobos/src/std/xml.d | 258 +-
libphobos/testsuite/libphobos.aa/test_aa.d | 60 +-
.../libphobos.allocations/alloc_from_assert.d | 25 +
.../testsuite/libphobos.exceptions/assert_fail.d | 295 +-
libphobos/testsuite/libphobos.gc/attributes.d | 30 +
libphobos/testsuite/libphobos.hash/test_hash.d | 33 +-
.../testsuite/libphobos.init_fini/custom_gc.d | 2 +-
.../large_aggregate_destroy_21097.d | 78 +
.../testsuite/libphobos.lifetime/lifetime.exp | 27 +
libphobos/testsuite/libphobos.thread/join_detach.d | 20 +
libphobos/testsuite/libphobos.typeinfo/enum_.d | 21 +
838 files changed, 65768 insertions(+), 42715 deletions(-)
diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in
index cb8c1c394db..320eda7e3ff 100644
--- a/gcc/d/Make-lang.in
+++ b/gcc/d/Make-lang.in
@@ -82,6 +82,7 @@ D_FRONTEND_OBJS = \
d/attrib.o \
d/ast_node.o \
d/astcodegen.o \
+ d/astenums.o \
d/bitarray.o \
d/blockexit.o \
d/builtin.o \
@@ -92,6 +93,7 @@ D_FRONTEND_OBJS = \
d/complex.o \
d/cond.o \
d/constfold.o \
+ d/cparse.o \
d/cppmangle.o \
d/ctfeexpr.o \
d/ctfloat.o \
@@ -215,7 +217,7 @@ d_OBJS = $(D_ALL_OBJS) d/d-spec.o
d21$(exeext): $(D_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS) $(d.prev)
@$(call LINK_PROGRESS,$(INDEX.d),start)
- +$(DLLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
+ +$(DLLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -static-libphobos -o $@ \
$(D_ALL_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
@$(call LINK_PROGRESS,$(INDEX.d),end)
diff --git a/gcc/d/d-attribs.cc b/gcc/d/d-attribs.cc
index 070866020a2..9fd3eaac862 100644
--- a/gcc/d/d-attribs.cc
+++ b/gcc/d/d-attribs.cc
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "dmd/attrib.h"
#include "dmd/declaration.h"
+#include "dmd/expression.h"
#include "dmd/module.h"
#include "dmd/mtype.h"
#include "dmd/template.h"
diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index a2260d971cd..ab3a950689f 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -99,7 +99,7 @@ build_frontend_type (tree type)
if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == char_type_node)
return Type::tchar->addMod (dtype->mod)->pointerTo ()->addMod (mod);
- if (dtype->ty == Tfunction)
+ if (dtype->ty == TY::Tfunction)
return (TypePointer::create (dtype))->addMod (mod);
return dtype->pointerTo ()->addMod (mod);
@@ -131,7 +131,7 @@ build_frontend_type (tree type)
/* For now, skip support for cent/ucent until the frontend
has better support for handling it. */
- for (size_t i = Tint8; i <= Tuns64; i++)
+ for (size_t i = (size_t) TY::Tint8; i <= (size_t) TY::Tuns64; i++)
{
dtype = Type::basic[i];
@@ -149,7 +149,7 @@ build_frontend_type (tree type)
{
unsigned size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
- for (size_t i = Tfloat32; i <= Tfloat80; i++)
+ for (size_t i = (size_t) TY::Tfloat32; i <= (size_t) TY::Tfloat80; i++)
{
dtype = Type::basic[i];
@@ -165,7 +165,8 @@ build_frontend_type (tree type)
case COMPLEX_TYPE:
{
unsigned size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
- for (size_t i = Tcomplex32; i <= Tcomplex80; i++)
+ for (size_t i = (size_t) TY::Tcomplex32; i <= (size_t) TY::Tcomplex80;
+ i++)
{
dtype = Type::basic[i];
@@ -236,7 +237,7 @@ build_frontend_type (tree type)
sdecl->structsize = int_size_in_bytes (type);
sdecl->alignsize = TYPE_ALIGN_UNIT (type);
sdecl->alignment = STRUCTALIGN_DEFAULT;
- sdecl->sizeok = SIZEOKdone;
+ sdecl->sizeok = Sizeok::done;
sdecl->type = (TypeStruct::create (sdecl))->addMod (mod);
sdecl->type->ctype = type;
sdecl->type->merge2 ();
@@ -328,7 +329,7 @@ build_frontend_type (tree type)
have no named parameters, and so can't be represented in D. */
if (args->length != 0 || varargs_p == VARARGnone)
{
- dtype = TypeFunction::create (args, dtype, varargs_p, LINKc);
+ dtype = TypeFunction::create (args, dtype, varargs_p, LINK::c);
return dtype->addMod (mod);
}
}
@@ -379,7 +380,7 @@ d_eval_constant_expression (const Loc &loc, tree cst)
else if (code == STRING_CST)
{
const void *string = TREE_STRING_POINTER (cst);
- size_t len = TREE_STRING_LENGTH (cst);
+ size_t len = TREE_STRING_LENGTH (cst) - 1;
return StringExp::create (loc, CONST_CAST (void *, string), len);
}
else if (code == VECTOR_CST)
@@ -461,7 +462,7 @@ d_init_versions (void)
VersionCondition::addPredefinedGlobalIdent ("GNU_InlineAsm");
/* LP64 only means 64bit pointers in D. */
- if (global.params.isLP64)
+ if (POINTER_SIZE == 64)
VersionCondition::addPredefinedGlobalIdent ("D_LP64");
/* Setting `global.params.cov' forces module info generation which is
@@ -659,7 +660,7 @@ d_build_builtins_module (Module *m)
members->push (build_alias_declaration ("__builtin_unwind_uint", t));
}
- m->members->push (LinkDeclaration::create (LINKc, members));
+ m->members->push (LinkDeclaration::create (Loc (), LINK::c, members));
}
/* Search for any `extern(C)' functions that match any known GCC library builtin
@@ -857,7 +858,7 @@ d_build_d_type_nodes (void)
/* Calling build_ctype() links the front-end Type to the GCC node,
and sets the TYPE_NAME to the D language type. */
- for (unsigned ty = 0; ty < TMAX; ty++)
+ for (unsigned ty = 0; ty < (unsigned) TY::TMAX; ty++)
{
if (Type::basic[ty] != NULL)
build_ctype (Type::basic[ty]);
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 8494d7ad639..18f8b75a616 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -75,7 +75,7 @@ d_decl_context (Dsymbol *dsym)
but only for extern(D) symbols. */
if (parent->isModule ())
{
- if ((decl != NULL && decl->linkage != LINKd)
+ if ((decl != NULL && decl->linkage != LINK::d)
|| (ad != NULL && ad->classKind != ClassKind::d))
return NULL_TREE;
@@ -130,7 +130,7 @@ declaration_reference_p (Declaration *decl)
Type *tb = decl->type->toBasetype ();
/* Declaration is a reference type. */
- if (tb->ty == Treference || decl->storage_class & (STCout | STCref))
+ if (tb->ty == TY::Treference || decl->storage_class & (STCout | STCref))
return true;
return false;
@@ -145,7 +145,7 @@ declaration_type (Declaration *decl)
if (decl->storage_class & STClazy)
{
TypeFunction *tf = TypeFunction::create (NULL, decl->type,
- VARARGnone, LINKd);
+ VARARGnone, LINK::d);
TypeDelegate *t = TypeDelegate::create (tf);
return build_ctype (t->merge2 ());
}
@@ -180,7 +180,7 @@ parameter_reference_p (Parameter *arg)
Type *tb = arg->type->toBasetype ();
/* Parameter is a reference type. */
- if (tb->ty == Treference || arg->storageClass & (STCout | STCref))
+ if (tb->ty == TY::Treference || arg->storageClass & (STCout | STCref))
return true;
return false;
@@ -195,7 +195,7 @@ parameter_type (Parameter *arg)
if (arg->storageClass & STClazy)
{
TypeFunction *tf = TypeFunction::create (NULL, arg->type,
- VARARGnone, LINKd);
+ VARARGnone, LINK::d);
TypeDelegate *t = TypeDelegate::create (tf);
return build_ctype (t->merge2 ());
}
@@ -318,10 +318,10 @@ get_array_length (tree exp, Type *type)
switch (tb->ty)
{
- case Tsarray:
+ case TY::Tsarray:
return size_int (tb->isTypeSArray ()->dim->toUInteger ());
- case Tarray:
+ case TY::Tarray:
return d_array_length (exp);
default:
@@ -410,7 +410,7 @@ build_delegate_cst (tree method, tree object, Type *type)
tree ctype;
Type *tb = type->toBasetype ();
- if (tb->ty == Tdelegate)
+ if (tb->ty == TY::Tdelegate)
ctype = build_ctype (type);
else
{
@@ -463,11 +463,11 @@ build_typeof_null_value (Type *type)
tree value;
/* For dynamic arrays, set length and pointer fields to zero. */
- if (tb->ty == Tarray)
+ if (tb->ty == TY::Tarray)
value = d_array_value (build_ctype (type), size_int (0), null_pointer_node);
/* For associative arrays, set the pointer field to null. */
- else if (tb->ty == Taarray)
+ else if (tb->ty == TY::Taarray)
{
tree ctype = build_ctype (type);
gcc_assert (TYPE_ASSOCIATIVE_ARRAY (ctype));
@@ -477,7 +477,7 @@ build_typeof_null_value (Type *type)
}
/* For delegates, set the frame and function pointer fields to null. */
- else if (tb->ty == Tdelegate)
+ else if (tb->ty == TY::Tdelegate)
value = build_delegate_cst (null_pointer_node, null_pointer_node, type);
/* Simple zero constant for all other types. */
@@ -881,7 +881,9 @@ identity_compare_p (StructDeclaration *sd)
}
/* Check for types that may have padding. */
- if ((tb->ty == Tcomplex80 || tb->ty == Tfloat80 || tb->ty == Timaginary80)
+ if ((tb->ty == TY::Tcomplex80
+ || tb->ty == TY::Tfloat80
+ || tb->ty == TY::Timaginary80)
&& target.realpad != 0)
return false;
@@ -959,12 +961,12 @@ lower_struct_comparison (tree_code code, StructDeclaration *sd,
/* Compare inner data structures. */
tcmp = lower_struct_comparison (code, ts->sym, t1ref, t2ref);
}
- else if (type->ty != Tvector && type->isintegral ())
+ else if (type->ty != TY::Tvector && type->isintegral ())
{
/* Integer comparison, no special handling required. */
tcmp = build_boolop (code, t1ref, t2ref);
}
- else if (type->ty != Tvector && type->isfloating ())
+ else if (type->ty != TY::Tvector && type->isfloating ())
{
/* Floating-point comparison, don't compare padding in type. */
if (!type->iscomplex ())
@@ -1894,7 +1896,7 @@ array_bounds_check (void)
case CHECKENABLEsafeonly:
/* For D2 safe functions only. */
fd = d_function_chain->function;
- if (fd && fd->type->ty == Tfunction)
+ if (fd && fd->type->ty == TY::Tfunction)
{
if (fd->type->isTypeFunction ()->trust == TRUST::safe)
return true;
@@ -1913,11 +1915,11 @@ TypeFunction *
get_function_type (Type *t)
{
TypeFunction *tf = NULL;
- if (t->ty == Tpointer)
+ if (t->ty == TY::Tpointer)
t = t->nextOf ()->toBasetype ();
- if (t->ty == Tfunction)
+ if (t->ty == TY::Tfunction)
tf = t->isTypeFunction ();
- else if (t->ty == Tdelegate)
+ else if (t->ty == TY::Tdelegate)
tf = t->isTypeDelegate ()->next->isTypeFunction ();
return tf;
}
@@ -1977,7 +1979,7 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
gcc_assert (FUNC_OR_METHOD_TYPE_P (ctype));
gcc_assert (tf != NULL);
- gcc_assert (tf->ty == Tfunction);
+ gcc_assert (tf->ty == TY::Tfunction);
if (TREE_CODE (ctype) != FUNCTION_TYPE && object == NULL_TREE)
{
@@ -2076,7 +2078,7 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
SET_EXPR_LOCATION (result, input_location);
/* Enforce left to right evaluation. */
- if (tf->linkage == LINKd)
+ if (tf->linkage == LINK::d)
CALL_EXPR_ARGS_ORDERED (result) = 1;
result = maybe_expand_intrinsic (result);
diff --git a/gcc/d/d-compiler.cc b/gcc/d/d-compiler.cc
index 44366988ba7..3df40073ac5 100644
--- a/gcc/d/d-compiler.cc
+++ b/gcc/d/d-compiler.cc
@@ -88,7 +88,7 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
/* Encode CST to buffer. */
int len = native_encode_expr (cst, buffer, sizeof (buffer));
- if (tb->ty == Tsarray)
+ if (tb->ty == TY::Tsarray)
{
/* Interpret value as a vector of the same size,
then return the array literal. */
@@ -126,22 +126,22 @@ Compiler::onParseModule (Module *m)
{
ModuleDeclaration *md = m->md;
- if (!md || !md->id || !md->packages)
+ if (!md || !md->id|| md->packages.length == 0)
{
Identifier *id = (md && md->id) ? md->id : m->ident;
if (!strcmp (id->toChars (), "object"))
create_tinfo_types (m);
}
- else if (md->packages->length == 1)
+ else if (md->packages.length == 1)
{
- if (!strcmp ((*md->packages)[0]->toChars (), "gcc")
+ if (!strcmp (md->packages.ptr[0]->toChars (), "gcc")
&& !strcmp (md->id->toChars (), "builtins"))
d_build_builtins_module (m);
}
- else if (md->packages->length == 2)
+ else if (md->packages.length == 2)
{
- if (!strcmp ((*md->packages)[0]->toChars (), "core")
- && !strcmp ((*md->packages)[1]->toChars (), "stdc"))
+ if (!strcmp (md->packages.ptr[0]->toChars (), "core")
+ && !strcmp (md->packages.ptr[1]->toChars (), "stdc"))
d_add_builtin_module (m);
}
}
diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc
index ae0b58efe18..0e030eca541 100644
--- a/gcc/d/d-convert.cc
+++ b/gcc/d/d-convert.cc
@@ -361,14 +361,14 @@ convert_expr (tree exp, Type *etype, Type *totype)
switch (ebtype->ty)
{
- case Tdelegate:
- if (tbtype->ty == Tdelegate)
+ case TY::Tdelegate:
+ if (tbtype->ty == TY::Tdelegate)
{
exp = d_save_expr (exp);
return build_delegate_cst (delegate_method (exp),
delegate_object (exp), totype);
}
- else if (tbtype->ty == Tpointer)
+ else if (tbtype->ty == TY::Tpointer)
{
/* The front-end converts <delegate>.ptr to cast (void *)<delegate>.
Maybe should only allow void* ? */
@@ -382,8 +382,8 @@ convert_expr (tree exp, Type *etype, Type *totype)
}
break;
- case Tstruct:
- if (tbtype->ty == Tstruct)
+ case TY::Tstruct:
+ if (tbtype->ty == TY::Tstruct)
{
if (totype->size () == etype->size ())
{
@@ -400,8 +400,8 @@ convert_expr (tree exp, Type *etype, Type *totype)
/* else, default conversion, which should produce an error. */
break;
- case Tclass:
- if (tbtype->ty == Tclass)
+ case TY::Tclass:
+ if (tbtype->ty == TY::Tclass)
{
ClassDeclaration *cdfrom = ebtype->isClassHandle ();
ClassDeclaration *cdto = tbtype->isClassHandle ();
@@ -460,12 +460,12 @@ convert_expr (tree exp, Type *etype, Type *totype)
/* else default conversion. */
break;
- case Tsarray:
- if (tbtype->ty == Tpointer)
+ case TY::Tsarray:
+ if (tbtype->ty == TY::Tpointer)
{
result = build_nop (build_ctype (totype), build_address (exp));
}
- else if (tbtype->ty == Tarray)
+ else if (tbtype->ty == TY::Tarray)
{
dinteger_t dim = ebtype->isTypeSArray ()->dim->toInteger ();
dinteger_t esize = ebtype->nextOf ()->size ();
@@ -490,12 +490,12 @@ convert_expr (tree exp, Type *etype, Type *totype)
return d_array_value (build_ctype (totype), size_int (dim),
build_nop (ptrtype, build_address (exp)));
}
- else if (tbtype->ty == Tsarray)
+ else if (tbtype->ty == TY::Tsarray)
{
/* D allows casting a static array to any static array type. */
return build_nop (build_ctype (totype), exp);
}
- else if (tbtype->ty == Tstruct)
+ else if (tbtype->ty == TY::Tstruct)
{
/* And allows casting a static array to any struct type too.
Type sizes should have already been checked by the frontend. */
@@ -510,12 +510,12 @@ convert_expr (tree exp, Type *etype, Type *totype)
}
break;
- case Tarray:
- if (tbtype->ty == Tpointer)
+ case TY::Tarray:
+ if (tbtype->ty == TY::Tpointer)
{
return d_convert (build_ctype (totype), d_array_ptr (exp));
}
- else if (tbtype->ty == Tarray)
+ else if (tbtype->ty == TY::Tarray)
{
/* Assume tvoid->size() == 1. */
d_uns64 fsize = ebtype->nextOf ()->toBasetype ()->size ();
@@ -543,7 +543,7 @@ convert_expr (tree exp, Type *etype, Type *totype)
return build_vconvert (build_ctype (totype), exp);
}
}
- else if (tbtype->ty == Tsarray)
+ else if (tbtype->ty == TY::Tsarray)
{
/* Strings are treated as dynamic arrays in D2. */
if (ebtype->isString () && tbtype->isString ())
@@ -557,23 +557,23 @@ convert_expr (tree exp, Type *etype, Type *totype)
}
break;
- case Taarray:
- if (tbtype->ty == Taarray)
+ case TY::Taarray:
+ if (tbtype->ty == TY::Taarray)
return build_vconvert (build_ctype (totype), exp);
/* Can convert associative arrays to void pointers. */
- else if (tbtype->ty == Tpointer && tbtype->nextOf ()->ty == Tvoid)
+ else if (tbtype->ty == TY::Tpointer && tbtype->nextOf ()->ty == TY::Tvoid)
return build_vconvert (build_ctype (totype), exp);
/* Else, default conversion, which should product an error. */
break;
- case Tpointer:
+ case TY::Tpointer:
/* Can convert void pointers to associative arrays too. */
- if (tbtype->ty == Taarray && ebtype->nextOf ()->ty == Tvoid)
+ if (tbtype->ty == TY::Taarray && ebtype->nextOf ()->ty == TY::Tvoid)
return build_vconvert (build_ctype (totype), exp);
break;
- case Tnull:
- case Tnoreturn:
+ case TY::Tnull:
+ case TY::Tnoreturn:
/* Casting from `typeof(null)' for `null' expressions, or `typeof(*null)'
for `noreturn' expressions is represented as all zeros. */
result = build_typeof_null_value (totype);
@@ -583,8 +583,8 @@ convert_expr (tree exp, Type *etype, Type *totype)
result = compound_expr (exp, result);
break;
- case Tvector:
- if (tbtype->ty == Tsarray)
+ case TY::Tvector:
+ if (tbtype->ty == TY::Tsarray)
{
if (tbtype->size () == ebtype->size ())
return build_vconvert (build_ctype (totype), exp);
@@ -624,7 +624,7 @@ convert_for_rvalue (tree expr, Type *etype, Type *totype)
switch (ebtype->ty)
{
- case Tbool:
+ case TY::Tbool:
/* If casting from bool, the result is either 0 or 1, any other value
violates @safe code, so enforce that it is never invalid. */
if (CONSTANT_CLASS_P (expr))
@@ -662,7 +662,7 @@ convert_for_assignment (tree expr, Type *etype, Type *totype)
/* Assuming this only has to handle converting a non Tsarray type to
arbitrarily dimensioned Tsarrays. */
- if (tbtype->ty == Tsarray)
+ if (tbtype->ty == TY::Tsarray)
{
Type *telem = tbtype->nextOf ()->baseElemOf ();
@@ -696,7 +696,7 @@ convert_for_assignment (tree expr, Type *etype, Type *totype)
}
/* D Front end uses IntegerExp(0) to mean zero-init an array or structure. */
- if ((tbtype->ty == Tsarray || tbtype->ty == Tstruct)
+ if ((tbtype->ty == TY::Tsarray || tbtype->ty == TY::Tstruct)
&& ebtype->isintegral ())
{
if (!integer_zerop (expr))
@@ -747,12 +747,12 @@ convert_for_condition (tree expr, Type *type)
switch (type->toBasetype ()->ty)
{
- case Taarray:
+ case TY::Taarray:
/* Checks that aa.ptr !is null. */
result = component_ref (expr, TYPE_FIELDS (TREE_TYPE (expr)));
break;
- case Tarray:
+ case TY::Tarray:
{
/* Checks (arr.length || arr.ptr) (i.e arr !is null). */
expr = d_save_expr (expr);
@@ -773,7 +773,7 @@ convert_for_condition (tree expr, Type *type)
break;
}
- case Tdelegate:
+ case TY::Tdelegate:
{
/* Checks (function || object), but what good is it if there is
a null function pointer? */
@@ -794,7 +794,7 @@ convert_for_condition (tree expr, Type *type)
break;
}
- case Tnoreturn:
+ case TY::Tnoreturn:
/* Front-end allows conditionals that never return, represent the
conditional result value as all zeros. */
result = build_zero_cst (d_bool_type);
@@ -821,10 +821,10 @@ d_array_convert (Expression *exp)
{
Type *tb = exp->type->toBasetype ();
- if (tb->ty == Tarray)
+ if (tb->ty == TY::Tarray)
return build_expr (exp);
- if (tb->ty == Tsarray)
+ if (tb->ty == TY::Tsarray)
{
Type *totype = tb->nextOf ()->arrayOf ();
return convert_expr (build_expr (exp), exp->type, totype);
@@ -843,7 +843,8 @@ d_array_convert (Type *etype, Expression *exp)
{
Type *tb = exp->type->toBasetype ();
- if ((tb->ty != Tarray && tb->ty != Tsarray) || same_type_p (tb, etype))
+ if ((tb->ty != TY::Tarray && tb->ty != TY::Tsarray)
+ || same_type_p (tb, etype))
{
/* Convert single element to an array. */
tree expr = build_expr (exp);
diff --git a/gcc/d/d-frontend.cc b/gcc/d/d-frontend.cc
index 256faeb6c13..522095f12c5 100644
--- a/gcc/d/d-frontend.cc
+++ b/gcc/d/d-frontend.cc
@@ -80,7 +80,7 @@ eval_builtin (Loc loc, FuncDeclaration *fd, Expressions *arguments)
Type *
getTypeInfoType (Loc loc, Type *type, Scope *sc)
{
- gcc_assert (type->ty != Terror);
+ gcc_assert (type->ty != TY::Terror);
check_typeinfo_type (loc, sc);
create_typeinfo (type, sc ? sc->_module->importedFrom : NULL);
return type->vtinfo->type;
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index 2a56e85158c..c8f9935da30 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -244,9 +244,9 @@ deps_write (Module *module, obstack *buffer)
&& m->parent == NULL)
continue;
- if (m->md && m->md->packages)
+ if (m->md && m->md->packages.length)
{
- Identifier *package = (*m->md->packages)[0];
+ Identifier *package = m->md->packages.ptr[0];
if (package == Identifier::idPool ("core")
|| package == Identifier::idPool ("std")
@@ -504,6 +504,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
case CppStdRevisionCpp11:
case CppStdRevisionCpp14:
case CppStdRevisionCpp17:
+ case CppStdRevisionCpp20:
global.params.cplusplus = (CppStdRevision) value;
break;
@@ -547,11 +548,11 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
break;
case OPT_fpreview_all:
- global.params.vsafe = value;
global.params.ehnogc = value;
- global.params.useDIP25 = value;
+ global.params.useDIP25 = FeatureState::enabled;
+ global.params.useDIP1000 = FeatureState::enabled;
global.params.useDIP1021 = value;
- global.params.dtorFields = value;
+ global.params.dtorFields = FeatureState::enabled;
global.params.fieldwise = value;
global.params.fixAliasThis = value;
global.params.previewIn = value;
@@ -559,10 +560,12 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
global.params.markdown = value;
global.params.noSharedAccess = value;
global.params.rvalueRefParam = value;
+ global.params.inclusiveInContracts = value;
+ global.params.shortenedMethods = value;
break;
case OPT_fpreview_dip1000:
- global.params.vsafe = value;
+ global.params.useDIP1000 = FeatureState::enabled;
break;
case OPT_fpreview_dip1008:
@@ -574,11 +577,11 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
break;
case OPT_fpreview_dip25:
- global.params.useDIP25 = value;
+ global.params.useDIP25 = FeatureState::enabled;
break;
case OPT_fpreview_dtorfields:
- global.params.dtorFields = value;
+ global.params.dtorFields = FeatureState::enabled;
break;
case OPT_fpreview_fieldwise:
@@ -601,10 +604,6 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
global.params.fix16997 = value;
break;
- case OPT_fpreview_markdown:
- global.params.markdown = value;
- break;
-
case OPT_fpreview_nosharedaccess:
global.params.noSharedAccess = value;
break;
@@ -613,16 +612,30 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
global.params.rvalueRefParam = value;
break;
+ case OPT_fpreview_shortenedMethods:
+ global.params.shortenedMethods = value;
+ break;
+
case OPT_frelease:
global.params.release = value;
break;
case OPT_frevert_all:
- global.params.noDIP25 = value;
+ global.params.useDIP25 = FeatureState::disabled;
+ global.params.markdown = !value;
+ global.params.dtorFields = FeatureState::disabled;
break;
case OPT_frevert_dip25:
- global.params.noDIP25 = value;
+ global.params.useDIP25 = FeatureState::disabled;
+ break;
+
+ case OPT_frevert_dtorfields:
+ global.params.dtorFields = FeatureState::disabled;
+ break;
+
+ case OPT_frevert_markdown:
+ global.params.markdown = !value;
break;
case OPT_frtti:
@@ -639,17 +652,12 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
break;
case OPT_ftransition_all:
- global.params.vcomplex = value;
global.params.vfield = value;
global.params.vgc = value;
global.params.vmarkdown= value;
global.params.vtls = value;
break;
- case OPT_ftransition_complex:
- global.params.vcomplex = value;
- break;
-
case OPT_ftransition_field:
global.params.vfield = value;
break;
@@ -881,7 +889,11 @@ d_post_options (const char ** fn)
/* Enabling DIP1021 implies DIP1000. */
if (global.params.useDIP1021)
- global.params.vsafe = true;
+ global.params.useDIP1000 = FeatureState::enabled;
+
+ /* Enabling DIP1000 implies DIP25. */
+ if (global.params.useDIP1000 == FeatureState::enabled)
+ global.params.useDIP25 = FeatureState::enabled;
/* Keep in sync with existing -fbounds-check flag. */
flag_bounds_check = (global.params.useArrayBounds == CHECKENABLEon);
@@ -1273,7 +1285,7 @@ d_parse_file (void)
if (name && (name[0] != '-' || name[1] != '\0'))
{
const char *nameext
- = FileName::defaultExt (name, global.json_ext.ptr);
+ = FileName::defaultExt (name, json_ext.ptr);
json_stream = fopen (nameext, "w");
if (!json_stream)
{
@@ -1500,7 +1512,7 @@ d_type_promotes_to (tree type)
/* Promotions are only applied on unnamed function arguments for declarations
with `extern(C)' or `extern(C++)' linkage. */
if (cfun && DECL_LANG_FRONTEND (cfun->decl)
- && DECL_LANG_FRONTEND (cfun->decl)->linkage != LINKd)
+ && DECL_LANG_FRONTEND (cfun->decl)->linkage != LINK::d)
{
/* In [type/integer-promotions], integer promotions are conversions of the
following types:
@@ -1653,7 +1665,8 @@ d_types_compatible_p (tree x, tree y)
return true;
/* Type system allows implicit conversion between. */
- if (tx->implicitConvTo (ty) || ty->implicitConvTo (tx))
+ if (tx->implicitConvTo (ty) != MATCH::nomatch
+ || ty->implicitConvTo (tx) != MATCH::nomatch)
return true;
}
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index 5133d1114b3..21417dddf78 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "tm_p.h"
#include "target.h"
+#include "calls.h"
#include "d-tree.h"
#include "d-target.h"
@@ -137,19 +138,19 @@ Target::_init (const Param &)
/* Define what type to use for size_t, ptrdiff_t. */
if (this->ptrsize == 8)
{
- global.params.isLP64 = true;
- Type::tsize_t = Type::basic[Tuns64];
- Type::tptrdiff_t = Type::basic[Tint64];
+ this->isLP64 = true;
+ Type::tsize_t = Type::basic[(int)TY::Tuns64];
+ Type::tptrdiff_t = Type::basic[(int)TY::Tint64];
}
else if (this->ptrsize == 4)
{
- Type::tsize_t = Type::basic[Tuns32];
- Type::tptrdiff_t = Type::basic[Tint32];
+ Type::tsize_t = Type::basic[(int)TY::Tuns32];
+ Type::tptrdiff_t = Type::basic[(int)TY::Tint32];
}
else if (this->ptrsize == 2)
{
- Type::tsize_t = Type::basic[Tuns16];
- Type::tptrdiff_t = Type::basic[Tint16];
+ Type::tsize_t = Type::basic[(int)TY::Tuns16];
+ Type::tptrdiff_t = Type::basic[(int)TY::Tint16];
}
else
sorry ("D does not support pointers on this target.");
@@ -159,15 +160,7 @@ Target::_init (const Param &)
/* Set-up target C ABI. */
this->c.longsize = int_size_in_bytes (long_integer_type_node);
this->c.long_doublesize = int_size_in_bytes (long_double_type_node);
-
- /* Define what type to use for wchar_t. We don't want to support wide
- characters less than "short" in D. */
- if (WCHAR_TYPE_SIZE == 32)
- this->c.twchar_t = Type::basic[Tdchar];
- else if (WCHAR_TYPE_SIZE == 16)
- this->c.twchar_t = Type::basic[Twchar];
- else
- sorry ("D does not support wide characters on this target.");
+ this->c.wchar_tsize = (WCHAR_TYPE_SIZE / BITS_PER_UNIT);
/* Set-up target C++ ABI. */
this->cpp.reverseOverloads = false;
@@ -177,6 +170,12 @@ Target::_init (const Param &)
/* Set-up target Objective-C ABI. */
this->objc.supported = false;
+ /* Set-up environmental settings. */
+ this->obj_ext = "o";
+ this->lib_ext = "a";
+ this->dll_ext = "so";
+ this->run_noext = true;
+
/* Initialize all compile-time properties for floating-point types.
Should ensure that our real_t type is able to represent real_value. */
gcc_assert (sizeof (real_t) >= sizeof (real_value));
@@ -268,7 +267,7 @@ Target::isVectorTypeSupported (int sz, Type *type)
type = Type::tuns8;
/* No support for non-trivial types, complex types, or booleans. */
- if (!type->isTypeBasic () || type->iscomplex () || type->ty == Tbool)
+ if (!type->isTypeBasic () || type->iscomplex () || type->ty == TY::Tbool)
return 2;
/* In [simd/vector extensions], which vector types are supported depends on
@@ -288,9 +287,9 @@ Target::isVectorTypeSupported (int sz, Type *type)
Returns true if the operation is supported or type is not a vector. */
bool
-Target::isVectorOpSupported (Type *type, TOK op, Type *)
+Target::isVectorOpSupported (Type *type, unsigned op, Type *)
{
- if (type->ty != Tvector)
+ if (type->ty != TY::Tvector)
return true;
/* Don't support if type is non-scalar, such as __vector(void[]). */
@@ -366,7 +365,8 @@ TargetCPP::thunkMangle (FuncDeclaration *fd, int offset)
const char *
TargetCPP::typeMangle (Type *type)
{
- if (type->isTypeBasic () || type->ty == Tvector || type->ty == Tstruct)
+ if (type->isTypeBasic () || type->ty == TY::Tvector
+ || type->ty == TY::Tstruct)
{
tree ctype = build_ctype (type);
return targetm.mangle_type (ctype);
@@ -387,14 +387,14 @@ TargetCPP::parameterType (Parameter *arg)
else if (arg->storageClass & STClazy)
{
/* Mangle as delegate. */
- Type *td = TypeFunction::create (NULL, t, VARARGnone, LINKd);
- td = TypeDelegate::create (td);
- t = t->merge2 ();
+ TypeFunction *tf = TypeFunction::create (NULL, t, VARARGnone, LINK::d);
+ TypeDelegate *td = TypeDelegate::create (tf);
+ t = td->merge2 ();
}
/* Could be a va_list, which we mangle as a pointer. */
Type *tvalist = target.va_listType (Loc (), NULL);
- if (t->ty == Tsarray && tvalist->ty == Tsarray)
+ if (t->ty == TY::Tsarray && tvalist->ty == TY::Tsarray)
{
Type *tb = t->toBasetype ()->mutableOf ();
if (tb == tvalist)
@@ -437,10 +437,10 @@ Target::systemLinkage (void)
/* In [attribute/linkage], `System' is the same as `Windows' on Windows
platforms, and `C' on other platforms. */
if (link_system)
- return LINKwindows;
+ return LINK::windows;
}
- return LINKc;
+ return LINK::c;
}
/* Generate a TypeTuple of the equivalent types used to determine if a
@@ -469,7 +469,7 @@ Target::isReturnOnStack (TypeFunction *tf, bool)
Type *tn = tf->next->toBasetype ();
- return (tn->ty == Tstruct || tn->ty == Tsarray);
+ return (tn->ty == TY::Tstruct || tn->ty == TY::Tsarray);
}
/* Add all target info in HANDLERS to D_TARGET_INFO_TABLE for use by
@@ -562,12 +562,49 @@ Target::getTargetInfo (const char *key, const Loc &loc)
return NULL;
}
-/**
- * Returns true if the implementation for object monitors is always defined
- * in the D runtime library (rt/monitor_.d). */
+/* Returns true if the callee invokes destructors for arguments. */
+
+bool
+Target::isCalleeDestroyingArgs (TypeFunction *tf)
+{
+ return tf->linkage == LINK::d;
+}
+
+/* Returns true if the implementation for object monitors is always defined
+ in the D runtime library (rt/monitor_.d). */
bool
Target::libraryObjectMonitors (FuncDeclaration *, Statement *)
{
return true;
}
+
+/* Decides whether an `in' parameter of the specified POD type PARAM_TYPE is to
+ be passed by reference or by valie. This is used only when compiling with
+ `-fpreview=in' enabled. */
+
+bool
+Target::preferPassByRef (Type *param_type)
+{
+ if (param_type->size () == SIZE_INVALID)
+ return false;
+
+ tree type = build_ctype (param_type);
+
+ /* Prefer a `ref' if the type is an aggregate, and its size is greater than
+ its alignment. */
+ if (AGGREGATE_TYPE_P (type)
+ && (!valid_constant_size_p (TYPE_SIZE_UNIT (type))
+ || compare_tree_int (TYPE_SIZE_UNIT (type), TYPE_ALIGN (type)) > 0))
+ return true;
+
+ /* If the back-end is always going to pass this by invisible reference. */
+ if (pass_by_reference (NULL, function_arg_info (type, true)))
+ return true;
+
+ /* If returning the parameter means the caller will do RVO. */
+ if (targetm.calls.return_in_memory (type, NULL_TREE))
+ return true;
+
+ return false;
+}
diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def
index 37764e0df38..67647515cf2 100644
--- a/gcc/d/d-target.def
+++ b/gcc/d/d-target.def
@@ -112,22 +112,5 @@ if they have external linkage. If this flag is false, then instantiated\n\
decls will be emitted as weak symbols. The default is @code{false}.",
bool, false)
-/* The floating point ABI, may be "hard" or "soft". */
-DEFHOOK
-(d_float_abi_type,
- "Returns a string specifying which floating-point ABI is in use, or whether\n\
-floating-point value types are passed in FPU registers. For most targets,\n\
-this would be described as either \"hard\" or \"soft\".",
- const char *, (void),
- hook_constcharptr_void_null)
-
-/* The target object format. */
-DEFHOOK
-(d_object_format,
- "Returns a string specifying the executable object format of the platform\n\
-the compiler is generating code for.",
- const char *, (void),
- hook_constcharptr_void_null)
-
/* Close the 'struct gcc_targetdm' definition. */
HOOK_VECTOR_END (C90_EMPTY_HACK)
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 0a6f804d55f..ac6161e234e 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -106,9 +106,9 @@ gcc_attribute_p (Dsymbol *decl)
{
ModuleDeclaration *md = decl->getModule ()->md;
- if (md && md->packages && md->packages->length == 1)
+ if (md && md->packages.length == 1)
{
- if (!strcmp ((*md->packages)[0]->toChars (), "gcc")
+ if (!strcmp (md->packages.ptr[0]->toChars (), "gcc")
&& !strcmp (md->id->toChars (), "attributes"))
return true;
}
@@ -156,7 +156,7 @@ apply_pragma_crt (Dsymbol *sym, bool isctor)
decl_fini_priority_insert (decl, DEFAULT_INIT_PRIORITY);
}
- if (fd->linkage != LINKc)
+ if (fd->linkage != LINK::c)
{
error_at (make_location_t (fd->loc),
"must be %<extern(C)%> for %<pragma(%s)%>",
@@ -376,14 +376,14 @@ public:
nested members. Only applies to classes or structs. */
Type *tb = fd->type->nextOf ()->baseElemOf ();
- while (tb->ty == Tarray || tb->ty == Tpointer)
+ while (tb->ty == TY::Tarray || tb->ty == TY::Tpointer)
tb = tb->nextOf ()->baseElemOf ();
TemplateInstance *ti = NULL;
- if (tb->ty == Tstruct)
+ if (tb->ty == TY::Tstruct)
ti = tb->isTypeStruct ()->sym->isInstantiated ();
- else if (tb->ty == Tclass)
+ else if (tb->ty == TY::Tclass)
ti = tb->isTypeClass ()->sym->isInstantiated ();
/* Return type is instantiated from this template declaration, walk over
@@ -425,7 +425,7 @@ public:
if (d->semanticRun >= PASSobj)
return;
- if (d->type->ty == Terror)
+ if (d->type->ty == TY::Terror)
{
error_at (make_location_t (d->loc),
"had semantic errors when compiling");
@@ -512,7 +512,8 @@ public:
if (fd2->isFuture ())
continue;
- if (fd->leastAsSpecialized (fd2) || fd2->leastAsSpecialized (fd))
+ if (fd->leastAsSpecialized (fd2) != MATCH::nomatch
+ || fd2->leastAsSpecialized (fd) != MATCH::nomatch)
{
error_at (make_location_t (fd->loc), "use of %qs",
fd->toPrettyChars ());
@@ -539,7 +540,7 @@ public:
if (d->semanticRun >= PASSobj)
return;
- if (d->type->ty == Terror)
+ if (d->type->ty == TY::Terror)
{
error_at (make_location_t (d->loc),
"had semantic errors when compiling");
@@ -613,7 +614,7 @@ public:
if (d->semanticRun >= PASSobj)
return;
- if (d->type->ty == Terror)
+ if (d->type->ty == TY::Terror)
{
error_at (make_location_t (d->loc),
"had semantic errors when compiling");
@@ -656,7 +657,7 @@ public:
if (d->semanticRun >= PASSobj)
return;
- if (d->errors || d->type->ty == Terror)
+ if (d->errors || d->type->ty == TY::Terror)
{
error_at (make_location_t (d->loc),
"had semantic errors when compiling");
@@ -695,7 +696,7 @@ public:
if (d->semanticRun >= PASSobj)
return;
- if (d->type->ty == Terror)
+ if (d->type->ty == TY::Terror)
{
error_at (make_location_t (d->loc),
"had semantic errors when compiling");
@@ -713,8 +714,6 @@ public:
/* Do not store variables we cannot take the address of,
but keep the values for purposes of debugging. */
if (!d->type->isscalar ())
- DECL_INITIAL (decl) = build_expr (ie, false, true);
- else
{
tree decl = get_symbol_decl (d);
d_pushdecl (decl);
@@ -763,7 +762,7 @@ public:
/* Frontend should have already caught this. */
gcc_assert (!integer_zerop (size)
- || d->type->toBasetype ()->ty == Tsarray);
+ || d->type->toBasetype ()->ty == TY::Tsarray);
d_finish_decl (decl);
@@ -838,7 +837,7 @@ public:
/* Check if any errors occurred when running semantic. */
if (TypeFunction *tf = d->type->isTypeFunction ())
{
- if (tf->next == NULL || tf->next->ty == Terror)
+ if (tf->next == NULL || tf->next->ty == TY::Terror)
return;
}
@@ -1317,9 +1316,9 @@ get_symbol_decl (Declaration *decl)
/* In [pragma/inline], functions decorated with `pragma(inline)' affects
whether they are inlined or not. */
- if (fd->inlining == PINLINEalways)
+ if (fd->inlining == PINLINE::always)
DECL_DECLARED_INLINE_P (decl->csym) = 1;
- else if (fd->inlining == PINLINEnever)
+ else if (fd->inlining == PINLINE::never)
DECL_UNINLINABLE (decl->csym) = 1;
/* Function was declared `naked'. */
@@ -1333,13 +1332,6 @@ get_symbol_decl (Declaration *decl)
if (fd->generated)
DECL_ARTIFICIAL (decl->csym) = 1;
- /* Vector array operations are always compiler generated. */
- if (fd->isArrayOp)
- {
- DECL_ARTIFICIAL (decl->csym) = 1;
- DECL_DECLARED_INLINE_P (decl->csym) = 1;
- }
-
/* Ensure and require contracts are lexically nested in the function they
part of, but are always publicly callable. */
if (fd->ident == Identifier::idPool ("ensure")
@@ -1350,7 +1342,7 @@ get_symbol_decl (Declaration *decl)
DECL_FINAL_P (decl->csym) = 1;
/* Function is of type `noreturn' or `typeof(*null)'. */
- if (fd->type->nextOf ()->ty == Tnoreturn)
+ if (fd->type->nextOf ()->ty == TY::Tnoreturn)
TREE_THIS_VOLATILE (decl->csym) = 1;
/* Check whether this function is expanded by the frontend. */
@@ -1377,10 +1369,10 @@ get_symbol_decl (Declaration *decl)
if (decl->storage_class & STCvolatile)
TREE_THIS_VOLATILE (decl->csym) = 1;
- /* Protection attributes are used by the debugger. */
- if (decl->protection.kind == Prot::private_)
+ /* Visibility attributes are used by the debugger. */
+ if (decl->visibility.kind == Visibility::private_)
TREE_PRIVATE (decl->csym) = 1;
- else if (decl->protection.kind == Prot::protected_)
+ else if (decl->visibility.kind == Visibility::protected_)
TREE_PROTECTED (decl->csym) = 1;
/* Likewise, so could the deprecated attribute. */
@@ -1873,7 +1865,7 @@ make_thunk (FuncDeclaration *decl, int offset)
forcing a D local thunk to be emitted. */
const char *ident;
- if (decl->linkage == LINKcpp)
+ if (decl->linkage == LINK::cpp)
ident = target.cpp.thunkMangle (decl, offset);
else
{
@@ -1889,7 +1881,9 @@ make_thunk (FuncDeclaration *decl, int offset)
SET_DECL_ASSEMBLER_NAME (thunk, DECL_NAME (thunk));
d_keep (thunk);
- free (CONST_CAST (char *, ident));
+
+ if (decl->linkage != LINK::cpp)
+ free (CONST_CAST (char *, ident));
if (!DECL_EXTERNAL (function))
finish_thunk (thunk, function);
@@ -2389,17 +2383,6 @@ create_field_decl (tree type, const char *name, int artificial, int ignored)
return decl;
}
-/* Returns the module NAMESPACE_DECL context of DECL or NULL. */
-
-static tree
-get_module_context (tree decl)
-{
- while (decl && TREE_CODE (decl) != NAMESPACE_DECL)
- decl = get_containing_scope (decl);
-
- return decl;
-}
-
/* Return the COMDAT group into which DECL should be placed. */
static tree
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index c93d090a51d..96d2e208f83 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-3a55c54a8e5773c3f56e10365a98f4570f8c6ce6
+2a48c54ad064f60eee50c63a27e28b730775546b
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/README.md b/gcc/d/dmd/README.md
index e517db14e4f..720d25683af 100644
--- a/gcc/d/dmd/README.md
+++ b/gcc/d/dmd/README.md
@@ -44,10 +44,11 @@ Note that these groups have no strict meaning, the category assignments are a bi
| File | Purpose |
|-----------------------------------------------------------------------|----------------------------------------------------------------------|
-| [lexer.d](https://github.com/dlang/dmd/blob/master/src/dmd/lexer.d) | Convert source code into tokens for the parser |
+| [lexer.d](https://github.com/dlang/dmd/blob/master/src/dmd/lexer.d) | Convert source code into tokens for the D and ImportC parsers |
| [entity.d](https://github.com/dlang/dmd/blob/master/src/dmd/entity.d) | Define "\\&Entity;" escape sequence for strings / character literals |
| [tokens.d](https://github.com/dlang/dmd/blob/master/src/dmd/tokens.d) | Define lexical tokens. |
-| [parse.d](https://github.com/dlang/dmd/blob/master/src/dmd/parse.d) | Convert tokens into an Abstract Syntax Tree (AST) |
+| [parse.d](https://github.com/dlang/dmd/blob/master/src/dmd/parse.d) | D parser, converting tokens into an Abstract Syntax Tree (AST) |
+| [cparse.d](https://github.com/dlang/dmd/blob/master/src/dmd/cparse.d) | ImportC parser, converting tokens into an Abstract Syntax Tree (AST) |
### Semantic analysis
@@ -76,6 +77,7 @@ Note that these groups have no strict meaning, the category assignments are a bi
| [ast_node.d](https://github.com/dlang/dmd/blob/master/src/dmd/ast_node.d) | Define an abstract AST node class |
| [astbase.d](https://github.com/dlang/dmd/blob/master/src/dmd/astbase.d) | Namespace of AST nodes that can be produced by the parser |
| [astcodegen.d](https://github.com/dlang/dmd/blob/master/src/dmd/astcodegen.d) | Namespace of AST nodes of a AST ready for code generation |
+| [astenums.d](https://github.com/dlang/dmd/blob/master/src/dmd/astenums.d) | Enums common to DMD and AST |
| [expression.d](https://github.com/dlang/dmd/blob/master/src/dmd/expression.d) | Define expression AST nodes |
| [statement.d](https://github.com/dlang/dmd/blob/master/src/dmd/statement.d) | Define statement AST nodes |
| [staticassert.d](https://github.com/dlang/dmd/blob/master/src/dmd/staticassert.d) | Define a `static assert` AST node |
@@ -174,7 +176,7 @@ Note that these groups have no strict meaning, the category assignments are a bi
| File | Purpose |
|-----------------------------------------------------------------------------|------------------------------------------------------------------------------------|
-| [chkformat.d](https://github.com/dlang/dmd/blob/master/src/dmd/chkformat.d) | Validate arguments wiht format specifiers for `printf` / `scanf` etc. |
+| [chkformat.d](https://github.com/dlang/dmd/blob/master/src/dmd/chkformat.d) | Validate arguments with format specifiers for `printf` / `scanf` etc. |
| [imphint.d](https://github.com/dlang/dmd/blob/master/src/dmd/imphint.d) | Give a suggestion to e.g. `import std.stdio` when `writeln` could not be resolved. |
### Library files
diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION
index 18ca570447d..6945fd11783 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@
-v2.094.0
+v2.097.0
diff --git a/gcc/d/dmd/access.d b/gcc/d/dmd/access.d
index 3f5916a36c3..20c162c7fa1 100644
--- a/gcc/d/dmd/access.d
+++ b/gcc/d/dmd/access.d
@@ -3,7 +3,7 @@
*
* Specification: $(LINK2 https://dlang.org/spec/attribute.html#visibility_attributes, Visibility Attributes)
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/access.d, _access.d)
@@ -14,6 +14,7 @@
module dmd.access;
import dmd.aggregate;
+import dmd.astenums;
import dmd.dclass;
import dmd.declaration;
import dmd.dmodule;
@@ -48,11 +49,19 @@ bool checkAccess(AggregateDeclaration ad, Loc loc, Scope* sc, Dsymbol smember)
return false; // for backward compatibility
}
- if (!symbolIsVisible(sc, smember) && (!(sc.flags & SCOPE.onlysafeaccess) || sc.func.setUnsafe()))
+ if (!symbolIsVisible(sc, smember))
{
+ // when in @safe code or with -preview=dip1000
+ if (sc.flags & SCOPE.onlysafeaccess)
+ {
+ // if there is a func. ask for it's opinion of safety, and if it considers the access @safe accept it.
+ if (sc.func && !sc.func.setUnsafe())
+ return false;
+ }
+
ad.error(loc, "member `%s` is not accessible%s", smember.toChars(), (sc.flags & SCOPE.onlysafeaccess) ? " from `@safe` code".ptr : "".ptr);
- //printf("smember = %s %s, prot = %d, semanticRun = %d\n",
- // smember.kind(), smember.toPrettyChars(), smember.prot(), smember.semanticRun);
+ //printf("smember = %s %s, vis = %d, semanticRun = %d\n",
+ // smember.kind(), smember.toPrettyChars(), smember.visible() smember.semanticRun);
return true;
}
return false;
@@ -70,14 +79,14 @@ private bool hasPackageAccess(Module mod, Dsymbol s)
{
static if (LOG)
{
- printf("hasPackageAccess(s = '%s', mod = '%s', s.protection.pkg = '%s')\n", s.toChars(), mod.toChars(), s.prot().pkg ? s.prot().pkg.toChars() : "NULL");
+ printf("hasPackageAccess(s = '%s', mod = '%s', s.visibility.pkg = '%s')\n", s.toChars(), mod.toChars(), s.visible().pkg ? s.visible().pkg.toChars() : "NULL");
}
Package pkg = null;
- if (s.prot().pkg)
- pkg = s.prot().pkg;
+ if (s.visible().pkg)
+ pkg = s.visible().pkg;
else
{
- // no explicit package for protection, inferring most qualified one
+ // no explicit package for visibility, inferring most qualified one
for (; s; s = s.parent)
{
if (auto m = s.isModule())
@@ -163,7 +172,7 @@ private bool hasProtectedAccess(Scope *sc, Dsymbol s)
* Check access to d for expression e.d
* Returns true if the declaration is not accessible.
*/
-bool checkAccess(Loc loc, Scope* sc, Expression e, Declaration d)
+bool checkAccess(Loc loc, Scope* sc, Expression e, Dsymbol d)
{
if (sc.flags & SCOPE.noaccesscheck)
return false;
@@ -227,7 +236,7 @@ bool checkAccess(Scope* sc, Package p)
return false;
for (; sc; sc = sc.enclosing)
{
- if (sc.scopesym && sc.scopesym.isPackageAccessible(p, Prot(Prot.Kind.private_)))
+ if (sc.scopesym && sc.scopesym.isPackageAccessible(p, Visibility(Visibility.Kind.private_)))
return false;
}
@@ -244,16 +253,16 @@ bool checkAccess(Scope* sc, Package p)
*/
bool symbolIsVisible(Module mod, Dsymbol s)
{
- // should sort overloads by ascending protection instead of iterating here
+ // should sort overloads by ascending visibility instead of iterating here
s = mostVisibleOverload(s);
- final switch (s.prot().kind)
+ final switch (s.visible().kind)
{
- case Prot.Kind.undefined: return true;
- case Prot.Kind.none: return false; // no access
- case Prot.Kind.private_: return s.getAccessModule() == mod;
- case Prot.Kind.package_: return s.getAccessModule() == mod || hasPackageAccess(mod, s);
- case Prot.Kind.protected_: return s.getAccessModule() == mod;
- case Prot.Kind.public_, Prot.Kind.export_: return true;
+ case Visibility.Kind.undefined: return true;
+ case Visibility.Kind.none: return false; // no access
+ case Visibility.Kind.private_: return s.getAccessModule() == mod;
+ case Visibility.Kind.package_: return s.getAccessModule() == mod || hasPackageAccess(mod, s);
+ case Visibility.Kind.protected_: return s.getAccessModule() == mod;
+ case Visibility.Kind.public_, Visibility.Kind.export_: return true;
}
}
@@ -291,21 +300,21 @@ bool symbolIsVisible(Scope *sc, Dsymbol s)
*/
bool checkSymbolAccess(Scope *sc, Dsymbol s)
{
- final switch (s.prot().kind)
+ final switch (s.visible().kind)
{
- case Prot.Kind.undefined: return true;
- case Prot.Kind.none: return false; // no access
- case Prot.Kind.private_: return sc._module == s.getAccessModule();
- case Prot.Kind.package_: return sc._module == s.getAccessModule() || hasPackageAccess(sc._module, s);
- case Prot.Kind.protected_: return hasProtectedAccess(sc, s);
- case Prot.Kind.public_, Prot.Kind.export_: return true;
+ case Visibility.Kind.undefined: return true;
+ case Visibility.Kind.none: return false; // no access
+ case Visibility.Kind.private_: return sc._module == s.getAccessModule();
+ case Visibility.Kind.package_: return sc._module == s.getAccessModule() || hasPackageAccess(sc._module, s);
+ case Visibility.Kind.protected_: return hasProtectedAccess(sc, s);
+ case Visibility.Kind.public_, Visibility.Kind.export_: return true;
}
}
/**
* Use the most visible overload to check visibility. Later perform an access
* check on the resolved overload. This function is similar to overloadApply,
- * but doesn't recurse nor resolve aliases because protection/visibility is an
+ * but doesn't recurse nor resolve aliases because visibility is an
* attribute of the alias not the aliasee.
*/
public Dsymbol mostVisibleOverload(Dsymbol s, Module mod = null)
@@ -355,7 +364,7 @@ public Dsymbol mostVisibleOverload(Dsymbol s, Module mod = null)
* Usually aliases should not be resolved for visibility checking
* b/c public aliases to private symbols are public. But for the
* overloadable alias situation, the Alias (_ad_) has been moved
- * into it's own Aliasee, leaving a shell that we peel away here.
+ * into its own Aliasee, leaving a shell that we peel away here.
*/
auto aliasee = ad.toAlias();
if (aliasee.isFuncAliasDeclaration || aliasee.isOverDeclaration)
@@ -378,23 +387,23 @@ public Dsymbol mostVisibleOverload(Dsymbol s, Module mod = null)
break;
/**
- * Return the "effective" protection attribute of a symbol when accessed in a module.
- * The effective protection attribute is the same as the regular protection attribute,
+ * Return the "effective" visibility attribute of a symbol when accessed in a module.
+ * The effective visibility attribute is the same as the regular visibility attribute,
* except package() is "private" if the module is outside the package;
* otherwise, "public".
*/
- static Prot protectionSeenFromModule(Dsymbol d, Module mod = null)
+ static Visibility visibilitySeenFromModule(Dsymbol d, Module mod = null)
{
- Prot prot = d.prot();
- if (mod && prot.kind == Prot.Kind.package_)
+ Visibility vis = d.visible();
+ if (mod && vis.kind == Visibility.Kind.package_)
{
- return hasPackageAccess(mod, d) ? Prot(Prot.Kind.public_) : Prot(Prot.Kind.private_);
+ return hasPackageAccess(mod, d) ? Visibility(Visibility.Kind.public_) : Visibility(Visibility.Kind.private_);
}
- return prot;
+ return vis;
}
if (next &&
- protectionSeenFromModule(mostVisible, mod).isMoreRestrictiveThan(protectionSeenFromModule(next, mod)))
+ visibilitySeenFromModule(mostVisible, mod) < visibilitySeenFromModule(next, mod))
mostVisible = next;
}
return mostVisible;
diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d
index f5cfc00d8fa..da54ba2bf9f 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/dmd/aggregate.d
@@ -4,7 +4,7 @@
* Specification: $(LINK2 https://dlang.org/spec/struct.html, Structs, Unions),
* $(LINK2 https://dlang.org/spec/class.html, Class).
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/aggregate.d, _aggregate.d)
@@ -20,7 +20,7 @@ import core.checkedint;
import dmd.aliasthis;
import dmd.apply;
import dmd.arraytypes;
-import dmd.gluelayer : Symbol;
+import dmd.astenums;
import dmd.declaration;
import dmd.dscope;
import dmd.dstruct;
@@ -38,29 +38,13 @@ import dmd.tokens;
import dmd.typesem : defaultInit;
import dmd.visitor;
-enum Sizeok : int
-{
- none, /// size of aggregate is not yet able to compute
- fwd, /// size of aggregate is ready to compute
- inProcess, /// in the midst of computing the size
- done, /// size of aggregate is set correctly
-}
-
-enum Baseok : int
-{
- none, /// base classes not computed yet
- start, /// in process of resolving base classes
- done, /// all base classes are resolved
- semanticdone, /// all base classes semantic done
-}
-
/**
* The ClassKind enum is used in AggregateDeclaration AST nodes to
* specify the linkage type of the struct/class/interface or if it
* is an anonymous class. If the class is anonymous it is also
* considered to be a D class.
*/
-enum ClassKind : int
+enum ClassKind : ubyte
{
/// the aggregate is a d(efault) class
d,
@@ -70,6 +54,16 @@ enum ClassKind : int
objc,
}
+/**
+ * If an aggregate has a pargma(mangle, ...) this holds the information
+ * to mangle.
+ */
+struct MangleOverride
+{
+ Dsymbol agg; // The symbol to copy template parameters from (if any)
+ Identifier id; // the name to override the aggregate's with, defaults to agg.ident
+}
+
/***********************************************************
* Abstract aggregate as a common ancestor for Class- and StructDeclaration.
*/
@@ -89,6 +83,9 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
/// Only valid for class and struct. TODO: Merge with ClassKind ?
CPPMANGLE cppmangle;
+ /// overridden symbol with pragma(mangle, "...") if not null
+ MangleOverride* mangleOverride;
+
/**
* !=null if is nested
* pointing to the dsymbol that directly enclosing it.
@@ -125,14 +122,15 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
Expression getRTInfo; /// pointer to GC info generated by object.RTInfo(this)
- Prot protection; /// visibility
+ ///
+ Visibility visibility;
bool noDefaultCtor; /// no default construction
Sizeok sizeok = Sizeok.none; /// set when structsize contains valid data
final extern (D) this(const ref Loc loc, Identifier id)
{
super(loc, id);
- protection = Prot(Prot.Kind.public_);
+ visibility = Visibility(Visibility.Kind.public_);
}
/***************************************
@@ -145,8 +143,8 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
sc2.stc &= STCFlowThruAggregate;
sc2.parent = this;
sc2.inunion = isUnionDeclaration();
- sc2.protection = Prot(Prot.Kind.public_);
- sc2.explicitProtection = 0;
+ sc2.visibility = Visibility(Visibility.Kind.public_);
+ sc2.explicitVisibility = 0;
sc2.aligndecl = null;
sc2.userAttribDecl = null;
sc2.namespace = null;
@@ -723,7 +721,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
// Emulate vthis.dsymbolSemantic()
vthis.storage_class |= STC.field;
vthis.parent = this;
- vthis.protection = Prot(Prot.Kind.public_);
+ vthis.visibility = Visibility(Visibility.Kind.public_);
vthis.alignment = t.alignment();
vthis.semanticRun = PASS.semanticdone;
@@ -767,7 +765,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
// Emulate vthis2.dsymbolSemantic()
vthis2.storage_class |= STC.field;
vthis2.parent = this;
- vthis2.protection = Prot(Prot.Kind.public_);
+ vthis2.visibility = Visibility(Visibility.Kind.public_);
vthis2.alignment = t.alignment();
vthis2.semanticRun = PASS.semanticdone;
@@ -777,7 +775,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
override final bool isExport() const
{
- return protection.kind == Prot.Kind.export_;
+ return visibility.kind == Visibility.Kind.export_;
}
/*******************************************
@@ -822,9 +820,9 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
return s;
}
- override final Prot prot() pure nothrow @nogc @safe
+ override final Visibility visible() pure nothrow @nogc @safe
{
- return protection;
+ return visibility;
}
// 'this' type
@@ -833,9 +831,14 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
return type;
}
+ // Does this class have an invariant function?
+ final bool hasInvariant()
+ {
+ return invs.length != 0;
+ }
+
// Back end
- Symbol* stag; /// tag symbol for debug data
- Symbol* sinit; /// initializer symbol
+ void* sinit; /// initializer symbol
override final inout(AggregateDeclaration) isAggregateDeclaration() inout
{
diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h
index cf6bde75d23..41572a82bdb 100644
--- a/gcc/d/dmd/aggregate.h
+++ b/gcc/d/dmd/aggregate.h
@@ -26,20 +26,20 @@ class InterfaceDeclaration;
class TypeInfoClassDeclaration;
class VarDeclaration;
-enum Sizeok
+enum class Sizeok : uint8_t
{
- SIZEOKnone, // size of aggregate is not yet able to compute
- SIZEOKfwd, // size of aggregate is ready to compute
- SIZEOKinProcess, // in the midst of computing the size
- SIZEOKdone // size of aggregate is set correctly
+ none, // size of aggregate is not yet able to compute
+ fwd, // size of aggregate is ready to compute
+ inProcess, // in the midst of computing the size
+ done // size of aggregate is set correctly
};
-enum Baseok
+enum class Baseok : uint8_t
{
- BASEOKnone, // base classes not computed yet
- BASEOKin, // in process of resolving base classes
- BASEOKdone, // all base classes are resolved
- BASEOKsemanticdone // all base classes semantic done
+ none, // base classes not computed yet
+ in, // in process of resolving base classes
+ done, // all base classes are resolved
+ semanticdone // all base classes semantic done
};
enum StructPOD
@@ -49,26 +49,29 @@ enum StructPOD
ISPODfwd // POD not yet computed
};
-enum Abstract
+enum class Abstract : uint8_t
{
- ABSfwdref = 0, // whether an abstract class is not yet computed
- ABSyes, // is abstract class
- ABSno // is not abstract class
+ fwdref = 0, // whether an abstract class is not yet computed
+ yes, // is abstract class
+ no // is not abstract class
};
FuncDeclaration *search_toString(StructDeclaration *sd);
-struct ClassKind
+enum class ClassKind : uint8_t
{
- enum Type
- {
- /// the aggregate is a d(efault) struct/class/interface
- d,
- /// the aggregate is a C++ struct/class/interface
- cpp,
- /// the aggregate is an Objective-C class/interface
- objc
- };
+ /// the aggregate is a d(efault) struct/class/interface
+ d,
+ /// the aggregate is a C++ struct/class/interface
+ cpp,
+ /// the aggregate is an Objective-C class/interface
+ objc
+};
+
+struct MangleOverride
+{
+ Dsymbol *agg;
+ Identifier *id;
};
class AggregateDeclaration : public ScopeDsymbol
@@ -81,9 +84,11 @@ public:
VarDeclarations fields; // VarDeclaration fields
Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol
- ClassKind::Type classKind; // specifies the linkage type
+ ClassKind classKind; // specifies the linkage type
CPPMANGLE cppmangle;
+ // overridden symbol with pragma(mangle, "...")
+ MangleOverride *mangleOverride;
/* !=NULL if is nested
* pointing to the dsymbol that directly enclosing it.
* 1. The function that enclosing it (nested struct and class)
@@ -115,7 +120,7 @@ public:
Expression *getRTInfo; // pointer to GC info generated by object.RTInfo(this)
- Prot protection;
+ Visibility visibility;
bool noDefaultCtor; // no default construction
Sizeok sizeok; // set when structsize contains valid data
@@ -134,14 +139,15 @@ public:
bool isExport() const;
Dsymbol *searchCtor();
- Prot prot();
+ Visibility visible();
// 'this' type
Type *handleType() { return type; }
+ bool hasInvariant();
+
// Back end
- Symbol *stag; // tag symbol for debug data
- Symbol *sinit;
+ void *sinit;
AggregateDeclaration *isAggregateDeclaration() { return this; }
void accept(Visitor *v) { v->visit(this); }
@@ -186,7 +192,7 @@ public:
TypeTuple *argTypes;
static StructDeclaration *create(Loc loc, Identifier *id, bool inObject);
- Dsymbol *syntaxCopy(Dsymbol *s);
+ StructDeclaration *syntaxCopy(Dsymbol *s);
void semanticTypeInfoMembers();
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
const char *kind() const;
@@ -199,12 +205,13 @@ public:
unsigned numArgTypes() const;
Type *argType(unsigned index);
+ bool hasRegularCtor(bool checkDisabled = false);
};
class UnionDeclaration : public StructDeclaration
{
public:
- Dsymbol *syntaxCopy(Dsymbol *s);
+ UnionDeclaration *syntaxCopy(Dsymbol *s);
const char *kind() const;
UnionDeclaration *isUnionDeclaration() { return this; }
@@ -280,7 +287,8 @@ public:
Symbol *cpp_type_info_ptr_sym; // cached instance of class Id.cpp_type_info_ptr
static ClassDeclaration *create(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject);
- Dsymbol *syntaxCopy(Dsymbol *s);
+ const char *toPrettyChars(bool QualifyTypes = false);
+ ClassDeclaration *syntaxCopy(Dsymbol *s);
Scope *newScope(Scope *sc);
bool isBaseOf2(ClassDeclaration *cd);
@@ -317,7 +325,7 @@ public:
class InterfaceDeclaration : public ClassDeclaration
{
public:
- Dsymbol *syntaxCopy(Dsymbol *s);
+ InterfaceDeclaration *syntaxCopy(Dsymbol *s);
Scope *newScope(Scope *sc);
bool isBaseOf(ClassDeclaration *cd, int *poffset);
bool isBaseOf(BaseClass *bc, int *poffset);
diff --git a/gcc/d/dmd/aliasthis.d b/gcc/d/dmd/aliasthis.d
index 27781ed1cfd..81e0d7e64be 100644
--- a/gcc/d/dmd/aliasthis.d
+++ b/gcc/d/dmd/aliasthis.d
@@ -3,7 +3,7 @@
*
* Specification: $(LINK2 https://dlang.org/spec/class.html#alias-this, Alias This)
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/aliasthis.d, _aliasthis.d)
@@ -43,7 +43,7 @@ extern (C++) final class AliasThis : Dsymbol
this.ident = ident;
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override AliasThis syntaxCopy(Dsymbol s)
{
assert(!s);
auto at = new AliasThis(loc, ident);
@@ -154,26 +154,49 @@ Expression resolveAliasThis(Scope* sc, Expression e, bool gag = false)
*/
bool checkDeprecatedAliasThis(AliasThis at, const ref Loc loc, Scope* sc)
{
- import dmd.errors : deprecation;
+ import dmd.errors : deprecation, Classification;
import dmd.dsymbolsem : getMessage;
if (global.params.useDeprecated != DiagnosticReporting.off
&& at.isDeprecated() && !sc.isDeprecated())
{
- const(char)* message = null;
- for (Dsymbol p = at; p; p = p.parent)
- {
- message = p.depdecl ? p.depdecl.getMessage() : null;
- if (message)
- break;
- }
+ const(char)* message = null;
+ for (Dsymbol p = at; p; p = p.parent)
+ {
+ message = p.depdecl ? p.depdecl.getMessage() : null;
if (message)
- deprecation(loc, "`alias %s this` is deprecated - %s",
- at.sym.toChars(), message);
- else
- deprecation(loc, "`alias %s this` is deprecated",
- at.sym.toChars());
+ break;
+ }
+ if (message)
+ deprecation(loc, "`alias %s this` is deprecated - %s",
+ at.sym.toChars(), message);
+ else
+ deprecation(loc, "`alias %s this` is deprecated",
+ at.sym.toChars());
+
+ if (auto ti = sc.parent ? sc.parent.isInstantiated() : null)
+ ti.printInstantiationTrace(Classification.deprecation);
+
return true;
}
return false;
}
+
+/**************************************
+ * Check and set 'att' if 't' is a recursive 'alias this' type
+ * Params:
+ * att = type reference used to detect recursion
+ * t = 'alias this' type
+ *
+ * Returns:
+ * Whether the 'alias this' is recursive or not
+ */
+bool isRecursiveAliasThis(ref Type att, Type t)
+{
+ auto tb = t.toBasetype();
+ if (att && tb.equivalent(att))
+ return true;
+ else if (!att && tb.checkAliasThisRec())
+ att = tb;
+ return false;
+}
diff --git a/gcc/d/dmd/aliasthis.h b/gcc/d/dmd/aliasthis.h
index c4630039d56..de93a8e6ae4 100644
--- a/gcc/d/dmd/aliasthis.h
+++ b/gcc/d/dmd/aliasthis.h
@@ -23,7 +23,7 @@ public:
Dsymbol *sym;
bool isDeprecated_;
- Dsymbol *syntaxCopy(Dsymbol *);
+ AliasThis *syntaxCopy(Dsymbol *);
const char *kind() const;
AliasThis *isAliasThis() { return this; }
void accept(Visitor *v) { v->visit(this); }
diff --git a/gcc/d/dmd/apply.d b/gcc/d/dmd/apply.d
index e989a8f0b79..ab427e885dc 100644
--- a/gcc/d/dmd/apply.d
+++ b/gcc/d/dmd/apply.d
@@ -1,7 +1,7 @@
/**
* A depth-first visitor for expressions.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/apply.d, _apply.d)
@@ -18,6 +18,46 @@ import dmd.dtemplate;
import dmd.expression;
import dmd.visitor;
+bool walkPostorder(Expression e, StoppableVisitor v)
+{
+ scope PostorderExpressionVisitor pv = new PostorderExpressionVisitor(v);
+ e.accept(pv);
+ return v.stop;
+}
+
+/*********************************
+ * Iterate this dsymbol or members of this scoped dsymbol, then
+ * call `fp` with the found symbol and `params`.
+ * Params:
+ * symbol = the dsymbol or parent of members to call fp on
+ * fp = function pointer to process the iterated symbol.
+ * If it returns nonzero, the iteration will be aborted.
+ * params = any parameters passed to fp.
+ * Returns:
+ * nonzero if the iteration is aborted by the return value of fp,
+ * or 0 if it's completed.
+ */
+int apply(FP, Params...)(Dsymbol symbol, FP fp, Params params)
+{
+ if (auto nd = symbol.isNspace())
+ {
+ return nd.members.foreachDsymbol( (s) { return s && s.apply(fp, params); } );
+ }
+ if (auto ad = symbol.isAttribDeclaration())
+ {
+ return ad.include(ad._scope).foreachDsymbol( (s) { return s && s.apply(fp, params); } );
+ }
+ if (auto tm = symbol.isTemplateMixin())
+ {
+ if (tm._scope) // if fwd reference
+ dsymbolSemantic(tm, null); // try to resolve it
+
+ return tm.members.foreachDsymbol( (s) { return s && s.apply(fp, params); } );
+ }
+
+ return fp(symbol, params);
+}
+
/**************************************
* An Expression tree walker that will visit each Expression e in the tree,
* in depth-first evaluation order, and call fp(e,param) on it.
@@ -147,43 +187,3 @@ public:
doCond(e.econd) || doCond(e.e1) || doCond(e.e2) || applyTo(e);
}
}
-
-bool walkPostorder(Expression e, StoppableVisitor v)
-{
- scope PostorderExpressionVisitor pv = new PostorderExpressionVisitor(v);
- e.accept(pv);
- return v.stop;
-}
-
-/*********************************
- * Iterate this dsymbol or members of this scoped dsymbol, then
- * call `fp` with the found symbol and `params`.
- * Params:
- * symbol = the dsymbol or parent of members to call fp on
- * fp = function pointer to process the iterated symbol.
- * If it returns nonzero, the iteration will be aborted.
- * params = any parameters passed to fp.
- * Returns:
- * nonzero if the iteration is aborted by the return value of fp,
- * or 0 if it's completed.
- */
-int apply(FP, Params...)(Dsymbol symbol, FP fp, Params params)
-{
- if (auto nd = symbol.isNspace())
- {
- return nd.members.foreachDsymbol( (s) { return s && s.apply(fp, params); } );
- }
- if (auto ad = symbol.isAttribDeclaration())
- {
- return ad.include(ad._scope).foreachDsymbol( (s) { return s && s.apply(fp, params); } );
- }
- if (auto tm = symbol.isTemplateMixin())
- {
- if (tm._scope) // if fwd reference
- dsymbolSemantic(tm, null); // try to resolve it
-
- return tm.members.foreachDsymbol( (s) { return s && s.apply(fp, params); } );
- }
-
- return fp(symbol, params);
-}
diff --git a/gcc/d/dmd/arrayop.d b/gcc/d/dmd/arrayop.d
index 9359c26f0ca..66be73ea21f 100644
--- a/gcc/d/dmd/arrayop.d
+++ b/gcc/d/dmd/arrayop.d
@@ -3,7 +3,7 @@
*
* Specification: $(LINK2 https://dlang.org/spec/arrays.html#array-operations, Array Operations)
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/arrayop.d, _arrayop.d)
@@ -15,6 +15,7 @@ module dmd.arrayop;
import core.stdc.stdio;
import dmd.arraytypes;
+import dmd.astenums;
import dmd.declaration;
import dmd.dscope;
import dmd.dsymbol;
diff --git a/gcc/d/dmd/arraytypes.d b/gcc/d/dmd/arraytypes.d
index b504b179f89..b1f8d86a208 100644
--- a/gcc/d/dmd/arraytypes.d
+++ b/gcc/d/dmd/arraytypes.d
@@ -1,7 +1,7 @@
/**
* Provide aliases for arrays of certain declarations or statements.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/arraytypes.d, _arraytypes.d)
@@ -52,3 +52,6 @@ alias ReturnStatements = Array!(ReturnStatement);
alias GotoStatements = Array!(GotoStatement);
alias TemplateInstances = Array!(TemplateInstance);
alias Ensures = Array!(Ensure);
+alias Designators = Array!(Designator);
+alias DesigInits = Array!(DesigInit);
+
diff --git a/gcc/d/dmd/arraytypes.h b/gcc/d/dmd/arraytypes.h
index 5fd32e41fdf..602d89059a0 100644
--- a/gcc/d/dmd/arraytypes.h
+++ b/gcc/d/dmd/arraytypes.h
@@ -63,3 +63,8 @@ typedef Array<class GotoStatement *> GotoStatements;
typedef Array<class TemplateInstance *> TemplateInstances;
typedef Array<struct Ensure> Ensures;
+
+typedef Array<struct Designator> Designators;
+
+typedef Array<struct DesigInit> DesigInits;
+
diff --git a/gcc/d/dmd/ast_node.d b/gcc/d/dmd/ast_node.d
index fd11481ea8d..82d62a03657 100644
--- a/gcc/d/dmd/ast_node.d
+++ b/gcc/d/dmd/ast_node.d
@@ -1,7 +1,7 @@
/**
* Defines the base class for all nodes which are part of the AST.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ast_node.d, _ast_node.d)
diff --git a/gcc/d/dmd/astcodegen.d b/gcc/d/dmd/astcodegen.d
index 364c058acd0..d40f836faae 100644
--- a/gcc/d/dmd/astcodegen.d
+++ b/gcc/d/dmd/astcodegen.d
@@ -34,12 +34,14 @@ struct ASTCodegen
public import dmd.staticassert;
public import dmd.typesem;
public import dmd.ctfeexpr;
+ public import dmd.init : Designator;
alias initializerToExpression = dmd.initsem.initializerToExpression;
alias typeToExpression = dmd.typesem.typeToExpression;
alias UserAttributeDeclaration = dmd.attrib.UserAttributeDeclaration;
alias Ensure = dmd.func.Ensure; // workaround for bug in older DMD frontends
+ alias ErrorExp = dmd.expression.ErrorExp;
alias MODFlags = dmd.mtype.MODFlags;
alias Type = dmd.mtype.Type;
@@ -57,6 +59,7 @@ struct ASTCodegen
alias Tfloat80 = dmd.mtype.Tfloat80;
alias Tfunction = dmd.mtype.Tfunction;
alias Tpointer = dmd.mtype.Tpointer;
+ alias Treference = dmd.mtype.Treference;
alias Tident = dmd.mtype.Tident;
alias Tint8 = dmd.mtype.Tint8;
alias Tint16 = dmd.mtype.Tint16;
@@ -70,20 +73,30 @@ struct ASTCodegen
alias Tuns64 = dmd.mtype.Tuns64;
alias Tvoid = dmd.mtype.Tvoid;
alias Twchar = dmd.mtype.Twchar;
+ alias Tnoreturn = dmd.mtype.Tnoreturn;
+
+ alias Timaginary32 = dmd.mtype.Timaginary32;
+ alias Timaginary64 = dmd.mtype.Timaginary64;
+ alias Timaginary80 = dmd.mtype.Timaginary80;
+ alias Tcomplex32 = dmd.mtype.Tcomplex32;
+ alias Tcomplex64 = dmd.mtype.Tcomplex64;
+ alias Tcomplex80 = dmd.mtype.Tcomplex80;
alias ParameterList = dmd.mtype.ParameterList;
alias VarArg = dmd.mtype.VarArg;
alias STC = dmd.declaration.STC;
alias Dsymbol = dmd.dsymbol.Dsymbol;
alias Dsymbols = dmd.dsymbol.Dsymbols;
- alias Prot = dmd.dsymbol.Prot;
+ alias Visibility = dmd.dsymbol.Visibility;
alias stcToBuffer = dmd.hdrgen.stcToBuffer;
alias linkageToChars = dmd.hdrgen.linkageToChars;
- alias protectionToChars = dmd.hdrgen.protectionToChars;
+ alias visibilityToChars = dmd.hdrgen.visibilityToChars;
alias isType = dmd.dtemplate.isType;
alias isExpression = dmd.dtemplate.isExpression;
alias isTuple = dmd.dtemplate.isTuple;
+ alias IgnoreErrors = dmd.dsymbol.IgnoreErrors;
+ alias PASS = dmd.dsymbol.PASS;
}
diff --git a/gcc/d/dmd/astenums.d b/gcc/d/dmd/astenums.d
new file mode 100644
index 00000000000..0860c55e178
--- /dev/null
+++ b/gcc/d/dmd/astenums.d
@@ -0,0 +1,347 @@
+/**
+ * Defines enums common to dmd and dmd as parse library.
+ *
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/astenums.d, _astenums.d)
+ * Documentation: https://dlang.org/phobos/dmd_astenums.html
+ * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/astenums.d
+ */
+
+module dmd.astenums;
+
+enum Sizeok : ubyte
+{
+ none, /// size of aggregate is not yet able to compute
+ fwd, /// size of aggregate is ready to compute
+ inProcess, /// in the midst of computing the size
+ done, /// size of aggregate is set correctly
+}
+
+enum Baseok : ubyte
+{
+ none, /// base classes not computed yet
+ start, /// in process of resolving base classes
+ done, /// all base classes are resolved
+ semanticdone, /// all base classes semantic done
+}
+
+enum MODFlags : int
+{
+ const_ = 1, // type is const
+ immutable_ = 4, // type is immutable
+ shared_ = 2, // type is shared
+ wild = 8, // type is wild
+ wildconst = (MODFlags.wild | MODFlags.const_), // type is wild const
+ mutable = 0x10, // type is mutable (only used in wildcard matching)
+}
+
+alias MOD = ubyte;
+
+enum STC : ulong
+{
+ undefined_ = 0L,
+ static_ = (1L << 0),
+ extern_ = (1L << 1),
+ const_ = (1L << 2),
+ final_ = (1L << 3),
+ abstract_ = (1L << 4),
+ parameter = (1L << 5),
+ field = (1L << 6),
+ override_ = (1L << 7),
+ auto_ = (1L << 8),
+ synchronized_ = (1L << 9),
+ deprecated_ = (1L << 10),
+ in_ = (1L << 11), // in parameter
+ out_ = (1L << 12), // out parameter
+ lazy_ = (1L << 13), // lazy parameter
+ foreach_ = (1L << 14), // variable for foreach loop
+ //(1L << 15)
+ variadic = (1L << 16), // the 'variadic' parameter in: T foo(T a, U b, V variadic...)
+ ctorinit = (1L << 17), // can only be set inside constructor
+ templateparameter = (1L << 18), // template parameter
+ scope_ = (1L << 19),
+ immutable_ = (1L << 20),
+ ref_ = (1L << 21),
+ init = (1L << 22), // has explicit initializer
+ manifest = (1L << 23), // manifest constant
+ nodtor = (1L << 24), // don't run destructor
+ nothrow_ = (1L << 25), // never throws exceptions
+ pure_ = (1L << 26), // pure function
+ tls = (1L << 27), // thread local
+ alias_ = (1L << 28), // alias parameter
+ shared_ = (1L << 29), // accessible from multiple threads
+ gshared = (1L << 30), // accessible from multiple threads, but not typed as "shared"
+ wild = (1L << 31), // for "wild" type constructor
+ property = (1L << 32),
+ safe = (1L << 33),
+ trusted = (1L << 34),
+ system = (1L << 35),
+ ctfe = (1L << 36), // can be used in CTFE, even if it is static
+ disable = (1L << 37), // for functions that are not callable
+ result = (1L << 38), // for result variables passed to out contracts
+ nodefaultctor = (1L << 39), // must be set inside constructor
+ temp = (1L << 40), // temporary variable
+ rvalue = (1L << 41), // force rvalue for variables
+ nogc = (1L << 42), // @nogc
+ volatile_ = (1L << 43), // destined for volatile in the back end
+ return_ = (1L << 44), // 'return ref' or 'return scope' for function parameters
+ autoref = (1L << 45), // Mark for the already deduced 'auto ref' parameter
+ inference = (1L << 46), // do attribute inference
+ exptemp = (1L << 47), // temporary variable that has lifetime restricted to an expression
+ maybescope = (1L << 48), // parameter might be 'scope'
+ scopeinferred = (1L << 49), // 'scope' has been inferred and should not be part of mangling
+ future = (1L << 50), // introducing new base class function
+ local = (1L << 51), // do not forward (see dmd.dsymbol.ForwardingScopeDsymbol).
+ returninferred = (1L << 52), // 'return' has been inferred and should not be part of mangling
+ live = (1L << 53), // function @live attribute
+ register = (1L << 54), // `register` storage class
+
+ safeGroup = STC.safe | STC.trusted | STC.system,
+ IOR = STC.in_ | STC.ref_ | STC.out_,
+ TYPECTOR = (STC.const_ | STC.immutable_ | STC.shared_ | STC.wild),
+ FUNCATTR = (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.property | STC.live |
+ safeGroup),
+}
+
+/* This is different from the one in declaration.d, make that fix a separate PR */
+static if (0)
+extern (C++) __gshared const(StorageClass) STCStorageClass =
+ (STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.const_ | STC.final_ |
+ STC.abstract_ | STC.synchronized_ | STC.deprecated_ | STC.override_ | STC.lazy_ |
+ STC.alias_ | STC.out_ | STC.in_ | STC.manifest | STC.immutable_ | STC.shared_ |
+ STC.wild | STC.nothrow_ | STC.nogc | STC.pure_ | STC.ref_ | STC.return_ | STC.tls |
+ STC.gshared | STC.property | STC.live |
+ STC.safeGroup | STC.disable);
+
+enum TY : ubyte
+{
+ Tarray, // slice array, aka T[]
+ Tsarray, // static array, aka T[dimension]
+ Taarray, // associative array, aka T[type]
+ Tpointer,
+ Treference,
+ Tfunction,
+ Tident,
+ Tclass,
+ Tstruct,
+ Tenum,
+
+ Tdelegate,
+ Tnone,
+ Tvoid,
+ Tint8,
+ Tuns8,
+ Tint16,
+ Tuns16,
+ Tint32,
+ Tuns32,
+ Tint64,
+
+ Tuns64,
+ Tfloat32,
+ Tfloat64,
+ Tfloat80,
+ Timaginary32,
+ Timaginary64,
+ Timaginary80,
+ Tcomplex32,
+ Tcomplex64,
+ Tcomplex80,
+
+ Tbool,
+ Tchar,
+ Twchar,
+ Tdchar,
+ Terror,
+ Tinstance,
+ Ttypeof,
+ Ttuple,
+ Tslice,
+ Treturn,
+
+ Tnull,
+ Tvector,
+ Tint128,
+ Tuns128,
+ Ttraits,
+ Tmixin,
+ Tnoreturn,
+ Ttag,
+ TMAX
+}
+
+alias Tarray = TY.Tarray;
+alias Tsarray = TY.Tsarray;
+alias Taarray = TY.Taarray;
+alias Tpointer = TY.Tpointer;
+alias Treference = TY.Treference;
+alias Tfunction = TY.Tfunction;
+alias Tident = TY.Tident;
+alias Tclass = TY.Tclass;
+alias Tstruct = TY.Tstruct;
+alias Tenum = TY.Tenum;
+alias Tdelegate = TY.Tdelegate;
+alias Tnone = TY.Tnone;
+alias Tvoid = TY.Tvoid;
+alias Tint8 = TY.Tint8;
+alias Tuns8 = TY.Tuns8;
+alias Tint16 = TY.Tint16;
+alias Tuns16 = TY.Tuns16;
+alias Tint32 = TY.Tint32;
+alias Tuns32 = TY.Tuns32;
+alias Tint64 = TY.Tint64;
+alias Tuns64 = TY.Tuns64;
+alias Tfloat32 = TY.Tfloat32;
+alias Tfloat64 = TY.Tfloat64;
+alias Tfloat80 = TY.Tfloat80;
+alias Timaginary32 = TY.Timaginary32;
+alias Timaginary64 = TY.Timaginary64;
+alias Timaginary80 = TY.Timaginary80;
+alias Tcomplex32 = TY.Tcomplex32;
+alias Tcomplex64 = TY.Tcomplex64;
+alias Tcomplex80 = TY.Tcomplex80;
+alias Tbool = TY.Tbool;
+alias Tchar = TY.Tchar;
+alias Twchar = TY.Twchar;
+alias Tdchar = TY.Tdchar;
+alias Terror = TY.Terror;
+alias Tinstance = TY.Tinstance;
+alias Ttypeof = TY.Ttypeof;
+alias Ttuple = TY.Ttuple;
+alias Tslice = TY.Tslice;
+alias Treturn = TY.Treturn;
+alias Tnull = TY.Tnull;
+alias Tvector = TY.Tvector;
+alias Tint128 = TY.Tint128;
+alias Tuns128 = TY.Tuns128;
+alias Ttraits = TY.Ttraits;
+alias Tmixin = TY.Tmixin;
+alias Tnoreturn = TY.Tnoreturn;
+alias Ttag = TY.Ttag;
+alias TMAX = TY.TMAX;
+
+enum TFlags
+{
+ integral = 1,
+ floating = 2,
+ unsigned = 4,
+ real_ = 8,
+ imaginary = 0x10,
+ complex = 0x20,
+}
+
+enum PKG : int
+{
+ unknown, /// not yet determined whether it's a package.d or not
+ module_, /// already determined that's an actual package.d
+ package_, /// already determined that's an actual package
+}
+
+enum StructPOD : int
+{
+ no, /// struct is not POD
+ yes, /// struct is POD
+ fwd, /// POD not yet computed
+}
+
+enum TRUST : ubyte
+{
+ default_ = 0,
+ system = 1, // @system (same as TRUST.default)
+ trusted = 2, // @trusted
+ safe = 3, // @safe
+}
+
+enum PURE : ubyte
+{
+ impure = 0, // not pure at all
+ fwdref = 1, // it's pure, but not known which level yet
+ weak = 2, // no mutable globals are read or written
+ const_ = 3, // parameters are values or const
+ strong = 4, // parameters are values or immutable
+}
+
+// Whether alias this dependency is recursive or not
+enum AliasThisRec : int
+{
+ no = 0, // no alias this recursion
+ yes = 1, // alias this has recursive dependency
+ fwdref = 2, // not yet known
+ typeMask = 3, // mask to read no/yes/fwdref
+ tracing = 0x4, // mark in progress of implicitConvTo/deduceWild
+ tracingDT = 0x8, // mark in progress of deduceType
+}
+
+/***************
+ * Variadic argument lists
+ * https://dlang.org/spec/function.html#variadic
+ */
+enum VarArg : ubyte
+{
+ none = 0, /// fixed number of arguments
+ variadic = 1, /// (T t, ...) can be C-style (core.stdc.stdarg) or D-style (core.vararg)
+ typesafe = 2, /// (T t ...) typesafe https://dlang.org/spec/function.html#typesafe_variadic_functions
+ /// or https://dlang.org/spec/function.html#typesafe_variadic_functions
+}
+
+/*************************
+ * Identify Statement types with this enum rather than
+ * virtual functions
+ */
+enum STMT : ubyte
+{
+ Error,
+ Peel,
+ Exp, DtorExp,
+ Compile,
+ Compound, CompoundDeclaration, CompoundAsm,
+ UnrolledLoop,
+ Scope,
+ Forwarding,
+ While,
+ Do,
+ For,
+ Foreach,
+ ForeachRange,
+ If,
+ Conditional,
+ StaticForeach,
+ Pragma,
+ StaticAssert,
+ Switch,
+ Case,
+ CaseRange,
+ Default,
+ GotoDefault,
+ GotoCase,
+ SwitchError,
+ Return,
+ Break,
+ Continue,
+ Synchronized,
+ With,
+ TryCatch,
+ TryFinally,
+ ScopeGuard,
+ Throw,
+ Debug,
+ Goto,
+ Label,
+ Asm, InlineAsm, GccAsm,
+ Import,
+}
+
+/**********************
+ * Discriminant for which kind of initializer
+ */
+enum InitKind : ubyte
+{
+ void_,
+ error,
+ struct_,
+ array,
+ exp,
+ C_,
+}
+
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index d4f1f7d9965..646dd3c7a40 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -14,7 +14,7 @@
* - Protection (`private`, `public`)
* - Deprecated declarations (`@deprecated`)
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/attrib.d, _attrib.d)
@@ -26,6 +26,7 @@ module dmd.attrib;
import dmd.aggregate;
import dmd.arraytypes;
+import dmd.astenums;
import dmd.cond;
import dmd.declaration;
import dmd.dmodule;
@@ -33,10 +34,10 @@ import dmd.dscope;
import dmd.dsymbol;
import dmd.dsymbolsem : dsymbolSemantic;
import dmd.expression;
-import dmd.expressionsem : arrayExpressionSemantic;
+import dmd.expressionsem;
import dmd.func;
import dmd.globals;
-import dmd.hdrgen : protectionToBuffer;
+import dmd.hdrgen : visibilityToBuffer;
import dmd.id;
import dmd.identifier;
import dmd.mtype;
@@ -81,15 +82,15 @@ extern (C++) abstract class AttribDeclaration : Dsymbol
* the scope after it used.
*/
extern (D) static Scope* createNewScope(Scope* sc, StorageClass stc, LINK linkage,
- CPPMANGLE cppmangle, Prot protection, int explicitProtection,
- AlignDeclaration aligndecl, PINLINE inlining)
+ CPPMANGLE cppmangle, Visibility visibility, int explicitVisibility,
+ AlignDeclaration aligndecl, PragmaDeclaration inlining)
{
Scope* sc2 = sc;
if (stc != sc.stc ||
linkage != sc.linkage ||
cppmangle != sc.cppmangle ||
- !protection.isSubsetOf(sc.protection) ||
- explicitProtection != sc.explicitProtection ||
+ explicitVisibility != sc.explicitVisibility ||
+ visibility != sc.visibility ||
aligndecl !is sc.aligndecl ||
inlining != sc.inlining)
{
@@ -98,8 +99,8 @@ extern (C++) abstract class AttribDeclaration : Dsymbol
sc2.stc = stc;
sc2.linkage = linkage;
sc2.cppmangle = cppmangle;
- sc2.protection = protection;
- sc2.explicitProtection = explicitProtection;
+ sc2.visibility = visibility;
+ sc2.explicitVisibility = explicitVisibility;
sc2.aligndecl = aligndecl;
sc2.inlining = inlining;
}
@@ -231,7 +232,7 @@ extern (C++) class StorageClassDeclaration : AttribDeclaration
this.stc = stc;
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override StorageClassDeclaration syntaxCopy(Dsymbol s)
{
assert(!s);
return new StorageClassDeclaration(stc, Dsymbol.arraySyntaxCopy(decl));
@@ -256,7 +257,7 @@ extern (C++) class StorageClassDeclaration : AttribDeclaration
scstc |= stc;
//printf("scstc = x%llx\n", scstc);
return createNewScope(sc, scstc, sc.linkage, sc.cppmangle,
- sc.protection, sc.explicitProtection, sc.aligndecl, sc.inlining);
+ sc.visibility, sc.explicitVisibility, sc.aligndecl, sc.inlining);
}
override final bool oneMember(Dsymbol* ps, Identifier ident)
@@ -344,7 +345,7 @@ extern (C++) final class DeprecatedDeclaration : StorageClassDeclaration
this.msg = msg;
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override DeprecatedDeclaration syntaxCopy(Dsymbol s)
{
assert(!s);
return new DeprecatedDeclaration(msg.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl));
@@ -393,27 +394,27 @@ extern (C++) final class LinkDeclaration : AttribDeclaration
{
LINK linkage; /// either explicitly set or `default_`
- extern (D) this(LINK linkage, Dsymbols* decl)
+ extern (D) this(const ref Loc loc, LINK linkage, Dsymbols* decl)
{
- super(decl);
+ super(loc, null, decl);
//printf("LinkDeclaration(linkage = %d, decl = %p)\n", linkage, decl);
this.linkage = (linkage == LINK.system) ? target.systemLinkage() : linkage;
}
- static LinkDeclaration create(LINK p, Dsymbols* decl)
+ static LinkDeclaration create(const ref Loc loc, LINK p, Dsymbols* decl)
{
- return new LinkDeclaration(p, decl);
+ return new LinkDeclaration(loc, p, decl);
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override LinkDeclaration syntaxCopy(Dsymbol s)
{
assert(!s);
- return new LinkDeclaration(linkage, Dsymbol.arraySyntaxCopy(decl));
+ return new LinkDeclaration(loc, linkage, Dsymbol.arraySyntaxCopy(decl));
}
override Scope* newScope(Scope* sc)
{
- return createNewScope(sc, sc.stc, this.linkage, sc.cppmangle, sc.protection, sc.explicitProtection,
+ return createNewScope(sc, sc.stc, this.linkage, sc.cppmangle, sc.visibility, sc.explicitVisibility,
sc.aligndecl, sc.inlining);
}
@@ -445,22 +446,22 @@ extern (C++) final class CPPMangleDeclaration : AttribDeclaration
{
CPPMANGLE cppmangle;
- extern (D) this(CPPMANGLE cppmangle, Dsymbols* decl)
+ extern (D) this(const ref Loc loc, CPPMANGLE cppmangle, Dsymbols* decl)
{
- super(decl);
+ super(loc, null, decl);
//printf("CPPMangleDeclaration(cppmangle = %d, decl = %p)\n", cppmangle, decl);
this.cppmangle = cppmangle;
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override CPPMangleDeclaration syntaxCopy(Dsymbol s)
{
assert(!s);
- return new CPPMangleDeclaration(cppmangle, Dsymbol.arraySyntaxCopy(decl));
+ return new CPPMangleDeclaration(loc, cppmangle, Dsymbol.arraySyntaxCopy(decl));
}
override Scope* newScope(Scope* sc)
{
- return createNewScope(sc, sc.stc, LINK.cpp, cppmangle, sc.protection, sc.explicitProtection,
+ return createNewScope(sc, sc.stc, LINK.cpp, cppmangle, sc.visibility, sc.explicitVisibility,
sc.aligndecl, sc.inlining);
}
@@ -515,32 +516,30 @@ extern (C++) final class CPPNamespaceDeclaration : AttribDeclaration
/// CTFE-able expression, resolving to `TupleExp` or `StringExp`
Expression exp;
- extern (D) this(Identifier ident, Dsymbols* decl)
+ extern (D) this(const ref Loc loc, Identifier ident, Dsymbols* decl)
{
- super(decl);
- this.ident = ident;
+ super(loc, ident, decl);
}
- extern (D) this(Expression exp, Dsymbols* decl)
+ extern (D) this(const ref Loc loc, Expression exp, Dsymbols* decl)
{
- super(decl);
+ super(loc, null, decl);
this.exp = exp;
}
- extern (D) this(Identifier ident, Expression exp, Dsymbols* decl,
+ extern (D) this(const ref Loc loc, Identifier ident, Expression exp, Dsymbols* decl,
CPPNamespaceDeclaration parent)
{
- super(decl);
- this.ident = ident;
+ super(loc, ident, decl);
this.exp = exp;
this.cppnamespace = parent;
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override CPPNamespaceDeclaration syntaxCopy(Dsymbol s)
{
assert(!s);
return new CPPNamespaceDeclaration(
- this.ident, this.exp, Dsymbol.arraySyntaxCopy(this.decl), this.cppnamespace);
+ this.loc, this.ident, this.exp, Dsymbol.arraySyntaxCopy(this.decl), this.cppnamespace);
}
/**
@@ -576,24 +575,24 @@ extern (C++) final class CPPNamespaceDeclaration : AttribDeclaration
/***********************************************************
* Visibility declaration for Dsymbols, e.g. `public int i;`
*
- * `<protection> <decl...>` or
+ * `<visibility> <decl...>` or
* `package(<pkg_identifiers>) <decl...>` if `pkg_identifiers !is null`
*/
-extern (C++) final class ProtDeclaration : AttribDeclaration
+extern (C++) final class VisibilityDeclaration : AttribDeclaration
{
- Prot protection; /// the visibility
- Identifiers* pkg_identifiers; /// identifiers for `package(foo.bar)` or null
+ Visibility visibility; /// the visibility
+ Identifier[] pkg_identifiers; /// identifiers for `package(foo.bar)` or null
/**
* Params:
* loc = source location of attribute token
- * protection = protection attribute data
- * decl = declarations which are affected by this protection attribute
+ * visibility = visibility attribute data
+ * decl = declarations which are affected by this visibility attribute
*/
- extern (D) this(const ref Loc loc, Prot protection, Dsymbols* decl)
+ extern (D) this(const ref Loc loc, Visibility visibility, Dsymbols* decl)
{
super(loc, null, decl);
- this.protection = protection;
+ this.visibility = visibility;
//printf("decl = %p\n", decl);
}
@@ -601,35 +600,36 @@ extern (C++) final class ProtDeclaration : AttribDeclaration
* Params:
* loc = source location of attribute token
* pkg_identifiers = list of identifiers for a qualified package name
- * decl = declarations which are affected by this protection attribute
+ * decl = declarations which are affected by this visibility attribute
*/
- extern (D) this(const ref Loc loc, Identifiers* pkg_identifiers, Dsymbols* decl)
+ extern (D) this(const ref Loc loc, Identifier[] pkg_identifiers, Dsymbols* decl)
{
super(loc, null, decl);
- this.protection.kind = Prot.Kind.package_;
+ this.visibility.kind = Visibility.Kind.package_;
this.pkg_identifiers = pkg_identifiers;
- if (pkg_identifiers !is null && pkg_identifiers.dim > 0)
+ if (pkg_identifiers.length > 0)
{
Dsymbol tmp;
Package.resolve(pkg_identifiers, &tmp, null);
- protection.pkg = tmp ? tmp.isPackage() : null;
+ visibility.pkg = tmp ? tmp.isPackage() : null;
}
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override VisibilityDeclaration syntaxCopy(Dsymbol s)
{
assert(!s);
- if (protection.kind == Prot.Kind.package_)
- return new ProtDeclaration(this.loc, pkg_identifiers, Dsymbol.arraySyntaxCopy(decl));
+
+ if (visibility.kind == Visibility.Kind.package_)
+ return new VisibilityDeclaration(this.loc, pkg_identifiers, Dsymbol.arraySyntaxCopy(decl));
else
- return new ProtDeclaration(this.loc, protection, Dsymbol.arraySyntaxCopy(decl));
+ return new VisibilityDeclaration(this.loc, visibility, Dsymbol.arraySyntaxCopy(decl));
}
override Scope* newScope(Scope* sc)
{
if (pkg_identifiers)
dsymbolSemantic(this, sc);
- return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, this.protection, 1, sc.aligndecl, sc.inlining);
+ return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, this.visibility, 1, sc.aligndecl, sc.inlining);
}
override void addMember(Scope* sc, ScopeDsymbol sds)
@@ -638,24 +638,24 @@ extern (C++) final class ProtDeclaration : AttribDeclaration
{
Dsymbol tmp;
Package.resolve(pkg_identifiers, &tmp, null);
- protection.pkg = tmp ? tmp.isPackage() : null;
+ visibility.pkg = tmp ? tmp.isPackage() : null;
pkg_identifiers = null;
}
- if (protection.kind == Prot.Kind.package_ && protection.pkg && sc._module)
+ if (visibility.kind == Visibility.Kind.package_ && visibility.pkg && sc._module)
{
Module m = sc._module;
// While isAncestorPackageOf does an equality check, the fix for issue 17441 adds a check to see if
// each package's .isModule() properites are equal.
//
- // Properties generated from `package(foo)` i.e. protection.pkg have .isModule() == null.
+ // Properties generated from `package(foo)` i.e. visibility.pkg have .isModule() == null.
// This breaks package declarations of the package in question if they are declared in
// the same package.d file, which _do_ have a module associated with them, and hence a non-null
// isModule()
- if (!m.isPackage() || !protection.pkg.ident.equals(m.isPackage().ident))
+ if (!m.isPackage() || !visibility.pkg.ident.equals(m.isPackage().ident))
{
Package pkg = m.parent ? m.parent.isPackage() : null;
- if (!pkg || !protection.pkg.isAncestorPackageOf(pkg))
+ if (!pkg || !visibility.pkg.isAncestorPackageOf(pkg))
error("does not bind to one of ancestor packages of module `%s`", m.toPrettyChars(true));
}
}
@@ -664,18 +664,18 @@ extern (C++) final class ProtDeclaration : AttribDeclaration
override const(char)* kind() const
{
- return "protection attribute";
+ return "visibility attribute";
}
override const(char)* toPrettyChars(bool)
{
- assert(protection.kind > Prot.Kind.undefined);
+ assert(visibility.kind > Visibility.Kind.undefined);
OutBuffer buf;
- protectionToBuffer(&buf, protection);
+ visibilityToBuffer(&buf, visibility);
return buf.extractChars();
}
- override inout(ProtDeclaration) isProtDeclaration() inout
+ override inout(VisibilityDeclaration) isVisibilityDeclaration() inout
{
return this;
}
@@ -709,7 +709,7 @@ extern (C++) final class AlignDeclaration : AttribDeclaration
this.ealign = ealign;
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override AlignDeclaration syntaxCopy(Dsymbol s)
{
assert(!s);
return new AlignDeclaration(loc,
@@ -719,7 +719,7 @@ extern (C++) final class AlignDeclaration : AttribDeclaration
override Scope* newScope(Scope* sc)
{
- return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, sc.protection, sc.explicitProtection, this, sc.inlining);
+ return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, sc.visibility, sc.explicitVisibility, this, sc.inlining);
}
override void accept(Visitor v)
@@ -745,7 +745,7 @@ extern (C++) final class AnonDeclaration : AttribDeclaration
this.isunion = isunion;
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override AnonDeclaration syntaxCopy(Dsymbol s)
{
assert(!s);
return new AnonDeclaration(loc, isunion, Dsymbol.arraySyntaxCopy(decl));
@@ -865,7 +865,7 @@ extern (C++) final class PragmaDeclaration : AttribDeclaration
this.args = args;
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override PragmaDeclaration syntaxCopy(Dsymbol s)
{
//printf("PragmaDeclaration::syntaxCopy(%s)\n", toChars());
assert(!s);
@@ -876,32 +876,9 @@ extern (C++) final class PragmaDeclaration : AttribDeclaration
{
if (ident == Id.Pinline)
{
- PINLINE inlining = PINLINE.default_;
- if (!args || args.dim == 0)
- inlining = PINLINE.default_;
- else if (args.dim != 1)
- {
- error("one boolean expression expected for `pragma(inline)`, not %llu", cast(ulong) args.dim);
- args.setDim(1);
- (*args)[0] = ErrorExp.get();
- }
- else
- {
- Expression e = (*args)[0];
- if (e.op != TOK.int64 || !e.type.equals(Type.tbool))
- {
- if (e.op != TOK.error)
- {
- error("pragma(`inline`, `true` or `false`) expected, not `%s`", e.toChars());
- (*args)[0] = ErrorExp.get();
- }
- }
- else if (e.isBool(true))
- inlining = PINLINE.always;
- else if (e.isBool(false))
- inlining = PINLINE.never;
- }
- return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, sc.protection, sc.explicitProtection, sc.aligndecl, inlining);
+ // We keep track of this pragma inside scopes,
+ // then it's evaluated on demand in function semantic
+ return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, sc.visibility, sc.explicitVisibility, sc.aligndecl, this);
}
if (ident == Id.printf || ident == Id.scanf)
{
@@ -918,6 +895,34 @@ extern (C++) final class PragmaDeclaration : AttribDeclaration
return sc;
}
+ PINLINE evalPragmaInline(Scope* sc)
+ {
+ if (!args || args.dim == 0)
+ return PINLINE.default_;
+
+ Expression e = (*args)[0];
+ if (!e.type)
+ {
+
+ sc = sc.startCTFE();
+ e = e.expressionSemantic(sc);
+ e = resolveProperties(sc, e);
+ sc = sc.endCTFE();
+ e = e.ctfeInterpret();
+ e = e.toBoolean(sc);
+ if (e.isErrorExp())
+ error("pragma(`inline`, `true` or `false`) expected, not `%s`", (*args)[0].toChars());
+ (*args)[0] = e;
+ }
+
+ if (e.isBool(true))
+ return PINLINE.always;
+ else if (e.isBool(false))
+ return PINLINE.never;
+ else
+ return PINLINE.default_;
+ }
+
override const(char)* kind() const
{
return "pragma";
@@ -940,18 +945,18 @@ extern (C++) class ConditionalDeclaration : AttribDeclaration
Condition condition; /// condition deciding whether decl or elsedecl applies
Dsymbols* elsedecl; /// array of Dsymbol's for else block
- extern (D) this(Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
+ extern (D) this(const ref Loc loc, Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
{
- super(decl);
+ super(loc, null, decl);
//printf("ConditionalDeclaration::ConditionalDeclaration()\n");
this.condition = condition;
this.elsedecl = elsedecl;
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override ConditionalDeclaration syntaxCopy(Dsymbol s)
{
assert(!s);
- return new ConditionalDeclaration(condition.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl), Dsymbol.arraySyntaxCopy(elsedecl));
+ return new ConditionalDeclaration(loc, condition.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl), Dsymbol.arraySyntaxCopy(elsedecl));
}
override final bool oneMember(Dsymbol* ps, Identifier ident)
@@ -1018,16 +1023,16 @@ extern (C++) final class StaticIfDeclaration : ConditionalDeclaration
private bool addisdone = false; /// true if members have been added to scope
private bool onStack = false; /// true if a call to `include` is currently active
- extern (D) this(Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
+ extern (D) this(const ref Loc loc, Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
{
- super(condition, decl, elsedecl);
+ super(loc, condition, decl, elsedecl);
//printf("StaticIfDeclaration::StaticIfDeclaration()\n");
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override StaticIfDeclaration syntaxCopy(Dsymbol s)
{
assert(!s);
- return new StaticIfDeclaration(condition.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl), Dsymbol.arraySyntaxCopy(elsedecl));
+ return new StaticIfDeclaration(loc, condition.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl), Dsymbol.arraySyntaxCopy(elsedecl));
}
/****************************************
@@ -1129,11 +1134,11 @@ extern (C++) final class StaticForeachDeclaration : AttribDeclaration
extern (D) this(StaticForeach sfe, Dsymbols* decl)
{
- super(decl);
+ super(sfe.loc, null, decl);
this.sfe = sfe;
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override StaticForeachDeclaration syntaxCopy(Dsymbol s)
{
assert(!s);
return new StaticForeachDeclaration(
@@ -1312,7 +1317,7 @@ extern (C++) final class CompileDeclaration : AttribDeclaration
this.exps = exps;
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override CompileDeclaration syntaxCopy(Dsymbol s)
{
//printf("CompileDeclaration::syntaxCopy('%s')\n", toChars());
return new CompileDeclaration(loc, Expression.arraySyntaxCopy(exps));
@@ -1357,11 +1362,10 @@ extern (C++) final class UserAttributeDeclaration : AttribDeclaration
extern (D) this(Expressions* atts, Dsymbols* decl)
{
super(decl);
- //printf("UserAttributeDeclaration()\n");
this.atts = atts;
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override UserAttributeDeclaration syntaxCopy(Dsymbol s)
{
//printf("UserAttributeDeclaration::syntaxCopy('%s')\n", toChars());
assert(!s);
diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h
index e68ed284935..e58db84016c 100644
--- a/gcc/d/dmd/attrib.h
+++ b/gcc/d/dmd/attrib.h
@@ -47,7 +47,7 @@ class StorageClassDeclaration : public AttribDeclaration
public:
StorageClass stc;
- Dsymbol *syntaxCopy(Dsymbol *s);
+ StorageClassDeclaration *syntaxCopy(Dsymbol *s);
Scope *newScope(Scope *sc);
bool oneMember(Dsymbol **ps, Identifier *ident);
void addMember(Scope *sc, ScopeDsymbol *sds);
@@ -62,7 +62,7 @@ public:
Expression *msg;
const char *msgstr;
- Dsymbol *syntaxCopy(Dsymbol *s);
+ DeprecatedDeclaration *syntaxCopy(Dsymbol *s);
Scope *newScope(Scope *sc);
void setScope(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
@@ -73,8 +73,8 @@ class LinkDeclaration : public AttribDeclaration
public:
LINK linkage;
- static LinkDeclaration *create(LINK p, Dsymbols *decl);
- Dsymbol *syntaxCopy(Dsymbol *s);
+ static LinkDeclaration *create(const Loc &loc, LINK p, Dsymbols *decl);
+ LinkDeclaration *syntaxCopy(Dsymbol *s);
Scope *newScope(Scope *sc);
const char *toChars() const;
void accept(Visitor *v) { v->visit(this); }
@@ -85,7 +85,7 @@ class CPPMangleDeclaration : public AttribDeclaration
public:
CPPMANGLE cppmangle;
- Dsymbol *syntaxCopy(Dsymbol *s);
+ CPPMangleDeclaration *syntaxCopy(Dsymbol *s);
Scope *newScope(Scope *sc);
void setScope(Scope *sc);
const char *toChars() const;
@@ -97,24 +97,24 @@ class CPPNamespaceDeclaration : public AttribDeclaration
public:
Expression *exp;
- Dsymbol *syntaxCopy(Dsymbol *s);
+ CPPNamespaceDeclaration *syntaxCopy(Dsymbol *s);
Scope *newScope(Scope *sc);
const char *toChars() const;
void accept(Visitor *v) { v->visit(this); }
};
-class ProtDeclaration : public AttribDeclaration
+class VisibilityDeclaration : public AttribDeclaration
{
public:
- Prot protection;
- Identifiers* pkg_identifiers;
+ Visibility visibility;
+ DArray<Identifier*> pkg_identifiers;
- Dsymbol *syntaxCopy(Dsymbol *s);
+ VisibilityDeclaration *syntaxCopy(Dsymbol *s);
Scope *newScope(Scope *sc);
void addMember(Scope *sc, ScopeDsymbol *sds);
const char *kind() const;
const char *toPrettyChars(bool unused);
- ProtDeclaration *isProtDeclaration() { return this; }
+ VisibilityDeclaration *isVisibilityDeclaration() { return this; }
void accept(Visitor *v) { v->visit(this); }
};
@@ -125,7 +125,7 @@ public:
structalign_t salign;
AlignDeclaration(const Loc &loc, Expression *ealign, Dsymbols *decl);
- Dsymbol *syntaxCopy(Dsymbol *s);
+ AlignDeclaration *syntaxCopy(Dsymbol *s);
Scope *newScope(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
@@ -139,7 +139,7 @@ public:
unsigned anonstructsize; // size of anonymous struct
unsigned anonalignsize; // size of anonymous struct for alignment purposes
- Dsymbol *syntaxCopy(Dsymbol *s);
+ AnonDeclaration *syntaxCopy(Dsymbol *s);
void setScope(Scope *sc);
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
const char *kind() const;
@@ -152,8 +152,9 @@ class PragmaDeclaration : public AttribDeclaration
public:
Expressions *args; // array of Expression's
- Dsymbol *syntaxCopy(Dsymbol *s);
+ PragmaDeclaration *syntaxCopy(Dsymbol *s);
Scope *newScope(Scope *sc);
+ PINLINE evalPragmaInline(Scope* sc);
const char *kind() const;
void accept(Visitor *v) { v->visit(this); }
};
@@ -164,7 +165,7 @@ public:
Condition *condition;
Dsymbols *elsedecl; // array of Dsymbol's for else block
- Dsymbol *syntaxCopy(Dsymbol *s);
+ ConditionalDeclaration *syntaxCopy(Dsymbol *s);
bool oneMember(Dsymbol **ps, Identifier *ident);
Dsymbols *include(Scope *sc);
void addComment(const utf8_t *comment);
@@ -179,7 +180,7 @@ public:
bool addisdone;
bool onStack;
- Dsymbol *syntaxCopy(Dsymbol *s);
+ StaticIfDeclaration *syntaxCopy(Dsymbol *s);
Dsymbols *include(Scope *sc);
void addMember(Scope *sc, ScopeDsymbol *sds);
void setScope(Scope *sc);
@@ -197,7 +198,7 @@ public:
bool cached;
Dsymbols *cache;
- Dsymbol *syntaxCopy(Dsymbol *s);
+ StaticForeachDeclaration *syntaxCopy(Dsymbol *s);
bool oneMember(Dsymbol **ps, Identifier *ident);
Dsymbols *include(Scope *sc);
void addMember(Scope *sc, ScopeDsymbol *sds);
@@ -229,7 +230,7 @@ public:
ScopeDsymbol *scopesym;
bool compiled;
- Dsymbol *syntaxCopy(Dsymbol *s);
+ CompileDeclaration *syntaxCopy(Dsymbol *s);
void addMember(Scope *sc, ScopeDsymbol *sds);
void setScope(Scope *sc);
const char *kind() const;
@@ -245,7 +246,7 @@ class UserAttributeDeclaration : public AttribDeclaration
public:
Expressions *atts;
- Dsymbol *syntaxCopy(Dsymbol *s);
+ UserAttributeDeclaration *syntaxCopy(Dsymbol *s);
Scope *newScope(Scope *sc);
void setScope(Scope *sc);
Expressions *getAttributes();
diff --git a/gcc/d/dmd/blockexit.d b/gcc/d/dmd/blockexit.d
index ab7cce42fc2..efeb3fac748 100644
--- a/gcc/d/dmd/blockexit.d
+++ b/gcc/d/dmd/blockexit.d
@@ -1,7 +1,7 @@
/**
* Find out in what ways control flow can exit a statement block.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/blockexit.d, _blockexit.d)
@@ -14,6 +14,7 @@ module dmd.blockexit;
import core.stdc.stdio;
import dmd.arraytypes;
+import dmd.astenums;
import dmd.canthrow;
import dmd.dclass;
import dmd.declaration;
@@ -107,6 +108,8 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
return;
}
}
+ if (s.exp.type.toBasetype().isTypeNoreturn())
+ result = BE.halt;
if (canThrow(s.exp, func, mustNotThrow))
result |= BE.throw_;
}
diff --git a/gcc/d/dmd/builtin.d b/gcc/d/dmd/builtin.d
index a60a269b602..b99f690e156 100644
--- a/gcc/d/dmd/builtin.d
+++ b/gcc/d/dmd/builtin.d
@@ -3,7 +3,7 @@
*
* Currently includes functions from `std.math`, `core.math` and `core.bitop`.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/builtin.d, _builtin.d)
diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d
index 7f2a961c5e1..fcb884df72d 100644
--- a/gcc/d/dmd/canthrow.d
+++ b/gcc/d/dmd/canthrow.d
@@ -3,7 +3,7 @@
*
* Specification: $(LINK2 https://dlang.org/spec/function.html#nothrow-functions, Nothrow Functions)
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/canthrow.d, _canthrow.d)
@@ -17,6 +17,7 @@ import dmd.aggregate;
import dmd.apply;
import dmd.arraytypes;
import dmd.attrib;
+import dmd.astenums;
import dmd.declaration;
import dmd.dsymbol;
import dmd.expression;
diff --git a/gcc/d/dmd/chkformat.d b/gcc/d/dmd/chkformat.d
index bd9d47d7815..97adc5ad8ac 100644
--- a/gcc/d/dmd/chkformat.d
+++ b/gcc/d/dmd/chkformat.d
@@ -1,7 +1,7 @@
/**
* Check the arguments to `printf` and `scanf` against the `format` string.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/chkformat.d, _chkformat.d)
@@ -13,9 +13,12 @@ module dmd.chkformat;
//import core.stdc.stdio : printf, scanf;
import core.stdc.ctype : isdigit;
+import dmd.astenums;
+import dmd.cond;
import dmd.errors;
import dmd.expression;
import dmd.globals;
+import dmd.identifier;
import dmd.mtype;
import dmd.target;
@@ -59,7 +62,7 @@ import dmd.target;
bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expression[] args, bool isVa_list)
{
//printf("checkPrintFormat('%.*s')\n", cast(int)format.length, format.ptr);
- size_t n = 0;
+ size_t n, gnu_m_count; // index in args / number of Format.GNU_m
for (size_t i = 0; i < format.length;)
{
if (format[i] != '%')
@@ -85,17 +88,23 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
continue;
}
- Expression getNextArg()
+ if (fmt == Format.GNU_m)
+ ++gnu_m_count;
+
+ Expression getNextArg(ref bool skip)
{
if (n == args.length)
{
- deprecation(loc, "more format specifiers than %d arguments", cast(int)n);
+ if (args.length < (n + 1) - gnu_m_count)
+ deprecation(loc, "more format specifiers than %d arguments", cast(int)n);
+ else
+ skip = true;
return null;
}
return args[n++];
}
- void errorMsg(const char* prefix, const char[] specifier, Expression arg, const char* texpect, Type tactual)
+ void errorMsg(const char* prefix, Expression arg, const char* texpect, Type tactual)
{
deprecation(arg.loc, "%sargument `%s` for format specification `\"%.*s\"` must be `%s`, not `%s`",
prefix ? prefix : "", arg.toChars(), cast(int)slice.length, slice.ptr, texpect, tactual.toChars());
@@ -103,31 +112,40 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
if (widthStar)
{
- auto e = getNextArg();
+ bool skip;
+ auto e = getNextArg(skip);
+ if (skip)
+ continue;
if (!e)
return true;
auto t = e.type.toBasetype();
if (t.ty != Tint32 && t.ty != Tuns32)
- errorMsg("width ", slice, e, "int", t);
+ errorMsg("width ", e, "int", t);
}
if (precisionStar)
{
- auto e = getNextArg();
+ bool skip;
+ auto e = getNextArg(skip);
+ if (skip)
+ continue;
if (!e)
return true;
auto t = e.type.toBasetype();
if (t.ty != Tint32 && t.ty != Tuns32)
- errorMsg("precision ", slice, e, "int", t);
+ errorMsg("precision ", e, "int", t);
}
- auto e = getNextArg();
+ bool skip;
+ auto e = getNextArg(skip);
+ if (skip)
+ continue;
if (!e)
return true;
auto t = e.type.toBasetype();
auto tnext = t.nextOf();
const c_longsize = target.c.longsize;
- const is64bit = global.params.is64bit;
+ const ptrsize = target.ptrsize;
// Types which are promoted to int are allowed.
// Spec: C99 6.5.2.2.7
@@ -136,130 +154,143 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
case Format.u: // unsigned int
case Format.d: // int
if (t.ty != Tint32 && t.ty != Tuns32)
- errorMsg(null, slice, e, "int", t);
+ errorMsg(null, e, fmt == Format.u ? "uint" : "int", t);
break;
case Format.hhu: // unsigned char
case Format.hhd: // signed char
if (t.ty != Tint32 && t.ty != Tuns32 && t.ty != Tint8 && t.ty != Tuns8)
- errorMsg(null, slice, e, "byte", t);
+ errorMsg(null, e, fmt == Format.hhu ? "ubyte" : "byte", t);
break;
case Format.hu: // unsigned short int
case Format.hd: // short int
if (t.ty != Tint32 && t.ty != Tuns32 && t.ty != Tint16 && t.ty != Tuns16)
- errorMsg(null, slice, e, "short", t);
+ errorMsg(null, e, fmt == Format.hu ? "ushort" : "short", t);
break;
case Format.lu: // unsigned long int
case Format.ld: // long int
if (!(t.isintegral() && t.size() == c_longsize))
- errorMsg(null, slice, e, (c_longsize == 4 ? "int" : "long"), t);
+ {
+ if (fmt == Format.lu)
+ errorMsg(null, e, (c_longsize == 4 ? "uint" : "ulong"), t);
+ else
+ errorMsg(null, e, (c_longsize == 4 ? "int" : "long"), t);
+ }
break;
case Format.llu: // unsigned long long int
case Format.lld: // long long int
if (t.ty != Tint64 && t.ty != Tuns64)
- errorMsg(null, slice, e, "long", t);
+ errorMsg(null, e, fmt == Format.llu ? "ulong" : "long", t);
break;
case Format.ju: // uintmax_t
case Format.jd: // intmax_t
if (t.ty != Tint64 && t.ty != Tuns64)
- errorMsg(null, slice, e, "core.stdc.stdint.intmax_t", t);
+ {
+ if (fmt == Format.ju)
+ errorMsg(null, e, "core.stdc.stdint.uintmax_t", t);
+ else
+ errorMsg(null, e, "core.stdc.stdint.intmax_t", t);
+ }
break;
case Format.zd: // size_t
- if (!(t.isintegral() && t.size() == (is64bit ? 8 : 4)))
- errorMsg(null, slice, e, "size_t", t);
+ if (!(t.isintegral() && t.size() == ptrsize))
+ errorMsg(null, e, "size_t", t);
break;
case Format.td: // ptrdiff_t
- if (!(t.isintegral() && t.size() == (is64bit ? 8 : 4)))
- errorMsg(null, slice, e, "ptrdiff_t", t);
+ if (!(t.isintegral() && t.size() == ptrsize))
+ errorMsg(null, e, "ptrdiff_t", t);
break;
+ case Format.GNU_a: // Format.GNU_a is only for scanf
case Format.lg:
case Format.g: // double
if (t.ty != Tfloat64 && t.ty != Timaginary64)
- errorMsg(null, slice, e, "double", t);
+ errorMsg(null, e, "double", t);
break;
case Format.Lg: // long double
if (t.ty != Tfloat80 && t.ty != Timaginary80)
- errorMsg(null, slice, e, "real", t);
+ errorMsg(null, e, "real", t);
break;
case Format.p: // pointer
if (t.ty != Tpointer && t.ty != Tnull && t.ty != Tclass && t.ty != Tdelegate && t.ty != Taarray)
- errorMsg(null, slice, e, "void*", t);
+ errorMsg(null, e, "void*", t);
break;
case Format.n: // pointer to int
if (!(t.ty == Tpointer && tnext.ty == Tint32))
- errorMsg(null, slice, e, "int*", t);
+ errorMsg(null, e, "int*", t);
break;
case Format.ln: // pointer to long int
if (!(t.ty == Tpointer && tnext.isintegral() && tnext.size() == c_longsize))
- errorMsg(null, slice, e, (c_longsize == 4 ? "int*" : "long*"), t);
+ errorMsg(null, e, (c_longsize == 4 ? "int*" : "long*"), t);
break;
case Format.lln: // pointer to long long int
if (!(t.ty == Tpointer && tnext.ty == Tint64))
- errorMsg(null, slice, e, "long*", t);
+ errorMsg(null, e, "long*", t);
break;
case Format.hn: // pointer to short
if (!(t.ty == Tpointer && tnext.ty == Tint16))
- errorMsg(null, slice, e, "short*", t);
+ errorMsg(null, e, "short*", t);
break;
case Format.hhn: // pointer to signed char
if (!(t.ty == Tpointer && tnext.ty == Tint16))
- errorMsg(null, slice, e, "byte*", t);
+ errorMsg(null, e, "byte*", t);
break;
case Format.jn: // pointer to intmax_t
if (!(t.ty == Tpointer && tnext.ty == Tint64))
- errorMsg(null, slice, e, "core.stdc.stdint.intmax_t*", t);
+ errorMsg(null, e, "core.stdc.stdint.intmax_t*", t);
break;
case Format.zn: // pointer to size_t
- if (!(t.ty == Tpointer && tnext.ty == (is64bit ? Tuns64 : Tuns32)))
- errorMsg(null, slice, e, "size_t*", t);
+ if (!(t.ty == Tpointer && tnext.isintegral() && tnext.isunsigned() && tnext.size() == ptrsize))
+ errorMsg(null, e, "size_t*", t);
break;
case Format.tn: // pointer to ptrdiff_t
- if (!(t.ty == Tpointer && tnext.ty == (is64bit ? Tint64 : Tint32)))
- errorMsg(null, slice, e, "ptrdiff_t*", t);
+ if (!(t.ty == Tpointer && tnext.isintegral() && !tnext.isunsigned() && tnext.size() == ptrsize))
+ errorMsg(null, e, "ptrdiff_t*", t);
break;
case Format.c: // char
if (t.ty != Tint32 && t.ty != Tuns32)
- errorMsg(null, slice, e, "char", t);
+ errorMsg(null, e, "char", t);
break;
case Format.lc: // wint_t
if (t.ty != Tint32 && t.ty != Tuns32)
- errorMsg(null, slice, e, "wchar_t", t);
+ errorMsg(null, e, "wchar_t", t);
break;
case Format.s: // pointer to char string
if (!(t.ty == Tpointer && (tnext.ty == Tchar || tnext.ty == Tint8 || tnext.ty == Tuns8)))
- errorMsg(null, slice, e, "char*", t);
+ errorMsg(null, e, "char*", t);
break;
case Format.ls: // pointer to wchar_t string
- const twchar_t = global.params.isWindows ? Twchar : Tdchar;
- if (!(t.ty == Tpointer && tnext.ty == twchar_t))
- errorMsg(null, slice, e, "wchar_t*", t);
+ if (!(t.ty == Tpointer && tnext.ty.isSomeChar && tnext.size() == target.c.wchar_tsize))
+ errorMsg(null, e, "wchar_t*", t);
break;
case Format.error:
deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr);
break;
+ case Format.GNU_m:
+ break; // not assert(0) because it may go through it if there are extra arguments
+
case Format.percent:
assert(0);
}
@@ -340,7 +371,7 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres
return args[n++];
}
- void errorMsg(const char* prefix, const char[] specifier, Expression arg, const char* texpect, Type tactual)
+ void errorMsg(const char* prefix, Expression arg, const char* texpect, Type tactual)
{
deprecation(arg.loc, "%sargument `%s` for format specification `\"%.*s\"` must be `%s`, not `%s`",
prefix ? prefix : "", arg.toChars(), cast(int)slice.length, slice.ptr, texpect, tactual.toChars());
@@ -353,117 +384,120 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres
auto t = e.type.toBasetype();
auto tnext = t.nextOf();
const c_longsize = target.c.longsize;
- const is64bit = global.params.is64bit;
+ const ptrsize = target.ptrsize;
final switch (fmt)
{
case Format.n:
case Format.d: // pointer to int
if (!(t.ty == Tpointer && tnext.ty == Tint32))
- errorMsg(null, slice, e, "int*", t);
+ errorMsg(null, e, "int*", t);
break;
case Format.hhn:
case Format.hhd: // pointer to signed char
if (!(t.ty == Tpointer && tnext.ty == Tint16))
- errorMsg(null, slice, e, "byte*", t);
+ errorMsg(null, e, "byte*", t);
break;
case Format.hn:
case Format.hd: // pointer to short
if (!(t.ty == Tpointer && tnext.ty == Tint16))
- errorMsg(null, slice, e, "short*", t);
+ errorMsg(null, e, "short*", t);
break;
case Format.ln:
case Format.ld: // pointer to long int
- if (!(t.ty == Tpointer && tnext.isintegral() && tnext.size() == c_longsize))
- errorMsg(null, slice, e, (c_longsize == 4 ? "int*" : "long*"), t);
+ if (!(t.ty == Tpointer && tnext.isintegral() && !tnext.isunsigned() && tnext.size() == c_longsize))
+ errorMsg(null, e, (c_longsize == 4 ? "int*" : "long*"), t);
break;
case Format.lln:
case Format.lld: // pointer to long long int
if (!(t.ty == Tpointer && tnext.ty == Tint64))
- errorMsg(null, slice, e, "long*", t);
+ errorMsg(null, e, "long*", t);
break;
case Format.jn:
case Format.jd: // pointer to intmax_t
if (!(t.ty == Tpointer && tnext.ty == Tint64))
- errorMsg(null, slice, e, "core.stdc.stdint.intmax_t*", t);
+ errorMsg(null, e, "core.stdc.stdint.intmax_t*", t);
break;
case Format.zn:
case Format.zd: // pointer to size_t
- if (!(t.ty == Tpointer && tnext.ty == (is64bit ? Tuns64 : Tuns32)))
- errorMsg(null, slice, e, "size_t*", t);
+ if (!(t.ty == Tpointer && tnext.isintegral() && tnext.isunsigned() && tnext.size() == ptrsize))
+ errorMsg(null, e, "size_t*", t);
break;
case Format.tn:
case Format.td: // pointer to ptrdiff_t
- if (!(t.ty == Tpointer && tnext.ty == (is64bit ? Tint64 : Tint32)))
- errorMsg(null, slice, e, "ptrdiff_t*", t);
+ if (!(t.ty == Tpointer && tnext.isintegral() && !tnext.isunsigned() && tnext.size() == ptrsize))
+ errorMsg(null, e, "ptrdiff_t*", t);
break;
case Format.u: // pointer to unsigned int
if (!(t.ty == Tpointer && tnext.ty == Tuns32))
- errorMsg(null, slice, e, "uint*", t);
+ errorMsg(null, e, "uint*", t);
break;
case Format.hhu: // pointer to unsigned char
if (!(t.ty == Tpointer && tnext.ty == Tuns8))
- errorMsg(null, slice, e, "ubyte*", t);
+ errorMsg(null, e, "ubyte*", t);
break;
case Format.hu: // pointer to unsigned short int
if (!(t.ty == Tpointer && tnext.ty == Tuns16))
- errorMsg(null, slice, e, "ushort*", t);
+ errorMsg(null, e, "ushort*", t);
break;
case Format.lu: // pointer to unsigned long int
- if (!(t.ty == Tpointer && tnext.ty == (is64bit ? Tuns64 : Tuns32)))
- errorMsg(null, slice, e, (c_longsize == 4 ? "uint*" : "ulong*"), t);
+ if (!(t.ty == Tpointer && tnext.isintegral() && tnext.isunsigned() && tnext.size() == c_longsize))
+ errorMsg(null, e, (c_longsize == 4 ? "uint*" : "ulong*"), t);
break;
case Format.llu: // pointer to unsigned long long int
if (!(t.ty == Tpointer && tnext.ty == Tuns64))
- errorMsg(null, slice, e, "ulong*", t);
+ errorMsg(null, e, "ulong*", t);
break;
case Format.ju: // pointer to uintmax_t
- if (!(t.ty == Tpointer && tnext.ty == (is64bit ? Tuns64 : Tuns32)))
- errorMsg(null, slice, e, "ulong*", t);
+ if (!(t.ty == Tpointer && tnext.ty == Tuns64))
+ errorMsg(null, e, "core.stdc.stdint.uintmax_t*", t);
break;
case Format.g: // pointer to float
if (!(t.ty == Tpointer && tnext.ty == Tfloat32))
- errorMsg(null, slice, e, "float*", t);
+ errorMsg(null, e, "float*", t);
break;
+
case Format.lg: // pointer to double
if (!(t.ty == Tpointer && tnext.ty == Tfloat64))
- errorMsg(null, slice, e, "double*", t);
+ errorMsg(null, e, "double*", t);
break;
+
case Format.Lg: // pointer to long double
if (!(t.ty == Tpointer && tnext.ty == Tfloat80))
- errorMsg(null, slice, e, "real*", t);
+ errorMsg(null, e, "real*", t);
break;
+ case Format.GNU_a:
+ case Format.GNU_m:
case Format.c:
case Format.s: // pointer to char string
if (!(t.ty == Tpointer && (tnext.ty == Tchar || tnext.ty == Tint8 || tnext.ty == Tuns8)))
- errorMsg(null, slice, e, "char*", t);
+ errorMsg(null, e, "char*", t);
break;
case Format.lc:
case Format.ls: // pointer to wchar_t string
- const twchar_t = global.params.isWindows ? Twchar : Tdchar;
- if (!(t.ty == Tpointer && tnext.ty == twchar_t))
- errorMsg(null, slice, e, "wchar_t*", t);
+ if (!(t.ty == Tpointer && tnext.ty.isSomeChar && tnext.size() == target.c.wchar_tsize))
+ errorMsg(null, e, "wchar_t*", t);
break;
case Format.p: // double pointer
if (!(t.ty == Tpointer && tnext.ty == Tpointer))
- errorMsg(null, slice, e, "void**", t);
+ errorMsg(null, e, "void**", t);
break;
case Format.error:
@@ -493,9 +527,8 @@ private:
* Returns:
* Format
*/
-pure nothrow @safe
Format parseScanfFormatSpecifier(scope const char[] format, ref size_t idx,
- out bool asterisk)
+ out bool asterisk) nothrow pure @safe
{
auto i = idx;
assert(format[i] == '%');
@@ -583,9 +616,8 @@ Format parseScanfFormatSpecifier(scope const char[] format, ref size_t idx,
* Returns:
* Format
*/
-pure nothrow @safe
Format parsePrintfFormatSpecifier(scope const char[] format, ref size_t idx,
- out bool widthStar, out bool precisionStar)
+ out bool widthStar, out bool precisionStar) nothrow pure @safe
{
auto i = idx;
assert(format[i] == '%');
@@ -767,6 +799,8 @@ enum Format
jn, // pointer to intmax_t
zn, // pointer to size_t
tn, // pointer to ptrdiff_t
+ GNU_a, // GNU ext. : address to a string with no maximum size (scanf)
+ GNU_m, // GNU ext. : string corresponding to the error code in errno (printf) / length modifier (scanf)
percent, // %% (i.e. no argument)
error, // invalid format specification
}
@@ -785,9 +819,9 @@ enum Format
* Returns:
* Format
*/
-pure @safe nothrow
Format parseGenericFormatSpecifier(scope const char[] format,
- ref size_t idx, out char genSpecifier)
+ ref size_t idx, out char genSpecifier, bool useGNUExts =
+ findCondition(global.versionids, Identifier.idPool("CRuntime_Glibc"))) nothrow pure @trusted
{
const length = format.length;
@@ -859,13 +893,21 @@ Format parseGenericFormatSpecifier(scope const char[] format,
Format.u;
break;
+ case 'a':
+ if (useGNUExts)
+ {
+ // https://www.gnu.org/software/libc/manual/html_node/Dynamic-String-Input.html
+ specifier = Format.GNU_a;
+ break;
+ }
+ goto case;
+
case 'f':
case 'F':
case 'e':
case 'E':
case 'g':
case 'G':
- case 'a':
case 'A':
if (lm == 'L')
specifier = Format.Lg;
@@ -910,6 +952,15 @@ Format parseGenericFormatSpecifier(scope const char[] format,
Format.n;
break;
+ case 'm':
+ if (useGNUExts)
+ {
+ // http://www.gnu.org/software/libc/manual/html_node/Other-Output-Conversions.html
+ specifier = Format.GNU_m;
+ break;
+ }
+ goto default;
+
default:
specifier = Format.error;
break;
@@ -1075,7 +1126,8 @@ unittest
assert(idx == 2);
idx = 0;
- assert(parsePrintfFormatSpecifier("%a", idx, widthStar, precisionStar) == Format.g);
+ Format g = parsePrintfFormatSpecifier("%a", idx, widthStar, precisionStar);
+ assert(g == Format.g || g == Format.GNU_a);
assert(idx == 2);
idx = 0;
@@ -1123,7 +1175,6 @@ unittest
{
idx = 0;
assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar) == Format.error);
- import std.stdio;
assert(idx == s.length);
}
}
@@ -1245,7 +1296,8 @@ unittest
assert(idx == 2);
idx = 0;
- assert(parseScanfFormatSpecifier("%a", idx, asterisk) == Format.g);
+ g = parseScanfFormatSpecifier("%a", idx, asterisk);
+ assert(g == Format.g || g == Format.GNU_a);
assert(idx == 2);
idx = 0;
diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d
index a76f109e66b..094ce0051a0 100644
--- a/gcc/d/dmd/clone.d
+++ b/gcc/d/dmd/clone.d
@@ -1,7 +1,8 @@
/**
- * Define the implicit `opEquals`, `opAssign`, post blit, copy constructor and destructor for structs.
+ * Builds struct member functions if needed and not defined by the user.
+ * Includes `opEquals`, `opAssign`, post blit, copy constructor and destructor.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/clone.d, _clone.d)
@@ -14,6 +15,7 @@ module dmd.clone;
import core.stdc.stdio;
import dmd.aggregate;
import dmd.arraytypes;
+import dmd.astenums;
import dmd.dclass;
import dmd.declaration;
import dmd.dscope;
@@ -21,6 +23,7 @@ import dmd.dstruct;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.dtemplate;
+import dmd.errors;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
@@ -31,6 +34,7 @@ import dmd.init;
import dmd.mtype;
import dmd.opover;
import dmd.semantic2;
+import dmd.semantic3;
import dmd.statement;
import dmd.target;
import dmd.typesem;
@@ -1113,8 +1117,8 @@ DtorDeclaration buildExternDDtor(AggregateDeclaration ad, Scope* sc)
if (!dtor)
return null;
- // ABI incompatible on all (?) x86 32-bit platforms
- if (ad.classKind != ClassKind.cpp || global.params.is64bit)
+ // Generate shim only when ABI incompatible on target platform
+ if (ad.classKind != ClassKind.cpp || !target.cpp.wrapDtorInExternD)
return dtor;
// generate member function that adjusts calling convention
@@ -1201,3 +1205,501 @@ FuncDeclaration buildInv(AggregateDeclaration ad, Scope* sc)
return inv;
}
}
+
+/*****************************************
+ * Create inclusive postblit for struct by aggregating
+ * all the postblits in postblits[] with the postblits for
+ * all the members.
+ * Note the close similarity with AggregateDeclaration::buildDtor(),
+ * and the ordering changes (runs forward instead of backwards).
+ */
+FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
+{
+ //printf("buildPostBlit() %s\n", sd.toChars());
+ if (sd.isUnionDeclaration())
+ return null;
+
+ const hasUserDefinedPosblit = sd.postblits.dim && !sd.postblits[0].isDisabled ? true : false;
+
+ // by default, the storage class of the created postblit
+ StorageClass stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
+ Loc declLoc = sd.postblits.dim ? sd.postblits[0].loc : sd.loc;
+ Loc loc; // internal code should have no loc to prevent coverage
+
+ // if any of the postblits are disabled, then the generated postblit
+ // will be disabled
+ for (size_t i = 0; i < sd.postblits.dim; i++)
+ {
+ stc |= sd.postblits[i].storage_class & STC.disable;
+ }
+
+ VarDeclaration[] fieldsToDestroy;
+ auto postblitCalls = new Statements();
+ // iterate through all the struct fields that are not disabled
+ for (size_t i = 0; i < sd.fields.dim && !(stc & STC.disable); i++)
+ {
+ auto structField = sd.fields[i];
+ if (structField.storage_class & STC.ref_)
+ continue;
+ if (structField.overlapped)
+ continue;
+ // if it's a struct declaration or an array of structs
+ Type tv = structField.type.baseElemOf();
+ if (tv.ty != Tstruct)
+ continue;
+ auto sdv = (cast(TypeStruct)tv).sym;
+ // which has a postblit declaration
+ if (!sdv.postblit)
+ continue;
+ assert(!sdv.isUnionDeclaration());
+
+ // if this field's postblit is not `nothrow`, add a `scope(failure)`
+ // block to destroy any prior successfully postblitted fields should
+ // this field's postblit fail
+ if (fieldsToDestroy.length > 0 && !(cast(TypeFunction)sdv.postblit.type).isnothrow)
+ {
+ // create a list of destructors that need to be called
+ Expression[] dtorCalls;
+ foreach(sf; fieldsToDestroy)
+ {
+ Expression ex;
+ tv = sf.type.toBasetype();
+ if (tv.ty == Tstruct)
+ {
+ // this.v.__xdtor()
+
+ ex = new ThisExp(loc);
+ ex = new DotVarExp(loc, ex, sf);
+
+ // This is a hack so we can call destructors on const/immutable objects.
+ ex = new AddrExp(loc, ex);
+ ex = new CastExp(loc, ex, sf.type.mutableOf().pointerTo());
+ ex = new PtrExp(loc, ex);
+ if (stc & STC.safe)
+ stc = (stc & ~STC.safe) | STC.trusted;
+
+ auto sfv = (cast(TypeStruct)sf.type.baseElemOf()).sym;
+
+ ex = new DotVarExp(loc, ex, sfv.dtor, false);
+ ex = new CallExp(loc, ex);
+
+ dtorCalls ~= ex;
+ }
+ else
+ {
+ // _ArrayDtor((cast(S*)this.v.ptr)[0 .. n])
+
+ const length = tv.numberOfElems(loc);
+
+ ex = new ThisExp(loc);
+ ex = new DotVarExp(loc, ex, sf);
+
+ // This is a hack so we can call destructors on const/immutable objects.
+ ex = new DotIdExp(loc, ex, Id.ptr);
+ ex = new CastExp(loc, ex, sdv.type.pointerTo());
+ if (stc & STC.safe)
+ stc = (stc & ~STC.safe) | STC.trusted;
+
+ auto se = new SliceExp(loc, ex, new IntegerExp(loc, 0, Type.tsize_t),
+ new IntegerExp(loc, length, Type.tsize_t));
+ // Prevent redundant bounds check
+ se.upperIsInBounds = true;
+ se.lowerIsLessThanUpper = true;
+
+ ex = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), se);
+
+ dtorCalls ~= ex;
+ }
+ }
+ fieldsToDestroy = [];
+
+ // aggregate the destructor calls
+ auto dtors = new Statements();
+ foreach_reverse(dc; dtorCalls)
+ {
+ dtors.push(new ExpStatement(loc, dc));
+ }
+
+ // put destructor calls in a `scope(failure)` block
+ postblitCalls.push(new ScopeGuardStatement(loc, TOK.onScopeFailure, new CompoundStatement(loc, dtors)));
+ }
+
+ // perform semantic on the member postblit in order to
+ // be able to aggregate it later on with the rest of the
+ // postblits
+ sdv.postblit.functionSemantic();
+
+ stc = mergeFuncAttrs(stc, sdv.postblit);
+ stc = mergeFuncAttrs(stc, sdv.dtor);
+
+ // if any of the struct member fields has disabled
+ // its postblit, then `sd` is not copyable, so no
+ // postblit is generated
+ if (stc & STC.disable)
+ {
+ postblitCalls.setDim(0);
+ break;
+ }
+
+ Expression ex;
+ tv = structField.type.toBasetype();
+ if (tv.ty == Tstruct)
+ {
+ // this.v.__xpostblit()
+
+ ex = new ThisExp(loc);
+ ex = new DotVarExp(loc, ex, structField);
+
+ // This is a hack so we can call postblits on const/immutable objects.
+ ex = new AddrExp(loc, ex);
+ ex = new CastExp(loc, ex, structField.type.mutableOf().pointerTo());
+ ex = new PtrExp(loc, ex);
+ if (stc & STC.safe)
+ stc = (stc & ~STC.safe) | STC.trusted;
+
+ ex = new DotVarExp(loc, ex, sdv.postblit, false);
+ ex = new CallExp(loc, ex);
+ }
+ else
+ {
+ // _ArrayPostblit((cast(S*)this.v.ptr)[0 .. n])
+
+ const length = tv.numberOfElems(loc);
+ if (length == 0)
+ continue;
+
+ ex = new ThisExp(loc);
+ ex = new DotVarExp(loc, ex, structField);
+
+ // This is a hack so we can call postblits on const/immutable objects.
+ ex = new DotIdExp(loc, ex, Id.ptr);
+ ex = new CastExp(loc, ex, sdv.type.pointerTo());
+ if (stc & STC.safe)
+ stc = (stc & ~STC.safe) | STC.trusted;
+
+ auto se = new SliceExp(loc, ex, new IntegerExp(loc, 0, Type.tsize_t),
+ new IntegerExp(loc, length, Type.tsize_t));
+ // Prevent redundant bounds check
+ se.upperIsInBounds = true;
+ se.lowerIsLessThanUpper = true;
+ ex = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayPostblit), se);
+ }
+ postblitCalls.push(new ExpStatement(loc, ex)); // combine in forward order
+
+ /* https://issues.dlang.org/show_bug.cgi?id=10972
+ * When subsequent field postblit calls fail,
+ * this field should be destructed for Exception Safety.
+ */
+ if (sdv.dtor)
+ {
+ sdv.dtor.functionSemantic();
+
+ // keep a list of fields that need to be destroyed in case
+ // of a future postblit failure
+ fieldsToDestroy ~= structField;
+ }
+ }
+
+ void checkShared()
+ {
+ if (sd.type.isShared())
+ stc |= STC.shared_;
+ }
+
+ // Build our own "postblit" which executes a, but only if needed.
+ if (postblitCalls.dim || (stc & STC.disable))
+ {
+ //printf("Building __fieldPostBlit()\n");
+ checkShared();
+ auto dd = new PostBlitDeclaration(declLoc, Loc.initial, stc, Id.__fieldPostblit);
+ dd.generated = true;
+ dd.storage_class |= STC.inference | STC.scope_;
+ dd.fbody = (stc & STC.disable) ? null : new CompoundStatement(loc, postblitCalls);
+ sd.postblits.shift(dd);
+ sd.members.push(dd);
+ dd.dsymbolSemantic(sc);
+ }
+
+ // create __xpostblit, which is the generated postblit
+ FuncDeclaration xpostblit = null;
+ switch (sd.postblits.dim)
+ {
+ case 0:
+ break;
+
+ case 1:
+ xpostblit = sd.postblits[0];
+ break;
+
+ default:
+ Expression e = null;
+ stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
+ for (size_t i = 0; i < sd.postblits.dim; i++)
+ {
+ auto fd = sd.postblits[i];
+ stc = mergeFuncAttrs(stc, fd);
+ if (stc & STC.disable)
+ {
+ e = null;
+ break;
+ }
+ Expression ex = new ThisExp(loc);
+ ex = new DotVarExp(loc, ex, fd, false);
+ ex = new CallExp(loc, ex);
+ e = Expression.combine(e, ex);
+ }
+
+ checkShared();
+ auto dd = new PostBlitDeclaration(declLoc, Loc.initial, stc, Id.__aggrPostblit);
+ dd.generated = true;
+ dd.storage_class |= STC.inference;
+ dd.fbody = new ExpStatement(loc, e);
+ sd.members.push(dd);
+ dd.dsymbolSemantic(sc);
+ xpostblit = dd;
+ break;
+ }
+
+ // Add an __xpostblit alias to make the inclusive postblit accessible
+ if (xpostblit)
+ {
+ auto _alias = new AliasDeclaration(Loc.initial, Id.__xpostblit, xpostblit);
+ _alias.dsymbolSemantic(sc);
+ sd.members.push(_alias);
+ _alias.addMember(sc, sd); // add to symbol table
+ }
+
+ if (sd.hasCopyCtor)
+ {
+ // we have user defined postblit, so we prioritize it
+ if (hasUserDefinedPosblit)
+ {
+ sd.hasCopyCtor = false;
+ return xpostblit;
+ }
+ // we have fields with postblits, so print deprecations
+ if (xpostblit && !xpostblit.isDisabled())
+ {
+ deprecation(sd.loc, "`struct %s` implicitly-generated postblit hides copy constructor.", sd.toChars);
+ deprecationSupplemental(sd.loc, "The field postblit will have priority over the copy constructor.");
+ deprecationSupplemental(sd.loc, "To change this, the postblit should be disabled for `struct %s`", sd.toChars());
+ sd.hasCopyCtor = false;
+ }
+ else
+ xpostblit = null;
+ }
+
+ return xpostblit;
+}
+
+/**
+ * Generates a copy constructor declaration with the specified storage
+ * class for the parameter and the function.
+ *
+ * Params:
+ * sd = the `struct` that contains the copy constructor
+ * paramStc = the storage class of the copy constructor parameter
+ * funcStc = the storage class for the copy constructor declaration
+ *
+ * Returns:
+ * The copy constructor declaration for struct `sd`.
+ */
+private CtorDeclaration generateCopyCtorDeclaration(StructDeclaration sd, const StorageClass paramStc, const StorageClass funcStc)
+{
+ auto fparams = new Parameters();
+ auto structType = sd.type;
+ fparams.push(new Parameter(paramStc | STC.ref_ | STC.return_ | STC.scope_, structType, Id.p, null, null));
+ ParameterList pList = ParameterList(fparams);
+ auto tf = new TypeFunction(pList, structType, LINK.d, STC.ref_);
+ auto ccd = new CtorDeclaration(sd.loc, Loc.initial, STC.ref_, tf, true);
+ ccd.storage_class |= funcStc;
+ ccd.storage_class |= STC.inference;
+ ccd.generated = true;
+ return ccd;
+}
+
+/**
+ * Generates a trivial copy constructor body that simply does memberwise
+ * initialization:
+ *
+ * this.field1 = rhs.field1;
+ * this.field2 = rhs.field2;
+ * ...
+ *
+ * Params:
+ * sd = the `struct` declaration that contains the copy constructor
+ *
+ * Returns:
+ * A `CompoundStatement` containing the body of the copy constructor.
+ */
+private Statement generateCopyCtorBody(StructDeclaration sd)
+{
+ Loc loc;
+ Expression e;
+ foreach (v; sd.fields)
+ {
+ auto ec = new AssignExp(loc,
+ new DotVarExp(loc, new ThisExp(loc), v),
+ new DotVarExp(loc, new IdentifierExp(loc, Id.p), v));
+ e = Expression.combine(e, ec);
+ //printf("e.toChars = %s\n", e.toChars());
+ }
+ Statement s1 = new ExpStatement(loc, e);
+ return new CompoundStatement(loc, s1);
+}
+
+/**
+ * Determine if a copy constructor is needed for struct sd,
+ * if the following conditions are met:
+ *
+ * 1. sd does not define a copy constructor
+ * 2. at least one field of sd defines a copy constructor
+ *
+ * Params:
+ * sd = the `struct` for which the copy constructor is generated
+ * hasCpCtor = set to true if a copy constructor is already present
+ *
+ * Returns:
+ * `true` if one needs to be generated
+ * `false` otherwise
+ */
+private bool needCopyCtor(StructDeclaration sd, out bool hasCpCtor)
+{
+ if (global.errors)
+ return false;
+
+ auto ctor = sd.search(sd.loc, Id.ctor);
+ if (ctor)
+ {
+ if (ctor.isOverloadSet())
+ return false;
+ if (auto td = ctor.isTemplateDeclaration())
+ ctor = td.funcroot;
+ }
+
+ CtorDeclaration cpCtor;
+ CtorDeclaration rvalueCtor;
+
+ if (!ctor)
+ goto LcheckFields;
+
+ overloadApply(ctor, (Dsymbol s)
+ {
+ if (s.isTemplateDeclaration())
+ return 0;
+ auto ctorDecl = s.isCtorDeclaration();
+ assert(ctorDecl);
+ if (ctorDecl.isCpCtor)
+ {
+ if (!cpCtor)
+ cpCtor = ctorDecl;
+ return 0;
+ }
+
+ auto tf = ctorDecl.type.toTypeFunction();
+ const dim = tf.parameterList.length;
+ if (dim == 1)
+ {
+ auto param = tf.parameterList[0];
+ if (param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
+ {
+ rvalueCtor = ctorDecl;
+ }
+ }
+ return 0;
+ });
+
+ if (cpCtor)
+ {
+ if (rvalueCtor)
+ {
+ .error(sd.loc, "`struct %s` may not define both a rvalue constructor and a copy constructor", sd.toChars());
+ errorSupplemental(rvalueCtor.loc,"rvalue constructor defined here");
+ errorSupplemental(cpCtor.loc, "copy constructor defined here");
+ }
+ hasCpCtor = true;
+ return false;
+ }
+
+LcheckFields:
+ VarDeclaration fieldWithCpCtor;
+ // see if any struct members define a copy constructor
+ foreach (v; sd.fields)
+ {
+ if (v.storage_class & STC.ref_)
+ continue;
+ if (v.overlapped)
+ continue;
+
+ auto ts = v.type.baseElemOf().isTypeStruct();
+ if (!ts)
+ continue;
+ if (ts.sym.hasCopyCtor)
+ {
+ fieldWithCpCtor = v;
+ break;
+ }
+ }
+
+ if (fieldWithCpCtor && rvalueCtor)
+ {
+ .error(sd.loc, "`struct %s` may not define a rvalue constructor and have fields with copy constructors", sd.toChars());
+ errorSupplemental(rvalueCtor.loc,"rvalue constructor defined here");
+ errorSupplemental(fieldWithCpCtor.loc, "field with copy constructor defined here");
+ return false;
+ }
+ else if (!fieldWithCpCtor)
+ return false;
+ return true;
+}
+
+/**
+ * Generates a copy constructor if needCopyCtor() returns true.
+ * The generated copy constructor will be of the form:
+ * this(ref return scope inout(S) rhs) inout
+ * {
+ * this.field1 = rhs.field1;
+ * this.field2 = rhs.field2;
+ * ...
+ * }
+ *
+ * Params:
+ * sd = the `struct` for which the copy constructor is generated
+ * sc = the scope where the copy constructor is generated
+ *
+ * Returns:
+ * `true` if `struct` sd defines a copy constructor (explicitly or generated),
+ * `false` otherwise.
+ */
+bool buildCopyCtor(StructDeclaration sd, Scope* sc)
+{
+ bool hasCpCtor;
+ if (!needCopyCtor(sd, hasCpCtor))
+ return hasCpCtor;
+
+ //printf("generating copy constructor for %s\n", sd.toChars());
+ const MOD paramMod = MODFlags.wild;
+ const MOD funcMod = MODFlags.wild;
+ auto ccd = generateCopyCtorDeclaration(sd, ModToStc(paramMod), ModToStc(funcMod));
+ auto copyCtorBody = generateCopyCtorBody(sd);
+ ccd.fbody = copyCtorBody;
+ sd.members.push(ccd);
+ ccd.addMember(sc, sd);
+ const errors = global.startGagging();
+ Scope* sc2 = sc.push();
+ sc2.stc = 0;
+ sc2.linkage = LINK.d;
+ ccd.dsymbolSemantic(sc2);
+ ccd.semantic2(sc2);
+ ccd.semantic3(sc2);
+ //printf("ccd semantic: %s\n", ccd.type.toChars());
+ sc2.pop();
+ if (global.endGagging(errors) || sd.isUnionDeclaration())
+ {
+ ccd.storage_class |= STC.disable;
+ ccd.fbody = null;
+ }
+ return true;
+}
+
+
diff --git a/gcc/d/dmd/compiler.d b/gcc/d/dmd/compiler.d
index 667beb5bf95..28f9ba6fdc4 100644
--- a/gcc/d/dmd/compiler.d
+++ b/gcc/d/dmd/compiler.d
@@ -1,7 +1,7 @@
/**
* Describes a back-end compiler and implements compiler-specific actions.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/compiler.d, _compiler.d)
@@ -20,9 +20,6 @@ import dmd.root.array;
extern (C++) __gshared
{
- /// Module in which the D main is
- Module rootHasMain = null;
-
bool includeImports = false;
// array of module patterns used to include/exclude imported modules
Array!(const(char)*) includeModulePatterns;
diff --git a/gcc/d/dmd/compiler.h b/gcc/d/dmd/compiler.h
index c8259edfa8b..27e87b692a8 100644
--- a/gcc/d/dmd/compiler.h
+++ b/gcc/d/dmd/compiler.h
@@ -22,9 +22,6 @@ class Type;
struct Scope;
struct UnionExp;
-// Module in which the D main is
-extern Module *rootHasMain;
-
extern bool includeImports;
// array of module patterns used to include/exclude imported modules
extern Array<const char*> includeModulePatterns;
diff --git a/gcc/d/dmd/complex.d b/gcc/d/dmd/complex.d
index 61bffdabb6d..84bf5e9763a 100644
--- a/gcc/d/dmd/complex.d
+++ b/gcc/d/dmd/complex.d
@@ -1,7 +1,7 @@
/**
* Implements a complex number type.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/complex.d, _complex.d)
diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d
index 22387072e61..cf12ee4e530 100644
--- a/gcc/d/dmd/cond.d
+++ b/gcc/d/dmd/cond.d
@@ -3,7 +3,7 @@
*
* Specification: $(LINK2 https://dlang.org/spec/version.html, Conditional Compilation)
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cond.d, _cond.d)
@@ -15,6 +15,7 @@ module dmd.cond;
import core.stdc.string;
import dmd.arraytypes;
+import dmd.astenums;
import dmd.ast_node;
import dmd.dcast;
import dmd.dmodule;
@@ -42,7 +43,7 @@ import dmd.func;
/***********************************************************
*/
-enum Include
+enum Include : ubyte
{
notComputed, /// not computed yet
yes, /// include the conditional code
@@ -130,8 +131,8 @@ extern (C++) final class StaticForeach : RootObject
{
return new StaticForeach(
loc,
- aggrfe ? cast(ForeachStatement)aggrfe.syntaxCopy() : null,
- rangefe ? cast(ForeachRangeStatement)rangefe.syntaxCopy() : null
+ aggrfe ? aggrfe.syntaxCopy() : null,
+ rangefe ? rangefe.syntaxCopy() : null
);
}
@@ -173,6 +174,7 @@ extern (C++) final class StaticForeach : RootObject
aggrfe.aggr = new TupleExp(aggr.loc, es);
aggrfe.aggr = aggrfe.aggr.expressionSemantic(sc);
aggrfe.aggr = aggrfe.aggr.optimize(WANTvalue);
+ aggrfe.aggr = aggrfe.aggr.ctfeInterpret();
}
else
{
@@ -255,7 +257,8 @@ extern (C++) final class StaticForeach : RootObject
auto ty = new TypeTypeof(loc, new TupleExp(loc, e));
sdecl.members.push(new VarDeclaration(loc, ty, fid, null, 0));
auto r = cast(TypeStruct)sdecl.type;
- r.vtinfo = TypeInfoStructDeclaration.create(r); // prevent typeinfo from going to object file
+ if (global.params.useTypeInfo && Type.dtypeinfo)
+ r.vtinfo = TypeInfoStructDeclaration.create(r); // prevent typeinfo from going to object file
return r;
}
@@ -364,20 +367,30 @@ extern (C++) final class StaticForeach : RootObject
sfe.push(new ReturnStatement(aloc, res[0]));
s1.push(createForeach(aloc, pparams[0], new CompoundStatement(aloc, sfe)));
s1.push(new ExpStatement(aloc, new AssertExp(aloc, IntegerExp.literal!0)));
- auto ety = new TypeTypeof(aloc, wrapAndCall(aloc, new CompoundStatement(aloc, s1)));
+ Type ety = new TypeTypeof(aloc, wrapAndCall(aloc, new CompoundStatement(aloc, s1)));
auto aty = ety.arrayOf();
auto idres = Identifier.generateId("__res");
auto vard = new VarDeclaration(aloc, aty, idres, null);
auto s2 = new Statements();
- s2.push(new ExpStatement(aloc, vard));
- auto catass = new CatAssignExp(aloc, new IdentifierExp(aloc, idres), res[1]);
- s2.push(createForeach(aloc, pparams[1], new ExpStatement(aloc, catass)));
- s2.push(new ReturnStatement(aloc, new IdentifierExp(aloc, idres)));
+
+ // Run 'typeof' gagged to avoid duplicate errors and if it fails just create
+ // an empty foreach to expose them.
+ uint olderrors = global.startGagging();
+ ety = ety.typeSemantic(aloc, sc);
+ if (global.endGagging(olderrors))
+ s2.push(createForeach(aloc, pparams[1], null));
+ else
+ {
+ s2.push(new ExpStatement(aloc, vard));
+ auto catass = new CatAssignExp(aloc, new IdentifierExp(aloc, idres), res[1]);
+ s2.push(createForeach(aloc, pparams[1], new ExpStatement(aloc, catass)));
+ s2.push(new ReturnStatement(aloc, new IdentifierExp(aloc, idres)));
+ }
Expression aggr = void;
Type indexty = void;
- if (rangefe && (indexty = ety.typeSemantic(aloc, sc)).isintegral())
+ if (rangefe && (indexty = ety).isintegral())
{
rangefe.lwr.type = indexty;
rangefe.upr.type = indexty;
@@ -440,11 +453,6 @@ extern (C++) final class StaticForeach : RootObject
aggrfe.aggr = aggrfe.aggr.expressionSemantic(sc);
sc = sc.endCTFE();
aggrfe.aggr = aggrfe.aggr.optimize(WANTvalue);
- auto tab = aggrfe.aggr.type.toBasetype();
- if (tab.ty != Ttuple)
- {
- aggrfe.aggr = aggrfe.aggr.ctfeInterpret();
- }
}
if (aggrfe && aggrfe.aggr.type.toBasetype().ty == Terror)
@@ -483,15 +491,15 @@ extern (C++) class DVCondition : Condition
Identifier ident;
Module mod;
- extern (D) this(Module mod, uint level, Identifier ident)
+ extern (D) this(const ref Loc loc, Module mod, uint level, Identifier ident)
{
- super(Loc.initial);
+ super(loc);
this.mod = mod;
this.level = level;
this.ident = ident;
}
- override final Condition syntaxCopy()
+ override final DVCondition syntaxCopy()
{
return this; // don't need to copy
}
@@ -548,10 +556,11 @@ extern (C++) final class DebugCondition : DVCondition
* Only used if `ident` is `null`.
* ident = Identifier required for this condition to pass.
* If `null`, this conditiion will use an integer level.
+ * loc = Location in the source file
*/
- extern (D) this(Module mod, uint level, Identifier ident)
+ extern (D) this(const ref Loc loc, Module mod, uint level, Identifier ident)
{
- super(mod, level, ident);
+ super(loc, mod, level, ident);
}
override int include(Scope* sc)
@@ -655,6 +664,7 @@ extern (C++) final class VersionCondition : DVCondition
case "CRuntime_Glibc":
case "CRuntime_Microsoft":
case "CRuntime_Musl":
+ case "CRuntime_Newlib":
case "CRuntime_UClibc":
case "CRuntime_WASI":
case "Cygwin":
@@ -822,10 +832,11 @@ extern (C++) final class VersionCondition : DVCondition
* Only used if `ident` is `null`.
* ident = Identifier required for this condition to pass.
* If `null`, this conditiion will use an integer level.
+ * loc = Location in the source file
*/
- extern (D) this(Module mod, uint level, Identifier ident)
+ extern (D) this(const ref Loc loc, Module mod, uint level, Identifier ident)
{
- super(mod, level, ident);
+ super(loc, mod, level, ident);
}
override int include(Scope* sc)
@@ -891,7 +902,7 @@ extern (C++) final class StaticIfCondition : Condition
this.exp = exp;
}
- override Condition syntaxCopy()
+ override StaticIfCondition syntaxCopy()
{
return new StaticIfCondition(loc, exp.syntaxCopy());
}
@@ -958,7 +969,7 @@ extern (C++) final class StaticIfCondition : Condition
* Returns:
* true if found
*/
-bool findCondition(Identifiers* ids, Identifier ident)
+bool findCondition(Identifiers* ids, Identifier ident) @safe nothrow pure
{
if (ids)
{
@@ -977,7 +988,7 @@ private void printDepsConditional(Scope* sc, DVCondition condition, const(char)[
if (!global.params.moduleDeps || global.params.moduleDepsFile)
return;
OutBuffer* ob = global.params.moduleDeps;
- Module imod = sc ? sc.instantiatingModule() : condition.mod;
+ Module imod = sc ? sc._module : condition.mod;
if (!imod)
return;
ob.writestring(depType);
diff --git a/gcc/d/dmd/cond.h b/gcc/d/dmd/cond.h
index 87a2d92409e..4f261162ebb 100644
--- a/gcc/d/dmd/cond.h
+++ b/gcc/d/dmd/cond.h
@@ -62,7 +62,7 @@ public:
Identifier *ident;
Module *mod;
- Condition *syntaxCopy();
+ DVCondition *syntaxCopy();
void accept(Visitor *v) { v->visit(this); }
};
@@ -92,7 +92,7 @@ class StaticIfCondition : public Condition
public:
Expression *exp;
- Condition *syntaxCopy();
+ StaticIfCondition *syntaxCopy();
int include(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
diff --git a/gcc/d/dmd/constfold.d b/gcc/d/dmd/constfold.d
index 3d3bafbed15..1dada60de3b 100644
--- a/gcc/d/dmd/constfold.d
+++ b/gcc/d/dmd/constfold.d
@@ -5,7 +5,7 @@
*
* Specification: $(LINK2 https://dlang.org/spec/float.html#fp_const_folding, Floating Point Constant Folding)
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/constfold.d, _constfold.d)
@@ -18,6 +18,7 @@ module dmd.constfold;
import core.stdc.string;
import core.stdc.stdio;
import dmd.arraytypes;
+import dmd.astenums;
import dmd.complex;
import dmd.ctfeexpr;
import dmd.declaration;
@@ -1497,11 +1498,10 @@ private Expressions* copyElements(Expression e1, Expression e2 = null)
/* Also return TOK.cantExpression if this fails
*/
-UnionExp Cat(Type type, Expression e1, Expression e2)
+UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
{
UnionExp ue = void;
Expression e = CTFEExp.cantexp;
- Loc loc = e1.loc;
Type t;
Type t1 = e1.type.toBasetype();
Type t2 = e2.type.toBasetype();
@@ -1731,7 +1731,7 @@ UnionExp Cat(Type type, Expression e1, Expression e2)
? copyElements(e1) : new Expressions();
elems.push(e2);
- emplaceExp!(ArrayLiteralExp)(&ue, e1.loc, cast(Type)null, elems);
+ emplaceExp!(ArrayLiteralExp)(&ue, loc, cast(Type)null, elems);
e = ue.exp();
if (type.toBasetype().ty == Tsarray)
@@ -1747,7 +1747,7 @@ UnionExp Cat(Type type, Expression e1, Expression e2)
{
auto elems = copyElements(e1, e2);
- emplaceExp!(ArrayLiteralExp)(&ue, e2.loc, cast(Type)null, elems);
+ emplaceExp!(ArrayLiteralExp)(&ue, loc, cast(Type)null, elems);
e = ue.exp();
if (type.toBasetype().ty == Tsarray)
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
new file mode 100644
index 00000000000..f64813d613f
--- /dev/null
+++ b/gcc/d/dmd/cparse.d
@@ -0,0 +1,4052 @@
+/**
+ * Takes a token stream from the lexer, and parses it into an abstract syntax tree.
+ *
+ * Specification: C11
+ *
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
+ * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cparse.d, _cparse.d)
+ * Documentation: https://dlang.org/phobos/dmd_cparse.html
+ * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/cparse.d
+ */
+
+module dmd.cparse;
+
+import core.stdc.stdio;
+import core.stdc.string;
+import dmd.astenums;
+import dmd.globals;
+import dmd.id;
+import dmd.identifier;
+import dmd.lexer;
+import dmd.parse;
+import dmd.errors;
+import dmd.root.filename;
+import dmd.root.outbuffer;
+import dmd.root.rmem;
+import dmd.root.rootobject;
+import dmd.root.string;
+import dmd.tokens;
+
+/***********************************************************
+ */
+final class CParser(AST) : Parser!AST
+{
+ AST.Dsymbols* symbols; // symbols declared in current scope
+
+ bool addFuncName; /// add declaration of __func__ to function symbol table
+
+ extern (D) this(TARGET)(AST.Module _module, const(char)[] input, bool doDocComment,
+ const ref TARGET target)
+ {
+ super(_module, input, doDocComment);
+
+ //printf("CParser.this()\n");
+ mod = _module;
+ linkage = LINK.c;
+ Ccompile = true;
+
+ // Configure sizes for C `long`, `long double`, `wchar_t`
+ this.longsize = target.longsize;
+ this.long_doublesize = target.long_doublesize;
+ this.wchar_tsize = target.wchar_tsize;
+
+ // C `char` is always unsigned in ImportC
+ }
+
+ /********************************************
+ * Parse translation unit.
+ * C11 6.9
+ * translation-unit:
+ * external-declaration
+ * translation-unit external-declaration
+ *
+ * external-declaration:
+ * function-definition
+ * declaration
+ * Returns:
+ * array of Dsymbols that were declared
+ */
+ override AST.Dsymbols* parseModule()
+ {
+ //printf("cparseTranslationUnit()\n");
+ symbols = new AST.Dsymbols();
+ while (1)
+ {
+ if (token.value == TOK.endOfFile)
+ {
+ // wrap the symbols in `extern (C) { symbols }`
+ auto wrap = new AST.Dsymbols();
+ auto ld = new AST.LinkDeclaration(token.loc, LINK.c, symbols);
+ wrap.push(ld);
+
+ return wrap;
+ }
+
+ cparseDeclaration(LVL.global);
+ }
+ }
+
+ /******************************************************************************/
+ /********************************* Statement Parser ***************************/
+ //{
+
+ /**********************
+ * C11 6.8
+ * statement:
+ * labeled-statement
+ * compound-statement
+ * expression-statement
+ * selection-statement
+ * iteration-statement
+ * jump-statement
+ *
+ * Params:
+ * flags = PSxxxx
+ * endPtr = store location of closing brace
+ * pEndloc = if { ... statements ... }, store location of closing brace, otherwise loc of last token of statement
+ * Returns:
+ * parsed statement
+ */
+ AST.Statement cparseStatement(int flags, const(char)** endPtr = null, Loc* pEndloc = null)
+ {
+ AST.Statement s;
+ const loc = token.loc;
+
+ //printf("cparseStatement()\n");
+
+ auto symbolsSave = symbols;
+ if (!(flags & (ParseStatementFlags.scope_ | ParseStatementFlags.curlyScope)))
+ symbols = new AST.Dsymbols();
+
+ switch (token.value)
+ {
+ case TOK.identifier:
+ /* A leading identifier can be a declaration, label, or expression.
+ * A quick check of the next token can disambiguate most cases.
+ */
+ switch (peekNext())
+ {
+ case TOK.colon:
+ {
+ // It's a label
+ auto ident = token.ident;
+ nextToken(); // advance to `:`
+ nextToken(); // advance past `:`
+ if (token.value == TOK.rightCurly)
+ s = null;
+ else if (token.value == TOK.leftCurly)
+ s = cparseStatement(ParseStatementFlags.curly | ParseStatementFlags.scope_);
+ else
+ s = cparseStatement(ParseStatementFlags.semiOk);
+ s = new AST.LabelStatement(loc, ident, s);
+ break;
+ }
+
+ case TOK.dot:
+ case TOK.arrow:
+ case TOK.plusPlus:
+ case TOK.minusMinus:
+ case TOK.leftBracket:
+ case TOK.question:
+ case TOK.assign:
+ case TOK.addAssign:
+ case TOK.minAssign:
+ case TOK.mulAssign:
+ case TOK.divAssign:
+ case TOK.modAssign:
+ case TOK.andAssign:
+ case TOK.orAssign:
+ case TOK.xorAssign:
+ case TOK.leftShiftAssign:
+ case TOK.rightShiftAssign:
+ goto Lexp;
+
+ default:
+ {
+ /* If tokens look like a declaration, assume it is one
+ */
+ auto tk = &token;
+ if (isCDeclaration(tk))
+ goto Ldeclaration;
+ goto Lexp;
+ }
+ }
+ break;
+
+ case TOK.int32Literal:
+ case TOK.uns32Literal:
+ case TOK.int64Literal:
+ case TOK.uns64Literal:
+ case TOK.int128Literal:
+ case TOK.uns128Literal:
+ case TOK.float32Literal:
+ case TOK.float64Literal:
+ case TOK.float80Literal:
+ case TOK.imaginary32Literal:
+ case TOK.imaginary64Literal:
+ case TOK.imaginary80Literal:
+ case TOK.leftParenthesis:
+ case TOK.and:
+ case TOK.mul:
+ case TOK.min:
+ case TOK.add:
+ case TOK.tilde:
+ case TOK.not:
+ case TOK.plusPlus:
+ case TOK.minusMinus:
+ case TOK.sizeof_:
+ Lexp:
+ auto exp = cparseExpression();
+ if (token.value == TOK.identifier && exp.op == TOK.identifier)
+ {
+ error("found `%s` when expecting `;` or `=`, did you mean `%s %s = %s`?", peek(&token).toChars(), exp.toChars(), token.toChars(), peek(peek(&token)).toChars());
+ nextToken();
+ }
+ else
+ check(TOK.semicolon, "statement");
+ s = new AST.ExpStatement(loc, exp);
+ break;
+
+ // type-specifiers
+ case TOK.void_:
+ case TOK.char_:
+ case TOK.int16:
+ case TOK.int32:
+ case TOK.int64:
+ case TOK.float32:
+ case TOK.float64:
+ case TOK.signed:
+ case TOK.unsigned:
+ case TOK._Bool:
+ //case TOK._Imaginary:
+ case TOK._Complex:
+ case TOK.struct_:
+ case TOK.union_:
+ case TOK.enum_:
+
+ // storage-class-specifiers
+ case TOK.typedef_:
+ case TOK.extern_:
+ case TOK.static_:
+ case TOK._Thread_local:
+ case TOK.auto_:
+ case TOK.register:
+
+ // function-specifiers
+ case TOK.inline:
+ case TOK._Noreturn:
+
+ // type-qualifiers
+ case TOK.const_:
+ case TOK.volatile:
+ case TOK.restrict:
+
+ // alignment-specifier
+ case TOK._Alignas:
+
+ // atomic-type-specifier or type_qualifier
+ case TOK._Atomic:
+
+ Ldeclaration:
+ {
+ cparseDeclaration(LVL.local);
+ if (symbols.length > 1)
+ {
+ auto as = new AST.Statements();
+ as.reserve(symbols.length);
+ foreach (d; (*symbols)[])
+ {
+ s = new AST.ExpStatement(loc, d);
+ as.push(s);
+ }
+ s = new AST.CompoundDeclarationStatement(loc, as);
+ symbols.setDim(0);
+ }
+ else if (symbols.length == 1)
+ {
+ auto d = (*symbols)[0];
+ s = new AST.ExpStatement(loc, d);
+ symbols.setDim(0);
+ }
+ else
+ s = new AST.ExpStatement(loc, cast(AST.Expression)null);
+ if (flags & ParseStatementFlags.scope_)
+ s = new AST.ScopeStatement(loc, s, token.loc);
+ break;
+ }
+
+ case TOK._Static_assert: // _Static_assert ( constant-expression, string-literal ) ;
+ s = new AST.StaticAssertStatement(cparseStaticAssert());
+ break;
+
+ case TOK.leftCurly:
+ {
+ /* C11 6.8.2
+ * compound-statement:
+ * { block-item-list (opt) }
+ *
+ * block-item-list:
+ * block-item
+ * block-item-list block-item
+ *
+ * block-item:
+ * declaration
+ * statement
+ */
+ nextToken();
+ auto statements = new AST.Statements();
+ while (token.value != TOK.rightCurly && token.value != TOK.endOfFile)
+ {
+ statements.push(cparseStatement(ParseStatementFlags.semi | ParseStatementFlags.curlyScope));
+ }
+ if (endPtr)
+ *endPtr = token.ptr;
+ endloc = token.loc;
+ if (pEndloc)
+ {
+ *pEndloc = token.loc;
+ pEndloc = null; // don't set it again
+ }
+ s = new AST.CompoundStatement(loc, statements);
+ if (flags & (ParseStatementFlags.scope_ | ParseStatementFlags.curlyScope))
+ s = new AST.ScopeStatement(loc, s, token.loc);
+ check(TOK.rightCurly, "compound statement");
+ break;
+ }
+
+ case TOK.while_:
+ {
+ nextToken();
+ check(TOK.leftParenthesis);
+ auto condition = cparseExpression();
+ check(TOK.rightParenthesis);
+ Loc endloc;
+ auto _body = cparseStatement(ParseStatementFlags.scope_, null, &endloc);
+ s = new AST.WhileStatement(loc, condition, _body, endloc, null);
+ break;
+ }
+
+ case TOK.semicolon:
+ /* C11 6.8.3 null statement
+ */
+ nextToken();
+ s = new AST.ExpStatement(loc, cast(AST.Expression)null);
+ break;
+
+ case TOK.do_:
+ {
+ nextToken();
+ auto _body = cparseStatement(ParseStatementFlags.scope_);
+ check(TOK.while_);
+ check(TOK.leftParenthesis);
+ auto condition = cparseExpression();
+ check(TOK.rightParenthesis);
+ check(TOK.semicolon, "terminating `;` required after do-while statement");
+ s = new AST.DoStatement(loc, _body, condition, token.loc);
+ break;
+ }
+
+ case TOK.for_:
+ {
+ AST.Statement _init;
+ AST.Expression condition;
+ AST.Expression increment;
+
+ nextToken();
+ check(TOK.leftParenthesis);
+ if (token.value == TOK.semicolon)
+ {
+ _init = null;
+ nextToken();
+ }
+ else
+ {
+ _init = cparseStatement(0);
+ }
+ if (token.value == TOK.semicolon)
+ {
+ condition = null;
+ nextToken();
+ }
+ else
+ {
+ condition = cparseExpression();
+ check(TOK.semicolon, "`for` condition");
+ }
+ if (token.value == TOK.rightParenthesis)
+ {
+ increment = null;
+ nextToken();
+ }
+ else
+ {
+ increment = cparseExpression();
+ check(TOK.rightParenthesis);
+ }
+ Loc endloc;
+ auto _body = cparseStatement(ParseStatementFlags.scope_, null, &endloc);
+ s = new AST.ForStatement(loc, _init, condition, increment, _body, endloc);
+ break;
+ }
+
+ case TOK.if_:
+ {
+ nextToken();
+ check(TOK.leftParenthesis);
+ auto condition = cparseExpression();
+ check(TOK.rightParenthesis);
+ auto ifbody = cparseStatement(ParseStatementFlags.scope_);
+ AST.Statement elsebody;
+ if (token.value == TOK.else_)
+ {
+ nextToken();
+ elsebody = cparseStatement(ParseStatementFlags.scope_);
+ }
+ else
+ elsebody = null;
+ if (condition && ifbody)
+ s = new AST.IfStatement(loc, null, condition, ifbody, elsebody, token.loc);
+ else
+ s = null; // don't propagate parsing errors
+ break;
+ }
+
+ case TOK.else_:
+ error("found `else` without a corresponding `if` statement");
+ goto Lerror;
+
+ case TOK.switch_:
+ {
+ nextToken();
+ check(TOK.leftParenthesis);
+ auto condition = cparseExpression();
+ check(TOK.rightParenthesis);
+ auto _body = cparseStatement(ParseStatementFlags.scope_);
+ s = new AST.SwitchStatement(loc, condition, _body, false);
+ break;
+ }
+
+ case TOK.case_:
+ {
+
+ nextToken();
+ auto exp = cparseAssignExp();
+ check(TOK.colon);
+
+ if (flags & ParseStatementFlags.curlyScope)
+ {
+ auto statements = new AST.Statements();
+ while (token.value != TOK.case_ && token.value != TOK.default_ && token.value != TOK.endOfFile && token.value != TOK.rightCurly)
+ {
+ auto cur = cparseStatement(ParseStatementFlags.semi | ParseStatementFlags.curlyScope);
+ statements.push(cur);
+
+ // https://issues.dlang.org/show_bug.cgi?id=21739
+ // Stop at the last break s.t. the following non-case statements are
+ // not merged into the current case. This can happen for
+ // case 1: ... break;
+ // debug { case 2: ... }
+ if (cur && cur.isBreakStatement())
+ break;
+ }
+ s = new AST.CompoundStatement(loc, statements);
+ }
+ else
+ {
+ s = cparseStatement(ParseStatementFlags.semi);
+ }
+ s = new AST.ScopeStatement(loc, s, token.loc);
+ s = new AST.CaseStatement(loc, exp, s);
+ break;
+ }
+
+ case TOK.default_:
+ {
+ nextToken();
+ check(TOK.colon);
+
+ if (flags & ParseStatementFlags.curlyScope)
+ {
+ auto statements = new AST.Statements();
+ while (token.value != TOK.case_ && token.value != TOK.default_ && token.value != TOK.endOfFile && token.value != TOK.rightCurly)
+ {
+ statements.push(cparseStatement(ParseStatementFlags.semi | ParseStatementFlags.curlyScope));
+ }
+ s = new AST.CompoundStatement(loc, statements);
+ }
+ else
+ s = cparseStatement(ParseStatementFlags.semi);
+ s = new AST.ScopeStatement(loc, s, token.loc);
+ s = new AST.DefaultStatement(loc, s);
+ break;
+ }
+
+ case TOK.return_:
+ {
+ /* return ;
+ * return expression ;
+ */
+ nextToken();
+ auto exp = token.value == TOK.semicolon ? null : cparseExpression();
+ check(TOK.semicolon, "`return` statement");
+ s = new AST.ReturnStatement(loc, exp);
+ break;
+ }
+
+ case TOK.break_:
+ nextToken();
+ check(TOK.semicolon, "`break` statement");
+ s = new AST.BreakStatement(loc, null);
+ break;
+
+ case TOK.continue_:
+ nextToken();
+ check(TOK.semicolon, "`continue` statement");
+ s = new AST.ContinueStatement(loc, null);
+ break;
+
+ case TOK.goto_:
+ {
+ Identifier ident;
+ nextToken();
+ if (token.value != TOK.identifier)
+ {
+ error("identifier expected following `goto`");
+ ident = null;
+ }
+ else
+ {
+ ident = token.ident;
+ nextToken();
+ }
+ s = new AST.GotoStatement(loc, ident);
+ check(TOK.semicolon, "`goto` statement");
+ break;
+ }
+
+ case TOK.asm_:
+ s = parseAsm();
+ break;
+
+ default:
+ error("found `%s` instead of statement", token.toChars());
+ goto Lerror;
+
+ Lerror:
+ panic();
+ if (token.value == TOK.semicolon)
+ nextToken();
+ s = null;
+ break;
+ }
+ if (pEndloc)
+ *pEndloc = prevloc;
+ symbols = symbolsSave;
+ return s;
+ }
+
+ //}
+ /*******************************************************************************/
+ /********************************* Expression Parser ***************************/
+ //{
+
+ /**************
+ * C11 6.5.17
+ * expression:
+ * assignment-expression
+ * expression , assignment-expression
+ */
+ AST.Expression cparseExpression()
+ {
+ auto loc = token.loc;
+
+ //printf("cparseExpression() loc = %d\n", loc.linnum);
+ auto e = cparseAssignExp();
+ while (token.value == TOK.comma)
+ {
+ nextToken();
+ auto e2 = cparseAssignExp();
+ e = new AST.CommaExp(loc, e, e2, false);
+ loc = token.loc;
+ }
+ return e;
+ }
+
+
+ /*********************
+ * C11 6.5.1
+ * primary-expression:
+ * identifier
+ * constant
+ * string-literal
+ * ( expression )
+ * generic-selection
+ */
+ AST.Expression cparsePrimaryExp()
+ {
+ AST.Expression e;
+ const loc = token.loc;
+
+ //printf("parsePrimaryExp(): loc = %d\n", loc.linnum);
+ switch (token.value)
+ {
+ case TOK.identifier:
+ if (token.ident is Id.__func__)
+ {
+ addFuncName = true; // implicitly declare __func__
+ }
+ e = new AST.IdentifierExp(loc, token.ident);
+ nextToken();
+ break;
+
+ case TOK.int32Literal:
+ e = new AST.IntegerExp(loc, token.intvalue, AST.Type.tint32);
+ nextToken();
+ break;
+
+ case TOK.uns32Literal:
+ e = new AST.IntegerExp(loc, token.unsvalue, AST.Type.tuns32);
+ nextToken();
+ break;
+
+ case TOK.int64Literal:
+ e = new AST.IntegerExp(loc, token.intvalue, AST.Type.tint64);
+ nextToken();
+ break;
+
+ case TOK.uns64Literal:
+ e = new AST.IntegerExp(loc, token.unsvalue, AST.Type.tuns64);
+ nextToken();
+ break;
+
+ case TOK.float32Literal:
+ e = new AST.RealExp(loc, token.floatvalue, AST.Type.tfloat32);
+ nextToken();
+ break;
+
+ case TOK.float64Literal:
+ e = new AST.RealExp(loc, token.floatvalue, AST.Type.tfloat64);
+ nextToken();
+ break;
+
+ case TOK.float80Literal:
+ e = new AST.RealExp(loc, token.floatvalue, AST.Type.tfloat80);
+ nextToken();
+ break;
+
+ case TOK.imaginary32Literal:
+ e = new AST.RealExp(loc, token.floatvalue, AST.Type.timaginary32);
+ nextToken();
+ break;
+
+ case TOK.imaginary64Literal:
+ e = new AST.RealExp(loc, token.floatvalue, AST.Type.timaginary64);
+ nextToken();
+ break;
+
+ case TOK.imaginary80Literal:
+ e = new AST.RealExp(loc, token.floatvalue, AST.Type.timaginary80);
+ nextToken();
+ break;
+
+ case TOK.string_:
+ {
+ // cat adjacent strings
+ auto s = token.ustring;
+ auto len = token.len;
+ auto postfix = token.postfix;
+ while (1)
+ {
+ nextToken();
+ if (token.value == TOK.string_)
+ {
+ if (token.postfix)
+ {
+ if (token.postfix != postfix)
+ error("mismatched string literal postfixes `'%c'` and `'%c'`", postfix, token.postfix);
+ postfix = token.postfix;
+ }
+
+ const len1 = len;
+ const len2 = token.len;
+ len = len1 + len2;
+ auto s2 = cast(char*)mem.xmalloc_noscan(len * char.sizeof);
+ memcpy(s2, s, len1 * char.sizeof);
+ memcpy(s2 + len1, token.ustring, len2 * char.sizeof);
+ s = s2;
+ }
+ else
+ break;
+ }
+ e = new AST.StringExp(loc, s[0 .. len], len, 1, postfix);
+ break;
+ }
+
+ case TOK.leftParenthesis:
+ nextToken();
+ e = cparseExpression();
+ check(TOK.rightParenthesis);
+ break;
+
+ case TOK._Generic:
+ e = cparseGenericSelection();
+ break;
+
+ default:
+ error("expression expected, not `%s`", token.toChars());
+ // Anything for e, as long as it's not NULL
+ e = new AST.IntegerExp(loc, 0, AST.Type.tint32);
+ nextToken();
+ break;
+ }
+ return e;
+ }
+
+ /*********************************
+ * C11 6.5.2
+ * postfix-expression:
+ * primary-expression
+ * postfix-expression [ expression ]
+ * postfix-expression ( argument-expression-list (opt) )
+ * postfix-expression . identifier
+ * postfix-expression -> identifier
+ * postfix-expression ++
+ * postfix-expression --
+ * ( type-name ) { initializer-list }
+ * ( type-name ) { initializer-list , }
+ *
+ * argument-expression-list:
+ * assignment-expression
+ * argument-expression-list , assignment-expression
+ */
+ private AST.Expression cparsePostfixExp(AST.Expression e)
+ {
+ e = cparsePrimaryExp();
+ return cparsePostfixOperators(e);
+ }
+
+ /********************************
+ * C11 6.5.2
+ * Parse a series of operators for a postfix expression after already parsing
+ * a primary-expression or compound literal expression.
+ * Params:
+ * e = parsed primary or compound literal expression
+ * Returns:
+ * parsed postfix expression
+ */
+ private AST.Expression cparsePostfixOperators(AST.Expression e)
+ {
+ while (1)
+ {
+ const loc = token.loc;
+ switch (token.value)
+ {
+ case TOK.dot:
+ case TOK.arrow:
+ nextToken();
+ if (token.value == TOK.identifier)
+ {
+ Identifier id = token.ident;
+ e = new AST.DotIdExp(loc, e, id);
+ break;
+ }
+ error("identifier expected following `.`, not `%s`", token.toChars());
+ break;
+
+ case TOK.plusPlus:
+ e = new AST.PostExp(TOK.plusPlus, loc, e);
+ break;
+
+ case TOK.minusMinus:
+ e = new AST.PostExp(TOK.minusMinus, loc, e);
+ break;
+
+ case TOK.leftParenthesis:
+ e = new AST.CallExp(loc, e, cparseArguments());
+ continue;
+
+ case TOK.leftBracket:
+ {
+ // array dereferences:
+ // array[index]
+ AST.Expression index;
+ auto arguments = new AST.Expressions();
+
+ inBrackets++;
+ nextToken();
+ index = cparseAssignExp();
+ arguments.push(index);
+ check(TOK.rightBracket);
+ inBrackets--;
+ e = new AST.ArrayExp(loc, e, arguments);
+ continue;
+ }
+ default:
+ return e;
+ }
+ nextToken();
+ }
+ }
+
+ /************************
+ * C11 6.5.3
+ * unary-expression:
+ * postfix-expression
+ * ++ unary-expression
+ * -- unary-expression
+ * unary-operator cast-expression
+ * sizeof unary-expression
+ * sizeof ( type-name )
+ * _Alignof ( type-name )
+ *
+ * unary-operator:
+ * & * + - ~ !
+ */
+ private AST.Expression cparseUnaryExp()
+ {
+ AST.Expression e;
+ const loc = token.loc;
+
+ switch (token.value)
+ {
+ case TOK.plusPlus:
+ nextToken();
+ // Parse `++` as an unary operator so that cast expressions only give
+ // an error for being non-lvalues.
+ e = cparseCastExp();
+ e = new AST.PreExp(TOK.prePlusPlus, loc, e);
+ break;
+
+ case TOK.minusMinus:
+ nextToken();
+ // Parse `--` as an unary operator, same as prefix increment.
+ e = cparseCastExp();
+ e = new AST.PreExp(TOK.preMinusMinus, loc, e);
+ break;
+
+ case TOK.and:
+ nextToken();
+ e = cparseCastExp();
+ e = new AST.AddrExp(loc, e);
+ break;
+
+ case TOK.mul:
+ nextToken();
+ e = cparseCastExp();
+ e = new AST.PtrExp(loc, e);
+ break;
+
+ case TOK.min:
+ nextToken();
+ e = cparseCastExp();
+ e = new AST.NegExp(loc, e);
+ break;
+
+ case TOK.add:
+ nextToken();
+ e = cparseCastExp();
+ e = new AST.UAddExp(loc, e);
+ break;
+
+ case TOK.not:
+ nextToken();
+ e = cparseCastExp();
+ e = new AST.NotExp(loc, e);
+ break;
+
+ case TOK.tilde:
+ nextToken();
+ e = cparseCastExp();
+ e = new AST.ComExp(loc, e);
+ break;
+
+ case TOK.sizeof_:
+ {
+ nextToken();
+ if (token.value == TOK.leftParenthesis)
+ {
+ auto tk = peek(&token);
+ if (isTypeName(tk))
+ {
+ /* Expression may be either be requesting the sizeof a type-name
+ * or a compound literal, which requires checking whether
+ * the next token is `{`
+ */
+ nextToken();
+ auto t = cparseTypeName();
+ check(TOK.rightParenthesis);
+ if (token.value == TOK.leftCurly)
+ {
+ // ( type-name ) { initializer-list }
+ auto ci = cparseInitializer();
+ e = new AST.CompoundLiteralExp(loc, t, ci);
+ e = cparsePostfixOperators(e);
+ }
+ else
+ {
+ // ( type-name )
+ e = new AST.TypeExp(loc, t);
+ }
+ e = new AST.DotIdExp(loc, e, Id.__sizeof);
+ break;
+ }
+ }
+ e = cparseUnaryExp();
+ e = new AST.DotIdExp(loc, e, Id.__sizeof);
+ break;
+ }
+
+ case TOK._Alignof:
+ {
+ nextToken();
+ check(TOK.leftParenthesis);
+ auto t = cparseTypeName();
+ check(TOK.rightParenthesis);
+ e = new AST.TypeExp(loc, t);
+ e = new AST.DotIdExp(loc, e, Id.__xalignof);
+ break;
+ }
+
+ default:
+ e = cparsePostfixExp(e);
+ break;
+ }
+ assert(e);
+ return e;
+ }
+
+ /**************
+ * C11 6.5.4
+ * cast-expression
+ * unary-expression
+ * ( type-name ) cast-expression
+ */
+ private AST.Expression cparseCastExp()
+ {
+ if (token.value == TOK.leftParenthesis)
+ {
+ // If ( type-name )
+ auto pt = &token;
+ if (isCastExpression(pt))
+ {
+ // Expression may be either a cast or a compound literal, which
+ // requires checking whether the next token is `{`
+ const loc = token.loc;
+ nextToken();
+ auto t = cparseTypeName();
+ check(TOK.rightParenthesis);
+
+ if (token.value == TOK.leftCurly)
+ {
+ // C11 6.5.2.5 ( type-name ) { initializer-list }
+ auto ci = cparseInitializer();
+ auto ce = new AST.CompoundLiteralExp(loc, t, ci);
+ return cparsePostfixOperators(ce);
+ }
+ else
+ {
+ // (type-name) cast-expression
+ auto ce = cparseCastExp();
+ return new AST.CastExp(loc, ce, t);
+ }
+ }
+ }
+ return cparseUnaryExp();
+ }
+
+ /**************
+ * C11 6.5.5
+ * multiplicative-expression
+ * cast-expression
+ * multiplicative-expression * cast-expression
+ * multiplicative-expression / cast-expression
+ * multiplicative-expression % cast-expression
+ */
+ private AST.Expression cparseMulExp()
+ {
+ const loc = token.loc;
+ auto e = cparseCastExp();
+
+ while (1)
+ {
+ switch (token.value)
+ {
+ case TOK.mul:
+ nextToken();
+ auto e2 = cparseCastExp();
+ e = new AST.MulExp(loc, e, e2);
+ continue;
+
+ case TOK.div:
+ nextToken();
+ auto e2 = cparseCastExp();
+ e = new AST.DivExp(loc, e, e2);
+ continue;
+
+ case TOK.mod:
+ nextToken();
+ auto e2 = cparseCastExp();
+ e = new AST.ModExp(loc, e, e2);
+ continue;
+
+ default:
+ break;
+ }
+ break;
+ }
+ return e;
+ }
+
+ /**************
+ * C11 6.5.6
+ * additive-expression
+ * multiplicative-expression
+ * additive-expression + multiplicative-expression
+ * additive-expression - multiplicative-expression
+ */
+ private AST.Expression cparseAddExp()
+ {
+ const loc = token.loc;
+ auto e = cparseMulExp();
+
+ while (1)
+ {
+ switch (token.value)
+ {
+ case TOK.add:
+ nextToken();
+ auto e2 = cparseMulExp();
+ e = new AST.AddExp(loc, e, e2);
+ continue;
+
+ case TOK.min:
+ nextToken();
+ auto e2 = cparseMulExp();
+ e = new AST.MinExp(loc, e, e2);
+ continue;
+
+ default:
+ break;
+ }
+ break;
+ }
+ return e;
+ }
+
+ /**************
+ * C11 6.5.7
+ * shift-expression
+ * additive-expression
+ * shift-expression << additive-expression
+ * shift-expression >> additive-expression
+ */
+ private AST.Expression cparseShiftExp()
+ {
+ const loc = token.loc;
+ auto e = cparseAddExp();
+
+ while (1)
+ {
+ switch (token.value)
+ {
+ case TOK.leftShift:
+ nextToken();
+ auto e2 = cparseAddExp();
+ e = new AST.ShlExp(loc, e, e2);
+ continue;
+
+ case TOK.rightShift:
+ nextToken();
+ auto e2 = cparseAddExp();
+ e = new AST.ShrExp(loc, e, e2);
+ continue;
+
+ default:
+ break;
+ }
+ break;
+ }
+ return e;
+ }
+
+ /**************
+ * C11 6.5.8
+ * relational-expression
+ * shift-expression
+ * relational-expression < shift-expression
+ * relational-expression > shift-expression
+ * relational-expression <= shift-expression
+ * relational-expression >= shift-expression
+ */
+ private AST.Expression cparseRelationalExp()
+ {
+ const loc = token.loc;
+
+ auto e = cparseShiftExp();
+ TOK op = token.value;
+
+ switch (op)
+ {
+ case TOK.lessThan:
+ case TOK.lessOrEqual:
+ case TOK.greaterThan:
+ case TOK.greaterOrEqual:
+ nextToken();
+ auto e2 = cparseShiftExp();
+ e = new AST.CmpExp(op, loc, e, e2);
+ break;
+
+ default:
+ break;
+ }
+ return e;
+ }
+
+ /**************
+ * C11 6.5.9
+ * equality-expression
+ * relational-expression
+ * equality-expression == relational-expression
+ * equality-expression != relational-expression
+ */
+ private AST.Expression cparseEqualityExp()
+ {
+ const loc = token.loc;
+
+ auto e = cparseRelationalExp();
+ const TOK op = token.value;
+
+ switch (op)
+ {
+ case TOK.equal:
+ case TOK.notEqual:
+ nextToken();
+ auto e2 = cparseRelationalExp();
+ e = new AST.EqualExp(op, loc, e, e2);
+ break;
+
+ default:
+ break;
+ }
+ return e;
+ }
+
+ /**************
+ * C11 6.5.10
+ * AND-expression
+ * equality-expression
+ * AND-expression & equality-expression
+ */
+ private AST.Expression cparseAndExp()
+ {
+ Loc loc = token.loc;
+ auto e = cparseEqualityExp();
+ while (token.value == TOK.and)
+ {
+ nextToken();
+ auto e2 = cparseEqualityExp();
+ e = new AST.AndExp(loc, e, e2);
+ loc = token.loc;
+ }
+ return e;
+ }
+
+ /**************
+ * C11 6.5.11
+ * exclusive-OR-expression
+ * AND-expression
+ * exclusive-OR-expression ^ AND-expression
+ */
+ private AST.Expression cparseXorExp()
+ {
+ const loc = token.loc;
+
+ auto e = cparseAndExp();
+ while (token.value == TOK.xor)
+ {
+ nextToken();
+ auto e2 = cparseAndExp();
+ e = new AST.XorExp(loc, e, e2);
+ }
+ return e;
+ }
+
+ /**************
+ * C11 6.5.12
+ * inclusive-OR-expression
+ * exclusive-OR-expression
+ * inclusive-OR-expression | exclusive-OR-expression
+ */
+ private AST.Expression cparseOrExp()
+ {
+ const loc = token.loc;
+
+ auto e = cparseXorExp();
+ while (token.value == TOK.or)
+ {
+ nextToken();
+ auto e2 = cparseXorExp();
+ e = new AST.OrExp(loc, e, e2);
+ }
+ return e;
+ }
+
+ /**************
+ * C11 6.5.13
+ * logical-AND-expression
+ * inclusive-OR-expression
+ * logical-AND-expression && inclusive-OR-expression
+ */
+ private AST.Expression cparseAndAndExp()
+ {
+ const loc = token.loc;
+
+ auto e = cparseOrExp();
+ while (token.value == TOK.andAnd)
+ {
+ nextToken();
+ auto e2 = cparseOrExp();
+ e = new AST.LogicalExp(loc, TOK.andAnd, e, e2);
+ }
+ return e;
+ }
+
+ /**************
+ * C11 6.5.14
+ * logical-OR-expression
+ * logical-AND-expression
+ * logical-OR-expression || logical-AND-expression
+ */
+ private AST.Expression cparseOrOrExp()
+ {
+ const loc = token.loc;
+
+ auto e = cparseAndAndExp();
+ while (token.value == TOK.orOr)
+ {
+ nextToken();
+ auto e2 = cparseAndAndExp();
+ e = new AST.LogicalExp(loc, TOK.orOr, e, e2);
+ }
+ return e;
+ }
+
+ /**************
+ * C11 6.5.15
+ * conditional-expression:
+ * logical-OR-expression
+ * logical-OR-expression ? expression : conditional-expression
+ */
+ private AST.Expression cparseCondExp()
+ {
+ const loc = token.loc;
+
+ auto e = cparseOrOrExp();
+ if (token.value == TOK.question)
+ {
+ nextToken();
+ auto e1 = cparseExpression();
+ check(TOK.colon);
+ auto e2 = cparseCondExp();
+ e = new AST.CondExp(loc, e, e1, e2);
+ }
+ return e;
+ }
+
+ /**************
+ * C11 6.5.16
+ * assignment-expression:
+ * conditional-expression
+ * unary-expression assignment-operator assignment-expression
+ *
+ * assignment-operator:
+ * = *= /= %= += -= <<= >>= &= ^= |=
+ */
+ AST.Expression cparseAssignExp()
+ {
+ AST.Expression e;
+ e = cparseCondExp(); // constrain it to being unary-expression in semantic pass
+ if (e is null)
+ return e;
+
+ const loc = token.loc;
+ switch (token.value)
+ {
+ case TOK.assign:
+ nextToken();
+ auto e2 = cparseAssignExp();
+ e = new AST.AssignExp(loc, e, e2);
+ break;
+
+ case TOK.addAssign:
+ nextToken();
+ auto e2 = cparseAssignExp();
+ e = new AST.AddAssignExp(loc, e, e2);
+ break;
+
+ case TOK.minAssign:
+ nextToken();
+ auto e2 = cparseAssignExp();
+ e = new AST.MinAssignExp(loc, e, e2);
+ break;
+
+ case TOK.mulAssign:
+ nextToken();
+ auto e2 = cparseAssignExp();
+ e = new AST.MulAssignExp(loc, e, e2);
+ break;
+
+ case TOK.divAssign:
+ nextToken();
+ auto e2 = cparseAssignExp();
+ e = new AST.DivAssignExp(loc, e, e2);
+ break;
+
+ case TOK.modAssign:
+ nextToken();
+ auto e2 = cparseAssignExp();
+ e = new AST.ModAssignExp(loc, e, e2);
+ break;
+
+ case TOK.andAssign:
+ nextToken();
+ auto e2 = cparseAssignExp();
+ e = new AST.AndAssignExp(loc, e, e2);
+ break;
+
+ case TOK.orAssign:
+ nextToken();
+ auto e2 = cparseAssignExp();
+ e = new AST.OrAssignExp(loc, e, e2);
+ break;
+
+ case TOK.xorAssign:
+ nextToken();
+ auto e2 = cparseAssignExp();
+ e = new AST.XorAssignExp(loc, e, e2);
+ break;
+
+ case TOK.leftShiftAssign:
+ nextToken();
+ auto e2 = cparseAssignExp();
+ e = new AST.ShlAssignExp(loc, e, e2);
+ break;
+
+ case TOK.rightShiftAssign:
+ nextToken();
+ auto e2 = cparseAssignExp();
+ e = new AST.ShrAssignExp(loc, e, e2);
+ break;
+
+ default:
+ break;
+ }
+
+ return e;
+ }
+
+ /***********************
+ * C11 6.5.1.1
+ * _Generic ( assignment-expression, generic-assoc-list )
+ *
+ * generic-assoc-list:
+ * generic-association
+ * generic-assoc-list generic-association
+ *
+ * generic-association:
+ * type-name : assignment-expression
+ * default : assignment-expression
+ */
+ private AST.Expression cparseGenericSelection()
+ {
+ const loc = token.loc;
+ nextToken();
+ check(TOK.leftParenthesis);
+ cparseAssignExp();
+ check(TOK.comma);
+ bool sawDefault;
+ while (1)
+ {
+ if (token.value == TOK.default_)
+ {
+ if (sawDefault)
+ error("only one `default` allowed in generic-assoc-list");
+ sawDefault = true;
+ }
+ else
+ cparseTypeName();
+
+ check(TOK.colon);
+ cparseAssignExp();
+ if (token.value == TOK.rightParenthesis || token.value == TOK.endOfFile)
+ break;
+ }
+ check(TOK.rightParenthesis);
+ error("`_Generic` not supported"); // TODO
+ return new AST.IntegerExp(loc, 0, AST.Type.tint32);
+ }
+
+ /***********************
+ * C11 6.6 Constant expressions
+ * constant-expression:
+ * conditional-expression
+ */
+ private AST.Expression cparseConstantExp()
+ {
+ return cparseAssignExp();
+ }
+
+ //}
+ /********************************************************************************/
+ /********************************* Declaration Parser ***************************/
+ //{
+
+ /*************************************
+ * C11 6.7
+ * declaration:
+ * declaration-specifiers init-declarator-list (opt) ;
+ * static_assert-declaration
+ *
+ * init-declarator-list:
+ * init-declarator
+ * init-declarator-list , init-declarator
+ *
+ * init-declarator:
+ * declarator
+ * declarator = initializer
+ *
+ * Params:
+ * level = declaration context
+ */
+ void cparseDeclaration(LVL level)
+ {
+ //printf("cparseDeclaration(level = %d)\n", level);
+ if (token.value == TOK._Static_assert)
+ {
+ auto s = cparseStaticAssert();
+ symbols.push(s);
+ return;
+ }
+
+ auto symbolsSave = symbols;
+ Specifier specifier;
+ auto tspec = cparseDeclarationSpecifiers(level, specifier);
+
+ /* If a declarator does not follow, it is unnamed
+ */
+ if (token.value == TOK.semicolon && tspec)
+ {
+ nextToken();
+ auto tt = tspec.isTypeTag();
+ if (!tt || !tt.id)
+ return; // legal but meaningless empty declaration, ignore it
+
+ /* `struct tag;` and `struct tag { ... };`
+ * always result in a declaration in the current scope
+ */
+ // TODO: merge in specifier
+ auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) :
+ (tt.tok == TOK.union_) ? new AST.UnionDeclaration(tt.loc, tt.id) :
+ new AST.EnumDeclaration(tt.loc, tt.id, AST.Type.tint32);
+ stag.members = tt.members;
+ if (!symbols)
+ symbols = new AST.Dsymbols();
+ symbols.push(stag);
+
+ if (tt.tok == TOK.enum_)
+ {
+ if (!tt.members)
+ error(tt.loc, "`enum %s` has no members", stag.toChars());
+ }
+ return;
+ }
+
+ if (tspec && specifier.mod & MOD.xconst)
+ {
+ tspec = toConst(tspec);
+ specifier.mod = MOD.xnone; // 'used' it
+ }
+
+ bool first = true;
+ while (1)
+ {
+ Identifier id;
+ AST.Expression asmname;
+ auto dt = cparseDeclarator(DTR.xdirect, tspec, id);
+ if (!dt)
+ {
+ panic();
+ nextToken();
+ break; // error recovery
+ }
+
+ /* GNU Extensions
+ * init-declarator:
+ * declarator simple-asm-expr (opt) gnu-attributes (opt)
+ * declarator simple-asm-expr (opt) gnu-attributes (opt) = initializer
+ */
+ switch (token.value)
+ {
+ case TOK.assign:
+ case TOK.comma:
+ case TOK.semicolon:
+ case TOK.asm_:
+ case TOK.__attribute__:
+ /* This is a data definition, there cannot now be a
+ * function definition.
+ */
+ first = false;
+ if (token.value == TOK.asm_)
+ asmname = cparseSimpleAsmExpr();
+ if (token.value == TOK.__attribute__)
+ {
+ cparseGnuAttributes();
+ if (token.value == TOK.leftCurly)
+ {
+ error("attributes should be specified before the function definition");
+ auto t = &token;
+ if (skipBraces(t))
+ {
+ token = *t;
+ return;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* C11 6.9.1 Function Definitions
+ * function-definition:
+ * declaration-specifiers declarator declaration-list (opt) compound-statement
+ *
+ * declaration-list:
+ * declaration
+ * declaration-list declaration
+ */
+ auto t = &token;
+ if (first && // first declarator
+ id &&
+ dt.isTypeFunction() && // function type not inherited from a typedef
+ isDeclarationList(t) && // optional declaration-list
+ level == LVL.global && // function definitions only at global scope
+ t.value == TOK.leftCurly) // start of compound-statement
+ {
+ auto s = cparseFunctionDefinition(id, dt.isTypeFunction(), specifier.scw);
+ symbols = symbolsSave;
+ symbols.push(s);
+ return;
+ }
+ AST.Dsymbol s = null;
+ symbols = symbolsSave;
+ if (!symbols)
+ symbols = new AST.Dsymbols; // lazilly create it
+
+ if (level != LVL.global && !tspec && !specifier.scw && !specifier.mod)
+ error("declaration-specifier-seq required");
+ else if (specifier.scw == SCW.xtypedef)
+ {
+ if (token.value == TOK.assign)
+ error("no initializer for typedef declaration");
+
+ bool isalias = true;
+ if (auto ts = dt.isTypeStruct())
+ {
+ if (ts.sym.isAnonymous())
+ {
+ // This is a typedef for an anonymous struct-or-union.
+ // Directly set the ident for the struct-or-union.
+ ts.sym.ident = id;
+ isalias = false;
+ }
+ }
+ else if (auto te = dt.isTypeEnum())
+ {
+ if (te.sym.isAnonymous())
+ {
+ // This is a typedef for an anonymous enum.
+ te.sym.ident = id;
+ isalias = false;
+ }
+ }
+ if (isalias)
+ s = new AST.AliasDeclaration(token.loc, id, dt);
+ }
+ else if (id)
+ {
+ if (level == LVL.prototype)
+ break; // declared later as Parameter, not VarDeclaration
+
+ if (dt.ty == AST.Tvoid)
+ error("`void` has no value");
+
+ AST.Initializer initializer;
+ bool hasInitializer;
+ if (token.value == TOK.assign)
+ {
+ nextToken();
+ hasInitializer = true;
+ initializer = cparseInitializer();
+ }
+ // declare the symbol
+ assert(id);
+ if (dt.isTypeFunction())
+ {
+ if (hasInitializer)
+ error("no initializer for function declaration");
+ if (specifier.scw & SCW.x_Thread_local)
+ error("functions cannot be `_Thread_local`"); // C11 6.7.1-4
+ s = new AST.FuncDeclaration(token.loc, Loc.initial, id, specifiersToSTC(level, specifier), dt);
+ }
+ else
+ {
+ // Give non-extern variables an implicit void initializer
+ // if one has not been explicitly set.
+ if (!hasInitializer && !(specifier.scw & SCW.xextern))
+ initializer = new AST.VoidInitializer(token.loc);
+ s = new AST.VarDeclaration(token.loc, dt, id, initializer, specifiersToSTC(level, specifier));
+ }
+ }
+ if (s !is null)
+ {
+ 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 maps directly to `pragma(mangle, "name")`
+ if (asmname)
+ {
+ auto args = new AST.Expressions(1);
+ (*args)[0] = asmname;
+ auto decls = new AST.Dsymbols(1);
+ (*decls)[0] = s;
+ s = new AST.PragmaDeclaration(asmname.loc, Id.mangle, args, decls);
+ }
+ symbols.push(s);
+ }
+ first = false;
+
+ switch (token.value)
+ {
+ case TOK.identifier:
+ error("missing comma");
+ goto default;
+
+ case TOK.semicolon:
+ nextToken();
+ return;
+
+ case TOK.comma:
+ nextToken();
+ break;
+
+ default:
+ error("`=`, `;` or `,` expected");
+ while (token.value != TOK.semicolon && token.value != TOK.endOfFile)
+ nextToken();
+ nextToken();
+ return;
+ }
+ }
+ }
+
+ /***************************************
+ * C11 Function Definitions
+ * function-definition
+ * declaration-specifiers declarator declaration-list (opt) compound-statement
+ *
+ * declaration-list:
+ * declaration
+ * declaration-list declaration
+ *
+ * It's already been parsed up to the declaration-list (opt).
+ * Pick it up from there.
+ * Params:
+ * id = function identifier
+ * ft = function type
+ * scw = function storage classes
+ * Returns:
+ * Dsymbol for the function
+ */
+ AST.Dsymbol cparseFunctionDefinition(Identifier id, AST.TypeFunction ft, SCW scw)
+ {
+ if (token.value != TOK.leftCurly) // if not start of a compound-statement
+ {
+ // Do declaration-list
+ do
+ {
+ cparseDeclaration(LVL.parameter);
+ } while (token.value != TOK.leftCurly);
+
+ /* Since there were declarations, the parameter-list must have been
+ * an identifier-list.
+ */
+ auto pl = ft.parameterList;
+ pl.hasIdentifierList = true; // semantic needs to know to adjust parameter types
+ if (pl.varargs != AST.VarArg.none)
+ error("function identifier-list cannot end with `...`");
+ auto plLength = pl.length;
+ if (symbols.length != plLength)
+ error("%d identifiers does not match %d declarations", cast(int)plLength, cast(int)symbols.length);
+
+ /* Transfer the types and storage classes from symbols[] to pl[]
+ */
+ foreach (i; 0 .. plLength)
+ {
+ auto p = pl[i]; // yes, quadratic
+
+ // Convert typedef-identifier to identifier
+ if (p.type)
+ {
+ if (auto t = p.type.isTypeIdentifier())
+ {
+ p.ident = t.ident;
+ p.type = null;
+ }
+ }
+
+ if (p.type || !(p.storageClass & STC.parameter))
+ error("storage class and type are not allowed in identifier-list");
+ foreach (s; (*symbols)[]) // yes, quadratic
+ {
+ auto d = s.isDeclaration();
+ if (p.ident == d.ident && d.type)
+ {
+ p.type = d.type;
+ p.storageClass = d.storage_class;
+ d.type = null; // don't reuse
+ break;
+ }
+ }
+ if (!p.type)
+ error("no declaration for identifier `%s`", p.ident.toChars());
+ }
+ }
+
+ addFuncName = false; // gets set to true if somebody references __func__ in this function
+ const locFunc = token.loc;
+
+ auto body = cparseStatement(ParseStatementFlags.curly); // don't start a new scope; continue with parameter scope
+ Specifier specifier;
+ specifier.scw = scw;
+ auto fd = new AST.FuncDeclaration(token.loc, Loc.initial, id, specifiersToSTC(LVL.global, specifier), ft);
+
+ if (addFuncName)
+ {
+ auto s = createFuncName(locFunc, id);
+ body = new AST.CompoundStatement(locFunc, s, body);
+ }
+ fd.fbody = body;
+
+ // TODO add `symbols` to the function's local symbol table `sc2` in FuncDeclaration::semantic3()
+
+ return fd;
+ }
+
+ /***************************************
+ * C11 Initialization
+ * initializer:
+ * assignment-expression
+ * { initializer-list }
+ * { initializer-list , }
+ *
+ * initializer-list:
+ * designation (opt) initializer
+ * initializer-list , designation (opt) initializer
+ *
+ * designation:
+ * designator-list =
+ *
+ * designator-list:
+ * designator
+ * designator-list designator
+ *
+ * designator:
+ * [ constant-expression ]
+ * . identifier
+ * Returns:
+ * initializer
+ */
+ AST.Initializer cparseInitializer()
+ {
+ if (token.value != TOK.leftCurly)
+ {
+ auto ae = cparseAssignExp(); // assignment-expression
+ return new AST.ExpInitializer(token.loc, ae);
+ }
+ nextToken();
+ const loc = token.loc;
+
+ /* Collect one or more `designation (opt) initializer`
+ * into ci.initializerList, but lazily create ci
+ */
+ AST.CInitializer ci;
+ while (1)
+ {
+ /* There can be 0 or more designators preceding an initializer.
+ * Collect them in desigInit
+ */
+ AST.DesigInit desigInit;
+ while (1)
+ {
+ if (token.value == TOK.leftBracket) // [ constant-expression ]
+ {
+ nextToken();
+ auto e = cparseConstantExp();
+ check(TOK.rightBracket);
+ if (!desigInit.designatorList)
+ desigInit.designatorList = new AST.Designators;
+ desigInit.designatorList.push(AST.Designator(e));
+ }
+ else if (token.value == TOK.dot) // . identifier
+ {
+ nextToken();
+ if (token.value != TOK.identifier)
+ {
+ error("identifier expected following `.` designator");
+ break;
+ }
+ if (!desigInit.designatorList)
+ desigInit.designatorList = new AST.Designators;
+ desigInit.designatorList.push(AST.Designator(token.ident));
+ nextToken();
+ }
+ else
+ {
+ if (desigInit.designatorList)
+ check(TOK.assign);
+ break;
+ }
+ }
+
+ desigInit.initializer = cparseInitializer();
+ if (!ci)
+ ci = new AST.CInitializer(loc);
+ ci.initializerList.push(desigInit);
+ if (token.value == TOK.comma)
+ {
+ nextToken();
+ if (token.value != TOK.rightCurly)
+ continue;
+ }
+ break;
+ }
+ check(TOK.rightCurly);
+ //printf("ci: %s\n", ci.toChars());
+ return ci;
+ }
+
+ /*************************************
+ * C11 6.7
+ * declaration-specifier:
+ * storage-class-specifier declaration-specifiers (opt)
+ * type-specifier declaration-specifiers (opt)
+ * type-qualifier declaration-specifiers (opt)
+ * function-specifier declaration-specifiers (opt)
+ * alignment-specifier declaration-specifiers (opt)
+ * Params:
+ * level = declaration context
+ * specifier = specifiers in and out
+ * Returns:
+ * resulting type, null if not specified
+ */
+ private AST.Type cparseDeclarationSpecifiers(LVL level, ref Specifier specifier)
+ {
+ enum TKW : uint
+ {
+ xnone = 0,
+ xchar = 1,
+ xsigned = 2,
+ xunsigned = 4,
+ xshort = 8,
+ xint = 0x10,
+ xlong = 0x20,
+ xllong = 0x40,
+ xfloat = 0x80,
+ xdouble = 0x100,
+ xldouble = 0x200,
+ xtag = 0x400,
+ xident = 0x800,
+ xvoid = 0x1000,
+ xbool = 0x4000,
+ ximaginary = 0x8000,
+ xcomplex = 0x10000,
+ x_Atomic = 0x20000,
+ }
+
+ AST.Type t;
+ Loc loc;
+ //printf("parseDeclarationSpecifiers()\n");
+
+ TKW tkw;
+ SCW scw = specifier.scw & SCW.xtypedef;
+ MOD mod;
+ Identifier id;
+ Identifier previd;
+
+ Lwhile:
+ while (1)
+ {
+ //printf("token %s\n", token.toChars());
+ TKW tkwx;
+ SCW scwx;
+ MOD modx;
+ switch (token.value)
+ {
+ // Storage class specifiers
+ case TOK.static_: scwx = SCW.xstatic; break;
+ case TOK.extern_: scwx = SCW.xextern; break;
+ case TOK.auto_: scwx = SCW.xauto; break;
+ case TOK.register: scwx = SCW.xregister; break;
+ case TOK.typedef_: scwx = SCW.xtypedef; break;
+ case TOK.inline: scwx = SCW.xinline; break;
+ case TOK._Noreturn: scwx = SCW.x_Noreturn; break;
+ case TOK._Thread_local: scwx = SCW.x_Thread_local; break;
+
+ // Type qualifiers
+ case TOK.const_: modx = MOD.xconst; break;
+ case TOK.volatile: modx = MOD.xvolatile; break;
+ case TOK.restrict: modx = MOD.xrestrict; break;
+
+ // Type specifiers
+ case TOK.char_: tkwx = TKW.xchar; break;
+ case TOK.signed: tkwx = TKW.xsigned; break;
+ case TOK.unsigned: tkwx = TKW.xunsigned; break;
+ case TOK.int16: tkwx = TKW.xshort; break;
+ case TOK.int32: tkwx = TKW.xint; break;
+ case TOK.int64: tkwx = TKW.xlong; break;
+ case TOK.float32: tkwx = TKW.xfloat; break;
+ case TOK.float64: tkwx = TKW.xdouble; break;
+ case TOK.void_: tkwx = TKW.xvoid; break;
+ case TOK._Bool: tkwx = TKW.xbool; break;
+ case TOK._Imaginary: tkwx = TKW.ximaginary; break;
+ case TOK._Complex: tkwx = TKW.xcomplex; break;
+
+ case TOK.identifier:
+ tkwx = TKW.xident;
+ id = token.ident;
+ break;
+
+ case TOK.struct_:
+ case TOK.union_:
+ {
+ const structOrUnion = token.value;
+ const sloc = token.loc;
+ nextToken();
+
+ /* GNU Extensions
+ * struct-or-union-specifier:
+ * struct-or-union gnu-attributes (opt) identifier (opt) { struct-declaration-list } gnu-attributes (opt)
+ * struct-or-union gnu-attribute (opt) identifier
+ */
+ if (token.value == TOK.__attribute__)
+ cparseGnuAttributes();
+
+ t = cparseStruct(sloc, structOrUnion, symbols);
+ tkwx = TKW.xtag;
+ break;
+ }
+
+ case TOK.enum_:
+ t = cparseEnum(symbols);
+ tkwx = TKW.xtag;
+ break;
+
+ case TOK._Atomic:
+ {
+ // C11 6.7.2.4
+ // type-specifier if followed by `( type-name )`
+ auto tk = peek(&token);
+ if (tk.value == TOK.leftParenthesis)
+ {
+ tk = peek(tk);
+ if (isTypeName(tk) && tk.value == TOK.rightParenthesis)
+ {
+ nextToken();
+ t = cparseTypeName();
+ // TODO - implement the "atomic" part of t
+ tkwx = TKW.x_Atomic;
+ break;
+ }
+ }
+ // C11 6.7.3 type-qualifier if not
+ modx = MOD.x_Atomic;
+ break;
+ }
+
+ case TOK._Alignas:
+ {
+ /* C11 6.7.5
+ * _Alignas ( type-name )
+ * _Alignas ( constant-expression )
+ */
+ nextToken();
+ check(TOK.leftParenthesis);
+ auto tk = &token;
+ if (isTypeName(tk))
+ {
+ cparseTypeName();
+ }
+ else
+ {
+ cparseConstantExp();
+ }
+ check(TOK.rightParenthesis);
+ error("`_Alignas` not supported"); // TODO
+ break;
+ }
+
+ case TOK.__attribute__:
+ {
+ /* GNU Extensions
+ * declaration-specifiers:
+ * gnu-attributes declaration-specifiers (opt)
+ */
+ cparseGnuAttributes();
+ break;
+ }
+
+ default:
+ break Lwhile;
+ }
+
+ if (tkwx)
+ {
+ if (tkw & TKW.xlong && tkwx & TKW.xlong)
+ {
+ tkw &= ~TKW.xlong;
+ tkwx = TKW.xllong;
+ }
+ if (tkw && tkwx & TKW.xident)
+ {
+ // 2nd identifier can't be a typedef
+ break Lwhile; // leave parser on the identifier for the following declarator
+ }
+ else if (tkwx & TKW.xident)
+ {
+ // 1st identifier, save it for TypeIdentifier
+ previd = id;
+ }
+ if (tkw & TKW.xident && tkwx || // typedef-name followed by type-specifier
+ tkw & tkwx) // duplicate type-specifiers
+ {
+ error("illegal combination of type specifiers");
+ tkwx = TKW.init;
+ }
+ tkw |= tkwx;
+ if (!(tkwx & TKW.xtag)) // if parser already advanced
+ nextToken();
+ continue;
+ }
+
+ if (modx)
+ {
+ mod |= modx;
+ nextToken();
+ continue;
+ }
+
+ if (scwx)
+ {
+ if (scw & scwx)
+ error("duplicate storage class");
+ scw |= scwx;
+ const scw2 = scw & (SCW.xstatic | SCW.xextern | SCW.xauto | SCW.xregister | SCW.xtypedef);
+ if (scw2 & (scw2 - 1) ||
+ scw & (SCW.xauto | SCW.xregister) && scw & (SCW.xinline | SCW.x_Noreturn))
+ {
+ error("conflicting storage class");
+ scw &= ~scwx;
+ }
+ if (level & (LVL.parameter | LVL.prototype) &&
+ scw & ~SCW.xregister)
+ {
+ error("only `register` storage class allowed for function parameters");
+ scw &= ~scwx;
+ }
+ if (level == LVL.global &&
+ scw & (SCW.xauto | SCW.xregister))
+ {
+ error("`auto` and `register` storage class not allowed for global");
+ scw &= ~scwx;
+ }
+ nextToken();
+ continue;
+ }
+ }
+
+ specifier.scw = scw;
+ specifier.mod = mod;
+
+ // Convert TKW bits to type t
+ switch (tkw)
+ {
+ case TKW.xnone: t = null; break;
+
+ case TKW.xchar: t = AST.Type.tchar; break;
+ case TKW.xsigned | TKW.xchar: t = AST.Type.tint8; break;
+ case TKW.xunsigned | TKW.xchar: t = AST.Type.tuns8; break;
+
+ case TKW.xshort:
+ case TKW.xsigned | TKW.xshort:
+ case TKW.xsigned | TKW.xshort | TKW.xint:
+ case TKW.xshort | TKW.xint: t = AST.Type.tint16; break;
+
+ case TKW.xunsigned | TKW.xshort | TKW.xint:
+ case TKW.xunsigned | TKW.xshort: t = AST.Type.tuns16; break;
+
+ case TKW.xint:
+ case TKW.xsigned:
+ case TKW.xsigned | TKW.xint: t = AST.Type.tint32; break;
+
+ case TKW.xunsigned:
+ case TKW.xunsigned | TKW.xint: t = AST.Type.tuns32; break;
+
+ case TKW.xlong:
+ case TKW.xsigned | TKW.xlong:
+ case TKW.xsigned | TKW.xlong | TKW.xint:
+ case TKW.xlong | TKW.xint: t = longsize == 4 ? AST.Type.tint32 : AST.Type.tint64; break;
+
+ case TKW.xunsigned | TKW.xlong | TKW.xint:
+ case TKW.xunsigned | TKW.xlong: t = longsize == 4 ? AST.Type.tuns32 : AST.Type.tuns64; break;
+
+ case TKW.xllong:
+ case TKW.xsigned | TKW.xllong:
+ case TKW.xsigned | TKW.xllong | TKW.xint:
+ case TKW.xllong | TKW.xint: t = AST.Type.tint64; break;
+
+ case TKW.xunsigned | TKW.xllong | TKW.xint:
+ case TKW.xunsigned | TKW.xllong: t = AST.Type.tuns64; break;
+
+ case TKW.xvoid: t = AST.Type.tvoid; break;
+ case TKW.xbool: t = AST.Type.tbool; break;
+
+ case TKW.xfloat: t = AST.Type.tfloat32; break;
+ case TKW.xdouble: t = AST.Type.tfloat64; break;
+ case TKW.xlong | TKW.xdouble: t = realType(RTFlags.realfloat); break;
+
+ case TKW.ximaginary | TKW.xfloat: t = AST.Type.timaginary32; break;
+ case TKW.ximaginary | TKW.xdouble: t = AST.Type.timaginary64; break;
+ case TKW.ximaginary | TKW.xlong | TKW.xdouble: t = realType(RTFlags.imaginary); break;
+
+ case TKW.xcomplex | TKW.xfloat: t = AST.Type.tcomplex32; break;
+ case TKW.xcomplex | TKW.xdouble: t = AST.Type.tcomplex64; break;
+ case TKW.xcomplex | TKW.xlong | TKW.xdouble: t = realType(RTFlags.complex); break;
+
+ case TKW.xident: t = new AST.TypeIdentifier(loc, previd);
+ break;
+
+ case TKW.xtag:
+ break; // t is already set
+
+ default:
+ error("illegal type combination");
+ t = AST.Type.terror;
+ break;
+ }
+
+ return t;
+ }
+
+ /********************************
+ * C11 6.7.6
+ * Parse a declarator (including function definitions).
+ * declarator:
+ * pointer (opt) direct-declarator
+ *
+ * direct-declarator :
+ * identifier
+ * ( declarator )
+ * direct-declarator [ type-qualifier-list (opt) assignment-expression (opt) ]
+ * direct-declarator [ static type-qualifier-list (opt) assignment-expression ]
+ * direct-declarator [ type-qualifier-list static assignment-expression (opt) ]
+ * direct-declarator [ type-qualifier-list (opt) * ]
+ * direct-declarator ( parameter-type-list )
+ * direct-declarator ( identifier-list (opt) )
+ *
+ * pointer :
+ * * type-qualifier-list (opt)
+ * * type-qualifier-list (opt) pointer
+ *
+ * type-qualifier-list :
+ * type-qualifier
+ * type-qualifier-list type-qualifier
+ *
+ * parameter-type-list :
+ * parameter-list
+ * parameter-list , ...
+ *
+ * parameter-list :
+ * parameter-declaration
+ * parameter-list , parameter-declaration
+ *
+ * parameter-declaration :
+ * declaration-specifiers declarator
+ * declaration-specifiers abstract-declarator (opt)
+ *
+ * identifier-list :
+ * identifier
+ * identifier-list , identifier
+ *
+ * Params:
+ * declarator = declarator kind
+ * t = base type to start with
+ * pident = set to Identifier if there is one, null if not
+ * storageClass = any storage classes seen so far that apply to a function
+ * Returns:
+ * type declared. If a TypeFunction is returned, this.symbols is the
+ * symbol table for the parameter-type-list, which will contain any
+ * declared struct, union or enum tags.
+ */
+ private AST.Type cparseDeclarator(DTR declarator, AST.Type t,
+ out Identifier pident, StorageClass storageClass = 0)
+ {
+ //printf("cparseDeclarator(%d)\n", declarator);
+ AST.Types constTypes; // all the Types that will need `const` applied to them
+ constTypes.setDim(0);
+
+ AST.Type parseDecl(AST.Type t)
+ {
+ AST.Type ts;
+ while (1)
+ {
+ switch (token.value)
+ {
+ case TOK.identifier: // identifier
+ //printf("identifier %s\n", token.ident.toChars());
+ if (declarator == DTR.xabstract)
+ error("identifier not allowed in abstract-declarator");
+ pident = token.ident;
+ ts = t;
+ nextToken();
+ break;
+
+ case TOK.leftParenthesis: // ( declarator )
+ /* like: T (*fp)();
+ * T ((*fp))();
+ */
+ nextToken();
+ ts = parseDecl(t);
+ check(TOK.rightParenthesis);
+ break;
+
+ case TOK.mul: // pointer
+ t = new AST.TypePointer(t);
+ nextToken();
+ // add post fixes const/volatile/restrict/_Atomic
+ const mod = cparseTypeQualifierList();
+ if (mod & MOD.xconst)
+ constTypes.push(t);
+ continue;
+
+ default:
+ if (declarator == DTR.xdirect)
+ {
+ error("identifier or `(` expected"); // )
+ panic();
+ }
+ ts = t;
+ break;
+ }
+ break;
+ }
+
+ // parse DeclaratorSuffixes
+ while (1)
+ {
+ /* Insert tx -> t into
+ * ts -> ... -> t
+ * so that
+ * ts -> ... -> tx -> t
+ */
+ static void insertTx(ref AST.Type ts, AST.Type tx, AST.Type t)
+ {
+ AST.Type* pt;
+ for (pt = &ts; *pt != t; pt = &(cast(AST.TypeNext)*pt).next)
+ {
+ }
+ *pt = tx;
+ }
+
+ switch (token.value)
+ {
+ case TOK.leftBracket:
+ {
+ // post [] syntax.
+ AST.Type ta;
+ nextToken();
+
+ // pick up any leading type qualifiers, `static` and `*`
+ bool isStatic;
+ if (token.value == TOK.static_)
+ {
+ isStatic = true;
+ nextToken();
+ }
+
+ bool isVLA;
+ if (!isStatic)
+ {
+ if (token.value == TOK.static_)
+ {
+ isStatic = true;
+ nextToken();
+ }
+ else if (token.value == TOK.mul)
+ {
+ if (peekNext() == TOK.rightBracket)
+ {
+ isVLA = true;
+ nextToken();
+ }
+ }
+ }
+ if (isVLA) // C11 6.7.6.2
+ {
+ error("variable length arrays are not supported");
+ }
+ if (isStatic) // C11 6.7.6.3
+ {
+ error("static array parameters are not supported");
+ }
+
+ if (token.value == TOK.rightBracket)
+ {
+ // An array of unknown size, fake it with a DArray
+ ta = new AST.TypeDArray(t); // []
+ nextToken();
+ }
+ else
+ {
+ //printf("It's a static array\n");
+ AST.Expression e = cparseAssignExp(); // [ expression ]
+ ta = new AST.TypeSArray(t, e);
+ check(TOK.rightBracket);
+ }
+
+ const mod = cparseTypeQualifierList(); // const/volatile/restrict/_Atomic
+ if (mod & MOD.xconst) // ignore the other bits
+ ta = toConst(ta);
+
+ insertTx(ts, ta, t); // ts -> ... -> ta -> t
+ continue;
+ }
+
+ case TOK.leftParenthesis:
+ {
+ // New symbol table for parameter-list
+ auto symbolsSave = this.symbols;
+ this.symbols = null;
+
+ auto parameterList = cparseParameterList();
+ AST.Type tf = new AST.TypeFunction(parameterList, t, linkage, 0);
+ // tf = tf.addSTC(storageClass); // TODO
+ insertTx(ts, tf, t); // ts -> ... -> tf -> t
+
+ if (ts != tf)
+ this.symbols = symbolsSave;
+ break;
+ }
+
+ default:
+ break;
+ }
+ break;
+ }
+ return ts;
+ }
+
+ t = parseDecl(t);
+
+ /* Because const is transitive, cannot assemble types from
+ * fragments. Instead, types to be annotated with const are put
+ * in constTypes[], and a bottom up scan of t is done to apply
+ * const
+ */
+ if (constTypes.length)
+ {
+ AST.Type constApply(AST.Type t)
+ {
+ if (t.nextOf())
+ {
+ auto tn = cast(AST.TypeNext)t; // t.nextOf() should return a ref instead of this
+ tn.next = constApply(tn.next);
+ }
+ foreach (tc; constTypes[])
+ {
+ if (tc is t)
+ {
+ return toConst(t);
+ }
+ }
+ return t;
+ }
+
+ t = constApply(t);
+ }
+
+ //printf("result: %s\n", t.toChars());
+ return t;
+ }
+
+ /******************************
+ * C11 6.7.3
+ * type-qualifier:
+ * const
+ * restrict
+ * volatile
+ * _Atomic
+ */
+ MOD cparseTypeQualifierList()
+ {
+ MOD mod;
+ while (1)
+ {
+ switch (token.value)
+ {
+ case TOK.const_: mod |= MOD.xconst; break;
+ case TOK.volatile: mod |= MOD.xvolatile; break;
+ case TOK.restrict: mod |= MOD.xrestrict; break;
+ case TOK._Atomic: mod |= MOD.x_Atomic; break;
+
+ default:
+ return mod;
+ }
+ nextToken();
+ }
+ }
+
+ /***********************************
+ * C11 6.7.7
+ */
+ AST.Type cparseTypeName()
+ {
+ Specifier specifier;
+ auto tspec = cparseSpecifierQualifierList(LVL.global, specifier);
+ Identifier id;
+ return cparseDeclarator(DTR.xabstract, tspec, id);
+ }
+
+ /***********************************
+ * C11 6.7.2.1
+ * specifier-qualifier-list:
+ * type-specifier specifier-qualifier-list (opt)
+ * type-qualifier specifier-qualifier-list (opt)
+ * Params:
+ * level = declaration context
+ * specifier = specifiers in and out
+ * Returns:
+ * resulting type, null if not specified
+ */
+ AST.Type cparseSpecifierQualifierList(LVL level, ref Specifier specifier)
+ {
+ auto t = cparseDeclarationSpecifiers(level, specifier);
+ if (specifier.scw)
+ error("storage class not allowed in specifier-qualified-list");
+ return t;
+ }
+
+ /***********************************
+ * C11 6.7.6.3
+ * ( parameter-type-list )
+ * ( identifier-list (opt) )
+ */
+ AST.ParameterList cparseParameterList()
+ {
+ auto parameters = new AST.Parameters();
+ AST.VarArg varargs = AST.VarArg.none;
+ StorageClass varargsStc;
+
+ check(TOK.leftParenthesis);
+ if (token.value == TOK.void_ && peekNext() == TOK.rightParenthesis)
+ {
+ nextToken();
+ nextToken();
+ return AST.ParameterList(parameters, varargs, varargsStc);
+ }
+
+ /* The check for identifier-list comes later,
+ * when doing the trailing declaration-list (opt)
+ */
+ while (1)
+ {
+ if (token.value == TOK.rightParenthesis)
+ break;
+ if (token.value == TOK.dotDotDot)
+ {
+ varargs = AST.VarArg.variadic; // C-style variadics
+ nextToken();
+ check(TOK.rightParenthesis);
+ return AST.ParameterList(parameters, varargs, varargsStc);
+ }
+
+ Specifier specifier;
+ auto tspec = cparseDeclarationSpecifiers(LVL.prototype, specifier);
+
+ Identifier id;
+ auto t = cparseDeclarator(DTR.xparameter, tspec, id);
+ if (specifier.mod & MOD.xconst)
+ t = toConst(t);
+ auto param = new AST.Parameter(STC.parameter, t, id, null, null);
+ parameters.push(param);
+ if (token.value == TOK.rightParenthesis)
+ break;
+ check(TOK.comma);
+ }
+ nextToken();
+ return AST.ParameterList(parameters, varargs, varargsStc);
+ }
+
+ /***********************************
+ * C11 6.7.10
+ * _Static_assert ( constant-expression , string-literal ) ;
+ */
+ private AST.StaticAssert cparseStaticAssert()
+ {
+ const loc = token.loc;
+
+ //printf("cparseStaticAssert()\n");
+ nextToken();
+ check(TOK.leftParenthesis);
+ auto exp = cparseConstantExp();
+ check(TOK.comma);
+ if (token.value != TOK.string_)
+ error("string literal expected");
+ auto msg = cparsePrimaryExp();
+ check(TOK.rightParenthesis);
+ check(TOK.semicolon);
+ return new AST.StaticAssert(loc, exp, msg);
+ }
+
+ /*************************
+ * Collect argument list.
+ * Parser is on opening parenthesis.
+ * Returns:
+ * the arguments
+ */
+ private AST.Expressions* cparseArguments()
+ {
+ nextToken();
+ auto arguments = new AST.Expressions();
+ while (token.value != TOK.rightParenthesis && token.value != TOK.endOfFile)
+ {
+ auto arg = cparseAssignExp();
+ arguments.push(arg);
+ if (token.value != TOK.comma)
+ break;
+
+ nextToken(); // consume comma
+ }
+
+ check(TOK.rightParenthesis);
+
+ return arguments;
+ }
+
+ /*************************
+ * __declspec parser
+ * https://docs.microsoft.com/en-us/cpp/cpp/declspec
+ * decl-specifier:
+ * __declspec ( extended-decl-modifier-seq )
+ *
+ * extended-decl-modifier-seq:
+ * extended-decl-modifier (opt)
+ * extended-decl-modifier extended-decl-modifier-seq
+ *
+ * extended-decl-modifier:
+ * dllimport
+ * dllexport
+ */
+ private void cparseDeclspec()
+ {
+ /* Check for dllexport, dllimport
+ * Ignore the rest
+ */
+ bool dllimport; // TODO implement
+ bool dllexport; // TODO implement
+ nextToken(); // move past __declspec
+ check(TOK.leftParenthesis);
+ while (1)
+ {
+ if (token.value == TOK.rightParenthesis)
+ {
+ nextToken();
+ break;
+ }
+ else if (token.value == TOK.endOfFile)
+ break;
+ else if (token.value == TOK.identifier)
+ {
+ if (token.ident == Id.dllimport)
+ {
+ dllimport = true;
+ nextToken();
+ }
+ else if (token.ident == Id.dllexport)
+ {
+ dllexport = true;
+ nextToken();
+ }
+ else
+ {
+ nextToken();
+ if (token.value == TOK.leftParenthesis)
+ cparseParens();
+ }
+ }
+ else
+ {
+ error("extended-decl-modifier expected");
+ }
+ break;
+ }
+ }
+
+ /*************************
+ * Simple asm parser
+ * https://gcc.gnu.org/onlinedocs/gcc/Asm-Labels.html
+ * simple-asm-expr:
+ * asm ( asm-string-literal )
+ *
+ * asm-string-literal:
+ * string-literal
+ */
+ private AST.Expression cparseSimpleAsmExpr()
+ {
+ nextToken(); // move past asm
+ check(TOK.leftParenthesis);
+ if (token.value != TOK.string_)
+ error("string literal expected");
+ auto label = cparsePrimaryExp();
+ check(TOK.rightParenthesis);
+ return label;
+ }
+
+ /*************************
+ * __attribute__ parser
+ * https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
+ * gnu-attributes:
+ * gnu-attributes gnu-attribute-specifier
+ *
+ * gnu-attribute-specifier:
+ * __attribute__ (( gnu-attribute-list ))
+ *
+ * gnu-attribute-list:
+ * gnu-attribute (opt)
+ * gnu-attribute-list , gnu-attribute
+ */
+ private void cparseGnuAttributes()
+ {
+ while (token.value == TOK.__attribute__)
+ {
+ nextToken(); // move past __attribute__
+ check(TOK.leftParenthesis);
+ cparseParens(); // TODO: implement
+ check(TOK.rightParenthesis);
+ }
+ }
+
+ /*************************
+ * Parse a single GNU attribute
+ * gnu-attribute:
+ * gnu-attribute-name
+ * gnu-attribute-name ( identifier )
+ * gnu-attribute-name ( identifier , expression-list )
+ * gnu-attribute-name ( expression-list (opt) )
+ *
+ * gnu-attribute-name:
+ * keyword
+ * identifier
+ *
+ * expression-list:
+ * constant-expression
+ * expression-list , constant-expression
+ */
+ private void cparseGnuAttribute()
+ {
+ /* Check for dllimport, dllexport, vector_size(bytes)
+ * Ignore the rest
+ */
+ bool dllimport; // TODO implement
+ bool dllexport; // TODO implement
+ nextToken(); // move past __attribute__
+ check(TOK.leftParenthesis);
+ check(TOK.leftParenthesis);
+ while (1)
+ {
+ if (token.value == TOK.rightParenthesis)
+ {
+ nextToken();
+ check(TOK.rightParenthesis);
+ break;
+ }
+ else if (token.value == TOK.endOfFile)
+ break;
+ else if (token.value == TOK.identifier)
+ {
+ if (token.ident == Id.dllimport)
+ {
+ dllimport = true;
+ nextToken();
+ }
+ else if (token.ident == Id.dllexport)
+ {
+ dllexport = true;
+ nextToken();
+ }
+ else if (token.ident == Id.vector_size)
+ {
+ nextToken();
+ check(TOK.leftParenthesis);
+ cparseConstantExp(); // TODO implement
+ check(TOK.rightParenthesis);
+ }
+ else
+ {
+ nextToken();
+ if (token.value == TOK.leftParenthesis)
+ cparseParens();
+ }
+ }
+ else
+ {
+ error("extended-decl-modifier expected");
+ }
+ break;
+ }
+ }
+
+ /***************************
+ * Like skipParens(), but consume the tokens.
+ */
+ private void cparseParens()
+ {
+ check(TOK.leftParenthesis);
+ int parens = 1;
+
+ while (1)
+ {
+ switch (token.value)
+ {
+ case TOK.leftParenthesis:
+ ++parens;
+ break;
+
+ case TOK.rightParenthesis:
+ --parens;
+ if (parens < 0)
+ {
+ error("extra right parenthesis");
+ return;
+ }
+ if (parens == 0)
+ {
+ nextToken();
+ return;
+ }
+ break;
+
+ case TOK.endOfFile:
+ error("end of file found before right parenthesis");
+ return;
+
+ default:
+ break;
+ }
+ nextToken();
+ }
+ }
+
+ //}
+ /******************************************************************************/
+ /***************************** Struct & Enum Parser ***************************/
+ //{
+
+ /*************************************
+ * C11 6.7.2.2
+ * enum-specifier:
+ * enum identifier (opt) { enumerator-list }
+ * enum identifier (opt) { enumerator-list , }
+ * enum identifier
+ *
+ * enumerator-list:
+ * enumerator
+ * enumerator-list , enumerator
+ *
+ * enumerator:
+ * enumeration-constant
+ * enumeration-constant = constant-expression
+ *
+ * enumeration-constant:
+ * identifier
+ *
+ * Params:
+ * symbols = symbols to add enum declaration to
+ * Returns:
+ * type of the enum
+ */
+ private AST.Type cparseEnum(ref AST.Dsymbols* symbols)
+ {
+ const loc = token.loc;
+ nextToken();
+
+ /* GNU Extensions
+ * enum-specifier:
+ * enum gnu-attributes (opt) identifier (opt) { enumerator-list } gnu-attributes (opt)
+ * enum gnu-attributes (opt) identifier (opt) { enumerator-list , } gnu-attributes (opt)
+ * enum gnu-attributes (opt) identifier
+ */
+ if (token.value == TOK.__attribute__)
+ cparseGnuAttributes();
+
+ Identifier tag;
+ if (token.value == TOK.identifier)
+ {
+ tag = token.ident;
+ nextToken();
+ }
+
+ AST.Dsymbols* members;
+ if (token.value == TOK.leftCurly)
+ {
+ nextToken();
+ members = new AST.Dsymbols();
+
+ if (token.value == TOK.rightCurly) // C11 6.7.2.2-1
+ {
+ if (tag)
+ error("no members for `enum %s`", tag.toChars());
+ else
+ error("no members for anonymous enum");
+ }
+
+ while (token.value == TOK.identifier)
+ {
+ auto ident = token.ident; // enumeration-constant
+ nextToken();
+ auto mloc = token.loc;
+
+ AST.Expression value;
+ if (token.value == TOK.assign)
+ {
+ nextToken();
+ value = cparseConstantExp();
+ // TODO C11 6.7.2.2-2 value must fit into an int
+ }
+
+ auto em = new AST.EnumMember(mloc, ident, value, null, 0, null, null);
+ members.push(em);
+
+ if (token.value == TOK.comma)
+ {
+ nextToken();
+ continue;
+ }
+ break;
+ }
+ check(TOK.rightCurly);
+
+ /* GNU Extensions
+ * Parse the postfix gnu-attributes (opt)
+ */
+ if (token.value == TOK.__attribute__)
+ cparseGnuAttributes();
+ }
+ else if (!tag)
+ error("missing `identifier` after `enum`");
+
+ /* Need semantic information to determine if this is a declaration,
+ * redeclaration, or reference to existing declaration.
+ * Defer to the semantic() pass with a TypeTag.
+ */
+ return new AST.TypeTag(loc, TOK.enum_, tag, members);
+ }
+
+ /*************************************
+ * C11 6.7.2.1
+ * Parse struct and union specifiers.
+ * Parser is advanced to the tag identifier or brace.
+ * struct-or-union-specifier:
+ * struct-or-union identifier (opt) { struct-declaration-list }
+ * struct-or-union identifier
+ *
+ * struct-or-union:
+ * struct
+ * union
+ *
+ * struct-declaration-list:
+ * struct-declaration
+ * struct-declaration-list struct-declaration
+ *
+ * Params:
+ * loc = location of `struct` or `union`
+ * structOrUnion = TOK.struct_ or TOK.union_
+ * symbols = symbols to add struct-or-union declaration to
+ * Returns:
+ * type of the struct
+ */
+ private AST.Type cparseStruct(Loc loc, TOK structOrUnion, ref AST.Dsymbols* symbols)
+ {
+ Identifier tag;
+
+ if (token.value == TOK.identifier)
+ {
+ tag = token.ident;
+ nextToken();
+ }
+
+ AST.Dsymbols* members;
+ if (token.value == TOK.leftCurly)
+ {
+ nextToken();
+ auto symbolsSave = symbols;
+ symbols = new AST.Dsymbols();
+ while (token.value != TOK.rightCurly)
+ {
+ cparseStructDeclaration();
+
+ if (token.value == TOK.endOfFile)
+ break;
+ }
+ members = symbols; // `members` will be non-null even with 0 members
+ symbols = symbolsSave;
+ check(TOK.rightCurly);
+
+ if ((*members).length == 0) // C11 6.7.2.1-8
+ /* TODO: not strict enough, should really be contains "no named members",
+ * not just "no members".
+ * I.e. an unnamed bit field, _Static_assert, etc, are not named members,
+ * but will pass this check.
+ * Be careful to detect named members that come anonymous structs.
+ * Correctly doing this will likely mean moving it to typesem.d.
+ */
+ error("empty struct-declaration-list for `%s %s`", Token.toChars(structOrUnion), tag ? tag.toChars() : "Anonymous".ptr);
+ }
+ else if (!tag)
+ error("missing tag `identifier` after `%s`", Token.toChars(structOrUnion));
+
+ /* Need semantic information to determine if this is a declaration,
+ * redeclaration, or reference to existing declaration.
+ * Defer to the semantic() pass with a TypeTag.
+ */
+ return new AST.TypeTag(loc, structOrUnion, tag, members);
+ }
+
+ /*************************************
+ * C11 6.7.2.1
+ * Parse a struct declaration member.
+ * struct-declaration:
+ * specifier-qualifier-list struct-declarator-list (opt) ;
+ * static_assert-declaration
+ *
+ * struct-declarator-list:
+ * struct-declarator
+ * struct-declarator-list , struct-declarator
+ *
+ * struct-declarator:
+ * declarator
+ * declarator (opt) : constant-expression
+ */
+ void cparseStructDeclaration()
+ {
+ //printf("cparseStructDeclaration()\n");
+ if (token.value == TOK._Static_assert)
+ {
+ auto s = cparseStaticAssert();
+ symbols.push(s);
+ return;
+ }
+
+ auto symbolsSave = symbols;
+ Specifier specifier;
+ auto tspec = cparseSpecifierQualifierList(LVL.member, specifier);
+
+ /* If a declarator does not follow, it is unnamed
+ */
+ if (token.value == TOK.semicolon && tspec)
+ {
+ nextToken();
+ auto tt = tspec.isTypeTag();
+ if (!tt)
+ return; // legal but meaningless empty declaration
+
+ /* If anonymous struct declaration
+ * struct { ... members ... };
+ * C11 6.7.2.1-13
+ */
+ if (!tt.id && tt.members)
+ {
+ /* members of anonymous struct are considered members of
+ * the containing struct
+ */
+ // TODO: merge in specifier
+ auto ad = new AST.AnonDeclaration(tt.loc, tt.tok == TOK.union_, tt.members);
+ if (!symbols)
+ symbols = new AST.Dsymbols();
+ symbols.push(ad);
+ return;
+ }
+ if (!tt.id && !tt.members)
+ return; // already gave error in cparseStruct()
+
+ /* `struct tag;` and `struct tag { ... };`
+ * always result in a declaration in the current scope
+ */
+ // TODO: merge in specifier
+ auto stag = (tt.tok == TOK.struct_)
+ ? new AST.StructDeclaration(tt.loc, tt.id, false)
+ : new AST.UnionDeclaration(tt.loc, tt.id);
+ stag.members = tt.members;
+ if (!symbols)
+ symbols = new AST.Dsymbols();
+ symbols.push(stag);
+ return;
+ }
+
+ while (1)
+ {
+ Identifier id;
+ AST.Type dt;
+ if (token.value == TOK.colon)
+ {
+ // C11 6.7.2.1-12 unnamed bit-field
+ nextToken();
+ cparseConstantExp();
+ error("unnamed bit fields are not supported"); // TODO
+ dt = AST.Type.tuns32;
+ }
+ else
+ dt = cparseDeclarator(DTR.xdirect, tspec, id);
+ if (!dt)
+ {
+ panic();
+ nextToken();
+ break; // error recovery
+ }
+ if (id && token.value == TOK.colon)
+ {
+ // C11 6.7.2.1-10 bit-field
+ nextToken();
+ cparseConstantExp();
+ error("bit fields are not supported"); // TODO
+ }
+
+ if (specifier.mod & MOD.xconst)
+ dt = toConst(dt);
+
+ /* GNU Extensions
+ * struct-declarator:
+ * declarator gnu-attributes (opt)
+ * declarator (opt) : constant-expression gnu-attributes (opt)
+ */
+ if (token.value == TOK.__attribute__)
+ cparseGnuAttributes();
+
+ AST.Dsymbol s = null;
+ symbols = symbolsSave;
+ if (!symbols)
+ symbols = new AST.Dsymbols; // lazilly create it
+
+ if (!tspec && !specifier.scw && !specifier.mod)
+ error("specifier-qualifier-list required");
+ else if (id)
+ {
+ if (dt.ty == AST.Tvoid)
+ error("`void` has no value");
+
+ // declare the symbol
+ // Give member variables an implicit void initializer
+ auto initializer = new AST.VoidInitializer(token.loc);
+ s = new AST.VarDeclaration(token.loc, dt, id, initializer, specifiersToSTC(LVL.member, specifier));
+ }
+ if (s !is null)
+ symbols.push(s);
+
+ switch (token.value)
+ {
+ case TOK.identifier:
+ error("missing comma");
+ goto default;
+
+ case TOK.semicolon:
+ nextToken();
+ return;
+
+ case TOK.comma:
+ nextToken();
+ break;
+
+ default:
+ error("`;` or `,` expected");
+ while (token.value != TOK.semicolon && token.value != TOK.endOfFile)
+ nextToken();
+ nextToken();
+ return;
+ }
+ }
+ }
+
+ //}
+ /******************************************************************************/
+ /********************************* Lookahead Parser ***************************/
+ //{
+
+ /************************************
+ * Determine if the scanner is sitting on the start of a declaration.
+ * Params:
+ * t = current token of the scanner
+ * needId = flag with additional requirements for a declaration
+ * endtok = ending token
+ * pt = will be set ending token (if not null)
+ * Returns:
+ * true at start of a declaration
+ */
+ private bool isCDeclaration(ref Token* pt)
+ {
+ //printf("isCDeclaration()\n");
+ auto t = pt;
+ if (!isDeclarationSpecifiers(t))
+ return false;
+
+ while (1)
+ {
+ if (t.value == TOK.semicolon)
+ {
+ t = peek(t);
+ pt = t;
+ return true;
+ }
+ if (!isCDeclarator(t, DTR.xdirect))
+ return false;
+ if (t.value == TOK.asm_)
+ {
+ t = peek(t);
+ if (t.value != TOK.leftParenthesis || !skipParens(t, &t))
+ return false;
+ }
+ if (t.value == TOK.__attribute__)
+ {
+ t = peek(t);
+ if (t.value != TOK.leftParenthesis || !skipParens(t, &t))
+ return false;
+ }
+ if (t.value == TOK.assign)
+ {
+ t = peek(t);
+ if (!isInitializer(t))
+ return false;
+ }
+ switch (t.value)
+ {
+ case TOK.comma:
+ t = peek(t);
+ break;
+
+ case TOK.semicolon:
+ t = peek(t);
+ pt = t;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+ }
+
+ /********************************
+ * See if match for initializer.
+ * Params:
+ * pt = starting token, updated to one past end of initializer if true
+ * Returns:
+ * true if initializer
+ */
+ private bool isInitializer(ref Token* pt)
+ {
+ //printf("isInitializer()\n");
+ auto t = pt;
+
+ if (t.value == TOK.leftCurly)
+ {
+ if (!skipBraces(t))
+ return false;
+ pt = t;
+ return true;
+ }
+
+ // skip over assignment-expression, ending before comma or semiColon or EOF
+ if (!isAssignmentExpression(t))
+ return false;
+ pt = t;
+ return true;
+ }
+
+ /********************************
+ * See if match for assignment-expression.
+ * Params:
+ * pt = starting token, updated to one past end of assignment-expression if true
+ * Returns:
+ * true if assignment-expression
+ */
+ private bool isAssignmentExpression(ref Token* pt)
+ {
+ //printf("isAssignmentExpression()\n");
+ auto t = pt;
+
+ /* This doesn't actually check for grammar matching an
+ * assignment-expression. It just matches ( ) [ ] looking for
+ * an ending token that would terminate one.
+ */
+ bool any;
+ while (1)
+ {
+ switch (t.value)
+ {
+ case TOK.comma:
+ case TOK.semicolon:
+ case TOK.rightParenthesis:
+ case TOK.rightBracket:
+ case TOK.endOfFile:
+ if (!any)
+ return false;
+ break;
+
+ case TOK.leftParenthesis:
+ if (!skipParens(t, &t))
+ return false;
+ continue;
+
+ case TOK.leftBracket:
+ if (!skipBrackets(t))
+ return false;
+ continue;
+
+ default:
+ any = true; // assume token was part of an a-e
+ t = peek(t);
+ continue;
+ }
+ pt = t;
+ return true;
+ }
+ }
+
+ /********************************
+ * See if match for constant-expression.
+ * Params:
+ * pt = starting token, updated to one past end of constant-expression if true
+ * Returns:
+ * true if constant-expression
+ */
+ private bool isConstantExpression(ref Token* pt)
+ {
+ return isAssignmentExpression(pt);
+ }
+
+ /********************************
+ * See if match for declaration-specifiers.
+ * No errors are diagnosed.
+ * Params:
+ * pt = starting token, updated to one past end of declaration-specifiers if true
+ * Returns:
+ * true if declaration-specifiers
+ */
+ private bool isDeclarationSpecifiers(ref Token* pt)
+ {
+ //printf("isDeclarationSpecifiers()\n");
+
+ auto t = pt;
+
+ bool any;
+ while (1)
+ {
+ switch (t.value)
+ {
+ // type-specifiers
+ case TOK.void_:
+ case TOK.char_:
+ case TOK.int16:
+ case TOK.int32:
+ case TOK.int64:
+ case TOK.float32:
+ case TOK.float64:
+ case TOK.signed:
+ case TOK.unsigned:
+ case TOK._Bool:
+ //case TOK._Imaginary:
+ case TOK._Complex:
+ case TOK.identifier: // typedef-name
+ t = peek(t);
+ any = true;
+ break;
+
+ case TOK.struct_:
+ case TOK.union_:
+ case TOK.enum_:
+ t = peek(t);
+ if (t.value == TOK.identifier)
+ {
+ t = peek(t);
+ if (t.value == TOK.leftCurly)
+ {
+ if (!skipBraces(t))
+ return false;
+ }
+ }
+ else if (t.value == TOK.leftCurly)
+ {
+ if (!skipBraces(t))
+ return false;
+ }
+ else
+ return false;
+ any = true;
+ continue;
+
+ // storage-class-specifiers
+ case TOK.typedef_:
+ case TOK.extern_:
+ case TOK.static_:
+ case TOK._Thread_local:
+ case TOK.auto_:
+ case TOK.register:
+
+ // function-specifiers
+ case TOK.inline:
+ case TOK._Noreturn:
+
+ // type-qualifiers
+ case TOK.const_:
+ case TOK.volatile:
+ case TOK.restrict:
+ t = peek(t);
+ any = true;
+ continue;
+
+ case TOK._Alignas: // alignment-specifier
+ case TOK.__declspec: // decl-specifier
+ case TOK.__attribute__: // attribute-specifier
+ t = peek(t);
+ if (!skipParens(t, &t))
+ return false;
+ any = true;
+ continue;
+
+ // either atomic-type-specifier or type_qualifier
+ case TOK._Atomic: // TODO _Atomic ( type-name )
+ t = peek(t);
+ if (t.value == TOK.leftParenthesis) // maybe atomic-type-specifier
+ {
+ auto tsave = t;
+ t = peek(t);
+ if (!isTypeName(t) || t.value != TOK.rightParenthesis)
+ { // it's a type-qualifier
+ t = tsave; // back up parser
+ any = true;
+ continue;
+ }
+ t = peek(t); // move past right parenthesis of atomic-type-specifier
+ }
+ any = true;
+ continue;
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ if (any)
+ {
+ pt = t;
+ return true;
+ }
+ return false;
+ }
+
+ /**************************************
+ * See if declaration-list is present.
+ * Returns:
+ * true if declaration-list is present, even an empty one
+ */
+ bool isDeclarationList(ref Token* pt)
+ {
+ auto t = pt;
+ while (1)
+ {
+ if (t.value == TOK.leftCurly)
+ {
+ pt = t;
+ return true;
+ }
+ if (!isCDeclaration(t))
+ return false;
+ }
+ }
+
+ /*******************************************
+ * Skip braces.
+ * Params:
+ * pt = enters on left brace, set to token past right bracket on true
+ * Returns:
+ * true if successful
+ */
+ private bool skipBraces(ref Token* pt)
+ {
+ auto t = pt;
+ if (t.value != TOK.leftCurly)
+ return false;
+
+ int braces = 0;
+
+ while (1)
+ {
+ switch (t.value)
+ {
+ case TOK.leftCurly:
+ ++braces;
+ t = peek(t);
+ continue;
+
+ case TOK.rightCurly:
+ --braces;
+ if (braces == 0)
+ {
+ pt = peek(t);
+ return true;
+ }
+ if (braces < 0)
+ return false;
+
+ t = peek(t);
+ continue;
+
+ case TOK.endOfFile:
+ return false;
+
+ default:
+ t = peek(t);
+ continue;
+ }
+ }
+ }
+
+ /*******************************************
+ * Skip brackets.
+ * Params:
+ * pt = enters on left bracket, set to token past right bracket on true
+ * Returns:
+ * true if successful
+ */
+ private bool skipBrackets(ref Token* pt)
+ {
+ auto t = pt;
+ if (t.value != TOK.leftBracket)
+ return false;
+
+ int brackets = 0;
+
+ while (1)
+ {
+ switch (t.value)
+ {
+ case TOK.leftBracket:
+ ++brackets;
+ t = peek(t);
+ continue;
+
+ case TOK.rightBracket:
+ --brackets;
+ if (brackets == 0)
+ {
+ pt = peek(t);
+ return true;
+ }
+ if (brackets < 0)
+ return false;
+
+ t = peek(t);
+ continue;
+
+ case TOK.endOfFile:
+ return false;
+
+ default:
+ t = peek(t);
+ continue;
+ }
+ }
+ }
+
+ /*********************************
+ * Check to see if tokens starting with *pt form a declarator.
+ * Params:
+ * pt = pointer to starting token, updated to point past declarator if true is returned
+ * declarator = declarator kind
+ * Returns:
+ * true if it does
+ */
+ private bool isCDeclarator(ref Token* pt, DTR declarator)
+ {
+ auto t = pt;
+ while (1)
+ {
+ if (t.value == TOK.mul) // pointer
+ {
+ t = peek(t);
+ if (!isTypeQualifierList(t))
+ return false;
+ }
+ else
+ break;
+ }
+
+ if (t.value == TOK.identifier)
+ {
+ if (declarator == DTR.xabstract)
+ return false;
+ t = peek(t);
+ }
+ else if (t.value == TOK.leftParenthesis)
+ {
+ t = peek(t);
+ if (!isCDeclarator(t, declarator))
+ return false;
+ if (t.value != TOK.rightParenthesis)
+ return false;
+ t = peek(t);
+ }
+ else if (declarator == DTR.xdirect)
+ {
+ return false;
+ }
+
+ if (t.value == TOK.leftBracket)
+ {
+ if (!skipBrackets(t))
+ return false;
+ }
+ else if (t.value == TOK.leftParenthesis)
+ {
+ if (!skipParens(t, &t))
+ return false;
+ }
+ pt = t;
+ return true;
+ }
+
+ /***************************
+ * Is this the start of a type-qualifier-list?
+ * (Can be empty.)
+ * Params:
+ * pt = first token; updated with past end of type-qualifier-list if true
+ * Returns:
+ * true if start of type-qualifier-list
+ */
+ private bool isTypeQualifierList(ref Token* pt)
+ {
+ auto t = pt;
+ while (1)
+ {
+ switch (t.value)
+ {
+ case TOK.const_:
+ case TOK.restrict:
+ case TOK.volatile:
+ case TOK._Atomic:
+ t = peek(t);
+ continue;
+
+ default:
+ break;
+ }
+ break;
+ }
+ pt = t;
+ return true;
+ }
+
+ /***************************
+ * Is this the start of a type-name?
+ * Params:
+ * pt = first token; updated with past end of type-name if true
+ * Returns:
+ * true if start of type-name
+ */
+ private bool isTypeName(ref Token* pt)
+ {
+ auto t = pt;
+ //printf("isTypeName() %s\n", t.toChars());
+ if (!isSpecifierQualifierList(t))
+ return false;
+ if (!isCDeclarator(t, DTR.xabstract))
+ return false;
+ pt = t;
+ return true;
+ }
+
+ /***************************
+ * Is this the start of a specifier-qualifier-list?
+ * Params:
+ * pt = first token; updated with past end of specifier-qualifier-list if true
+ * Returns:
+ * true if start of specifier-qualifier-list
+ */
+ private bool isSpecifierQualifierList(ref Token* pt)
+ {
+ auto t = pt;
+ bool result;
+ while (1)
+ {
+ switch (t.value)
+ {
+ // Type Qualifiers
+ case TOK.const_:
+ case TOK.restrict:
+ case TOK.volatile:
+
+ // Type Specifiers
+ case TOK.char_:
+ case TOK.signed:
+ case TOK.unsigned:
+ case TOK.int16:
+ case TOK.int32:
+ case TOK.int64:
+ case TOK.float32:
+ case TOK.float64:
+ case TOK.void_:
+ case TOK._Bool:
+ //case TOK._Imaginary: // ? missing in Spec
+ case TOK._Complex:
+
+ // typedef-name
+ case TOK.identifier: // will not know until semantic if typedef
+ t = peek(t);
+ break;
+
+ // struct-or-union-specifier
+ // enum-specifier
+ case TOK.struct_:
+ case TOK.union_:
+ case TOK.enum_:
+ t = peek(t);
+ if (t.value == TOK.identifier)
+ {
+ t = peek(t);
+ if (t.value == TOK.leftCurly)
+ {
+ if (!skipBraces(t))
+ return false;
+ }
+ }
+ else if (t.value == TOK.leftCurly)
+ {
+ if (!skipBraces(t))
+ return false;
+ }
+ else
+ return false;
+ break;
+
+ // atomic-type-specifier
+ case TOK._Atomic:
+ t = peek(t);
+ if (t.value != TOK.leftParenthesis ||
+ !skipParens(t, &t))
+ return false;
+ break;
+
+ default:
+ if (result)
+ pt = t;
+ return result;
+ }
+ result = true;
+ }
+ }
+
+ /************************************
+ * Looking at the leading left parenthesis, and determine if it is
+ * either of the following:
+ * ( type-name ) cast-expression
+ * ( type-name ) { initializer-list }
+ * as opposed to:
+ * ( expression )
+ * Params:
+ * pt = starting token, updated to one past end of constant-expression if true
+ * afterParenType = true if already seen ( type-name )
+ * Returns:
+ * true if matches ( type-name ) ...
+ */
+ private bool isCastExpression(ref Token* pt, bool afterParenType = false)
+ {
+ auto t = pt;
+ switch (t.value)
+ {
+ case TOK.leftParenthesis:
+ auto tk = peek(t); // move past left parenthesis
+ if (!isTypeName(tk) || tk.value != TOK.rightParenthesis)
+ {
+ if (afterParenType)
+ goto default; // could be ( type-name ) ( unary-expression )
+ return false;
+ }
+ t = peek(tk); // move past right parenthesis
+
+ if (t.value == TOK.leftCurly)
+ {
+ // ( type-name ) { initializer-list }
+ if (!isInitializer(t))
+ return false;
+ break;
+ }
+ if (!isCastExpression(t, true))
+ return false;
+ // ( type-name ) cast-expression
+ break;
+
+ default:
+ if (!afterParenType || !isUnaryExpression(t, afterParenType))
+ return false;
+ // if we've already seen ( type-name ), then this is a cast
+ break;
+ }
+ pt = t;
+ return true;
+ }
+
+ /********************************
+ * See if match for unary-expression.
+ * Params:
+ * pt = starting token, updated to one past end of constant-expression if true
+ * afterParenType = true if already seen ( type-name ) of a cast-expression
+ * Returns:
+ * true if unary-expression
+ */
+ private bool isUnaryExpression(ref Token* pt, bool afterParenType = false)
+ {
+ auto t = pt;
+ switch (t.value)
+ {
+ case TOK.plusPlus:
+ case TOK.minusMinus:
+ t = peek(t);
+ if (!isUnaryExpression(t, afterParenType))
+ return false;
+ break;
+
+ case TOK.and:
+ case TOK.mul:
+ case TOK.min:
+ case TOK.add:
+ case TOK.not:
+ case TOK.tilde:
+ t = peek(t);
+ if (!isCastExpression(t, afterParenType))
+ return false;
+ break;
+
+ case TOK.sizeof_:
+ t = peek(t);
+ if (t.value == TOK.leftParenthesis)
+ {
+ auto tk = peek(t);
+ if (isTypeName(tk))
+ {
+ if (tk.value != TOK.rightParenthesis)
+ return false;
+ t = peek(tk);
+ break;
+ }
+ }
+ if (!isUnaryExpression(t, afterParenType))
+ return false;
+ break;
+
+ case TOK._Alignof:
+ t = peek(t);
+ if (t.value != TOK.leftParenthesis)
+ return false;
+ t = peek(t);
+ if (!isTypeName(t) || t.value != TOK.rightParenthesis)
+ return false;
+ break;
+
+ default:
+ // Compound literals are handled by cast and sizeof expressions,
+ // so be content with just seeing a primary expression.
+ if (!isPrimaryExpression(t))
+ return false;
+ break;
+ }
+ pt = t;
+ return true;
+ }
+
+ /********************************
+ * See if match for primary-expression.
+ * Params:
+ * pt = starting token, updated to one past end of constant-expression if true
+ * Returns:
+ * true if primary-expression
+ */
+ private bool isPrimaryExpression(ref Token* pt)
+ {
+ auto t = pt;
+ switch (t.value)
+ {
+ case TOK.identifier:
+ case TOK.int32Literal:
+ case TOK.uns32Literal:
+ case TOK.int64Literal:
+ case TOK.uns64Literal:
+ case TOK.float32Literal:
+ case TOK.float64Literal:
+ case TOK.float80Literal:
+ case TOK.imaginary32Literal:
+ case TOK.imaginary64Literal:
+ case TOK.imaginary80Literal:
+ case TOK.string_:
+ t = peek(t);
+ break;
+
+ case TOK.leftParenthesis:
+ // ( expression )
+ if (!skipParens(t, &t))
+ return false;
+ break;
+
+ case TOK._Generic:
+ t = peek(t);
+ if (!skipParens(t, &t))
+ return false;
+ break;
+
+ default:
+ return false;
+ }
+ pt = t;
+ return true;
+ }
+
+ //}
+ /******************************************************************************/
+ /********************************* More ***************************************/
+ //{
+
+ /**************
+ * Declaration context
+ */
+ enum LVL
+ {
+ global = 1, /// global
+ parameter = 2, /// function parameter (declarations for function identifier-list)
+ prototype = 4, /// function prototype
+ local = 8, /// local
+ member = 0x10, /// struct member
+ }
+
+ /// Types of declarator to parse
+ enum DTR
+ {
+ xdirect = 1, /// C11 6.7.6 direct-declarator
+ xabstract = 2, /// C11 6.7.7 abstract-declarator
+ xparameter = 3, /// parameter declarator may be either direct or abstract
+ }
+
+ /// C11 6.7.1 Storage-class specifiers
+ enum SCW : uint
+ {
+ xnone = 0,
+ xtypedef = 1,
+ xextern = 2,
+ xstatic = 4,
+ x_Thread_local = 8,
+ xauto = 0x10,
+ xregister = 0x20,
+ // C11 6.7.4 Function specifiers
+ xinline = 0x40,
+ x_Noreturn = 0x80,
+ }
+
+ /// C11 6.7.3 Type qualifiers
+ enum MOD : uint
+ {
+ xnone = 0,
+ xconst = 1,
+ xvolatile = 2,
+ xrestrict = 4,
+ x_Atomic = 8,
+ }
+
+ /**********************************
+ * Aggregate for all the various specifiers
+ */
+ struct Specifier
+ {
+ SCW scw; /// storage-class specifiers
+ MOD mod; /// type qualifiers
+ }
+
+ /***********************
+ * Convert from C specifiers to D storage class
+ * Params:
+ * level = declaration context
+ * specifier = specifiers, context, etc.
+ * Returns:
+ * corresponding D storage class
+ */
+ StorageClass specifiersToSTC(LVL level, const ref Specifier specifier)
+ {
+ StorageClass stc;
+ if (specifier.scw & SCW.x_Thread_local)
+ {
+ if (level == LVL.global)
+ {
+ if (specifier.scw & SCW.xextern)
+ stc = AST.STC.extern_;
+ }
+ else if (level == LVL.local)
+ {
+ if (specifier.scw & SCW.xextern)
+ stc = AST.STC.extern_;
+ else if (specifier.scw & SCW.xstatic)
+ stc = AST.STC.static_;
+ }
+ else if (level == LVL.member)
+ {
+ if (specifier.scw & SCW.xextern)
+ stc = AST.STC.extern_;
+ else if (specifier.scw & SCW.xstatic)
+ stc = AST.STC.static_;
+ }
+ }
+ else
+ {
+ if (level == LVL.global)
+ {
+ if (specifier.scw & SCW.xextern)
+ stc = AST.STC.extern_ | AST.STC.gshared;
+ else
+ stc = AST.STC.gshared;
+ }
+ else if (level == LVL.local)
+ {
+ if (specifier.scw & SCW.xextern)
+ stc = AST.STC.extern_ | AST.STC.gshared;
+ else if (specifier.scw & SCW.xstatic)
+ stc = AST.STC.gshared;
+ }
+ else if (level == LVL.member)
+ {
+ if (specifier.scw & SCW.xextern)
+ stc = AST.STC.extern_ | AST.STC.gshared;
+ else if (specifier.scw & SCW.xstatic)
+ stc = AST.STC.gshared;
+ }
+ }
+ return stc;
+ }
+
+ /***********************
+ * Return suitable D float type for C `long double`
+ * Params:
+ * flags = kind of float to return (real, imaginary, complex).
+ * Returns:
+ * corresponding D type
+ */
+ private AST.Type realType(RTFlags flags)
+ {
+ if (long_doublesize == AST.Type.tfloat80.size())
+ {
+ // On GDC and LDC, D `real` types map to C `long double`, so never
+ // return a double type when real.sizeof == double.sizeof.
+ final switch (flags)
+ {
+ case RTFlags.realfloat: return AST.Type.tfloat80;
+ case RTFlags.imaginary: return AST.Type.timaginary80;
+ case RTFlags.complex: return AST.Type.tcomplex80;
+ }
+ }
+ else
+ {
+ final switch (flags)
+ {
+ case RTFlags.realfloat: return long_doublesize == 8 ? AST.Type.tfloat64 : AST.Type.tfloat80;
+ case RTFlags.imaginary: return long_doublesize == 8 ? AST.Type.timaginary64 : AST.Type.timaginary80;
+ case RTFlags.complex: return long_doublesize == 8 ? AST.Type.tcomplex64 : AST.Type.tcomplex80;
+ }
+ }
+ }
+
+ /**************
+ * Flags for realType
+ */
+ private enum RTFlags
+ {
+ realfloat,
+ imaginary,
+ complex,
+ }
+
+ /********************
+ * C11 6.4.2.2 Create declaration to predefine __func__
+ * `static const char __func__[] = " function-name ";`
+ * Params:
+ * loc = location for this declaration
+ * id = identifier of function
+ * Returns:
+ * statement representing the declaration of __func__
+ */
+ private AST.Statement createFuncName(Loc loc, Identifier id)
+ {
+ const fn = id.toString(); // function-name
+ auto efn = new AST.StringExp(loc, fn, fn.length, 1, 'c');
+ auto ifn = new AST.ExpInitializer(loc, efn);
+ auto lenfn = new AST.IntegerExp(loc, fn.length + 1, AST.Type.tuns32); // +1 for terminating 0
+ auto tfn = new AST.TypeSArray(AST.Type.tchar, lenfn);
+ efn.type = tfn.immutableOf();
+ efn.committed = 1;
+ auto sfn = new AST.VarDeclaration(loc, tfn, Id.__func__, ifn, STC.gshared | STC.immutable_);
+ auto e = new AST.DeclarationExp(loc, sfn);
+ return new AST.ExpStatement(loc, e);
+ }
+
+ /************************
+ * After encountering an error, scan forward until a right brace or ; is found
+ * or the end of the file.
+ */
+ void panic()
+ {
+ while (token.value != TOK.rightCurly && token.value != TOK.semicolon && token.value != TOK.endOfFile)
+ nextToken();
+ }
+
+ /**************************
+ * Apply `const` to a type.
+ * Params:
+ * t = type to add const to
+ * Returns:
+ * resulting type
+ */
+ private AST.Type toConst(AST.Type t)
+ {
+ // `const` is always applied to the return type, not the
+ // type function itself.
+ if (auto tf = t.isTypeFunction())
+ tf.next = tf.next.addSTC(STC.const_);
+ else
+ t = t.addSTC(STC.const_);
+ return t;
+ }
+
+ //}
+}
diff --git a/gcc/d/dmd/cppmangle.d b/gcc/d/dmd/cppmangle.d
index 93395ca471e..0381f9ad6a4 100644
--- a/gcc/d/dmd/cppmangle.d
+++ b/gcc/d/dmd/cppmangle.d
@@ -4,7 +4,7 @@
* This is the POSIX side of the implementation.
* It exports two functions to C++, `toCppMangleItanium` and `cppTypeInfoMangleItanium`.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: Walter Bright, http://www.digitalmars.com
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cppmangle.d, _cppmangle.d)
@@ -27,6 +27,7 @@ import core.stdc.string;
import core.stdc.stdio;
import dmd.arraytypes;
+import dmd.astenums;
import dmd.attrib;
import dmd.declaration;
import dmd.dsymbol;
@@ -85,6 +86,17 @@ extern(C++) const(char)* cppTypeInfoMangleItanium(Dsymbol s)
return buf.extractChars();
}
+///
+extern(C++) const(char)* cppThunkMangleItanium(FuncDeclaration fd, int offset)
+{
+ //printf("cppThunkMangleItanium(%s)\n", fd.toChars());
+ OutBuffer buf;
+ buf.printf("_ZThn%u_", offset); // "Th" means thunk, "n%u" is the call offset
+ scope CppMangleVisitor v = new CppMangleVisitor(&buf, fd.loc);
+ v.mangle_function_encoding(fd);
+ return buf.extractChars();
+}
+
/******************************
* Determine if sym is the 'primary' destructor, that is,
* the most-aggregate destructor (the one that is defined as __xdtor)
@@ -259,19 +271,18 @@ private final class CppMangleVisitor : Visitor
{
//printf("substitute %s\n", p ? p.toChars() : null);
auto i = find(p);
- if (i >= 0)
- {
- //printf("\tmatch\n");
- /* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ...
- */
- if (nested)
- buf.writeByte('N');
- buf.writeByte('S');
- writeSequenceFromIndex(i);
- buf.writeByte('_');
- return true;
- }
- return false;
+ if (i < 0)
+ return false;
+
+ //printf("\tmatch\n");
+ /* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ...
+ */
+ if (nested)
+ buf.writeByte('N');
+ buf.writeByte('S');
+ writeSequenceFromIndex(i);
+ buf.writeByte('_');
+ return true;
}
/******
@@ -600,51 +611,74 @@ private final class CppMangleVisitor : Visitor
auto sl = this.buf.peekSlice();
assert(sl.length == 0 || haveNE || s.cppnamespace is null || sl != "_ZN");
}
- if (TemplateInstance ti = s.isTemplateInstance())
+ auto ti = s.isTemplateInstance();
+
+ if (!ti)
{
- bool needsTa = false;
+ auto ag = s.isAggregateDeclaration();
+ const ident = (ag && ag.mangleOverride) ? ag.mangleOverride.id : s.ident;
+ this.writeNamespace(s.cppnamespace, () {
+ this.writeIdentifier(ident);
+ this.abiTags.writeSymbol(s, this);
+ },
+ haveNE);
+ return;
+ }
- // https://issues.dlang.org/show_bug.cgi?id=20413
- // N..E is not needed when substituting members of the std namespace.
- // This is observed in the GCC and Clang implementations.
- // The Itanium specification is not clear enough on this specific case.
- // References:
- // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.name
- // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-compression
- Dsymbol q = getQualifier(ti.tempdecl);
- Dsymbol ns = ti.tempdecl.cppnamespace;
- const inStd = ns && isStd(ns) || q && isStd(q);
- const isNested = !inStd && (ns || q);
+ bool needsTa = false;
- if (substitute(ti.tempdecl, !haveNE && isNested))
- {
+ // https://issues.dlang.org/show_bug.cgi?id=20413
+ // N..E is not needed when substituting members of the std namespace.
+ // This is observed in the GCC and Clang implementations.
+ // The Itanium specification is not clear enough on this specific case.
+ // References:
+ // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.name
+ // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-compression
+ Dsymbol q = getQualifier(ti.tempdecl);
+ Dsymbol ns = ti.tempdecl.cppnamespace;
+ const inStd = ns && isStd(ns) || q && isStd(q);
+ const isNested = !inStd && (ns || q);
+
+ if (substitute(ti.tempdecl, !haveNE && isNested))
+ {
+ template_args(ti);
+ if (!haveNE && isNested)
+ buf.writeByte('E');
+ return;
+ }
+ else if (this.writeStdSubstitution(ti, needsTa))
+ {
+ this.abiTags.writeSymbol(ti, this);
+ if (needsTa)
template_args(ti);
- if (!haveNE && isNested)
- buf.writeByte('E');
- }
- else if (this.writeStdSubstitution(ti, needsTa))
- {
- this.abiTags.writeSymbol(ti, this);
- if (needsTa)
- template_args(ti);
- }
- else
- {
- this.writeNamespace(
- s.cppnamespace, () {
- this.writeIdentifier(ti.tempdecl.toAlias().ident);
- append(ti.tempdecl);
- this.abiTags.writeSymbol(ti.tempdecl, this);
- template_args(ti);
- }, haveNE);
- }
+ return;
+ }
+
+ auto ag = ti.aliasdecl ? ti.aliasdecl.isAggregateDeclaration() : null;
+ if (ag && ag.mangleOverride)
+ {
+ this.writeNamespace(
+ ti.toAlias().cppnamespace, () {
+ this.writeIdentifier(ag.mangleOverride.id);
+ if (ag.mangleOverride.agg && ag.mangleOverride.agg.isInstantiated())
+ {
+ auto to = ag.mangleOverride.agg.isInstantiated();
+ append(to);
+ this.abiTags.writeSymbol(to.tempdecl, this);
+ template_args(to);
+ }
+ }, haveNE);
}
else
- this.writeNamespace(s.cppnamespace, () {
- this.writeIdentifier(s.ident);
- this.abiTags.writeSymbol(s, this);
- },
- haveNE);
+ {
+ this.writeNamespace(
+ s.cppnamespace, () {
+ this.writeIdentifier(ti.tempdecl.toAlias().ident);
+ append(ti.tempdecl);
+ this.abiTags.writeSymbol(ti.tempdecl, this);
+ template_args(ti);
+ }, haveNE);
+ }
}
/********
@@ -850,7 +884,6 @@ private final class CppMangleVisitor : Visitor
return false;
}
-
void cpp_mangle_name(Dsymbol s, bool qualified)
{
//printf("cpp_mangle_name(%s, %d)\n", s.toChars(), qualified);
@@ -864,74 +897,75 @@ private final class CppMangleVisitor : Visitor
write_prefix = false;
p = p.toParent();
}
- if (p && !p.isModule())
+ if (!p || p.isModule())
{
- /* The N..E is not required if:
- * 1. the parent is 'std'
- * 2. 'std' is the initial qualifier
- * 3. there is no CV-qualifier or a ref-qualifier for a member function
- * ABI 5.1.8
- */
- if (isStd(p) && !qualified)
+ source_name(se, false);
+ append(s);
+ return;
+ }
+
+ if (!isStd(p) || qualified)
+ {
+ buf.writeByte('N');
+ if (write_prefix)
{
- TemplateInstance ti = se.isTemplateInstance();
- if (s.ident == Id.allocator)
- {
- buf.writestring("Sa"); // "Sa" is short for ::std::allocator
- template_args(ti);
- }
- else if (s.ident == Id.basic_string)
- {
- // ::std::basic_string<char, ::std::char_traits<char>, ::std::allocator<char>>
- if (ti.tiargs.dim == 3 &&
- isChar((*ti.tiargs)[0]) &&
- isChar_traits_char((*ti.tiargs)[1]) &&
- isAllocator_char((*ti.tiargs)[2]))
- {
- buf.writestring("Ss");
- return;
- }
- buf.writestring("Sb"); // ::std::basic_string
- template_args(ti);
- }
- else
- {
- // ::std::basic_istream<char, ::std::char_traits<char>>
- if (s.ident == Id.basic_istream)
- {
- if (char_std_char_traits_char(ti, "Si"))
- return;
- }
- else if (s.ident == Id.basic_ostream)
- {
- if (char_std_char_traits_char(ti, "So"))
- return;
- }
- else if (s.ident == Id.basic_iostream)
- {
- if (char_std_char_traits_char(ti, "Sd"))
- return;
- }
+ if (isStd(p))
buf.writestring("St");
- source_name(se, true);
- }
+ else
+ prefix_name(p);
}
- else
+ source_name(se, true);
+ buf.writeByte('E');
+ append(s);
+ return;
+ }
+ /* The N..E is not required if:
+ * 1. the parent is 'std'
+ * 2. 'std' is the initial qualifier
+ * 3. there is no CV-qualifier or a ref-qualifier for a member function
+ * ABI 5.1.8
+ */
+ TemplateInstance ti = se.isTemplateInstance();
+ if (s.ident == Id.allocator)
+ {
+ buf.writestring("Sa"); // "Sa" is short for ::std::allocator
+ template_args(ti);
+ }
+ else if (s.ident == Id.basic_string)
+ {
+ // ::std::basic_string<char, ::std::char_traits<char>, ::std::allocator<char>>
+ if (ti.tiargs.dim == 3 &&
+ isChar((*ti.tiargs)[0]) &&
+ isChar_traits_char((*ti.tiargs)[1]) &&
+ isAllocator_char((*ti.tiargs)[2]))
{
- buf.writeByte('N');
- if (write_prefix)
- {
- if (isStd(p))
- buf.writestring("St");
- else
- prefix_name(p);
- }
- source_name(se, true);
- buf.writeByte('E');
+ buf.writestring("Ss");
+ return;
}
+ buf.writestring("Sb"); // ::std::basic_string
+ template_args(ti);
}
else
- source_name(se, false);
+ {
+ // ::std::basic_istream<char, ::std::char_traits<char>>
+ if (s.ident == Id.basic_istream)
+ {
+ if (char_std_char_traits_char(ti, "Si"))
+ return;
+ }
+ else if (s.ident == Id.basic_ostream)
+ {
+ if (char_std_char_traits_char(ti, "So"))
+ return;
+ }
+ else if (s.ident == Id.basic_iostream)
+ {
+ if (char_std_char_traits_char(ti, "Sd"))
+ return;
+ }
+ buf.writestring("St");
+ source_name(se, true);
+ }
append(s);
}
@@ -1003,12 +1037,20 @@ private final class CppMangleVisitor : Visitor
//printf("mangle_function(%s)\n", d.toChars());
/*
* <mangled-name> ::= _Z <encoding>
+ */
+ buf.writestring("_Z");
+ this.mangle_function_encoding(d);
+ }
+
+ void mangle_function_encoding(FuncDeclaration d)
+ {
+ //printf("mangle_function_encoding(%s)\n", d.toChars());
+ /*
* <encoding> ::= <function name> <bare-function-type>
* ::= <data name>
* ::= <special-name>
*/
TypeFunction tf = cast(TypeFunction)d.type;
- buf.writestring("_Z");
if (TemplateDeclaration ftd = getFuncTemplateDecl(d))
{
@@ -1017,45 +1059,44 @@ private final class CppMangleVisitor : Visitor
TemplateInstance ti = d.parent.isTemplateInstance();
assert(ti);
this.mangleTemplatedFunction(d, tf, ftd, ti);
+ return;
+ }
+
+ Dsymbol p = d.toParent();
+ if (p && !p.isModule() && tf.linkage == LINK.cpp)
+ {
+ this.mangleNestedFuncPrefix(tf, p);
+
+ if (auto ctor = d.isCtorDeclaration())
+ buf.writestring(ctor.isCpCtor ? "C2" : "C1");
+ else if (d.isPrimaryDtor())
+ buf.writestring("D1");
+ else if (d.ident && d.ident == Id.assign)
+ buf.writestring("aS");
+ else if (d.ident && d.ident == Id.eq)
+ buf.writestring("eq");
+ else if (d.ident && d.ident == Id.index)
+ buf.writestring("ix");
+ else if (d.ident && d.ident == Id.call)
+ buf.writestring("cl");
+ else
+ source_name(d, true);
+ buf.writeByte('E');
}
else
{
- Dsymbol p = d.toParent();
- if (p && !p.isModule() && tf.linkage == LINK.cpp)
- {
- this.mangleNestedFuncPrefix(tf, p);
-
- if (auto ctor = d.isCtorDeclaration())
- buf.writestring(ctor.isCpCtor ? "C2" : "C1");
- else if (d.isPrimaryDtor())
- buf.writestring("D1");
- else if (d.ident && d.ident == Id.assign)
- buf.writestring("aS");
- else if (d.ident && d.ident == Id.eq)
- buf.writestring("eq");
- else if (d.ident && d.ident == Id.index)
- buf.writestring("ix");
- else if (d.ident && d.ident == Id.call)
- buf.writestring("cl");
- else
- source_name(d, true);
- buf.writeByte('E');
- }
- else
- {
- source_name(d, false);
- }
+ source_name(d, false);
+ }
- // Save offset for potentially writing tags
- const size_t off = this.buf.length();
+ // Save offset for potentially writing tags
+ const size_t off = this.buf.length();
- // Template args accept extern "C" symbols with special mangling
- if (tf.linkage == LINK.cpp)
- mangleFunctionParameters(tf.parameterList);
+ // Template args accept extern "C" symbols with special mangling
+ if (tf.linkage == LINK.cpp)
+ mangleFunctionParameters(tf.parameterList);
- if (!tf.next.isTypeBasic())
- this.writeRemainingTags(off, tf);
- }
+ if (!tf.next.isTypeBasic())
+ this.writeRemainingTags(off, tf);
}
/**
@@ -1073,7 +1114,7 @@ private final class CppMangleVisitor : Visitor
{
void runDg () { if (dg !is null) dg(); }
- if (ns is null)
+ if (ns is null || ns.ident is null)
return runDg();
if (isStd(ns))
@@ -1140,121 +1181,123 @@ private final class CppMangleVisitor : Visitor
if (d.isCtorDeclaration())
{
buf.writestring("C1");
+ mangleFunctionParameters(tf.parameterList);
+ return;
}
else if (d.isPrimaryDtor())
{
buf.writestring("D1");
+ mangleFunctionParameters(tf.parameterList);
+ return;
}
- else
- {
- int firstTemplateArg = 0;
- bool appendReturnType = true;
- bool isConvertFunc = false;
- string symName;
- // test for special symbols
- CppOperator whichOp = isCppOperator(ti.name);
- final switch (whichOp)
+ int firstTemplateArg = 0;
+ bool appendReturnType = true;
+ bool isConvertFunc = false;
+ string symName;
+
+ // test for special symbols
+ CppOperator whichOp = isCppOperator(ti.name);
+ final switch (whichOp)
+ {
+ case CppOperator.Unknown:
+ break;
+ case CppOperator.Cast:
+ symName = "cv";
+ firstTemplateArg = 1;
+ isConvertFunc = true;
+ appendReturnType = false;
+ break;
+ case CppOperator.Assign:
+ symName = "aS";
+ break;
+ case CppOperator.Eq:
+ symName = "eq";
+ break;
+ case CppOperator.Index:
+ symName = "ix";
+ break;
+ case CppOperator.Call:
+ symName = "cl";
+ break;
+ case CppOperator.Unary:
+ case CppOperator.Binary:
+ case CppOperator.OpAssign:
+ TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration();
+ assert(td);
+ assert(ti.tiargs.dim >= 1);
+ TemplateParameter tp = (*td.parameters)[0];
+ TemplateValueParameter tv = tp.isTemplateValueParameter();
+ if (!tv || !tv.valType.isString())
+ break; // expecting a string argument to operators!
+ Expression exp = (*ti.tiargs)[0].isExpression();
+ StringExp str = exp.toStringExp();
+ switch (whichOp)
{
- case CppOperator.Unknown:
- break;
- case CppOperator.Cast:
- symName = "cv";
- firstTemplateArg = 1;
- isConvertFunc = true;
- appendReturnType = false;
- break;
- case CppOperator.Assign:
- symName = "aS";
- break;
- case CppOperator.Eq:
- symName = "eq";
- break;
- case CppOperator.Index:
- symName = "ix";
- break;
- case CppOperator.Call:
- symName = "cl";
- break;
case CppOperator.Unary:
+ switch (str.peekString())
+ {
+ case "*": symName = "de"; goto continue_template;
+ case "++": symName = "pp"; goto continue_template;
+ case "--": symName = "mm"; goto continue_template;
+ case "-": symName = "ng"; goto continue_template;
+ case "+": symName = "ps"; goto continue_template;
+ case "~": symName = "co"; goto continue_template;
+ default: break;
+ }
+ break;
case CppOperator.Binary:
+ switch (str.peekString())
+ {
+ case ">>": symName = "rs"; goto continue_template;
+ case "<<": symName = "ls"; goto continue_template;
+ case "*": symName = "ml"; goto continue_template;
+ case "-": symName = "mi"; goto continue_template;
+ case "+": symName = "pl"; goto continue_template;
+ case "&": symName = "an"; goto continue_template;
+ case "/": symName = "dv"; goto continue_template;
+ case "%": symName = "rm"; goto continue_template;
+ case "^": symName = "eo"; goto continue_template;
+ case "|": symName = "or"; goto continue_template;
+ default: break;
+ }
+ break;
case CppOperator.OpAssign:
- TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration();
- assert(td);
- assert(ti.tiargs.dim >= 1);
- TemplateParameter tp = (*td.parameters)[0];
- TemplateValueParameter tv = tp.isTemplateValueParameter();
- if (!tv || !tv.valType.isString())
- break; // expecting a string argument to operators!
- Expression exp = (*ti.tiargs)[0].isExpression();
- StringExp str = exp.toStringExp();
- switch (whichOp)
+ switch (str.peekString())
{
- case CppOperator.Unary:
- switch (str.peekString())
- {
- case "*": symName = "de"; goto continue_template;
- case "++": symName = "pp"; goto continue_template;
- case "--": symName = "mm"; goto continue_template;
- case "-": symName = "ng"; goto continue_template;
- case "+": symName = "ps"; goto continue_template;
- case "~": symName = "co"; goto continue_template;
- default: break;
- }
- break;
- case CppOperator.Binary:
- switch (str.peekString())
- {
- case ">>": symName = "rs"; goto continue_template;
- case "<<": symName = "ls"; goto continue_template;
- case "*": symName = "ml"; goto continue_template;
- case "-": symName = "mi"; goto continue_template;
- case "+": symName = "pl"; goto continue_template;
- case "&": symName = "an"; goto continue_template;
- case "/": symName = "dv"; goto continue_template;
- case "%": symName = "rm"; goto continue_template;
- case "^": symName = "eo"; goto continue_template;
- case "|": symName = "or"; goto continue_template;
- default: break;
- }
- break;
- case CppOperator.OpAssign:
- switch (str.peekString())
- {
- case "*": symName = "mL"; goto continue_template;
- case "+": symName = "pL"; goto continue_template;
- case "-": symName = "mI"; goto continue_template;
- case "/": symName = "dV"; goto continue_template;
- case "%": symName = "rM"; goto continue_template;
- case ">>": symName = "rS"; goto continue_template;
- case "<<": symName = "lS"; goto continue_template;
- case "&": symName = "aN"; goto continue_template;
- case "|": symName = "oR"; goto continue_template;
- case "^": symName = "eO"; goto continue_template;
- default: break;
- }
- break;
- default:
- assert(0);
- continue_template:
- firstTemplateArg = 1;
- break;
+ case "*": symName = "mL"; goto continue_template;
+ case "+": symName = "pL"; goto continue_template;
+ case "-": symName = "mI"; goto continue_template;
+ case "/": symName = "dV"; goto continue_template;
+ case "%": symName = "rM"; goto continue_template;
+ case ">>": symName = "rS"; goto continue_template;
+ case "<<": symName = "lS"; goto continue_template;
+ case "&": symName = "aN"; goto continue_template;
+ case "|": symName = "oR"; goto continue_template;
+ case "^": symName = "eO"; goto continue_template;
+ default: break;
}
break;
+ default:
+ assert(0);
+ continue_template:
+ firstTemplateArg = 1;
+ break;
}
- if (symName.length == 0)
- source_name(ti, true);
- else
- {
- buf.writestring(symName);
- if (isConvertFunc)
- template_arg(ti, 0);
- appendReturnType = template_args(ti, firstTemplateArg) && appendReturnType;
- }
- buf.writeByte('E');
- if (appendReturnType)
- headOfType(tf.nextOf()); // mangle return type
+ break;
+ }
+ if (symName.length == 0)
+ source_name(ti, true);
+ else
+ {
+ buf.writestring(symName);
+ if (isConvertFunc)
+ template_arg(ti, 0);
+ appendReturnType = template_args(ti, firstTemplateArg) && appendReturnType;
}
+ buf.writeByte('E');
+ if (appendReturnType)
+ headOfType(tf.nextOf()); // mangle return type
mangleFunctionParameters(tf.parameterList);
}
@@ -1291,6 +1334,10 @@ private final class CppMangleVisitor : Visitor
return (*tf.parameterList.parameters)[n].type;
}());
scope (exit) this.context.pop(prev);
+
+ if (this.context.ti && global.params.cplusplus >= CppStdRevision.cpp11)
+ handleParamPack(t, this.context.ti.tempdecl.isTemplateDeclaration().parameters);
+
headOfType(t);
++numparams;
}
@@ -1468,6 +1515,26 @@ private final class CppMangleVisitor : Visitor
prefix_name(parent);
}
+ /**
+ * Write `Dp` (C++11 function parameter pack prefix) if 't' is a TemplateSequenceParameter (T...).
+ *
+ * Params:
+ * t = Parameter type
+ * params = Template parameters of the function
+ */
+ private void handleParamPack(Type t, TemplateParameters* params)
+ {
+ if (t.isTypeReference())
+ t = t.nextOf();
+ auto ti = t.isTypeIdentifier();
+ if (!ti)
+ return;
+
+ auto idx = templateParamIndex(ti.ident, params);
+ if (idx < params.length && (*params)[idx].isTemplateTupleParameter())
+ buf.writestring("Dp");
+ }
+
/**
* Helper function to write a `T..._` template index.
*
@@ -1480,9 +1547,6 @@ private final class CppMangleVisitor : Visitor
// expressions are mangled in <X..E>
if (param.isTemplateValueParameter())
buf.writeByte('X');
- else if (param.isTemplateTupleParameter() &&
- global.params.cplusplus >= CppStdRevision.cpp11)
- buf.writestring("Dp");
buf.writeByte('T');
writeSequenceFromIndex(idx);
buf.writeByte('_');
@@ -1580,6 +1644,14 @@ extern(C++):
writeBasicType(t, 'D', 'n');
}
+ override void visit(TypeNoreturn t)
+ {
+ if (t.isImmutable() || t.isShared())
+ return error(t);
+
+ writeBasicType(t, 0, 'v'); // mangle like `void`
+ }
+
override void visit(TypeBasic t)
{
if (t.isImmutable() || t.isShared())
@@ -1688,15 +1760,11 @@ extern(C++):
else
{
assert(t.basetype && t.basetype.ty == Tsarray);
- assert((cast(TypeSArray)t.basetype).dim);
- version (none)
- {
- buf.writestring("Dv");
- buf.print((cast(TypeSArray *)t.basetype).dim.toInteger()); // -- Gnu ABI v.4
- buf.writeByte('_');
- }
- else
- buf.writestring("U8__vector"); //-- Gnu ABI v.3
+ auto tsa = t.basetype.isTypeSArray();
+ assert(tsa.dim);
+ buf.writestring("Dv"); // -- Gnu ABI v.4
+ buf.print(tsa.dim.toInteger());
+ buf.writeByte('_');
t.basetype.nextOf().accept(this);
}
}
@@ -1796,7 +1864,7 @@ extern(C++):
if (t.isImmutable() || t.isShared())
return error(t);
- /* __c_(u)long(long) get special mangling
+ /* __c_(u)long(long) and others get special mangling
*/
const id = t.sym.ident;
//printf("enum id = '%s'\n", id.toChars());
@@ -1810,6 +1878,12 @@ extern(C++):
return writeBasicType(t, 0, 'x');
else if (id == Id.__c_ulonglong)
return writeBasicType(t, 0, 'y');
+ else if (id == Id.__c_complex_float)
+ return writeBasicType(t, 'C', 'f');
+ else if (id == Id.__c_complex_double)
+ return writeBasicType(t, 'C', 'd');
+ else if (id == Id.__c_complex_real)
+ return writeBasicType(t, 'C', 'e');
doSymbol(t);
}
diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d
index d9f9044f95d..91d1b663fa8 100644
--- a/gcc/d/dmd/ctfeexpr.d
+++ b/gcc/d/dmd/ctfeexpr.d
@@ -1,7 +1,7 @@
/**
* CTFE for expressions involving pointers, slices, array concatenation etc.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ctfeexpr.d, _ctfeexpr.d)
@@ -15,6 +15,7 @@ import core.stdc.stdio;
import core.stdc.stdlib;
import core.stdc.string;
import dmd.arraytypes;
+import dmd.astenums;
import dmd.complex;
import dmd.constfold;
import dmd.compiler;
@@ -179,7 +180,7 @@ extern (C++) final class CTFEExp : Expression
case TOK.cantExpression:
return "<cant>";
case TOK.voidExpression:
- return "<void>";
+ return "cast(void)0";
case TOK.showCtfeContext:
return "<error>";
case TOK.break_:
@@ -453,7 +454,7 @@ private UnionExp paintTypeOntoLiteralCopy(Type type, Expression lit)
return ue;
}
// If it is a cast to inout, retain the original type of the referenced part.
- if (type.hasWild() && type.hasPointers())
+ if (type.hasWild())
{
emplaceExp!(UnionExp)(&ue, lit);
ue.exp().type = type;
@@ -686,7 +687,7 @@ bool isSafePointerCast(Type srcPointee, Type destPointee)
return true;
// It's OK if function pointers differ only in safe/pure/nothrow
if (srcPointee.ty == Tfunction && destPointee.ty == Tfunction)
- return srcPointee.covariant(destPointee) == 1;
+ return srcPointee.covariant(destPointee) == 1 || destPointee.covariant(srcPointee) == 1;
// it's OK to cast to void*
if (destPointee.ty == Tvoid)
return true;
@@ -1510,7 +1511,7 @@ UnionExp ctfeCat(const ref Loc loc, Type type, Expression e1, Expression e2)
ue = paintTypeOntoLiteralCopy(type, copyLiteral(e2).copy());
return ue;
}
- ue = Cat(type, e1, e2);
+ ue = Cat(loc, type, e1, e2);
return ue;
}
diff --git a/gcc/d/dmd/ctorflow.d b/gcc/d/dmd/ctorflow.d
index 10024fa8385..c8b61be44a5 100644
--- a/gcc/d/dmd/ctorflow.d
+++ b/gcc/d/dmd/ctorflow.d
@@ -1,7 +1,7 @@
/**
* Manage flow analysis for constructors.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ctorflow.d, _ctorflow.d)
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index df4120cd7bd..cd360e93cad 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -1,7 +1,7 @@
/**
* Semantic analysis for cast-expressions.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dcast.d, _dcast.d)
@@ -17,6 +17,7 @@ import dmd.aggregate;
import dmd.aliasthis;
import dmd.arrayop;
import dmd.arraytypes;
+import dmd.astenums;
import dmd.dclass;
import dmd.declaration;
import dmd.dscope;
@@ -44,9 +45,20 @@ import dmd.visitor;
enum LOG = false;
-/**************************************
- * Do an implicit cast.
- * Issue error if it can't be done.
+/**
+ * Attempt to implicitly cast the expression into type `t`.
+ *
+ * This routine will change `e`. To check the matching level,
+ * use `implicitConvTo`.
+ *
+ * Params:
+ * e = Expression that is to be casted
+ * sc = Current scope
+ * t = Expected resulting type
+ *
+ * Returns:
+ * The resulting casted expression (mutating `e`), or `ErrorExp`
+ * if such an implicit conversion is not possible.
*/
Expression implicitCastTo(Expression e, Scope* sc, Type t)
{
@@ -68,7 +80,7 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t)
{
//printf("Expression.implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars());
- if (const match = e.implicitConvTo(t))
+ if (const match = (sc && sc.flags & SCOPE.Cfile) ? e.cimplicitConvTo(t) : e.implicitConvTo(t))
{
if (match == MATCH.constant && (e.type.constConv(t) || !e.isLvalue() && e.type.equivalent(t)))
{
@@ -206,9 +218,19 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t)
return v.result;
}
-/*******************************************
- * Return MATCH level of implicitly converting e to type t.
- * Don't do the actual cast; don't change e.
+/**
+ * Checks whether or not an expression can be implicitly converted
+ * to type `t`.
+ *
+ * Unlike `implicitCastTo`, this routine does not perform the actual cast,
+ * but only checks up to what `MATCH` level the conversion would be possible.
+ *
+ * Params:
+ * e = Expression that is to be casted
+ * t = Expected resulting type
+ *
+ * Returns:
+ * The `MATCH` level between `e.type` and `t`.
*/
MATCH implicitConvTo(Expression e, Type t)
{
@@ -834,7 +856,7 @@ MATCH implicitConvTo(Expression e, Type t)
* convert to immutable
*/
if (e.f && e.f.isReturnIsolated() &&
- (!global.params.vsafe || // lots of legacy code breaks with the following purity check
+ (global.params.useDIP1000 != FeatureState.enabled || // lots of legacy code breaks with the following purity check
e.f.isPure() >= PURE.strong ||
// Special case exemption for Object.dup() which we assume is implemented correctly
e.f.ident == Id.dup &&
@@ -1311,7 +1333,7 @@ MATCH implicitConvTo(Expression e, Type t)
struct ClassCheck
{
- extern (C++) static bool convertible(Loc loc, ClassDeclaration cd, MOD mod)
+ extern (C++) static bool convertible(Expression e, ClassDeclaration cd, MOD mod)
{
for (size_t i = 0; i < cd.fields.dim; i++)
{
@@ -1324,6 +1346,11 @@ MATCH implicitConvTo(Expression e, Type t)
}
else if (ExpInitializer ei = _init.isExpInitializer())
{
+ // https://issues.dlang.org/show_bug.cgi?id=21319
+ // This is to prevent re-analyzing the same expression
+ // over and over again.
+ if (ei.exp == e)
+ return false;
Type tb = v.type.toBasetype();
if (implicitMod(ei.exp, tb, mod) == MATCH.nomatch)
return false;
@@ -1335,14 +1362,14 @@ MATCH implicitConvTo(Expression e, Type t)
return false;
}
}
- else if (!v.type.isZeroInit(loc))
+ else if (!v.type.isZeroInit(e.loc))
return false;
}
- return cd.baseClass ? convertible(loc, cd.baseClass, mod) : true;
+ return cd.baseClass ? convertible(e, cd.baseClass, mod) : true;
}
}
- if (!ClassCheck.convertible(e.loc, cd, mod))
+ if (!ClassCheck.convertible(e, cd, mod))
return;
}
}
@@ -1374,7 +1401,13 @@ MATCH implicitConvTo(Expression e, Type t)
{
typeb = toStaticArrayType(e);
if (typeb)
+ {
+ // Try: T[] -> T[dim]
+ // (Slice with compile-time known boundaries to static array)
result = typeb.implicitConvTo(t);
+ if (result > MATCH.convert)
+ result = MATCH.convert; // match with implicit conversion at most
+ }
return;
}
@@ -1423,6 +1456,42 @@ MATCH implicitConvTo(Expression e, Type t)
return v.result;
}
+/**
+ * Same as implicitConvTo(); except follow C11 rules, which are quite a bit
+ * more permissive than D.
+ * C11 6.3 and 6.5.16.1
+ * Params:
+ * e = Expression that is to be casted
+ * t = Expected resulting type
+ * Returns:
+ * The `MATCH` level between `e.type` and `t`.
+ */
+MATCH cimplicitConvTo(Expression e, Type t)
+{
+ Type tb = t.toBasetype();
+ Type typeb = e.type.toBasetype();
+
+ if (tb.equals(typeb))
+ return MATCH.exact;
+ if ((typeb.isintegral() || typeb.isfloating()) &&
+ (tb.isintegral() || tb.isfloating()))
+ return MATCH.convert;
+ if (tb.ty == Tpointer && typeb.isintegral()) // C11 6.3.2.3-5
+ return MATCH.convert;
+ if (tb.isintegral() && typeb.ty == Tpointer) // C11 6.3.2.3-6
+ return MATCH.convert;
+ if (tb.ty == Tpointer && typeb.ty == Tpointer)
+ {
+ if (tb.isTypePointer().next.ty == Tvoid ||
+ typeb.isTypePointer().next.ty == Tvoid)
+ return MATCH.convert; // convert to/from void* C11 6.3.2.3-1
+ }
+
+ return implicitConvTo(e, t);
+}
+
+/*****************************************
+ */
Type toStaticArrayType(SliceExp e)
{
if (e.lwr && e.upr)
@@ -1446,32 +1515,12 @@ Type toStaticArrayType(SliceExp e)
return null;
}
-// Try casting the alias this member. Return the expression if it succeeds, null otherwise.
-private Expression tryAliasThisCast(Expression e, Scope* sc, Type tob, Type t1b, Type t)
-{
- Expression result;
- AggregateDeclaration t1ad = isAggregate(t1b);
- if (!t1ad)
- return null;
-
- AggregateDeclaration toad = isAggregate(tob);
- if (t1ad == toad || !t1ad.aliasthis)
- return null;
-
- /* Forward the cast to our alias this member, rewrite to:
- * cast(to)e1.aliasthis
- */
- result = resolveAliasThis(sc, e);
- const errors = global.startGagging();
- result = result.castTo(sc, t);
- return global.endGagging(errors) ? null : result;
-}
-
/**************************************
* Do an explicit cast.
- * Assume that the 'this' expression does not have any indirections.
+ * Assume that the expression `e` does not have any indirections.
+ * (Parameter 'att' is used to stop 'alias this' recursion)
*/
-Expression castTo(Expression e, Scope* sc, Type t)
+Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
{
extern (C++) final class CastTo : Visitor
{
@@ -1547,6 +1596,22 @@ Expression castTo(Expression e, Scope* sc, Type t)
const(bool) tob_isA = ((tob.isintegral() || tob.isfloating()) && tob.ty != Tvector);
const(bool) t1b_isA = ((t1b.isintegral() || t1b.isfloating()) && t1b.ty != Tvector);
+ // Try casting the alias this member.
+ // Return the expression if it succeeds, null otherwise.
+ Expression tryAliasThisCast()
+ {
+ if (isRecursiveAliasThis(att, t1b))
+ return null;
+
+ /* Forward the cast to our alias this member, rewrite to:
+ * cast(to)e1.aliasthis
+ */
+ auto exp = resolveAliasThis(sc, e);
+ const errors = global.startGagging();
+ exp = castTo(exp, sc, t, att);
+ return global.endGagging(errors) ? null : exp;
+ }
+
bool hasAliasThis;
if (AggregateDeclaration t1ad = isAggregate(t1b))
{
@@ -1608,7 +1673,7 @@ Expression castTo(Expression e, Scope* sc, Type t)
{
if (hasAliasThis)
{
- result = tryAliasThisCast(e, sc, tob, t1b, t);
+ result = tryAliasThisCast();
if (result)
return;
}
@@ -1698,7 +1763,7 @@ Expression castTo(Expression e, Scope* sc, Type t)
*/
if (hasAliasThis)
{
- result = tryAliasThisCast(e, sc, tob, t1b, t);
+ result = tryAliasThisCast();
if (result)
return;
}
@@ -2069,9 +2134,9 @@ Expression castTo(Expression e, Scope* sc, Type t)
{
f.tookAddressOf++;
auto se = new SymOffExp(e.loc, f, 0, false);
- se.expressionSemantic(sc);
+ auto se2 = se.expressionSemantic(sc);
// Let SymOffExp::castTo() do the heavy lifting
- visit(se);
+ visit(se2);
return;
}
}
@@ -2149,7 +2214,7 @@ Expression castTo(Expression e, Scope* sc, Type t)
ArrayLiteralExp ae = e;
Type tb = t.toBasetype();
- if (tb.ty == Tarray && global.params.vsafe)
+ if (tb.ty == Tarray && global.params.useDIP1000 == FeatureState.enabled)
{
if (checkArrayLiteralEscape(sc, ae, false))
{
@@ -2537,6 +2602,23 @@ Expression castTo(Expression e, Scope* sc, Type t)
}
}
+ // Casting to noreturn isn't an actual cast
+ // Rewrite cast(<qual> noreturn) <exp>
+ // as <exp>, assert(false)
+ if (t.isTypeNoreturn())
+ {
+ // Don't generate an unreachable assert(false) if e will abort
+ if (e.type.isTypeNoreturn())
+ {
+ // Paint e to accomodate for different type qualifiers
+ e.type = t;
+ return e;
+ }
+
+ auto ini = t.defaultInitLiteral(e.loc);
+ return Expression.combine(e, ini);
+ }
+
scope CastTo v = new CastTo(sc, t);
e.accept(v);
return v.result;
@@ -2711,38 +2793,32 @@ private bool isVoidArrayLiteral(Expression e, Type other)
return (e.op == TOK.arrayLiteral && t.ty == Tarray && t.nextOf().ty == Tvoid && (cast(ArrayLiteralExp)e).elements.dim == 0);
}
-/**************************************
- * Combine types.
- * Output:
- * *pt merged type, if *pt is not NULL
- * *pe1 rewritten e1
- * *pe2 rewritten e2
+/**
+ * Merge types of `e1` and `e2` into a common subset
+ *
+ * Parameters `e1` and `e2` will be rewritten in place as needed.
+ *
+ * Params:
+ * sc = Current scope
+ * op = Operator such as `e1 op e2`. In practice, either TOK.question
+ * or one of the binary operator.
+ * pe1 = The LHS of the operation, will be rewritten
+ * pe2 = The RHS of the operation, will be rewritten
+ *
* Returns:
- * true success
- * false failed
+ * The resulting type in case of success, `null` in case of error
*/
-bool typeMerge(Scope* sc, TOK op, Type* pt, Expression* pe1, Expression* pe2)
+Type typeMerge(Scope* sc, TOK op, ref Expression pe1, ref Expression pe2)
{
- //printf("typeMerge() %s op %s\n", pe1.toChars(), pe2.toChars());
+ //printf("typeMerge() %s op %s\n", e1.toChars(), e2.toChars());
- MATCH m;
- Expression e1 = *pe1;
- Expression e2 = *pe2;
+ Expression e1 = pe1;
+ Expression e2 = pe2;
- Type t1 = e1.type;
- Type t2 = e2.type;
-
- Type t1b = e1.type.toBasetype();
- Type t2b = e2.type.toBasetype();
-
- Type t;
-
- bool Lret()
+ Type Lret(Type result)
{
- if (!*pt)
- *pt = t;
- *pe1 = e1;
- *pe2 = e2;
+ pe1 = e1;
+ pe2 = e2;
version (none)
{
@@ -2751,26 +2827,28 @@ bool typeMerge(Scope* sc, TOK op, Type* pt, Expression* pe1, Expression* pe2)
printf("\tt1 = %s\n", e1.type.toChars());
if (e2.type)
printf("\tt2 = %s\n", e2.type.toChars());
- printf("\ttype = %s\n", t.toChars());
+ printf("\ttype = %s\n", result.toChars());
}
- return true;
+ return result;
}
- bool Lt1()
+ /// Converts one of the expression too the other
+ Type convert(ref Expression from, Type to)
{
- e2 = e2.castTo(sc, t1);
- t = t1;
- return Lret();
+ from = from.castTo(sc, to);
+ return Lret(to);
}
- bool Lt2()
+ /// Converts both expression to a third type
+ Type coerce(Type towards)
{
- e1 = e1.castTo(sc, t2);
- t = t2;
- return Lret();
+ e1 = e1.castTo(sc, towards);
+ e2 = e2.castTo(sc, towards);
+ return Lret(towards);
}
- bool Lincompatible() { return false; }
+ Type t1b = e1.type.toBasetype();
+ Type t2b = e2.type.toBasetype();
if (op != TOK.question || t1b.ty != t2b.ty && (t1b.isTypeBasic() && t2b.isTypeBasic()))
{
@@ -2786,10 +2864,11 @@ bool typeMerge(Scope* sc, TOK op, Type* pt, Expression* pe1, Expression* pe2)
}
}
- t1 = e1.type;
- t2 = e2.type;
+ MATCH m;
+ Type t1 = e1.type;
+ Type t2 = e2.type;
assert(t1);
- t = t1;
+ Type t = t1;
/* The start type of alias this type recursion.
* In following case, we should save A, and stop recursion
@@ -2799,15 +2878,6 @@ bool typeMerge(Scope* sc, TOK op, Type* pt, Expression* pe1, Expression* pe2)
Type att1 = null;
Type att2 = null;
- //if (t1) printf("\tt1 = %s\n", t1.toChars());
- //if (t2) printf("\tt2 = %s\n", t2.toChars());
- debug
- {
- if (!t2)
- printf("\te2 = '%s'\n", e2.toChars());
- }
- assert(t2);
-
if (t1.mod != t2.mod &&
t1.ty == Tenum && t2.ty == Tenum &&
(cast(TypeEnum)t1).sym == (cast(TypeEnum)t2).sym)
@@ -2821,78 +2891,71 @@ Lagain:
t1b = t1.toBasetype();
t2b = t2.toBasetype();
- TY ty = cast(TY)impcnvResult[t1b.ty][t2b.ty];
+ const ty = implicitConvCommonTy(t1b.ty, t2b.ty);
if (ty != Terror)
{
- TY ty1 = cast(TY)impcnvType1[t1b.ty][t2b.ty];
- TY ty2 = cast(TY)impcnvType2[t1b.ty][t2b.ty];
+ const ty1 = implicitConvTy1(t1b.ty, t2b.ty);
+ const ty2 = implicitConvTy1(t2b.ty, t1b.ty);
if (t1b.ty == ty1) // if no promotions
{
if (t1.equals(t2))
- {
- t = t1;
- return Lret();
- }
+ return Lret(t1);
if (t1b.equals(t2b))
- {
- t = t1b;
- return Lret();
- }
+ return Lret(t1b);
}
- t = Type.basic[ty];
-
t1 = Type.basic[ty1];
t2 = Type.basic[ty2];
e1 = e1.castTo(sc, t1);
e2 = e2.castTo(sc, t2);
- return Lret();
+ return Lret(Type.basic[ty]);
}
t1 = t1b;
t2 = t2b;
if (t1.ty == Ttuple || t2.ty == Ttuple)
- return Lincompatible();
+ return null;
if (t1.equals(t2))
{
// merging can not result in new enum type
if (t.ty == Tenum)
- t = t1b;
+ return Lret(t1b);
+ return Lret(t);
}
- else if ((t1.ty == Tpointer && t2.ty == Tpointer) || (t1.ty == Tdelegate && t2.ty == Tdelegate))
+
+ if ((t1.ty == Tpointer && t2.ty == Tpointer) || (t1.ty == Tdelegate && t2.ty == Tdelegate))
{
// Bring pointers to compatible type
Type t1n = t1.nextOf();
Type t2n = t2.nextOf();
if (t1n.equals(t2n))
- {
- }
- else if (t1n.ty == Tvoid) // pointers to void are always compatible
- t = t2;
- else if (t2n.ty == Tvoid)
- {
- }
- else if (t1.implicitConvTo(t2))
- {
- return Lt2();
- }
- else if (t2.implicitConvTo(t1))
- {
- return Lt1();
- }
- else if (t1n.ty == Tfunction && t2n.ty == Tfunction)
+ return Lret(t);
+
+ if (t1n.ty == Tvoid) // pointers to void are always compatible
+ return Lret(t2);
+
+ if (t2n.ty == Tvoid)
+ return Lret(t);
+
+ if (t1.implicitConvTo(t2))
+ return convert(e1, t2);
+
+ if (t2.implicitConvTo(t1))
+ return convert(e2, t1);
+
+ if (t1n.ty == Tfunction && t2n.ty == Tfunction)
{
TypeFunction tf1 = cast(TypeFunction)t1n;
TypeFunction tf2 = cast(TypeFunction)t2n;
tf1.purityLevel();
tf2.purityLevel();
- TypeFunction d = cast(TypeFunction)tf1.syntaxCopy();
+ TypeFunction d = tf1.syntaxCopy();
if (tf1.purity != tf2.purity)
d.purity = PURE.impure;
@@ -2908,36 +2971,26 @@ Lagain:
else
d.trust = TRUST.trusted;
- Type tx = null;
- if (t1.ty == Tdelegate)
- {
- tx = new TypeDelegate(d);
- }
- else
- tx = d.pointerTo();
-
+ Type tx = (t1.ty == Tdelegate) ? new TypeDelegate(d) : d.pointerTo();
tx = tx.typeSemantic(e1.loc, sc);
if (t1.implicitConvTo(tx) && t2.implicitConvTo(tx))
- {
- t = tx;
- e1 = e1.castTo(sc, t);
- e2 = e2.castTo(sc, t);
- return Lret();
- }
- return Lincompatible();
+ return coerce(tx);
+ return null;
}
- else if (t1n.mod != t2n.mod)
+
+ if (t1n.mod != t2n.mod)
{
if (!t1n.isImmutable() && !t2n.isImmutable() && t1n.isShared() != t2n.isShared())
- return Lincompatible();
+ return null;
ubyte mod = MODmerge(t1n.mod, t2n.mod);
t1 = t1n.castMod(mod).pointerTo();
t2 = t2n.castMod(mod).pointerTo();
t = t1;
goto Lagain;
}
- else if (t1n.ty == Tclass && t2n.ty == Tclass)
+
+ if (t1n.ty == Tclass && t2n.ty == Tclass)
{
ClassDeclaration cd1 = t1n.isClassHandle();
ClassDeclaration cd2 = t2n.isClassHandle();
@@ -2946,32 +2999,29 @@ Lagain:
{
if (offset)
e2 = e2.castTo(sc, t);
+ return Lret(t);
}
- else if (cd2.isBaseOf(cd1, &offset))
+
+ if (cd2.isBaseOf(cd1, &offset))
{
- t = t2;
if (offset)
- e1 = e1.castTo(sc, t);
- }
- else
- return Lincompatible();
- }
- else
- {
- t1 = t1n.constOf().pointerTo();
- t2 = t2n.constOf().pointerTo();
- if (t1.implicitConvTo(t2))
- {
- return Lt2();
- }
- else if (t2.implicitConvTo(t1))
- {
- return Lt1();
+ e1 = e1.castTo(sc, t2);
+ return Lret(t2);
}
- return Lincompatible();
+
+ return null;
}
+
+ t1 = t1n.constOf().pointerTo();
+ t2 = t2n.constOf().pointerTo();
+ if (t1.implicitConvTo(t2))
+ return convert(e1, t2);
+ if (t2.implicitConvTo(t1))
+ return convert(e2, t1);
+ return null;
}
- else if ((t1.ty == Tsarray || t1.ty == Tarray) && (e2.op == TOK.null_ && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == TOK.arrayLiteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && (cast(TypeSArray)t2).dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1)))
+
+ if ((t1.ty == Tsarray || t1.ty == Tarray) && (e2.op == TOK.null_ && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == TOK.arrayLiteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && (cast(TypeSArray)t2).dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1)))
{
/* (T[n] op void*) => T[]
* (T[] op void*) => T[]
@@ -2980,9 +3030,10 @@ Lagain:
* (T[n] op void[]) => T[]
* (T[] op void[]) => T[]
*/
- goto Lx1;
+ return coerce(t1.nextOf().arrayOf());
}
- else if ((t2.ty == Tsarray || t2.ty == Tarray) && (e1.op == TOK.null_ && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == TOK.arrayLiteral && t1.ty == Tsarray && t1.nextOf().ty == Tvoid && (cast(TypeSArray)t1).dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2)))
+
+ if ((t2.ty == Tsarray || t2.ty == Tarray) && (e1.op == TOK.null_ && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == TOK.arrayLiteral && t1.ty == Tsarray && t1.nextOf().ty == Tvoid && (cast(TypeSArray)t1).dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2)))
{
/* (void* op T[n]) => T[]
* (void* op T[]) => T[]
@@ -2991,35 +3042,37 @@ Lagain:
* (void[] op T[n]) => T[]
* (void[] op T[]) => T[]
*/
- goto Lx2;
+ return coerce(t2.nextOf().arrayOf());
}
- else if ((t1.ty == Tsarray || t1.ty == Tarray) && (m = t1.implicitConvTo(t2)) != MATCH.nomatch)
+
+ if ((t1.ty == Tsarray || t1.ty == Tarray) && (m = t1.implicitConvTo(t2)) != MATCH.nomatch)
{
// https://issues.dlang.org/show_bug.cgi?id=7285
// Tsarray op [x, y, ...] should to be Tsarray
// https://issues.dlang.org/show_bug.cgi?id=14737
// Tsarray ~ [x, y, ...] should to be Tarray
if (t1.ty == Tsarray && e2.op == TOK.arrayLiteral && op != TOK.concatenate)
- return Lt1();
+ return convert(e2, t1);
if (m == MATCH.constant && (op == TOK.addAssign || op == TOK.minAssign || op == TOK.mulAssign || op == TOK.divAssign || op == TOK.modAssign || op == TOK.powAssign || op == TOK.andAssign || op == TOK.orAssign || op == TOK.xorAssign))
{
// Don't make the lvalue const
- t = t2;
- return Lret();
+ return Lret(t2);
}
- return Lt2();
+ return convert(e1, t2);
}
- else if ((t2.ty == Tsarray || t2.ty == Tarray) && t2.implicitConvTo(t1))
+
+ if ((t2.ty == Tsarray || t2.ty == Tarray) && t2.implicitConvTo(t1))
{
// https://issues.dlang.org/show_bug.cgi?id=7285
// https://issues.dlang.org/show_bug.cgi?id=14737
if (t2.ty == Tsarray && e1.op == TOK.arrayLiteral && op != TOK.concatenate)
- return Lt2();
- return Lt1();
+ return convert(e1, t2);
+ return convert(e2, t1);
}
- else if ((t1.ty == Tsarray || t1.ty == Tarray || t1.ty == Tpointer) && (t2.ty == Tsarray || t2.ty == Tarray || t2.ty == Tpointer) && t1.nextOf().mod != t2.nextOf().mod)
+
+ if ((t1.ty == Tsarray || t1.ty == Tarray || t1.ty == Tpointer) && (t2.ty == Tsarray || t2.ty == Tarray || t2.ty == Tpointer) && t1.nextOf().mod != t2.nextOf().mod)
{
- /* If one is mutable and the other invariant, then retry
+ /* If one is mutable and the other immutable, then retry
* with both of them as const
*/
Type t1n = t1.nextOf();
@@ -3030,7 +3083,7 @@ Lagain:
else if (e1.op != TOK.null_ && e2.op == TOK.null_)
mod = t1n.mod;
else if (!t1n.isImmutable() && !t2n.isImmutable() && t1n.isShared() != t2n.isShared())
- return Lincompatible();
+ return null;
else
mod = MODmerge(t1n.mod, t2n.mod);
@@ -3046,7 +3099,8 @@ Lagain:
t = t1;
goto Lagain;
}
- else if (t1.ty == Tclass && t2.ty == Tclass)
+
+ if (t1.ty == Tclass && t2.ty == Tclass)
{
if (t1.mod != t2.mod)
{
@@ -3056,7 +3110,7 @@ Lagain:
else if (e1.op != TOK.null_ && e2.op == TOK.null_)
mod = t1.mod;
else if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
- return Lincompatible();
+ return null;
else
mod = MODmerge(t1.mod, t2.mod);
t1 = t1.castMod(mod);
@@ -3066,7 +3120,8 @@ Lagain:
}
goto Lcc;
}
- else if (t1.ty == Tclass || t2.ty == Tclass)
+
+ if (t1.ty == Tclass || t2.ty == Tclass)
{
Lcc:
while (1)
@@ -3084,16 +3139,11 @@ Lagain:
}
if (i2)
- {
- e2 = e2.castTo(sc, t2);
- return Lt2();
- }
- else if (i1)
- {
- e1 = e1.castTo(sc, t1);
- return Lt1();
- }
- else if (t1.ty == Tclass && t2.ty == Tclass)
+ return coerce(t2);
+ if (i1)
+ return coerce(t1);
+
+ if (t1.ty == Tclass && t2.ty == Tclass)
{
TypeClass tc1 = cast(TypeClass)t1;
TypeClass tc2 = cast(TypeClass)t2;
@@ -3112,14 +3162,12 @@ Lagain:
else if (cd2)
t2 = cd2.type;
else
- return Lincompatible();
+ return null;
}
else if (t1.ty == Tstruct && (cast(TypeStruct)t1).sym.aliasthis)
{
- if (att1 && e1.type == att1)
- return Lincompatible();
- if (!att1 && e1.type.checkAliasThisRec())
- att1 = e1.type;
+ if (isRecursiveAliasThis(att1, e1.type))
+ return null;
//printf("att tmerge(c || c) e1 = %s\n", e1.type.toChars());
e1 = resolveAliasThis(sc, e1);
t1 = e1.type;
@@ -3127,25 +3175,24 @@ Lagain:
}
else if (t2.ty == Tstruct && (cast(TypeStruct)t2).sym.aliasthis)
{
- if (att2 && e2.type == att2)
- return Lincompatible();
- if (!att2 && e2.type.checkAliasThisRec())
- att2 = e2.type;
+ if (isRecursiveAliasThis(att2, e2.type))
+ return null;
//printf("att tmerge(c || c) e2 = %s\n", e2.type.toChars());
e2 = resolveAliasThis(sc, e2);
t2 = e2.type;
continue;
}
else
- return Lincompatible();
+ return null;
}
}
- else if (t1.ty == Tstruct && t2.ty == Tstruct)
+
+ if (t1.ty == Tstruct && t2.ty == Tstruct)
{
if (t1.mod != t2.mod)
{
if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
- return Lincompatible();
+ return null;
ubyte mod = MODmerge(t1.mod, t2.mod);
t1 = t1.castMod(mod);
t2 = t2.castMod(mod);
@@ -3158,7 +3205,7 @@ Lagain:
if (ts1.sym != ts2.sym)
{
if (!ts1.sym.aliasthis && !ts2.sym.aliasthis)
- return Lincompatible();
+ return null;
MATCH i1 = MATCH.nomatch;
MATCH i2 = MATCH.nomatch;
@@ -3167,31 +3214,27 @@ Lagain:
Expression e2b = null;
if (ts2.sym.aliasthis)
{
- if (att2 && e2.type == att2)
- return Lincompatible();
- if (!att2 && e2.type.checkAliasThisRec())
- att2 = e2.type;
+ if (isRecursiveAliasThis(att2, e2.type))
+ return null;
//printf("att tmerge(s && s) e2 = %s\n", e2.type.toChars());
e2b = resolveAliasThis(sc, e2);
i1 = e2b.implicitConvTo(t1);
}
if (ts1.sym.aliasthis)
{
- if (att1 && e1.type == att1)
- return Lincompatible();
- if (!att1 && e1.type.checkAliasThisRec())
- att1 = e1.type;
+ if (isRecursiveAliasThis(att1, e1.type))
+ return null;
//printf("att tmerge(s && s) e1 = %s\n", e1.type.toChars());
e1b = resolveAliasThis(sc, e1);
i2 = e1b.implicitConvTo(t2);
}
if (i1 && i2)
- return Lincompatible();
+ return null;
if (i1)
- return Lt1();
- else if (i2)
- return Lt2();
+ return convert(e2, t1);
+ if (i2)
+ return convert(e1, t2);
if (e1b)
{
@@ -3207,14 +3250,13 @@ Lagain:
goto Lagain;
}
}
- else if (t1.ty == Tstruct || t2.ty == Tstruct)
+
+ if (t1.ty == Tstruct || t2.ty == Tstruct)
{
if (t1.ty == Tstruct && (cast(TypeStruct)t1).sym.aliasthis)
{
- if (att1 && e1.type == att1)
- return Lincompatible();
- if (!att1 && e1.type.checkAliasThisRec())
- att1 = e1.type;
+ if (isRecursiveAliasThis(att1, e1.type))
+ return null;
//printf("att tmerge(s || s) e1 = %s\n", e1.type.toChars());
e1 = resolveAliasThis(sc, e1);
t1 = e1.type;
@@ -3223,41 +3265,27 @@ Lagain:
}
if (t2.ty == Tstruct && (cast(TypeStruct)t2).sym.aliasthis)
{
- if (att2 && e2.type == att2)
- return Lincompatible();
- if (!att2 && e2.type.checkAliasThisRec())
- att2 = e2.type;
+ if (isRecursiveAliasThis(att2, e2.type))
+ return null;
//printf("att tmerge(s || s) e2 = %s\n", e2.type.toChars());
e2 = resolveAliasThis(sc, e2);
t2 = e2.type;
t = t2;
goto Lagain;
}
- return Lincompatible();
- }
- else if ((e1.op == TOK.string_ || e1.op == TOK.null_) && e1.implicitConvTo(t2))
- {
- return Lt2();
- }
- else if ((e2.op == TOK.string_ || e2.op == TOK.null_) && e2.implicitConvTo(t1))
- {
- return Lt1();
- }
- else if (t1.ty == Tsarray && t2.ty == Tsarray && e2.implicitConvTo(t1.nextOf().arrayOf()))
- {
- Lx1:
- t = t1.nextOf().arrayOf(); // T[]
- e1 = e1.castTo(sc, t);
- e2 = e2.castTo(sc, t);
- }
- else if (t1.ty == Tsarray && t2.ty == Tsarray && e1.implicitConvTo(t2.nextOf().arrayOf()))
- {
- Lx2:
- t = t2.nextOf().arrayOf();
- e1 = e1.castTo(sc, t);
- e2 = e2.castTo(sc, t);
+ return null;
}
- else if (t1.ty == Tvector && t2.ty == Tvector)
+
+ if ((e1.op == TOK.string_ || e1.op == TOK.null_) && e1.implicitConvTo(t2))
+ return convert(e1, t2);
+ if ((e2.op == TOK.string_ || e2.op == TOK.null_) && e2.implicitConvTo(t1))
+ return convert(e2, t1);
+ if (t1.ty == Tsarray && t2.ty == Tsarray && e2.implicitConvTo(t1.nextOf().arrayOf()))
+ return coerce(t1.nextOf().arrayOf());
+ if (t1.ty == Tsarray && t2.ty == Tsarray && e1.implicitConvTo(t2.nextOf().arrayOf()))
+ return coerce(t2.nextOf().arrayOf());
+
+ if (t1.ty == Tvector && t2.ty == Tvector)
{
// https://issues.dlang.org/show_bug.cgi?id=13841
// all vector types should have no common types between
@@ -3265,30 +3293,33 @@ Lagain:
auto tv1 = cast(TypeVector)t1;
auto tv2 = cast(TypeVector)t2;
if (!tv1.basetype.equals(tv2.basetype))
- return Lincompatible();
+ return null;
goto LmodCompare;
}
- else if (t1.ty == Tvector && t2.ty != Tvector && e2.implicitConvTo(t1))
+
+ if (t1.ty == Tvector && t2.ty != Tvector && e2.implicitConvTo(t1))
{
e2 = e2.castTo(sc, t1);
t2 = t1;
t = t1;
goto Lagain;
}
- else if (t2.ty == Tvector && t1.ty != Tvector && e1.implicitConvTo(t2))
+
+ if (t2.ty == Tvector && t1.ty != Tvector && e1.implicitConvTo(t2))
{
e1 = e1.castTo(sc, t2);
t1 = t2;
t = t1;
goto Lagain;
}
- else if (t1.isintegral() && t2.isintegral())
+
+ if (t1.isintegral() && t2.isintegral())
{
if (t1.ty != t2.ty)
{
if (t1.ty == Tvector || t2.ty == Tvector)
- return Lincompatible();
+ return null;
e1 = integralPromotions(e1, sc);
e2 = integralPromotions(e2, sc);
t1 = e1.type;
@@ -3298,7 +3329,7 @@ Lagain:
assert(t1.ty == t2.ty);
LmodCompare:
if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
- return Lincompatible();
+ return null;
ubyte mod = MODmerge(t1.mod, t2.mod);
t1 = t1.castMod(mod);
@@ -3308,39 +3339,34 @@ LmodCompare:
e2 = e2.castTo(sc, t);
goto Lagain;
}
- else if (t1.ty == Tnull && t2.ty == Tnull)
- {
- ubyte mod = MODmerge(t1.mod, t2.mod);
- t = t1.castMod(mod);
- e1 = e1.castTo(sc, t);
- e2 = e2.castTo(sc, t);
- return Lret();
- }
- else if (t2.ty == Tnull && (t1.ty == Tpointer || t1.ty == Taarray || t1.ty == Tarray))
+ if (t1.ty == Tnull && t2.ty == Tnull)
{
- return Lt1();
- }
- else if (t1.ty == Tnull && (t2.ty == Tpointer || t2.ty == Taarray || t2.ty == Tarray))
- {
- return Lt2();
+ ubyte mod = MODmerge(t1.mod, t2.mod);
+ return coerce(t1.castMod(mod));
}
- else if (t1.ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e1))
+
+ if (t2.ty == Tnull && (t1.ty == Tpointer || t1.ty == Taarray || t1.ty == Tarray))
+ return convert(e2, t1);
+ if (t1.ty == Tnull && (t2.ty == Tpointer || t2.ty == Taarray || t2.ty == Tarray))
+ return convert(e1, t2);
+
+ if (t1.ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e1))
{
if (e2.implicitConvTo(t1.nextOf()))
{
// T[] op T
// T[] op cast(T)U
e2 = e2.castTo(sc, t1.nextOf());
- t = t1.nextOf().arrayOf();
+ return Lret(t1.nextOf().arrayOf());
}
- else if (t1.nextOf().implicitConvTo(e2.type))
+ if (t1.nextOf().implicitConvTo(e2.type))
{
// (cast(T)U)[] op T (https://issues.dlang.org/show_bug.cgi?id=12780)
// e1 is left as U[], it will be handled in arrayOp() later.
- t = e2.type.arrayOf();
+ return Lret(e2.type.arrayOf());
}
- else if (t2.ty == Tarray && isArrayOpOperand(e2))
+ if (t2.ty == Tarray && isArrayOpOperand(e2))
{
if (t1.nextOf().implicitConvTo(t2.nextOf()))
{
@@ -3349,8 +3375,9 @@ LmodCompare:
// if cast won't be handled in arrayOp() later
if (!isArrayOpImplicitCast(t1.isTypeDArray(), t2.isTypeDArray()))
e1 = e1.castTo(sc, t);
+ return Lret(t);
}
- else if (t2.nextOf().implicitConvTo(t1.nextOf()))
+ if (t2.nextOf().implicitConvTo(t1.nextOf()))
{
// T[] op (cast(T)U)[] (https://issues.dlang.org/show_bug.cgi?id=12780)
// e2 is left as U[], it will be handled in arrayOp() later.
@@ -3358,12 +3385,11 @@ LmodCompare:
// if cast won't be handled in arrayOp() later
if (!isArrayOpImplicitCast(t2.isTypeDArray(), t1.isTypeDArray()))
e2 = e2.castTo(sc, t);
+ return Lret(t);
}
- else
- return Lincompatible();
+ return null;
}
- else
- return Lincompatible();
+ return null;
}
else if (t2.ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e2))
{
@@ -3381,7 +3407,7 @@ LmodCompare:
t = e1.type.arrayOf();
}
else
- return Lincompatible();
+ return null;
//printf("test %s\n", Token::toChars(op));
e1 = e1.optimize(WANTvalue);
@@ -3394,12 +3420,10 @@ LmodCompare:
e1 = e2;
e2 = tmp;
}
+ return Lret(t);
}
- else
- {
- return Lincompatible();
- }
- return Lret();
+
+ return null;
}
/************************************
@@ -3431,7 +3455,12 @@ Expression typeCombine(BinExp be, Scope* sc)
return errorReturn();
}
- if (!typeMerge(sc, be.op, &be.type, &be.e1, &be.e2))
+ if (auto result = typeMerge(sc, be.op, be.e1, be.e2))
+ {
+ if (be.type is null)
+ be.type = result;
+ }
+ else
return errorReturn();
// If the types have no value, return an error
@@ -3487,7 +3516,7 @@ Expression integralPromotions(Expression e, Scope* sc)
void fix16997(Scope* sc, UnaExp ue)
{
- if (global.params.fix16997)
+ if (global.params.fix16997 || sc.flags & SCOPE.Cfile)
ue.e1 = integralPromotions(ue.e1, sc); // desired C-like behavor
else
{
diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d
index 22c163b1a17..9c5f0da2f97 100644
--- a/gcc/d/dmd/dclass.d
+++ b/gcc/d/dmd/dclass.d
@@ -3,7 +3,7 @@
*
* Specification: $(LINK2 https://dlang.org/spec/class.html, Classes)
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dclass.d, _dclass.d)
@@ -19,6 +19,7 @@ import core.stdc.string;
import dmd.aggregate;
import dmd.apply;
import dmd.arraytypes;
+import dmd.astenums;
import dmd.gluelayer;
import dmd.declaration;
import dmd.dscope;
@@ -34,7 +35,7 @@ import dmd.root.rmem;
import dmd.target;
import dmd.visitor;
-enum Abstract : int
+enum Abstract : ubyte
{
fwdref = 0, // whether an abstract class is not yet computed
yes, // is abstract class
@@ -129,7 +130,7 @@ extern (C++) struct BaseClass
}
}
-enum ClassFlags : int
+enum ClassFlags : uint
{
none = 0x0,
isCOMclass = 0x1,
@@ -380,7 +381,15 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
return new ClassDeclaration(loc, id, baseclasses, members, inObject);
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override const(char)* toPrettyChars(bool qualifyTypes = false)
+ {
+ if (objc.isMeta)
+ return .objc.toPrettyChars(this, qualifyTypes);
+
+ return super.toPrettyChars(qualifyTypes);
+ }
+
+ override ClassDeclaration syntaxCopy(Dsymbol s)
{
//printf("ClassDeclaration.syntaxCopy('%s')\n", toChars());
ClassDeclaration cd =
@@ -397,7 +406,8 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
(*cd.baseclasses)[i] = b2;
}
- return ScopeDsymbol.syntaxCopy(cd);
+ ScopeDsymbol.syntaxCopy(cd);
+ return cd;
}
override Scope* newScope(Scope* sc)
@@ -488,7 +498,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
if (!members || !symtab) // opaque or addMember is not yet done
{
// .stringof is always defined (but may be hidden by some other symbol)
- if (ident != Id.stringof)
+ if (ident != Id.stringof && !(flags & IgnoreErrors))
error("is forward referenced when looking for `%s`", ident.toChars());
//*(char*)0=0;
return null;
@@ -519,7 +529,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
continue;
else if (s == this) // happens if s is nested in this and derives from this
s = null;
- else if (!(flags & IgnoreSymbolVisibility) && !(s.prot().kind == Prot.Kind.protected_) && !symbolIsVisible(this, s))
+ else if (!(flags & IgnoreSymbolVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(this, s))
s = null;
else
break;
@@ -565,10 +575,13 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
assert(baseClass.sizeok == Sizeok.done);
alignsize = baseClass.alignsize;
- structsize = baseClass.structsize;
- if (classKind == ClassKind.cpp && global.params.isWindows)
- structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
+ if (classKind == ClassKind.cpp)
+ structsize = target.cpp.derivedClassOffset(baseClass);
+ else
+ structsize = baseClass.structsize;
}
+ else if (classKind == ClassKind.objc)
+ structsize = 0; // no hidden member for an Objective-C class
else if (isInterfaceDeclaration())
{
if (interfaces.length == 0)
@@ -997,12 +1010,13 @@ extern (C++) final class InterfaceDeclaration : ClassDeclaration
}
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override InterfaceDeclaration syntaxCopy(Dsymbol s)
{
InterfaceDeclaration id =
s ? cast(InterfaceDeclaration)s
: new InterfaceDeclaration(loc, ident, null);
- return ClassDeclaration.syntaxCopy(id);
+ ClassDeclaration.syntaxCopy(id);
+ return id;
}
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 98bfd8a982d..2135ef039dd 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -2,7 +2,7 @@
* Miscellaneous declarations, including typedef, alias, variable declarations including the
* implicit this declaration, type tuples, ClassInfo, ModuleInfo and various TypeInfos.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/declaration.d, _declaration.d)
@@ -15,6 +15,7 @@ module dmd.declaration;
import core.stdc.stdio;
import dmd.aggregate;
import dmd.arraytypes;
+import dmd.astenums;
import dmd.ctorflow;
import dmd.dclass;
import dmd.delegatize;
@@ -89,18 +90,15 @@ bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
if (s)
fd = s.isFuncDeclaration();
if (fd &&
- ((var.isField() && (fd.isCtorDeclaration() || fd.isPostBlitDeclaration())) ||
- (!var.isField() && fd.isStaticCtorDeclaration())) &&
+ ((fd.isCtorDeclaration() && var.isField()) ||
+ (fd.isStaticCtorDeclaration() && !var.isField())) &&
fd.toParentDecl() == var.toParent2() &&
(!e1 || e1.op == TOK.this_))
{
bool result = true;
- if (!fd.isPostBlitDeclaration())
- {
- var.ctorinit = true;
- //printf("setting ctorinit\n");
- }
+ var.ctorinit = true;
+ //printf("setting ctorinit\n");
if (var.isField() && sc.ctorflow.fieldinit.length && !sc.intypeof)
{
@@ -196,75 +194,6 @@ extern (C++) void ObjectNotFound(Identifier id)
fatal();
}
-enum STC : ulong
-{
- undefined_ = 0L,
- static_ = (1L << 0),
- extern_ = (1L << 1),
- const_ = (1L << 2),
- final_ = (1L << 3),
- abstract_ = (1L << 4),
- parameter = (1L << 5),
- field = (1L << 6),
- override_ = (1L << 7),
- auto_ = (1L << 8),
- synchronized_ = (1L << 9),
- deprecated_ = (1L << 10),
- in_ = (1L << 11), // in parameter
- out_ = (1L << 12), // out parameter
- lazy_ = (1L << 13), // lazy parameter
- foreach_ = (1L << 14), // variable for foreach loop
- //(1L << 15)
- variadic = (1L << 16), // the 'variadic' parameter in: T foo(T a, U b, V variadic...)
- ctorinit = (1L << 17), // can only be set inside constructor
- templateparameter = (1L << 18), // template parameter
- scope_ = (1L << 19),
- immutable_ = (1L << 20),
- ref_ = (1L << 21),
- init = (1L << 22), // has explicit initializer
- manifest = (1L << 23), // manifest constant
- nodtor = (1L << 24), // don't run destructor
- nothrow_ = (1L << 25), // never throws exceptions
- pure_ = (1L << 26), // pure function
- tls = (1L << 27), // thread local
- alias_ = (1L << 28), // alias parameter
- shared_ = (1L << 29), // accessible from multiple threads
- gshared = (1L << 30), // accessible from multiple threads, but not typed as "shared"
- wild = (1L << 31), // for "wild" type constructor
- property = (1L << 32),
- safe = (1L << 33),
- trusted = (1L << 34),
- system = (1L << 35),
- ctfe = (1L << 36), // can be used in CTFE, even if it is static
- disable = (1L << 37), // for functions that are not callable
- result = (1L << 38), // for result variables passed to out contracts
- nodefaultctor = (1L << 39), // must be set inside constructor
- temp = (1L << 40), // temporary variable
- rvalue = (1L << 41), // force rvalue for variables
- nogc = (1L << 42), // @nogc
- volatile_ = (1L << 43), // destined for volatile in the back end
- return_ = (1L << 44), // 'return ref' or 'return scope' for function parameters
- autoref = (1L << 45), // Mark for the already deduced 'auto ref' parameter
- inference = (1L << 46), // do attribute inference
- exptemp = (1L << 47), // temporary variable that has lifetime restricted to an expression
- maybescope = (1L << 48), // parameter might be 'scope'
- scopeinferred = (1L << 49), // 'scope' has been inferred and should not be part of mangling
- future = (1L << 50), // introducing new base class function
- local = (1L << 51), // do not forward (see dmd.dsymbol.ForwardingScopeDsymbol).
- returninferred = (1L << 52), // 'return' has been inferred and should not be part of mangling
- live = (1L << 53), // function @live attribute
-
- // Group members are mutually exclusive (there can be only one)
- safeGroup = STC.safe | STC.trusted | STC.system,
-
- /// Group for `in` / `out` / `ref` storage classes on parameter
- IOR = STC.in_ | STC.ref_ | STC.out_,
-
- TYPECTOR = (STC.const_ | STC.immutable_ | STC.shared_ | STC.wild),
- FUNCATTR = (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.property | STC.live |
- STC.safeGroup),
-}
-
enum STCStorageClass =
(STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.const_ | STC.final_ | STC.abstract_ | STC.synchronized_ |
STC.deprecated_ | STC.future | STC.override_ | STC.lazy_ | STC.alias_ | STC.out_ | STC.in_ | STC.manifest |
@@ -295,9 +224,13 @@ extern (C++) abstract class Declaration : Dsymbol
Type type;
Type originalType; // before semantic analysis
StorageClass storage_class = STC.undefined_;
- Prot protection;
+ Visibility visibility;
LINK linkage = LINK.default_;
- int inuse; // used to detect cycles
+ short inuse; // used to detect cycles
+
+ ubyte adFlags; // control re-assignment of AliasDeclaration (put here for packing reasons)
+ enum wasRead = 1; // set if AliasDeclaration was read
+ enum ignoreRead = 2; // ignore any reads of AliasDeclaration
// overridden symbol with pragma(mangle, "...")
const(char)[] mangleOverride;
@@ -305,13 +238,13 @@ extern (C++) abstract class Declaration : Dsymbol
final extern (D) this(Identifier ident)
{
super(ident);
- protection = Prot(Prot.Kind.undefined);
+ visibility = Visibility(Visibility.Kind.undefined);
}
final extern (D) this(const ref Loc loc, Identifier ident)
{
super(loc, ident);
- protection = Prot(Prot.Kind.undefined);
+ visibility = Visibility(Visibility.Kind.undefined);
}
override const(char)* kind() const
@@ -347,11 +280,42 @@ extern (C++) abstract class Declaration : Dsymbol
if (sc.func && sc.func.storage_class & STC.disable)
return true;
- auto p = toParent();
- if (p && isPostBlitDeclaration())
+ if (auto p = toParent())
{
- p.error(loc, "is not copyable because it is annotated with `@disable`");
- return true;
+ if (auto postblit = isPostBlitDeclaration())
+ {
+ /* https://issues.dlang.org/show_bug.cgi?id=21885
+ *
+ * If the generated postblit is disabled, it
+ * means that one of the fields has a disabled
+ * postblit. Print the first field that has
+ * a disabled postblit.
+ */
+ if (postblit.generated)
+ {
+ auto sd = p.isStructDeclaration();
+ assert(sd);
+ for (size_t i = 0; i < sd.fields.dim; i++)
+ {
+ auto structField = sd.fields[i];
+ if (structField.overlapped)
+ continue;
+ Type tv = structField.type.baseElemOf();
+ if (tv.ty != Tstruct)
+ continue;
+ auto sdv = (cast(TypeStruct)tv).sym;
+ if (!sdv.postblit)
+ continue;
+ if (sdv.postblit.isDisabled())
+ {
+ p.error(loc, "is not copyable because field `%s` is not copyable", structField.toChars());
+ return true;
+ }
+ }
+ }
+ p.error(loc, "is not copyable because it has a disabled postblit");
+ return true;
+ }
}
// if the function is @disabled, maybe there
@@ -418,7 +382,7 @@ extern (C++) abstract class Declaration : Dsymbol
if (scx.func == vthis.parent && (scx.flags & SCOPE.contract))
{
if (!flag)
- error(loc, "cannot modify parameter 'this' in contract");
+ error(loc, "cannot modify parameter `this` in contract");
return Modifiable.initialization; // do not report type related errors
}
}
@@ -567,9 +531,9 @@ extern (C++) abstract class Declaration : Dsymbol
return (storage_class & STC.future) != 0;
}
- override final Prot prot() pure nothrow @nogc @safe
+ override final Visibility visible() pure nothrow @nogc @safe
{
- return protection;
+ return visibility;
}
override final inout(Declaration) isDeclaration() inout
@@ -597,7 +561,7 @@ extern (C++) final class TupleDeclaration : Declaration
this.objects = objects;
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override TupleDeclaration syntaxCopy(Dsymbol s)
{
assert(0);
}
@@ -743,7 +707,7 @@ extern (C++) final class AliasDeclaration : Declaration
return new AliasDeclaration(loc, id, type);
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override AliasDeclaration syntaxCopy(Dsymbol s)
{
//printf("AliasDeclaration::syntaxCopy()\n");
assert(!s);
@@ -786,18 +750,22 @@ extern (C++) final class AliasDeclaration : Declaration
* aliassym is determined already. See the case in: test/compilable/test61.d
*/
auto sa = aliassym.toAlias();
+
+ if (auto td = s.toAlias().isTemplateDeclaration())
+ s = td.funcroot ? td.funcroot : td;
+
if (auto fd = sa.isFuncDeclaration())
{
auto fa = new FuncAliasDeclaration(ident, fd);
- fa.protection = protection;
+ fa.visibility = visibility;
fa.parent = parent;
aliassym = fa;
return aliassym.overloadInsert(s);
}
if (auto td = sa.isTemplateDeclaration())
{
- auto od = new OverDeclaration(ident, td);
- od.protection = protection;
+ auto od = new OverDeclaration(ident, td.funcroot ? td.funcroot : td);
+ od.visibility = visibility;
od.parent = parent;
aliassym = od;
return aliassym.overloadInsert(s);
@@ -807,7 +775,7 @@ extern (C++) final class AliasDeclaration : Declaration
if (sa.ident != ident || sa.parent != parent)
{
od = new OverDeclaration(ident, od);
- od.protection = protection;
+ od.visibility = visibility;
od.parent = parent;
aliassym = od;
}
@@ -818,7 +786,7 @@ extern (C++) final class AliasDeclaration : Declaration
if (sa.ident != ident || sa.parent != parent)
{
os = new OverloadSet(ident, os);
- // TODO: protection is lost here b/c OverloadSets have no protection attribute
+ // TODO: visibility is lost here b/c OverloadSets have no visibility attribute
// Might no be a practical issue, b/c the code below fails to resolve the overload anyhow.
// ----
// module os1;
@@ -833,7 +801,7 @@ extern (C++) final class AliasDeclaration : Declaration
// import os1, os2;
// void test() { merged(123); } // should only look at os2.merged
//
- // os.protection = protection;
+ // os.visibility = visibility;
os.parent = parent;
aliassym = os;
}
@@ -872,6 +840,11 @@ extern (C++) final class AliasDeclaration : Declaration
// loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse);
assert(this != aliassym);
//static int count; if (++count == 10) *(char*)0=0;
+
+ // Reading the AliasDeclaration
+ if (!(adFlags & ignoreRead))
+ adFlags |= wasRead; // can never assign to this AliasDeclaration again
+
if (inuse == 1 && type && _scope)
{
inuse = 2;
@@ -986,23 +959,11 @@ extern (C++) final class OverDeclaration : Declaration
{
Dsymbol overnext; // next in overload list
Dsymbol aliassym;
- bool hasOverloads;
- extern (D) this(Identifier ident, Dsymbol s, bool hasOverloads = true)
+ extern (D) this(Identifier ident, Dsymbol s)
{
super(ident);
this.aliassym = s;
- this.hasOverloads = hasOverloads;
- if (hasOverloads)
- {
- if (OverDeclaration od = aliassym.isOverDeclaration())
- this.hasOverloads = od.hasOverloads;
- }
- else
- {
- // for internal use
- assert(!aliassym.isOverDeclaration());
- }
}
override const(char)* kind() const
@@ -1019,25 +980,9 @@ extern (C++) final class OverDeclaration : Declaration
if (!s)
return false;
- auto od1 = this;
if (auto od2 = s.isOverDeclaration())
- {
- return od1.aliassym.equals(od2.aliassym) && od1.hasOverloads == od2.hasOverloads;
- }
- if (aliassym == s)
- {
- if (hasOverloads)
- return true;
- if (auto fd = s.isFuncDeclaration())
- {
- return fd.isUnique();
- }
- if (auto td = s.isTemplateDeclaration())
- {
- return td.overnext is null;
- }
- }
- return false;
+ return this.aliassym.equals(od2.aliassym);
+ return this.aliassym == s;
}
override bool overloadInsert(Dsymbol s)
@@ -1058,15 +1003,6 @@ extern (C++) final class OverDeclaration : Declaration
Dsymbol isUnique()
{
- if (!hasOverloads)
- {
- if (aliassym.isFuncDeclaration() ||
- aliassym.isTemplateDeclaration())
- {
- return aliassym;
- }
- }
-
Dsymbol result = null;
overloadApply(aliassym, (Dsymbol s)
{
@@ -1100,11 +1036,24 @@ extern (C++) final class OverDeclaration : Declaration
extern (C++) class VarDeclaration : Declaration
{
Initializer _init;
+ FuncDeclarations nestedrefs; // referenced by these lexically nested functions
+ Dsymbol aliassym; // if redone as alias to another symbol
+ VarDeclaration lastVar; // Linked list of variables for goto-skips-init detection
+ Expression edtor; // if !=null, does the destruction of the variable
+ IntRange* range; // if !=null, the variable is known to be within the range
+ VarDeclarations* maybes; // STC.maybescope variables that are assigned to this STC.maybescope variable
+
+ uint endlinnum; // line number of end of scope that this var lives in
uint offset;
uint sequenceNumber; // order the variables are declared
__gshared uint nextSequenceNumber; // the counter for sequenceNumber
- FuncDeclarations nestedrefs; // referenced by these lexically nested functions
structalign_t alignment;
+
+ // When interpreting, these point to the value (NULL if value not determinable)
+ // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated
+ enum AdrOnStackNone = ~0u;
+ uint ctfeAdrOnStack;
+
bool isargptr; // if parameter that _argptr points to
bool ctorinit; // it has been initialized in a ctor
bool iscatchvar; // this is the exception object variable in catch() clause
@@ -1121,19 +1070,8 @@ extern (C++) class VarDeclaration : Declaration
bool doNotInferScope; // do not infer 'scope' for this variable
bool doNotInferReturn; // do not infer 'return' for this variable
ubyte isdataseg; // private data for isDataseg 0 unset, 1 true, 2 false
- Dsymbol aliassym; // if redone as alias to another symbol
- VarDeclaration lastVar; // Linked list of variables for goto-skips-init detection
- uint endlinnum; // line number of end of scope that this var lives in
-
- // When interpreting, these point to the value (NULL if value not determinable)
- // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated
- enum AdrOnStackNone = ~0u;
- uint ctfeAdrOnStack;
-
- Expression edtor; // if !=null, does the destruction of the variable
- IntRange* range; // if !=null, the variable is known to be within the range
- VarDeclarations* maybes; // STC.maybescope variables that are assigned to this STC.maybescope variable
+ bool isArgDtorVar; // temporary created to handle scope destruction of a function argument
final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
in
@@ -1166,7 +1104,7 @@ extern (C++) class VarDeclaration : Declaration
return new VarDeclaration(loc, type, ident, _init, storage_class);
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override VarDeclaration syntaxCopy(Dsymbol s)
{
//printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
assert(!s);
@@ -1293,12 +1231,12 @@ extern (C++) class VarDeclaration : Declaration
override final bool isExport() const
{
- return protection.kind == Prot.Kind.export_;
+ return visibility.kind == Visibility.Kind.export_;
}
override final bool isImportedSymbol() const
{
- if (protection.kind == Prot.Kind.export_ && !_init && (storage_class & STC.static_ || parent.isModule()))
+ if (visibility.kind == Visibility.Kind.export_ && !_init && (storage_class & STC.static_ || parent.isModule()))
return true;
return false;
}
@@ -1479,14 +1417,22 @@ extern (C++) class VarDeclaration : Declaration
//if (cd.isInterfaceDeclaration())
// error("interface `%s` cannot be scope", cd.toChars());
- // Destroying C++ scope classes crashes currently. Since C++ class dtors are not currently supported, simply do not run dtors for them.
- // See https://issues.dlang.org/show_bug.cgi?id=13182
- if (cd.classKind == ClassKind.cpp)
- {
- break;
- }
if (mynew || onstack) // if any destructors
{
+ // delete'ing C++ classes crashes (and delete is deprecated anyway)
+ if (cd.classKind == ClassKind.cpp)
+ {
+ // Don't call non-existant dtor
+ if (!cd.dtor)
+ break;
+
+ e = new VarExp(loc, this);
+ e.type = e.type.mutableOf().unSharedOf(); // Hack for mutable ctor on immutable instances
+ e = new DotVarExp(loc, e, cd.dtor, false);
+ e = new CallExp(loc, e);
+ break;
+ }
+
// delete this;
Expression ec;
ec = new VarExp(loc, this);
@@ -1668,7 +1614,37 @@ extern (C++) class VarDeclaration : Declaration
*/
final bool enclosesLifetimeOf(VarDeclaration v) const pure
{
- return sequenceNumber < v.sequenceNumber;
+ // VarDeclaration's with these STC's need special treatment
+ enum special = STC.temp | STC.foreach_;
+
+ // Sequence numbers work when there are no special VarDeclaration's involved
+ if (!((this.storage_class | v.storage_class) & special))
+ {
+ // FIXME: VarDeclaration's for parameters are created in semantic3, so
+ // they will have a greater sequence number than local variables.
+ // Hence reverse the result for mixed comparisons.
+ const exp = this.isParameter() == v.isParameter();
+
+ return (this.sequenceNumber < v.sequenceNumber) == exp;
+ }
+
+ // Assume that semantic produces temporaries according to their lifetime
+ // (It won't create a temporary before the actual content)
+ if ((this.storage_class & special) && (v.storage_class & special))
+ return this.sequenceNumber < v.sequenceNumber;
+
+ // Fall back to lexical order
+ assert(this.loc != Loc.initial);
+ assert(v.loc != Loc.initial);
+
+ if (auto ld = this.loc.linnum - v.loc.linnum)
+ return ld < 0;
+
+ if (auto cd = this.loc.charnum - v.loc.charnum)
+ return cd < 0;
+
+ // Default fallback
+ return this.sequenceNumber < v.sequenceNumber;
}
/***************************************
@@ -1726,7 +1702,7 @@ extern (C++) class TypeInfoDeclaration : VarDeclaration
super(Loc.initial, Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null);
this.tinfo = tinfo;
storage_class = STC.static_ | STC.gshared;
- protection = Prot(Prot.Kind.public_);
+ visibility = Visibility(Visibility.Kind.public_);
linkage = LINK.c;
alignment = target.ptrsize;
}
@@ -1736,7 +1712,7 @@ extern (C++) class TypeInfoDeclaration : VarDeclaration
return new TypeInfoDeclaration(tinfo);
}
- override final Dsymbol syntaxCopy(Dsymbol s)
+ override final TypeInfoDeclaration syntaxCopy(Dsymbol s)
{
assert(0); // should never be produced by syntax
}
@@ -2173,7 +2149,7 @@ extern (C++) final class ThisDeclaration : VarDeclaration
storage_class |= STC.nodtor;
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override ThisDeclaration syntaxCopy(Dsymbol s)
{
assert(0); // should never be produced by syntax
}
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 2b32e2caf1e..58f72c6e7a0 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -87,6 +87,8 @@ struct IntRange;
#define STCfuture 0x4000000000000ULL // introducing new base class function
#define STClocal 0x8000000000000ULL // do not forward (see dmd.dsymbol.ForwardingScopeDsymbol).
#define STCreturninferred 0x10000000000000ULL // 'return' has been inferred and should not be part of mangling
+#define STClive 0x20000000000000ULL // function @live attribute
+#define STCregister 0x40000000000000ULL // `register` storage class
void ObjectNotFound(Identifier *id);
@@ -98,9 +100,10 @@ public:
Type *type;
Type *originalType; // before semantic analysis
StorageClass storage_class;
- Prot protection;
+ Visibility visibility;
LINK linkage;
- int inuse; // used to detect cycles
+ short inuse; // used to detect cycles
+ uint8_t adFlags;
DString mangleOverride; // overridden symbol with pragma(mangle, "...")
const char *kind() const;
@@ -134,7 +137,7 @@ public:
bool isFuture() const { return (storage_class & STCfuture) != 0; }
- Prot prot();
+ Visibility visible();
Declaration *isDeclaration() { return this; }
void accept(Visitor *v) { v->visit(this); }
@@ -150,7 +153,7 @@ public:
TypeTuple *tupletype; // !=NULL if this is a type tuple
- Dsymbol *syntaxCopy(Dsymbol *);
+ TupleDeclaration *syntaxCopy(Dsymbol *);
const char *kind() const;
Type *getType();
Dsymbol *toAlias2();
@@ -170,7 +173,7 @@ public:
Dsymbol *_import; // !=NULL if unresolved internal alias for selective import
static AliasDeclaration *create(Loc loc, Identifier *id, Type *type);
- Dsymbol *syntaxCopy(Dsymbol *);
+ AliasDeclaration *syntaxCopy(Dsymbol *);
bool overloadInsert(Dsymbol *s);
const char *kind() const;
Type *getType();
@@ -189,7 +192,6 @@ class OverDeclaration : public Declaration
public:
Dsymbol *overnext; // next in overload list
Dsymbol *aliassym;
- bool hasOverloads;
const char *kind() const;
bool equals(const RootObject *o) const;
@@ -209,10 +211,22 @@ class VarDeclaration : public Declaration
{
public:
Initializer *_init;
+ FuncDeclarations nestedrefs; // referenced by these lexically nested functions
+ Dsymbol *aliassym; // if redone as alias to another symbol
+ VarDeclaration *lastVar; // Linked list of variables for goto-skips-init detection
+ Expression *edtor; // if !=NULL, does the destruction of the variable
+ IntRange *range; // if !NULL, the variable is known to be within the range
+ VarDeclarations *maybes; // STCmaybescope variables that are assigned to this STCmaybescope variable
+
+ unsigned endlinnum; // line number of end of scope that this var lives in
unsigned offset;
unsigned sequenceNumber; // order the variables are declared
- FuncDeclarations nestedrefs; // referenced by these lexically nested functions
structalign_t alignment;
+
+ // When interpreting, these point to the value (NULL if value not determinable)
+ // The index of this variable on the CTFE stack, ~0u if not allocated
+ unsigned ctfeAdrOnStack;
+
bool isargptr; // if parameter that _argptr points to
bool ctorinit; // it has been initialized in a ctor
bool iscatchvar; // this is the exception object variable in catch() clause
@@ -225,21 +239,11 @@ public:
bool doNotInferScope; // do not infer 'scope' for this variable
bool doNotInferReturn; // do not infer 'return' for this variable
unsigned char isdataseg; // private data for isDataseg
- Dsymbol *aliassym; // if redone as alias to another symbol
- VarDeclaration *lastVar; // Linked list of variables for goto-skips-init detection
- unsigned endlinnum; // line number of end of scope that this var lives in
-
- // When interpreting, these point to the value (NULL if value not determinable)
- // The index of this variable on the CTFE stack, ~0u if not allocated
- unsigned ctfeAdrOnStack;
- Expression *edtor; // if !=NULL, does the destruction of the variable
- IntRange *range; // if !NULL, the variable is known to be within the range
-
- VarDeclarations *maybes; // STCmaybescope variables that are assigned to this STCmaybescope variable
+ bool isArgDtorVar; // temporary created to handle scope destruction of a function argument
public:
static VarDeclaration *create(const Loc &loc, Type *t, Identifier *id, Initializer *init, StorageClass storage_class = STCundefined);
- Dsymbol *syntaxCopy(Dsymbol *);
+ VarDeclaration *syntaxCopy(Dsymbol *);
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
const char *kind() const;
AggregateDeclaration *isThis();
@@ -281,7 +285,7 @@ public:
Type *tinfo;
static TypeInfoDeclaration *create(Type *tinfo);
- Dsymbol *syntaxCopy(Dsymbol *);
+ TypeInfoDeclaration *syntaxCopy(Dsymbol *);
const char *toChars() const;
TypeInfoDeclaration *isTypeInfoDeclaration() { return this; }
@@ -421,12 +425,12 @@ public:
class ThisDeclaration : public VarDeclaration
{
public:
- Dsymbol *syntaxCopy(Dsymbol *);
+ ThisDeclaration *syntaxCopy(Dsymbol *);
ThisDeclaration *isThisDeclaration() { return this; }
void accept(Visitor *v) { v->visit(this); }
};
-enum ILS
+enum class ILS : unsigned char
{
ILSuninitialized, // not computed yet
ILSno, // cannot inline
@@ -584,7 +588,7 @@ public:
ObjcFuncDeclaration objc;
static FuncDeclaration *create(const Loc &loc, const Loc &endloc, Identifier *id, StorageClass storage_class, Type *type);
- Dsymbol *syntaxCopy(Dsymbol *);
+ FuncDeclaration *syntaxCopy(Dsymbol *);
bool functionSemantic();
bool functionSemantic3();
bool equals(const RootObject *o) const;
@@ -595,7 +599,7 @@ public:
bool overloadInsert(Dsymbol *s);
bool inUnittest();
MATCH leastAsSpecialized(FuncDeclaration *g);
- LabelDsymbol *searchLabel(Identifier *ident);
+ LabelDsymbol *searchLabel(Identifier *ident, const Loc &loc);
int getLevel(FuncDeclaration *fd, int intypeof); // lexical nesting level difference
int getLevelAndCheck(const Loc &loc, Scope *sc, FuncDeclaration *fd);
const char *toPrettyChars(bool QualifyTypes = false);
@@ -635,7 +639,7 @@ public:
static FuncDeclaration *genCfunc(Parameters *args, Type *treturn, const char *name, StorageClass stc=0);
static FuncDeclaration *genCfunc(Parameters *args, Type *treturn, Identifier *id, StorageClass stc=0);
- bool checkNrvo();
+ bool checkNRVO();
FuncDeclaration *isFuncDeclaration() { return this; }
@@ -665,7 +669,7 @@ public:
// backend
bool deferToObj;
- Dsymbol *syntaxCopy(Dsymbol *);
+ FuncLiteralDeclaration *syntaxCopy(Dsymbol *);
bool isNested() const;
AggregateDeclaration *isThis();
bool isVirtual() const;
@@ -684,7 +688,7 @@ class CtorDeclaration : public FuncDeclaration
{
public:
bool isCpCtor;
- Dsymbol *syntaxCopy(Dsymbol *);
+ CtorDeclaration *syntaxCopy(Dsymbol *);
const char *kind() const;
const char *toChars() const;
bool isVirtual() const;
@@ -698,7 +702,7 @@ public:
class PostBlitDeclaration : public FuncDeclaration
{
public:
- Dsymbol *syntaxCopy(Dsymbol *);
+ PostBlitDeclaration *syntaxCopy(Dsymbol *);
bool isVirtual() const;
bool addPreInvariant();
bool addPostInvariant();
@@ -711,7 +715,7 @@ public:
class DtorDeclaration : public FuncDeclaration
{
public:
- Dsymbol *syntaxCopy(Dsymbol *);
+ DtorDeclaration *syntaxCopy(Dsymbol *);
const char *kind() const;
const char *toChars() const;
bool isVirtual() const;
@@ -726,7 +730,7 @@ public:
class StaticCtorDeclaration : public FuncDeclaration
{
public:
- Dsymbol *syntaxCopy(Dsymbol *);
+ StaticCtorDeclaration *syntaxCopy(Dsymbol *);
AggregateDeclaration *isThis();
bool isVirtual() const;
bool addPreInvariant();
@@ -740,7 +744,7 @@ public:
class SharedStaticCtorDeclaration : public StaticCtorDeclaration
{
public:
- Dsymbol *syntaxCopy(Dsymbol *);
+ SharedStaticCtorDeclaration *syntaxCopy(Dsymbol *);
SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return this; }
void accept(Visitor *v) { v->visit(this); }
@@ -751,7 +755,7 @@ class StaticDtorDeclaration : public FuncDeclaration
public:
VarDeclaration *vgate; // 'gate' variable
- Dsymbol *syntaxCopy(Dsymbol *);
+ StaticDtorDeclaration *syntaxCopy(Dsymbol *);
AggregateDeclaration *isThis();
bool isVirtual() const;
bool hasStaticCtorOrDtor();
@@ -765,7 +769,7 @@ public:
class SharedStaticDtorDeclaration : public StaticDtorDeclaration
{
public:
- Dsymbol *syntaxCopy(Dsymbol *);
+ SharedStaticDtorDeclaration *syntaxCopy(Dsymbol *);
SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { return this; }
void accept(Visitor *v) { v->visit(this); }
@@ -774,7 +778,7 @@ public:
class InvariantDeclaration : public FuncDeclaration
{
public:
- Dsymbol *syntaxCopy(Dsymbol *);
+ InvariantDeclaration *syntaxCopy(Dsymbol *);
bool isVirtual() const;
bool addPreInvariant();
bool addPostInvariant();
@@ -791,7 +795,7 @@ public:
// toObjFile() these nested functions after this one
FuncDeclarations deferredNested;
- Dsymbol *syntaxCopy(Dsymbol *);
+ UnitTestDeclaration *syntaxCopy(Dsymbol *);
AggregateDeclaration *isThis();
bool isVirtual() const;
bool addPreInvariant();
@@ -807,7 +811,7 @@ public:
Parameters *parameters;
VarArg varargs;
- Dsymbol *syntaxCopy(Dsymbol *);
+ NewDeclaration *syntaxCopy(Dsymbol *);
const char *kind() const;
bool isVirtual() const;
bool addPreInvariant();
diff --git a/gcc/d/dmd/delegatize.d b/gcc/d/dmd/delegatize.d
index 3aa4f84ce9f..07c1bbda650 100644
--- a/gcc/d/dmd/delegatize.d
+++ b/gcc/d/dmd/delegatize.d
@@ -3,7 +3,7 @@
*
* Specification: $(LINK2 https://dlang.org/spec/function.html#lazy-params, Lazy Parameters)
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/delegatize.d, _delegatize.d)
@@ -15,6 +15,7 @@ module dmd.delegatize;
import core.stdc.stdio;
import dmd.apply;
+import dmd.astenums;
import dmd.declaration;
import dmd.dscope;
import dmd.dsymbol;
diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d
index 95197a4e6c6..2d449af9f7d 100644
--- a/gcc/d/dmd/denum.d
+++ b/gcc/d/dmd/denum.d
@@ -3,7 +3,7 @@
*
* Specification: $(LINK2 https://dlang.org/spec/enum.html, Enums)
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/denum.d, _denum.d)
@@ -50,7 +50,7 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
Type type; // the TypeEnum
Type memtype; // type of the members
- Prot protection;
+ Visibility visibility;
Expression maxval;
Expression minval;
Expression defaultval; // default initializer
@@ -64,14 +64,15 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
//printf("EnumDeclaration() %s\n", toChars());
type = new TypeEnum(this);
this.memtype = memtype;
- protection = Prot(Prot.Kind.undefined);
+ visibility = Visibility(Visibility.Kind.undefined);
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override EnumDeclaration syntaxCopy(Dsymbol s)
{
assert(!s);
auto ed = new EnumDeclaration(loc, ident, memtype ? memtype.syntaxCopy() : null);
- return ScopeDsymbol.syntaxCopy(ed);
+ ScopeDsymbol.syntaxCopy(ed);
+ return ed;
}
override void addMember(Scope* sc, ScopeDsymbol sds)
@@ -85,29 +86,12 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
printf(" member %s\n", em.toChars());
}
}
-
- /* Anonymous enum members get added to enclosing scope.
- */
- ScopeDsymbol scopesym = isAnonymous() ? sds : this;
-
if (!isAnonymous())
{
ScopeDsymbol.addMember(sc, sds);
- if (!symtab)
- symtab = new DsymbolTable();
}
- if (members)
- {
- for (size_t i = 0; i < members.dim; i++)
- {
- EnumMember em = (*members)[i].isEnumMember();
- em.ed = this;
- //printf("add %s to scope %s\n", em.toChars(), scopesym.toChars());
- em.addMember(sc, isAnonymous() ? scopesym : this);
- }
- }
- added = true;
+ addEnumMembers(this, sc, sds);
}
override void setScope(Scope* sc)
@@ -143,13 +127,6 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
dsymbolSemantic(this, _scope);
}
- if (!members || !symtab || _scope)
- {
- error("is forward referenced when looking for `%s`", ident.toChars());
- //*(char*)0=0;
- return null;
- }
-
Dsymbol s = ScopeDsymbol.search(loc, ident, flags);
return s;
}
@@ -160,9 +137,9 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
return isdeprecated;
}
- override Prot prot() pure nothrow @nogc @safe
+ override Visibility visible() pure nothrow @nogc @safe
{
- return protection;
+ return visibility;
}
/******************************
@@ -209,7 +186,7 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
dsymbolSemantic(this, _scope);
if (errors)
return errorReturn();
- if (semanticRun == PASS.init || !members)
+ if (!members)
{
if (isSpecial())
{
@@ -218,7 +195,7 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
return memtype.getProperty(_scope, loc, id, 0);
}
- error("is forward referenced looking for `.%s`", id.toChars());
+ error(loc, "is opaque and has no `.%s`", id.toChars());
return errorReturn();
}
if (!(memtype && memtype.isintegral()))
@@ -239,6 +216,13 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
continue;
}
+ if (em.semanticRun < PASS.semanticdone)
+ {
+ em.error("is forward referenced looking for `.%s`", id.toChars());
+ errors = true;
+ continue;
+ }
+
if (first)
{
*pval = em.value;
@@ -298,16 +282,16 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
dsymbolSemantic(this, _scope);
if (errors)
return handleErrors();
- if (semanticRun == PASS.init || !members)
+ if (!members)
{
if (isSpecial())
{
/* Allow these special enums to not need a member list
*/
- return memtype.defaultInit(loc);
+ return defaultval = memtype.defaultInit(loc);
}
- error(loc, "forward reference of `%s.init`", toChars());
+ error(loc, "is opaque and has no default initializer");
return handleErrors();
}
@@ -316,6 +300,12 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
EnumMember em = (*members)[i].isEnumMember();
if (em)
{
+ if (em.semanticRun < PASS.semanticdone)
+ {
+ error(loc, "forward reference of `%s.init`", toChars());
+ return handleErrors();
+ }
+
defaultval = em.value;
return defaultval;
}
@@ -337,13 +327,13 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
}
else
{
- if (!isAnonymous() && members)
- memtype = Type.tint32;
+ // Run semantic to get the type from a possible first member value
+ dsymbolSemantic(this, _scope);
}
}
if (!memtype)
{
- if (!isAnonymous() && members)
+ if (!isAnonymous() && (members || semanticRun >= PASS.semanticdone))
memtype = Type.tint32;
else
{
@@ -407,7 +397,7 @@ extern (C++) final class EnumMember : VarDeclaration
depdecl = dd;
}
- override Dsymbol syntaxCopy(Dsymbol s)
+ override EnumMember syntaxCopy(Dsymbol s)
{
assert(!s);
return new EnumMember(
@@ -415,8 +405,8 @@ extern (C++) final class EnumMember : VarDeclaration
value ? value.syntaxCopy() : null,
origType ? origType.syntaxCopy() : null,
storage_class,
- userAttribDecl ? cast(UserAttributeDeclaration)userAttribDecl.syntaxCopy(s) : null,
- depdecl ? cast(DeprecatedDeclaration)depdecl.syntaxCopy(s) : null);
+ userAttribDecl ? userAttribDecl.syntaxCopy(s) : null,
+ depdecl ? depdecl.syntaxCopy(s) : null);
}
override const(char)* kind() const
@@ -469,5 +459,8 @@ bool isSpecialEnumIdent(const Identifier ident) @nogc nothrow
ident == Id.__c_longlong ||
ident == Id.__c_ulonglong ||
ident == Id.__c_long_double ||
- ident == Id.__c_wchar_t;
+ ident == Id.__c_wchar_t ||
+ ident == Id.__c_complex_float ||
+ ident == Id.__c_complex_double ||
+ ident == Id.__c_complex_real;
}
diff --git a/gcc/d/dmd/dimport.d b/gcc/d/dmd/dimport.d
index 31947645542..8cd436422ee 100644
--- a/gcc/d/dmd/dimport.d
+++ b/gcc/d/dmd/dimport.d
@@ -1,7 +1,7 @@
/**
* A `Dsymbol` representing a renamed import.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dimport.d, _dimport.d)
@@ -12,6 +12,7 @@
module dmd.dimport;
import dmd.arraytypes;
+import dmd.astenums;
import dmd.declaration;
import dmd.dmodule;
import dmd.dscope;
@@ -22,7 +23,6 @@ import dmd.expression;
import dmd.globals;
import dmd.identifier;
import dmd.mtype;
-import dmd.root.rmem;
import dmd.visitor;
/***********************************************************
@@ -31,11 +31,11 @@ extern (C++) final class Import : Dsymbol
{
/* static import aliasId = pkg1.pkg2.id : alias1 = name1, alias2 = name2;
*/
- Identifiers* packages; // array of Identifier's representing packages
+ Identifier[] packages; // array of Identifier's representing packages
Identifier id; // module Identifier
Identifier aliasId;
int isstatic; // !=0 if static import
- Prot protection;
+ Visibility visibility;
// Pairs of alias=name to bind into current namespace
Identifiers names;
@@ -47,7 +47,7 @@ extern (C++) final class Import : Dsymbol
// corresponding AliasDeclarations for alias=name pairs
AliasDeclarations aliasdecls;
- extern (D) this(const ref Loc loc, Identifiers* packages, Identifier id, Identifier aliasId, int isstatic)
+ extern (D) this(const ref Loc loc, Identifier[] packages, Identifier id, Identifier aliasId, int isstatic)
{
Identifier selectIdent()
{
@@ -57,10 +57,10 @@ extern (C++) final class Import : Dsymbol
// import [aliasId] = std.stdio;
return aliasId;
}
- else if (packages && packages.dim)
+ else if (packages.length > 0)
{
// import [std].stdio;
- return (*packages)[0];
+ return packages[0];
}
else
{
@@ -75,13 +75,9 @@ extern (C++) final class Import : Dsymbol
version (none)
{
printf("Import::Import(");
- if (packages && packages.dim)
+ foreach (id; packages)
{
- for (size_t i = 0; i < packages.dim; i++)
- {
- Identifier id = (*packages)[i];
- printf("%s.", id.toChars());
- }
+ printf("%s.", id.toChars());
}
printf("%s)\n", id.toChars());
}
@@ -89,7 +85,7 @@ extern (C++) final class Import : Dsymbol
this.id = id;
this.aliasId = aliasId;
this.isstatic = isstatic;
- this.protection = Prot.Kind.private_; // default to private
+ this.visibility = Visibility.Kind.private_; // default to private
}
extern (D) void addAlias(Identifier name, Identifier _alias)
@@ -107,13 +103,13 @@ extern (C++) final class Import : Dsymbol
return isstatic ? "static import" : "import";
}
- override Prot prot() pure nothrow @nogc @safe
+ override Visibility visible() pure nothrow @nogc @safe
{
- return protection;
+ return visibility;
}
// copy only syntax trees
- override Dsymbol syntaxCopy(Dsymbol s)
+ override Import syntaxCopy(Dsymbol s)
{
assert(!s);
auto si = new Import(loc, packages, id, aliasId, isstatic);
@@ -234,12 +230,45 @@ extern (C++) final class Import : Dsymbol
isstatic = true;
mod.importAll(null);
mod.checkImportDeprecation(loc, sc);
- if (sc.explicitProtection)
- protection = sc.protection;
+ if (sc.explicitVisibility)
+ visibility = sc.visibility;
if (!isstatic && !aliasId && !names.dim)
- sc.scopesym.importScope(mod, protection);
+ sc.scopesym.importScope(mod, visibility);
+ // Enable access to pkgs/mod as soon as posible, because compiler
+ // can traverse them before the import gets semantic (Issue: 21501)
+ if (!aliasId && !names.dim)
+ addPackageAccess(sc.scopesym);
}
+ /*******************************
+ * Mark the imported packages as accessible from the current
+ * scope. This access check is necessary when using FQN b/c
+ * we're using a single global package tree.
+ * https://issues.dlang.org/show_bug.cgi?id=313
+ */
+ extern (D) void addPackageAccess(ScopeDsymbol scopesym)
+ {
+ //printf("Import::addPackageAccess('%s') %p\n", toPrettyChars(), this);
+ if (packages.length > 0)
+ {
+ // import a.b.c.d;
+ auto p = pkg; // a
+ scopesym.addAccessiblePackage(p, visibility);
+ foreach (id; packages[1 .. $]) // [b, c]
+ {
+ p = cast(Package) 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 (p is null)
+ break;
+ scopesym.addAccessiblePackage(p, visibility);
+ }
+ }
+ scopesym.addAccessiblePackage(mod, visibility); // d
+ }
+
override Dsymbol toAlias()
{
if (aliasId)
@@ -266,7 +295,7 @@ extern (C++) final class Import : Dsymbol
Identifier _alias = aliases[i];
if (!_alias)
_alias = name;
- auto tname = Pool!TypeIdentifier.make(loc, name);
+ auto tname = new TypeIdentifier(loc, name);
auto ad = new AliasDeclaration(loc, _alias, tname);
ad._import = this;
ad.addMember(sc, sd);
@@ -283,7 +312,7 @@ extern (C++) final class Import : Dsymbol
importAll(sc);
sc = sc.push(mod);
- sc.protection = protection;
+ sc.visibility = visibility;
foreach (ad; aliasdecls)
ad.setScope(sc);
sc = sc.pop();
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 78e5777bf05..853758a7197 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -3,7 +3,7 @@
*
* Specification: ($LINK2 https://dlang.org/spec/function.html#interpretation, Compile Time Function Execution (CTFE))
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dinterpret.d, _dinterpret.d)
@@ -18,6 +18,7 @@ import core.stdc.stdlib;
import core.stdc.string;
import dmd.apply;
import dmd.arraytypes;
+import dmd.astenums;
import dmd.attrib;
import dmd.builtin;
import dmd.constfold;
@@ -38,6 +39,7 @@ import dmd.identifier;
import dmd.init;
import dmd.initsem;
import dmd.mtype;
+import dmd.printast;
import dmd.root.rmem;
import dmd.root.array;
import dmd.root.region;
@@ -70,6 +72,10 @@ public Expression ctfeInterpret(Expression e)
case TOK.super_:
case TOK.type:
case TOK.typeid_:
+ case TOK.template_: // non-eponymous template/instance
+ case TOK.scope_: // ditto
+ case TOK.dotTemplateDeclaration: // ditto, e.e1 doesn't matter here
+ case TOK.dot: // ditto
if (e.type.ty == Terror)
return ErrorExp.get();
goto case TOK.error;
@@ -308,6 +314,7 @@ public:
extern (C++) Expression getValue(VarDeclaration v)
{
+ //printf("getValue() %s\n", v.toChars());
if ((v.isDataseg() || v.storage_class & STC.manifest) && !v.isCTFE())
{
assert(v.ctfeAdrOnStack < globalValues.dim);
@@ -319,6 +326,7 @@ public:
extern (C++) void setValue(VarDeclaration v, Expression e)
{
+ //printf("setValue() %s : %s\n", v.toChars(), e.toChars());
assert(!v.isDataseg() || v.isCTFE());
assert(v.ctfeAdrOnStack < stackPointer());
values[v.ctfeAdrOnStack] = e;
@@ -326,6 +334,7 @@ public:
extern (C++) void push(VarDeclaration v)
{
+ //printf("push() %s\n", v.toChars());
assert(!v.isDataseg() || v.isCTFE());
if (v.ctfeAdrOnStack != VarDeclaration.AdrOnStackNone && v.ctfeAdrOnStack >= framepointer)
{
@@ -417,11 +426,12 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
if (!fd.functionSemantic3())
return CTFEExp.cantexp;
if (fd.semanticRun < PASS.semantic3done)
+ {
+ fd.error("circular dependency. Functions cannot be interpreted while being compiled");
return CTFEExp.cantexp;
+ }
- Type tb = fd.type.toBasetype();
- assert(tb.ty == Tfunction);
- TypeFunction tf = cast(TypeFunction)tb;
+ auto tf = fd.type.toBasetype().isTypeFunction();
if (tf.parameterList.varargs != VarArg.none && arguments &&
((fd.parameters && arguments.dim != fd.parameters.dim) || (!fd.parameters && arguments.dim)))
{
@@ -498,11 +508,11 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
if (earg.op == TOK.structLiteral && !(fparam.storageClass & (STC.const_ | STC.immutable_)))
earg = copyLiteral(earg).copy();
}
- if (earg.op == TOK.thrownException)
+ if (auto tee = earg.isThrownExceptionExp())
{
if (istate)
- return earg;
- (cast(ThrownExceptionExp)earg).generateUncaughtError();
+ return tee;
+ tee.generateUncaughtError();
return CTFEExp.cantexp;
}
eargs[i] = earg;
@@ -552,9 +562,9 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
ctfeGlobals.stack.push(v);
if (fparam.isReference() && earg.op == TOK.variable &&
- (cast(VarExp)earg).var.toParent2() == fd)
+ earg.isVarExp().var.toParent2() == fd)
{
- VarDeclaration vx = (cast(VarExp)earg).var.isVarDeclaration();
+ VarDeclaration vx = earg.isVarExp().var.isVarDeclaration();
if (!vx)
{
fd.error("cannot interpret `%s` as a `ref` parameter", earg.toChars());
@@ -655,23 +665,22 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
// If fell off the end of a void function, return void
if (!e && tf.next.ty == Tvoid)
e = CTFEExp.voidexp;
- if (tf.isref && e.op == TOK.variable && (cast(VarExp)e).var == fd.vthis)
+ if (tf.isref && e.op == TOK.variable && e.isVarExp().var == fd.vthis)
e = thisarg;
if (tf.isref && fd.isThis2 && e.op == TOK.index)
{
- auto ie = cast(IndexExp)e;
+ auto ie = e.isIndexExp();
auto pe = ie.e1.isPtrExp();
auto ve = !pe ? null : pe.e1.isVarExp();
if (ve && ve.var == fd.vthis)
{
auto ne = ie.e2.isIntegerExp();
assert(ne);
- assert(thisarg.op == TOK.address);
- e = (cast(AddrExp)thisarg).e1;
- e = (*(cast(ArrayLiteralExp)e).elements)[cast(size_t)ne.getInteger()];
- if (e.op == TOK.address)
+ auto ale = thisarg.isAddrExp().e1.isArrayLiteralExp();
+ e = (*ale.elements)[cast(size_t)ne.getInteger()];
+ if (auto ae = e.isAddrExp())
{
- e = (cast(AddrExp)e).e1;
+ e = ae.e1;
}
}
}
@@ -683,11 +692,11 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
ctfeGlobals.stack.endFrame();
// If it generated an uncaught exception, report error.
- if (!istate && e.op == TOK.thrownException)
+ if (!istate && e.isThrownExceptionExp())
{
if (e == pue.exp())
e = pue.copy();
- (cast(ThrownExceptionExp)e).generateUncaughtError();
+ e.isThrownExceptionExp().generateUncaughtError();
e = CTFEExp.cantexp;
}
@@ -1432,9 +1441,9 @@ public:
Expression e = interpret(s._body, istate);
// An exception was thrown
- if (e && e.op == TOK.thrownException)
+ if (e && e.isThrownExceptionExp())
{
- ThrownExceptionExp ex = cast(ThrownExceptionExp)e;
+ ThrownExceptionExp ex = e.isThrownExceptionExp();
Type extype = ex.thrown.originalClass().type;
// Search for an appropriate catch clause.
@@ -1565,11 +1574,11 @@ public:
result = ey;
return;
}
- if (ey && ey.op == TOK.thrownException)
+ if (ey && ey.isThrownExceptionExp())
{
// Check for collided exceptions
- if (ex && ex.op == TOK.thrownException)
- ex = chainExceptions(cast(ThrownExceptionExp)ex, cast(ThrownExceptionExp)ey);
+ if (ex && ex.isThrownExceptionExp())
+ ex = chainExceptions(ex.isThrownExceptionExp(), ey.isThrownExceptionExp());
else
ex = ey;
}
@@ -2086,6 +2095,7 @@ public:
e = v._init.initializerToExpression();
}
else
+ // Zero-length arrays don't have an initializer
e = v.type.defaultInitLiteral(e.loc);
e = interpret(e, istate);
@@ -2098,17 +2108,23 @@ public:
else
{
e = hasValue(v) ? getValue(v) : null;
- if (!e && !v.isCTFE() && v.isDataseg())
- {
- error(loc, "static variable `%s` cannot be read at compile time", v.toChars());
- return CTFEExp.cantexp;
- }
if (!e)
{
- assert(!(v._init && v._init.isVoidInitializer()));
- // CTFE initiated from inside a function
- error(loc, "variable `%s` cannot be read at compile time", v.toChars());
- return CTFEExp.cantexp;
+ // Zero-length arrays don't have an initializer
+ if (v.type.size() == 0)
+ e = v.type.defaultInitLiteral(loc);
+ else if (!v.isCTFE() && v.isDataseg())
+ {
+ error(loc, "static variable `%s` cannot be read at compile time", v.toChars());
+ return CTFEExp.cantexp;
+ }
+ else
+ {
+ assert(!(v._init && v._init.isVoidInitializer()));
+ // CTFE initiated from inside a function
+ error(loc, "variable `%s` cannot be read at compile time", v.toChars());
+ return CTFEExp.cantexp;
+ }
}
if (auto vie = e.isVoidInitExp())
{
@@ -2199,6 +2215,15 @@ public:
result = getVarExp(e.loc, istate, e.var, goal);
if (exceptionOrCant(result))
return;
+
+ // Visit the default initializer for noreturn variables
+ // (Custom initializers would abort the current function call and exit above)
+ if (result.type.ty == Tnoreturn)
+ {
+ result.accept(this);
+ return;
+ }
+
if ((e.var.storage_class & (STC.ref_ | STC.out_)) == 0 && e.type.baseElemOf().ty != Tstruct)
{
/* Ultimately, STC.ref_|STC.out_ check should be enough to see the
@@ -2221,6 +2246,12 @@ public:
printf("%s DeclarationExp::interpret() %s\n", e.loc.toChars(), e.toChars());
}
Dsymbol s = e.declaration;
+ while (s.isAttribDeclaration())
+ {
+ auto ad = cast(AttribDeclaration)s;
+ assert(ad.decl && ad.decl.dim == 1); // Currently, only one allowed when parsing
+ s = (*ad.decl)[0];
+ }
if (VarDeclaration v = s.isVarDeclaration())
{
if (TupleDeclaration td = v.toAlias().isTupleDeclaration())
@@ -2303,20 +2334,8 @@ public:
}
return;
}
- if (s.isAttribDeclaration() || s.isTemplateMixin() || s.isTupleDeclaration())
+ if (s.isTemplateMixin() || s.isTupleDeclaration())
{
- // Check for static struct declarations, which aren't executable
- AttribDeclaration ad = e.declaration.isAttribDeclaration();
- if (ad && ad.decl && ad.decl.dim == 1)
- {
- Dsymbol sparent = (*ad.decl)[0];
- if (sparent.isAggregateDeclaration() || sparent.isTemplateDeclaration() || sparent.isAliasDeclaration())
- {
- result = null;
- return; // static (template) struct declaration. Nothing to do.
- }
- }
-
// These can be made to work, too lazy now
e.error("declaration `%s` is not yet implemented in CTFE", e.toChars());
result = CTFEExp.cantexp;
@@ -2994,16 +3013,6 @@ public:
er = interpret(pue, ex, istate);
if (exceptionOrCant(er))
return false;
- if (er.isConst() != 1)
- {
- if (er.op == TOK.arrayLiteral)
- // Until we get it to work, issue a reasonable error message
- e.error("cannot interpret array literal expression `%s` at compile time", e.toChars());
- else
- e.error("CTFE internal error: non-constant value `%s`", ex.toChars());
- result = CTFEExp.cantexp;
- return false;
- }
return true;
}
@@ -3028,7 +3037,67 @@ public:
return;
}
}
- *pue = (*fp)(e.loc, e.type, e1, e2);
+
+ /******************************************
+ * Perform the operation fp on operands e1 and e2.
+ */
+ UnionExp evaluate(Loc loc, Type type, Expression e1, Expression e2)
+ {
+ UnionExp ue = void;
+ auto ae1 = e1.isArrayLiteralExp();
+ auto ae2 = e2.isArrayLiteralExp();
+ if (ae1 || ae2)
+ {
+ /* Cases:
+ * 1. T[] op T[]
+ * 2. T op T[]
+ * 3. T[] op T
+ */
+ if (ae1 && e2.implicitConvTo(e1.type.toBasetype().nextOf())) // case 3
+ ae2 = null;
+ else if (ae2 && e1.implicitConvTo(e2.type.toBasetype().nextOf())) // case 2
+ ae1 = null;
+ // else case 1
+
+ auto aex = ae1 ? ae1 : ae2;
+ if (!aex.elements)
+ {
+ emplaceExp!ArrayLiteralExp(&ue, loc, type, cast(Expressions*) null);
+ return ue;
+ }
+ const length = aex.elements.length;
+ Expressions* elements = new Expressions(length);
+
+ emplaceExp!ArrayLiteralExp(&ue, loc, type, elements);
+ foreach (i; 0 .. length)
+ {
+ Expression e1x = ae1 ? ae1[i] : e1;
+ Expression e2x = ae2 ? ae2[i] : e2;
+ UnionExp uex = evaluate(loc, e1x.type, e1x, e2x);
+ // This can be made more efficient by making use of ue.basis
+ (*elements)[i] = uex.copy();
+ }
+ return ue;
+ }
+
+ if (e1.isConst() != 1)
+ {
+ // The following should really be an assert()
+ e1.error("CTFE internal error: non-constant value `%s`", e1.toChars());
+ emplaceExp!CTFEExp(&ue, TOK.cantExpression);
+ return ue;
+ }
+ if (e2.isConst() != 1)
+ {
+ e2.error("CTFE internal error: non-constant value `%s`", e2.toChars());
+ emplaceExp!CTFEExp(&ue, TOK.cantExpression);
+ return ue;
+ }
+
+ return (*fp)(loc, type, e1, e2);
+ }
+
+ *pue = evaluate(e.loc, e.type, e1, e2);
result = (*pue).exp();
if (CTFEExp.isCantExp(result))
e.error("`%s` cannot be interpreted at compile time", e.toChars());
@@ -3694,6 +3763,7 @@ public:
private Expression assignToLvalue(BinExp e, Expression e1, Expression newval)
{
+ //printf("assignToLvalue() e: %s e1: %s newval: %s\n", e.toChars(), e1.toChars(), newval.toChars());
VarDeclaration vd = null;
Expression* payload = null; // dead-store to prevent spurious warning
Expression oldval;
@@ -3786,6 +3856,17 @@ public:
Type t1b = e1.type.toBasetype();
bool wantCopy = t1b.baseElemOf().ty == Tstruct;
+ if (auto ve = newval.isVectorExp())
+ {
+ // Ensure ve is an array literal, and not a broadcast
+ if (ve.e1.op == TOK.int64 || ve.e1.op == TOK.float64) // if broadcast
+ {
+ UnionExp ue = void;
+ Expression ex = interpretVectorToArray(&ue, ve);
+ ve.e1 = (ex == ue.exp()) ? ue.copy() : ex;
+ }
+ }
+
if (newval.op == TOK.structLiteral && oldval)
{
assert(oldval.op == TOK.structLiteral || oldval.op == TOK.arrayLiteral || oldval.op == TOK.string_);
@@ -4800,12 +4881,11 @@ public:
{
// Make a virtual function call.
// Get the function from the vtable of the original class
- assert(pthis.op == TOK.classReference);
- ClassDeclaration cd = (cast(ClassReferenceExp)pthis).originalClass();
+ ClassDeclaration cd = pthis.isClassReferenceExp().originalClass();
// We can't just use the vtable index to look it up, because
// vtables for interfaces don't get populated until the glue layer.
- fd = cd.findFunc(fd.ident, cast(TypeFunction)fd.type);
+ fd = cd.findFunc(fd.ident, fd.type.isTypeFunction());
assert(fd);
}
}
@@ -4879,10 +4959,10 @@ public:
// (this is particularly important for struct constructors)
if (e.e1.op == TOK.declaration &&
e.e2.op == TOK.variable &&
- (cast(DeclarationExp)e.e1).declaration == (cast(VarExp)e.e2).var &&
- (cast(VarExp)e.e2).var.storage_class & STC.ctfe)
+ e.e1.isDeclarationExp().declaration == e.e2.isVarExp().var &&
+ e.e2.isVarExp().var.storage_class & STC.ctfe)
{
- VarExp ve = cast(VarExp)e.e2;
+ VarExp ve = e.e2.isVarExp();
VarDeclaration v = ve.var.isVarDeclaration();
ctfeGlobals.stack.push(v);
if (!v._init && !getValue(v))
@@ -4985,7 +5065,7 @@ public:
static Expression interpretVectorToArray(UnionExp* pue, VectorExp e)
{
if (auto ale = e.e1.isArrayLiteralExp())
- return ale;
+ return ale; // it's already an array literal
if (e.e1.op == TOK.int64 || e.e1.op == TOK.float64)
{
// Convert literal __vector(int) -> __vector([array])
@@ -4995,7 +5075,7 @@ public:
auto type = (e.type.ty == Tvector) ? e.type.isTypeVector().basetype : e.type.isTypeSArray();
assert(type);
emplaceExp!(ArrayLiteralExp)(pue, e.loc, type, elements);
- auto ale = cast(ArrayLiteralExp)pue.exp();
+ auto ale = pue.exp().isArrayLiteralExp();
ale.ownedByCtfe = OwnedBy.ctfe;
return ale;
}
@@ -5026,7 +5106,7 @@ public:
if (e1 == pue.exp())
e1 = pue.copy();
emplaceExp!(VectorExp)(pue, e.loc, e1, e.to);
- auto ve = cast(VectorExp)pue.exp();
+ auto ve = pue.exp().isVectorExp();
ve.type = e.type;
ve.dim = e.dim;
ve.ownedByCtfe = OwnedBy.ctfe;
@@ -5657,12 +5737,26 @@ public:
auto cre = cast(ClassReferenceExp)result;
auto cd = cre.originalClass();
- if (cd.dtor)
+ // Find dtor(s) in inheritance chain
+ do
{
- result = interpretFunction(pue, cd.dtor, istate, null, cre);
- if (exceptionOrCant(result))
- return;
- }
+ if (cd.dtor)
+ {
+ result = interpretFunction(pue, cd.dtor, istate, null, cre);
+ if (exceptionOrCant(result))
+ return;
+
+ // Dtors of Non-extern(D) classes use implicit chaining (like structs)
+ import dmd.aggregate : ClassKind;
+ if (cd.classKind != ClassKind.d)
+ break;
+ }
+
+ // Emulate manual chaining as done in rt_finalize2
+ cd = cd.baseClass;
+
+ } while (cd); // Stop after Object
+
break;
case Tpointer:
@@ -7349,6 +7443,7 @@ private void setValueWithoutChecking(VarDeclaration vd, Expression newval)
private void setValue(VarDeclaration vd, Expression newval)
{
+ //printf("setValue() vd: %s newval: %s\n", vd.toChars(), newval.toChars());
version (none)
{
if (!((vd.storage_class & (STC.out_ | STC.ref_)) ? isCtfeReferenceValid(newval) : isCtfeValueValid(newval)))
diff --git a/gcc/d/dmd/dmacro.d b/gcc/d/dmd/dmacro.d
index 3a31926fe97..ddfee2ccab0 100644
--- a/gcc/d/dmd/dmacro.d
+++ b/gcc/d/dmd/dmacro.d
@@ -1,7 +1,7 @@
/**
* Text macro processor for Ddoc.
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dmacro.d, _dmacro.d)
diff --git a/gcc/d/dmd/dmangle.d b/gcc/d/dmd/dmangle.d
index fbc52cc1175..71b8c7a6098 100644
--- a/gcc/d/dmd/dmangle.d
+++ b/gcc/d/dmd/dmangle.d
@@ -3,7 +3,7 @@
*
* Specification: $(LINK2 https://dlang.org/spec/abi.html#name_mangling, Name Mangling)
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: Walter Bright, http://www.digitalmars.com
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dmangle.d, _dmangle.d)
@@ -14,6 +14,113 @@
module dmd.dmangle;
+import dmd.astenums;
+
+/******************************************************************************
+ * Returns exact mangled name of function.
+ */
+extern (C++) const(char)* mangleExact(FuncDeclaration fd)
+{
+ if (!fd.mangleString)
+ {
+ OutBuffer buf;
+ scope Mangler v = new Mangler(&buf);
+ v.mangleExact(fd);
+ fd.mangleString = buf.extractChars();
+ }
+ return fd.mangleString;
+}
+
+extern (C++) void mangleToBuffer(Type t, OutBuffer* buf)
+{
+ if (t.deco)
+ buf.writestring(t.deco);
+ else
+ {
+ scope Mangler v = new Mangler(buf, t);
+ v.visitWithMask(t, 0);
+ }
+}
+
+extern (C++) void mangleToBuffer(Expression e, OutBuffer* buf)
+{
+ scope Mangler v = new Mangler(buf);
+ e.accept(v);
+}
+
+extern (C++) void mangleToBuffer(Dsymbol s, OutBuffer* buf)
+{
+ scope Mangler v = new Mangler(buf);
+ s.accept(v);
+}
+
+extern (C++) void mangleToBuffer(TemplateInstance ti, OutBuffer* buf)
+{
+ scope Mangler v = new Mangler(buf);
+ v.mangleTemplateInstance(ti);
+}
+
+/// Returns: `true` if the given character is a valid mangled character
+package bool isValidMangling(dchar c) nothrow
+{
+ return
+ c >= 'A' && c <= 'Z' ||
+ c >= 'a' && c <= 'z' ||
+ c >= '0' && c <= '9' ||
+ c != 0 && strchr("$%().:?@[]_", c) ||
+ isUniAlpha(c);
+}
+
+// valid mangled characters
+unittest
+{
+ assert('a'.isValidMangling);
+ assert('B'.isValidMangling);
+ assert('2'.isValidMangling);
+ assert('@'.isValidMangling);
+ assert('_'.isValidMangling);
+}
+
+// invalid mangled characters
+unittest
+{
+ assert(!'-'.isValidMangling);
+ assert(!0.isValidMangling);
+ assert(!'/'.isValidMangling);
+ assert(!'\\'.isValidMangling);
+}
+
+/**********************************************
+ * Convert a string representing a type (the deco) and
+ * return its equivalent Type.
+ * Params:
+ * deco = string containing the deco
+ * Returns:
+ * null for failed to convert
+ * Type for succeeded
+ */
+
+public Type decoToType(const(char)[] deco)
+{
+ //printf("decoToType(): %.*s\n", cast(int)deco.length, deco.ptr);
+ if (auto sv = Type.stringtable.lookup(deco))
+ {
+ if (sv.value)
+ {
+ Type t = cast(Type)sv.value;
+ assert(t.deco);
+ return t;
+ }
+ }
+ return null;
+}
+
+
+/***************************************** private ***************************************/
+
+private:
+
+
import core.stdc.ctype;
import core.stdc.stdio;
import core.stdc.string;
@@ -35,6 +142,7 @@ import dmd.root.ctfloat;
import dmd.root.outbuffer;
import dmd.root.aav;
import dmd.root.string;
+import dmd.root.stringtable;
import dmd.target;
import dmd.tokens;
import dmd.utf;
@@ -55,8 +163,7 @@ private immutable char[TMAX] mangleChar =
Tuns32 : 'k',
Tint64 : 'l',
Tuns64 : 'm',
- Tnone : 'n',
- Tnull : 'n', // yes, same as TypeNone
+ Tnull : 'n',
Timaginary32 : 'o',
Timaginary64 : 'p',
Tcomplex32 : 'q',
@@ -84,7 +191,7 @@ private immutable char[TMAX] mangleChar =
// K // ref
// L // lazy
// M // has this, or scope
- // N // Nh:vector Ng:wild
+ // N // Nh:vector Ng:wild Nn:noreturn
// O // shared
Tpointer : 'P',
// Q // Type/symbol/identifier backward reference
@@ -92,13 +199,13 @@ private immutable char[TMAX] mangleChar =
Tstruct : 'S',
// T // Ttypedef
// U // C function
- // V // Pascal function
// W // Windows function
// X // variadic T t...)
// Y // variadic T t,...)
// Z // not variadic, end of parameters
// '@' shouldn't appear anywhere in the deco'd names
+ Tnone : '@',
Tident : '@',
Tinstance : '@',
Terror : '@',
@@ -108,6 +215,8 @@ private immutable char[TMAX] mangleChar =
Tvector : '@',
Ttraits : '@',
Tmixin : '@',
+ Ttag : '@',
+ Tnoreturn : '@', // becomes 'Nn'
];
unittest
@@ -180,10 +289,12 @@ public:
AssocArray!(Type, size_t) types; // Type => (offset+1) in buf
AssocArray!(Identifier, size_t) idents; // Identifier => (offset+1) in buf
OutBuffer* buf;
+ Type rootType;
- extern (D) this(OutBuffer* buf)
+ extern (D) this(OutBuffer* buf, Type rootType = null)
{
this.buf = buf;
+ this.rootType = rootType;
}
/**
@@ -191,7 +302,7 @@ public:
* using upper case letters for all digits but the last digit which uses
* a lower case letter.
* The decoder has to look up the referenced position to determine
- * whether the back reference is an identifer (starts with a digit)
+ * whether the back reference is an identifier (starts with a digit)
* or a type (starts with a letter).
*
* Params:
@@ -229,9 +340,28 @@ public:
*/
bool backrefType(Type t)
{
- if (!t.isTypeBasic())
- return backrefImpl(types, t);
- return false;
+ if (t.isTypeBasic())
+ return false;
+
+ /**
+ * https://issues.dlang.org/show_bug.cgi?id=21591
+ *
+ * Special case for unmerged TypeFunctions: use the generic merged
+ * function type as backref cache key to avoid missed backrefs.
+ *
+ * Merging is based on mangling, so we need to avoid an infinite
+ * recursion by excluding the case where `t` is the root type passed to
+ * `mangleToBuffer()`.
+ */
+ if (t != rootType)
+ {
+ if (t.isFunction_Delegate_PtrToFunction())
+ {
+ t = t.merge2();
+ }
+ }
+
+ return backrefImpl(types, t);
}
/**
@@ -369,9 +499,6 @@ public:
case LINK.windows:
mc = 'W';
break;
- case LINK.pascal:
- mc = 'V';
- break;
case LINK.cpp:
mc = 'R';
break;
@@ -466,6 +593,11 @@ public:
visit(cast(Type)t);
}
+ override void visit(TypeNoreturn t)
+ {
+ buf.writestring("Nn");
+ }
+
////////////////////////////////////////////////////////////////////////////
void mangleDecl(Declaration sthis)
{
@@ -486,6 +618,7 @@ public:
void mangleParent(Dsymbol s)
{
+ //printf("mangleParent() %s %s\n", s.kind(), s.toChars());
Dsymbol p;
if (TemplateInstance ti = s.isTemplateInstance())
p = ti.isTemplateMixin() ? ti.parent : ti.tempdecl.parent;
@@ -493,10 +626,12 @@ public:
p = s.parent;
if (p)
{
+ uint localNum = s.localNum;
mangleParent(p);
auto ti = p.isTemplateInstance();
if (ti && !ti.isTemplateMixin())
{
+ localNum = ti.tempdecl.localNum;
mangleTemplateInstance(ti);
}
else if (p.getIdent())
@@ -507,6 +642,25 @@ public:
}
else
buf.writeByte('0');
+
+ /* There can be multiple different declarations in the same
+ * function that have the same mangled name.
+ * This results in localNum having a non-zero number, which
+ * is used to add a fake parent of the form `__Sddd` to make
+ * the mangled names unique.
+ * https://issues.dlang.org/show_bug.cgi?id=20565
+ */
+ if (localNum)
+ {
+ uint ndigits = 1;
+ auto n = localNum;
+ while (n >= 10)
+ {
+ n /= 10;
+ ++ndigits;
+ }
+ buf.printf("%u__S%u", ndigits + 3, localNum);
+ }
}
}
@@ -574,13 +728,14 @@ public:
const par = d.toParent(); //toParent() skips over mixin templates
if (!par || par.isModule() || d.linkage == LINK.cpp)
{
+ if (d.linkage != LINK.d && d.localNum)
+ d.error("the same declaration cannot be in multiple scopes with non-D linkage");
final switch (d.linkage)
{
case LINK.d:
break;
case LINK.c:
case LINK.windows:
- case LINK.pascal:
case LINK.objc:
return d.ident.toString();
case LINK.cpp:
@@ -682,7 +837,7 @@ public:
}
if (FuncDeclaration fd = od.aliassym.isFuncDeclaration())
{
- if (!od.hasOverloads || fd.isUnique())
+ if (fd.isUnique())
{
mangleExact(fd);
return;
@@ -690,7 +845,7 @@ public:
}
if (TemplateDeclaration td = od.aliassym.isTemplateDeclaration())
{
- if (!od.hasOverloads || td.overnext is null)
+ if (td.overnext is null)
{
mangleSymbol(td);
return;
@@ -1091,6 +1246,15 @@ public:
}
}
+ override void visit(FuncExp e)
+ {
+ buf.writeByte('f');
+ if (e.td)
+ mangleSymbol(e.td);
+ else
+ mangleSymbol(e.fd);
+ }
+
////////////////////////////////////////////////////////////////////////////
override void visit(Parameter p)
@@ -1131,99 +1295,3 @@ public:
visitWithMask(p.type, (p.storageClass & STC.in_) ? MODFlags.const_ : 0);
}
}
-
-/// Returns: `true` if the given character is a valid mangled character
-package bool isValidMangling(dchar c) nothrow
-{
- return
- c >= 'A' && c <= 'Z' ||
- c >= 'a' && c <= 'z' ||
- c >= '0' && c <= '9' ||
- c != 0 && strchr("$%().:?@[]_", c) ||
- isUniAlpha(c);
-}
-
-// valid mangled characters
-unittest
-{
- assert('a'.isValidMangling);
- assert('B'.isValidMangling);
- assert('2'.isValidMangling);
- assert('@'.isValidMangling);
- assert('_'.isValidMangling);
-}
-
-// invalid mangled characters
-unittest
-{
- assert(!'-'.isValidMangling);
- assert(!0.isValidMangling);
- assert(!'/'.isValidMangling);
- assert(!'\\'.isValidMangling);
-}
-
-/******************************************************************************
- * Returns exact mangled name of function.
- */
-extern (C++) const(char)* mangleExact(FuncDeclaration fd)
-{
- if (!fd.mangleString)
- {
- OutBuffer buf;
- scope Mangler v = new Mangler(&buf);
- v.mangleExact(fd);
- fd.mangleString = buf.extractChars();
- }
- return fd.mangleString;
-}
-
-extern (C++) void mangleToBuffer(Type t, OutBuffer* buf)
-{
- if (t.deco)
- buf.writestring(t.deco);
- else
- {
- scope Mangler v = new Mangler(buf);
- v.visitWithMask(t, 0);
- }
-}
-
-extern (C++) void mangleToBuffer(Expression e, OutBuffer* buf)
-{
- scope Mangler v = new Mangler(buf);
- e.accept(v);
-}
-
-extern (C++) void mangleToBuffer(Dsymbol s, OutBuffer* buf)
-{
- scope Mangler v = new Mangler(buf);
- s.accept(v);
-}
-
-extern (C++) void mangleToBuffer(TemplateInstance ti, OutBuffer* buf)
-{
- scope Mangler v = new Mangler(buf);
- v.mangleTemplateInstance(ti);
-}
-
-/******************************************************************************
- * Mangle function signatures ('this' qualifier, and parameter types)
- * to check conflicts in function overloads.
- * It's different from fd.type.deco. For example, fd.type.deco would be null
- * if fd is an auto function.
- *
- * Params:
- * buf = `OutBuffer` to write the mangled function signature to
-* fd = `FuncDeclaration` to mangle
- */
-void mangleToFuncSignature(ref OutBuffer buf, FuncDeclaration fd)
-{
- auto tf = fd.type.isTypeFunction();
-
- scope Mangler v = new Mangler(&buf);
-
- MODtoDecoBuffer(&buf, tf.mod);
- foreach (idx, param; tf.parameterList)
- param.accept(v);
- buf.writeByte('Z' - tf.parameterList.varargs);
-}
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 504c7bc09d6..841fff6c485 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -3,7 +3,7 @@
*
* Specification: $(LINK2 https://dlang.org/spec/module.html, Modules)
*
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dmodule.d, _dmodule.d)
@@ -19,6 +19,7 @@ import core.stdc.string;
import dmd.aggregate;
import dmd.arraytypes;
import dmd.astcodegen;
+import dmd.astenums;
import dmd.compiler;
import dmd.gluelayer;
import dmd.dimport;
@@ -34,6 +35,8 @@ import dmd.globals;
import dmd.id;
import dmd.identifier;
import dmd.parse;
+import dmd.cparse;
+import dmd.root.array;
import dmd.root.file;
import dmd.root.filename;
import dmd.root.outbuffer;
@@ -43,79 +46,96 @@ import dmd.root.rootobject;
import dmd.root.string;
import dmd.semantic2;
import dmd.semantic3;
+import dmd.target;
+import dmd.utils;
import dmd.visitor;
-version(Windows) {
- extern (C) char* getcwd(char* buffer, size_t maxlen);
-} else {
- import core.sys.posix.unistd : getcwd;
-}
+enum package_d = "package." ~ mars_ext;
+enum package_di = "package." ~ hdr_ext;
-/* =========================== ===================== */
/********************************************
* Look for the source file if it's different from filename.
* Look for .di, .d, directory, and along global.path.
* Does not open the file.
- * Input:
- * filename as supplied by the user
- * global.path
+ * Params:
+ * filename = as supplied by the user
+ * path = path to look for filename
* Returns:
- * NULL if it's not different from filename.
+ * the found file name or
+ * `null` if it is not different from filename.
*/
-private const(char)[] lookForSourceFile(const(char)[] filename)
+private const(char)[] lookForSourceFile(const char[] filename, const char*[] path)
{
- /* Search along global.path for .di file, then .d file.
+ //printf("lookForSourceFile(`%.*s`)\n", cast(int)filename.length, filename.ptr);
+ /* Search along path[] for .di file, then .d file.
*/
- const sdi = FileName.forceExt(filename, global.hdr_ext);
+ const sdi = FileName.forceExt(filename, hdr_ext);
if (FileName.exists(sdi) == 1)
return sdi;
scope(exit) FileName.free(sdi.ptr);
- const sd = FileName.forceExt(filename, global.mars_ext);
+
+ const sd = FileName.forceExt(filename, mars_ext);
if (FileName.exists(sd) == 1)
return sd;
scope(exit) FileName.free(sd.ptr);
+
+ const sc = FileName.forceExt(filename, c_ext);
+ if (FileName.exists(sc) == 1)
+ return sc;
+ scope(exit) FileName.free(sc.ptr);
+
if (FileName.exists(filename) == 2)
{
/* The filename exists and it's a directory.
* Therefore, the result should be: filename/package.d
* iff filename/package.d is a file
*/
- const ni = FileName.combine(filename, "package.di");
+ const ni = FileName.combine(filename, package_di);
if (FileName.exists(ni) == 1)
return ni;
FileName.free(ni.ptr);
- const n = FileName.combine(filename, "package.d");
+
+ const n = FileName.combine(filename, package_d);
if (FileName.exists(n) == 1)
return n;
FileName.free(n.ptr);
}
if (FileName.absolute(filename))
return null;
- if (!global.path)
+ if (!path.length)
return null;
- for (size_t i = 0; i < global.path.dim; i++)
+ foreach (entry; path)
{
- const p = (*global.path)[i].toDString();
+ const p = entry.toDString();
+
const(char)[] n = FileName.combine(p, sdi);
if (FileName.exists(n) == 1) {
return n;
}
FileName.free(n.ptr);
+
n = FileName.combine(p, sd);
if (FileName.exists(n) == 1) {
return n;
}
FileName.free(n.ptr);
+
+ n = FileName.combine(p, sc);
+ if (FileName.exists(n) == 1) {
+ return n;
+ }
+ FileName.free(n.ptr);
+
const b = FileName.removeExt(filename);
n = FileName.combine(p, b);
FileName.free(b.ptr);
if (FileName.exists(n) == 2)
{
- const n2i = FileName.combine(n, "package.di");
+ const n2i = FileName.combine(n, package_di);
if (FileName.exists(n2i) == 1)
return n2i;
FileName.free(n2i.ptr);
- const n2 = FileName.combine(n, "package.d");
+ const n2 = FileName.combine(n, package_d);
if (FileName.exists(n2) == 1) {
return n2;
}
@@ -169,11 +189,11 @@ void removeHdrFilesAndFail(ref Param params, ref Modules modules)
* Returns:
* the filename of the child package or module
*/
-private const(char)[] getFilename(Identifiers* packages, Identifier ident)
+private const(char)[] getFilename(Identifier[] packages, Identifier ident)
{
const(char)[] filename = ident.toString();
- if (packages == null || packages.dim == 0)
+ if (packages.length == 0)
return filename;
OutBuffer buf;
@@ -203,7 +223,7 @@ private const(char)[] getFilename(Identifiers* packages, Identifier ident)
dotmods.writeByte('.');
}
- foreach (pid; *packages)
+ foreach (pid; packages)
{
const p = pid.toString();
buf.writestring(p);
@@ -224,13 +244,6 @@ private const(char)[] getFilename(Identifiers* packages, Identifier ident)
return filename;
}
-enum PKG : int
-{
- unknown, // not yet determined whether it's a package.d or not
- module_, // already determined that's an actual package.d
- package_, // already determined that's an actual package
-}
-
/***********************************************************
*/
extern (C++) class Package : ScopeDsymbol
@@ -269,52 +282,49 @@ extern (C++) class Package : ScopeDsymbol
* *pparent the rightmost package, i.e. pkg2, or NULL if no packages
* *ppkg the leftmost package, i.e. pkg1, or NULL if no packages
*/
- extern (D) static DsymbolTable resolve(Identifiers* packages, Dsymbol* pparent, Package* ppkg)
+ extern (D) static DsymbolTable resolve(Identifier[] packages, Dsymbol* pparent, Package* ppkg)
{
DsymbolTable dst = Module.modules;
Dsymbol parent = null;
//printf("Package::resolve()\n");
if (ppkg)
*ppkg = null;
- if (packages)
+ foreach (pid; packages)
{
- for (size_t i = 0; i < packages.dim; i++)
+ Package pkg;
+ Dsymbol p = dst.lookup(pid);
+ if (!p)
{
- Identifier pid = (*packages)[i];
- Package pkg;
- Dsymbol p = dst.lookup(pid);
- if (!p)
- {
- pkg = new Package(Loc.initial, pid);
- dst.insert(pkg);
- pkg.parent = parent;
+ pkg = new Package(Loc.initial, pid);
+ dst.insert(pkg);
+ pkg.parent = parent;
+ pkg.symtab = new DsymbolTable();
+ }
+ else
+ {
+ pkg = p.isPackage();
+ assert(pkg);
+ // It might already be a module, not a package, but that needs
+ // to be checked at a higher level, where a nice error message
+ // can be generated.
+ // dot net needs modules and packages with same name
+ // But we still need a symbol table for it
+ if (!pkg.symtab)
pkg.symtab = new DsymbolTable();
- }
- else
- {
- pkg = p.isPackage();
- assert(pkg);
- // It might already be a module, not a package, but that needs
- // to be checked at a higher level, where a nice error message
- // can be generated.
- // dot net needs modules and packages with same name
- // But we still need a symbol table for it
- if (!pkg.symtab)
- pkg.symtab = new DsymbolTable();
- }
- parent = pkg;
- dst = pkg.symtab;
- if (ppkg && !*ppkg)
- *ppkg = pkg;
- if (pkg.isModule())
- {
- // Return the module so that a nice error message can be generated
- if (ppkg)
- *ppkg = cast(Package)p;
- break;
- }
+ }
+ parent = pkg;
+ dst = pkg.symtab;
+ if (ppkg && !*ppkg)
+ *ppkg = pkg;
+ if (pkg[...]
[diff truncated at 524288 bytes]
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-07-30 8:44 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-30 8:44 [gcc(refs/users/ibuclaw/heads/gdc)] Import dmd v2.097.0: dmd 2a48c54ad, druntime c3a4c517, phobos 61c00065a Iain Buclaw
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).