Merge dmd 1.056.

This commit is contained in:
Robert Clipsham
2010-02-06 15:53:52 +00:00
parent 8176222719
commit daa102a5cd
29 changed files with 641 additions and 288 deletions

View File

@@ -392,12 +392,11 @@ void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d)
#endif
if (!e)
{
if (d->getModule() != sc->module)
if (d->prot() == PROTprivate ||
d->prot() == PROTpackage && !hasPackageAccess(sc, d))
if (d->prot() == PROTprivate && d->getModule() != sc->module ||
d->prot() == PROTpackage && !hasPackageAccess(sc, d))
error(loc, "%s %s.%s is not accessible from %s",
d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars());
error(loc, "%s %s.%s is not accessible from %s",
d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars());
}
else if (e->type->ty == Tclass)
{ // Do access check

View File

@@ -19,9 +19,11 @@
#include "dsymbol.h"
#if IN_LLVM
#include <vector>
#include <set>
#include <map>
#endif
struct Identifier;
struct Type;
@@ -38,6 +40,7 @@ struct ClassInfoDeclaration;
struct VarDeclaration;
struct dt_t;
#if IN_LLVM
namespace llvm
{
class Type;
@@ -46,6 +49,7 @@ namespace llvm
class ConstantStruct;
class GlobalVariable;
}
#endif
struct AggregateDeclaration : ScopeDsymbol
{

View File

@@ -24,6 +24,15 @@
#include "module.h"
#include "init.h"
#if IN_DMD
extern int binary(const char *p , const char **tab, int high);
/**************************************
* Hash table of array op functions already generated or known about.
*/
StringTable arrayfuncs;
#endif
/***********************************
* Construct the array operation expression.

View File

@@ -392,6 +392,8 @@ void StorageClassDeclaration::setScope(Scope *sc)
scstc &= ~(STCconst | STCimmutable | STCmanifest);
if (stc & (STCgshared | STCshared | STCtls))
scstc &= ~(STCgshared | STCshared | STCtls);
if (stc & (STCsafe | STCtrusted | STCsystem))
scstc &= ~(STCsafe | STCtrusted | STCsystem);
scstc |= stc;
setScopeNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
@@ -415,6 +417,8 @@ void StorageClassDeclaration::semantic(Scope *sc)
scstc &= ~(STCconst | STCimmutable | STCmanifest);
if (stc & (STCgshared | STCshared | STCtls))
scstc &= ~(STCgshared | STCshared | STCtls);
if (stc & (STCsafe | STCtrusted | STCsystem))
scstc &= ~(STCsafe | STCtrusted | STCsystem);
scstc |= stc;
semanticNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
@@ -453,6 +457,10 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
{ STCref, TOKref },
{ STCtls, TOKtls },
{ STCgshared, TOKgshared },
{ STCproperty, TOKat },
{ STCsafe, TOKat },
{ STCtrusted, TOKat },
{ STCdisable, TOKat },
#endif
};
@@ -714,6 +722,8 @@ void AnonDeclaration::semantic(Scope *sc)
scope = NULL;
}
unsigned dprogress_save = Module::dprogress;
assert(sc->parent);
Dsymbol *parent = sc->parent->pastMixin();
@@ -743,7 +753,7 @@ void AnonDeclaration::semantic(Scope *sc)
sc = sc->push();
sc->anonAgg = &aad;
sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls);
sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
sc->inunion = isunion;
sc->offset = 0;
sc->flags = 0;
@@ -775,6 +785,7 @@ void AnonDeclaration::semantic(Scope *sc)
scope->setNoFree();
scope->module->addDeferredSemantic(this);
}
Module::dprogress = dprogress_save;
//printf("\tforward reference %p\n", this);
return;
}
@@ -805,15 +816,15 @@ void AnonDeclaration::semantic(Scope *sc)
{
VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
// LDC
#if IN_LLVM
v->offset2 = sc->offset;
#endif
v->offset += sc->offset;
// LDC
#if IN_LLVM
if (!v->anonDecl)
v->anonDecl = this;
#endif
ad->fields.push(v);
}
@@ -1369,7 +1380,21 @@ void PragmaDeclaration::toObjFile(int multiobj)
char *name = (char *)mem.malloc(se->len + 1);
memcpy(name, se->string, se->len);
name[se->len] = 0;
#if OMFOBJ
/* The OMF format allows library names to be inserted
* into the object file. The linker will then automatically
* search that library, too.
*/
obj_includelib(name);
#elif ELFOBJ || MACHOBJ
/* The format does not allow embedded library names,
* so instead append the library name to the list to be passed
* to the linker.
*/
global.params.libfiles->push((void *) name);
#else
error("pragma lib not supported");
#endif
}
#if DMDV2
else if (ident == Id::startaddress)

View File

@@ -264,6 +264,7 @@ void ClassDeclaration::semantic(Scope *sc)
scx = scope; // save so we don't make redundant copies
scope = NULL;
}
unsigned dprogress_save = Module::dprogress;
#ifdef IN_GCC
methods.setDim(0);
#endif
@@ -628,6 +629,8 @@ void ClassDeclaration::semantic(Scope *sc)
scope->setNoFree();
scope->module->addDeferredSemantic(this);
Module::dprogress = dprogress_save;
//printf("\tsemantic('%s') failed due to forward references\n", toChars());
return;
}

View File

@@ -142,10 +142,11 @@ void VersionCondition::checkPredefined(Loc loc, const char *ident)
"all",
"none",
// LDC
#if IN_LLVM
"LLVM", "LDC", "LLVM64",
"PPC", "PPC64",
"darwin","solaris","freebsd"
#endif
};
for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++)

View File

@@ -835,7 +835,7 @@ void VarDeclaration::semantic(Scope *sc)
//printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
v->semantic(sc);
/*
#if !IN_LLVM
// removed for LDC since TupleDeclaration::toObj already creates the fields;
// adding them to the scope again leads to duplicates
if (sc->scopesym)
@@ -843,7 +843,8 @@ void VarDeclaration::semantic(Scope *sc)
if (sc->scopesym->members)
sc->scopesym->members->push(v);
}
*/
#endif
Expression *e = new DsymbolExp(loc, v);
exps->data[i] = e;
}
@@ -1490,9 +1491,10 @@ Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *s)
void TypeInfoDeclaration::semantic(Scope *sc)
{
assert(linkage == LINKc);
// LDC
#if IN_LLVM
if (!global.params.useAvailableExternally)
availableExternally = false;
#endif
}
/***************************** TypeInfoConstDeclaration **********************/

View File

@@ -15,9 +15,11 @@
#pragma once
#endif /* __DMC__ */
#if IN_LLVM
#include <set>
#include <map>
#include <string>
#endif
#include "dsymbol.h"
#include "lexer.h"

View File

@@ -29,7 +29,9 @@
#include "import.h"
#include "template.h"
#include "attrib.h"
#if IN_LLVM
#include "../gen/enums.h"
#endif
/****************************** Dsymbol ******************************/

View File

@@ -21,8 +21,9 @@
#include "mars.h"
#include "arraytypes.h"
// llvm
#if IN_LLVM
#include "../ir/irdsymbol.h"
#endif
struct Identifier;
struct Scope;
@@ -51,6 +52,9 @@ struct UnitTestDeclaration;
struct NewDeclaration;
struct VarDeclaration;
struct AttribDeclaration;
#if IN_DMD
struct Symbol;
#endif
struct Package;
struct Module;
struct Import;
@@ -76,9 +80,6 @@ struct OverloadSet;
#if TARGET_NET
struct PragmaScope;
#endif
#if IN_DMD
struct Symbol;
#endif
#if IN_GCC
union tree_node;
typedef union tree_node TYPE;
@@ -109,6 +110,18 @@ enum PROT
PROTexport,
};
/* State of symbol in winding its way through the passes of the compiler
*/
enum PASS
{
PASSinit, // initial state
PASSsemantic, // semantic() started
PASSsemanticdone, // semantic() done
PASSsemantic2, // semantic2() run
PASSsemantic3, // semantic3() started
PASSsemantic3done, // semantic3() done
PASSobj, // toObjFile() run
};
struct Dsymbol : Object
{

View File

@@ -1,5 +1,5 @@
// 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
@@ -14,6 +14,7 @@
#include "enum.h"
#include "mtype.h"
#include "scope.h"
#include "module.h"
#include "declaration.h"
/********************************* EnumDeclaration ****************************/
@@ -74,6 +75,8 @@ void EnumDeclaration::semantic(Scope *sc)
scope = NULL;
}
unsigned dprogress_save = Module::dprogress;
if (sc->stc & STCdeprecated)
isdeprecated = 1;
@@ -97,6 +100,7 @@ void EnumDeclaration::semantic(Scope *sc)
}
isdone = 1;
Module::dprogress++;
t = isAnonymous() ? memtype : type;
symtab = new DsymbolTable();

View File

@@ -1,6 +1,6 @@
// 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
@@ -3710,7 +3710,6 @@ Lagain:
break;
}
}
}
}
else if (thisexp)
@@ -8777,8 +8776,11 @@ Expression *ShlAssignExp::semantic(Scope *sc)
typeCombine(sc);
e1->checkIntegral();
e2 = e2->checkIntegral();
//e2 = e2->castTo(sc, Type::tshiftcnt);
e2 = e2->castTo(sc, e1->type); // LDC
#if !IN_LLVM
e2 = e2->castTo(sc, Type::tshiftcnt);
#else
e2 = e2->castTo(sc, e1->type);
#endif
return this;
}
@@ -8806,8 +8808,11 @@ Expression *ShrAssignExp::semantic(Scope *sc)
typeCombine(sc);
e1->checkIntegral();
e2 = e2->checkIntegral();
//e2 = e2->castTo(sc, Type::tshiftcnt);
e2 = e2->castTo(sc, e1->type); // LDC
#if !IN_LLVM
e2 = e2->castTo(sc, Type::tshiftcnt);
#else
e2 = e2->castTo(sc, e1->type);
#endif
return this;
}
@@ -8835,8 +8840,11 @@ Expression *UshrAssignExp::semantic(Scope *sc)
typeCombine(sc);
e1->checkIntegral();
e2 = e2->checkIntegral();
//e2 = e2->castTo(sc, Type::tshiftcnt);
e2 = e2->castTo(sc, e1->type); // LDC
#if !IN_LLVM
e2 = e2->castTo(sc, Type::tshiftcnt);
#else
e2 = e2->castTo(sc, e1->type);
#endif
return this;
}
@@ -9323,8 +9331,11 @@ Expression *ShlExp::semantic(Scope *sc)
e1 = e1->checkIntegral();
e2 = e2->checkIntegral();
e1 = e1->integralPromotions(sc);
//e2 = e2->castTo(sc, Type::tshiftcnt);
e2 = e2->castTo(sc, e1->type); // LDC
#if !IN_LLVM
e2 = e2->castTo(sc, Type::tshiftcnt);
#else
e2 = e2->castTo(sc, e1->type);
#endif
type = e1->type;
}
return this;
@@ -9348,8 +9359,11 @@ Expression *ShrExp::semantic(Scope *sc)
e1 = e1->checkIntegral();
e2 = e2->checkIntegral();
e1 = e1->integralPromotions(sc);
//e2 = e2->castTo(sc, Type::tshiftcnt);
e2 = e2->castTo(sc, e1->type); // LDC
#if !IN_LLVM
e2 = e2->castTo(sc, Type::tshiftcnt);
#else
e2 = e2->castTo(sc, e1->type);
#endif
type = e1->type;
}
return this;
@@ -9373,8 +9387,11 @@ Expression *UshrExp::semantic(Scope *sc)
e1 = e1->checkIntegral();
e2 = e2->checkIntegral();
e1 = e1->integralPromotions(sc);
//e2 = e2->castTo(sc, Type::tshiftcnt);
e2 = e2->castTo(sc, e1->type); // LDC
#if !IN_LLVM
e2 = e2->castTo(sc, Type::tshiftcnt);
#else
e2 = e2->castTo(sc, e1->type);
#endif
type = e1->type;
}
return this;

View File

@@ -1,6 +1,6 @@
// 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
@@ -645,6 +645,7 @@ struct SymOffExp : Expression
SymOffExp(Loc loc, Declaration *var, unsigned offset);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate);
void checkEscape();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isConst();
@@ -722,6 +723,7 @@ struct FuncExp : Expression
FuncExp(Loc loc, FuncLiteralDeclaration *fd);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate);
void scanForNestedRef(Scope *sc);
char *toChars();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -985,6 +987,7 @@ struct DelegateExp : UnaExp
DelegateExp(Loc loc, Expression *e, FuncDeclaration *func);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);

View File

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

View File

@@ -16,11 +16,12 @@
#endif /* __DMC__ */
#include "root.h"
#if IN_LLVM
namespace llvm
{
class Value;
}
#endif
struct Identifier : Object
{

View File

@@ -1281,7 +1281,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
if (needThis() && !hasthis)
return 0;
if (inlineNest || (semanticRun < 3 && !hdrscan))
if (inlineNest || (semanticRun < PASSsemantic3 && !hdrscan))
{
#if CANINLINE_LOG
printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun);

View File

@@ -1,6 +1,6 @@
// 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
@@ -52,6 +52,8 @@ Expression *interpret_length(InterState *istate, Expression *earg);
Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd);
Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd);
ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type, Expression *elem, size_t dim);
/*************************************
* Attempt to interpret a function given the arguments.
* Input:
@@ -92,7 +94,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
}
#endif
if (cantInterpret || semanticRun == 3)
if (cantInterpret || semanticRun == PASSsemantic3)
return NULL;
if (!fbody)
@@ -100,13 +102,13 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
return NULL;
}
if (semanticRun < 3 && scope)
if (semanticRun < PASSsemantic3 && scope)
{
semantic3(scope);
if (global.errors) // if errors compiling this function
return NULL;
}
if (semanticRun < 4)
if (semanticRun < PASSsemantic3done)
return NULL;
Type *tb = type->toBasetype();
@@ -160,7 +162,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
{ Expression *earg = (Expression *)arguments->data[i];
Parameter *arg = Parameter::getNth(tf->parameters, i);
if (arg->storageClass & (STCout | STCref))
if (arg->storageClass & (STCout | STCref | STClazy))
{
}
else
@@ -1005,6 +1007,35 @@ Expression *StringExp::interpret(InterState *istate)
return this;
}
Expression *FuncExp::interpret(InterState *istate)
{
#if LOG
printf("FuncExp::interpret() %s\n", toChars());
#endif
return this;
}
Expression *SymOffExp::interpret(InterState *istate)
{
#if LOG
printf("SymOffExp::interpret() %s\n", toChars());
#endif
if (var->isFuncDeclaration() && offset == 0)
{
return this;
}
error("Cannot interpret %s at compile time", toChars());
return EXP_CANT_INTERPRET;
}
Expression *DelegateExp::interpret(InterState *istate)
{
#if LOG
printf("DelegateExp::interpret() %s\n", toChars());
#endif
return this;
}
Expression *getVarExp(Loc loc, InterState *istate, Declaration *d)
{
Expression *e = EXP_CANT_INTERPRET;
@@ -1013,6 +1044,11 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d)
if (v)
{
#if DMDV2
/* Magic variable __ctfe always returns true when interpreting
*/
if (v->ident == Id::ctfe)
return new IntegerExp(loc, 1, Type::tbool);
if ((v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) && v->init && !v->value)
#else
if (v->isConst() && v->init)
@@ -1021,6 +1057,16 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d)
if (e && !e->type)
e->type = v->type;
}
else if (v->isCTFE() && !v->value)
{
if (v->init)
{
e = v->init->toExpression();
e = e->interpret(istate);
}
else // This should never happen
e = v->type->defaultInitLiteral();
}
else
{ e = v->value;
if (!v->isCTFE())
@@ -1482,7 +1528,7 @@ Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, void
}
/***************************************
* Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint..$]
* Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint+newelems.length..$]
*/
Expressions *spliceElements(Expressions *oldelems,
Expressions *newelems, size_t insertpoint)
@@ -1499,6 +1545,26 @@ Expressions *spliceElements(Expressions *oldelems,
return expsx;
}
/***************************************
* Returns oldstr[0..insertpoint] ~ newstr ~ oldstr[insertpoint+newlen..$]
*/
StringExp *spliceStringExp(StringExp *oldstr, StringExp *newstr, size_t insertpoint)
{
assert(oldstr->sz==newstr->sz);
unsigned char *s;
size_t oldlen = oldstr->len;
size_t newlen = newstr->len;
size_t sz = oldstr->sz;
s = (unsigned char *)mem.calloc(oldlen + 1, sz);
memcpy(s, oldstr->string, oldlen * sz);
memcpy(s + insertpoint * sz, newstr->string, newlen * sz);
StringExp *se2 = new StringExp(oldstr->loc, s, oldlen);
se2->committed = oldstr->committed;
se2->postfix = oldstr->postfix;
se2->type = oldstr->type;
return se2;
}
/******************************
* Create an array literal consisting of 'elem' duplicated 'dim' times.
*/
@@ -1514,6 +1580,28 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type,
return ae;
}
/******************************
* Create a string literal consisting of 'value' duplicated 'dim' times.
*/
StringExp *createBlockDuplicatedStringLiteral(Type *type,
unsigned value, size_t dim, int sz)
{
unsigned char *s;
s = (unsigned char *)mem.calloc(dim + 1, sz);
for (int elemi=0; elemi<dim; ++elemi)
{
switch (sz)
{
case 1: s[elemi] = value; break;
case 2: ((unsigned short *)s)[elemi] = value; break;
case 4: ((unsigned *)s)[elemi] = value; break;
default: assert(0);
}
}
StringExp *se = new StringExp(0, s, dim);
se->type = type;
return se;
}
/********************************
* Add v to the istate list, unless it already exists there.
@@ -1582,13 +1670,16 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
// To reduce code complexity of handling dotvar expressions,
// extract the aggregate now.
Expression *aggregate;
if (e1->op == TOKdotvar) {
if (e1->op == TOKdotvar)
{
aggregate = ((DotVarExp *)e1)->e1;
// Get rid of 'this'.
if (aggregate->op == TOKthis && istate->localThis)
aggregate = istate->localThis;
aggregate = istate->localThis;
}
if (e1->op == TOKthis && istate->localThis)
e1 = istate->localThis;
/* Assignment to variable of the form:
* v = e2
*/
@@ -1623,7 +1714,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
if (e2 == EXP_CANT_INTERPRET)
return e2;
addVarToInterstate(istate, v);
if (istate)
addVarToInterstate(istate, v);
v->value = e2;
e = Cast(type, type, post ? ev : e2);
}
@@ -1668,16 +1760,21 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
* on the void value - to do that we'd need a VoidExp.
* That's probably a good enhancement idea.
*/
v->value = v->type->defaultInit();
v->value = v->type->defaultInitLiteral();
}
Expression *vie = v->value;
assert(vie != EXP_CANT_INTERPRET);
if (vie->op == TOKvar)
{
Declaration *d = ((VarExp *)vie)->var;
vie = getVarExp(e1->loc, istate, d);
}
if (vie->op != TOKstructliteral)
{
error("Cannot assign %s=%s in CTFE", v->toChars(), vie->toChars());
return EXP_CANT_INTERPRET;
}
StructLiteralExp *se = (StructLiteralExp *)vie;
VarDeclaration *vf = ((DotVarExp *)e1)->var->isVarDeclaration();
if (!vf)
@@ -2015,19 +2112,19 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
error("%s cannot be modified at compile time", v->toChars());
return EXP_CANT_INTERPRET;
}
// Chase down rebinding of out and ref
if (v->value && v->value->op == TOKvar)
{
VarExp *ve2 = (VarExp *)v->value;
if (ve2->var->isStaticStructInitDeclaration())
{ // This can happen if v is a struct initialized to
// 0 using an __initZ SymbolDeclaration from
// TypeStruct::defaultInit()
}
else
v = ve2->var->isVarDeclaration();
assert(v);
// Chase down rebinding of out and ref
if (v->value && v->value->op == TOKvar)
{
VarExp *ve2 = (VarExp *)v->value;
if (ve2->var->isStaticStructInitDeclaration())
{ // This can happen if v is a struct initialized to
// 0 using an __initZ SymbolDeclaration from
// TypeStruct::defaultInit()
}
else
v = ve2->var->isVarDeclaration();
assert(v);
}
/* Set the $ variable
*/
Expression *ee = v->value ? ArrayLength(Type::tsize_t, v->value)
@@ -2062,10 +2159,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
if (v->value->op == TOKarrayliteral)
dim = ((ArrayLiteralExp *)v->value)->elements->dim;
else if (v->value->op ==TOKstring)
{
error("String slice assignment is not yet supported in CTFE");
return EXP_CANT_INTERPRET;
}
dim = ((StringExp *)v->value)->len;
}
else
{
@@ -2075,67 +2169,87 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
int upperbound = upper ? upper->toInteger() : dim;
int lowerbound = lower ? lower->toInteger() : 0;
ArrayLiteralExp *existing;
if (((int)lowerbound < 0) || (upperbound > dim))
{
error("Array bounds [0..%d] exceeded in slice [%d..%d]", dim, lowerbound, upperbound);
error("Array bounds [0..%d] exceeded in slice [%d..%d]",
dim, lowerbound, upperbound);
return EXP_CANT_INTERPRET;
}
if (upperbound-lowerbound != dim)
// Could either be slice assignment (v[] = e[]),
// or block assignment (v[] = val).
// For the former, we check that the lengths match.
bool isSliceAssignment = (e2->op == TOKarrayliteral)
|| (e2->op == TOKstring);
size_t srclen = 0;
if (e2->op == TOKarrayliteral)
srclen = ((ArrayLiteralExp *)e2)->elements->dim;
else if (e2->op == TOKstring)
srclen = ((StringExp *)e2)->len;
if (isSliceAssignment && srclen != (upperbound - lowerbound))
{
// Only modifying part of the array. Must create a new array literal.
// If the existing array is uninitialized (this can only happen
// with static arrays), create it.
if (v->value && v->value->op == TOKarrayliteral)
existing = (ArrayLiteralExp *)v->value;
else
{
// this can only happen with static arrays
existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim);
}
error("Array length mismatch assigning [0..%d] to [%d..%d]", srclen, lowerbound, upperbound);
return e;
}
if (e2->op == TOKarrayliteral)
{
// Static array assignment from literal
ArrayLiteralExp *ae = (ArrayLiteralExp *)e2;
if (ae->elements->dim != (upperbound - lowerbound))
{
error("Array length mismatch assigning [0..%d] to [%d..%d]", ae->elements->dim, lowerbound, upperbound);
return e;
}
if (upperbound - lowerbound == dim)
v->value = ae;
else
{
ArrayLiteralExp *existing;
// Only modifying part of the array. Must create a new array literal.
// If the existing array is uninitialized (this can only happen
// with static arrays), create it.
if (v->value && v->value->op == TOKarrayliteral)
existing = (ArrayLiteralExp *)v->value;
else // this can only happen with static arrays
existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim);
// value[] = value[0..lower] ~ ae ~ value[upper..$]
existing->elements = spliceElements(existing->elements, ae->elements, lowerbound);
v->value = existing;
}
return e2;
}
else if (t->nextOf()->ty == e2->type->ty)
{
// Static array block assignment
if (upperbound-lowerbound ==dim)
v->value = createBlockDuplicatedArrayLiteral(v->type, e2, dim);
else
{
// value[] = value[0..lower] ~ ae ~ value[upper..$]
existing->elements = spliceElements(existing->elements, createBlockDuplicatedArrayLiteral(v->type, e2, upperbound-lowerbound)->elements, lowerbound);
v->value = existing;
}
return e2;
}
else if (e2->op == TOKstring)
{
StringExp *se = (StringExp *)e2;
// This is problematic. char[8] should be storing
// values as a string literal, not
// as an array literal. Then, for static arrays, we
// could do modifications
// in-place, with a dramatic memory and speed improvement.
error("String slice assignment is not yet supported in CTFE");
if (upperbound-lowerbound == dim)
v->value = e2;
else
{
if (!v->value)
v->value = createBlockDuplicatedStringLiteral(se->type,
se->type->defaultInit()->toInteger(), dim, se->sz);
if (v->value->op==TOKstring)
v->value = spliceStringExp((StringExp *)v->value, se, lowerbound);
else
error("String slice assignment is not yet supported in CTFE");
}
return e2;
}
else if (t->nextOf()->ty == e2->type->ty)
{
// Static array block assignment
if (upperbound - lowerbound == dim)
v->value = createBlockDuplicatedArrayLiteral(v->type, e2, dim);
else
{
ArrayLiteralExp *existing;
// Only modifying part of the array. Must create a new array literal.
// If the existing array is uninitialized (this can only happen
// with static arrays), create it.
if (v->value && v->value->op == TOKarrayliteral)
existing = (ArrayLiteralExp *)v->value;
else // this can only happen with static arrays
existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim);
// value[] = value[0..lower] ~ ae ~ value[upper..$]
existing->elements = spliceElements(existing->elements,
createBlockDuplicatedArrayLiteral(v->type, e2, upperbound-lowerbound)->elements,
lowerbound);
v->value = existing;
}
return e2;
}
else
@@ -2260,74 +2374,118 @@ Expression *CallExp::interpret(InterState *istate)
#if LOG
printf("CallExp::interpret() %s\n", toChars());
#endif
if (e1->op == TOKdotvar)
Expression * pthis = NULL;
FuncDeclaration *fd = NULL;
Expression *ecall = e1;
if (ecall->op == TOKindex)
ecall = e1->interpret(istate);
if (ecall->op == TOKdotvar && !((DotVarExp*)ecall)->var->isFuncDeclaration())
ecall = e1->interpret(istate);
if (ecall->op == TOKdotvar)
{ // Calling a member function
pthis = ((DotVarExp*)e1)->e1;
fd = ((DotVarExp*)e1)->var->isFuncDeclaration();
}
else if (ecall->op == TOKvar)
{
Expression * pthis = ((DotVarExp*)e1)->e1;
FuncDeclaration *fd = ((DotVarExp*)e1)->var->isFuncDeclaration();
TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL;
if (tf)
{ // Member function call
if(pthis->op == TOKthis)
pthis = istate->localThis;
Expression *eresult = fd->interpret(istate, arguments, pthis);
VarDeclaration *vd = ((VarExp *)ecall)->var->isVarDeclaration();
if (vd && vd->value)
ecall = vd->value;
else // Calling a function
fd = ((VarExp *)e1)->var->isFuncDeclaration();
}
if (ecall->op == TOKdelegate)
{ // Calling a delegate
fd = ((DelegateExp *)ecall)->func;
pthis = ((DelegateExp *)ecall)->e1;
}
else if (ecall->op == TOKfunction)
{ // Calling a delegate literal
fd = ((FuncExp*)ecall)->fd;
}
else if (ecall->op == TOKstar && ((PtrExp*)ecall)->e1->op==TOKfunction)
{ // Calling a function literal
fd = ((FuncExp*)((PtrExp*)ecall)->e1)->fd;
}
else if (ecall->op == TOKstar && ((PtrExp*)ecall)->e1->op==TOKvar)
{ // Calling a function pointer
VarDeclaration *vd = ((VarExp *)((PtrExp*)ecall)->e1)->var->isVarDeclaration();
if (vd && vd->value && vd->value->op==TOKsymoff)
fd = ((SymOffExp *)vd->value)->var->isFuncDeclaration();
}
TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL;
if (!tf)
{ // DAC: I'm not sure if this ever happens
//printf("ecall=%s %d %d\n", ecall->toChars(), ecall->op, TOKcall);
error("cannot evaluate %s at compile time", toChars());
return EXP_CANT_INTERPRET;
}
if (pthis && fd)
{ // Member function call
if (pthis->op == TOKthis)
pthis = istate->localThis;
else if (pthis->op == TOKcomma)
pthis = pthis->interpret(istate);
Expression *eresult = fd->interpret(istate, arguments, pthis);
if (eresult)
e = eresult;
else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors)
e = EXP_VOID_INTERPRET;
else
error("cannot evaluate %s at compile time", toChars());
return e;
}
else if (fd)
{ // function call
#if DMDV2
enum BUILTIN b = fd->isBuiltin();
if (b)
{ Expressions args;
args.setDim(arguments->dim);
for (size_t i = 0; i < args.dim; i++)
{
Expression *earg = (Expression *)arguments->data[i];
earg = earg->interpret(istate);
if (earg == EXP_CANT_INTERPRET)
return earg;
args.data[i] = (void *)earg;
}
e = eval_builtin(b, &args);
if (!e)
e = EXP_CANT_INTERPRET;
}
else
#endif
// Inline .dup
if (fd->ident == Id::adDup && arguments && arguments->dim == 2)
{
e = (Expression *)arguments->data[1];
e = e->interpret(istate);
if (e != EXP_CANT_INTERPRET)
{
e = expType(type, e);
}
}
else
{
Expression *eresult = fd->interpret(istate, arguments);
if (eresult)
e = eresult;
else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors)
e = EXP_VOID_INTERPRET;
else
error("cannot evaluate %s at compile time", toChars());
return e;
}
}
}
else
{
error("cannot evaluate %s at compile time", toChars());
return EXP_CANT_INTERPRET;
}
if (e1->op == TOKvar)
{
FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
if (fd)
{
#if DMDV2
enum BUILTIN b = fd->isBuiltin();
if (b)
{ Expressions args;
args.setDim(arguments->dim);
for (size_t i = 0; i < args.dim; i++)
{
Expression *earg = (Expression *)arguments->data[i];
earg = earg->interpret(istate);
if (earg == EXP_CANT_INTERPRET)
return earg;
args.data[i] = (void *)earg;
}
e = eval_builtin(b, &args);
if (!e)
e = EXP_CANT_INTERPRET;
}
else
#endif
// Inline .dup
if (fd->ident == Id::adDup && arguments && arguments->dim == 2)
{
e = (Expression *)arguments->data[1];
e = e->interpret(istate);
if (e != EXP_CANT_INTERPRET)
{
e = expType(type, e);
}
}
else
{
Expression *eresult = fd->interpret(istate, arguments);
if (eresult)
e = eresult;
else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors)
e = EXP_VOID_INTERPRET;
else
error("cannot evaluate %s at compile time", toChars());
}
}
}
return e;
return e;
}
Expression *CommaExp::interpret(InterState *istate)
@@ -2335,6 +2493,21 @@ Expression *CommaExp::interpret(InterState *istate)
#if LOG
printf("CommaExp::interpret() %s\n", toChars());
#endif
// If the comma returns a temporary variable, it needs to be an lvalue
// (this is particularly important for struct constructors)
if (e1->op == TOKdeclaration && e2->op == TOKvar
&& ((DeclarationExp *)e1)->declaration == ((VarExp*)e2)->var)
{
VarExp* ve = (VarExp *)e2;
VarDeclaration *v = ve->var->isVarDeclaration();
if (!v->init && !v->value)
v->value = v->type->defaultInitLiteral();
if (!v->value)
v->value = v->init->toExpression();
v->value = v->value->interpret(istate);
return e2;
}
Expression *e = e1->interpret(istate);
if (e != EXP_CANT_INTERPRET)
e = e2->interpret(istate);
@@ -2516,14 +2689,18 @@ Expression *AssertExp::interpret(InterState *istate)
if( this->e1->op == TOKaddress)
{ // Special case: deal with compiler-inserted assert(&this, "null this")
AddrExp *ade = (AddrExp *)this->e1;
if(ade->e1->op == TOKthis && istate->localThis)
return istate->localThis->interpret(istate);
if (ade->e1->op == TOKthis && istate->localThis)
if (ade->e1->op == TOKdotvar
&& ((DotVarExp *)(istate->localThis))->e1->op == TOKthis)
return getVarExp(loc, istate, ((DotVarExp*)(istate->localThis))->var);
else
return istate->localThis->interpret(istate);
}
if (this->e1->op == TOKthis)
{
if (istate->localThis)
return istate->localThis->interpret(istate);
}
if (this->e1->op == TOKthis)
{
if(istate->localThis)
return istate->localThis->interpret(istate);
}
e1 = this->e1->interpret(istate);
if (e1 == EXP_CANT_INTERPRET)
goto Lcant;

View File

@@ -113,9 +113,9 @@ char *Declaration::mangle()
case LINKd:
break;
// LDC
#if IN_LLVM
case LINKintrinsic:
#endif
case LINKc:
case LINKwindows:
case LINKpascal:

View File

@@ -1,6 +1,6 @@
// 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
@@ -13,8 +13,10 @@
#include <ctype.h>
#include <assert.h>
#include <limits.h>
#if IN_LLVM
#include <string>
#include <cstdarg>
#endif
#if POSIX
#include <errno.h>
@@ -34,7 +36,9 @@
#include "lexer.h"
#include "json.h"
#if IN_LLVM
#include "gen/revisions.h"
#endif
Global global;
@@ -46,6 +50,7 @@ Global::Global()
doc_ext = "html";
ddoc_ext = "ddoc";
json_ext = "json";
map_ext = "map";
// LDC
ll_ext = "ll";
@@ -58,7 +63,7 @@ Global::Global()
copyright = "Copyright (c) 1999-2009 by Digital Mars and Tomas Lindquist Olsen";
written = "written by Walter Bright and Tomas Lindquist Olsen";
version = "v1.055";
version = "v1.056";
ldc_version = LDC_REV;
llvm_version = LLVM_REV_STR;
global.structalign = 8;

View File

@@ -1,6 +1,6 @@
// 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
@@ -235,7 +235,9 @@ struct Param
char *deffile;
char *resfile;
char *exefile;
char *mapfile;
#if IN_LLVM
// LDC stuff
OUTPUTFLAG output_ll;
OUTPUTFLAG output_bc;
@@ -250,6 +252,7 @@ struct Param
const char* llvmArch;
const char *targetTriple;
const char *dataLayout;
#endif
};
struct Global
@@ -268,6 +271,7 @@ struct Global
const char *ddoc_ext; // for Ddoc macro include files
const char *hdr_ext; // for D 'header' import files
const char *json_ext; // for JSON files
const char *map_ext; // for .map files
const char *copyright;
const char *written;
Array *path; // Array of char*'s which form the import lookup path
@@ -393,8 +397,9 @@ enum LINK
LINKwindows,
LINKpascal,
// LDC
#if IN_LLVM
LINKintrinsic,
#endif
};
enum DYNCAST

View File

@@ -1,6 +1,6 @@
// 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
@@ -44,7 +44,7 @@
#include "d-dmd-gcc.h"
#endif
#if IN_LLVM
#include "llvm/Support/CommandLine.h"
#include <map>
@@ -55,8 +55,7 @@ static llvm::cl::opt<bool> preservePaths("op",
static llvm::cl::opt<bool> fqnNames("oq",
llvm::cl::desc("Write object files with fully qualified names"),
llvm::cl::ZeroOrMore);
#endif
ClassDeclaration *Module::moduleinfo;
@@ -971,7 +970,8 @@ void Module::addDeferredSemantic(Dsymbol *s)
void Module::runDeferredSemantic()
{
size_t len;
if (dprogress == 0)
return;
static int nested;
if (nested)
@@ -979,6 +979,7 @@ void Module::runDeferredSemantic()
//if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
nested++;
size_t len;
do
{
dprogress = 0;

View File

@@ -153,7 +153,7 @@ struct Module : Package
Dsymbol *symtabInsert(Dsymbol *s);
void deleteObjFile();
void addDeferredSemantic(Dsymbol *s);
void runDeferredSemantic();
static void runDeferredSemantic();
int imports(Module *m);
// Back end

View File

@@ -4061,8 +4061,15 @@ Dsymbol *TypeEnum::toDsymbol(Scope *sc)
Type *TypeEnum::toBasetype()
{
if (sym->scope)
{
sym->semantic(NULL); // attempt to resolve forward reference
{ // Enum is forward referenced. We don't need to resolve the whole thing,
// just the base type
if (sym->memtype)
{ sym->memtype = sym->memtype->semantic(sym->loc, sym->scope);
}
else
{ if (!sym->isAnonymous())
sym->memtype = Type::tint32;
}
}
if (!sym->memtype)
{

View File

@@ -1,6 +1,6 @@
// 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
@@ -344,7 +344,9 @@ Expression *NewExp::optimize(int result)
}
Expression *CallExp::optimize(int result)
{ Expression *e = this;
{
//printf("CallExp::optimize(result = %d) %s\n", result, toChars());
Expression *e = this;
// Optimize parameters
if (arguments)
@@ -358,17 +360,15 @@ Expression *CallExp::optimize(int result)
}
e1 = e1->optimize(result);
if (e1->op == TOKvar && result & WANTinterpret)
if (result & WANTinterpret)
{
FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
if (fd)
{
Expression *eresult = fd->interpret(NULL, arguments);
if (eresult && eresult != EXP_VOID_INTERPRET)
e = eresult;
else if (result & WANTinterpret)
error("cannot evaluate %s at compile time", toChars());
}
Expression *eresult = interpret(NULL);
if (eresult == EXP_CANT_INTERPRET)
return e;
if (eresult && eresult != EXP_VOID_INTERPRET)
e = eresult;
else
error("cannot evaluate %s at compile time", toChars());
}
return e;
}
@@ -624,6 +624,22 @@ Expression *CommaExp::optimize(int result)
{ Expression *e;
//printf("CommaExp::optimize(result = %d) %s\n", result, toChars());
// Comma needs special treatment, because it may
// contain compiler-generated declarations. We can interpret them, but
// otherwise we must NOT attempt to constant-fold them.
// In particular, if the comma returns a temporary variable, it needs
// to be an lvalue (this is particularly important for struct constructors)
if (result & WANTinterpret)
{ // Interpreting comma needs special treatment, because it may
// contain compiler-generated declarations.
e = interpret(NULL);
return (e == EXP_CANT_INTERPRET) ? this : e;
}
// Don't constant fold if it is a compiler-generated temporary.
if (e1->op == TOKdeclaration)
return this;
e1 = e1->optimize(result & WANTinterpret);
e2 = e2->optimize(result);
if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2))
@@ -709,8 +725,8 @@ Expression *SliceExp::optimize(int result)
{ if (e1->op == TOKstring)
{ // Convert slice of string literal into dynamic array
Type *t = e1->type->toBasetype();
if (t->next)
e = e1->castTo(NULL, t->next->arrayOf());
if (t->nextOf())
e = e1->castTo(NULL, t->nextOf()->arrayOf());
}
return e;
}

View File

@@ -2483,7 +2483,14 @@ Statement *PragmaStatement::semantic(Scope *sc)
Expression *e = (Expression *)args->data[i];
e = e->semantic(sc);
#if 1
e = e->optimize(WANTvalue | WANTinterpret);
#else
e = e->interpret(NULL);
if (e == EXP_CANT_INTERPRET)
fprintf(stdmsg, ((Expression *)args->data[i])->toChars());
else
#endif
if (e->op == TOKstring)
{
StringExp *se = (StringExp *)e;

View File

@@ -54,13 +54,14 @@ struct VolatileStatement;
struct SynchronizedStatement;
enum TOK;
#if IN_LLVM
namespace llvm
{
class Value;
class BasicBlock;
class ConstantInt;
}
#endif
// Back end
struct IRState;
@@ -141,9 +142,10 @@ struct Statement : Object
virtual IfStatement *isIfStatement() { return NULL; }
virtual CaseStatement* isCaseStatement() { return NULL; }
// LDC
#if IN_LLVM
virtual void toNakedIR(IRState *irs);
virtual AsmBlockStatement* endsWithAsm();
#endif
};
struct PeelStatement : Statement
@@ -172,8 +174,9 @@ struct ExpStatement : Statement
void toIR(IRState *irs);
// LDC
#if IN_LLVM
void toNakedIR(IRState *irs);
#endif
};
struct CompileStatement : Statement

View File

@@ -19,6 +19,7 @@
#include "module.h"
#include "id.h"
#include "statement.h"
#include "template.h"
/********************************* AggregateDeclaration ****************************/
@@ -269,6 +270,8 @@ void StructDeclaration::semantic(Scope *sc)
scope = NULL;
}
unsigned dprogress_save = Module::dprogress;
parent = sc->parent;
type = type->semantic(loc, sc);
#if STRUCTTHISREF
@@ -417,6 +420,8 @@ void StructDeclaration::semantic(Scope *sc)
scope = scx ? scx : new Scope(*sc);
scope->setNoFree();
scope->module->addDeferredSemantic(this);
Module::dprogress = dprogress_save;
//printf("\tdeferring %s\n", toChars());
return;
}

View File

@@ -1,6 +1,6 @@
// 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
@@ -3539,7 +3539,8 @@ void TemplateInstance::semantic(Scope *sc)
error("error instantiating");
if (tinst)
{ tinst->printInstantiationTrace();
fatal();
if (!global.gag)
fatal();
}
errors = 1;
if (global.gag)

14
tests/mini/bug372.d Normal file
View File

@@ -0,0 +1,14 @@
class A {
class B {
}
}
class C : A {
void test () {
B foo = new B();
}
}
int main () {
return 0;
}