From patchwork Mon Dec 17 18:32:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 1014670 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-492669-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdcproject.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="m0L7/9Y+"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 43JVCM5BqLz9s3q for ; Tue, 18 Dec 2018 05:33:18 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=IZyAZMhK9hdJ2lCuDle0nTnS9hJTkUZTJsJRxfQ2APKUBm SFn/rUW3CFn4lNH4TqcnWqjr9IYyJJ8Lkvw8Qsn+pzZgynCg8VyxOf2u0g+pIFHm M6qD+ixWlerGYkgzO5WJxO7wb4UEMRDXKtrAQbZxAwM68cZMMzEI1GOIkzaTQ= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=tX75ySNzoAuL4ln109b86yyMerc=; b=m0L7/9Y+DDuxucevQ2LX UvkFrm0I/A4P3PNXZyrSAn/hc09jAUhGvvK2Ztcf6f8nO0AdPzL3jFy3XcCqIagS VvHKrQXwxc4BNho4B0/qcNN9HHaoBeW+QeEBj/N/DC/12SlaMy05Qne21RspbcXS xhCNnDqYtv8xGK3Rm95uoCI= Received: (qmail 14939 invoked by alias); 17 Dec 2018 18:33:10 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 14925 invoked by uid 89); 17 Dec 2018 18:33:09 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=corruption, mod, UD:dlang.org, tel X-HELO: mail-qt1-f181.google.com Received: from mail-qt1-f181.google.com (HELO mail-qt1-f181.google.com) (209.85.160.181) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 17 Dec 2018 18:33:04 +0000 Received: by mail-qt1-f181.google.com with SMTP id k12so15214067qtf.7 for ; Mon, 17 Dec 2018 10:33:03 -0800 (PST) MIME-Version: 1.0 From: Iain Buclaw Date: Mon, 17 Dec 2018 19:32:50 +0100 Message-ID: Subject: [PATCH, d] Committed merge with upstream dmd To: gcc-patches X-IsSubscribed: yes Hi, This patch merges the D front-end implementation with dmd upstream 237ca3fbe. Backports a fix where a bad cast to TypeFunction resulted in memory corruption. The logic in the function semantic has been fixed, and casts have been replaced with a function call to always check the front-end AST node value. Bootstrapped and tested on x86_64-linux-gnu. Committed to trunk as r267207. diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index a1a1fa0efd1..bc35d4adc1f 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -e2fe2687b817a201528abaa3aa882333e04db01b +237ca3fbe8f9ac4b64e26ce912c20439ee4fc63a 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/dclass.c b/gcc/d/dmd/dclass.c index 6fe17b36576..ce9849fc7dd 100644 --- a/gcc/d/dmd/dclass.c +++ b/gcc/d/dmd/dclass.c @@ -805,7 +805,7 @@ Lancestorsdone: if (fd && !fd->errors) { //printf("Creating default this(){} for class %s\n", toChars()); - TypeFunction *btf = (TypeFunction *)fd->type; + TypeFunction *btf = fd->type->toTypeFunction(); TypeFunction *tf = new TypeFunction(NULL, NULL, 0, LINKd, fd->storage_class); tf->mod = btf->mod; tf->purity = btf->purity; @@ -1152,7 +1152,7 @@ int isf(void *param, Dsymbol *s) bool ClassDeclaration::isFuncHidden(FuncDeclaration *fd) { - //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toChars()); + //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toPrettyChars()); Dsymbol *s = search(Loc(), fd->ident, IgnoreAmbiguous | IgnoreErrors); if (!s) { @@ -1749,6 +1749,7 @@ bool InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset) //printf("\tX base %s\n", b->sym->toChars()); if (this == b->sym) { + //printf("\tfound at offset %d\n", b->offset); if (poffset) { // don't return incorrect offsets https://issues.dlang.org/show_bug.cgi?id=16980 @@ -1882,8 +1883,7 @@ bool BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newin assert(ifd); // Find corresponding function in this class - tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL; - assert(tf); // should always be non-null + tf = ifd->type->toTypeFunction(); fd = cd->findFunc(ifd->ident, tf); if (fd && !fd->isAbstract()) { diff --git a/gcc/d/dmd/dstruct.c b/gcc/d/dmd/dstruct.c index f9f15ba9092..77d6174241d 100644 --- a/gcc/d/dmd/dstruct.c +++ b/gcc/d/dmd/dstruct.c @@ -46,7 +46,7 @@ FuncDeclaration *search_toString(StructDeclaration *sd) if (!tftostring) { tftostring = new TypeFunction(NULL, Type::tstring, 0, LINKd); - tftostring = (TypeFunction *)tftostring->merge(); + tftostring = tftostring->merge()->toTypeFunction(); } fd = fd->overloadExactMatch(tftostring); @@ -92,6 +92,7 @@ void semanticTypeInfo(Scope *sc, Type *t) } void visit(TypeStruct *t) { + //printf("semanticTypeInfo::visit(TypeStruct = %s)\n", t->toChars()); StructDeclaration *sd = t->sym; /* Step 1: create TypeInfoDeclaration diff --git a/gcc/d/dmd/func.c b/gcc/d/dmd/func.c index c8f9c5c350a..4e1b3e2d2d3 100644 --- a/gcc/d/dmd/func.c +++ b/gcc/d/dmd/func.c @@ -411,8 +411,8 @@ static bool canInferAttributes(FuncDeclaration *fd, Scope *sc) */ static void initInferAttributes(FuncDeclaration *fd) { - assert(fd->type->ty == Tfunction); - TypeFunction *tf = (TypeFunction *)fd->type; + //printf("initInferAttributes() for %s\n", toPrettyChars()); + TypeFunction *tf = fd->type->toTypeFunction(); if (tf->purity == PUREimpure) // purity not specified fd->flags |= FUNCFLAGpurityInprocess; @@ -495,7 +495,7 @@ void FuncDeclaration::semantic(Scope *sc) fld->tok = TOKfunction; else assert(0); - linkage = ((TypeFunction *)treq->nextOf())->linkage; + linkage = treq->nextOf()->toTypeFunction()->linkage; } else linkage = sc->linkage; @@ -505,11 +505,21 @@ void FuncDeclaration::semantic(Scope *sc) if (!originalType) originalType = type->syntaxCopy(); + if (type->ty != Tfunction) + { + if (type->ty != Terror) + { + error("%s must be a function instead of %s", toChars(), type->toChars()); + type = Type::terror; + } + errors = true; + return; + } if (!type->deco) { sc = sc->push(); sc->stc |= storage_class & (STCdisable | STCdeprecated); // forward to function type - TypeFunction *tf = (TypeFunction *)type; + TypeFunction *tf = type->toTypeFunction(); if (sc->func) { @@ -678,8 +688,8 @@ void FuncDeclaration::semantic(Scope *sc) { // Merge back function attributes into 'originalType'. // It's used for mangling, ddoc, and json output. - TypeFunction *tfo = (TypeFunction *)originalType; - TypeFunction *tfx = (TypeFunction *)type; + TypeFunction *tfo = originalType->toTypeFunction(); + TypeFunction *tfx = type->toTypeFunction(); tfo->mod = tfx->mod; tfo->isscope = tfx->isscope; tfo->isscopeinferred = tfx->isscopeinferred; @@ -1132,8 +1142,7 @@ void FuncDeclaration::semantic(Scope *sc) error("override only applies to class member functions"); // Reflect this->type to f because it could be changed by findVtblIndex - assert(type->ty == Tfunction); - f = (TypeFunction *)type; + f = type->toTypeFunction(); /* Do not allow template instances to add virtual functions * to a class. @@ -2560,8 +2569,7 @@ void FuncDeclaration::buildResultVar(Scope *sc, Type *tret) if (sc && vresult->semanticRun == PASSinit) { - assert(type->ty == Tfunction); - TypeFunction *tf = (TypeFunction *)type; + TypeFunction *tf = type->toTypeFunction(); if (tf->isref) vresult->storage_class |= STCref; vresult->type = tret; @@ -3135,7 +3143,7 @@ FuncDeclaration *FuncDeclaration::overloadModMatch(Loc loc, Type *tthis, bool &h return 0; m->anyf = f; - TypeFunction *tf = (TypeFunction *)f->type; + TypeFunction *tf = f->type->toTypeFunction(); //printf("tf = %s\n", tf->toChars()); MATCH match; @@ -3205,7 +3213,7 @@ FuncDeclaration *FuncDeclaration::overloadModMatch(Loc loc, Type *tthis, bool &h else // no match { hasOverloads = true; - TypeFunction *tf = (TypeFunction *)this->type; + TypeFunction *tf = this->type->toTypeFunction(); assert(tthis); assert(!MODimplicitConv(tthis->mod, tf->mod)); // modifier mismatch { @@ -3270,8 +3278,8 @@ MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g) * as g() is. */ - TypeFunction *tf = (TypeFunction *)type; - TypeFunction *tg = (TypeFunction *)g->type; + TypeFunction *tf = type->toTypeFunction(); + TypeFunction *tg = g->type->toTypeFunction(); size_t nfparams = Parameter::dim(tf->parameters); /* If both functions have a 'this' pointer, and the mods are not @@ -3524,7 +3532,7 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s, assert(fd); bool hasOverloads = fd->overnext != NULL; - TypeFunction *tf = (TypeFunction *)fd->type; + TypeFunction *tf = fd->type->toTypeFunction(); if (tthis && !MODimplicitConv(tthis->mod, tf->mod)) // modifier mismatch { OutBuffer thisBuf, funcBuf; @@ -3562,8 +3570,8 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s, } else if (m.nextf) { - TypeFunction *tf1 = (TypeFunction *)m.lastf->type; - TypeFunction *tf2 = (TypeFunction *)m.nextf->type; + TypeFunction *tf1 = m.lastf->type->toTypeFunction(); + TypeFunction *tf2 = m.nextf->type->toTypeFunction(); const char *lastprms = parametersTypeToChars(tf1->parameters, tf1->varargs); const char *nextprms = parametersTypeToChars(tf2->parameters, tf2->varargs); ::error(loc, "%s.%s called with argument types %s matches both:\n" @@ -3679,7 +3687,7 @@ const char *FuncDeclaration::toPrettyChars(bool QualifyTypes) const char *FuncDeclaration::toFullSignature() { OutBuffer buf; - functionToBufferWithIdent((TypeFunction *)type, &buf, toChars()); + functionToBufferWithIdent(type->toTypeFunction(), &buf, toChars()); return buf.extractString(); } @@ -3776,8 +3784,7 @@ bool FuncDeclaration::isOverloadable() PURE FuncDeclaration::isPure() { //printf("FuncDeclaration::isPure() '%s'\n", toChars()); - assert(type->ty == Tfunction); - TypeFunction *tf = (TypeFunction *)type; + TypeFunction *tf = type->toTypeFunction(); if (flags & FUNCFLAGpurityInprocess) setImpure(); if (tf->purity == PUREfwdref) @@ -3829,10 +3836,9 @@ bool FuncDeclaration::setImpure() bool FuncDeclaration::isSafe() { - assert(type->ty == Tfunction); if (flags & FUNCFLAGsafetyInprocess) setUnsafe(); - return ((TypeFunction *)type)->trust == TRUSTsafe; + return type->toTypeFunction()->trust == TRUSTsafe; } bool FuncDeclaration::isSafeBypassingInference() @@ -3842,10 +3848,9 @@ bool FuncDeclaration::isSafeBypassingInference() bool FuncDeclaration::isTrusted() { - assert(type->ty == Tfunction); if (flags & FUNCFLAGsafetyInprocess) setUnsafe(); - return ((TypeFunction *)type)->trust == TRUSTtrusted; + return type->toTypeFunction()->trust == TRUSTtrusted; } /************************************** @@ -3858,7 +3863,7 @@ bool FuncDeclaration::setUnsafe() if (flags & FUNCFLAGsafetyInprocess) { flags &= ~FUNCFLAGsafetyInprocess; - ((TypeFunction *)type)->trust = TRUSTsystem; + type->toTypeFunction()->trust = TRUSTsystem; if (fes) fes->func->setUnsafe(); } @@ -3869,10 +3874,9 @@ bool FuncDeclaration::setUnsafe() bool FuncDeclaration::isNogc() { - assert(type->ty == Tfunction); if (flags & FUNCFLAGnogcInprocess) setGC(); - return ((TypeFunction *)type)->isnogc; + return type->toTypeFunction()->isnogc; } bool FuncDeclaration::isNogcBypassingInference() @@ -3891,7 +3895,7 @@ bool FuncDeclaration::setGC() if (flags & FUNCFLAGnogcInprocess) { flags &= ~FUNCFLAGnogcInprocess; - ((TypeFunction *)type)->isnogc = false; + type->toTypeFunction()->isnogc = false; if (fes) fes->func->setGC(); } @@ -4000,8 +4004,7 @@ bool traverseIndirections(Type *ta, Type *tb, void *p = NULL, bool reversePass = bool FuncDeclaration::isolateReturn() { - assert(type->ty == Tfunction); - TypeFunction *tf = (TypeFunction *)type; + TypeFunction *tf = type->toTypeFunction(); assert(tf->next); Type *treti = tf->next; @@ -4022,8 +4025,7 @@ bool FuncDeclaration::parametersIntersect(Type *t) if (!isPureBypassingInference() || isNested()) return false; - assert(type->ty == Tfunction); - TypeFunction *tf = (TypeFunction *)type; + TypeFunction *tf = type->toTypeFunction(); //printf("parametersIntersect(%s) t = %s\n", tf->toChars(), t->toChars()); @@ -4229,7 +4231,7 @@ FuncDeclaration *FuncDeclaration::genCfunc(Parameters *fparams, Type *treturn, I */ void FuncDeclaration::checkDmain() { - TypeFunction *tf = (TypeFunction *)type; + TypeFunction *tf = type->toTypeFunction(); const size_t nparams = Parameter::dim(tf->parameters); bool argerr = false; if (nparams == 1) @@ -4608,8 +4610,7 @@ Parameters *FuncDeclaration::getParameters(int *pvarargs) if (type) { - assert(type->ty == Tfunction); - TypeFunction *fdtype = (TypeFunction *)type; + TypeFunction *fdtype = type->toTypeFunction(); fparameters = fdtype->parameters; fvarargs = fdtype->varargs; } @@ -4752,7 +4753,7 @@ void FuncLiteralDeclaration::modifyReturns(Scope *sc, Type *tret) // This is required so the code generator does not try to cast the // modified returns back to the original type. if (inferRetType && type->nextOf() != tret) - ((TypeFunction *)type)->next = tret; + type->toTypeFunction()->next = tret; } const char *FuncLiteralDeclaration::kind() const @@ -4820,8 +4821,7 @@ void CtorDeclaration::semantic(Scope *sc) if (errors) return; - TypeFunction *tf = (TypeFunction *)type; - assert(tf && tf->ty == Tfunction); + TypeFunction *tf = type->toTypeFunction(); /* See if it's the default constructor * But, template constructor should not become a default constructor. @@ -5502,10 +5502,9 @@ void NewDeclaration::semantic(Scope *sc) type = new TypeFunction(parameters, tret, varargs, LINKd, storage_class); type = type->semantic(loc, sc); - assert(type->ty == Tfunction); // Check that there is at least one argument of type size_t - TypeFunction *tf = (TypeFunction *)type; + TypeFunction *tf = type->toTypeFunction(); if (Parameter::dim(tf->parameters) < 1) { error("at least one argument of type size_t expected"); @@ -5581,10 +5580,9 @@ void DeleteDeclaration::semantic(Scope *sc) type = new TypeFunction(parameters, Type::tvoid, 0, LINKd, storage_class); type = type->semantic(loc, sc); - assert(type->ty == Tfunction); // Check that there is only one argument of type void* - TypeFunction *tf = (TypeFunction *)type; + TypeFunction *tf = type->toTypeFunction(); if (Parameter::dim(tf->parameters) != 1) { error("one argument of type void* expected"); diff --git a/gcc/d/dmd/mtype.c b/gcc/d/dmd/mtype.c index b35b7af3201..52598033832 100644 --- a/gcc/d/dmd/mtype.c +++ b/gcc/d/dmd/mtype.c @@ -2345,6 +2345,12 @@ TypeBasic *Type::isTypeBasic() return NULL; } +TypeFunction *Type::toTypeFunction() +{ + if (ty != Tfunction) + assert(0); + return (TypeFunction *)this; +} /*************************************** * Resolve 'this' type to either type, symbol, or expression. @@ -4808,14 +4814,14 @@ Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int Parameters *fparams = new Parameters(); fparams->push(new Parameter(STCin, this, NULL, NULL)); fd_aaLen = FuncDeclaration::genCfunc(fparams, Type::tsize_t, Id::aaLen); - TypeFunction *tf = (TypeFunction *)fd_aaLen->type; + TypeFunction *tf = fd_aaLen->type->toTypeFunction(); tf->purity = PUREconst; tf->isnothrow = true; tf->isnogc = false; } Expression *ev = new VarExp(e->loc, fd_aaLen, false); e = new CallExp(e->loc, ev, e); - e->type = ((TypeFunction *)fd_aaLen->type)->next; + e->type = fd_aaLen->type->toTypeFunction()->next; } else e = Type::dotExp(sc, e, ident, flag); @@ -5425,7 +5431,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) * This can produce redundant copies if inferring return type, * as semantic() will get called again on this. */ - TypeFunction *tf = (TypeFunction *)copy(); + TypeFunction *tf = copy()->toTypeFunction(); if (parameters) { tf->parameters = parameters->copy(); @@ -6283,7 +6289,7 @@ Expression *TypeFunction::defaultInit(Loc loc) Type *TypeFunction::addStorageClass(StorageClass stc) { //printf("addStorageClass(%llx) %d\n", stc, (stc & STCscope) != 0); - TypeFunction *t = (TypeFunction *)Type::addStorageClass(stc); + TypeFunction *t = Type::addStorageClass(stc)->toTypeFunction(); if ((stc & STCpure && !t->purity) || (stc & STCnothrow && !t->isnothrow) || (stc & STCnogc && !t->isnogc) || @@ -9181,7 +9187,7 @@ Type *Parameter::isLazyArray() if (tel->ty == Tdelegate) { TypeDelegate *td = (TypeDelegate *)tel; - TypeFunction *tf = (TypeFunction *)td->next; + TypeFunction *tf = td->next->toTypeFunction(); if (!tf->varargs && Parameter::dim(tf->parameters) == 0) { diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h index c3b8a979bbe..b459fdf869f 100644 --- a/gcc/d/dmd/mtype.h +++ b/gcc/d/dmd/mtype.h @@ -335,6 +335,7 @@ public: virtual bool needsDestruction(); virtual bool needsNested(); void checkComplexTransition(Loc loc); + TypeFunction *toTypeFunction(); static void error(Loc loc, const char *format, ...); static void warning(Loc loc, const char *format, ...);