mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
Merge dmd 1.056.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
35
dmd/attrib.c
35
dmd/attrib.c
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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++)
|
||||
|
||||
@@ -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 **********************/
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#if IN_LLVM
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
#include "dsymbol.h"
|
||||
#include "lexer.h"
|
||||
|
||||
@@ -29,7 +29,9 @@
|
||||
#include "import.h"
|
||||
#include "template.h"
|
||||
#include "attrib.h"
|
||||
#if IN_LLVM
|
||||
#include "../gen/enums.h"
|
||||
#endif
|
||||
|
||||
/****************************** Dsymbol ******************************/
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
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);
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#if IN_LLVM
|
||||
namespace llvm
|
||||
{
|
||||
class Value;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct Identifier : Object
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
437
dmd/interpret.c
437
dmd/interpret.c
@@ -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;
|
||||
|
||||
@@ -113,9 +113,9 @@ char *Declaration::mangle()
|
||||
case LINKd:
|
||||
break;
|
||||
|
||||
// LDC
|
||||
#if IN_LLVM
|
||||
case LINKintrinsic:
|
||||
|
||||
#endif
|
||||
case LINKc:
|
||||
case LINKwindows:
|
||||
case LINKpascal:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
11
dmd/module.c
11
dmd/module.c
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
11
dmd/mtype.c
11
dmd/mtype.c
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
14
tests/mini/bug372.d
Normal file
@@ -0,0 +1,14 @@
|
||||
class A {
|
||||
class B {
|
||||
}
|
||||
}
|
||||
|
||||
class C : A {
|
||||
void test () {
|
||||
B foo = new B();
|
||||
}
|
||||
}
|
||||
|
||||
int main () {
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user