mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-09-20 20:30:19 +02:00
Merge of DMD 2.062.
This commit is contained in:
+2
-1
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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; }
|
||||
};
|
||||
|
||||
@@ -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
@@ -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, "<") == 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 '<' 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 '>' 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 '&' 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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+8
-9
@@ -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
@@ -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
@@ -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
@@ -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)); }
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
|
||||
@@ -123,7 +123,6 @@ struct ArrayInitializer : Initializer
|
||||
|
||||
#if IN_DMD
|
||||
dt_t *toDt();
|
||||
dt_t *toDtBit(); // for bit arrays
|
||||
#endif
|
||||
|
||||
ArrayInitializer *isArrayInitializer() { return this; }
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+4
-2
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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++ = ',';
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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,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
@@ -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;
|
||||
|
||||
@@ -25,7 +25,6 @@ struct LabelStatement;
|
||||
struct ForeachStatement;
|
||||
struct ClassDeclaration;
|
||||
struct AggregateDeclaration;
|
||||
struct AnonymousAggregateDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct DocComment;
|
||||
struct TemplateInstance;
|
||||
|
||||
+47
-78
@@ -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
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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,4 +1,3 @@
|
||||
// utf.c
|
||||
// Copyright (c) 2003-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
+1
-1
Submodule runtime/druntime updated: 676c9c8ddf...72c6461387
+1
-1
Submodule runtime/phobos updated: ae03a52195...c9efed917c
Reference in New Issue
Block a user