diff --git a/dmd2/access.c b/dmd2/access.c
index b8b677c6..1d2e5a1c 100644
--- a/dmd2/access.c
+++ b/dmd2/access.c
@@ -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
diff --git a/dmd2/aggregate.h b/dmd2/aggregate.h
index c9f69be1..620f6f00 100644
--- a/dmd2/aggregate.h
+++ b/dmd2/aggregate.h
@@ -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
diff --git a/dmd2/argtypes.c b/dmd2/argtypes.c
index 5f1579ad..a26a1166 100644
--- a/dmd2/argtypes.c
+++ b/dmd2/argtypes.c
@@ -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.
diff --git a/dmd2/attrib.c b/dmd2/attrib.c
index 6783a199..d8defdf1 100644
--- a/dmd2/attrib.c
+++ b/dmd2/attrib.c
@@ -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)
{
diff --git a/dmd2/attrib.h b/dmd2/attrib.h
index b40f06c7..42ca18ae 100644
--- a/dmd2/attrib.h
+++ b/dmd2/attrib.h
@@ -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);
};
diff --git a/dmd2/cast.c b/dmd2/cast.c
index 4744ea74..f0018dc0 100644
--- a/dmd2/cast.c
+++ b/dmd2/cast.c
@@ -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;
diff --git a/dmd2/class.c b/dmd2/class.c
index 55cbb050..1621b43c 100644
--- a/dmd2/class.c
+++ b/dmd2/class.c
@@ -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)
diff --git a/dmd2/clone.c b/dmd2/clone.c
index 37fa2a13..c0a0b97a 100644
--- a/dmd2/clone.c
+++ b/dmd2/clone.c
@@ -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);
diff --git a/dmd2/cppmangle.c b/dmd2/cppmangle.c
index 48e37094..78750549 100644
--- a/dmd2/cppmangle.c
+++ b/dmd2/cppmangle.c
@@ -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);
diff --git a/dmd2/ctfeexpr.c b/dmd2/ctfeexpr.c
index b9f95356..e56a35da 100644
--- a/dmd2/ctfeexpr.c
+++ b/dmd2/ctfeexpr.c
@@ -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];
diff --git a/dmd2/declaration.c b/dmd2/declaration.c
index ac7f65fa..b44307b2 100644
--- a/dmd2/declaration.c
+++ b/dmd2/declaration.c
@@ -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;
diff --git a/dmd2/declaration.h b/dmd2/declaration.h
index ee488b2d..3e0d21dd 100644
--- a/dmd2/declaration.h
+++ b/dmd2/declaration.h
@@ -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; }
};
diff --git a/dmd2/delegatize.c b/dmd2/delegatize.c
index b6014892..3c9670f5 100644
--- a/dmd2/delegatize.c
+++ b/dmd2/delegatize.c
@@ -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);
diff --git a/dmd2/doc.c b/dmd2/doc.c
index 4b566155..4ac4bc85 100644
--- a/dmd2/doc.c
+++ b/dmd2/doc.c
@@ -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 =
\n\
\n\
$(TITLE)
\n\
$(BODY)\n\
-
$(SMALL Page generated by $(LINK2 http://www.digitalmars.com/d/2.0/ddoc.html, Ddoc). $(COPYRIGHT))\n\
+
$(SMALL Page generated by $(LINK2 http://dlang.org/ddoc.html, Ddoc). $(COPYRIGHT))\n\
\n\
\n\
B = $0\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
}
/****************************************
diff --git a/dmd2/dsymbol.c b/dmd2/dsymbol.c
index 87dd10a6..6be7b208 100644
--- a/dmd2/dsymbol.c
+++ b/dmd2/dsymbol.c
@@ -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.
diff --git a/dmd2/dsymbol.h b/dmd2/dsymbol.h
index 07506121..c9f28003 100644
--- a/dmd2/dsymbol.h
+++ b/dmd2/dsymbol.h
@@ -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);
diff --git a/dmd2/enum.c b/dmd2/enum.c
index ecc32504..df01847e 100644
--- a/dmd2/enum.c
+++ b/dmd2/enum.c
@@ -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.
diff --git a/dmd2/enum.h b/dmd2/enum.h
index 5059317f..165f5356 100644
--- a/dmd2/enum.h
+++ b/dmd2/enum.h
@@ -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; }
diff --git a/dmd2/expression.c b/dmd2/expression.c
index a410a390..827b916b 100644
--- a/dmd2/expression.c
+++ b/dmd2/expression.c
@@ -1,5 +1,5 @@
// 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
@@ -786,23 +786,9 @@ void preFunctionParameters(Loc loc, Scope *sc, Expressions *exps)
{ Expression *arg = (*exps)[i];
arg = resolveProperties(sc, arg);
-#if 0
- if (arg->op == TOKtype)
- { arg->error("%s is not an expression", arg->toChars());
- arg = new ErrorExp();
- }
-#endif
(*exps)[i] = arg;
//arg->rvalue();
-#if 0
- if (arg->type->ty == Tfunction)
- {
- arg = new AddrExp(arg->loc, arg);
- arg = arg->semantic(sc);
- (*exps)[i] = arg;
- }
-#endif
}
}
}
@@ -933,25 +919,22 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
size_t nparams = Parameter::dim(tf->parameters);
if (nargs > nparams && tf->varargs == 0)
- { error(loc, "expected %zu arguments, not %llu for non-variadic function type %s", nparams, (ulonglong)nargs, tf->toChars());
+ { error(loc, "expected %llu arguments, not %llu for non-variadic function type %s", (ulonglong)nparams, (ulonglong)nargs, tf->toChars());
return Type::terror;
}
// If inferring return type, and semantic3() needs to be run if not already run
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;
+ fd->functionSemantic();
+ }
+ else if (fd && fd->parent)
+ {
+ TemplateInstance *ti = fd->parent->isTemplateInstance();
+ if (ti && ti->tempdecl)
+ {
+ fd->functionSemantic3();
+ }
}
size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
@@ -1149,7 +1132,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
if (p->type->hasWild())
{
arg = arg->implicitCastTo(sc, p->type->substWildTo(wildmatch));
- arg = arg->optimize(WANTvalue);
+ arg = arg->optimize(WANTvalue, p->storageClass & STCref);
}
else if (p->type != arg->type)
{
@@ -1161,7 +1144,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
}
else
arg = arg->implicitCastTo(sc, p->type);
- arg = arg->optimize(WANTvalue);
+ arg = arg->optimize(WANTvalue, p->storageClass & STCref);
}
}
if (p->storageClass & STCref)
@@ -1171,7 +1154,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
else if (p->storageClass & STCout)
{
Type *t = arg->type;
- if (!t->isMutable() || !t->isAssignable(1)) // check blit assignable
+ if (!t->isMutable() || !t->isAssignable()) // check blit assignable
arg->error("cannot modify struct %s with immutable members", arg->toChars());
arg = arg->toLvalue(sc, arg);
}
@@ -1184,13 +1167,8 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
Type *tb = arg->type->toBasetype();
if (tb->ty == Tsarray)
{
-#if !SARRAYVALUE && !IN_LLVM
- // Convert static arrays to pointers
- arg = arg->checkToPointer();
-#else
// call copy constructor of each element
arg = callCpCtor(loc, sc, arg, 1);
-#endif
}
#if DMDV2
else if (tb->ty == Tstruct)
@@ -1648,7 +1626,6 @@ int Expression::isLvalue()
return 0;
}
-
/*******************************
* Give error if we're not an lvalue.
* If we can, convert expression to be an lvalue.
@@ -1664,17 +1641,53 @@ Expression *Expression::toLvalue(Scope *sc, Expression *e)
return new ErrorExp();
}
+/***************************************
+ * Parameters:
+ * sc: scope
+ * flag: 1: do not issue error message for invalid modification
+ * Returns:
+ * 0: is not modifiable
+ * 1: is modifiable in default == being related to type->isMutable()
+ * 2: is modifiable, because this is a part of initializing.
+ */
+
+int Expression::checkModifiable(Scope *sc, int flag)
+{
+ return type ? 1 : 0; // default modifiable
+}
+
Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
{
//printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
// See if this expression is a modifiable lvalue (i.e. not const)
-#if DMDV2
- if (type && !type->isMutable())
- { e->error("%s is not mutable", e->toChars());
- return new ErrorExp();
+ if (checkModifiable(sc) == 1)
+ {
+ assert(type);
+ if (type->isMutable())
+ {
+ if (!type->isAssignable())
+ error("cannot modify struct %s %s with immutable members", toChars(), type->toChars());
+ }
+ else
+ {
+ Declaration *var = NULL;
+ if (op == TOKvar)
+ var = ((VarExp *)this)->var;
+ else if (op == TOKdotvar)
+ var = ((DotVarExp *)this)->var;
+ if (var && var->storage_class & STCctorinit)
+ {
+ const char *p = var->isStatic() ? "static " : "";
+ error("can only initialize %sconst member %s inside %sconstructor",
+ p, var->toChars(), p);
+ }
+ else
+ {
+ error("cannot modify %s expression %s", MODtoChars(type->mod), toChars());
+ }
+ }
}
-#endif
return toLvalue(sc, e);
}
@@ -1926,54 +1939,6 @@ void Expression::checkSafety(Scope *sc, FuncDeclaration *f)
}
#endif
-void Expression::checkModifiable(Scope *sc)
-{
- assert(type);
-
- /* We should call checkCtorInit() first, because this rejects
- the modifying parameter and result inside contract.
- */
- if (!checkCtorInit(sc))
- {
- if (type->isMutable())
- {
- if (!type->isAssignable())
- {
- error("cannot modify struct %s %s with immutable members", toChars(), type->toChars());
- }
- }
- else
- {
- Declaration *var = NULL;
- if (op == TOKvar)
- var = ((VarExp *)this)->var;
- else if (op == TOKdotvar)
- var = ((DotVarExp *)this)->var;
- if (var && var->storage_class & STCctorinit)
- {
- const char *p = var->isStatic() ? "static " : "";
- error("can only initialize %sconst member %s inside %sconstructor",
- p, var->toChars(), p);
- }
- else
- {
- OutBuffer buf;
- MODtoBuffer(&buf, type->mod);
- error("cannot modify %s expression %s", buf.toChars(), toChars());
- }
- }
- }
-}
-
-/***************************************
- * Return !=0 if expression is a part of initializing.
- */
-
-int Expression::checkCtorInit(Scope *sc)
-{
- return FALSE;
-}
-
/*****************************
* Check that expression can be tested for true or false.
*/
@@ -2028,18 +1993,6 @@ Expression *Expression::checkToPointer()
//printf("Expression::checkToPointer()\n");
Expression *e = this;
-#if !SARRAYVALUE
- // If C static array, convert to pointer
- Type *tb = type->toBasetype();
- if (tb->ty == Tsarray)
- { TypeSArray *ts = (TypeSArray *)tb;
- if (ts->size(loc) == 0)
- e = new NullExp(loc);
- else
- e = new AddrExp(loc, this);
- e->type = ts->next->pointerTo();
- }
-#endif
return e;
}
@@ -2207,14 +2160,7 @@ int IntegerExp::equals(Object *o)
char *IntegerExp::toChars()
{
-#if 1
return Expression::toChars();
-#else
- static char buffer[sizeof(value) * 3 + 1];
-
- sprintf(buffer, "%lld", value);
- return buffer;
-#endif
}
dinteger_t IntegerExp::toInteger()
@@ -2620,8 +2566,6 @@ void floatToBuffer(OutBuffer *buf, Type *type, real_t value)
__locale_decpoint = ".";
real_t r = strtold(buffer, NULL);
__locale_decpoint = save;
-#elif IN_LLVM
- real_t r = Port::strtold(buffer, NULL);
#else
real_t r = strtold(buffer, NULL);
#endif
@@ -2995,16 +2939,8 @@ int IdentifierExp::isLvalue()
return 1;
}
-
Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e)
{
-#if 0
- tym = tybasic(e1->ET->Tty);
- if (!(tyscalar(tym) ||
- tym == TYstruct ||
- tym == TYarray && e->Eoper == TOKaddr))
- synerr(EM_lvalue); // lvalue expected
-#endif
return this;
}
@@ -3122,34 +3058,10 @@ Lagain:
}
f = s->isFuncDeclaration();
if (f)
- { f = f->toAliasFunc();
-
- if (!f->originalType && f->scope) // semantic not yet run
- {
- unsigned oldgag = global.gag;
- if (global.isSpeculativeGagging() && !f->isSpeculative())
- global.gag = 0;
- f->semantic(f->scope);
- global.gag = oldgag;
- }
-
- // if inferring return type, sematic3 needs to be run
- if (f->scope && (f->inferRetType && f->type && !f->type->nextOf() ||
- getFuncTemplateDecl(f)))
- {
- TemplateInstance *spec = f->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;
- f->semantic3(f->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;
- }
+ {
+ f = f->toAliasFunc();
+ if (!f->functionSemantic())
+ return new ErrorExp();
if (f->isUnitTestDeclaration())
{
@@ -3280,16 +3192,8 @@ int DsymbolExp::isLvalue()
return 1;
}
-
Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e)
{
-#if 0
- tym = tybasic(e1->ET->Tty);
- if (!(tyscalar(tym) ||
- tym == TYstruct ||
- tym == TYarray && e->Eoper == TOKaddr))
- synerr(EM_lvalue); // lvalue expected
-#endif
return this;
}
@@ -3339,11 +3243,7 @@ Expression *ThisExp::semantic(Scope *sc)
StructDeclaration *sd = s->isStructDeclaration();
if (sd)
{
-#if STRUCTTHISREF
type = sd->type;
-#else
- type = sd->type->pointerTo();
-#endif
return this;
}
}
@@ -3382,7 +3282,6 @@ int ThisExp::isLvalue()
return 1;
}
-
Expression *ThisExp::toLvalue(Scope *sc, Expression *e)
{
return this;
@@ -3391,7 +3290,10 @@ Expression *ThisExp::toLvalue(Scope *sc, Expression *e)
Expression *ThisExp::modifiableLvalue(Scope *sc, Expression *e)
{
if (type->toBasetype()->ty == Tclass)
+ {
error("Cannot modify '%s'", toChars());
+ return toLvalue(sc, e);
+ }
return Expression::modifiableLvalue(sc, e);
}
@@ -3452,6 +3354,8 @@ Expression *SuperExp::semantic(Scope *sc)
s = fd->toParent();
while (s && s->isTemplateInstance())
s = s->toParent();
+ if (s->isTemplateDeclaration()) // allow inside template constraint
+ s = s->toParent();
assert(s);
cd = s->isClassDeclaration();
//printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars());
@@ -3816,7 +3720,6 @@ int StringExp::isLvalue()
return 0;
}
-
Expression *StringExp::toLvalue(Scope *sc, Expression *e)
{
//printf("StringExp::toLvalue(%s)\n", toChars());
@@ -4221,6 +4124,7 @@ Expression *StructLiteralExp::semantic(Scope *sc)
Type *telem = v->type;
if (stype)
telem = telem->addMod(stype->mod);
+ Type *origType = telem;
while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray)
{ /* Static array initialization, as in:
* T[3][5] = e;
@@ -4228,6 +4132,9 @@ Expression *StructLiteralExp::semantic(Scope *sc)
telem = telem->toBasetype()->nextOf();
}
+ if (!e->implicitConvTo(telem))
+ telem = origType; // restore type for better diagnostic
+
e = e->implicitCastTo(sc, telem);
if (e->op == TOKerror)
return e;
@@ -4309,13 +4216,16 @@ Expression *StructLiteralExp::semantic(Scope *sc)
Expression *StructLiteralExp::getField(Type *type, unsigned offset)
{
//printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
-// /*toChars()*/"", type->toChars(), offset);
+ // /*toChars()*/"", type->toChars(), offset);
Expression *e = NULL;
int i = getFieldIndex(type, offset);
if (i != -1)
{
//printf("\ti = %d\n", i);
+ if (i == sd->fields.dim - 1 && sd->isNested())
+ return NULL;
+
assert(i < elements->dim);
e = (*elements)[i];
if (e)
@@ -4372,7 +4282,11 @@ int StructLiteralExp::getFieldIndex(Type *type, unsigned offset)
if (offset == v->offset &&
type->size() == v->type->size())
- { Expression *e = (*elements)[i];
+ {
+ /* context field might not be filled. */
+ if (i == sd->fields.dim - 1 && sd->isNested())
+ return (int)i;
+ Expression *e = (*elements)[i];
if (e)
{
return (int)i;
@@ -4747,25 +4661,7 @@ Lagain:
goto Lerr;
}
}
-#if 0
- else
- {
- for (Dsymbol *sf = sc->func; 1; sf= sf->toParent2()->isFuncDeclaration())
- {
- if (!sf)
- {
- error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
- goto Lerr;
}
- printf("sf = %s\n", sf->toChars());
- AggregateDeclaration *ad = sf->isThis();
- if (ad && (ad == cdn || cdn->isBaseOf(ad->isClassDeclaration(), NULL)))
- break;
- }
- }
-#endif
- }
-#if 1
else if (thisexp)
{ error("e.new is only for allocating nested classes");
goto Lerr;
@@ -4785,19 +4681,6 @@ Lagain:
}
}
}
-#else
- else if (fdn)
- { /* The nested class cd is nested inside a function,
- * we'll let getEthis() look for errors.
- */
- //printf("nested class %s is nested inside function %s, we're in %s\n", cd->toChars(), fdn->toChars(), sc->func->toChars());
- if (thisexp)
- { // Because thisexp cannot be a function frame pointer
- error("e.new is only for allocating nested classes");
- goto Lerr;
- }
- }
-#endif
else
assert(0);
}
@@ -5182,20 +5065,16 @@ Expression *VarExp::semantic(Scope *sc)
#if LOGSEMANTIC
printf("VarExp::semantic(%s)\n", toChars());
#endif
-// if (var->sem == SemanticStart && var->scope) // if forward referenced
-// var->semantic(sc);
- if (!type)
- { type = var->type;
-#if 0
- if (var->storage_class & STClazy)
- {
- TypeFunction *tf = new TypeFunction(NULL, type, 0, LINKd);
- type = new TypeDelegate(tf);
- type = type->semantic(loc, sc);
- }
-#endif
+ if (FuncDeclaration *f = var->isFuncDeclaration())
+ {
+ //printf("L%d fd = %s\n", __LINE__, f->toChars());
+ if (!f->functionSemantic())
+ return new ErrorExp();
}
+ if (!type)
+ type = var->type;
+
if (type && !type->deco)
type = type->semantic(loc, sc);
@@ -5216,14 +5095,6 @@ Expression *VarExp::semantic(Scope *sc)
FuncDeclaration *f = var->isFuncDeclaration();
if (f)
f->checkNestedReference(sc, loc);
-#if 0
- else if ((fd = var->isFuncLiteralDeclaration()) != NULL)
- { Expression *e;
- e = new FuncExp(loc, fd);
- e->type = type;
- return e;
- }
-#endif
return this;
}
@@ -5264,12 +5135,6 @@ void VarExp::checkEscapeRef()
}
}
-int VarExp::checkCtorInit(Scope *sc)
-{
- return var->checkModify(loc, sc, type);
-}
-
-
int VarExp::isLvalue()
{
if (var->storage_class & (STClazy | STCtemp))
@@ -5277,16 +5142,8 @@ int VarExp::isLvalue()
return 1;
}
-
Expression *VarExp::toLvalue(Scope *sc, Expression *e)
{
-#if 0
- tym = tybasic(e1->ET->Tty);
- if (!(tyscalar(tym) ||
- tym == TYstruct ||
- tym == TYarray && e->Eoper == TOKaddr))
- synerr(EM_lvalue); // lvalue expected
-#endif
if (var->storage_class & STClazy)
{ error("lazy variables cannot be lvalues");
return new ErrorExp();
@@ -5299,6 +5156,13 @@ Expression *VarExp::toLvalue(Scope *sc, Expression *e)
return this;
}
+int VarExp::checkModifiable(Scope *sc, int flag)
+{
+ //printf("VarExp::checkModifiable %s", toChars());
+ assert(type);
+ return var->checkModify(loc, sc, type, NULL, flag);
+}
+
Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e)
{
//printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
@@ -5315,10 +5179,8 @@ Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e)
deprecation("variable modified in foreach body requires ref storage class");
#endif
- checkModifiable(sc);
-
// See if this expression is a modifiable lvalue (i.e. not const)
- return toLvalue(sc, e);
+ return Expression::modifiableLvalue(sc, e);
}
@@ -5793,6 +5655,9 @@ Expression *TypeidExp::semantic(Scope *sc)
if (ea)
{
+ Dsymbol *sym = getDsymbol(ea);
+ if (sym)
+ ea = new DsymbolExp(loc, sym);
ea = ea->semantic(sc);
ea = resolveProperties(sc, ea);
ta = ea->type;
@@ -6063,6 +5928,12 @@ Expression *IsExp::semantic(Scope *sc)
for (size_t i = 0; i < dim; i++)
{ Parameter *arg = Parameter::getNth(params, i);
assert(arg && arg->type);
+ /* If one of the default arguments was an error,
+ don't return an invalid tuple
+ */
+ if (tok2 == TOKparameters && arg->defaultArg &&
+ arg->defaultArg->op == TOKerror)
+ return new ErrorExp();
args->push(new Parameter(arg->storageClass, arg->type,
(tok2 == TOKparameters) ? arg->ident : NULL,
(tok2 == TOKparameters) ? arg->defaultArg : NULL));
@@ -6457,15 +6328,17 @@ Expression *BinExp::incompatibleTypes()
e2->type->toBasetype() != Type::terror
)
{
+ // CondExp uses 'a ? b : c' but we're comparing 'b : c'
+ TOK thisOp = (op == TOKquestion) ? TOKcolon : op;
if (e1->op == TOKtype || e2->op == TOKtype)
{
error("incompatible types for ((%s) %s (%s)): cannot use '%s' with types",
- e1->toChars(), Token::toChars(op), e2->toChars(), Token::toChars(op));
+ e1->toChars(), Token::toChars(thisOp), e2->toChars(), Token::toChars(op));
}
else
{
error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
- e1->toChars(), Token::toChars(op), e2->toChars(),
+ e1->toChars(), Token::toChars(thisOp), e2->toChars(),
e1->type->toChars(), e2->type->toChars());
}
return new ErrorExp();
@@ -6612,6 +6485,7 @@ Expression *BinAssignExp::toLvalue(Scope *sc, Expression *ex)
Expression *BinAssignExp::modifiableLvalue(Scope *sc, Expression *e)
{
+ // should check e1->checkModifiable() ?
return toLvalue(sc, this);
}
@@ -6672,7 +6546,8 @@ FileExp::FileExp(Loc loc, Expression *e)
}
Expression *FileExp::semantic(Scope *sc)
-{ char *name;
+{
+ const char *name;
StringExp *se;
#if LOGSEMANTIC
@@ -6819,18 +6694,6 @@ Expression *DotIdExp::semantic(Scope *sc, int flag)
//{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
-#if 0
- /* Don't do semantic analysis if we'll be converting
- * it to a string.
- */
- if (ident == Id::stringof)
- { char *s = e1->toChars();
- e = new StringExp(loc, s, strlen(s), 'c');
- e = e->semantic(sc);
- return e;
- }
-#endif
-
/* Special case: rewrite this.id and super.id
* to be classtype.id and baseclasstype.id
* if we have no this pointer.
@@ -6876,26 +6739,6 @@ Expression *DotIdExp::semantic(Scope *sc, int flag)
UnaExp::semantic(sc);
-#if 0
- /*
- * Identify typeof(var).stringof and use the original type of var, if possible
- */
- if (ident == Id::stringof && e1->op == TOKtype && t1save && t1save->ty == Ttypeof)
- { TypeTypeof *t = (TypeTypeof *)t1save;
- if (t->exp->op == TOKvar)
- {
- Type *ot = ((VarExp *)t->exp)->var->originalType;
- if (ot)
- {
- char *s = ((VarExp *)t->exp)->var->originalType->toChars();
- e = new StringExp(loc, s, strlen(s), 'c');
- e = e->semantic(sc);
- return e;
- }
- }
- }
-#endif
-
if (ident == Id::mangleof)
{ // symbol.mangleof
Dsymbol *ds;
@@ -7289,16 +7132,27 @@ Expression *DotVarExp::semantic(Scope *sc)
e1 = e1->semantic(sc);
e1 = e1->addDtorHook(sc);
- type = var->type;
- if (!type && global.errors)
- { // var is goofed up, just return 0
- return new ErrorExp();
- }
- assert(type);
Type *t1 = e1->type;
- if (!var->isFuncDeclaration()) // for functions, do checks after overload resolution
+ FuncDeclaration *f = var->isFuncDeclaration();
+ if (f) // for functions, do checks after overload resolution
{
+ //printf("L%d fd = %s\n", __LINE__, f->toChars());
+ if (!f->functionSemantic())
+ return new ErrorExp();
+
+ type = f->type;
+ assert(type);
+ }
+ else
+ {
+ type = var->type;
+ if (!type && global.errors)
+ { // var is goofed up, just return 0
+ goto Lerr;
+ }
+ assert(type);
+
if (t1->ty == Tpointer)
t1 = t1->nextOf();
@@ -7337,21 +7191,11 @@ Lerr:
return new ErrorExp();
}
-int DotVarExp::checkCtorInit(Scope *sc)
-{
- if (e1->op == TOKthis)
- return modifyFieldVar(loc, sc, var->isVarDeclaration(), e1);
- else
- return e1->checkCtorInit(sc);
-}
-
-
int DotVarExp::isLvalue()
{
return 1;
}
-
Expression *DotVarExp::toLvalue(Scope *sc, Expression *e)
{
//printf("DotVarExp::toLvalue(%s)\n", toChars());
@@ -7394,6 +7238,16 @@ int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1)
return FALSE;
}
+int DotVarExp::checkModifiable(Scope *sc, int flag)
+{
+ //printf("DotVarExp::checkModifiable %s %s\n", toChars(), type->toChars());
+ if (e1->op == TOKthis)
+ return var->checkModify(loc, sc, type, e1, flag);
+
+ //printf("\te1 = %s\n", e1->toChars());
+ return e1->checkModifiable(sc, flag);
+}
+
Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
{
#if 0
@@ -7402,8 +7256,7 @@ Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
printf("var->type = %s\n", var->type->toChars());
#endif
- checkModifiable(sc);
- return this;
+ return Expression::modifiableLvalue(sc, e);
}
void DotVarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
@@ -7780,9 +7633,7 @@ Expression *CallExp::resolveUFCS(Scope *sc)
return new ErrorExp();
}
if (!e->type->isMutable())
- { OutBuffer buf;
- MODtoBuffer(&buf, e->type->mod);
- error("cannot remove key from %s associative array %s", buf.toChars(), e->toChars());
+ { error("cannot remove key from %s associative array %s", MODtoChars(e->type->mod), e->toChars());
return new ErrorExp();
}
Expression *key = (*arguments)[0];
@@ -7909,7 +7760,6 @@ Expression *CallExp::semantic(Scope *sc)
if (e)
return e;
-#if 1
/* This recognizes:
* foo!(tiargs)(funcargs)
*/
@@ -7953,17 +7803,6 @@ Ldotti:
* If not, go with partial explicit specialization.
*/
ti->semanticTiargs(sc);
-#if 0
- Expression *etmp = e1->trySemantic(sc);
- if (etmp)
- e1 = etmp; // it worked
- else // didn't work
- {
- targsi = ti->tiargs;
- tierror = ti; // for error reporting
- e1 = new DotIdExp(loc, se->e1, ti->name);
- }
-#else
if (!ti->tempdecl)
{
se->getTempdecl(sc);
@@ -7980,10 +7819,8 @@ Ldotti:
{
e1 = e1->semantic(sc);
}
-#endif
}
}
-#endif
istemp = 0;
Lagain:
@@ -8055,8 +7892,6 @@ Lagain:
e1 = ve;
}
}
-
-
}
#else
else if (e1->op == TOKsymoff && ((SymOffExp *)e1)->hasOverloads)
@@ -8066,7 +7901,6 @@ Lagain:
e1 = e1->semantic(sc);
}
#endif
-#if 1 // patch for #540 by Oskar Linde
else if (e1->op == TOKdotexp)
{
DotExp *de = (DotExp *) e1;
@@ -8089,7 +7923,6 @@ Lagain:
e1 = new DotTemplateExp(loc,de->e1,te->td);
}
}
-#endif
}
t1 = NULL;
@@ -8104,6 +7937,17 @@ Lagain:
{
ad = ((TypeStruct *)t1)->sym;
#if DMDV2
+
+ if (ad->sizeok == SIZEOKnone && !ad->ctor &&
+ ad->search(0, Id::ctor, 0))
+ {
+ // The constructor hasn't been found yet, see bug 8741
+ // This can happen if we are inferring type from
+ // from VarDeclaration::semantic() in declaration.c
+ error("cannot create a struct until its size is determined");
+ return new ErrorExp();
+ }
+
// First look for constructor
if (e1->op == TOKtype && ad->ctor && (ad->noDefaultCtor || arguments && arguments->dim))
{
@@ -8134,11 +7978,6 @@ Lagain:
e = new DotTemplateExp(loc, av, td);
}
e = new CallExp(loc, e, arguments);
-#if !STRUCTTHISREF
- /* Constructors return a pointer to the instance
- */
- e = new PtrExp(loc, e);
-#endif
e = e->semantic(sc);
return e;
}
@@ -8247,6 +8086,8 @@ Lagain:
if (f->needThis())
{
ue->e1 = getRightThis(loc, sc, ad, ue->e1, f);
+ if (ue->e1->op == TOKerror)
+ return ue->e1;
ethis = ue->e1;
}
@@ -8297,43 +8138,6 @@ Lagain:
printf("e1 = %s\n", e1->toChars());
printf("e1->type = %s\n", e1->type->toChars());
#endif
- // Const member function can take const/immutable/mutable/inout this
- if (!(f->type->isConst()))
- {
- // Check for const/immutable compatibility
- Type *tthis = ue->e1->type->toBasetype();
- if (tthis->ty == Tpointer)
- tthis = tthis->nextOf()->toBasetype();
-#if 0 // this checking should have been already done
- if (f->type->isImmutable())
- {
- if (tthis->mod != MODimmutable)
- error("%s can only be called with an immutable object", e1->toChars());
- }
- else if (f->type->isShared())
- {
- if (tthis->mod != MODimmutable &&
- tthis->mod != MODshared &&
- tthis->mod != (MODshared | MODconst))
- error("shared %s can only be called with a shared or immutable object", e1->toChars());
- }
- else
- {
- if (tthis->mod != 0)
- { //printf("mod = %x\n", tthis->mod);
- error("%s can only be called with a mutable object, not %s", e1->toChars(), tthis->toChars());
- }
- }
-#endif
- /* Cannot call mutable method on a final struct
- */
- if (tthis->ty == Tstruct &&
- ue->e1->op == TOKvar)
- { VarExp *v = (VarExp *)ue->e1;
- if (v->var->storage_class & STCfinal)
- error("cannot call mutable method on final struct");
- }
- }
// See if we need to adjust the 'this' pointer
AggregateDeclaration *ad = f->isThis();
@@ -8369,10 +8173,6 @@ Lagain:
{
if (!sc->intypeof)
{
-#if 0
- if (sc->callSuper & (CSXthis | CSXsuper))
- error("reference to this before super()");
-#endif
if (sc->noctor || sc->callSuper & CSXlabel)
error("constructor calls not allowed in loops or after labels");
if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
@@ -8383,6 +8183,8 @@ Lagain:
}
f = resolveFuncCall(sc, loc, cd->baseClass->ctor, NULL, NULL, arguments, 0);
+ if (!f)
+ return new ErrorExp();
accessCheck(loc, sc, NULL, f);
checkDeprecated(sc, f);
#if DMDV2
@@ -8411,10 +8213,6 @@ Lagain:
{
if (!sc->intypeof)
{
-#if 0
- if (sc->callSuper & (CSXthis | CSXsuper))
- error("reference to this before super()");
-#endif
if (sc->noctor || sc->callSuper & CSXlabel)
error("constructor calls not allowed in loops or after labels");
if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
@@ -8425,6 +8223,8 @@ Lagain:
}
f = resolveFuncCall(sc, loc, cd->ctor, NULL, NULL, arguments, 0);
+ if (!f)
+ return new ErrorExp();
checkDeprecated(sc, f);
#if DMDV2
checkPurity(sc, f);
@@ -8705,7 +8505,6 @@ int CallExp::isLvalue()
return 0;
}
-
Expression *CallExp::toLvalue(Scope *sc, Expression *e)
{
if (isLvalue())
@@ -8997,16 +8796,6 @@ void PtrExp::checkEscapeRef()
e1->checkEscape();
}
-int PtrExp::checkCtorInit(Scope *sc)
-{
- if (e1->op == TOKsymoff)
- { SymOffExp *se = (SymOffExp *)e1;
- return se->var->checkModify(loc, sc, type);
- }
- return FALSE;
-}
-
-
int PtrExp::isLvalue()
{
return 1;
@@ -9014,23 +8803,28 @@ int PtrExp::isLvalue()
Expression *PtrExp::toLvalue(Scope *sc, Expression *e)
{
-#if 0
- tym = tybasic(e1->ET->Tty);
- if (!(tyscalar(tym) ||
- tym == TYstruct ||
- tym == TYarray && e->Eoper == TOKaddr))
- synerr(EM_lvalue); // lvalue expected
-#endif
return this;
}
+int PtrExp::checkModifiable(Scope *sc, int flag)
+{
+ if (e1->op == TOKsymoff)
+ { SymOffExp *se = (SymOffExp *)e1;
+ return se->var->checkModify(loc, sc, type, NULL, flag);
+ }
+ else if (e1->op == TOKaddress)
+ {
+ AddrExp *ae = (AddrExp *)e1;
+ return ae->e1->checkModifiable(sc, flag);
+ }
+ return 1;
+}
+
#if DMDV2
Expression *PtrExp::modifiableLvalue(Scope *sc, Expression *e)
{
//printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
-
- checkModifiable(sc);
- return toLvalue(sc, e);
+ return Expression::modifiableLvalue(sc, e);
}
#endif
@@ -9356,13 +9150,6 @@ Expression *CastExp::semantic(Scope *sc)
if (!to->equals(e1->type))
{
-#if 0 // attempt at fixing 6720
- if (e1->type->ty == Tvoid)
- {
- error("cannot cast from void to %s", to->toChars());
- return new ErrorExp();
- }
-#endif
Expression *e = op_overload(sc);
if (e)
{
@@ -9626,6 +9413,16 @@ Expression *SliceExp::semantic(Scope *sc)
Lagain:
UnaExp::semantic(sc);
e1 = resolveProperties(sc, e1);
+ if (e1->op == TOKtype && e1->type->ty != Ttuple)
+ {
+ if (lwr || upr)
+ {
+ error("cannot slice type '%s'", e1->toChars());
+ return new ErrorExp();
+ }
+ e = new TypeExp(loc, e1->type->arrayOf());
+ return e->semantic(sc);
+ }
e = this;
@@ -9809,29 +9606,28 @@ void SliceExp::checkEscapeRef()
e1->checkEscapeRef();
}
-int SliceExp::checkCtorInit(Scope *sc)
-{
- if (e1->type->ty == Tsarray ||
- (e1->op == TOKindex && e1->type->ty != Tarray) ||
- e1->op == TOKslice)
- {
- return e1->checkCtorInit(sc);
- }
- return FALSE;
-}
-
-
int SliceExp::isLvalue()
{
return 1;
}
-
Expression *SliceExp::toLvalue(Scope *sc, Expression *e)
{
return this;
}
+int SliceExp::checkModifiable(Scope *sc, int flag)
+{
+ //printf("SliceExp::checkModifiable %s\n", toChars());
+ if (e1->type->ty == Tsarray ||
+ (e1->op == TOKindex && e1->type->ty != Tarray) ||
+ e1->op == TOKslice)
+ {
+ return e1->checkModifiable(sc, flag);
+ }
+ return 1;
+}
+
Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e)
{
error("slice expression %s is not a modifiable lvalue", toChars());
@@ -10009,7 +9805,6 @@ int ArrayExp::isLvalue()
return 1;
}
-
Expression *ArrayExp::toLvalue(Scope *sc, Expression *e)
{
if (type && type->toBasetype()->ty == Tvoid)
@@ -10090,24 +9885,22 @@ void CommaExp::checkEscapeRef()
e2->checkEscapeRef();
}
-int CommaExp::checkCtorInit(Scope *sc)
-{
- return e2->checkCtorInit(sc);
-}
-
-
int CommaExp::isLvalue()
{
return e2->isLvalue();
}
-
Expression *CommaExp::toLvalue(Scope *sc, Expression *e)
{
e2 = e2->toLvalue(sc, NULL);
return this;
}
+int CommaExp::checkModifiable(Scope *sc, int flag)
+{
+ return e2->checkModifiable(sc, flag);
+}
+
Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e)
{
e2 = e2->modifiableLvalue(sc, e);
@@ -10158,6 +9951,18 @@ Expression *IndexExp::semantic(Scope *sc)
if (!e1->type)
e1 = e1->semantic(sc);
assert(e1->type); // semantic() should already be run on it
+ if (e1->op == TOKtype && e1->type->ty != Ttuple)
+ {
+ e2 = e2->semantic(sc);
+ e2 = resolveProperties(sc, e2);
+ Type *nt;
+ if (e2->op == TOKtype)
+ nt = new TypeAArray(e1->type, e2->type);
+ else
+ nt = new TypeSArray(e1->type, e2);
+ e = new TypeExp(loc, nt);
+ return e->semantic(sc);
+ }
if (e1->op == TOKerror)
goto Lerr;
e = this;
@@ -10187,6 +9992,19 @@ Expression *IndexExp::semantic(Scope *sc)
switch (t1->ty)
{
case Tpointer:
+ e2 = e2->implicitCastTo(sc, Type::tsize_t);
+ e2 = e2->optimize(WANTvalue);
+ if (e2->op == TOKint64 && e2->toInteger() == 0)
+ ;
+ else if (sc->func->setUnsafe())
+ {
+ error("safe function '%s' cannot index pointer '%s'",
+ sc->func->toPrettyChars(), e1->toChars());
+ return new ErrorExp();
+ }
+ e->type = ((TypeNext *)t1)->next;
+ break;
+
case Tarray:
e2 = e2->implicitCastTo(sc, Type::tsize_t);
e->type = ((TypeNext *)t1)->next;
@@ -10195,21 +10013,7 @@ Expression *IndexExp::semantic(Scope *sc)
case Tsarray:
{
e2 = e2->implicitCastTo(sc, Type::tsize_t);
-
TypeSArray *tsa = (TypeSArray *)t1;
-
-#if 0 // Don't do now, because it might be short-circuit evaluated
- // Do compile time array bounds checking if possible
- e2 = e2->optimize(WANTvalue);
- if (e2->op == TOKint64)
- {
- dinteger_t index = e2->toInteger();
- dinteger_t length = tsa->dim->toInteger();
- if (index < 0 || index >= length)
- error("array index [%lld] is outside array bounds [0 .. %lld]",
- index, length);
- }
-#endif
e->type = t1->nextOf();
break;
}
@@ -10287,24 +10091,11 @@ Lerr:
return new ErrorExp();
}
-int IndexExp::checkCtorInit(Scope *sc)
-{
- if (e1->type->ty == Tsarray ||
- (e1->op == TOKindex && e1->type->ty != Tarray) ||
- e1->op == TOKslice)
- {
- return e1->checkCtorInit(sc);
- }
- return FALSE;
-}
-
-
int IndexExp::isLvalue()
{
return 1;
}
-
Expression *IndexExp::toLvalue(Scope *sc, Expression *e)
{
// if (type && type->toBasetype()->ty == Tvoid)
@@ -10312,6 +10103,17 @@ Expression *IndexExp::toLvalue(Scope *sc, Expression *e)
return this;
}
+int IndexExp::checkModifiable(Scope *sc, int flag)
+{
+ if (e1->type->ty == Tsarray ||
+ (e1->op == TOKindex && e1->type->ty != Tarray) ||
+ e1->op == TOKslice)
+ {
+ return e1->checkModifiable(sc, flag);
+ }
+ return 1;
+}
+
Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e)
{
//printf("IndexExp::modifiableLvalue(%s)\n", toChars());
@@ -10323,12 +10125,10 @@ Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e)
if (t2b->ty == Tarray && t2b->nextOf()->isMutable())
error("associative arrays can only be assigned values with immutable keys, not %s", e2->type->toChars());
e1 = e1->modifiableLvalue(sc, e1);
+ return toLvalue(sc, e);
}
- else
- {
- checkModifiable(sc);
- }
- return toLvalue(sc, e);
+
+ return Expression::modifiableLvalue(sc, e);
}
void IndexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
@@ -10751,13 +10551,13 @@ Expression *AssignExp::semantic(Scope *sc)
Type *t1 = e1->type->toBasetype();
e2 = e2->inferType(t1);
- if (!e2->rvalue())
- return new ErrorExp();
e2 = e2->semantic(sc);
if (e2->op == TOKerror)
return new ErrorExp();
e2 = resolveProperties(sc, e2);
+ if (!e2->rvalue())
+ return new ErrorExp();
/* Rewrite tuple assignment as a tuple of assignments.
*/
@@ -10832,8 +10632,6 @@ Ltupleassign:
}
}
- int ctorinit = e1->checkCtorInit(sc);
-
// Determine if this is an initialization of a reference
int refinit = 0;
if (op == TOKconstruct && e1->op == TOKvar)
@@ -10851,17 +10649,6 @@ Ltupleassign:
StructDeclaration *sd = ((TypeStruct *)t1)->sym;
if (op == TOKassign)
{
- /* See if we need to set ctorinit, i.e. track
- * assignments to fields. An assignment to a field counts even
- * if done through an opAssign overload.
- */
- if (e1->op == TOKdotvar)
- { DotVarExp *dve = (DotVarExp *)e1;
- VarDeclaration *v = dve->var->isVarDeclaration();
- if (v && v->storage_class & STCnodefaultctor)
- modifyFieldVar(loc, sc, v, dve->e1);
- }
-
Expression *e = op_overload(sc);
if (e && e1->op == TOKindex &&
((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray)
@@ -10893,7 +10680,14 @@ Ltupleassign:
e = this;
}
if (e)
+ {
+ /* See if we need to set ctorinit, i.e. track
+ * assignments to fields. An assignment to a field counts even
+ * if done through an opAssign overload.
+ */
+ e1->checkModifiable(sc);
return e;
+ }
}
else if (op == TOKconstruct && !refinit)
{ Type *t2 = e2->type->toBasetype();
@@ -10984,7 +10778,7 @@ Ltupleassign:
else if (e1->op == TOKslice)
{
Type *tn = e1->type->nextOf();
- if (op == TOKassign && !ctorinit && !tn->isMutable())
+ if (op == TOKassign && e1->checkModifiable(sc) == 1 && !tn->isMutable())
{ error("slice %s is not mutable", e1->toChars());
return new ErrorExp();
}
@@ -11000,16 +10794,7 @@ Ltupleassign:
}
Type *t2 = e2->type->toBasetype();
-#if 0
- if (t1->ty == Tvector && t2->ty != Tvector &&
- e2->implicitConvTo(((TypeVector *)t1)->basetype->nextOf())
- )
- { // memset
- ismemset = 1; // make it easy for back end to tell what this is
- e2 = e2->implicitCastTo(sc, ((TypeVector *)t1)->basetype->nextOf());
- }
- else
-#endif
+
// If it is a array, get the element type. Note that it may be
// multi-dimensional.
Type *telem = t1;
@@ -11588,7 +11373,8 @@ Expression *CatExp::semantic(Scope *sc)
*/
}
else if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
- e2->implicitConvTo(tb1next) >= MATCHconvert)
+ e2->implicitConvTo(tb1next) >= MATCHconvert &&
+ tb2->ty != Tvoid)
{
checkPostblit(e2->loc, tb2);
e2 = e2->implicitCastTo(sc, tb1next);
@@ -11601,7 +11387,8 @@ Expression *CatExp::semantic(Scope *sc)
return this;
}
else if ((tb2->ty == Tsarray || tb2->ty == Tarray) &&
- e1->implicitConvTo(tb2next) >= MATCHconvert)
+ e1->implicitConvTo(tb2next) >= MATCHconvert &&
+ tb1->ty != Tvoid)
{
checkPostblit(e1->loc, tb1);
e1 = e1->implicitCastTo(sc, tb2next);
@@ -12431,28 +12218,6 @@ Expression *CmpExp::semantic(Scope *sc)
if (e->op == TOKerror)
return e;
-#if 0
- // For integer comparisons, ensure the combined type can hold both arguments.
- if (type && type->isintegral() && (op == TOKlt || op == TOKle ||
- op == TOKgt || op == TOKge))
- {
- IntRange trange = IntRange::fromType(type);
-
- Expression *errorexp = 0;
- if (!trange.contains(eb1->getIntRange()))
- errorexp = eb1;
- if (!trange.contains(eb2->getIntRange()))
- errorexp = eb2;
-
- if (errorexp)
- {
- error("implicit conversion of '%s' to '%s' is unsafe in '(%s) %s (%s)'",
- errorexp->toChars(), type->toChars(), eb1->toChars(), Token::toChars(op), eb2->toChars());
- return new ErrorExp();
- }
- }
-#endif
-
type = Type::tboolean;
// Special handling for array comparisons
@@ -12478,13 +12243,11 @@ Expression *CmpExp::semantic(Scope *sc)
error("need member function opCmp() for %s %s to compare", t1->toDsymbol(sc)->kind(), t1->toChars());
e = new ErrorExp();
}
-#if 1
else if (t1->iscomplex() || t2->iscomplex())
{
error("compare not defined for complex operands");
e = new ErrorExp();
}
-#endif
else if (t1->ty == Tvector)
return incompatibleTypes();
else
@@ -12723,30 +12486,6 @@ Expression *CondExp::semantic(Scope *sc)
econd = econd->checkToPointer();
econd = econd->checkToBoolean(sc);
-#if 0 /* this cannot work right because the types of e1 and e2
- * both contribute to the type of the result.
- */
- if (sc->flags & SCOPEstaticif)
- {
- /* If in static if, don't evaluate what we don't have to.
- */
- econd = econd->optimize(WANTflags);
- if (econd->isBool(TRUE))
- {
- e1 = e1->semantic(sc);
- e1 = resolveProperties(sc, e1);
- return e1;
- }
- else if (econd->isBool(FALSE))
- {
- e2 = e2->semantic(sc);
- e2 = resolveProperties(sc, e2);
- return e2;
- }
- }
-#endif
-
-
cs0 = sc->callSuper;
e1 = e1->semantic(sc);
e1 = resolveProperties(sc, e1);
@@ -12797,12 +12536,6 @@ Expression *CondExp::semantic(Scope *sc)
return this;
}
-int CondExp::checkCtorInit(Scope *sc)
-{
- return e1->checkCtorInit(sc) && e2->checkCtorInit(sc);
-}
-
-
int CondExp::isLvalue()
{
return e1->isLvalue() && e2->isLvalue();
@@ -12825,6 +12558,11 @@ Expression *CondExp::toLvalue(Scope *sc, Expression *ex)
return e;
}
+int CondExp::checkModifiable(Scope *sc, int flag)
+{
+ return e1->checkModifiable(sc, flag) && e2->checkModifiable(sc, flag);
+}
+
Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e)
{
//error("conditional expression %s is not a modifiable lvalue", toChars());
diff --git a/dmd2/expression.h b/dmd2/expression.h
index 40028dbb..1d28a95d 100644
--- a/dmd2/expression.h
+++ b/dmd2/expression.h
@@ -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);
diff --git a/dmd2/func.c b/dmd2/func.c
index 7a7b55bc..776252f3 100644
--- a/dmd2/func.c
+++ b/dmd2/func.c
@@ -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
}
}
diff --git a/dmd2/hdrgen.c b/dmd2/hdrgen.c
index 6ba45e2d..a1e288e8 100644
--- a/dmd2/hdrgen.c
+++ b/dmd2/hdrgen.c
@@ -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();
}
diff --git a/dmd2/hdrgen.h b/dmd2/hdrgen.h
index 19900fed..cce63383 100644
--- a/dmd2/hdrgen.h
+++ b/dmd2/hdrgen.h
@@ -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)); }
-};
-
-
+};
\ No newline at end of file
diff --git a/dmd2/idgen.c b/dmd2/idgen.c
index edd66bf9..eb156eb5 100644
--- a/dmd2/idgen.c
+++ b/dmd2/idgen.c
@@ -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.
diff --git a/dmd2/import.c b/dmd2/import.c
index 0d8a7b80..a9fecd1e 100644
--- a/dmd2/import.c
+++ b/dmd2/import.c
@@ -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);
diff --git a/dmd2/import.h b/dmd2/import.h
index a3ef1a55..5549a82b 100644
--- a/dmd2/import.h
+++ b/dmd2/import.h
@@ -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; }
};
diff --git a/dmd2/init.h b/dmd2/init.h
index ecc4c151..88db7487 100644
--- a/dmd2/init.h
+++ b/dmd2/init.h
@@ -123,7 +123,6 @@ struct ArrayInitializer : Initializer
#if IN_DMD
dt_t *toDt();
- dt_t *toDtBit(); // for bit arrays
#endif
ArrayInitializer *isArrayInitializer() { return this; }
diff --git a/dmd2/inline.c b/dmd2/inline.c
index 6198eb78..3b3313d6 100644
--- a/dmd2/inline.c
+++ b/dmd2/inline.c
@@ -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;
}
diff --git a/dmd2/interpret.c b/dmd2/interpret.c
index 49e456e7..d9284786 100644
--- a/dmd2/interpret.c
+++ b/dmd2/interpret.c
@@ -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;
diff --git a/dmd2/json.c b/dmd2/json.c
index fc4ca016..24503b07 100644
--- a/dmd2/json.c
+++ b/dmd2/json.c
@@ -1,6 +1,5 @@
-
// 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,92 +11,122 @@
#include
#include
-#include
-#include
#include
#include "rmem.h"
-#include "root.h"
-#include "mars.h"
#include "dsymbol.h"
-#include "macro.h"
#include "template.h"
-#include "lexer.h"
#include "aggregate.h"
#include "declaration.h"
#include "enum.h"
-#include "id.h"
#include "module.h"
-#include "scope.h"
-#include "hdrgen.h"
#include "json.h"
#include "mtype.h"
#include "attrib.h"
#include "cond.h"
+#include "init.h"
+#include "import.h"
+#include "id.h"
-const char Pname[] = "name";
-const char Pkind[] = "kind";
-const char Pfile[] = "file";
-const char Pline[] = "line";
-const char Ptype[] = "type";
-const char Pcomment[] = "comment";
-const char Pmembers[] = "members";
-const char Pprotection[] = "protection";
+struct JsonOut
+{
+ OutBuffer *buf;
+ int indentLevel;
+ const char *filename;
-void JsonRemoveComma(OutBuffer *buf);
+ JsonOut(OutBuffer *buf) {this->buf = buf; indentLevel = 0; filename = NULL;}
-void json_generate(Modules *modules)
-{ OutBuffer buf;
+ void indent();
+ void removeComma();
+ void comma();
+ void stringStart();
+ void stringEnd();
+ void stringPart(const char* part);
- buf.writestring("[\n");
+ void value(const char* s);
+ void value(int value);
+ void valueBool(bool value);
+
+ void item(const char*);
+ void item(int);
+ void itemBool(bool);
+
+
+ void arrayStart();
+ void arrayEnd();
+ void objectStart();
+ void objectEnd();
+
+ void propertyStart(const char* name);
+
+ void property(const char *name, const char* s);
+ void property(const char *name, int value);
+ void propertyBool(const char *name, bool value);
+ void propertyStorageClass(const char *name, StorageClass stc);
+ void property(const char *name, Loc* loc);
+ void property(const char *name, Type* type);
+ void property(const char *name, const char *deconame, Type* type);
+ void property(const char *name, Parameters* parameters);
+ void property(const char *name, Expressions* expressions);
+ void property(const char *name, enum TRUST trust);
+ void property(const char *name, enum PURE purity);
+ void property(const char *name, enum LINK linkage);
+};
+
+
+void json_generate(OutBuffer *buf, Modules *modules)
+{
+ JsonOut json(buf);
+
+ json.arrayStart();
for (size_t i = 0; i < modules->dim; i++)
{ Module *m = (*modules)[i];
if (global.params.verbose)
printf("json gen %s\n", m->toChars());
- m->toJsonBuffer(&buf);
- buf.writestring(",\n");
+ m->toJson(&json);
}
- JsonRemoveComma(&buf);
- buf.writestring("]\n");
-
- // Write buf to file
- char *arg = global.params.xfilename;
- if (!arg || !*arg)
- { // Generate lib file name from first obj name
- char *n = (*global.params.objfiles)[0];
-
- n = FileName::name(n);
- FileName *fn = FileName::forceExt(n, global.json_ext);
- arg = fn->toChars();
- }
- else if (arg[0] == '-' && arg[1] == 0)
- { // Write to stdout; assume it succeeds
- size_t n = fwrite(buf.data, 1, buf.offset, stdout);
- assert(n == buf.offset); // keep gcc happy about return values
- return;
- }
-// if (!FileName::absolute(arg))
-// arg = FileName::combine(dir, arg);
- FileName *jsonfilename = FileName::defaultExt(arg, global.json_ext);
- File *jsonfile = new File(jsonfilename);
- assert(jsonfile);
- jsonfile->setbuffer(buf.data, buf.offset);
- jsonfile->ref = 1;
- char *pt = FileName::path(jsonfile->toChars());
- if (*pt)
- FileName::ensurePathExists(pt);
- mem.free(pt);
- jsonfile->writev();
+ json.arrayEnd();
+ json.removeComma();
}
-/*********************************
- * Encode string into buf, and wrap it in double quotes.
- */
-void JsonString(OutBuffer *buf, const char *s)
+
+
+void JsonOut::indent()
+{
+ if (buf->offset >= 1 &&
+ buf->data[buf->offset - 1] == '\n')
+ for (int i = 0; i < indentLevel; i++)
+ buf->writeByte(' ');
+}
+
+void JsonOut::removeComma()
+{
+ if (buf->offset >= 2 &&
+ buf->data[buf->offset - 2] == ',' &&
+ (buf->data[buf->offset - 1] == '\n' || buf->data[buf->offset - 1] == ' '))
+ buf->offset -= 2;
+}
+
+void JsonOut::comma()
+{
+ if (indentLevel > 0)
+ buf->writestring(",\n");
+}
+
+void JsonOut::stringStart()
{
buf->writeByte('\"');
+}
+
+void JsonOut::stringEnd()
+{
+ buf->writeByte('\"');
+}
+
+void JsonOut::stringPart(const char *s)
+{
for (; *s; s++)
{
unsigned char c = (unsigned char) *s;
@@ -123,10 +152,6 @@ void JsonString(OutBuffer *buf, const char *s)
buf->writestring("\\\\");
break;
- case '/':
- buf->writestring("\\/");
- break;
-
case '\b':
buf->writestring("\\b");
break;
@@ -144,318 +169,923 @@ void JsonString(OutBuffer *buf, const char *s)
break;
}
}
- buf->writeByte('\"');
}
-void JsonProperty(OutBuffer *buf, const char *name, const char *value)
+
+// Json value functions
+
+/*********************************
+ * Encode string into buf, and wrap it in double quotes.
+ */
+void JsonOut::value(const char *s)
{
- JsonString(buf, name);
- buf->writestring(" : ");
- JsonString(buf, value);
- buf->writestring(",\n");
+ stringStart();
+ stringPart(s);
+ stringEnd();
}
-void JsonProperty(OutBuffer *buf, const char *name, int value)
+void JsonOut::value(int value)
{
- JsonString(buf, name);
- buf->writestring(" : ");
buf->printf("%d", value);
- buf->writestring(",\n");
}
-void JsonRemoveComma(OutBuffer *buf)
+void JsonOut::valueBool(bool value)
{
+ buf->writestring(value? "true" : "false");
+}
+
+/*********************************
+ * Item is an intented value and a comma, for use in arrays
+ */
+void JsonOut::item(const char *s)
+{
+ indent();
+ value(s);
+ comma();
+}
+
+void JsonOut::item(int i)
+{
+ indent();
+ value(i);
+ comma();
+}
+
+void JsonOut::itemBool(bool b)
+{
+ indent();
+ valueBool(b);
+ comma();
+}
+
+
+// Json array functions
+
+void JsonOut::arrayStart()
+{
+ indent();
+ buf->writestring("[\n");
+ indentLevel++;
+}
+
+void JsonOut::arrayEnd()
+{
+ indentLevel--;
+ removeComma();
if (buf->offset >= 2 &&
- buf->data[buf->offset - 2] == ',' &&
+ buf->data[buf->offset - 2] == '[' &&
buf->data[buf->offset - 1] == '\n')
- buf->offset -= 2;
+ buf->offset -= 1;
+ else if (!(buf->offset >= 1 &&
+ buf->data[buf->offset - 1] == '['))
+ {
+ buf->writestring("\n");
+ indent();
+ }
+ buf->writestring("]");
+ comma();
}
-void Dsymbol::toJsonBuffer(OutBuffer *buf)
-{
-}
-void Module::toJsonBuffer(OutBuffer *buf)
+// Json object functions
+
+void JsonOut::objectStart()
{
+ indent();
buf->writestring("{\n");
+ indentLevel++;
+}
- if (md)
- JsonProperty(buf, Pname, md->toChars());
+void JsonOut::objectEnd()
+{
+ indentLevel--;
+ removeComma();
+ if (buf->offset >= 2 &&
+ buf->data[buf->offset - 2] == '{' &&
+ buf->data[buf->offset - 1] == '\n')
+ buf->offset -= 1;
+ else
+ {
+ buf->writestring("\n");
+ indent();
+ }
+ buf->writestring("}");
+ comma();
+}
- JsonProperty(buf, Pkind, kind());
- JsonProperty(buf, Pfile, srcfile->toChars());
- if (comment)
- JsonProperty(buf, Pcomment, (const char *)comment);
+// Json object property functions
- JsonString(buf, Pmembers);
- buf->writestring(" : [\n");
+void JsonOut::propertyStart(const char *name)
+{
+ indent();
+ value(name);
+ buf->writestring(" : ");
+}
- size_t offset = buf->offset;
- for (size_t i = 0; i < members->dim; i++)
- { Dsymbol *s = (*members)[i];
- if (offset != buf->offset)
- { buf->writestring(",\n");
- offset = buf->offset;
+void JsonOut::property(const char *name, const char *s)
+{
+ if (s == NULL) return;
+
+ propertyStart(name);
+ value(s);
+ comma();
+}
+
+void JsonOut::property(const char *name, int i)
+{
+ propertyStart(name);
+ value(i);
+ comma();
+}
+
+void JsonOut::propertyBool(const char *name, bool b)
+{
+ propertyStart(name);
+ valueBool(b);
+ comma();
+}
+
+
+void JsonOut::property(const char *name, enum TRUST trust)
+{
+ switch (trust)
+ {
+ case TRUSTdefault:
+ // Should not be printed
+ //property(name, "default");
+ break;
+ case TRUSTsystem:
+ property(name, "system");
+ break;
+ case TRUSTtrusted:
+ property(name, "trusted");
+ break;
+ case TRUSTsafe:
+ property(name, "safe");
+ break;
+ default:
+ assert(false);
+ }
+}
+
+void JsonOut::property(const char *name, enum PURE purity)
+{
+ switch (purity)
+ {
+ case PUREimpure:
+ // Should not be printed
+ //property(name, "impure");
+ break;
+ case PUREweak:
+ property(name, "weak");
+ break;
+ case PUREconst:
+ property(name, "const");
+ break;
+ case PUREstrong:
+ property(name, "strong");
+ break;
+ case PUREfwdref:
+ property(name, "fwdref");
+ break;
+ default:
+ assert(false);
+ }
+}
+
+void JsonOut::property(const char *name, enum LINK linkage)
+{
+ switch (linkage)
+ {
+ case LINKdefault:
+ // Should not be printed
+ //property(name, "default");
+ break;
+ case LINKd:
+ // Should not be printed
+ //property(name, "d");
+ break;
+ case LINKc:
+ property(name, "c");
+ break;
+ case LINKcpp:
+ property(name, "cpp");
+ break;
+ case LINKwindows:
+ property(name, "windows");
+ break;
+ case LINKpascal:
+ property(name, "pascal");
+ break;
+ default:
+ assert(false);
+ }
+}
+
+void JsonOut::propertyStorageClass(const char *name, StorageClass stc)
+{
+ stc &= STCStorageClass;
+ if (stc)
+ {
+ propertyStart(name);
+ arrayStart();
+
+ while (stc)
+ { char tmp[20];
+ const char *p = StorageClassDeclaration::stcToChars(tmp, stc);
+ assert(p);
+ assert(strlen(p) < sizeof(tmp));
+ if (p[0] == '@')
+ {
+ indent();
+ stringStart();
+ buf->writestring(p);
+ stringEnd();
+ comma();
+ }
+ else
+ item(p);
}
- s->toJsonBuffer(buf);
+
+ arrayEnd();
+ }
+}
+
+void JsonOut::property(const char *name, Loc *loc)
+{
+ if (loc)
+ {
+ const char *filename = loc->filename;
+ if (filename)
+ {
+ if (!this->filename || strcmp(filename, this->filename))
+ { this->filename = filename;
+ property("file", filename);
+ }
+ }
+
+ if (loc->linnum)
+ property(name, loc->linnum);
+ }
+}
+
+void JsonOut::property(const char *name, Type *type)
+{
+ if (type)
+ {
+ property(name, type->toChars());
+ }
+}
+
+void JsonOut::property(const char *name, const char *deconame, Type *type)
+{
+ if (type)
+ {
+ if (type->deco)
+ property(deconame, type->deco);
+ else
+ property(name, type->toChars());
+ }
+}
+
+void JsonOut::property(const char *name, Parameters *parameters)
+{
+ if (parameters == NULL || parameters->dim == 0)
+ return;
+
+ propertyStart(name);
+ arrayStart();
+
+ if (parameters)
+ for (size_t i = 0; i < parameters->dim; i++)
+ { Parameter *p = (*parameters)[i];
+ objectStart();
+
+ if (p->ident)
+ property("name", p->ident->toChars());
+
+ property("type", "deco", p->type);
+
+ propertyStorageClass("storageClass", p->storageClass);
+
+ if (p->defaultArg)
+ property("default", p->defaultArg->toChars());
+
+
+ objectEnd();
+ }
+
+ arrayEnd();
+}
+
+/* ========================================================================== */
+
+void Type::toJson(JsonOut *json)
+{
+}
+
+void TypeSArray::toJson(JsonOut *json)
+{
+ json->property("elementType", next);
+ json->property("dim", dim->toChars());
+}
+
+void TypeDArray::toJson(JsonOut *json)
+{
+ json->property("elementType", next);
+}
+
+void TypeAArray::toJson(JsonOut *json)
+{
+ json->property("elementType", next);
+ json->property("index", index);
+}
+
+void TypePointer::toJson(JsonOut *json)
+{
+ json->property("targetType", next);
+}
+
+void TypeReference::toJson(JsonOut *json)
+{
+ json->property("targetType", next);
+}
+
+void TypeFunction::toJson(JsonOut *json)
+{
+ if (purity || isnothrow || isproperty || isref)
+ {
+ json->propertyStart("attributes");
+ json->arrayStart();
+ if (purity) json->item("pure");
+ if (isnothrow) json->item("nothrow");
+ if (isproperty) json->item("@property");
+ if (isref) json->item("ref");
+ json->arrayEnd();
}
- JsonRemoveComma(buf);
- buf->writestring("]\n");
+ json->property("trust", trust);
+ json->property("purity", purity);
+ json->property("linkage", linkage);
- buf->writestring("}\n");
+ json->property("returnType", next);
+ json->property("parameters", parameters);
}
-void AttribDeclaration::toJsonBuffer(OutBuffer *buf)
+void TypeDelegate::toJson(JsonOut *json)
{
- //printf("AttribDeclaration::toJsonBuffer()\n");
+ next->toJson(json); // next is TypeFunction
+}
+void TypeQualified::toJson(JsonOut *json) // ident.ident.ident.etc
+{
+ json->propertyStart("idents");
+ json->arrayStart();
+
+ for (size_t i = 0; i < idents.dim; i++)
+ { Identifier *ident = idents[i];
+ json->item(ident->toChars());
+ }
+
+ json->arrayEnd();
+}
+
+void TypeIdentifier::toJson(JsonOut *json)
+{
+ TypeQualified::toJson(json);
+ json->property("rawIdentifier", ident->toChars());
+ json->property("identifier", ident->toHChars2());
+}
+
+void TypeInstance::toJson(JsonOut *json)
+{
+ TypeQualified::toJson(json);
+ json->property("tempinst", tempinst->toChars());
+}
+
+void TypeTypeof::toJson(JsonOut *json)
+{
+ TypeQualified::toJson(json);
+ json->property("exp", exp->toChars());
+ json->property("type", exp->type);
+}
+
+void TypeReturn::toJson(JsonOut *json)
+{
+ TypeQualified::toJson(json);
+}
+
+void TypeStruct::toJson(JsonOut *json)
+{
+ json->propertyStorageClass("storageClass", sym->storage_class);
+}
+
+void TypeEnum::toJson(JsonOut *json)
+{
+ sym->jsonProperties(json);
+}
+
+void TypeTypedef::toJson(JsonOut *json)
+{
+ sym->jsonProperties(json);
+}
+
+void TypeClass::toJson(JsonOut *json)
+{
+ json->propertyStorageClass("storageClass", sym->storage_class);
+}
+
+void TypeTuple::toJson(JsonOut *json)
+{
+ json->property("arguments", arguments);
+}
+
+void TypeSlice::toJson(JsonOut *json)
+{
+ json->property("lower", lwr->toChars());
+ json->property("upper", upr->toChars());
+}
+
+void TypeNull::toJson(JsonOut *json) { }
+
+void TypeVector::toJson(JsonOut *json)
+{
+ json->property("basetype", basetype);
+}
+
+
+/* ========================================================================== */
+
+void Dsymbol::toJson(JsonOut *json)
+{
+#if 0
+ json->objectStart();
+ jsonProperties(json);
+ json->objectEnd();
+#endif
+}
+
+void Dsymbol::jsonProperties(JsonOut *json)
+{
+ json->property("name", toChars());
+ if (!isTemplateDeclaration()) // TemplateDeclaration::kind() acts weird sometimes
+ json->property("kind", kind());
+
+ if (prot() != PROTpublic)
+ json->property("protection", Pprotectionnames[prot()]);
+
+ json->property("comment", (const char *)comment);
+
+ json->property("line", &loc);
+
+#if 0
+ if (!isModule())
+ {
+ Module *module = getModule();
+ if (module)
+ {
+ json->propertyStart("module");
+ json->objectStart();
+ module->jsonProperties(json);
+ json->objectEnd();
+ }
+
+ Module *accessModule = getAccessModule();
+ if (accessModule && accessModule != module)
+ {
+ json->propertyStart("accessModule");
+ json->objectStart();
+ accessModule->jsonProperties(json);
+ json->objectEnd();
+ }
+ }
+#endif
+}
+
+void Module::toJson(JsonOut *json)
+{
+ json->objectStart();
+
+ if (md)
+ json->property("name", md->toChars());
+
+ json->property("kind", kind());
+
+ json->filename = srcfile->toChars();
+ json->property("file", json->filename);
+
+ json->property("comment", (const char *)comment);
+
+ json->propertyStart("members");
+ json->arrayStart();
+ for (size_t i = 0; i < members->dim; i++)
+ { Dsymbol *s = (*members)[i];
+ s->toJson(json);
+ }
+ json->arrayEnd();
+
+ json->objectEnd();
+}
+
+void Module::jsonProperties(JsonOut *json)
+{
+#if 0
+ Dsymbol::jsonProperties(json);
+
+ if (md && md->packages)
+ {
+ json->propertyStart("package");
+ json->arrayStart();
+ for (size_t i = 0; i < md->packages->dim; i++)
+ { Identifier *pid = (*md->packages)[i];
+ json->item(pid->toChars());
+ }
+ json->arrayEnd();
+ }
+
+ json->property("prettyName", toPrettyChars());
+#endif
+}
+
+void Import::toJson(JsonOut *json)
+{
+ if (id == Id::object)
+ return;
+
+ json->objectStart();
+
+ json->propertyStart("name");
+ json->stringStart();
+ if (packages && packages->dim)
+ {
+ for (size_t i = 0; i < packages->dim; i++)
+ { Identifier *pid = (*packages)[i];
+
+ json->stringPart(pid->toChars());
+ json->buf->writeByte('.');
+ }
+ }
+ json->stringPart(id->toChars());
+ json->stringEnd();
+ json->comma();
+
+ json->property("kind", kind());
+ json->property("comment", (const char *)comment);
+ json->property("line", &loc);
+ if (prot() != PROTpublic)
+ json->property("protection", Pprotectionnames[prot()]);
+ if (aliasId)
+ json->property("alias", aliasId->toChars());
+
+ bool hasRenamed = false;
+ bool hasSelective = false;
+ for (size_t i = 0; i < aliases.dim; i++)
+ { // avoid empty "renamed" and "selective" sections
+ if (hasRenamed && hasSelective)
+ break;
+ else if (aliases[i])
+ hasRenamed = true;
+ else
+ hasSelective = true;
+ }
+
+ if (hasRenamed)
+ {
+ // import foo : alias1 = target1;
+ json->propertyStart("renamed");
+ json->objectStart();
+ for (size_t i = 0; i < aliases.dim; i++)
+ {
+ Identifier *name = names[i];
+ Identifier *alias = aliases[i];
+ if (alias) json->property(alias->toChars(), name->toChars());
+ }
+ json->objectEnd();
+ }
+
+ if (hasSelective)
+ {
+ // import foo : target1;
+ json->propertyStart("selective");
+ json->arrayStart();
+ for (size_t i = 0; i < names.dim; i++)
+ {
+ Identifier *name = names[i];
+ if (!aliases[i]) json->item(name->toChars());
+ }
+ json->arrayEnd();
+ }
+
+ json->objectEnd();
+}
+
+void AttribDeclaration::toJson(JsonOut *json)
+{
Dsymbols *d = include(NULL, NULL);
if (d)
{
- size_t offset = buf->offset;
- for (unsigned i = 0; i < d->dim; i++)
+ for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
- //printf("AttribDeclaration::toJsonBuffer %s\n", s->toChars());
- if (offset != buf->offset)
- { buf->writestring(",\n");
- offset = buf->offset;
- }
- s->toJsonBuffer(buf);
+ s->toJson(json);
}
- JsonRemoveComma(buf);
}
}
-void ConditionalDeclaration::toJsonBuffer(OutBuffer *buf)
+void ConditionalDeclaration::toJson(JsonOut *json)
{
- //printf("ConditionalDeclaration::toJsonBuffer()\n");
if (condition->inc)
{
- AttribDeclaration::toJsonBuffer(buf);
+ AttribDeclaration::toJson(json);
}
}
-void InvariantDeclaration::toJsonBuffer(OutBuffer *buf) { }
-void DtorDeclaration::toJsonBuffer(OutBuffer *buf) { }
-void StaticCtorDeclaration::toJsonBuffer(OutBuffer *buf) { }
-void StaticDtorDeclaration::toJsonBuffer(OutBuffer *buf) { }
-void ClassInfoDeclaration::toJsonBuffer(OutBuffer *buf) { }
-void ModuleInfoDeclaration::toJsonBuffer(OutBuffer *buf) { }
-void TypeInfoDeclaration::toJsonBuffer(OutBuffer *buf) { }
-void UnitTestDeclaration::toJsonBuffer(OutBuffer *buf) { }
+void ClassInfoDeclaration::toJson(JsonOut *json) { }
+void ModuleInfoDeclaration::toJson(JsonOut *json) { }
+void TypeInfoDeclaration::toJson(JsonOut *json) { }
#if DMDV2
-void PostBlitDeclaration::toJsonBuffer(OutBuffer *buf) { }
+void PostBlitDeclaration::toJson(JsonOut *json) { }
#endif
-void Declaration::toJsonBuffer(OutBuffer *buf)
+
+void Declaration::toJson(JsonOut *json)
{
- //printf("Declaration::toJsonBuffer()\n");
- buf->writestring("{\n");
+ json->objectStart();
- JsonProperty(buf, Pname, toChars());
- JsonProperty(buf, Pkind, kind());
+ //json->property("unknown", "declaration");
- if (prot())
- JsonProperty(buf, Pprotection, Pprotectionnames[prot()]);
+ jsonProperties(json);
- if (type)
- JsonProperty(buf, Ptype, type->toChars());
-
- if (comment)
- JsonProperty(buf, Pcomment, (const char *)comment);
-
- if (loc.linnum)
- JsonProperty(buf, Pline, loc.linnum);
-
- TypedefDeclaration *td = isTypedefDeclaration();
- if (td)
- {
- JsonProperty(buf, "base", td->basetype->toChars());
- }
-
- JsonRemoveComma(buf);
- buf->writestring("}\n");
+ json->objectEnd();
}
-void AggregateDeclaration::toJsonBuffer(OutBuffer *buf)
+void Declaration::jsonProperties(JsonOut *json)
{
- //printf("AggregateDeclaration::toJsonBuffer()\n");
- buf->writestring("{\n");
+ Dsymbol::jsonProperties(json);
- JsonProperty(buf, Pname, toChars());
- JsonProperty(buf, Pkind, kind());
+ json->propertyStorageClass("storageClass", storage_class);
- if (prot())
- JsonProperty(buf, Pprotection, Pprotectionnames[prot()]);
+ json->property("type", "deco", type);
- if (comment)
- JsonProperty(buf, Pcomment, (const char *)comment);
+ // Emit originalType if it differs from type
+ if (type != originalType && originalType)
+ {
+ const char *ostr = originalType->toChars();
+ if (type)
+ { const char *tstr = type->toChars();
+ if (strcmp(tstr, ostr))
+ {
+ //printf("tstr = %s, ostr = %s\n", tstr, ostr);
+ json->property("originalType", ostr);
+ }
+ }
+ else
+ json->property("originalType", ostr);
+ }
+}
- if (loc.linnum)
- JsonProperty(buf, Pline, loc.linnum);
+void TypedefDeclaration::toJson(JsonOut *json)
+{
+ json->objectStart();
+
+ jsonProperties(json);
+
+ json->property("base", "baseDeco", basetype);
+
+ json->objectEnd();
+}
+
+void AggregateDeclaration::toJson(JsonOut *json)
+{
+ json->objectStart();
+
+ jsonProperties(json);
ClassDeclaration *cd = isClassDeclaration();
if (cd)
{
- if (cd->baseClass)
+ if (cd->baseClass && cd->baseClass->ident != Id::Object)
{
- JsonProperty(buf, "base", cd->baseClass->toChars());
+ json->property("base", cd->baseClass->toChars());
}
if (cd->interfaces_dim)
{
- JsonString(buf, "interfaces");
- buf->writestring(" : [\n");
- size_t offset = buf->offset;
+ json->propertyStart("interfaces");
+ json->arrayStart();
for (size_t i = 0; i < cd->interfaces_dim; i++)
{ BaseClass *b = cd->interfaces[i];
- if (offset != buf->offset)
- { buf->writestring(",\n");
- offset = buf->offset;
- }
- JsonString(buf, b->base->toChars());
+ json->item(b->base->toChars());
}
- JsonRemoveComma(buf);
- buf->writestring("],\n");
+ json->arrayEnd();
}
}
if (members)
{
- JsonString(buf, Pmembers);
- buf->writestring(" : [\n");
- size_t offset = buf->offset;
+ json->propertyStart("members");
+ json->arrayStart();
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
- if (offset != buf->offset)
- { buf->writestring(",\n");
- offset = buf->offset;
- }
- s->toJsonBuffer(buf);
+ s->toJson(json);
}
- JsonRemoveComma(buf);
- buf->writestring("]\n");
+ json->arrayEnd();
}
- JsonRemoveComma(buf);
- buf->writestring("}\n");
+ json->objectEnd();
}
-void TemplateDeclaration::toJsonBuffer(OutBuffer *buf)
+void FuncDeclaration::toJson(JsonOut *json)
{
- //printf("TemplateDeclaration::toJsonBuffer()\n");
+ json->objectStart();
- buf->writestring("{\n");
+ jsonProperties(json);
- JsonProperty(buf, Pname, toChars());
- JsonProperty(buf, Pkind, kind());
+ TypeFunction *tf = (TypeFunction *)type;
+ if (tf && tf->ty == Tfunction)
+ json->property("parameters", tf->parameters);
- if (prot())
- JsonProperty(buf, Pprotection, Pprotectionnames[prot()]);
+ json->property("endline", &endloc);
- if (comment)
- JsonProperty(buf, Pcomment, (const char *)comment);
+ if (foverrides.dim)
+ {
+ json->propertyStart("overrides");
+ json->arrayStart();
+ for (size_t i = 0; i < foverrides.dim; i++)
+ { FuncDeclaration *fd = foverrides[i];
+ json->item(fd->toPrettyChars());
+ }
+ json->arrayEnd();
+ }
- if (loc.linnum)
- JsonProperty(buf, Pline, loc.linnum);
+ if (fdrequire)
+ {
+ json->propertyStart("in");
+ fdrequire->toJson(json);
+ }
- JsonString(buf, Pmembers);
- buf->writestring(" : [\n");
- size_t offset = buf->offset;
+ if (fdensure)
+ {
+ json->propertyStart("out");
+ fdensure->toJson(json);
+ }
+
+ json->objectEnd();
+}
+
+void TemplateDeclaration::toJson(JsonOut *json)
+{
+ json->objectStart();
+
+ // TemplateDeclaration::kind returns the kind of its Aggregate onemember, if it is one
+ json->property("kind", "template");
+
+ jsonProperties(json);
+
+ json->propertyStart("parameters");
+ json->arrayStart();
+ for (size_t i = 0; i < parameters->dim; i++)
+ { TemplateParameter *s = (*parameters)[i];
+ json->objectStart();
+
+ json->property("name", s->ident->toChars());
+
+ TemplateTypeParameter *type = s->isTemplateTypeParameter();
+ if (type)
+ {
+#if DMDV2
+ if (s->isTemplateThisParameter())
+ json->property("kind", "this");
+ else
+#endif
+ json->property("kind", "type");
+
+ json->property("type", "deco", type->specType);
+
+ json->property("default", "defaultDeco", type->defaultType);
+ }
+
+ TemplateValueParameter *value = s->isTemplateValueParameter();
+ if (value)
+ {
+ json->property("kind", "value");
+
+ json->property("type", "deco", value->valType);
+
+ if (value->specValue)
+ json->property("specValue", value->specValue->toChars());
+
+ if (value->defaultValue)
+ json->property("defaultValue", value->defaultValue->toChars());
+ }
+
+ TemplateAliasParameter *alias = s->isTemplateAliasParameter();
+ if (alias)
+ {
+ json->property("kind", "alias");
+
+ json->property("type", "deco", alias->specType);
+
+ if (alias->specAlias)
+ json->property("specAlias", alias->specAlias->toChars());
+
+ if (alias->defaultAlias)
+ json->property("defaultAlias", alias->defaultAlias->toChars());
+ }
+
+ TemplateTupleParameter *tuple = s->isTemplateTupleParameter();
+ if (tuple)
+ {
+ json->property("kind", "tuple");
+ }
+
+ json->objectEnd();
+ }
+ json->arrayEnd();
+
+ json->propertyStart("members");
+ json->arrayStart();
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
- if (offset != buf->offset)
- { buf->writestring(",\n");
- offset = buf->offset;
- }
- s->toJsonBuffer(buf);
+ s->toJson(json);
}
- JsonRemoveComma(buf);
- buf->writestring("]\n");
+ json->arrayEnd();
- buf->writestring("}\n");
+ json->objectEnd();
}
-void EnumDeclaration::toJsonBuffer(OutBuffer *buf)
+void EnumDeclaration::toJson(JsonOut *json)
{
- //printf("EnumDeclaration::toJsonBuffer()\n");
if (isAnonymous())
{
if (members)
{
for (size_t i = 0; i < members->dim; i++)
- {
- Dsymbol *s = (*members)[i];
- s->toJsonBuffer(buf);
- buf->writestring(",\n");
+ { Dsymbol *s = (*members)[i];
+ s->toJson(json);
}
- JsonRemoveComma(buf);
}
return;
}
- buf->writestring("{\n");
+ json->objectStart();
- JsonProperty(buf, Pname, toChars());
- JsonProperty(buf, Pkind, kind());
+ jsonProperties(json);
- if (prot())
- JsonProperty(buf, Pprotection, Pprotectionnames[prot()]);
-
- if (comment)
- JsonProperty(buf, Pcomment, (const char *)comment);
-
- if (loc.linnum)
- JsonProperty(buf, Pline, loc.linnum);
-
- if (memtype)
- JsonProperty(buf, "base", memtype->toChars());
+ json->property("base", "baseDeco", memtype);
if (members)
{
- JsonString(buf, Pmembers);
- buf->writestring(" : [\n");
- size_t offset = buf->offset;
+ json->propertyStart("members");
+ json->arrayStart();
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
- if (offset != buf->offset)
- { buf->writestring(",\n");
- offset = buf->offset;
- }
- s->toJsonBuffer(buf);
+ s->toJson(json);
}
- JsonRemoveComma(buf);
- buf->writestring("]\n");
+ json->arrayEnd();
}
- JsonRemoveComma(buf);
- buf->writestring("}\n");
+ json->objectEnd();
}
-void EnumMember::toJsonBuffer(OutBuffer *buf)
+void EnumMember::toJson(JsonOut *json)
{
- //printf("EnumMember::toJsonBuffer()\n");
- buf->writestring("{\n");
+ json->objectStart();
- JsonProperty(buf, Pname, toChars());
- JsonProperty(buf, Pkind, kind());
+ jsonProperties(json);
- if (prot())
- JsonProperty(buf, Pprotection, Pprotectionnames[prot()]);
+ json->property("type", "deco", type);
- if (comment)
- JsonProperty(buf, Pcomment, (const char *)comment);
-
- if (loc.linnum)
- JsonProperty(buf, Pline, loc.linnum);
-
- JsonRemoveComma(buf);
- buf->writestring("}\n");
+ json->objectEnd();
}
+void VarDeclaration::toJson(JsonOut *json)
+{
+ json->objectStart();
+
+ jsonProperties(json);
+
+ if (init)
+ json->property("init", init->toChars());
+
+ if (storage_class & STCfield)
+ json->property("offset", offset);
+
+ if (alignment && alignment != STRUCTALIGN_DEFAULT)
+ json->property("align", alignment);
+
+ json->objectEnd();
+}
+
+void TemplateMixin::toJson(JsonOut *json)
+{
+ json->objectStart();
+
+ jsonProperties(json);
+
+ json->objectEnd();
+}
diff --git a/dmd2/json.h b/dmd2/json.h
index 2c7e2e60..4e80300d 100644
--- a/dmd2/json.h
+++ b/dmd2/json.h
@@ -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 */
diff --git a/dmd2/lexer.c b/dmd2/lexer.c
index a142ad78..2e53a992 100644
--- a/dmd2/lexer.c
+++ b/dmd2/lexer.c
@@ -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
diff --git a/dmd2/mangle.c b/dmd2/mangle.c
index 629a9315..3e627104 100644
--- a/dmd2/mangle.c
+++ b/dmd2/mangle.c
@@ -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);
diff --git a/dmd2/mars.c b/dmd2/mars.c
index 146b8bb4..cd06970f 100644
--- a/dmd2/mars.c
+++ b/dmd2/mars.c
@@ -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(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)
{
diff --git a/dmd2/mars.h b/dmd2/mars.h
index 62b2f52e..59e1f7f6 100644
--- a/dmd2/mars.h
+++ b/dmd2/mars.h
@@ -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
diff --git a/dmd2/module.c b/dmd2/module.c
index a3068dce..2cf024af 100644
--- a/dmd2/module.c
+++ b/dmd2/module.c
@@ -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
#include
-#if defined (__sun)
-#include
-#endif
-
-#if defined(_MSC_VER) || defined(__MINGW32__)
-#include
-#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