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 #endif
if (!e) if (!e)
{ {
if (d->getModule() != sc->module) if (d->prot() == PROTprivate && d->getModule() != sc->module ||
if (d->prot() == PROTprivate || d->prot() == PROTpackage && !hasPackageAccess(sc, d))
d->prot() == PROTpackage && !hasPackageAccess(sc, d))
error(loc, "%s %s.%s is not accessible from %s", error(loc, "%s %s.%s is not accessible from %s",
d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars()); d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars());
} }
else if (e->type->ty == Tclass) else if (e->type->ty == Tclass)
{ // Do access check { // Do access check

View File

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

View File

@@ -24,6 +24,15 @@
#include "module.h" #include "module.h"
#include "init.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. * Construct the array operation expression.

View File

@@ -392,6 +392,8 @@ void StorageClassDeclaration::setScope(Scope *sc)
scstc &= ~(STCconst | STCimmutable | STCmanifest); scstc &= ~(STCconst | STCimmutable | STCmanifest);
if (stc & (STCgshared | STCshared | STCtls)) if (stc & (STCgshared | STCshared | STCtls))
scstc &= ~(STCgshared | STCshared | STCtls); scstc &= ~(STCgshared | STCshared | STCtls);
if (stc & (STCsafe | STCtrusted | STCsystem))
scstc &= ~(STCsafe | STCtrusted | STCsystem);
scstc |= stc; scstc |= stc;
setScopeNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign); setScopeNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
@@ -415,6 +417,8 @@ void StorageClassDeclaration::semantic(Scope *sc)
scstc &= ~(STCconst | STCimmutable | STCmanifest); scstc &= ~(STCconst | STCimmutable | STCmanifest);
if (stc & (STCgshared | STCshared | STCtls)) if (stc & (STCgshared | STCshared | STCtls))
scstc &= ~(STCgshared | STCshared | STCtls); scstc &= ~(STCgshared | STCshared | STCtls);
if (stc & (STCsafe | STCtrusted | STCsystem))
scstc &= ~(STCsafe | STCtrusted | STCsystem);
scstc |= stc; scstc |= stc;
semanticNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign); semanticNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
@@ -453,6 +457,10 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
{ STCref, TOKref }, { STCref, TOKref },
{ STCtls, TOKtls }, { STCtls, TOKtls },
{ STCgshared, TOKgshared }, { STCgshared, TOKgshared },
{ STCproperty, TOKat },
{ STCsafe, TOKat },
{ STCtrusted, TOKat },
{ STCdisable, TOKat },
#endif #endif
}; };
@@ -714,6 +722,8 @@ void AnonDeclaration::semantic(Scope *sc)
scope = NULL; scope = NULL;
} }
unsigned dprogress_save = Module::dprogress;
assert(sc->parent); assert(sc->parent);
Dsymbol *parent = sc->parent->pastMixin(); Dsymbol *parent = sc->parent->pastMixin();
@@ -743,7 +753,7 @@ void AnonDeclaration::semantic(Scope *sc)
sc = sc->push(); sc = sc->push();
sc->anonAgg = &aad; sc->anonAgg = &aad;
sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls); sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
sc->inunion = isunion; sc->inunion = isunion;
sc->offset = 0; sc->offset = 0;
sc->flags = 0; sc->flags = 0;
@@ -775,6 +785,7 @@ void AnonDeclaration::semantic(Scope *sc)
scope->setNoFree(); scope->setNoFree();
scope->module->addDeferredSemantic(this); scope->module->addDeferredSemantic(this);
} }
Module::dprogress = dprogress_save;
//printf("\tforward reference %p\n", this); //printf("\tforward reference %p\n", this);
return; return;
} }
@@ -805,15 +816,15 @@ void AnonDeclaration::semantic(Scope *sc)
{ {
VarDeclaration *v = (VarDeclaration *)aad.fields.data[i]; VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
// LDC #if IN_LLVM
v->offset2 = sc->offset; v->offset2 = sc->offset;
#endif
v->offset += sc->offset; v->offset += sc->offset;
// LDC #if IN_LLVM
if (!v->anonDecl) if (!v->anonDecl)
v->anonDecl = this; v->anonDecl = this;
#endif
ad->fields.push(v); ad->fields.push(v);
} }
@@ -1369,7 +1380,21 @@ void PragmaDeclaration::toObjFile(int multiobj)
char *name = (char *)mem.malloc(se->len + 1); char *name = (char *)mem.malloc(se->len + 1);
memcpy(name, se->string, se->len); memcpy(name, se->string, se->len);
name[se->len] = 0; 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); 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 #if DMDV2
else if (ident == Id::startaddress) 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 scx = scope; // save so we don't make redundant copies
scope = NULL; scope = NULL;
} }
unsigned dprogress_save = Module::dprogress;
#ifdef IN_GCC #ifdef IN_GCC
methods.setDim(0); methods.setDim(0);
#endif #endif
@@ -628,6 +629,8 @@ void ClassDeclaration::semantic(Scope *sc)
scope->setNoFree(); scope->setNoFree();
scope->module->addDeferredSemantic(this); scope->module->addDeferredSemantic(this);
Module::dprogress = dprogress_save;
//printf("\tsemantic('%s') failed due to forward references\n", toChars()); //printf("\tsemantic('%s') failed due to forward references\n", toChars());
return; return;
} }

View File

@@ -142,10 +142,11 @@ void VersionCondition::checkPredefined(Loc loc, const char *ident)
"all", "all",
"none", "none",
// LDC #if IN_LLVM
"LLVM", "LDC", "LLVM64", "LLVM", "LDC", "LLVM64",
"PPC", "PPC64", "PPC", "PPC64",
"darwin","solaris","freebsd" "darwin","solaris","freebsd"
#endif
}; };
for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++) 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()); //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
v->semantic(sc); v->semantic(sc);
/* #if !IN_LLVM
// removed for LDC since TupleDeclaration::toObj already creates the fields; // removed for LDC since TupleDeclaration::toObj already creates the fields;
// adding them to the scope again leads to duplicates // adding them to the scope again leads to duplicates
if (sc->scopesym) if (sc->scopesym)
@@ -843,7 +843,8 @@ void VarDeclaration::semantic(Scope *sc)
if (sc->scopesym->members) if (sc->scopesym->members)
sc->scopesym->members->push(v); sc->scopesym->members->push(v);
} }
*/ #endif
Expression *e = new DsymbolExp(loc, v); Expression *e = new DsymbolExp(loc, v);
exps->data[i] = e; exps->data[i] = e;
} }
@@ -1490,9 +1491,10 @@ Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *s)
void TypeInfoDeclaration::semantic(Scope *sc) void TypeInfoDeclaration::semantic(Scope *sc)
{ {
assert(linkage == LINKc); assert(linkage == LINKc);
// LDC #if IN_LLVM
if (!global.params.useAvailableExternally) if (!global.params.useAvailableExternally)
availableExternally = false; availableExternally = false;
#endif
} }
/***************************** TypeInfoConstDeclaration **********************/ /***************************** TypeInfoConstDeclaration **********************/

View File

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

View File

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

View File

@@ -21,8 +21,9 @@
#include "mars.h" #include "mars.h"
#include "arraytypes.h" #include "arraytypes.h"
// llvm #if IN_LLVM
#include "../ir/irdsymbol.h" #include "../ir/irdsymbol.h"
#endif
struct Identifier; struct Identifier;
struct Scope; struct Scope;
@@ -51,6 +52,9 @@ struct UnitTestDeclaration;
struct NewDeclaration; struct NewDeclaration;
struct VarDeclaration; struct VarDeclaration;
struct AttribDeclaration; struct AttribDeclaration;
#if IN_DMD
struct Symbol;
#endif
struct Package; struct Package;
struct Module; struct Module;
struct Import; struct Import;
@@ -76,9 +80,6 @@ struct OverloadSet;
#if TARGET_NET #if TARGET_NET
struct PragmaScope; struct PragmaScope;
#endif #endif
#if IN_DMD
struct Symbol;
#endif
#if IN_GCC #if IN_GCC
union tree_node; union tree_node;
typedef union tree_node TYPE; typedef union tree_node TYPE;
@@ -109,6 +110,18 @@ enum PROT
PROTexport, 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 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 // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -14,6 +14,7 @@
#include "enum.h" #include "enum.h"
#include "mtype.h" #include "mtype.h"
#include "scope.h" #include "scope.h"
#include "module.h"
#include "declaration.h" #include "declaration.h"
/********************************* EnumDeclaration ****************************/ /********************************* EnumDeclaration ****************************/
@@ -74,6 +75,8 @@ void EnumDeclaration::semantic(Scope *sc)
scope = NULL; scope = NULL;
} }
unsigned dprogress_save = Module::dprogress;
if (sc->stc & STCdeprecated) if (sc->stc & STCdeprecated)
isdeprecated = 1; isdeprecated = 1;
@@ -97,6 +100,7 @@ void EnumDeclaration::semantic(Scope *sc)
} }
isdone = 1; isdone = 1;
Module::dprogress++;
t = isAnonymous() ? memtype : type; t = isAnonymous() ? memtype : type;
symtab = new DsymbolTable(); symtab = new DsymbolTable();

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars // Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -3710,7 +3710,6 @@ Lagain:
break; break;
} }
} }
} }
} }
else if (thisexp) else if (thisexp)
@@ -8777,8 +8776,11 @@ Expression *ShlAssignExp::semantic(Scope *sc)
typeCombine(sc); typeCombine(sc);
e1->checkIntegral(); e1->checkIntegral();
e2 = e2->checkIntegral(); e2 = e2->checkIntegral();
//e2 = e2->castTo(sc, Type::tshiftcnt); #if !IN_LLVM
e2 = e2->castTo(sc, e1->type); // LDC e2 = e2->castTo(sc, Type::tshiftcnt);
#else
e2 = e2->castTo(sc, e1->type);
#endif
return this; return this;
} }
@@ -8806,8 +8808,11 @@ Expression *ShrAssignExp::semantic(Scope *sc)
typeCombine(sc); typeCombine(sc);
e1->checkIntegral(); e1->checkIntegral();
e2 = e2->checkIntegral(); e2 = e2->checkIntegral();
//e2 = e2->castTo(sc, Type::tshiftcnt); #if !IN_LLVM
e2 = e2->castTo(sc, e1->type); // LDC e2 = e2->castTo(sc, Type::tshiftcnt);
#else
e2 = e2->castTo(sc, e1->type);
#endif
return this; return this;
} }
@@ -8835,8 +8840,11 @@ Expression *UshrAssignExp::semantic(Scope *sc)
typeCombine(sc); typeCombine(sc);
e1->checkIntegral(); e1->checkIntegral();
e2 = e2->checkIntegral(); e2 = e2->checkIntegral();
//e2 = e2->castTo(sc, Type::tshiftcnt); #if !IN_LLVM
e2 = e2->castTo(sc, e1->type); // LDC e2 = e2->castTo(sc, Type::tshiftcnt);
#else
e2 = e2->castTo(sc, e1->type);
#endif
return this; return this;
} }
@@ -9323,8 +9331,11 @@ Expression *ShlExp::semantic(Scope *sc)
e1 = e1->checkIntegral(); e1 = e1->checkIntegral();
e2 = e2->checkIntegral(); e2 = e2->checkIntegral();
e1 = e1->integralPromotions(sc); e1 = e1->integralPromotions(sc);
//e2 = e2->castTo(sc, Type::tshiftcnt); #if !IN_LLVM
e2 = e2->castTo(sc, e1->type); // LDC e2 = e2->castTo(sc, Type::tshiftcnt);
#else
e2 = e2->castTo(sc, e1->type);
#endif
type = e1->type; type = e1->type;
} }
return this; return this;
@@ -9348,8 +9359,11 @@ Expression *ShrExp::semantic(Scope *sc)
e1 = e1->checkIntegral(); e1 = e1->checkIntegral();
e2 = e2->checkIntegral(); e2 = e2->checkIntegral();
e1 = e1->integralPromotions(sc); e1 = e1->integralPromotions(sc);
//e2 = e2->castTo(sc, Type::tshiftcnt); #if !IN_LLVM
e2 = e2->castTo(sc, e1->type); // LDC e2 = e2->castTo(sc, Type::tshiftcnt);
#else
e2 = e2->castTo(sc, e1->type);
#endif
type = e1->type; type = e1->type;
} }
return this; return this;
@@ -9373,8 +9387,11 @@ Expression *UshrExp::semantic(Scope *sc)
e1 = e1->checkIntegral(); e1 = e1->checkIntegral();
e2 = e2->checkIntegral(); e2 = e2->checkIntegral();
e1 = e1->integralPromotions(sc); e1 = e1->integralPromotions(sc);
//e2 = e2->castTo(sc, Type::tshiftcnt); #if !IN_LLVM
e2 = e2->castTo(sc, e1->type); // LDC e2 = e2->castTo(sc, Type::tshiftcnt);
#else
e2 = e2->castTo(sc, e1->type);
#endif
type = e1->type; type = e1->type;
} }
return this; return this;

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars // Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -645,6 +645,7 @@ struct SymOffExp : Expression
SymOffExp(Loc loc, Declaration *var, unsigned offset); SymOffExp(Loc loc, Declaration *var, unsigned offset);
Expression *semantic(Scope *sc); Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate);
void checkEscape(); void checkEscape();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isConst(); int isConst();
@@ -722,6 +723,7 @@ struct FuncExp : Expression
FuncExp(Loc loc, FuncLiteralDeclaration *fd); FuncExp(Loc loc, FuncLiteralDeclaration *fd);
Expression *syntaxCopy(); Expression *syntaxCopy();
Expression *semantic(Scope *sc); Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate);
void scanForNestedRef(Scope *sc); void scanForNestedRef(Scope *sc);
char *toChars(); char *toChars();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -985,6 +987,7 @@ struct DelegateExp : UnaExp
DelegateExp(Loc loc, Expression *e, FuncDeclaration *func); DelegateExp(Loc loc, Expression *e, FuncDeclaration *func);
Expression *semantic(Scope *sc); Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate);
MATCH implicitConvTo(Type *t); MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t); Expression *castTo(Scope *sc, Type *t);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toCBuffer(OutBuffer *buf, HdrGenState *hgs);

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars // Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // 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_keys(InterState *istate, Expression *earg, FuncDeclaration *fd);
Expression *interpret_values(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. * Attempt to interpret a function given the arguments.
* Input: * Input:
@@ -92,7 +94,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
} }
#endif #endif
if (cantInterpret || semanticRun == 3) if (cantInterpret || semanticRun == PASSsemantic3)
return NULL; return NULL;
if (!fbody) if (!fbody)
@@ -100,13 +102,13 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
return NULL; return NULL;
} }
if (semanticRun < 3 && scope) if (semanticRun < PASSsemantic3 && scope)
{ {
semantic3(scope); semantic3(scope);
if (global.errors) // if errors compiling this function if (global.errors) // if errors compiling this function
return NULL; return NULL;
} }
if (semanticRun < 4) if (semanticRun < PASSsemantic3done)
return NULL; return NULL;
Type *tb = type->toBasetype(); Type *tb = type->toBasetype();
@@ -160,7 +162,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
{ Expression *earg = (Expression *)arguments->data[i]; { Expression *earg = (Expression *)arguments->data[i];
Parameter *arg = Parameter::getNth(tf->parameters, i); Parameter *arg = Parameter::getNth(tf->parameters, i);
if (arg->storageClass & (STCout | STCref)) if (arg->storageClass & (STCout | STCref | STClazy))
{ {
} }
else else
@@ -1005,6 +1007,35 @@ Expression *StringExp::interpret(InterState *istate)
return this; 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 *getVarExp(Loc loc, InterState *istate, Declaration *d)
{ {
Expression *e = EXP_CANT_INTERPRET; Expression *e = EXP_CANT_INTERPRET;
@@ -1013,6 +1044,11 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d)
if (v) if (v)
{ {
#if DMDV2 #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) if ((v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) && v->init && !v->value)
#else #else
if (v->isConst() && v->init) if (v->isConst() && v->init)
@@ -1021,6 +1057,16 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d)
if (e && !e->type) if (e && !e->type)
e->type = v->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 else
{ e = v->value; { e = v->value;
if (!v->isCTFE()) 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 *spliceElements(Expressions *oldelems,
Expressions *newelems, size_t insertpoint) Expressions *newelems, size_t insertpoint)
@@ -1499,6 +1545,26 @@ Expressions *spliceElements(Expressions *oldelems,
return expsx; 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. * Create an array literal consisting of 'elem' duplicated 'dim' times.
*/ */
@@ -1514,6 +1580,28 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type,
return ae; 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. * 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, // To reduce code complexity of handling dotvar expressions,
// extract the aggregate now. // extract the aggregate now.
Expression *aggregate; Expression *aggregate;
if (e1->op == TOKdotvar) { if (e1->op == TOKdotvar)
{
aggregate = ((DotVarExp *)e1)->e1; aggregate = ((DotVarExp *)e1)->e1;
// Get rid of 'this'. // Get rid of 'this'.
if (aggregate->op == TOKthis && istate->localThis) 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: /* Assignment to variable of the form:
* v = e2 * v = e2
*/ */
@@ -1623,7 +1714,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
if (e2 == EXP_CANT_INTERPRET) if (e2 == EXP_CANT_INTERPRET)
return e2; return e2;
addVarToInterstate(istate, v); if (istate)
addVarToInterstate(istate, v);
v->value = e2; v->value = e2;
e = Cast(type, type, post ? ev : 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. * on the void value - to do that we'd need a VoidExp.
* That's probably a good enhancement idea. * That's probably a good enhancement idea.
*/ */
v->value = v->type->defaultInit(); v->value = v->type->defaultInitLiteral();
} }
Expression *vie = v->value; Expression *vie = v->value;
assert(vie != EXP_CANT_INTERPRET);
if (vie->op == TOKvar) if (vie->op == TOKvar)
{ {
Declaration *d = ((VarExp *)vie)->var; Declaration *d = ((VarExp *)vie)->var;
vie = getVarExp(e1->loc, istate, d); vie = getVarExp(e1->loc, istate, d);
} }
if (vie->op != TOKstructliteral) if (vie->op != TOKstructliteral)
{
error("Cannot assign %s=%s in CTFE", v->toChars(), vie->toChars());
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
}
StructLiteralExp *se = (StructLiteralExp *)vie; StructLiteralExp *se = (StructLiteralExp *)vie;
VarDeclaration *vf = ((DotVarExp *)e1)->var->isVarDeclaration(); VarDeclaration *vf = ((DotVarExp *)e1)->var->isVarDeclaration();
if (!vf) 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()); error("%s cannot be modified at compile time", v->toChars());
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
// Chase down rebinding of out and ref // Chase down rebinding of out and ref
if (v->value && v->value->op == TOKvar) if (v->value && v->value->op == TOKvar)
{ {
VarExp *ve2 = (VarExp *)v->value; VarExp *ve2 = (VarExp *)v->value;
if (ve2->var->isStaticStructInitDeclaration()) if (ve2->var->isStaticStructInitDeclaration())
{ // This can happen if v is a struct initialized to { // This can happen if v is a struct initialized to
// 0 using an __initZ SymbolDeclaration from // 0 using an __initZ SymbolDeclaration from
// TypeStruct::defaultInit() // TypeStruct::defaultInit()
}
else
v = ve2->var->isVarDeclaration();
assert(v);
} }
else
v = ve2->var->isVarDeclaration();
assert(v);
}
/* Set the $ variable /* Set the $ variable
*/ */
Expression *ee = v->value ? ArrayLength(Type::tsize_t, v->value) 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) if (v->value->op == TOKarrayliteral)
dim = ((ArrayLiteralExp *)v->value)->elements->dim; dim = ((ArrayLiteralExp *)v->value)->elements->dim;
else if (v->value->op ==TOKstring) else if (v->value->op ==TOKstring)
{ dim = ((StringExp *)v->value)->len;
error("String slice assignment is not yet supported in CTFE");
return EXP_CANT_INTERPRET;
}
} }
else else
{ {
@@ -2075,67 +2169,87 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
int upperbound = upper ? upper->toInteger() : dim; int upperbound = upper ? upper->toInteger() : dim;
int lowerbound = lower ? lower->toInteger() : 0; int lowerbound = lower ? lower->toInteger() : 0;
ArrayLiteralExp *existing;
if (((int)lowerbound < 0) || (upperbound > dim)) 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; 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. error("Array length mismatch assigning [0..%d] to [%d..%d]", srclen, lowerbound, upperbound);
// If the existing array is uninitialized (this can only happen return e;
// 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);
}
} }
if (e2->op == TOKarrayliteral) if (e2->op == TOKarrayliteral)
{ {
// Static array assignment from literal // Static array assignment from literal
ArrayLiteralExp *ae = (ArrayLiteralExp *)e2; 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) if (upperbound - lowerbound == dim)
v->value = ae; v->value = ae;
else 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..$] // value[] = value[0..lower] ~ ae ~ value[upper..$]
existing->elements = spliceElements(existing->elements, ae->elements, lowerbound); existing->elements = spliceElements(existing->elements, ae->elements, lowerbound);
v->value = existing; v->value = existing;
} }
return e2; 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) else if (e2->op == TOKstring)
{ {
StringExp *se = (StringExp *)e2; StringExp *se = (StringExp *)e2;
// This is problematic. char[8] should be storing if (upperbound-lowerbound == dim)
// values as a string literal, not v->value = e2;
// as an array literal. Then, for static arrays, we else
// could do modifications {
// in-place, with a dramatic memory and speed improvement. if (!v->value)
error("String slice assignment is not yet supported in CTFE"); 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; return e2;
} }
else else
@@ -2260,74 +2374,118 @@ Expression *CallExp::interpret(InterState *istate)
#if LOG #if LOG
printf("CallExp::interpret() %s\n", toChars()); printf("CallExp::interpret() %s\n", toChars());
#endif #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; VarDeclaration *vd = ((VarExp *)ecall)->var->isVarDeclaration();
FuncDeclaration *fd = ((DotVarExp*)e1)->var->isFuncDeclaration(); if (vd && vd->value)
TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL; ecall = vd->value;
if (tf) else // Calling a function
{ // Member function call fd = ((VarExp *)e1)->var->isFuncDeclaration();
if(pthis->op == TOKthis) }
pthis = istate->localThis; if (ecall->op == TOKdelegate)
Expression *eresult = fd->interpret(istate, arguments, pthis); { // 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) if (eresult)
e = eresult; e = eresult;
else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors) else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors)
e = EXP_VOID_INTERPRET; e = EXP_VOID_INTERPRET;
else else
error("cannot evaluate %s at compile time", toChars()); error("cannot evaluate %s at compile time", toChars());
return e; }
} }
else
{
error("cannot evaluate %s at compile time", toChars()); error("cannot evaluate %s at compile time", toChars());
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
if (e1->op == TOKvar) return e;
{
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;
} }
Expression *CommaExp::interpret(InterState *istate) Expression *CommaExp::interpret(InterState *istate)
@@ -2335,6 +2493,21 @@ Expression *CommaExp::interpret(InterState *istate)
#if LOG #if LOG
printf("CommaExp::interpret() %s\n", toChars()); printf("CommaExp::interpret() %s\n", toChars());
#endif #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); Expression *e = e1->interpret(istate);
if (e != EXP_CANT_INTERPRET) if (e != EXP_CANT_INTERPRET)
e = e2->interpret(istate); e = e2->interpret(istate);
@@ -2516,14 +2689,18 @@ Expression *AssertExp::interpret(InterState *istate)
if( this->e1->op == TOKaddress) if( this->e1->op == TOKaddress)
{ // Special case: deal with compiler-inserted assert(&this, "null this") { // Special case: deal with compiler-inserted assert(&this, "null this")
AddrExp *ade = (AddrExp *)this->e1; AddrExp *ade = (AddrExp *)this->e1;
if(ade->e1->op == TOKthis && istate->localThis) if (ade->e1->op == TOKthis && istate->localThis)
return istate->localThis->interpret(istate); 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); e1 = this->e1->interpret(istate);
if (e1 == EXP_CANT_INTERPRET) if (e1 == EXP_CANT_INTERPRET)
goto Lcant; goto Lcant;

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars // Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -235,7 +235,9 @@ struct Param
char *deffile; char *deffile;
char *resfile; char *resfile;
char *exefile; char *exefile;
char *mapfile;
#if IN_LLVM
// LDC stuff // LDC stuff
OUTPUTFLAG output_ll; OUTPUTFLAG output_ll;
OUTPUTFLAG output_bc; OUTPUTFLAG output_bc;
@@ -250,6 +252,7 @@ struct Param
const char* llvmArch; const char* llvmArch;
const char *targetTriple; const char *targetTriple;
const char *dataLayout; const char *dataLayout;
#endif
}; };
struct Global struct Global
@@ -268,6 +271,7 @@ struct Global
const char *ddoc_ext; // for Ddoc macro include files const char *ddoc_ext; // for Ddoc macro include files
const char *hdr_ext; // for D 'header' import files const char *hdr_ext; // for D 'header' import files
const char *json_ext; // for JSON files const char *json_ext; // for JSON files
const char *map_ext; // for .map files
const char *copyright; const char *copyright;
const char *written; const char *written;
Array *path; // Array of char*'s which form the import lookup path Array *path; // Array of char*'s which form the import lookup path
@@ -393,8 +397,9 @@ enum LINK
LINKwindows, LINKwindows,
LINKpascal, LINKpascal,
// LDC #if IN_LLVM
LINKintrinsic, LINKintrinsic,
#endif
}; };
enum DYNCAST enum DYNCAST

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars // Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -44,7 +44,7 @@
#include "d-dmd-gcc.h" #include "d-dmd-gcc.h"
#endif #endif
#if IN_LLVM
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include <map> #include <map>
@@ -55,8 +55,7 @@ static llvm::cl::opt<bool> preservePaths("op",
static llvm::cl::opt<bool> fqnNames("oq", static llvm::cl::opt<bool> fqnNames("oq",
llvm::cl::desc("Write object files with fully qualified names"), llvm::cl::desc("Write object files with fully qualified names"),
llvm::cl::ZeroOrMore); llvm::cl::ZeroOrMore);
#endif
ClassDeclaration *Module::moduleinfo; ClassDeclaration *Module::moduleinfo;
@@ -971,7 +970,8 @@ void Module::addDeferredSemantic(Dsymbol *s)
void Module::runDeferredSemantic() void Module::runDeferredSemantic()
{ {
size_t len; if (dprogress == 0)
return;
static int nested; static int nested;
if (nested) if (nested)
@@ -979,6 +979,7 @@ void Module::runDeferredSemantic()
//if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
nested++; nested++;
size_t len;
do do
{ {
dprogress = 0; dprogress = 0;

View File

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

View File

@@ -4061,8 +4061,15 @@ Dsymbol *TypeEnum::toDsymbol(Scope *sc)
Type *TypeEnum::toBasetype() Type *TypeEnum::toBasetype()
{ {
if (sym->scope) if (sym->scope)
{ { // Enum is forward referenced. We don't need to resolve the whole thing,
sym->semantic(NULL); // attempt to resolve forward reference // 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) if (!sym->memtype)
{ {

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars // Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -344,7 +344,9 @@ Expression *NewExp::optimize(int result)
} }
Expression *CallExp::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 // Optimize parameters
if (arguments) if (arguments)
@@ -358,17 +360,15 @@ Expression *CallExp::optimize(int result)
} }
e1 = e1->optimize(result); e1 = e1->optimize(result);
if (e1->op == TOKvar && result & WANTinterpret) if (result & WANTinterpret)
{ {
FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); Expression *eresult = interpret(NULL);
if (fd) if (eresult == EXP_CANT_INTERPRET)
{ return e;
Expression *eresult = fd->interpret(NULL, arguments); if (eresult && eresult != EXP_VOID_INTERPRET)
if (eresult && eresult != EXP_VOID_INTERPRET) e = eresult;
e = eresult; else
else if (result & WANTinterpret) error("cannot evaluate %s at compile time", toChars());
error("cannot evaluate %s at compile time", toChars());
}
} }
return e; return e;
} }
@@ -624,6 +624,22 @@ Expression *CommaExp::optimize(int result)
{ Expression *e; { Expression *e;
//printf("CommaExp::optimize(result = %d) %s\n", result, toChars()); //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); e1 = e1->optimize(result & WANTinterpret);
e2 = e2->optimize(result); e2 = e2->optimize(result);
if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2)) if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2))
@@ -709,8 +725,8 @@ Expression *SliceExp::optimize(int result)
{ if (e1->op == TOKstring) { if (e1->op == TOKstring)
{ // Convert slice of string literal into dynamic array { // Convert slice of string literal into dynamic array
Type *t = e1->type->toBasetype(); Type *t = e1->type->toBasetype();
if (t->next) if (t->nextOf())
e = e1->castTo(NULL, t->next->arrayOf()); e = e1->castTo(NULL, t->nextOf()->arrayOf());
} }
return e; return e;
} }

View File

@@ -2483,7 +2483,14 @@ Statement *PragmaStatement::semantic(Scope *sc)
Expression *e = (Expression *)args->data[i]; Expression *e = (Expression *)args->data[i];
e = e->semantic(sc); e = e->semantic(sc);
#if 1
e = e->optimize(WANTvalue | WANTinterpret); 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) if (e->op == TOKstring)
{ {
StringExp *se = (StringExp *)e; StringExp *se = (StringExp *)e;

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars // Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -3539,7 +3539,8 @@ void TemplateInstance::semantic(Scope *sc)
error("error instantiating"); error("error instantiating");
if (tinst) if (tinst)
{ tinst->printInstantiationTrace(); { tinst->printInstantiationTrace();
fatal(); if (!global.gag)
fatal();
} }
errors = 1; errors = 1;
if (global.gag) 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;
}