mirror of git://gcc.gnu.org/git/gcc.git
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:
parent
22b04f05ab
commit
4d814b6989
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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, ...);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue