Merge of DMD 2.062.

This commit is contained in:
kai
2013-03-06 20:23:46 +01:00
committed by David Nadlinger
parent 0b5e04580c
commit e8814d0603
65 changed files with 2964 additions and 2108 deletions
+2 -1
View File
@@ -219,7 +219,8 @@ void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember)
result = access2 >= PROTpublic ||
hasPrivateAccess(f) ||
isFriendOf(cdscope) ||
(access2 == PROTpackage && hasPackageAccess(sc, this));
(access2 == PROTpackage && hasPackageAccess(sc, this)) ||
getAccessModule() == sc->module;
#if LOG
printf("result1 = %d\n", result);
#endif
+7 -13
View File
@@ -118,9 +118,13 @@ struct AggregateDeclaration : ScopeDsymbol
int isExport();
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toJson(JsonOut *json);
void toDocBuffer(OutBuffer *buf, Scope *sc);
FuncDeclaration *hasIdentityOpAssign(Scope *sc, Dsymbol *assign);
char *mangle(bool isv = false);
// For access checking
virtual PROT getAccess(Dsymbol *smember); // determine access to smember
int isFriendOf(AggregateDeclaration *cd);
@@ -144,16 +148,6 @@ struct AggregateDeclaration : ScopeDsymbol
#endif
};
struct AnonymousAggregateDeclaration : AggregateDeclaration
{
AnonymousAggregateDeclaration()
: AggregateDeclaration(0, NULL)
{
}
AnonymousAggregateDeclaration *isAnonymousAggregateDeclaration() { return this; }
};
struct StructDeclaration : AggregateDeclaration
{
int zeroInit; // !=0 if initialize with 0 fill
@@ -179,7 +173,7 @@ struct StructDeclaration : AggregateDeclaration
void semantic(Scope *sc);
Dsymbol *search(Loc, Identifier *ident, int flags);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *mangle();
char *mangle(bool isv = false);
const char *kind();
void finalizeSize(Scope *sc);
bool isPOD();
@@ -320,7 +314,7 @@ struct ClassDeclaration : AggregateDeclaration
int isAbstract();
virtual int vtblOffset();
const char *kind();
char *mangle();
char *mangle(bool isv = false);
void toDocBuffer(OutBuffer *buf, Scope *sc);
PROT getAccess(Dsymbol *smember); // determine access to smember
-1
View File
@@ -4,7 +4,6 @@
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// http://www.dsource.org/projects/dmd/browser/branches/dmd-1.x/src/argtypes.c
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
+36 -48
View File
@@ -27,14 +27,10 @@
#include "module.h"
#include "parse.h"
#include "template.h"
#if TARGET_NET
#include "frontend.net/pragma.h"
#endif
#if IN_LLVM
#include "../gen/pragma.h"
#endif
#if IN_DMD
extern bool obj_includelib(const char *name);
void obj_startaddress(Symbol *s);
@@ -484,7 +480,14 @@ void StorageClassDeclaration::semantic(Scope *sc)
}
}
void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
/*************************************************
* Pick off one of the storage classes from stc,
* and return a pointer to a string representation of it.
* stc is reduced by the one picked.
* tmp[] is a buffer big enough to hold that string.
*/
const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc)
{
struct SCstring
{
@@ -528,21 +531,39 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
{
if (stc & table[i].stc)
StorageClass tbl = table[i].stc;
assert(tbl & STCStorageClass);
if (stc & tbl)
{
stc &= ~tbl;
enum TOK tok = table[i].tok;
#if DMDV2
if (tok == TOKat)
{
buf->writeByte('@');
buf->writestring(table[i].id->toChars());
tmp[0] = '@';
strcpy(tmp + 1, table[i].id->toChars());
return tmp;
}
else
#endif
buf->writestring(Token::toChars(tok));
buf->writeByte(' ');
return Token::toChars(tok);
}
}
//printf("stc = %llx\n", (unsigned long long)stc);
return NULL;
}
void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
{
while (stc)
{ char tmp[20];
const char *p = stcToChars(tmp, stc);
if (!p)
break;
assert(strlen(p) < sizeof(tmp));
buf->writestring(p);
buf->writeByte(' ');
}
}
void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
@@ -916,7 +937,9 @@ void AnonDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset
void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->printf(isunion ? "union" : "struct");
buf->writestring("\n{\n");
buf->writenl();
buf->writestring("{");
buf->writenl();
buf->level++;
if (decl)
{
@@ -927,7 +950,8 @@ void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
}
}
buf->level--;
buf->writestring("}\n");
buf->writestring("}");
buf->writenl();
}
const char *AnonDeclaration::kind()
@@ -958,37 +982,6 @@ Dsymbol *PragmaDeclaration::syntaxCopy(Dsymbol *s)
void PragmaDeclaration::setScope(Scope *sc)
{
#if TARGET_NET
if (ident == Lexer::idPool("assembly"))
{
if (!args || args->dim != 1)
{
error("pragma has invalid number of arguments");
}
else
{
Expression *e = (*args)[0];
e = e->semantic(sc);
e = resolveProperties(sc, e);
e = e->ctfeInterpret();
(*args)[0] = e;
StringExp* se = e->toString();
if (!se)
{
error("string expected, not '%s'", e->toChars());
}
PragmaScope* pragma = new PragmaScope(this, sc->parent, se);
assert(sc);
pragma->setScope(sc);
//add to module members
assert(sc->module);
assert(sc->module->members);
sc->module->members->push(pragma);
}
}
#endif // TARGET_NET
}
void PragmaDeclaration::semantic(Scope *sc)
@@ -1113,11 +1106,6 @@ void PragmaDeclaration::semantic(Scope *sc)
goto Lnodecl;
}
#endif
#if TARGET_NET
else if (ident == Lexer::idPool("assembly"))
{
}
#endif // TARGET_NET
#if IN_LLVM
else if ((llvm_internal = DtoGetPragma(sc, this, arg1str)) != LLVMnone)
{
+3 -2
View File
@@ -55,7 +55,7 @@ struct AttribDeclaration : Dsymbol
void checkCtorConstInit();
void addLocalClass(ClassDeclarations *);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJsonBuffer(OutBuffer *buf);
void toJson(JsonOut *json);
AttribDeclaration *isAttribDeclaration() { return this; }
#if IN_DMD
@@ -78,6 +78,7 @@ struct StorageClassDeclaration : AttribDeclaration
int oneMember(Dsymbol **ps, Identifier *ident);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
static const char *stcToChars(char tmp[], StorageClass& stc);
static void stcToCBuffer(OutBuffer *buf, StorageClass stc);
};
@@ -176,7 +177,7 @@ struct ConditionalDeclaration : AttribDeclaration
Dsymbols *include(Scope *sc, ScopeDsymbol *s);
void addComment(unsigned char *comment);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJsonBuffer(OutBuffer *buf);
void toJson(JsonOut *json);
void importAll(Scope *sc);
void setScope(Scope *sc);
};
+32 -13
View File
@@ -1992,18 +1992,10 @@ Expression *CondExp::inferType(Type *t, int flag, TemplateParameters *tparams)
Expression *BinExp::scaleFactor(Scope *sc)
{
if (sc->func && !sc->intypeof)
{
if (sc->func->setUnsafe())
{
error("pointer arithmetic not allowed in @safe functions");
return new ErrorExp();
}
}
d_uns64 stride;
Type *t1b = e1->type->toBasetype();
Type *t2b = e2->type->toBasetype();
Expression *eoff;
if (t1b->ty == Tpointer && t2b->isintegral())
{ // Need to adjust operator by the stride
@@ -2017,6 +2009,7 @@ Expression *BinExp::scaleFactor(Scope *sc)
#if !IN_LLVM
e2 = new MulExp(loc, e2, new IntegerExp(0, stride, t));
#endif
eoff = e2;
e2->type = t;
type = e1->type;
}
@@ -2034,11 +2027,27 @@ Expression *BinExp::scaleFactor(Scope *sc)
#if !IN_LLVM
e = new MulExp(loc, e, new IntegerExp(0, stride, t));
#endif
eoff = e;
e->type = t;
type = e2->type;
e1 = e2;
e2 = e;
}
else
assert(0);
if (sc->func && !sc->intypeof)
{
eoff = eoff->optimize(WANTvalue);
if (eoff->op == TOKint64 && eoff->toInteger() == 0)
;
else if (sc->func->setUnsafe())
{
error("pointer arithmetic not allowed in @safe functions");
return new ErrorExp();
}
}
return this;
}
@@ -2088,9 +2097,11 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression
MATCH m;
Expression *e1 = *pe1;
Expression *e2 = *pe2;
Type *t1b = e1->type->toBasetype();
Type *t2b = e2->type->toBasetype();
if (e->op != TOKquestion ||
e1->type->toBasetype()->ty != e2->type->toBasetype()->ty)
t1b->ty != t2b->ty && (t1b->isTypeBasic() && t2b->isTypeBasic()))
{
e1 = e1->integralPromotions(sc);
e2 = e2->integralPromotions(sc);
@@ -2109,8 +2120,8 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression
assert(t2);
Lagain:
Type *t1b = t1->toBasetype();
Type *t2b = t2->toBasetype();
t1b = t1->toBasetype();
t2b = t2->toBasetype();
TY ty = (TY)Type::impcnvResult[t1b->ty][t2b->ty];
if (ty != Terror)
@@ -2199,11 +2210,12 @@ Lagain:
if (t1->ty == Tdelegate)
{
tx = new TypeDelegate(d);
tx = tx->merge();
}
else
tx = d->pointerTo();
tx = tx->semantic(e1->loc, sc);
if (t1->implicitConvTo(tx) && t2->implicitConvTo(tx))
{
t = tx;
@@ -2534,6 +2546,13 @@ Lcc:
}
else if (t1->isintegral() && t2->isintegral())
{
if (t1->ty != t2->ty)
{
e1 = e1->integralPromotions(sc);
e2 = e2->integralPromotions(sc);
t1 = e1->type; t1b = t1->toBasetype();
t2 = e2->type; t2b = t2->toBasetype();
}
assert(t1->ty == t2->ty);
if (!t1->isImmutable() && !t2->isImmutable() && t1->isShared() != t2->isShared())
goto Lincompatible;
+18 -28
View File
@@ -609,14 +609,17 @@ void ClassDeclaration::semantic(Scope *sc)
if (isCOMclass())
{
#if _WIN32
sc->linkage = LINKwindows;
#if IN_LLVM
if (global.params.targetTriple.isOSWindows())
#else
/* This enables us to use COM objects under Linux and
* work with things like XPCOM
*/
sc->linkage = LINKc;
if (global.params.isWindows)
#endif
sc->linkage = LINKwindows;
else
/* This enables us to use COM objects under Linux and
* work with things like XPCOM
*/
sc->linkage = LINKc;
}
sc->protection = PROTpublic;
sc->explicitProtection = 0;
@@ -794,27 +797,11 @@ void ClassDeclaration::semantic(Scope *sc)
dtor = buildDtor(sc);
if (Dsymbol *assign = search_function(this, Id::assign))
{
Expression *e = new NullExp(loc, type); // dummy rvalue
Expressions *arguments = new Expressions();
arguments->push(e);
// check identity opAssign exists
FuncDeclaration *fd = assign->isFuncDeclaration();
if (fd)
{ fd = fd->overloadResolve(loc, e, arguments, 1);
if (fd && !(fd->storage_class & STCdisable))
goto Lassignerr;
if (FuncDeclaration *f = hasIdentityOpAssign(sc, assign))
{
if (!(f->storage_class & STCdisable))
error("identity assignment operator overload is illegal");
}
if (TemplateDeclaration *td = assign->isTemplateDeclaration())
{ fd = td->deduceFunctionTemplate(sc, loc, NULL, e, arguments, 1+2);
if (fd && !(fd->storage_class & STCdisable))
goto Lassignerr;
}
Lassignerr:
if (fd && !(fd->storage_class & STCdisable))
error("identity assignment operator overload is illegal");
}
sc->pop();
@@ -1664,6 +1651,7 @@ int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newins
assert(ifd);
// Find corresponding function in this class
tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL;
assert(tf); // should always be non-null
fd = cd->findFunc(ifd->ident, tf);
if (fd && !fd->isAbstract())
{
@@ -1687,8 +1675,10 @@ int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newins
//printf(" not found\n");
// BUG: should mark this class as abstract?
if (!cd->isAbstract())
cd->error("interface function %s.%s isn't implemented",
id->toChars(), ifd->ident->toChars());
cd->error("interface function %s.%s%s isn't implemented",
id->toChars(), ifd->ident->toChars(),
Parameter::argsTypesToChars(tf->parameters, tf->varargs));
fd = NULL;
}
if (vtbl)
+94 -58
View File
@@ -24,6 +24,62 @@
#include "template.h"
/*******************************************
* Check given opAssign symbol is really identity opAssign or not.
*/
FuncDeclaration *AggregateDeclaration::hasIdentityOpAssign(Scope *sc, Dsymbol *assign)
{
if (assign)
{
assert(assign->ident == Id::assign);
/* check identity opAssign exists
*/
Expression *er = new NullExp(loc, type); // dummy rvalue
Expression *el = new IdentifierExp(loc, Id::p); // dummy lvalue
el->type = type;
Expressions ar; ar.push(er);
Expressions al; al.push(el);
FuncDeclaration *f = NULL;
if (FuncDeclaration *fd = assign->isFuncDeclaration())
{
f = fd->overloadResolve(loc, er, &ar, 1);
if (!f) f = fd->overloadResolve(loc, er, &al, 1);
}
if (TemplateDeclaration *td = assign->isTemplateDeclaration())
{
unsigned errors = global.startGagging(); // Do not report errors, even if the
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
global.speculativeGag = global.gag;
Scope *sc2 = sc->push();
sc2->speculative = true;
f = td->deduceFunctionTemplate(sc2, loc, NULL, er, &ar, 1);
if (!f) f = td->deduceFunctionTemplate(sc2, loc, NULL, er, &al, 1);
sc2->pop();
global.speculativeGag = oldspec;
global.endGagging(errors);
}
if (f)
{
int varargs;
Parameters *fparams = f->getParameters(&varargs);
if (fparams->dim >= 1)
{
Parameter *arg0 = Parameter::getNth(fparams, 0);
if (arg0->type->toDsymbol(NULL) != this)
f = NULL;
}
}
// BUGS: This detection mechanism cannot find some opAssign-s like follows:
// struct S { void opAssign(ref immutable S) const; }
return f;
}
return NULL;
}
/*******************************************
* We need an opAssign for the struct if
* it has a destructor or a postblit.
@@ -90,27 +146,8 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
Dsymbol *assign = search_function(this, Id::assign);
if (assign)
{
/* check identity opAssign exists
*/
Expression *er = new NullExp(loc, type); // dummy rvalue
Expression *el = new IdentifierExp(loc, Id::p); // dummy lvalue
el->type = type;
Expressions ar; ar.push(er);
Expressions al; al.push(el);
if (FuncDeclaration *fd = assign->isFuncDeclaration())
{
FuncDeclaration *f = fd->overloadResolve(loc, er, &ar, 1);
if (f == NULL) f = fd->overloadResolve(loc, er, &al, 1);
if (f)
return (f->storage_class & STCdisable) ? NULL : f;
}
if (TemplateDeclaration *td = assign->isTemplateDeclaration())
{
FuncDeclaration *f = td->deduceFunctionTemplate(sc, loc, NULL, er, &ar, 1);
if (f == NULL) f = td->deduceFunctionTemplate(sc, loc, NULL, er, &al, 1);
if (f)
return (f->storage_class & STCdisable) ? NULL : f;
}
if (FuncDeclaration *f = hasIdentityOpAssign(sc, assign))
return f;
// Even if non-identity opAssign is defined, built-in identity opAssign
// will be defined. (Is this an exception of operator overloading rule?)
}
@@ -123,9 +160,7 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
Parameters *fparams = new Parameters;
fparams->push(new Parameter(STCnodtor, type, Id::p, NULL));
Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd);
#if STRUCTTHISREF
((TypeFunction *)ftype)->isref = 1;
#endif
FuncDeclaration *fop = new FuncDeclaration(loc, 0, Id::assign, STCundefined, ftype);
@@ -146,21 +181,13 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
e = new DeclarationExp(0, tmp);
ec = new AssignExp(0,
new VarExp(0, tmp),
#if STRUCTTHISREF
new ThisExp(0)
#else
new PtrExp(0, new ThisExp(0))
#endif
);
ec->op = TOKblit;
e = Expression::combine(e, ec);
}
ec = new AssignExp(0,
#if STRUCTTHISREF
new ThisExp(0),
#else
new PtrExp(0, new ThisExp(0)),
#endif
new IdentifierExp(0, Id::p));
ec->op = TOKblit;
e = Expression::combine(e, ec);
@@ -213,14 +240,29 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
}
members->push(s);
s->addMember(sc, this, 1);
this->hasIdentityAssign = 1; // temporary mark identity assignable
sc = sc->push();
sc->stc = 0;
sc->linkage = LINKd;
s->semantic(sc);
sc->pop();
unsigned errors = global.startGagging(); // Do not report errors, even if the
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
global.speculativeGag = global.gag;
Scope *sc2 = sc->push();
sc2->stc = 0;
sc2->linkage = LINKd;
sc2->speculative = true;
//printf("-StructDeclaration::buildOpAssign() %s\n", toChars());
s->semantic(sc2);
s->semantic2(sc2);
s->semantic3(sc2);
sc2->pop();
global.speculativeGag = oldspec;
if (global.endGagging(errors)) // if errors happened
{ // Disable generated opAssign, because some members forbid identity assignment.
fop->storage_class |= STCdisable;
fop->fbody = NULL; // remove fbody which contains the error
}
//printf("-StructDeclaration::buildOpAssign() %s %s, errors = %d\n", toChars(), s->kind(), (fop->storage_class & STCdisable) != 0);
return fop;
}
@@ -410,20 +452,20 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
size_t index = members->dim;
members->push(fop);
sc = sc->push();
sc->stc = 0;
sc->linkage = LINKd;
unsigned errors = global.startGagging(); // Do not report errors, even if the
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
global.speculativeGag = global.gag;
Scope *sc2 = sc->push();
sc2->stc = 0;
sc2->linkage = LINKd;
sc2->speculative = true;
unsigned errors = global.startGagging();
fop->semantic(sc);
if (errors == global.gaggedErrors)
{ fop->semantic2(sc);
if (errors == global.gaggedErrors)
{ fop->semantic3(sc);
if (errors == global.gaggedErrors)
fop->addMember(sc, this, 1);
}
}
fop->semantic(sc2);
fop->semantic2(sc2);
fop->semantic3(sc2);
sc2->pop();
global.speculativeGag = oldspec;
if (global.endGagging(errors)) // if errors happened
{
members->remove(index);
@@ -441,8 +483,8 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
}
fop = xerreq;
}
sc->pop();
else
fop->addMember(sc, this, 1);
return fop;
}
@@ -492,9 +534,6 @@ FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
{
// Build *this = p;
Expression *e = new ThisExp(0);
#if !STRUCTTHISREF
e = new PtrExp(0, e);
#endif
AssignExp *ea = new AssignExp(0,
new PtrExp(0, new CastExp(0, new AddrExp(0, e), type->mutableOf()->pointerTo())),
new PtrExp(0, new CastExp(0, new AddrExp(0, new IdentifierExp(0, Id::p)), type->mutableOf()->pointerTo()))
@@ -504,9 +543,6 @@ FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
// Build postBlit();
e = new ThisExp(0);
#if !STRUCTTHISREF
e = new PtrExp(0, e);
#endif
e = new PtrExp(0, new CastExp(0, new AddrExp(0, e), type->mutableOf()->pointerTo()));
e = new DotVarExp(0, e, postblit, 0);
e = new CallExp(0, e);
+3 -3
View File
@@ -160,10 +160,10 @@ char *cpp_mangle(Dsymbol *s)
cms.components.setDim(0);
OutBuffer buf;
#if TARGET_OSX
buf.writestring("__Z");
#if IN_LLVM
buf.writestring("__Z" + !(global.params.targetTriple.isMacOSX())); // "_Z" for OSX
#else
buf.writestring("_Z");
buf.writestring("__Z" + !global.params.isOSX); // "_Z" for OSX
#endif
cpp_mangle_name(&buf, &cms, s);
+2 -2
View File
@@ -1575,7 +1575,7 @@ Expression *ctfeIndex(Loc loc, Type *type, Expression *e1, uinteger_t indx)
{ StringExp *es1 = (StringExp *)e1;
if (indx >= es1->len)
{
error(loc, "string index %ju is out of bounds [0 .. %zu]", indx, es1->len);
error(loc, "string index %llu is out of bounds [0 .. %llu]", indx, (ulonglong)es1->len);
return EXP_CANT_INTERPRET;
}
else
@@ -1585,7 +1585,7 @@ Expression *ctfeIndex(Loc loc, Type *type, Expression *e1, uinteger_t indx)
ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
if (indx >= ale->elements->dim)
{
error(loc, "array index %ju is out of bounds %s[0 .. %u]", indx, e1->toChars(), ale->elements->dim);
error(loc, "array index %llu is out of bounds %s[0 .. %llu]", indx, e1->toChars(), (ulonglong)ale->elements->dim);
return EXP_CANT_INTERPRET;
}
Expression *e = ale->elements->tdata()[indx];
+35 -16
View File
@@ -19,6 +19,7 @@
#include "scope.h"
#include "aggregate.h"
#include "module.h"
#include "import.h"
#include "id.h"
#include "expression.h"
#include "statement.h"
@@ -130,26 +131,30 @@ enum PROT Declaration::prot()
#if DMDV2
int Declaration::checkModify(Loc loc, Scope *sc, Type *t)
int Declaration::checkModify(Loc loc, Scope *sc, Type *t, Expression *e1, int flag)
{
VarDeclaration *v = isVarDeclaration();
if (v && v->canassign)
return 2;
if ((sc->flags & SCOPEcontract) && isParameter())
error(loc, "cannot modify parameter '%s' in contract", toChars());
if ((sc->flags & SCOPEcontract) && isResult())
error(loc, "cannot modify result '%s' in contract", toChars());
if (isCtorinit() && !t->isMutable() ||
(storage_class & STCnodefaultctor))
{ // It's only modifiable if inside the right constructor
return modifyFieldVar(loc, sc, isVarDeclaration(), NULL);
}
else
{
VarDeclaration *v = isVarDeclaration();
if (v && v->canassign)
return TRUE;
if (!flag) error(loc, "cannot modify parameter '%s' in contract", toChars());
return 0;
}
return FALSE;
if ((sc->flags & SCOPEcontract) && isResult())
{
if (!flag) error(loc, "cannot modify result '%s' in contract", toChars());
return 0;
}
if (v && isCtorinit())
{ // It's only modifiable if inside the right constructor
if ((storage_class & (STCforeach | STCref)) == (STCforeach | STCref))
return 2;
return modifyFieldVar(loc, sc, v, e1) ? 2 : 1;
}
return 1;
}
#endif
@@ -431,6 +436,7 @@ AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type)
this->loc = loc;
this->type = type;
this->aliassym = NULL;
this->import = NULL;
this->htype = NULL;
this->haliassym = NULL;
this->overnext = NULL;
@@ -447,6 +453,7 @@ AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s)
this->loc = loc;
this->type = NULL;
this->aliassym = s;
this->import = NULL;
this->htype = NULL;
this->haliassym = NULL;
this->overnext = NULL;
@@ -694,6 +701,13 @@ Dsymbol *AliasDeclaration::toAlias()
}
else if (aliassym || type->deco)
; // semantic is already done.
else if (import)
{
/* If this is an internal alias for selective import,
* resolve it under the correct scope.
*/
import->semantic(NULL);
}
else if (scope)
semantic(scope);
Dsymbol *s = aliassym ? aliassym->toAlias() : this;
@@ -1126,6 +1140,7 @@ Lnomatch:
(*exps)[i] = e;
}
TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps);
v2->parent = this->parent;
v2->isexp = 1;
aliassym = v2;
return;
@@ -2065,6 +2080,10 @@ Expression *VarDeclaration::getConstInitializer()
ExpInitializer *ei = getExpInitializer();
if (ei)
return ei->exp;
else if (init)
{
return init->toExpression();
}
}
return NULL;
+25 -16
View File
@@ -104,6 +104,12 @@ enum PURE;
#define STCtemp 0x10000000000LL // temporary variable introduced by inlining
// and used only in backend process, so it's rvalue
#define STCStorageClass (STCauto | STCscope | STCstatic | STCextern | STCconst | STCfinal | \
STCabstract | STCsynchronized | STCdeprecated | STCoverride | STClazy | STCalias | \
STCout | STCin | \
STCmanifest | STCimmutable | STCshared | STCnothrow | STCpure | STCref | STCtls | \
STCgshared | STCproperty | STCsafe | STCtrusted | STCsystem | STCdisable)
#ifdef BUG6652
#define STCbug6652 0x800000000000LL //
#endif
@@ -152,15 +158,16 @@ struct Declaration : Dsymbol
void semantic(Scope *sc);
const char *kind();
unsigned size(Loc loc);
int checkModify(Loc loc, Scope *sc, Type *t);
int checkModify(Loc loc, Scope *sc, Type *t, Expression *e1, int flag);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toJson(JsonOut *json);
void jsonProperties(JsonOut *json);
void toDocBuffer(OutBuffer *buf, Scope *sc);
char *mangle();
char *mangle(bool isv = false);
int isStatic() { return storage_class & STCstatic; }
virtual int isDelete();
virtual int isDataseg();
@@ -229,10 +236,11 @@ struct TypedefDeclaration : Declaration
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void semantic2(Scope *sc);
char *mangle();
char *mangle(bool isv = false);
const char *kind();
Type *getType();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJson(JsonOut *json);
Type *htype;
Type *hbasetype;
@@ -263,6 +271,7 @@ struct AliasDeclaration : Declaration
{
Dsymbol *aliassym;
Dsymbol *overnext; // next in overload list
Dsymbol *import; // !=NULL if unresolved internal alias for selective import
int inSemantic;
PROT importprot; // if generated by import, store its protection
@@ -327,6 +336,7 @@ struct VarDeclaration : Declaration
void semantic2(Scope *sc);
const char *kind();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJson(JsonOut *json);
Type *htype;
Initializer *hinit;
AggregateDeclaration *isThis();
@@ -405,7 +415,7 @@ struct ClassInfoDeclaration : VarDeclaration
void semantic(Scope *sc);
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toJson(JsonOut *json);
#if IN_DMD
Symbol *toSymbol();
@@ -423,7 +433,7 @@ struct ModuleInfoDeclaration : VarDeclaration
void semantic(Scope *sc);
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toJson(JsonOut *json);
#if IN_DMD
Symbol *toSymbol();
@@ -439,7 +449,7 @@ struct TypeInfoDeclaration : VarDeclaration
void semantic(Scope *sc);
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toJson(JsonOut *json);
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
@@ -812,6 +822,8 @@ struct FuncDeclaration : Declaration
VarDeclarations closureVars; // local variables in this function
// which are referenced by nested
// functions
FuncDeclarations siblingCallers; // Sibling nested functions which
// called this one
FuncDeclarations deferred; // toObjFile() these functions after this one
unsigned flags;
@@ -827,13 +839,15 @@ struct FuncDeclaration : Declaration
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
bool functionSemantic();
bool functionSemantic3();
// called from semantic3
void varArgs(Scope *sc, TypeFunction*, VarDeclaration *&, VarDeclaration *&);
VarDeclaration *declareThis(Scope *sc, AggregateDeclaration *ad);
int equals(Object *o);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJson(JsonOut *json);
int overrides(FuncDeclaration *fd);
int findVtblIndex(Dsymbols *vtbl, int dim);
int overloadInsert(Dsymbol *s);
@@ -846,7 +860,7 @@ struct FuncDeclaration : Declaration
int getLevel(Loc loc, Scope *sc, FuncDeclaration *fd); // lexical nesting level difference
void appendExp(Expression *e);
void appendState(Statement *s);
char *mangle();
char *mangle(bool isv = false);
const char *toPrettyChars();
int isMain();
int isWinMain();
@@ -956,7 +970,7 @@ struct FuncAliasDeclaration : FuncDeclaration
#if IN_DMD
Symbol *toSymbol();
#endif
char *mangle() { return toAliasFunc()->mangle(); }
char *mangle(bool isv = false) { return toAliasFunc()->mangle(isv); }
FuncDeclaration *toAliasFunc();
};
@@ -1009,12 +1023,12 @@ struct PostBlitDeclaration : FuncDeclaration
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJson(JsonOut *json);
int isVirtual();
int addPreInvariant();
int addPostInvariant();
int overloadInsert(Dsymbol *s);
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
PostBlitDeclaration *isPostBlitDeclaration() { return this; }
};
@@ -1034,7 +1048,6 @@ struct DtorDeclaration : FuncDeclaration
int addPostInvariant();
int overloadInsert(Dsymbol *s);
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
DtorDeclaration *isDtorDeclaration() { return this; }
};
@@ -1051,7 +1064,6 @@ struct StaticCtorDeclaration : FuncDeclaration
int addPostInvariant();
bool hasStaticCtorOrDtor();
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
StaticCtorDeclaration *isStaticCtorDeclaration() { return this; }
@@ -1081,7 +1093,6 @@ struct StaticDtorDeclaration : FuncDeclaration
int addPreInvariant();
int addPostInvariant();
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
StaticDtorDeclaration *isStaticDtorDeclaration() { return this; }
@@ -1107,7 +1118,6 @@ struct InvariantDeclaration : FuncDeclaration
int addPreInvariant();
int addPostInvariant();
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
InvariantDeclaration *isInvariantDeclaration() { return this; }
@@ -1123,7 +1133,6 @@ struct UnitTestDeclaration : FuncDeclaration
int addPreInvariant();
int addPostInvariant();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJsonBuffer(OutBuffer *buf);
UnitTestDeclaration *isUnitTestDeclaration() { return this; }
};
+1
View File
@@ -41,6 +41,7 @@ Expression *Expression::toDelegate(Scope *sc, Type *t)
Type *tw = t->semantic(loc, sc);
Type *tc = t->substWildTo(MODconst)->semantic(loc, sc);
TypeFunction *tf = new TypeFunction(NULL, tc, 0, LINKd);
if (tw != tc) tf->mod = MODwild; // hack for bug7757
(tf = (TypeFunction *)tf->semantic(loc, sc))->next = tw; // hack for bug7757
FuncLiteralDeclaration *fld =
new FuncLiteralDeclaration(loc, loc, tf, TOKdelegate, NULL);
+101 -64
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2012 by Digital Mars
// Copyright (c) 1999-2013 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -18,10 +18,7 @@
#include "rmem.h"
#include "root.h"
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
#include "gnuc.h"
#endif
#include "port.h"
#include "mars.h"
#include "dsymbol.h"
@@ -30,6 +27,7 @@
#include "lexer.h"
#include "aggregate.h"
#include "declaration.h"
#include "statement.h"
#include "enum.h"
#include "id.h"
#include "module.h"
@@ -43,7 +41,7 @@ struct Escape
{
const char *strings[256];
static const char *escapeChar(unsigned c);
const char *escapeChar(unsigned c);
};
struct Section
@@ -117,7 +115,7 @@ DDOC = <html><head>\n\
</head><body>\n\
<h1>$(TITLE)</h1>\n\
$(BODY)\n\
<hr>$(SMALL Page generated by $(LINK2 http://www.digitalmars.com/d/2.0/ddoc.html, Ddoc). $(COPYRIGHT))\n\
<hr>$(SMALL Page generated by $(LINK2 http://dlang.org/ddoc.html, Ddoc). $(COPYRIGHT))\n\
</body></html>\n\
\n\
B = <b>$0</b>\n\
@@ -290,7 +288,7 @@ void Module::gendocfile()
dc->macros->write(dc, sc, this, sc->docbuf);
}
sc->docbuf->write(comment, commentlen);
highlightText(NULL, this, sc->docbuf, 0);
highlightText(sc, this, sc->docbuf, 0);
}
else
{
@@ -341,10 +339,7 @@ void Module::gendocfile()
assert(docfile);
docfile->setbuffer(buf.data, buf.offset);
docfile->ref = 1;
char *pt = FileName::path(docfile->toChars());
if (*pt)
FileName::ensurePathExists(pt);
mem.free(pt);
FileName::ensurePathToNameExists(docfile->toChars());
docfile->writev();
#else
/* Remove all the escape sequences from buf2
@@ -367,10 +362,7 @@ void Module::gendocfile()
// Transfer image to file
docfile->setbuffer(buf2.data, buf2.offset);
docfile->ref = 1;
char *pt = FileName::path(docfile->toChars());
if (*pt)
FileName::ensurePathExists(pt);
mem.free(pt);
FileName::ensurePathToNameExists(docfile->toChars());
docfile->writev();
#endif
}
@@ -515,6 +507,34 @@ void Dsymbol::emitDitto(Scope *sc)
sc->lastoffset += b.offset;
}
void emitUnittestComment(Scope *sc, Dsymbol *s, UnitTestDeclaration *test)
{
static char pre[] = "$(D_CODE \n";
OutBuffer *buf = sc->docbuf;
buf->writestring("$(DDOC_SECTION ");
buf->writestring("$(B Example:)");
for (UnitTestDeclaration *utd = test; utd; utd = utd->unittest)
{
if (utd->protection == PROTprivate || !utd->comment || !utd->fbody)
continue;
OutBuffer codebuf;
const char *body = utd->fbody->toChars();
if (strlen(body))
{
codebuf.writestring(pre);
codebuf.writestring(body);
codebuf.writestring(")");
codebuf.writeByte(0);
highlightCode2(sc, s, &codebuf, 0);
buf->writestring(codebuf.toChars());
}
}
buf->writestring(")");
}
void ScopeDsymbol::emitMemberComments(Scope *sc)
{
//printf("ScopeDsymbol::emitMemberComments() %s\n", toChars());
@@ -989,7 +1009,7 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
declarationToDocBuffer(this, buf, td);
highlightCode(NULL, this, buf, o);
highlightCode(sc, this, buf, o);
}
else
{
@@ -1037,7 +1057,7 @@ void StructDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
td->onemember == this)
{ size_t o = buf->offset;
td->toDocBuffer(buf, sc);
highlightCode(NULL, this, buf, o);
highlightCode(sc, this, buf, o);
}
else
{
@@ -1063,7 +1083,7 @@ void ClassDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
td->onemember == this)
{ size_t o = buf->offset;
td->toDocBuffer(buf, sc);
highlightCode(NULL, this, buf, o);
highlightCode(sc, this, buf, o);
}
else
{
@@ -1299,6 +1319,8 @@ void DocComment::writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf)
buf->writestring(")\n");
}
}
if (s->unittest)
emitUnittestComment(sc, s, s->unittest);
buf->writestring(")\n");
}
else
@@ -1618,8 +1640,10 @@ void DocComment::parseEscapes(Escape **pescapetable, unsigned char *textstart, s
if (!escapetable)
{ escapetable = new Escape;
memset(escapetable, 0, sizeof(Escape));
*pescapetable = escapetable;
}
//printf("parseEscapes('%.*s') pescapetable = %p\n", textlen, textstart, pescapetable);
unsigned char *p = textstart;
unsigned char *pend = p + textlen;
@@ -1650,7 +1674,7 @@ void DocComment::parseEscapes(Escape **pescapetable, unsigned char *textstart, s
char *s = (char *)memcpy(mem.malloc(len + 1), start, len);
s[len] = 0;
escapetable->strings[c] = s;
//printf("%c = '%s'\n", c, s);
//printf("\t%c = '%s'\n", c, s);
p++;
}
}
@@ -1676,7 +1700,7 @@ int icmp(const char *stringz, void *s, size_t slen)
if (len1 != slen)
return len1 - slen;
return memicmp(stringz, (char *)s, slen);
return Port::memicmp(stringz, (char *)s, slen);
}
/*****************************************
@@ -1689,7 +1713,7 @@ int isDitto(unsigned char *comment)
{
unsigned char *p = skipwhitespace(comment);
if (memicmp((char *)p, "ditto", 5) == 0 && *skipwhitespace(p + 5) == 0)
if (Port::memicmp((char *)p, "ditto", 5) == 0 && *skipwhitespace(p + 5) == 0)
return 1;
}
return 0;
@@ -1787,11 +1811,11 @@ size_t skippastURL(OutBuffer *buf, size_t i)
size_t j;
unsigned sawdot = 0;
if (length > 7 && memicmp((char *)p, "http://", 7) == 0)
if (length > 7 && Port::memicmp((char *)p, "http://", 7) == 0)
{
j = 7;
}
else if (length > 8 && memicmp((char *)p, "https://", 8) == 0)
else if (length > 8 && Port::memicmp((char *)p, "https://", 8) == 0)
{
j = 8;
}
@@ -1901,7 +1925,8 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
break;
case '\n':
if (sc && !inCode && i == iLineStart && i + 1 < buf->offset) // if "\n\n"
if (!sc->module->isDocFile &&
!inCode && i == iLineStart && i + 1 < buf->offset) // if "\n\n"
{
static char blankline[] = "$(DDOC_BLANKLINE)\n";
@@ -1916,48 +1941,53 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
if (inCode)
break;
p = &buf->data[i];
se = sc->module->escapetable->escapeChar('<');
// Skip over comments
if (p[1] == '!' && p[2] == '-' && p[3] == '-')
{ size_t j = i + 4;
p += 4;
while (1)
if (se && strcmp(se, "&lt;") == 0)
{
// Generating HTML
// Skip over comments
if (p[1] == '!' && p[2] == '-' && p[3] == '-')
{
if (j == buf->offset)
goto L1;
if (p[0] == '-' && p[1] == '-' && p[2] == '>')
size_t j = i + 4;
p += 4;
while (1)
{
i = j + 2; // place on closing '>'
break;
if (j == buf->offset)
goto L1;
if (p[0] == '-' && p[1] == '-' && p[2] == '>')
{
i = j + 2; // place on closing '>'
break;
}
j++;
p++;
}
j++;
p++;
break;
}
break;
}
// Skip over HTML tag
if (isalpha(p[1]) || (p[1] == '/' && isalpha(p[2])))
{ size_t j = i + 2;
p += 2;
while (1)
// Skip over HTML tag
if (isalpha(p[1]) || (p[1] == '/' && isalpha(p[2])))
{
if (j == buf->offset)
goto L1;
if (p[0] == '>')
size_t j = i + 2;
p += 2;
while (1)
{
i = j; // place on closing '>'
break;
if (j == buf->offset)
break;
if (p[0] == '>')
{
i = j; // place on closing '>'
break;
}
j++;
p++;
}
j++;
p++;
break;
}
break;
}
L1:
// Replace '<' with '&lt;' character entity
se = Escape::escapeChar('<');
if (se)
{ size_t len = strlen(se);
buf->remove(i, 1);
@@ -1971,7 +2001,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
if (inCode)
break;
// Replace '>' with '&gt;' character entity
se = Escape::escapeChar('>');
se = sc->module->escapetable->escapeChar('>');
if (se)
{ size_t len = strlen(se);
buf->remove(i, 1);
@@ -1988,7 +2018,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
if (p[1] == '#' || isalpha(p[1]))
break; // already a character entity
// Replace '&' with '&amp;' character entity
se = Escape::escapeChar('&');
se = sc->module->escapetable->escapeChar('&');
if (se)
{ size_t len = strlen(se);
buf->remove(i, 1);
@@ -2073,7 +2103,8 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
default:
leadingBlank = 0;
if (sc && !inCode && isIdStart(&buf->data[i]))
if (!sc->module->isDocFile &&
!inCode && isIdStart(&buf->data[i]))
{
size_t j = skippastident(buf, i);
if (j > i)
@@ -2144,7 +2175,7 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool an
{ unsigned char c = buf->data[i];
const char *se;
se = Escape::escapeChar(c);
se = sc->module->escapetable->escapeChar(c);
if (se)
{
size_t len = strlen(se);
@@ -2180,10 +2211,10 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool an
/****************************************
*/
void highlightCode3(OutBuffer *buf, unsigned char *p, unsigned char *pend)
void highlightCode3(Scope *sc, OutBuffer *buf, unsigned char *p, unsigned char *pend)
{
for (; p < pend; p++)
{ const char *s = Escape::escapeChar(*p);
{ const char *s = sc->module->escapetable->escapeChar(*p);
if (s)
buf->writestring(s);
else
@@ -2212,7 +2243,7 @@ void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
while (1)
{
lex.scan(&tok);
highlightCode3(&res, lastp, tok.ptr);
highlightCode3(sc, &res, lastp, tok.ptr);
highlight = NULL;
switch (tok.value)
{
@@ -2250,7 +2281,7 @@ void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
}
if (highlight)
res.writestring(highlight);
highlightCode3(&res, tok.ptr, lex.p);
highlightCode3(sc, &res, tok.ptr, lex.p);
if (highlight)
res.writeByte(')');
if (tok.value == TOKeof)
@@ -2267,8 +2298,13 @@ void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
*/
const char *Escape::escapeChar(unsigned c)
{ const char *s;
{
#if 1
assert(c < 256);
//printf("escapeChar('%c') => %p, %p\n", c, strings, strings[c]);
return strings[c];
#else
const char *s;
switch (c)
{
case '<':
@@ -2285,6 +2321,7 @@ const char *Escape::escapeChar(unsigned c)
break;
}
return s;
#endif
}
/****************************************
+30 -16
View File
@@ -54,7 +54,7 @@ Dsymbol::Dsymbol()
this->scope = NULL;
this->errors = false;
this->userAttributes = NULL;
this->unittest = NULL;
#if IN_LLVM
this->llvmInternal = LLVMnone;
#endif
@@ -76,7 +76,7 @@ Dsymbol::Dsymbol(Identifier *ident)
this->errors = false;
this->depmsg = NULL;
this->userAttributes = NULL;
this->unittest = NULL;
#if IN_LLVM
this->llvmInternal = LLVMnone;
#endif
@@ -220,16 +220,6 @@ const char *Dsymbol::toPrettyChars()
if (q == s)
break;
q--;
#if TARGET_NET
if (AggregateDeclaration* ad = p->isAggregateDeclaration())
{
if (ad->isNested() && p->parent && p->parent->isAggregateDeclaration())
{
*q = '/';
continue;
}
}
#endif
*q = '.';
}
return s;
@@ -285,6 +275,7 @@ Dsymbol *Dsymbol::pastMixin()
/**********************************
* Use this instead of toParent() when looking for the
* 'this' pointer of the enclosing function/class.
* This skips over both TemplateInstance's and TemplateMixin's.
*/
Dsymbol *Dsymbol::toParent2()
@@ -1353,6 +1344,9 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
*/
return NULL;
while (ce->op == TOKcomma)
ce = ((CommaExp *)ce)->e2;
/* If we are indexing into an array that is really a type
* tuple, rewrite this as an index into a type tuple and
* try again.
@@ -1403,6 +1397,29 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
return NULL;
s = s->toAlias();
if (ce->hasSideEffect())
{
/* Even if opDollar is needed, 'ce' should be evaluate only once. So
* Rewrite:
* ce.opIndex( ... use of $ ... )
* ce.opSlice( ... use of $ ... )
* as:
* (ref __dop = ce, __dop).opIndex( ... __dop.opDollar ...)
* (ref __dop = ce, __dop).opSlice( ... __dop.opDollar ...)
*/
Identifier *id = Lexer::uniqueId("__dop");
ExpInitializer *ei = new ExpInitializer(loc, ce);
VarDeclaration *v = new VarDeclaration(loc, NULL, id, ei);
v->storage_class |= STCctfe | STCforeach | STCref;
DeclarationExp *de = new DeclarationExp(loc, v);
VarExp *ve = new VarExp(loc, v);
v->semantic(sc);
de->type = ce->type;
ve->type = ce->type;
((UnaExp *)exp)->e1 = new CommaExp(loc, de, ve);
ce = ve;
}
Expression *e = NULL;
// Check for multi-dimensional opDollar(dim) template.
if (TemplateDeclaration *td = s->isTemplateDeclaration())
@@ -1411,14 +1428,11 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
if (exp->op == TOKarray)
{
dim = ((ArrayExp *)exp)->currentDimension;
e = ((ArrayExp *)exp)->e1;
}
else if (exp->op == TOKslice)
{
dim = 0; // slices are currently always one-dimensional
e = ((SliceExp *)exp)->e1;
}
assert(e);
Objects *tdargs = new Objects();
Expression *edim = new IntegerExp(0, dim, Type::tsize_t);
@@ -1428,7 +1442,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
//TemplateInstance *ti = new TemplateInstance(loc, td, tdargs);
//ti->semantic(sc);
e = new DotTemplateInstanceExp(loc, e, td->ident, tdargs);
e = new DotTemplateInstanceExp(loc, ce, td->ident, tdargs);
}
else
{ /* opDollar exists, but it's not a template.
+7 -10
View File
@@ -82,14 +82,11 @@ struct DeleteDeclaration;
struct HdrGenState;
struct OverloadSet;
struct AA;
#if TARGET_NET
struct PragmaScope;
#endif
struct JsonOut;
#if IN_LLVM
struct TypeInfoDeclaration;
struct ClassInfoDeclaration;
#endif
#ifdef IN_GCC
union tree_node;
typedef union tree_node TYPE;
@@ -153,6 +150,7 @@ struct Dsymbol : Object
bool errors; // this symbol failed to pass semantic()
char *depmsg; // customized deprecation message
Expressions *userAttributes; // user defined attributes from UserAttributeDeclaration
UnitTestDeclaration *unittest; // !=NULL means there's a unittest associated with this symbol
Dsymbol();
Dsymbol(Identifier *);
@@ -198,7 +196,8 @@ struct Dsymbol : Object
virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toDocBuffer(OutBuffer *buf, Scope *sc);
virtual void toJsonBuffer(OutBuffer *buf);
virtual void toJson(JsonOut *json);
virtual void jsonProperties(JsonOut *json);
virtual unsigned size(Loc loc);
virtual int isforwardRef();
virtual void defineRef(Dsymbol *s);
@@ -216,7 +215,7 @@ struct Dsymbol : Object
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
virtual Type *getType(); // is this a type?
virtual char *mangle();
virtual char *mangle(bool isv = false);
virtual int needThis(); // need a 'this' pointer?
virtual enum PROT prot();
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
@@ -285,12 +284,10 @@ struct Dsymbol : Object
virtual StaticStructInitDeclaration *isStaticStructInitDeclaration() { return NULL; }
virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
virtual OverloadSet *isOverloadSet() { return NULL; }
#if IN_LLVM
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
#if TARGET_NET
virtual PragmaScope* isPragmaScope() { return NULL; }
#endif
#if IN_LLVM
/// Codegen traversal
virtual void codegen(Ir* ir);
+10
View File
@@ -35,6 +35,9 @@ EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
#endif
isdeprecated = 0;
isdone = 0;
#if IN_DMD
objFileDone = 0;
#endif
}
Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
@@ -54,6 +57,13 @@ Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
return ed;
}
void EnumDeclaration::setScope(Scope *sc)
{
if (isdone)
return;
ScopeDsymbol::setScope(sc);
}
void EnumDeclaration::semantic0(Scope *sc)
{
/* This function is a hack to get around a significant problem.
+4 -2
View File
@@ -49,6 +49,7 @@ struct EnumDeclaration : ScopeDsymbol
EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
Dsymbol *syntaxCopy(Dsymbol *s);
void setScope(Scope *sc);
void semantic0(Scope *sc);
void semantic(Scope *sc);
int oneMember(Dsymbol **ps, Identifier *ident = NULL);
@@ -61,12 +62,13 @@ struct EnumDeclaration : ScopeDsymbol
int isDeprecated(); // is Dsymbol deprecated?
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toJson(JsonOut *json);
void toDocBuffer(OutBuffer *buf, Scope *sc);
EnumDeclaration *isEnumDeclaration() { return this; }
#if IN_DMD
bool objFileDone; // if toObjFile was already called
void toObjFile(int multiobj); // compile to .obj file
void toDebug();
int cvMember(unsigned char *p);
@@ -92,7 +94,7 @@ struct EnumMember : Dsymbol
const char *kind();
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toJson(JsonOut *json);
void toDocBuffer(OutBuffer *buf, Scope *sc);
EnumMember *isEnumMember() { return this; }
+257 -519
View File
File diff suppressed because it is too large Load Diff
+8 -9
View File
@@ -173,8 +173,7 @@ struct Expression : Object
void checkPurity(Scope *sc, FuncDeclaration *f);
void checkPurity(Scope *sc, VarDeclaration *v, Expression *e1);
void checkSafety(Scope *sc, FuncDeclaration *f);
void checkModifiable(Scope *sc);
virtual int checkCtorInit(Scope *sc);
virtual int checkModifiable(Scope *sc, int flag = 0);
virtual Expression *checkToBoolean(Scope *sc);
virtual Expression *addDtorHook(Scope *sc);
Expression *checkToPointer();
@@ -778,7 +777,7 @@ struct VarExp : SymbolExp
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void checkEscape();
void checkEscapeRef();
int checkCtorInit(Scope *sc);
int checkModifiable(Scope *sc, int flag);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
@@ -1069,7 +1068,7 @@ struct DotVarExp : UnaExp
DotVarExp(Loc loc, Expression *e, Declaration *var, int hasOverloads = 0);
Expression *semantic(Scope *sc);
int checkCtorInit(Scope *sc);
int checkModifiable(Scope *sc, int flag);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
@@ -1202,7 +1201,7 @@ struct PtrExp : UnaExp
PtrExp(Loc loc, Expression *e, Type *t);
Expression *semantic(Scope *sc);
void checkEscapeRef();
int checkCtorInit(Scope *sc);
int checkModifiable(Scope *sc, int flag);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
@@ -1385,7 +1384,7 @@ struct SliceExp : UnaExp
Expression *semantic(Scope *sc);
void checkEscape();
void checkEscapeRef();
int checkCtorInit(Scope *sc);
int checkModifiable(Scope *sc, int flag);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
@@ -1466,7 +1465,7 @@ struct CommaExp : BinExp
Expression *semantic(Scope *sc);
void checkEscape();
void checkEscapeRef();
int checkCtorInit(Scope *sc);
int checkModifiable(Scope *sc, int flag);
IntRange getIntRange();
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
@@ -1495,7 +1494,7 @@ struct IndexExp : BinExp
IndexExp(Loc loc, Expression *e1, Expression *e2);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
int checkCtorInit(Scope *sc);
int checkModifiable(Scope *sc, int flag);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
@@ -2070,7 +2069,7 @@ struct CondExp : BinExp
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void checkEscape();
void checkEscapeRef();
int checkCtorInit(Scope *sc);
int checkModifiable(Scope *sc, int flag);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
+325 -149
View File
@@ -25,10 +25,6 @@
#include "template.h"
#include "hdrgen.h"
#ifdef IN_GCC
#include "d-dmd-gcc.h"
#endif
/********************************* FuncDeclaration ****************************/
FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageClass storage_class, Type *type)
@@ -429,7 +425,7 @@ void FuncDeclaration::semantic(Scope *sc)
isNewDeclaration() || isDelete())
error("constructors, destructors, postblits, invariants, new and delete functions are not allowed in interface %s", id->toChars());
if (fbody && isVirtual())
error("function body is not abstract in interface %s", id->toChars());
error("function body only allowed in final functions in interface %s", id->toChars());
}
/* Contracts can only appear without a body when they are virtual interface functions
@@ -546,8 +542,23 @@ void FuncDeclaration::semantic(Scope *sc)
return;
default:
{ FuncDeclaration *fdv = (FuncDeclaration *)cd->baseClass->vtbl[vi];
{ FuncDeclaration *fdv = cd->baseClass->vtbl[vi]->isFuncDeclaration();
FuncDeclaration *fdc = cd->vtbl[vi]->isFuncDeclaration();
// This function is covariant with fdv
if (fdc->toParent() == parent)
{
//printf("vi = %d,\tthis = %p %s %s @ [%s]\n\tfdc = %p %s %s @ [%s]\n\tfdv = %p %s %s @ [%s]\n",
// vi, this, this->toChars(), this->type->toChars(), this->loc.toChars(),
// fdc, fdc ->toChars(), fdc ->type->toChars(), fdc ->loc.toChars(),
// fdv, fdv ->toChars(), fdv ->type->toChars(), fdv ->loc.toChars());
// fdc overrides fdv exactly, then this introduces new function.
if (fdc->type->mod == fdv->type->mod && this->type->mod != fdv->type->mod)
goto Lintro;
}
// This function overrides fdv
if (fdv->isFinal())
error("cannot override final function %s", fdv->toPrettyChars());
@@ -557,28 +568,20 @@ void FuncDeclaration::semantic(Scope *sc)
::deprecation(loc, "overriding base class function without using override attribute is deprecated (%s overrides %s)", toPrettyChars(), fdv->toPrettyChars());
#endif
FuncDeclaration *fdc = ((Dsymbol *)cd->vtbl.data[vi])->isFuncDeclaration();
if (fdc->toParent() == parent)
{
// fdc overrides fdv exactly, then this introduces new function.
if (fdc->type->mod == fdv->type->mod && this->type->mod != fdv->type->mod)
goto Lintro;
// If both are mixins, then error.
// If both are mixins, or both are not, then error.
// If either is not, the one that is not overrides the other.
if (this->parent->isClassDeclaration() && fdc->parent->isClassDeclaration())
bool thismixin = this->parent->isClassDeclaration() != NULL;
bool fdcmixin = fdc->parent->isClassDeclaration() != NULL;
if (thismixin == fdcmixin)
{
error("multiple overrides of same function");
// if (this is mixin) && (fdc is not mixin) then fdc overrides
else if (!this->parent->isClassDeclaration() && fdc->parent->isClassDeclaration())
}
else if (!thismixin) // fdc overrides fdv
{ // this doesn't override any function
break;
else if (!this->parent->isClassDeclaration() // if both are mixins then error
#if DMDV2
&& !isPostBlitDeclaration()
#endif
)
error("multiple overrides of same function");
}
}
cd->vtbl[vi] = this;
vtblIndex = vi;
@@ -691,9 +694,15 @@ void FuncDeclaration::semantic(Scope *sc)
if (!doesoverride && isOverride())
{
Dsymbol *s = cd->search_correct(ident);
Dsymbol *s = NULL;
for (size_t i = 0; i < cd->baseclasses->dim; i++)
{
s = (*cd->baseclasses)[i]->base->search_correct(ident);
if (s) break;
}
if (s)
error("does not override any function, did you mean '%s'", s->toPrettyChars());
error("does not override any function, did you mean to override '%s'?", s->toPrettyChars());
else
error("does not override any function");
}
@@ -1030,9 +1039,6 @@ void FuncDeclaration::semantic3(Scope *sc)
// Declare hidden variable _arguments[] and _argptr
if (f->varargs == 1)
{
#if TARGET_NET
varArgs(sc2, f, argptr, _arguments);
#else
Type *t;
#if !IN_GCC && !IN_LLVM
@@ -1072,17 +1078,12 @@ void FuncDeclaration::semantic3(Scope *sc)
}
if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters)))
{ // Declare _argptr
#ifdef IN_GCC
t = d_gcc_builtin_va_list_d_type;
#else
t = Type::tvoid->pointerTo();
#endif
t = Type::tvalist;
argptr = new VarDeclaration(0, t, Id::_argptr, NULL);
argptr->semantic(sc2);
sc2->insert(argptr);
argptr->parent = this;
}
#endif
}
#if IN_LLVM
@@ -1244,10 +1245,8 @@ void FuncDeclaration::semantic3(Scope *sc)
Expression *v = new ThisExp(0);
#endif
v->type = vthis->type;
#if STRUCTTHISREF
if (ad->isStructDeclaration())
v = v->addressOf(sc);
#endif
Expression *se = new StringExp(0, (char *)"null this");
se = se->semantic(sc);
se->type = Type::tchar->arrayOf();
@@ -1293,10 +1292,8 @@ void FuncDeclaration::semantic3(Scope *sc)
Expression *v = new ThisExp(0);
#endif
v->type = vthis->type;
#if STRUCTTHISREF
if (ad->isStructDeclaration())
v = v->addressOf(sc);
#endif
e = new AssertExp(0, v);
}
if (e)
@@ -1345,7 +1342,7 @@ void FuncDeclaration::semantic3(Scope *sc)
{ // If no return type inferred yet, then infer a void
if (!type->nextOf())
{
((TypeFunction *)type)->next = Type::tvoid;
f->next = Type::tvoid;
//type = type->semantic(loc, sc); // Removed with 6902
}
else if (returns && f->next->ty != Tvoid)
@@ -1414,11 +1411,7 @@ void FuncDeclaration::semantic3(Scope *sc)
* as delegating calls to other constructors
*/
if (v->isCtorinit() && !v->type->isMutable() && cd)
{
OutBuffer buf;
MODtoBuffer(&buf, v->type->mod);
error("missing initializer for %s field %s", buf.toChars(), v->toChars());
}
error("missing initializer for %s field %s", MODtoChars(v->type->mod), v->toChars());
else if (v->storage_class & STCnodefaultctor)
error("field %s must be initialized in constructor", v->toChars());
else if (v->type->needsNested())
@@ -1449,6 +1442,20 @@ void FuncDeclaration::semantic3(Scope *sc)
fbody = new CompoundStatement(0, s, fbody);
}
}
/* Append:
* return this;
* to function body
*/
if (blockexit & BEfallthru)
{
Expression *e = new ThisExp(loc);
if (cd)
e->type = cd->type;
Statement *s = new ReturnStatement(loc, e);
s = s->semantic(sc2);
fbody = new CompoundStatement(loc, fbody, s);
}
}
else if (fes)
{ // For foreach(){} body, append a return 0;
@@ -1472,7 +1479,10 @@ void FuncDeclaration::semantic3(Scope *sc)
if (f->isnothrow && (global.errors != nothrowErrors) )
error("'%s' is nothrow yet may throw", toChars());
if (flags & FUNCFLAGnothrowInprocess)
{
if (type == f) f = f->copy();
f->isnothrow = !(blockexit & BEthrow);
}
int offend = blockexit & BEfallthru;
#endif
@@ -1748,15 +1758,6 @@ void FuncDeclaration::semantic3(Scope *sc)
if (v->storage_class & (STCref | STCout | STClazy))
continue;
#if !SARRAYVALUE
/* Don't do this for static arrays, since static
* arrays are called by reference. Remove this
* when we change them to call by value.
*/
if (v->type->toBasetype()->ty == Tsarray)
continue;
#endif
if (v->noscope)
continue;
@@ -1782,7 +1783,6 @@ void FuncDeclaration::semantic3(Scope *sc)
flags &= ~FUNCFLAGnothrowInprocess;
#endif
#if 1
if (isSynchronized())
{ /* Wrap the entire function body in a synchronized statement
*/
@@ -1791,8 +1791,12 @@ void FuncDeclaration::semantic3(Scope *sc)
if (cd)
{
#if TARGET_WINDOS
if (!global.params.is64bit &&
#if IN_LLVM
global.params.targetTriple.isOSWindows() &&
#else
global.params.isWindows &&
#endif
!isStatic() && !fbody->usesEH())
{
/* The back end uses the "jmonitor" hack for syncing;
@@ -1800,7 +1804,6 @@ void FuncDeclaration::semantic3(Scope *sc)
*/
}
else
#endif
{
Expression *vsync;
if (isStatic())
@@ -1821,7 +1824,6 @@ void FuncDeclaration::semantic3(Scope *sc)
error("synchronized function %s must be a member of a class", toChars());
}
}
#endif
}
sc2->callSuper = 0;
@@ -1833,19 +1835,28 @@ void FuncDeclaration::semantic3(Scope *sc)
if (flags & FUNCFLAGpurityInprocess)
{
flags &= ~FUNCFLAGpurityInprocess;
if (type == f) f = f->copy();
f->purity = PUREfwdref;
}
if (flags & FUNCFLAGsafetyInprocess)
{
flags &= ~FUNCFLAGsafetyInprocess;
if (type == f) f = f->copy();
f->trust = TRUSTsafe;
}
// reset deco to apply inference result to mangled name
if (f != type)
f->deco = NULL;
// Do semantic type AFTER pure/nothrow inference.
if (inferRetType)
if (!f->deco)
{
type = type->semantic(loc, sc);
sc = sc->push();
sc->linkage = linkage; // Bugzilla 8496
type = f->semantic(loc, sc);
sc = sc->pop();
}
if (global.gag && global.errors != nerrors)
@@ -1868,13 +1879,82 @@ void FuncDeclaration::semantic3(Scope *sc)
//fflush(stdout);
}
bool FuncDeclaration::functionSemantic()
{
if (scope && !originalType) // semantic not yet run
{
TemplateInstance *spec = isSpeculative();
unsigned olderrs = global.errors;
unsigned oldgag = global.gag;
if (global.gag && !spec)
global.gag = 0;
semantic(scope);
global.gag = oldgag;
if (spec && global.errors != olderrs)
spec->errors = global.errors - olderrs;
if (olderrs != global.errors) // if errors compiling this function
return false;
}
// if inferring return type, sematic3 needs to be run
if (scope && (inferRetType && type && !type->nextOf() ||
getFuncTemplateDecl(this)))
{
return functionSemantic3();
}
return true;
}
bool FuncDeclaration::functionSemantic3()
{
if (semanticRun < PASSsemantic3 && scope)
{
/* Forward reference - we need to run semantic3 on this function.
* If errors are gagged, and it's not part of a speculative
* template instance, we need to temporarily ungag errors.
*/
TemplateInstance *spec = isSpeculative();
unsigned olderrs = global.errors;
unsigned oldgag = global.gag;
if (global.gag && !spec)
global.gag = 0;
semantic3(scope);
global.gag = oldgag;
// If it is a speculatively-instantiated template, and errors occur,
// we need to mark the template as having errors.
if (spec && global.errors != olderrs)
spec->errors = global.errors - olderrs;
if (olderrs != global.errors) // if errors compiling this function
return false;
}
return true;
}
void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
//printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
StorageClassDeclaration::stcToCBuffer(buf, storage_class);
type->toCBuffer(buf, ident, hgs);
bodyToCBuffer(buf, hgs);
if(hgs->hdrgen == 1)
{
if(storage_class & STCauto)
{
hgs->autoMember++;
bodyToCBuffer(buf, hgs);
hgs->autoMember--;
}
else if(hgs->tpltMember == 0 && global.params.useInline == 0)
buf->writestring(";");
else
bodyToCBuffer(buf, hgs);
}
else
bodyToCBuffer(buf, hgs);
buf->writenl();
}
VarDeclaration *FuncDeclaration::declareThis(Scope *sc, AggregateDeclaration *ad)
@@ -1885,43 +1965,15 @@ VarDeclaration *FuncDeclaration::declareThis(Scope *sc, AggregateDeclaration *ad
{
assert(ad->handle);
Type *thandle = ad->handle;
#if STRUCTTHISREF
thandle = thandle->addMod(type->mod);
thandle = thandle->addStorageClass(storage_class);
//if (isPure())
//thandle = thandle->addMod(MODconst);
#else
if (storage_class & STCconst || type->isConst())
{
assert(0); // BUG: shared not handled
if (thandle->ty == Tclass)
thandle = thandle->constOf();
else
{ assert(thandle->ty == Tpointer);
thandle = thandle->nextOf()->constOf()->pointerTo();
}
}
else if (storage_class & STCimmutable || type->isImmutable())
{
if (thandle->ty == Tclass)
thandle = thandle->invariantOf();
else
{ assert(thandle->ty == Tpointer);
thandle = thandle->nextOf()->invariantOf()->pointerTo();
}
}
else if (storage_class & STCshared || type->isShared())
{
assert(0); // not implemented
}
#endif
v = new ThisDeclaration(loc, thandle);
//v = new ThisDeclaration(loc, isCtorDeclaration() ? ad->handle : thandle);
v->storage_class |= STCparameter;
#if STRUCTTHISREF
if (thandle->ty == Tstruct)
v->storage_class |= STCref;
#endif
v->semantic(sc);
if (!sc->insert(v))
assert(0);
@@ -1969,21 +2021,27 @@ int FuncDeclaration::equals(Object *o)
void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (fbody &&
(!hgs->hdrgen || hgs->tpltMember || canInline(1,1,1))
)
{ buf->writenl();
if (fbody && (!hgs->hdrgen || global.params.useInline || hgs->autoMember || hgs->tpltMember))
{
int savetlpt = hgs->tpltMember;
int saveauto = hgs->autoMember;
hgs->tpltMember = 0;
hgs->autoMember = 0;
buf->writenl();
// in{}
if (frequire)
{ buf->writestring("in");
{
buf->writestring("in");
buf->writenl();
frequire->toCBuffer(buf, hgs);
}
// out{}
if (fensure)
{ buf->writestring("out");
{
buf->writestring("out");
if (outId)
{ buf->writebyte('(');
buf->writestring(outId->toChars());
@@ -1994,7 +2052,8 @@ void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
}
if (frequire || fensure)
{ buf->writestring("body");
{
buf->writestring("body");
buf->writenl();
}
@@ -2005,6 +2064,9 @@ void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->level--;
buf->writebyte('}');
buf->writenl();
hgs->tpltMember = savetlpt;
hgs->autoMember = saveauto;
}
else
{ buf->writeByte(';');
@@ -2654,6 +2716,28 @@ void overloadResolveX(Match *m, FuncDeclaration *fstart,
overloadApply(fstart, &fp2, &p);
}
static void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char rhsMod)
{
bool bothMutable = ((lhsMod & rhsMod) == 0);
bool sharedMismatch = ((lhsMod ^ rhsMod) & MODshared);
bool sharedMismatchOnly = ((lhsMod ^ rhsMod) == MODshared);
if (lhsMod & MODshared)
buf->writestring("shared ");
else if (sharedMismatch && !(lhsMod & MODimmutable))
buf->writestring("non-shared ");
if (bothMutable && sharedMismatchOnly)
{ }
else if (lhsMod & MODimmutable)
buf->writestring("immutable ");
else if (lhsMod & MODconst)
buf->writestring("const ");
else if (lhsMod & MODwild)
buf->writestring("inout ");
else
buf->writestring("mutable ");
}
FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags, Module* from)
{
@@ -2704,15 +2788,23 @@ if (arguments)
return NULL; // no match
tf = (TypeFunction *)type;
if (ethis && !MODimplicitConv(ethis->type->mod, tf->mod)) // modifier mismatch
{
OutBuffer thisBuf, funcBuf;
MODMatchToBuffer(&thisBuf, ethis->type->mod, tf->mod);
MODMatchToBuffer(&funcBuf, tf->mod, ethis->type->mod);
::error(loc, "%smethod %s is not callable using a %sobject",
funcBuf.toChars(), this->toPrettyChars(), thisBuf.toChars());
}
else
{
//printf("tf = %s, args = %s\n", tf->deco, (*arguments)[0]->type->deco);
error(loc, "%s%s is not callable using argument types %s",
Parameter::argsTypesToChars(tf->parameters, tf->varargs),
tf->modToChars(),
buf.toChars());
}
OutBuffer buf2;
tf->modToBuffer(&buf2);
//printf("tf = %s, args = %s\n", tf->deco, (*arguments)[0]->type->deco);
error(loc, "%s%s is not callable using argument types %s",
Parameter::argsTypesToChars(tf->parameters, tf->varargs),
buf2.toChars(),
buf.toChars());
return m.anyf; // as long as it's not a FuncAliasDeclaration
}
else
@@ -3144,6 +3236,8 @@ enum PURE FuncDeclaration::isPure()
if (tf->purity == PUREfwdref)
tf->purityLevel();
enum PURE purity = tf->purity;
if (purity > PUREweak && isNested())
purity = PUREweak;
if (purity > PUREweak && needThis())
{ // The attribute of the 'this' reference affects purity strength
if (type->mod & (MODimmutable | MODwild))
@@ -3317,14 +3411,24 @@ const char *FuncDeclaration::kind()
return "function";
}
/*********************************************
* In the current function, we are calling 'this' function.
* 1. Check to see if the current function can call 'this' function, issue error if not.
* 2. If the current function is not the parent of 'this' function, then add
* the current function to the list of siblings of 'this' function.
* 3. If the current function is a literal, and it's accessing an uplevel scope,
* then mark it as a delegate.
*/
void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
{
//printf("FuncDeclaration::checkNestedReference() %s\n", toChars());
//printf("FuncDeclaration::checkNestedReference() %s\n", toPrettyChars());
if (parent && parent != sc->parent && this->isNested() &&
this->ident != Id::require && this->ident != Id::ensure)
{
// The function that this function is in
FuncDeclaration *fdv = toParent()->isFuncDeclaration();
FuncDeclaration *fdv2 = toParent2()->isFuncDeclaration();
// The current function
FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
@@ -3332,13 +3436,35 @@ void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
//printf("fdv = %s in [%s]\n", fdv->toChars(), fdv->loc.toChars());
//printf("fdthis = %s in [%s]\n", fdthis->toChars(), fdthis->loc.toChars());
if (fdv2 && fdthis && fdv2 != fdthis)
{
// Add this function to the list of those which called us
if (fdthis != this)
{
bool found = false;
for (int i = 0; i < siblingCallers.dim; ++i)
{ if (siblingCallers[i] == fdthis)
found = true;
}
if (!found)
{
//printf("\tadding sibling %s\n", fdthis->toPrettyChars());
siblingCallers.push(fdthis);
}
}
}
FuncDeclaration *fdv = toParent()->isFuncDeclaration();
fdv = toParent()->isFuncDeclaration();
if (fdv && fdthis && fdv != fdthis)
{
int lv = fdthis->getLevel(loc, sc, fdv);
if (lv == -1)
return; // OK
return; // downlevel call
if (lv == 0)
return; // OK
return; // same level call
// Uplevel call
// BUG: may need to walk up outer scopes like Declaration::checkNestedReference() does
@@ -3349,6 +3475,52 @@ void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
}
}
/* For all functions between outerFunc and f, mark them as needing
* a closure.
*/
void markAsNeedingClosure(Dsymbol *f, FuncDeclaration *outerFunc)
{
for (Dsymbol *sx = f; sx != outerFunc; sx = sx->parent)
{
FuncDeclaration *fy = sx->isFuncDeclaration();
if (fy && fy->closureVars.dim)
{
/* fy needs a closure if it has closureVars[],
* because the frame pointer in the closure will be accessed.
*/
fy->requiresClosure = true;
}
}
}
/* Given a nested function f inside a function outerFunc, check
* if any sibling callers of f have escaped. If so, mark
* all the enclosing functions as needing closures.
* Return true if any closures were detected.
* This is recursive: we need to check the callers of our siblings.
* Note that nested functions can only call lexically earlier nested
* functions, so loops are impossible.
*/
bool checkEscapingSiblings(FuncDeclaration *f, FuncDeclaration *outerFunc)
{
//printf("checkEscapingSiblings(f = %s, outerfunc = %s)\n", f->toChars(), outerFunc->toChars());
bool bAnyClosures = false;
for (int i = 0; i < f->siblingCallers.dim; ++i)
{
FuncDeclaration *g = f->siblingCallers[i];
if (g->isThis() || g->tookAddressOf)
{
markAsNeedingClosure(g, outerFunc);
bAnyClosures = true;
}
bAnyClosures |= checkEscapingSiblings(g, outerFunc);
}
//printf("\t%d\n", bAnyClosures);
return bAnyClosures;
}
/*******************************
* Look at all the variables in this function that are referenced
* by nested functions, and determine if a closure needs to be
@@ -3361,12 +3533,14 @@ int FuncDeclaration::needsClosure()
/* Need a closure for all the closureVars[] if any of the
* closureVars[] are accessed by a
* function that escapes the scope of this function.
* We take the conservative approach and decide that any function that:
* We take the conservative approach and decide that a function needs
* a closure if it:
* 1) is a virtual function
* 2) has its address taken
* 3) has a parent that escapes
* 4) calls another nested function that needs a closure
* -or-
* 4) this function returns a local struct/class
* 5) this function returns a local struct/class
*
* Note that since a non-virtual function can be called by
* a virtual one, if that non-virtual function accesses a closure
@@ -3390,7 +3564,11 @@ int FuncDeclaration::needsClosure()
//printf("\t\tf = %s, isVirtual=%d, isThis=%p, tookAddressOf=%d\n", f->toChars(), f->isVirtual(), f->isThis(), f->tookAddressOf);
// Look to see if f or any parents of f that are below this escape
/* Look to see if f escapes. We consider all parents of f within
* this, and also all siblings which call f; if any of them escape,
* so does f.
* Mark all affected functions as requiring closures.
*/
for (Dsymbol *s = f; s && s != this; s = s->parent)
{
FuncDeclaration *fx = s->isFuncDeclaration();
@@ -3400,26 +3578,22 @@ int FuncDeclaration::needsClosure()
/* Mark as needing closure any functions between this and f
*/
for (Dsymbol *sx = fx; sx != this; sx = sx->parent)
{
if (sx != f)
{ FuncDeclaration *fy = sx->isFuncDeclaration();
if (fy && fy->closureVars.dim)
{
/* fy needs a closure if it has closureVars[],
* because the frame pointer in the closure will be accessed.
*/
fy->requiresClosure = true;
}
}
}
markAsNeedingClosure( (fx == f) ? fx->parent : fx, this);
goto Lyes;
}
/* We also need to check if any sibling functions that
* called us, have escaped. This is recursive: we need
* to check the callers of our siblings.
*/
if (fx && checkEscapingSiblings(fx, this))
goto Lyes;
}
}
}
/* Look for case (4)
/* Look for case (5)
*/
if (closureVars.dim)
{
@@ -3610,10 +3784,31 @@ const char *FuncLiteralDeclaration::kind()
void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring(kind());
buf->writeByte(' ');
type->toCBuffer(buf, NULL, hgs);
bodyToCBuffer(buf, hgs);
if (tok != TOKreserved)
{
buf->writestring(kind());
buf->writeByte(' ');
}
TypeFunction *tf = (TypeFunction *)type;
// Don't print tf->mod, tf->trust, and tf->linkage
if (tf->next)
tf->next->toCBuffer2(buf, hgs, 0);
Parameter::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs);
ReturnStatement *ret = !fbody->isCompoundStatement() ?
fbody->isReturnStatement() : NULL;
if (ret && ret->exp)
{
buf->writestring(" => ");
ret->exp->toCBuffer(buf, hgs);
}
else
{
hgs->tpltMember++;
bodyToCBuffer(buf, hgs);
hgs->tpltMember--;
}
}
@@ -3676,22 +3871,8 @@ void CtorDeclaration::semantic(Scope *sc)
originalType = type->syntaxCopy();
type = type->semantic(loc, sc);
#if STRUCTTHISREF
if (ad && ad->isStructDeclaration())
((TypeFunction *)type)->isref = 1;
#endif
// Append:
// return this;
// to the function body
if (fbody && semanticRun < PASSsemantic)
{
ThisExp *e = new ThisExp(loc);
if (parent->isClassDeclaration())
e->type = tret;
Statement *s = new ReturnStatement(loc, e);
fbody = new CompoundStatement(loc, fbody, s);
}
FuncDeclaration::semantic(sc);
@@ -3979,9 +4160,6 @@ void StaticCtorDeclaration::semantic(Scope *sc)
if (m)
{ m->needmoduleinfo = 1;
//printf("module1 %s needs moduleinfo\n", m->toChars());
#ifdef IN_GCC
m->strictlyneedmoduleinfo = 1;
#endif
}
}
@@ -4013,7 +4191,8 @@ int StaticCtorDeclaration::addPostInvariant()
void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (hgs->hdrgen && !hgs->tpltMember)
{ buf->writestring("static this();");
{
buf->writestring("static this();");
buf->writenl();
return;
}
@@ -4116,9 +4295,6 @@ void StaticDtorDeclaration::semantic(Scope *sc)
if (m)
{ m->needmoduleinfo = 1;
//printf("module2 %s needs moduleinfo\n", m->toChars());
#ifdef IN_GCC
m->strictlyneedmoduleinfo = 1;
#endif
}
}
+1 -4
View File
@@ -66,10 +66,7 @@ void Module::genhdrfile()
hdrfile->setbuffer(hdrbufr.data, hdrbufr.offset);
hdrbufr.data = NULL;
char *pt = FileName::path(hdrfile->toChars());
if (*pt)
FileName::ensurePathExists(pt);
mem.free(pt);
FileName::ensurePathToNameExists(hdrfile->toChars());
hdrfile->writev();
}
+3 -3
View File
@@ -23,6 +23,8 @@ struct HdrGenState
int inBinExp;
int inArrExp;
int emitInst;
int autoMember;
struct
{
int init;
@@ -31,6 +33,4 @@ struct HdrGenState
Scope* scope; // Scope when generating ddoc
HdrGenState() { memset(this, 0, sizeof(HdrGenState)); }
};
};
-1
View File
@@ -4,7 +4,6 @@
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// http://www.dsource.org/projects/dmd/browser/trunk/src/idgen.c
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
+12 -10
View File
@@ -93,8 +93,6 @@ void Import::load(Scope *sc)
// See if existing module
DsymbolTable *dst = Package::resolve(packages, NULL, &pkg);
#if TARGET_NET //dot net needs modules and packages with same name
#else
if (pkg && pkg->isModule())
{
::error(loc, "can only import from a module, not from a member of module %s. Did you mean `import %s : %s`?",
@@ -102,13 +100,9 @@ void Import::load(Scope *sc)
mod = pkg->isModule(); // Error recovery - treat as import of that module
return;
}
#endif
Dsymbol *s = dst->lookup(id);
if (s)
{
#if TARGET_NET
mod = (Module *)s;
#else
if (s->isModule())
mod = (Module *)s;
else
@@ -124,7 +118,6 @@ void Import::load(Scope *sc)
id->toChars());
}
}
#endif
}
if (!mod)
@@ -187,6 +180,11 @@ void Import::semantic(Scope *sc)
{
//printf("Import::semantic('%s')\n", toChars());
if (scope)
{ sc = scope;
scope = NULL;
}
// Load if not already done so
if (!mod)
{ load(sc);
@@ -241,14 +239,17 @@ void Import::semantic(Scope *sc)
sc->protection = PROTpublic;
#endif
for (size_t i = 0; i < aliasdecls.dim; i++)
{ Dsymbol *s = aliasdecls[i];
{ AliasDeclaration *ad = aliasdecls[i];
//printf("\tImport alias semantic('%s')\n", s->toChars());
if (mod->search(loc, names[i], 0))
s->semantic(sc);
{
ad->semantic(sc);
ad->import = NULL; // forward reference resolved
}
else
{
s = mod->search_correct(names[i]);
Dsymbol *s = mod->search_correct(names[i]);
if (s)
mod->error(loc, "import '%s' not found, did you mean '%s %s'?", names[i]->toChars(), s->kind(), s->toChars());
else
@@ -381,6 +382,7 @@ int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
TypeIdentifier *tname = new TypeIdentifier(loc, name);
AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname);
ad->import = this;
result |= ad->addMember(sc, sd, memnum);
aliasdecls.push(ad);
+1
View File
@@ -59,6 +59,7 @@ struct Import : Dsymbol
Dsymbol *search(Loc loc, Identifier *ident, int flags);
int overloadInsert(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJson(JsonOut *json);
Import *isImport() { return this; }
};
-1
View File
@@ -123,7 +123,6 @@ struct ArrayInitializer : Initializer
#if IN_DMD
dt_t *toDt();
dt_t *toDtBit(); // for bit arrays
#endif
ArrayInitializer *isArrayInitializer() { return this; }
-14
View File
@@ -1647,7 +1647,6 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
ExpInitializer *ei;
VarExp *ve;
#if STRUCTTHISREF
if (ethis->type->ty == Tpointer)
{ Type *t = ethis->type->nextOf();
ethis = new PtrExp(ethis->loc, ethis);
@@ -1660,17 +1659,6 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
vthis->storage_class = STCref;
else
vthis->storage_class = STCin;
#else
if (ethis->type->ty != Tclass && ethis->type->ty != Tpointer)
{
ethis = ethis->addressOf(NULL);
}
ei = new ExpInitializer(ethis->loc, ethis);
vthis = new VarDeclaration(ethis->loc, ethis->type, Id::This, ei);
vthis->storage_class = STCin;
#endif
vthis->linkage = LINKd;
vthis->parent = iss->fd;
@@ -1679,13 +1667,11 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
ei->exp = new AssignExp(vthis->loc, ve, ethis);
ei->exp->type = ve->type;
#if STRUCTTHISREF
if (ethis->type->ty != Tclass)
{ /* This is a reference initialization, not a simple assignment.
*/
ei->exp->op = TOKconstruct;
}
#endif
ids.vthis = vthis;
}
+17 -42
View File
@@ -278,29 +278,8 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
error("circular dependency. Functions cannot be interpreted while being compiled");
return EXP_CANT_INTERPRET;
}
if (semanticRun < PASSsemantic3 && scope)
{
/* Forward reference - we need to run semantic3 on this function.
* If errors are gagged, and it's not part of a speculative
* template instance, we need to temporarily ungag errors.
*/
int olderrors = global.errors;
int oldgag = global.gag;
TemplateInstance *spec = isSpeculative();
if (global.gag && !spec)
global.gag = 0;
++scope->ignoreTemplates;
semantic3(scope);
--scope->ignoreTemplates;
global.gag = oldgag; // regag errors
// If it is a speculatively-instantiated template, and errors occur,
// we need to mark the template as having errors.
if (spec && global.errors != olderrors)
spec->errors = global.errors - olderrors;
if (olderrors != global.errors) // if errors compiling this function
return EXP_CANT_INTERPRET;
}
if (!functionSemantic3())
return EXP_CANT_INTERPRET;
if (semanticRun < PASSsemantic3done)
return EXP_CANT_INTERPRET;
@@ -1325,6 +1304,11 @@ Expression *WithStatement::interpret(InterState *istate)
#if LOG
printf("%s WithStatement::interpret()\n", loc.toChars());
#endif
// If it is with(Enum) {...}, just execute the body.
if (exp->op == TOKimport || exp->op == TOKtype)
return body ? body->interpret(istate) : EXP_VOID_INTERPRET;
START()
Expression *e = exp->interpret(istate);
if (exceptionOrCantInterpret(e))
@@ -4051,25 +4035,16 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal)
}
if (pthis)
{ // Member function call
Expression *oldpthis;
if (pthis->op == TOKthis)
{
pthis = istate ? istate->localThis : NULL;
oldpthis = pthis;
}
else
{
if (pthis->op == TOKcomma)
pthis = pthis->interpret(istate);
if (exceptionOrCantInterpret(pthis))
return pthis;
// Evaluate 'this'
oldpthis = pthis;
if (pthis->op != TOKvar)
pthis = pthis->interpret(istate, ctfeNeedLvalue);
if (exceptionOrCantInterpret(pthis))
return pthis;
}
if (pthis->op == TOKcomma)
pthis = pthis->interpret(istate);
if (exceptionOrCantInterpret(pthis))
return pthis;
// Evaluate 'this'
Expression *oldpthis = pthis;
if (pthis->op != TOKvar)
pthis = pthis->interpret(istate, ctfeNeedLvalue);
if (exceptionOrCantInterpret(pthis))
return pthis;
if (fd->isVirtual())
{ // Make a virtual function call.
Expression *thisval = pthis;
+881 -251
View File
File diff suppressed because it is too large Load Diff
+4 -2
View File
@@ -1,7 +1,7 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2013 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -18,7 +18,9 @@
#include "arraytypes.h"
void json_generate(Modules *);
struct OutBuffer;
void json_generate(OutBuffer *, Modules *);
#endif /* DMD_JSON_H */
-2
View File
@@ -2364,8 +2364,6 @@ done:
#endif
#ifdef IN_GCC
t->float80value = real_t::parse((char *)stringbuffer.data, real_t::LongDouble);
#elif IN_LLVM
t->float80value = Port::strtold((char *)stringbuffer.data, NULL);
#else
t->float80value = strtold((char *)stringbuffer.data, NULL);
#endif
+60 -21
View File
@@ -24,11 +24,18 @@
#include "id.h"
#include "module.h"
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS || IN_LLVM
#if CPP_MANGLE || IN_LLVM
char *cpp_mangle(Dsymbol *s);
#endif
char *mangle(Declaration *sthis)
/******************************************************************************
* isv : for the enclosing auto functions of an inner class/struct type.
* An aggregate type which defined inside auto function, it might
* become Voldemort Type so its object might be returned.
* This flag is necessary due to avoid mutual mangling
* between return type and enclosing scope. See bugzilla 8847.
*/
char *mangle(Declaration *sthis, bool isv)
{
OutBuffer buf;
char *id;
@@ -44,7 +51,7 @@ char *mangle(Declaration *sthis)
FuncDeclaration *fd = s->isFuncDeclaration();
if (s != sthis && fd)
{
id = mangle(fd);
id = mangle(fd, isv);
buf.prependstring(id);
goto L1;
}
@@ -70,7 +77,23 @@ L1:
FuncDeclaration *fd = sthis->isFuncDeclaration();
if (fd && (fd->needThis() || fd->isNested()))
buf.writeByte(Type::needThisPrefix());
if (sthis->type->deco)
if (isv && fd && (fd->inferRetType || getFuncTemplateDecl(fd)))
{
TypeFunction tfn = *(TypeFunction *)sthis->type;
TypeFunction *tfo = (TypeFunction *)sthis->originalType;
tfn.purity = tfo->purity;
tfn.isnothrow = tfo->isnothrow;
tfn.isproperty = tfo->isproperty;
tfn.isref = fd->storage_class & STCauto ? false : tfo->isref;
tfn.trust = tfo->trust;
tfn.next = NULL; // do not mangle return type
#if IN_LLVM
tfn.toDecoBuffer(&buf, 0, true);
#else
tfn.toDecoBuffer(&buf, 0);
#endif
}
else if (sthis->type->deco)
buf.writestring(sthis->type->deco);
else
{
@@ -86,7 +109,7 @@ L1:
return id;
}
char *Declaration::mangle()
char *Declaration::mangle(bool isv)
#if __DMC__
__out(result)
{
@@ -138,7 +161,7 @@ char *Declaration::mangle()
assert(0);
}
}
char *p = ::mangle(this);
char *p = ::mangle(this, isv);
OutBuffer buf;
buf.writestring("_D");
buf.writestring(p);
@@ -148,7 +171,7 @@ char *Declaration::mangle()
return p;
}
char *FuncDeclaration::mangle()
char *FuncDeclaration::mangle(bool isv)
#if __DMC__
__out(result)
{
@@ -164,24 +187,40 @@ char *FuncDeclaration::mangle()
return ident->toChars();
assert(this);
return Declaration::mangle();
return Declaration::mangle(isv);
}
char *StructDeclaration::mangle()
{
//printf("StructDeclaration::mangle() '%s'\n", toChars());
return Dsymbol::mangle();
}
char *TypedefDeclaration::mangle()
char *TypedefDeclaration::mangle(bool isv)
{
//printf("TypedefDeclaration::mangle() '%s'\n", toChars());
return Dsymbol::mangle();
return Dsymbol::mangle(isv);
}
char *ClassDeclaration::mangle()
char *AggregateDeclaration::mangle(bool isv)
{
#if 1
//printf("AggregateDeclaration::mangle() '%s'\n", toChars());
if (Dsymbol *p = toParent2())
{ if (FuncDeclaration *fd = p->isFuncDeclaration())
{ // This might be the Voldemort Type
char *id = Dsymbol::mangle(fd->inferRetType || getFuncTemplateDecl(fd));
//printf("isv ad %s, %s\n", toChars(), id);
return id;
}
}
#endif
return Dsymbol::mangle(isv);
}
char *StructDeclaration::mangle(bool isv)
{
//printf("StructDeclaration::mangle() '%s'\n", toChars());
return AggregateDeclaration::mangle(isv);
}
char *ClassDeclaration::mangle(bool isv)
{
Dsymbol *parentsave = parent;
@@ -209,13 +248,13 @@ char *ClassDeclaration::mangle()
)
parent = NULL;
char *id = Dsymbol::mangle();
char *id = AggregateDeclaration::mangle(isv);
parent = parentsave;
return id;
}
char *TemplateInstance::mangle()
char *TemplateInstance::mangle(bool isv)
{
OutBuffer buf;
@@ -274,7 +313,7 @@ char *TemplateMixin::mangle()
}
#endif
char *Dsymbol::mangle()
char *Dsymbol::mangle(bool isv)
{
OutBuffer buf;
char *id;
@@ -288,7 +327,7 @@ char *Dsymbol::mangle()
id = ident ? ident->toChars() : toChars();
if (parent)
{
char *p = parent->mangle();
char *p = parent->mangle(isv);
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
+75 -26
View File
@@ -80,7 +80,6 @@ Global::Global()
obj_ext = "obj";
#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
obj_ext = "o";
#elif TARGET_NET
#else
#error "fix this"
#endif
@@ -89,23 +88,24 @@ Global::Global()
lib_ext = "lib";
#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
lib_ext = "a";
#elif TARGET_NET
#else
#error "fix this"
#endif
#endif
copyright = "Copyright (c) 1999-2012 by Digital Mars";
written = "written by Walter Bright"
#if TARGET_NET
"\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
#endif
written = "written by Walter Bright";
#if IN_DMD
version = "v"
#include "verstr.h"
;
version = "v2.061";
#endif
#if IN_LLVM
version = "v2.062";
ldc_version = "trunk";
llvm_version = "LLVM "LDC_LLVM_VERSION_STRING;
#endif
global.structalign = STRUCTALIGN_DEFAULT;
// This should only be used as a global, so the other fields are
@@ -321,7 +321,7 @@ void usage()
sizeof(size_t) * 8,
global.version, global.copyright, global.written);
printf("\
Documentation: http://www.dlang.org/index.html\n\
Documentation: http://dlang.org/\n\
Usage:\n\
dmd files.d ... { -switch }\n\
\n\
@@ -344,6 +344,7 @@ Usage:\n\
" -g add symbolic debug info\n\
-gc add symbolic debug info, pretend to be C\n\
-gs always emit stack frame\n\
-gx add stack stomp code\n\
-H generate 'header' file\n\
-Hddirectory write 'header' file to directory\n\
-Hffilename write 'header' file to filename\n\
@@ -466,7 +467,6 @@ int tryMain(size_t argc, char *argv[])
global.params.defaultlibname = "phobos";
#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
global.params.defaultlibname = "phobos2";
#elif TARGET_NET
#else
#error "fix this"
#endif
@@ -477,10 +477,6 @@ int tryMain(size_t argc, char *argv[])
#if TARGET_WINDOS
VersionCondition::addPredefinedGlobalIdent("Windows");
global.params.isWindows = 1;
#if TARGET_NET
// TARGET_NET macro is NOT mutually-exclusive with TARGET_WINDOS
VersionCondition::addPredefinedGlobalIdent("D_NET");
#endif
#elif TARGET_LINUX
VersionCondition::addPredefinedGlobalIdent("Posix");
VersionCondition::addPredefinedGlobalIdent("linux");
@@ -579,6 +575,8 @@ int tryMain(size_t argc, char *argv[])
global.params.symdebug = 2;
else if (strcmp(p + 1, "gs") == 0)
global.params.alwaysframe = 1;
else if (strcmp(p + 1, "gx") == 0)
global.params.stackstomp = true;
else if (strcmp(p + 1, "gt") == 0)
{ error(0, "use -profile instead of -gt");
global.params.trace = 1;
@@ -834,35 +832,35 @@ int tryMain(size_t argc, char *argv[])
#if DMDV1
browse("http://www.digitalmars.com/d/1.0/dmd-windows.html");
#else
browse("http://www.dlang.org/dmd-windows.html");
browse("http://dlang.org/dmd-windows.html");
#endif
#endif
#if linux
#if DMDV1
browse("http://www.digitalmars.com/d/1.0/dmd-linux.html");
#else
browse("http://www.dlang.org/dmd-linux.html");
browse("http://dlang.org/dmd-linux.html");
#endif
#endif
#if __APPLE__
#if DMDV1
browse("http://www.digitalmars.com/d/1.0/dmd-osx.html");
#else
browse("http://www.dlang.org/dmd-osx.html");
browse("http://dlang.org/dmd-osx.html");
#endif
#endif
#if __FreeBSD__
#if DMDV1
browse("http://www.digitalmars.com/d/1.0/dmd-freebsd.html");
#else
browse("http://www.dlang.org/dmd-freebsd.html");
browse("http://dlang.org/dmd-freebsd.html");
#endif
#endif
#if __OpenBSD__
#if DMDV1
browse("http://www.digitalmars.com/d/1.0/dmd-openbsd.html");
#else
browse("http://www.dlang.org/dmd-openbsd.html");
browse("http://dlang.org/dmd-openbsd.html");
#endif
#endif
exit(EXIT_SUCCESS);
@@ -872,6 +870,14 @@ int tryMain(size_t argc, char *argv[])
global.params.runargs_length = ((i >= argcstart) ? argc : argcstart) - i - 1;
if (global.params.runargs_length)
{
const char *ext = FileName::ext(argv[i + 1]);
if (ext && FileName::equals(ext, "d") == 0
&& FileName::equals(ext, "di") == 0)
{
error(0, "-run must be followed by a source file, not '%s'", argv[i + 1]);
break;
}
files.push(argv[i + 1]);
global.params.runargs = &argv[i + 2];
i += global.params.runargs_length;
@@ -896,7 +902,7 @@ int tryMain(size_t argc, char *argv[])
else
{
#if TARGET_WINDOS
char *ext = FileName::ext(p);
const char *ext = FileName::ext(p);
if (ext && FileName::compare(ext, "exe") == 0)
{
global.params.objname = p;
@@ -961,14 +967,14 @@ int tryMain(size_t argc, char *argv[])
/* Use this to name the one object file with the same
* name as the exe file.
*/
global.params.objname = FileName::forceExt(global.params.objname, global.obj_ext)->toChars();
global.params.objname = const_cast<char *>(FileName::forceExt(global.params.objname, global.obj_ext));
/* If output directory is given, use that path rather than
* the exe file path.
*/
if (global.params.objdir)
{ char *name = FileName::name(global.params.objname);
global.params.objname = FileName::combine(global.params.objdir, name);
{ const char *name = FileName::name(global.params.objname);
global.params.objname = (char *)FileName::combine(global.params.objdir, name);
}
}
}
@@ -1101,7 +1107,7 @@ int tryMain(size_t argc, char *argv[])
int firstmodule = 1;
for (size_t i = 0; i < files.dim; i++)
{
char *ext;
const char *ext;
char *name;
p = files[i];
@@ -1115,7 +1121,7 @@ int tryMain(size_t argc, char *argv[])
}
#endif
p = FileName::name(p); // strip path
p = (char *)FileName::name(p); // strip path
ext = FileName::ext(p);
if (ext)
{ /* Deduce what to do with a file based on its extension
@@ -1214,7 +1220,7 @@ int tryMain(size_t argc, char *argv[])
modules.push(m);
if (firstmodule)
{ global.params.objfiles->push(m->objfile->name->str);
{ global.params.objfiles->push((char *)m->objfile->name->str);
firstmodule = 0;
}
}
@@ -1431,7 +1437,50 @@ int tryMain(size_t argc, char *argv[])
// Generate output files
if (global.params.doXGeneration)
json_generate(&modules);
{
OutBuffer buf;
json_generate(&buf, &modules);
// Write buf to file
const char *name = global.params.xfilename;
if (name && name[0] == '-' && name[1] == 0)
{ // Write to stdout; assume it succeeds
int n = fwrite(buf.data, 1, buf.offset, stdout);
assert(n == buf.offset); // keep gcc happy about return values
}
else
{
/* The filename generation code here should be harmonized with Module::setOutfile()
*/
const char *jsonfilename;
if (name && *name)
{
jsonfilename = FileName::defaultExt(name, global.json_ext);
}
else
{
// Generate json file name from first obj name
const char *n = (*global.params.objfiles)[0];
n = FileName::name(n);
//if (!FileName::absolute(name))
//name = FileName::combine(dir, name);
jsonfilename = FileName::forceExt(n, global.json_ext);
}
FileName::ensurePathToNameExists(jsonfilename);
File *jsonfile = new File(jsonfilename);
jsonfile->setbuffer(buf.data, buf.offset);
jsonfile->ref = 1;
jsonfile->writev();
}
}
if (global.params.oneobj)
{
+4 -6
View File
@@ -51,7 +51,6 @@ the target object file format:
TARGET_FREEBSD Covers 32 and 64 bit FreeBSD
TARGET_OPENBSD Covers 32 and 64 bit OpenBSD
TARGET_SOLARIS Covers 32 and 64 bit Solaris
TARGET_NET Covers .Net
It is expected that the compiler for each platform will be able
to generate 32 and 64 bit code from the same compiler binary.
@@ -101,11 +100,9 @@ void unittests();
#define DMDV1 0
#define DMDV2 1 // Version 2.0 features
#define STRUCTTHISREF DMDV2 // if 'this' for struct is a reference, not a pointer
#define SNAN_DEFAULT_INIT DMDV2 // if floats are default initialized to signalling NaN
#define SARRAYVALUE DMDV2 // static arrays are value types
#define MODULEINFO_IS_STRUCT DMDV2 // if ModuleInfo is a struct rather than a class
#define BUG6652 1 // Making foreach range statement parameter non-ref in default
#define BUG6652 2 // Making foreach range statement parameter non-ref in default
// 1: Modifying iteratee in body is warned with -w switch
// 2: Modifying iteratee in body is error without -d switch
@@ -167,7 +164,7 @@ struct Param
char lib; // write library file instead of object file(s)
char multiobj; // break one object file into multiple ones
char oneobj; // write one object file instead of multiple ones
char trace; // insert profiling hooks
bool trace; // insert profiling hooks
char quiet; // suppress non-error messages
#endif
bool verbose; // verbose compile
@@ -184,7 +181,7 @@ struct Param
char isOSX; // generate code for Mac OSX
char isWindows; // generate code for Windows
char isFreeBSD; // generate code for FreeBSD
char isOPenBSD; // generate code for OpenBSD
char isOpenBSD; // generate code for OpenBSD
char isSolaris; // generate code for Solaris
char scheduler; // which scheduler to use
#endif
@@ -203,6 +200,7 @@ struct Param
// 2: array bounds checks for all functions
#endif
bool noboundscheck; // no array bounds checking at all
bool stackstomp; // add stack stomping code
bool useSwitchError; // check for switches without a default
bool useUnitTests; // generate unittest code
bool useInline; // inline expand functions
+67 -129
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2012 by Digital Mars
// Copyright (c) 1999-2013 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -12,20 +12,6 @@
#include <stdlib.h>
#include <assert.h>
#if defined (__sun)
#include <alloca.h>
#endif
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <malloc.h>
#endif
#ifdef IN_GCC
#include "gdc_alloca.h"
#endif
#include "rmem.h"
#include "mars.h"
#include "module.h"
#include "parse.h"
@@ -37,11 +23,6 @@
#include "hdrgen.h"
#include "lexer.h"
// stricmp
#if __GNUC__ && !_WIN32
#include "gnuc.h"
#endif
#ifdef IN_GCC
#include "d-dmd-gcc.h"
#endif
@@ -59,6 +40,12 @@
#include "llvm/Support/CommandLine.h"
#include <map>
#if _WIN32
#define strcasecmp(s1, s2) _stricmp(s1, s2)
#else
#define strcasecmp(s1, s2) strcmp(s1, s2)
#endif
static llvm::cl::opt<bool> preservePaths("op",
llvm::cl::desc("Do not strip paths from source file"),
llvm::cl::ZeroOrMore);
@@ -85,10 +72,9 @@ void Module::init()
Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen)
: Package(ident)
{
FileName *srcfilename;
const char *srcfilename;
#if IN_DMD
FileName *objfilename;
FileName *symfilename;
const char *symfilename;
#endif
// printf("Module::Module(filename = '%s', ident = '%s')\n", filename, ident->toChars());
@@ -99,9 +85,6 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
members = NULL;
isDocFile = 0;
needmoduleinfo = 0;
#ifdef IN_GCC
strictlyneedmoduleinfo = 0;
#endif
selfimports = 0;
insearch = 0;
searchCacheIdent = NULL;
@@ -150,61 +133,27 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
namelen = 0;
srcfilename = FileName::defaultExt(filename, global.mars_ext);
if (!srcfilename->equalsExt(global.mars_ext) &&
!srcfilename->equalsExt(global.hdr_ext) &&
!srcfilename->equalsExt("dd"))
if (!FileName::equalsExt(srcfilename, global.mars_ext) &&
!FileName::equalsExt(srcfilename, global.hdr_ext) &&
!FileName::equalsExt(srcfilename, "dd"))
{
error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.mars_ext);
error("source file name '%s' must have .%s extension", srcfilename, global.mars_ext);
fatal();
}
#if !IN_LLVM
char *argobj;
if (global.params.objname)
argobj = global.params.objname;
#if 0
else if (global.params.preservePaths)
argobj = filename;
else
argobj = FileName::name(filename);
if (!FileName::absolute(argobj))
{
argobj = FileName::combine(global.params.objdir, argobj);
}
#else // Bugzilla 3547
else
{
if (global.params.preservePaths)
argobj = filename;
else
argobj = FileName::name(filename);
if (!FileName::absolute(argobj))
{
argobj = FileName::combine(global.params.objdir, argobj);
}
}
#endif
srcfile = new File(srcfilename);
if (global.params.objname)
objfilename = new FileName(argobj);
else
objfilename = FileName::forceExt(argobj, global.obj_ext);
#if IN_DMD
objfile = setOutfile(global.params.objname, global.params.objdir, filename, global.obj_ext);
symfilename = FileName::forceExt(filename, global.sym_ext);
#endif
srcfile = new File(srcfilename);
#if IN_DMD
if (doDocComment)
{
setDocfile();
}
if (doHdrGen)
{
setHdrfile();
}
hdrfile = setOutfile(global.params.hdrname, global.params.hdrdir, arg, global.hdr_ext);
objfile = new File(objfilename);
//objfile = new File(objfilename);
symfile = new File(symfilename);
#endif
#if IN_LLVM
@@ -263,8 +212,8 @@ File* Module::buildFilePath(const char* forcename, const char* path, const char*
// else
// allow for .o and .obj on windows
#if _WIN32
if (ext == global.params.objdir && FileName::ext(argobj)
&& stricmp(FileName::ext(argobj), global.obj_ext_alt) == 0)
if (ext == global.params.objdir && FileName::ext(argobj)
&& strcasecmp(FileName::ext(argobj), global.obj_ext_alt) == 0)
return new File((char*)argobj);
#endif
return new File(FileName::forceExt(argobj, ext));
@@ -273,58 +222,50 @@ File* Module::buildFilePath(const char* forcename, const char* path, const char*
#if IN_DMD
void Module::setDocfile()
{
FileName *docfilename;
char *argdoc;
if (global.params.docname)
argdoc = global.params.docname;
else if (global.params.preservePaths)
argdoc = (char *)arg;
else
argdoc = FileName::name((char *)arg);
if (!FileName::absolute(argdoc))
{ //FileName::ensurePathExists(global.params.docdir);
argdoc = FileName::combine(global.params.docdir, argdoc);
}
if (global.params.docname)
docfilename = new FileName(argdoc);
else
docfilename = FileName::forceExt(argdoc, global.doc_ext);
if (docfilename->equals(srcfile->name))
{ error("Source file and documentation file have same name '%s'", srcfile->name->str);
fatal();
}
docfile = new File(docfilename);
docfile = setOutfile(global.params.docname, global.params.docdir, arg, global.doc_ext);
}
void Module::setHdrfile()
/*********************************************
* Combines things into output file name for .html and .di files.
* Input:
* name Command line name given for the file, NULL if none
* dir Command line directory given for the file, NULL if none
* arg Name of the source file
* ext File name extension to use if 'name' is NULL
* global.params.preservePaths get output path from arg
* srcfile Input file - output file name must not match input file
*/
File *Module::setOutfile(const char *name, const char *dir, const char *arg, const char *ext)
{
FileName *hdrfilename;
char *arghdr;
const char *docfilename;
if (global.params.hdrname)
arghdr = global.params.hdrname;
else if (global.params.preservePaths)
arghdr = (char *)arg;
else
arghdr = FileName::name((char *)arg);
if (!FileName::absolute(arghdr))
{ //FileName::ensurePathExists(global.params.hdrdir);
arghdr = FileName::combine(global.params.hdrdir, arghdr);
if (name)
{
docfilename = name;
}
if (global.params.hdrname)
hdrfilename = new FileName(arghdr);
else
hdrfilename = FileName::forceExt(arghdr, global.hdr_ext);
{
const char *argdoc;
if (global.params.preservePaths)
argdoc = arg;
else
argdoc = FileName::name(arg);
if (hdrfilename->equals(srcfile->name))
{ error("Source file and 'header' file have same name '%s'", srcfile->name->str);
// If argdoc doesn't have an absolute path, make it relative to dir
if (!FileName::absolute(argdoc))
{ //FileName::ensurePathExists(dir);
argdoc = FileName::combine(dir, argdoc);
}
docfilename = FileName::forceExt(argdoc, ext);
}
if (FileName::equals(docfilename, srcfile->name->str))
{ error("Source file and output file have same name '%s'", srcfile->name->str);
fatal();
}
hdrfile = new File(hdrfilename);
return new File(docfilename);
}
#endif
@@ -361,7 +302,7 @@ void Module::buildTargetFiles(bool singleObj)
global.params.targetTriple.isOSWindows() ? global.obj_ext_alt : global.obj_ext);
else if (global.params.output_bc)
objfile = Module::buildFilePath(global.params.objname, global.params.objdir, global.bc_ext);
else if (global.params.output_ll)
else if (global.params.output_ll)
objfile = Module::buildFilePath(global.params.objname, global.params.objdir, global.ll_ext);
else if (global.params.output_s)
objfile = Module::buildFilePath(global.params.objname, global.params.objdir, global.s_ext);
@@ -372,17 +313,17 @@ void Module::buildTargetFiles(bool singleObj)
hdrfile = Module::buildFilePath(global.params.hdrname, global.params.hdrdir, global.hdr_ext);
// safety check: never allow obj, doc or hdr file to have the source file's name
if(stricmp(FileName::name(objfile->name->str), FileName::name((char*)this->arg)) == 0)
if(strcasecmp(FileName::name(objfile->name->str), FileName::name((char*)this->arg)) == 0)
{
error("Output object files with the same name as the source file are forbidden");
fatal();
}
if(docfile && stricmp(FileName::name(docfile->name->str), FileName::name((char*)this->arg)) == 0)
if(docfile && strcasecmp(FileName::name(docfile->name->str), FileName::name((char*)this->arg)) == 0)
{
error("Output doc files with the same name as the source file are forbidden");
fatal();
}
if(hdrfile && stricmp(FileName::name(hdrfile->name->str), FileName::name((char*)this->arg)) == 0)
if(hdrfile && strcasecmp(FileName::name(hdrfile->name->str), FileName::name((char*)this->arg)) == 0)
{
error("Output header files with the same name as the source file are forbidden");
fatal();
@@ -457,11 +398,11 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
/* Search along global.path for .di file, then .d file.
*/
char *result = NULL;
FileName *fdi = FileName::forceExt(filename, global.hdr_ext);
FileName *fd = FileName::forceExt(filename, global.mars_ext);
char *sdi = fdi->toChars();
char *sd = fd->toChars();
const char *result = NULL;
const char *fdi = FileName::forceExt(filename, global.hdr_ext);
const char *fd = FileName::forceExt(filename, global.mars_ext);
const char *sdi = fdi;
const char *sd = fd;
if (FileName::exists(sdi))
result = sdi;
@@ -475,19 +416,19 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
{
for (size_t i = 0; i < global.path->dim; i++)
{
char *p = (*global.path)[i];
char *n = FileName::combine(p, sdi);
const char *p = (*global.path)[i];
const char *n = FileName::combine(p, sdi);
if (FileName::exists(n))
{ result = n;
break;
}
mem.free(n);
FileName::free(n);
n = FileName::combine(p, sd);
if (FileName::exists(n))
{ result = n;
break;
}
mem.free(n);
FileName::free(n);
}
}
if (result)
@@ -1395,15 +1336,12 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package
dst = ((Package *)p)->symtab;
if (ppkg && !*ppkg)
*ppkg = (Package *)p;
#if TARGET_NET
#else
if (p->isModule())
{ // Return the module so that a nice error message can be generated
if (ppkg)
*ppkg = (Package *)p;
break;
}
#endif
}
if (pparent)
{
+3 -7
View File
@@ -81,9 +81,6 @@ struct Module : Package
unsigned numlines; // number of lines in source file
int isDocFile; // if it is a documentation input file, not D source
int needmoduleinfo;
#ifdef IN_GCC
int strictlyneedmoduleinfo;
#endif
int selfimports; // 0: don't know, 1: does not, 2: does
int selfImports(); // returns !=0 if module imports itself
@@ -132,9 +129,11 @@ struct Module : Package
static Module *load(Loc loc, Identifiers *packages, Identifier *ident);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJsonBuffer(OutBuffer *buf);
void toJson(JsonOut *json);
void jsonProperties(JsonOut *json);
const char *kind();
#if !IN_LLVM
File *setOutfile(const char *name, const char *dir, const char *arg, const char *ext);
void setDocfile(); // set docfile member
#endif
bool read(Loc loc); // read file, returns 'true' if succeed, 'false' otherwise.
@@ -148,9 +147,6 @@ struct Module : Package
void semantic2(Scope* unused_sc = NULL); // pass 2 semantic analysis
void semantic3(Scope* unused_sc = NULL); // pass 3 semantic analysis
void inlineScan(); // scan for functions to inline
#if !IN_LLVM
void setHdrfile(); // set hdrfile member
#endif
void genhdrfile(); // generate D import file
// void gensymfile();
void gendocfile();
+231 -118
View File
@@ -4,7 +4,6 @@
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// http://www.dsource.org/projects/dmd/browser/trunk/src/mtype.c
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
@@ -12,16 +11,11 @@
#define __C99FEATURES__ 1 // Needed on Solaris for NaN and more
#define __USE_ISOC99 1 // so signbit() gets defined
#if defined (__sun)
#include <alloca.h>
#endif
#ifdef __DMC__
#include <math.h>
#else
#include <cmath>
#endif
#include <stdio.h>
#include <assert.h>
#include <float.h>
@@ -136,6 +130,7 @@ TemplateDeclaration *Type::rtinfo;
Type *Type::tvoidptr;
Type *Type::tstring;
Type *Type::tvalist;
Type *Type::basic[TMAX];
unsigned char Type::mangleChar[TMAX];
unsigned short Type::sizeTy[TMAX];
@@ -172,6 +167,12 @@ Type::Type(TY ty)
#endif
}
const char *Type::kind()
{
assert(false); // should be overridden
return NULL;
}
Type *Type::syntaxCopy()
{
print();
@@ -315,6 +316,7 @@ void Type::init()
tvoidptr = tvoid->pointerTo();
tstring = tchar->invariantOf()->arrayOf();
tvalist = tvoid->pointerTo();
#if IN_DMD
if (global.params.is64bit)
@@ -1370,28 +1372,13 @@ Type *Type::aliasthisOf()
FuncDeclaration *fd = (FuncDeclaration *)d;
Expression *ethis = this->defaultInit(0);
fd = fd->overloadResolve(0, ethis, NULL, 1);
if (fd)
{ TypeFunction *tf = (TypeFunction *)fd->type;
if (!tf->next && fd->inferRetType)
{
TemplateInstance *spec = fd->isSpeculative();
int olderrs = global.errors;
// If it isn't speculative, we need to show errors
unsigned oldgag = global.gag;
if (global.gag && !spec)
global.gag = 0;
fd->semantic3(fd->scope);
global.gag = oldgag;
// Update the template instantiation with the number
// of errors which occured.
if (spec && global.errors != olderrs)
spec->errors = global.errors - olderrs;
tf = (TypeFunction *)fd->type;
}
t = tf->next;
if (tf->isWild())
t = t->substWildTo(mod == 0 ? MODmutable : mod);
if (fd && fd->functionSemantic())
{
t = fd->type->nextOf();
t = t->substWildTo(mod == 0 ? MODmutable : mod);
}
else
return Type::terror;
}
return t;
}
@@ -1406,26 +1393,14 @@ Type *Type::aliasthisOf()
{ assert(td->scope);
Expression *ethis = defaultInit(0);
FuncDeclaration *fd = td->deduceFunctionTemplate(td->scope, 0, NULL, ethis, NULL, 1);
if (fd)
if (fd && fd->functionSemantic())
{
//if (!fd->type->nextOf() && fd->inferRetType)
{
TemplateInstance *spec = fd->isSpeculative();
int olderrs = global.errors;
fd->semantic3(fd->scope);
// Update the template instantiation with the number
// of errors which occured.
if (spec && global.errors != olderrs)
spec->errors = global.errors - olderrs;
}
if (!fd->errors)
{
Type *t = fd->type->nextOf();
t = t->substWildTo(mod == 0 ? MODmutable : mod);
return t;
}
Type *t = fd->type->nextOf();
t = t->substWildTo(mod == 0 ? MODmutable : mod);
return t;
}
return Type::terror;
else
return Type::terror;
}
//printf("%s\n", ad->aliasthis->kind());
}
@@ -1592,7 +1567,7 @@ void MODtoDecoBuffer(OutBuffer *buf, unsigned char mod)
}
/*********************************
* Name for mod.
* Store modifier name into buf.
*/
void MODtoBuffer(OutBuffer *buf, unsigned char mod)
{
@@ -1626,6 +1601,18 @@ void MODtoBuffer(OutBuffer *buf, unsigned char mod)
}
}
/*********************************
* Return modifier name.
*/
char *MODtoChars(unsigned char mod)
{
OutBuffer buf;
MODtoBuffer(&buf, mod);
buf.writebyte(0);
return buf.extractData();
}
/********************************
* Name mangling.
* Input:
@@ -1699,6 +1686,9 @@ void Type::toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod)
}
}
/*********************************
* Store this type's modifier name into buf.
*/
void Type::modToBuffer(OutBuffer *buf)
{
if (mod)
@@ -1708,6 +1698,17 @@ void Type::modToBuffer(OutBuffer *buf)
}
}
/*********************************
* Return this type's modifier name.
*/
char *Type::modToChars()
{
OutBuffer buf;
modToBuffer(&buf);
buf.writebyte(0);
return buf.extractData();
}
/************************************
*/
@@ -1719,7 +1720,7 @@ Type *Type::merge()
if (ty == Tinstance) return this;
if (ty == Taarray && !((TypeAArray *)this)->index->merge()->deco)
return this;
if (nextOf() && !nextOf()->merge()->deco)
if (nextOf() && !nextOf()->deco)
return this;
//printf("merge(%s)\n", toChars());
@@ -1847,13 +1848,14 @@ int Type::isString()
}
/**************************
* When T is mutable,
* Given:
* T a, b;
* Can we assign:
* Can we bitwise assign:
* a = b;
* ?
*/
int Type::isAssignable(int blit)
int Type::isAssignable()
{
return TRUE;
}
@@ -2289,9 +2291,6 @@ Identifier *Type::getTypeInfoIdent(int internal)
{
// _init_10TypeInfo_%s
OutBuffer buf;
Identifier *id;
char *name;
size_t len;
if (internal)
{ buf.writeByte(mangleChar[ty]);
@@ -2300,21 +2299,29 @@ Identifier *Type::getTypeInfoIdent(int internal)
}
else
toDecoBuffer(&buf, 0, true);
len = buf.offset;
name = (char *)alloca(19 + sizeof(len) * 3 + len + 1);
size_t len = buf.offset;
buf.writeByte(0);
#if TARGET_OSX
// The LINKc will prepend the _
sprintf(name, "D%dTypeInfo_%s6__initZ", 9 + len, buf.data);
#else
// Allocate buffer on stack, fail over to using malloc()
char namebuf[40];
size_t namelen = 19 + sizeof(len) * 3 + len + 1;
char *name = namelen <= sizeof(namebuf) ? namebuf : (char *)malloc(namelen);
assert(name);
sprintf(name, "_D%dTypeInfo_%s6__initZ", 9 + len, buf.data);
#endif
#if !IN_LLVM
if (global.params.isWindows && !global.params.is64bit)
name++; // C mangling will add it back in
#endif
//printf("name = %s\n", name);
id = Lexer::idPool(name);
assert(strlen(name) < namelen); // don't overflow the buffer
size_t off = 0;
#if !IN_LLVM
if (global.params.isOSX || global.params.isWindows && !global.params.is64bit)
++off; // C mangling will add '_' back in
#endif
Identifier *id = Lexer::idPool(name + off);
if (name != namebuf)
free(name);
return id;
}
@@ -2815,6 +2822,11 @@ TypeBasic::TypeBasic(TY ty)
merge();
}
const char *TypeBasic::kind()
{
return dstring;
}
Type *TypeBasic::syntaxCopy()
{
// No semantic analysis done on basic types, no need to copy
@@ -3496,6 +3508,11 @@ TypeVector::TypeVector(Loc loc, Type *basetype)
this->basetype = basetype;
}
const char *TypeVector::kind()
{
return "vector";
}
Type *TypeVector::syntaxCopy()
{
return new TypeVector(0, basetype->syntaxCopy());
@@ -3842,6 +3859,11 @@ TypeSArray::TypeSArray(Type *t, Expression *dim)
this->dim = dim;
}
const char *TypeSArray::kind()
{
return "sarray";
}
Type *TypeSArray::syntaxCopy()
{
Type *t = next->syntaxCopy();
@@ -4163,11 +4185,19 @@ Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
#endif
if (ident == Id::length)
{
e = dim;
Loc oldLoc = e->loc;
e = dim->copy();
e->loc = oldLoc;
}
else if (ident == Id::ptr)
{
e = e->castTo(sc, next->pointerTo());
if (size(e->loc) == 0)
e = new NullExp(e->loc, next->pointerTo());
else
{
e = new IndexExp(e->loc, e, new IntegerExp(0));
e = new AddrExp(e->loc, e);
}
}
else
{
@@ -4343,6 +4373,11 @@ TypeDArray::TypeDArray(Type *t)
//printf("TypeDArray(t = %p)\n", t);
}
const char *TypeDArray::kind()
{
return "darray";
}
Type *TypeDArray::syntaxCopy()
{
Type *t = next->syntaxCopy();
@@ -4497,7 +4532,7 @@ MATCH TypeDArray::implicitConvTo(Type *to)
return MATCHconvert;
}
return next->constConv(to);
return next->constConv(to) ? MATCHconvert : MATCHnomatch;
}
if (to->ty == Tarray)
@@ -4567,6 +4602,11 @@ TypeAArray::TypeAArray(Type *t, Type *index)
this->sc = NULL;
}
const char *TypeAArray::kind()
{
return "aarray";
}
Type *TypeAArray::syntaxCopy()
{
Type *t = next->syntaxCopy();
@@ -5002,6 +5042,11 @@ TypePointer::TypePointer(Type *t)
{
}
const char *TypePointer::kind()
{
return "pointer";
}
Type *TypePointer::syntaxCopy()
{
Type *t = next->syntaxCopy();
@@ -5170,6 +5215,11 @@ TypeReference::TypeReference(Type *t)
// BUG: what about references to static arrays?
}
const char *TypeReference::kind()
{
return "reference";
}
Type *TypeReference::syntaxCopy()
{
Type *t = next->syntaxCopy();
@@ -5274,6 +5324,18 @@ TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, e
this->trust = TRUSTtrusted;
}
const char *TypeFunction::kind()
{
return "function";
}
TypeFunction *TypeFunction::copy()
{
TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
memcpy(tf, this, sizeof(TypeFunction));
return tf;
}
Type *TypeFunction::syntaxCopy()
{
Type *treturn = next ? next->syntaxCopy() : NULL;
@@ -5558,8 +5620,8 @@ void TypeFunction::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
Parameter::argsToDecoBuffer(buf, parameters, mangle);
//if (buf->data[buf->offset - 1] == '@') halt();
buf->writeByte('Z' - varargs); // mark end of arg list
assert(next);
next->toDecoBuffer(buf, 0, mangle);
if(next != NULL)
next->toDecoBuffer(buf, 0, mangle);
inuse--;
}
@@ -5763,8 +5825,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
* This can produce redundant copies if inferring return type,
* as semantic() will get called again on this.
*/
TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
memcpy(tf, this, sizeof(TypeFunction));
TypeFunction *tf = copy();
if (parameters)
{ tf->parameters = (Parameters *)parameters->copy();
for (size_t i = 0; i < parameters->dim; i++)
@@ -5817,12 +5878,6 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
sc->stc &= ~(STC_TYPECTOR | STC_FUNCATTR);
tf->next = tf->next->semantic(loc,sc);
sc = sc->pop();
#if !SARRAYVALUE
if (tf->next->toBasetype()->ty == Tsarray)
{ error(loc, "functions cannot return static array %s", tf->next->toChars());
tf->next = Type::terror;
}
#endif
if (tf->next->toBasetype()->ty == Tfunction)
{ error(loc, "functions cannot return a function");
tf->next = Type::terror;
@@ -5888,9 +5943,9 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
if (fparam->defaultArg)
{ Expression *e = fparam->defaultArg;
e = e->inferType(fparam->type);
e = e->semantic(argsc);
e = resolveProperties(argsc, e);
Initializer *init = new ExpInitializer(e->loc, e);
init = init->semantic(argsc, fparam->type, INITnointerpret);
e = init->toExpression();
if (e->op == TOKfunction) // see Bugzilla 4820
{ FuncExp *fe = (FuncExp *)e;
// Replace function literal with a function symbol,
@@ -6302,25 +6357,6 @@ MATCH TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag)
new IntegerExp(0, ((StringExp *)arg)->len,
Type::tindex));
}
else if (ta && ta->implicitConvTo(tprm))
{
goto Nomatch;
}
else if (arg->op == TOKstructliteral)
{
match = MATCHconvert;
}
else if (arg->op == TOKcall)
{
CallExp *ce = (CallExp *)arg;
if (ce->e1->op == TOKdotvar &&
((DotVarExp *)ce->e1)->var->isCtorDeclaration())
{
match = MATCHconvert;
}
else
goto Nomatch;
}
else
goto Nomatch;
}
@@ -6557,6 +6593,11 @@ TypeDelegate::TypeDelegate(Type *t)
ty = Tdelegate;
}
const char *TypeDelegate::kind()
{
return "delegate";
}
Type *TypeDelegate::syntaxCopy()
{
Type *t = next->syntaxCopy();
@@ -6750,6 +6791,7 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
VarDeclaration *v;
EnumMember *em;
Expression *e;
TemplateInstance *ti;
#if 0
printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, toChars());
@@ -6775,6 +6817,7 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
{ Type *t;
v = s->isVarDeclaration();
ti = s->isTemplateInstance();
if (v && id == Id::length)
{
e = new VarExp(loc, v);
@@ -6783,7 +6826,8 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
goto Lerror;
goto L3;
}
else if (v && (id == Id::stringof || id == Id::offsetof))
else if ((v && (id == Id::stringof || id == Id::offsetof))
|| (ti && (id == Id::stringof || id == Id::mangleof)))
{
e = new DsymbolExp(loc, s, 0);
do
@@ -6959,6 +7003,11 @@ TypeIdentifier::TypeIdentifier(Loc loc, Identifier *ident)
this->ident = ident;
}
const char *TypeIdentifier::kind()
{
return "identifier";
}
Type *TypeIdentifier::syntaxCopy()
{
@@ -7133,6 +7182,11 @@ TypeInstance::TypeInstance(Loc loc, TemplateInstance *tempinst)
this->tempinst = tempinst;
}
const char *TypeInstance::kind()
{
return "instance";
}
Type *TypeInstance::syntaxCopy()
{
//printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.dim);
@@ -7274,6 +7328,11 @@ TypeTypeof::TypeTypeof(Loc loc, Expression *exp)
inuse = 0;
}
const char *TypeTypeof::kind()
{
return "typeof";
}
Type *TypeTypeof::syntaxCopy()
{
//printf("TypeTypeof::syntaxCopy() %s\n", toChars());
@@ -7458,6 +7517,11 @@ TypeReturn::TypeReturn(Loc loc)
{
}
const char *TypeReturn::kind()
{
return "return";
}
Type *TypeReturn::syntaxCopy()
{
TypeReturn *t = new TypeReturn(loc);
@@ -7541,6 +7605,11 @@ TypeEnum::TypeEnum(EnumDeclaration *sym)
this->sym = sym;
}
const char *TypeEnum::kind()
{
return "enum";
}
char *TypeEnum::toChars()
{
if (mod)
@@ -7722,9 +7791,9 @@ int TypeEnum::isscalar()
return sym->memtype->isscalar();
}
int TypeEnum::isAssignable(int blit)
int TypeEnum::isAssignable()
{
return sym->memtype->isAssignable(blit);
return sym->memtype->isAssignable();
}
int TypeEnum::checkBoolean()
@@ -7811,6 +7880,11 @@ TypeTypedef::TypeTypedef(TypedefDeclaration *sym)
this->sym = sym;
}
const char *TypeTypedef::kind()
{
return "typedef";
}
Type *TypeTypedef::syntaxCopy()
{
return this;
@@ -7939,9 +8013,9 @@ int TypeTypedef::isscalar()
return sym->basetype->isscalar();
}
int TypeTypedef::isAssignable(int blit)
int TypeTypedef::isAssignable()
{
return sym->basetype->isAssignable(blit);
return sym->basetype->isAssignable();
}
int TypeTypedef::checkBoolean()
@@ -8094,6 +8168,11 @@ TypeStruct::TypeStruct(StructDeclaration *sym)
this->unaligned = 0;
}
const char *TypeStruct::kind()
{
return "struct";
}
char *TypeStruct::toChars()
{
//printf("sym.parent: %s, deco = %s\n", sym->parent->toChars(), deco);
@@ -8423,6 +8502,7 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc)
for (size_t j = 0; j < structelems->dim; j++)
{
VarDeclaration *vd = sym->fields[j];
Type *telem = vd->type->addMod(this->mod);
Expression *e;
if (vd->init)
{ if (vd->init->isVoidInitializer())
@@ -8433,7 +8513,10 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc)
else
e = vd->type->defaultInitLiteral(loc);
if (e && vd->scope)
e = e->semantic(vd->scope);
{
e = e->semantic(vd->scope);
e = e->implicitCastTo(vd->scope, telem);
}
(*structelems)[j] = e;
}
StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems);
@@ -8481,18 +8564,8 @@ bool TypeStruct::needsNested()
return false;
}
int TypeStruct::isAssignable(int blit)
int TypeStruct::isAssignable()
{
if (!blit)
{
if (sym->hasIdentityAssign)
return TRUE;
// has non-identity opAssign
if (search_function(sym, Id::assign))
return FALSE;
}
int assignable = TRUE;
unsigned offset;
@@ -8518,7 +8591,7 @@ int TypeStruct::isAssignable(int blit)
if (!assignable)
return FALSE;
}
assignable = v->type->isMutable() && v->type->isAssignable(blit);
assignable = v->type->isMutable() && v->type->isAssignable();
offset = v->offset;
//printf(" -> assignable = %d\n", assignable);
}
@@ -8638,6 +8711,11 @@ TypeClass::TypeClass(ClassDeclaration *sym)
this->sym = sym;
}
const char *TypeClass::kind()
{
return "class";
}
char *TypeClass::toChars()
{
if (mod)
@@ -9122,7 +9200,7 @@ int TypeClass::isscope()
int TypeClass::isBaseOf(Type *t, int *poffset)
{
if (t->ty == Tclass)
if (t && t->ty == Tclass)
{ ClassDeclaration *cd;
cd = ((TypeClass *)t)->sym;
@@ -9294,6 +9372,11 @@ TypeTuple::TypeTuple(Type *t1, Type *t2)
arguments->push(new Parameter(0, t2, NULL, NULL));
}
const char *TypeTuple::kind()
{
return "tuple";
}
Type *TypeTuple::syntaxCopy()
{
Parameters *args = Parameter::arraySyntaxCopy(arguments);
@@ -9440,6 +9523,11 @@ TypeSlice::TypeSlice(Type *next, Expression *lwr, Expression *upr)
this->upr = upr;
}
const char *TypeSlice::kind()
{
return "slice";
}
Type *TypeSlice::syntaxCopy()
{
Type *t = new TypeSlice(next->syntaxCopy(), lwr->syntaxCopy(), upr->syntaxCopy());
@@ -9568,6 +9656,11 @@ TypeNull::TypeNull()
{
}
const char *TypeNull::kind()
{
return "null";
}
Type *TypeNull::syntaxCopy()
{
// No semantic analysis done, no need to copy
@@ -9596,10 +9689,23 @@ MATCH TypeNull::implicitConvTo(Type *to)
return MATCHnomatch;
}
int TypeNull::checkBoolean()
{
return TRUE;
}
#if IN_LLVM
void TypeNull::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
#else
void TypeNull::toDecoBuffer(OutBuffer *buf, int flag)
#endif
{
//tvoidptr->toDecoBuffer(buf, flag);
#if IN_LLVM
Type::toDecoBuffer(buf, flag, mangle);
#else
Type::toDecoBuffer(buf, flag);
#endif
}
void TypeNull::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
@@ -9700,6 +9806,13 @@ void Parameter::argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Parameters *argu
{ if (arg->ident)
argbuf.writestring(arg->ident->toChars());
}
else if (arg->type->ty == Tident &&
((TypeIdentifier *)arg->type)->ident->len > 3 &&
strncmp(((TypeIdentifier *)arg->type)->ident->string, "__T", 3) == 0)
{
// print parameter name, instead of undetermined type parameter
argbuf.writestring(arg->ident->toChars());
}
else
arg->type->toCBuffer(&argbuf, arg->ident, hgs);
if (arg->defaultArg)
+63 -5
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2012 by Digital Mars
// Copyright (c) 1999-2013 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -41,6 +41,7 @@ struct Dsymbol;
struct TemplateInstance;
struct CppMangleState;
struct TemplateDeclaration;
struct JsonOut;
enum LINK;
struct TypeBasic;
@@ -191,6 +192,7 @@ struct Type : Object
#define tindex tsize_t // array/ptr index
static Type *tvoidptr; // void*
static Type *tstring; // immutable(char)[]
static Type *tvalist; // va_list alias
#define terror basic[Terror] // for error recovery
#define tnull basic[Tnull] // for null type
@@ -239,6 +241,7 @@ struct Type : Object
static unsigned char impcnvWarn[TMAX][TMAX];
Type(TY ty);
virtual const char *kind();
virtual Type *syntaxCopy();
int equals(Object *o);
int dyncast() { return DYNCAST_TYPE; } // kludge for template.isType()
@@ -263,6 +266,9 @@ struct Type : Object
virtual void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod);
void modToBuffer(OutBuffer *buf);
char *modToChars();
void toJsonProperty(JsonOut *json, const char *);
virtual void toJson(JsonOut *json);
#if CPP_MANGLE
virtual void toCppMangle(OutBuffer *buf, CppMangleState *cms);
#endif
@@ -275,7 +281,7 @@ struct Type : Object
virtual int isunsigned();
virtual int isscope();
virtual int isString();
virtual int isAssignable(int blit = 0);
virtual int isAssignable();
virtual int checkBoolean(); // if can be converted to boolean value
virtual void checkDeprecated(Loc loc, Scope *sc);
int isConst() { return mod & MODconst; }
@@ -412,6 +418,7 @@ struct TypeBasic : Type
unsigned flags;
TypeBasic(TY ty);
const char *kind();
Type *syntaxCopy();
d_uns64 size(Loc loc);
unsigned alignsize();
@@ -447,6 +454,7 @@ struct TypeVector : Type
Type *basetype;
TypeVector(Loc loc, Type *basetype);
const char *kind();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
@@ -455,7 +463,12 @@ struct TypeVector : Type
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
char *toChars();
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
#if IN_LLVM
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
#else
void toDecoBuffer(OutBuffer *buf, int flag);
#endif
void toJson(JsonOut *json);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
#if CPP_MANGLE
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
@@ -489,6 +502,7 @@ struct TypeSArray : TypeArray
Expression *dim;
TypeSArray(Type *t, Expression *dim);
const char *kind();
Type *syntaxCopy();
d_uns64 size(Loc loc);
unsigned alignsize();
@@ -496,6 +510,7 @@ struct TypeSArray : TypeArray
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
int isString();
int isZeroInit(Loc loc);
@@ -530,6 +545,7 @@ struct TypeSArray : TypeArray
struct TypeDArray : TypeArray
{
TypeDArray(Type *t);
const char *kind();
Type *syntaxCopy();
d_uns64 size(Loc loc);
unsigned alignsize();
@@ -537,6 +553,7 @@ struct TypeDArray : TypeArray
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
int isString();
int isZeroInit(Loc loc);
@@ -566,6 +583,7 @@ struct TypeAArray : TypeArray
StructDeclaration *impl; // implementation
TypeAArray(Type *t, Type *index);
const char *kind();
Type *syntaxCopy();
d_uns64 size(Loc loc);
Type *semantic(Loc loc, Scope *sc);
@@ -573,6 +591,7 @@ struct TypeAArray : TypeArray
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *defaultInit(Loc loc);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
@@ -600,10 +619,12 @@ struct TypeAArray : TypeArray
struct TypePointer : TypeNext
{
TypePointer(Type *t);
const char *kind();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
MATCH implicitConvTo(Type *to);
MATCH constConv(Type *to);
int isscalar();
@@ -624,10 +645,12 @@ struct TypePointer : TypeNext
struct TypeReference : TypeNext
{
TypeReference(Type *t);
const char *kind();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *defaultInit(Loc loc);
int isZeroInit(Loc loc);
@@ -678,6 +701,8 @@ struct TypeFunction : TypeNext
int inuse;
TypeFunction(Parameters *parameters, Type *treturn, int varargs, enum LINK linkage, StorageClass stc = 0);
const char *kind();
TypeFunction *copy();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
void purityLevel();
@@ -686,6 +711,7 @@ struct TypeFunction : TypeNext
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
void toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, HdrGenState* hgs, TypeFunction *attrs, TemplateDeclaration *td);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
void attributesToCBuffer(OutBuffer *buf, int mod);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
TypeInfoDeclaration *getTypeInfoDeclaration();
@@ -723,12 +749,14 @@ struct TypeDelegate : TypeNext
// .next is a TypeFunction
TypeDelegate(Type *t);
const char *kind();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
unsigned alignsize();
MATCH implicitConvTo(Type *to);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *defaultInit(Loc loc);
int isZeroInit(Loc loc);
int checkBoolean();
@@ -754,6 +782,7 @@ struct TypeQualified : Type
void syntaxCopyHelper(TypeQualified *t);
void addIdent(Identifier *ident);
void toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs);
void toJson(JsonOut *json);
d_uns64 size(Loc loc);
void resolveHelper(Loc loc, Scope *sc, Dsymbol *s, Dsymbol *scopesym,
Expression **pe, Type **pt, Dsymbol **ps);
@@ -765,10 +794,12 @@ struct TypeIdentifier : TypeQualified
Dsymbol *originalSymbol; // The symbol representing this identifier, before alias resolution
TypeIdentifier(Loc loc, Identifier *ident);
const char *kind();
Type *syntaxCopy();
//char *toChars();
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Dsymbol *toDsymbol(Scope *sc);
Type *semantic(Loc loc, Scope *sc);
@@ -784,10 +815,12 @@ struct TypeInstance : TypeQualified
TemplateInstance *tempinst;
TypeInstance(Loc loc, TemplateInstance *tempinst);
const char *kind();
Type *syntaxCopy();
//char *toChars();
//void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc);
@@ -801,9 +834,11 @@ struct TypeTypeof : TypeQualified
int inuse;
TypeTypeof(Loc loc, Expression *exp);
const char *kind();
Type *syntaxCopy();
Dsymbol *toDsymbol(Scope *sc);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
};
@@ -811,10 +846,12 @@ struct TypeTypeof : TypeQualified
struct TypeReturn : TypeQualified
{
TypeReturn(Loc loc);
const char *kind();
Type *syntaxCopy();
Dsymbol *toDsymbol(Scope *sc);
Type *semantic(Loc loc, Scope *sc);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
};
struct TypeStruct : Type
@@ -822,6 +859,7 @@ struct TypeStruct : Type
StructDeclaration *sym;
TypeStruct(StructDeclaration *sym);
const char *kind();
d_uns64 size(Loc loc);
unsigned alignsize();
char *toChars();
@@ -830,13 +868,14 @@ struct TypeStruct : Type
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
structalign_t alignment();
Expression *defaultInit(Loc loc);
Expression *defaultInitLiteral(Loc loc);
Expression *voidInitLiteral(VarDeclaration *var);
int isZeroInit(Loc loc);
int isAssignable(int blit = 0);
int isAssignable();
int checkBoolean();
int needsDestruction();
bool needsNested();
@@ -870,6 +909,7 @@ struct TypeEnum : Type
EnumDeclaration *sym;
TypeEnum(EnumDeclaration *sym);
const char *kind();
Type *syntaxCopy();
d_uns64 size(Loc loc);
unsigned alignsize();
@@ -878,6 +918,7 @@ struct TypeEnum : Type
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *getProperty(Loc loc, Identifier *ident);
int isintegral();
@@ -888,7 +929,7 @@ struct TypeEnum : Type
int isscalar();
int isunsigned();
int checkBoolean();
int isAssignable(int blit = 0);
int isAssignable();
int needsDestruction();
bool needsNested();
MATCH implicitConvTo(Type *to);
@@ -914,6 +955,7 @@ struct TypeTypedef : Type
TypedefDeclaration *sym;
TypeTypedef(TypedefDeclaration *sym);
const char *kind();
Type *syntaxCopy();
d_uns64 size(Loc loc);
unsigned alignsize();
@@ -922,6 +964,7 @@ struct TypeTypedef : Type
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
structalign_t alignment();
Expression *getProperty(Loc loc, Identifier *ident);
@@ -933,7 +976,7 @@ struct TypeTypedef : Type
int isscalar();
int isunsigned();
int checkBoolean();
int isAssignable(int blit = 0);
int isAssignable();
int needsDestruction();
bool needsNested();
Type *toBasetype();
@@ -966,6 +1009,7 @@ struct TypeClass : Type
ClassDeclaration *sym;
TypeClass(ClassDeclaration *sym);
const char *kind();
d_uns64 size(Loc loc);
char *toChars();
Type *syntaxCopy();
@@ -973,6 +1017,7 @@ struct TypeClass : Type
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
ClassDeclaration *isClassHandle();
int isBaseOf(Type *t, int *poffset);
@@ -1009,12 +1054,18 @@ struct TypeTuple : Type
TypeTuple();
TypeTuple(Type *t1);
TypeTuple(Type *t1, Type *t2);
const char *kind();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
int equals(Object *o);
Type *reliesOnTident(TemplateParameters *tparams = NULL);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
#if IN_LLVM
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
#else
void toDecoBuffer(OutBuffer *buf, int flag);
#endif
void toJson(JsonOut *json);
Expression *getProperty(Loc loc, Identifier *ident);
Expression *defaultInit(Loc loc);
TypeInfoDeclaration *getTypeInfoDeclaration();
@@ -1026,21 +1077,26 @@ struct TypeSlice : TypeNext
Expression *upr;
TypeSlice(Type *next, Expression *lwr, Expression *upr);
const char *kind();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
};
struct TypeNull : Type
{
TypeNull();
const char *kind();
Type *syntaxCopy();
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
MATCH implicitConvTo(Type *to);
int checkBoolean();
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
void toJson(JsonOut *json);
d_uns64 size(Loc loc);
//Expression *getProperty(Loc loc, Identifier *ident);
@@ -1066,6 +1122,7 @@ struct Parameter : Object
Type *isLazyArray();
void toDecoBuffer(OutBuffer *buf, bool mangle);
int dyncast() { return DYNCAST_PARAMETER; } // kludge for template.isType()
void toJson(JsonOut *json);
static Parameters *arraySyntaxCopy(Parameters *args);
static char *argsTypesToChars(Parameters *args, int varargs);
static void argsCppMangle(OutBuffer *buf, CppMangleState *cms, Parameters *arguments, int varargs);
@@ -1089,6 +1146,7 @@ extern int Tptrdiff_t;
int arrayTypeCompatible(Loc loc, Type *t1, Type *t2);
int arrayTypeCompatibleWithoutCasting(Loc loc, Type *t1, Type *t2);
void MODtoBuffer(OutBuffer *buf, unsigned char mod);
char *MODtoChars(unsigned char mod);
int MODimplicitConv(unsigned char modfrom, unsigned char modto);
int MODmethodConv(unsigned char modfrom, unsigned char modto);
int MODmerge(unsigned char mod1, unsigned char mod2);
+9
View File
@@ -465,6 +465,15 @@ Expression *BinExp::op_overload(Scope *sc)
AggregateDeclaration *ad1 = isAggregate(e1->type);
AggregateDeclaration *ad2 = isAggregate(e2->type);
if (op == TOKassign && ad1 == ad2)
{
StructDeclaration *sd = ad1->isStructDeclaration();
if (sd && !sd->hasIdentityAssign)
{ /* This is bitwise struct assignment. */
return NULL;
}
}
Dsymbol *s = NULL;
Dsymbol *s_r = NULL;
-3
View File
@@ -27,9 +27,6 @@
#ifdef IN_GCC
#include "d-gcc-real.h"
/* %% fix? */
extern "C" bool real_isnan (const real_t *);
#endif
static real_t zero; // work around DMC bug for now
+21 -1
View File
@@ -269,6 +269,20 @@ Dsymbols *Parser::parseDeclDefs(int once)
case TOKunittest:
s = parseUnitTest();
if (decldefs && decldefs->dim)
{
Dsymbol *ds = (*decldefs)[decldefs->dim-1];
AttribDeclaration *ad;
while ((ad = ds->isAttribDeclaration()) != NULL)
{
if (ad->decl && ad->decl->dim)
ds = (*ad->decl)[ad->decl->dim-1];
else
break;
}
ds->unittest = (UnitTestDeclaration *)s;
}
break;
case TOKnew:
@@ -2238,7 +2252,11 @@ Objects *Parser::parseTemplateArgument()
break;
}
if (token.value == TOKnot)
error("multiple ! arguments are not allowed");
{
enum TOK tok = peekNext();
if (tok != TOKis && tok != TOKin)
error("multiple ! arguments are not allowed");
}
return tiargs;
}
@@ -2843,6 +2861,7 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, unsigned char *c
addComment(s, comment);
return a;
}
#if 0
/* Look for:
* alias this = identifier;
*/
@@ -2858,6 +2877,7 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, unsigned char *c
addComment(s, comment);
return a;
}
#endif
/* Look for:
* alias identifier = type;
*/
+7 -39
View File
@@ -1,5 +1,5 @@
// Copyright (c) 1999-2010 by Digital Mars
// Copyright (c) 1999-2013 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -9,35 +9,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#if defined (__sun)
#include <alloca.h>
#endif
#if _MSC_VER || __MINGW32__
#include <malloc.h>
#endif
#if IN_GCC
#include "gdc_alloca.h"
#endif
#if _WIN32
#include <windows.h>
#endif
#ifndef _WIN32
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <utime.h>
#endif
#include "port.h"
#include "root.h"
#include "rmem.h"
@@ -181,25 +155,19 @@ void Array::remove(size_t i)
char *Array::toChars()
{
size_t len;
size_t u;
char **buf;
char *str;
char *p;
buf = (char **)malloc(dim * sizeof(char *));
char **buf = (char **)malloc(dim * sizeof(char *));
assert(buf);
len = 2;
for (u = 0; u < dim; u++)
size_t len = 2;
for (size_t u = 0; u < dim; u++)
{
buf[u] = ((Object *)data[u])->toChars();
len += strlen(buf[u]) + 1;
}
str = (char *)mem.malloc(len);
char *str = (char *)mem.malloc(len);
str[0] = '[';
p = str + 1;
for (u = 0; u < dim; u++)
char *p = str + 1;
for (size_t u = 0; u < dim; u++)
{
if (u)
*p++ = ',';
-63
View File
@@ -1,63 +0,0 @@
// Copyright (c) 2009-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
// Put functions in here missing from gnu C
#include "gnuc.h"
int memicmp(const char *s1, const char *s2, int n)
{
int result = 0;
for (int i = 0; i < n; i++)
{ char c1 = s1[i];
char c2 = s2[i];
result = c1 - c2;
if (result)
{
if ('A' <= c1 && c1 <= 'Z')
c1 += 'a' - 'A';
if ('A' <= c2 && c2 <= 'Z')
c2 += 'a' - 'A';
result = c1 - c2;
if (result)
break;
}
}
return result;
}
int stricmp(const char *s1, const char *s2)
{
int result = 0;
for (;;)
{ char c1 = *s1;
char c2 = *s2;
result = c1 - c2;
if (result)
{
if ('A' <= c1 && c1 <= 'Z')
c1 += 'a' - 'A';
if ('A' <= c2 && c2 <= 'Z')
c2 += 'a' - 'A';
result = c1 - c2;
if (result)
break;
}
if (!c1)
break;
s1++;
s2++;
}
return result;
}
-16
View File
@@ -1,16 +0,0 @@
// Copyright (c) 2009-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef _GNUC_H
#define _GNUC_H 1
int memicmp(const char *s1, const char *s2, int n);
int stricmp(const char *s1, const char *s2);
#endif
+62 -15
View File
@@ -116,6 +116,16 @@ char *Port::strupr(char *s)
return ::strupr(s);
}
int Port::memicmp(const char *s1, const char *s2, int n)
{
return ::memicmp(s1, s2, n);
}
int Port::stricmp(const char *s1, const char *s2)
{
return ::stricmp(s1, s2);
}
#endif
#if _MSC_VER
@@ -328,6 +338,16 @@ char *Port::strupr(char *s)
return ::strupr(s);
}
int Port::memicmp(const char *s1, const char *s2, int n)
{
return ::memicmp(s1, s2, n);
}
int Port::stricmp(const char *s1, const char *s2)
{
return ::stricmp(s1, s2);
}
#endif
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __HAIKU__ || __MINGW32__
@@ -524,6 +544,48 @@ char *Port::strupr(char *s)
return t;
}
int Port::memicmp(const char *s1, const char *s2, int n)
{
int result = 0;
for (int i = 0; i < n; i++)
{ char c1 = s1[i];
char c2 = s2[i];
result = c1 - c2;
if (result)
{
result = toupper(c1) - toupper(c2);
if (result)
break;
}
}
return result;
}
int Port::stricmp(const char *s1, const char *s2)
{
int result = 0;
for (;;)
{ char c1 = *s1;
char c2 = *s2;
result = c1 - c2;
if (result)
{
result = toupper(c1) - toupper(c2);
if (result)
break;
}
if (!c1)
break;
s1++;
s2++;
}
return result;
}
#endif
#if __sun
@@ -670,18 +732,3 @@ char *Port::strupr(char *s)
}
#endif
#if IN_LLVM
#if __MINGW32__
longdouble Port::strtold(const char *str, char **pend)
{
return __mingw_strtold(str, pend);
}
#else
longdouble Port::strtold(const char *str, char **pend)
{
return ::strtold(str, pend);
}
#endif
#endif
+3 -3
View File
@@ -61,9 +61,6 @@ struct Port
static longdouble fmodl(longdouble x, longdouble y);
static ulonglong strtoull(const char *p, char **pend, int base);
#if IN_LLVM
static longdouble strtold(const char *str, char **pend);
#endif
static char *ull_to_string(char *buffer, ulonglong ull);
static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
@@ -76,6 +73,9 @@ struct Port
static const wchar_t *wlist_separator();
static char *strupr(char *);
static int memicmp(const char *s1, const char *s2, int n);
static int stricmp(const char *s1, const char *s2);
};
#endif
+1 -1
View File
@@ -5,7 +5,7 @@
// Written by Walter Bright
/*
* This source file is made available for personal use
* only. The license is in /dmd/src/dmd/backendlicense.txt
* only. The license is in backendlicense.txt
* For any other uses, please contact Digital Mars.
*/
+89 -87
View File
@@ -139,19 +139,19 @@ void Object::mark()
/****************************** String ********************************/
String::String(char *str)
String::String(const char *str)
: str(mem.strdup(str))
{
}
String::~String()
{
mem.free(str);
mem.free((void *)str);
}
void String::mark()
{
mem.mark(str);
mem.mark((void *)str);
}
hash_t String::calcHash(const char *str, size_t len)
@@ -218,7 +218,7 @@ int String::compare(Object *obj)
char *String::toChars()
{
return str;
return (char *)str; // toChars() should really be const
}
void String::print()
@@ -229,12 +229,12 @@ void String::print()
/****************************** FileName ********************************/
FileName::FileName(char *str)
FileName::FileName(const char *str)
: String(str)
{
}
char *FileName::combine(const char *path, const char *name)
const char *FileName::combine(const char *path, const char *name)
{ char *f;
size_t pathlen;
size_t namelen;
@@ -431,12 +431,11 @@ int FileName::absolute(const char *name)
* If there isn't one, return NULL.
*/
char *FileName::ext(const char *str)
const char *FileName::ext(const char *str)
{
char *e;
size_t len = strlen(str);
e = (char *)str + len;
const char *e = str + len;
for (;;)
{
switch (*e)
@@ -462,7 +461,7 @@ char *FileName::ext(const char *str)
}
}
char *FileName::ext()
const char *FileName::ext()
{
return ext(str);
}
@@ -471,7 +470,7 @@ char *FileName::ext()
* Return mem.malloc'd filename with extension removed.
*/
char *FileName::removeExt(const char *str)
const char *FileName::removeExt(const char *str)
{
const char *e = ext(str);
if (e)
@@ -488,12 +487,11 @@ char *FileName::removeExt(const char *str)
* Return filename name excluding path (read-only).
*/
char *FileName::name(const char *str)
const char *FileName::name(const char *str)
{
char *e;
size_t len = strlen(str);
e = (char *)str + len;
const char *e = str + len;
for (;;)
{
switch (*e)
@@ -525,7 +523,7 @@ char *FileName::name(const char *str)
}
}
char *FileName::name()
const char *FileName::name()
{
return name(str);
}
@@ -535,10 +533,9 @@ char *FileName::name()
* Path will does not include trailing path separator.
*/
char *FileName::path(const char *str)
const char *FileName::path(const char *str)
{
char *n = name(str);
char *path;
const char *n = name(str);
size_t pathlen;
if (n > str)
@@ -554,7 +551,7 @@ char *FileName::path(const char *str)
#endif
}
pathlen = n - str;
path = (char *)mem.malloc(pathlen + 1);
char *path = (char *)mem.malloc(pathlen + 1);
memcpy(path, str, pathlen);
path[pathlen] = 0;
return path;
@@ -565,20 +562,19 @@ char *FileName::path(const char *str)
*/
const char *FileName::replaceName(const char *path, const char *name)
{ char *f;
char *n;
{
size_t pathlen;
size_t namelen;
if (absolute(name))
return name;
n = FileName::name(path);
const char *n = FileName::name(path);
if (n == path)
return name;
pathlen = n - path;
namelen = strlen(name);
f = (char *)mem.malloc(pathlen + 1 + namelen + 1);
char *f = (char *)mem.malloc(pathlen + 1 + namelen + 1);
memcpy(f, path, pathlen);
#if POSIX
if (path[pathlen - 1] != '/')
@@ -600,48 +596,40 @@ const char *FileName::replaceName(const char *path, const char *name)
}
/***************************
* Free returned value with FileName::free()
*/
FileName *FileName::defaultExt(const char *name, const char *ext)
const char *FileName::defaultExt(const char *name, const char *ext)
{
char *e;
char *s;
size_t len;
size_t extlen;
e = FileName::ext(name);
const char *e = FileName::ext(name);
if (e) // if already has an extension
return new FileName((char *)name);
return mem.strdup(name);
len = strlen(name);
extlen = strlen(ext);
s = (char *)alloca(len + 1 + extlen + 1);
size_t len = strlen(name);
size_t extlen = strlen(ext);
char *s = (char *)mem.malloc(len + 1 + extlen + 1);
memcpy(s,name,len);
s[len] = '.';
memcpy(s + len + 1, ext, extlen + 1);
return new FileName(s);
return s;
}
/***************************
* Free returned value with FileName::free()
*/
FileName *FileName::forceExt(const char *name, const char *ext)
const char *FileName::forceExt(const char *name, const char *ext)
{
char *e;
char *s;
size_t len;
size_t extlen;
e = FileName::ext(name);
const char *e = FileName::ext(name);
if (e) // if already has an extension
{
len = e - name;
extlen = strlen(ext);
size_t len = e - name;
size_t extlen = strlen(ext);
s = (char *)alloca(len + extlen + 1);
char *s = (char *)mem.malloc(len + extlen + 1);
memcpy(s,name,len);
memcpy(s + len, ext, extlen + 1);
return new FileName(s);
return s;
}
else
return defaultExt(name, ext); // doesn't have one
@@ -652,20 +640,18 @@ FileName *FileName::forceExt(const char *name, const char *ext)
*/
int FileName::equalsExt(const char *ext)
{ const char *e;
{
return equalsExt(str, ext);
}
e = FileName::ext();
int FileName::equalsExt(const char *name, const char *ext)
{
const char *e = FileName::ext(name);
if (!e && !ext)
return 1;
if (!e || !ext)
return 0;
#if POSIX
return strcmp(e,ext) == 0;
#elif _WIN32
return stricmp(e,ext) == 0;
#else
assert(0);
#endif
return FileName::compare(e, ext) == 0;
}
/*************************************
@@ -694,24 +680,24 @@ void FileName::CopyTo(FileName *to)
* cwd if !=0, search current directory before searching path
*/
char *FileName::searchPath(Strings *path, const char *name, int cwd)
const char *FileName::searchPath(Strings *path, const char *name, int cwd)
{
if (absolute(name))
{
return exists(name) ? (char *)name : NULL;
return exists(name) ? name : NULL;
}
if (cwd)
{
if (exists(name))
return (char *)name;
return name;
}
if (path)
{ unsigned i;
{
for (i = 0; i < path->dim; i++)
for (size_t i = 0; i < path->dim; i++)
{
char *p = path->tdata()[i];
char *n = combine(p, name);
const char *p = path->tdata()[i];
const char *n = combine(p, name);
if (exists(n))
return n;
@@ -734,7 +720,7 @@ char *FileName::searchPath(Strings *path, const char *name, int cwd)
* !=NULL mem.malloc'd file name
*/
char *FileName::safeSearchPath(Strings *path, const char *name)
const char *FileName::safeSearchPath(Strings *path, const char *name)
{
#if _WIN32
/* Disallow % / \ : and .. in name characters
@@ -763,15 +749,14 @@ char *FileName::safeSearchPath(Strings *path, const char *name)
}
if (path)
{ unsigned i;
{
/* Each path is converted to a cannonical name and then a check is done to see
* that the searched name is really a child one of the the paths searched.
*/
for (i = 0; i < path->dim; i++)
for (size_t i = 0; i < path->dim; i++)
{
char *cname = NULL;
char *cpath = canonicalName(path->tdata()[i]);
const char *cname = NULL;
const char *cpath = canonicalName(path->tdata()[i]);
//printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n",
// name, (char *)path->data[i], cpath);
if (cpath == NULL)
@@ -786,16 +771,16 @@ char *FileName::safeSearchPath(Strings *path, const char *name)
// exists and name is *really* a "child" of path
if (exists(cname) && strncmp(cpath, cname, strlen(cpath)) == 0)
{
free(cpath);
char *p = mem.strdup(cname);
free(cname);
::free((void *)cpath);
const char *p = mem.strdup(cname);
::free((void *)cname);
return p;
}
cont:
if (cpath)
free(cpath);
::free((void *)cpath);
if (cname)
free(cname);
::free((void *)cname);
}
}
return NULL;
@@ -839,18 +824,18 @@ void FileName::ensurePathExists(const char *path)
{
if (!exists(path))
{
char *p = FileName::path(path);
const char *p = FileName::path(path);
if (*p)
{
#if _WIN32
size_t len = strlen(path);
if (len > 2 && p[-1] == ':' && path + 2 == p)
{ mem.free(p);
{ mem.free((void *)p);
return;
}
#endif
ensurePathExists(p);
mem.free(p);
mem.free((void *)p);
}
#if _WIN32
if (path[strlen(path) - 1] != '\\')
@@ -878,12 +863,20 @@ void FileName::ensurePathExists(const char *path)
}
}
void FileName::ensurePathToNameExists(const char *name)
{
const char *pt = path(name);
if (*pt)
ensurePathExists(pt);
free(pt);
}
/******************************************
* Return canonical version of name in a malloc'd buffer.
* This code is high risk.
*/
char *FileName::canonicalName(const char *name)
const char *FileName::canonicalName(const char *name)
{
#if linux
// Lovely glibc extension to do it for us
@@ -922,7 +915,7 @@ char *FileName::canonicalName(const char *name)
result = GetFullPathName(name, result, buf, NULL);
if (result == 0)
{
free(buf);
::free(buf);
return NULL;
}
return buf;
@@ -934,19 +927,31 @@ char *FileName::canonicalName(const char *name)
#endif
}
/********************************
* Free memory allocated by FileName routines
*/
void FileName::free(const char *str)
{
if (str)
{ assert(str[0] != 0xAB);
memset((void *)str, 0xAB, strlen(str) + 1); // stomp
}
mem.free((void *)str);
}
/****************************** File ********************************/
File::File(FileName *n)
File::File(const FileName *n)
{
ref = 0;
buffer = NULL;
len = 0;
touchtime = NULL;
name = n;
name = (FileName *)n;
}
File::File(char *n)
File::File(const char *n)
{
ref = 0;
buffer = NULL;
@@ -1372,13 +1377,10 @@ Files *File::match(FileName *n)
#elif _WIN32
HANDLE h;
WIN32_FIND_DATAA fileinfo;
Files *a;
char *c;
char *name;
a = new Files();
c = n->toChars();
name = n->name();
Files *a = new Files();
const char *c = n->toChars();
const char *name = n->name();
h = FindFirstFileA(c,&fileinfo);
if (h != INVALID_HANDLE_VALUE)
{
+23 -18
View File
@@ -76,9 +76,9 @@ struct Object
struct String : Object
{
char *str; // the string itself
const char *str; // the string itself
String(char *str);
String(const char *str);
~String();
static hash_t calcHash(const char *str, size_t len);
@@ -94,33 +94,38 @@ struct String : Object
struct FileName : String
{
FileName(char *str);
FileName(const char *str);
hash_t hashCode();
int equals(Object *obj);
static int equals(const char *name1, const char *name2);
int compare(Object *obj);
static int compare(const char *name1, const char *name2);
static int absolute(const char *name);
static char *ext(const char *);
char *ext();
static char *removeExt(const char *str);
static char *name(const char *);
char *name();
static char *path(const char *);
static const char *ext(const char *);
const char *ext();
static const char *removeExt(const char *str);
static const char *name(const char *);
const char *name();
static const char *path(const char *);
static const char *replaceName(const char *path, const char *name);
static char *combine(const char *path, const char *name);
static const char *combine(const char *path, const char *name);
static Strings *splitPath(const char *path);
static FileName *defaultExt(const char *name, const char *ext);
static FileName *forceExt(const char *name, const char *ext);
static const char *defaultExt(const char *name, const char *ext);
static const char *forceExt(const char *name, const char *ext);
static int equalsExt(const char *name, const char *ext);
int equalsExt(const char *ext);
void CopyTo(FileName *to);
static char *searchPath(Strings *path, const char *name, int cwd);
static char *safeSearchPath(Strings *path, const char *name);
static const char *searchPath(Strings *path, const char *name, int cwd);
static const char *safeSearchPath(Strings *path, const char *name);
static int exists(const char *name);
static void ensurePathExists(const char *path);
static char *canonicalName(const char *name);
static void ensurePathToNameExists(const char *name);
static const char *canonicalName(const char *name);
static void free(const char *str);
};
struct File : Object
@@ -132,8 +137,8 @@ struct File : Object
FileName *name; // name of our file
File(char *);
File(FileName *);
File(const char *);
File(const FileName *);
~File();
void mark();
@@ -271,7 +276,7 @@ struct OutBuffer : Object
char *extractString();
};
struct Array : Object
struct Array
{
size_t dim;
void **data;
+1 -1
View File
@@ -1,5 +1,5 @@
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2013 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
+1 -1
View File
@@ -131,7 +131,7 @@ Scope::Scope(Scope *enclosing)
this->parameterSpecialization = enclosing->parameterSpecialization;
this->ignoreTemplates = enclosing->ignoreTemplates;
this->callSuper = enclosing->callSuper;
this->flags = (enclosing->flags & SCOPEcontract);
this->flags = (enclosing->flags & (SCOPEcontract | SCOPEdebug));
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = enclosing->docbuf;
-1
View File
@@ -25,7 +25,6 @@ struct LabelStatement;
struct ForeachStatement;
struct ClassDeclaration;
struct AggregateDeclaration;
struct AnonymousAggregateDeclaration;
struct FuncDeclaration;
struct DocComment;
struct TemplateInstance;
+47 -78
View File
@@ -31,8 +31,6 @@
#include "import.h"
#if IN_LLVM
// From pragma.cpp
bool matchPragma(Identifier* needle, Identifier* ident, Identifier* oldIdent);
#if defined(_MSC_VER)
#include <windows.h>
#else
@@ -923,7 +921,8 @@ void UnrolledLoopStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->level++;
for (size_t i = 0; i < statements->dim; i++)
{ Statement *s;
{
Statement *s;
s = (*statements)[i];
if (s)
@@ -1131,46 +1130,20 @@ bool WhileStatement::hasContinue()
bool WhileStatement::usesEH()
{
assert(0);
return body ? body->usesEH() : 0;
assert(global.errors);
return 0;
}
int WhileStatement::blockExit(bool mustNotThrow)
{
assert(0);
//printf("WhileStatement::blockExit(%p)\n", this);
int result = BEnone;
if (condition->canThrow(mustNotThrow))
result |= BEthrow;
if (condition->isBool(TRUE))
{
if (body)
{ result |= body->blockExit(mustNotThrow);
if (result & BEbreak)
result |= BEfallthru;
}
}
else if (condition->isBool(FALSE))
{
result |= BEfallthru;
}
else
{
if (body)
result |= body->blockExit(mustNotThrow);
result |= BEfallthru;
}
result &= ~(BEbreak | BEcontinue);
return result;
assert(global.errors);
return BEfallthru;
}
int WhileStatement::comeFrom()
{
assert(0);
if (body)
return body->comeFrom();
assert(global.errors);
return FALSE;
}
@@ -1847,7 +1820,9 @@ Lagain:
{
/* Reference to immutable data should be marked as const
*/
if (!tn->isMutable())
if (aggr->checkModifiable(sc, 1) == 2)
var->storage_class |= STCctorinit;
else if (!tn->isMutable())
var->storage_class |= STCconst;
Type *t = tab->nextOf();
@@ -1982,18 +1957,12 @@ Lagain:
error("only one or two arguments for associative array foreach");
break;
}
#if SARRAYVALUE
/* This only works if Key or Value is a static array.
*/
tab = taa->getImpl()->type;
goto Lagain;
#else
if (op == TOKforeach_reverse)
{
error("no reverse iteration on associative arrays");
}
goto Lapply;
#endif
case Tclass:
case Tstruct:
#if DMDV2
@@ -2757,33 +2726,20 @@ bool ForeachRangeStatement::hasContinue()
bool ForeachRangeStatement::usesEH()
{
assert(0);
assert(global.errors);
return body->usesEH();
}
int ForeachRangeStatement::blockExit(bool mustNotThrow)
{
assert(0);
int result = BEfallthru;
if (lwr && lwr->canThrow(mustNotThrow))
result |= BEthrow;
else if (upr && upr->canThrow(mustNotThrow))
result |= BEthrow;
if (body)
{
result |= body->blockExit(mustNotThrow) & ~(BEbreak | BEcontinue);
}
return result;
assert(global.errors);
return BEfallthru;
}
int ForeachRangeStatement::comeFrom()
{
assert(0);
if (body)
return body->comeFrom();
assert(global.errors);
return FALSE;
}
@@ -2952,7 +2908,8 @@ void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
if (arg->type)
arg->type->toCBuffer(buf, arg->ident, hgs);
else
{ buf->writestring("auto ");
{
buf->writestring("auto ");
buf->writestring(arg->ident->toChars());
}
buf->writestring(" = ");
@@ -2966,7 +2923,8 @@ void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
if (!ifbody->isScopeStatement())
buf->level--;
if (elsebody)
{ buf->writestring("else");
{
buf->writestring("else");
buf->writenl();
if (!elsebody->isScopeStatement())
buf->level++;
@@ -3170,8 +3128,8 @@ Statement *PragmaStatement::semantic(Scope *sc)
#endif
}
#if IN_LLVM
// FIXME Move to pragma.cpp
else if (matchPragma(ident, Id::LDC_allow_inline, Id::allow_inline))
// LDC
else if (ident == Id::allow_inline)
{
sc->func->allowInlining = true;
}
@@ -3343,7 +3301,8 @@ Statement *SwitchStatement::semantic(Scope *sc)
}
else
{ condition = condition->integralPromotions(sc);
condition->checkIntegral();
if (!condition->type->isintegral())
error("'%s' must be of integral or string type, it is a %s", condition->toChars(), condition->type->toChars());
}
condition = condition->optimize(WANTvalue);
@@ -3392,14 +3351,18 @@ Statement *SwitchStatement::semantic(Scope *sc)
#if DMDV2
if (isFinal)
{ Type *t = condition->type;
while (t->ty == Ttypedef)
while (t && t->ty == Ttypedef)
{ // Don't use toBasetype() because that will skip past enums
t = ((TypeTypedef *)t)->sym->basetype;
}
if (te)
Dsymbol *ds;
EnumDeclaration *ed = NULL;
if (t && ((ds = t->toDsymbol(sc)) != NULL))
ed = ds->isEnumDeclaration(); // typedef'ed enum
if (!ed && te && ((ds = te->toDsymbol(sc)) != NULL))
ed = ds->isEnumDeclaration();
if (ed)
{
EnumDeclaration *ed = te->toDsymbol(sc)->isEnumDeclaration();
assert(ed);
size_t dim = ed->members->dim;
for (size_t i = 0; i < dim; i++)
{
@@ -3442,8 +3405,10 @@ Statement *SwitchStatement::semantic(Scope *sc)
a->reserve(2);
sc->sw->sdefault = new DefaultStatement(loc, s);
a->push(sc->sw->sdefault);
a->push(body);
if (body->blockExit(FALSE) & BEfallthru)
a->push(new BreakStatement(0, NULL));
a->push(sc->sw->sdefault);
cs = new CompoundStatement(loc, a);
body = cs;
}
@@ -3490,7 +3455,8 @@ void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
if (body)
{
if (!body->isScopeStatement())
{ buf->writebyte('{');
{
buf->writebyte('{');
buf->writenl();
buf->level++;
body->toCBuffer(buf, hgs);
@@ -3567,7 +3533,7 @@ Statement *CaseStatement::semantic(Scope *sc)
if (exp->op != TOKstring && exp->op != TOKint64 && exp->op != TOKerror)
{
error("case must be a string or an integral constant, not %s", exp->toChars());
exp = new IntegerExp(0);
exp = new ErrorExp();
}
L1:
@@ -4073,7 +4039,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
}
else
{
if (tf->isref)
if (tf->isref && (fd->storage_class & STCauto))
{ /* Determine "refness" of function return:
* if it's an lvalue, return by ref, else return by value
*/
@@ -4086,11 +4052,11 @@ Statement *ReturnStatement::semantic(Scope *sc)
unsigned errors = global.startGagging();
exp->checkEscapeRef();
if (global.endGagging(errors))
{ tf->isref = FALSE; // return by value
}
tf->isref = FALSE; // return by value
}
else
tf->isref = FALSE; // return by value
fd->storage_class &= ~STCauto;
}
tf->next = exp->type;
//fd->type = tf->semantic(loc, sc); // Removed with 6902
@@ -4786,7 +4752,7 @@ Statement *WithStatement::semantic(Scope *sc)
sym->parent = sc->scopesym;
}
else
{ error("with expressions must be class objects, not '%s'", exp->type->toChars());
{ error("with expressions must be aggregate types, not '%s'", exp->type->toChars());
return NULL;
}
}
@@ -5269,9 +5235,10 @@ Statement *ThrowStatement::semantic(Scope *sc)
int ThrowStatement::blockExit(bool mustNotThrow)
{
if (mustNotThrow)
Type *t = exp->type->toBasetype();
if (mustNotThrow && t->ty != Terror)
{
ClassDeclaration *cd = exp->type->toBasetype()->isClassHandle();
ClassDeclaration *cd = t->isClassHandle();
assert(cd);
// Bugzilla 8675
@@ -5649,6 +5616,7 @@ void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("asm { ");
Token *t = tokens;
buf->level++;
while (t)
{
buf->writestring(t->toChars());
@@ -5669,6 +5637,7 @@ void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
}
t = t->next;
}
buf->level--;
buf->writestring("; }");
buf->writenl();
}
+1 -1
View File
@@ -673,7 +673,7 @@ struct SwitchErrorStatement : Statement
struct ReturnStatement : Statement
{
Expression *exp;
int implicit0;
bool implicit0; // this is an implicit "return 0;"
ReturnStatement(Loc loc, Expression *exp);
Statement *syntaxCopy();
-1
View File
@@ -3,7 +3,6 @@
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// http://www.dsource.org/projects/dmd/browser/trunk/src/staticassert.c
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
+1 -5
View File
@@ -441,11 +441,7 @@ void StructDeclaration::semantic(Scope *sc)
parent = sc->parent;
type = type->semantic(loc, sc);
#if STRUCTTHISREF
handle = type;
#else
handle = type->pointerTo();
#endif
protection = sc->protection;
alignment = sc->structalign;
storage_class |= sc->stc;
@@ -743,7 +739,7 @@ void StructDeclaration::finalizeSize(Scope *sc)
void StructDeclaration::makeNested()
{
if (!isnested && sizeok != SIZEOKdone)
if (!isnested && sizeok != SIZEOKdone && !isUnionDeclaration())
{
// If nested struct, add in hidden 'this' pointer to outer scope
if (!(storage_class & STCstatic))
+191 -125
View File
@@ -699,7 +699,7 @@ void TemplateDeclaration::makeParamNamesVisibleInConstraint(Scope *paramscope, E
if (!paramscope->insert(v))
error("parameter %s.%s is already defined", toChars(), v->toChars());
else
v->parent = this;
v->parent = fd;
}
}
}
@@ -1350,6 +1350,15 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
if (m < match)
match = m;
/* Remove top const for dynamic array types and pointer types
*/
if ((tt->ty == Tarray || tt->ty == Tpointer) &&
!tt->isMutable() &&
(!(fparam->storageClass & STCref) ||
(fparam->storageClass & STCauto) && !farg->isLvalue()))
{
tt = tt->mutableOf();
}
t->objects[i] = tt;
}
declareParameter(paramscope, tp, t);
@@ -1585,21 +1594,7 @@ Lretry:
if (m && (fparam->storageClass & (STCref | STCauto)) == STCref)
{ if (!farg->isLvalue())
{
if (farg->op == TOKstructliteral)
m = MATCHconvert;
else if (farg->op == TOKcall)
{
CallExp *ce = (CallExp *)farg;
if (ce->e1->op == TOKdotvar &&
((DotVarExp *)ce->e1)->var->isCtorDeclaration())
{
m = MATCHconvert;
}
else
goto Lnomatch;
}
else
goto Lnomatch;
goto Lnomatch;
}
}
if (m && (fparam->storageClass & STCout))
@@ -2253,22 +2248,19 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
/* As Bugzilla 3682 shows, a template instance can be matched while instantiating
* that same template. Thus, the function type can be incomplete. Complete it.
*
* Bugzilla 9208: For auto function, completion should be deferred to the end of
* its semantic3. Should not complete it in here.
*/
{ TypeFunction *tf = (TypeFunction *)fd_best->type;
assert(tf->ty == Tfunction);
if (tf->next)
if (tf->next && !fd_best->inferRetType)
{
fd_best->type = tf->semantic(loc, sc);
}
}
if (fd_best->scope)
{
TemplateInstance *spec = fd_best->isSpeculative();
int olderrs = global.errors;
fd_best->semantic3(fd_best->scope);
// Update the template instantiation with the number
// of errors which occured.
if (spec && global.errors != olderrs)
spec->errors = global.errors - olderrs;
}
fd_best->functionSemantic();
return fd_best;
@@ -2448,9 +2440,11 @@ char *TemplateDeclaration::toChars()
}
buf.writeByte(')');
if (onemember && onemember->toAlias())
{
FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration();
if (onemember)
{ /* Bugzilla 9406:
* onemember->toAlias() might run semantic, so should not call it in stringizing
*/
FuncDeclaration *fd = onemember->isFuncDeclaration();
if (fd && fd->type)
{
TypeFunction *tf = (TypeFunction *)fd->type;
@@ -3983,6 +3977,45 @@ Lnomatch:
return 0;
}
/* Bugzilla 6538: In template constraint, each function parameters, 'this',
* and 'super' is *pseudo* symbol. If it is passed to other template through
* alias/tuple parameter, it will cause an error. Because such symbol
* does not have the actual entity yet.
*
* Example:
* template Sym(alias A) { enum Sym = true; }
* struct S {
* void foo() if (Sym!(this)) {} // Sym!(this) always make an error,
* } // because Sym template cannot
* void main() { S s; s.foo(); } // access to the valid 'this' symbol.
*/
bool isPseudoDsymbol(Object *o)
{
Dsymbol *s = isDsymbol(o);
Expression *e = isExpression(o);
if (e && e->op == TOKvar) s = ((VarExp *)e)->var->isVarDeclaration();
if (e && e->op == TOKthis) s = ((ThisExp *)e)->var->isThisDeclaration();
if (e && e->op == TOKsuper) s = ((SuperExp *)e)->var->isThisDeclaration();
if (s && s->parent)
{
s = s->toAlias();
VarDeclaration *v = s->isVarDeclaration();
TupleDeclaration *t = s->isTupleDeclaration();
if (v || t)
{
FuncDeclaration *fd = s->parent->isFuncDeclaration();
if (fd && fd->parent && fd->parent->isTemplateDeclaration())
{
const char *str = (e && e->op == TOKsuper) ? "super" : s->toChars();
::error(s->loc, "cannot take a not yet instantiated symbol '%s' inside template constraint", str);
return true;
}
}
}
return false;
}
MATCH TemplateAliasParameter::matchArg(Scope *sc, Objects *tiargs,
size_t i, TemplateParameters *parameters, Objects *dedtypes,
Declaration **psparam)
@@ -4678,7 +4711,10 @@ Dsymbol *TemplateInstance::syntaxCopy(Dsymbol *s)
ti->tiargs = arraySyntaxCopy(tiargs);
ScopeDsymbol::syntaxCopy(ti);
if (inst)
tempdecl->ScopeDsymbol::syntaxCopy(ti);
else
ScopeDsymbol::syntaxCopy(ti);
return ti;
}
@@ -5020,8 +5056,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
a = scx->scopesym->members;
}
else
{ //Module *m = sc->module->importedFrom;
Module *m = tempdecl->scope->module->importedFrom;
{
Module *m = (isnested ? sc : tempdecl->scope)->module->importedFrom;
//printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
a = m->members;
if (m->semanticRun >= 3)
@@ -5278,70 +5314,50 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
//printf("type %s\n", ta->toChars());
// It might really be an Expression or an Alias
ta->resolve(loc, sc, &ea, &ta, &sa);
if (ea)
{
ea = ea->semantic(sc);
//printf("-> ea = %s %s\n", Token::toChars(ea->op), ea->toChars());
/* This test is to skip substituting a const var with
* its initializer. The problem is the initializer won't
* match with an 'alias' parameter. Instead, do the
* const substitution in TemplateValueParameter::matchArg().
*/
if (flags & 1) // only used by __traits, must not interpret the args
ea = ea->optimize(WANTvalue);
else if (ea->op != TOKvar)
ea = ea->ctfeInterpret();
(*tiargs)[j] = ea;
}
else if (sa)
{
Ldsym:
(*tiargs)[j] = sa;
TupleDeclaration *d = sa->toAlias()->isTupleDeclaration();
if (d)
{
size_t dim = d->objects->dim;
tiargs->remove(j);
tiargs->insert(j, d->objects);
j--;
}
}
else if (ta)
{
Ltype:
if (ta->ty == Ttuple)
{ // Expand tuple
TypeTuple *tt = (TypeTuple *)ta;
size_t dim = tt->arguments->dim;
tiargs->remove(j);
if (dim)
{ tiargs->reserve(dim);
for (size_t i = 0; i < dim; i++)
{ Parameter *arg = (*tt->arguments)[i];
if (flags & 2 && arg->ident)
tiargs->insert(j + i, arg);
else
tiargs->insert(j + i, arg->type);
}
}
j--;
}
else
(*tiargs)[j] = ta;
}
else
if (ea) goto Lexpr;
if (sa) goto Ldsym;
if (ta == NULL)
{
assert(global.errors);
(*tiargs)[j] = Type::terror;
ta = Type::terror;
}
Ltype:
if (ta->ty == Ttuple)
{ // Expand tuple
TypeTuple *tt = (TypeTuple *)ta;
size_t dim = tt->arguments->dim;
tiargs->remove(j);
if (dim)
{ tiargs->reserve(dim);
for (size_t i = 0; i < dim; i++)
{ Parameter *arg = (*tt->arguments)[i];
if (flags & 2 && arg->ident)
tiargs->insert(j + i, arg);
else
tiargs->insert(j + i, arg->type);
}
}
j--;
continue;
}
(*tiargs)[j] = ta;
}
else if (ea)
{
Lexpr:
//printf("+[%d] ea = %s %s\n", j, Token::toChars(ea->op), ea->toChars());
ea = ea->semantic(sc);
if (flags & 1) // only used by __traits, must not interpret the args
ea = ea->optimize(WANTvalue);
else if (ea->op != TOKvar && ea->op != TOKtuple &&
else if (ea->op == TOKvar)
{ /* This test is to skip substituting a const var with
* its initializer. The problem is the initializer won't
* match with an 'alias' parameter. Instead, do the
* const substitution in TemplateValueParameter::matchArg().
*/
}
else if (ea->op != TOKtuple &&
ea->op != TOKimport && ea->op != TOKtype &&
ea->op != TOKfunction && ea->op != TOKerror &&
ea->op != TOKthis && ea->op != TOKsuper)
@@ -5352,7 +5368,25 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
ea = new ErrorExp();
}
//printf("-[%d] ea = %s %s\n", j, Token::toChars(ea->op), ea->toChars());
if (!flags && isPseudoDsymbol(ea))
{ (*tiargs)[j] = new ErrorExp();
continue;
}
if (ea->op == TOKtuple)
{ // Expand tuple
TupleExp *te = (TupleExp *)ea;
size_t dim = te->exps->dim;
tiargs->remove(j);
if (dim)
{ tiargs->reserve(dim);
for (size_t i = 0; i < dim; i++)
tiargs->insert(j + i, (*te->exps)[i]);
}
j--;
continue;
}
(*tiargs)[j] = ea;
if (ea->op == TOKtype)
{ ta = ea->type;
goto Ltype;
@@ -5375,9 +5409,8 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
else if (fe->td)
{ /* If template argument is a template lambda,
* get template declaration itself. */
ea = NULL;
(*tiargs)[j] = sa = fe->td;
goto Lsa;
sa = fe->td;
goto Ldsym;
}
}
if (ea->op == TOKdotvar)
@@ -5394,25 +5427,31 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
sa = ((DotTemplateExp *)ea)->td;
goto Ldsym;
}
if (ea->op == TOKtuple)
{ // Expand tuple
TupleExp *te = (TupleExp *)ea;
size_t dim = te->exps->dim;
tiargs->remove(j);
if (dim)
{ tiargs->reserve(dim);
for (size_t i = 0; i < dim; i++)
tiargs->insert(j + i, (*te->exps)[i]);
}
j--;
}
}
else if (sa)
{
Lsa:
Ldsym:
//printf("dsym %s %s\n", sa->kind(), sa->toChars());
if (!flags && isPseudoDsymbol(sa))
{ (*tiargs)[j] = new ErrorExp();
continue;
}
TupleDeclaration *d = sa->toAlias()->isTupleDeclaration();
if (d)
{ // Expand tuple
size_t dim = d->objects->dim;
tiargs->remove(j);
tiargs->insert(j, d->objects);
j--;
continue;
}
(*tiargs)[j] = sa;
TemplateDeclaration *td = sa->isTemplateDeclaration();
if (td && !td->semanticRun && td->literal)
{
td->semantic(sc);
}
}
else if (isParameter(o))
{
@@ -6002,7 +6041,7 @@ int TemplateInstance::needsTypeInference(Scope *sc)
*/
FuncDeclaration *fd;
if (!td->onemember ||
(fd = td->onemember->toAlias()->isFuncDeclaration()) == NULL ||
(fd = td->onemember/*->toAlias()*/->isFuncDeclaration()) == NULL ||
fd->type->ty != Tfunction)
{
/* Not a template function, therefore type inference is not possible.
@@ -6516,30 +6555,25 @@ void TemplateMixin::semantic(Scope *sc)
{
if (!td->semanticRun)
{
if (td->scope)
td->semantic(td->scope);
/* Cannot handle forward references if mixin is a struct member,
* because addField must happen during struct's semantic, not
* during the mixin semantic.
* runDeferred will re-run mixin's semantic outside of the struct's
* semantic.
*/
semanticRun = PASSinit;
AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
if (ad)
ad->sizeok = SIZEOKfwd;
else
{
/* Cannot handle forward references if mixin is a struct member,
* because addField must happen during struct's semantic, not
* during the mixin semantic.
* runDeferred will re-run mixin's semantic outside of the struct's
* semantic.
*/
semanticRun = PASSinit;
AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
if (ad)
ad->sizeok = SIZEOKfwd;
else
{
// Forward reference
//printf("forward reference - deferring\n");
scope = scx ? scx : new Scope(*sc);
scope->setNoFree();
scope->module->addDeferredSemantic(this);
}
return;
// Forward reference
//printf("forward reference - deferring\n");
scope = scx ? scx : new Scope(*sc);
scope->setNoFree();
scope->module->addDeferredSemantic(this);
}
return;
}
}
@@ -6658,6 +6692,8 @@ void TemplateMixin::semantic(Scope *sc)
sc2 = argscope->push(this);
sc2->offset = sc->offset;
size_t deferred_dim = Module::deferred.dim;
static int nest;
//printf("%d\n", nest);
if (++nest > 500)
@@ -6677,6 +6713,36 @@ void TemplateMixin::semantic(Scope *sc)
sc->offset = sc2->offset;
if (!sc->func && Module::deferred.dim > deferred_dim)
{
sc2->pop();
argscope->pop();
scy->pop();
//printf("deferring mixin %s, deferred.dim += %d\n", toChars(), Module::deferred.dim - deferred_dim);
//printf("\t[");
//for (size_t u = 0; u < Module::deferred.dim; u++) printf("%s%s", Module::deferred[u]->toChars(), u == Module::deferred.dim-1?"":", ");
//printf("]\n");
semanticRun = PASSinit;
AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
if (ad)
{
/* Forward reference of base class should not make derived class SIZEfwd.
*/
//printf("\tad = %s, sizeok = %d\n", ad->toChars(), ad->sizeok);
//ad->sizeok = SIZEOKfwd;
}
else
{
// Forward reference
//printf("forward reference - deferring\n");
scope = scx ? scx : new Scope(*sc);
scope->setNoFree();
scope->module->addDeferredSemantic(this);
}
return;
}
/* The problem is when to parse the initializer for a variable.
* Perhaps VarDeclaration::semantic() should do it like it does
* for initializers inside a function.
+3 -2
View File
@@ -89,7 +89,7 @@ struct TemplateDeclaration : ScopeDsymbol
char *toChars();
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toJson(JsonOut *json);
// void toDocBuffer(OutBuffer *buf);
MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, Expressions *fargs, int flag);
@@ -328,7 +328,7 @@ struct TemplateInstance : ScopeDsymbol
int oneMember(Dsymbol **ps, Identifier *ident);
int needsTypeInference(Scope *sc);
char *toChars();
char *mangle();
char *mangle(bool isv = false);
void printInstantiationTrace();
#if IN_DMD
@@ -378,6 +378,7 @@ struct TemplateMixin : TemplateInstance
char *toChars();
char *mangle();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJson(JsonOut *json);
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
+3 -2
View File
@@ -267,9 +267,10 @@ Expression *TraitsExp::semantic(Scope *sc)
{
if (FuncDeclaration *fd = s->isFuncDeclaration()) // Bugzilla 8943
s = fd->toAliasFunc();
s = s->toParent();
if (!s->isImport()) // Bugzilla 8922
s = s->toParent();
}
if (!s)
if (!s || s->isImport())
{
error("argument %s has no parent", o->toChars());
goto Lfalse;
-1
View File
@@ -1,4 +1,3 @@
// utf.c
// Copyright (c) 2003-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
-1
View File
@@ -1,5 +1,4 @@
// Compiler implementation of the D programming language
// utf.h
// Copyright (c) 2003-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
+77 -29
View File
@@ -51,9 +51,10 @@
#include <windows.h>
#endif
// stricmp
#if __GNUC__ && !_WIN32
#include "gnuc.h"
#if _WIN32
#define strcasecmp(s1, s2) _stricmp(s1, s2)
#else
#define strcasecmp(s1, s2) strcmp(s1, s2)
#endif
// Needs Type already declared.
@@ -166,7 +167,7 @@ int main(int argc, char** argv)
llvm::sys::PrintStackTraceOnErrorSignal();
Strings files;
char *p, *ext;
const char *p, *ext;
Module *m;
int status = EXIT_SUCCESS;
@@ -792,8 +793,8 @@ int main(int argc, char** argv)
modules.reserve(files.dim);
for (unsigned i = 0; i < files.dim; i++)
{ Identifier *id;
char *ext;
char *name;
const char *ext;
const char *name;
p = static_cast<char *>(files.data[i]);
@@ -805,9 +806,9 @@ int main(int argc, char** argv)
if (strcmp(ext, global.obj_ext) == 0 ||
strcmp(ext, global.bc_ext) == 0)
#else
if (stricmp(ext, global.obj_ext) == 0 ||
stricmp(ext, global.obj_ext_alt) == 0 ||
stricmp(ext, global.bc_ext) == 0)
if (strcasecmp(ext, global.obj_ext) == 0 ||
strcasecmp(ext, global.obj_ext_alt) == 0 ||
strcasecmp(ext, global.bc_ext) == 0)
#endif
{
global.params.objfiles->push(static_cast<char *>(files.data[i]));
@@ -819,7 +820,7 @@ int main(int argc, char** argv)
#elif __MINGW32__
if (stricmp(ext, "a") == 0)
#else
if (stricmp(ext, "lib") == 0)
if (strcasecmp(ext, "lib") == 0)
#endif
{
global.params.libfiles->push(static_cast<char *>(files.data[i]));
@@ -840,41 +841,40 @@ int main(int argc, char** argv)
}
#if !POSIX
if (stricmp(ext, "res") == 0)
if (strcasecmp(ext, "res") == 0)
{
global.params.resfile = static_cast<char *>(files.data[i]);
continue;
}
if (stricmp(ext, "def") == 0)
if (strcasecmp(ext, "def") == 0)
{
global.params.deffile = static_cast<char *>(files.data[i]);
continue;
}
if (stricmp(ext, "exe") == 0)
if (strcasecmp(ext, "exe") == 0)
{
global.params.exefile = static_cast<char *>(files.data[i]);
continue;
}
#endif
if (stricmp(ext, global.mars_ext) == 0 ||
stricmp(ext, global.hdr_ext) == 0)
if (strcasecmp(ext, global.mars_ext) == 0 ||
strcasecmp(ext, global.hdr_ext) == 0)
{
ext--; // skip onto '.'
assert(*ext == '.');
name = static_cast<char *>(mem.malloc((ext - p) + 1));
memcpy(name, p, ext - p);
name[ext - p] = 0; // strip extension
char *tmp = static_cast<char *>(mem.malloc((ext - p) + 1));
memcpy(tmp, p, ext - p);
tmp[ext - p] = 0; // strip extension
name = tmp;
if (name[0] == 0 ||
strcmp(name, "..") == 0 ||
strcmp(name, ".") == 0)
{
Linvalid:
error("invalid file name '%s'", static_cast<char *>(files.data[i]));
fatal();
goto Linvalid;
}
}
else
@@ -884,8 +884,13 @@ int main(int argc, char** argv)
}
else
{ name = p;
if (!*name)
goto Linvalid;
if (!*p)
{
Linvalid:
error("invalid file name '%s'", static_cast<char *>(files.data[i]));
fatal();
}
name = p;
}
id = Lexer::idPool(name);
@@ -1073,7 +1078,7 @@ int main(int argc, char** argv)
{
m->deleteObjFile();
writeModule(lm, m->objfile->name->str);
global.params.objfiles->push(m->objfile->name->str);
global.params.objfiles->push(const_cast<char*>(m->objfile->name->str));
delete lm;
}
else
@@ -1094,10 +1099,10 @@ int main(int argc, char** argv)
Module* m = static_cast<Module*>(modules.data[0]);
char* oname;
char* filename;
const char* filename;
if ((oname = global.params.exefile) || (oname = global.params.objname))
{
filename = FileName::forceExt(oname, global.obj_ext)->toChars();
filename = FileName::forceExt(oname, global.obj_ext);
if (global.params.objdir)
{
filename = FileName::combine(global.params.objdir, FileName::name(filename));
@@ -1108,7 +1113,7 @@ int main(int argc, char** argv)
#if 1
// Temporary workaround for http://llvm.org/bugs/show_bug.cgi?id=11479.
char* moduleName = filename;
char* moduleName = const_cast<char*>(filename);
#else
char* moduleName = m->toChars();
#endif
@@ -1124,12 +1129,55 @@ int main(int argc, char** argv)
m->deleteObjFile();
writeModule(linker.getModule(), filename);
global.params.objfiles->push(filename);
global.params.objfiles->push(const_cast<char*>(filename));
}
// output json file
if (global.params.doXGeneration)
json_generate(&modules);
{
OutBuffer buf;
json_generate(&buf, &modules);
// Write buf to file
const char *name = global.params.xfilename;
if (name && name[0] == '-' && name[1] == 0)
{ // Write to stdout; assume it succeeds
int n = fwrite(buf.data, 1, buf.offset, stdout);
assert(n == buf.offset); // keep gcc happy about return values
}
else
{
/* The filename generation code here should be harmonized with Module::setOutfile()
*/
const char *jsonfilename;
if (name && *name)
{
jsonfilename = FileName::defaultExt(name, global.json_ext);
}
else
{
// Generate json file name from first obj name
const char *n = (*global.params.objfiles)[0];
n = FileName::name(n);
//if (!FileName::absolute(name))
//name = FileName::combine(dir, name);
jsonfilename = FileName::forceExt(n, global.json_ext);
}
FileName::ensurePathToNameExists(jsonfilename);
File *jsonfile = new File(jsonfilename);
jsonfile->setbuffer(buf.data, buf.offset);
jsonfile->ref = 1;
jsonfile->writev();
}
}
backend_term();
if (global.errors)