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
merge done from the dlang/dmd repository.

View File

@ -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())
{

View File

@ -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

View File

@ -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");

View File

@ -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)
{

View File

@ -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, ...);