From patchwork Fri May 27 19:10:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 1636442 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=vz4n5IB1; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4L8vY62nTMz9sBF for ; Sat, 28 May 2022 05:11:21 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B2CB3382832D for ; Fri, 27 May 2022 19:11:17 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B2CB3382832D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1653678677; bh=ymrn8QPN0WOfPd4ML3CsBJDwrtmZ234UXub5BrmJQXo=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=vz4n5IB1HB9qekNP0xJ4xiOuOxdivLjW1/seBO8VvRAXW19zO+Bq1dtwqZueN4p/z Pmy4NieJrPLpnKuUfmt1w+xMclg+gsS00h4AL/dhy7LZ02cSEUPGNWgA19y+tZd5Xj lPFwW4RDz7bKzr0AX12ZMj/SAB+7hchAvvMfsLdE= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mout-p-201.mailbox.org (mout-p-201.mailbox.org [IPv6:2001:67c:2050:0:465::201]) by sourceware.org (Postfix) with ESMTPS id BBF66383B7B4 for ; Fri, 27 May 2022 19:10:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org BBF66383B7B4 Received: from smtp102.mailbox.org (smtp102.mailbox.org [10.196.197.102]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-201.mailbox.org (Postfix) with ESMTPS id 4L8vWw3RyJz9sRj; Fri, 27 May 2022 21:10:20 +0200 (CEST) To: gcc-patches@gcc.gnu.org Subject: [committed] d: Merge upstream dmd 4d07f22f2, druntime f89da313, phobos d46814c86. Date: Fri, 27 May 2022 21:10:17 +0200 Message-Id: <20220527191017.2663556-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Iain Buclaw via Gcc-patches From: Iain Buclaw Reply-To: Iain Buclaw Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Hi, This patch merges the D front-end with upstream dmd 4d07f22f2, and the standard library with druntime f89da313 and phobos d46814c86. D front-end changes: - `scope' semantics are now enforced in `@safe' code on pointers to stack memory, but only as deprecation warnings. - Overriding virtual functions are now marked with the `override' and `final' in the generated headers of `-fdump-c++-spec='. - `-fpreview=fiximmmutableconv` has been added that disallows implicitly converting a return value with indirections to immutable if it determines the result must be unique. D runtime changes: - Posix (excluding Darwin): Switch default GC signals from SIGUSR1/2 to SIGRTMIN/SIGRTMIN+1 Phobos changes: - Import latest bug fixes to mainline. Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, and committed to mainline. Regards, Iain. --- gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 4d07f22f2 * d-lang.cc (d_handle_option): Handle OPT_fpreview_fiximmutableconv. * lang.opt (fpreview=fiximmutableconv): New option. * runtime.def (ARRAYAPPENDT): Remove. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime f89da313. * src/MERGE: Merge upstream phobos d46814c86. Signed-off-by: Iain Buclaw --- gcc/d/d-lang.cc | 5 + gcc/d/dmd/MERGE | 2 +- gcc/d/dmd/aggregate.h | 80 +- gcc/d/dmd/aliasthis.h | 10 +- gcc/d/dmd/attrib.h | 212 ++--- gcc/d/dmd/cond.h | 34 +- gcc/d/dmd/cparse.d | 156 +++- gcc/d/dmd/ctfe.h | 20 +- gcc/d/dmd/dcast.d | 21 +- gcc/d/dmd/declaration.h | 396 +++++----- gcc/d/dmd/dmodule.d | 33 +- gcc/d/dmd/dsymbol.d | 23 +- gcc/d/dmd/dsymbol.h | 64 +- gcc/d/dmd/dsymbolsem.d | 20 +- gcc/d/dmd/dtemplate.d | 2 +- gcc/d/dmd/dtoh.d | 28 +- gcc/d/dmd/enum.h | 34 +- gcc/d/dmd/escape.d | 231 ++++-- gcc/d/dmd/expression.d | 22 +- gcc/d/dmd/expression.h | 732 +++++++++--------- gcc/d/dmd/expressionsem.d | 59 +- gcc/d/dmd/func.d | 102 ++- gcc/d/dmd/globals.d | 3 +- gcc/d/dmd/globals.h | 4 +- gcc/d/dmd/hdrgen.d | 18 +- gcc/d/dmd/id.d | 2 + gcc/d/dmd/identifier.h | 7 +- gcc/d/dmd/import.h | 26 +- gcc/d/dmd/init.d | 2 +- gcc/d/dmd/init.h | 30 +- gcc/d/dmd/initsem.d | 5 +- gcc/d/dmd/lexer.d | 60 +- gcc/d/dmd/module.h | 27 +- gcc/d/dmd/mtype.d | 109 +-- gcc/d/dmd/mtype.h | 540 +++++++------ gcc/d/dmd/nspace.h | 20 +- gcc/d/dmd/parsetimevisitor.d | 4 + gcc/d/dmd/root/object.h | 4 +- gcc/d/dmd/safe.d | 19 +- gcc/d/dmd/sideeffect.d | 29 +- gcc/d/dmd/statement.d | 2 +- gcc/d/dmd/statement.h | 318 ++++---- gcc/d/dmd/statementsem.d | 13 +- gcc/d/dmd/staticassert.h | 12 +- gcc/d/dmd/template.h | 154 ++-- gcc/d/dmd/transitivevisitor.d | 14 +- gcc/d/dmd/typesem.d | 20 +- gcc/d/dmd/version.h | 28 +- gcc/d/dmd/visitor.h | 6 + gcc/d/lang.opt | 4 + gcc/d/runtime.def | 4 - .../compilable/dtoh_ClassDeclaration.d | 10 +- .../compilable/dtoh_TemplateDeclaration.d | 2 +- gcc/testsuite/gdc.test/compilable/test22865.d | 35 + .../fail_compilation/dip1000_deprecation.d | 59 ++ .../gdc.test/fail_compilation/dip25.d | 2 +- .../gdc.test/fail_compilation/fail12390.d | 3 +- .../gdc.test/fail_compilation/fail22351.d | 20 + .../gdc.test/fail_compilation/fail23135.d | 17 + .../gdc.test/fail_compilation/fail_scope.d | 2 +- .../gdc.test/fail_compilation/fix22108.d | 13 + .../gdc.test/fail_compilation/fix23138.d | 16 + .../gdc.test/fail_compilation/test15660.d | 2 +- .../gdc.test/fail_compilation/test18484.d | 2 +- .../gdc.test/fail_compilation/test20881.d | 2 +- .../runnable_cxx/extra-files/test22351.cpp | 46 ++ .../runnable_cxx/extra-files/test23135.cpp | 52 ++ .../gdc.test/runnable_cxx/test22351.d | 55 ++ .../gdc.test/runnable_cxx/test23135.d | 38 + libphobos/libdruntime/MERGE | 2 +- .../core/internal/array/appending.d | 21 +- libphobos/libdruntime/core/memory.d | 2 +- libphobos/libdruntime/core/thread/fiber.d | 7 +- libphobos/libdruntime/core/thread/osthread.d | 21 +- .../libdruntime/core/thread/threadbase.d | 4 +- libphobos/libdruntime/object.d | 25 +- libphobos/libdruntime/rt/arrayassign.d | 72 -- libphobos/libdruntime/rt/lifetime.d | 39 - libphobos/src/MERGE | 2 +- libphobos/src/std/package.d | 2 + libphobos/src/std/process.d | 4 +- libphobos/src/std/utf.d | 4 +- 82 files changed, 2497 insertions(+), 1854 deletions(-) create mode 100644 gcc/testsuite/gdc.test/compilable/test22865.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail22351.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail23135.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fix22108.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fix23138.d create mode 100644 gcc/testsuite/gdc.test/runnable_cxx/extra-files/test22351.cpp create mode 100644 gcc/testsuite/gdc.test/runnable_cxx/extra-files/test23135.cpp create mode 100644 gcc/testsuite/gdc.test/runnable_cxx/test22351.d create mode 100644 gcc/testsuite/gdc.test/runnable_cxx/test23135.d diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc index d1f4959f119..ef0fe0b8adb 100644 --- a/gcc/d/d-lang.cc +++ b/gcc/d/d-lang.cc @@ -581,6 +581,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value, global.params.rvalueRefParam = FeatureState::enabled; global.params.inclusiveInContracts = value; global.params.shortenedMethods = value; + global.params.fixImmutableConv = value; break; case OPT_fpreview_bitfields: @@ -615,6 +616,10 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value, global.params.fixAliasThis = value; break; + case OPT_fpreview_fiximmutableconv: + global.params.fixImmutableConv = value; + break; + case OPT_fpreview_in: global.params.previewIn = value; break; diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index b4d42ec6d2b..c37da0585d9 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -a6c5224b2d6b61fa3856aa8a3369581f7c949b68 +4d07f22f29d098869ad937f0499d8895df089a71 The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h index bdeb38e8b45..f27ca0769c9 100644 --- a/gcc/d/dmd/aggregate.h +++ b/gcc/d/dmd/aggregate.h @@ -120,20 +120,20 @@ public: Sizeok sizeok; // set when structsize contains valid data virtual Scope *newScope(Scope *sc); - void setScope(Scope *sc); + void setScope(Scope *sc) override final; size_t nonHiddenFields(); bool determineSize(const Loc &loc); virtual void finalizeSize() = 0; - uinteger_t size(const Loc &loc); + uinteger_t size(const Loc &loc) override final; bool fill(const Loc &loc, Expressions *elements, bool ctorinit); - Type *getType(); - bool isDeprecated() const; // is aggregate deprecated? + Type *getType() override final; + bool isDeprecated() const override final; // is aggregate deprecated? void setDeprecated(); bool isNested() const; - bool isExport() const; + bool isExport() const override final; Dsymbol *searchCtor(); - Visibility visible(); + Visibility visible() override final; // 'this' type Type *handleType() { return type; } @@ -143,8 +143,8 @@ public: // Back end void *sinit; - AggregateDeclaration *isAggregateDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + AggregateDeclaration *isAggregateDeclaration() override final { return this; } + void accept(Visitor *v) override { v->visit(this); } }; struct StructFlags @@ -186,28 +186,28 @@ public: TypeTuple *argTypes; static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject); - StructDeclaration *syntaxCopy(Dsymbol *s); - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); - const char *kind() const; - void finalizeSize(); + StructDeclaration *syntaxCopy(Dsymbol *s) override; + Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final; + const char *kind() const override; + void finalizeSize() override final; bool isPOD(); - StructDeclaration *isStructDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + StructDeclaration *isStructDeclaration() override final { return this; } + void accept(Visitor *v) override { v->visit(this); } unsigned numArgTypes() const; Type *argType(unsigned index); bool hasRegularCtor(bool checkDisabled = false); }; -class UnionDeclaration : public StructDeclaration +class UnionDeclaration final : public StructDeclaration { public: - UnionDeclaration *syntaxCopy(Dsymbol *s); - const char *kind() const; + UnionDeclaration *syntaxCopy(Dsymbol *s) override; + const char *kind() const override; - UnionDeclaration *isUnionDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + UnionDeclaration *isUnionDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; struct BaseClass @@ -279,9 +279,9 @@ public: Symbol *cpp_type_info_ptr_sym; // cached instance of class Id.cpp_type_info_ptr static ClassDeclaration *create(const Loc &loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject); - const char *toPrettyChars(bool QualifyTypes = false); - ClassDeclaration *syntaxCopy(Dsymbol *s); - Scope *newScope(Scope *sc); + const char *toPrettyChars(bool QualifyTypes = false) override; + ClassDeclaration *syntaxCopy(Dsymbol *s) override; + Scope *newScope(Scope *sc) override; bool isBaseOf2(ClassDeclaration *cd); #define OFFSET_RUNTIME 0x76543210 @@ -289,9 +289,9 @@ public: virtual bool isBaseOf(ClassDeclaration *cd, int *poffset); bool isBaseInfoComplete(); - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); + Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final; ClassDeclaration *searchBase(Identifier *ident); - void finalizeSize(); + void finalizeSize() override; bool hasMonitor(); bool isFuncHidden(FuncDeclaration *fd); FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf); @@ -301,30 +301,30 @@ public: virtual bool isCPPinterface() const; bool isAbstract(); virtual int vtblOffset() const; - const char *kind() const; + const char *kind() const override; - void addLocalClass(ClassDeclarations *); - void addObjcSymbols(ClassDeclarations *classes, ClassDeclarations *categories); + void addLocalClass(ClassDeclarations *) override final; + void addObjcSymbols(ClassDeclarations *classes, ClassDeclarations *categories) override final; // Back end Dsymbol *vtblsym; Dsymbol *vtblSymbol(); - ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; } - void accept(Visitor *v) { v->visit(this); } + ClassDeclaration *isClassDeclaration() override final { return (ClassDeclaration *)this; } + void accept(Visitor *v) override { v->visit(this); } }; -class InterfaceDeclaration : public ClassDeclaration +class InterfaceDeclaration final : public ClassDeclaration { public: - InterfaceDeclaration *syntaxCopy(Dsymbol *s); - Scope *newScope(Scope *sc); - bool isBaseOf(ClassDeclaration *cd, int *poffset); - const char *kind() const; - int vtblOffset() const; - bool isCPPinterface() const; - bool isCOMinterface() const; - - InterfaceDeclaration *isInterfaceDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + InterfaceDeclaration *syntaxCopy(Dsymbol *s) override; + Scope *newScope(Scope *sc) override; + bool isBaseOf(ClassDeclaration *cd, int *poffset) override; + const char *kind() const override; + int vtblOffset() const override; + bool isCPPinterface() const override; + bool isCOMinterface() const override; + + InterfaceDeclaration *isInterfaceDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/aliasthis.h b/gcc/d/dmd/aliasthis.h index 3b67903c4d0..c63d717a7bd 100644 --- a/gcc/d/dmd/aliasthis.h +++ b/gcc/d/dmd/aliasthis.h @@ -15,7 +15,7 @@ /**************************************************************/ -class AliasThis : public Dsymbol +class AliasThis final : public Dsymbol { public: // alias Identifier this; @@ -23,9 +23,9 @@ public: Dsymbol *sym; bool isDeprecated_; - AliasThis *syntaxCopy(Dsymbol *); - const char *kind() const; + AliasThis *syntaxCopy(Dsymbol *) override; + const char *kind() const override; AliasThis *isAliasThis() { return this; } - void accept(Visitor *v) { v->visit(this); } - bool isDeprecated() const { return this->isDeprecated_; } + void accept(Visitor *v) override { v->visit(this); } + bool isDeprecated() const override { return this->isDeprecated_; } }; diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h index 812729b3f27..1fe33a6ba51 100644 --- a/gcc/d/dmd/attrib.h +++ b/gcc/d/dmd/attrib.h @@ -26,20 +26,20 @@ public: virtual Dsymbols *include(Scope *sc); virtual Scope *newScope(Scope *sc); - void addMember(Scope *sc, ScopeDsymbol *sds); - void setScope(Scope *sc); - void importAll(Scope *sc); - void addComment(const utf8_t *comment); - const char *kind() const; - bool oneMember(Dsymbol **ps, Identifier *ident); - void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion); - bool hasPointers(); - bool hasStaticCtorOrDtor(); - void checkCtorConstInit(); - void addLocalClass(ClassDeclarations *); - AttribDeclaration *isAttribDeclaration() { return this; } - - void accept(Visitor *v) { v->visit(this); } + void addMember(Scope *sc, ScopeDsymbol *sds) override; + void setScope(Scope *sc) override; + void importAll(Scope *sc) override; + void addComment(const utf8_t *comment) override; + const char *kind() const override; + bool oneMember(Dsymbol **ps, Identifier *ident) override; + void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override; + bool hasPointers() override final; + bool hasStaticCtorOrDtor() override final; + void checkCtorConstInit() override final; + void addLocalClass(ClassDeclarations *) override final; + AttribDeclaration *isAttribDeclaration() override final { return this; } + + void accept(Visitor *v) override { v->visit(this); } }; class StorageClassDeclaration : public AttribDeclaration @@ -47,90 +47,90 @@ class StorageClassDeclaration : public AttribDeclaration public: StorageClass stc; - StorageClassDeclaration *syntaxCopy(Dsymbol *s); - Scope *newScope(Scope *sc); - bool oneMember(Dsymbol **ps, Identifier *ident); - void addMember(Scope *sc, ScopeDsymbol *sds); - StorageClassDeclaration *isStorageClassDeclaration() { return this; } + StorageClassDeclaration *syntaxCopy(Dsymbol *s) override; + Scope *newScope(Scope *sc) override; + bool oneMember(Dsymbol **ps, Identifier *ident) override final; + void addMember(Scope *sc, ScopeDsymbol *sds) override; + StorageClassDeclaration *isStorageClassDeclaration() override { return this; } - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class DeprecatedDeclaration : public StorageClassDeclaration +class DeprecatedDeclaration final : public StorageClassDeclaration { public: Expression *msg; const char *msgstr; - DeprecatedDeclaration *syntaxCopy(Dsymbol *s); - Scope *newScope(Scope *sc); - void setScope(Scope *sc); - void accept(Visitor *v) { v->visit(this); } + DeprecatedDeclaration *syntaxCopy(Dsymbol *s) override; + Scope *newScope(Scope *sc) override; + void setScope(Scope *sc) override; + void accept(Visitor *v) override { v->visit(this); } }; -class LinkDeclaration : public AttribDeclaration +class LinkDeclaration final : public AttribDeclaration { public: LINK linkage; static LinkDeclaration *create(const Loc &loc, LINK p, Dsymbols *decl); - LinkDeclaration *syntaxCopy(Dsymbol *s); - Scope *newScope(Scope *sc); - const char *toChars() const; - void accept(Visitor *v) { v->visit(this); } + LinkDeclaration *syntaxCopy(Dsymbol *s) override; + Scope *newScope(Scope *sc) override; + const char *toChars() const override; + void accept(Visitor *v) override { v->visit(this); } }; -class CPPMangleDeclaration : public AttribDeclaration +class CPPMangleDeclaration final : public AttribDeclaration { public: CPPMANGLE cppmangle; - CPPMangleDeclaration *syntaxCopy(Dsymbol *s); - Scope *newScope(Scope *sc); - void setScope(Scope *sc); - const char *toChars() const; - void accept(Visitor *v) { v->visit(this); } + CPPMangleDeclaration *syntaxCopy(Dsymbol *s) override; + Scope *newScope(Scope *sc) override; + void setScope(Scope *sc) override; + const char *toChars() const override; + void accept(Visitor *v) override { v->visit(this); } }; -class CPPNamespaceDeclaration : public AttribDeclaration +class CPPNamespaceDeclaration final : public AttribDeclaration { public: Expression *exp; - CPPNamespaceDeclaration *syntaxCopy(Dsymbol *s); - Scope *newScope(Scope *sc); - const char *toChars() const; - void accept(Visitor *v) { v->visit(this); } + CPPNamespaceDeclaration *syntaxCopy(Dsymbol *s) override; + Scope *newScope(Scope *sc) override; + const char *toChars() const override; + void accept(Visitor *v) override { v->visit(this); } }; -class VisibilityDeclaration : public AttribDeclaration +class VisibilityDeclaration final : public AttribDeclaration { public: Visibility visibility; DArray pkg_identifiers; - VisibilityDeclaration *syntaxCopy(Dsymbol *s); - Scope *newScope(Scope *sc); - void addMember(Scope *sc, ScopeDsymbol *sds); - const char *kind() const; - const char *toPrettyChars(bool unused); - VisibilityDeclaration *isVisibilityDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + VisibilityDeclaration *syntaxCopy(Dsymbol *s) override; + Scope *newScope(Scope *sc) override; + void addMember(Scope *sc, ScopeDsymbol *sds) override; + const char *kind() const override; + const char *toPrettyChars(bool unused) override; + VisibilityDeclaration *isVisibilityDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; -class AlignDeclaration : public AttribDeclaration +class AlignDeclaration final : public AttribDeclaration { public: Expressions *alignExps; structalign_t salign; AlignDeclaration(const Loc &loc, Expression *ealign, Dsymbols *decl); - AlignDeclaration *syntaxCopy(Dsymbol *s); - Scope *newScope(Scope *sc); - void accept(Visitor *v) { v->visit(this); } + AlignDeclaration *syntaxCopy(Dsymbol *s) override; + Scope *newScope(Scope *sc) override; + void accept(Visitor *v) override { v->visit(this); } }; -class AnonDeclaration : public AttribDeclaration +class AnonDeclaration final : public AttribDeclaration { public: bool isunion; @@ -139,24 +139,24 @@ public: unsigned anonstructsize; // size of anonymous struct unsigned anonalignsize; // size of anonymous struct for alignment purposes - AnonDeclaration *syntaxCopy(Dsymbol *s); - void setScope(Scope *sc); - void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion); - const char *kind() const; - AnonDeclaration *isAnonDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + AnonDeclaration *syntaxCopy(Dsymbol *s) override; + void setScope(Scope *sc) override; + void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override; + const char *kind() const override; + AnonDeclaration *isAnonDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; -class PragmaDeclaration : public AttribDeclaration +class PragmaDeclaration final : public AttribDeclaration { public: Expressions *args; // array of Expression's - PragmaDeclaration *syntaxCopy(Dsymbol *s); - Scope *newScope(Scope *sc); + PragmaDeclaration *syntaxCopy(Dsymbol *s) override; + Scope *newScope(Scope *sc) override; PINLINE evalPragmaInline(Scope* sc); - const char *kind() const; - void accept(Visitor *v) { v->visit(this); } + const char *kind() const override; + void accept(Visitor *v) override { v->visit(this); } }; class ConditionalDeclaration : public AttribDeclaration @@ -165,31 +165,31 @@ public: Condition *condition; Dsymbols *elsedecl; // array of Dsymbol's for else block - ConditionalDeclaration *syntaxCopy(Dsymbol *s); - bool oneMember(Dsymbol **ps, Identifier *ident); - Dsymbols *include(Scope *sc); - void addComment(const utf8_t *comment); - void setScope(Scope *sc); - void accept(Visitor *v) { v->visit(this); } + ConditionalDeclaration *syntaxCopy(Dsymbol *s) override; + bool oneMember(Dsymbol **ps, Identifier *ident) override final; + Dsymbols *include(Scope *sc) override; + void addComment(const utf8_t *comment) override final; + void setScope(Scope *sc) override; + void accept(Visitor *v) override { v->visit(this); } }; -class StaticIfDeclaration : public ConditionalDeclaration +class StaticIfDeclaration final : public ConditionalDeclaration { public: ScopeDsymbol *scopesym; bool addisdone; bool onStack; - StaticIfDeclaration *syntaxCopy(Dsymbol *s); - Dsymbols *include(Scope *sc); - void addMember(Scope *sc, ScopeDsymbol *sds); - void setScope(Scope *sc); - void importAll(Scope *sc); - const char *kind() const; - void accept(Visitor *v) { v->visit(this); } + StaticIfDeclaration *syntaxCopy(Dsymbol *s) override; + Dsymbols *include(Scope *sc) override; + void addMember(Scope *sc, ScopeDsymbol *sds) override; + void setScope(Scope *sc) override; + void importAll(Scope *sc) override; + const char *kind() const override; + void accept(Visitor *v) override { v->visit(this); } }; -class StaticForeachDeclaration : public AttribDeclaration +class StaticForeachDeclaration final : public AttribDeclaration { public: StaticForeach *sfe; @@ -198,31 +198,31 @@ public: bool cached; Dsymbols *cache; - StaticForeachDeclaration *syntaxCopy(Dsymbol *s); - bool oneMember(Dsymbol **ps, Identifier *ident); - Dsymbols *include(Scope *sc); - void addMember(Scope *sc, ScopeDsymbol *sds); - void addComment(const utf8_t *comment); - void setScope(Scope *sc); - void importAll(Scope *sc); - const char *kind() const; - void accept(Visitor *v) { v->visit(this); } + StaticForeachDeclaration *syntaxCopy(Dsymbol *s) override; + bool oneMember(Dsymbol **ps, Identifier *ident) override; + Dsymbols *include(Scope *sc) override; + void addMember(Scope *sc, ScopeDsymbol *sds) override; + void addComment(const utf8_t *comment) override; + void setScope(Scope *sc) override; + void importAll(Scope *sc) override; + const char *kind() const override; + void accept(Visitor *v) override { v->visit(this); } }; -class ForwardingAttribDeclaration : public AttribDeclaration +class ForwardingAttribDeclaration final : public AttribDeclaration { public: ForwardingScopeDsymbol *sym; - Scope *newScope(Scope *sc); - void addMember(Scope *sc, ScopeDsymbol *sds); - ForwardingAttribDeclaration *isForwardingAttribDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + Scope *newScope(Scope *sc) override; + void addMember(Scope *sc, ScopeDsymbol *sds) override; + ForwardingAttribDeclaration *isForwardingAttribDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; // Mixin declarations -class CompileDeclaration : public AttribDeclaration +class CompileDeclaration final : public AttribDeclaration { public: Expressions *exps; @@ -230,26 +230,26 @@ public: ScopeDsymbol *scopesym; bool compiled; - CompileDeclaration *syntaxCopy(Dsymbol *s); - void addMember(Scope *sc, ScopeDsymbol *sds); - void setScope(Scope *sc); - const char *kind() const; - void accept(Visitor *v) { v->visit(this); } + CompileDeclaration *syntaxCopy(Dsymbol *s) override; + void addMember(Scope *sc, ScopeDsymbol *sds) override; + void setScope(Scope *sc) override; + const char *kind() const override; + void accept(Visitor *v) override { v->visit(this); } }; /** * User defined attributes look like: * @(args, ...) */ -class UserAttributeDeclaration : public AttribDeclaration +class UserAttributeDeclaration final : public AttribDeclaration { public: Expressions *atts; - UserAttributeDeclaration *syntaxCopy(Dsymbol *s); - Scope *newScope(Scope *sc); - void setScope(Scope *sc); + UserAttributeDeclaration *syntaxCopy(Dsymbol *s) override; + Scope *newScope(Scope *sc) override; + void setScope(Scope *sc) override; Expressions *getAttributes(); - const char *kind() const; - void accept(Visitor *v) { v->visit(this); } + const char *kind() const override; + void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/cond.h b/gcc/d/dmd/cond.h index d69c13e8101..b33f288f9df 100644 --- a/gcc/d/dmd/cond.h +++ b/gcc/d/dmd/cond.h @@ -35,14 +35,16 @@ public: Loc loc; Include inc; + DYNCAST dyncast() const override final { return DYNCAST_CONDITION; } + virtual Condition *syntaxCopy() = 0; virtual int include(Scope *sc) = 0; virtual DebugCondition *isDebugCondition() { return NULL; } virtual VersionCondition *isVersionCondition() { return NULL; } - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class StaticForeach +class StaticForeach final : public RootObject { public: Loc loc; @@ -62,37 +64,37 @@ public: Identifier *ident; Module *mod; - DVCondition *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + DVCondition *syntaxCopy() override final; + void accept(Visitor *v) override { v->visit(this); } }; -class DebugCondition : public DVCondition +class DebugCondition final : public DVCondition { public: static void addGlobalIdent(const char *ident); - int include(Scope *sc); - DebugCondition *isDebugCondition() { return this; } - void accept(Visitor *v) { v->visit(this); } + int include(Scope *sc) override; + DebugCondition *isDebugCondition() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; -class VersionCondition : public DVCondition +class VersionCondition final : public DVCondition { public: static void addGlobalIdent(const char *ident); static void addPredefinedGlobalIdent(const char *ident); - int include(Scope *sc); - VersionCondition *isVersionCondition() { return this; } - void accept(Visitor *v) { v->visit(this); } + int include(Scope *sc) override; + VersionCondition *isVersionCondition() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; -class StaticIfCondition : public Condition +class StaticIfCondition final : public Condition { public: Expression *exp; - StaticIfCondition *syntaxCopy(); - int include(Scope *sc); - void accept(Visitor *v) { v->visit(this); } + StaticIfCondition *syntaxCopy() override; + int include(Scope *sc) override; + void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d index fde06484370..344933ace83 100644 --- a/gcc/d/dmd/cparse.d +++ b/gcc/d/dmd/cparse.d @@ -59,8 +59,16 @@ final class CParser(AST) : Parser!AST */ Array!(void*) typedefTab; /// Array of AST.Type[Identifier], typedef's indexed by Identifier + /* This is passed in as a list of #define lines, as generated by the C preprocessor with the + * appropriate switch to emit them. We append to it any #define's and #undef's encountered in the source + * file, as cpp with the -dD embeds them in the preprocessed output file. + * Once the file is parsed, then the #define's are converted to D symbols and appended to the array + * of Dsymbols returned by parseModule(). + */ + OutBuffer* defines; + extern (D) this(TARGET)(AST.Module _module, const(char)[] input, bool doDocComment, - const ref TARGET target) + const ref TARGET target, OutBuffer* defines) { super(_module, input, doDocComment); @@ -69,6 +77,7 @@ final class CParser(AST) : Parser!AST linkage = LINK.c; Ccompile = true; this.packalign.setDefault(); + this.defines = defines; // Configure sizes for C `long`, `long double`, `wchar_t`, ... this.boolsize = target.boolsize; @@ -104,6 +113,8 @@ final class CParser(AST) : Parser!AST { if (token.value == TOK.endOfFile) { + addDefines(); // convert #define's to Dsymbols + // wrap the symbols in `extern (C) { symbols }` auto wrap = new AST.Dsymbols(); auto ld = new AST.LinkDeclaration(token.loc, LINK.c, symbols); @@ -976,16 +987,19 @@ final class CParser(AST) : Parser!AST // ( type-name ) e = new AST.TypeExp(loc, t); } - e = new AST.DotIdExp(loc, e, Id.__sizeof); - break; } - // must be an expression - e = cparsePrimaryExp(); - e = new AST.DotIdExp(loc, e, Id.__sizeof); - break; + else + { + // must be an expression + e = cparseUnaryExp(); + } + } + else + { + //C11 6.5.3 + e = cparseUnaryExp(); } - e = cparseUnaryExp(); e = new AST.DotIdExp(loc, e, Id.__sizeof); break; } @@ -1697,7 +1711,7 @@ final class CParser(AST) : Parser!AST while (1) { Identifier id; - AST.Expression asmname; + AST.StringExp asmName; auto dt = cparseDeclarator(DTR.xdirect, tspec, id, specifier); if (!dt) { @@ -1719,7 +1733,7 @@ final class CParser(AST) : Parser!AST case TOK.asm_: case TOK.__attribute__: if (token.value == TOK.asm_) - asmname = cparseSimpleAsmExpr(); + asmName = cparseSimpleAsmExpr(); if (token.value == TOK.__attribute__) { cparseGnuAttributes(specifier); @@ -1876,14 +1890,26 @@ final class CParser(AST) : Parser!AST s = new AST.LinkDeclaration(s.loc, linkage, decls); } // Saw `asm("name")` in the function, type, or variable definition. - // This maps directly to `pragma(mangle, "name")` - if (asmname) + // This is equivalent to `pragma(mangle, "name")` in D + if (asmName) { - auto args = new AST.Expressions(1); - (*args)[0] = asmname; - auto decls = new AST.Dsymbols(1); - (*decls)[0] = s; - s = new AST.PragmaDeclaration(asmname.loc, Id.mangle, args, decls); + /* + https://issues.dlang.org/show_bug.cgi?id=23012 + Ideally this would be translated to a pragma(mangle) + decl. This is not possible because ImportC symbols are + (currently) merged before semantic analysis is performed, + so the pragma(mangle) never effects any change on the declarations + it pertains too. + + Writing to mangleOverride directly avoids this, and is possible + because C only a StringExp is allowed unlike a full fat pragma(mangle) + which is more liberal. + */ + if (auto p = s.isDeclaration()) + { + auto str = asmName.peekString(); + p.mangleOverride = str; + } } symbols.push(s); } @@ -3062,7 +3088,7 @@ final class CParser(AST) : Parser!AST * asm-string-literal: * string-literal */ - private AST.Expression cparseSimpleAsmExpr() + private AST.StringExp cparseSimpleAsmExpr() { nextToken(); // move past asm check(TOK.leftParenthesis); @@ -3070,7 +3096,7 @@ final class CParser(AST) : Parser!AST error("string literal expected"); auto label = cparsePrimaryExp(); check(TOK.rightParenthesis); - return label; + return cast(AST.StringExp) label; } /************************* @@ -4250,12 +4276,21 @@ final class CParser(AST) : Parser!AST case TOK._Bool: //case TOK._Imaginary: // ? missing in Spec case TOK._Complex: - - // typedef-name - case TOK.identifier: // will not know until semantic if typedef t = peek(t); break; + case TOK.identifier: + // Use typedef table to disambiguate + if (isTypedef(t.ident)) + { + t = peek(t); + break; + } + else + { + return false; + } + // struct-or-union-specifier // enum-specifier case TOK.struct_: @@ -4891,6 +4926,17 @@ final class CParser(AST) : Parser!AST poundLine(n, false); return true; } + else if (defines && (n.ident == Id.define || n.ident == Id.undef)) + { + /* Append this line to `defines`. + * Not canonicalizing it - assume it already is + */ + defines.writeByte('#'); + defines.writestring(n.ident.toString()); + skipToNextLine(defines); + defines.writeByte('\n'); + return true; + } else if (n.ident == Id.__pragma) { pragmaDirective(scanloc); @@ -5078,4 +5124,70 @@ final class CParser(AST) : Parser!AST } //} + + /******************************************************************************/ + /********************************* #define Parser *****************************/ + //{ + + /** + * Go through the #define's in the defines buffer and see what we can convert + * to Dsymbols, which are then appended to symbols[] + */ + void addDefines() + { + if (!defines || defines.length < 10) // minimum length of a #define line + return; + const length = defines.length; + auto slice = defines.peekChars()[0 .. length]; + resetDefineLines(slice); // reset lexer + + const(char)* endp = &slice[length - 7]; + + Token n; + + while (p < endp) + { + if (p[0 .. 7] == "#define") + { + p += 7; + scan(&n); + //printf("%s\n", n.toChars()); + if (n.value == TOK.identifier) + { + auto id = n.ident; + scan(&n); + if (n.value == TOK.endOfLine) // #define identifier + { + nextDefineLine(); + continue; + } + if (n.value == TOK.int32Literal) + { + const value = n.intvalue; + scan(&n); + if (n.value == TOK.endOfLine) + { + /* Declare manifest constant: + * enum id = value; + */ + AST.Expression e = new AST.IntegerExp(scanloc, value, AST.Type.tint32); + auto v = new AST.VarDeclaration(scanloc, AST.Type.tint32, id, new AST.ExpInitializer(scanloc, e), STC.manifest); + symbols.push(v); + nextDefineLine(); + continue; + } + } + } + skipToNextLine(); + } + else if (n.value != TOK.endOfLine) + { + skipToNextLine(); + } + nextDefineLine(); + assert(p - slice.ptr <= length); + } + } + + //} } diff --git a/gcc/d/dmd/ctfe.h b/gcc/d/dmd/ctfe.h index 5979aa70e41..ab022ff505e 100644 --- a/gcc/d/dmd/ctfe.h +++ b/gcc/d/dmd/ctfe.h @@ -17,7 +17,7 @@ A reference to a class, or an interface. We need this when we point to a base class (we must record what the type is). */ -class ClassReferenceExp : public Expression +class ClassReferenceExp final : public Expression { public: StructLiteralExp *value; @@ -26,39 +26,39 @@ public: /// Return index of the field, or -1 if not found /// Same as getFieldIndex, but checks for a direct match with the VarDeclaration int findFieldIndexByName(VarDeclaration *v); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; /** An uninitialized value */ -class VoidInitExp : public Expression +class VoidInitExp final : public Expression { public: VarDeclaration *var; - const char *toChars() const; - void accept(Visitor *v) { v->visit(this); } + const char *toChars() const override; + void accept(Visitor *v) override { v->visit(this); } }; /** Fake class which holds the thrown exception. Used for implementing exception handling. */ -class ThrownExceptionExp : public Expression +class ThrownExceptionExp final : public Expression { public: ClassReferenceExp *thrown; // the thing being tossed - const char *toChars() const; - void accept(Visitor *v) { v->visit(this); } + const char *toChars() const override; + void accept(Visitor *v) override { v->visit(this); } }; /****************************************************************/ // This type is only used by the interpreter. -class CTFEExp : public Expression +class CTFEExp final : public Expression { public: - const char *toChars() const; + const char *toChars() const override; }; diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index c0a86f57dd2..4607d6fee7c 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -824,9 +824,8 @@ MATCH implicitConvTo(Expression e, Type t) * convert to immutable */ if (e.f && - // lots of legacy code breaks with the following purity check - (global.params.useDIP1000 != FeatureState.enabled || e.f.isPure() >= PURE.const_) && - e.f.isReturnIsolated() // check isReturnIsolated last, because it is potentially expensive. + (!global.params.fixImmutableConv || e.f.isPure() >= PURE.const_) && + e.f.isReturnIsolated() // check isReturnIsolated last, because it is potentially expensive. ) { result = e.type.immutableOf().implicitConvTo(t); @@ -2768,16 +2767,14 @@ Expression scaleFactor(BinExp be, Scope* sc) else assert(0); - if (sc.func && !sc.intypeof) + + eoff = eoff.optimize(WANTvalue); + if (eoff.op == EXP.int64 && eoff.toInteger() == 0) { - eoff = eoff.optimize(WANTvalue); - if (eoff.op == EXP.int64 && eoff.toInteger() == 0) - { - } - else if (sc.func.setUnsafe(false, be.loc, "pointer arithmetic not allowed in @safe functions")) - { - return ErrorExp.get(); - } + } + else if (sc.setUnsafe(false, be.loc, "pointer arithmetic not allowed in @safe functions")) + { + return ErrorExp.get(); } return be; diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h index 0bde33dd9e9..2c7d381e797 100644 --- a/gcc/d/dmd/declaration.h +++ b/gcc/d/dmd/declaration.h @@ -122,10 +122,10 @@ public: Symbol* isym; // import version of csym DString mangleOverride; // overridden symbol with pragma(mangle, "...") - const char *kind() const; - uinteger_t size(const Loc &loc); + const char *kind() const override; + uinteger_t size(const Loc &loc) override final; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); + Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final; bool isStatic() const { return (storage_class & STCstatic) != 0; } LINK resolvedLinkage() const; // returns the linkage, resolving the target-specific `System` one @@ -142,7 +142,7 @@ public: bool isScope() const { return (storage_class & STCscope) != 0; } bool isSynchronized() const { return (storage_class & STCsynchronized) != 0; } bool isParameter() const { return (storage_class & STCparameter) != 0; } - bool isDeprecated() const { return (storage_class & STCdeprecated) != 0; } + bool isDeprecated() const override final { return (storage_class & STCdeprecated) != 0; } bool isOverride() const { return (storage_class & STCoverride) != 0; } bool isResult() const { return (storage_class & STCresult) != 0; } bool isField() const { return (storage_class & STCfield) != 0; } @@ -154,15 +154,15 @@ public: bool isFuture() const { return (storage_class & STCfuture) != 0; } - Visibility visible(); + Visibility visible() override final; - Declaration *isDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + Declaration *isDeclaration() override final { return this; } + void accept(Visitor *v) override { v->visit(this); } }; /**************************************************************/ -class TupleDeclaration : public Declaration +class TupleDeclaration final : public Declaration { public: Objects *objects; @@ -170,19 +170,19 @@ public: TypeTuple *tupletype; // !=NULL if this is a type tuple - TupleDeclaration *syntaxCopy(Dsymbol *); - const char *kind() const; - Type *getType(); - Dsymbol *toAlias2(); - bool needThis(); + TupleDeclaration *syntaxCopy(Dsymbol *) override; + const char *kind() const override; + Type *getType() override; + Dsymbol *toAlias2() override; + bool needThis() override; - TupleDeclaration *isTupleDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + TupleDeclaration *isTupleDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; /**************************************************************/ -class AliasDeclaration : public Declaration +class AliasDeclaration final : public Declaration { public: Dsymbol *aliassym; @@ -190,36 +190,36 @@ public: Dsymbol *_import; // !=NULL if unresolved internal alias for selective import static AliasDeclaration *create(const Loc &loc, Identifier *id, Type *type); - AliasDeclaration *syntaxCopy(Dsymbol *); - bool overloadInsert(Dsymbol *s); - const char *kind() const; - Type *getType(); - Dsymbol *toAlias(); - Dsymbol *toAlias2(); - bool isOverloadable() const; + AliasDeclaration *syntaxCopy(Dsymbol *) override; + bool overloadInsert(Dsymbol *s) override; + const char *kind() const override; + Type *getType() override; + Dsymbol *toAlias() override; + Dsymbol *toAlias2() override; + bool isOverloadable() const override; - AliasDeclaration *isAliasDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + AliasDeclaration *isAliasDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; /**************************************************************/ -class OverDeclaration : public Declaration +class OverDeclaration final : public Declaration { public: Dsymbol *overnext; // next in overload list Dsymbol *aliassym; - const char *kind() const; - bool equals(const RootObject *o) const; - bool overloadInsert(Dsymbol *s); + const char *kind() const override; + bool equals(const RootObject *o) const override; + bool overloadInsert(Dsymbol *s) override; - Dsymbol *toAlias(); + Dsymbol *toAlias() override; Dsymbol *isUnique(); - bool isOverloadable() const; + bool isOverloadable() const override; - OverDeclaration *isOverDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + OverDeclaration *isOverDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; /**************************************************************/ @@ -271,26 +271,26 @@ public: bool isArgDtorVar() const; // temporary created to handle scope destruction of a function argument bool isArgDtorVar(bool v); static VarDeclaration *create(const Loc &loc, Type *t, Identifier *id, Initializer *init, StorageClass storage_class = STCundefined); - VarDeclaration *syntaxCopy(Dsymbol *); - void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion); - const char *kind() const; - AggregateDeclaration *isThis(); - bool needThis(); - bool isExport() const; - bool isImportedSymbol() const; + VarDeclaration *syntaxCopy(Dsymbol *) override; + void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override final; + const char *kind() const override; + AggregateDeclaration *isThis() override final; + bool needThis() override final; + bool isExport() const override final; + bool isImportedSymbol() const override final; bool isCtorinit() const; - bool isDataseg(); - bool isThreadlocal(); + bool isDataseg() override final; + bool isThreadlocal() override final; bool isCTFE(); bool isOverlappedWith(VarDeclaration *v); - bool hasPointers(); + bool hasPointers() override final; bool canTakeAddressOf(); bool needsScopeDtor(); - void checkCtorConstInit(); - Dsymbol *toAlias(); + void checkCtorConstInit() override final; + Dsymbol *toAlias() override final; // Eliminate need for dynamic_cast - VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; } - void accept(Visitor *v) { v->visit(this); } + VarDeclaration *isVarDeclaration() override final { return (VarDeclaration *)this; } + void accept(Visitor *v) override { v->visit(this); } }; /**************************************************************/ @@ -303,23 +303,23 @@ public: unsigned fieldWidth; unsigned bitOffset; - BitFieldDeclaration *syntaxCopy(Dsymbol*); - BitFieldDeclaration *isBitFieldDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + BitFieldDeclaration *syntaxCopy(Dsymbol *) override; + BitFieldDeclaration *isBitFieldDeclaration() override final { return this; } + void accept(Visitor *v) override { v->visit(this); } }; /**************************************************************/ // This is a shell around a back end symbol -class SymbolDeclaration : public Declaration +class SymbolDeclaration final : public Declaration { public: AggregateDeclaration *dsym; // Eliminate need for dynamic_cast - SymbolDeclaration *isSymbolDeclaration() { return (SymbolDeclaration *)this; } - void accept(Visitor *v) { v->visit(this); } + SymbolDeclaration *isSymbolDeclaration() override { return (SymbolDeclaration *)this; } + void accept(Visitor *v) override { v->visit(this); } }; class TypeInfoDeclaration : public VarDeclaration @@ -328,149 +328,149 @@ public: Type *tinfo; static TypeInfoDeclaration *create(Type *tinfo); - TypeInfoDeclaration *syntaxCopy(Dsymbol *); - const char *toChars() const; + TypeInfoDeclaration *syntaxCopy(Dsymbol *) override final; + const char *toChars() const override final; - TypeInfoDeclaration *isTypeInfoDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + TypeInfoDeclaration *isTypeInfoDeclaration() override final { return this; } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoStructDeclaration : public TypeInfoDeclaration +class TypeInfoStructDeclaration final : public TypeInfoDeclaration { public: static TypeInfoStructDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoClassDeclaration : public TypeInfoDeclaration +class TypeInfoClassDeclaration final : public TypeInfoDeclaration { public: static TypeInfoClassDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoInterfaceDeclaration : public TypeInfoDeclaration +class TypeInfoInterfaceDeclaration final : public TypeInfoDeclaration { public: static TypeInfoInterfaceDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoPointerDeclaration : public TypeInfoDeclaration +class TypeInfoPointerDeclaration final : public TypeInfoDeclaration { public: static TypeInfoPointerDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoArrayDeclaration : public TypeInfoDeclaration +class TypeInfoArrayDeclaration final : public TypeInfoDeclaration { public: static TypeInfoArrayDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoStaticArrayDeclaration : public TypeInfoDeclaration +class TypeInfoStaticArrayDeclaration final : public TypeInfoDeclaration { public: static TypeInfoStaticArrayDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoAssociativeArrayDeclaration : public TypeInfoDeclaration +class TypeInfoAssociativeArrayDeclaration final : public TypeInfoDeclaration { public: static TypeInfoAssociativeArrayDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoEnumDeclaration : public TypeInfoDeclaration +class TypeInfoEnumDeclaration final : public TypeInfoDeclaration { public: static TypeInfoEnumDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoFunctionDeclaration : public TypeInfoDeclaration +class TypeInfoFunctionDeclaration final : public TypeInfoDeclaration { public: static TypeInfoFunctionDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoDelegateDeclaration : public TypeInfoDeclaration +class TypeInfoDelegateDeclaration final : public TypeInfoDeclaration { public: static TypeInfoDelegateDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoTupleDeclaration : public TypeInfoDeclaration +class TypeInfoTupleDeclaration final : public TypeInfoDeclaration { public: static TypeInfoTupleDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoConstDeclaration : public TypeInfoDeclaration +class TypeInfoConstDeclaration final : public TypeInfoDeclaration { public: static TypeInfoConstDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoInvariantDeclaration : public TypeInfoDeclaration +class TypeInfoInvariantDeclaration final : public TypeInfoDeclaration { public: static TypeInfoInvariantDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoSharedDeclaration : public TypeInfoDeclaration +class TypeInfoSharedDeclaration final : public TypeInfoDeclaration { public: static TypeInfoSharedDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoWildDeclaration : public TypeInfoDeclaration +class TypeInfoWildDeclaration final : public TypeInfoDeclaration { public: static TypeInfoWildDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeInfoVectorDeclaration : public TypeInfoDeclaration +class TypeInfoVectorDeclaration final : public TypeInfoDeclaration { public: static TypeInfoVectorDeclaration *create(Type *tinfo); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; /**************************************************************/ -class ThisDeclaration : public VarDeclaration +class ThisDeclaration final : public VarDeclaration { public: - ThisDeclaration *syntaxCopy(Dsymbol *); - ThisDeclaration *isThisDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + ThisDeclaration *syntaxCopy(Dsymbol *) override; + ThisDeclaration *isThisDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; enum class ILS : unsigned char @@ -614,9 +614,7 @@ public: FuncDeclarations *inlinedNestedCallees; -private: AttributeViolation* safetyViolation; -public: unsigned flags; // FUNCFLAGxxxxx @@ -625,31 +623,31 @@ public: ObjcFuncDeclaration objc; static FuncDeclaration *create(const Loc &loc, const Loc &endloc, Identifier *id, StorageClass storage_class, Type *type, bool noreturn = false); - FuncDeclaration *syntaxCopy(Dsymbol *); + FuncDeclaration *syntaxCopy(Dsymbol *) override; bool functionSemantic(); bool functionSemantic3(); - bool equals(const RootObject *o) const; + bool equals(const RootObject *o) const override final; int overrides(FuncDeclaration *fd); int findVtblIndex(Dsymbols *vtbl, int dim); BaseClass *overrideInterface(); - bool overloadInsert(Dsymbol *s); + bool overloadInsert(Dsymbol *s) override; bool inUnittest(); MATCH leastAsSpecialized(FuncDeclaration *g); LabelDsymbol *searchLabel(Identifier *ident, const Loc &loc); int getLevel(FuncDeclaration *fd, int intypeof); // lexical nesting level difference int getLevelAndCheck(const Loc &loc, Scope *sc, FuncDeclaration *fd); - const char *toPrettyChars(bool QualifyTypes = false); + const char *toPrettyChars(bool QualifyTypes = false) override; const char *toFullSignature(); // for diagnostics, e.g. 'int foo(int x, int y) pure' bool isMain() const; bool isCMain() const; bool isWinMain() const; bool isDllMain() const; - bool isExport() const; - bool isImportedSymbol() const; - bool isCodeseg() const; - bool isOverloadable() const; - bool isAbstract(); + bool isExport() const override final; + bool isImportedSymbol() const override final; + bool isCodeseg() const override final; + bool isOverloadable() const override final; + bool isAbstract() override final; PURE isPure(); PURE isPureBypassingInference(); bool isSafe(); @@ -676,14 +674,14 @@ public: void isCrtDtor(bool v); virtual bool isNested() const; - AggregateDeclaration *isThis(); - bool needThis(); + AggregateDeclaration *isThis() override; + bool needThis() override final; bool isVirtualMethod(); virtual bool isVirtual() const; bool isFinalFunc() const; virtual bool addPreInvariant(); virtual bool addPostInvariant(); - const char *kind() const; + const char *kind() const override; bool isUnique(); bool needsClosure(); bool hasNestedFrameRefs(); @@ -694,26 +692,26 @@ public: bool checkNRVO(); - FuncDeclaration *isFuncDeclaration() { return this; } + FuncDeclaration *isFuncDeclaration() override final { return this; } virtual FuncDeclaration *toAliasFunc() { return this; } - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class FuncAliasDeclaration : public FuncDeclaration +class FuncAliasDeclaration final : public FuncDeclaration { public: FuncDeclaration *funcalias; bool hasOverloads; - FuncAliasDeclaration *isFuncAliasDeclaration() { return this; } - const char *kind() const; + FuncAliasDeclaration *isFuncAliasDeclaration() override { return this; } + const char *kind() const override; - FuncDeclaration *toAliasFunc(); - void accept(Visitor *v) { v->visit(this); } + FuncDeclaration *toAliasFunc() override; + void accept(Visitor *v) override { v->visit(this); } }; -class FuncLiteralDeclaration : public FuncDeclaration +class FuncLiteralDeclaration final : public FuncDeclaration { public: TOK tok; // TOKfunction or TOKdelegate @@ -722,85 +720,85 @@ public: // backend bool deferToObj; - FuncLiteralDeclaration *syntaxCopy(Dsymbol *); - bool isNested() const; - AggregateDeclaration *isThis(); - bool isVirtual() const; - bool addPreInvariant(); - bool addPostInvariant(); + FuncLiteralDeclaration *syntaxCopy(Dsymbol *) override; + bool isNested() const override; + AggregateDeclaration *isThis() override; + bool isVirtual() const override; + bool addPreInvariant() override; + bool addPostInvariant() override; void modifyReturns(Scope *sc, Type *tret); - FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; } - const char *kind() const; - const char *toPrettyChars(bool QualifyTypes = false); - void accept(Visitor *v) { v->visit(this); } + FuncLiteralDeclaration *isFuncLiteralDeclaration() override { return this; } + const char *kind() const override; + const char *toPrettyChars(bool QualifyTypes = false) override; + void accept(Visitor *v) override { v->visit(this); } }; -class CtorDeclaration : public FuncDeclaration +class CtorDeclaration final : public FuncDeclaration { public: bool isCpCtor; - CtorDeclaration *syntaxCopy(Dsymbol *); - const char *kind() const; - const char *toChars() const; - bool isVirtual() const; - bool addPreInvariant(); - bool addPostInvariant(); + CtorDeclaration *syntaxCopy(Dsymbol *) override; + const char *kind() const override; + const char *toChars() const override; + bool isVirtual() const override; + bool addPreInvariant() override; + bool addPostInvariant() override; - CtorDeclaration *isCtorDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + CtorDeclaration *isCtorDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; -class PostBlitDeclaration : public FuncDeclaration +class PostBlitDeclaration final : public FuncDeclaration { public: - PostBlitDeclaration *syntaxCopy(Dsymbol *); - bool isVirtual() const; - bool addPreInvariant(); - bool addPostInvariant(); - bool overloadInsert(Dsymbol *s); + PostBlitDeclaration *syntaxCopy(Dsymbol *) override; + bool isVirtual() const override; + bool addPreInvariant() override; + bool addPostInvariant() override; + bool overloadInsert(Dsymbol *s) override; - PostBlitDeclaration *isPostBlitDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + PostBlitDeclaration *isPostBlitDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; -class DtorDeclaration : public FuncDeclaration +class DtorDeclaration final : public FuncDeclaration { public: - DtorDeclaration *syntaxCopy(Dsymbol *); - const char *kind() const; - const char *toChars() const; - bool isVirtual() const; - bool addPreInvariant(); - bool addPostInvariant(); - bool overloadInsert(Dsymbol *s); + DtorDeclaration *syntaxCopy(Dsymbol *) override; + const char *kind() const override; + const char *toChars() const override; + bool isVirtual() const override; + bool addPreInvariant() override; + bool addPostInvariant() override; + bool overloadInsert(Dsymbol *s) override; - DtorDeclaration *isDtorDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + DtorDeclaration *isDtorDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; class StaticCtorDeclaration : public FuncDeclaration { public: - StaticCtorDeclaration *syntaxCopy(Dsymbol *); - AggregateDeclaration *isThis(); - bool isVirtual() const; - bool addPreInvariant(); - bool addPostInvariant(); - bool hasStaticCtorOrDtor(); + StaticCtorDeclaration *syntaxCopy(Dsymbol *) override; + AggregateDeclaration *isThis() override final; + bool isVirtual() const override final; + bool addPreInvariant() override final; + bool addPostInvariant() override final; + bool hasStaticCtorOrDtor() override final; - StaticCtorDeclaration *isStaticCtorDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + StaticCtorDeclaration *isStaticCtorDeclaration() override final { return this; } + void accept(Visitor *v) override { v->visit(this); } }; -class SharedStaticCtorDeclaration : public StaticCtorDeclaration +class SharedStaticCtorDeclaration final : public StaticCtorDeclaration { public: - SharedStaticCtorDeclaration *syntaxCopy(Dsymbol *); + SharedStaticCtorDeclaration *syntaxCopy(Dsymbol *) override; - SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; class StaticDtorDeclaration : public FuncDeclaration @@ -808,39 +806,39 @@ class StaticDtorDeclaration : public FuncDeclaration public: VarDeclaration *vgate; // 'gate' variable - StaticDtorDeclaration *syntaxCopy(Dsymbol *); - AggregateDeclaration *isThis(); - bool isVirtual() const; - bool hasStaticCtorOrDtor(); - bool addPreInvariant(); - bool addPostInvariant(); + StaticDtorDeclaration *syntaxCopy(Dsymbol *) override; + AggregateDeclaration *isThis() override final; + bool isVirtual() const override final; + bool hasStaticCtorOrDtor() override final; + bool addPreInvariant() override final; + bool addPostInvariant() override final; - StaticDtorDeclaration *isStaticDtorDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + StaticDtorDeclaration *isStaticDtorDeclaration() override final { return this; } + void accept(Visitor *v) override { v->visit(this); } }; -class SharedStaticDtorDeclaration : public StaticDtorDeclaration +class SharedStaticDtorDeclaration final : public StaticDtorDeclaration { public: - SharedStaticDtorDeclaration *syntaxCopy(Dsymbol *); + SharedStaticDtorDeclaration *syntaxCopy(Dsymbol *) override; - SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; -class InvariantDeclaration : public FuncDeclaration +class InvariantDeclaration final : public FuncDeclaration { public: - InvariantDeclaration *syntaxCopy(Dsymbol *); - bool isVirtual() const; - bool addPreInvariant(); - bool addPostInvariant(); + InvariantDeclaration *syntaxCopy(Dsymbol *) override; + bool isVirtual() const override; + bool addPreInvariant() override; + bool addPostInvariant() override; - InvariantDeclaration *isInvariantDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + InvariantDeclaration *isInvariantDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; -class UnitTestDeclaration : public FuncDeclaration +class UnitTestDeclaration final : public FuncDeclaration { public: char *codedoc; /** For documented unittest. */ @@ -848,25 +846,25 @@ public: // toObjFile() these nested functions after this one FuncDeclarations deferredNested; - UnitTestDeclaration *syntaxCopy(Dsymbol *); - AggregateDeclaration *isThis(); - bool isVirtual() const; - bool addPreInvariant(); - bool addPostInvariant(); + UnitTestDeclaration *syntaxCopy(Dsymbol *) override; + AggregateDeclaration *isThis() override; + bool isVirtual() const override; + bool addPreInvariant() override; + bool addPostInvariant() override; - UnitTestDeclaration *isUnitTestDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + UnitTestDeclaration *isUnitTestDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; -class NewDeclaration : public FuncDeclaration +class NewDeclaration final : public FuncDeclaration { public: - NewDeclaration *syntaxCopy(Dsymbol *); - const char *kind() const; - bool isVirtual() const; - bool addPreInvariant(); - bool addPostInvariant(); + NewDeclaration *syntaxCopy(Dsymbol *) override; + const char *kind() const override; + bool isVirtual() const override; + bool addPreInvariant() override; + bool addPostInvariant() override; - NewDeclaration *isNewDeclaration() { return this; } - void accept(Visitor *v) { v->visit(this); } + NewDeclaration *isNewDeclaration() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d index 26a0ff03092..f8e5073a5f1 100644 --- a/gcc/d/dmd/dmodule.d +++ b/gcc/d/dmd/dmodule.d @@ -363,6 +363,9 @@ extern (C++) final class Module : Package int selfimports; // 0: don't know, 1: does not, 2: does Dsymbol[void*] tagSymTab; /// ImportC: tag symbols that conflict with other symbols used as the index + private OutBuffer defines; // collect all the #define lines here + + /************************************* * Return true if module imports itself. */ @@ -677,33 +680,7 @@ extern (C++) final class Module : Package FileName.equalsExt(srcfile.toString(), c_ext) && FileName.exists(srcfile.toString())) { - /* Look for "importc.h" by searching along import path. - * It should be in the same place as "object.d" - */ - const(char)* importc_h; - - foreach (entry; (global.path ? (*global.path)[] : null)) - { - auto f = FileName.combine(entry, "importc.h"); - if (FileName.exists(f) == 1) - { - importc_h = f; - break; - } - FileName.free(f); - } - - if (importc_h) - { - if (global.params.verbose) - message("include %s", importc_h); - } - else - { - error("cannot find \"importc.h\" along import path"); - fatal(); - } - filename = global.preprocess(srcfile, importc_h, global.params.cppswitches, ifile); // run C preprocessor + filename = global.preprocess(srcfile, loc, global.params.cppswitches, ifile, &defines); // run C preprocessor } if (auto result = global.fileManager.lookup(filename)) @@ -1001,7 +978,7 @@ extern (C++) final class Module : Package { filetype = FileType.c; - scope p = new CParser!AST(this, buf, cast(bool) docfile, target.c); + scope p = new CParser!AST(this, buf, cast(bool) docfile, target.c, &defines); p.nextToken(); checkCompiledImport(); members = p.parseModule(); diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d index b0069403408..3b3a527dc52 100644 --- a/gcc/d/dmd/dsymbol.d +++ b/gcc/d/dmd/dsymbol.d @@ -1978,8 +1978,9 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol } const DYNCAST kind = arrayContent.dyncast(); - if (kind == DYNCAST.dsymbol) + switch (kind) with (DYNCAST) { + case dsymbol: TupleDeclaration td = cast(TupleDeclaration) arrayContent; /* $ gives the number of elements in the tuple */ @@ -1989,10 +1990,10 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol v.storage_class |= STC.temp | STC.static_ | STC.const_; v.dsymbolSemantic(sc); return v; - } - if (kind == DYNCAST.type) - { + case type: return dollarFromTypeTuple(loc, cast(TypeTuple) arrayContent, sc); + default: + break; } Expression exp = cast(Expression) arrayContent; if (auto ie = exp.isIndexExp()) @@ -2531,6 +2532,16 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy if (log) printf(" collision\n"); return null; } + /* + Handle merging declarations with asm("foo") and their definitions + */ + static void mangleWrangle(Declaration oldDecl, Declaration newDecl) + { + if (oldDecl && newDecl) + { + newDecl.mangleOverride = oldDecl.mangleOverride ? oldDecl.mangleOverride : null; + } + } auto vd = s.isVarDeclaration(); // new declaration auto vd2 = s2.isVarDeclaration(); // existing declaration @@ -2548,6 +2559,8 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy if (i1 && i2) return collision(); // can't both have initializers + mangleWrangle(vd2, vd); + if (i1) // vd is the definition { vd2.storage_class |= STC.extern_; // so toObjFile() won't emit it @@ -2593,6 +2606,8 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy if (fd.fbody && fd2.fbody) return collision(); // can't both have bodies + mangleWrangle(fd2, fd); + if (fd.fbody) // fd is the definition { if (log) printf(" replace existing with new\n"); diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h index 35500af4548..23a2c775d4c 100644 --- a/gcc/d/dmd/dsymbol.h +++ b/gcc/d/dmd/dsymbol.h @@ -185,11 +185,11 @@ public: UserAttributeDeclaration *userAttribDecl; // user defined attributes static Dsymbol *create(Identifier *); - const char *toChars() const; + const char *toChars() const override; virtual const char *toPrettyCharsHelper(); // helper to print fully qualified (template) arguments Loc getLoc(); const char *locToChars(); - bool equals(const RootObject *o) const; + bool equals(const RootObject *o) const override; bool isAnonymous() const; void error(const Loc &loc, const char *format, ...); void error(const char *format, ...); @@ -211,7 +211,7 @@ public: Ungag ungagSpeculative(); // kludge for template.isSymbol() - DYNCAST dyncast() const { return DYNCAST_DSYMBOL; } + DYNCAST dyncast() const override final { return DYNCAST_DSYMBOL; } virtual Identifier *getIdent(); virtual const char *toPrettyChars(bool QualifyTypes = false); @@ -310,7 +310,7 @@ public: virtual OverloadSet *isOverloadSet() { return NULL; } virtual CompileDeclaration *isCompileDeclaration() { return NULL; } virtual StaticAssert *isStaticAssert() { return NULL; } - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; // Dsymbol that generates a scope @@ -329,89 +329,89 @@ private: BitArray accessiblePackages, privateAccessiblePackages; public: - ScopeDsymbol *syntaxCopy(Dsymbol *s); - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); + ScopeDsymbol *syntaxCopy(Dsymbol *s) override; + Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; virtual void importScope(Dsymbol *s, Visibility visibility); virtual bool isPackageAccessible(Package *p, Visibility visibility, int flags = 0); - bool isforwardRef(); + bool isforwardRef() override final; static void multiplyDefined(const Loc &loc, Dsymbol *s1, Dsymbol *s2); - const char *kind() const; + const char *kind() const override; FuncDeclaration *findGetMembers(); virtual Dsymbol *symtabInsert(Dsymbol *s); virtual Dsymbol *symtabLookup(Dsymbol *s, Identifier *id); - bool hasStaticCtorOrDtor(); + bool hasStaticCtorOrDtor() override; - ScopeDsymbol *isScopeDsymbol() { return this; } - void accept(Visitor *v) { v->visit(this); } + ScopeDsymbol *isScopeDsymbol() override final { return this; } + void accept(Visitor *v) override { v->visit(this); } }; // With statement scope -class WithScopeSymbol : public ScopeDsymbol +class WithScopeSymbol final : public ScopeDsymbol { public: WithStatement *withstate; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); + Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; - WithScopeSymbol *isWithScopeSymbol() { return this; } - void accept(Visitor *v) { v->visit(this); } + WithScopeSymbol *isWithScopeSymbol() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; // Array Index/Slice scope -class ArrayScopeSymbol : public ScopeDsymbol +class ArrayScopeSymbol final : public ScopeDsymbol { private: RootObject *arrayContent; public: Scope *sc; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone); + Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone) override; - ArrayScopeSymbol *isArrayScopeSymbol() { return this; } - void accept(Visitor *v) { v->visit(this); } + ArrayScopeSymbol *isArrayScopeSymbol() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; // Overload Sets -class OverloadSet : public Dsymbol +class OverloadSet final : public Dsymbol { public: Dsymbols a; // array of Dsymbols void push(Dsymbol *s); - OverloadSet *isOverloadSet() { return this; } - const char *kind() const; - void accept(Visitor *v) { v->visit(this); } + OverloadSet *isOverloadSet() override { return this; } + const char *kind() const override; + void accept(Visitor *v) override { v->visit(this); } }; // Forwarding ScopeDsymbol -class ForwardingScopeDsymbol : public ScopeDsymbol +class ForwardingScopeDsymbol final : public ScopeDsymbol { public: ScopeDsymbol *forward; - Dsymbol *symtabInsert(Dsymbol *s); - Dsymbol *symtabLookup(Dsymbol *s, Identifier *id); - void importScope(Dsymbol *s, Visibility visibility); - const char *kind() const; + Dsymbol *symtabInsert(Dsymbol *s) override; + Dsymbol *symtabLookup(Dsymbol *s, Identifier *id) override; + void importScope(Dsymbol *s, Visibility visibility) override; + const char *kind() const override; - ForwardingScopeDsymbol *isForwardingScopeDsymbol() { return this; } + ForwardingScopeDsymbol *isForwardingScopeDsymbol() override { return this; } }; -class ExpressionDsymbol : public Dsymbol +class ExpressionDsymbol final : public Dsymbol { public: Expression *exp; - ExpressionDsymbol *isExpressionDsymbol() { return this; } + ExpressionDsymbol *isExpressionDsymbol() override { return this; } }; // Table of Dsymbol's -class DsymbolTable : public RootObject +class DsymbolTable final : public RootObject { public: AA *tab; diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index 5d880560c4e..e49127220a0 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -468,12 +468,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor dsym.type.checkComplexTransition(dsym.loc, sc); // Calculate type size + safety checks - if (sc.func && !sc.intypeof) + if (dsym.storage_class & STC.gshared && !dsym.isMember()) { - if (dsym.storage_class & STC.gshared && !dsym.isMember()) - { - sc.func.setUnsafe(false, dsym.loc, "__gshared not allowed in safe functions; use shared"); - } + sc.setUnsafe(false, dsym.loc, "__gshared not allowed in safe functions; use shared"); } Dsymbol parent = dsym.toParent(); @@ -857,23 +854,23 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } // Calculate type size + safety checks - if (sc.func && !sc.intypeof) + if (1) { if (dsym._init && dsym._init.isVoidInitializer() && (dsym.type.hasPointers() || dsym.type.hasInvariant())) // also computes type size { if (dsym.type.hasPointers()) - sc.func.setUnsafe(false, dsym.loc, + sc.setUnsafe(false, dsym.loc, "`void` initializers for pointers not allowed in safe functions"); else - sc.func.setUnsafe(false, dsym.loc, + sc.setUnsafe(false, dsym.loc, "`void` initializers for structs with invariants are not allowed in safe functions"); } else if (!dsym._init && !(dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field | STC.parameter)) && dsym.type.hasVoidInitPointers()) { - sc.func.setUnsafe(false, dsym.loc, "`void` initializers for pointers not allowed in safe functions"); + sc.setUnsafe(false, dsym.loc, "`void` initializers for pointers not allowed in safe functions"); } } @@ -3595,6 +3592,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor break; } + auto vtf = getFunctionType(fdv); + if (vtf.trust > TRUST.system && f.trust == TRUST.system) + funcdecl.error("cannot override `@safe` method `%s` with a `@system` attribute", + fdv.toPrettyChars); + if (fdc.toParent() == parent) { //printf("vi = %d,\tthis = %p %s %s @ [%s]\n\tfdc = %p %s %s @ [%s]\n\tfdv = %p %s %s @ [%s]\n", diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d index ed0126eeef6..a450ea559ac 100644 --- a/gcc/d/dmd/dtemplate.d +++ b/gcc/d/dmd/dtemplate.d @@ -5352,7 +5352,7 @@ extern (C++) class TemplateParameter : ASTNode return this.ident.toChars(); } - override DYNCAST dyncast() const pure @nogc nothrow @safe + override DYNCAST dyncast() const { return DYNCAST.templateparameter; } diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d index 55f7c724e5a..9afcc7fe687 100644 --- a/gcc/d/dmd/dtoh.d +++ b/gcc/d/dmd/dtoh.d @@ -801,26 +801,22 @@ public: if (adparent && fd.isDisabled && global.params.cplusplus < CppStdRevision.cpp11) writeProtection(AST.Visibility.Kind.private_); funcToBuffer(tf, fd); - // FIXME: How to determine if fd is const without tf? - if (adparent && tf && (tf.isConst() || tf.isImmutable())) + if (adparent) { - bool fdOverridesAreConst = true; - foreach (fdv; fd.foverrides) + if (tf && (tf.isConst() || tf.isImmutable())) + buf.writestring(" const"); + if (global.params.cplusplus >= CppStdRevision.cpp11) { - auto tfv = cast(AST.TypeFunction)fdv.type; - if (!tfv.isConst() && !tfv.isImmutable()) - { - fdOverridesAreConst = false; - break; - } + if (fd.vtblIndex != -1 && !(adparent.storage_class & AST.STC.final_) && fd.isFinalFunc()) + buf.writestring(" final"); + if (fd.isOverride()) + buf.writestring(" override"); } - - buf.writestring(fdOverridesAreConst ? " const" : " /* const */"); + if (fd.isAbstract()) + buf.writestring(" = 0"); + else if (global.params.cplusplus >= CppStdRevision.cpp11 && fd.isDisabled()) + buf.writestring(" = delete"); } - if (adparent && fd.isAbstract()) - buf.writestring(" = 0"); - if (adparent && fd.isDisabled && global.params.cplusplus >= CppStdRevision.cpp11) - buf.writestring(" = delete"); buf.writestringln(";"); if (adparent && fd.isDisabled && global.params.cplusplus < CppStdRevision.cpp11) writeProtection(AST.Visibility.Kind.public_); diff --git a/gcc/d/dmd/enum.h b/gcc/d/dmd/enum.h index ab80c8b9073..9ec130099fe 100644 --- a/gcc/d/dmd/enum.h +++ b/gcc/d/dmd/enum.h @@ -17,7 +17,7 @@ class Identifier; class Type; class Expression; -class EnumDeclaration : public ScopeDsymbol +class EnumDeclaration final : public ScopeDsymbol { public: /* The separate, and distinct, cases are: @@ -40,27 +40,27 @@ public: bool added; int inuse; - EnumDeclaration *syntaxCopy(Dsymbol *s); - void addMember(Scope *sc, ScopeDsymbol *sds); - void setScope(Scope *sc); - bool oneMember(Dsymbol **ps, Identifier *ident); - Type *getType(); - const char *kind() const; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); - bool isDeprecated() const; // is Dsymbol deprecated? - Visibility visible(); + EnumDeclaration *syntaxCopy(Dsymbol *s) override; + void addMember(Scope *sc, ScopeDsymbol *sds) override; + void setScope(Scope *sc) override; + bool oneMember(Dsymbol **ps, Identifier *ident) override; + Type *getType() override; + const char *kind() const override; + Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; + bool isDeprecated() const override; // is Dsymbol deprecated? + Visibility visible() override; bool isSpecial() const; Expression *getDefaultValue(const Loc &loc); Type *getMemtype(const Loc &loc); - EnumDeclaration *isEnumDeclaration() { return this; } + EnumDeclaration *isEnumDeclaration() override { return this; } Symbol *sinit; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class EnumMember : public VarDeclaration +class EnumMember final : public VarDeclaration { public: /* Can take the following forms: @@ -78,9 +78,9 @@ public: EnumDeclaration *ed; - EnumMember *syntaxCopy(Dsymbol *s); - const char *kind() const; + EnumMember *syntaxCopy(Dsymbol *s) override; + const char *kind() const override; - EnumMember *isEnumMember() { return this; } - void accept(Visitor *v) { v->visit(this); } + EnumMember *isEnumMember() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d index 3f41c298c2c..97a655289b5 100644 --- a/gcc/d/dmd/escape.d +++ b/gcc/d/dmd/escape.d @@ -145,7 +145,7 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf, refs = true; auto var = outerVars[i - (len - outerVars.length)]; eb.isMutable = var.type.isMutable(); - eb.er.byref.push(var); + eb.er.pushRef(var, false); continue; } @@ -165,7 +165,7 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf, if (!(eb.isMutable || eb2.isMutable)) return; - if (!(global.params.useDIP1000 == FeatureState.enabled && sc.func.setUnsafe())) + if (!(global.params.useDIP1000 == FeatureState.enabled && sc.setUnsafe())) return; if (!gag) @@ -1185,6 +1185,8 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) if (v.isDataseg()) continue; + const vsr = buildScopeRef(v.storage_class); + Dsymbol p = v.toParent2(); if ((v.isScope() || (v.storage_class & STC.maybescope)) && @@ -1200,8 +1202,13 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) if (v.isScope()) { - if (v.storage_class & STC.return_) + /* If `return scope` applies to v. + */ + if (vsr == ScopeRef.ReturnScope || + vsr == ScopeRef.Ref_ReturnScope) + { continue; + } auto pfunc = p.isFuncDeclaration(); if (pfunc && @@ -1245,7 +1252,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) } } - foreach (VarDeclaration v; er.byref) + foreach (i, VarDeclaration v; er.byref[]) { if (log) { @@ -1281,9 +1288,16 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) } else { - if (!gag) - previewErrorFunc(sc.isDeprecated(), featureState)(e.loc, msg, e.toChars(), v.toChars()); - result = true; + if (er.refRetRefTransition[i]) + { + result |= sc.setUnsafeDIP1000(gag, e.loc, msg, e, v); + } + else + { + if (!gag) + previewErrorFunc(sc.isDeprecated(), featureState)(e.loc, msg, e.toChars(), v.toChars()); + result = true; + } } } @@ -1374,14 +1388,21 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) } } - foreach (Expression ee; er.byexp) + foreach (i, Expression ee; er.byexp[]) { if (log) printf("byexp %s\n", ee.toChars()); - if (!gag) - error(ee.loc, "escaping reference to stack allocated value returned by `%s`", ee.toChars()); - result = true; + if (er.expRetRefTransition[i]) + { + result |= sc.setUnsafeDIP1000(gag, ee.loc, + "escaping reference to stack allocated value returned by `%s`", ee); + } + else + { + if (!gag) + error(ee.loc, "escaping reference to stack allocated value returned by `%s`", ee.toChars()); + result = true; + } } - return result; } @@ -1449,8 +1470,9 @@ private void inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope) * e = expression to be returned by value * er = where to place collected data * live = if @live semantics apply, i.e. expressions `p`, `*p`, `**p`, etc., all return `p`. + * retRefTransition = if `e` is returned through a `return ref scope` function call */ -void escapeByValue(Expression e, EscapeByResults* er, bool live = false) +void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool retRefTransition = false) { //printf("[%s] escapeByValue, e: %s\n", e.loc.toChars(), e.toChars()); @@ -1465,14 +1487,14 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) * but it'll be placed in static data so no need to check it. */ if (e.e1.op != EXP.structLiteral) - escapeByRef(e.e1, er, live); + escapeByRef(e.e1, er, live, retRefTransition); } void visitSymOff(SymOffExp e) { VarDeclaration v = e.var.isVarDeclaration(); if (v) - er.byref.push(v); + er.pushRef(v, retRefTransition); } void visitVar(VarExp e) @@ -1494,7 +1516,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) void visitPtr(PtrExp e) { if (live && e.type.hasPointers()) - escapeByValue(e.e1, er, live); + escapeByValue(e.e1, er, live, retRefTransition); } void visitDotVar(DotVarExp e) @@ -1502,7 +1524,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) auto t = e.e1.type.toBasetype(); if (e.type.hasPointers() && (live || t.ty == Tstruct)) { - escapeByValue(e.e1, er, live); + escapeByValue(e.e1, er, live, retRefTransition); } } @@ -1510,9 +1532,9 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) { Type t = e.e1.type.toBasetype(); if (t.ty == Tclass || t.ty == Tpointer) - escapeByValue(e.e1, er, live); + escapeByValue(e.e1, er, live, retRefTransition); else - escapeByRef(e.e1, er, live); + escapeByRef(e.e1, er, live, retRefTransition); er.byfunc.push(e.func); } @@ -1533,11 +1555,11 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) if (tb.ty == Tsarray || tb.ty == Tarray) { if (e.basis) - escapeByValue(e.basis, er, live); + escapeByValue(e.basis, er, live, retRefTransition); foreach (el; *e.elements) { if (el) - escapeByValue(el, er, live); + escapeByValue(el, er, live, retRefTransition); } } } @@ -1549,7 +1571,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) foreach (ex; *e.elements) { if (ex) - escapeByValue(ex, er, live); + escapeByValue(ex, er, live, retRefTransition); } } } @@ -1562,7 +1584,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) foreach (ex; *e.arguments) { if (ex) - escapeByValue(ex, er, live); + escapeByValue(ex, er, live, retRefTransition); } } } @@ -1574,10 +1596,10 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) Type tb = e.type.toBasetype(); if (tb.ty == Tarray && e.e1.type.toBasetype().ty == Tsarray) { - escapeByRef(e.e1, er, live); + escapeByRef(e.e1, er, live, retRefTransition); } else - escapeByValue(e.e1, er, live); + escapeByValue(e.e1, er, live, retRefTransition); } void visitSlice(SliceExp e) @@ -1602,10 +1624,10 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) { Type tb = e.type.toBasetype(); if (tb.ty != Tsarray) - escapeByRef(e.e1, er, live); + escapeByRef(e.e1, er, live, retRefTransition); } else - escapeByValue(e.e1, er, live); + escapeByValue(e.e1, er, live, retRefTransition); } void visitIndex(IndexExp e) @@ -1613,7 +1635,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) if (e.e1.type.toBasetype().ty == Tsarray || live && e.type.hasPointers()) { - escapeByValue(e.e1, er, live); + escapeByValue(e.e1, er, live, retRefTransition); } } @@ -1622,30 +1644,30 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) Type tb = e.type.toBasetype(); if (tb.ty == Tpointer) { - escapeByValue(e.e1, er, live); - escapeByValue(e.e2, er, live); + escapeByValue(e.e1, er, live, retRefTransition); + escapeByValue(e.e2, er, live, retRefTransition); } } void visitBinAssign(BinAssignExp e) { - escapeByValue(e.e1, er, live); + escapeByValue(e.e1, er, live, retRefTransition); } void visitAssign(AssignExp e) { - escapeByValue(e.e1, er, live); + escapeByValue(e.e1, er, live, retRefTransition); } void visitComma(CommaExp e) { - escapeByValue(e.e2, er, live); + escapeByValue(e.e2, er, live, retRefTransition); } void visitCond(CondExp e) { - escapeByValue(e.e1, er, live); - escapeByValue(e.e2, er, live); + escapeByValue(e.e1, er, live, retRefTransition); + escapeByValue(e.e2, er, live, retRefTransition); } void visitCall(CallExp e) @@ -1686,7 +1708,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) const stc = tf.parameterStorageClass(null, p); ScopeRef psr = buildScopeRef(stc); if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope) - escapeByValue(arg, er, live); + escapeByValue(arg, er, live, retRefTransition); else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope) { if (tf.isref) @@ -1696,10 +1718,10 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) * as: * p; */ - escapeByValue(arg, er, live); + escapeByValue(arg, er, live, retRefTransition); } else - escapeByRef(arg, er, live); + escapeByRef(arg, er, live, retRefTransition); } } } @@ -1709,7 +1731,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) { DotVarExp dve = e.e1.isDotVarExp(); FuncDeclaration fd = dve.var.isFuncDeclaration(); - if (global.params.useDIP1000 == FeatureState.enabled) + if (1) { if (fd && fd.isThis()) { @@ -1741,7 +1763,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) const psr = buildScopeRef(getThisStorageClass(fd)); if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope) - escapeByValue(dve.e1, er, live); + escapeByValue(dve.e1, er, live, retRefTransition); else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope) { if (tf.isref) @@ -1751,10 +1773,10 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) * as: * this; */ - escapeByValue(dve.e1, er, live); + escapeByValue(dve.e1, er, live, retRefTransition); } else - escapeByRef(dve.e1, er, live); + escapeByRef(dve.e1, er, live, psr == ScopeRef.ReturnRef_Scope); } } } @@ -1767,16 +1789,16 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) const psr = buildScopeRef(stc); if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope) - escapeByValue(dve.e1, er, live); + escapeByValue(dve.e1, er, live, retRefTransition); else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope) - escapeByRef(dve.e1, er, live); + escapeByRef(dve.e1, er, live, retRefTransition); } // If it's also a nested function that is 'return scope' if (fd && fd.isNested()) { if (tf.isreturn && tf.isScopeQual) - er.byexp.push(e); + er.pushExp(e, false); } } @@ -1786,7 +1808,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) if (dg) { if (tf.isreturn) - escapeByValue(e.e1, er, live); + escapeByValue(e.e1, er, live, retRefTransition); } /* If it's a nested function that is 'return scope' @@ -1797,7 +1819,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) if (fd && fd.isNested()) { if (tf.isreturn && tf.isScopeQual) - er.byexp.push(e); + er.pushExp(e, false); } } } @@ -1852,10 +1874,11 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false) * e = expression to be returned by 'ref' * er = where to place collected data * live = if @live semantics apply, i.e. expressions `p`, `*p`, `**p`, etc., all return `p`. + * retRefTransition = if `e` is returned through a `return ref scope` function call */ -void escapeByRef(Expression e, EscapeByResults* er, bool live = false) +void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retRefTransition = false) { - //printf("[%s] escapeByRef, e: %s\n", e.loc.toChars(), e.toChars()); + //printf("[%s] escapeByRef, e: %s, retRefTransition: %d\n", e.loc.toChars(), e.toChars(), retRefTransition); void visit(Expression e) { } @@ -1874,27 +1897,27 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false) if (ExpInitializer ez = v._init.isExpInitializer()) { if (auto ce = ez.exp.isConstructExp()) - escapeByRef(ce.e2, er, live); + escapeByRef(ce.e2, er, live, retRefTransition); else - escapeByRef(ez.exp, er, live); + escapeByRef(ez.exp, er, live, retRefTransition); } } else - er.byref.push(v); + er.pushRef(v, retRefTransition); } } void visitThis(ThisExp e) { if (e.var && e.var.toParent2().isFuncDeclaration().hasDualContext()) - escapeByValue(e, er, live); + escapeByValue(e, er, live, retRefTransition); else if (e.var) - er.byref.push(e.var); + er.pushRef(e.var, retRefTransition); } void visitPtr(PtrExp e) { - escapeByValue(e.e1, er, live); + escapeByValue(e.e1, er, live, retRefTransition); } void visitIndex(IndexExp e) @@ -1907,18 +1930,18 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false) { if (v && v.storage_class & STC.variadic) { - er.byref.push(v); + er.pushRef(v, retRefTransition); return; } } } if (tb.ty == Tsarray) { - escapeByRef(e.e1, er, live); + escapeByRef(e.e1, er, live, retRefTransition); } else if (tb.ty == Tarray) { - escapeByValue(e.e1, er, live); + escapeByValue(e.e1, er, live, retRefTransition); } } @@ -1929,40 +1952,40 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false) foreach (ex; *e.elements) { if (ex) - escapeByRef(ex, er, live); + escapeByRef(ex, er, live, retRefTransition); } } - er.byexp.push(e); + er.pushExp(e, retRefTransition); } void visitDotVar(DotVarExp e) { Type t1b = e.e1.type.toBasetype(); if (t1b.ty == Tclass) - escapeByValue(e.e1, er, live); + escapeByValue(e.e1, er, live, retRefTransition); else - escapeByRef(e.e1, er, live); + escapeByRef(e.e1, er, live, retRefTransition); } void visitBinAssign(BinAssignExp e) { - escapeByRef(e.e1, er, live); + escapeByRef(e.e1, er, live, retRefTransition); } void visitAssign(AssignExp e) { - escapeByRef(e.e1, er, live); + escapeByRef(e.e1, er, live, retRefTransition); } void visitComma(CommaExp e) { - escapeByRef(e.e2, er, live); + escapeByRef(e.e2, er, live, retRefTransition); } void visitCond(CondExp e) { - escapeByRef(e.e1, er, live); - escapeByRef(e.e2, er, live); + escapeByRef(e.e1, er, live, retRefTransition); + escapeByRef(e.e2, er, live, retRefTransition); } void visitCall(CallExp e) @@ -1997,16 +2020,16 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false) const stc = tf.parameterStorageClass(null, p); ScopeRef psr = buildScopeRef(stc); if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope) - escapeByRef(arg, er, live); + escapeByRef(arg, er, live, retRefTransition); else if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope) { if (auto de = arg.isDelegateExp()) { if (de.func.isNested()) - er.byexp.push(de); + er.pushExp(de, false); } else - escapeByValue(arg, er, live); + escapeByValue(arg, er, live, retRefTransition); } } } @@ -2019,7 +2042,7 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false) // https://issues.dlang.org/show_bug.cgi?id=20149#c10 if (dve.var.isCtorDeclaration()) { - er.byexp.push(e); + er.pushExp(e, false); return; } @@ -2035,23 +2058,23 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false) const psr = buildScopeRef(stc); if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope) - escapeByRef(dve.e1, er, live); + escapeByRef(dve.e1, er, live, psr == ScopeRef.ReturnRef_Scope); else if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope) - escapeByValue(dve.e1, er, live); + escapeByValue(dve.e1, er, live, retRefTransition); // If it's also a nested function that is 'return ref' if (FuncDeclaration fd = dve.var.isFuncDeclaration()) { if (fd.isNested() && tf.isreturn) { - er.byexp.push(e); + er.pushExp(e, false); } } } // If it's a delegate, check it too if (e.e1.op == EXP.variable && t1.ty == Tdelegate) { - escapeByValue(e.e1, er, live); + escapeByValue(e.e1, er, live, retRefTransition); } /* If it's a nested function that is 'return ref' @@ -2062,12 +2085,12 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false) if (fd && fd.isNested()) { if (tf.isreturn) - er.byexp.push(e); + er.pushExp(e, false); } } } else - er.byexp.push(e); + er.pushExp(e, retRefTransition); } switch (e.op) @@ -2091,7 +2114,6 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false) } } - /************************************ * Aggregate the data collected by the escapeBy??() functions. */ @@ -2099,8 +2121,23 @@ struct EscapeByResults { VarDeclarations byref; // array into which variables being returned by ref are inserted VarDeclarations byvalue; // array into which variables with values containing pointers are inserted - FuncDeclarations byfunc; // nested functions that are turned into delegates - Expressions byexp; // array into which temporaries being returned by ref are inserted + private FuncDeclarations byfunc; // nested functions that are turned into delegates + private Expressions byexp; // array into which temporaries being returned by ref are inserted + + import dmd.root.array: Array; + + /** + * Whether the variable / expression went through a `return ref scope` function call + * + * This is needed for the dip1000 by default transition, since the rules for + * disambiguating `return scope ref` have changed. Therefore, functions in legacy code + * can be mistakenly treated as `return ref` making the compiler believe stack variables + * are being escaped, which is an error even in `@system` code. By keeping track of this + * information, variables escaped through `return ref` can be treated as a deprecation instead + * of error, see test/fail_compilation/dip1000_deprecation.d + */ + private Array!bool refRetRefTransition; + private Array!bool expRetRefTransition; /** Reset arrays so the storage can be used again */ @@ -2110,6 +2147,33 @@ struct EscapeByResults byvalue.setDim(0); byfunc.setDim(0); byexp.setDim(0); + + refRetRefTransition.setDim(0); + expRetRefTransition.setDim(0); + } + + /** + * Escape variable `v` by reference + * Params: + * v = variable to escape + * retRefTransition = `v` is escaped through a `return ref scope` function call + */ + void pushRef(VarDeclaration v, bool retRefTransition) + { + byref.push(v); + refRetRefTransition.push(retRefTransition); + } + + /** + * Escape a reference to expression `e` + * Params: + * e = expression to escape + * retRefTransition = `e` is escaped through a `return ref scope` function call + */ + void pushExp(Expression e, bool retRefTransition) + { + byexp.push(e); + expRetRefTransition.push(retRefTransition); } } @@ -2438,7 +2502,7 @@ private bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, con } else if (fs == FeatureState.enabled) { - return sc.func.setUnsafe(gag, loc, msg, arg0, arg1); + return sc.setUnsafe(gag, loc, msg, arg0, arg1); } else { @@ -2449,6 +2513,11 @@ private bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, con loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "" ); } + else if (!sc.func.safetyViolation) + { + import dmd.func : AttributeViolation; + sc.func.safetyViolation = new AttributeViolation(loc, msg, arg0, arg1); + } return false; } } diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d index 08723565355..4d171059306 100644 --- a/gcc/d/dmd/expression.d +++ b/gcc/d/dmd/expression.d @@ -1370,7 +1370,7 @@ extern (C++) abstract class Expression : ASTNode */ if (v.storage_class & STC.gshared) { - if (sc.func.setUnsafe(false, this.loc, + if (sc.setUnsafe(false, this.loc, "`@safe` function `%s` cannot access `__gshared` data `%s`", sc.func, v)) { err = true; @@ -1419,7 +1419,7 @@ extern (C++) abstract class Expression : ASTNode error("`@safe` %s `%s` cannot call `@system` %s `%s`", sc.func.kind(), sc.func.toPrettyChars(), f.kind(), prettyChars); - f.errorSupplementalInferredSafety(/*max depth*/ 10); + f.errorSupplementalInferredSafety(/*max depth*/ 10, /*deprecation*/ false); .errorSupplemental(f.loc, "`%s` is declared here", prettyChars); checkOverridenDtor(sc, f, dd => dd.type.toTypeFunction().trust > TRUST.system, "@system"); @@ -1427,6 +1427,20 @@ extern (C++) abstract class Expression : ASTNode return true; } } + else if (f.isSafe() && f.safetyViolation) + { + // for dip1000 by default transition, print deprecations for calling functions that will become `@system` + if (sc.func.isSafeBypassingInference()) + { + .deprecation(this.loc, "`@safe` function `%s` calling `%s`", sc.func.toChars(), f.toChars()); + errorSupplementalInferredSafety(f, 10, true); + } + else if (!sc.func.safetyViolation) + { + import dmd.func : AttributeViolation; + sc.func.safetyViolation = new AttributeViolation(this.loc, null, f, null); + } + } return false; } @@ -5761,7 +5775,7 @@ extern (C++) final class DelegatePtrExp : UnaExp override Expression modifiableLvalue(Scope* sc, Expression e) { - if (sc.func.setUnsafe(false, this.loc, "cannot modify delegate pointer in `@safe` code `%s`", this)) + if (sc.setUnsafe(false, this.loc, "cannot modify delegate pointer in `@safe` code `%s`", this)) { return ErrorExp.get(); } @@ -5799,7 +5813,7 @@ extern (C++) final class DelegateFuncptrExp : UnaExp override Expression modifiableLvalue(Scope* sc, Expression e) { - if (sc.func.setUnsafe(false, this.loc, "cannot modify delegate function pointer in `@safe` code `%s`", this)) + if (sc.setUnsafe(false, this.loc, "cannot modify delegate function pointer in `@safe` code `%s`", this)) { return ErrorExp.get(); } diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h index 330dcdb77ec..9ab1cab9877 100644 --- a/gcc/d/dmd/expression.h +++ b/gcc/d/dmd/expression.h @@ -90,9 +90,9 @@ public: virtual Expression *syntaxCopy(); // kludge for template.isExpression() - DYNCAST dyncast() const { return DYNCAST_EXPRESSION; } + DYNCAST dyncast() const override final { return DYNCAST_EXPRESSION; } - const char *toChars() const; + const char *toChars() const override; void error(const char *format, ...) const; void warning(const char *format, ...) const; void deprecation(const char *format, ...) const; @@ -206,6 +206,8 @@ public: ShrAssignExp* isShrAssignExp(); UshrAssignExp* isUshrAssignExp(); CatAssignExp* isCatAssignExp(); + CatElemAssignExp* isCatElemAssignExp(); + CatDcharAssignExp* isCatDcharAssignExp(); AddExp* isAddExp(); MinExp* isMinExp(); CatExp* isCatExp(); @@ -238,71 +240,71 @@ public: BinExp* isBinExp(); BinAssignExp* isBinAssignExp(); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class IntegerExp : public Expression +class IntegerExp final : public Expression { public: dinteger_t value; static IntegerExp *create(const Loc &loc, dinteger_t value, Type *type); static void emplace(UnionExp *pue, const Loc &loc, dinteger_t value, Type *type); - bool equals(const RootObject *o) const; - dinteger_t toInteger(); - real_t toReal(); - real_t toImaginary(); - complex_t toComplex(); - Optional toBool(); - Expression *toLvalue(Scope *sc, Expression *e); - void accept(Visitor *v) { v->visit(this); } + bool equals(const RootObject *o) const override; + dinteger_t toInteger() override; + real_t toReal() override; + real_t toImaginary() override; + complex_t toComplex() override; + Optional toBool() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + void accept(Visitor *v) override { v->visit(this); } dinteger_t getInteger() { return value; } void setInteger(dinteger_t value); template static IntegerExp literal(); }; -class ErrorExp : public Expression +class ErrorExp final : public Expression { public: - Expression *toLvalue(Scope *sc, Expression *e); - void accept(Visitor *v) { v->visit(this); } + Expression *toLvalue(Scope *sc, Expression *e) override; + void accept(Visitor *v) override { v->visit(this); } static ErrorExp *errorexp; // handy shared value }; -class RealExp : public Expression +class RealExp final : public Expression { public: real_t value; static RealExp *create(const Loc &loc, real_t value, Type *type); static void emplace(UnionExp *pue, const Loc &loc, real_t value, Type *type); - bool equals(const RootObject *o) const; - dinteger_t toInteger(); - uinteger_t toUInteger(); - real_t toReal(); - real_t toImaginary(); - complex_t toComplex(); - Optional toBool(); - void accept(Visitor *v) { v->visit(this); } + bool equals(const RootObject *o) const override; + dinteger_t toInteger() override; + uinteger_t toUInteger() override; + real_t toReal() override; + real_t toImaginary() override; + complex_t toComplex() override; + Optional toBool() override; + void accept(Visitor *v) override { v->visit(this); } }; -class ComplexExp : public Expression +class ComplexExp final : public Expression { public: complex_t value; static ComplexExp *create(const Loc &loc, complex_t value, Type *type); static void emplace(UnionExp *pue, const Loc &loc, complex_t value, Type *type); - bool equals(const RootObject *o) const; - dinteger_t toInteger(); - uinteger_t toUInteger(); - real_t toReal(); - real_t toImaginary(); - complex_t toComplex(); - Optional toBool(); - void accept(Visitor *v) { v->visit(this); } + bool equals(const RootObject *o) const override; + dinteger_t toInteger() override; + uinteger_t toUInteger() override; + real_t toReal() override; + real_t toImaginary() override; + complex_t toComplex() override; + Optional toBool() override; + void accept(Visitor *v) override { v->visit(this); } }; class IdentifierExp : public Expression @@ -311,27 +313,27 @@ public: Identifier *ident; static IdentifierExp *create(const Loc &loc, Identifier *ident); - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - void accept(Visitor *v) { v->visit(this); } + bool isLvalue() override final; + Expression *toLvalue(Scope *sc, Expression *e) override final; + void accept(Visitor *v) override { v->visit(this); } }; -class DollarExp : public IdentifierExp +class DollarExp final : public IdentifierExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class DsymbolExp : public Expression +class DsymbolExp final : public Expression { public: Dsymbol *s; bool hasOverloads; - DsymbolExp *syntaxCopy(); - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - void accept(Visitor *v) { v->visit(this); } + DsymbolExp *syntaxCopy() override; + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + void accept(Visitor *v) override { v->visit(this); } }; class ThisExp : public Expression @@ -339,30 +341,30 @@ class ThisExp : public Expression public: VarDeclaration *var; - ThisExp *syntaxCopy(); - Optional toBool(); - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); + ThisExp *syntaxCopy() override; + Optional toBool() override; + bool isLvalue() override final; + Expression *toLvalue(Scope *sc, Expression *e) override final; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class SuperExp : public ThisExp +class SuperExp final : public ThisExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class NullExp : public Expression +class NullExp final : public Expression { public: - bool equals(const RootObject *o) const; - Optional toBool(); - StringExp *toStringExp(); - void accept(Visitor *v) { v->visit(this); } + bool equals(const RootObject *o) const override; + Optional toBool() override; + StringExp *toStringExp() override; + void accept(Visitor *v) override { v->visit(this); } }; -class StringExp : public Expression +class StringExp final : public Expression { public: void *string; // char, wchar, or dchar data @@ -375,23 +377,23 @@ public: static StringExp *create(const Loc &loc, const char *s); static StringExp *create(const Loc &loc, const void *s, d_size_t len); static void emplace(UnionExp *pue, const Loc &loc, const char *s); - bool equals(const RootObject *o) const; + bool equals(const RootObject *o) const override; char32_t getCodeUnit(d_size_t i) const; void setCodeUnit(d_size_t i, char32_t c); - StringExp *toStringExp(); + StringExp *toStringExp() override; StringExp *toUTF8(Scope *sc); - Optional toBool(); - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - Expression *modifiableLvalue(Scope *sc, Expression *e); - void accept(Visitor *v) { v->visit(this); } + Optional toBool() override; + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + Expression *modifiableLvalue(Scope *sc, Expression *e) override; + void accept(Visitor *v) override { v->visit(this); } size_t numberOfCodeUnits(int tynto = 0) const; void writeTo(void* dest, bool zero, int tyto = 0) const; }; // Tuple -class TupleExp : public Expression +class TupleExp final : public Expression { public: Expression *e0; // side-effect part @@ -405,13 +407,13 @@ public: Expressions *exps; static TupleExp *create(const Loc &loc, Expressions *exps); - TupleExp *syntaxCopy(); - bool equals(const RootObject *o) const; + TupleExp *syntaxCopy() override; + bool equals(const RootObject *o) const override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ArrayLiteralExp : public Expression +class ArrayLiteralExp final : public Expression { public: Expression *basis; @@ -420,31 +422,31 @@ public: static ArrayLiteralExp *create(const Loc &loc, Expressions *elements); static void emplace(UnionExp *pue, const Loc &loc, Expressions *elements); - ArrayLiteralExp *syntaxCopy(); - bool equals(const RootObject *o) const; + ArrayLiteralExp *syntaxCopy() override; + bool equals(const RootObject *o) const override; Expression *getElement(d_size_t i); // use opIndex instead Expression *opIndex(d_size_t i); - Optional toBool(); - StringExp *toStringExp(); + Optional toBool() override; + StringExp *toStringExp() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class AssocArrayLiteralExp : public Expression +class AssocArrayLiteralExp final : public Expression { public: Expressions *keys; Expressions *values; OwnedBy ownedByCtfe; - bool equals(const RootObject *o) const; - AssocArrayLiteralExp *syntaxCopy(); - Optional toBool(); + bool equals(const RootObject *o) const override; + AssocArrayLiteralExp *syntaxCopy() override; + Optional toBool() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class StructLiteralExp : public Expression +class StructLiteralExp final : public Expression { public: StructDeclaration *sd; // which aggregate this is for @@ -475,50 +477,50 @@ public: OwnedBy ownedByCtfe; static StructLiteralExp *create(const Loc &loc, StructDeclaration *sd, void *elements, Type *stype = NULL); - bool equals(const RootObject *o) const; - StructLiteralExp *syntaxCopy(); + bool equals(const RootObject *o) const override; + StructLiteralExp *syntaxCopy() override; Expression *getField(Type *type, unsigned offset); int getFieldIndex(Type *type, unsigned offset); - Expression *addDtorHook(Scope *sc); - Expression *toLvalue(Scope *sc, Expression *e); + Expression *addDtorHook(Scope *sc) override; + Expression *toLvalue(Scope *sc, Expression *e) override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeExp : public Expression +class TypeExp final : public Expression { public: - TypeExp *syntaxCopy(); - bool checkType(); - bool checkValue(); - void accept(Visitor *v) { v->visit(this); } + TypeExp *syntaxCopy() override; + bool checkType() override; + bool checkValue() override; + void accept(Visitor *v) override { v->visit(this); } }; -class ScopeExp : public Expression +class ScopeExp final : public Expression { public: ScopeDsymbol *sds; - ScopeExp *syntaxCopy(); - bool checkType(); - bool checkValue(); - void accept(Visitor *v) { v->visit(this); } + ScopeExp *syntaxCopy() override; + bool checkType() override; + bool checkValue() override; + void accept(Visitor *v) override { v->visit(this); } }; -class TemplateExp : public Expression +class TemplateExp final : public Expression { public: TemplateDeclaration *td; FuncDeclaration *fd; - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - bool checkType(); - bool checkValue(); - void accept(Visitor *v) { v->visit(this); } + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + bool checkType() override; + bool checkValue() override; + void accept(Visitor *v) override { v->visit(this); } }; -class NewExp : public Expression +class NewExp final : public Expression { public: /* newtype(arguments) @@ -534,12 +536,12 @@ public: bool thrownew; // this NewExp is the expression of a ThrowStatement static NewExp *create(const Loc &loc, Expression *thisexp, Type *newtype, Expressions *arguments); - NewExp *syntaxCopy(); + NewExp *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class NewAnonClassExp : public Expression +class NewAnonClassExp final : public Expression { public: /* class baseclasses { } (arguments) @@ -548,8 +550,8 @@ public: ClassDeclaration *cd; // class being instantiated Expressions *arguments; // Array of Expression's to call class constructor - NewAnonClassExp *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + NewAnonClassExp *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; class SymbolExp : public Expression @@ -559,64 +561,64 @@ public: Dsymbol *originalScope; bool hasOverloads; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; // Offset from symbol -class SymOffExp : public SymbolExp +class SymOffExp final : public SymbolExp { public: dinteger_t offset; - Optional toBool(); + Optional toBool() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; // Variable -class VarExp : public SymbolExp +class VarExp final : public SymbolExp { public: bool delegateWasExtracted; static VarExp *create(const Loc &loc, Declaration *var, bool hasOverloads = true); - bool equals(const RootObject *o) const; - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - Expression *modifiableLvalue(Scope *sc, Expression *e); + bool equals(const RootObject *o) const override; + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + Expression *modifiableLvalue(Scope *sc, Expression *e) override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; // Overload Set -class OverExp : public Expression +class OverExp final : public Expression { public: OverloadSet *vars; - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - void accept(Visitor *v) { v->visit(this); } + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + void accept(Visitor *v) override { v->visit(this); } }; // Function/Delegate literal -class FuncExp : public Expression +class FuncExp final : public Expression { public: FuncLiteralDeclaration *fd; TemplateDeclaration *td; TOK tok; - bool equals(const RootObject *o) const; - FuncExp *syntaxCopy(); - const char *toChars() const; - bool checkType(); - bool checkValue(); + bool equals(const RootObject *o) const override; + FuncExp *syntaxCopy() override; + const char *toChars() const override; + bool checkType() override; + bool checkValue() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; // Declaration of a symbol @@ -624,44 +626,44 @@ public: // D grammar allows declarations only as statements. However in AST representation // it can be part of any expression. This is used, for example, during internal // syntax re-writes to inject hidden symbols. -class DeclarationExp : public Expression +class DeclarationExp final : public Expression { public: Dsymbol *declaration; - DeclarationExp *syntaxCopy(); + DeclarationExp *syntaxCopy() override; - bool hasCode(); + bool hasCode() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeidExp : public Expression +class TypeidExp final : public Expression { public: RootObject *obj; - TypeidExp *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + TypeidExp *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; -class TraitsExp : public Expression +class TraitsExp final : public Expression { public: Identifier *ident; Objects *args; - TraitsExp *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + TraitsExp *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; -class HaltExp : public Expression +class HaltExp final : public Expression { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class IsExp : public Expression +class IsExp final : public Expression { public: /* is(targ id tok tspec) @@ -674,8 +676,8 @@ public: TOK tok; // ':' or '==' TOK tok2; // 'struct', 'union', etc. - IsExp *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + IsExp *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; /****************************************************************/ @@ -686,11 +688,11 @@ public: Expression *e1; Type *att1; // Save alias this type to detect recursion - UnaExp *syntaxCopy(); + UnaExp *syntaxCopy() override; Expression *incompatibleTypes(); - Expression *resolveLoc(const Loc &loc, Scope *sc); + Expression *resolveLoc(const Loc &loc, Scope *sc) override final; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; class BinExp : public Expression @@ -702,56 +704,56 @@ public: Type *att1; // Save alias this type to detect recursion Type *att2; // Save alias this type to detect recursion - BinExp *syntaxCopy(); + BinExp *syntaxCopy() override; Expression *incompatibleTypes(); Expression *reorderSettingAAElem(Scope *sc); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; class BinAssignExp : public BinExp { public: - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *ex); - Expression *modifiableLvalue(Scope *sc, Expression *e); - void accept(Visitor *v) { v->visit(this); } + bool isLvalue() override final; + Expression *toLvalue(Scope *sc, Expression *ex) override final; + Expression *modifiableLvalue(Scope *sc, Expression *e) override final; + void accept(Visitor *v) override { v->visit(this); } }; /****************************************************************/ -class MixinExp : public UnaExp +class MixinExp final : public UnaExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ImportExp : public UnaExp +class ImportExp final : public UnaExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class AssertExp : public UnaExp +class AssertExp final : public UnaExp { public: Expression *msg; - AssertExp *syntaxCopy(); + AssertExp *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ThrowExp : public UnaExp +class ThrowExp final : public UnaExp { public: - ThrowExp *syntaxCopy(); + ThrowExp *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class DotIdExp : public UnaExp +class DotIdExp final : public UnaExp { public: Identifier *ident; @@ -760,44 +762,44 @@ public: bool arrow; // ImportC: if -> instead of . static DotIdExp *create(const Loc &loc, Expression *e, Identifier *ident); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class DotTemplateExp : public UnaExp +class DotTemplateExp final : public UnaExp { public: TemplateDeclaration *td; - bool checkType(); - bool checkValue(); - void accept(Visitor *v) { v->visit(this); } + bool checkType() override; + bool checkValue() override; + void accept(Visitor *v) override { v->visit(this); } }; -class DotVarExp : public UnaExp +class DotVarExp final : public UnaExp { public: Declaration *var; bool hasOverloads; - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - Expression *modifiableLvalue(Scope *sc, Expression *e); - void accept(Visitor *v) { v->visit(this); } + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + Expression *modifiableLvalue(Scope *sc, Expression *e) override; + void accept(Visitor *v) override { v->visit(this); } }; -class DotTemplateInstanceExp : public UnaExp +class DotTemplateInstanceExp final : public UnaExp { public: TemplateInstance *ti; - DotTemplateInstanceExp *syntaxCopy(); + DotTemplateInstanceExp *syntaxCopy() override; bool findTempDecl(Scope *sc); - bool checkType(); - bool checkValue(); - void accept(Visitor *v) { v->visit(this); } + bool checkType() override; + bool checkValue() override; + void accept(Visitor *v) override { v->visit(this); } }; -class DelegateExp : public UnaExp +class DelegateExp final : public UnaExp { public: FuncDeclaration *func; @@ -805,18 +807,18 @@ public: VarDeclaration *vthis2; // container for multi-context - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class DotTypeExp : public UnaExp +class DotTypeExp final : public UnaExp { public: Dsymbol *sym; // symbol that represents a type - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class CallExp : public UnaExp +class CallExp final : public UnaExp { public: Expressions *arguments; // function arguments @@ -831,76 +833,76 @@ public: static CallExp *create(const Loc &loc, Expression *e, Expression *earg1); static CallExp *create(const Loc &loc, FuncDeclaration *fd, Expression *earg1); - CallExp *syntaxCopy(); - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - Expression *addDtorHook(Scope *sc); + CallExp *syntaxCopy() override; + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + Expression *addDtorHook(Scope *sc) override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class AddrExp : public UnaExp +class AddrExp final : public UnaExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class PtrExp : public UnaExp +class PtrExp final : public UnaExp { public: - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - Expression *modifiableLvalue(Scope *sc, Expression *e); + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + Expression *modifiableLvalue(Scope *sc, Expression *e) override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class NegExp : public UnaExp +class NegExp final : public UnaExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class UAddExp : public UnaExp +class UAddExp final : public UnaExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ComExp : public UnaExp +class ComExp final : public UnaExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class NotExp : public UnaExp +class NotExp final : public UnaExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class DeleteExp : public UnaExp +class DeleteExp final : public UnaExp { public: bool isRAII; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class CastExp : public UnaExp +class CastExp final : public UnaExp { public: // Possible to cast to one type while painting to another type Type *to; // type to cast to unsigned char mod; // MODxxxxx - CastExp *syntaxCopy(); - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); + CastExp *syntaxCopy() override; + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class VectorExp : public UnaExp +class VectorExp final : public UnaExp { public: TypeVector *to; // the target vector type before semantic() @@ -909,19 +911,19 @@ public: static VectorExp *create(const Loc &loc, Expression *e, Type *t); static void emplace(UnionExp *pue, const Loc &loc, Expression *e, Type *t); - VectorExp *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + VectorExp *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; -class VectorArrayExp : public UnaExp +class VectorArrayExp final : public UnaExp { public: - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - void accept(Visitor *v) { v->visit(this); } + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + void accept(Visitor *v) override { v->visit(this); } }; -class SliceExp : public UnaExp +class SliceExp final : public UnaExp { public: Expression *upr; // NULL if implicit 0 @@ -931,115 +933,115 @@ public: bool lowerIsLessThanUpper; // true if lwr <= upr bool arrayop; // an array operation, rather than a slice - SliceExp *syntaxCopy(); - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - Expression *modifiableLvalue(Scope *sc, Expression *e); - Optional toBool(); + SliceExp *syntaxCopy() override; + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + Expression *modifiableLvalue(Scope *sc, Expression *e) override; + Optional toBool() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ArrayLengthExp : public UnaExp +class ArrayLengthExp final : public UnaExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class IntervalExp : public Expression +class IntervalExp final : public Expression { public: Expression *lwr; Expression *upr; - IntervalExp *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + IntervalExp *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; -class DelegatePtrExp : public UnaExp +class DelegatePtrExp final : public UnaExp { public: - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - Expression *modifiableLvalue(Scope *sc, Expression *e); - void accept(Visitor *v) { v->visit(this); } + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + Expression *modifiableLvalue(Scope *sc, Expression *e) override; + void accept(Visitor *v) override { v->visit(this); } }; -class DelegateFuncptrExp : public UnaExp +class DelegateFuncptrExp final : public UnaExp { public: - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - Expression *modifiableLvalue(Scope *sc, Expression *e); - void accept(Visitor *v) { v->visit(this); } + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + Expression *modifiableLvalue(Scope *sc, Expression *e) override; + void accept(Visitor *v) override { v->visit(this); } }; // e1[a0,a1,a2,a3,...] -class ArrayExp : public UnaExp +class ArrayExp final : public UnaExp { public: Expressions *arguments; // Array of Expression's size_t currentDimension; // for opDollar VarDeclaration *lengthVar; - ArrayExp *syntaxCopy(); - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); + ArrayExp *syntaxCopy() override; + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; /****************************************************************/ -class DotExp : public BinExp +class DotExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class CommaExp : public BinExp +class CommaExp final : public BinExp { public: bool isGenerated; bool allowCommaExp; - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - Expression *modifiableLvalue(Scope *sc, Expression *e); - Optional toBool(); - Expression *addDtorHook(Scope *sc); - void accept(Visitor *v) { v->visit(this); } + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + Expression *modifiableLvalue(Scope *sc, Expression *e) override; + Optional toBool() override; + Expression *addDtorHook(Scope *sc) override; + void accept(Visitor *v) override { v->visit(this); } }; -class IndexExp : public BinExp +class IndexExp final : public BinExp { public: VarDeclaration *lengthVar; bool modifiable; bool indexIsInBounds; // true if 0 <= e2 && e2 <= e1.length - 1 - IndexExp *syntaxCopy(); - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - Expression *modifiableLvalue(Scope *sc, Expression *e); + IndexExp *syntaxCopy() override; + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + Expression *modifiableLvalue(Scope *sc, Expression *e) override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; /* For both i++ and i-- */ -class PostExp : public BinExp +class PostExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; /* For both ++i and --i */ -class PreExp : public UnaExp +class PreExp final : public UnaExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; enum class MemorySet @@ -1054,245 +1056,257 @@ class AssignExp : public BinExp public: MemorySet memset; - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *ex); + bool isLvalue() override final; + Expression *toLvalue(Scope *sc, Expression *ex) override final; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ConstructExp : public AssignExp +class ConstructExp final : public AssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class BlitExp : public AssignExp +class BlitExp final : public AssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class AddAssignExp : public BinAssignExp +class AddAssignExp final : public BinAssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class MinAssignExp : public BinAssignExp +class MinAssignExp final : public BinAssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class MulAssignExp : public BinAssignExp +class MulAssignExp final : public BinAssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class DivAssignExp : public BinAssignExp +class DivAssignExp final : public BinAssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ModAssignExp : public BinAssignExp +class ModAssignExp final : public BinAssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class AndAssignExp : public BinAssignExp +class AndAssignExp final : public BinAssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class OrAssignExp : public BinAssignExp +class OrAssignExp final : public BinAssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class XorAssignExp : public BinAssignExp +class XorAssignExp final : public BinAssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class PowAssignExp : public BinAssignExp +class PowAssignExp final : public BinAssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ShlAssignExp : public BinAssignExp +class ShlAssignExp final : public BinAssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ShrAssignExp : public BinAssignExp +class ShrAssignExp final : public BinAssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class UshrAssignExp : public BinAssignExp +class UshrAssignExp final : public BinAssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; class CatAssignExp : public BinAssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class AddExp : public BinExp +class CatElemAssignExp final : public CatAssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class MinExp : public BinExp +class CatDcharAssignExp final : public CatAssignExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class CatExp : public BinExp +class AddExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class MulExp : public BinExp +class MinExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class DivExp : public BinExp +class CatExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ModExp : public BinExp +class MulExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class PowExp : public BinExp +class DivExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ShlExp : public BinExp +class ModExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ShrExp : public BinExp +class PowExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class UshrExp : public BinExp +class ShlExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class AndExp : public BinExp +class ShrExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class OrExp : public BinExp +class UshrExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class XorExp : public BinExp +class AndExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class LogicalExp : public BinExp +class OrExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class CmpExp : public BinExp +class XorExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class InExp : public BinExp +class LogicalExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class RemoveExp : public BinExp +class CmpExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } +}; + +class InExp final : public BinExp +{ +public: + void accept(Visitor *v) override { v->visit(this); } +}; + +class RemoveExp final : public BinExp +{ +public: + void accept(Visitor *v) override { v->visit(this); } }; // == and != -class EqualExp : public BinExp +class EqualExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; // is and !is -class IdentityExp : public BinExp +class IdentityExp final : public BinExp { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; /****************************************************************/ -class CondExp : public BinExp +class CondExp final : public BinExp { public: Expression *econd; - CondExp *syntaxCopy(); - bool isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); - Expression *modifiableLvalue(Scope *sc, Expression *e); + CondExp *syntaxCopy() override; + bool isLvalue() override; + Expression *toLvalue(Scope *sc, Expression *e) override; + Expression *modifiableLvalue(Scope *sc, Expression *e) override; void hookDtors(Scope *sc); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class GenericExp : Expression +class GenericExp final : Expression { Expression *cntlExp; Types *types; Expressions *exps; - GenericExp *syntaxCopy(); + GenericExp *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; /****************************************************************/ @@ -1300,42 +1314,42 @@ class GenericExp : Expression class DefaultInitExp : public Expression { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class FileInitExp : public DefaultInitExp +class FileInitExp final : public DefaultInitExp { public: - Expression *resolveLoc(const Loc &loc, Scope *sc); - void accept(Visitor *v) { v->visit(this); } + Expression *resolveLoc(const Loc &loc, Scope *sc) override; + void accept(Visitor *v) override { v->visit(this); } }; -class LineInitExp : public DefaultInitExp +class LineInitExp final : public DefaultInitExp { public: - Expression *resolveLoc(const Loc &loc, Scope *sc); - void accept(Visitor *v) { v->visit(this); } + Expression *resolveLoc(const Loc &loc, Scope *sc) override; + void accept(Visitor *v) override { v->visit(this); } }; -class ModuleInitExp : public DefaultInitExp +class ModuleInitExp final : public DefaultInitExp { public: - Expression *resolveLoc(const Loc &loc, Scope *sc); - void accept(Visitor *v) { v->visit(this); } + Expression *resolveLoc(const Loc &loc, Scope *sc) override; + void accept(Visitor *v) override { v->visit(this); } }; -class FuncInitExp : public DefaultInitExp +class FuncInitExp final : public DefaultInitExp { public: - Expression *resolveLoc(const Loc &loc, Scope *sc); - void accept(Visitor *v) { v->visit(this); } + Expression *resolveLoc(const Loc &loc, Scope *sc) override; + void accept(Visitor *v) override { v->visit(this); } }; -class PrettyFuncInitExp : public DefaultInitExp +class PrettyFuncInitExp final : public DefaultInitExp { public: - Expression *resolveLoc(const Loc &loc, Scope *sc); - void accept(Visitor *v) { v->visit(this); } + Expression *resolveLoc(const Loc &loc, Scope *sc) override; + void accept(Visitor *v) override { v->visit(this); } }; /****************************************************************/ @@ -1396,10 +1410,10 @@ private: /****************************************************************/ -class ObjcClassReferenceExp : public Expression +class ObjcClassReferenceExp final : public Expression { public: ClassDeclaration* classDeclaration; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index b65b0ed1375..cb720271ae7 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -4989,7 +4989,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars()); err = true; } - if (tf.trust <= TRUST.system && sc.func.setUnsafe()) + if (tf.trust <= TRUST.system && sc.setUnsafe()) { exp.error("`@safe` %s `%s` cannot call `@system` %s `%s`", sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars()); @@ -5995,7 +5995,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor auto idxReserved = FileName.findReservedChar(namez); if (idxReserved != size_t.max) { - e.error("`%s` is not a valid filename on this platform", se.toChars()); + e.error("`%s` is not a valid filename on this platform", se.toChars()); e.errorSupplemental("Character `'%c'` is reserved and cannot be used", namez[idxReserved]); return setError(); } @@ -6543,8 +6543,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor RootObject o = (*tup.objects)[i]; Expression e; Declaration var; - if (o.dyncast() == DYNCAST.expression) + switch (o.dyncast()) with (DYNCAST) { + case expression: e = cast(Expression)o; if (auto se = e.isDsymbolExp()) var = se.s.isDeclaration(); @@ -6553,9 +6554,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // Exempt functions for backwards compatibility reasons. // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1 var = ve.var; - } - else if (o.dyncast() == DYNCAST.dsymbol) - { + break; + case dsymbol: Dsymbol s = cast(Dsymbol) o; Declaration d = s.isDeclaration(); if (!d || d.isFuncDeclaration()) @@ -6564,13 +6564,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor e = new DsymbolExp(exp.loc, s); else var = d; - } - else if (o.dyncast() == DYNCAST.type) - { + break; + case type: e = new TypeExp(exp.loc, cast(Type)o); - } - else - { + break; + default: exp.error("`%s` is not an expression", o.toChars()); return setError(); } @@ -6894,9 +6892,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor * because it might end up being a pointer to undefined * memory. */ - if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_)) + if (1) { - if (sc.func.setUnsafe(false, exp.loc, + if (sc.setUnsafe(false, exp.loc, "cannot take address of lazy parameter `%s` in `@safe` function `%s`", ve, sc.func)) { setError(); @@ -7045,7 +7043,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_)) { - sc.func.setUnsafe(false, exp.loc, + sc.setUnsafe(false, exp.loc, "`this` reference necessary to take address of member `%s` in `@safe` function `%s`", f, sc.func); } @@ -7552,10 +7550,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } // Check for unsafe casts - if (!sc.intypeof && - !(sc.flags & SCOPE.debug_) && - !isSafeCast(ex, t1b, tob) && - (!sc.func && sc.stc & STC.safe || sc.func && sc.func.setUnsafe())) + if (!isSafeCast(ex, t1b, tob) && + (!sc.func && sc.stc & STC.safe || sc.setUnsafe())) { exp.error("cast from `%s` to `%s` not allowed in safe code", exp.e1.type.toChars(), exp.to.toChars()); return setError(); @@ -7816,11 +7812,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return setError(); } - if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_)) - { - if (sc.func.setUnsafe(false, exp.loc, "pointer slicing not allowed in safe functions")) - return setError(); - } + if (sc.setUnsafe(false, exp.loc, "pointer slicing not allowed in safe functions")) + return setError(); } else if (t1b.ty == Tarray) { @@ -8328,11 +8321,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (exp.e2.op == EXP.int64 && exp.e2.toInteger() == 0) { } - else if (sc.func && !(sc.flags & SCOPE.debug_)) + else if (sc.setUnsafe(false, exp.loc, "`@safe` function `%s` cannot index pointer `%s`", sc.func, exp.e1)) { - if (sc.func.setUnsafe(false, exp.loc, - "`@safe` function `%s` cannot index pointer `%s`", sc.func, exp.e1)) - return setError(); + return setError(); } exp.type = (cast(TypeNext)t1b).next; break; @@ -9729,11 +9720,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } if (t1n.toBasetype.ty == Tvoid && t2n.toBasetype.ty == Tvoid) { - if (!sc.intypeof && sc.func && !(sc.flags & SCOPE.debug_)) - { - if (sc.func.setUnsafe(false, exp.loc, "cannot copy `void[]` to `void[]` in `@safe` code")) - return setError(); - } + if (sc.setUnsafe(false, exp.loc, "cannot copy `void[]` to `void[]` in `@safe` code")) + return setError(); } } else @@ -13089,9 +13077,8 @@ bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v) v.storage_class &= ~STC.maybescope; v.doNotInferScope = true; if (global.params.useDIP1000 != FeatureState.enabled && - !(sc.flags & SCOPE.debug_) && !(v.storage_class & STC.temp) && - sc.func.setUnsafe()) + sc.setUnsafe()) { exp.error("cannot take address of %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars()); return false; @@ -13304,7 +13291,7 @@ private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions { if ((!stype.alignment.isDefault() && stype.alignment.get() < target.ptrsize || (v.offset & (target.ptrsize - 1))) && - (sc.func && sc.func.setUnsafe(false, loc, + (sc.setUnsafe(false, loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code", sd, v))) { return false; diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index e53a540bb12..04039483930 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -346,7 +346,7 @@ extern (C++) class FuncDeclaration : Declaration /// In case of failed `@safe` inference, store the error that made the function `@system` for /// better diagnostics - private AttributeViolation* safetyViolation; + AttributeViolation* safetyViolation; /// Function flags: A collection of boolean packed for memory efficiency /// See the `FUNCFLAG` enum @@ -713,6 +713,44 @@ extern (C++) class FuncDeclaration : Declaration } } } + if (_linkage == LINK.cpp && bestvi != -1) + { + StorageClass stc = 0; + FuncDeclaration fdv = (*vtbl)[bestvi].isFuncDeclaration(); + assert(fdv && fdv.ident == ident); + if (type.covariant(fdv.type, &stc, /*cppCovariant=*/true) == Covariant.no) + { + /* https://issues.dlang.org/show_bug.cgi?id=22351 + * Under D rules, `type` and `fdv.type` are covariant, but under C++ rules, they are not. + * For now, continue to allow D covariant rules to apply when `override` has been used, + * but issue a deprecation warning that this behaviour will change in the future. + * Otherwise, follow the C++ covariant rules, which will create a new vtable entry. + */ + if (isOverride()) + { + /* @@@DEPRECATED_2.110@@@ + * After deprecation period has ended, be sure to remove this entire `LINK.cpp` branch, + * but also the `cppCovariant` parameter from Type.covariant, and update the function + * so that both `LINK.cpp` covariant conditions within are always checked. + */ + .deprecation(loc, "overriding `extern(C++)` function `%s%s` with `const` qualified function `%s%s%s` is deprecated", + fdv.toPrettyChars(), fdv.type.toTypeFunction().parameterList.parametersTypeToChars(), + toPrettyChars(), type.toTypeFunction().parameterList.parametersTypeToChars(), type.modToChars()); + + const char* where = type.isNaked() ? "parameters" : "type"; + deprecationSupplemental(loc, "Either remove `override`, or adjust the `const` qualifiers of the " + ~ "overriding function %s", where); + } + else + { + // Treat as if Covariant.no + mismatchvi = bestvi; + mismatchstc = stc; + mismatch = fdv; + bestvi = -1; + } + } + } if (bestvi == -1 && mismatch) { //type.print(); @@ -1447,7 +1485,7 @@ extern (C++) class FuncDeclaration : Declaration { flags &= ~FUNCFLAG.safetyInprocess; type.toTypeFunction().trust = TRUST.system; - if (!gag && !safetyViolation && (fmt || arg0)) + if (fmt || arg0) safetyViolation = new AttributeViolation(loc, fmt, arg0, arg1); if (fes) @@ -4321,6 +4359,50 @@ extern (C++) final class NewDeclaration : FuncDeclaration } } +/************************************** + * A statement / expression in this scope is not `@safe`, + * so mark the enclosing function as `@system` + * + * Params: + * sc = scope that the unsafe statement / expression is in + * gag = surpress error message (used in escape.d) + * loc = location of error + * fmt = printf-style format string + * arg0 = (optional) argument for first %s format specifier + * arg1 = (optional) argument for second %s format specifier + * Returns: whether there's a safe error + */ +bool setUnsafe(Scope* sc, + bool gag = false, Loc loc = Loc.init, const(char)* fmt = null, RootObject arg0 = null, RootObject arg1 = null) +{ + // TODO: + // For @system variables, unsafe initializers at global scope should mark + // the variable @system, see https://dlang.org/dips/1035 + + if (!sc.func) + return false; + + if (sc.intypeof) + return false; // typeof(cast(int*)0) is safe + + if (sc.flags & SCOPE.debug_) // debug {} scopes are permissive + return false; + + if (sc.flags & SCOPE.compile) // __traits(compiles, x) + { + if (sc.func.isSafeBypassingInference()) + { + // Message wil be gagged, but still call error() to update global.errors and for + // -verrors=spec + .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : ""); + return true; + } + return false; + } + + return sc.func.setUnsafe(gag, loc, fmt, arg0, arg1); +} + /// Stores a reason why a function failed to infer a function attribute like `@safe` or `pure` /// /// Has two modes: @@ -4329,7 +4411,7 @@ extern (C++) final class NewDeclaration : FuncDeclaration /// that function might recursively also have a `AttributeViolation`. This way, in case /// of a big call stack, the error can go down all the way to the root cause. /// The `FunctionDeclaration` is then stored in `arg0` and `fmtStr` must be `null`. -private struct AttributeViolation +struct AttributeViolation { /// location of error Loc loc = Loc.init; @@ -4345,21 +4427,25 @@ private struct AttributeViolation /// Params: /// fd = function to check /// maxDepth = up to how many functions deep to report errors -void errorSupplementalInferredSafety(FuncDeclaration fd, int maxDepth) +/// deprecation = print deprecations instead of errors +void errorSupplementalInferredSafety(FuncDeclaration fd, int maxDepth, bool deprecation) { + auto errorFunc = deprecation ? &deprecationSupplemental : &errorSupplemental; if (auto s = fd.safetyViolation) { if (s.fmtStr) { - errorSupplemental(s.loc, "which was inferred `@system` because of:"); - errorSupplemental(s.loc, s.fmtStr, s.arg0 ? s.arg0.toChars() : "", s.arg1 ? s.arg1.toChars() : ""); + errorFunc(s.loc, deprecation ? + "which would be `@system` because of:" : + "which was inferred `@system` because of:"); + errorFunc(s.loc, s.fmtStr, s.arg0 ? s.arg0.toChars() : "", s.arg1 ? s.arg1.toChars() : ""); } else if (FuncDeclaration fd2 = cast(FuncDeclaration) s.arg0) { if (maxDepth > 0) { - errorSupplemental(s.loc, "which calls `%s`", fd2.toPrettyChars()); - errorSupplementalInferredSafety(fd2, maxDepth - 1); + errorFunc(s.loc, "which calls `%s`", fd2.toPrettyChars()); + errorSupplementalInferredSafety(fd2, maxDepth - 1, deprecation); } } } diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d index ba4ccbe5134..3766a0be07d 100644 --- a/gcc/d/dmd/globals.d +++ b/gcc/d/dmd/globals.d @@ -118,6 +118,7 @@ extern (C++) struct Param bool useInline = false; // inline expand functions FeatureState useDIP25; // implement https://wiki.dlang.org/DIP25 FeatureState useDIP1000; // implement https://dlang.org/spec/memory-safe-d.html#scope-return-params + bool fixImmutableConv; // error on unsound immutable conversion - https://github.com/dlang/dmd/pull/14070 bool useDIP1021; // implement https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md bool release; // build release version bool preservePaths; // true means don't strip path from source file @@ -298,7 +299,7 @@ extern (C++) struct Global enum recursionLimit = 500; /// number of recursive template expansions before abort - extern (C++) FileName function(FileName, const(char)* importc_h, ref Array!(const(char)*) cppswitches, out bool) preprocess; + extern (C++) FileName function(FileName, ref const Loc, ref Array!(const(char)*) cppswitches, out bool, OutBuffer* defines) preprocess; nothrow: diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h index 5c164fd484d..07298ddb792 100644 --- a/gcc/d/dmd/globals.h +++ b/gcc/d/dmd/globals.h @@ -20,6 +20,7 @@ template struct Array; class FileManager; +struct Loc; typedef unsigned char Diagnostic; enum @@ -117,6 +118,7 @@ struct Param bool useInline; // inline expand functions FeatureState useDIP25; // implement https://wiki.dlang.org/DIP25 FeatureState useDIP1000; // implement https://dlang.org/spec/memory-safe-d.html#scope-return-params + bool fixImmutableConv; bool useDIP1021; // implement https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md bool release; // build release version bool preservePaths; // true means don't strip path from source file @@ -270,7 +272,7 @@ struct Global FileManager* fileManager; - FileName (*preprocess)(FileName, const char*, Array& cppswitches, bool&); + FileName (*preprocess)(FileName, const Loc&, Array& cppswitches, bool&, OutBuffer&); /* Start gagging. Return the current number of gagged errors */ diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d index fd35e1cf846..fcc9b61b54a 100644 --- a/gcc/d/dmd/hdrgen.d +++ b/gcc/d/dmd/hdrgen.d @@ -3835,26 +3835,24 @@ private void typeToBufferx(Type t, OutBuffer* buf, HdrGenState* hgs) { foreach (id; t.idents) { - if (id.dyncast() == DYNCAST.dsymbol) + switch (id.dyncast()) with (DYNCAST) { + case dsymbol: buf.writeByte('.'); TemplateInstance ti = cast(TemplateInstance)id; ti.dsymbolToBuffer(buf, hgs); - } - else if (id.dyncast() == DYNCAST.expression) - { + break; + case expression: buf.writeByte('['); (cast(Expression)id).expressionToBuffer(buf, hgs); buf.writeByte(']'); - } - else if (id.dyncast() == DYNCAST.type) - { + break; + case type: buf.writeByte('['); typeToBufferx(cast(Type)id, buf, hgs); buf.writeByte(']'); - } - else - { + break; + default: buf.writeByte('.'); buf.writestring(id.toString()); } diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d index ab9528a4f00..4993a9eb1b2 100644 --- a/gcc/d/dmd/id.d +++ b/gcc/d/dmd/id.d @@ -523,6 +523,8 @@ immutable Msgtable[] msgtable = { "show" }, { "push" }, { "pop" }, + { "define" }, + { "undef" }, ]; diff --git a/gcc/d/dmd/identifier.h b/gcc/d/dmd/identifier.h index 4c748beb5d8..fa7a25aaaa1 100644 --- a/gcc/d/dmd/identifier.h +++ b/gcc/d/dmd/identifier.h @@ -13,7 +13,7 @@ #include "root/dcompat.h" #include "root/object.h" -class Identifier : public RootObject +class Identifier final : public RootObject { private: int value; @@ -22,12 +22,11 @@ private: public: static Identifier* create(const char *string); - bool equals(const RootObject *o) const; - const char *toChars() const; + const char *toChars() const override; int getValue() const; bool isAnonymous() const; const char *toHChars2() const; - DYNCAST dyncast() const; + DYNCAST dyncast() const override; static Identifier *generateId(const char *prefix, size_t length, size_t suffix); static Identifier *idPool(const char *s, unsigned len); diff --git a/gcc/d/dmd/import.h b/gcc/d/dmd/import.h index 5e7550e16ec..f749ef5b5f6 100644 --- a/gcc/d/dmd/import.h +++ b/gcc/d/dmd/import.h @@ -17,7 +17,7 @@ struct Scope; class Module; class Package; -class Import : public Dsymbol +class Import final : public Dsymbol { public: /* static import aliasId = pkg1.pkg2.id : alias1 = name1, alias2 = name2; @@ -38,17 +38,17 @@ public: AliasDeclarations aliasdecls; // corresponding AliasDeclarations for alias=name pairs - const char *kind() const; - Visibility visible(); - Import *syntaxCopy(Dsymbol *s); // copy only syntax trees + const char *kind() const override; + Visibility visible() override; + Import *syntaxCopy(Dsymbol *s) override; // copy only syntax trees void load(Scope *sc); - void importAll(Scope *sc); - Dsymbol *toAlias(); - void addMember(Scope *sc, ScopeDsymbol *sds); - void setScope(Scope* sc); - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); - bool overloadInsert(Dsymbol *s); - - Import *isImport() { return this; } - void accept(Visitor *v) { v->visit(this); } + void importAll(Scope *sc) override; + Dsymbol *toAlias() override; + void addMember(Scope *sc, ScopeDsymbol *sds) override; + void setScope(Scope* sc) override; + Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; + bool overloadInsert(Dsymbol *s) override; + + Import *isImport() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/init.d b/gcc/d/dmd/init.d index 179e0b6a5ab..164a5f3e56b 100644 --- a/gcc/d/dmd/init.d +++ b/gcc/d/dmd/init.d @@ -44,7 +44,7 @@ extern (C++) class Initializer : ASTNode Loc loc; InitKind kind; - override DYNCAST dyncast() const nothrow pure + override DYNCAST dyncast() const { return DYNCAST.initializer; } diff --git a/gcc/d/dmd/init.h b/gcc/d/dmd/init.h index 73dc4bba2e4..296c31d1a5e 100644 --- a/gcc/d/dmd/init.h +++ b/gcc/d/dmd/init.h @@ -33,7 +33,9 @@ public: Loc loc; unsigned char kind; - const char *toChars() const; + DYNCAST dyncast() const override { return DYNCAST_INITIALIZER; } + + const char *toChars() const override final; ErrorInitializer *isErrorInitializer(); VoidInitializer *isVoidInitializer(); @@ -42,33 +44,33 @@ public: ExpInitializer *isExpInitializer(); CInitializer *isCInitializer(); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class VoidInitializer : public Initializer +class VoidInitializer final : public Initializer { public: Type *type; // type that this will initialize to - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ErrorInitializer : public Initializer +class ErrorInitializer final : public Initializer { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class StructInitializer : public Initializer +class StructInitializer final : public Initializer { public: Identifiers field; // of Identifier *'s Initializers value; // parallel array of Initializer *'s - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ArrayInitializer : public Initializer +class ArrayInitializer final : public Initializer { public: Expressions index; // indices @@ -80,16 +82,16 @@ public: bool isAssociativeArray() const; Expression *toAssocArrayLiteral(); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ExpInitializer : public Initializer +class ExpInitializer final : public Initializer { public: bool expandTuples; Expression *exp; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; struct Designator @@ -104,14 +106,14 @@ struct DesigInit Initializer *initializer; }; -class CInitializer : public Initializer +class CInitializer final : public Initializer { public: DesigInits initializerList; Type *type; // type that array will be used to initialize bool sem; // true if semantic() is run - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; Expression *initializerToExpression(Initializer *init, Type *t = NULL, const bool isCfile = false); diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d index 2cddd282a02..a1963dabcdc 100644 --- a/gcc/d/dmd/initsem.d +++ b/gcc/d/dmd/initsem.d @@ -197,10 +197,9 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ if (vd.type.hasPointers) { if ((!t.alignment.isDefault() && t.alignment.get() < target.ptrsize || - (vd.offset & (target.ptrsize - 1))) && - sc.func) + (vd.offset & (target.ptrsize - 1)))) { - if (sc.func.setUnsafe(false, i.value[j].loc, + if (sc.setUnsafe(false, i.value[j].loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code", sd, vd)) { errors = true; diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d index 5945da32259..ef918e275d0 100644 --- a/gcc/d/dmd/lexer.d +++ b/gcc/d/dmd/lexer.d @@ -146,6 +146,36 @@ class Lexer } } + /****************** + * Used for unittests for a mock Lexer + */ + this() { } + + /************************************** + * Reset lexer to lex #define's + */ + final void resetDefineLines(const(char)[] slice) + { + base = slice.ptr; + end = base + slice.length; + assert(*end == 0); + p = base; + line = p; + tokenizeNewlines = true; + inTokenStringConstant = 0; + lastDocLine = 0; + scanloc = Loc("#defines", 1, 1); + } + + /********************************** + * Set up for next #define line. + * p should be at start of next line. + */ + final void nextDefineLine() + { + tokenizeNewlines = true; + } + version (DMDLIB) { this(const(char)* filename, const(char)* base, size_t begoffset, size_t endoffset, @@ -1184,7 +1214,7 @@ class Lexer * Returns: * the escape sequence as a single character */ - private static dchar escapeSequence(const ref Loc loc, ref const(char)* sequence, bool Ccompile) + private dchar escapeSequence(const ref Loc loc, ref const(char)* sequence, bool Ccompile) { const(char)* p = sequence; // cache sequence reference on stack scope(exit) sequence = p; @@ -1268,13 +1298,13 @@ class Lexer break; if (!ishex(cast(char)c)) { - .error(loc, "escape hex sequence has %d hex digits instead of %d", n, ndigits); + error(loc, "escape hex sequence has %d hex digits instead of %d", n, ndigits); break; } } if (ndigits != 2 && !utf_isValidDchar(v)) { - .error(loc, "invalid UTF character \\U%08x", v); + error(loc, "invalid UTF character \\U%08x", v); v = '?'; // recover with valid UTF character } } @@ -1282,7 +1312,7 @@ class Lexer } else { - .error(loc, "undefined escape hex sequence \\%c%c", sequence[0], c); + error(loc, "undefined escape hex sequence \\%c%c", sequence[0], c); p++; } break; @@ -1299,7 +1329,7 @@ class Lexer c = HtmlNamedEntity(idstart, p - idstart); if (c == ~0) { - .error(loc, "unnamed character entity &%.*s;", cast(int)(p - idstart), idstart); + error(loc, "unnamed character entity &%.*s;", cast(int)(p - idstart), idstart); c = '?'; } p++; @@ -1307,7 +1337,7 @@ class Lexer default: if (isalpha(*p) || (p != idstart && isdigit(*p))) continue; - .error(loc, "unterminated named entity &%.*s;", cast(int)(p - idstart + 1), idstart); + error(loc, "unterminated named entity &%.*s;", cast(int)(p - idstart + 1), idstart); c = '?'; break; } @@ -1332,11 +1362,11 @@ class Lexer while (++n < 3 && isoctal(cast(char)c)); c = v; if (c > 0xFF) - .error(loc, "escape octal sequence \\%03o is larger than \\377", c); + error(loc, "escape octal sequence \\%03o is larger than \\377", c); } else { - .error(loc, "undefined escape sequence \\%c", c); + error(loc, "undefined escape sequence \\%c", c); p++; } break; @@ -2732,8 +2762,10 @@ class Lexer /*************************************** * Scan forward to start of next line. + * Params: + * defines = send characters to `defines` */ - final void skipToNextLine() + final void skipToNextLine(OutBuffer* defines = null) { while (1) { @@ -2754,7 +2786,9 @@ class Lexer break; default: - if (*p & 0x80) + if (defines) + defines.writeByte(*p); // don't care about Unicode line endings for C + else if (*p & 0x80) { const u = decodeUTF(); if (u == PS || u == LS) @@ -3146,7 +3180,8 @@ unittest static void test(T)(string sequence, T expected, bool Ccompile = false) { auto p = cast(const(char)*)sequence.ptr; - assert(expected == Lexer.escapeSequence(Loc.initial, p, Ccompile)); + Lexer lexer = new Lexer(); + assert(expected == lexer.escapeSequence(Loc.initial, p, Ccompile)); assert(p == sequence.ptr + sequence.length); } @@ -3212,7 +3247,8 @@ unittest gotError = false; expected = expectedError; auto p = cast(const(char)*)sequence.ptr; - auto actualReturnValue = Lexer.escapeSequence(Loc.initial, p, Ccompile); + Lexer lexer = new Lexer(); + auto actualReturnValue = lexer.escapeSequence(Loc.initial, p, Ccompile); assert(gotError); assert(expectedReturnValue == actualReturnValue); diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h index 048b3a0452c..5808c28dc82 100644 --- a/gcc/d/dmd/module.h +++ b/gcc/d/dmd/module.h @@ -35,21 +35,21 @@ public: unsigned tag; // auto incremented tag, used to mask package tree in scopes Module *mod; // != NULL if isPkgMod == PKGmodule - const char *kind() const; + const char *kind() const override; - bool equals(const RootObject *o) const; + bool equals(const RootObject *o) const override; - Package *isPackage() { return this; } + Package *isPackage() override final { return this; } bool isAncestorPackageOf(const Package * const pkg) const; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); - void accept(Visitor *v) { v->visit(this); } + Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; + void accept(Visitor *v) override { v->visit(this); } Module *isPackageMod(); }; -class Module : public Package +class Module final : public Package { public: static Module *rootModule; @@ -82,6 +82,7 @@ public: int needmoduleinfo; int selfimports; // 0: don't know, 1: does not, 2: does void* tagSymTab; // ImportC: tag symbols that conflict with other symbols used as the index + OutBuffer defines; // collect all the #define lines here bool selfImports(); // returns true if module imports itself int rootimports; // 0: don't know, 1: does not, 2: does @@ -119,14 +120,14 @@ public: static Module *load(const Loc &loc, Identifiers *packages, Identifier *ident); - const char *kind() const; + const char *kind() const override; bool read(const Loc &loc); // read file, returns 'true' if succeed, 'false' otherwise. Module *parse(); // syntactic parse - void importAll(Scope *sc); + void importAll(Scope *sc) override; int needModuleInfo(); - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); - bool isPackageAccessible(Package *p, Visibility visibility, int flags = 0); - Dsymbol *symtabInsert(Dsymbol *s); + Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; + bool isPackageAccessible(Package *p, Visibility visibility, int flags = 0) override; + Dsymbol *symtabInsert(Dsymbol *s) override; void deleteObjFile(); static void runDeferredSemantic(); static void runDeferredSemantic2(); @@ -155,8 +156,8 @@ public: void *ctfe_cov; // stores coverage information from ctfe - Module *isModule() { return this; } - void accept(Visitor *v) { v->visit(this); } + Module *isModule() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index be17ab3e9ad..052c23d4420 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -525,10 +525,12 @@ extern (C++) abstract class Type : ASTNode * Params: * t = type 'this' is covariant with * pstc = if not null, store STCxxxx which would make it covariant + * cppCovariant = true if extern(C++) function types should follow C++ covariant rules * Returns: * An enum value of either `Covariant.yes` or a reason it's not covariant. */ - final Covariant covariant(Type t, StorageClass* pstc = null) + extern (D) + final Covariant covariant(Type t, StorageClass* pstc = null, bool cppCovariant = false) { version (none) { @@ -563,11 +565,11 @@ extern (C++) abstract class Type : ASTNode foreach (i, fparam1; t1.parameterList) { Parameter fparam2 = t2.parameterList[i]; + Type tp1 = fparam1.type; + Type tp2 = fparam2.type; - if (!fparam1.type.equals(fparam2.type)) + if (!tp1.equals(tp2)) { - Type tp1 = fparam1.type; - Type tp2 = fparam2.type; if (tp1.ty == tp2.ty) { if (auto tc1 = tp1.isTypeClass()) @@ -600,6 +602,16 @@ extern (C++) abstract class Type : ASTNode } Lcov: notcovariant |= !fparam1.isCovariant(t1.isref, fparam2); + + /* https://issues.dlang.org/show_bug.cgi?id=23135 + * extern(C++) mutable parameters are not covariant with const. + */ + if (t1.linkage == LINK.cpp && cppCovariant) + { + notcovariant |= tp1.isNaked() != tp2.isNaked(); + if (auto tpn1 = tp1.nextOf()) + notcovariant |= tpn1.isNaked() != tp2.nextOf().isNaked(); + } } } else if (t1.parameterList.parameters != t2.parameterList.parameters) @@ -701,6 +713,12 @@ extern (C++) abstract class Type : ASTNode else if (t1.isreturn && !t2.isreturn) goto Lnotcovariant; + /* https://issues.dlang.org/show_bug.cgi?id=23135 + * extern(C++) mutable member functions are not covariant with const. + */ + if (t1.linkage == LINK.cpp && cppCovariant && t1.isNaked() != t2.isNaked()) + goto Lnotcovariant; + /* Can convert mutable to const */ if (!MODimplicitConv(t2.mod, t1.mod)) @@ -3237,7 +3255,7 @@ extern (C++) final class TypeBasic : Type return this; } - override uinteger_t size(const ref Loc loc) const + override uinteger_t size(const ref Loc loc) { uint size; //printf("TypeBasic::size()\n"); @@ -3325,32 +3343,32 @@ extern (C++) final class TypeBasic : Type return (flags & TFlags.integral) != 0; } - override bool isfloating() const + override bool isfloating() { return (flags & TFlags.floating) != 0; } - override bool isreal() const + override bool isreal() { return (flags & TFlags.real_) != 0; } - override bool isimaginary() const + override bool isimaginary() { return (flags & TFlags.imaginary) != 0; } - override bool iscomplex() const + override bool iscomplex() { return (flags & TFlags.complex) != 0; } - override bool isscalar() const + override bool isscalar() { return (flags & (TFlags.integral | TFlags.floating)) != 0; } - override bool isunsigned() const + override bool isunsigned() { return (flags & TFlags.unsigned) != 0; } @@ -3447,7 +3465,7 @@ extern (C++) final class TypeBasic : Type return MATCH.convert; } - override bool isZeroInit(const ref Loc loc) const + override bool isZeroInit(const ref Loc loc) { switch (ty) { @@ -3543,7 +3561,7 @@ extern (C++) final class TypeVector : Type return basetype.nextOf().isunsigned(); } - override bool isBoolean() const + override bool isBoolean() { return false; } @@ -3860,13 +3878,13 @@ extern (C++) final class TypeDArray : TypeArray return result; } - override uinteger_t size(const ref Loc loc) const + override uinteger_t size(const ref Loc loc) { //printf("TypeDArray::size()\n"); return target.ptrsize * 2; } - override uint alignsize() const + override uint alignsize() { // A DArray consists of two ptr-sized values, so align it on pointer size // boundary @@ -3879,12 +3897,12 @@ extern (C++) final class TypeDArray : TypeArray return nty.isSomeChar; } - override bool isZeroInit(const ref Loc loc) const + override bool isZeroInit(const ref Loc loc) { return true; } - override bool isBoolean() const + override bool isBoolean() { return true; } @@ -3918,7 +3936,7 @@ extern (C++) final class TypeDArray : TypeArray return Type.implicitConvTo(to); } - override bool hasPointers() const + override bool hasPointers() { return true; } @@ -3964,22 +3982,22 @@ extern (C++) final class TypeAArray : TypeArray return result; } - override uinteger_t size(const ref Loc loc) const + override uinteger_t size(const ref Loc loc) { return target.ptrsize; } - override bool isZeroInit(const ref Loc loc) const + override bool isZeroInit(const ref Loc loc) { return true; } - override bool isBoolean() const + override bool isBoolean() { return true; } - override bool hasPointers() const + override bool hasPointers() { return true; } @@ -4056,7 +4074,7 @@ extern (C++) final class TypePointer : TypeNext return result; } - override uinteger_t size(const ref Loc loc) const + override uinteger_t size(const ref Loc loc) { return target.ptrsize; } @@ -4112,17 +4130,17 @@ extern (C++) final class TypePointer : TypeNext return TypeNext.constConv(to); } - override bool isscalar() const + override bool isscalar() { return true; } - override bool isZeroInit(const ref Loc loc) const + override bool isZeroInit(const ref Loc loc) { return true; } - override bool hasPointers() const + override bool hasPointers() { return true; } @@ -4159,12 +4177,12 @@ extern (C++) final class TypeReference : TypeNext return result; } - override uinteger_t size(const ref Loc loc) const + override uinteger_t size(const ref Loc loc) { return target.ptrsize; } - override bool isZeroInit(const ref Loc loc) const + override bool isZeroInit(const ref Loc loc) { return true; } @@ -4760,7 +4778,7 @@ extern (C++) final class TypeFunction : TypeNext char[] s; if (!f.isPure && sc.func.setImpure()) s ~= "pure "; - if (!f.isSafe() && !f.isTrusted() && sc.func.setUnsafe()) + if (!f.isSafe() && !f.isTrusted() && sc.setUnsafe()) s ~= "@safe "; if (!f.isNogc && sc.func.setGC()) s ~= "nogc "; @@ -5156,12 +5174,12 @@ extern (C++) final class TypeDelegate : TypeNext return t; } - override uinteger_t size(const ref Loc loc) const + override uinteger_t size(const ref Loc loc) { return target.ptrsize * 2; } - override uint alignsize() const + override uint alignsize() { return target.ptrsize; } @@ -5189,17 +5207,17 @@ extern (C++) final class TypeDelegate : TypeNext return MATCH.nomatch; } - override bool isZeroInit(const ref Loc loc) const + override bool isZeroInit(const ref Loc loc) { return true; } - override bool isBoolean() const + override bool isBoolean() { return true; } - override bool hasPointers() const + override bool hasPointers() { return true; } @@ -5748,12 +5766,12 @@ extern (C++) final class TypeStruct : Type return assignable; } - override bool isBoolean() const + override bool isBoolean() { return false; } - override bool needsDestruction() const + override bool needsDestruction() { return sym.dtor !is null; } @@ -5985,6 +6003,7 @@ extern (C++) final class TypeEnum : Type { return sym.getMemtype(loc); } + override uint alignsize() { Type t = memType(); @@ -6143,7 +6162,7 @@ extern (C++) final class TypeClass : Type return "class"; } - override uinteger_t size(const ref Loc loc) const + override uinteger_t size(const ref Loc loc) { return target.ptrsize; } @@ -6268,22 +6287,22 @@ extern (C++) final class TypeClass : Type return this; } - override bool isZeroInit(const ref Loc loc) const + override bool isZeroInit(const ref Loc loc) { return true; } - override bool isscope() const + override bool isscope() { return sym.stack; } - override bool isBoolean() const + override bool isBoolean() { return true; } - override bool hasPointers() const + override bool hasPointers() { return true; } @@ -6538,12 +6557,12 @@ extern (C++) final class TypeNull : Type return true; } - override bool isBoolean() const + override bool isBoolean() { return true; } - override uinteger_t size(const ref Loc loc) const + override uinteger_t size(const ref Loc loc) { return tvoidptr.size(loc); } @@ -6597,12 +6616,12 @@ extern (C++) final class TypeNoreturn : Type return this.implicitConvTo(to); } - override bool isBoolean() const + override bool isBoolean() { return true; // bottom type can be implicitly converted to any other type } - override uinteger_t size(const ref Loc loc) const + override uinteger_t size(const ref Loc loc) { return 0; } diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h index d2b136443e8..3565913ed27 100644 --- a/gcc/d/dmd/mtype.h +++ b/gcc/d/dmd/mtype.h @@ -119,14 +119,6 @@ enum MODFlags }; typedef unsigned char MOD; -enum class Covariant -{ - distinct = 0, - yes = 1, - no = 2, - fwdref = 3, -}; - enum VarArgValues { VARARGnone = 0, /// fixed number of arguments @@ -221,13 +213,12 @@ public: virtual const char *kind(); Type *copy() const; virtual Type *syntaxCopy(); - bool equals(const RootObject *o) const; + bool equals(const RootObject *o) const override; bool equivalent(Type *t); // kludge for template.isType() - DYNCAST dyncast() const { return DYNCAST_TYPE; } + DYNCAST dyncast() const override final { return DYNCAST_TYPE; } size_t getUniqueID() const; - Covariant covariant(Type *t, StorageClass *pstc = NULL); - const char *toChars() const; + const char *toChars() const override; char *toPrettyChars(bool QualifyTypes = false); static void _init(); @@ -306,7 +297,7 @@ public: virtual ClassDeclaration *isClassHandle(); virtual structalign_t alignment(); virtual Expression *defaultInitLiteral(const Loc &loc); - virtual bool isZeroInit(const Loc &loc = Loc()); // if initializer is 0 + virtual bool isZeroInit(const Loc &loc = Loc()); // if initializer is 0 Identifier *getTypeInfoIdent(); virtual int hasWild() const; virtual bool hasPointers(); @@ -349,18 +340,18 @@ public: TypeNoreturn *isTypeNoreturn(); TypeTag *isTypeTag(); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeError : public Type +class TypeError final : public Type { public: - const char *kind(); - TypeError *syntaxCopy(); + const char *kind() override; + TypeError *syntaxCopy() override; - uinteger_t size(const Loc &loc); - Expression *defaultInitLiteral(const Loc &loc); - void accept(Visitor *v) { v->visit(this); } + uinteger_t size(const Loc &loc) override; + Expression *defaultInitLiteral(const Loc &loc) override; + void accept(Visitor *v) override { v->visit(this); } }; class TypeNext : public Type @@ -368,164 +359,164 @@ class TypeNext : public Type public: Type *next; - void checkDeprecated(const Loc &loc, Scope *sc); - int hasWild() const; - Type *nextOf(); - Type *makeConst(); - Type *makeImmutable(); - Type *makeShared(); - Type *makeSharedConst(); - Type *makeWild(); - Type *makeWildConst(); - Type *makeSharedWild(); - Type *makeSharedWildConst(); - Type *makeMutable(); - MATCH constConv(Type *to); - unsigned char deduceWild(Type *t, bool isRef); + void checkDeprecated(const Loc &loc, Scope *sc) override final; + int hasWild() const override final; + Type *nextOf() override final; + Type *makeConst() override final; + Type *makeImmutable() override final; + Type *makeShared() override final; + Type *makeSharedConst() override final; + Type *makeWild() override final; + Type *makeWildConst() override final; + Type *makeSharedWild() override final; + Type *makeSharedWildConst() override final; + Type *makeMutable() override final; + MATCH constConv(Type *to) override; + unsigned char deduceWild(Type *t, bool isRef) override final; void transitive(); - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeBasic : public Type +class TypeBasic final : public Type { public: const char *dstring; unsigned flags; - const char *kind(); - TypeBasic *syntaxCopy(); - uinteger_t size(const Loc &loc) /*const*/; - unsigned alignsize(); - bool isintegral(); - bool isfloating() /*const*/; - bool isreal() /*const*/; - bool isimaginary() /*const*/; - bool iscomplex() /*const*/; - bool isscalar() /*const*/; - bool isunsigned() /*const*/; - MATCH implicitConvTo(Type *to); - bool isZeroInit(const Loc &loc) /*const*/; + const char *kind() override; + TypeBasic *syntaxCopy() override; + uinteger_t size(const Loc &loc) override; + unsigned alignsize() override; + bool isintegral() override; + bool isfloating() override; + bool isreal() override; + bool isimaginary() override; + bool iscomplex() override; + bool isscalar() override; + bool isunsigned() override; + MATCH implicitConvTo(Type *to) override; + bool isZeroInit(const Loc &loc) override; // For eliminating dynamic_cast - TypeBasic *isTypeBasic(); - void accept(Visitor *v) { v->visit(this); } + TypeBasic *isTypeBasic() override; + void accept(Visitor *v) override { v->visit(this); } }; -class TypeVector : public Type +class TypeVector final : public Type { public: Type *basetype; static TypeVector *create(Type *basetype); - const char *kind(); - TypeVector *syntaxCopy(); - uinteger_t size(const Loc &loc); - unsigned alignsize(); - bool isintegral(); - bool isfloating(); - bool isscalar(); - bool isunsigned(); - bool isBoolean() /*const*/; - MATCH implicitConvTo(Type *to); - Expression *defaultInitLiteral(const Loc &loc); + const char *kind() override; + TypeVector *syntaxCopy() override; + uinteger_t size(const Loc &loc) override; + unsigned alignsize() override; + bool isintegral() override; + bool isfloating() override; + bool isscalar() override; + bool isunsigned() override; + bool isBoolean() override; + MATCH implicitConvTo(Type *to) override; + Expression *defaultInitLiteral(const Loc &loc) override; TypeBasic *elementType(); - bool isZeroInit(const Loc &loc); + bool isZeroInit(const Loc &loc) override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; class TypeArray : public TypeNext { public: - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; // Static array, one with a fixed dimension -class TypeSArray : public TypeArray +class TypeSArray final : public TypeArray { public: Expression *dim; - const char *kind(); - TypeSArray *syntaxCopy(); + const char *kind() override; + TypeSArray *syntaxCopy() override; bool isIncomplete(); - uinteger_t size(const Loc &loc); - unsigned alignsize(); - bool isString(); - bool isZeroInit(const Loc &loc); - structalign_t alignment(); - MATCH constConv(Type *to); - MATCH implicitConvTo(Type *to); - Expression *defaultInitLiteral(const Loc &loc); - bool hasPointers(); - bool hasInvariant(); - bool needsDestruction(); - bool needsCopyOrPostblit(); - bool needsNested(); - - void accept(Visitor *v) { v->visit(this); } + uinteger_t size(const Loc &loc) override; + unsigned alignsize() override; + bool isString() override; + bool isZeroInit(const Loc &loc) override; + structalign_t alignment() override; + MATCH constConv(Type *to) override; + MATCH implicitConvTo(Type *to) override; + Expression *defaultInitLiteral(const Loc &loc) override; + bool hasPointers() override; + bool hasInvariant() override; + bool needsDestruction() override; + bool needsCopyOrPostblit() override; + bool needsNested() override; + + void accept(Visitor *v) override { v->visit(this); } }; // Dynamic array, no dimension -class TypeDArray : public TypeArray +class TypeDArray final : public TypeArray { public: - const char *kind(); - TypeDArray *syntaxCopy(); - uinteger_t size(const Loc &loc) /*const*/; - unsigned alignsize() /*const*/; - bool isString(); - bool isZeroInit(const Loc &loc) /*const*/; - bool isBoolean() /*const*/; - MATCH implicitConvTo(Type *to); - bool hasPointers() /*const*/; + const char *kind() override; + TypeDArray *syntaxCopy() override; + uinteger_t size(const Loc &loc) override; + unsigned alignsize() override; + bool isString() override; + bool isZeroInit(const Loc &loc) override; + bool isBoolean() override; + MATCH implicitConvTo(Type *to) override; + bool hasPointers() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeAArray : public TypeArray +class TypeAArray final : public TypeArray { public: Type *index; // key type Loc loc; static TypeAArray *create(Type *t, Type *index); - const char *kind(); - TypeAArray *syntaxCopy(); - uinteger_t size(const Loc &loc); - bool isZeroInit(const Loc &loc) /*const*/; - bool isBoolean() /*const*/; - bool hasPointers() /*const*/; - MATCH implicitConvTo(Type *to); - MATCH constConv(Type *to); + const char *kind() override; + TypeAArray *syntaxCopy() override; + uinteger_t size(const Loc &loc) override; + bool isZeroInit(const Loc &loc) override; + bool isBoolean() override; + bool hasPointers() override; + MATCH implicitConvTo(Type *to) override; + MATCH constConv(Type *to) override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypePointer : public TypeNext +class TypePointer final : public TypeNext { public: static TypePointer *create(Type *t); - const char *kind(); - TypePointer *syntaxCopy(); - uinteger_t size(const Loc &loc) /*const*/; - MATCH implicitConvTo(Type *to); - MATCH constConv(Type *to); - bool isscalar() /*const*/; - bool isZeroInit(const Loc &loc) /*const*/; - bool hasPointers() /*const*/; + const char *kind() override; + TypePointer *syntaxCopy() override; + uinteger_t size(const Loc &loc) override; + MATCH implicitConvTo(Type *to) override; + MATCH constConv(Type *to) override; + bool isscalar() override; + bool isZeroInit(const Loc &loc) override; + bool hasPointers() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeReference : public TypeNext +class TypeReference final : public TypeNext { public: - const char *kind(); - TypeReference *syntaxCopy(); - uinteger_t size(const Loc &loc) /*const*/; - bool isZeroInit(const Loc &loc) /*const*/; - void accept(Visitor *v) { v->visit(this); } + const char *kind() override; + TypeReference *syntaxCopy() override; + uinteger_t size(const Loc &loc) override; + bool isZeroInit(const Loc &loc) override; + void accept(Visitor *v) override { v->visit(this); } }; enum RET @@ -556,7 +547,7 @@ enum class PURE : unsigned char const_ = 3, // parameters are values or const }; -class Parameter : public ASTNode +class Parameter final : public ASTNode { public: StorageClass storageClass; @@ -570,12 +561,12 @@ public: Parameter *syntaxCopy(); Type *isLazyArray(); // kludge for template.isType() - DYNCAST dyncast() const { return DYNCAST_PARAMETER; } - void accept(Visitor *v) { v->visit(this); } + DYNCAST dyncast() const override { return DYNCAST_PARAMETER; } + void accept(Visitor *v) override { v->visit(this); } static size_t dim(Parameters *parameters); static Parameter *getNth(Parameters *parameters, d_size_t nth); - const char *toChars() const; + const char *toChars() const override; bool isCovariant(bool returnByRef, const Parameter *p, bool previewIn) const; }; @@ -590,7 +581,7 @@ struct ParameterList Parameter *operator[](size_t i) { return Parameter::getNth(parameters, i); } }; -class TypeFunction : public TypeNext +class TypeFunction final : public TypeNext { public: // .next is the return type @@ -604,16 +595,16 @@ public: Expressions *fargs; // function arguments static TypeFunction *create(Parameters *parameters, Type *treturn, VarArg varargs, LINK linkage, StorageClass stc = 0); - const char *kind(); - TypeFunction *syntaxCopy(); + const char *kind() override; + TypeFunction *syntaxCopy() override; void purityLevel(); bool hasLazyParameters(); bool isDstyleVariadic() const; StorageClass parameterStorageClass(Parameter *p); - Type *addStorageClass(StorageClass stc); + Type *addStorageClass(StorageClass stc) override; - Type *substWildTo(unsigned mod); - MATCH constConv(Type *to); + Type *substWildTo(unsigned mod) override; + MATCH constConv(Type *to) override; bool isnothrow() const; void isnothrow(bool v); @@ -643,29 +634,29 @@ public: void isInOutQual(bool v); bool iswild() const; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeDelegate : public TypeNext +class TypeDelegate final : public TypeNext { public: // .next is a TypeFunction static TypeDelegate *create(TypeFunction *t); - const char *kind(); - TypeDelegate *syntaxCopy(); - Type *addStorageClass(StorageClass stc); - uinteger_t size(const Loc &loc) /*const*/; - unsigned alignsize() /*const*/; - MATCH implicitConvTo(Type *to); - bool isZeroInit(const Loc &loc) /*const*/; - bool isBoolean() /*const*/; - bool hasPointers() /*const*/; + const char *kind() override; + TypeDelegate *syntaxCopy() override; + Type *addStorageClass(StorageClass stc) override; + uinteger_t size(const Loc &loc) override; + unsigned alignsize() override; + MATCH implicitConvTo(Type *to) override; + bool isZeroInit(const Loc &loc) override; + bool isBoolean() override; + bool hasPointers() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeTraits : public Type +class TypeTraits final : public Type { Loc loc; /// The expression to resolve as type or symbol. @@ -673,23 +664,23 @@ class TypeTraits : public Type /// Cached type/symbol after semantic analysis. RootObject *obj; - const char *kind(); - TypeTraits *syntaxCopy(); - uinteger_t size(const Loc &loc); - Dsymbol *toDsymbol(Scope *sc); - void accept(Visitor *v) { v->visit(this); } + const char *kind() override; + TypeTraits *syntaxCopy() override; + uinteger_t size(const Loc &loc) override; + Dsymbol *toDsymbol(Scope *sc) override; + void accept(Visitor *v) override { v->visit(this); } }; -class TypeMixin : public Type +class TypeMixin final : public Type { Loc loc; Expressions *exps; RootObject *obj; - const char *kind(); - TypeMixin *syntaxCopy(); - Dsymbol *toDsymbol(Scope *sc); - void accept(Visitor *v) { v->visit(this); } + const char *kind() override; + TypeMixin *syntaxCopy() override; + Dsymbol *toDsymbol(Scope *sc) override; + void accept(Visitor *v) override { v->visit(this); } }; class TypeQualified : public Type @@ -704,57 +695,57 @@ public: void addIdent(Identifier *ident); void addInst(TemplateInstance *inst); void addIndex(RootObject *expr); - uinteger_t size(const Loc &loc); + uinteger_t size(const Loc &loc) override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeIdentifier : public TypeQualified +class TypeIdentifier final : public TypeQualified { public: Identifier *ident; Dsymbol *originalSymbol; // The symbol representing this identifier, before alias resolution static TypeIdentifier *create(const Loc &loc, Identifier *ident); - const char *kind(); - TypeIdentifier *syntaxCopy(); - Dsymbol *toDsymbol(Scope *sc); - void accept(Visitor *v) { v->visit(this); } + const char *kind() override; + TypeIdentifier *syntaxCopy() override; + Dsymbol *toDsymbol(Scope *sc) override; + void accept(Visitor *v) override { v->visit(this); } }; /* Similar to TypeIdentifier, but with a TemplateInstance as the root */ -class TypeInstance : public TypeQualified +class TypeInstance final : public TypeQualified { public: TemplateInstance *tempinst; - const char *kind(); - TypeInstance *syntaxCopy(); - Dsymbol *toDsymbol(Scope *sc); - void accept(Visitor *v) { v->visit(this); } + const char *kind() override; + TypeInstance *syntaxCopy() override; + Dsymbol *toDsymbol(Scope *sc) override; + void accept(Visitor *v) override { v->visit(this); } }; -class TypeTypeof : public TypeQualified +class TypeTypeof final : public TypeQualified { public: Expression *exp; int inuse; - const char *kind(); - TypeTypeof *syntaxCopy(); - Dsymbol *toDsymbol(Scope *sc); - uinteger_t size(const Loc &loc); - void accept(Visitor *v) { v->visit(this); } + const char *kind() override; + TypeTypeof *syntaxCopy() override; + Dsymbol *toDsymbol(Scope *sc) override; + uinteger_t size(const Loc &loc) override; + void accept(Visitor *v) override { v->visit(this); } }; -class TypeReturn : public TypeQualified +class TypeReturn final : public TypeQualified { public: - const char *kind(); - TypeReturn *syntaxCopy(); - Dsymbol *toDsymbol(Scope *sc); - void accept(Visitor *v) { v->visit(this); } + const char *kind() override; + TypeReturn *syntaxCopy() override; + Dsymbol *toDsymbol(Scope *sc) override; + void accept(Visitor *v) override { v->visit(this); } }; // Whether alias this dependency is recursive or not. @@ -769,7 +760,7 @@ enum AliasThisRec RECtracingDT = 0x8 // mark in progress of deduceType }; -class TypeStruct : public Type +class TypeStruct final : public Type { public: StructDeclaration *sym; @@ -777,91 +768,91 @@ public: bool inuse; static TypeStruct *create(StructDeclaration *sym); - const char *kind(); - uinteger_t size(const Loc &loc); - unsigned alignsize(); - TypeStruct *syntaxCopy(); - Dsymbol *toDsymbol(Scope *sc); - structalign_t alignment(); - Expression *defaultInitLiteral(const Loc &loc); - bool isZeroInit(const Loc &loc); - bool isAssignable(); - bool isBoolean() /*const*/; - bool needsDestruction() /*const*/; - bool needsCopyOrPostblit(); - bool needsNested(); - bool hasPointers(); - bool hasVoidInitPointers(); - bool hasInvariant(); - MATCH implicitConvTo(Type *to); - MATCH constConv(Type *to); - unsigned char deduceWild(Type *t, bool isRef); - Type *toHeadMutable(); - - void accept(Visitor *v) { v->visit(this); } -}; - -class TypeEnum : public Type + const char *kind() override; + uinteger_t size(const Loc &loc) override; + unsigned alignsize() override; + TypeStruct *syntaxCopy() override; + Dsymbol *toDsymbol(Scope *sc) override; + structalign_t alignment() override; + Expression *defaultInitLiteral(const Loc &loc) override; + bool isZeroInit(const Loc &loc) override; + bool isAssignable() override; + bool isBoolean() override; + bool needsDestruction() override; + bool needsCopyOrPostblit() override; + bool needsNested() override; + bool hasPointers() override; + bool hasVoidInitPointers() override; + bool hasInvariant() override; + MATCH implicitConvTo(Type *to) override; + MATCH constConv(Type *to) override; + unsigned char deduceWild(Type *t, bool isRef) override; + Type *toHeadMutable() override; + + void accept(Visitor *v) override { v->visit(this); } +}; + +class TypeEnum final : public Type { public: EnumDeclaration *sym; - const char *kind(); - TypeEnum *syntaxCopy(); - uinteger_t size(const Loc &loc); - unsigned alignsize(); + const char *kind() override; + TypeEnum *syntaxCopy() override; + uinteger_t size(const Loc &loc) override; + unsigned alignsize() override; Type *memType(const Loc &loc = Loc()); - Dsymbol *toDsymbol(Scope *sc); - bool isintegral(); - bool isfloating(); - bool isreal(); - bool isimaginary(); - bool iscomplex(); - bool isscalar(); - bool isunsigned(); - bool isBoolean(); - bool isString(); - bool isAssignable(); - bool needsDestruction(); - bool needsCopyOrPostblit(); - bool needsNested(); - MATCH implicitConvTo(Type *to); - MATCH constConv(Type *to); - bool isZeroInit(const Loc &loc); - bool hasPointers(); - bool hasVoidInitPointers(); - bool hasInvariant(); - Type *nextOf(); - - void accept(Visitor *v) { v->visit(this); } -}; - -class TypeClass : public Type + Dsymbol *toDsymbol(Scope *sc) override; + bool isintegral() override; + bool isfloating() override; + bool isreal() override; + bool isimaginary() override; + bool iscomplex() override; + bool isscalar() override; + bool isunsigned() override; + bool isBoolean() override; + bool isString() override; + bool isAssignable() override; + bool needsDestruction() override; + bool needsCopyOrPostblit() override; + bool needsNested() override; + MATCH implicitConvTo(Type *to) override; + MATCH constConv(Type *to) override; + bool isZeroInit(const Loc &loc) override; + bool hasPointers() override; + bool hasVoidInitPointers() override; + bool hasInvariant() override; + Type *nextOf() override; + + void accept(Visitor *v) override { v->visit(this); } +}; + +class TypeClass final : public Type { public: ClassDeclaration *sym; AliasThisRec att; CPPMANGLE cppmangle; - const char *kind(); - uinteger_t size(const Loc &loc) /*const*/; - TypeClass *syntaxCopy(); - Dsymbol *toDsymbol(Scope *sc); - ClassDeclaration *isClassHandle(); - bool isBaseOf(Type *t, int *poffset); - MATCH implicitConvTo(Type *to); - MATCH constConv(Type *to); - unsigned char deduceWild(Type *t, bool isRef); - Type *toHeadMutable(); - bool isZeroInit(const Loc &loc) /*const*/; - bool isscope() /*const*/; - bool isBoolean() /*const*/; - bool hasPointers() /*const*/; + const char *kind() override; + uinteger_t size(const Loc &loc) override; + TypeClass *syntaxCopy() override; + Dsymbol *toDsymbol(Scope *sc) override; + ClassDeclaration *isClassHandle() override; + bool isBaseOf(Type *t, int *poffset) override; + MATCH implicitConvTo(Type *to) override; + MATCH constConv(Type *to) override; + unsigned char deduceWild(Type *t, bool isRef) override; + Type *toHeadMutable() override; + bool isZeroInit(const Loc &loc) override; + bool isscope() override; + bool isBoolean() override; + bool hasPointers() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TypeTuple : public Type +class TypeTuple final : public Type { public: // 'logically immutable' cached global - don't modify (neither pointer nor pointee)! @@ -873,56 +864,57 @@ public: static TypeTuple *create(); static TypeTuple *create(Type *t1); static TypeTuple *create(Type *t1, Type *t2); - const char *kind(); - TypeTuple *syntaxCopy(); - bool equals(const RootObject *o) const; - void accept(Visitor *v) { v->visit(this); } + const char *kind() override; + TypeTuple *syntaxCopy() override; + bool equals(const RootObject *o) const override; + void accept(Visitor *v) override { v->visit(this); } }; -class TypeSlice : public TypeNext +class TypeSlice final : public TypeNext { public: Expression *lwr; Expression *upr; - const char *kind(); - TypeSlice *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + const char *kind() override; + TypeSlice *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; -class TypeNull : public Type +class TypeNull final : public Type { public: - const char *kind(); + const char *kind() override; - TypeNull *syntaxCopy(); - MATCH implicitConvTo(Type *to); - bool isBoolean() /*const*/; + TypeNull *syntaxCopy() override; + MATCH implicitConvTo(Type *to) override; + bool hasPointers() override; + bool isBoolean() override; - uinteger_t size(const Loc &loc) /*const*/; - void accept(Visitor *v) { v->visit(this); } + uinteger_t size(const Loc &loc) override; + void accept(Visitor *v) override { v->visit(this); } }; class TypeNoreturn final : public Type { public: - const char *kind(); - TypeNoreturn *syntaxCopy(); - MATCH implicitConvTo(Type* to); - MATCH constConv(Type* to); - bool isBoolean() /* const */; - uinteger_t size(const Loc& loc) /* const */; - unsigned alignsize(); + const char *kind() override; + TypeNoreturn *syntaxCopy() override; + MATCH implicitConvTo(Type* to) override; + MATCH constConv(Type* to) override; + bool isBoolean() override; + uinteger_t size(const Loc& loc) override; + unsigned alignsize() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; class TypeTag final : public Type { public: - TypeTag *syntaxCopy(); + TypeTag *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; /**************************************************************/ diff --git a/gcc/d/dmd/nspace.h b/gcc/d/dmd/nspace.h index 7d6f65d5fa6..9dbbdf2fd0a 100644 --- a/gcc/d/dmd/nspace.h +++ b/gcc/d/dmd/nspace.h @@ -16,17 +16,17 @@ * Implies extern(C++). */ -class Nspace : public ScopeDsymbol +class Nspace final : public ScopeDsymbol { public: Expression *identExp; - Nspace *syntaxCopy(Dsymbol *s); - void addMember(Scope *sc, ScopeDsymbol *sds); - void setScope(Scope *sc); - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); - bool hasPointers(); - void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion); - const char *kind() const; - Nspace *isNspace() { return this; } - void accept(Visitor *v) { v->visit(this); } + Nspace *syntaxCopy(Dsymbol *s) override; + void addMember(Scope *sc, ScopeDsymbol *sds) override; + void setScope(Scope *sc) override; + Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; + bool hasPointers() override; + void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override; + const char *kind() const override; + Nspace *isNspace() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/parsetimevisitor.d b/gcc/d/dmd/parsetimevisitor.d index 7d5e19da9ee..387b28c1532 100644 --- a/gcc/d/dmd/parsetimevisitor.d +++ b/gcc/d/dmd/parsetimevisitor.d @@ -272,6 +272,10 @@ public: void visit(AST.UshrAssignExp e) { visit(cast(AST.BinAssignExp)e); } void visit(AST.CatAssignExp e) { visit(cast(AST.BinAssignExp)e); } + // CatAssignExp + void visit(AST.CatElemAssignExp e) { visit(cast(AST.CatAssignExp)e); } + void visit(AST.CatDcharAssignExp e) { visit(cast(AST.CatAssignExp)e); } + //=============================================================================== // TemplateParameter void visit(AST.TemplateAliasParameter tp) { visit(cast(AST.TemplateParameter)tp); } diff --git a/gcc/d/dmd/root/object.h b/gcc/d/dmd/root/object.h index 609e7633cbe..0c92a9af54f 100644 --- a/gcc/d/dmd/root/object.h +++ b/gcc/d/dmd/root/object.h @@ -26,7 +26,9 @@ enum DYNCAST DYNCAST_TUPLE, DYNCAST_PARAMETER, DYNCAST_STATEMENT, - DYNCAST_TEMPLATEPARAMETER + DYNCAST_CONDITION, + DYNCAST_TEMPLATEPARAMETER, + DYNCAST_INITIALIZER }; /* diff --git a/gcc/d/dmd/safe.d b/gcc/d/dmd/safe.d index 1c5275b3b34..4446b5e66b0 100644 --- a/gcc/d/dmd/safe.d +++ b/gcc/d/dmd/safe.d @@ -26,7 +26,7 @@ import dmd.identifier; import dmd.mtype; import dmd.target; import dmd.tokens; - +import dmd.func : setUnsafe; /************************************************************* * Check for unsafe access in @safe code: @@ -66,7 +66,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg) { if (v.overlapped) { - if (sc.func.setUnsafe(!printmsg, e.loc, + if (sc.setUnsafe(!printmsg, e.loc, "field `%s.%s` cannot access pointers in `@safe` code that overlap other fields", ad, v)) return true; } @@ -76,7 +76,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg) { if (v.overlapped) { - if (sc.func.setUnsafe(!printmsg, e.loc, + if (sc.setUnsafe(!printmsg, e.loc, "field `%s.%s` cannot access structs with invariants in `@safe` code that overlap other fields", ad, v)) return true; @@ -91,7 +91,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg) if ((!ad.type.alignment.isDefault() && ad.type.alignment.get() < target.ptrsize || (v.offset & (target.ptrsize - 1)))) { - if (sc.func.setUnsafe(!printmsg, e.loc, + if (sc.setUnsafe(!printmsg, e.loc, "field `%s.%s` cannot modify misaligned pointers in `@safe` code", ad, v)) return true; } @@ -99,7 +99,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg) if (v.overlapUnsafe) { - if (sc.func.setUnsafe(!printmsg, e.loc, + if (sc.setUnsafe(!printmsg, e.loc, "field `%s.%s` cannot modify fields in `@safe` code that overlap fields with other storage classes", ad, v)) { @@ -211,15 +211,12 @@ bool isSafeCast(Expression e, Type tfrom, Type tto) */ bool checkUnsafeDotExp(Scope* sc, Expression e, Identifier id, int flag) { - if (!(flag & DotExpFlag.noDeref) && // this use is attempting a dereference - sc.func && // inside a function - !sc.intypeof && // allow unsafe code in typeof expressions - !(sc.flags & SCOPE.debug_)) // allow unsafe code in debug statements + if (!(flag & DotExpFlag.noDeref)) // this use is attempting a dereference { if (id == Id.ptr) - return sc.func.setUnsafe(false, e.loc, "`%s.ptr` cannot be used in `@safe` code, use `&%s[0]` instead", e, e); + return sc.setUnsafe(false, e.loc, "`%s.ptr` cannot be used in `@safe` code, use `&%s[0]` instead", e, e); else - return sc.func.setUnsafe(false, e.loc, "`%s.%s` cannot be used in `@safe` code", e, id); + return sc.setUnsafe(false, e.loc, "`%s.%s` cannot be used in `@safe` code", e, id); } return false; } diff --git a/gcc/d/dmd/sideeffect.d b/gcc/d/dmd/sideeffect.d index 5691f3b75b6..f7a3836961c 100644 --- a/gcc/d/dmd/sideeffect.d +++ b/gcc/d/dmd/sideeffect.d @@ -203,10 +203,9 @@ private bool lambdaHasSideEffect(Expression e, bool assumeImpureCalls = false) Type t = ce.e1.type.toBasetype(); if (t.ty == Tdelegate) t = (cast(TypeDelegate)t).next; - if (t.ty == Tfunction && (ce.f ? callSideEffectLevel(ce.f) : callSideEffectLevel(ce.e1.type)) > 0) - { - } - else + + const level = t.ty == Tfunction && (ce.f ? callSideEffectLevel(ce.f) : callSideEffectLevel(ce.e1.type)); + if (level == 0) // 0 means the function has a side effect return true; } break; @@ -251,8 +250,9 @@ bool discardValue(Expression e) } break; // complain } + // Assumption that error => no side effect case EXP.error: - return false; + return true; case EXP.variable: { VarDeclaration v = (cast(VarExp)e).var.isVarDeclaration(); @@ -356,6 +356,25 @@ bool discardValue(Expression e) if (!hasSideEffect(e)) break; return false; + case EXP.identity, EXP.notIdentity: + case EXP.equal, EXP.notEqual: + /* + `[side effect] == 0` + Technically has a side effect but is clearly wrong; + */ + BinExp tmp = e.isBinExp(); + assert(tmp); + + e.error("the result of the equality expression `%s` is discarded", e.toChars()); + bool seenSideEffect = false; + foreach(expr; [tmp.e1, tmp.e2]) + { + if (hasSideEffect(expr)) { + expr.errorSupplemental("note that `%s` may have a side effect", expr.toChars()); + seenSideEffect |= true; + } + } + return !seenSideEffect; default: break; } diff --git a/gcc/d/dmd/statement.d b/gcc/d/dmd/statement.d index 71713249009..06546256d17 100644 --- a/gcc/d/dmd/statement.d +++ b/gcc/d/dmd/statement.d @@ -696,7 +696,7 @@ extern (C++) final class UnrolledLoopStatement : Statement /*********************************************************** */ -extern (C++) class ScopeStatement : Statement +extern (C++) final class ScopeStatement : Statement { Statement statement; Loc endloc; // location of closing curly bracket diff --git a/gcc/d/dmd/statement.h b/gcc/d/dmd/statement.h index 66eddd8ab55..681b4816320 100644 --- a/gcc/d/dmd/statement.h +++ b/gcc/d/dmd/statement.h @@ -109,9 +109,11 @@ public: Loc loc; STMT stmt; + DYNCAST dyncast() const override final { return DYNCAST_STATEMENT; } + virtual Statement *syntaxCopy(); - const char *toChars() const; + const char *toChars() const override final; void error(const char *format, ...); void warning(const char *format, ...); @@ -159,26 +161,26 @@ public: ForeachRangeStatement *isForeachRangeStatement() { return stmt == STMTforeachRange ? (ForeachRangeStatement*)this : NULL; } CompoundDeclarationStatement *isCompoundDeclarationStatement() { return stmt == STMTcompoundDeclaration ? (CompoundDeclarationStatement*)this : NULL; } - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; /** Any Statement that fails semantic() or has a component that is an ErrorExp or * a TypeError should return an ErrorStatement from semantic(). */ -class ErrorStatement : public Statement +class ErrorStatement final : public Statement { public: - ErrorStatement *syntaxCopy(); + ErrorStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class PeelStatement : public Statement +class PeelStatement final : public Statement { public: Statement *s; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; class ExpStatement : public Statement @@ -187,12 +189,12 @@ public: Expression *exp; static ExpStatement *create(const Loc &loc, Expression *exp); - ExpStatement *syntaxCopy(); + ExpStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class DtorExpStatement : public ExpStatement +class DtorExpStatement final : public ExpStatement { public: /* Wraps an expression that is the destruction of 'var' @@ -200,17 +202,17 @@ public: VarDeclaration *var; - DtorExpStatement *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + DtorExpStatement *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; -class CompileStatement : public Statement +class CompileStatement final : public Statement { public: Expressions *exps; - CompileStatement *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + CompileStatement *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; class CompoundStatement : public Statement @@ -219,60 +221,60 @@ public: Statements *statements; static CompoundStatement *create(const Loc &loc, Statement *s1, Statement *s2); - CompoundStatement *syntaxCopy(); - ReturnStatement *endsWithReturnStatement(); - Statement *last(); + CompoundStatement *syntaxCopy() override; + ReturnStatement *endsWithReturnStatement() override final; + Statement *last() override final; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class CompoundDeclarationStatement : public CompoundStatement +class CompoundDeclarationStatement final : public CompoundStatement { public: - CompoundDeclarationStatement *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + CompoundDeclarationStatement *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; /* The purpose of this is so that continue will go to the next * of the statements, and break will go to the end of the statements. */ -class UnrolledLoopStatement : public Statement +class UnrolledLoopStatement final : public Statement { public: Statements *statements; - UnrolledLoopStatement *syntaxCopy(); - bool hasBreak() const; - bool hasContinue() const; + UnrolledLoopStatement *syntaxCopy() override; + bool hasBreak() const override; + bool hasContinue() const override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ScopeStatement : public Statement +class ScopeStatement final : public Statement { public: Statement *statement; Loc endloc; // location of closing curly bracket - ScopeStatement *syntaxCopy(); - ReturnStatement *endsWithReturnStatement(); - bool hasBreak() const; - bool hasContinue() const; + ScopeStatement *syntaxCopy() override; + ReturnStatement *endsWithReturnStatement() override; + bool hasBreak() const override; + bool hasContinue() const override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ForwardingStatement : public Statement +class ForwardingStatement final : public Statement { public: ForwardingScopeDsymbol *sym; Statement *statement; - ForwardingStatement *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + ForwardingStatement *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; -class WhileStatement : public Statement +class WhileStatement final : public Statement { public: Parameter *param; @@ -280,28 +282,28 @@ public: Statement *_body; Loc endloc; // location of closing curly bracket - WhileStatement *syntaxCopy(); - bool hasBreak() const; - bool hasContinue() const; + WhileStatement *syntaxCopy() override; + bool hasBreak() const override; + bool hasContinue() const override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class DoStatement : public Statement +class DoStatement final : public Statement { public: Statement *_body; Expression *condition; Loc endloc; // location of ';' after while - DoStatement *syntaxCopy(); - bool hasBreak() const; - bool hasContinue() const; + DoStatement *syntaxCopy() override; + bool hasBreak() const override; + bool hasContinue() const override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ForStatement : public Statement +class ForStatement final : public Statement { public: Statement *_init; @@ -315,15 +317,15 @@ public: // treat that label as referring to this loop. Statement *relatedLabeled; - ForStatement *syntaxCopy(); - Statement *getRelatedLabeled() { return relatedLabeled ? relatedLabeled : this; } - bool hasBreak() const; - bool hasContinue() const; + ForStatement *syntaxCopy() override; + Statement *getRelatedLabeled() override { return relatedLabeled ? relatedLabeled : this; } + bool hasBreak() const override; + bool hasContinue() const override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ForeachStatement : public Statement +class ForeachStatement final : public Statement { public: TOK op; // TOKforeach or TOKforeach_reverse @@ -340,14 +342,14 @@ public: Statements *cases; // put breaks, continues, gotos and returns here ScopeStatements *gotos; // forward referenced goto's go here - ForeachStatement *syntaxCopy(); - bool hasBreak() const; - bool hasContinue() const; + ForeachStatement *syntaxCopy() override; + bool hasBreak() const override; + bool hasContinue() const override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ForeachRangeStatement : public Statement +class ForeachRangeStatement final : public Statement { public: TOK op; // TOKforeach or TOKforeach_reverse @@ -359,14 +361,14 @@ public: VarDeclaration *key; - ForeachRangeStatement *syntaxCopy(); - bool hasBreak() const; - bool hasContinue() const; + ForeachRangeStatement *syntaxCopy() override; + bool hasBreak() const override; + bool hasContinue() const override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class IfStatement : public Statement +class IfStatement final : public Statement { public: Parameter *prm; @@ -376,56 +378,56 @@ public: VarDeclaration *match; // for MatchExpression results Loc endloc; // location of closing curly bracket - IfStatement *syntaxCopy(); + IfStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ConditionalStatement : public Statement +class ConditionalStatement final : public Statement { public: Condition *condition; Statement *ifbody; Statement *elsebody; - ConditionalStatement *syntaxCopy(); + ConditionalStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class StaticForeachStatement : public Statement +class StaticForeachStatement final : public Statement { public: StaticForeach *sfe; - StaticForeachStatement *syntaxCopy(); + StaticForeachStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class PragmaStatement : public Statement +class PragmaStatement final : public Statement { public: Identifier *ident; Expressions *args; // array of Expression's Statement *_body; - PragmaStatement *syntaxCopy(); + PragmaStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class StaticAssertStatement : public Statement +class StaticAssertStatement final : public Statement { public: StaticAssert *sa; - StaticAssertStatement *syntaxCopy(); + StaticAssertStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class SwitchStatement : public Statement +class SwitchStatement final : public Statement { public: Expression *condition; @@ -441,13 +443,13 @@ public: int hasVars; // !=0 if has variable case values VarDeclaration *lastVar; - SwitchStatement *syntaxCopy(); - bool hasBreak() const; + SwitchStatement *syntaxCopy() override; + bool hasBreak() const override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class CaseStatement : public Statement +class CaseStatement final : public Statement { public: Expression *exp; @@ -457,110 +459,110 @@ public: VarDeclaration *lastVar; void* extra; // for use by Statement_toIR() - CaseStatement *syntaxCopy(); + CaseStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class CaseRangeStatement : public Statement +class CaseRangeStatement final : public Statement { public: Expression *first; Expression *last; Statement *statement; - CaseRangeStatement *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + CaseRangeStatement *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; -class DefaultStatement : public Statement +class DefaultStatement final : public Statement { public: Statement *statement; VarDeclaration *lastVar; - DefaultStatement *syntaxCopy(); + DefaultStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class GotoDefaultStatement : public Statement +class GotoDefaultStatement final : public Statement { public: SwitchStatement *sw; - GotoDefaultStatement *syntaxCopy(); + GotoDefaultStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class GotoCaseStatement : public Statement +class GotoCaseStatement final : public Statement { public: Expression *exp; // NULL, or which case to goto CaseStatement *cs; // case statement it resolves to - GotoCaseStatement *syntaxCopy(); + GotoCaseStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class SwitchErrorStatement : public Statement +class SwitchErrorStatement final : public Statement { public: Expression *exp; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ReturnStatement : public Statement +class ReturnStatement final : public Statement { public: Expression *exp; size_t caseDim; - ReturnStatement *syntaxCopy(); + ReturnStatement *syntaxCopy() override; - ReturnStatement *endsWithReturnStatement() { return this; } - void accept(Visitor *v) { v->visit(this); } + ReturnStatement *endsWithReturnStatement() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; -class BreakStatement : public Statement +class BreakStatement final : public Statement { public: Identifier *ident; - BreakStatement *syntaxCopy(); + BreakStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ContinueStatement : public Statement +class ContinueStatement final : public Statement { public: Identifier *ident; - ContinueStatement *syntaxCopy(); + ContinueStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class SynchronizedStatement : public Statement +class SynchronizedStatement final : public Statement { public: Expression *exp; Statement *_body; - SynchronizedStatement *syntaxCopy(); - bool hasBreak() const; - bool hasContinue() const; + SynchronizedStatement *syntaxCopy() override; + bool hasBreak() const override; + bool hasContinue() const override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class WithStatement : public Statement +class WithStatement final : public Statement { public: Expression *exp; @@ -568,12 +570,12 @@ public: VarDeclaration *wthis; Loc endloc; - WithStatement *syntaxCopy(); + WithStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class TryCatchStatement : public Statement +class TryCatchStatement final : public Statement { public: Statement *_body; @@ -581,13 +583,13 @@ public: Statement *tryBody; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion - TryCatchStatement *syntaxCopy(); - bool hasBreak() const; + TryCatchStatement *syntaxCopy() override; + bool hasBreak() const override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class Catch : public RootObject +class Catch final : public RootObject { public: Loc loc; @@ -606,7 +608,7 @@ public: Catch *syntaxCopy(); }; -class TryFinallyStatement : public Statement +class TryFinallyStatement final : public Statement { public: Statement *_body; @@ -616,25 +618,25 @@ public: bool bodyFallsThru; // true if _body falls through to finally static TryFinallyStatement *create(const Loc &loc, Statement *body, Statement *finalbody); - TryFinallyStatement *syntaxCopy(); - bool hasBreak() const; - bool hasContinue() const; + TryFinallyStatement *syntaxCopy() override; + bool hasBreak() const override; + bool hasContinue() const override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ScopeGuardStatement : public Statement +class ScopeGuardStatement final : public Statement { public: TOK tok; Statement *statement; - ScopeGuardStatement *syntaxCopy(); + ScopeGuardStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ThrowStatement : public Statement +class ThrowStatement final : public Statement { public: Expression *exp; @@ -642,21 +644,21 @@ public: // wasn't present in source code bool internalThrow; - ThrowStatement *syntaxCopy(); + ThrowStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class DebugStatement : public Statement +class DebugStatement final : public Statement { public: Statement *statement; - DebugStatement *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + DebugStatement *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; -class GotoStatement : public Statement +class GotoStatement final : public Statement { public: Identifier *ident; @@ -666,12 +668,12 @@ public: ScopeGuardStatement *os; VarDeclaration *lastVar; - GotoStatement *syntaxCopy(); + GotoStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class LabelStatement : public Statement +class LabelStatement final : public Statement { public: Identifier *ident; @@ -684,12 +686,12 @@ public: void* extra; // used by Statement_toIR() bool breaks; // someone did a 'break ident' - LabelStatement *syntaxCopy(); + LabelStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class LabelDsymbol : public Dsymbol +class LabelDsymbol final : public Dsymbol { public: LabelStatement *statement; @@ -698,8 +700,8 @@ public: bool iasm; // set if used by inline assembler static LabelDsymbol *create(Identifier *ident); - LabelDsymbol *isLabel(); - void accept(Visitor *v) { v->visit(this); } + LabelDsymbol *isLabel() override; + void accept(Visitor *v) override { v->visit(this); } }; Statement* asmSemantic(AsmStatement *s, Scope *sc); @@ -709,11 +711,11 @@ class AsmStatement : public Statement public: Token *tokens; - AsmStatement *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + AsmStatement *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; -class InlineAsmStatement : public AsmStatement +class InlineAsmStatement final : public AsmStatement { public: code *asmcode; @@ -722,12 +724,12 @@ public: bool refparam; // true if function parameter is referenced bool naked; // true if function is to be naked - InlineAsmStatement *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + InlineAsmStatement *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; // A GCC asm statement - assembler instructions with D expression operands -class GccAsmStatement : public AsmStatement +class GccAsmStatement final : public AsmStatement { public: StorageClass stc; // attributes of the asm {} block @@ -740,27 +742,27 @@ public: Identifiers *labels; // list of goto labels GotoStatements *gotos; // of the goto labels, the equivalent statements they represent - GccAsmStatement *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + GccAsmStatement *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; // a complete asm {} block -class CompoundAsmStatement : public CompoundStatement +class CompoundAsmStatement final : public CompoundStatement { public: StorageClass stc; // postfix attributes like nothrow/pure/@trusted - CompoundAsmStatement *syntaxCopy(); + CompoundAsmStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; -class ImportStatement : public Statement +class ImportStatement final : public Statement { public: Dsymbols *imports; // Array of Import's - ImportStatement *syntaxCopy(); + ImportStatement *syntaxCopy() override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d index a7ad84f8504..ed47b916c0a 100644 --- a/gcc/d/dmd/statementsem.d +++ b/gcc/d/dmd/statementsem.d @@ -1616,9 +1616,8 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor static FuncExp foreachBodyToFunction(Scope* sc, ForeachStatement fs, TypeFunction tfld) { auto params = new Parameters(); - foreach (i; 0 .. fs.parameters.dim) + foreach (i, p; *fs.parameters) { - Parameter p = (*fs.parameters)[i]; StorageClass stc = STC.ref_ | (p.storageClass & STC.scope_); Identifier id; @@ -3929,7 +3928,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor cas.error("`asm` statement is assumed to use the GC - mark it with `@nogc` if it does not"); if (!(cas.stc & (STC.trusted | STC.safe))) { - sc.func.setUnsafe(false, cas.loc, "`asm` statement is assumed to be `@system` - mark it with `@trusted` if it is not"); + sc.setUnsafe(false, cas.loc, "`asm` statement is assumed to be `@system` - mark it with `@trusted` if it is not"); } sc.pop(); @@ -4034,9 +4033,9 @@ void catchSemantic(Catch c, Scope* sc) error(c.loc, "catching C++ class objects not supported for this target"); c.errors = true; } - if (sc.func && !sc.intypeof && !c.internalCatch) + if (!c.internalCatch) { - if (sc.func.setUnsafe(false, c.loc, "cannot catch C++ class objects in `@safe` code")) + if (sc.setUnsafe(false, c.loc, "cannot catch C++ class objects in `@safe` code")) c.errors = true; } } @@ -4045,9 +4044,9 @@ void catchSemantic(Catch c, Scope* sc) error(c.loc, "can only catch class objects derived from `Throwable`, not `%s`", c.type.toChars()); c.errors = true; } - else if (sc.func && !sc.intypeof && !c.internalCatch && ClassDeclaration.exception && + else if (!c.internalCatch && ClassDeclaration.exception && cd != ClassDeclaration.exception && !ClassDeclaration.exception.isBaseOf(cd, null) && - sc.func.setUnsafe(false, c.loc, + sc.setUnsafe(false, c.loc, "can only catch class objects derived from `Exception` in `@safe` code, not `%s`", c.type)) { c.errors = true; diff --git a/gcc/d/dmd/staticassert.h b/gcc/d/dmd/staticassert.h index 38142bc6efc..d9389901469 100644 --- a/gcc/d/dmd/staticassert.h +++ b/gcc/d/dmd/staticassert.h @@ -20,10 +20,10 @@ public: Expression *exp; Expression *msg; - StaticAssert *syntaxCopy(Dsymbol *s); - void addMember(Scope *sc, ScopeDsymbol *sds); - bool oneMember(Dsymbol **ps, Identifier *ident); - const char *kind() const; - StaticAssert *isStaticAssert() { return this; } - void accept(Visitor *v) { v->visit(this); } + StaticAssert *syntaxCopy(Dsymbol *s) override; + void addMember(Scope *sc, ScopeDsymbol *sds) override; + bool oneMember(Dsymbol **ps, Identifier *ident) override; + const char *kind() const override; + StaticAssert *isStaticAssert() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h index 86863769141..9ad027a8647 100644 --- a/gcc/d/dmd/template.h +++ b/gcc/d/dmd/template.h @@ -28,15 +28,15 @@ class Expression; class FuncDeclaration; class Parameter; -class Tuple : public RootObject +class Tuple final : public RootObject { public: Objects objects; // kludge for template.isType() - DYNCAST dyncast() const { return DYNCAST_TUPLE; } + DYNCAST dyncast() const override { return DYNCAST_TUPLE; } - const char *toChars() const { return objects.toChars(); } + const char *toChars() const override { return objects.toChars(); } }; struct TemplatePrevious @@ -46,7 +46,7 @@ struct TemplatePrevious Objects *dedargs; }; -class TemplateDeclaration : public ScopeDsymbol +class TemplateDeclaration final : public ScopeDsymbol { public: TemplateParameters *parameters; // array of TemplateParameter's @@ -74,24 +74,24 @@ public: TemplatePrevious *previous; // threaded list of previous instantiation attempts on stack - TemplateDeclaration *syntaxCopy(Dsymbol *); - bool overloadInsert(Dsymbol *s); - bool hasStaticCtorOrDtor(); - const char *kind() const; - const char *toChars() const; + TemplateDeclaration *syntaxCopy(Dsymbol *) override; + bool overloadInsert(Dsymbol *s) override; + bool hasStaticCtorOrDtor() override; + const char *kind() const override; + const char *toChars() const override; - Visibility visible(); + Visibility visible() override; MATCH leastAsSpecialized(Scope *sc, TemplateDeclaration *td2, Expressions *fargs); RootObject *declareParameter(Scope *sc, TemplateParameter *tp, RootObject *o); - TemplateDeclaration *isTemplateDeclaration() { return this; } + TemplateDeclaration *isTemplateDeclaration() override { return this; } TemplateTupleParameter *isVariadic(); - bool isDeprecated() const; - bool isOverloadable() const; + bool isDeprecated() const override; + bool isOverloadable() const override; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; /* For type-parameter: @@ -134,10 +134,12 @@ public: virtual RootObject *defaultArg(const Loc &instLoc, Scope *sc) = 0; virtual bool hasDefaultArg() = 0; + DYNCAST dyncast() const override { return DYNCAST_TEMPLATEPARAMETER; } + /* Create dummy argument based on parameter. */ virtual RootObject *dummyArg() = 0; - void accept(Visitor *v) { v->visit(this); } + void accept(Visitor *v) override { v->visit(this); } }; /* Syntax: @@ -149,85 +151,85 @@ public: Type *specType; // type parameter: if !=NULL, this is the type specialization Type *defaultType; - TemplateTypeParameter *isTemplateTypeParameter(); - TemplateTypeParameter *syntaxCopy(); - bool declareParameter(Scope *sc); - void print(RootObject *oarg, RootObject *oded); - RootObject *specialization(); - RootObject *defaultArg(const Loc &instLoc, Scope *sc); - bool hasDefaultArg(); - RootObject *dummyArg(); - void accept(Visitor *v) { v->visit(this); } + TemplateTypeParameter *isTemplateTypeParameter() override final; + TemplateTypeParameter *syntaxCopy() override; + bool declareParameter(Scope *sc) override final; + void print(RootObject *oarg, RootObject *oded) override final; + RootObject *specialization() override final; + RootObject *defaultArg(const Loc &instLoc, Scope *sc) override final; + bool hasDefaultArg() override final; + RootObject *dummyArg() override final; + void accept(Visitor *v) override { v->visit(this); } }; /* Syntax: * this ident : specType = defaultType */ -class TemplateThisParameter : public TemplateTypeParameter +class TemplateThisParameter final : public TemplateTypeParameter { public: - TemplateThisParameter *isTemplateThisParameter(); - TemplateThisParameter *syntaxCopy(); - void accept(Visitor *v) { v->visit(this); } + TemplateThisParameter *isTemplateThisParameter() override; + TemplateThisParameter *syntaxCopy() override; + void accept(Visitor *v) override { v->visit(this); } }; /* Syntax: * valType ident : specValue = defaultValue */ -class TemplateValueParameter : public TemplateParameter +class TemplateValueParameter final : public TemplateParameter { public: Type *valType; Expression *specValue; Expression *defaultValue; - TemplateValueParameter *isTemplateValueParameter(); - TemplateValueParameter *syntaxCopy(); - bool declareParameter(Scope *sc); - void print(RootObject *oarg, RootObject *oded); - RootObject *specialization(); - RootObject *defaultArg(const Loc &instLoc, Scope *sc); - bool hasDefaultArg(); - RootObject *dummyArg(); - void accept(Visitor *v) { v->visit(this); } + TemplateValueParameter *isTemplateValueParameter() override; + TemplateValueParameter *syntaxCopy() override; + bool declareParameter(Scope *sc) override; + void print(RootObject *oarg, RootObject *oded) override; + RootObject *specialization() override; + RootObject *defaultArg(const Loc &instLoc, Scope *sc) override; + bool hasDefaultArg() override; + RootObject *dummyArg() override; + void accept(Visitor *v) override { v->visit(this); } }; /* Syntax: * specType ident : specAlias = defaultAlias */ -class TemplateAliasParameter : public TemplateParameter +class TemplateAliasParameter final : public TemplateParameter { public: Type *specType; RootObject *specAlias; RootObject *defaultAlias; - TemplateAliasParameter *isTemplateAliasParameter(); - TemplateAliasParameter *syntaxCopy(); - bool declareParameter(Scope *sc); - void print(RootObject *oarg, RootObject *oded); - RootObject *specialization(); - RootObject *defaultArg(const Loc &instLoc, Scope *sc); - bool hasDefaultArg(); - RootObject *dummyArg(); - void accept(Visitor *v) { v->visit(this); } + TemplateAliasParameter *isTemplateAliasParameter() override; + TemplateAliasParameter *syntaxCopy() override; + bool declareParameter(Scope *sc) override; + void print(RootObject *oarg, RootObject *oded) override; + RootObject *specialization() override; + RootObject *defaultArg(const Loc &instLoc, Scope *sc) override; + bool hasDefaultArg() override; + RootObject *dummyArg() override; + void accept(Visitor *v) override { v->visit(this); } }; /* Syntax: * ident ... */ -class TemplateTupleParameter : public TemplateParameter +class TemplateTupleParameter final : public TemplateParameter { public: - TemplateTupleParameter *isTemplateTupleParameter(); - TemplateTupleParameter *syntaxCopy(); - bool declareParameter(Scope *sc); - void print(RootObject *oarg, RootObject *oded); - RootObject *specialization(); - RootObject *defaultArg(const Loc &instLoc, Scope *sc); - bool hasDefaultArg(); - RootObject *dummyArg(); - void accept(Visitor *v) { v->visit(this); } + TemplateTupleParameter *isTemplateTupleParameter() override; + TemplateTupleParameter *syntaxCopy() override; + bool declareParameter(Scope *sc) override; + void print(RootObject *oarg, RootObject *oded) override; + RootObject *specialization() override; + RootObject *defaultArg(const Loc &instLoc, Scope *sc) override; + bool hasDefaultArg() override; + RootObject *dummyArg() override; + void accept(Visitor *v) override { v->visit(this); } }; /* Given: @@ -275,36 +277,36 @@ private: public: unsigned char inuse; // for recursive expansion detection - TemplateInstance *syntaxCopy(Dsymbol *); - Dsymbol *toAlias(); // resolve real symbol - const char *kind() const; - bool oneMember(Dsymbol **ps, Identifier *ident); - const char *toChars() const; - const char* toPrettyCharsHelper(); - Identifier *getIdent(); + TemplateInstance *syntaxCopy(Dsymbol *) override; + Dsymbol *toAlias() override final; // resolve real symbol + const char *kind() const override; + bool oneMember(Dsymbol **ps, Identifier *ident) override; + const char *toChars() const override; + const char* toPrettyCharsHelper() override final; + Identifier *getIdent() override final; hash_t toHash(); bool isDiscardable(); bool needsCodegen(); - TemplateInstance *isTemplateInstance() { return this; } - void accept(Visitor *v) { v->visit(this); } + TemplateInstance *isTemplateInstance() override final { return this; } + void accept(Visitor *v) override { v->visit(this); } }; -class TemplateMixin : public TemplateInstance +class TemplateMixin final : public TemplateInstance { public: TypeQualified *tqual; - TemplateMixin *syntaxCopy(Dsymbol *s); - const char *kind() const; - bool oneMember(Dsymbol **ps, Identifier *ident); - bool hasPointers(); - void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion); - const char *toChars() const; + TemplateMixin *syntaxCopy(Dsymbol *s) override; + const char *kind() const override; + bool oneMember(Dsymbol **ps, Identifier *ident) override; + bool hasPointers() override; + void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override; + const char *toChars() const override; - TemplateMixin *isTemplateMixin() { return this; } - void accept(Visitor *v) { v->visit(this); } + TemplateMixin *isTemplateMixin() override { return this; } + void accept(Visitor *v) override { v->visit(this); } }; Expression *isExpression(RootObject *o); diff --git a/gcc/d/dmd/transitivevisitor.d b/gcc/d/dmd/transitivevisitor.d index 0acad6ae14a..25dee7f4185 100644 --- a/gcc/d/dmd/transitivevisitor.d +++ b/gcc/d/dmd/transitivevisitor.d @@ -423,12 +423,20 @@ package mixin template ParseVisitMethods(AST) //printf("Visiting TypeQualified\n"); foreach (id; t.idents) { - if (id.dyncast() == DYNCAST.dsymbol) + switch(id.dyncast()) with(DYNCAST) + { + case dsymbol: (cast(AST.TemplateInstance)id).accept(this); - else if (id.dyncast() == DYNCAST.expression) + break; + case expression: (cast(AST.Expression)id).accept(this); - else if (id.dyncast() == DYNCAST.type) + break; + case type: (cast(AST.Type)id).accept(this); + break; + default: + break; + } } } diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index ac4c23b0605..4c9ca28f2fc 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -239,9 +239,10 @@ private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymb for (size_t i = 0; i < mt.idents.dim; i++) { RootObject id = mt.idents[i]; - if (id.dyncast() == DYNCAST.expression || - id.dyncast() == DYNCAST.type) + switch (id.dyncast()) with (DYNCAST) { + case expression: + case type: Type tx; Expression ex; Dsymbol sx; @@ -259,6 +260,8 @@ private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymb ex = ex.expressionSemantic(sc); resolveExp(ex, pt, pe, ps); return; + default: + break; } Type t = s.getType(); // type symbol, type alias, or type tuple? @@ -2799,21 +2802,20 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type } RootObject o = (*tup.objects)[cast(size_t)d]; - if (o.dyncast() == DYNCAST.dsymbol) + switch (o.dyncast()) with (DYNCAST) { + case dsymbol: return returnSymbol(cast(Dsymbol)o); - } - if (o.dyncast() == DYNCAST.expression) - { + case expression: Expression e = cast(Expression)o; if (e.op == EXP.dSymbol) return returnSymbol(e.isDsymbolExp().s); else return returnExp(e); - } - if (o.dyncast() == DYNCAST.type) - { + case type: return returnType((cast(Type)o).addMod(mt.mod)); + default: + break; } /* Create a new TupleDeclaration which diff --git a/gcc/d/dmd/version.h b/gcc/d/dmd/version.h index afc455784aa..b76393bc1ec 100644 --- a/gcc/d/dmd/version.h +++ b/gcc/d/dmd/version.h @@ -12,30 +12,30 @@ #include "dsymbol.h" -class DebugSymbol : public Dsymbol +class DebugSymbol final : public Dsymbol { public: unsigned level; - DebugSymbol *syntaxCopy(Dsymbol *); + DebugSymbol *syntaxCopy(Dsymbol *) override; - const char *toChars() const; - void addMember(Scope *sc, ScopeDsymbol *sds); - const char *kind() const; - DebugSymbol *isDebugSymbol(); - void accept(Visitor *v) { v->visit(this); } + const char *toChars() const override; + void addMember(Scope *sc, ScopeDsymbol *sds) override; + const char *kind() const override; + DebugSymbol *isDebugSymbol() override; + void accept(Visitor *v) override { v->visit(this); } }; -class VersionSymbol : public Dsymbol +class VersionSymbol final : public Dsymbol { public: unsigned level; - VersionSymbol *syntaxCopy(Dsymbol *); + VersionSymbol *syntaxCopy(Dsymbol *) override; - const char *toChars() const; - void addMember(Scope *sc, ScopeDsymbol *sds); - const char *kind() const; - VersionSymbol *isVersionSymbol(); - void accept(Visitor *v) { v->visit(this); } + const char *toChars() const override; + void addMember(Scope *sc, ScopeDsymbol *sds) override; + const char *kind() const override; + VersionSymbol *isVersionSymbol() override; + void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/visitor.h b/gcc/d/dmd/visitor.h index 5d6b94ccd02..b45ef790de3 100644 --- a/gcc/d/dmd/visitor.h +++ b/gcc/d/dmd/visitor.h @@ -265,6 +265,8 @@ class ShlAssignExp; class ShrAssignExp; class UshrAssignExp; class CatAssignExp; +class CatElemAssignExp; +class CatDcharAssignExp; class AddExp; class MinExp; class CatExp; @@ -564,6 +566,10 @@ public: virtual void visit(UshrAssignExp *e) { visit((BinAssignExp *)e); } virtual void visit(CatAssignExp *e) { visit((BinAssignExp *)e); } + // CatAssignExp + virtual void visit(CatElemAssignExp *e) { visit((CatAssignExp *)e); } + virtual void visit(CatDcharAssignExp *e) { visit((CatAssignExp *)e); } + // TemplateParameter virtual void visit(TemplateAliasParameter *tp) { visit((TemplateParameter *)tp); } virtual void visit(TemplateTypeParameter *tp) { visit((TemplateParameter *)tp); } diff --git a/gcc/d/lang.opt b/gcc/d/lang.opt index c2635827ad3..954eb9a22f1 100644 --- a/gcc/d/lang.opt +++ b/gcc/d/lang.opt @@ -372,6 +372,10 @@ fpreview=fixaliasthis D RejectNegative When a symbol is resolved, check `alias this' scope before going to upper scopes. +fpreview=fiximmutableconv +D RejectNegative +Disallow unsound immutable conversions that were formerly incorrectly permitted. + fpreview=in D RejectNegative Implement 'in' parameters to mean scope const. diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def index 534f8661b3e..1ad0369a75d 100644 --- a/gcc/d/runtime.def +++ b/gcc/d/runtime.def @@ -145,10 +145,6 @@ DEF_D_RUNTIME (ARRAYAPPENDCD, "_d_arrayappendcd", RT(ARRAY_VOID), DEF_D_RUNTIME (ARRAYAPPENDWD, "_d_arrayappendwd", RT(ARRAY_VOID), P2(ARRAYPTR_BYTE, DCHAR), 0) -/* Used for appending an existing array to another. */ -DEF_D_RUNTIME (ARRAYAPPENDT, "_d_arrayappendT", RT(ARRAY_VOID), - P3(TYPEINFO, ARRAYPTR_BYTE, ARRAY_BYTE), 0) - /* Used for allocating a new associative array. */ DEF_D_RUNTIME (ASSOCARRAYLITERALTX, "_d_assocarrayliteralTX", RT(VOIDPTR), P3(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID), 0) diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_ClassDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_ClassDeclaration.d index de4c7ba4247..169b7b15364 100644 --- a/gcc/testsuite/gdc.test/compilable/dtoh_ClassDeclaration.d +++ b/gcc/testsuite/gdc.test/compilable/dtoh_ClassDeclaration.d @@ -142,8 +142,8 @@ class B : public A, public I1, public I2 { public: using A::bar; - void foo(); - void bar(); + void foo() final override; + void bar() override; }; class Parent @@ -157,7 +157,7 @@ public: class Child final : public Parent { public: - void foo() /* const */; + void foo() override; }; class VisitorBase @@ -289,7 +289,7 @@ interface I2 : I1 class B : A, I1, I2 { alias bar = A.bar; - override void foo() {} + override final void foo() {} override void bar() {} } @@ -303,7 +303,7 @@ class Parent final class Child : Parent { extern(D) override void over() {} - override void foo() const {} + override void foo() {} } class VisitorBase diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_TemplateDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_TemplateDeclaration.d index 35c4ed7e03f..1e2be909e75 100644 --- a/gcc/testsuite/gdc.test/compilable/dtoh_TemplateDeclaration.d +++ b/gcc/testsuite/gdc.test/compilable/dtoh_TemplateDeclaration.d @@ -160,7 +160,7 @@ class Child final : public Parent { public: T childMember; - void parentVirtual(); + void parentVirtual() override; T childFinal(); }; diff --git a/gcc/testsuite/gdc.test/compilable/test22865.d b/gcc/testsuite/gdc.test/compilable/test22865.d new file mode 100644 index 00000000000..0f4026279e0 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test22865.d @@ -0,0 +1,35 @@ +// https://issues.dlang.org/show_bug.cgi?id=22865 + +// Test that safety errors inside speculative scopes don't affect attribute inference + +void main() @safe +{ + foo(); +} + +__gshared int g; + +auto foo() +{ + alias x0 = typeof(g++); + alias x1 = typeof(cast(int*) 0); + + auto x2 = __traits(compiles, g++); + enum x3 = __traits(compiles, (cast(int*) 0)); + + debug + { + g++; + const x4 = cast(int*) 0; + asm { } + } +} + +// Test that safety violations still occur if the function is inside the __traits(compiles) + +static assert(!__traits(compiles, { + void f() @safe + { + g++; + } +})); diff --git a/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d b/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d new file mode 100644 index 00000000000..bf51363c07e --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d @@ -0,0 +1,59 @@ +/* +REQUIRED_ARGS: -de +TEST_OUTPUT: +--- +fail_compilation/dip1000_deprecation.d(20): Deprecation: `@safe` function `main` calling `inferred` +fail_compilation/dip1000_deprecation.d(28): which would be `@system` because of: +fail_compilation/dip1000_deprecation.d(28): scope variable `x0` may not be returned +fail_compilation/dip1000_deprecation.d(22): Deprecation: `@safe` function `main` calling `inferredC` +fail_compilation/dip1000_deprecation.d(39): which calls `dip1000_deprecation.inferred` +fail_compilation/dip1000_deprecation.d(28): which would be `@system` because of: +fail_compilation/dip1000_deprecation.d(28): scope variable `x0` may not be returned +fail_compilation/dip1000_deprecation.d(54): Deprecation: escaping reference to stack allocated value returned by `S(null)` +fail_compilation/dip1000_deprecation.d(55): Deprecation: escaping reference to stack allocated value returned by `createS()` +fail_compilation/dip1000_deprecation.d(58): Deprecation: returning `s.incorrectReturnRef()` escapes a reference to local variable `s` +--- +*/ + +void main() @safe +{ + inferred(); + inferredB(); // no deprecation, trusted + inferredC(); // nested deprecation +} + +auto inferred() +{ + scope int* x0; + return x0; +} + +auto inferredB() @trusted +{ + scope int* x1; + return x1; +} + +auto inferredC() +{ + return inferred(); // no deprecation, inferredC is not explicit `@safe` +} + +@safe: + +struct S +{ + int* ptr; + int* incorrectReturnRef() scope return @trusted {return ptr;} +} + +S createS() { return S.init; } + +int* escape() +{ + return S().incorrectReturnRef(); + return createS().incorrectReturnRef(); + + S s; + return s.incorrectReturnRef(); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/dip25.d b/gcc/testsuite/gdc.test/fail_compilation/dip25.d index 41bfe49e484..02f31407754 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/dip25.d +++ b/gcc/testsuite/gdc.test/fail_compilation/dip25.d @@ -19,7 +19,7 @@ struct Data } ref int identity(return ref int x) @safe { return x; } -ref int fun(return int x) { return identity(x); } +ref int fun(return int x) @safe { return identity(x); } ref int fun2(ref int x) @safe { return identity(x); } void main() diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail12390.d b/gcc/testsuite/gdc.test/fail_compilation/fail12390.d index dd28163adb7..5c852a1ac91 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail12390.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail12390.d @@ -1,7 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/fail12390.d(14): Error: `fun().i == 4` has no effect +fail_compilation/fail12390.d(15): Error: the result of the equality expression `fun().i == 4` is discarded +fail_compilation/fail12390.d(15): note that `fun().i` may have a side effect --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22351.d b/gcc/testsuite/gdc.test/fail_compilation/fail22351.d new file mode 100644 index 00000000000..405ab557d75 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fail22351.d @@ -0,0 +1,20 @@ +/* https://issues.dlang.org/show_bug.cgi?id=22351 +REQUIRED_ARGS: -de +TEST_OUTPUT: +--- +fail_compilation/fail22351.d(18): Deprecation: overriding `extern(C++)` function `fail22351.C22351.func(int*)` with `const` qualified function `fail22351.Fail22351.func(const(int*))` is deprecated +fail_compilation/fail22351.d(18): Either remove `override`, or adjust the `const` qualifiers of the overriding function parameters +fail_compilation/fail22351.d(19): Error: function `extern (C++) void fail22351.Fail22351.func(const(int*)**)` does not override any function, did you mean to override `extern (C++) void fail22351.C22351.func(int*)`? +--- +*/ +extern(C++) class C22351 +{ + void func(int*) { } + void func(int***) { } +} + +extern(C++) final class Fail22351 : C22351 +{ + override void func(const int*) { } + override void func(const(int*)**) { } +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23135.d b/gcc/testsuite/gdc.test/fail_compilation/fail23135.d new file mode 100644 index 00000000000..d32c6aeef51 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fail23135.d @@ -0,0 +1,17 @@ +/* https://issues.dlang.org/show_bug.cgi?id=23135 +REQUIRED_ARGS: -de +TEST_OUTPUT: +--- +fail_compilation/fail23135.d(16): Deprecation: overriding `extern(C++)` function `fail23135.C23135.func()` with `const` qualified function `fail23135.Fail23135.func() const` is deprecated +fail_compilation/fail23135.d(16): Either remove `override`, or adjust the `const` qualifiers of the overriding function type +--- +*/ +extern(C++) class C23135 +{ + void func() { } +} + +extern(C++) final class Fail23135 : C23135 +{ + override void func() const { } +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d b/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d index 153e90b034a..3e7637ff667 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d @@ -13,7 +13,7 @@ fail_compilation/fail_scope.d(82): Error: returning `& string` escapes a referen fail_compilation/fail_scope.d(92): Error: returning `cast(int[])a` escapes a reference to local variable `a` fail_compilation/fail_scope.d(100): Error: returning `cast(int[])a` escapes a reference to local variable `a` fail_compilation/fail_scope.d(108): Deprecation: escaping reference to outer local variable `x` -fail_compilation/fail_scope.d(127): Error: returning `s.bar()` escapes a reference to local variable `s` +fail_compilation/fail_scope.d(127): Deprecation: returning `s.bar()` escapes a reference to local variable `s` fail_compilation/fail_scope.d(137): Error: returning `foo16226(i)` escapes a reference to local variable `i` --- //fail_compilation/fail_scope.d(30): Error: scope variable `da` may not be returned diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix22108.d b/gcc/testsuite/gdc.test/fail_compilation/fix22108.d new file mode 100644 index 00000000000..149bebae0ea --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fix22108.d @@ -0,0 +1,13 @@ +/* REQUIRED_ARGS: -preview=dip1000 +TEST_OUTPUT: +--- +fail_compilation/fix22108.d(12): Error: scope variable `p` may not be returned +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=22108 + +@safe ref int test(ref scope return int* p) +{ + return *p; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix23138.d b/gcc/testsuite/gdc.test/fail_compilation/fix23138.d new file mode 100644 index 00000000000..58766c86b7b --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fix23138.d @@ -0,0 +1,16 @@ +/* TEST_OUTPUT: +--- +fail_compilation/fix23138.d(14): Error: function `fix23138.C2.foo` cannot override `@safe` method `fix23138.C1.foo` with a `@system` attribute +--- + */ + +class C1 { + void foo() @safe + {} +} + +class C2 : C1 +{ + override void foo() @system + {} +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15660.d b/gcc/testsuite/gdc.test/fail_compilation/test15660.d index be244d78e71..ae573b2af2a 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test15660.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test15660.d @@ -1,4 +1,4 @@ -/* REQUIRED_ARGS: -preview=dip1000 +/* REQUIRED_ARGS: -preview=fixImmutableConv TEST_OUTPUT: --- fail_compilation/test15660.d(20): Error: cannot implicitly convert expression `f(v)` of type `int[]` to `immutable(int[])` diff --git a/gcc/testsuite/gdc.test/fail_compilation/test18484.d b/gcc/testsuite/gdc.test/fail_compilation/test18484.d index d604f380a18..e51647b3491 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test18484.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test18484.d @@ -19,7 +19,7 @@ int* test1() @safe auto x = S(); return x.bar(); // error } -int* test2() +int* test2() @safe { return S().bar(); // error } diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20881.d b/gcc/testsuite/gdc.test/fail_compilation/test20881.d index 72826352af2..d4c5f07bea5 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test20881.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test20881.d @@ -2,6 +2,7 @@ REQUIRED_ARGS: -preview=dip1000 TEST_OUTPUT: --- +fail_compilation/test20881.d(20): Error: scope variable `this` may not be returned fail_compilation/test20881.d(27): Error: address of variable `s` assigned to `global` with longer lifetime fail_compilation/test20881.d(28): Error: address of variable `s` assigned to `global` with longer lifetime fail_compilation/test20881.d(29): Error: address of variable `s` assigned to `global` with longer lifetime @@ -10,7 +11,6 @@ fail_compilation/test20881.d(29): Error: address of variable `s` assigned to `gl @safe: // https://issues.dlang.org/show_bug.cgi?id=20881 - struct S { int* ptr; diff --git a/gcc/testsuite/gdc.test/runnable_cxx/extra-files/test22351.cpp b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/test22351.cpp new file mode 100644 index 00000000000..ad70d0a01d4 --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/test22351.cpp @@ -0,0 +1,46 @@ +#include + +class A22351 +{ +public: + virtual int f(); + virtual int g(int *); + virtual int h(); + virtual int h() const; +}; + +class B22351 : public A22351 +{ +public: + virtual int f() const; + virtual int g(const int *); + int h() const override; +}; + +B22351 *createB(); + +int main() +{ + // mutable A calls functions in A vtable + A22351 *a = createB(); + assert(a->f() == 1); + assert(a->g(0) == 3); + assert(a->h() == 5); + + // cast to B calls functions in B vtable + B22351 *b = (B22351 *)a; + assert(b->f() == 2); + assert(b->g(0) == 4); + assert(b->h() == 6); + + // cast to const calls B override function + const A22351 *ca = a; + assert(ca->h() == 6); + + // const B calls functions in B vtable + const B22351 *cb = createB(); + assert(cb->f() == 2); + assert(cb->h() == 6); + + return 0; +} diff --git a/gcc/testsuite/gdc.test/runnable_cxx/extra-files/test23135.cpp b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/test23135.cpp new file mode 100644 index 00000000000..d4193c95669 --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/test23135.cpp @@ -0,0 +1,52 @@ +class Mutable +{ +public: + virtual ~Mutable(); + virtual void func(); +}; + +Mutable::~Mutable() +{ +} + +class DeriveMutable final : public Mutable +{ +public: + virtual ~DeriveMutable(); + void func() override; +}; + +DeriveMutable::~DeriveMutable() +{ +} + +class Const +{ +public: + virtual ~Const(); + virtual void func() const; +}; + +Const::~Const() +{ +} + +class DeriveConst final : public Const +{ +public: + virtual ~DeriveConst(); + void func() const override; +}; + +DeriveConst::~DeriveConst() +{ +} + +void test23135() +{ + DeriveMutable mut; + mut.func(); + + DeriveConst cst; + cst.func(); +} diff --git a/gcc/testsuite/gdc.test/runnable_cxx/test22351.d b/gcc/testsuite/gdc.test/runnable_cxx/test22351.d new file mode 100644 index 00000000000..1c930b6ea82 --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable_cxx/test22351.d @@ -0,0 +1,55 @@ +// https://issues.dlang.org/show_bug.cgi?id=22351 +// EXTRA_CPP_SOURCES: test22351.cpp +// REQUIRED_ARGS: -extern-std=c++11 +// CXXFLAGS: -std=c++11 +// DISABLED: win32 + +extern(C++) class A22351 +{ + int f() + { + return 1; + } + + int g(int*) + { + return 3; + } + + int h() + { + return 5; + } + + int h() const + { + return 7; + } +} + +extern(C++) class B22351 : A22351 +{ + alias f = A22351.f; + alias g = A22351.g; + alias h = A22351.h; + + int f() const + { + return 2; + } + + int g(const(int)*) + { + return 4; + } + + override int h() const + { + return 6; + } +} + +extern(C++) B22351 createB() +{ + return new B22351; +} diff --git a/gcc/testsuite/gdc.test/runnable_cxx/test23135.d b/gcc/testsuite/gdc.test/runnable_cxx/test23135.d new file mode 100644 index 00000000000..4a184bb7924 --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable_cxx/test23135.d @@ -0,0 +1,38 @@ +// https://issues.dlang.org/show_bug.cgi?id=23135 +// EXTRA_CPP_SOURCES: test23135.cpp +// REQUIRED_ARGS: -extern-std=c++11 +// CXXFLAGS: -std=c++11 +// DISABLED: win32 + +void main() +{ + test23135(); +} + +extern(C++): + +void test23135(); + +class Mutable +{ + ~this(); + void func() { } +} + +final class DeriveMutable : Mutable +{ + ~this(); + override void func() { } +} + +class Const +{ + ~this(); + void func() const { } +} + +final class DeriveConst : Const +{ + ~this(); + override void func() const { } +} diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index 1a9faf9be04..d503bae835c 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -94bd5bcb448405d90bc50113d1cfd45a0880a50d +f89da31331ef5df50d3bc7a26efd1b7acdefde8c The first line of this file holds the git revision number of the last merge done from the dlang/druntime repository. diff --git a/libphobos/libdruntime/core/internal/array/appending.d b/libphobos/libdruntime/core/internal/array/appending.d index 5d4f3b498f9..d416efe1c50 100644 --- a/libphobos/libdruntime/core/internal/array/appending.d +++ b/libphobos/libdruntime/core/internal/array/appending.d @@ -85,20 +85,35 @@ ref Tarr _d_arrayappendT(Tarr : T[], T)(return ref scope Tarr x, scope Tarr y) @ import core.internal.traits : hasElaborateCopyConstructor, Unqual; import core.lifetime : copyEmplace; + enum hasPostblit = __traits(hasPostblit, T); auto length = x.length; _d_arrayappendcTXImpl!Tarr._d_arrayappendcTX(x, y.length); - static if (hasElaborateCopyConstructor!T) + // Only call `copyEmplace` if `T` has a copy ctor and no postblit. + static if (hasElaborateCopyConstructor!T && !hasPostblit) { foreach (i, ref elem; y) copyEmplace(elem, x[length + i]); } else { - // blit all elements at once if (y.length) - memcpy(cast(Unqual!T *)&x[length], cast(Unqual!T *)&y[0], y.length * T.sizeof); + { + // blit all elements at once + auto xptr = cast(Unqual!T *)&x[length]; + immutable size = T.sizeof; + + memcpy(xptr, cast(Unqual!T *)&y[0], y.length * size); + + // call postblits if they exist + static if (hasPostblit) + { + auto eptr = xptr + y.length; + for (auto ptr = xptr; ptr < eptr; ptr++) + ptr.__xpostblit(); + } + } } return x; diff --git a/libphobos/libdruntime/core/memory.d b/libphobos/libdruntime/core/memory.d index b63b11100c1..7d1356af0be 100644 --- a/libphobos/libdruntime/core/memory.d +++ b/libphobos/libdruntime/core/memory.d @@ -38,7 +38,7 @@ * * Notes_to_implementors: * $(UL - * $(LI On POSIX systems, the signals SIGUSR1 and SIGUSR2 are reserved + * $(LI On POSIX systems, the signals `SIGRTMIN` and `SIGRTMIN + 1` are reserved * by this module for use in the garbage collector implementation. * Typically, they will be used to stop and resume other threads * when performing a collection, but an implementation may choose diff --git a/libphobos/libdruntime/core/thread/fiber.d b/libphobos/libdruntime/core/thread/fiber.d index bd53eed2d10..efbad7d6b74 100644 --- a/libphobos/libdruntime/core/thread/fiber.d +++ b/libphobos/libdruntime/core/thread/fiber.d @@ -653,14 +653,9 @@ class Fiber */ this( void delegate() dg, size_t sz = PAGESIZE * defaultStackPages, size_t guardPageSize = PAGESIZE ) nothrow - in - { - assert( dg ); - } - do { allocStack( sz, guardPageSize ); - reset( dg ); + reset( cast(void delegate() const) dg ); } diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d index 1bbce3f858d..ef073a93324 100644 --- a/libphobos/libdruntime/core/thread/osthread.d +++ b/libphobos/libdruntime/core/thread/osthread.d @@ -1251,7 +1251,7 @@ version (CoreDdoc) { /** * Instruct the thread module, when initialized, to use a different set of - * signals besides SIGUSR1 and SIGUSR2 for suspension and resumption of threads. + * signals besides SIGRTMIN and SIGRTMIN + 1 for suspension and resumption of threads. * This function should be called at most once, prior to thread_init(). * This function is Posix-only. */ @@ -1281,8 +1281,8 @@ else version (Posix) version (Posix) { - private __gshared int suspendSignalNumber = SIGUSR1; - private __gshared int resumeSignalNumber = SIGUSR2; + private __gshared int suspendSignalNumber; + private __gshared int resumeSignalNumber; } private extern (D) ThreadBase attachThread(ThreadBase _thisThread) @nogc nothrow @@ -2115,11 +2115,6 @@ extern (C) void thread_init() @nogc initLowlevelThreads(); Thread.initLocks(); - // The Android VM runtime intercepts SIGUSR1 and apparently doesn't allow - // its signal handler to run, so swap the two signals on Android, since - // thread_resumeHandler does nothing. - version (Android) thread_setGCSignals(SIGUSR2, SIGUSR1); - version (Darwin) { // thread id different in forked child process @@ -2135,6 +2130,16 @@ extern (C) void thread_init() @nogc } else version (Posix) { + if ( suspendSignalNumber == 0 ) + { + suspendSignalNumber = SIGRTMIN; + } + + if ( resumeSignalNumber == 0 ) + { + resumeSignalNumber = SIGRTMIN + 1; + assert(resumeSignalNumber <= SIGRTMAX); + } int status; sigaction_t suspend = void; sigaction_t resume = void; diff --git a/libphobos/libdruntime/core/thread/threadbase.d b/libphobos/libdruntime/core/thread/threadbase.d index 9042a365242..505be000c56 100644 --- a/libphobos/libdruntime/core/thread/threadbase.d +++ b/libphobos/libdruntime/core/thread/threadbase.d @@ -108,8 +108,8 @@ class ThreadBase m_call = fn; } - this(void delegate() dg, size_t sz = 0) @safe pure nothrow @nogc - in(dg) + this(void delegate() dg, size_t sz = 0) @trusted pure nothrow @nogc + in( cast(void delegate() const) dg) { this(sz); m_call = dg; diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d index 3a88552f302..fe65c0973e1 100644 --- a/libphobos/libdruntime/object.d +++ b/libphobos/libdruntime/object.d @@ -1481,7 +1481,7 @@ class TypeInfo_Delegate : TypeInfo override size_t getHash(scope const void* p) @trusted const { - return hashOf(*cast(void delegate()*)p); + return hashOf(*cast(const void delegate() *)p); } override bool equals(in void* p1, in void* p2) const @@ -4428,7 +4428,7 @@ nothrow @safe @nogc unittest } } -private extern (C) void rt_finalize(void *data, bool det=true) nothrow; +private extern (C) void rt_finalize2(void* p, bool det = true, bool resetMemory = true) nothrow; /// ditto void destroy(bool initialize = true, T)(T obj) if (is(T == class)) @@ -4448,7 +4448,7 @@ void destroy(bool initialize = true, T)(T obj) if (is(T == class)) { // Bypass overloaded opCast auto ptr = (() @trusted => *cast(void**) &obj)(); - rt_finalize(ptr); + rt_finalize2(ptr, true, initialize); } } @@ -4723,6 +4723,25 @@ nothrow unittest destroy(B.init); } +// make sure destroy!false skips re-initialization +unittest +{ + static struct S { int x; } + static class C { int x; } + static extern(C++) class Cpp { int x; } + + static void test(T)(T inst) + { + inst.x = 123; + destroy!false(inst); + assert(inst.x == 123, T.stringof); + } + + test(S()); + test(new C()); + test(new Cpp()); +} + /// ditto void destroy(bool initialize = true, T)(ref T obj) if (__traits(isStaticArray, T)) diff --git a/libphobos/libdruntime/rt/arrayassign.d b/libphobos/libdruntime/rt/arrayassign.d index 21d50b0413a..9a34ec750f1 100644 --- a/libphobos/libdruntime/rt/arrayassign.d +++ b/libphobos/libdruntime/rt/arrayassign.d @@ -162,45 +162,6 @@ extern (C) void[] _d_arrayassign_r(TypeInfo ti, void[] src, void[] dst, void* pt return dst; } -/** - * Does array initialization (not assignment) from another - * array of the same element type. - * ti is the element type. - */ -extern (C) void[] _d_arrayctor(TypeInfo ti, void[] from, void[] to) -{ - debug(PRINTF) printf("_d_arrayctor(from = %p,%d, to = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, ti.tsize); - - - auto element_size = ti.tsize; - - enforceRawArraysConformable("initialization", element_size, from, to); - - size_t i; - try - { - for (i = 0; i < to.length; i++) - { - // Copy construction is defined as bit copy followed by postblit. - memcpy(to.ptr + i * element_size, from.ptr + i * element_size, element_size); - ti.postblit(to.ptr + i * element_size); - } - } - catch (Throwable o) - { - /* Destroy, in reverse order, what we've constructed so far - */ - while (i--) - { - ti.destroy(to.ptr + i * element_size); - } - - throw o; - } - return to; -} - - /** * Do assignment to an array. * p[0 .. count] = value; @@ -227,36 +188,3 @@ extern (C) void* _d_arraysetassign(void* p, void* value, int count, TypeInfo ti) free(ptmp); return pstart; } - -/** - * Do construction of an array. - * ti[count] p = value; - */ -extern (C) void* _d_arraysetctor(void* p, void* value, int count, TypeInfo ti) -{ - void* pstart = p; - auto element_size = ti.tsize; - - try - { - foreach (i; 0 .. count) - { - // Copy construction is defined as bit copy followed by postblit. - memcpy(p, value, element_size); - ti.postblit(p); - p += element_size; - } - } - catch (Throwable o) - { - // Destroy, in reverse order, what we've constructed so far - while (p > pstart) - { - p -= element_size; - ti.destroy(p); - } - - throw o; - } - return pstart; -} diff --git a/libphobos/libdruntime/rt/lifetime.d b/libphobos/libdruntime/rt/lifetime.d index 96d9a804d7c..5a18968f6ee 100644 --- a/libphobos/libdruntime/rt/lifetime.d +++ b/libphobos/libdruntime/rt/lifetime.d @@ -163,23 +163,6 @@ extern (C) void _d_delclass(Object* p) @weak } } -/** - * This is called for a delete statement where the value - * being deleted is a pointer to a struct with a destructor - * but doesn't have an overloaded delete operator. - */ -extern (C) void _d_delstruct(void** p, TypeInfo_Struct inf) @weak -{ - if (*p) - { - debug(PRINTF) printf("_d_delstruct(%p, %p)\n", *p, cast(void*)inf); - - inf.destroy(*p); - GC.free(*p); - *p = null; - } -} - // strip const/immutable/shared/inout from type info inout(TypeInfo) unqualify(return scope inout(TypeInfo) cti) pure nothrow @nogc { @@ -1872,23 +1855,6 @@ do return *p; } -/** - * Append y[] to array x[] - */ -extern (C) void[] _d_arrayappendT(const TypeInfo ti, ref byte[] x, byte[] y) @weak -{ - import core.stdc.string; - auto length = x.length; - auto tinext = unqualify(ti.next); - auto sizeelem = tinext.tsize; // array element size - _d_arrayappendcTX(ti, x, y.length); - memcpy(x.ptr + length * sizeelem, y.ptr, y.length * sizeelem); - - // do postblit - __doPostblit(x.ptr + length * sizeelem, y.length * sizeelem, tinext); - return x; -} - /** * @@ -2606,11 +2572,6 @@ deprecated unittest } } - dtorCount = 0; - S1* s1 = new S1; - _d_delstruct(cast(void**)&s1, typeid(typeof(*s1))); // delete s1; - assert(dtorCount == 1); - dtorCount = 0; S1[] arr1 = new S1[7]; _d_delarray_t(cast(void[]*)&arr1, typeid(typeof(arr1[0]))); // delete arr1; diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE index 3de142fe009..ddf730ef333 100644 --- a/libphobos/src/MERGE +++ b/libphobos/src/MERGE @@ -1,4 +1,4 @@ -3a1cd9a01479155958c7799e573e55a93dd189a0 +d46814c86392007ebb4fb73cb684ef9e8caa605a The first line of this file holds the git revision number of the last merge done from the dlang/phobos repository. diff --git a/libphobos/src/std/package.d b/libphobos/src/std/package.d index a1d04444d62..bfb135b1885 100644 --- a/libphobos/src/std/package.d +++ b/libphobos/src/std/package.d @@ -35,6 +35,7 @@ public import std.base64, std.bigint, std.bitmanip, + std.checkedint, std.compiler, std.complex, std.concurrency, @@ -50,6 +51,7 @@ public import std.format, std.functional, std.getopt, + std.int128, std.json, std.math, std.mathspecial, diff --git a/libphobos/src/std/process.d b/libphobos/src/std/process.d index 28bfb049c2b..d4fe8a1c7e8 100644 --- a/libphobos/src/std/process.d +++ b/libphobos/src/std/process.d @@ -613,7 +613,7 @@ private: * writefln("Current process ID: %d", thisProcessID); * --- */ -@property int thisProcessID() @trusted nothrow //TODO: @safe +@property int thisProcessID() @trusted nothrow @nogc //TODO: @safe { version (Windows) return GetCurrentProcessId(); else version (Posix) return core.sys.posix.unistd.getpid(); @@ -632,7 +632,7 @@ private: * writefln("Current thread ID: %s", thisThreadID); * --- */ -@property ThreadID thisThreadID() @trusted nothrow //TODO: @safe +@property ThreadID thisThreadID() @trusted nothrow @nogc //TODO: @safe { version (Windows) return GetCurrentThreadId(); diff --git a/libphobos/src/std/utf.d b/libphobos/src/std/utf.d index f0200ce7052..d22dac8b15d 100644 --- a/libphobos/src/std/utf.d +++ b/libphobos/src/std/utf.d @@ -4275,10 +4275,10 @@ private int impureVariable; * UseReplacementDchar.no means throw `UTFException` for invalid UTF * * Throws: - * `UTFException` if invalid UTF sequence and `useReplacementDchar` is set to `UseReplacementDchar.yes` + * `UTFException` if invalid UTF sequence and `useReplacementDchar` is set to `UseReplacementDchar.no` * * GC: - * Does not use GC if `useReplacementDchar` is set to `UseReplacementDchar.no` + * Does not use GC if `useReplacementDchar` is set to `UseReplacementDchar.yes` * * Returns: * A bidirectional range if `R` is a bidirectional range and not auto-decodable,