mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-04-24 12:49:12 +02: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
|
#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
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
35
dmd/attrib.c
35
dmd/attrib.c
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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++)
|
||||||
|
|||||||
@@ -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 **********************/
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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 ******************************/
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
205
dmd/func.c
205
dmd/func.c
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
437
dmd/interpret.c
437
dmd/interpret.c
@@ -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;
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
11
dmd/module.c
11
dmd/module.c
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
11
dmd/mtype.c
11
dmd/mtype.c
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
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