Merge 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.

Reviewed-on: https://github.com/dlang/dmd/pull/9054

From-SVN: r267207
This commit is contained in:
Iain Buclaw 2018-12-17 18:32:31 +00:00
parent 22b04f05ab
commit 4d814b6989
6 changed files with 59 additions and 53 deletions

View File

@ -1,4 +1,4 @@
e2fe2687b817a201528abaa3aa882333e04db01b 237ca3fbe8f9ac4b64e26ce912c20439ee4fc63a
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository. merge done from the dlang/dmd repository.

View File

@ -805,7 +805,7 @@ Lancestorsdone:
if (fd && !fd->errors) if (fd && !fd->errors)
{ {
//printf("Creating default this(){} for class %s\n", toChars()); //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); TypeFunction *tf = new TypeFunction(NULL, NULL, 0, LINKd, fd->storage_class);
tf->mod = btf->mod; tf->mod = btf->mod;
tf->purity = btf->purity; tf->purity = btf->purity;
@ -1152,7 +1152,7 @@ int isf(void *param, Dsymbol *s)
bool ClassDeclaration::isFuncHidden(FuncDeclaration *fd) 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); Dsymbol *s = search(Loc(), fd->ident, IgnoreAmbiguous | IgnoreErrors);
if (!s) if (!s)
{ {
@ -1749,6 +1749,7 @@ bool InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
//printf("\tX base %s\n", b->sym->toChars()); //printf("\tX base %s\n", b->sym->toChars());
if (this == b->sym) if (this == b->sym)
{ {
//printf("\tfound at offset %d\n", b->offset);
if (poffset) if (poffset)
{ {
// don't return incorrect offsets https://issues.dlang.org/show_bug.cgi?id=16980 // 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); assert(ifd);
// Find corresponding function in this class // Find corresponding function in this class
tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL; tf = ifd->type->toTypeFunction();
assert(tf); // should always be non-null
fd = cd->findFunc(ifd->ident, tf); fd = cd->findFunc(ifd->ident, tf);
if (fd && !fd->isAbstract()) if (fd && !fd->isAbstract())
{ {

View File

@ -46,7 +46,7 @@ FuncDeclaration *search_toString(StructDeclaration *sd)
if (!tftostring) if (!tftostring)
{ {
tftostring = new TypeFunction(NULL, Type::tstring, 0, LINKd); tftostring = new TypeFunction(NULL, Type::tstring, 0, LINKd);
tftostring = (TypeFunction *)tftostring->merge(); tftostring = tftostring->merge()->toTypeFunction();
} }
fd = fd->overloadExactMatch(tftostring); fd = fd->overloadExactMatch(tftostring);
@ -92,6 +92,7 @@ void semanticTypeInfo(Scope *sc, Type *t)
} }
void visit(TypeStruct *t) void visit(TypeStruct *t)
{ {
//printf("semanticTypeInfo::visit(TypeStruct = %s)\n", t->toChars());
StructDeclaration *sd = t->sym; StructDeclaration *sd = t->sym;
/* Step 1: create TypeInfoDeclaration /* Step 1: create TypeInfoDeclaration

View File

@ -411,8 +411,8 @@ static bool canInferAttributes(FuncDeclaration *fd, Scope *sc)
*/ */
static void initInferAttributes(FuncDeclaration *fd) static void initInferAttributes(FuncDeclaration *fd)
{ {
assert(fd->type->ty == Tfunction); //printf("initInferAttributes() for %s\n", toPrettyChars());
TypeFunction *tf = (TypeFunction *)fd->type; TypeFunction *tf = fd->type->toTypeFunction();
if (tf->purity == PUREimpure) // purity not specified if (tf->purity == PUREimpure) // purity not specified
fd->flags |= FUNCFLAGpurityInprocess; fd->flags |= FUNCFLAGpurityInprocess;
@ -495,7 +495,7 @@ void FuncDeclaration::semantic(Scope *sc)
fld->tok = TOKfunction; fld->tok = TOKfunction;
else else
assert(0); assert(0);
linkage = ((TypeFunction *)treq->nextOf())->linkage; linkage = treq->nextOf()->toTypeFunction()->linkage;
} }
else else
linkage = sc->linkage; linkage = sc->linkage;
@ -505,11 +505,21 @@ void FuncDeclaration::semantic(Scope *sc)
if (!originalType) if (!originalType)
originalType = type->syntaxCopy(); 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) if (!type->deco)
{ {
sc = sc->push(); sc = sc->push();
sc->stc |= storage_class & (STCdisable | STCdeprecated); // forward to function type sc->stc |= storage_class & (STCdisable | STCdeprecated); // forward to function type
TypeFunction *tf = (TypeFunction *)type; TypeFunction *tf = type->toTypeFunction();
if (sc->func) if (sc->func)
{ {
@ -678,8 +688,8 @@ void FuncDeclaration::semantic(Scope *sc)
{ {
// Merge back function attributes into 'originalType'. // Merge back function attributes into 'originalType'.
// It's used for mangling, ddoc, and json output. // It's used for mangling, ddoc, and json output.
TypeFunction *tfo = (TypeFunction *)originalType; TypeFunction *tfo = originalType->toTypeFunction();
TypeFunction *tfx = (TypeFunction *)type; TypeFunction *tfx = type->toTypeFunction();
tfo->mod = tfx->mod; tfo->mod = tfx->mod;
tfo->isscope = tfx->isscope; tfo->isscope = tfx->isscope;
tfo->isscopeinferred = tfx->isscopeinferred; tfo->isscopeinferred = tfx->isscopeinferred;
@ -1132,8 +1142,7 @@ void FuncDeclaration::semantic(Scope *sc)
error("override only applies to class member functions"); error("override only applies to class member functions");
// Reflect this->type to f because it could be changed by findVtblIndex // Reflect this->type to f because it could be changed by findVtblIndex
assert(type->ty == Tfunction); f = type->toTypeFunction();
f = (TypeFunction *)type;
/* Do not allow template instances to add virtual functions /* Do not allow template instances to add virtual functions
* to a class. * to a class.
@ -2560,8 +2569,7 @@ void FuncDeclaration::buildResultVar(Scope *sc, Type *tret)
if (sc && vresult->semanticRun == PASSinit) if (sc && vresult->semanticRun == PASSinit)
{ {
assert(type->ty == Tfunction); TypeFunction *tf = type->toTypeFunction();
TypeFunction *tf = (TypeFunction *)type;
if (tf->isref) if (tf->isref)
vresult->storage_class |= STCref; vresult->storage_class |= STCref;
vresult->type = tret; vresult->type = tret;
@ -3135,7 +3143,7 @@ FuncDeclaration *FuncDeclaration::overloadModMatch(Loc loc, Type *tthis, bool &h
return 0; return 0;
m->anyf = f; m->anyf = f;
TypeFunction *tf = (TypeFunction *)f->type; TypeFunction *tf = f->type->toTypeFunction();
//printf("tf = %s\n", tf->toChars()); //printf("tf = %s\n", tf->toChars());
MATCH match; MATCH match;
@ -3205,7 +3213,7 @@ FuncDeclaration *FuncDeclaration::overloadModMatch(Loc loc, Type *tthis, bool &h
else // no match else // no match
{ {
hasOverloads = true; hasOverloads = true;
TypeFunction *tf = (TypeFunction *)this->type; TypeFunction *tf = this->type->toTypeFunction();
assert(tthis); assert(tthis);
assert(!MODimplicitConv(tthis->mod, tf->mod)); // modifier mismatch assert(!MODimplicitConv(tthis->mod, tf->mod)); // modifier mismatch
{ {
@ -3270,8 +3278,8 @@ MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
* as g() is. * as g() is.
*/ */
TypeFunction *tf = (TypeFunction *)type; TypeFunction *tf = type->toTypeFunction();
TypeFunction *tg = (TypeFunction *)g->type; TypeFunction *tg = g->type->toTypeFunction();
size_t nfparams = Parameter::dim(tf->parameters); size_t nfparams = Parameter::dim(tf->parameters);
/* If both functions have a 'this' pointer, and the mods are not /* 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); assert(fd);
bool hasOverloads = fd->overnext != NULL; bool hasOverloads = fd->overnext != NULL;
TypeFunction *tf = (TypeFunction *)fd->type; TypeFunction *tf = fd->type->toTypeFunction();
if (tthis && !MODimplicitConv(tthis->mod, tf->mod)) // modifier mismatch if (tthis && !MODimplicitConv(tthis->mod, tf->mod)) // modifier mismatch
{ {
OutBuffer thisBuf, funcBuf; OutBuffer thisBuf, funcBuf;
@ -3562,8 +3570,8 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
} }
else if (m.nextf) else if (m.nextf)
{ {
TypeFunction *tf1 = (TypeFunction *)m.lastf->type; TypeFunction *tf1 = m.lastf->type->toTypeFunction();
TypeFunction *tf2 = (TypeFunction *)m.nextf->type; TypeFunction *tf2 = m.nextf->type->toTypeFunction();
const char *lastprms = parametersTypeToChars(tf1->parameters, tf1->varargs); const char *lastprms = parametersTypeToChars(tf1->parameters, tf1->varargs);
const char *nextprms = parametersTypeToChars(tf2->parameters, tf2->varargs); const char *nextprms = parametersTypeToChars(tf2->parameters, tf2->varargs);
::error(loc, "%s.%s called with argument types %s matches both:\n" ::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() const char *FuncDeclaration::toFullSignature()
{ {
OutBuffer buf; OutBuffer buf;
functionToBufferWithIdent((TypeFunction *)type, &buf, toChars()); functionToBufferWithIdent(type->toTypeFunction(), &buf, toChars());
return buf.extractString(); return buf.extractString();
} }
@ -3776,8 +3784,7 @@ bool FuncDeclaration::isOverloadable()
PURE FuncDeclaration::isPure() PURE FuncDeclaration::isPure()
{ {
//printf("FuncDeclaration::isPure() '%s'\n", toChars()); //printf("FuncDeclaration::isPure() '%s'\n", toChars());
assert(type->ty == Tfunction); TypeFunction *tf = type->toTypeFunction();
TypeFunction *tf = (TypeFunction *)type;
if (flags & FUNCFLAGpurityInprocess) if (flags & FUNCFLAGpurityInprocess)
setImpure(); setImpure();
if (tf->purity == PUREfwdref) if (tf->purity == PUREfwdref)
@ -3829,10 +3836,9 @@ bool FuncDeclaration::setImpure()
bool FuncDeclaration::isSafe() bool FuncDeclaration::isSafe()
{ {
assert(type->ty == Tfunction);
if (flags & FUNCFLAGsafetyInprocess) if (flags & FUNCFLAGsafetyInprocess)
setUnsafe(); setUnsafe();
return ((TypeFunction *)type)->trust == TRUSTsafe; return type->toTypeFunction()->trust == TRUSTsafe;
} }
bool FuncDeclaration::isSafeBypassingInference() bool FuncDeclaration::isSafeBypassingInference()
@ -3842,10 +3848,9 @@ bool FuncDeclaration::isSafeBypassingInference()
bool FuncDeclaration::isTrusted() bool FuncDeclaration::isTrusted()
{ {
assert(type->ty == Tfunction);
if (flags & FUNCFLAGsafetyInprocess) if (flags & FUNCFLAGsafetyInprocess)
setUnsafe(); setUnsafe();
return ((TypeFunction *)type)->trust == TRUSTtrusted; return type->toTypeFunction()->trust == TRUSTtrusted;
} }
/************************************** /**************************************
@ -3858,7 +3863,7 @@ bool FuncDeclaration::setUnsafe()
if (flags & FUNCFLAGsafetyInprocess) if (flags & FUNCFLAGsafetyInprocess)
{ {
flags &= ~FUNCFLAGsafetyInprocess; flags &= ~FUNCFLAGsafetyInprocess;
((TypeFunction *)type)->trust = TRUSTsystem; type->toTypeFunction()->trust = TRUSTsystem;
if (fes) if (fes)
fes->func->setUnsafe(); fes->func->setUnsafe();
} }
@ -3869,10 +3874,9 @@ bool FuncDeclaration::setUnsafe()
bool FuncDeclaration::isNogc() bool FuncDeclaration::isNogc()
{ {
assert(type->ty == Tfunction);
if (flags & FUNCFLAGnogcInprocess) if (flags & FUNCFLAGnogcInprocess)
setGC(); setGC();
return ((TypeFunction *)type)->isnogc; return type->toTypeFunction()->isnogc;
} }
bool FuncDeclaration::isNogcBypassingInference() bool FuncDeclaration::isNogcBypassingInference()
@ -3891,7 +3895,7 @@ bool FuncDeclaration::setGC()
if (flags & FUNCFLAGnogcInprocess) if (flags & FUNCFLAGnogcInprocess)
{ {
flags &= ~FUNCFLAGnogcInprocess; flags &= ~FUNCFLAGnogcInprocess;
((TypeFunction *)type)->isnogc = false; type->toTypeFunction()->isnogc = false;
if (fes) if (fes)
fes->func->setGC(); fes->func->setGC();
} }
@ -4000,8 +4004,7 @@ bool traverseIndirections(Type *ta, Type *tb, void *p = NULL, bool reversePass =
bool FuncDeclaration::isolateReturn() bool FuncDeclaration::isolateReturn()
{ {
assert(type->ty == Tfunction); TypeFunction *tf = type->toTypeFunction();
TypeFunction *tf = (TypeFunction *)type;
assert(tf->next); assert(tf->next);
Type *treti = tf->next; Type *treti = tf->next;
@ -4022,8 +4025,7 @@ bool FuncDeclaration::parametersIntersect(Type *t)
if (!isPureBypassingInference() || isNested()) if (!isPureBypassingInference() || isNested())
return false; return false;
assert(type->ty == Tfunction); TypeFunction *tf = type->toTypeFunction();
TypeFunction *tf = (TypeFunction *)type;
//printf("parametersIntersect(%s) t = %s\n", tf->toChars(), t->toChars()); //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() void FuncDeclaration::checkDmain()
{ {
TypeFunction *tf = (TypeFunction *)type; TypeFunction *tf = type->toTypeFunction();
const size_t nparams = Parameter::dim(tf->parameters); const size_t nparams = Parameter::dim(tf->parameters);
bool argerr = false; bool argerr = false;
if (nparams == 1) if (nparams == 1)
@ -4608,8 +4610,7 @@ Parameters *FuncDeclaration::getParameters(int *pvarargs)
if (type) if (type)
{ {
assert(type->ty == Tfunction); TypeFunction *fdtype = type->toTypeFunction();
TypeFunction *fdtype = (TypeFunction *)type;
fparameters = fdtype->parameters; fparameters = fdtype->parameters;
fvarargs = fdtype->varargs; 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 // This is required so the code generator does not try to cast the
// modified returns back to the original type. // modified returns back to the original type.
if (inferRetType && type->nextOf() != tret) if (inferRetType && type->nextOf() != tret)
((TypeFunction *)type)->next = tret; type->toTypeFunction()->next = tret;
} }
const char *FuncLiteralDeclaration::kind() const const char *FuncLiteralDeclaration::kind() const
@ -4820,8 +4821,7 @@ void CtorDeclaration::semantic(Scope *sc)
if (errors) if (errors)
return; return;
TypeFunction *tf = (TypeFunction *)type; TypeFunction *tf = type->toTypeFunction();
assert(tf && tf->ty == Tfunction);
/* See if it's the default constructor /* See if it's the default constructor
* But, template constructor should not become a 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 = new TypeFunction(parameters, tret, varargs, LINKd, storage_class);
type = type->semantic(loc, sc); type = type->semantic(loc, sc);
assert(type->ty == Tfunction);
// Check that there is at least one argument of type size_t // 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) if (Parameter::dim(tf->parameters) < 1)
{ {
error("at least one argument of type size_t expected"); 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 = new TypeFunction(parameters, Type::tvoid, 0, LINKd, storage_class);
type = type->semantic(loc, sc); type = type->semantic(loc, sc);
assert(type->ty == Tfunction);
// Check that there is only one argument of type void* // Check that there is only one argument of type void*
TypeFunction *tf = (TypeFunction *)type; TypeFunction *tf = type->toTypeFunction();
if (Parameter::dim(tf->parameters) != 1) if (Parameter::dim(tf->parameters) != 1)
{ {
error("one argument of type void* expected"); error("one argument of type void* expected");

View File

@ -2345,6 +2345,12 @@ TypeBasic *Type::isTypeBasic()
return NULL; return NULL;
} }
TypeFunction *Type::toTypeFunction()
{
if (ty != Tfunction)
assert(0);
return (TypeFunction *)this;
}
/*************************************** /***************************************
* Resolve 'this' type to either type, symbol, or expression. * 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(); Parameters *fparams = new Parameters();
fparams->push(new Parameter(STCin, this, NULL, NULL)); fparams->push(new Parameter(STCin, this, NULL, NULL));
fd_aaLen = FuncDeclaration::genCfunc(fparams, Type::tsize_t, Id::aaLen); 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->purity = PUREconst;
tf->isnothrow = true; tf->isnothrow = true;
tf->isnogc = false; tf->isnogc = false;
} }
Expression *ev = new VarExp(e->loc, fd_aaLen, false); Expression *ev = new VarExp(e->loc, fd_aaLen, false);
e = new CallExp(e->loc, ev, e); e = new CallExp(e->loc, ev, e);
e->type = ((TypeFunction *)fd_aaLen->type)->next; e->type = fd_aaLen->type->toTypeFunction()->next;
} }
else else
e = Type::dotExp(sc, e, ident, flag); 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, * This can produce redundant copies if inferring return type,
* as semantic() will get called again on this. * as semantic() will get called again on this.
*/ */
TypeFunction *tf = (TypeFunction *)copy(); TypeFunction *tf = copy()->toTypeFunction();
if (parameters) if (parameters)
{ {
tf->parameters = parameters->copy(); tf->parameters = parameters->copy();
@ -6283,7 +6289,7 @@ Expression *TypeFunction::defaultInit(Loc loc)
Type *TypeFunction::addStorageClass(StorageClass stc) Type *TypeFunction::addStorageClass(StorageClass stc)
{ {
//printf("addStorageClass(%llx) %d\n", stc, (stc & STCscope) != 0); //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) || if ((stc & STCpure && !t->purity) ||
(stc & STCnothrow && !t->isnothrow) || (stc & STCnothrow && !t->isnothrow) ||
(stc & STCnogc && !t->isnogc) || (stc & STCnogc && !t->isnogc) ||
@ -9181,7 +9187,7 @@ Type *Parameter::isLazyArray()
if (tel->ty == Tdelegate) if (tel->ty == Tdelegate)
{ {
TypeDelegate *td = (TypeDelegate *)tel; TypeDelegate *td = (TypeDelegate *)tel;
TypeFunction *tf = (TypeFunction *)td->next; TypeFunction *tf = td->next->toTypeFunction();
if (!tf->varargs && Parameter::dim(tf->parameters) == 0) if (!tf->varargs && Parameter::dim(tf->parameters) == 0)
{ {

View File

@ -335,6 +335,7 @@ public:
virtual bool needsDestruction(); virtual bool needsDestruction();
virtual bool needsNested(); virtual bool needsNested();
void checkComplexTransition(Loc loc); void checkComplexTransition(Loc loc);
TypeFunction *toTypeFunction();
static void error(Loc loc, const char *format, ...); static void error(Loc loc, const char *format, ...);
static void warning(Loc loc, const char *format, ...); static void warning(Loc loc, const char *format, ...);