mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-02-26 16:43:13 +01:00
Merge dmd 1.056.
This commit is contained in:
205
dmd/func.c
205
dmd/func.c
@@ -1,5 +1,5 @@
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -65,7 +65,7 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
|
||||
inlineNest = 0;
|
||||
inlineAsm = 0;
|
||||
cantInterpret = 0;
|
||||
semanticRun = 0;
|
||||
semanticRun = PASSinit;
|
||||
#if DMDV1
|
||||
nestedFrameRef = 0;
|
||||
#endif
|
||||
@@ -131,8 +131,9 @@ Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
|
||||
f->fbody = fbody ? fbody->syntaxCopy() : NULL;
|
||||
assert(!fthrows); // deprecated
|
||||
|
||||
// LDC
|
||||
#if IN_LLVM
|
||||
f->intrinsicName = intrinsicName;
|
||||
#endif
|
||||
|
||||
return f;
|
||||
}
|
||||
@@ -155,7 +156,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
printf("type: %p, %s\n", type, type->toChars());
|
||||
#endif
|
||||
|
||||
if (semanticRun && isFuncLiteralDeclaration())
|
||||
if (semanticRun != PASSinit && isFuncLiteralDeclaration())
|
||||
{
|
||||
/* Member functions that have return types that are
|
||||
* forward references can have semantic() run more than
|
||||
@@ -164,8 +165,24 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
*/
|
||||
return;
|
||||
}
|
||||
assert(semanticRun <= 1);
|
||||
semanticRun = 1;
|
||||
parent = sc->parent;
|
||||
Dsymbol *parent = toParent();
|
||||
|
||||
if (semanticRun == PASSsemanticdone)
|
||||
{
|
||||
if (!parent->isClassDeclaration())
|
||||
return;
|
||||
// need to re-run semantic() in order to set the class's vtbl[]
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(semanticRun <= PASSsemantic);
|
||||
semanticRun = PASSsemantic;
|
||||
}
|
||||
|
||||
unsigned dprogress_save = Module::dprogress;
|
||||
|
||||
foverrides.setDim(0); // reset in case semantic() is being retried for this function
|
||||
|
||||
if (!type->deco)
|
||||
{
|
||||
@@ -181,15 +198,9 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
size_t nparams = Parameter::dim(f->parameters);
|
||||
|
||||
linkage = sc->linkage;
|
||||
// if (!parent)
|
||||
{
|
||||
//parent = sc->scopesym;
|
||||
parent = sc->parent;
|
||||
}
|
||||
protection = sc->protection;
|
||||
storage_class |= sc->stc;
|
||||
//printf("function storage_class = x%x\n", storage_class);
|
||||
Dsymbol *parent = toParent();
|
||||
|
||||
if (ident == Id::ctor && !isCtorDeclaration())
|
||||
error("_ctor is reserved for constructors");
|
||||
@@ -267,7 +278,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
isInvariantDeclaration() ||
|
||||
isUnitTestDeclaration() || isNewDeclaration() || isDelete())
|
||||
error("special function not allowed in interface %s", id->toChars());
|
||||
if (fbody)
|
||||
if (fbody && isVirtual())
|
||||
error("function body is not abstract in interface %s", id->toChars());
|
||||
}
|
||||
|
||||
@@ -337,8 +348,12 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
goto Ldone;
|
||||
}
|
||||
|
||||
// Find index of existing function in vtbl[] to override
|
||||
vi = findVtblIndex(&cd->vtbl, cd->baseClass ? cd->baseClass->vtbl.dim : 0);
|
||||
/* Find index of existing function in base class's vtbl[] to override
|
||||
* (the index will be the same as in cd's current vtbl[])
|
||||
*/
|
||||
vi = cd->baseClass ? findVtblIndex(&cd->baseClass->vtbl, cd->baseClass->vtbl.dim)
|
||||
: -1;
|
||||
|
||||
switch (vi)
|
||||
{
|
||||
case -1:
|
||||
@@ -378,10 +393,11 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
|
||||
case -2: // can't determine because of fwd refs
|
||||
cd->sizeok = 2; // can't finish due to forward reference
|
||||
Module::dprogress = dprogress_save;
|
||||
return;
|
||||
|
||||
default:
|
||||
{ FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi];
|
||||
{ FuncDeclaration *fdv = (FuncDeclaration *)cd->baseClass->vtbl.data[vi];
|
||||
// This function is covariant with fdv
|
||||
if (fdv->isFinal())
|
||||
error("cannot override final function %s", fdv->toPrettyChars());
|
||||
@@ -455,6 +471,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
|
||||
case -2:
|
||||
cd->sizeok = 2; // can't finish due to forward reference
|
||||
Module::dprogress = dprogress_save;
|
||||
return;
|
||||
|
||||
default:
|
||||
@@ -472,19 +489,22 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
/* Only need to have a tintro if the vptr
|
||||
* offsets differ
|
||||
*/
|
||||
unsigned errors = global.errors;
|
||||
global.gag++; // suppress printing of error messages
|
||||
int offset;
|
||||
if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
|
||||
int baseOf = fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset);
|
||||
global.gag--; // suppress printing of error messages
|
||||
if (errors != global.errors)
|
||||
{
|
||||
// any error in isBaseOf() is a forward reference error, so we bail out
|
||||
global.errors = errors;
|
||||
cd->sizeok = 2; // can't finish due to forward reference
|
||||
Module::dprogress = dprogress_save;
|
||||
return;
|
||||
}
|
||||
if (baseOf)
|
||||
{
|
||||
ti = fdv->type;
|
||||
#if 0
|
||||
if (offset)
|
||||
ti = fdv->type;
|
||||
else if (type->nextOf()->ty == Tclass)
|
||||
{ ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
|
||||
if (cdn && cdn->sizeok != 1)
|
||||
ti = fdv->type;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (ti)
|
||||
@@ -596,7 +616,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
}
|
||||
|
||||
if (isVirtual())
|
||||
if (isVirtual() && semanticRun != PASSsemanticdone)
|
||||
{
|
||||
/* Rewrite contracts as nested functions, then call them.
|
||||
* Doing it as nested functions means that overriding functions
|
||||
@@ -652,6 +672,9 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
|
||||
Ldone:
|
||||
Module::dprogress++;
|
||||
semanticRun = PASSsemanticdone;
|
||||
|
||||
/* Save scope for possible later use (if we need the
|
||||
* function internals)
|
||||
*/
|
||||
@@ -688,14 +711,14 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
//printf("\tlinkage = %d\n", sc->linkage);
|
||||
|
||||
//printf(" sc->incontract = %d\n", sc->incontract);
|
||||
if (semanticRun >= 3)
|
||||
if (semanticRun >= PASSsemantic3)
|
||||
return;
|
||||
semanticRun = 3;
|
||||
semanticRun = PASSsemantic3;
|
||||
|
||||
// LDC
|
||||
#if IN_LLVM
|
||||
if (!global.params.useAvailableExternally)
|
||||
availableExternally = false;
|
||||
|
||||
#endif
|
||||
if (!type || type->ty != Tfunction)
|
||||
return;
|
||||
f = (TypeFunction *)(type);
|
||||
@@ -1466,7 +1489,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
sc2->callSuper = 0;
|
||||
sc2->pop();
|
||||
}
|
||||
semanticRun = 4;
|
||||
semanticRun = PASSsemantic3done;
|
||||
}
|
||||
|
||||
void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
@@ -1638,6 +1661,7 @@ int FuncDeclaration::overrides(FuncDeclaration *fd)
|
||||
/*************************************************
|
||||
* Find index of function in vtbl[0..dim] that
|
||||
* this function overrides.
|
||||
* Prefer an exact match to a covariant one.
|
||||
* Returns:
|
||||
* -1 didn't find one
|
||||
* -2 can't determine because of forward references
|
||||
@@ -1645,11 +1669,16 @@ int FuncDeclaration::overrides(FuncDeclaration *fd)
|
||||
|
||||
int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
|
||||
{
|
||||
FuncDeclaration *mismatch = NULL;
|
||||
int bestvi = -1;
|
||||
for (int vi = 0; vi < dim; vi++)
|
||||
{
|
||||
FuncDeclaration *fdv = ((Dsymbol *)vtbl->data[vi])->isFuncDeclaration();
|
||||
if (fdv && fdv->ident == ident)
|
||||
{
|
||||
if (type->equals(fdv->type)) // if exact match
|
||||
return vi; // no need to look further
|
||||
|
||||
int cov = type->covariant(fdv->type);
|
||||
//printf("\tbaseclass cov = %d\n", cov);
|
||||
switch (cov)
|
||||
@@ -1658,15 +1687,12 @@ int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
|
||||
break;
|
||||
|
||||
case 1:
|
||||
return vi;
|
||||
bestvi = vi; // covariant, but not identical
|
||||
break; // keep looking for an exact match
|
||||
|
||||
case 2:
|
||||
//type->print();
|
||||
//fdv->type->print();
|
||||
//printf("%s %s\n", type->deco, fdv->type->deco);
|
||||
error("of type %s overrides but is not covariant with %s of type %s",
|
||||
type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
|
||||
break;
|
||||
mismatch = fdv; // overrides, but is not covariant
|
||||
break; // keep looking for an exact match
|
||||
|
||||
case 3:
|
||||
return -2; // forward references
|
||||
@@ -1676,7 +1702,15 @@ int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
if (bestvi == -1 && mismatch)
|
||||
{
|
||||
//type->print();
|
||||
//mismatch->type->print();
|
||||
//printf("%s %s\n", type->deco, mismatch->type->deco);
|
||||
error("of type %s overrides but is not covariant with %s of type %s",
|
||||
type->toChars(), mismatch->toPrettyChars(), mismatch->type->toChars());
|
||||
}
|
||||
return bestvi;
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
@@ -2554,7 +2588,7 @@ FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
|
||||
id = "__dgliteral";
|
||||
else
|
||||
id = "__funcliteral";
|
||||
this->ident = Identifier::generateId(id);
|
||||
this->ident = Lexer::uniqueId(id);
|
||||
this->tok = tok;
|
||||
this->fes = fes;
|
||||
//printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
|
||||
@@ -2568,7 +2602,9 @@ Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
|
||||
if (s)
|
||||
f = (FuncLiteralDeclaration *)s;
|
||||
else
|
||||
f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
|
||||
{ f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
|
||||
f->ident = ident; // keep old identifier
|
||||
}
|
||||
FuncDeclaration::syntaxCopy(f);
|
||||
return f;
|
||||
}
|
||||
@@ -2634,19 +2670,14 @@ Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
|
||||
|
||||
void CtorDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
ClassDeclaration *cd;
|
||||
Type *tret;
|
||||
|
||||
//printf("CtorDeclaration::semantic()\n");
|
||||
if (type)
|
||||
return;
|
||||
|
||||
//printf("CtorDeclaration::semantic() %s\n", toChars());
|
||||
sc = sc->push();
|
||||
sc->stc &= ~STCstatic; // not a static constructor
|
||||
|
||||
parent = sc->parent;
|
||||
Dsymbol *parent = toParent();
|
||||
cd = parent->isClassDeclaration();
|
||||
Type *tret;
|
||||
ClassDeclaration *cd = parent->isClassDeclaration();
|
||||
if (!cd)
|
||||
{
|
||||
error("constructors are only for class definitions");
|
||||
@@ -2655,7 +2686,8 @@ void CtorDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
else
|
||||
tret = cd->type; //->referenceTo();
|
||||
type = new TypeFunction(arguments, tret, varargs, LINKd);
|
||||
if (!type)
|
||||
type = new TypeFunction(arguments, tret, varargs, LINKd);
|
||||
#if STRUCTTHISREF
|
||||
if (ad && ad->isStructDeclaration())
|
||||
((TypeFunction *)type)->isref = 1;
|
||||
@@ -2670,7 +2702,7 @@ void CtorDeclaration::semantic(Scope *sc)
|
||||
// Append:
|
||||
// return this;
|
||||
// to the function body
|
||||
if (fbody)
|
||||
if (fbody && semanticRun < PASSsemantic)
|
||||
{
|
||||
Expression *e = new ThisExp(loc);
|
||||
Statement *s = new ReturnStatement(loc, e);
|
||||
@@ -2744,6 +2776,7 @@ void PostBlitDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
//printf("PostBlitDeclaration::semantic() %s\n", toChars());
|
||||
//printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
|
||||
//printf("stc = x%llx\n", sc->stc);
|
||||
parent = sc->parent;
|
||||
Dsymbol *parent = toParent();
|
||||
StructDeclaration *ad = parent->isStructDeclaration();
|
||||
@@ -2751,9 +2784,11 @@ void PostBlitDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
error("post blits are only for struct/union definitions, not %s %s", parent->kind(), parent->toChars());
|
||||
}
|
||||
else if (ident == Id::_postblit)
|
||||
else if (ident == Id::_postblit && semanticRun < PASSsemantic)
|
||||
ad->postblits.push(this);
|
||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
||||
|
||||
if (!type)
|
||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
||||
|
||||
sc = sc->push();
|
||||
sc->stc &= ~STCstatic; // not static
|
||||
@@ -2786,9 +2821,7 @@ int PostBlitDeclaration::isVirtual()
|
||||
|
||||
void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (hgs->hdrgen)
|
||||
return;
|
||||
buf->writestring("=this()");
|
||||
buf->writestring("this(this)");
|
||||
bodyToCBuffer(buf, hgs);
|
||||
}
|
||||
#endif
|
||||
@@ -2825,9 +2858,11 @@ void DtorDeclaration::semantic(Scope *sc)
|
||||
error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars());
|
||||
fatal();
|
||||
}
|
||||
else
|
||||
else if (semanticRun < PASSsemantic)
|
||||
cd->dtors.push(this);
|
||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
||||
|
||||
if (!type)
|
||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
||||
|
||||
sc = sc->push();
|
||||
sc->stc &= ~STCstatic; // not a static destructor
|
||||
@@ -2893,10 +2928,8 @@ StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
|
||||
|
||||
Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
|
||||
{
|
||||
StaticCtorDeclaration *scd;
|
||||
|
||||
assert(!s);
|
||||
scd = new StaticCtorDeclaration(loc, endloc);
|
||||
StaticCtorDeclaration *scd = new StaticCtorDeclaration(loc, endloc);
|
||||
return FuncDeclaration::syntaxCopy(scd);
|
||||
}
|
||||
|
||||
@@ -2905,13 +2938,14 @@ void StaticCtorDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
//printf("StaticCtorDeclaration::semantic()\n");
|
||||
|
||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
||||
if (!type)
|
||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
||||
|
||||
/* If the static ctor appears within a template instantiation,
|
||||
* it could get called multiple times by the module constructors
|
||||
* for different modules. Thus, protect it with a gate.
|
||||
*/
|
||||
if (inTemplateInstance())
|
||||
if (inTemplateInstance() && semanticRun < PASSsemantic)
|
||||
{
|
||||
/* Add this prefix to the function:
|
||||
* static int gate;
|
||||
@@ -2943,6 +2977,7 @@ void StaticCtorDeclaration::semantic(Scope *sc)
|
||||
m = sc->module;
|
||||
if (m)
|
||||
{ m->needmoduleinfo = 1;
|
||||
//printf("module1 %s needs moduleinfo\n", m->toChars());
|
||||
#ifdef IN_GCC
|
||||
m->strictlyneedmoduleinfo = 1;
|
||||
#endif
|
||||
@@ -3005,20 +3040,16 @@ Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
|
||||
|
||||
void StaticDtorDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
ClassDeclaration *cd;
|
||||
Type *tret;
|
||||
ClassDeclaration *cd = sc->scopesym->isClassDeclaration();
|
||||
|
||||
cd = sc->scopesym->isClassDeclaration();
|
||||
if (!cd)
|
||||
{
|
||||
}
|
||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
||||
if (!type)
|
||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
||||
|
||||
/* If the static ctor appears within a template instantiation,
|
||||
* it could get called multiple times by the module constructors
|
||||
* for different modules. Thus, protect it with a gate.
|
||||
*/
|
||||
if (inTemplateInstance())
|
||||
if (inTemplateInstance() && semanticRun < PASSsemantic)
|
||||
{
|
||||
/* Add this prefix to the function:
|
||||
* static int gate;
|
||||
@@ -3112,23 +3143,21 @@ Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
|
||||
|
||||
void InvariantDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
AggregateDeclaration *ad;
|
||||
Type *tret;
|
||||
|
||||
parent = sc->parent;
|
||||
Dsymbol *parent = toParent();
|
||||
ad = parent->isAggregateDeclaration();
|
||||
AggregateDeclaration *ad = parent->isAggregateDeclaration();
|
||||
if (!ad)
|
||||
{
|
||||
error("invariants are only for struct/union/class definitions");
|
||||
return;
|
||||
}
|
||||
else if (ad->inv && ad->inv != this)
|
||||
else if (ad->inv && ad->inv != this && semanticRun < PASSsemantic)
|
||||
{
|
||||
error("more than one invariant for %s", ad->toChars());
|
||||
}
|
||||
ad->inv = this;
|
||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
||||
if (!type)
|
||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
||||
|
||||
sc = sc->push();
|
||||
sc->stc &= ~STCstatic; // not a static invariant
|
||||
@@ -3195,7 +3224,8 @@ void UnitTestDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
if (global.params.useUnitTests)
|
||||
{
|
||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
||||
if (!type)
|
||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
||||
Scope *sc2 = sc->push();
|
||||
sc2->linkage = LINKd;
|
||||
FuncDeclaration::semantic(sc2);
|
||||
@@ -3271,20 +3301,18 @@ Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s)
|
||||
|
||||
void NewDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
ClassDeclaration *cd;
|
||||
Type *tret;
|
||||
|
||||
//printf("NewDeclaration::semantic()\n");
|
||||
|
||||
parent = sc->parent;
|
||||
Dsymbol *parent = toParent();
|
||||
cd = parent->isClassDeclaration();
|
||||
ClassDeclaration *cd = parent->isClassDeclaration();
|
||||
if (!cd && !parent->isStructDeclaration())
|
||||
{
|
||||
error("new allocators only are for class or struct definitions");
|
||||
}
|
||||
tret = Type::tvoid->pointerTo();
|
||||
type = new TypeFunction(arguments, tret, varargs, LINKd);
|
||||
Type *tret = Type::tvoid->pointerTo();
|
||||
if (!type)
|
||||
type = new TypeFunction(arguments, tret, varargs, LINKd);
|
||||
|
||||
type = type->semantic(loc, sc);
|
||||
assert(type->ty == Tfunction);
|
||||
@@ -3357,18 +3385,17 @@ Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s)
|
||||
|
||||
void DeleteDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
ClassDeclaration *cd;
|
||||
|
||||
//printf("DeleteDeclaration::semantic()\n");
|
||||
|
||||
parent = sc->parent;
|
||||
Dsymbol *parent = toParent();
|
||||
cd = parent->isClassDeclaration();
|
||||
ClassDeclaration *cd = parent->isClassDeclaration();
|
||||
if (!cd && !parent->isStructDeclaration())
|
||||
{
|
||||
error("new allocators only are for class or struct definitions");
|
||||
}
|
||||
type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
|
||||
if (!type)
|
||||
type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
|
||||
|
||||
type = type->semantic(loc, sc);
|
||||
assert(type->ty == Tfunction);
|
||||
|
||||
Reference in New Issue
Block a user