From f70a51a18c972c7918927020ac9e4f486cf1b970 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 22 Apr 2017 01:45:03 +0200 Subject: [PATCH 01/19] Merge 2.074.0 front-end --- CMakeLists.txt | 14 +- ddmd/access.d | 2 +- ddmd/aggregate.d | 31 +-- ddmd/aliasthis.d | 2 +- ddmd/apply.d | 2 +- ddmd/argtypes.d | 2 +- ddmd/arrayop.d | 6 +- ddmd/arraytypes.d | 2 +- ddmd/asttypename.d | 115 ++++++++++++ ddmd/attrib.d | 2 +- ddmd/builtin.d | 2 +- ddmd/canthrow.d | 4 +- ddmd/clone.d | 15 +- ddmd/complex.d | 2 +- ddmd/cond.d | 7 +- ddmd/constfold.d | 28 ++- ddmd/cppmangle.d | 2 +- ddmd/ctfeexpr.d | 2 +- ddmd/dcast.d | 2 +- ddmd/dclass.d | 7 +- ddmd/declaration.d | 13 +- ddmd/declaration.h | 17 +- ddmd/delegatize.d | 2 +- ddmd/denum.d | 5 +- ddmd/dimport.d | 2 +- ddmd/dinifile.d | 2 +- ddmd/dinterpret.d | 5 +- ddmd/dmacro.d | 2 +- ddmd/dmangle.d | 4 +- ddmd/dmodule.d | 2 +- ddmd/doc.d | 6 +- ddmd/dscope.d | 2 +- ddmd/dstruct.d | 2 +- ddmd/dsymbol.d | 16 +- ddmd/dsymbol.h | 5 +- ddmd/dtemplate.d | 206 +++++++++++++++----- ddmd/dversion.d | 2 +- ddmd/entity.d | 6 +- ddmd/errors.d | 2 +- ddmd/escape.d | 45 +++-- ddmd/expression.d | 133 ++++++++++--- ddmd/expression.h | 3 +- ddmd/func.d | 322 +++++++------------------------- ddmd/globals.d | 24 +-- ddmd/globals.h | 12 +- ddmd/gluelayer.d | 12 +- ddmd/hdrgen.d | 83 ++++++-- ddmd/identifier.d | 6 +- ddmd/identifier.h | 2 +- ddmd/idgen.d | 11 +- ddmd/impcnvtab.d | 2 +- ddmd/imphint.d | 2 +- ddmd/import.h | 3 +- ddmd/init.d | 4 +- ddmd/inline.d | 2 +- ddmd/intrange.d | 2 +- ddmd/json.d | 2 +- ddmd/lexer.d | 43 +++-- ddmd/mars.d | 40 +++- ddmd/module.h | 1 + ddmd/mtype.d | 248 ++++++++++++++++++------ ddmd/mtype.h | 11 +- ddmd/nogc.d | 2 +- ddmd/nspace.d | 2 +- ddmd/objc.d | 2 +- ddmd/opover.d | 2 +- ddmd/optimize.d | 2 +- ddmd/parse.d | 38 ++-- ddmd/root/aav.d | 2 +- ddmd/root/array.d | 2 +- ddmd/root/array.h | 12 +- ddmd/root/ctfloat.d | 12 +- ddmd/root/file.d | 2 +- ddmd/root/filename.d | 2 +- ddmd/root/hash.d | 67 +++++++ ddmd/root/man.d | 2 +- ddmd/root/object.h | 14 +- ddmd/root/outbuffer.d | 2 +- ddmd/root/port.d | 2 +- ddmd/root/rmem.d | 2 +- ddmd/root/rootobject.d | 23 ++- ddmd/root/speller.d | 2 +- ddmd/root/stringtable.d | 51 +---- ddmd/root/stringtable.h | 2 + ddmd/safe.d | 2 +- ddmd/sapply.d | 2 +- ddmd/scope.h | 2 +- ddmd/sideeffect.d | 2 +- ddmd/statement.d | 7 +- ddmd/statement.h | 4 + ddmd/statement_rewrite_walker.d | 265 ++++++++++++++++++++++++++ ddmd/statementsem.d | 149 +++++++-------- ddmd/staticassert.d | 2 +- ddmd/target.d | 20 +- ddmd/target.h | 1 + ddmd/template.h | 2 +- ddmd/tokens.d | 2 +- ddmd/traits.d | 82 ++++---- ddmd/typinf.d | 2 +- ddmd/utf.d | 2 +- ddmd/utils.d | 2 +- ddmd/visitor.d | 2 +- gen/pragma.cpp | 4 +- gen/target.cpp | 1 + runtime/druntime | 2 +- runtime/phobos | 2 +- tests/d2/dmd-testsuite | 2 +- 107 files changed, 1561 insertions(+), 810 deletions(-) create mode 100644 ddmd/asttypename.d create mode 100644 ddmd/root/hash.d create mode 100644 ddmd/statement_rewrite_walker.d diff --git a/CMakeLists.txt b/CMakeLists.txt index d8aed899ba9..e0f05bc0bd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,11 +46,11 @@ endfunction() # # Version information -set(LDC_VERSION "1.3.0") # May be overridden by git hash tag +set(LDC_VERSION "1.4.0") # May be overridden by git hash tag set(DMDFE_MAJOR_VERSION 2) set(DMDFE_MINOR_VERSION 0) -set(DMDFE_PATCH_VERSION 73) -set(DMDFE_FIX_LEVEL 2) # Comment out if not used +set(DMDFE_PATCH_VERSION 74) +set(DMDFE_FIX_LEVEL 0) # Comment out if not used set(DMD_VERSION ${DMDFE_MAJOR_VERSION}.${DMDFE_MINOR_VERSION}${DMDFE_PATCH_VERSION}) if(DEFINED DMDFE_FIX_LEVEL) @@ -263,15 +263,15 @@ endmacro() # # Build idgen. # -build_idgen(${DDMDFE_PATH}/idgen.d ${PROJECT_BINARY_DIR}/${DDMDFE_PATH}/idgen${CMAKE_EXECUTABLE_SUFFIX} ${DDMD_DFLAGS} "" "") +build_idgen(${DDMDFE_PATH}/idgen.d ${PROJECT_BINARY_DIR}/idgen${CMAKE_EXECUTABLE_SUFFIX} ${DDMD_DFLAGS} "" "") # Run idgen. add_custom_command( OUTPUT ${PROJECT_BINARY_DIR}/${DDMDFE_PATH}/id.d ${PROJECT_BINARY_DIR}/${DDMDFE_PATH}/id.h - COMMAND ${PROJECT_BINARY_DIR}/${DDMDFE_PATH}/idgen #provide full path to avoid clash with idgen on path - WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/${DDMDFE_PATH} - DEPENDS ${PROJECT_BINARY_DIR}/${DDMDFE_PATH}/idgen${CMAKE_EXECUTABLE_SUFFIX} + COMMAND ${PROJECT_BINARY_DIR}/idgen #provide full path to avoid clash with idgen on path + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${PROJECT_BINARY_DIR}/idgen${CMAKE_EXECUTABLE_SUFFIX} ) set(LDC_CXX_GENERATED ${PROJECT_BINARY_DIR}/${DDMDFE_PATH}/id.h diff --git a/ddmd/access.d b/ddmd/access.d index 4679819378e..cbdf9e60364 100644 --- a/ddmd/access.d +++ b/ddmd/access.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _access.d) diff --git a/ddmd/aggregate.d b/ddmd/aggregate.d index 026dee13f69..3c06de41cfb 100644 --- a/ddmd/aggregate.d +++ b/ddmd/aggregate.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _aggregate.d) @@ -232,6 +232,8 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol return true; //printf("determineFields() %s, fields.dim = %d\n", toChars(), fields.dim); + // determineFields can be called recursively from one of the fields's v.semantic + fields.setDim(0); extern (C++) static int func(Dsymbol s, void* param) { @@ -241,8 +243,14 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol if (v.storage_class & STCmanifest) return 0; + auto ad = cast(AggregateDeclaration)param; + if (v._scope) v.semantic(null); + // Return in case a recursive determineFields triggered by v.semantic already finished + if (ad.sizeok != SIZEOKnone) + return 1; + if (v.aliassym) return 0; // If this variable was really a tuple, skip it. @@ -251,18 +259,6 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol if (!v.isField() || v.semanticRun < PASSsemanticdone) return 1; // unresolvable forward reference - auto ad = cast(AggregateDeclaration)param; - version(IN_LLVM) - { - for (size_t i = 0; i < ad.fields.dim; i++) - { - if (ad.fields[i] == v) - { - // already a field - return 0; - } - } - } ad.fields.push(v); if (v.storage_class & STCref) @@ -281,13 +277,18 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol return 0; } - fields.setDim(0); - for (size_t i = 0; i < members.dim; i++) { auto s = (*members)[i]; if (s.apply(&func, cast(void*)this)) + { + if (sizeok != SIZEOKnone) + { + // recursive determineFields already finished + return true; + } return false; + } } if (sizeok != SIZEOKdone) diff --git a/ddmd/aliasthis.d b/ddmd/aliasthis.d index 24d4f7a08de..5c4d604eba7 100644 --- a/ddmd/aliasthis.d +++ b/ddmd/aliasthis.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _aliasthis.d) diff --git a/ddmd/apply.d b/ddmd/apply.d index 30d0f9751f8..372369c3968 100644 --- a/ddmd/apply.d +++ b/ddmd/apply.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _apply.d) diff --git a/ddmd/argtypes.d b/ddmd/argtypes.d index 3b18483fa3f..0bc94dbb9bc 100644 --- a/ddmd/argtypes.d +++ b/ddmd/argtypes.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _argtypes.d) diff --git a/ddmd/arrayop.d b/ddmd/arrayop.d index c6cd0511143..b16c03ca6c0 100644 --- a/ddmd/arrayop.d +++ b/ddmd/arrayop.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _arrayop.d) @@ -321,7 +321,7 @@ extern (C++) void buildArrayIdent(Expression e, OutBuffer* buf, Expressions* arg switch (e.op) { case TOKaddass: s = "Addass"; break; - case TOKminass: s = "Subass"; break; + case TOKminass: s = "Minass"; break; case TOKmulass: s = "Mulass"; break; case TOKdivass: s = "Divass"; break; case TOKmodass: s = "Modass"; break; @@ -355,7 +355,7 @@ extern (C++) void buildArrayIdent(Expression e, OutBuffer* buf, Expressions* arg switch (e.op) { case TOKadd: s = "Add"; break; - case TOKmin: s = "Sub"; break; + case TOKmin: s = "Min"; break; case TOKmul: s = "Mul"; break; case TOKdiv: s = "Div"; break; case TOKmod: s = "Mod"; break; diff --git a/ddmd/arraytypes.d b/ddmd/arraytypes.d index fc351ee06e6..df288ea97cc 100644 --- a/ddmd/arraytypes.d +++ b/ddmd/arraytypes.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _arraytypes.d) diff --git a/ddmd/asttypename.d b/ddmd/asttypename.d new file mode 100644 index 00000000000..3b5b381a6ad --- /dev/null +++ b/ddmd/asttypename.d @@ -0,0 +1,115 @@ +/** + * Part of the Compiler implementation of the D programming language + * Copyright: Copyright (c) 1999-2017 by The D Language Foundation, All Rights Reserved + * Authors: Stefan Koch + * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) + * Source: $(DMDSRC _asttypename.d) + */ + +module ddmd.asttypename; + +import ddmd.attrib; +import ddmd.aliasthis; +import ddmd.aggregate; +import ddmd.complex; +import ddmd.cond; +import ddmd.ctfeexpr; +import ddmd.dclass; +import ddmd.declaration; +import ddmd.denum; +import ddmd.dimport; +import ddmd.declaration; +import ddmd.dstruct; +import ddmd.dsymbol; +import ddmd.dtemplate; +import ddmd.dversion; +import ddmd.expression; +import ddmd.func; +import ddmd.denum; +import ddmd.dimport; +import ddmd.dmodule; +import ddmd.mtype; +import ddmd.typinf; +import ddmd.identifier; +import ddmd.init; +import ddmd.doc; +import ddmd.root.rootobject; +import ddmd.statement; +import ddmd.staticassert; +import ddmd.nspace; +import ddmd.visitor; + +/// Returns: the typename of the dynamic ast-node-type +/// (this is a development tool, do not use in actual code) +string astTypeName(RootObject node) +{ + final switch (node.dyncast()) + { + case DYNCAST.object: + return "RootObject"; + case DYNCAST.identifier: + return "Identifier"; + + case DYNCAST.expression: + return astTypeName(cast(Expression) node); + case DYNCAST.dsymbol: + return astTypeName(cast(Dsymbol) node); + case DYNCAST.type: + return astTypeName(cast(Type) node); + case DYNCAST.tuple: + return astTypeName(cast(Tuple) node); + case DYNCAST.parameter: + return astTypeName(cast(Parameter) node); + case DYNCAST.statement: + return astTypeName(cast(Statement) node); + case DYNCAST.condition: + return astTypeName(cast(Condition) node); + } +} + +mixin +({ + string astTypeNameFunctions; + string visitOverloads; + + foreach (ov; __traits(getOverloads, Visitor, "visit")) + { + static if (is(typeof(ov) P == function)) + { + static if (is(P[0] S == super) && is(S[0] == RootObject)) + { + astTypeNameFunctions ~= ` +string astTypeName(` ~ P[0].stringof ~ ` node) +{ + scope tsv = new AstTypeNameVisitor; + node.accept(tsv); + return tsv.typeName; +} +`; + } + + visitOverloads ~= ` + override void visit (` ~ P[0].stringof ~ ` _) + { + typeName = "` ~ P[0].stringof ~ `"; + } +`; + } + } + + return astTypeNameFunctions ~ ` +extern(C++) final class AstTypeNameVisitor : Visitor +{ + alias visit = super.visit; +public : + string typeName; +` ~ visitOverloads ~ "}"; +}()); + +/// +unittest +{ + import ddmd.globals : Loc; + Expression e = new TypeidExp(Loc.init, null); + assert(e.astTypeName == "TypeidExp"); +} diff --git a/ddmd/attrib.d b/ddmd/attrib.d index d5d5facdfc8..5359a60714a 100644 --- a/ddmd/attrib.d +++ b/ddmd/attrib.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _attrib.d) diff --git a/ddmd/builtin.d b/ddmd/builtin.d index cba159e6924..f37c26b73a1 100644 --- a/ddmd/builtin.d +++ b/ddmd/builtin.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _builtin.d) diff --git a/ddmd/canthrow.d b/ddmd/canthrow.d index 8349a4f5f3b..0f1294834d8 100644 --- a/ddmd/canthrow.d +++ b/ddmd/canthrow.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _canthrow.d) @@ -294,7 +294,7 @@ extern (C++) bool Dsymbol_canThrow(Dsymbol s, FuncDeclaration func, bool mustNot for (size_t i = 0; i < td.objects.dim; i++) { RootObject o = (*td.objects)[i]; - if (o.dyncast() == DYNCAST_EXPRESSION) + if (o.dyncast() == DYNCAST.expression) { Expression eo = cast(Expression)o; if (eo.op == TOKdsymbol) diff --git a/ddmd/clone.d b/ddmd/clone.d index 7b9f425637f..0421d5a602e 100644 --- a/ddmd/clone.d +++ b/ddmd/clone.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _clone.d) @@ -782,7 +782,7 @@ extern (C++) FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc) stc |= sd.postblits[i].storage_class & STCdisable; } - Statements* a = null; + auto a = new Statements(); for (size_t i = 0; i < sd.fields.dim && !(stc & STCdisable); i++) { auto v = sd.fields[i]; @@ -803,11 +803,9 @@ extern (C++) FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc) stc = mergeFuncAttrs(stc, sdv.dtor); if (stc & STCdisable) { - a = null; + a.setDim(0); break; } - if (!a) - a = new Statements(); Expression ex; tv = v.type.toBasetype(); @@ -918,15 +916,14 @@ extern (C++) FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc) a.push(new OnScopeStatement(loc, TOKon_scope_failure, new ExpStatement(loc, ex))); } - /* Build our own "postblit" which executes a - */ - if (a || (stc & STCdisable)) + // Build our own "postblit" which executes a, but only if needed. + if (a.dim || (stc & STCdisable)) { //printf("Building __fieldPostBlit()\n"); auto dd = new PostBlitDeclaration(declLoc, Loc(), stc, Id.__fieldPostblit); dd.generated = true; dd.storage_class |= STCinference; - dd.fbody = a ? new CompoundStatement(loc, a) : null; + dd.fbody = (stc & STCdisable) ? null : new CompoundStatement(loc, a); sd.postblits.shift(dd); sd.members.push(dd); dd.semantic(sc); diff --git a/ddmd/complex.d b/ddmd/complex.d index 87122e914c8..7e26f419309 100644 --- a/ddmd/complex.d +++ b/ddmd/complex.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _complex.d) diff --git a/ddmd/cond.d b/ddmd/cond.d index b04f85df9a7..8efb4549f2f 100644 --- a/ddmd/cond.d +++ b/ddmd/cond.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _cond.d) @@ -38,6 +38,11 @@ extern (C++) abstract class Condition : RootObject // 2: do not include int inc; + override final DYNCAST dyncast() const + { + return DYNCAST.condition; + } + final extern (D) this(Loc loc) { this.loc = loc; diff --git a/ddmd/constfold.d b/ddmd/constfold.d index 2e116181ead..6e53a36492e 100644 --- a/ddmd/constfold.d +++ b/ddmd/constfold.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _constfold.d) @@ -449,6 +449,22 @@ extern (C++) UnionExp Div(Loc loc, Type type, Expression e1, Expression e2) e2.error("divide by 0"); n2 = 1; } + if (n2 == -1 && !type.isunsigned()) + { + // Check for int.min / -1 + if (n1 == 0xFFFFFFFF80000000UL && type.toBasetype().ty != Tint64) + { + e2.error("integer overflow: int.min / -1"); + emplaceExp!(ErrorExp)(&ue); + return ue; + } + else if (n1 == 0x8000000000000000L) // long.min / -1 + { + e2.error("integer overflow: long.min / -1"); + emplaceExp!(ErrorExp)(&ue); + return ue; + } + } if (e1.type.isunsigned() || e2.type.isunsigned()) n = (cast(dinteger_t)n1) / (cast(dinteger_t)n2); else @@ -502,13 +518,15 @@ extern (C++) UnionExp Mod(Loc loc, Type type, Expression e1, Expression e2) // Check for int.min % -1 if (n1 == 0xFFFFFFFF80000000UL && type.toBasetype().ty != Tint64) { - e2.error("integer overflow: int.min % -1"); - n2 = 1; + e2.error("integer overflow: int.min %% -1"); + emplaceExp!(ErrorExp)(&ue); + return ue; } else if (n1 == 0x8000000000000000L) // long.min % -1 { - e2.error("integer overflow: long.min % -1"); - n2 = 1; + e2.error("integer overflow: long.min %% -1"); + emplaceExp!(ErrorExp)(&ue); + return ue; } } if (e1.type.isunsigned() || e2.type.isunsigned()) diff --git a/ddmd/cppmangle.d b/ddmd/cppmangle.d index 0301a3714e6..5a53176063a 100644 --- a/ddmd/cppmangle.d +++ b/ddmd/cppmangle.d @@ -1,7 +1,7 @@ /** * Compiler implementation of the $(LINK2 http://www.dlang.org, D programming language) * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _cppmangle.d) diff --git a/ddmd/ctfeexpr.d b/ddmd/ctfeexpr.d index 64dc94da5f1..17e643cf14a 100644 --- a/ddmd/ctfeexpr.d +++ b/ddmd/ctfeexpr.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _ctfeexpr.d) diff --git a/ddmd/dcast.d b/ddmd/dcast.d index ede38075e16..c0790da49a8 100644 --- a/ddmd/dcast.d +++ b/ddmd/dcast.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _dcast.d) diff --git a/ddmd/dclass.d b/ddmd/dclass.d index 9a167b81c80..490be4493ee 100644 --- a/ddmd/dclass.d +++ b/ddmd/dclass.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _dclass.d) @@ -922,12 +922,15 @@ extern (C++) class ClassDeclaration : AggregateDeclaration // this() { } if (!ctor && baseClass && baseClass.ctor) { - auto fd = resolveFuncCall(loc, sc2, baseClass.ctor, null, null, null, 1); + auto fd = resolveFuncCall(loc, sc2, baseClass.ctor, null, type, null, 1); + if (!fd) // try shared base ctor instead + fd = resolveFuncCall(loc, sc2, baseClass.ctor, null, type.sharedOf, null, 1); if (fd && !fd.errors) { //printf("Creating default this(){} for class %s\n", toChars()); auto btf = cast(TypeFunction)fd.type; auto tf = new TypeFunction(null, null, 0, LINKd, fd.storage_class); + tf.mod = btf.mod; tf.purity = btf.purity; tf.isnothrow = btf.isnothrow; tf.isnogc = btf.isnogc; diff --git a/ddmd/declaration.d b/ddmd/declaration.d index 7c58220f67c..8651e846454 100644 --- a/ddmd/declaration.d +++ b/ddmd/declaration.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _declaration.d) @@ -393,7 +393,7 @@ extern (C++) final class TupleDeclaration : Declaration for (size_t i = 0; i < objects.dim; i++) { RootObject o = (*objects)[i]; - if (o.dyncast() != DYNCAST_TYPE) + if (o.dyncast() != DYNCAST.type) { //printf("\tnot[%d], %p, %d\n", i, o, o.dyncast()); return null; @@ -456,7 +456,7 @@ extern (C++) final class TupleDeclaration : Declaration for (size_t i = 0; i < objects.dim; i++) { RootObject o = (*objects)[i]; - if (o.dyncast() == DYNCAST_EXPRESSION) + if (o.dyncast() == DYNCAST.expression) { Expression e = cast(Expression)o; if (e.op == TOKdsymbol) @@ -1857,7 +1857,7 @@ extern (C++) class VarDeclaration : Declaration for (size_t i = 0; i < v2.objects.dim; i++) { RootObject o = (*v2.objects)[i]; - assert(o.dyncast() == DYNCAST_EXPRESSION); + assert(o.dyncast() == DYNCAST.expression); Expression e = cast(Expression)o; assert(e.op == TOKdsymbol); DsymbolExp se = cast(DsymbolExp)e; @@ -2064,7 +2064,8 @@ extern (C++) class VarDeclaration : Declaration version (none) { printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars()); - printf("%llx, isModule: %p, isTemplateInstance: %p\n", storage_class & (STCstatic | STCconst), parent.isModule(), parent.isTemplateInstance()); + printf("%llx, isModule: %p, isTemplateInstance: %p, isNspace: %p\n", + storage_class & (STCstatic | STCconst), parent.isModule(), parent.isTemplateInstance(), parent.isNspace()); printf("parent = '%s'\n", parent.toChars()); } @@ -2084,7 +2085,7 @@ extern (C++) class VarDeclaration : Declaration type = Type.terror; } else if (storage_class & (STCstatic | STCextern | STCtls | STCgshared) || - parent.isModule() || parent.isTemplateInstance()) + parent.isModule() || parent.isTemplateInstance() || parent.isNspace()) { isdataseg = 1; // It is in the DataSegment } diff --git a/ddmd/declaration.h b/ddmd/declaration.h index 2ed170e9200..b57c0a79a24 100644 --- a/ddmd/declaration.h +++ b/ddmd/declaration.h @@ -57,7 +57,7 @@ enum PINLINE; #define STCout 0x1000LL // out parameter #define STClazy 0x2000LL // lazy parameter #define STCforeach 0x4000LL // variable for foreach loop -#define STCvariadic 0x10000LL // variadic function argument +#define STCvariadic 0x10000LL // the 'variadic' parameter in: T foo(T a, U b, V variadic...) #define STCctorinit 0x20000LL // can only be set inside constructor #define STCtemplateparameter 0x40000LL // template parameter #define STCscope 0x80000LL @@ -90,9 +90,11 @@ enum PINLINE; #define STCrvalue 0x20000000000LL // force rvalue for variables #define STCnogc 0x40000000000LL // @nogc #define STCvolatile 0x80000000000LL // destined for volatile in the back end -#define STCreturn 0x100000000000LL // 'return ref' for function parameters +#define STCreturn 0x100000000000LL // 'return ref' or 'return scope' for function parameters #define STCautoref 0x200000000000LL // Mark for the already deduced 'auto ref' parameter #define STCinference 0x400000000000LL // do attribute inference +#define STCexptemp 0x800000000000LL // temporary variable that has lifetime restricted to an expression +#define STCmaybescope 0x1000000000000LL // parameter might be 'scope' const StorageClass STCStorageClass = (STCauto | STCscope | STCstatic | STCextern | STCconst | STCfinal | STCabstract | STCsynchronized | STCdeprecated | STCoverride | STClazy | STCalias | @@ -205,6 +207,7 @@ class AliasDeclaration : public Declaration Type *getType(); Dsymbol *toAlias(); Dsymbol *toAlias2(); + bool isOverloadable(); AliasDeclaration *isAliasDeclaration() { return this; } void accept(Visitor *v) { v->visit(this); } @@ -226,6 +229,7 @@ class OverDeclaration : public Declaration Dsymbol *toAlias(); Dsymbol *isUnique(); + bool isOverloadable(); OverDeclaration *isOverDeclaration() { return this; } void accept(Visitor *v) { v->visit(this); } @@ -280,8 +284,10 @@ class VarDeclaration : public Declaration bool hasPointers(); bool canTakeAddressOf(); bool needsScopeDtor(); + bool enclosesLifetimeOf(VarDeclaration *v) const; Expression *callScopeDtor(Scope *sc); Expression *getConstInitializer(bool needFullType = true); + Expression *expandInitializer(Loc loc); void checkCtorConstInit(); bool checkNestedReference(Scope *sc, Loc loc); Dsymbol *toAlias(); @@ -484,6 +490,8 @@ void builtin_init(); #define FUNCFLAGnothrowInprocess 4 // working on determining nothrow #define FUNCFLAGnogcInprocess 8 // working on determining @nogc #define FUNCFLAGreturnInprocess 0x10 // working on inferring 'return' for parameters +#define FUNCFLAGinlineScanned 0x20 // function has been scanned for inline possibilities +#define FUNCFLAGinferScope 0x40 // infer 'scope' for parameters class FuncDeclaration : public Declaration { @@ -597,15 +605,17 @@ class FuncDeclaration : public Declaration void semantic3(Scope *sc); bool functionSemantic(); bool functionSemantic3(); + bool checkForwardRef(Loc loc); // called from semantic3 VarDeclaration *declareThis(Scope *sc, AggregateDeclaration *ad); bool equals(RootObject *o); int overrides(FuncDeclaration *fd); int findVtblIndex(Dsymbols *vtbl, int dim); + BaseClass *overrideInterface(); bool overloadInsert(Dsymbol *s); FuncDeclaration *overloadExactMatch(Type *t); - FuncDeclaration *overloadModMatch(Loc loc, Type *tthis, Type *&t); + FuncDeclaration *overloadModMatch(Loc loc, Type *tthis, bool &hasOverloads); TemplateDeclaration *findTemplateDeclRoot(); bool inUnittest(); MATCH leastAsSpecialized(FuncDeclaration *g); @@ -662,6 +672,7 @@ class FuncDeclaration : public Declaration 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); + void checkDmain(); FuncDeclaration *isFuncDeclaration() { return this; } diff --git a/ddmd/delegatize.d b/ddmd/delegatize.d index ea9fe85efde..760de171fb1 100644 --- a/ddmd/delegatize.d +++ b/ddmd/delegatize.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _delegatize.d) diff --git a/ddmd/denum.d b/ddmd/denum.d index ba54cf1325f..43b9671abcb 100644 --- a/ddmd/denum.d +++ b/ddmd/denum.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _denum.d) @@ -11,6 +11,7 @@ module ddmd.denum; import core.stdc.stdio; +import ddmd.root.rootobject; import ddmd.gluelayer; import ddmd.declaration; import ddmd.dmodule; @@ -585,7 +586,7 @@ extern (C++) final class EnumMember : VarDeclaration if (value) { Expression e = value; - assert(e.dyncast() == DYNCAST_EXPRESSION); + assert(e.dyncast() == DYNCAST.expression); e = e.semantic(sc); e = resolveProperties(sc, e); e = e.ctfeInterpret(); diff --git a/ddmd/dimport.d b/ddmd/dimport.d index 262754cb5b2..e1880425823 100644 --- a/ddmd/dimport.d +++ b/ddmd/dimport.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _dimport.d) diff --git a/ddmd/dinifile.d b/ddmd/dinifile.d index 49b94f813a5..8e1c85cba32 100644 --- a/ddmd/dinifile.d +++ b/ddmd/dinifile.d @@ -1,6 +1,6 @@ /* * Some portions copyright (c) 1994-1995 by Symantec - * Copyright (c) 1999-2016 by Digital Mars + * Copyright (c) 1999-2017 by Digital Mars * All Rights Reserved * http://www.digitalmars.com * Written by Walter Bright diff --git a/ddmd/dinterpret.d b/ddmd/dinterpret.d index 986cf0f47e9..2d1c65e8ee2 100644 --- a/ddmd/dinterpret.d +++ b/ddmd/dinterpret.d @@ -1,5 +1,5 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2016 by Digital Mars +// Copyright (c) 1999-2017 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -2022,7 +2022,8 @@ public: } if (goal == ctfeNeedLvalue) { - if (istate.fd.vthis) + // We might end up here with istate being zero (see bugzilla 16382) + if (istate && istate.fd.vthis) { result = new VarExp(e.loc, istate.fd.vthis); result.type = e.type; diff --git a/ddmd/dmacro.d b/ddmd/dmacro.d index 0592aeeb423..5c2212ef0a2 100644 --- a/ddmd/dmacro.d +++ b/ddmd/dmacro.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _dmacro.d) diff --git a/ddmd/dmangle.d b/ddmd/dmangle.d index dc473df98b0..97b2084fbe9 100644 --- a/ddmd/dmangle.d +++ b/ddmd/dmangle.d @@ -1,7 +1,7 @@ /** * Compiler implementation of the $(LINK2 http://www.dlang.org, D programming language) * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _dmangle.d) @@ -287,7 +287,7 @@ public: if (ta.isreturn) buf.writestring("Nj"); if (ta.isscope && !ta.isreturn) - buf.writestring("M"); + buf.writestring("Nl"); switch (ta.trust) { case TRUSTtrusted: diff --git a/ddmd/dmodule.d b/ddmd/dmodule.d index 37dcbf0368b..778c0e187af 100644 --- a/ddmd/dmodule.d +++ b/ddmd/dmodule.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _dmodule.d) diff --git a/ddmd/doc.d b/ddmd/doc.d index bc834041446..73683a1b7b1 100644 --- a/ddmd/doc.d +++ b/ddmd/doc.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _doc.d) @@ -939,7 +939,7 @@ extern (C++) void emitComment(Dsymbol s, OutBuffer* buf, Scope* sc) if (isDitto(td.comment)) com = td.comment; else - com = Lexer.combineComments(td.comment, com); + com = Lexer.combineComments(td.comment, com, true); } else { @@ -971,7 +971,7 @@ extern (C++) void emitComment(Dsymbol s, OutBuffer* buf, Scope* sc) if (isDitto(td.comment)) com = td.comment; else - com = Lexer.combineComments(td.comment, com); + com = Lexer.combineComments(td.comment, com, true); } else { diff --git a/ddmd/dscope.d b/ddmd/dscope.d index 38ea4bb692b..5a97b0a4fd1 100644 --- a/ddmd/dscope.d +++ b/ddmd/dscope.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _dscope.d) diff --git a/ddmd/dstruct.d b/ddmd/dstruct.d index 911d384843b..c3483549ede 100644 --- a/ddmd/dstruct.d +++ b/ddmd/dstruct.d @@ -1,5 +1,5 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2016 by Digital Mars +// Copyright (c) 1999-2017 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com diff --git a/ddmd/dsymbol.d b/ddmd/dsymbol.d index dbb8c9da188..092d34a8237 100644 --- a/ddmd/dsymbol.d +++ b/ddmd/dsymbol.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _dsymbol.d) @@ -514,9 +514,9 @@ extern (C++) class Dsymbol : RootObject } // kludge for template.isSymbol() - override final int dyncast() const + override final DYNCAST dyncast() const { - return DYNCAST_DSYMBOL; + return DYNCAST.dsymbol; } /************************************* @@ -772,10 +772,10 @@ extern (C++) class Dsymbol : RootObject } switch (id.dyncast()) { - case DYNCAST_IDENTIFIER: + case DYNCAST.identifier: sm = s.search(loc, cast(Identifier)id); break; - case DYNCAST_DSYMBOL: + case DYNCAST.dsymbol: { // It's a template instance //printf("\ttemplate instance id\n"); @@ -804,8 +804,8 @@ extern (C++) class Dsymbol : RootObject sm = ti.toAlias(); break; } - case DYNCAST_TYPE: - case DYNCAST_EXPRESSION: + case DYNCAST.type: + case DYNCAST.expression: default: assert(0); } @@ -1038,7 +1038,7 @@ extern (C++) class Dsymbol : RootObject else if (comment && strcmp(cast(char*)comment, cast(char*)this.comment) != 0) { // Concatenate the two - this.comment = Lexer.combineComments(this.comment, comment); + this.comment = Lexer.combineComments(this.comment, comment, true); } } diff --git a/ddmd/dsymbol.h b/ddmd/dsymbol.h index 9fb7d02714a..49170a15ccd 100644 --- a/ddmd/dsymbol.h +++ b/ddmd/dsymbol.h @@ -205,7 +205,7 @@ class Dsymbol : public RootObject Ungag ungagSpeculative(); // kludge for template.isSymbol() - int dyncast() { return DYNCAST_DSYMBOL; } + int dyncast() const { return DYNCAST_DSYMBOL; } static Dsymbols *arraySyntaxCopy(Dsymbols *a); @@ -318,7 +318,8 @@ class ScopeDsymbol : public Dsymbol Dsymbol *search(Loc loc, Identifier *ident, int flags = SearchLocalsOnly); OverloadSet *mergeOverloadSet(Identifier *ident, OverloadSet *os, Dsymbol *s); void importScope(Dsymbol *s, Prot protection); - virtual bool isPackageAccessible(Package p, Prot protection, int flags = 0); + void addAccessiblePackage(Package *p, Prot protection); + virtual bool isPackageAccessible(Package *p, Prot protection, int flags = 0); bool isforwardRef(); static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2); const char *kind(); diff --git a/ddmd/dtemplate.d b/ddmd/dtemplate.d index 2392d2c5813..254f9c2418f 100644 --- a/ddmd/dtemplate.d +++ b/ddmd/dtemplate.d @@ -4,7 +4,7 @@ * * Template implementation. * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _dtemplate.d) @@ -46,6 +46,7 @@ version(IN_LLVM) import gen.llvmhelpers; } +//debug = FindExistingInstance; // print debug stats of findExistingInstance private enum LOG = false; enum IDX_NOTFOUND = 0x12345678; @@ -57,7 +58,7 @@ enum IDX_NOTFOUND = 0x12345678; extern (C++) Expression isExpression(RootObject o) { //return dynamic_cast(o); - if (!o || o.dyncast() != DYNCAST_EXPRESSION) + if (!o || o.dyncast() != DYNCAST.expression) return null; return cast(Expression)o; } @@ -65,7 +66,7 @@ extern (C++) Expression isExpression(RootObject o) extern (C++) Dsymbol isDsymbol(RootObject o) { //return dynamic_cast(o); - if (!o || o.dyncast() != DYNCAST_DSYMBOL) + if (!o || o.dyncast() != DYNCAST.dsymbol) return null; return cast(Dsymbol)o; } @@ -73,7 +74,7 @@ extern (C++) Dsymbol isDsymbol(RootObject o) extern (C++) Type isType(RootObject o) { //return dynamic_cast(o); - if (!o || o.dyncast() != DYNCAST_TYPE) + if (!o || o.dyncast() != DYNCAST.type) return null; return cast(Type)o; } @@ -81,7 +82,7 @@ extern (C++) Type isType(RootObject o) extern (C++) Tuple isTuple(RootObject o) { //return dynamic_cast(o); - if (!o || o.dyncast() != DYNCAST_TUPLE) + if (!o || o.dyncast() != DYNCAST.tuple) return null; return cast(Tuple)o; } @@ -89,7 +90,7 @@ extern (C++) Tuple isTuple(RootObject o) extern (C++) Parameter isParameter(RootObject o) { //return dynamic_cast(o); - if (!o || o.dyncast() != DYNCAST_PARAMETER) + if (!o || o.dyncast() != DYNCAST.parameter) return null; return cast(Parameter)o; } @@ -209,18 +210,18 @@ private Expression getValue(Expression e) return e; } +private Expression getExpression(RootObject o) +{ + auto s = isDsymbol(o); + return s ? .getValue(s) : .getValue(isExpression(o)); +} + /****************************** * If o1 matches o2, return true. * Else, return false. */ private bool match(RootObject o1, RootObject o2) { - static Expression getExpression(RootObject o) - { - auto s = isDsymbol(o); - return s ? .getValue(s) : .getValue(isExpression(o)); - } - enum debugPrint = 0; static if (debugPrint) @@ -264,7 +265,12 @@ private bool match(RootObject o1, RootObject o2) printf("\te1 = %s '%s' %s\n", e1.type.toChars(), Token.toChars(e1.op), e1.toChars()); printf("\te2 = %s '%s' %s\n", e2.type.toChars(), Token.toChars(e2.op), e2.toChars()); } - if (!e1.equals(e2)) + + // two expressions can be equal although they do not have the same + // type; that happens when they have the same value. So check type + // as well as expression equality to ensure templates are properly + // matched. + if (!e1.type.equals(e2.type) || !e1.equals(e2)) goto Lnomatch; goto Lmatch; @@ -343,40 +349,115 @@ private int arrayObjectMatch(Objects* oa1, Objects* oa2) */ private hash_t arrayObjectHash(Objects* oa1) { + import ddmd.root.hash : mixHash; + hash_t hash = 0; - for (size_t j = 0; j < oa1.dim; j++) + foreach (o1; *oa1) { /* Must follow the logic of match() */ - RootObject o1 = (*oa1)[j]; - if (Type t1 = isType(o1)) - hash += cast(size_t)t1.deco; - else + if (auto t1 = isType(o1)) + hash = mixHash(hash, cast(size_t)t1.deco); + else if (auto e1 = getExpression(o1)) + hash = mixHash(hash, expressionHash(e1)); + else if (auto s1 = isDsymbol(o1)) { - Dsymbol s1 = isDsymbol(o1); - Expression e1 = s1 ? getValue(s1) : getValue(isExpression(o1)); - if (e1) - { - if (e1.op == TOKint64) - { - IntegerExp ne = cast(IntegerExp)e1; - hash += cast(size_t)ne.getInteger(); - } - } - else if (s1) - { - FuncAliasDeclaration fa1 = s1.isFuncAliasDeclaration(); - if (fa1) - s1 = fa1.toAliasFunc(); - hash += cast(size_t)cast(void*)s1.getIdent() + cast(size_t)cast(void*)s1.parent; - } - else if (Tuple u1 = isTuple(o1)) - hash += arrayObjectHash(&u1.objects); + auto fa1 = s1.isFuncAliasDeclaration(); + if (fa1) + s1 = fa1.toAliasFunc(); + hash = mixHash(hash, mixHash(cast(size_t)cast(void*)s1.getIdent(), cast(size_t)cast(void*)s1.parent)); } + else if (auto u1 = isTuple(o1)) + hash = mixHash(hash, arrayObjectHash(&u1.objects)); } return hash; } + +/************************************ + * Computes hash of expression. + * Handles all Expression classes and MUST match their equals method, + * i.e. e1.equals(e2) implies expressionHash(e1) == expressionHash(e2). + */ +private hash_t expressionHash(Expression e) +{ + import ddmd.root.ctfloat : CTFloat; + import ddmd.root.hash : calcHash, mixHash; + + switch (e.op) + { + case TOKint64: + return cast(size_t) (cast(IntegerExp)e).getInteger(); + + case TOKfloat64: + return CTFloat.hash((cast(RealExp)e).value); + + case TOKcomplex80: + auto ce = cast(ComplexExp)e; + return mixHash(CTFloat.hash(ce.toReal), CTFloat.hash(ce.toImaginary)); + + case TOKidentifier: + return cast(size_t)cast(void*) (cast(IdentifierExp)e).ident; + + case TOKnull: + return cast(size_t)cast(void*) (cast(NullExp)e).type; + + case TOKstring: + auto se = cast(StringExp)e; + return calcHash(se.string, se.len * se.sz); + + case TOKtuple: + { + auto te = cast(TupleExp)e; + size_t hash = 0; + hash += te.e0 ? expressionHash(te.e0) : 0; + foreach (elem; *te.exps) + hash = mixHash(hash, expressionHash(elem)); + return hash; + } + + case TOKarrayliteral: + { + auto ae = cast(ArrayLiteralExp)e; + size_t hash; + foreach (i; 0 .. ae.elements.dim) + hash = mixHash(hash, expressionHash(ae.getElement(i))); + return hash; + } + + case TOKassocarrayliteral: + { + auto ae = cast(AssocArrayLiteralExp)e; + size_t hash; + foreach (i; 0 .. ae.keys.dim) + // reduction needs associative op as keys are unsorted (use XOR) + hash ^= mixHash(expressionHash((*ae.keys)[i]), expressionHash((*ae.values)[i])); + return hash; + } + + case TOKstructliteral: + { + auto se = cast(StructLiteralExp)e; + size_t hash; + foreach (elem; *se.elements) + hash = mixHash(hash, elem ? expressionHash(elem) : 0); + return hash; + } + + case TOKvar: + return cast(size_t)cast(void*) (cast(VarExp)e).var; + + case TOKfunction: + return cast(size_t)cast(void*) (cast(FuncExp)e).fd; + + default: + // no custom equals for this expression + assert((&e.equals).funcptr is &RootObject.equals); + // equals based on identity + return cast(size_t)cast(void*) e; + } +} + RootObject objectSyntaxCopy(RootObject o) { if (!o) @@ -393,9 +474,9 @@ extern (C++) final class Tuple : RootObject Objects objects; // kludge for template.isType() - override int dyncast() + override DYNCAST dyncast() const { - return DYNCAST_TUPLE; + return DYNCAST.tuple; } override const(char)* toChars() @@ -2248,6 +2329,17 @@ else return fd; } + debug (FindExistingInstance) + { + __gshared uint nFound, nNotFound, nAdded, nRemoved; + + shared static ~this() + { + printf("debug (FindExistingInstance) nFound %u, nNotFound: %u, nAdded: %u, nRemoved: %u\n", + nFound, nNotFound, nAdded, nRemoved); + } + } + /**************************************************** * Given a new instance tithis of this TemplateDeclaration, * see if there already exists an instance. @@ -2259,6 +2351,7 @@ else tithis.fargs = fargs; auto tibox = TemplateInstanceBox(tithis); auto p = tibox in instances; + debug (FindExistingInstance) ++(p ? nFound : nNotFound); //if (p) printf("\tfound %p\n", *p); else printf("\tnot found\n"); return p ? *p : null; } @@ -2272,6 +2365,7 @@ else //printf("addInstance() %p %p\n", instances, ti); auto tibox = TemplateInstanceBox(ti); instances[tibox] = ti; + debug (FindExistingInstance) ++nAdded; return ti; } @@ -2284,6 +2378,7 @@ else { //printf("removeInstance()\n"); auto tibox = TemplateInstanceBox(ti); + debug (FindExistingInstance) ++nRemoved; instances.remove(tibox); } @@ -3264,7 +3359,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param for (size_t j = tident.idents.dim; j-- > 0;) { RootObject id = tident.idents[j]; - if (id.dyncast() == DYNCAST_IDENTIFIER) + if (id.dyncast() == DYNCAST.identifier) { if (!s || !s.parent) goto Lnomatch; @@ -3718,7 +3813,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param Parameter a = Parameter.getNth(t.parameters, i); Parameter ap = Parameter.getNth(tp.parameters, i); - if (!a.isCovariant(ap) || + if (!a.isCovariant(t.isref, ap) || !deduceType(a.type, sc, ap.type, parameters, dedtypes)) { result = MATCHnomatch; @@ -4043,7 +4138,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param if (tpi.idents.dim) { RootObject id = tpi.idents[tpi.idents.dim - 1]; - if (id.dyncast() == DYNCAST_IDENTIFIER && t.sym.ident.equals(cast(Identifier)id)) + if (id.dyncast() == DYNCAST.identifier && t.sym.ident.equals(cast(Identifier)id)) { Type tparent = t.sym.parent.getType(); if (tparent) @@ -4183,7 +4278,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param if (tpi.idents.dim) { RootObject id = tpi.idents[tpi.idents.dim - 1]; - if (id.dyncast() == DYNCAST_IDENTIFIER && t.sym.ident.equals(cast(Identifier)id)) + if (id.dyncast() == DYNCAST.identifier && t.sym.ident.equals(cast(Identifier)id)) { Type tparent = t.sym.parent.getType(); if (tparent) @@ -5408,8 +5503,10 @@ extern (C++) final class TemplateValueParameter : TemplateParameter if (e) { e = e.syntaxCopy(); - e = e.semantic(sc); - e = resolveProperties(sc, e); + if ((e = e.semantic(sc)) is null) + return null; + if ((e = resolveProperties(sc, e)) is null) + return null; e = e.resolveLoc(instLoc, sc); // use the instantiated loc e = e.optimize(WANTvalue); } @@ -8965,15 +9062,30 @@ struct TemplateInstanceBox bool opEquals(ref const TemplateInstanceBox s) @trusted const { + bool res = void; if (ti.inst && s.ti.inst) /* This clause is only used when an instance with errors * is replaced with a correct instance. */ - return ti is s.ti; + res = ti is s.ti; else /* Used when a proposed instance is used to see if there's * an existing instance. */ - return (cast()s.ti).compare(cast()ti) == 0; + res = (cast()s.ti).compare(cast()ti) == 0; + + debug (FindExistingInstance) ++(res ? nHits : nCollisions); + return res; + } + + debug (FindExistingInstance) + { + __gshared uint nHits, nCollisions; + + shared static ~this() + { + printf("debug (FindExistingInstance) TemplateInstanceBox.equals hits: %u collisions: %u\n", + nHits, nCollisions); + } } } diff --git a/ddmd/dversion.d b/ddmd/dversion.d index 44b6c7962f6..b5638cd0ea6 100644 --- a/ddmd/dversion.d +++ b/ddmd/dversion.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _dversion.d) diff --git a/ddmd/entity.d b/ddmd/entity.d index 654b43fffef..4ae7f7b5248 100644 --- a/ddmd/entity.d +++ b/ddmd/entity.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _entity.d) @@ -2232,9 +2232,9 @@ immutable NameId[] namesV = {"veeeq", 0x0225A}, // EQUIANGULAR TO {"vellip", 0x022EE}, // VERTICAL ELLIPSIS {"verbar", 0x0007C}, // VERTICAL LINE - {"Verbar", 0x02016}, // DOUBLE VERTICAL LINE + {"Verbar", 0x02017}, // DOUBLE VERTICAL LINE {"vert", 0x0007C}, // VERTICAL LINE - {"Vert", 0x02016}, // DOUBLE VERTICAL LINE + {"Vert", 0x02017}, // DOUBLE VERTICAL LINE {"VerticalBar", 0x02223}, // DIVIDES {"VerticalLine", 0x0007C}, // VERTICAL LINE {"VerticalSeparator", 0x02758}, // LIGHT VERTICAL BAR diff --git a/ddmd/errors.d b/ddmd/errors.d index 81da0bc76ec..fc986541421 100644 --- a/ddmd/errors.d +++ b/ddmd/errors.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _errors.d) diff --git a/ddmd/escape.d b/ddmd/escape.d index f221e2a47b1..3d04ee00189 100644 --- a/ddmd/escape.d +++ b/ddmd/escape.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _escape.d) @@ -66,13 +66,16 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier par, Ex { if (!gag) error(arg.loc, "%s %s assigned to non-scope parameter %s calling %s", - desc, v.toChars(), par.toChars(), fdc ? fdc.toPrettyChars() : "indirectly"); + desc, v.toChars(), + par ? par.toChars() : "unnamed", + fdc ? fdc.toPrettyChars() : "indirectly"); result = true; } } foreach (VarDeclaration v; er.byvalue) { + //printf("byvalue %s\n", v.toChars()); if (v.isDataseg()) continue; @@ -126,8 +129,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier par, Ex foreach (v; vars) { //printf("v = %s\n", v.toChars()); - if (v.isDataseg()) - continue; + assert(!v.isDataseg()); // these are not put in the closureVars[] Dsymbol p = v.toParent2(); @@ -147,7 +149,8 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier par, Ex { if (!gag) error(ee.loc, "reference to stack allocated value returned by %s assigned to non-scope parameter %s", - ee.toChars(), par.toChars()); + ee.toChars(), + par ? par.toChars() : "unnamed"); result = true; } } @@ -218,6 +221,9 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag) if (v.isDataseg()) continue; + if (v == va) + continue; + Dsymbol p = v.toParent2(); if (!(va && va.isScope())) @@ -225,8 +231,19 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag) if (v.isScope()) { + if (va && va.isScope() && va.storage_class & STCreturn && !(v.storage_class & STCreturn) && + sc.func.setUnsafe()) + { + if (!gag) + error(ae.loc, "scope variable %s assigned to return scope %s", v.toChars(), va.toChars()); + result = true; + continue; + } + // If va's lifetime encloses v's, then error - if (va && va.enclosesLifetimeOf(v) && !(v.storage_class & STCparameter) && sc.func.setUnsafe()) + if (va && + (va.enclosesLifetimeOf(v) && !(v.storage_class & STCparameter) || va.storage_class & STCref) && + sc.func.setUnsafe()) { if (!gag) error(ae.loc, "scope variable %s assigned to %s with longer lifetime", v.toChars(), va.toChars()); @@ -239,6 +256,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag) if (!va.isScope() && inferScope) { //printf("inferring scope for %s\n", va.toChars()); va.storage_class |= STCscope; + va.storage_class |= v.storage_class & STCreturn; } continue; } @@ -288,7 +306,9 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag) Dsymbol p = v.toParent2(); // If va's lifetime encloses v's, then error - if (va && va.enclosesLifetimeOf(v) && !(v.storage_class & STCparameter) && sc.func.setUnsafe()) + if (va && + (va.enclosesLifetimeOf(v) && !(v.storage_class & STCparameter) || va.storage_class & STCref) && + sc.func.setUnsafe()) { if (!gag) error(ae.loc, "address of variable %s assigned to %s with longer lifetime", v.toChars(), va.toChars()); @@ -329,8 +349,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag) foreach (v; vars) { //printf("v = %s\n", v.toChars()); - if (v.isDataseg()) - continue; + assert(!v.isDataseg()); // these are not put in the closureVars[] Dsymbol p = v.toParent2(); @@ -595,7 +614,7 @@ private void inferReturn(FuncDeclaration fd, VarDeclaration v) { // v is a local in the current function - //printf("inferring 'return' for variable '%s'\n", v.toChars()); + //printf("for function '%s' inferring 'return' for variable '%s'\n", fd.toChars(), v.toChars()); v.storage_class |= STCreturn; TypeFunction tf = cast(TypeFunction)fd.type; @@ -711,10 +730,7 @@ private void escapeByValue(Expression e, EscapeByResults* er) override void visit(TupleExp e) { - if (e.exps.dim) - { - (*e.exps)[e.exps.dim - 1].accept(this); // last one only - } + assert(0); // should have been lowered by now } override void visit(ArrayLiteralExp e) @@ -1123,6 +1139,7 @@ private struct EscapeByResults */ void findAllOuterAccessedVariables(FuncDeclaration fd, VarDeclarations* vars) { + //printf("findAllOuterAccessedVariables(fd: %s)\n", fd.toChars()); for (auto p = fd.parent; p; p = p.parent) { auto fdp = p.isFuncDeclaration(); diff --git a/ddmd/expression.d b/ddmd/expression.d index c262e581b3b..47c283899ab 100644 --- a/ddmd/expression.d +++ b/ddmd/expression.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _expression.d) @@ -916,6 +916,9 @@ extern (C++) Expression resolveUFCSProperties(Scope* sc, Expression e1, Expressi else return null; + if (e is null) + return null; + // Rewrite if (e2) { @@ -2594,9 +2597,9 @@ extern (C++) /* IN_LLVM abstract */ class Expression : RootObject } // kludge for template.isExpression() - override final int dyncast() + override final DYNCAST dyncast() const { - return DYNCAST_EXPRESSION; + return DYNCAST.expression; } override final void print() @@ -2801,6 +2804,21 @@ extern (C++) /* IN_LLVM abstract */ class Expression : RootObject assert(type); if (!type.isMutable()) { + if (op == TOKdotvar) + { + if (isNeedThisScope(sc, (cast(DotVarExp) this).var)) + for (Dsymbol s = sc.func; s; s = s.toParent2()) + { + FuncDeclaration ff = s.isFuncDeclaration(); + if (!ff) + break; + if (!ff.type.isMutable) + { + error("cannot modify %s in %s function", toChars(), MODtoChars(type.mod)); + return new ErrorExp(); + } + } + } error("cannot modify %s expression %s", MODtoChars(type.mod), toChars()); return new ErrorExp(); } @@ -3928,6 +3946,30 @@ extern (C++) class IdentifierExp : Expression return e; } + // If we've reached this point and are inside a with() scope then we may + // try one last attempt by checking whether the 'wthis' object supports + // dynamic dispatching via opDispatch. + // This is done by rewriting this expression as wthis.ident. + for (Scope* sc2 = sc; sc2; sc2 = sc2.enclosing) + { + if (!sc2.scopesym) + continue; + + if (auto ss = sc2.scopesym.isWithScopeSymbol()) + { + if (ss.withstate.wthis) + { + Expression e; + e = new VarExp(loc, ss.withstate.wthis); + e = new DotIdExp(loc, e, ident); + e = e.trySemantic(sc); + if (e) + return e; + } + break; + } + } + const(char)* n = importHint(ident.toChars()); if (n) error("'%s' is not defined, perhaps you need to import %s; ?", ident.toChars(), n); @@ -4353,7 +4395,7 @@ extern (C++) final class SuperExp : ThisExp s = s.toParent(); assert(s); cd = s.isClassDeclaration(); - //printf("parent is %s %s\n", fd.toParent()->kind(), fd.toParent()->toChars()); + //printf("parent is %s %s\n", fd.toParent().kind(), fd.toParent().toChars()); if (!cd) goto Lerr; if (!cd.baseClass) @@ -4399,7 +4441,7 @@ extern (C++) final class NullExp : Expression override bool equals(RootObject o) { - if (o && o.dyncast() == DYNCAST_EXPRESSION) + if (o && o.dyncast() == DYNCAST.expression) { Expression e = cast(Expression)o; if (e.op == TOKnull && type.equals(e.type)) @@ -4494,7 +4536,7 @@ extern (C++) final class StringExp : Expression override bool equals(RootObject o) { //printf("StringExp::equals('%s') %s\n", o.toChars(), toChars()); - if (o && o.dyncast() == DYNCAST_EXPRESSION) + if (o && o.dyncast() == DYNCAST.expression) { Expression e = cast(Expression)o; if (e.op == TOKstring) @@ -4932,13 +4974,13 @@ extern (C++) final class TupleExp : Expression Expression e = new DsymbolExp(loc, s); this.exps.push(e); } - else if (o.dyncast() == DYNCAST_EXPRESSION) + else if (o.dyncast() == DYNCAST.expression) { auto e = (cast(Expression)o).copy(); e.loc = loc; // Bugzilla 15669 this.exps.push(e); } - else if (o.dyncast() == DYNCAST_TYPE) + else if (o.dyncast() == DYNCAST.type) { Type t = cast(Type)o; Expression e = new TypeExp(loc, t); @@ -5069,7 +5111,7 @@ extern (C++) final class ArrayLiteralExp : Expression { if (this == o) return true; - if (o && o.dyncast() == DYNCAST_EXPRESSION && (cast(Expression)o).op == TOKarrayliteral) + if (o && o.dyncast() == DYNCAST.expression && (cast(Expression)o).op == TOKarrayliteral) { ArrayLiteralExp ae = cast(ArrayLiteralExp)o; if (elements.dim != ae.elements.dim) @@ -5275,7 +5317,7 @@ extern (C++) final class AssocArrayLiteralExp : Expression { if (this == o) return true; - if (o && o.dyncast() == DYNCAST_EXPRESSION && (cast(Expression)o).op == TOKassocarrayliteral) + if (o && o.dyncast() == DYNCAST.expression && (cast(Expression)o).op == TOKassocarrayliteral) { AssocArrayLiteralExp ae = cast(AssocArrayLiteralExp)o; if (keys.dim != ae.keys.dim) @@ -5427,7 +5469,7 @@ extern (C++) final class StructLiteralExp : Expression { if (this == o) return true; - if (o && o.dyncast() == DYNCAST_EXPRESSION && (cast(Expression)o).op == TOKstructliteral) + if (o && o.dyncast() == DYNCAST.expression && (cast(Expression)o).op == TOKstructliteral) { StructLiteralExp se = cast(StructLiteralExp)o; if (!type.equals(se.type)) @@ -6724,7 +6766,7 @@ extern (C++) final class FuncExp : Expression { if (this == o) return true; - if (o.dyncast() != DYNCAST_EXPRESSION) + if (o.dyncast() != DYNCAST.expression) return false; if ((cast(Expression)o).op == TOKfunction) { @@ -7644,6 +7686,12 @@ extern (C++) final class IsExp : Expression // not valid for a parameter break; + case TOKvector: + if (targ.ty != Tvector) + goto Lno; + tded = (cast(TypeVector)targ).basetype; + break; + default: assert(0); } @@ -7936,7 +7984,7 @@ extern (C++) abstract class BinExp : Expression // T opAssign floating yields a floating. Prevent truncating conversions (float to int). // See issue 3841. - // Should we also prevent double to float (type.isfloating() && type.size() < t2 ->size()) ? + // Should we also prevent double to float (type.isfloating() && type.size() < t2.size()) ? if (op == TOKaddass || op == TOKminass || op == TOKmulass || op == TOKdivass || op == TOKmodass || op == TOKpowass) @@ -8924,7 +8972,7 @@ extern (C++) final class DotIdExp : UnaExp if (e1.op == TOKtype || e1.op == TOKtemplate) flag = 0; e = e1.type.dotExp(sc, e1, ident, flag | (noderef ? Type.DotExpFlag.noDeref : 0)); - if (!flag || e) + if (e) e = e.semantic(sc); return e; } @@ -9009,7 +9057,7 @@ extern (C++) final class DotVarExp : UnaExp { RootObject o = (*tup.objects)[i]; Expression e; - if (o.dyncast() == DYNCAST_EXPRESSION) + if (o.dyncast() == DYNCAST.expression) { e = cast(Expression)o; if (e.op == TOKdsymbol) @@ -9018,11 +9066,11 @@ extern (C++) final class DotVarExp : UnaExp e = new DotVarExp(loc, ev, s.isDeclaration()); } } - else if (o.dyncast() == DYNCAST_DSYMBOL) + else if (o.dyncast() == DYNCAST.dsymbol) { e = new DsymbolExp(loc, cast(Dsymbol)o); } - else if (o.dyncast() == DYNCAST_TYPE) + else if (o.dyncast() == DYNCAST.type) { e = new TypeExp(loc, cast(Type)o); } @@ -9912,6 +9960,14 @@ extern (C++) final class CallExp : UnaExp else if (e1.op == TOKtype && t1.isscalar()) { Expression e; + + // Make sure to use the the enum type itself rather than its + // base type (see bugzilla 16346) + if (e1.type.ty == Tenum) + { + t1 = e1.type; + } + if (!arguments || arguments.dim == 0) { e = t1.defaultInitLiteral(loc); @@ -10019,7 +10075,7 @@ extern (C++) final class CallExp : UnaExp return ue.e1; ethis = ue.e1; tthis = ue.e1.type; - if (!f.type.isscope()) + if (!(f.type.ty == Tfunction && (cast(TypeFunction)f.type).isscope)) { if (global.params.vsafe && checkParamArgumentEscape(sc, f, Id.This, ethis, false)) return new ErrorExp(); @@ -10092,6 +10148,14 @@ extern (C++) final class CallExp : UnaExp } } } + // If we've got a pointer to a function then deference it + // https://issues.dlang.org/show_bug.cgi?id=16483 + if (e1.type.ty == Tpointer && e1.type.nextOf().ty == Tfunction) + { + Expression e = new PtrExp(loc, e1); + e.type = e1.type.nextOf(); + e1 = e; + } t1 = e1.type; } else if (e1.op == TOKsuper) @@ -10293,7 +10357,7 @@ extern (C++) final class CallExp : UnaExp if (tthis) tthis.modToBuffer(&buf); - //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0]->type.deco); + //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco); .error(loc, "%s %s %s is not callable using argument types %s", p, e1.toChars(), parametersTypeToChars(tf.parameters, tf.varargs), buf.peekString()); return new ErrorExp(); @@ -10362,7 +10426,7 @@ extern (C++) final class CallExp : UnaExp argExpTypesToCBuffer(&buf, arguments); buf.writeByte(')'); - //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0]->type.deco); + //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco); .error(loc, "%s %s is not callable using argument types %s", e1.toChars(), parametersTypeToChars(tf.parameters, tf.varargs), buf.peekString()); f = null; @@ -10495,7 +10559,7 @@ extern (C++) final class CallExp : UnaExp auto tmp = copyToTemp(0, "__tmpfordtor", this); auto de = new DeclarationExp(loc, tmp); auto ve = new VarExp(loc, tmp); - Expression e = new CommaExp(loc, de, new VarExp(loc, tmp)); + Expression e = new CommaExp(loc, de, ve); e = e.semantic(sc); return e; } @@ -10866,7 +10930,7 @@ extern (C++) final class PtrExp : UnaExp { super(loc, TOKstar, __traits(classInstanceSize, PtrExp), e); //if (e.type) - // type = ((TypePointer *)e.type)->next; + // type = ((TypePointer *)e.type).next; } extern (D) this(Loc loc, Expression e, Type t) @@ -15380,6 +15444,7 @@ extern (C++) final class CmpExp : BinExp type = Type.tbool; // Special handling for array comparisons + Expression arrayLowering = null; t1 = e1.type.toBasetype(); t2 = e2.type.toBasetype(); if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer)) @@ -15393,7 +15458,20 @@ extern (C++) final class CmpExp : BinExp } if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray)) { - semanticTypeInfo(sc, t1.nextOf()); + // Lower to object.__cmp(e1, e2) + Expression al = new IdentifierExp(loc, Id.empty); + al = new DotIdExp(loc, al, Id.object); + al = new DotIdExp(loc, al, Id.__cmp); + al = al.semantic(sc); + + auto arguments = new Expressions(); + arguments.push(e1); + arguments.push(e2); + + al = new CallExp(loc, al, arguments); + al = new CmpExp(op, loc, al, new IntegerExp(0)); + + arrayLowering = al; } } else if (t1.ty == Tstruct || t2.ty == Tstruct || (t1.ty == Tclass && t2.ty == Tclass)) @@ -15493,6 +15571,11 @@ extern (C++) final class CmpExp : BinExp } //printf("CmpExp: %s, type = %s\n", e.toChars(), e.type.toChars()); + if (arrayLowering) + { + arrayLowering = arrayLowering.semantic(sc); + return arrayLowering; + } return this; } @@ -15705,8 +15788,8 @@ extern (C++) final class IdentityExp : BinExp if (e1.type.toBasetype().ty == Tsarray || e2.type.toBasetype().ty == Tsarray) deprecation("identity comparison of static arrays " - "implicitly coerces them to slices, " - "which are compared by reference"); + ~ "implicitly coerces them to slices, " + ~ "which are compared by reference"); return this; } diff --git a/ddmd/expression.h b/ddmd/expression.h index bdd2377fcaa..3275f398e83 100644 --- a/ddmd/expression.h +++ b/ddmd/expression.h @@ -63,6 +63,7 @@ void initPrecedence(); Expression *resolveProperties(Scope *sc, Expression *e); Expression *resolvePropertiesOnly(Scope *sc, Expression *e1); bool checkAccess(Loc loc, Scope *sc, Expression *e, Declaration *d); +bool checkAccess(Loc loc, Scope *sc, Package *p); Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Dsymbol *d); Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid); void expandTuples(Expressions *exps); @@ -142,7 +143,7 @@ class Expression : public RootObject Expression *trySemantic(Scope *sc); // kludge for template.isExpression() - int dyncast() { return DYNCAST_EXPRESSION; } + int dyncast() const { return DYNCAST_EXPRESSION; } void print(); const char *toChars(); diff --git a/ddmd/func.d b/ddmd/func.d index 08c1e9187a3..2d5611d0e95 100644 --- a/ddmd/func.d +++ b/ddmd/func.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _func.d) @@ -41,6 +41,7 @@ import ddmd.opover; import ddmd.root.filename; import ddmd.root.outbuffer; import ddmd.root.rootobject; +import ddmd.statement_rewrite_walker; import ddmd.statementsem; import ddmd.statement; import ddmd.target; @@ -70,253 +71,6 @@ alias BUILTINunknown = BUILTIN.BUILTINunknown; alias BUILTINno = BUILTIN.BUILTINno; alias BUILTINyes = BUILTIN.BUILTINyes; -/** A visitor to walk entire statements and provides ability to replace any sub-statements. - */ -extern (C++) class StatementRewriteWalker : Visitor -{ - alias visit = super.visit; - - /* Point the currently visited statement. - * By using replaceCurrent() method, you can replace AST during walking. - */ - Statement* ps; - -public: - final void visitStmt(ref Statement s) - { - ps = &s; - s.accept(this); - } - - final void replaceCurrent(Statement s) - { - *ps = s; - } - - override void visit(ErrorStatement s) - { - } - - override void visit(PeelStatement s) - { - if (s.s) - visitStmt(s.s); - } - - override void visit(ExpStatement s) - { - } - - override void visit(DtorExpStatement s) - { - } - - override void visit(CompileStatement s) - { - } - - override void visit(CompoundStatement s) - { - if (s.statements && s.statements.dim) - { - for (size_t i = 0; i < s.statements.dim; i++) - { - if ((*s.statements)[i]) - visitStmt((*s.statements)[i]); - } - } - } - - override void visit(CompoundDeclarationStatement s) - { - visit(cast(CompoundStatement)s); - } - - override void visit(UnrolledLoopStatement s) - { - if (s.statements && s.statements.dim) - { - for (size_t i = 0; i < s.statements.dim; i++) - { - if ((*s.statements)[i]) - visitStmt((*s.statements)[i]); - } - } - } - - override void visit(ScopeStatement s) - { - if (s.statement) - visitStmt(s.statement); - } - - override void visit(WhileStatement s) - { - if (s._body) - visitStmt(s._body); - } - - override void visit(DoStatement s) - { - if (s._body) - visitStmt(s._body); - } - - override void visit(ForStatement s) - { - if (s._init) - visitStmt(s._init); - if (s._body) - visitStmt(s._body); - } - - override void visit(ForeachStatement s) - { - if (s._body) - visitStmt(s._body); - } - - override void visit(ForeachRangeStatement s) - { - if (s._body) - visitStmt(s._body); - } - - override void visit(IfStatement s) - { - if (s.ifbody) - visitStmt(s.ifbody); - if (s.elsebody) - visitStmt(s.elsebody); - } - - override void visit(ConditionalStatement s) - { - } - - override void visit(PragmaStatement s) - { - } - - override void visit(StaticAssertStatement s) - { - } - - override void visit(SwitchStatement s) - { - if (s._body) - visitStmt(s._body); - } - - override void visit(CaseStatement s) - { - if (s.statement) - visitStmt(s.statement); - } - - override void visit(CaseRangeStatement s) - { - if (s.statement) - visitStmt(s.statement); - } - - override void visit(DefaultStatement s) - { - if (s.statement) - visitStmt(s.statement); - } - - override void visit(GotoDefaultStatement s) - { - } - - override void visit(GotoCaseStatement s) - { - } - - override void visit(SwitchErrorStatement s) - { - } - - override void visit(ReturnStatement s) - { - } - - override void visit(BreakStatement s) - { - } - - override void visit(ContinueStatement s) - { - } - - override void visit(SynchronizedStatement s) - { - if (s._body) - visitStmt(s._body); - } - - override void visit(WithStatement s) - { - if (s._body) - visitStmt(s._body); - } - - override void visit(TryCatchStatement s) - { - if (s._body) - visitStmt(s._body); - if (s.catches && s.catches.dim) - { - for (size_t i = 0; i < s.catches.dim; i++) - { - Catch c = (*s.catches)[i]; - if (c && c.handler) - visitStmt(c.handler); - } - } - } - - override void visit(TryFinallyStatement s) - { - if (s._body) - visitStmt(s._body); - if (s.finalbody) - visitStmt(s.finalbody); - } - - override void visit(OnScopeStatement s) - { - } - - override void visit(ThrowStatement s) - { - } - - override void visit(DebugStatement s) - { - if (s.statement) - visitStmt(s.statement); - } - - override void visit(GotoStatement s) - { - } - - override void visit(LabelStatement s) - { - if (s.statement) - visitStmt(s.statement); - } - - override void visit(AsmStatement s) - { - } - - override void visit(ImportStatement s) - { - } -} /* Tweak all return statements and dtor call for nrvo_var, for correct NRVO. */ @@ -737,6 +491,17 @@ extern (C++) class FuncDeclaration : Declaration sc.stc |= STCref; } + // 'return' on a non-static class member function implies 'scope' as well + if (ad && ad.isClassDeclaration() && (tf.isreturn || sc.stc & STCreturn) && !(sc.stc & STCstatic)) + sc.stc |= STCscope; + + // If 'this' has no pointers, remove 'scope' as it has no meaning + if (sc.stc & STCscope && ad && ad.isStructDeclaration() && !ad.type.hasPointers()) + { + sc.stc &= ~STCscope; + tf.isscope = false; + } + sc.linkage = linkage; if (!tf.isNaked() && !(isThis() || isNested())) @@ -1204,6 +969,15 @@ extern (C++) class FuncDeclaration : Declaration } } } + + if (isOverride) + { + if (storage_class & STCdisable) + deprecation("overridden functions cannot be annotated @disable"); + if (isDeprecated) + deprecation("deprecated functions cannot be annotated @disable"); + } + } else if (isOverride() && !parent.isTemplateInstance()) error("override only applies to class member functions"); @@ -1914,7 +1688,7 @@ extern (C++) class FuncDeclaration : Declaration sc2.callSuper = 0; // Insert implicit super() at start of fbody - FuncDeclaration fd = resolveFuncCall(Loc(), sc2, cd.baseClass.ctor, null, null, null, 1); + FuncDeclaration fd = resolveFuncCall(Loc(), sc2, cd.baseClass.ctor, null, vthis.type, null, 1); if (!fd) { error("no match for implicit super() call in constructor"); @@ -2055,7 +1829,8 @@ extern (C++) class FuncDeclaration : Declaration if (!nrvo_can) exp = doCopyOrMove(sc2, exp); - checkEscape(sc2, exp, false); + if (tret.hasPointers()) + checkEscape(sc2, exp, false); } exp = checkGC(sc2, exp); @@ -2410,6 +2185,13 @@ else } } + if (vthis && vthis.storage_class & STCmaybescope) + { + vthis.storage_class &= ~STCmaybescope; + vthis.storage_class |= STCscope; + f.isscope = true; + } + // reset deco to apply inference result to mangled name if (f != type) f.deco = null; @@ -2560,6 +2342,7 @@ else { if (ad) { + //printf("declareThis() %s\n", toChars()); Type thandle = ad.handleType(); assert(thandle); thandle = thandle.addMod(type.mod); @@ -2581,6 +2364,8 @@ else if (tf.isscope) v.storage_class |= STCscope; } + if (flags & FUNCFLAGinferScope) + v.storage_class |= STCmaybescope; v.semantic(sc); if (!sc.insert(v)) @@ -2596,6 +2381,17 @@ else */ VarDeclaration v = new ThisDeclaration(loc, Type.tvoid.pointerTo()); v.storage_class |= STCparameter; + if (type.ty == Tfunction) + { + TypeFunction tf = cast(TypeFunction)type; + if (tf.isreturn) + v.storage_class |= STCreturn; + if (tf.isscope) + v.storage_class |= STCscope; + } + if (flags & FUNCFLAGinferScope) + v.storage_class |= STCmaybescope; + v.semantic(sc); if (!sc.insert(v)) assert(0); @@ -4619,17 +4415,27 @@ extern (C++) FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s, overloadApply(hasOverloads ? fd : null, (Dsymbol s) { auto fd = s.isFuncDeclaration(); - if (!fd || fd.errors || fd.type.ty == Terror) - return 0; - auto tf = cast(TypeFunction)fd.type; - .errorSupplemental(fd.loc, "%s%s", fd.toPrettyChars(), - parametersTypeToChars(tf.parameters, tf.varargs)); - if (global.params.verbose || --numToDisplay != 0 || !fd.overnext) + auto td = s.isTemplateDeclaration(); + if (fd) + { + if (fd.errors || fd.type.ty == Terror) + return 0; + + auto tf = cast(TypeFunction)fd.type; + .errorSupplemental(fd.loc, "%s%s", fd.toPrettyChars(), + parametersTypeToChars(tf.parameters, tf.varargs)); + } + else + { + .errorSupplemental(td.loc, "%s", td.toPrettyChars()); + } + + if (global.params.verbose || --numToDisplay != 0 || !fd) return 0; // Too many overloads to sensibly display. int num = 0; - overloadApply(fd.overnext, (s){ num += !!s.isFuncDeclaration(); return 0; }); + overloadApply(fd.overnext, (s){ ++num; return 0; }); if (num > 0) .errorSupplemental(loc, "... (%d more, -v to show) ...", num); return 1; // stop iterating @@ -4927,6 +4733,8 @@ extern (C++) final class FuncLiteralDeclaration : FuncDeclaration */ void modifyReturns(Scope* sc, Type tret) { + import ddmd.statement_rewrite_walker; + extern (C++) final class RetWalker : StatementRewriteWalker { alias visit = super.visit; diff --git a/ddmd/globals.d b/ddmd/globals.d index 64a38274d9b..6306c6190da 100644 --- a/ddmd/globals.d +++ b/ddmd/globals.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _globals.d) @@ -96,6 +96,7 @@ struct Param bool trace; // insert profiling hooks bool tracegc; // instrument calls to 'new' bool verbose; // verbose compile + bool vcg_ast; // write-out codegen-ast bool showColumns; // print character (column) numbers in diagnostics bool vtls; // identify thread local variables bool vgc; // identify gc usage @@ -402,7 +403,7 @@ else static assert(0, "fix this"); } } - copyright = "Copyright (c) 1999-2016 by Digital Mars"; + copyright = "Copyright (c) 1999-2017 by Digital Mars"; written = "written by Walter Bright"; version(IN_LLVM) { @@ -507,25 +508,6 @@ alias CPPMANGLEdefault = CPPMANGLE.def; alias CPPMANGLEstruct = CPPMANGLE.asStruct; alias CPPMANGLEclass = CPPMANGLE.asClass; -enum DYNCAST : int -{ - object, - expression, - dsymbol, - type, - identifier, - tuple, - parameter, -} - -alias DYNCAST_OBJECT = DYNCAST.object; -alias DYNCAST_EXPRESSION = DYNCAST.expression; -alias DYNCAST_DSYMBOL = DYNCAST.dsymbol; -alias DYNCAST_TYPE = DYNCAST.type; -alias DYNCAST_IDENTIFIER = DYNCAST.identifier; -alias DYNCAST_TUPLE = DYNCAST.tuple; -alias DYNCAST_PARAMETER = DYNCAST.parameter; - enum MATCH : int { nomatch, // no match diff --git a/ddmd/globals.h b/ddmd/globals.h index f7b9d5e121f..16f7d9e336b 100644 --- a/ddmd/globals.h +++ b/ddmd/globals.h @@ -78,6 +78,7 @@ struct Param bool trace; // insert profiling hooks bool tracegc; // instrument calls to 'new' bool verbose; // verbose compile + bool vcg_ast; // write-out codegen-ast bool showColumns; // print character (column) numbers in diagnostics bool vtls; // identify thread local variables #if !IN_LLVM @@ -382,17 +383,6 @@ enum CPPMANGLE CPPMANGLEclass, }; -enum DYNCAST -{ - DYNCAST_OBJECT, - DYNCAST_EXPRESSION, - DYNCAST_DSYMBOL, - DYNCAST_TYPE, - DYNCAST_IDENTIFIER, - DYNCAST_TUPLE, - DYNCAST_PARAMETER, -}; - enum MATCH { MATCHnomatch, // no match diff --git a/ddmd/gluelayer.d b/ddmd/gluelayer.d index 58ed16309cf..62deccb1cd3 100644 --- a/ddmd/gluelayer.d +++ b/ddmd/gluelayer.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _gluelayer.d) @@ -64,10 +64,7 @@ else version (NoBackend) RET retStyle(TypeFunction tf) { return RETregs; } void toObjFile(Dsymbol ds, bool multiobj) {} - version (OSX) - { - void objc_initSymbols() {} - } + void objc_initSymbols() {} } } else @@ -92,9 +89,6 @@ else RET retStyle(TypeFunction tf); void toObjFile(Dsymbol ds, bool multiobj); - version (OSX) - { - void objc_initSymbols(); - } + void objc_initSymbols(); } } diff --git a/ddmd/hdrgen.d b/ddmd/hdrgen.d index 2876d1ca50a..3a65649857a 100644 --- a/ddmd/hdrgen.d +++ b/ddmd/hdrgen.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _hdrgen.d) @@ -51,9 +51,11 @@ import ddmd.visitor; struct HdrGenState { - bool hdrgen; // true if generating header file - bool ddoc; // true if generating Ddoc file - bool fullQual; // fully qualify types when printing + bool hdrgen; /// true if generating header file + bool ddoc; /// true if generating Ddoc file + bool fullDump; /// true if generating a full AST dump file + + bool fullQual; /// fully qualify types when printing int tpltMember; int autoMember; int forStmtInit; @@ -89,6 +91,7 @@ public: OutBuffer* buf; HdrGenState* hgs; bool declstring; // set while declaring alias for string,wstring or dstring + EnumDeclaration inEnumDecl; extern (D) this(OutBuffer* buf, HdrGenState* hgs) { @@ -327,11 +330,18 @@ public: if (s.elsebody) { buf.writestring("else"); - buf.writenl(); - if (!s.elsebody.isScopeStatement()) + if (!s.elsebody.isIfStatement) + { + buf.writenl(); + } + else + { + buf.writeByte(' '); + } + if (!s.elsebody.isScopeStatement() && !s.elsebody.isIfStatement) buf.level++; s.elsebody.accept(this); - if (!s.elsebody.isScopeStatement()) + if (!s.elsebody.isScopeStatement() && !s.elsebody.isIfStatement) buf.level--; } } @@ -920,19 +930,19 @@ public: { foreach (id; t.idents) { - if (id.dyncast() == DYNCAST_DSYMBOL) + if (id.dyncast() == DYNCAST.dsymbol) { buf.writeByte('.'); TemplateInstance ti = cast(TemplateInstance)id; ti.accept(this); } - else if (id.dyncast() == DYNCAST_EXPRESSION) + else if (id.dyncast() == DYNCAST.expression) { buf.writeByte('['); (cast(Expression)id).accept(this); buf.writeByte(']'); } - else if (id.dyncast() == DYNCAST_TYPE) + else if (id.dyncast() == DYNCAST.type) { buf.writeByte('['); (cast(Type)id).accept(this); @@ -1323,7 +1333,7 @@ public: if (onemember && onemember.isFuncDeclaration()) buf.writestring("foo "); } - if (hgs.hdrgen && visitEponymousMember(d)) + if ((hgs.hdrgen || hgs.fullDump) && visitEponymousMember(d)) return; if (hgs.ddoc) buf.writestring(d.kind()); @@ -1335,7 +1345,7 @@ public: visitTemplateParameters(hgs.ddoc ? d.origParameters : d.parameters); buf.writeByte(')'); visitTemplateConstraint(d.constraint); - if (hgs.hdrgen) + if (hgs.hdrgen || hgs.fullDump) { hgs.tpltMember++; buf.writenl(); @@ -1452,6 +1462,17 @@ public: { buf.writestring(ti.name.toChars()); tiargsToBuffer(ti); + + if (hgs.fullDump) + { + buf.writenl(); + if (ti.aliasdecl) + { + // the ti.aliasDecl is the instantiated body + // if we have it, print it. + ti.aliasdecl.accept(this); + } + } } override void visit(TemplateMixin tm) @@ -1567,6 +1588,9 @@ public: override void visit(EnumDeclaration d) { + auto oldInEnumDecl = inEnumDecl; + scope(exit) inEnumDecl = oldInEnumDecl; + inEnumDecl = d; buf.writestring("enum "); if (d.ident) { @@ -1747,10 +1771,13 @@ public: //printf("FuncDeclaration::toCBuffer() '%s'\n", f.toChars()); if (stcToBuffer(buf, f.storage_class)) buf.writeByte(' '); - typeToBuffer(f.type, f.ident); - if (hgs.hdrgen == 1) + auto tf = cast(TypeFunction)f.type; + typeToBuffer(tf, f.ident); + + if (hgs.hdrgen) { - if (f.storage_class & STCauto) + // if the return type is missing (e.g. ref functions or auto) + if (!tf.next || f.storage_class & STCauto) { hgs.autoMember++; bodyToBuffer(f); @@ -1858,12 +1885,23 @@ public: override void visit(PostBlitDeclaration d) { + if (stcToBuffer(buf, d.storage_class)) + buf.writeByte(' '); buf.writestring("this(this)"); bodyToBuffer(d); } override void visit(DtorDeclaration d) { + if (d.storage_class & STCtrusted) + buf.writestring("@trusted "); + if (d.storage_class & STCsafe) + buf.writestring("@safe "); + if (d.storage_class & STCnogc) + buf.writestring("@nogc "); + if (d.storage_class & STCdisable) + buf.writestring("@disable "); + buf.writestring("~this()"); bodyToBuffer(d); } @@ -2100,6 +2138,21 @@ public: case Tenum: { TypeEnum te = cast(TypeEnum)t; + if (hgs.fullDump) + { + auto sym = te.sym; + if (inEnumDecl != sym) foreach(i;0 .. sym.members.dim) + { + EnumMember em = cast(EnumMember) (*sym.members)[i]; + if (em.value.toInteger == v) + { + buf.printf("%s.%s", sym.toChars(), em.ident.toChars()); + return ; + } + } + //assert(0, "We could not find the EmumMember");// for some reason it won't append char* ~ e.toChars() ~ " in " ~ sym.toChars() ); + } + buf.printf("cast(%s)", te.sym.toChars()); t = te.sym.memtype; goto L1; diff --git a/ddmd/identifier.d b/ddmd/identifier.d index 3904a093496..e15b56fca86 100644 --- a/ddmd/identifier.d +++ b/ddmd/identifier.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _identifier.d) @@ -114,9 +114,9 @@ public: return p; } - override int dyncast() const + override DYNCAST dyncast() const { - return DYNCAST_IDENTIFIER; + return DYNCAST.identifier; } extern (C++) static __gshared StringTable stringtable; diff --git a/ddmd/identifier.h b/ddmd/identifier.h index 9d785d2a4a5..406829c52a7 100644 --- a/ddmd/identifier.h +++ b/ddmd/identifier.h @@ -34,7 +34,7 @@ class Identifier : public RootObject const char *toChars(); int getValue() const; const char *toHChars2(); - int dyncast(); + int dyncast() const; static StringTable stringtable; static Identifier *generateId(const char *prefix); diff --git a/ddmd/idgen.d b/ddmd/idgen.d index ba183fa9e47..db39a97cb8a 100644 --- a/ddmd/idgen.d +++ b/ddmd/idgen.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _idgen.d) @@ -290,6 +290,7 @@ Msgtable[] msgtable = { "tls_get_addr", "___tls_get_addr" }, { "entrypoint", "__entrypoint" }, { "rt_init" }, + { "__cmp" }, // varargs implementation { "va_start" }, @@ -403,10 +404,10 @@ Msgtable[] msgtable = int main() { { - auto fp = fopen("id.h","wb"); + auto fp = fopen("ddmd/id.h","wb"); if (!fp) { - printf("can't open id.h\n"); + printf("can't open ddmd/id.h\n"); exit(EXIT_FAILURE); } @@ -431,10 +432,10 @@ int main() } { - auto fp = fopen("id.d","wb"); + auto fp = fopen("ddmd/id.d","wb"); if (!fp) { - printf("can't open id.d\n"); + printf("can't open ddmd/id.d\n"); exit(EXIT_FAILURE); } diff --git a/ddmd/impcnvtab.d b/ddmd/impcnvtab.d index aca479e0a68..9fff9583e3d 100644 --- a/ddmd/impcnvtab.d +++ b/ddmd/impcnvtab.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _impcnvtab.d) diff --git a/ddmd/imphint.d b/ddmd/imphint.d index 12275ecc177..8d917b2b240 100644 --- a/ddmd/imphint.d +++ b/ddmd/imphint.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _imphint.d) diff --git a/ddmd/import.h b/ddmd/import.h index 79eed7a7d9e..292edcb04b2 100644 --- a/ddmd/import.h +++ b/ddmd/import.h @@ -35,7 +35,7 @@ class Import : public Dsymbol Identifier *id; // module Identifier Identifier *aliasId; int isstatic; // !=0 if static import - PROTKIND protection; + Prot protection; // Pairs of alias=name to bind into current namespace Identifiers names; @@ -56,6 +56,7 @@ class Import : public Dsymbol void semantic2(Scope *sc); Dsymbol *toAlias(); void addMember(Scope *sc, ScopeDsymbol *sds); + void setScope(Scope* sc); Dsymbol *search(Loc loc, Identifier *ident, int flags = SearchLocalsOnly); bool overloadInsert(Dsymbol *s); diff --git a/ddmd/init.d b/ddmd/init.d index e9fdf05e82c..dafdbf735df 100644 --- a/ddmd/init.d +++ b/ddmd/init.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _init.d) @@ -884,6 +884,8 @@ extern (C++) final class ExpInitializer : Initializer { exp = exp.implicitCastTo(sc, t); } + if (!global.gag && olderrors != global.errors) + return this; exp = exp.ctfeInterpret(); } else diff --git a/ddmd/inline.d b/ddmd/inline.d index 337b777d87e..36645deeff3 100644 --- a/ddmd/inline.d +++ b/ddmd/inline.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _inline.d) diff --git a/ddmd/intrange.d b/ddmd/intrange.d index 0520593aeed..7c144e22de0 100644 --- a/ddmd/intrange.d +++ b/ddmd/intrange.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _intrange.d) diff --git a/ddmd/json.d b/ddmd/json.d index e883b30c80e..cd00f5ab346 100644 --- a/ddmd/json.d +++ b/ddmd/json.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _json.d) diff --git a/ddmd/lexer.d b/ddmd/lexer.d index 75483b5ff58..1b85b9b4f01 100644 --- a/ddmd/lexer.d +++ b/ddmd/lexer.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _lexer.d) @@ -157,6 +157,7 @@ class Lexer bool doDocComment; // collect doc comment information bool anyToken; // seen at least one token bool commentToken; // comments are TOKcomment's + int lastDocLine; // last line of previous doc comment bool errors; // errors occurred during lexing or parsing /********************* @@ -181,6 +182,7 @@ class Lexer line = p; this.doDocComment = doDocComment; this.commentToken = commentToken; + this.lastDocLine = 0; //initKeywords(); /* If first line starts with '#!', ignore the line */ @@ -561,7 +563,8 @@ class Lexer else if (doDocComment && t.ptr[2] == '*' && p - 4 != t.ptr) { // if /** but not /**/ - getDocComment(t, lastLine == startLoc.linnum); + getDocComment(t, lastLine == startLoc.linnum, startLoc.linnum - lastDocLine > 1); + lastDocLine = scanloc.linnum; } continue; case '/': // do // style comments @@ -587,7 +590,10 @@ class Lexer return; } if (doDocComment && t.ptr[2] == '/') - getDocComment(t, lastLine == startLoc.linnum); + { + getDocComment(t, lastLine == startLoc.linnum, startLoc.linnum - lastDocLine > 1); + lastDocLine = scanloc.linnum; + } p = end; t.loc = loc(); t.value = TOKeof; @@ -612,7 +618,10 @@ class Lexer return; } if (doDocComment && t.ptr[2] == '/') - getDocComment(t, lastLine == startLoc.linnum); + { + getDocComment(t, lastLine == startLoc.linnum, startLoc.linnum - lastDocLine > 1); + lastDocLine = scanloc.linnum; + } p++; endOfLine(); continue; @@ -681,7 +690,8 @@ class Lexer if (doDocComment && t.ptr[2] == '+' && p - 4 != t.ptr) { // if /++ but not /++/ - getDocComment(t, lastLine == startLoc.linnum); + getDocComment(t, lastLine == startLoc.linnum, startLoc.linnum - lastDocLine > 1); + lastDocLine = scanloc.linnum; } continue; } @@ -2334,8 +2344,11 @@ class Lexer * Remove leading comment character from each line. * Decide if it's a lineComment or a blockComment. * Append to previous one for this token. + * + * If newParagraph is true, an extra newline will be + * added between adjoining doc comments. */ - final void getDocComment(Token* t, uint lineComment) + final void getDocComment(Token* t, uint lineComment, bool newParagraph) { /* ct tells us which kind of comment it is: '/', '*', or '+' */ @@ -2461,19 +2474,20 @@ class Lexer auto dc = (lineComment && anyToken) ? &t.lineComment : &t.blockComment; // Combine with previous doc comment, if any if (*dc) - *dc = combineComments(*dc, buf.peekString()); + *dc = combineComments(*dc, buf.peekString(), newParagraph); else *dc = buf.extractString(); } /******************************************** * Combine two document comments into one, - * separated by a newline. + * separated by an extra newline if newParagraph is true. */ - static const(char)* combineComments(const(char)* c1, const(char)* c2) + static const(char)* combineComments(const(char)* c1, const(char)* c2, bool newParagraph) { - //printf("Lexer::combineComments('%s', '%s')\n", c1, c2); + //printf("Lexer::combineComments('%s', '%s', '%i')\n", c1, c2, newParagraph); auto c = c2; + const(int) newParagraphSize = newParagraph ? 1 : 0; // Size of the combining '\n' if (c1) { c = c1; @@ -2487,13 +2501,14 @@ class Lexer ++len1; insertNewLine = 1; } - auto p = cast(char*)mem.xmalloc(len1 + 1 + len2 + 1); + auto p = cast(char*)mem.xmalloc(len1 + newParagraphSize + len2 + 1); memcpy(p, c1, len1 - insertNewLine); if (insertNewLine) p[len1 - 1] = '\n'; - p[len1] = '\n'; - memcpy(p + len1 + 1, c2, len2); - p[len1 + 1 + len2] = 0; + if (newParagraph) + p[len1] = '\n'; + memcpy(p + len1 + newParagraphSize, c2, len2); + p[len1 + newParagraphSize + len2] = 0; c = p; } } diff --git a/ddmd/mars.d b/ddmd/mars.d index 8bd8a9a2f33..d90e083117d 100644 --- a/ddmd/mars.d +++ b/ddmd/mars.d @@ -7,7 +7,7 @@ * utilities needed for arguments parsing, path manipulation, etc... * This file is not shared with other compilers which use the DMD front-end. * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _mars.d) @@ -55,6 +55,9 @@ import ddmd.target; import ddmd.tokens; import ddmd.utils; +// strtol redeclared here because its signature changed from 2.073 to 2.074 +import core.stdc.config; +extern(C) c_long strtol(inout(char)* nptr, inout(char)** endptr, int base); version(IN_LLVM) { @@ -434,7 +437,7 @@ private int tryMain(size_t argc, const(char)** argv) { long percent; errno = 0; - percent = strtol(p + 5, cast(char**)&p, 10); + percent = strtol(p + 5, &p, 10); if (*p || errno || percent > 100) goto Lerror; global.params.covPercent = cast(ubyte)percent; @@ -543,6 +546,8 @@ private int tryMain(size_t argc, const(char)** argv) } else if (strcmp(p + 1, "v") == 0) global.params.verbose = true; + else if (strcmp(p + 1, "vcg-ast") == 0) + global.params.vcg_ast = true; else if (strcmp(p + 1, "vtls") == 0) global.params.vtls = true; else if (strcmp(p + 1, "vcolumns") == 0) @@ -555,7 +560,7 @@ private int tryMain(size_t argc, const(char)** argv) { long num; errno = 0; - num = strtol(p + 9, cast(char**)&p, 10); + num = strtol(p + 9, &p, 10); if (*p || errno || num > INT_MAX) goto Lerror; global.errorLimit = cast(uint)num; @@ -631,7 +636,7 @@ Language changes listed by -transition=id: { long num; errno = 0; - num = strtol(p + 12, cast(char**)&p, 10); + num = strtol(p + 12, &p, 10); if (*p || errno || num > INT_MAX) goto Lerror; // Bugzilla issue number @@ -882,7 +887,7 @@ Language changes listed by -transition=id: { long level; errno = 0; - level = strtol(p + 7, cast(char**)&p, 10); + level = strtol(p + 7, &p, 10); if (*p || errno || level > INT_MAX) goto Lerror; DebugCondition.setGlobalLevel(cast(int)level); @@ -908,7 +913,7 @@ Language changes listed by -transition=id: { long level; errno = 0; - level = strtol(p + 9, cast(char**)&p, 10); + level = strtol(p + 9, &p, 10); if (*p || errno || level > INT_MAX) goto Lerror; VersionCondition.setGlobalLevel(cast(int)level); @@ -1704,6 +1709,29 @@ extern (C++) int mars_mainBody(ref Strings files, ref Strings libmodules) gendocfile(m); } } + if (global.params.vcg_ast) + { + import ddmd.hdrgen; + foreach (mod; modules) + { + auto buf = new OutBuffer; + buf.doindent = 1; + scope HdrGenState hgs; + hgs.fullDump = 1; + scope PrettyPrintVisitor ppv = new PrettyPrintVisitor(buf, &hgs); + mod.accept(ppv); + + // write the output to $(filename).cg + auto modFilename = mod.srcfile.toChars(); + auto modFilenameLength = strlen(modFilename); + auto cgFilename = cast(char*)allocmemory(modFilenameLength + 4); + memcpy(cgFilename, modFilename, modFilenameLength); + cgFilename[modFilenameLength .. modFilenameLength + 4] = ".cg\0"; + auto cgFile = File(cgFilename); + cgFile.setbuffer(buf.data, buf.offset); + cgFile.write(); + } + } version (IN_LLVM) { codegenModules(modules); diff --git a/ddmd/module.h b/ddmd/module.h index ea823435824..308c253f8c8 100644 --- a/ddmd/module.h +++ b/ddmd/module.h @@ -144,6 +144,7 @@ class Module : public Package void semantic3(Scope *); // pass 3 semantic analysis int needModuleInfo(); Dsymbol *search(Loc loc, Identifier *ident, int flags = SearchLocalsOnly); + bool isPackageAccessible(Package *p, Prot protection, int flags = 0); Dsymbol *symtabInsert(Dsymbol *s); void deleteObjFile(); static void addDeferredSemantic(Dsymbol *s); diff --git a/ddmd/mtype.d b/ddmd/mtype.d index d81b568a40e..ddb7c61c62b 100644 --- a/ddmd/mtype.d +++ b/ddmd/mtype.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _mtype.d) @@ -643,9 +643,9 @@ extern (C++) abstract class Type : RootObject } // kludge for template.isType() - override final int dyncast() + override final DYNCAST dyncast() const { - return DYNCAST_TYPE; + return DYNCAST.type; } /******************************* @@ -704,7 +704,7 @@ extern (C++) abstract class Type : RootObject { goto Ldistinct; } - inoutmismatch = !fparam1.isCovariant(fparam2); + inoutmismatch = !fparam1.isCovariant(t1.isref, fparam2); } } else if (t1.parameters != t2.parameters) @@ -765,8 +765,28 @@ extern (C++) abstract class Type : RootObject if (t1.isref != t2.isref) goto Lnotcovariant; - // We can subtract 'return' from 'this', but cannot add it - if (t1.isreturn && !t2.isreturn) + if (!t1.isref && (t1.isscope || t2.isscope)) + { + StorageClass stc1 = t1.isscope ? STCscope : 0; + StorageClass stc2 = t2.isscope ? STCscope : 0; + if (t1.isreturn) + { + stc1 |= STCreturn; + if (!t1.isscope) + stc1 |= STCref; + } + if (t2.isreturn) + { + stc2 |= STCreturn; + if (!t2.isscope) + stc2 |= STCref; + } + if (!Parameter.isCovariantScope(t1.isref, stc1, stc2)) + goto Lnotcovariant; + } + + // We can subtract 'return ref' from 'this', but cannot add it + else if (t1.isreturn && !t2.isreturn) goto Lnotcovariant; /* Can convert mutable to const @@ -2642,7 +2662,7 @@ extern (C++) abstract class Type : RootObject e = getProperty(e.loc, ident, flag & DotExpFlag.gag); Lreturn: - if (!(flag & DotExpFlag.gag) || e) + if (e) e = e.semantic(sc); return e; } @@ -4759,7 +4779,7 @@ extern (C++) final class TypeSArray : TypeArray } RootObject o = (*tup.objects)[cast(size_t)d]; - if (o.dyncast() != DYNCAST_TYPE) + if (o.dyncast() != DYNCAST.type) { error(loc, "%s is not a type", toChars()); return Type.terror; @@ -4804,13 +4824,14 @@ extern (C++) final class TypeSArray : TypeArray if (d1 != d2) { Loverflow: - error(loc, "%s size %llu * %llu exceeds the size limit for static arrays (overflow)", toChars(), cast(ulong)tbn.size(loc), cast(ulong)d1); + error(loc, "%s size %llu * %llu exceeds 0x%llx size limit for static array", + toChars(), cast(ulong)tbn.size(loc), cast(ulong)d1, Target.maxStaticDataSize); goto Lerror; } Type tbx = tbn.baseElemOf(); if (tbx.ty == Tstruct && !(cast(TypeStruct)tbx).sym.members || tbx.ty == Tenum && !(cast(TypeEnum)tbx).sym.members) { - /* To avoid meaningess error message, skip the total size limit check + /* To avoid meaningless error message, skip the total size limit check * when the bottom of element type is opaque. */ } @@ -4820,20 +4841,8 @@ extern (C++) final class TypeSArray : TypeArray * run on them for the size, since they may be forward referenced. */ bool overflow = false; -version(IN_LLVM) -{ - /+ The size limit that DMD imposes here is only there to work around an optlink bug, which doesn't apply to LDC. - + https://issues.dlang.org/show_bug.cgi?id=14859 - +/ - auto _ = mulu(tbn.size(loc), d2, overflow); - if (overflow) - goto Loverflow; -} -else -{ - if (mulu(tbn.size(loc), d2, overflow) >= 0x100_0000 || overflow) // put a 'reasonable' limit on it + if (mulu(tbn.size(loc), d2, overflow) >= Target.maxStaticDataSize || overflow) goto Loverflow; -} } } switch (tbn.ty) @@ -4913,12 +4922,12 @@ else } RootObject o = (*tup.objects)[cast(size_t)d]; - if (o.dyncast() == DYNCAST_DSYMBOL) + if (o.dyncast() == DYNCAST.dsymbol) { *ps = cast(Dsymbol)o; return; } - if (o.dyncast() == DYNCAST_EXPRESSION) + if (o.dyncast() == DYNCAST.expression) { Expression e = cast(Expression)o; if (e.op == TOKdsymbol) @@ -4933,7 +4942,7 @@ else } return; } - if (o.dyncast() == DYNCAST_TYPE) + if (o.dyncast() == DYNCAST.type) { *ps = null; *pt = (cast(Type)o).addMod(this.mod); @@ -6165,8 +6174,8 @@ extern (C++) final class TypeFunction : TypeNext if (sc.stc & STCscope) tf.isscope = true; - if ((sc.stc & (STCreturn | STCref)) == STCreturn) - tf.isscope = true; // return by itself means 'return scope' +// if (tf.isreturn && !tf.isref) +// tf.isscope = true; // return by itself means 'return scope' if (tf.trust == TRUSTdefault) { @@ -6220,7 +6229,7 @@ extern (C++) final class TypeFunction : TypeNext if (tf.isreturn && !tf.isref && !tf.next.hasPointers()) { - error(loc, "function has 'return' but does not return any indirections"); + error(loc, "function type '%s' has 'return' but does not return any indirections", tf.toChars()); } } @@ -6339,7 +6348,7 @@ extern (C++) final class TypeFunction : TypeNext } } - if (fparam.storageClass & STCscope && !fparam.type.hasPointers()) + if (fparam.storageClass & STCscope && !fparam.type.hasPointers() && fparam.type.ty != Ttuple) { fparam.storageClass &= ~STCscope; if (!(fparam.storageClass & STCref)) @@ -6665,6 +6674,7 @@ extern (C++) final class TypeFunction : TypeNext */ final StorageClass parameterStorageClass(Parameter p) { + //printf("parameterStorageClass(p: %s)\n", p.toChars()); auto stc = p.storageClass; if (!global.params.vsafe) return stc; @@ -6686,6 +6696,8 @@ extern (C++) final class TypeFunction : TypeNext foreach (const i; 0 .. dim) { Parameter fparam = Parameter.getNth(parameters, i); + if (fparam == p) + continue; Type t = fparam.type; if (!t) continue; @@ -6708,13 +6720,21 @@ extern (C++) final class TypeFunction : TypeNext stc |= STCscope; - Type tret = nextOf().toBasetype(); - if (isref || tret.hasPointers()) + /* Inferring STCreturn here has false positives + * for pure functions, producing spurious error messages + * about escaping references. + * Give up on it for now. + */ + version (none) { - /* The result has references, so p could be escaping - * that way. - */ - stc |= STCreturn; + Type tret = nextOf().toBasetype(); + if (isref || tret.hasPointers()) + { + /* The result has references, so p could be escaping + * that way. + */ + stc |= STCreturn; + } } return stc; @@ -6722,8 +6742,13 @@ extern (C++) final class TypeFunction : TypeNext override Type addStorageClass(StorageClass stc) { + //printf("addStorageClass(%llx) %d\n", stc, (stc & STCscope) != 0); TypeFunction t = cast(TypeFunction)Type.addStorageClass(stc); - if ((stc & STCpure && !t.purity) || (stc & STCnothrow && !t.isnothrow) || (stc & STCnogc && !t.isnogc) || (stc & STCsafe && t.trust < TRUSTtrusted)) + if ((stc & STCpure && !t.purity) || + (stc & STCnothrow && !t.isnothrow) || + (stc & STCnogc && !t.isnogc) || + (stc & STCscope && !t.isscope) || + (stc & STCsafe && t.trust < TRUSTtrusted)) { // Klunky to change these auto tf = new TypeFunction(t.parameters, t.next, t.varargs, t.linkage, 0); @@ -6747,6 +6772,8 @@ extern (C++) final class TypeFunction : TypeNext tf.isnogc = true; if (stc & STCsafe) tf.trust = TRUSTsafe; + if (stc & STCscope) + tf.isscope = true; tf.deco = tf.merge().deco; t = tf; @@ -7216,6 +7243,25 @@ extern (C++) final class TypeDelegate : TypeNext } } + override Type addStorageClass(StorageClass stc) + { + TypeDelegate t = cast(TypeDelegate)Type.addStorageClass(stc); + if (!global.params.vsafe) + return t; + + /* The rest is meant to add 'scope' to a delegate declaration if it is of the form: + * alias dg_t = void* delegate(); + * scope dg_t dg = ...; + */ + auto n = t.next.addStorageClass(stc & STCscope); + if (n != t.next) + { + t.next = n; + t.deco = t.merge().deco; + } + return t; + } + override d_uns64 size(Loc loc) const { return Target.ptrsize * 2; @@ -7340,19 +7386,19 @@ extern (C++) abstract class TypeQualified : Type for (size_t i = 0; i < idents.dim; i++) { RootObject id = t.idents[i]; - if (id.dyncast() == DYNCAST_DSYMBOL) + if (id.dyncast() == DYNCAST.dsymbol) { TemplateInstance ti = cast(TemplateInstance)id; ti = cast(TemplateInstance)ti.syntaxCopy(null); id = ti; } - else if (id.dyncast() == DYNCAST_EXPRESSION) + else if (id.dyncast() == DYNCAST.expression) { Expression e = cast(Expression)id; e = e.syntaxCopy(); id = e; } - else if (id.dyncast() == DYNCAST_TYPE) + else if (id.dyncast() == DYNCAST.type) { Type tx = cast(Type)id; tx = tx.syntaxCopy(); @@ -7459,24 +7505,24 @@ extern (C++) abstract class TypeQualified : Type switch (id.dyncast()) { // ... '. ident' - case DYNCAST_IDENTIFIER: + case DYNCAST.identifier: e = new DotIdExp(e.loc, e, cast(Identifier)id); break; // ... '. name!(tiargs)' - case DYNCAST_DSYMBOL: + case DYNCAST.dsymbol: auto ti = (cast(Dsymbol)id).isTemplateInstance(); assert(ti); e = new DotTemplateInstanceExp(e.loc, e, ti.name, ti.tiargs); break; // ... '[type]' - case DYNCAST_TYPE: // Bugzilla 1215 + case DYNCAST.type: // Bugzilla 1215 e = new ArrayExp(loc, e, new TypeExp(loc, cast(Type)id)); break; // ... '[expr]' - case DYNCAST_EXPRESSION: // Bugzilla 1215 + case DYNCAST.expression: // Bugzilla 1215 e = new ArrayExp(loc, e, cast(Expression)id); break; @@ -7519,8 +7565,8 @@ extern (C++) abstract class TypeQualified : Type for (size_t i = 0; i < idents.dim; i++) { RootObject id = idents[i]; - if (id.dyncast() == DYNCAST_EXPRESSION || - id.dyncast() == DYNCAST_TYPE) + if (id.dyncast() == DYNCAST.expression || + id.dyncast() == DYNCAST.type) { Type tx; Expression ex; @@ -7586,7 +7632,7 @@ extern (C++) abstract class TypeQualified : Type if (t) { sm = t.toDsymbol(sc); - if (sm && id.dyncast() == DYNCAST_IDENTIFIER) + if (sm && id.dyncast() == DYNCAST.identifier) { sm = sm.search(loc, cast(Identifier)id); if (sm) @@ -7608,14 +7654,14 @@ extern (C++) abstract class TypeQualified : Type } else { - if (id.dyncast() == DYNCAST_DSYMBOL) + if (id.dyncast() == DYNCAST.dsymbol) { // searchX already handles errors for template instances assert(global.errors); } else { - assert(id.dyncast() == DYNCAST_IDENTIFIER); + assert(id.dyncast() == DYNCAST.identifier); sm = s.search_correct(cast(Identifier)id); if (sm) error(loc, "identifier '%s' of '%s' is not defined, did you mean %s '%s'?", id.toChars(), toChars(), sm.kind(), sm.toChars()); @@ -8012,7 +8058,7 @@ extern (C++) final class TypeTypeof : TypeQualified *pt = null; *ps = null; - //printf("TypeTypeof::resolve(sc = %p, idents = '%s')\n", sc, toChars()); + //printf("TypeTypeof::resolve(this = %p, sc = %p, idents = '%s')\n", this, sc, toChars()); //static int nest; if (++nest == 50) *(char*)0=0; if (inuse) { @@ -10075,7 +10121,7 @@ extern (C++) final class TypeNull : Type return m; // NULL implicitly converts to any pointer type or dynamic array - //if (type.ty == Tpointer && type.nextOf()->ty == Tvoid) + //if (type.ty == Tpointer && type.nextOf().ty == Tvoid) { Type tb = to.toBasetype(); if (tb.ty == Tnull || tb.ty == Tpointer || tb.ty == Tarray || tb.ty == Taarray || tb.ty == Tclass || tb.ty == Tdelegate) @@ -10162,9 +10208,9 @@ extern (C++) final class Parameter : RootObject } // kludge for template.isType() - override int dyncast() + override DYNCAST dyncast() const { - return DYNCAST_PARAMETER; + return DYNCAST.parameter; } void accept(Visitor v) @@ -10298,15 +10344,99 @@ extern (C++) final class Parameter : RootObject * true = `this` can be used in place of `p` * false = nope */ - final bool isCovariant(const Parameter p) const pure nothrow @nogc @safe + final bool isCovariant(bool returnByRef, const Parameter p) const pure nothrow @nogc @safe { enum stc = STCref | STCin | STCout | STClazy; - return !((this.storageClass & stc) != (p.storageClass & stc) || + if ((this.storageClass & stc) != (p.storageClass & stc)) + return false; + return isCovariantScope(returnByRef, this.storageClass, p.storageClass); + } + + static bool isCovariantScope(bool returnByRef, StorageClass from, StorageClass to) pure nothrow @nogc @safe + { + if (from == to) + return true; - // We can add scope, but not subtract it - (!(this.storageClass & STCscope) && (p.storageClass & STCscope)) || + /* Shrinking the representation is necessary because StorageClass is so wide + * Params: + * returnByRef = true if the function returns by ref + * stc = storage class of parameter + */ + static uint buildSR(bool returnByRef, StorageClass stc) pure nothrow @nogc @safe + { + uint result; + final switch (stc & (STCref | STCscope | STCreturn)) + { + case 0: result = SR.None; break; + case STCref: result = SR.Ref; break; + case STCscope: result = SR.Scope; break; + case STCreturn | STCref: result = SR.ReturnRef; break; + case STCreturn | STCscope: result = SR.ReturnScope; break; + case STCref | STCscope: result = SR.RefScope; break; + case STCreturn | STCref | STCscope: + result = returnByRef ? SR.ReturnRef_Scope : SR.Ref_ReturnScope; + break; + } + return result; + } + + /* result is true if the 'from' can be used as a 'to' + */ + + if ((from ^ to) & STCref) // differing in 'ref' means no covariance + return false; - // We can subtract return, but not add it - ((this.storageClass & STCreturn) && !(p.storageClass & STCreturn))); + return covariant[buildSR(returnByRef, from)][buildSR(returnByRef, to)]; } + + /* Classification of 'scope-return-ref' possibilities + */ + enum SR + { + None, + Scope, + ReturnScope, + Ref, + ReturnRef, + RefScope, + ReturnRef_Scope, + Ref_ReturnScope, + } + + static bool[SR.max + 1][SR.max + 1] covariantInit() pure nothrow @nogc @safe + { + /* Initialize covariant[][] with this: + + From\To n rs s + None X + ReturnScope X X + Scope X X X + + From\To r rr rs rr-s r-rs + Ref X X + ReturnRef X + RefScope X X X X X + ReturnRef-Scope X X + Ref-ReturnScope X X X + */ + bool[SR.max + 1][SR.max + 1] covariant; + + foreach (i; 0 .. SR.max + 1) + { + covariant[i][i] = true; + covariant[SR.RefScope][i] = true; + } + covariant[SR.ReturnScope][SR.None] = true; + covariant[SR.Scope ][SR.None] = true; + covariant[SR.Scope ][SR.ReturnScope] = true; + + covariant[SR.Ref ][SR.ReturnRef] = true; + covariant[SR.ReturnRef_Scope][SR.ReturnRef] = true; + covariant[SR.Ref_ReturnScope][SR.Ref ] = true; + covariant[SR.Ref_ReturnScope][SR.ReturnRef] = true; + + return covariant; + } + + extern (D) static immutable bool[SR.max + 1][SR.max + 1] covariant = covariantInit(); } diff --git a/ddmd/mtype.h b/ddmd/mtype.h index 0cae2a4eca8..fbe5fef7e09 100644 --- a/ddmd/mtype.h +++ b/ddmd/mtype.h @@ -242,7 +242,7 @@ class Type : public RootObject bool equals(RootObject *o); bool equivalent(Type *t); // kludge for template.isType() - int dyncast() { return DYNCAST_TYPE; } + int dyncast() const { return DYNCAST_TYPE; } int covariant(Type *t, StorageClass *pstc = NULL); const char *toChars(); char *toPrettyChars(bool QualifyTypes = false); @@ -336,6 +336,7 @@ class Type : public RootObject virtual bool isZeroInit(Loc loc = Loc()); // if initializer is 0 Identifier *getTypeInfoIdent(); virtual void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false); + void resolveExp(Expression *e, Type **pt, Expression **pe, Dsymbol **ps); virtual int hasWild() const; virtual Expression *toExpression(); virtual bool hasPointers(); @@ -622,6 +623,7 @@ class TypeFunction : public TypeNext void purityLevel(); bool hasLazyParameters(); bool parameterEscapes(Parameter *p); + StorageClass parameterStorageClass(Parameter *p); Type *addStorageClass(StorageClass stc); /** For each active attribute (ref/const/nogc/etc) call fp with a void* for the @@ -672,8 +674,7 @@ class TypeQualified : public Type void resolveTupleIndex(Loc loc, Scope *sc, Dsymbol *s, Expression **pe, Type **pt, Dsymbol **ps, RootObject *oindex); - void resolveExprType(Loc loc, Scope *sc, Expression *e, size_t i, - Expression **pe, Type **pt); + Expression *toExpressionHelper(Expression *e, size_t i = 0); void resolveHelper(Loc loc, Scope *sc, Dsymbol *s, Dsymbol *scopesym, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false); @@ -911,12 +912,14 @@ class Parameter : public RootObject Parameter *syntaxCopy(); Type *isLazyArray(); // kludge for template.isType() - int dyncast() { return DYNCAST_PARAMETER; } + int dyncast() const { return DYNCAST_PARAMETER; } virtual void accept(Visitor *v) { v->visit(this); } static Parameters *arraySyntaxCopy(Parameters *parameters); static size_t dim(Parameters *parameters); static Parameter *getNth(Parameters *parameters, d_size_t nth, d_size_t *pn = NULL); + const char *toChars(); + bool isCovariant(const Parameter *p) const; }; bool arrayTypeCompatible(Loc loc, Type *t1, Type *t2); diff --git a/ddmd/nogc.d b/ddmd/nogc.d index 6aef00d10b2..5264e9f197c 100644 --- a/ddmd/nogc.d +++ b/ddmd/nogc.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _nogc.d) diff --git a/ddmd/nspace.d b/ddmd/nspace.d index 4f2a1ad1182..f6dabb5fbb7 100644 --- a/ddmd/nspace.d +++ b/ddmd/nspace.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _nspace.d) diff --git a/ddmd/objc.d b/ddmd/objc.d index cd5a4e1efdf..b006bf1b72f 100644 --- a/ddmd/objc.d +++ b/ddmd/objc.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _objc.d) diff --git a/ddmd/opover.d b/ddmd/opover.d index a5eb50243a0..6983450a9f6 100644 --- a/ddmd/opover.d +++ b/ddmd/opover.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _opover.d) diff --git a/ddmd/optimize.d b/ddmd/optimize.d index 3e9793080c0..72625a4ae5f 100644 --- a/ddmd/optimize.d +++ b/ddmd/optimize.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _optimize.d) diff --git a/ddmd/parse.d b/ddmd/parse.d index 59e6a452599..e64a7ee6ac3 100644 --- a/ddmd/parse.d +++ b/ddmd/parse.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _parse.d) @@ -2869,22 +2869,29 @@ final class Parser : Lexer //if ((storageClass & STCscope) && (storageClass & (STCref | STCout))) //error("scope cannot be ref or out"); - Token* t; - if (tpl && token.value == TOKidentifier && (t = peek(&token), (t.value == TOKcomma || t.value == TOKrparen || t.value == TOKdotdotdot))) + if (tpl && token.value == TOKidentifier) { - Identifier id = Identifier.generateId("__T"); - const loc = token.loc; - at = new TypeIdentifier(loc, id); - if (!*tpl) - *tpl = new TemplateParameters(); - TemplateParameter tp = new TemplateTypeParameter(loc, id, null, null); - (*tpl).push(tp); - - ai = token.ident; - nextToken(); + Token* t = peek(&token); + if (t.value == TOKcomma || t.value == TOKrparen || t.value == TOKdotdotdot) + { + Identifier id = Identifier.generateId("__T"); + const loc = token.loc; + at = new TypeIdentifier(loc, id); + if (!*tpl) + *tpl = new TemplateParameters(); + TemplateParameter tp = new TemplateTypeParameter(loc, id, null, null); + (*tpl).push(tp); + + ai = token.ident; + nextToken(); + } + else goto _else; } else + { + _else: at = parseType(&ai); + } ae = null; if (token.value == TOKassign) // = defaultArg { @@ -6665,6 +6672,7 @@ final class Parser : Lexer case TOKscope: case TOKfinal: case TOKauto: + case TOKreturn: continue; case TOKconst: @@ -7409,7 +7417,7 @@ final class Parser : Lexer { tok = token.value; nextToken(); - if (tok == TOKequal && (token.value == TOKstruct || token.value == TOKunion || token.value == TOKclass || token.value == TOKsuper || token.value == TOKenum || token.value == TOKinterface || token.value == TOKargTypes || token.value == TOKparameters || token.value == TOKconst && peek(&token).value == TOKrparen || token.value == TOKimmutable && peek(&token).value == TOKrparen || token.value == TOKshared && peek(&token).value == TOKrparen || token.value == TOKwild && peek(&token).value == TOKrparen || token.value == TOKfunction || token.value == TOKdelegate || token.value == TOKreturn)) + if (tok == TOKequal && (token.value == TOKstruct || token.value == TOKunion || token.value == TOKclass || token.value == TOKsuper || token.value == TOKenum || token.value == TOKinterface || token.value == TOKargTypes || token.value == TOKparameters || token.value == TOKconst && peek(&token).value == TOKrparen || token.value == TOKimmutable && peek(&token).value == TOKrparen || token.value == TOKshared && peek(&token).value == TOKrparen || token.value == TOKwild && peek(&token).value == TOKrparen || token.value == TOKfunction || token.value == TOKdelegate || token.value == TOKreturn || (token.value == TOKvector && peek(&token).value == TOKrparen))) { tok2 = token.value; nextToken(); @@ -8421,7 +8429,7 @@ final class Parser : Lexer */ void addComment(Dsymbol s, const(char)* blockComment) { - s.addComment(combineComments(blockComment, token.lineComment)); + s.addComment(combineComments(blockComment, token.lineComment, true)); token.lineComment = null; } } diff --git a/ddmd/root/aav.d b/ddmd/root/aav.d index e57686756f6..00d2ce2cff9 100644 --- a/ddmd/root/aav.d +++ b/ddmd/root/aav.d @@ -2,7 +2,7 @@ * Compiler implementation of the D programming language * http://dlang.org * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC root/_aav.d) diff --git a/ddmd/root/array.d b/ddmd/root/array.d index b0ac6406b84..d0d4425acd9 100644 --- a/ddmd/root/array.d +++ b/ddmd/root/array.d @@ -1,5 +1,5 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2016 by Digital Mars +// Copyright (c) 1999-2017 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com diff --git a/ddmd/root/array.h b/ddmd/root/array.h index 49a320ed039..a215b45668c 100644 --- a/ddmd/root/array.h +++ b/ddmd/root/array.h @@ -133,7 +133,7 @@ struct Array dim++; } - void remove(size_t i) + void remove(d_size_t i) { if (dim - i - 1) memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0])); @@ -181,7 +181,7 @@ struct Array return data[index]; } - void insert(size_t index, TYPE v) + void insert(d_size_t index, TYPE v) { reserve(1); memmove(data + index + 1, data + index, (dim - index) * sizeof(*data)); @@ -189,11 +189,11 @@ struct Array dim++; } - void insert(size_t index, Array *a) + void insert(d_size_t index, Array *a) { if (a) { - size_t d = a->dim; + d_size_t d = a->dim; reserve(d); if (dim != index) memmove(data + index + d, data + index, (dim - index) * sizeof(*data)); @@ -355,8 +355,8 @@ struct BitArray mem.xfree(ptr); } - size_t len; - size_t *ptr; + d_size_t len; + d_size_t *ptr; private: BitArray(const BitArray&); diff --git a/ddmd/root/ctfloat.d b/ddmd/root/ctfloat.d index 3718fa7ca8e..f8a1d96ae11 100644 --- a/ddmd/root/ctfloat.d +++ b/ddmd/root/ctfloat.d @@ -1,5 +1,5 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2016 by Digital Mars +// Copyright (c) 1999-2017 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -95,6 +95,16 @@ extern (C++) struct CTFloat return memcmp(&a, &b, sz) == 0; } + static size_t hash(real_t a) + { + import ddmd.root.hash : calcHash; + + if (isNaN(a)) + a = real_t.nan; + enum sz = (real_t.mant_dig == 64) ? 10 : real_t.sizeof; + return calcHash(cast(ubyte*) &a, sz); + } + static bool isNaN(real_t r) { return !(r == r); diff --git a/ddmd/root/file.d b/ddmd/root/file.d index c0e84a3790d..b24b0ee7fec 100644 --- a/ddmd/root/file.d +++ b/ddmd/root/file.d @@ -2,7 +2,7 @@ * Compiler implementation of the D programming language * http://dlang.org * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC root/_file.d) diff --git a/ddmd/root/filename.d b/ddmd/root/filename.d index 1720eef706a..c4a72c5bd1d 100644 --- a/ddmd/root/filename.d +++ b/ddmd/root/filename.d @@ -2,7 +2,7 @@ * Compiler implementation of the D programming language * http://dlang.org * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC root/_filename.d) diff --git a/ddmd/root/hash.d b/ddmd/root/hash.d new file mode 100644 index 00000000000..74e53c26581 --- /dev/null +++ b/ddmd/root/hash.d @@ -0,0 +1,67 @@ +/** + * Compiler implementation of the D programming language + * http://dlang.org + * + * Copyright: Copyright (c) 1999-2017 by Digital Mars, All Rights Reserved + * Authors: Martin Nowak, Walter Bright, http://www.digitalmars.com + * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) + * Source: $(DMDSRC root/_hash.d) + */ + +module ddmd.root.hash; + +// MurmurHash2 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. +// https://sites.google.com/site/murmurhash/ +uint calcHash(const(char)* data, size_t len) pure nothrow @nogc +{ + return calcHash(cast(const(ubyte)*)data, len); +} + +uint calcHash(const(ubyte)* data, size_t len) pure nothrow @nogc +{ + // 'm' and 'r' are mixing constants generated offline. + // They're not really 'magic', they just happen to work well. + enum uint m = 0x5bd1e995; + enum int r = 24; + // Initialize the hash to a 'random' value + uint h = cast(uint)len; + // Mix 4 bytes at a time into the hash + while (len >= 4) + { + uint k = data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0]; + k *= m; + k ^= k >> r; + h = (h * m) ^ (k * m); + data += 4; + len -= 4; + } + // Handle the last few bytes of the input array + switch (len & 3) + { + case 3: + h ^= data[2] << 16; + goto case; + case 2: + h ^= data[1] << 8; + goto case; + case 1: + h ^= data[0]; + h *= m; + goto default; + default: + break; + } + // Do a few final mixes of the hash to ensure the last few + // bytes are well-incorporated. + h ^= h >> 13; + h *= m; + h ^= h >> 15; + return h; +} + +// combine and mix two words (boost::hash_combine) +size_t mixHash(size_t h, size_t k) +{ + return h ^ (k + 0x9e3779b9 + (h << 6) + (h >> 2)); +} diff --git a/ddmd/root/man.d b/ddmd/root/man.d index b1c684608e2..48f09b9b2d7 100644 --- a/ddmd/root/man.d +++ b/ddmd/root/man.d @@ -2,7 +2,7 @@ * Compiler implementation of the D programming language * http://dlang.org * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC root/_man.d) diff --git a/ddmd/root/object.h b/ddmd/root/object.h index 38a3c384993..fb6223ded7d 100644 --- a/ddmd/root/object.h +++ b/ddmd/root/object.h @@ -24,6 +24,18 @@ typedef size_t hash_t; struct OutBuffer; +enum DYNCAST +{ + DYNCAST_OBJECT, + DYNCAST_EXPRESSION, + DYNCAST_DSYMBOL, + DYNCAST_TYPE, + DYNCAST_IDENTIFIER, + DYNCAST_TUPLE, + DYNCAST_PARAMETER, + DYNCAST_STATEMENT, +}; + /* * Root of our class library. */ @@ -52,7 +64,7 @@ class RootObject * Used as a replacement for dynamic_cast. Returns a unique number * defined by the library user. For Object, the return value is 0. */ - virtual int dyncast(); + virtual int dyncast() const; }; #endif diff --git a/ddmd/root/outbuffer.d b/ddmd/root/outbuffer.d index 854cb394043..cc0f6594a9d 100644 --- a/ddmd/root/outbuffer.d +++ b/ddmd/root/outbuffer.d @@ -2,7 +2,7 @@ * Compiler implementation of the D programming language * http://dlang.org * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC root/_outbuffer.d) diff --git a/ddmd/root/port.d b/ddmd/root/port.d index 790235627b3..dc885a2d486 100644 --- a/ddmd/root/port.d +++ b/ddmd/root/port.d @@ -2,7 +2,7 @@ * Compiler implementation of the D programming language * http://dlang.org * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC root/_port.d) diff --git a/ddmd/root/rmem.d b/ddmd/root/rmem.d index 7daf69c85af..e954022d4f2 100644 --- a/ddmd/root/rmem.d +++ b/ddmd/root/rmem.d @@ -2,7 +2,7 @@ * Compiler implementation of the D programming language * http://dlang.org * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC root/_rmem.d) diff --git a/ddmd/root/rootobject.d b/ddmd/root/rootobject.d index a895fcbf7ea..710ce2b4ab8 100644 --- a/ddmd/root/rootobject.d +++ b/ddmd/root/rootobject.d @@ -2,7 +2,7 @@ * Compiler implementation of the D programming language * http://dlang.org * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC root/_rootobject.d) @@ -16,6 +16,23 @@ import ddmd.root.outbuffer; /*********************************************************** */ + +enum DYNCAST : int +{ + object, + expression, + dsymbol, + type, + identifier, + tuple, + parameter, + statement, + condition, +} + +/*********************************************************** + */ + extern (C++) class RootObject { this() @@ -47,8 +64,8 @@ extern (C++) class RootObject assert(0); } - int dyncast() + DYNCAST dyncast() const { - assert(0); + return DYNCAST.object; } } diff --git a/ddmd/root/speller.d b/ddmd/root/speller.d index 693ccf7c089..b0a805c2733 100644 --- a/ddmd/root/speller.d +++ b/ddmd/root/speller.d @@ -2,7 +2,7 @@ * Compiler implementation of the D programming language * http://dlang.org * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC root/_speller.d) diff --git a/ddmd/root/stringtable.d b/ddmd/root/stringtable.d index ee51b32c42e..f8bd2cc1511 100644 --- a/ddmd/root/stringtable.d +++ b/ddmd/root/stringtable.d @@ -2,7 +2,7 @@ * Compiler implementation of the D programming language * http://dlang.org * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC root/_stringtable.d) @@ -11,58 +11,11 @@ module ddmd.root.stringtable; import core.stdc.string; -import ddmd.root.rmem; +import ddmd.root.rmem, ddmd.root.hash; enum POOL_BITS = 12; enum POOL_SIZE = (1U << POOL_BITS); -// TODO: Merge with root.String -// MurmurHash2 was written by Austin Appleby, and is placed in the public -// domain. The author hereby disclaims copyright to this source code. -// https://sites.google.com/site/murmurhash/ -private uint calcHash(const(char)* key, size_t len) pure nothrow @nogc -{ - // 'm' and 'r' are mixing constants generated offline. - // They're not really 'magic', they just happen to work well. - enum uint m = 0x5bd1e995; - enum int r = 24; - // Initialize the hash to a 'random' value - uint h = cast(uint)len; - // Mix 4 bytes at a time into the hash - const(ubyte)* data = cast(const(ubyte)*)key; - while (len >= 4) - { - uint k = data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0]; - k *= m; - k ^= k >> r; - h = (h * m) ^ (k * m); - data += 4; - len -= 4; - } - // Handle the last few bytes of the input array - switch (len & 3) - { - case 3: - h ^= data[2] << 16; - goto case; - case 2: - h ^= data[1] << 8; - goto case; - case 1: - h ^= data[0]; - h *= m; - goto default; - default: - break; - } - // Do a few final mixes of the hash to ensure the last few - // bytes are well-incorporated. - h ^= h >> 13; - h *= m; - h ^= h >> 15; - return h; -} - private size_t nextpow2(size_t val) pure nothrow @nogc @safe { size_t res = 1; diff --git a/ddmd/root/stringtable.h b/ddmd/root/stringtable.h index 2294b2808eb..e18a22c6f70 100644 --- a/ddmd/root/stringtable.h +++ b/ddmd/root/stringtable.h @@ -51,7 +51,9 @@ struct StringTable ~StringTable(); StringValue *lookup(const char *s, d_size_t len); + StringValue *insert(const char *s, size_t len, void *ptrvalue); StringValue *update(const char *s, d_size_t len); + int apply(int (*fp)(StringValue *)); }; #endif diff --git a/ddmd/safe.d b/ddmd/safe.d index 5fa725fcc24..673f0f0a1a9 100644 --- a/ddmd/safe.d +++ b/ddmd/safe.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _safe.d) diff --git a/ddmd/sapply.d b/ddmd/sapply.d index 61f2e1b456f..6ab0e688855 100644 --- a/ddmd/sapply.d +++ b/ddmd/sapply.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _sparse.d) diff --git a/ddmd/scope.h b/ddmd/scope.h index fc266a4ab93..927b9744e74 100644 --- a/ddmd/scope.h +++ b/ddmd/scope.h @@ -74,7 +74,7 @@ struct Scope { Scope *enclosing; // enclosing Scope - Module *module; // Root module + Module *_module; // Root module ScopeDsymbol *scopesym; // current symbol ScopeDsymbol *sds; // if in static if, and declaring new symbols, // sds gets the addMember() diff --git a/ddmd/sideeffect.d b/ddmd/sideeffect.d index 70d22a36b9a..21118d987bc 100644 --- a/ddmd/sideeffect.d +++ b/ddmd/sideeffect.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _sideeffect.d) diff --git a/ddmd/statement.d b/ddmd/statement.d index eb2aa6ccd48..ac0a74a94b7 100644 --- a/ddmd/statement.d +++ b/ddmd/statement.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _statement.d) @@ -112,6 +112,11 @@ extern (C++) abstract class Statement : RootObject { Loc loc; + override final DYNCAST dyncast() const + { + return DYNCAST.statement; + } + final extern (D) this(Loc loc) { this.loc = loc; diff --git a/ddmd/statement.h b/ddmd/statement.h index c64759b6440..6d4aedc35ca 100644 --- a/ddmd/statement.h +++ b/ddmd/statement.h @@ -588,6 +588,10 @@ class Catch : public RootObject Identifier *ident; VarDeclaration *var; Statement *handler; + + // set if semantic processing errors + bool errors; + // was generated by the compiler, // wasn't present in source code bool internalCatch; diff --git a/ddmd/statement_rewrite_walker.d b/ddmd/statement_rewrite_walker.d new file mode 100644 index 00000000000..95bd04b3b47 --- /dev/null +++ b/ddmd/statement_rewrite_walker.d @@ -0,0 +1,265 @@ +/** + * Compiler implementation of the + * $(LINK2 http://www.dlang.org, D programming language). + * + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _statement_rewrite_walker.d) + */ + +module ddmd.statement_rewrite_walker; + +import core.stdc.stdio; + +import ddmd.statement; +import ddmd.visitor; + + +/** A visitor to walk entire statements and provides ability to replace any sub-statements. + */ +extern (C++) class StatementRewriteWalker : Visitor +{ + alias visit = super.visit; + + /* Point the currently visited statement. + * By using replaceCurrent() method, you can replace AST during walking. + */ + Statement* ps; + +public: + final void visitStmt(ref Statement s) + { + ps = &s; + s.accept(this); + } + + final void replaceCurrent(Statement s) + { + *ps = s; + } + + override void visit(ErrorStatement s) + { + } + + override void visit(PeelStatement s) + { + if (s.s) + visitStmt(s.s); + } + + override void visit(ExpStatement s) + { + } + + override void visit(DtorExpStatement s) + { + } + + override void visit(CompileStatement s) + { + } + + override void visit(CompoundStatement s) + { + if (s.statements && s.statements.dim) + { + for (size_t i = 0; i < s.statements.dim; i++) + { + if ((*s.statements)[i]) + visitStmt((*s.statements)[i]); + } + } + } + + override void visit(CompoundDeclarationStatement s) + { + visit(cast(CompoundStatement)s); + } + + override void visit(UnrolledLoopStatement s) + { + if (s.statements && s.statements.dim) + { + for (size_t i = 0; i < s.statements.dim; i++) + { + if ((*s.statements)[i]) + visitStmt((*s.statements)[i]); + } + } + } + + override void visit(ScopeStatement s) + { + if (s.statement) + visitStmt(s.statement); + } + + override void visit(WhileStatement s) + { + if (s._body) + visitStmt(s._body); + } + + override void visit(DoStatement s) + { + if (s._body) + visitStmt(s._body); + } + + override void visit(ForStatement s) + { + if (s._init) + visitStmt(s._init); + if (s._body) + visitStmt(s._body); + } + + override void visit(ForeachStatement s) + { + if (s._body) + visitStmt(s._body); + } + + override void visit(ForeachRangeStatement s) + { + if (s._body) + visitStmt(s._body); + } + + override void visit(IfStatement s) + { + if (s.ifbody) + visitStmt(s.ifbody); + if (s.elsebody) + visitStmt(s.elsebody); + } + + override void visit(ConditionalStatement s) + { + } + + override void visit(PragmaStatement s) + { + } + + override void visit(StaticAssertStatement s) + { + } + + override void visit(SwitchStatement s) + { + if (s._body) + visitStmt(s._body); + } + + override void visit(CaseStatement s) + { + if (s.statement) + visitStmt(s.statement); + } + + override void visit(CaseRangeStatement s) + { + if (s.statement) + visitStmt(s.statement); + } + + override void visit(DefaultStatement s) + { + if (s.statement) + visitStmt(s.statement); + } + + override void visit(GotoDefaultStatement s) + { + } + + override void visit(GotoCaseStatement s) + { + } + + override void visit(SwitchErrorStatement s) + { + } + + override void visit(ReturnStatement s) + { + } + + override void visit(BreakStatement s) + { + } + + override void visit(ContinueStatement s) + { + } + + override void visit(SynchronizedStatement s) + { + if (s._body) + visitStmt(s._body); + } + + override void visit(WithStatement s) + { + if (s._body) + visitStmt(s._body); + } + + override void visit(TryCatchStatement s) + { + if (s._body) + visitStmt(s._body); + if (s.catches && s.catches.dim) + { + for (size_t i = 0; i < s.catches.dim; i++) + { + Catch c = (*s.catches)[i]; + if (c && c.handler) + visitStmt(c.handler); + } + } + } + + override void visit(TryFinallyStatement s) + { + if (s._body) + visitStmt(s._body); + if (s.finalbody) + visitStmt(s.finalbody); + } + + override void visit(OnScopeStatement s) + { + } + + override void visit(ThrowStatement s) + { + } + + override void visit(DebugStatement s) + { + if (s.statement) + visitStmt(s.statement); + } + + override void visit(GotoStatement s) + { + } + + override void visit(LabelStatement s) + { + if (s.statement) + visitStmt(s.statement); + } + + override void visit(AsmStatement s) + { + } + + override void visit(ImportStatement s) + { + } +} diff --git a/ddmd/statementsem.d b/ddmd/statementsem.d index a68552fa80f..8962755501b 100644 --- a/ddmd/statementsem.d +++ b/ddmd/statementsem.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _statementsem.d) @@ -781,7 +781,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor if (dim < 1 || dim > 2) { fs.error("only one or two arguments for array foreach"); - goto Lerror2; + goto case Terror; } /* Look for special case of parsing char types out of char type @@ -801,7 +801,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor if (p.storageClass & STCref) { fs.error("foreach: value of UTF conversion cannot be ref"); - goto Lerror2; + goto case Terror; } if (dim == 2) { @@ -809,7 +809,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor if (p.storageClass & STCref) { fs.error("foreach: key cannot be ref"); - goto Lerror2; + goto case Terror; } } goto Lapply; @@ -838,7 +838,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor { fs.error("key type mismatch, %s to ref %s", var.type.toChars(), p.type.toChars()); - goto Lerror2; + goto case Terror; } } if (tab.ty == Tsarray) @@ -849,7 +849,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor { fs.error("index type '%s' cannot cover index range 0..%llu", p.type.toChars(), ta.dim.toInteger()); - goto Lerror2; + goto case Terror; } fs.key.range = new IntRange(SignExtendedNumber(0), dimrange.imax); } @@ -873,7 +873,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor { fs.error("argument type mismatch, %s to ref %s", t.toChars(), p.type.toChars()); - goto Lerror2; + goto case Terror; } } } @@ -902,7 +902,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor // converting array literal elements to telem might make it @nogc. fs.aggr = fs.aggr.implicitCastTo(sc, telem.sarrayOf(edim)); if (fs.aggr.op == TOKerror) - goto Lerror2; + goto case Terror; // for (T[edim] tmp = a, ...) tmp = new VarDeclaration(loc, fs.aggr.type, id, ie); @@ -1000,7 +1000,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor if (dim < 1 || dim > 2) { fs.error("only one or two arguments for associative array foreach"); - goto Lerror2; + goto case Terror; } goto Lapply; @@ -1109,7 +1109,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor if (tfront.ty == Tvoid) { fs.error("%s.front is void and has no value", oaggr.toChars()); - goto Lerror2; + goto case Terror; } // Resolve inout qualifier of front type @@ -1132,7 +1132,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor const(char)* plural = exps.dim > 1 ? "s" : ""; fs.error("cannot infer argument types, expected %d argument%s, not %d", exps.dim, plural, dim); - goto Lerror2; + goto case Terror; } foreach (i; 0 .. dim) @@ -1175,7 +1175,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor Lrangeerr: fs.error("cannot infer argument types"); - goto Lerror2; + goto case Terror; } case Tdelegate: if (fs.op == TOKforeach_reverse) @@ -1246,7 +1246,7 @@ version(IN_LLVM) if (!stc) { fs.error("foreach: cannot make %s ref", p.ident.toChars()); - goto Lerror2; + goto case Terror; } goto LcopyArg; } @@ -1330,7 +1330,7 @@ else e = new DeclarationExp(loc, vinit); e = e.semantic(sc2); if (e.op == TOKerror) - goto Lerror2; + goto case Terror; } if (taa) @@ -1346,7 +1346,7 @@ else { fs.error("foreach: index must be type %s, not %s", ti.toChars(), ta.toChars()); - goto Lerror2; + goto case Terror; } p = (*fs.parameters)[1]; isRef = (p.storageClass & STCref) != 0; @@ -1357,7 +1357,7 @@ else { fs.error("foreach: value must be type %s, not %s", taav.toChars(), ta.toChars()); - goto Lerror2; + goto case Terror; } /* Call: @@ -1390,7 +1390,7 @@ else exps.push(fs.aggr); auto keysize = taa.index.size(); if (keysize == SIZE_INVALID) - goto Lerror2; + goto case Terror; assert(keysize < keysize.max - Target.ptrsize); keysize = (keysize + (Target.ptrsize - 1)) & ~(Target.ptrsize - 1); // paint delegate argument to the type runtime expects @@ -1478,11 +1478,11 @@ else ec = new CallExp(loc, fs.aggr, flde); ec = ec.semantic(sc2); if (ec.op == TOKerror) - goto Lerror2; + goto case Terror; if (ec.type != Type.tint32) { fs.error("opApply() function for %s must return an int", tab.toChars()); - goto Lerror2; + goto case Terror; } } else @@ -1514,11 +1514,11 @@ else ec = new CallExp(loc, ec, flde); ec = ec.semantic(sc2); if (ec.op == TOKerror) - goto Lerror2; + goto case Terror; if (ec.type != Type.tint32) { fs.error("opApply() function for %s must return an int", tab.toChars()); - goto Lerror2; + goto case Terror; } } e = Expression.combine(e, ec); @@ -1554,13 +1554,12 @@ else break; } case Terror: - Lerror2: s = new ErrorStatement(); break; default: fs.error("foreach: %s is not an aggregate type", fs.aggr.type.toChars()); - goto Lerror2; + goto case Terror; } sc2.noctor--; sc2.pop(); @@ -1577,7 +1576,6 @@ else if (!fs.lwr.type) { fs.error("invalid range lower bound %s", fs.lwr.toChars()); - Lerror: return setError(); } @@ -1587,7 +1585,7 @@ else if (!fs.upr.type) { fs.error("invalid range upper bound %s", fs.upr.toChars()); - goto Lerror; + return setError(); } if (fs.prm.type) @@ -1741,7 +1739,7 @@ else if (fs.key.type.constConv(fs.prm.type) <= MATCHnomatch) { fs.error("prmument type mismatch, %s to ref %s", fs.key.type.toChars(), fs.prm.type.toChars()); - goto Lerror; + return setError(); } } @@ -1885,7 +1883,7 @@ else if (e.op == TOKerror) { errorSupplemental(ps.loc, "while evaluating pragma(msg, %s)", arg.toChars()); - goto Lerror; + return setError(); } StringExp se = e.toStringExp(); if (se) @@ -1906,20 +1904,20 @@ else /* Should this be allowed? */ ps.error("pragma(lib) not allowed as statement"); - goto Lerror; + return setError(); } else { if (!ps.args || ps.args.dim != 1) { ps.error("string expected for library name"); - goto Lerror; + return setError(); } else { auto se = semanticString(sc, (*ps.args)[0], "library name"); if (!se) - goto Lerror; + return setError(); if (global.params.verbose) { @@ -1945,7 +1943,7 @@ else if (!ps.args || ps.args.dim != 1 || !DtoCheckProfileInstrPragma((*ps.args)[0], emitInstr)) { ps.error("pragma(LDC_profile_instr, true or false) expected"); - goto Lerror; + return setError(); } else { @@ -1953,7 +1951,7 @@ else if (fd is null) { ps.error("pragma(LDC_profile_instr, ...) is not inside a function"); - goto Lerror; + return setError(); } fd.emitInstrumentation = emitInstr; } @@ -1976,7 +1974,7 @@ else if (!sa || !sa.isFuncDeclaration()) { ps.error("function name expected for start address, not '%s'", e.toChars()); - goto Lerror; + return setError(); } if (ps._body) { @@ -1999,7 +1997,7 @@ else else if (!ps.args || ps.args.dim != 1) { ps.error("boolean expression expected for pragma(inline)"); - goto Lerror; + return setError(); } else { @@ -2007,7 +2005,7 @@ else if (e.op != TOKint64 || !e.type.equals(Type.tbool)) { ps.error("pragma(inline, true or false) expected, not %s", e.toChars()); - goto Lerror; + return setError(); } if (e.isBool(true)) @@ -2019,7 +2017,7 @@ else if (!fd) { ps.error("pragma(inline) is not inside a function"); - goto Lerror; + return setError(); } fd.inlining = inlining; } @@ -2027,7 +2025,7 @@ else else { ps.error("unrecognized pragma(%s)", ps.ident.toChars()); - goto Lerror; + return setError(); } if (ps._body) @@ -2035,10 +2033,6 @@ else ps._body = ps._body.semantic(sc); } result = ps._body; - return; - - Lerror: - return setError(); } override void visit(StaticAssertStatement s) @@ -2122,15 +2116,20 @@ else sc.noctor--; if (conditionError || ss._body.isErrorStatement()) - goto Lerror; + { + sc.pop(); + return setError(); + } // Resolve any goto case's with exp + Lgotocase: foreach (gcs; ss.gotoCases) { if (!gcs.exp) { gcs.error("no case statement following goto case;"); - goto Lerror; + sc.pop(); + return setError(); } for (Scope* scx = sc; scx; scx = scx.enclosing) @@ -2146,14 +2145,13 @@ version(IN_LLVM) { cs.gototarget = true; } - goto Lfoundcase; + continue Lgotocase; } } } gcs.error("case %s not found", gcs.exp.toChars()); - goto Lerror; - - Lfoundcase: + sc.pop(); + return setError(); } if (ss.isFinal) @@ -2167,6 +2165,7 @@ version(IN_LLVM) ed = ds.isEnumDeclaration(); if (ed) { + Lmembers: foreach (es; *ed.members) { EnumMember em = es.isEnumMember(); @@ -2175,12 +2174,12 @@ version(IN_LLVM) foreach (cs; *ss.cases) { if (cs.exp.equals(em.value) || (!cs.exp.type.isString() && !em.value.type.isString() && cs.exp.toInteger() == em.value.toInteger())) - goto L1; + continue Lmembers; } ss.error("enum member %s not represented in final switch", em.toChars()); - goto Lerror; + sc.pop(); + return setError(); } - L1: } } else @@ -2215,7 +2214,10 @@ version(IN_LLVM) } if (ss.checkLabel()) - goto Lerror; + { + sc.pop(); + return setError(); + } version(IN_LLVM) { @@ -2231,11 +2233,6 @@ version(IN_LLVM) sc.pop(); result = ss; - return; - - Lerror: - sc.pop(); - result = new ErrorStatement(); } override void visit(CaseStatement cs) @@ -2254,11 +2251,17 @@ version(IN_LLVM) cs.exp = cs.exp.implicitCastTo(sc, sw.condition.type); cs.exp = cs.exp.optimize(WANTvalue | WANTexpand); + Expression e = cs.exp; + // Remove all the casts the user and/or implicitCastTo may introduce + // otherwise we'd sometimes fail the check below. + while (e.op == TOKcast) + e = (cast(CastExp)e).e1; + /* This is where variables are allowed as case expressions. */ - if (cs.exp.op == TOKvar) + if (e.op == TOKvar) { - VarExp ve = cast(VarExp)cs.exp; + VarExp ve = cast(VarExp)e; VarDeclaration v = ve.var.isVarDeclaration(); Type t = cs.exp.type.toBasetype(); if (v && (t.isintegral() || t.ty == Tclass)) @@ -3013,7 +3016,11 @@ version(IN_LLVM) ss.exp = ss.exp.optimize(WANTvalue); ss.exp = checkGC(sc, ss.exp); if (ss.exp.op == TOKerror) - goto Lbody; + { + if (ss._body) + ss._body = ss._body.semantic(sc); + return setError(); + } ClassDeclaration cd = ss.exp.type.isClassHandle(); if (!cd) @@ -3068,15 +3075,14 @@ version(IN_LLVM) s = new CompoundStatement(ss.loc, cs); result = s.semantic(sc); - return; } } else { /* Generate our own critical section, then rewrite as: - * __gshared byte[CriticalSection.sizeof] critsec; - * _d_criticalenter(critsec.ptr); - * try { body } finally { _d_criticalexit(critsec.ptr); } + * __gshared align(D_CRITICAL_SECTION.alignof) byte[D_CRITICAL_SECTION.sizeof] __critsec; + * _d_criticalenter(__critsec.ptr); + * try { body } finally { _d_criticalexit(__critsec.ptr); } */ auto id = Identifier.generateId("__critsec"); auto t = Type.tint8.sarrayOf(Target.ptrsize + Target.critsecsize()); @@ -3114,21 +3120,10 @@ version(IN_LLVM) s = new CompoundStatement(ss.loc, cs); result = s.semantic(sc); - version(IN_LLVM) // backport alignment fix for issue #1955 - { - tmp.alignment = Target.ptrsize; // must be set after semantic() - } - return; - } - Lbody: - if (ss._body) - ss._body = ss._body.semantic(sc); - if (ss._body && ss._body.isErrorStatement()) - { - result = ss._body; - return; + + // set the explicit __critsec alignment after semantic() + tmp.alignment = Target.ptrsize; } - result = ss; } override void visit(WithStatement ws) diff --git a/ddmd/staticassert.d b/ddmd/staticassert.d index 03a24cee014..7eb6f8a124a 100644 --- a/ddmd/staticassert.d +++ b/ddmd/staticassert.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _staticassert.d) diff --git a/ddmd/target.d b/ddmd/target.d index 3e994c79f53..c1d9a7364f5 100644 --- a/ddmd/target.d +++ b/ddmd/target.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _target.d) @@ -35,6 +35,7 @@ struct Target static __gshared int c_longsize; // size of a C 'long' or 'unsigned long' type static __gshared int c_long_doublesize; // size of a C 'long double' static __gshared int classinfosize; // size of 'ClassInfo' + extern (C++) static __gshared ulong maxStaticDataSize; // maximum size of static data extern(D) static struct FPTypeProperties(T) { @@ -119,6 +120,7 @@ struct Target extern (C++) static __gshared int c_longsize; // size of a C 'long' or 'unsigned long' type extern (C++) static __gshared int c_long_doublesize; // size of a C 'long double' extern (C++) static __gshared int classinfosize; // size of 'ClassInfo' + extern (C++) static __gshared ulong maxStaticDataSize; // maximum size of static data template FPTypeProperties(T) { @@ -153,6 +155,15 @@ struct Target // adjusted for 64 bit code. ptrsize = 4; classinfosize = 0x4C; // 76 + + /* gcc uses int.max for 32 bit compilations, and long.max for 64 bit ones. + * Set to int.max for both, because the rest of the compiler cannot handle + * 2^64-1 without some pervasive rework. The trouble is that much of the + * front and back end uses 32 bit ints for sizes and offsets. Since C++ + * silently truncates 64 bit ints to 32, finding all these dependencies will be a problem. + */ + maxStaticDataSize = int.max; + if (global.params.isLP64) { ptrsize = 8; @@ -179,6 +190,13 @@ struct Target realalignsize = 2; reverseCppOverloads = true; c_longsize = 4; + if (ptrsize == 4) + { + /* Optlink cannot deal with individual data chunks + * larger than 16Mb + */ + maxStaticDataSize = 0x100_0000; // 16Mb + } } else assert(0); diff --git a/ddmd/target.h b/ddmd/target.h index 0b8ff5c4a0b..56c6cb1b2ed 100644 --- a/ddmd/target.h +++ b/ddmd/target.h @@ -34,6 +34,7 @@ struct Target static int c_longsize; // size of a C 'long' or 'unsigned long' type static int c_long_doublesize; // size of a C 'long double' static int classinfosize; // size of 'ClassInfo' + static unsigned long long maxStaticDataSize; // maximum size of static data #ifdef IN_LLVM struct RealProperties diff --git a/ddmd/template.h b/ddmd/template.h index eb10fe25173..db26fd55d3e 100644 --- a/ddmd/template.h +++ b/ddmd/template.h @@ -47,7 +47,7 @@ class Tuple : public RootObject Objects objects; // kludge for template.isType() - int dyncast() { return DYNCAST_TUPLE; } + int dyncast() const { return DYNCAST_TUPLE; } const char *toChars() { return objects.toChars(); } }; diff --git a/ddmd/tokens.d b/ddmd/tokens.d index c581ec99ac3..8b08417b9c7 100644 --- a/ddmd/tokens.d +++ b/ddmd/tokens.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _tokens.d) diff --git a/ddmd/traits.d b/ddmd/traits.d index 6d2196c4c8a..51a2048e106 100644 --- a/ddmd/traits.d +++ b/ddmd/traits.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _traits.d) @@ -116,48 +116,29 @@ static this() /** * get an array of size_t values that indicate possible pointer words in memory * if interpreted as the type given as argument - * the first array element is the size of the type for independent interpretation - * of the array - * following elements bits represent one word (4/8 bytes depending on the target - * architecture). If set the corresponding memory might contain a pointer/reference. - * - * [T.sizeof, pointerbit0-31/63, pointerbit32/64-63/128, ...] + * Returns: the size of the type in bytes, d_uns64.max on error */ -extern (C++) Expression pointerBitmap(TraitsExp e) +extern (C++) d_uns64 getTypePointerBitmap(Loc loc, Type t, Array!(d_uns64)* data) { - if (!e.args || e.args.dim != 1) - { - error(e.loc, "a single type expected for trait pointerBitmap"); - return new ErrorExp(); - } - - Type t = getType((*e.args)[0]); - if (!t) - { - error(e.loc, "%s is not a type", (*e.args)[0].toChars()); - return new ErrorExp(); - } - d_uns64 sz; if (t.ty == Tclass && !(cast(TypeClass)t).sym.isInterfaceDeclaration()) - sz = (cast(TypeClass)t).sym.AggregateDeclaration.size(e.loc); + sz = (cast(TypeClass)t).sym.AggregateDeclaration.size(loc); else - sz = t.size(e.loc); + sz = t.size(loc); if (sz == SIZE_INVALID) - return new ErrorExp(); + return d_uns64.max; - const sz_size_t = Type.tsize_t.size(e.loc); + const sz_size_t = Type.tsize_t.size(loc); if (sz > sz.max - sz_size_t) { - error(e.loc, "size overflow for type %s", t.toChars()); - return new ErrorExp(); + error(loc, "size overflow for type %s", t.toChars()); + return d_uns64.max; } d_uns64 bitsPerWord = sz_size_t * 8; d_uns64 cntptr = (sz + sz_size_t - 1) / sz_size_t; d_uns64 cntdata = (cntptr + bitsPerWord - 1) / bitsPerWord; - Array!(d_uns64) data; data.setDim(cast(size_t)cntdata); data.zero(); @@ -342,21 +323,51 @@ extern (C++) Expression pointerBitmap(TraitsExp e) bool error; } - scope PointerBitmapVisitor pbv = new PointerBitmapVisitor(&data, sz_size_t); + scope PointerBitmapVisitor pbv = new PointerBitmapVisitor(data, sz_size_t); if (t.ty == Tclass) pbv.visitClass(cast(TypeClass)t); else t.accept(pbv); - if (pbv.error) + return pbv.error ? d_uns64.max : sz; +} + +/** + * get an array of size_t values that indicate possible pointer words in memory + * if interpreted as the type given as argument + * the first array element is the size of the type for independent interpretation + * of the array + * following elements bits represent one word (4/8 bytes depending on the target + * architecture). If set the corresponding memory might contain a pointer/reference. + * + * Returns: [T.sizeof, pointerbit0-31/63, pointerbit32/64-63/128, ...] + */ +extern (C++) Expression pointerBitmap(TraitsExp e) +{ + if (!e.args || e.args.dim != 1) + { + error(e.loc, "a single type expected for trait pointerBitmap"); + return new ErrorExp(); + } + + Type t = getType((*e.args)[0]); + if (!t) + { + error(e.loc, "%s is not a type", (*e.args)[0].toChars()); + return new ErrorExp(); + } + + Array!(d_uns64) data; + d_uns64 sz = getTypePointerBitmap(e.loc, t, &data); + if (sz == d_uns64.max) return new ErrorExp(); auto exps = new Expressions(); exps.push(new IntegerExp(e.loc, sz, Type.tsize_t)); - foreach (d_uns64 i; 0 .. cntdata) + foreach (d_uns64 i; 0 .. data.dim) exps.push(new IntegerExp(e.loc, data[cast(size_t)i], Type.tsize_t)); auto ale = new ArrayLiteralExp(e.loc, exps); - ale.type = Type.tsize_t.sarrayOf(cntdata + 1); + ale.type = Type.tsize_t.sarrayOf(data.dim + 1); return ale; } @@ -955,6 +966,8 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc) } if (sm.isTypeInfoDeclaration()) // Bugzilla 15177 return 0; + if (!sds.isModule() && sm.isImport()) // Bugzilla 17057 + return 0; //printf("\t%s\n", sm.ident.toChars()); @@ -1064,6 +1077,11 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc) err = true; } + // Carefully detach the scope from the parent and throw it away as + // we only need it to evaluate the expression + // https://issues.dlang.org/show_bug.cgi?id=15428 + sc2.freeFieldinit(); + sc2.enclosing = null; sc2.pop(); if (global.endGagging(errors) || err) diff --git a/ddmd/typinf.d b/ddmd/typinf.d index 2889bf5d779..c80d61506c1 100644 --- a/ddmd/typinf.d +++ b/ddmd/typinf.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _typeinf.d) diff --git a/ddmd/utf.d b/ddmd/utf.d index 8c2a7dd79ac..e7a7748b328 100644 --- a/ddmd/utf.d +++ b/ddmd/utf.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _utf.d) diff --git a/ddmd/utils.d b/ddmd/utils.d index 1f39450ceef..13d8f6fc8a1 100644 --- a/ddmd/utils.d +++ b/ddmd/utils.d @@ -5,7 +5,7 @@ * * This modules defines some utility functions for DMD. * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _utils.d) diff --git a/ddmd/visitor.d b/ddmd/visitor.d index 8180d080e1a..11c206dba93 100644 --- a/ddmd/visitor.d +++ b/ddmd/visitor.d @@ -2,7 +2,7 @@ * Compiler implementation of the * $(LINK2 http://www.dlang.org, D programming language). * - * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved + * Copyright: Copyright (c) 1999-2017 by Digital Mars, 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: $(DMDSRC _visitor.d) diff --git a/gen/pragma.cpp b/gen/pragma.cpp index a4822bc37c8..2d36a6c2d10 100644 --- a/gen/pragma.cpp +++ b/gen/pragma.cpp @@ -135,7 +135,7 @@ LDCPragma DtoGetPragma(Scope *sc, PragmaDeclaration *decl, error(Loc(), "takes no parameters"); fatal(); } - sc->module->noModuleInfo = true; + sc->_module->noModuleInfo = true; return LLVMignore; } @@ -235,7 +235,7 @@ LDCPragma DtoGetPragma(Scope *sc, PragmaDeclaration *decl, error(Loc(), "takes no parameters"); fatal(); } - sc->module->llvmForceLogging = true; + sc->_module->llvmForceLogging = true; return LLVMignore; } diff --git a/gen/target.cpp b/gen/target.cpp index 04bdcee69c0..d15edac8c4e 100644 --- a/gen/target.cpp +++ b/gen/target.cpp @@ -55,6 +55,7 @@ void Target::_init() { c_longsize = global.params.is64bit ? 8 : 4; c_long_doublesize = realsize; classinfosize = 0; // unused + maxStaticDataSize = std::numeric_limits::max(); const auto targetRealSemantics = &real->getFltSemantics(); #if LDC_LLVM_VER >= 400 diff --git a/runtime/druntime b/runtime/druntime index 8414f932691..ce9fa494819 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 8414f932691e01dc6c174b88f67ffd6e21ba7fcc +Subproject commit ce9fa4948190267f0a33f51848efd1969e16990b diff --git a/runtime/phobos b/runtime/phobos index c7f10c011fd..a81ed742140 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit c7f10c011fd9065a019102733bcc57346f03f79e +Subproject commit a81ed742140de51c15840612aa9872802c5bb9ee diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 97f43e2507f..232889a4ce8 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 97f43e2507f4e8d2537485f899a8c0cb19b972ca +Subproject commit 232889a4ce828f89976f66d71cea1b31e96f8500 From 83c9d66499a165effcdaafacff0ab73dd7aeae6a Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 22 Apr 2017 03:55:34 +0200 Subject: [PATCH 02/19] druntime: Remove obsolete OSX code in rt.sections_ldc --- runtime/druntime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime b/runtime/druntime index ce9fa494819..6ba85cca7c9 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit ce9fa4948190267f0a33f51848efd1969e16990b +Subproject commit 6ba85cca7c99c8afa11459ee70956273940f68d9 From 0a11aa87162a57135d527313b7eba9d22d2d4751 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 22 Apr 2017 04:21:08 +0200 Subject: [PATCH 03/19] druntime: Fix rt.sections_elf_shared regression --- runtime/druntime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime b/runtime/druntime index 6ba85cca7c9..7c5a7d4db08 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 6ba85cca7c99c8afa11459ee70956273940f68d9 +Subproject commit 7c5a7d4db080551a9a9aae145c1b13d6b875e940 From 708486d8d9f3bb02386a96398ae7878c0e372bf7 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 22 Apr 2017 16:24:43 +0200 Subject: [PATCH 04/19] druntime: Fix __cmp(void[], void[]) --- runtime/druntime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime b/runtime/druntime index 7c5a7d4db08..b3f47a44621 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 7c5a7d4db080551a9a9aae145c1b13d6b875e940 +Subproject commit b3f47a44621ba8acd4b3b9cc972b78c8d2b0c576 From 1e1127567720eb058f1321fdf098e1f912f7f100 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 22 Apr 2017 21:09:44 +0200 Subject: [PATCH 05/19] dmd-testsuite: Fix compile error for runnable/ldc_enum --- tests/d2/dmd-testsuite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 232889a4ce8..2d07fc62355 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 232889a4ce828f89976f66d71cea1b31e96f8500 +Subproject commit 2d07fc62355094c05edac6177cf6aec1b07522cf From 15e565e4f41f3d4e184dcb3f77c95f1174f7347c Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 22 Apr 2017 21:53:35 +0200 Subject: [PATCH 06/19] Support cast runtime variables as case expressions Fixes compilable/b17111.d, see dlang/dmd@84fcc60. --- gen/statements.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/gen/statements.cpp b/gen/statements.cpp index e203f5bfa67..c8c6af4bf1d 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -899,15 +899,20 @@ class ToIRVisitor : public Visitor { stringTableSlice = DtoConstSlice(arrLen, arrPtr); } else { for (auto cs : *cases) { - if (cs->exp->op == TOKvar) { - const auto vd = - static_cast(cs->exp)->var->isVarDeclaration(); + // skip over casts + auto ce = cs->exp; + while (ce->op == TOKcast) + ce = static_cast(ce)->e1; + + if (ce->op == TOKvar) { + const auto vd = static_cast(ce)->var->isVarDeclaration(); if (vd && (!vd->_init || !vd->isConst())) { indices.push_back(DtoRVal(toElemDtor(cs->exp))); useSwitchInst = false; continue; } } + indices.push_back(toConstElem(cs->exp, irs)); } } From fe3d36ada827506ac36cdd967248d8aa8d7f9bd6 Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 23 Apr 2017 04:26:19 +0200 Subject: [PATCH 07/19] druntime: Fix rt.arrayint (RAX instead of EAX for 64-bit inline asm) --- runtime/druntime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime b/runtime/druntime index b3f47a44621..8117337b6a9 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit b3f47a44621ba8acd4b3b9cc972b78c8d2b0c576 +Subproject commit 8117337b6a962cabd6cacc7f38e5b291fd62c7f6 From a5fe1ab8691fdaafe4080b81808a4f1340583e9c Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 23 Apr 2017 04:50:14 +0200 Subject: [PATCH 08/19] Phobos: Fix missing alignment for kernighan_ritchie allocator unittests --- runtime/phobos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/phobos b/runtime/phobos index a81ed742140..5c2c2720e1d 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit a81ed742140de51c15840612aa9872802c5bb9ee +Subproject commit 5c2c2720e1d397e83e70c83ea11c5a894698b044 From bcec3d2874e25da92deac446226dbeff3a4b033c Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 23 Apr 2017 18:29:35 +0200 Subject: [PATCH 09/19] dmd-testsuite: Disable Windows-specific runnable/testptrref --- tests/d2/dmd-testsuite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 2d07fc62355..77165be7703 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 2d07fc62355094c05edac6177cf6aec1b07522cf +Subproject commit 77165be7703903acea89ad9ee9d735c2f1d91976 From a966f22ce6dc36723bafcf2fa6129863f44b6ae2 Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 23 Apr 2017 19:15:51 +0200 Subject: [PATCH 10/19] druntime: Make LDC-specific fiber migration check @nogc Required for OSX, where version `CheckFiberMigration` is set. --- runtime/druntime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime b/runtime/druntime index 8117337b6a9..2b69a6dee83 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 8117337b6a962cabd6cacc7f38e5b291fd62c7f6 +Subproject commit 2b69a6dee8309385a23e857e5103bec458bef2b3 From 0637caad6dd955b5543492a08b6d42ed255c28ac Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 24 Apr 2017 00:03:02 +0200 Subject: [PATCH 11/19] Phobos: Relax a few unittests for double-precision reals --- runtime/phobos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/phobos b/runtime/phobos index 5c2c2720e1d..afac25a4b36 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit 5c2c2720e1d397e83e70c83ea11c5a894698b044 +Subproject commit afac25a4b36bcd2040f3ef1ca305f5bd8ff94042 From 60285b7b7d7ba1be1136ba3801e1f570b80fc4d0 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 12 May 2017 18:00:36 +0200 Subject: [PATCH 12/19] Phobos: Apply upstream SSE control register fixes --- runtime/phobos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/phobos b/runtime/phobos index ae28889dbf2..2220a3a9590 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit ae28889dbf2338032795396355824686ab7a5a1c +Subproject commit 2220a3a959090333005306134e20dd5e576fdb2a From 0ae2a953e6a43f8054b38a1cb3b09d3519091f00 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 12 May 2017 19:28:26 +0200 Subject: [PATCH 13/19] Phobos: Tiny std.math inline assembly constraints fixes --- runtime/phobos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/phobos b/runtime/phobos index 2220a3a9590..d2ce07e2a50 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit 2220a3a959090333005306134e20dd5e576fdb2a +Subproject commit d2ce07e2a5010d89c86284ae41a39124744c5f8d From 51f1b13d41c5feef55bb1de9fc2e65066ce5a1e7 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 12 May 2017 19:43:25 +0200 Subject: [PATCH 14/19] druntime: Mark dladdr() as @nogc for OSX --- runtime/druntime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime b/runtime/druntime index 329e3d256fd..1fd655dc81a 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 329e3d256fdb0d0f284e6208a78f95493e532739 +Subproject commit 1fd655dc81a5fc3052d11227b5be1992ed25dab8 From 6a44d574dc775f97074fa408eb3d41b9d67bd70e Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 14 May 2017 20:22:30 +0200 Subject: [PATCH 15/19] Support DMD's new undocumented -vcg-ast switch --- driver/cl_options.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/driver/cl_options.cpp b/driver/cl_options.cpp index 9cac488403f..495a6a67c73 100644 --- a/driver/cl_options.cpp +++ b/driver/cl_options.cpp @@ -102,6 +102,10 @@ static cl::opt verbose_cg("v-cg", cl::desc("Verbose codegen"), cl::ZeroOrMore, cl::location(global.params.verbose_cg)); +static cl::opt verbose_cg_ast("vcg-ast", cl::ZeroOrMore, cl::Hidden, + cl::desc("Write AST to .cg file"), + cl::location(global.params.vcg_ast)); + static cl::opt errorLimit( "verrors", cl::ZeroOrMore, cl::desc("Limit the number of error messages (0 means unlimited)"), From a3025b05e3d6a7b9e67055511c211b1981d4782b Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 15 May 2017 23:51:14 +0200 Subject: [PATCH 16/19] druntime: Adapt core.memory to LLVM optimizer cleverness --- runtime/druntime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime b/runtime/druntime index 1fd655dc81a..16d80d5b0a9 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 1fd655dc81a5fc3052d11227b5be1992ed25dab8 +Subproject commit 16d80d5b0a98d5d7d0bd24bc0fcf4a5932c228d7 From ff33356ebeeecea12cae0bc9ce14fa815441ef48 Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 16 May 2017 00:16:58 +0200 Subject: [PATCH 17/19] Phobos: Disable some new std.math tests affected by issue #888 --- runtime/phobos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/phobos b/runtime/phobos index d2ce07e2a50..e0ab515af91 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit d2ce07e2a5010d89c86284ae41a39124744c5f8d +Subproject commit e0ab515af914800e8e2180efa7741ea4547aac49 From 090031cd434d931e00d5e9a152746aebf02255f8 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 10 Jun 2017 02:53:07 +0200 Subject: [PATCH 18/19] Upgrade front-end + libs to v2.074.1 --- CMakeLists.txt | 2 +- ddmd/ctfeexpr.d | 4 +- ddmd/declaration.d | 3 +- ddmd/dinifile.d | 18 +++--- ddmd/dsymbol.h | 6 +- ddmd/errors.h | 43 ++++++------ ddmd/escape.d | 10 ++- ddmd/expression.d | 10 --- ddmd/expression.h | 11 +++- ddmd/module.h | 2 +- ddmd/readme.txt | 5 +- ddmd/root/array.h | 4 +- ddmd/root/ctfloat.h | 2 +- ddmd/target.d | 144 +++++++++++------------------------------ ddmd/target.h | 41 ++++++------ gen/target.cpp | 40 ++++-------- runtime/druntime | 2 +- runtime/phobos | 2 +- tests/d2/dmd-testsuite | 2 +- 19 files changed, 135 insertions(+), 216 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fd7c2e4465c..fc60153cfcf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,7 @@ set(LDC_VERSION "1.4.0") # May be overridden by git hash tag set(DMDFE_MAJOR_VERSION 2) set(DMDFE_MINOR_VERSION 0) set(DMDFE_PATCH_VERSION 74) -set(DMDFE_FIX_LEVEL 0) # Comment out if not used +set(DMDFE_FIX_LEVEL 1) # Comment out if not used set(DMD_VERSION ${DMDFE_MAJOR_VERSION}.${DMDFE_MINOR_VERSION}${DMDFE_PATCH_VERSION}) if(DEFINED DMDFE_FIX_LEVEL) diff --git a/ddmd/ctfeexpr.d b/ddmd/ctfeexpr.d index 17e643cf14a..8f7d6d4dcc7 100644 --- a/ddmd/ctfeexpr.d +++ b/ddmd/ctfeexpr.d @@ -1335,7 +1335,7 @@ extern (C++) int ctfeRawCmp(Loc loc, Expression e1, Expression e2) mem.xfree(used); return 0; } - error(loc, "CTFE internal error: bad compare"); + error(loc, "CTFE internal error: bad compare of `%s` and `%s`", e1.toChars(), e2.toChars()); assert(0); } @@ -1802,7 +1802,7 @@ extern (C++) bool isCtfeValueValid(Expression newval) } if (newval.op == TOKnull) { - return tb.ty == Tnull || tb.ty == Tpointer || tb.ty == Tarray || tb.ty == Taarray || tb.ty == Tclass; + return tb.ty == Tnull || tb.ty == Tpointer || tb.ty == Tarray || tb.ty == Taarray || tb.ty == Tclass || tb.ty == Tdelegate; } if (newval.op == TOKstring) return true; // CTFE would directly use the StringExp in AST. diff --git a/ddmd/declaration.d b/ddmd/declaration.d index 8651e846454..43c23065847 100644 --- a/ddmd/declaration.d +++ b/ddmd/declaration.d @@ -1131,7 +1131,7 @@ extern (C++) class VarDeclaration : Declaration if (needctfe) sc = sc.startCTFE(); - //printf("inferring type for %s with init %s\n", toChars(), init.toChars()); + //printf("inferring type for %s with init %s\n", toChars(), _init.toChars()); _init = _init.inferType(sc); type = _init.toExpression().type; if (needctfe) @@ -2467,6 +2467,7 @@ extern (C++) class TypeInfoDeclaration : VarDeclaration storage_class = STCstatic | STCgshared; protection = Prot(PROTpublic); linkage = LINKc; + alignment = Target.ptrsize; } static TypeInfoDeclaration create(Type tinfo) diff --git a/ddmd/dinifile.d b/ddmd/dinifile.d index 8e1c85cba32..be0bfa3f931 100644 --- a/ddmd/dinifile.d +++ b/ddmd/dinifile.d @@ -1,13 +1,13 @@ -/* - * Some portions copyright (c) 1994-1995 by Symantec - * Copyright (c) 1999-2017 by Digital Mars - * All Rights Reserved - * http://www.digitalmars.com - * Written by Walter Bright +/** + * Compiler implementation of the + * $(LINK2 http://www.dlang.org, D programming language). * - * This source file is made available for personal use - * only. The license is in backendlicense.txt - * For any other uses, please contact Digital Mars. + * Copyright: Copyright (C) 1994-1998 by Symantec + * Copyright (c) 2000-2017 by Digital Mars, All Rights Reserved + * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) + * License: Distributed under the Boost Software License, Version 1.0. + * http://www.boost.org/LICENSE_1_0.txt + * Source: https://github.com/dlang/dmd/blob/master/src/ddmd/_dinifile.d */ module ddmd.dinifile; diff --git a/ddmd/dsymbol.h b/ddmd/dsymbol.h index 49170a15ccd..570640f3ca3 100644 --- a/ddmd/dsymbol.h +++ b/ddmd/dsymbol.h @@ -63,7 +63,6 @@ class UnitTestDeclaration; class NewDeclaration; class VarDeclaration; class AttribDeclaration; -struct Symbol; class Package; class Module; class Import; @@ -84,6 +83,11 @@ class Expression; class DeleteDeclaration; class OverloadSet; struct AA; +#ifdef IN_GCC +typedef union tree_node Symbol; +#else +struct Symbol; +#endif struct Ungag { diff --git a/ddmd/errors.h b/ddmd/errors.h index 6f509077e9f..0827ec0d976 100644 --- a/ddmd/errors.h +++ b/ddmd/errors.h @@ -20,29 +20,36 @@ bool isConsoleColorSupported(); -void warning(const Loc& loc, const char *format, ...); -void warningSupplemental(const Loc& loc, const char *format, ...); -void deprecation(const Loc& loc, const char *format, ...); -void deprecationSupplemental(const Loc& loc, const char *format, ...); -void error(const Loc& loc, const char *format, ...); -void errorSupplemental(const Loc& loc, const char *format, ...); -void verror(const Loc& loc, const char *format, va_list ap, const char *p1 = NULL, const char *p2 = NULL, const char *header = "Error: "); -void verrorSupplemental(const Loc& loc, const char *format, va_list ap); -void vwarning(const Loc& loc, const char *format, va_list); -void vwarningSupplemental(const Loc& loc, const char *format, va_list ap); -void vdeprecation(const Loc& loc, const char *format, va_list ap, const char *p1 = NULL, const char *p2 = NULL); -void vdeprecationSupplemental(const Loc& loc, const char *format, va_list ap); +#if defined(__GNUC__) +#define D_ATTRIBUTE_FORMAT(m, n) __attribute__((format(printf, m, n))) __attribute__((nonnull (m))) +#else +#define D_ATTRIBUTE_FORMAT(m, n) +#endif + +// Print a warning, deprecation, or error, accepts printf-like format specifiers. +D_ATTRIBUTE_FORMAT(2, 3) void warning(const Loc& loc, const char *format, ...); +D_ATTRIBUTE_FORMAT(2, 3) void warningSupplemental(const Loc& loc, const char *format, ...); +D_ATTRIBUTE_FORMAT(2, 3) void deprecation(const Loc& loc, const char *format, ...); +D_ATTRIBUTE_FORMAT(2, 3) void deprecationSupplemental(const Loc& loc, const char *format, ...); +D_ATTRIBUTE_FORMAT(2, 3) void error(const Loc& loc, const char *format, ...); +D_ATTRIBUTE_FORMAT(2, 3) void errorSupplemental(const Loc& loc, const char *format, ...); +D_ATTRIBUTE_FORMAT(2, 0) void verror(const Loc& loc, const char *format, va_list ap, const char *p1 = NULL, const char *p2 = NULL, const char *header = "Error: "); +D_ATTRIBUTE_FORMAT(2, 0) void verrorSupplemental(const Loc& loc, const char *format, va_list ap); +D_ATTRIBUTE_FORMAT(2, 0) void vwarning(const Loc& loc, const char *format, va_list); +D_ATTRIBUTE_FORMAT(2, 0) void vwarningSupplemental(const Loc& loc, const char *format, va_list ap); +D_ATTRIBUTE_FORMAT(2, 0) void vdeprecation(const Loc& loc, const char *format, va_list ap, const char *p1 = NULL, const char *p2 = NULL); +D_ATTRIBUTE_FORMAT(2, 0) void vdeprecationSupplemental(const Loc& loc, const char *format, va_list ap); #if defined(__GNUC__) || defined(__clang__) -__attribute__((noreturn)) -void fatal(); +#define D_ATTRIBUTE_NORETURN __attribute__((noreturn)) #elif _MSC_VER -__declspec(noreturn) -void fatal(); +#define D_ATTRIBUTE_NORETURN __declspec(noreturn) #else -void fatal(); +#define D_ATTRIBUTE_NORETURN #endif -void halt(); +// Called after printing out fatal error messages. +D_ATTRIBUTE_NORETURN void fatal(); +D_ATTRIBUTE_NORETURN void halt(); #endif /* DMD_ERRORS_H */ diff --git a/ddmd/escape.d b/ddmd/escape.d index 3d04ee00189..23ac6743a31 100644 --- a/ddmd/escape.d +++ b/ddmd/escape.d @@ -705,9 +705,8 @@ private void escapeByValue(Expression e, EscapeByResults* er) override void visit(ThisExp e) { - VarDeclaration v = e.var.isVarDeclaration(); - if (v) - er.byvalue.push(v); + if (e.var) + er.byvalue.push(e.var); } override void visit(DotVarExp e) @@ -981,9 +980,8 @@ private void escapeByRef(Expression e, EscapeByResults* er) override void visit(ThisExp e) { - auto v = e.var.isVarDeclaration(); - if (v) - er.byref.push(v); + if (e.var) + er.byref.push(e.var); } override void visit(PtrExp e) diff --git a/ddmd/expression.d b/ddmd/expression.d index 47c283899ab..eb9ab4ec011 100644 --- a/ddmd/expression.d +++ b/ddmd/expression.d @@ -12202,16 +12202,6 @@ extern (C++) final class IntervalExp : Expression return this; } - override Expression modifiableLvalue(Scope* sc, Expression e) - { - if (sc.func.setUnsafe()) - { - error("cannot modify delegate pointer in @safe code %s", toChars()); - return new ErrorExp(); - } - return Expression.modifiableLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); diff --git a/ddmd/expression.h b/ddmd/expression.h index 3275f398e83..d81a44b0fd2 100644 --- a/ddmd/expression.h +++ b/ddmd/expression.h @@ -43,13 +43,20 @@ class TemplateInstance; class TemplateDeclaration; class ClassDeclaration; class BinExp; -struct Symbol; // back end symbol class OverloadSet; class Initializer; class StringExp; class ArrayExp; class SliceExp; struct UnionExp; +#ifdef IN_GCC +typedef union tree_node Symbol; +#else +struct Symbol; // back end symbol +#endif + +void initPrecedence(); + #if IN_LLVM class SymbolDeclaration; namespace llvm { @@ -1013,6 +1020,7 @@ class DelegatePtrExp : public UnaExp Expression *semantic(Scope *sc); bool isLvalue(); Expression *toLvalue(Scope *sc, Expression *e); + Expression *modifiableLvalue(Scope *sc, Expression *e); void accept(Visitor *v) { v->visit(this); } }; @@ -1022,6 +1030,7 @@ class DelegateFuncptrExp : public UnaExp Expression *semantic(Scope *sc); bool isLvalue(); Expression *toLvalue(Scope *sc, Expression *e); + Expression *modifiableLvalue(Scope *sc, Expression *e); void accept(Visitor *v) { v->visit(this); } }; diff --git a/ddmd/module.h b/ddmd/module.h index 308c253f8c8..0ecb4f16c85 100644 --- a/ddmd/module.h +++ b/ddmd/module.h @@ -60,7 +60,7 @@ class Package : public ScopeDsymbol bool isAncestorPackageOf(const Package * const pkg) const; - void semantic(Scope *sc) { } + void semantic(Scope *) { } Dsymbol *search(Loc loc, Identifier *ident, int flags = SearchLocalsOnly); void accept(Visitor *v) { v->visit(this); } diff --git a/ddmd/readme.txt b/ddmd/readme.txt index 18c96be6042..b07a0946384 100644 --- a/ddmd/readme.txt +++ b/ddmd/readme.txt @@ -1,7 +1,7 @@ The D Programming Language Compiler Front End Source - Copyright (c) 1999-2016, by Digital Mars + Copyright (c) 1999-2017, by Digital Mars http://www.digitalmars.com/ All Rights Reserved @@ -16,9 +16,6 @@ under the terms of the Boost Software License, Version 1.0. The terms of this license are in the file boostlicense.txt, or see http://www.boost.org/LICENSE_1_0.txt. -The optimizer and code generator sources are -covered under a separate license, backendlicense.txt. - It does not apply to anything else distributed by Digital Mars, including D compiler executables. diff --git a/ddmd/root/array.h b/ddmd/root/array.h index a215b45668c..f57de4e1ee4 100644 --- a/ddmd/root/array.h +++ b/ddmd/root/array.h @@ -155,8 +155,8 @@ struct Array #endif Array_sort_compare(const void *x, const void *y) { - RootObject *ox = *(RootObject **)x; - RootObject *oy = *(RootObject **)y; + RootObject *ox = *(RootObject **)const_cast(x); + RootObject *oy = *(RootObject **)const_cast(y); return ox->compare(oy); } diff --git a/ddmd/root/ctfloat.h b/ddmd/root/ctfloat.h index a5ff08f75eb..fdcfb7ec8d0 100644 --- a/ddmd/root/ctfloat.h +++ b/ddmd/root/ctfloat.h @@ -4,7 +4,7 @@ * http://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) - * https://github.com/D-Programming-Language/dmd/blob/master/src/root/port.h + * https://github.com/dlang/dmd/blob/master/src/root/ctfloat.h */ #ifndef CTFLOAT_H diff --git a/ddmd/target.d b/ddmd/target.d index c1d9a7364f5..98c0836b8e3 100644 --- a/ddmd/target.d +++ b/ddmd/target.d @@ -18,75 +18,50 @@ import ddmd.mtype; import ddmd.root.ctfloat; import ddmd.root.outbuffer; -version(IN_LLVM) -{ - -extern(C++): - +/*********************************************************** + */ struct Target { - static __gshared int ptrsize; - static __gshared int realsize; // size a real consumes in memory - static __gshared int realpad; // 'padding' added to the CPU real size to bring it up to realsize - static __gshared int realalignsize; // alignment for reals - static __gshared bool realislongdouble; // distinguish between C 'long double' and '__float128' - static __gshared bool reverseCppOverloads; // with dmc and cl, overloaded functions are grouped and in reverse order - static __gshared bool cppExceptions; // set if catching C++ exceptions is supported - static __gshared int c_longsize; // size of a C 'long' or 'unsigned long' type - static __gshared int c_long_doublesize; // size of a C 'long double' - static __gshared int classinfosize; // size of 'ClassInfo' + extern (C++) static __gshared int ptrsize; + extern (C++) static __gshared int realsize; // size a real consumes in memory + extern (C++) static __gshared int realpad; // 'padding' added to the CPU real size to bring it up to realsize + extern (C++) static __gshared int realalignsize; // alignment for reals + extern (C++) static __gshared bool realislongdouble; // distinguish between C 'long double' and '__float128' + extern (C++) static __gshared bool reverseCppOverloads; // with dmc and cl, overloaded functions are grouped and in reverse order + extern (C++) static __gshared bool cppExceptions; // set if catching C++ exceptions is supported + extern (C++) static __gshared int c_longsize; // size of a C 'long' or 'unsigned long' type + extern (C++) static __gshared int c_long_doublesize; // size of a C 'long double' + extern (C++) static __gshared int classinfosize; // size of 'ClassInfo' extern (C++) static __gshared ulong maxStaticDataSize; // maximum size of static data - extern(D) static struct FPTypeProperties(T) + extern (C++) struct FPTypeProperties(T) { - static real_t max() { return real_t(T.max); } - static real_t min_normal() { return real_t(T.min_normal); } - static real_t nan() { return real_t(T.nan); } - static real_t snan() { return real_t(T.init); } - static real_t infinity() { return real_t(T.infinity); } - static real_t epsilon() { return real_t(T.epsilon); } - - enum : long + static __gshared { - dig = T.dig, - mant_dig = T.mant_dig, - max_exp = T.max_exp, - min_exp = T.min_exp, - max_10_exp = T.max_10_exp, - min_10_exp = T.min_10_exp + real_t max = T.max; + real_t min_normal = T.min_normal; + real_t nan = T.nan; + real_t snan = T.init; + real_t infinity = T.infinity; + real_t epsilon = T.epsilon; + + d_int64 dig = T.dig; + d_int64 mant_dig = T.mant_dig; + d_int64 max_exp = T.max_exp; + d_int64 min_exp = T.min_exp; + d_int64 max_10_exp = T.max_10_exp; + d_int64 min_10_exp = T.min_10_exp; } } alias FloatProperties = FPTypeProperties!float; alias DoubleProperties = FPTypeProperties!double; + alias RealProperties = FPTypeProperties!real_t; - static struct RealProperties - { - // implemented in gen/target.cpp - static real_t max(); - static real_t min_normal(); - static real_t nan(); - static real_t snan(); - static real_t infinity(); - static real_t epsilon(); - - static real_t host_max() { return real_t.max; } - static real_t host_min_normal() { return real_t.min_normal; } - static real_t host_nan() { return real_t.nan; } - static real_t host_snan() { return real_t.init; } - static real_t host_infinity() { return real_t.infinity; } - static real_t host_epsilon() { return real_t.epsilon; } - - static __gshared - { - long dig = real_t.dig; - long mant_dig = real_t.mant_dig; - long max_exp = real_t.max_exp; - long min_exp = real_t.min_exp; - long max_10_exp = real_t.max_10_exp; - long min_10_exp = real_t.min_10_exp; - } - } + version(IN_LLVM) + { + // implemented in gen/target.cpp: + extern (C++): static void _init(); // Type sizes and support. @@ -100,55 +75,9 @@ struct Target // ABI and backend. static void loadModule(Module m); static void prefixName(OutBuffer *buf, LINK linkage); -} - -} -else // !IN_LLVM -{ - -/*********************************************************** - */ -struct Target -{ - extern (C++) static __gshared int ptrsize; - extern (C++) static __gshared int realsize; // size a real consumes in memory - extern (C++) static __gshared int realpad; // 'padding' added to the CPU real size to bring it up to realsize - extern (C++) static __gshared int realalignsize; // alignment for reals - extern (C++) static __gshared bool realislongdouble; // distinguish between C 'long double' and '__float128' - extern (C++) static __gshared bool reverseCppOverloads; // with dmc and cl, overloaded functions are grouped and in reverse order - extern (C++) static __gshared bool cppExceptions; // set if catching C++ exceptions is supported - extern (C++) static __gshared int c_longsize; // size of a C 'long' or 'unsigned long' type - extern (C++) static __gshared int c_long_doublesize; // size of a C 'long double' - extern (C++) static __gshared int classinfosize; // size of 'ClassInfo' - extern (C++) static __gshared ulong maxStaticDataSize; // maximum size of static data - - template FPTypeProperties(T) - { - enum : real_t - { - max = T.max, - min_normal = T.min_normal, - nan = T.nan, - snan = T.init, - infinity = T.infinity, - epsilon = T.epsilon - } - - enum : long - { - dig = T.dig, - mant_dig = T.mant_dig, - max_exp = T.max_exp, - min_exp = T.min_exp, - max_10_exp = T.max_10_exp, - min_10_exp = T.min_10_exp - } - } - - alias FloatProperties = FPTypeProperties!float; - alias DoubleProperties = FPTypeProperties!double; - alias RealProperties = FPTypeProperties!real; - + } + else // !IN_LLVM + { extern (C++) static void _init() { // These have default values for 32 bit code, they get @@ -440,8 +369,11 @@ struct Target break; } } + } // !IN_LLVM } +version(IN_LLVM) {} else { + /****************************** * Private helpers for Target::paintAsType. */ diff --git a/ddmd/target.h b/ddmd/target.h index 56c6cb1b2ed..eb756bdfde7 100644 --- a/ddmd/target.h +++ b/ddmd/target.h @@ -36,32 +36,27 @@ struct Target static int classinfosize; // size of 'ClassInfo' static unsigned long long maxStaticDataSize; // maximum size of static data -#ifdef IN_LLVM - struct RealProperties + template + struct FPTypeProperties { - // implemented in gen/target.cpp - static real_t max(); - static real_t min_normal(); - static real_t nan(); - static real_t snan(); - static real_t infinity(); - static real_t epsilon(); + static real_t max; + static real_t min_normal; + static real_t nan; + static real_t snan; + static real_t infinity; + static real_t epsilon; - static real_t host_max(); - static real_t host_min_normal(); - static real_t host_nan(); - static real_t host_snan(); - static real_t host_infinity(); - static real_t host_epsilon(); - - static int64_t dig; - static int64_t mant_dig; - static int64_t max_exp; - static int64_t min_exp; - static int64_t max_10_exp; - static int64_t min_10_exp; + static d_int64 dig; + static d_int64 mant_dig; + static d_int64 max_exp; + static d_int64 min_exp; + static d_int64 max_10_exp; + static d_int64 min_10_exp; }; -#endif + + typedef FPTypeProperties FloatProperties; + typedef FPTypeProperties DoubleProperties; + typedef FPTypeProperties RealProperties; static void _init(); // Type sizes and support. diff --git a/gen/target.cpp b/gen/target.cpp index 6099e6a23da..ec1f9687bd3 100644 --- a/gen/target.cpp +++ b/gen/target.cpp @@ -24,19 +24,6 @@ using llvm::APFloat; -// target-real values -real_t real_max; -real_t real_min_normal; -real_t real_epsilon; - -// Target::RealProperties functions -real_t Target::RealProperties::nan() { return host_nan(); } -real_t Target::RealProperties::snan() { return host_snan(); } -real_t Target::RealProperties::infinity() { return host_infinity(); } -real_t Target::RealProperties::max() { return real_max; } -real_t Target::RealProperties::min_normal() { return real_min_normal; } -real_t Target::RealProperties::epsilon() { return real_epsilon; } - void Target::_init() { ptrsize = gDataLayout->getPointerSize(ADDRESS_SPACE); @@ -69,9 +56,9 @@ void Target::_init() { #endif if (targetRealSemantics == IEEEdouble) { - real_max = CTFloat::parse("0x1.fffffffffffffp+1023"); - real_min_normal = CTFloat::parse("0x1p-1022"); - real_epsilon = CTFloat::parse("0x1p-52"); + RealProperties::max = CTFloat::parse("0x1.fffffffffffffp+1023"); + RealProperties::min_normal = CTFloat::parse("0x1p-1022"); + RealProperties::epsilon = CTFloat::parse("0x1p-52"); RealProperties::dig = 15; RealProperties::mant_dig = 53; RealProperties::max_exp = 1024; @@ -79,9 +66,9 @@ void Target::_init() { RealProperties::max_10_exp = 308; RealProperties::min_10_exp = -307; } else if (targetRealSemantics == x87DoubleExtended) { - real_max = CTFloat::parse("0x1.fffffffffffffffep+16383"); - real_min_normal = CTFloat::parse("0x1p-16382"); - real_epsilon = CTFloat::parse("0x1p-63"); + RealProperties::max = CTFloat::parse("0x1.fffffffffffffffep+16383"); + RealProperties::min_normal = CTFloat::parse("0x1p-16382"); + RealProperties::epsilon = CTFloat::parse("0x1p-63"); RealProperties::dig = 18; RealProperties::mant_dig = 64; RealProperties::max_exp = 16384; @@ -90,10 +77,12 @@ void Target::_init() { RealProperties::min_10_exp = -4931; } else if (targetRealSemantics == IEEEquad) { // FIXME: hex constants - real_max = CTFloat::parse("1.18973149535723176508575932662800702e+4932"); - real_min_normal = + RealProperties::max = + CTFloat::parse("1.18973149535723176508575932662800702e+4932"); + RealProperties::min_normal = CTFloat::parse("3.36210314311209350626267781732175260e-4932"); - real_epsilon = CTFloat::parse("1.92592994438723585305597794258492732e-34"); + RealProperties::epsilon = + CTFloat::parse("1.92592994438723585305597794258492732e-34"); RealProperties::dig = 33; RealProperties::mant_dig = 113; RealProperties::max_exp = 16384; @@ -101,11 +90,8 @@ void Target::_init() { RealProperties::max_10_exp = 4932; RealProperties::min_10_exp = -4931; } else { - // rely on host compiler - real_max = RealProperties::host_max(); - real_min_normal = RealProperties::host_min_normal(); - real_epsilon = RealProperties::host_epsilon(); - // the rest is already initialized with the corresponding real_t values + // leave initialized with host real_t values + warning(Loc(), "unknown properties for target real type"); } } diff --git a/runtime/druntime b/runtime/druntime index 2b175562c75..0a5e101bcda 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 2b175562c75aab4b55d8a4176810a98a428ef623 +Subproject commit 0a5e101bcda8a14b37081f1e3685266ad580beaf diff --git a/runtime/phobos b/runtime/phobos index e0ab515af91..bf1c82bf782 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit e0ab515af914800e8e2180efa7741ea4547aac49 +Subproject commit bf1c82bf782aa440a47b2e2be1ec29f88f782db7 diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 77165be7703..d02feb0deda 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 77165be7703903acea89ad9ee9d735c2f1d91976 +Subproject commit d02feb0deda29529f19b5506b36c08b37b112404 From 03d803419d7e95dfd3f7d0307bb494cbab5d0652 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 10 Jun 2017 04:23:32 +0200 Subject: [PATCH 19/19] Fix Target.RealProperties potentially aliasing Target.DoubleProperties In case the host real_t is double (e.g., for MSVC hosts). --- ddmd/target.d | 5 +++++ ddmd/target.h | 4 ++++ gen/target.cpp | 54 +++++++++++++++++++++++++------------------------- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/ddmd/target.d b/ddmd/target.d index 98c0836b8e3..9237af2a4b7 100644 --- a/ddmd/target.d +++ b/ddmd/target.d @@ -56,7 +56,12 @@ struct Target alias FloatProperties = FPTypeProperties!float; alias DoubleProperties = FPTypeProperties!double; + version(IN_LLVM) { + // host real_t may be double => make sure not to alias target's DoubleProperties + extern (C++) static __gshared FPTypeProperties!real_t RealProperties; + } else { alias RealProperties = FPTypeProperties!real_t; + } version(IN_LLVM) { diff --git a/ddmd/target.h b/ddmd/target.h index eb756bdfde7..393bb558100 100644 --- a/ddmd/target.h +++ b/ddmd/target.h @@ -56,7 +56,11 @@ struct Target typedef FPTypeProperties FloatProperties; typedef FPTypeProperties DoubleProperties; +#if IN_LLVM + static FPTypeProperties RealProperties; +#else typedef FPTypeProperties RealProperties; +#endif static void _init(); // Type sizes and support. diff --git a/gen/target.cpp b/gen/target.cpp index ec1f9687bd3..c027da12643 100644 --- a/gen/target.cpp +++ b/gen/target.cpp @@ -56,39 +56,39 @@ void Target::_init() { #endif if (targetRealSemantics == IEEEdouble) { - RealProperties::max = CTFloat::parse("0x1.fffffffffffffp+1023"); - RealProperties::min_normal = CTFloat::parse("0x1p-1022"); - RealProperties::epsilon = CTFloat::parse("0x1p-52"); - RealProperties::dig = 15; - RealProperties::mant_dig = 53; - RealProperties::max_exp = 1024; - RealProperties::min_exp = -1021; - RealProperties::max_10_exp = 308; - RealProperties::min_10_exp = -307; + RealProperties.max = CTFloat::parse("0x1.fffffffffffffp+1023"); + RealProperties.min_normal = CTFloat::parse("0x1p-1022"); + RealProperties.epsilon = CTFloat::parse("0x1p-52"); + RealProperties.dig = 15; + RealProperties.mant_dig = 53; + RealProperties.max_exp = 1024; + RealProperties.min_exp = -1021; + RealProperties.max_10_exp = 308; + RealProperties.min_10_exp = -307; } else if (targetRealSemantics == x87DoubleExtended) { - RealProperties::max = CTFloat::parse("0x1.fffffffffffffffep+16383"); - RealProperties::min_normal = CTFloat::parse("0x1p-16382"); - RealProperties::epsilon = CTFloat::parse("0x1p-63"); - RealProperties::dig = 18; - RealProperties::mant_dig = 64; - RealProperties::max_exp = 16384; - RealProperties::min_exp = -16381; - RealProperties::max_10_exp = 4932; - RealProperties::min_10_exp = -4931; + RealProperties.max = CTFloat::parse("0x1.fffffffffffffffep+16383"); + RealProperties.min_normal = CTFloat::parse("0x1p-16382"); + RealProperties.epsilon = CTFloat::parse("0x1p-63"); + RealProperties.dig = 18; + RealProperties.mant_dig = 64; + RealProperties.max_exp = 16384; + RealProperties.min_exp = -16381; + RealProperties.max_10_exp = 4932; + RealProperties.min_10_exp = -4931; } else if (targetRealSemantics == IEEEquad) { // FIXME: hex constants - RealProperties::max = + RealProperties.max = CTFloat::parse("1.18973149535723176508575932662800702e+4932"); - RealProperties::min_normal = + RealProperties.min_normal = CTFloat::parse("3.36210314311209350626267781732175260e-4932"); - RealProperties::epsilon = + RealProperties.epsilon = CTFloat::parse("1.92592994438723585305597794258492732e-34"); - RealProperties::dig = 33; - RealProperties::mant_dig = 113; - RealProperties::max_exp = 16384; - RealProperties::min_exp = -16381; - RealProperties::max_10_exp = 4932; - RealProperties::min_10_exp = -4931; + RealProperties.dig = 33; + RealProperties.mant_dig = 113; + RealProperties.max_exp = 16384; + RealProperties.min_exp = -16381; + RealProperties.max_10_exp = 4932; + RealProperties.min_10_exp = -4931; } else { // leave initialized with host real_t values warning(Loc(), "unknown properties for target real type");