diff --git a/CMakeLists.txt b/CMakeLists.txt
index 03b9cf64..3bbb287f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -70,7 +70,9 @@ file(MAKE_DIRECTORY
${PROJECT_BINARY_DIR}/${DMDFE_PATH}
)
-if(MSVC)
+if(UNIX)
+ ENABLE_LANGUAGE(ASM)
+elseif(MSVC)
ENABLE_LANGUAGE(ASM_MASM)
endif()
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 7193296c..f0b3298c 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();
@@ -959,7 +973,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();
};
@@ -1012,12 +1026,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; }
};
@@ -1037,7 +1051,6 @@ struct DtorDeclaration : FuncDeclaration
int addPostInvariant();
int overloadInsert(Dsymbol *s);
void emitComment(Scope *sc);
- void toJsonBuffer(OutBuffer *buf);
DtorDeclaration *isDtorDeclaration() { return this; }
};
@@ -1054,7 +1067,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; }
@@ -1084,7 +1096,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; }
@@ -1110,7 +1121,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; }
@@ -1126,7 +1136,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..9fd2eb1c 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
@@ -2696,7 +2640,12 @@ void realToMangleBuffer(OutBuffer *buf, real_t value)
buf->writestring("NAN"); // no -NAN bugs
else
{
+#if IN_LLVM
+ // The buffer is too small for a longdouble on PPC.
+ char buffer[36];
+#else
char buffer[32];
+#endif
int n = ld_sprint(buffer, 'A', value);
assert(n > 0 && n < sizeof(buffer));
for (int i = 0; i < n; i++)
@@ -2995,16 +2944,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 +3063,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 +3197,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 +3248,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 +3287,6 @@ int ThisExp::isLvalue()
return 1;
}
-
Expression *ThisExp::toLvalue(Scope *sc, Expression *e)
{
return this;
@@ -3391,7 +3295,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 +3359,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 +3725,6 @@ int StringExp::isLvalue()
return 0;
}
-
Expression *StringExp::toLvalue(Scope *sc, Expression *e)
{
//printf("StringExp::toLvalue(%s)\n", toChars());
@@ -4221,6 +4129,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 +4137,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 +4221,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 +4287,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 +4666,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 +4686,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 +5070,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 +5100,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 +5140,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 +5147,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 +5161,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 +5184,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 +5660,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 +5933,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 +6333,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();
@@ -6536,10 +6414,10 @@ Expression *BinAssignExp::semantic(Scope *sc)
}
if (shift)
{
-#if IN_DMD
- e2 = e2->castTo(sc, Type::tshiftcnt);
-#elif IN_LLVM
+#if IN_LLVM
e2 = e2->castTo(sc, e1->type);
+#else
+ e2 = e2->castTo(sc, Type::tshiftcnt);
#endif
}
@@ -6612,6 +6490,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 +6551,8 @@ FileExp::FileExp(Loc loc, Expression *e)
}
Expression *FileExp::semantic(Scope *sc)
-{ char *name;
+{
+ const char *name;
StringExp *se;
#if LOGSEMANTIC
@@ -6819,18 +6699,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 +6744,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 +7137,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 +7196,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 +7243,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 +7261,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 +7638,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 +7765,6 @@ Expression *CallExp::semantic(Scope *sc)
if (e)
return e;
-#if 1
/* This recognizes:
* foo!(tiargs)(funcargs)
*/
@@ -7953,17 +7808,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 +7824,8 @@ Ldotti:
{
e1 = e1->semantic(sc);
}
-#endif
}
}
-#endif
istemp = 0;
Lagain:
@@ -8055,8 +7897,6 @@ Lagain:
e1 = ve;
}
}
-
-
}
#else
else if (e1->op == TOKsymoff && ((SymOffExp *)e1)->hasOverloads)
@@ -8066,7 +7906,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 +7928,6 @@ Lagain:
e1 = new DotTemplateExp(loc,de->e1,te->td);
}
}
-#endif
}
t1 = NULL;
@@ -8104,6 +7942,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 +7983,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 +8091,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 +8143,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 +8178,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 +8188,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 +8218,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 +8228,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 +8510,6 @@ int CallExp::isLvalue()
return 0;
}
-
Expression *CallExp::toLvalue(Scope *sc, Expression *e)
{
if (isLvalue())
@@ -8997,16 +8801,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 +8808,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 +9155,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 +9418,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 +9611,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 +9810,6 @@ int ArrayExp::isLvalue()
return 1;
}
-
Expression *ArrayExp::toLvalue(Scope *sc, Expression *e)
{
if (type && type->toBasetype()->ty == Tvoid)
@@ -10090,24 +9890,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 +9956,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 +9997,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 +10018,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 +10096,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 +10108,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 +10130,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 +10556,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 +10637,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 +10654,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 +10685,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 +10783,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 +10799,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 +11378,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 +11392,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);
@@ -12009,8 +11801,11 @@ Expression *ShlExp::semantic(Scope *sc)
e2->type->toBasetype()->ty == Tvector)
return incompatibleTypes();
e1 = e1->integralPromotions(sc);
- //e2 = e2->castTo(sc, Type::tshiftcnt);
- e2 = e2->castTo(sc, e1->type); // LDC
+#if IN_LLVM
+ e2 = e2->castTo(sc, e1->type);
+#else
+ e2 = e2->castTo(sc, Type::tshiftcnt);
+#endif
type = e1->type;
}
return this;
@@ -12037,8 +11832,11 @@ Expression *ShrExp::semantic(Scope *sc)
e2->type->toBasetype()->ty == Tvector)
return incompatibleTypes();
e1 = e1->integralPromotions(sc);
- //e2 = e2->castTo(sc, Type::tshiftcnt);
- e2 = e2->castTo(sc, e1->type); // LDC
+#if IN_LLVM
+ e2 = e2->castTo(sc, e1->type);
+#else
+ e2 = e2->castTo(sc, Type::tshiftcnt);
+#endif
type = e1->type;
}
return this;
@@ -12065,8 +11863,11 @@ Expression *UshrExp::semantic(Scope *sc)
e2->type->toBasetype()->ty == Tvector)
return incompatibleTypes();
e1 = e1->integralPromotions(sc);
- //e2 = e2->castTo(sc, Type::tshiftcnt);
- e2 = e2->castTo(sc, e1->type); // LDC
+#if IN_LLVM
+ e2 = e2->castTo(sc, e1->type);
+#else
+ e2 = e2->castTo(sc, Type::tshiftcnt);
+#endif
type = e1->type;
}
return this;
@@ -12431,28 +12232,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 +12257,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 +12500,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 +12550,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 +12572,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 2f43947c..55b30f84 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)
@@ -430,7 +426,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
@@ -547,8 +543,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());
@@ -558,28 +569,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;
@@ -692,9 +695,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");
}
@@ -1031,9 +1040,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
@@ -1073,17 +1079,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
@@ -1245,10 +1246,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();
@@ -1294,10 +1293,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)
@@ -1346,7 +1343,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)
@@ -1415,11 +1412,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())
@@ -1450,6 +1443,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;
@@ -1473,7 +1480,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
@@ -1749,15 +1759,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;
@@ -1783,7 +1784,6 @@ void FuncDeclaration::semantic3(Scope *sc)
flags &= ~FUNCFLAGnothrowInprocess;
#endif
-#if 1
if (isSynchronized())
{ /* Wrap the entire function body in a synchronized statement
*/
@@ -1792,8 +1792,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;
@@ -1801,7 +1805,6 @@ void FuncDeclaration::semantic3(Scope *sc)
*/
}
else
-#endif
{
Expression *vsync;
if (isStatic())
@@ -1822,7 +1825,6 @@ void FuncDeclaration::semantic3(Scope *sc)
error("synchronized function %s must be a member of a class", toChars());
}
}
-#endif
}
sc2->callSuper = 0;
@@ -1834,19 +1836,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)
@@ -1869,13 +1880,88 @@ 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 &&
+#if IN_LLVM
+ !global.params.hdrKeepAllBodies
+#else
+ global.params.useInline == 0
+#endif
+ )
+ buf->writestring(";");
+ else
+ bodyToCBuffer(buf, hgs);
+ }
+ else
+ bodyToCBuffer(buf, hgs);
+ buf->writenl();
}
VarDeclaration *FuncDeclaration::declareThis(Scope *sc, AggregateDeclaration *ad)
@@ -1886,43 +1972,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);
@@ -1970,21 +2028,33 @@ 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 ||
+#if IN_LLVM
+ global.params.hdrKeepAllBodies ||
+#else
+ global.params.useInline ||
+#endif
+ 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());
@@ -1995,7 +2065,8 @@ void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
}
if (frequire || fensure)
- { buf->writestring("body");
+ {
+ buf->writestring("body");
buf->writenl();
}
@@ -2006,6 +2077,9 @@ void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->level--;
buf->writebyte('}');
buf->writenl();
+
+ hgs->tpltMember = savetlpt;
+ hgs->autoMember = saveauto;
}
else
{ buf->writeByte(';');
@@ -2655,6 +2729,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)
{
@@ -2705,15 +2801,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
@@ -3145,6 +3249,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))
@@ -3318,14 +3424,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();
@@ -3333,13 +3449,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
@@ -3350,6 +3488,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
@@ -3362,12 +3546,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
@@ -3391,7 +3577,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();
@@ -3401,26 +3591,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)
{
@@ -3611,10 +3797,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--;
+ }
}
@@ -3677,22 +3884,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);
@@ -3980,9 +4173,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
}
}
@@ -4014,7 +4204,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;
}
@@ -4117,9 +4308,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 8b71d3f8..25b97eae 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..5645093a 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
@@ -284,6 +282,11 @@ struct Param
char *exefile;
char *mapfile;
#if IN_LLVM
+ // Whether to keep all function bodies in .di file generation or to strip
+ // those of plain functions. For DMD, this is govenered by the -inline
+ // flag, which does not directly translate to LDC.
+ bool hdrKeepAllBodies;
+
// LDC stuff
OUTPUTFLAG output_ll;
OUTPUTFLAG output_bc;
diff --git a/dmd2/module.c b/dmd2/module.c
index a3068dce..77b8aea0 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
@@ -85,10 +66,9 @@ void Module::init()
Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen)
: Package(ident)
{
- FileName *srcfilename;
+ const char *srcfilename;
#if IN_DMD
- FileName *objfilename;
- FileName *symfilename;
+ const char *symfilename;
#endif
// printf("Module::Module(filename = '%s', ident = '%s')\n", filename, ident->toChars());
@@ -99,9 +79,6 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
members = NULL;
isDocFile = 0;
needmoduleinfo = 0;
-#ifdef IN_GCC
- strictlyneedmoduleinfo = 0;
-#endif
selfimports = 0;
insearch = 0;
searchCacheIdent = NULL;
@@ -150,61 +127,27 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
namelen = 0;
srcfilename = FileName::defaultExt(filename, global.mars_ext);
- if (!srcfilename->equalsExt(global.mars_ext) &&
- !srcfilename->equalsExt(global.hdr_ext) &&
- !srcfilename->equalsExt("dd"))
+ if (!FileName::equalsExt(srcfilename, global.mars_ext) &&
+ !FileName::equalsExt(srcfilename, global.hdr_ext) &&
+ !FileName::equalsExt(srcfilename, "dd"))
{
- error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.mars_ext);
+ error("source file name '%s' must have .%s extension", srcfilename, global.mars_ext);
fatal();
}
-#if !IN_LLVM
- char *argobj;
- if (global.params.objname)
- argobj = global.params.objname;
-#if 0
- else if (global.params.preservePaths)
- argobj = filename;
- else
- argobj = FileName::name(filename);
- if (!FileName::absolute(argobj))
- {
- argobj = FileName::combine(global.params.objdir, argobj);
- }
-#else // Bugzilla 3547
- else
- {
- if (global.params.preservePaths)
- argobj = filename;
- else
- argobj = FileName::name(filename);
- if (!FileName::absolute(argobj))
- {
- argobj = FileName::combine(global.params.objdir, argobj);
- }
- }
-#endif
+ srcfile = new File(srcfilename);
- if (global.params.objname)
- objfilename = new FileName(argobj);
- else
- objfilename = FileName::forceExt(argobj, global.obj_ext);
+#if IN_DMD
+ objfile = setOutfile(global.params.objname, global.params.objdir, filename, global.obj_ext);
symfilename = FileName::forceExt(filename, global.sym_ext);
-#endif
- srcfile = new File(srcfilename);
-#if IN_DMD
if (doDocComment)
- {
setDocfile();
- }
if (doHdrGen)
- {
- setHdrfile();
- }
+ hdrfile = setOutfile(global.params.hdrname, global.params.hdrdir, arg, global.hdr_ext);
- objfile = new File(objfilename);
+ //objfile = new File(objfilename);
symfile = new File(symfilename);
#endif
#if IN_LLVM
@@ -263,8 +206,8 @@ File* Module::buildFilePath(const char* forcename, const char* path, const char*
// else
// allow for .o and .obj on windows
#if _WIN32
- if (ext == global.params.objdir && FileName::ext(argobj)
- && stricmp(FileName::ext(argobj), global.obj_ext_alt) == 0)
+ if (ext == global.params.objdir && FileName::ext(argobj)
+ && Port::stricmp(FileName::ext(argobj), global.obj_ext_alt) == 0)
return new File((char*)argobj);
#endif
return new File(FileName::forceExt(argobj, ext));
@@ -273,58 +216,50 @@ File* Module::buildFilePath(const char* forcename, const char* path, const char*
#if IN_DMD
void Module::setDocfile()
{
- FileName *docfilename;
- char *argdoc;
-
- if (global.params.docname)
- argdoc = global.params.docname;
- else if (global.params.preservePaths)
- argdoc = (char *)arg;
- else
- argdoc = FileName::name((char *)arg);
- if (!FileName::absolute(argdoc))
- { //FileName::ensurePathExists(global.params.docdir);
- argdoc = FileName::combine(global.params.docdir, argdoc);
- }
- if (global.params.docname)
- docfilename = new FileName(argdoc);
- else
- docfilename = FileName::forceExt(argdoc, global.doc_ext);
-
- if (docfilename->equals(srcfile->name))
- { error("Source file and documentation file have same name '%s'", srcfile->name->str);
- fatal();
- }
-
- docfile = new File(docfilename);
+ docfile = setOutfile(global.params.docname, global.params.docdir, arg, global.doc_ext);
}
-void Module::setHdrfile()
+/*********************************************
+ * Combines things into output file name for .html and .di files.
+ * Input:
+ * name Command line name given for the file, NULL if none
+ * dir Command line directory given for the file, NULL if none
+ * arg Name of the source file
+ * ext File name extension to use if 'name' is NULL
+ * global.params.preservePaths get output path from arg
+ * srcfile Input file - output file name must not match input file
+ */
+
+File *Module::setOutfile(const char *name, const char *dir, const char *arg, const char *ext)
{
- FileName *hdrfilename;
- char *arghdr;
+ const char *docfilename;
- if (global.params.hdrname)
- arghdr = global.params.hdrname;
- else if (global.params.preservePaths)
- arghdr = (char *)arg;
- else
- arghdr = FileName::name((char *)arg);
- if (!FileName::absolute(arghdr))
- { //FileName::ensurePathExists(global.params.hdrdir);
- arghdr = FileName::combine(global.params.hdrdir, arghdr);
+ if (name)
+ {
+ docfilename = name;
}
- if (global.params.hdrname)
- hdrfilename = new FileName(arghdr);
else
- hdrfilename = FileName::forceExt(arghdr, global.hdr_ext);
+ {
+ const char *argdoc;
+ if (global.params.preservePaths)
+ argdoc = arg;
+ else
+ argdoc = FileName::name(arg);
- if (hdrfilename->equals(srcfile->name))
- { error("Source file and 'header' file have same name '%s'", srcfile->name->str);
+ // If argdoc doesn't have an absolute path, make it relative to dir
+ if (!FileName::absolute(argdoc))
+ { //FileName::ensurePathExists(dir);
+ argdoc = FileName::combine(dir, argdoc);
+ }
+ docfilename = FileName::forceExt(argdoc, ext);
+ }
+
+ if (FileName::equals(docfilename, srcfile->name->str))
+ { error("Source file and output file have same name '%s'", srcfile->name->str);
fatal();
}
- hdrfile = new File(hdrfilename);
+ return new File(docfilename);
}
#endif
@@ -361,7 +296,7 @@ void Module::buildTargetFiles(bool singleObj)
global.params.targetTriple.isOSWindows() ? global.obj_ext_alt : global.obj_ext);
else if (global.params.output_bc)
objfile = Module::buildFilePath(global.params.objname, global.params.objdir, global.bc_ext);
- else if (global.params.output_ll)
+ else if (global.params.output_ll)
objfile = Module::buildFilePath(global.params.objname, global.params.objdir, global.ll_ext);
else if (global.params.output_s)
objfile = Module::buildFilePath(global.params.objname, global.params.objdir, global.s_ext);
@@ -372,17 +307,17 @@ void Module::buildTargetFiles(bool singleObj)
hdrfile = Module::buildFilePath(global.params.hdrname, global.params.hdrdir, global.hdr_ext);
// safety check: never allow obj, doc or hdr file to have the source file's name
- if(stricmp(FileName::name(objfile->name->str), FileName::name((char*)this->arg)) == 0)
+ if(Port::stricmp(FileName::name(objfile->name->str), FileName::name((char*)this->arg)) == 0)
{
error("Output object files with the same name as the source file are forbidden");
fatal();
}
- if(docfile && stricmp(FileName::name(docfile->name->str), FileName::name((char*)this->arg)) == 0)
+ if(docfile && Port::stricmp(FileName::name(docfile->name->str), FileName::name((char*)this->arg)) == 0)
{
error("Output doc files with the same name as the source file are forbidden");
fatal();
}
- if(hdrfile && stricmp(FileName::name(hdrfile->name->str), FileName::name((char*)this->arg)) == 0)
+ if(hdrfile && Port::stricmp(FileName::name(hdrfile->name->str), FileName::name((char*)this->arg)) == 0)
{
error("Output header files with the same name as the source file are forbidden");
fatal();
@@ -457,11 +392,11 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
/* Search along global.path for .di file, then .d file.
*/
- char *result = NULL;
- FileName *fdi = FileName::forceExt(filename, global.hdr_ext);
- FileName *fd = FileName::forceExt(filename, global.mars_ext);
- char *sdi = fdi->toChars();
- char *sd = fd->toChars();
+ const char *result = NULL;
+ const char *fdi = FileName::forceExt(filename, global.hdr_ext);
+ const char *fd = FileName::forceExt(filename, global.mars_ext);
+ const char *sdi = fdi;
+ const char *sd = fd;
if (FileName::exists(sdi))
result = sdi;
@@ -475,19 +410,19 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
{
for (size_t i = 0; i < global.path->dim; i++)
{
- char *p = (*global.path)[i];
- char *n = FileName::combine(p, sdi);
+ const char *p = (*global.path)[i];
+ const char *n = FileName::combine(p, sdi);
if (FileName::exists(n))
{ result = n;
break;
}
- mem.free(n);
+ FileName::free(n);
n = FileName::combine(p, sd);
if (FileName::exists(n))
{ result = n;
break;
}
- mem.free(n);
+ FileName::free(n);
}
}
if (result)
@@ -815,7 +750,9 @@ void Module::parse()
{
comment = buf + 4;
isDocFile = 1;
-#if IN_DMD
+#if IN_LLVM
+ doDocComment = true;
+#else
if (!docfile)
setDocfile();
#endif
@@ -1395,15 +1332,12 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package
dst = ((Package *)p)->symtab;
if (ppkg && !*ppkg)
*ppkg = (Package *)p;
-#if TARGET_NET
-#else
if (p->isModule())
{ // Return the module so that a nice error message can be generated
if (ppkg)
*ppkg = (Package *)p;
break;
}
-#endif
}
if (pparent)
{
diff --git a/dmd2/module.h b/dmd2/module.h
index dabd3a83..b80a756f 100644
--- a/dmd2/module.h
+++ b/dmd2/module.h
@@ -81,9 +81,6 @@ struct Module : Package
unsigned numlines; // number of lines in source file
int isDocFile; // if it is a documentation input file, not D source
int needmoduleinfo;
-#ifdef IN_GCC
- int strictlyneedmoduleinfo;
-#endif
int selfimports; // 0: don't know, 1: does not, 2: does
int selfImports(); // returns !=0 if module imports itself
@@ -132,9 +129,11 @@ struct Module : Package
static Module *load(Loc loc, Identifiers *packages, Identifier *ident);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
- void toJsonBuffer(OutBuffer *buf);
+ void toJson(JsonOut *json);
+ void jsonProperties(JsonOut *json);
const char *kind();
#if !IN_LLVM
+ File *setOutfile(const char *name, const char *dir, const char *arg, const char *ext);
void setDocfile(); // set docfile member
#endif
bool read(Loc loc); // read file, returns 'true' if succeed, 'false' otherwise.
@@ -148,9 +147,6 @@ struct Module : Package
void semantic2(Scope* unused_sc = NULL); // pass 2 semantic analysis
void semantic3(Scope* unused_sc = NULL); // pass 3 semantic analysis
void inlineScan(); // scan for functions to inline
-#if !IN_LLVM
- void setHdrfile(); // set hdrfile member
-#endif
void genhdrfile(); // generate D import file
// void gensymfile();
void gendocfile();
diff --git a/dmd2/mtype.c b/dmd2/mtype.c
index 6b8786f1..1cd6c2ba 100644
--- a/dmd2/mtype.c
+++ b/dmd2/mtype.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/mtype.c
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
@@ -12,16 +11,11 @@
#define __C99FEATURES__ 1 // Needed on Solaris for NaN and more
#define __USE_ISOC99 1 // so signbit() gets defined
-#if defined (__sun)
-#include
-#endif
-
#ifdef __DMC__
#include
#else
#include
#endif
-
#include
#include
#include
@@ -136,6 +130,7 @@ TemplateDeclaration *Type::rtinfo;
Type *Type::tvoidptr;
Type *Type::tstring;
+Type *Type::tvalist;
Type *Type::basic[TMAX];
unsigned char Type::mangleChar[TMAX];
unsigned short Type::sizeTy[TMAX];
@@ -172,6 +167,12 @@ Type::Type(TY ty)
#endif
}
+const char *Type::kind()
+{
+ assert(false); // should be overridden
+ return NULL;
+}
+
Type *Type::syntaxCopy()
{
print();
@@ -315,6 +316,7 @@ void Type::init()
tvoidptr = tvoid->pointerTo();
tstring = tchar->invariantOf()->arrayOf();
+ tvalist = tvoid->pointerTo();
#if IN_DMD
if (global.params.is64bit)
@@ -1370,28 +1372,13 @@ Type *Type::aliasthisOf()
FuncDeclaration *fd = (FuncDeclaration *)d;
Expression *ethis = this->defaultInit(0);
fd = fd->overloadResolve(0, ethis, NULL, 1);
- if (fd)
- { TypeFunction *tf = (TypeFunction *)fd->type;
- if (!tf->next && fd->inferRetType)
- {
- TemplateInstance *spec = fd->isSpeculative();
- int olderrs = global.errors;
- // If it isn't speculative, we need to show errors
- unsigned oldgag = global.gag;
- if (global.gag && !spec)
- global.gag = 0;
- fd->semantic3(fd->scope);
- global.gag = oldgag;
- // Update the template instantiation with the number
- // of errors which occured.
- if (spec && global.errors != olderrs)
- spec->errors = global.errors - olderrs;
- tf = (TypeFunction *)fd->type;
- }
- t = tf->next;
- if (tf->isWild())
- t = t->substWildTo(mod == 0 ? MODmutable : mod);
+ if (fd && fd->functionSemantic())
+ {
+ t = fd->type->nextOf();
+ t = t->substWildTo(mod == 0 ? MODmutable : mod);
}
+ else
+ return Type::terror;
}
return t;
}
@@ -1406,26 +1393,14 @@ Type *Type::aliasthisOf()
{ assert(td->scope);
Expression *ethis = defaultInit(0);
FuncDeclaration *fd = td->deduceFunctionTemplate(td->scope, 0, NULL, ethis, NULL, 1);
- if (fd)
+ if (fd && fd->functionSemantic())
{
- //if (!fd->type->nextOf() && fd->inferRetType)
- {
- TemplateInstance *spec = fd->isSpeculative();
- int olderrs = global.errors;
- fd->semantic3(fd->scope);
- // Update the template instantiation with the number
- // of errors which occured.
- if (spec && global.errors != olderrs)
- spec->errors = global.errors - olderrs;
- }
- if (!fd->errors)
- {
- Type *t = fd->type->nextOf();
- t = t->substWildTo(mod == 0 ? MODmutable : mod);
- return t;
- }
+ Type *t = fd->type->nextOf();
+ t = t->substWildTo(mod == 0 ? MODmutable : mod);
+ return t;
}
- return Type::terror;
+ else
+ return Type::terror;
}
//printf("%s\n", ad->aliasthis->kind());
}
@@ -1592,7 +1567,7 @@ void MODtoDecoBuffer(OutBuffer *buf, unsigned char mod)
}
/*********************************
- * Name for mod.
+ * Store modifier name into buf.
*/
void MODtoBuffer(OutBuffer *buf, unsigned char mod)
{
@@ -1626,6 +1601,18 @@ void MODtoBuffer(OutBuffer *buf, unsigned char mod)
}
}
+
+/*********************************
+ * Return modifier name.
+ */
+char *MODtoChars(unsigned char mod)
+{
+ OutBuffer buf;
+ MODtoBuffer(&buf, mod);
+ buf.writebyte(0);
+ return buf.extractData();
+}
+
/********************************
* Name mangling.
* Input:
@@ -1699,6 +1686,9 @@ void Type::toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod)
}
}
+/*********************************
+ * Store this type's modifier name into buf.
+ */
void Type::modToBuffer(OutBuffer *buf)
{
if (mod)
@@ -1708,6 +1698,17 @@ void Type::modToBuffer(OutBuffer *buf)
}
}
+/*********************************
+ * Return this type's modifier name.
+ */
+char *Type::modToChars()
+{
+ OutBuffer buf;
+ modToBuffer(&buf);
+ buf.writebyte(0);
+ return buf.extractData();
+}
+
/************************************
*/
@@ -1719,7 +1720,7 @@ Type *Type::merge()
if (ty == Tinstance) return this;
if (ty == Taarray && !((TypeAArray *)this)->index->merge()->deco)
return this;
- if (nextOf() && !nextOf()->merge()->deco)
+ if (nextOf() && !nextOf()->deco)
return this;
//printf("merge(%s)\n", toChars());
@@ -1847,13 +1848,14 @@ int Type::isString()
}
/**************************
+ * When T is mutable,
* Given:
* T a, b;
- * Can we assign:
+ * Can we bitwise assign:
* a = b;
* ?
*/
-int Type::isAssignable(int blit)
+int Type::isAssignable()
{
return TRUE;
}
@@ -2289,9 +2291,6 @@ Identifier *Type::getTypeInfoIdent(int internal)
{
// _init_10TypeInfo_%s
OutBuffer buf;
- Identifier *id;
- char *name;
- size_t len;
if (internal)
{ buf.writeByte(mangleChar[ty]);
@@ -2300,21 +2299,29 @@ Identifier *Type::getTypeInfoIdent(int internal)
}
else
toDecoBuffer(&buf, 0, true);
- len = buf.offset;
- name = (char *)alloca(19 + sizeof(len) * 3 + len + 1);
+
+ size_t len = buf.offset;
buf.writeByte(0);
-#if TARGET_OSX
- // The LINKc will prepend the _
- sprintf(name, "D%dTypeInfo_%s6__initZ", 9 + len, buf.data);
-#else
+
+ // Allocate buffer on stack, fail over to using malloc()
+ char namebuf[40];
+ size_t namelen = 19 + sizeof(len) * 3 + len + 1;
+ char *name = namelen <= sizeof(namebuf) ? namebuf : (char *)malloc(namelen);
+ assert(name);
+
sprintf(name, "_D%dTypeInfo_%s6__initZ", 9 + len, buf.data);
-#endif
-#if !IN_LLVM
- if (global.params.isWindows && !global.params.is64bit)
- name++; // C mangling will add it back in
-#endif
//printf("name = %s\n", name);
- id = Lexer::idPool(name);
+ assert(strlen(name) < namelen); // don't overflow the buffer
+
+ size_t off = 0;
+#if !IN_LLVM
+ if (global.params.isOSX || global.params.isWindows && !global.params.is64bit)
+ ++off; // C mangling will add '_' back in
+#endif
+ Identifier *id = Lexer::idPool(name + off);
+
+ if (name != namebuf)
+ free(name);
return id;
}
@@ -2815,6 +2822,11 @@ TypeBasic::TypeBasic(TY ty)
merge();
}
+const char *TypeBasic::kind()
+{
+ return dstring;
+}
+
Type *TypeBasic::syntaxCopy()
{
// No semantic analysis done on basic types, no need to copy
@@ -3496,6 +3508,11 @@ TypeVector::TypeVector(Loc loc, Type *basetype)
this->basetype = basetype;
}
+const char *TypeVector::kind()
+{
+ return "vector";
+}
+
Type *TypeVector::syntaxCopy()
{
return new TypeVector(0, basetype->syntaxCopy());
@@ -3842,6 +3859,11 @@ TypeSArray::TypeSArray(Type *t, Expression *dim)
this->dim = dim;
}
+const char *TypeSArray::kind()
+{
+ return "sarray";
+}
+
Type *TypeSArray::syntaxCopy()
{
Type *t = next->syntaxCopy();
@@ -4163,11 +4185,19 @@ Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
#endif
if (ident == Id::length)
{
- e = dim;
+ Loc oldLoc = e->loc;
+ e = dim->copy();
+ e->loc = oldLoc;
}
else if (ident == Id::ptr)
{
- e = e->castTo(sc, next->pointerTo());
+ if (size(e->loc) == 0)
+ e = new NullExp(e->loc, next->pointerTo());
+ else
+ {
+ e = new IndexExp(e->loc, e, new IntegerExp(0));
+ e = new AddrExp(e->loc, e);
+ }
}
else
{
@@ -4343,6 +4373,11 @@ TypeDArray::TypeDArray(Type *t)
//printf("TypeDArray(t = %p)\n", t);
}
+const char *TypeDArray::kind()
+{
+ return "darray";
+}
+
Type *TypeDArray::syntaxCopy()
{
Type *t = next->syntaxCopy();
@@ -4497,7 +4532,7 @@ MATCH TypeDArray::implicitConvTo(Type *to)
return MATCHconvert;
}
- return next->constConv(to);
+ return next->constConv(to) ? MATCHconvert : MATCHnomatch;
}
if (to->ty == Tarray)
@@ -4567,6 +4602,11 @@ TypeAArray::TypeAArray(Type *t, Type *index)
this->sc = NULL;
}
+const char *TypeAArray::kind()
+{
+ return "aarray";
+}
+
Type *TypeAArray::syntaxCopy()
{
Type *t = next->syntaxCopy();
@@ -5002,6 +5042,11 @@ TypePointer::TypePointer(Type *t)
{
}
+const char *TypePointer::kind()
+{
+ return "pointer";
+}
+
Type *TypePointer::syntaxCopy()
{
Type *t = next->syntaxCopy();
@@ -5170,6 +5215,11 @@ TypeReference::TypeReference(Type *t)
// BUG: what about references to static arrays?
}
+const char *TypeReference::kind()
+{
+ return "reference";
+}
+
Type *TypeReference::syntaxCopy()
{
Type *t = next->syntaxCopy();
@@ -5274,6 +5324,18 @@ TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, e
this->trust = TRUSTtrusted;
}
+const char *TypeFunction::kind()
+{
+ return "function";
+}
+
+TypeFunction *TypeFunction::copy()
+{
+ TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
+ memcpy(tf, this, sizeof(TypeFunction));
+ return tf;
+}
+
Type *TypeFunction::syntaxCopy()
{
Type *treturn = next ? next->syntaxCopy() : NULL;
@@ -5558,8 +5620,8 @@ void TypeFunction::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
Parameter::argsToDecoBuffer(buf, parameters, mangle);
//if (buf->data[buf->offset - 1] == '@') halt();
buf->writeByte('Z' - varargs); // mark end of arg list
- assert(next);
- next->toDecoBuffer(buf, 0, mangle);
+ if(next != NULL)
+ next->toDecoBuffer(buf, 0, mangle);
inuse--;
}
@@ -5763,8 +5825,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
* This can produce redundant copies if inferring return type,
* as semantic() will get called again on this.
*/
- TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
- memcpy(tf, this, sizeof(TypeFunction));
+ TypeFunction *tf = copy();
if (parameters)
{ tf->parameters = (Parameters *)parameters->copy();
for (size_t i = 0; i < parameters->dim; i++)
@@ -5817,12 +5878,6 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
sc->stc &= ~(STC_TYPECTOR | STC_FUNCATTR);
tf->next = tf->next->semantic(loc,sc);
sc = sc->pop();
-#if !SARRAYVALUE
- if (tf->next->toBasetype()->ty == Tsarray)
- { error(loc, "functions cannot return static array %s", tf->next->toChars());
- tf->next = Type::terror;
- }
-#endif
if (tf->next->toBasetype()->ty == Tfunction)
{ error(loc, "functions cannot return a function");
tf->next = Type::terror;
@@ -5888,9 +5943,9 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
if (fparam->defaultArg)
{ Expression *e = fparam->defaultArg;
- e = e->inferType(fparam->type);
- e = e->semantic(argsc);
- e = resolveProperties(argsc, e);
+ Initializer *init = new ExpInitializer(e->loc, e);
+ init = init->semantic(argsc, fparam->type, INITnointerpret);
+ e = init->toExpression();
if (e->op == TOKfunction) // see Bugzilla 4820
{ FuncExp *fe = (FuncExp *)e;
// Replace function literal with a function symbol,
@@ -6302,25 +6357,6 @@ MATCH TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag)
new IntegerExp(0, ((StringExp *)arg)->len,
Type::tindex));
}
- else if (ta && ta->implicitConvTo(tprm))
- {
- goto Nomatch;
- }
- else if (arg->op == TOKstructliteral)
- {
- match = MATCHconvert;
- }
- else if (arg->op == TOKcall)
- {
- CallExp *ce = (CallExp *)arg;
- if (ce->e1->op == TOKdotvar &&
- ((DotVarExp *)ce->e1)->var->isCtorDeclaration())
- {
- match = MATCHconvert;
- }
- else
- goto Nomatch;
- }
else
goto Nomatch;
}
@@ -6557,6 +6593,11 @@ TypeDelegate::TypeDelegate(Type *t)
ty = Tdelegate;
}
+const char *TypeDelegate::kind()
+{
+ return "delegate";
+}
+
Type *TypeDelegate::syntaxCopy()
{
Type *t = next->syntaxCopy();
@@ -6750,6 +6791,7 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
VarDeclaration *v;
EnumMember *em;
Expression *e;
+ TemplateInstance *ti;
#if 0
printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, toChars());
@@ -6775,6 +6817,7 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
{ Type *t;
v = s->isVarDeclaration();
+ ti = s->isTemplateInstance();
if (v && id == Id::length)
{
e = new VarExp(loc, v);
@@ -6783,7 +6826,8 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
goto Lerror;
goto L3;
}
- else if (v && (id == Id::stringof || id == Id::offsetof))
+ else if ((v && (id == Id::stringof || id == Id::offsetof))
+ || (ti && (id == Id::stringof || id == Id::mangleof)))
{
e = new DsymbolExp(loc, s, 0);
do
@@ -6959,6 +7003,11 @@ TypeIdentifier::TypeIdentifier(Loc loc, Identifier *ident)
this->ident = ident;
}
+const char *TypeIdentifier::kind()
+{
+ return "identifier";
+}
+
Type *TypeIdentifier::syntaxCopy()
{
@@ -7133,6 +7182,11 @@ TypeInstance::TypeInstance(Loc loc, TemplateInstance *tempinst)
this->tempinst = tempinst;
}
+const char *TypeInstance::kind()
+{
+ return "instance";
+}
+
Type *TypeInstance::syntaxCopy()
{
//printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.dim);
@@ -7274,6 +7328,11 @@ TypeTypeof::TypeTypeof(Loc loc, Expression *exp)
inuse = 0;
}
+const char *TypeTypeof::kind()
+{
+ return "typeof";
+}
+
Type *TypeTypeof::syntaxCopy()
{
//printf("TypeTypeof::syntaxCopy() %s\n", toChars());
@@ -7458,6 +7517,11 @@ TypeReturn::TypeReturn(Loc loc)
{
}
+const char *TypeReturn::kind()
+{
+ return "return";
+}
+
Type *TypeReturn::syntaxCopy()
{
TypeReturn *t = new TypeReturn(loc);
@@ -7541,6 +7605,11 @@ TypeEnum::TypeEnum(EnumDeclaration *sym)
this->sym = sym;
}
+const char *TypeEnum::kind()
+{
+ return "enum";
+}
+
char *TypeEnum::toChars()
{
if (mod)
@@ -7722,9 +7791,9 @@ int TypeEnum::isscalar()
return sym->memtype->isscalar();
}
-int TypeEnum::isAssignable(int blit)
+int TypeEnum::isAssignable()
{
- return sym->memtype->isAssignable(blit);
+ return sym->memtype->isAssignable();
}
int TypeEnum::checkBoolean()
@@ -7811,6 +7880,11 @@ TypeTypedef::TypeTypedef(TypedefDeclaration *sym)
this->sym = sym;
}
+const char *TypeTypedef::kind()
+{
+ return "typedef";
+}
+
Type *TypeTypedef::syntaxCopy()
{
return this;
@@ -7939,9 +8013,9 @@ int TypeTypedef::isscalar()
return sym->basetype->isscalar();
}
-int TypeTypedef::isAssignable(int blit)
+int TypeTypedef::isAssignable()
{
- return sym->basetype->isAssignable(blit);
+ return sym->basetype->isAssignable();
}
int TypeTypedef::checkBoolean()
@@ -8094,6 +8168,11 @@ TypeStruct::TypeStruct(StructDeclaration *sym)
this->unaligned = 0;
}
+const char *TypeStruct::kind()
+{
+ return "struct";
+}
+
char *TypeStruct::toChars()
{
//printf("sym.parent: %s, deco = %s\n", sym->parent->toChars(), deco);
@@ -8423,6 +8502,7 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc)
for (size_t j = 0; j < structelems->dim; j++)
{
VarDeclaration *vd = sym->fields[j];
+ Type *telem = vd->type->addMod(this->mod);
Expression *e;
if (vd->init)
{ if (vd->init->isVoidInitializer())
@@ -8433,7 +8513,10 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc)
else
e = vd->type->defaultInitLiteral(loc);
if (e && vd->scope)
- e = e->semantic(vd->scope);
+ {
+ e = e->semantic(vd->scope);
+ e = e->implicitCastTo(vd->scope, telem);
+ }
(*structelems)[j] = e;
}
StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems);
@@ -8481,18 +8564,8 @@ bool TypeStruct::needsNested()
return false;
}
-int TypeStruct::isAssignable(int blit)
+int TypeStruct::isAssignable()
{
- if (!blit)
- {
- if (sym->hasIdentityAssign)
- return TRUE;
-
- // has non-identity opAssign
- if (search_function(sym, Id::assign))
- return FALSE;
- }
-
int assignable = TRUE;
unsigned offset;
@@ -8518,7 +8591,7 @@ int TypeStruct::isAssignable(int blit)
if (!assignable)
return FALSE;
}
- assignable = v->type->isMutable() && v->type->isAssignable(blit);
+ assignable = v->type->isMutable() && v->type->isAssignable();
offset = v->offset;
//printf(" -> assignable = %d\n", assignable);
}
@@ -8638,6 +8711,11 @@ TypeClass::TypeClass(ClassDeclaration *sym)
this->sym = sym;
}
+const char *TypeClass::kind()
+{
+ return "class";
+}
+
char *TypeClass::toChars()
{
if (mod)
@@ -9122,7 +9200,7 @@ int TypeClass::isscope()
int TypeClass::isBaseOf(Type *t, int *poffset)
{
- if (t->ty == Tclass)
+ if (t && t->ty == Tclass)
{ ClassDeclaration *cd;
cd = ((TypeClass *)t)->sym;
@@ -9294,6 +9372,11 @@ TypeTuple::TypeTuple(Type *t1, Type *t2)
arguments->push(new Parameter(0, t2, NULL, NULL));
}
+const char *TypeTuple::kind()
+{
+ return "tuple";
+}
+
Type *TypeTuple::syntaxCopy()
{
Parameters *args = Parameter::arraySyntaxCopy(arguments);
@@ -9440,6 +9523,11 @@ TypeSlice::TypeSlice(Type *next, Expression *lwr, Expression *upr)
this->upr = upr;
}
+const char *TypeSlice::kind()
+{
+ return "slice";
+}
+
Type *TypeSlice::syntaxCopy()
{
Type *t = new TypeSlice(next->syntaxCopy(), lwr->syntaxCopy(), upr->syntaxCopy());
@@ -9568,6 +9656,11 @@ TypeNull::TypeNull()
{
}
+const char *TypeNull::kind()
+{
+ return "null";
+}
+
Type *TypeNull::syntaxCopy()
{
// No semantic analysis done, no need to copy
@@ -9596,10 +9689,23 @@ MATCH TypeNull::implicitConvTo(Type *to)
return MATCHnomatch;
}
+int TypeNull::checkBoolean()
+{
+ return TRUE;
+}
+
+#if IN_LLVM
void TypeNull::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
+#else
+void TypeNull::toDecoBuffer(OutBuffer *buf, int flag)
+#endif
{
//tvoidptr->toDecoBuffer(buf, flag);
+#if IN_LLVM
Type::toDecoBuffer(buf, flag, mangle);
+#else
+ Type::toDecoBuffer(buf, flag);
+#endif
}
void TypeNull::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
@@ -9700,6 +9806,13 @@ void Parameter::argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Parameters *argu
{ if (arg->ident)
argbuf.writestring(arg->ident->toChars());
}
+ else if (arg->type->ty == Tident &&
+ ((TypeIdentifier *)arg->type)->ident->len > 3 &&
+ strncmp(((TypeIdentifier *)arg->type)->ident->string, "__T", 3) == 0)
+ {
+ // print parameter name, instead of undetermined type parameter
+ argbuf.writestring(arg->ident->toChars());
+ }
else
arg->type->toCBuffer(&argbuf, arg->ident, hgs);
if (arg->defaultArg)
diff --git a/dmd2/mtype.h b/dmd2/mtype.h
index 50142416..6dbda261 100644
--- a/dmd2/mtype.h
+++ b/dmd2/mtype.h
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
-// Copyright (c) 1999-2012 by Digital Mars
+// Copyright (c) 1999-2013 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -41,6 +41,7 @@ struct Dsymbol;
struct TemplateInstance;
struct CppMangleState;
struct TemplateDeclaration;
+struct JsonOut;
enum LINK;
struct TypeBasic;
@@ -191,6 +192,7 @@ struct Type : Object
#define tindex tsize_t // array/ptr index
static Type *tvoidptr; // void*
static Type *tstring; // immutable(char)[]
+ static Type *tvalist; // va_list alias
#define terror basic[Terror] // for error recovery
#define tnull basic[Tnull] // for null type
@@ -239,6 +241,7 @@ struct Type : Object
static unsigned char impcnvWarn[TMAX][TMAX];
Type(TY ty);
+ virtual const char *kind();
virtual Type *syntaxCopy();
int equals(Object *o);
int dyncast() { return DYNCAST_TYPE; } // kludge for template.isType()
@@ -263,6 +266,9 @@ struct Type : Object
virtual void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod);
void modToBuffer(OutBuffer *buf);
+ char *modToChars();
+ void toJsonProperty(JsonOut *json, const char *);
+ virtual void toJson(JsonOut *json);
#if CPP_MANGLE
virtual void toCppMangle(OutBuffer *buf, CppMangleState *cms);
#endif
@@ -275,7 +281,7 @@ struct Type : Object
virtual int isunsigned();
virtual int isscope();
virtual int isString();
- virtual int isAssignable(int blit = 0);
+ virtual int isAssignable();
virtual int checkBoolean(); // if can be converted to boolean value
virtual void checkDeprecated(Loc loc, Scope *sc);
int isConst() { return mod & MODconst; }
@@ -412,6 +418,7 @@ struct TypeBasic : Type
unsigned flags;
TypeBasic(TY ty);
+ const char *kind();
Type *syntaxCopy();
d_uns64 size(Loc loc);
unsigned alignsize();
@@ -447,6 +454,7 @@ struct TypeVector : Type
Type *basetype;
TypeVector(Loc loc, Type *basetype);
+ const char *kind();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
@@ -455,7 +463,12 @@ struct TypeVector : Type
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
char *toChars();
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+#if IN_LLVM
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
+#else
+ void toDecoBuffer(OutBuffer *buf, int flag);
+#endif
+ void toJson(JsonOut *json);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
#if CPP_MANGLE
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
@@ -489,6 +502,7 @@ struct TypeSArray : TypeArray
Expression *dim;
TypeSArray(Type *t, Expression *dim);
+ const char *kind();
Type *syntaxCopy();
d_uns64 size(Loc loc);
unsigned alignsize();
@@ -496,6 +510,7 @@ struct TypeSArray : TypeArray
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
int isString();
int isZeroInit(Loc loc);
@@ -530,6 +545,7 @@ struct TypeSArray : TypeArray
struct TypeDArray : TypeArray
{
TypeDArray(Type *t);
+ const char *kind();
Type *syntaxCopy();
d_uns64 size(Loc loc);
unsigned alignsize();
@@ -537,6 +553,7 @@ struct TypeDArray : TypeArray
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
int isString();
int isZeroInit(Loc loc);
@@ -566,6 +583,7 @@ struct TypeAArray : TypeArray
StructDeclaration *impl; // implementation
TypeAArray(Type *t, Type *index);
+ const char *kind();
Type *syntaxCopy();
d_uns64 size(Loc loc);
Type *semantic(Loc loc, Scope *sc);
@@ -573,6 +591,7 @@ struct TypeAArray : TypeArray
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *defaultInit(Loc loc);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
@@ -600,10 +619,12 @@ struct TypeAArray : TypeArray
struct TypePointer : TypeNext
{
TypePointer(Type *t);
+ const char *kind();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
MATCH implicitConvTo(Type *to);
MATCH constConv(Type *to);
int isscalar();
@@ -624,10 +645,12 @@ struct TypePointer : TypeNext
struct TypeReference : TypeNext
{
TypeReference(Type *t);
+ const char *kind();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *defaultInit(Loc loc);
int isZeroInit(Loc loc);
@@ -678,6 +701,8 @@ struct TypeFunction : TypeNext
int inuse;
TypeFunction(Parameters *parameters, Type *treturn, int varargs, enum LINK linkage, StorageClass stc = 0);
+ const char *kind();
+ TypeFunction *copy();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
void purityLevel();
@@ -686,6 +711,7 @@ struct TypeFunction : TypeNext
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
void toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, HdrGenState* hgs, TypeFunction *attrs, TemplateDeclaration *td);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
void attributesToCBuffer(OutBuffer *buf, int mod);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
TypeInfoDeclaration *getTypeInfoDeclaration();
@@ -723,12 +749,14 @@ struct TypeDelegate : TypeNext
// .next is a TypeFunction
TypeDelegate(Type *t);
+ const char *kind();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
unsigned alignsize();
MATCH implicitConvTo(Type *to);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
Expression *defaultInit(Loc loc);
int isZeroInit(Loc loc);
int checkBoolean();
@@ -754,6 +782,7 @@ struct TypeQualified : Type
void syntaxCopyHelper(TypeQualified *t);
void addIdent(Identifier *ident);
void toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs);
+ void toJson(JsonOut *json);
d_uns64 size(Loc loc);
void resolveHelper(Loc loc, Scope *sc, Dsymbol *s, Dsymbol *scopesym,
Expression **pe, Type **pt, Dsymbol **ps);
@@ -765,10 +794,12 @@ struct TypeIdentifier : TypeQualified
Dsymbol *originalSymbol; // The symbol representing this identifier, before alias resolution
TypeIdentifier(Loc loc, Identifier *ident);
+ const char *kind();
Type *syntaxCopy();
//char *toChars();
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Dsymbol *toDsymbol(Scope *sc);
Type *semantic(Loc loc, Scope *sc);
@@ -784,10 +815,12 @@ struct TypeInstance : TypeQualified
TemplateInstance *tempinst;
TypeInstance(Loc loc, TemplateInstance *tempinst);
+ const char *kind();
Type *syntaxCopy();
//char *toChars();
//void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc);
@@ -801,9 +834,11 @@ struct TypeTypeof : TypeQualified
int inuse;
TypeTypeof(Loc loc, Expression *exp);
+ const char *kind();
Type *syntaxCopy();
Dsymbol *toDsymbol(Scope *sc);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
};
@@ -811,10 +846,12 @@ struct TypeTypeof : TypeQualified
struct TypeReturn : TypeQualified
{
TypeReturn(Loc loc);
+ const char *kind();
Type *syntaxCopy();
Dsymbol *toDsymbol(Scope *sc);
Type *semantic(Loc loc, Scope *sc);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
};
struct TypeStruct : Type
@@ -822,6 +859,7 @@ struct TypeStruct : Type
StructDeclaration *sym;
TypeStruct(StructDeclaration *sym);
+ const char *kind();
d_uns64 size(Loc loc);
unsigned alignsize();
char *toChars();
@@ -830,13 +868,14 @@ struct TypeStruct : Type
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
structalign_t alignment();
Expression *defaultInit(Loc loc);
Expression *defaultInitLiteral(Loc loc);
Expression *voidInitLiteral(VarDeclaration *var);
int isZeroInit(Loc loc);
- int isAssignable(int blit = 0);
+ int isAssignable();
int checkBoolean();
int needsDestruction();
bool needsNested();
@@ -870,6 +909,7 @@ struct TypeEnum : Type
EnumDeclaration *sym;
TypeEnum(EnumDeclaration *sym);
+ const char *kind();
Type *syntaxCopy();
d_uns64 size(Loc loc);
unsigned alignsize();
@@ -878,6 +918,7 @@ struct TypeEnum : Type
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *getProperty(Loc loc, Identifier *ident);
int isintegral();
@@ -888,7 +929,7 @@ struct TypeEnum : Type
int isscalar();
int isunsigned();
int checkBoolean();
- int isAssignable(int blit = 0);
+ int isAssignable();
int needsDestruction();
bool needsNested();
MATCH implicitConvTo(Type *to);
@@ -914,6 +955,7 @@ struct TypeTypedef : Type
TypedefDeclaration *sym;
TypeTypedef(TypedefDeclaration *sym);
+ const char *kind();
Type *syntaxCopy();
d_uns64 size(Loc loc);
unsigned alignsize();
@@ -922,6 +964,7 @@ struct TypeTypedef : Type
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
structalign_t alignment();
Expression *getProperty(Loc loc, Identifier *ident);
@@ -933,7 +976,7 @@ struct TypeTypedef : Type
int isscalar();
int isunsigned();
int checkBoolean();
- int isAssignable(int blit = 0);
+ int isAssignable();
int needsDestruction();
bool needsNested();
Type *toBasetype();
@@ -966,6 +1009,7 @@ struct TypeClass : Type
ClassDeclaration *sym;
TypeClass(ClassDeclaration *sym);
+ const char *kind();
d_uns64 size(Loc loc);
char *toChars();
Type *syntaxCopy();
@@ -973,6 +1017,7 @@ struct TypeClass : Type
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
ClassDeclaration *isClassHandle();
int isBaseOf(Type *t, int *poffset);
@@ -1009,12 +1054,18 @@ struct TypeTuple : Type
TypeTuple();
TypeTuple(Type *t1);
TypeTuple(Type *t1, Type *t2);
+ const char *kind();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
int equals(Object *o);
Type *reliesOnTident(TemplateParameters *tparams = NULL);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+#if IN_LLVM
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
+#else
+ void toDecoBuffer(OutBuffer *buf, int flag);
+#endif
+ void toJson(JsonOut *json);
Expression *getProperty(Loc loc, Identifier *ident);
Expression *defaultInit(Loc loc);
TypeInfoDeclaration *getTypeInfoDeclaration();
@@ -1026,21 +1077,26 @@ struct TypeSlice : TypeNext
Expression *upr;
TypeSlice(Type *next, Expression *lwr, Expression *upr);
+ const char *kind();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toJson(JsonOut *json);
};
struct TypeNull : Type
{
TypeNull();
+ const char *kind();
Type *syntaxCopy();
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
MATCH implicitConvTo(Type *to);
+ int checkBoolean();
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toJson(JsonOut *json);
d_uns64 size(Loc loc);
//Expression *getProperty(Loc loc, Identifier *ident);
@@ -1066,6 +1122,7 @@ struct Parameter : Object
Type *isLazyArray();
void toDecoBuffer(OutBuffer *buf, bool mangle);
int dyncast() { return DYNCAST_PARAMETER; } // kludge for template.isType()
+ void toJson(JsonOut *json);
static Parameters *arraySyntaxCopy(Parameters *args);
static char *argsTypesToChars(Parameters *args, int varargs);
static void argsCppMangle(OutBuffer *buf, CppMangleState *cms, Parameters *arguments, int varargs);
@@ -1089,6 +1146,7 @@ extern int Tptrdiff_t;
int arrayTypeCompatible(Loc loc, Type *t1, Type *t2);
int arrayTypeCompatibleWithoutCasting(Loc loc, Type *t1, Type *t2);
void MODtoBuffer(OutBuffer *buf, unsigned char mod);
+char *MODtoChars(unsigned char mod);
int MODimplicitConv(unsigned char modfrom, unsigned char modto);
int MODmethodConv(unsigned char modfrom, unsigned char modto);
int MODmerge(unsigned char mod1, unsigned char mod2);
diff --git a/dmd2/opover.c b/dmd2/opover.c
index 5d731df2..16cea8a2 100644
--- a/dmd2/opover.c
+++ b/dmd2/opover.c
@@ -465,6 +465,15 @@ Expression *BinExp::op_overload(Scope *sc)
AggregateDeclaration *ad1 = isAggregate(e1->type);
AggregateDeclaration *ad2 = isAggregate(e2->type);
+ if (op == TOKassign && ad1 == ad2)
+ {
+ StructDeclaration *sd = ad1->isStructDeclaration();
+ if (sd && !sd->hasIdentityAssign)
+ { /* This is bitwise struct assignment. */
+ return NULL;
+ }
+ }
+
Dsymbol *s = NULL;
Dsymbol *s_r = NULL;
diff --git a/dmd2/optimize.c b/dmd2/optimize.c
index 0b0530b3..a6f8453a 100644
--- a/dmd2/optimize.c
+++ b/dmd2/optimize.c
@@ -27,9 +27,6 @@
#ifdef IN_GCC
#include "d-gcc-real.h"
-
-/* %% fix? */
-extern "C" bool real_isnan (const real_t *);
#endif
static real_t zero; // work around DMC bug for now
diff --git a/dmd2/parse.c b/dmd2/parse.c
index ef36b455..603e0c4f 100644
--- a/dmd2/parse.c
+++ b/dmd2/parse.c
@@ -269,6 +269,20 @@ Dsymbols *Parser::parseDeclDefs(int once)
case TOKunittest:
s = parseUnitTest();
+ if (decldefs && decldefs->dim)
+ {
+ Dsymbol *ds = (*decldefs)[decldefs->dim-1];
+ AttribDeclaration *ad;
+ while ((ad = ds->isAttribDeclaration()) != NULL)
+ {
+ if (ad->decl && ad->decl->dim)
+ ds = (*ad->decl)[ad->decl->dim-1];
+ else
+ break;
+ }
+
+ ds->unittest = (UnitTestDeclaration *)s;
+ }
break;
case TOKnew:
@@ -2238,7 +2252,11 @@ Objects *Parser::parseTemplateArgument()
break;
}
if (token.value == TOKnot)
- error("multiple ! arguments are not allowed");
+ {
+ enum TOK tok = peekNext();
+ if (tok != TOKis && tok != TOKin)
+ error("multiple ! arguments are not allowed");
+ }
return tiargs;
}
@@ -2843,6 +2861,7 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, unsigned char *c
addComment(s, comment);
return a;
}
+#if 0
/* Look for:
* alias this = identifier;
*/
@@ -2858,6 +2877,7 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, unsigned char *c
addComment(s, comment);
return a;
}
+#endif
/* Look for:
* alias identifier = type;
*/
diff --git a/dmd2/root/array.c b/dmd2/root/array.c
index 94c2cebb..6f949755 100644
--- a/dmd2/root/array.c
+++ b/dmd2/root/array.c
@@ -1,5 +1,5 @@
-// Copyright (c) 1999-2010 by Digital Mars
+// Copyright (c) 1999-2013 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -9,35 +9,9 @@
#include
#include
-#include
#include
#include
-#if defined (__sun)
-#include
-#endif
-
-#if _MSC_VER || __MINGW32__
-#include
-#endif
-
-#if IN_GCC
-#include "gdc_alloca.h"
-#endif
-
-#if _WIN32
-#include
-#endif
-
-#ifndef _WIN32
-#include
-#include
-#include
-#include
-#include
-#include
-#endif
-
#include "port.h"
#include "root.h"
#include "rmem.h"
@@ -181,25 +155,19 @@ void Array::remove(size_t i)
char *Array::toChars()
{
- size_t len;
- size_t u;
- char **buf;
- char *str;
- char *p;
-
- buf = (char **)malloc(dim * sizeof(char *));
+ char **buf = (char **)malloc(dim * sizeof(char *));
assert(buf);
- len = 2;
- for (u = 0; u < dim; u++)
+ size_t len = 2;
+ for (size_t u = 0; u < dim; u++)
{
buf[u] = ((Object *)data[u])->toChars();
len += strlen(buf[u]) + 1;
}
- str = (char *)mem.malloc(len);
+ char *str = (char *)mem.malloc(len);
str[0] = '[';
- p = str + 1;
- for (u = 0; u < dim; u++)
+ char *p = str + 1;
+ for (size_t u = 0; u < dim; u++)
{
if (u)
*p++ = ',';
diff --git a/dmd2/root/gnuc.c b/dmd2/root/gnuc.c
deleted file mode 100644
index 90358da1..00000000
--- a/dmd2/root/gnuc.c
+++ /dev/null
@@ -1,63 +0,0 @@
-
-// Copyright (c) 2009-2012 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-// Put functions in here missing from gnu C
-
-#include "gnuc.h"
-
-int memicmp(const char *s1, const char *s2, int n)
-{
- int result = 0;
-
- for (int i = 0; i < n; i++)
- { char c1 = s1[i];
- char c2 = s2[i];
-
- result = c1 - c2;
- if (result)
- {
- if ('A' <= c1 && c1 <= 'Z')
- c1 += 'a' - 'A';
- if ('A' <= c2 && c2 <= 'Z')
- c2 += 'a' - 'A';
- result = c1 - c2;
- if (result)
- break;
- }
- }
- return result;
-}
-
-int stricmp(const char *s1, const char *s2)
-{
- int result = 0;
-
- for (;;)
- { char c1 = *s1;
- char c2 = *s2;
-
- result = c1 - c2;
- if (result)
- {
- if ('A' <= c1 && c1 <= 'Z')
- c1 += 'a' - 'A';
- if ('A' <= c2 && c2 <= 'Z')
- c2 += 'a' - 'A';
- result = c1 - c2;
- if (result)
- break;
- }
- if (!c1)
- break;
- s1++;
- s2++;
- }
- return result;
-}
-
diff --git a/dmd2/root/gnuc.h b/dmd2/root/gnuc.h
deleted file mode 100644
index 6b25fbf2..00000000
--- a/dmd2/root/gnuc.h
+++ /dev/null
@@ -1,16 +0,0 @@
-
-// Copyright (c) 2009-2012 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef _GNUC_H
-#define _GNUC_H 1
-
-int memicmp(const char *s1, const char *s2, int n);
-int stricmp(const char *s1, const char *s2);
-
-#endif
diff --git a/dmd2/root/port.c b/dmd2/root/port.c
index 238059a6..820a36e8 100644
--- a/dmd2/root/port.c
+++ b/dmd2/root/port.c
@@ -116,6 +116,16 @@ char *Port::strupr(char *s)
return ::strupr(s);
}
+int Port::memicmp(const char *s1, const char *s2, int n)
+{
+ return ::memicmp(s1, s2, n);
+}
+
+int Port::stricmp(const char *s1, const char *s2)
+{
+ return ::stricmp(s1, s2);
+}
+
#endif
#if _MSC_VER
@@ -328,6 +338,16 @@ char *Port::strupr(char *s)
return ::strupr(s);
}
+int Port::memicmp(const char *s1, const char *s2, int n)
+{
+ return ::memicmp(s1, s2, n);
+}
+
+int Port::stricmp(const char *s1, const char *s2)
+{
+ return ::stricmp(s1, s2);
+}
+
#endif
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __HAIKU__ || __MINGW32__
@@ -524,6 +544,48 @@ char *Port::strupr(char *s)
return t;
}
+int Port::memicmp(const char *s1, const char *s2, int n)
+{
+ int result = 0;
+
+ for (int i = 0; i < n; i++)
+ { char c1 = s1[i];
+ char c2 = s2[i];
+
+ result = c1 - c2;
+ if (result)
+ {
+ result = toupper(c1) - toupper(c2);
+ if (result)
+ break;
+ }
+ }
+ return result;
+}
+
+int Port::stricmp(const char *s1, const char *s2)
+{
+ int result = 0;
+
+ for (;;)
+ { char c1 = *s1;
+ char c2 = *s2;
+
+ result = c1 - c2;
+ if (result)
+ {
+ result = toupper(c1) - toupper(c2);
+ if (result)
+ break;
+ }
+ if (!c1)
+ break;
+ s1++;
+ s2++;
+ }
+ return result;
+}
+
#endif
#if __sun
@@ -670,18 +732,3 @@ char *Port::strupr(char *s)
}
#endif
-
-
-#if IN_LLVM
-#if __MINGW32__
-longdouble Port::strtold(const char *str, char **pend)
-{
- return __mingw_strtold(str, pend);
-}
-#else
-longdouble Port::strtold(const char *str, char **pend)
-{
- return ::strtold(str, pend);
-}
-#endif
-#endif
diff --git a/dmd2/root/port.h b/dmd2/root/port.h
index 8d4136aa..c02675d0 100644
--- a/dmd2/root/port.h
+++ b/dmd2/root/port.h
@@ -10,6 +10,10 @@
// Portable wrapper around compiler/system specific things.
// The idea is to minimize #ifdef's in the app code.
+#if defined(IN_LLVM) && (LDC_LLVM_VER >= 303)
+#include "llvm/Config/config.h"
+#endif
+
#include "longdouble.h"
#if _MSC_VER
@@ -61,9 +65,6 @@ struct Port
static longdouble fmodl(longdouble x, longdouble y);
static ulonglong strtoull(const char *p, char **pend, int base);
-#if IN_LLVM
- static longdouble strtold(const char *str, char **pend);
-#endif
static char *ull_to_string(char *buffer, ulonglong ull);
static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
@@ -76,6 +77,9 @@ struct Port
static const wchar_t *wlist_separator();
static char *strupr(char *);
+
+ static int memicmp(const char *s1, const char *s2, int n);
+ static int stricmp(const char *s1, const char *s2);
};
#endif
diff --git a/dmd2/root/response.c b/dmd2/root/response.c
index e2e91b92..31b41b7d 100644
--- a/dmd2/root/response.c
+++ b/dmd2/root/response.c
@@ -5,7 +5,7 @@
// Written by Walter Bright
/*
* This source file is made available for personal use
- * only. The license is in /dmd/src/dmd/backendlicense.txt
+ * only. The license is in backendlicense.txt
* For any other uses, please contact Digital Mars.
*/
diff --git a/dmd2/root/root.c b/dmd2/root/root.c
index 01fe0d89..8a16e83f 100644
--- a/dmd2/root/root.c
+++ b/dmd2/root/root.c
@@ -139,19 +139,19 @@ void Object::mark()
/****************************** String ********************************/
-String::String(char *str)
+String::String(const char *str)
: str(mem.strdup(str))
{
}
String::~String()
{
- mem.free(str);
+ mem.free((void *)str);
}
void String::mark()
{
- mem.mark(str);
+ mem.mark((void *)str);
}
hash_t String::calcHash(const char *str, size_t len)
@@ -218,7 +218,7 @@ int String::compare(Object *obj)
char *String::toChars()
{
- return str;
+ return (char *)str; // toChars() should really be const
}
void String::print()
@@ -229,12 +229,12 @@ void String::print()
/****************************** FileName ********************************/
-FileName::FileName(char *str)
+FileName::FileName(const char *str)
: String(str)
{
}
-char *FileName::combine(const char *path, const char *name)
+const char *FileName::combine(const char *path, const char *name)
{ char *f;
size_t pathlen;
size_t namelen;
@@ -431,12 +431,11 @@ int FileName::absolute(const char *name)
* If there isn't one, return NULL.
*/
-char *FileName::ext(const char *str)
+const char *FileName::ext(const char *str)
{
- char *e;
size_t len = strlen(str);
- e = (char *)str + len;
+ const char *e = str + len;
for (;;)
{
switch (*e)
@@ -462,7 +461,7 @@ char *FileName::ext(const char *str)
}
}
-char *FileName::ext()
+const char *FileName::ext()
{
return ext(str);
}
@@ -471,7 +470,7 @@ char *FileName::ext()
* Return mem.malloc'd filename with extension removed.
*/
-char *FileName::removeExt(const char *str)
+const char *FileName::removeExt(const char *str)
{
const char *e = ext(str);
if (e)
@@ -488,12 +487,11 @@ char *FileName::removeExt(const char *str)
* Return filename name excluding path (read-only).
*/
-char *FileName::name(const char *str)
+const char *FileName::name(const char *str)
{
- char *e;
size_t len = strlen(str);
- e = (char *)str + len;
+ const char *e = str + len;
for (;;)
{
switch (*e)
@@ -525,7 +523,7 @@ char *FileName::name(const char *str)
}
}
-char *FileName::name()
+const char *FileName::name()
{
return name(str);
}
@@ -535,10 +533,9 @@ char *FileName::name()
* Path will does not include trailing path separator.
*/
-char *FileName::path(const char *str)
+const char *FileName::path(const char *str)
{
- char *n = name(str);
- char *path;
+ const char *n = name(str);
size_t pathlen;
if (n > str)
@@ -554,7 +551,7 @@ char *FileName::path(const char *str)
#endif
}
pathlen = n - str;
- path = (char *)mem.malloc(pathlen + 1);
+ char *path = (char *)mem.malloc(pathlen + 1);
memcpy(path, str, pathlen);
path[pathlen] = 0;
return path;
@@ -565,20 +562,19 @@ char *FileName::path(const char *str)
*/
const char *FileName::replaceName(const char *path, const char *name)
-{ char *f;
- char *n;
+{
size_t pathlen;
size_t namelen;
if (absolute(name))
return name;
- n = FileName::name(path);
+ const char *n = FileName::name(path);
if (n == path)
return name;
pathlen = n - path;
namelen = strlen(name);
- f = (char *)mem.malloc(pathlen + 1 + namelen + 1);
+ char *f = (char *)mem.malloc(pathlen + 1 + namelen + 1);
memcpy(f, path, pathlen);
#if POSIX
if (path[pathlen - 1] != '/')
@@ -600,48 +596,40 @@ const char *FileName::replaceName(const char *path, const char *name)
}
/***************************
+ * Free returned value with FileName::free()
*/
-FileName *FileName::defaultExt(const char *name, const char *ext)
+const char *FileName::defaultExt(const char *name, const char *ext)
{
- char *e;
- char *s;
- size_t len;
- size_t extlen;
-
- e = FileName::ext(name);
+ const char *e = FileName::ext(name);
if (e) // if already has an extension
- return new FileName((char *)name);
+ return mem.strdup(name);
- len = strlen(name);
- extlen = strlen(ext);
- s = (char *)alloca(len + 1 + extlen + 1);
+ size_t len = strlen(name);
+ size_t extlen = strlen(ext);
+ char *s = (char *)mem.malloc(len + 1 + extlen + 1);
memcpy(s,name,len);
s[len] = '.';
memcpy(s + len + 1, ext, extlen + 1);
- return new FileName(s);
+ return s;
}
/***************************
+ * Free returned value with FileName::free()
*/
-FileName *FileName::forceExt(const char *name, const char *ext)
+const char *FileName::forceExt(const char *name, const char *ext)
{
- char *e;
- char *s;
- size_t len;
- size_t extlen;
-
- e = FileName::ext(name);
+ const char *e = FileName::ext(name);
if (e) // if already has an extension
{
- len = e - name;
- extlen = strlen(ext);
+ size_t len = e - name;
+ size_t extlen = strlen(ext);
- s = (char *)alloca(len + extlen + 1);
+ char *s = (char *)mem.malloc(len + extlen + 1);
memcpy(s,name,len);
memcpy(s + len, ext, extlen + 1);
- return new FileName(s);
+ return s;
}
else
return defaultExt(name, ext); // doesn't have one
@@ -652,20 +640,18 @@ FileName *FileName::forceExt(const char *name, const char *ext)
*/
int FileName::equalsExt(const char *ext)
-{ const char *e;
+{
+ return equalsExt(str, ext);
+}
- e = FileName::ext();
+int FileName::equalsExt(const char *name, const char *ext)
+{
+ const char *e = FileName::ext(name);
if (!e && !ext)
return 1;
if (!e || !ext)
return 0;
-#if POSIX
- return strcmp(e,ext) == 0;
-#elif _WIN32
- return stricmp(e,ext) == 0;
-#else
- assert(0);
-#endif
+ return FileName::compare(e, ext) == 0;
}
/*************************************
@@ -694,24 +680,24 @@ void FileName::CopyTo(FileName *to)
* cwd if !=0, search current directory before searching path
*/
-char *FileName::searchPath(Strings *path, const char *name, int cwd)
+const char *FileName::searchPath(Strings *path, const char *name, int cwd)
{
if (absolute(name))
{
- return exists(name) ? (char *)name : NULL;
+ return exists(name) ? name : NULL;
}
if (cwd)
{
if (exists(name))
- return (char *)name;
+ return name;
}
if (path)
- { unsigned i;
+ {
- for (i = 0; i < path->dim; i++)
+ for (size_t i = 0; i < path->dim; i++)
{
- char *p = path->tdata()[i];
- char *n = combine(p, name);
+ const char *p = path->tdata()[i];
+ const char *n = combine(p, name);
if (exists(n))
return n;
@@ -734,7 +720,7 @@ char *FileName::searchPath(Strings *path, const char *name, int cwd)
* !=NULL mem.malloc'd file name
*/
-char *FileName::safeSearchPath(Strings *path, const char *name)
+const char *FileName::safeSearchPath(Strings *path, const char *name)
{
#if _WIN32
/* Disallow % / \ : and .. in name characters
@@ -763,15 +749,14 @@ char *FileName::safeSearchPath(Strings *path, const char *name)
}
if (path)
- { unsigned i;
-
+ {
/* Each path is converted to a cannonical name and then a check is done to see
* that the searched name is really a child one of the the paths searched.
*/
- for (i = 0; i < path->dim; i++)
+ for (size_t i = 0; i < path->dim; i++)
{
- char *cname = NULL;
- char *cpath = canonicalName(path->tdata()[i]);
+ const char *cname = NULL;
+ const char *cpath = canonicalName(path->tdata()[i]);
//printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n",
// name, (char *)path->data[i], cpath);
if (cpath == NULL)
@@ -786,16 +771,16 @@ char *FileName::safeSearchPath(Strings *path, const char *name)
// exists and name is *really* a "child" of path
if (exists(cname) && strncmp(cpath, cname, strlen(cpath)) == 0)
{
- free(cpath);
- char *p = mem.strdup(cname);
- free(cname);
+ ::free((void *)cpath);
+ const char *p = mem.strdup(cname);
+ ::free((void *)cname);
return p;
}
cont:
if (cpath)
- free(cpath);
+ ::free((void *)cpath);
if (cname)
- free(cname);
+ ::free((void *)cname);
}
}
return NULL;
@@ -839,18 +824,18 @@ void FileName::ensurePathExists(const char *path)
{
if (!exists(path))
{
- char *p = FileName::path(path);
+ const char *p = FileName::path(path);
if (*p)
{
#if _WIN32
size_t len = strlen(path);
if (len > 2 && p[-1] == ':' && path + 2 == p)
- { mem.free(p);
+ { mem.free((void *)p);
return;
}
#endif
ensurePathExists(p);
- mem.free(p);
+ mem.free((void *)p);
}
#if _WIN32
if (path[strlen(path) - 1] != '\\')
@@ -878,12 +863,20 @@ void FileName::ensurePathExists(const char *path)
}
}
+void FileName::ensurePathToNameExists(const char *name)
+{
+ const char *pt = path(name);
+ if (*pt)
+ ensurePathExists(pt);
+ free(pt);
+}
+
/******************************************
* Return canonical version of name in a malloc'd buffer.
* This code is high risk.
*/
-char *FileName::canonicalName(const char *name)
+const char *FileName::canonicalName(const char *name)
{
#if linux
// Lovely glibc extension to do it for us
@@ -922,7 +915,7 @@ char *FileName::canonicalName(const char *name)
result = GetFullPathName(name, result, buf, NULL);
if (result == 0)
{
- free(buf);
+ ::free(buf);
return NULL;
}
return buf;
@@ -934,19 +927,31 @@ char *FileName::canonicalName(const char *name)
#endif
}
+/********************************
+ * Free memory allocated by FileName routines
+ */
+void FileName::free(const char *str)
+{
+ if (str)
+ { assert(str[0] != 0xAB);
+ memset((void *)str, 0xAB, strlen(str) + 1); // stomp
+ }
+ mem.free((void *)str);
+}
+
/****************************** File ********************************/
-File::File(FileName *n)
+File::File(const FileName *n)
{
ref = 0;
buffer = NULL;
len = 0;
touchtime = NULL;
- name = n;
+ name = (FileName *)n;
}
-File::File(char *n)
+File::File(const char *n)
{
ref = 0;
buffer = NULL;
@@ -1372,13 +1377,10 @@ Files *File::match(FileName *n)
#elif _WIN32
HANDLE h;
WIN32_FIND_DATAA fileinfo;
- Files *a;
- char *c;
- char *name;
- a = new Files();
- c = n->toChars();
- name = n->name();
+ Files *a = new Files();
+ const char *c = n->toChars();
+ const char *name = n->name();
h = FindFirstFileA(c,&fileinfo);
if (h != INVALID_HANDLE_VALUE)
{
diff --git a/dmd2/root/root.h b/dmd2/root/root.h
index 6b7ba246..6cb36d69 100644
--- a/dmd2/root/root.h
+++ b/dmd2/root/root.h
@@ -76,9 +76,9 @@ struct Object
struct String : Object
{
- char *str; // the string itself
+ const char *str; // the string itself
- String(char *str);
+ String(const char *str);
~String();
static hash_t calcHash(const char *str, size_t len);
@@ -94,33 +94,38 @@ struct String : Object
struct FileName : String
{
- FileName(char *str);
+ FileName(const char *str);
hash_t hashCode();
int equals(Object *obj);
static int equals(const char *name1, const char *name2);
int compare(Object *obj);
static int compare(const char *name1, const char *name2);
static int absolute(const char *name);
- static char *ext(const char *);
- char *ext();
- static char *removeExt(const char *str);
- static char *name(const char *);
- char *name();
- static char *path(const char *);
+ static const char *ext(const char *);
+ const char *ext();
+ static const char *removeExt(const char *str);
+ static const char *name(const char *);
+ const char *name();
+ static const char *path(const char *);
static const char *replaceName(const char *path, const char *name);
- static char *combine(const char *path, const char *name);
+ static const char *combine(const char *path, const char *name);
static Strings *splitPath(const char *path);
- static FileName *defaultExt(const char *name, const char *ext);
- static FileName *forceExt(const char *name, const char *ext);
+ static const char *defaultExt(const char *name, const char *ext);
+ static const char *forceExt(const char *name, const char *ext);
+ static int equalsExt(const char *name, const char *ext);
+
int equalsExt(const char *ext);
void CopyTo(FileName *to);
- static char *searchPath(Strings *path, const char *name, int cwd);
- static char *safeSearchPath(Strings *path, const char *name);
+ static const char *searchPath(Strings *path, const char *name, int cwd);
+ static const char *safeSearchPath(Strings *path, const char *name);
static int exists(const char *name);
static void ensurePathExists(const char *path);
- static char *canonicalName(const char *name);
+ static void ensurePathToNameExists(const char *name);
+ static const char *canonicalName(const char *name);
+
+ static void free(const char *str);
};
struct File : Object
@@ -132,8 +137,8 @@ struct File : Object
FileName *name; // name of our file
- File(char *);
- File(FileName *);
+ File(const char *);
+ File(const FileName *);
~File();
void mark();
@@ -271,7 +276,7 @@ struct OutBuffer : Object
char *extractString();
};
-struct Array : Object
+struct Array
{
size_t dim;
void **data;
diff --git a/dmd2/root/stringtable.c b/dmd2/root/stringtable.c
index 5464f7f0..f1ea45d3 100644
--- a/dmd2/root/stringtable.c
+++ b/dmd2/root/stringtable.c
@@ -1,5 +1,5 @@
-// Copyright (c) 1999-2011 by Digital Mars
+// Copyright (c) 1999-2013 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
diff --git a/dmd2/scope.c b/dmd2/scope.c
index a58ed613..09da8d9c 100644
--- a/dmd2/scope.c
+++ b/dmd2/scope.c
@@ -131,7 +131,7 @@ Scope::Scope(Scope *enclosing)
this->parameterSpecialization = enclosing->parameterSpecialization;
this->ignoreTemplates = enclosing->ignoreTemplates;
this->callSuper = enclosing->callSuper;
- this->flags = (enclosing->flags & SCOPEcontract);
+ this->flags = (enclosing->flags & (SCOPEcontract | SCOPEdebug));
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = enclosing->docbuf;
diff --git a/dmd2/scope.h b/dmd2/scope.h
index 09f60b03..a3b7725b 100644
--- a/dmd2/scope.h
+++ b/dmd2/scope.h
@@ -25,7 +25,6 @@ struct LabelStatement;
struct ForeachStatement;
struct ClassDeclaration;
struct AggregateDeclaration;
-struct AnonymousAggregateDeclaration;
struct FuncDeclaration;
struct DocComment;
struct TemplateInstance;
diff --git a/dmd2/statement.c b/dmd2/statement.c
index 9f064312..02314b12 100644
--- a/dmd2/statement.c
+++ b/dmd2/statement.c
@@ -923,7 +923,8 @@ void UnrolledLoopStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->level++;
for (size_t i = 0; i < statements->dim; i++)
- { Statement *s;
+ {
+ Statement *s;
s = (*statements)[i];
if (s)
@@ -1131,46 +1132,20 @@ bool WhileStatement::hasContinue()
bool WhileStatement::usesEH()
{
- assert(0);
- return body ? body->usesEH() : 0;
+ assert(global.errors);
+ return 0;
}
int WhileStatement::blockExit(bool mustNotThrow)
{
- assert(0);
- //printf("WhileStatement::blockExit(%p)\n", this);
-
- int result = BEnone;
- if (condition->canThrow(mustNotThrow))
- result |= BEthrow;
- if (condition->isBool(TRUE))
- {
- if (body)
- { result |= body->blockExit(mustNotThrow);
- if (result & BEbreak)
- result |= BEfallthru;
- }
- }
- else if (condition->isBool(FALSE))
- {
- result |= BEfallthru;
- }
- else
- {
- if (body)
- result |= body->blockExit(mustNotThrow);
- result |= BEfallthru;
- }
- result &= ~(BEbreak | BEcontinue);
- return result;
+ assert(global.errors);
+ return BEfallthru;
}
int WhileStatement::comeFrom()
{
- assert(0);
- if (body)
- return body->comeFrom();
+ assert(global.errors);
return FALSE;
}
@@ -1847,7 +1822,9 @@ Lagain:
{
/* Reference to immutable data should be marked as const
*/
- if (!tn->isMutable())
+ if (aggr->checkModifiable(sc, 1) == 2)
+ var->storage_class |= STCctorinit;
+ else if (!tn->isMutable())
var->storage_class |= STCconst;
Type *t = tab->nextOf();
@@ -1982,18 +1959,12 @@ Lagain:
error("only one or two arguments for associative array foreach");
break;
}
-#if SARRAYVALUE
+
/* This only works if Key or Value is a static array.
*/
tab = taa->getImpl()->type;
goto Lagain;
-#else
- if (op == TOKforeach_reverse)
- {
- error("no reverse iteration on associative arrays");
- }
- goto Lapply;
-#endif
+
case Tclass:
case Tstruct:
#if DMDV2
@@ -2757,33 +2728,20 @@ bool ForeachRangeStatement::hasContinue()
bool ForeachRangeStatement::usesEH()
{
- assert(0);
+ assert(global.errors);
return body->usesEH();
}
int ForeachRangeStatement::blockExit(bool mustNotThrow)
{
- assert(0);
- int result = BEfallthru;
-
- if (lwr && lwr->canThrow(mustNotThrow))
- result |= BEthrow;
- else if (upr && upr->canThrow(mustNotThrow))
- result |= BEthrow;
-
- if (body)
- {
- result |= body->blockExit(mustNotThrow) & ~(BEbreak | BEcontinue);
- }
- return result;
+ assert(global.errors);
+ return BEfallthru;
}
int ForeachRangeStatement::comeFrom()
{
- assert(0);
- if (body)
- return body->comeFrom();
+ assert(global.errors);
return FALSE;
}
@@ -2952,7 +2910,8 @@ void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
if (arg->type)
arg->type->toCBuffer(buf, arg->ident, hgs);
else
- { buf->writestring("auto ");
+ {
+ buf->writestring("auto ");
buf->writestring(arg->ident->toChars());
}
buf->writestring(" = ");
@@ -2966,7 +2925,8 @@ void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
if (!ifbody->isScopeStatement())
buf->level--;
if (elsebody)
- { buf->writestring("else");
+ {
+ buf->writestring("else");
buf->writenl();
if (!elsebody->isScopeStatement())
buf->level++;
@@ -3347,7 +3307,8 @@ Statement *SwitchStatement::semantic(Scope *sc)
}
else
{ condition = condition->integralPromotions(sc);
- condition->checkIntegral();
+ if (!condition->type->isintegral())
+ error("'%s' must be of integral or string type, it is a %s", condition->toChars(), condition->type->toChars());
}
condition = condition->optimize(WANTvalue);
@@ -3396,14 +3357,18 @@ Statement *SwitchStatement::semantic(Scope *sc)
#if DMDV2
if (isFinal)
{ Type *t = condition->type;
- while (t->ty == Ttypedef)
+ while (t && t->ty == Ttypedef)
{ // Don't use toBasetype() because that will skip past enums
t = ((TypeTypedef *)t)->sym->basetype;
}
- if (te)
+ Dsymbol *ds;
+ EnumDeclaration *ed = NULL;
+ if (t && ((ds = t->toDsymbol(sc)) != NULL))
+ ed = ds->isEnumDeclaration(); // typedef'ed enum
+ if (!ed && te && ((ds = te->toDsymbol(sc)) != NULL))
+ ed = ds->isEnumDeclaration();
+ if (ed)
{
- EnumDeclaration *ed = te->toDsymbol(sc)->isEnumDeclaration();
- assert(ed);
size_t dim = ed->members->dim;
for (size_t i = 0; i < dim; i++)
{
@@ -3446,8 +3411,10 @@ Statement *SwitchStatement::semantic(Scope *sc)
a->reserve(2);
sc->sw->sdefault = new DefaultStatement(loc, s);
- a->push(sc->sw->sdefault);
a->push(body);
+ if (body->blockExit(FALSE) & BEfallthru)
+ a->push(new BreakStatement(0, NULL));
+ a->push(sc->sw->sdefault);
cs = new CompoundStatement(loc, a);
body = cs;
}
@@ -3494,7 +3461,8 @@ void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
if (body)
{
if (!body->isScopeStatement())
- { buf->writebyte('{');
+ {
+ buf->writebyte('{');
buf->writenl();
buf->level++;
body->toCBuffer(buf, hgs);
@@ -3571,7 +3539,7 @@ Statement *CaseStatement::semantic(Scope *sc)
if (exp->op != TOKstring && exp->op != TOKint64 && exp->op != TOKerror)
{
error("case must be a string or an integral constant, not %s", exp->toChars());
- exp = new IntegerExp(0);
+ exp = new ErrorExp();
}
L1:
@@ -4077,7 +4045,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
}
else
{
- if (tf->isref)
+ if (tf->isref && (fd->storage_class & STCauto))
{ /* Determine "refness" of function return:
* if it's an lvalue, return by ref, else return by value
*/
@@ -4090,11 +4058,11 @@ Statement *ReturnStatement::semantic(Scope *sc)
unsigned errors = global.startGagging();
exp->checkEscapeRef();
if (global.endGagging(errors))
- { tf->isref = FALSE; // return by value
- }
+ tf->isref = FALSE; // return by value
}
else
tf->isref = FALSE; // return by value
+ fd->storage_class &= ~STCauto;
}
tf->next = exp->type;
//fd->type = tf->semantic(loc, sc); // Removed with 6902
@@ -4790,7 +4758,7 @@ Statement *WithStatement::semantic(Scope *sc)
sym->parent = sc->scopesym;
}
else
- { error("with expressions must be class objects, not '%s'", exp->type->toChars());
+ { error("with expressions must be aggregate types, not '%s'", exp->type->toChars());
return NULL;
}
}
@@ -5273,9 +5241,10 @@ Statement *ThrowStatement::semantic(Scope *sc)
int ThrowStatement::blockExit(bool mustNotThrow)
{
- if (mustNotThrow)
+ Type *t = exp->type->toBasetype();
+ if (mustNotThrow && t->ty != Terror)
{
- ClassDeclaration *cd = exp->type->toBasetype()->isClassHandle();
+ ClassDeclaration *cd = t->isClassHandle();
assert(cd);
// Bugzilla 8675
@@ -5653,6 +5622,7 @@ void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("asm { ");
Token *t = tokens;
+ buf->level++;
while (t)
{
buf->writestring(t->toChars());
@@ -5673,6 +5643,7 @@ void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
}
t = t->next;
}
+ buf->level--;
buf->writestring("; }");
buf->writenl();
}
diff --git a/dmd2/statement.h b/dmd2/statement.h
index e085a409..4ff0ddee 100644
--- a/dmd2/statement.h
+++ b/dmd2/statement.h
@@ -673,7 +673,7 @@ struct SwitchErrorStatement : Statement
struct ReturnStatement : Statement
{
Expression *exp;
- int implicit0;
+ bool implicit0; // this is an implicit "return 0;"
ReturnStatement(Loc loc, Expression *exp);
Statement *syntaxCopy();
diff --git a/dmd2/staticassert.c b/dmd2/staticassert.c
index 662b74a1..3ce09b1d 100644
--- a/dmd2/staticassert.c
+++ b/dmd2/staticassert.c
@@ -3,7 +3,6 @@
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
-// http://www.dsource.org/projects/dmd/browser/trunk/src/staticassert.c
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
diff --git a/dmd2/struct.c b/dmd2/struct.c
index 3bef2d59..6c7135d2 100644
--- a/dmd2/struct.c
+++ b/dmd2/struct.c
@@ -441,11 +441,7 @@ void StructDeclaration::semantic(Scope *sc)
parent = sc->parent;
type = type->semantic(loc, sc);
-#if STRUCTTHISREF
handle = type;
-#else
- handle = type->pointerTo();
-#endif
protection = sc->protection;
alignment = sc->structalign;
storage_class |= sc->stc;
@@ -743,7 +739,7 @@ void StructDeclaration::finalizeSize(Scope *sc)
void StructDeclaration::makeNested()
{
- if (!isnested && sizeok != SIZEOKdone)
+ if (!isnested && sizeok != SIZEOKdone && !isUnionDeclaration())
{
// If nested struct, add in hidden 'this' pointer to outer scope
if (!(storage_class & STCstatic))
diff --git a/dmd2/template.c b/dmd2/template.c
index bafbf7ae..367db45d 100644
--- a/dmd2/template.c
+++ b/dmd2/template.c
@@ -699,7 +699,7 @@ void TemplateDeclaration::makeParamNamesVisibleInConstraint(Scope *paramscope, E
if (!paramscope->insert(v))
error("parameter %s.%s is already defined", toChars(), v->toChars());
else
- v->parent = this;
+ v->parent = fd;
}
}
}
@@ -1350,6 +1350,15 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
if (m < match)
match = m;
+ /* Remove top const for dynamic array types and pointer types
+ */
+ if ((tt->ty == Tarray || tt->ty == Tpointer) &&
+ !tt->isMutable() &&
+ (!(fparam->storageClass & STCref) ||
+ (fparam->storageClass & STCauto) && !farg->isLvalue()))
+ {
+ tt = tt->mutableOf();
+ }
t->objects[i] = tt;
}
declareParameter(paramscope, tp, t);
@@ -1585,21 +1594,7 @@ Lretry:
if (m && (fparam->storageClass & (STCref | STCauto)) == STCref)
{ if (!farg->isLvalue())
{
- if (farg->op == TOKstructliteral)
- m = MATCHconvert;
- else if (farg->op == TOKcall)
- {
- CallExp *ce = (CallExp *)farg;
- if (ce->e1->op == TOKdotvar &&
- ((DotVarExp *)ce->e1)->var->isCtorDeclaration())
- {
- m = MATCHconvert;
- }
- else
- goto Lnomatch;
- }
- else
- goto Lnomatch;
+ goto Lnomatch;
}
}
if (m && (fparam->storageClass & STCout))
@@ -2253,22 +2248,19 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
/* As Bugzilla 3682 shows, a template instance can be matched while instantiating
* that same template. Thus, the function type can be incomplete. Complete it.
+ *
+ * Bugzilla 9208: For auto function, completion should be deferred to the end of
+ * its semantic3. Should not complete it in here.
*/
{ TypeFunction *tf = (TypeFunction *)fd_best->type;
assert(tf->ty == Tfunction);
- if (tf->next)
+ if (tf->next && !fd_best->inferRetType)
+ {
fd_best->type = tf->semantic(loc, sc);
+ }
}
- if (fd_best->scope)
- {
- TemplateInstance *spec = fd_best->isSpeculative();
- int olderrs = global.errors;
- fd_best->semantic3(fd_best->scope);
- // Update the template instantiation with the number
- // of errors which occured.
- if (spec && global.errors != olderrs)
- spec->errors = global.errors - olderrs;
- }
+
+ fd_best->functionSemantic();
return fd_best;
@@ -2448,9 +2440,11 @@ char *TemplateDeclaration::toChars()
}
buf.writeByte(')');
- if (onemember && onemember->toAlias())
- {
- FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration();
+ if (onemember)
+ { /* Bugzilla 9406:
+ * onemember->toAlias() might run semantic, so should not call it in stringizing
+ */
+ FuncDeclaration *fd = onemember->isFuncDeclaration();
if (fd && fd->type)
{
TypeFunction *tf = (TypeFunction *)fd->type;
@@ -3983,6 +3977,45 @@ Lnomatch:
return 0;
}
+/* Bugzilla 6538: In template constraint, each function parameters, 'this',
+ * and 'super' is *pseudo* symbol. If it is passed to other template through
+ * alias/tuple parameter, it will cause an error. Because such symbol
+ * does not have the actual entity yet.
+ *
+ * Example:
+ * template Sym(alias A) { enum Sym = true; }
+ * struct S {
+ * void foo() if (Sym!(this)) {} // Sym!(this) always make an error,
+ * } // because Sym template cannot
+ * void main() { S s; s.foo(); } // access to the valid 'this' symbol.
+ */
+bool isPseudoDsymbol(Object *o)
+{
+ Dsymbol *s = isDsymbol(o);
+ Expression *e = isExpression(o);
+ if (e && e->op == TOKvar) s = ((VarExp *)e)->var->isVarDeclaration();
+ if (e && e->op == TOKthis) s = ((ThisExp *)e)->var->isThisDeclaration();
+ if (e && e->op == TOKsuper) s = ((SuperExp *)e)->var->isThisDeclaration();
+
+ if (s && s->parent)
+ {
+ s = s->toAlias();
+ VarDeclaration *v = s->isVarDeclaration();
+ TupleDeclaration *t = s->isTupleDeclaration();
+ if (v || t)
+ {
+ FuncDeclaration *fd = s->parent->isFuncDeclaration();
+ if (fd && fd->parent && fd->parent->isTemplateDeclaration())
+ {
+ const char *str = (e && e->op == TOKsuper) ? "super" : s->toChars();
+ ::error(s->loc, "cannot take a not yet instantiated symbol '%s' inside template constraint", str);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
MATCH TemplateAliasParameter::matchArg(Scope *sc, Objects *tiargs,
size_t i, TemplateParameters *parameters, Objects *dedtypes,
Declaration **psparam)
@@ -4678,7 +4711,10 @@ Dsymbol *TemplateInstance::syntaxCopy(Dsymbol *s)
ti->tiargs = arraySyntaxCopy(tiargs);
- ScopeDsymbol::syntaxCopy(ti);
+ if (inst)
+ tempdecl->ScopeDsymbol::syntaxCopy(ti);
+ else
+ ScopeDsymbol::syntaxCopy(ti);
return ti;
}
@@ -5020,8 +5056,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
a = scx->scopesym->members;
}
else
- { //Module *m = sc->module->importedFrom;
- Module *m = tempdecl->scope->module->importedFrom;
+ {
+ Module *m = (isnested ? sc : tempdecl->scope)->module->importedFrom;
//printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
a = m->members;
if (m->semanticRun >= 3)
@@ -5045,6 +5081,11 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
#endif
// Copy the syntax trees from the TemplateDeclaration
+#if IN_LLVM // Backport of DMD pull request #1760.
+ if (members && speculative)
+ {} // Don't copy again so they were previously created.
+ else
+#endif
members = Dsymbol::arraySyntaxCopy(tempdecl->members);
// Create our own scope for the template parameters
@@ -5278,70 +5319,50 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
//printf("type %s\n", ta->toChars());
// It might really be an Expression or an Alias
ta->resolve(loc, sc, &ea, &ta, &sa);
- if (ea)
- {
- ea = ea->semantic(sc);
- //printf("-> ea = %s %s\n", Token::toChars(ea->op), ea->toChars());
- /* This test is to skip substituting a const var with
- * its initializer. The problem is the initializer won't
- * match with an 'alias' parameter. Instead, do the
- * const substitution in TemplateValueParameter::matchArg().
- */
- if (flags & 1) // only used by __traits, must not interpret the args
- ea = ea->optimize(WANTvalue);
- else if (ea->op != TOKvar)
- ea = ea->ctfeInterpret();
- (*tiargs)[j] = ea;
- }
- else if (sa)
- {
- Ldsym:
- (*tiargs)[j] = sa;
- TupleDeclaration *d = sa->toAlias()->isTupleDeclaration();
- if (d)
- {
- size_t dim = d->objects->dim;
- tiargs->remove(j);
- tiargs->insert(j, d->objects);
- j--;
- }
- }
- else if (ta)
- {
- Ltype:
- if (ta->ty == Ttuple)
- { // Expand tuple
- TypeTuple *tt = (TypeTuple *)ta;
- size_t dim = tt->arguments->dim;
- tiargs->remove(j);
- if (dim)
- { tiargs->reserve(dim);
- for (size_t i = 0; i < dim; i++)
- { Parameter *arg = (*tt->arguments)[i];
- if (flags & 2 && arg->ident)
- tiargs->insert(j + i, arg);
- else
- tiargs->insert(j + i, arg->type);
- }
- }
- j--;
- }
- else
- (*tiargs)[j] = ta;
- }
- else
+ if (ea) goto Lexpr;
+ if (sa) goto Ldsym;
+ if (ta == NULL)
{
assert(global.errors);
- (*tiargs)[j] = Type::terror;
+ ta = Type::terror;
}
+
+ Ltype:
+ if (ta->ty == Ttuple)
+ { // Expand tuple
+ TypeTuple *tt = (TypeTuple *)ta;
+ size_t dim = tt->arguments->dim;
+ tiargs->remove(j);
+ if (dim)
+ { tiargs->reserve(dim);
+ for (size_t i = 0; i < dim; i++)
+ { Parameter *arg = (*tt->arguments)[i];
+ if (flags & 2 && arg->ident)
+ tiargs->insert(j + i, arg);
+ else
+ tiargs->insert(j + i, arg->type);
+ }
+ }
+ j--;
+ continue;
+ }
+ (*tiargs)[j] = ta;
}
else if (ea)
{
+ Lexpr:
//printf("+[%d] ea = %s %s\n", j, Token::toChars(ea->op), ea->toChars());
ea = ea->semantic(sc);
if (flags & 1) // only used by __traits, must not interpret the args
ea = ea->optimize(WANTvalue);
- else if (ea->op != TOKvar && ea->op != TOKtuple &&
+ else if (ea->op == TOKvar)
+ { /* This test is to skip substituting a const var with
+ * its initializer. The problem is the initializer won't
+ * match with an 'alias' parameter. Instead, do the
+ * const substitution in TemplateValueParameter::matchArg().
+ */
+ }
+ else if (ea->op != TOKtuple &&
ea->op != TOKimport && ea->op != TOKtype &&
ea->op != TOKfunction && ea->op != TOKerror &&
ea->op != TOKthis && ea->op != TOKsuper)
@@ -5352,7 +5373,25 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
ea = new ErrorExp();
}
//printf("-[%d] ea = %s %s\n", j, Token::toChars(ea->op), ea->toChars());
+ if (!flags && isPseudoDsymbol(ea))
+ { (*tiargs)[j] = new ErrorExp();
+ continue;
+ }
+ if (ea->op == TOKtuple)
+ { // Expand tuple
+ TupleExp *te = (TupleExp *)ea;
+ size_t dim = te->exps->dim;
+ tiargs->remove(j);
+ if (dim)
+ { tiargs->reserve(dim);
+ for (size_t i = 0; i < dim; i++)
+ tiargs->insert(j + i, (*te->exps)[i]);
+ }
+ j--;
+ continue;
+ }
(*tiargs)[j] = ea;
+
if (ea->op == TOKtype)
{ ta = ea->type;
goto Ltype;
@@ -5375,9 +5414,8 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
else if (fe->td)
{ /* If template argument is a template lambda,
* get template declaration itself. */
- ea = NULL;
- (*tiargs)[j] = sa = fe->td;
- goto Lsa;
+ sa = fe->td;
+ goto Ldsym;
}
}
if (ea->op == TOKdotvar)
@@ -5394,25 +5432,31 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
sa = ((DotTemplateExp *)ea)->td;
goto Ldsym;
}
- if (ea->op == TOKtuple)
- { // Expand tuple
- TupleExp *te = (TupleExp *)ea;
- size_t dim = te->exps->dim;
- tiargs->remove(j);
- if (dim)
- { tiargs->reserve(dim);
- for (size_t i = 0; i < dim; i++)
- tiargs->insert(j + i, (*te->exps)[i]);
- }
- j--;
- }
}
else if (sa)
{
- Lsa:
+ Ldsym:
+ //printf("dsym %s %s\n", sa->kind(), sa->toChars());
+ if (!flags && isPseudoDsymbol(sa))
+ { (*tiargs)[j] = new ErrorExp();
+ continue;
+ }
+ TupleDeclaration *d = sa->toAlias()->isTupleDeclaration();
+ if (d)
+ { // Expand tuple
+ size_t dim = d->objects->dim;
+ tiargs->remove(j);
+ tiargs->insert(j, d->objects);
+ j--;
+ continue;
+ }
+ (*tiargs)[j] = sa;
+
TemplateDeclaration *td = sa->isTemplateDeclaration();
if (td && !td->semanticRun && td->literal)
+ {
td->semantic(sc);
+ }
}
else if (isParameter(o))
{
@@ -6002,7 +6046,7 @@ int TemplateInstance::needsTypeInference(Scope *sc)
*/
FuncDeclaration *fd;
if (!td->onemember ||
- (fd = td->onemember->toAlias()->isFuncDeclaration()) == NULL ||
+ (fd = td->onemember/*->toAlias()*/->isFuncDeclaration()) == NULL ||
fd->type->ty != Tfunction)
{
/* Not a template function, therefore type inference is not possible.
@@ -6516,30 +6560,25 @@ void TemplateMixin::semantic(Scope *sc)
{
if (!td->semanticRun)
{
- if (td->scope)
- td->semantic(td->scope);
+ /* Cannot handle forward references if mixin is a struct member,
+ * because addField must happen during struct's semantic, not
+ * during the mixin semantic.
+ * runDeferred will re-run mixin's semantic outside of the struct's
+ * semantic.
+ */
+ semanticRun = PASSinit;
+ AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
+ if (ad)
+ ad->sizeok = SIZEOKfwd;
else
{
- /* Cannot handle forward references if mixin is a struct member,
- * because addField must happen during struct's semantic, not
- * during the mixin semantic.
- * runDeferred will re-run mixin's semantic outside of the struct's
- * semantic.
- */
- semanticRun = PASSinit;
- AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
- if (ad)
- ad->sizeok = SIZEOKfwd;
- else
- {
- // Forward reference
- //printf("forward reference - deferring\n");
- scope = scx ? scx : new Scope(*sc);
- scope->setNoFree();
- scope->module->addDeferredSemantic(this);
- }
- return;
+ // Forward reference
+ //printf("forward reference - deferring\n");
+ scope = scx ? scx : new Scope(*sc);
+ scope->setNoFree();
+ scope->module->addDeferredSemantic(this);
}
+ return;
}
}
@@ -6610,6 +6649,11 @@ void TemplateMixin::semantic(Scope *sc)
}
// Copy the syntax trees from the TemplateDeclaration
+#if IN_LLVM // Backport of DMD pull request #1760.
+ if (scx && members)
+ {} // Don't copy again so they were previously created.
+ else
+#endif
members = Dsymbol::arraySyntaxCopy(tempdecl->members);
if (!members)
return;
@@ -6658,6 +6702,8 @@ void TemplateMixin::semantic(Scope *sc)
sc2 = argscope->push(this);
sc2->offset = sc->offset;
+ size_t deferred_dim = Module::deferred.dim;
+
static int nest;
//printf("%d\n", nest);
if (++nest > 500)
@@ -6677,6 +6723,36 @@ void TemplateMixin::semantic(Scope *sc)
sc->offset = sc2->offset;
+ if (!sc->func && Module::deferred.dim > deferred_dim)
+ {
+ sc2->pop();
+ argscope->pop();
+ scy->pop();
+ //printf("deferring mixin %s, deferred.dim += %d\n", toChars(), Module::deferred.dim - deferred_dim);
+ //printf("\t[");
+ //for (size_t u = 0; u < Module::deferred.dim; u++) printf("%s%s", Module::deferred[u]->toChars(), u == Module::deferred.dim-1?"":", ");
+ //printf("]\n");
+
+ semanticRun = PASSinit;
+ AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
+ if (ad)
+ {
+ /* Forward reference of base class should not make derived class SIZEfwd.
+ */
+ //printf("\tad = %s, sizeok = %d\n", ad->toChars(), ad->sizeok);
+ //ad->sizeok = SIZEOKfwd;
+ }
+ else
+ {
+ // Forward reference
+ //printf("forward reference - deferring\n");
+ scope = scx ? scx : new Scope(*sc);
+ scope->setNoFree();
+ scope->module->addDeferredSemantic(this);
+ }
+ return;
+ }
+
/* The problem is when to parse the initializer for a variable.
* Perhaps VarDeclaration::semantic() should do it like it does
* for initializers inside a function.
diff --git a/dmd2/template.h b/dmd2/template.h
index bd0b872f..108f3c5b 100644
--- a/dmd2/template.h
+++ b/dmd2/template.h
@@ -89,7 +89,7 @@ struct TemplateDeclaration : ScopeDsymbol
char *toChars();
void emitComment(Scope *sc);
- void toJsonBuffer(OutBuffer *buf);
+ void toJson(JsonOut *json);
// void toDocBuffer(OutBuffer *buf);
MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, Expressions *fargs, int flag);
@@ -328,7 +328,7 @@ struct TemplateInstance : ScopeDsymbol
int oneMember(Dsymbol **ps, Identifier *ident);
int needsTypeInference(Scope *sc);
char *toChars();
- char *mangle();
+ char *mangle(bool isv = false);
void printInstantiationTrace();
#if IN_DMD
@@ -378,6 +378,7 @@ struct TemplateMixin : TemplateInstance
char *toChars();
char *mangle();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+ void toJson(JsonOut *json);
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
diff --git a/dmd2/traits.c b/dmd2/traits.c
index 0b686777..411bee0d 100644
--- a/dmd2/traits.c
+++ b/dmd2/traits.c
@@ -267,9 +267,10 @@ Expression *TraitsExp::semantic(Scope *sc)
{
if (FuncDeclaration *fd = s->isFuncDeclaration()) // Bugzilla 8943
s = fd->toAliasFunc();
- s = s->toParent();
+ if (!s->isImport()) // Bugzilla 8922
+ s = s->toParent();
}
- if (!s)
+ if (!s || s->isImport())
{
error("argument %s has no parent", o->toChars());
goto Lfalse;
diff --git a/dmd2/utf.c b/dmd2/utf.c
index 52230b28..c05fc101 100644
--- a/dmd2/utf.c
+++ b/dmd2/utf.c
@@ -1,4 +1,3 @@
-// utf.c
// Copyright (c) 2003-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
diff --git a/dmd2/utf.h b/dmd2/utf.h
index e48ffaab..22e405bc 100644
--- a/dmd2/utf.h
+++ b/dmd2/utf.h
@@ -1,5 +1,4 @@
// Compiler implementation of the D programming language
-// utf.h
// Copyright (c) 2003-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
diff --git a/driver/cl_options.cpp b/driver/cl_options.cpp
index 76878d02..c88a2633 100644
--- a/driver/cl_options.cpp
+++ b/driver/cl_options.cpp
@@ -187,6 +187,10 @@ cl::opt hdrFile("Hf",
cl::value_desc("filename"),
cl::Prefix);
+static cl::opt hdrKeepAllBodies("Hkeep-all-bodies",
+ cl::desc("Keep all function bodies in .di files"),
+ cl::ZeroOrMore,
+ cl::location(global.params.hdrKeepAllBodies));
static cl::opt unittest("unittest",
cl::desc("Compile in unit tests"),
diff --git a/driver/ldmd.cpp b/driver/ldmd.cpp
index 940dc256..f918d61a 100644
--- a/driver/ldmd.cpp
+++ b/driver/ldmd.cpp
@@ -822,7 +822,11 @@ void buildCommandLine(std::vector& r, const Params& p)
if (p.jsonName) r.push_back(concat("-Xf=", p.jsonName));
if (p.ignoreUnsupportedPragmas) r.push_back("-ignore");
if (p.enforcePropertySyntax) r.push_back("-property");
- if (p.enableInline) r.push_back("-enable-inlining");
+ if (p.enableInline) {
+ // -inline also influences .di generation with DMD.
+ r.push_back("-enable-inlining");
+ r.push_back("-Hkeep-all-bodies");
+ }
if (p.emitStaticLib) r.push_back("-lib");
if (p.noFloat) warning("-nofloat is ignored by LDC.");
if (p.quiet) r.push_back("-quiet"); // Undocumented.
diff --git a/driver/main.cpp b/driver/main.cpp
index 4dd31edc..3ebafbc5 100644
--- a/driver/main.cpp
+++ b/driver/main.cpp
@@ -51,11 +51,6 @@
#include
#endif
-// stricmp
-#if __GNUC__ && !_WIN32
-#include "gnuc.h"
-#endif
-
// Needs Type already declared.
#include "cond.h"
@@ -166,7 +161,7 @@ int main(int argc, char** argv)
llvm::sys::PrintStackTraceOnErrorSignal();
Strings files;
- char *p, *ext;
+ const char *p, *ext;
Module *m;
int status = EXIT_SUCCESS;
@@ -311,7 +306,14 @@ int main(int argc, char** argv)
// we're looking for it anyway, and pre-setting the flag...
global.params.run = true;
if (!runargs.empty()) {
- files.push(mem.strdup(runargs[0].c_str()));
+ char const * name = runargs[0].c_str();
+ char const * ext = FileName::ext(name);
+ if (ext && FileName::equals(ext, "d") == 0 &&
+ FileName::equals(ext, "di") == 0) {
+ error("-run must be followed by a source file, not '%s'", name);
+ }
+
+ files.push(mem.strdup(name));
runargs.erase(runargs.begin());
} else {
global.params.run = false;
@@ -378,7 +380,7 @@ int main(int argc, char** argv)
// LDC output determination
// if we don't link, autodetect target from extension
- if(!global.params.link && global.params.objname) {
+ if(!global.params.link && !createStaticLib && global.params.objname) {
ext = FileName::ext(global.params.objname);
bool autofound = false;
if (!ext) {
@@ -792,8 +794,8 @@ int main(int argc, char** argv)
modules.reserve(files.dim);
for (unsigned i = 0; i < files.dim; i++)
{ Identifier *id;
- char *ext;
- char *name;
+ const char *ext;
+ const char *name;
p = static_cast(files.data[i]);
@@ -805,9 +807,9 @@ int main(int argc, char** argv)
if (strcmp(ext, global.obj_ext) == 0 ||
strcmp(ext, global.bc_ext) == 0)
#else
- if (stricmp(ext, global.obj_ext) == 0 ||
- stricmp(ext, global.obj_ext_alt) == 0 ||
- stricmp(ext, global.bc_ext) == 0)
+ if (Port::stricmp(ext, global.obj_ext) == 0 ||
+ Port::stricmp(ext, global.obj_ext_alt) == 0 ||
+ Port::stricmp(ext, global.bc_ext) == 0)
#endif
{
global.params.objfiles->push(static_cast(files.data[i]));
@@ -817,9 +819,9 @@ int main(int argc, char** argv)
#if POSIX
if (strcmp(ext, "a") == 0)
#elif __MINGW32__
- if (stricmp(ext, "a") == 0)
+ if (Port::stricmp(ext, "a") == 0)
#else
- if (stricmp(ext, "lib") == 0)
+ if (Port::stricmp(ext, "lib") == 0)
#endif
{
global.params.libfiles->push(static_cast(files.data[i]));
@@ -840,41 +842,40 @@ int main(int argc, char** argv)
}
#if !POSIX
- if (stricmp(ext, "res") == 0)
+ if (Port::stricmp(ext, "res") == 0)
{
global.params.resfile = static_cast(files.data[i]);
continue;
}
- if (stricmp(ext, "def") == 0)
+ if (Port::stricmp(ext, "def") == 0)
{
global.params.deffile = static_cast(files.data[i]);
continue;
}
- if (stricmp(ext, "exe") == 0)
+ if (Port::stricmp(ext, "exe") == 0)
{
global.params.exefile = static_cast(files.data[i]);
continue;
}
#endif
- if (stricmp(ext, global.mars_ext) == 0 ||
- stricmp(ext, global.hdr_ext) == 0)
+ if (Port::stricmp(ext, global.mars_ext) == 0 ||
+ Port::stricmp(ext, global.hdr_ext) == 0)
{
ext--; // skip onto '.'
assert(*ext == '.');
- name = static_cast(mem.malloc((ext - p) + 1));
- memcpy(name, p, ext - p);
- name[ext - p] = 0; // strip extension
+ char *tmp = static_cast(mem.malloc((ext - p) + 1));
+ memcpy(tmp, p, ext - p);
+ tmp[ext - p] = 0; // strip extension
+ name = tmp;
if (name[0] == 0 ||
strcmp(name, "..") == 0 ||
strcmp(name, ".") == 0)
{
- Linvalid:
- error("invalid file name '%s'", static_cast(files.data[i]));
- fatal();
+ goto Linvalid;
}
}
else
@@ -884,8 +885,13 @@ int main(int argc, char** argv)
}
else
{ name = p;
- if (!*name)
- goto Linvalid;
+ if (!*p)
+ {
+ Linvalid:
+ error("invalid file name '%s'", static_cast(files.data[i]));
+ fatal();
+ }
+ name = p;
}
id = Lexer::idPool(name);
@@ -984,17 +990,6 @@ int main(int argc, char** argv)
if (global.errors)
fatal();
-#if !IN_LLVM
- // Scan for functions to inline
- if (global.params.useInline)
- {
- /* The problem with useArrayBounds and useAssert is that the
- * module being linked to may not have generated them, so if
- * we inline functions from those modules, the symbols for them will
- * not be found at link time.
- */
- if (!global.params.useArrayBounds && !global.params.useAssert)
-#else
// This doesn't play nice with debug info at the moment.
//
// Also, don't run the additional semantic3 passes when building unit tests.
@@ -1016,7 +1011,6 @@ int main(int argc, char** argv)
{
global.params.useAvailableExternally = true;
Logger::println("Running some extra semantic3's for inlining purposes");
-#endif
{
// Do pass 3 semantic analysis on all imported modules,
// since otherwise functions in them cannot be inlined
@@ -1031,16 +1025,6 @@ int main(int argc, char** argv)
if (global.errors)
fatal();
}
-
-#if !IN_LLVM
- for (int i = 0; i < modules.dim; i++)
- {
- m = static_cast(modules.data[i]);
- if (global.params.verbose)
- printf("inline scan %s\n", m->toChars());
- m->inlineScan();
- }
-#endif
}
if (global.errors || global.warnings)
fatal();
@@ -1073,7 +1057,7 @@ int main(int argc, char** argv)
{
m->deleteObjFile();
writeModule(lm, m->objfile->name->str);
- global.params.objfiles->push(m->objfile->name->str);
+ global.params.objfiles->push(const_cast(m->objfile->name->str));
delete lm;
}
else
@@ -1094,10 +1078,10 @@ int main(int argc, char** argv)
Module* m = static_cast(modules.data[0]);
char* oname;
- char* filename;
+ const char* filename;
if ((oname = global.params.exefile) || (oname = global.params.objname))
{
- filename = FileName::forceExt(oname, global.obj_ext)->toChars();
+ filename = FileName::forceExt(oname, global.obj_ext);
if (global.params.objdir)
{
filename = FileName::combine(global.params.objdir, FileName::name(filename));
@@ -1108,7 +1092,7 @@ int main(int argc, char** argv)
#if 1
// Temporary workaround for http://llvm.org/bugs/show_bug.cgi?id=11479.
- char* moduleName = filename;
+ char* moduleName = const_cast(filename);
#else
char* moduleName = m->toChars();
#endif
@@ -1124,12 +1108,55 @@ int main(int argc, char** argv)
m->deleteObjFile();
writeModule(linker.getModule(), filename);
- global.params.objfiles->push(filename);
+ global.params.objfiles->push(const_cast(filename));
}
// output json file
if (global.params.doXGeneration)
- json_generate(&modules);
+ {
+ OutBuffer buf;
+ json_generate(&buf, &modules);
+
+ // Write buf to file
+ const char *name = global.params.xfilename;
+
+ if (name && name[0] == '-' && name[1] == 0)
+ { // Write to stdout; assume it succeeds
+ int n = fwrite(buf.data, 1, buf.offset, stdout);
+ assert(n == buf.offset); // keep gcc happy about return values
+ }
+ else
+ {
+ /* The filename generation code here should be harmonized with Module::setOutfile()
+ */
+
+ const char *jsonfilename;
+
+ if (name && *name)
+ {
+ jsonfilename = FileName::defaultExt(name, global.json_ext);
+ }
+ else
+ {
+ // Generate json file name from first obj name
+ const char *n = (*global.params.objfiles)[0];
+ n = FileName::name(n);
+
+ //if (!FileName::absolute(name))
+ //name = FileName::combine(dir, name);
+
+ jsonfilename = FileName::forceExt(n, global.json_ext);
+ }
+
+ FileName::ensurePathToNameExists(jsonfilename);
+
+ File *jsonfile = new File(jsonfilename);
+
+ jsonfile->setbuffer(buf.data, buf.offset);
+ jsonfile->ref = 1;
+ jsonfile->writev();
+ }
+ }
backend_term();
if (global.errors)
diff --git a/gen/abi-ppc64.cpp b/gen/abi-ppc64.cpp
index d707193c..d8f110ce 100644
--- a/gen/abi-ppc64.cpp
+++ b/gen/abi-ppc64.cpp
@@ -1,4 +1,4 @@
-//===-- abi-x86-64.cpp ----------------------------------------------------===//
+//===-- abi-ppc64.cpp -----------------------------------------------------===//
//
// LDC – the LLVM D compiler
//
@@ -29,10 +29,9 @@ struct PPC64TargetABI : TargetABI {
case LINKintrinsic:
case LINKpascal:
case LINKwindows:
- return llvm::CallingConv::C;
case LINKd:
case LINKdefault:
- return llvm::CallingConv::Fast;
+ return llvm::CallingConv::C;
default:
llvm_unreachable("Unhandled D linkage type.");
}
diff --git a/gen/abi-ppc64.h b/gen/abi-ppc64.h
index 367701af..fbf9c688 100644
--- a/gen/abi-ppc64.h
+++ b/gen/abi-ppc64.h
@@ -1,4 +1,4 @@
-//===-- gen/abi-x86-64.h - x86_64 ABI description ---------------*- C++ -*-===//
+//===-- gen/abi-ppc-64.h - PPC64 ABI description ----------------*- C++ -*-===//
//
// LDC – the LLVM D compiler
//
diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp
index 7d410fb4..85736c33 100644
--- a/gen/llvmhelpers.cpp
+++ b/gen/llvmhelpers.cpp
@@ -741,6 +741,14 @@ DValue* DtoCastNull(Loc& loc, DValue* val, Type* to)
rval = DtoAggrPair(DtoConstSize_t(0), rval, "null_array");
return new DImValue(to, rval);
}
+ else if (totype->ty == Tbool)
+ {
+ // In theory, we could return 'false' as a constant here, but DMD
+ // treats non-null values casted to typeof(null) as true.
+ LLValue* rval = val->getRVal();
+ LLValue* zero = LLConstant::getNullValue(rval->getType());
+ return new DImValue(to, gIR->ir->CreateICmpNE(rval, zero, "tmp"));
+ }
else
{
error(loc, "invalid cast from null to '%s'", to->toChars());
diff --git a/gen/naked.cpp b/gen/naked.cpp
index 786d5e8b..f2474192 100644
--- a/gen/naked.cpp
+++ b/gen/naked.cpp
@@ -72,7 +72,7 @@ void ExpStatement::toNakedIR(IRState *p)
Statement::toNakedIR(p);
return;
}
- else if (vd && !vd->isDataseg())
+ else if (vd && !(vd->storage_class & (STCstatic | STCmanifest)))
{
error("non-static variable '%s' not allowed in naked function", vd->toChars());
return;
diff --git a/gen/tocall.cpp b/gen/tocall.cpp
index 9ade207f..35afc353 100644
--- a/gen/tocall.cpp
+++ b/gen/tocall.cpp
@@ -61,8 +61,9 @@ DValue* DtoVaArg(Loc& loc, Type* type, Expression* valistArg)
if (DtoIsPassedByRef(type))
llt = getPtrToType(llt);
// issue a warning for broken va_arg instruction.
- if (global.params.targetTriple.getArch() != llvm::Triple::x86)
- warning(Loc(), "%s: va_arg for C variadic functions is probably broken for anything but x86", loc.toChars());
+ if (global.params.targetTriple.getArch() != llvm::Triple::x86
+ && global.params.targetTriple.getArch() != llvm::Triple::ppc64)
+ warning(Loc(), "%s: va_arg for C variadic functions is probably broken for anything but x86 and ppc64", loc.toChars());
// done
return new DImValue(type, gIR->ir->CreateVAArg(expelem->getLVal(), llt, "tmp"));
}
diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp
index e6e14777..624fefc3 100644
--- a/gen/tollvm.cpp
+++ b/gen/tollvm.cpp
@@ -287,7 +287,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
{
const bool mustDefine = mustDefineSymbol(sym);
- // global variable
+ // global/static variable
if (VarDeclaration* vd = sym->isVarDeclaration())
{
if (mustDefine)
@@ -302,11 +302,23 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
// template
if (needsTemplateLinkage(sym))
return templateLinkage;
- // never use InternalLinkage for variables marked as "extern"
- if (vd->storage_class & STCextern)
+
+ // Currently, we have to consider all variables, even function-local
+ // statics, to be external, as CTFE might cause template functions
+ // instances to be semantic3'd that occur within the body of a function
+ // from an imported module. Consequently, a copy of them is codegen'd
+ // in the importing module, even if they might reference a static in a
+ // function in the imported module (e.g. via an alias parameter).
+ //
+ // A fix for this would be to track instantiations/semantic3 runs made
+ // solely for CTFE purposes in a way similar to how the extra inlining
+ // semantic runs are handled.
+ //
+ // LDC_FIXME: Can this also occur for functions? Find a better solution.
+ if (true || vd->storage_class & STCextern)
return llvm::GlobalValue::ExternalLinkage;
+
}
- // function
else if (FuncDeclaration* fdecl = sym->isFuncDeclaration())
{
if (mustDefine)
diff --git a/gen/typinf.cpp b/gen/typinf.cpp
index f9df4a57..28042511 100644
--- a/gen/typinf.cpp
+++ b/gen/typinf.cpp
@@ -613,10 +613,14 @@ void TypeInfoStructDeclaration::llvmDefine()
b.push_string(sd->toPrettyChars());
// void[] init
- // never emit a null array, even for zero initialized typeinfo
- // the size() method uses this array!
- size_t init_size = getTypeStoreSize(tc->irtype->getLLType());
- b.push_void_array(init_size, irstruct->getInitSymbol());
+ // The protocol is to write a null pointer for zero-initialized arrays. The
+ // length field is always needed for tsize().
+ llvm::Constant *initPtr;
+ if (tc->isZeroInit(0))
+ initPtr = getNullValue(getVoidPtrType());
+ else
+ initPtr = irstruct->getInitSymbol();
+ b.push_void_array(getTypeStoreSize(tc->irtype->getLLType()), initPtr);
// toX functions ground work
static TypeFunction *tftohash;
diff --git a/ldc2.conf.in b/ldc2.conf.in
index 3a13080a..296e6bca 100644
--- a/ldc2.conf.in
+++ b/ldc2.conf.in
@@ -8,8 +8,7 @@ default:
// arguments before they are parsed.
switches = [
"-I@PROJECT_BINARY_DIR@/../import",
- "-I@RUNTIME_DIR@/import",
- "-I@RUNTIME_DIR@/src",
+ "-I@RUNTIME_DIR@/src", // Needed for gc.*/rt.* unit tests.
"-L-L@PROJECT_BINARY_DIR@/../lib@LIB_SUFFIX@", @MULTILIB_ADDITIONAL_PATH@
"-defaultlib=@RUNTIME_AIO@",
"-debuglib=@RUNTIME_AIO@-debug"
diff --git a/ldc2_phobos.conf.in b/ldc2_phobos.conf.in
index b9a17f9d..d5722722 100644
--- a/ldc2_phobos.conf.in
+++ b/ldc2_phobos.conf.in
@@ -8,8 +8,7 @@ default:
// arguments before they are parsed.
switches = [
"-I@CMAKE_BINARY_DIR@/import",
- "-I@RUNTIME_DIR@/import",
- "-I@RUNTIME_DIR@/src",
+ "-I@RUNTIME_DIR@/src", // Needed for gc.*/rt.* unit tests.
"-I@PHOBOS2_DIR@/",
"-L-L@PROJECT_BINARY_DIR@/../lib@LIB_SUFFIX@", @MULTILIB_ADDITIONAL_PATH@
"-defaultlib=phobos-ldc",
diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt
index 87d17dd1..ba436894 100644
--- a/runtime/CMakeLists.txt
+++ b/runtime/CMakeLists.txt
@@ -7,7 +7,7 @@ cmake_minimum_required(VERSION 2.6)
#
set(DMDFE_MINOR_VERSION 0)
-set(DMDFE_PATCH_VERSION 61)
+set(DMDFE_PATCH_VERSION 62)
set(DMDFE_VERSION ${D_VERSION}.${DMDFE_MINOR_VERSION}.${DMDFE_PATCH_VERSION})
set(MULTILIB OFF CACHE BOOL "Build both 32/64 bit runtime libraries")
@@ -95,6 +95,7 @@ file(GLOB_RECURSE CORE_D_WIN ${RUNTIME_DIR}/src/core/sys/windows/*.d)
set(CORE_D_SYS)
if(UNIX)
list(APPEND CORE_D_SYS ${CORE_D_UNIX})
+ list(APPEND DCRT_C ${RUNTIME_DIR}/src/core/threadasm.S)
if(APPLE)
list(APPEND CORE_D_SYS ${CORE_D_OSX})
endif()
@@ -110,7 +111,6 @@ elseif(WIN32)
list(REMOVE_ITEM DCRT_C ${RUNTIME_DC_DIR}/monitor.c)
endif()
list(APPEND CORE_D ${CORE_D_SYNC} ${CORE_D_SYS} ${CORE_D_STDC})
-set(CORE_D_HEADERS ${CORE_D} ${CORE_D_UNIX} ${CORE_D_OSX} ${CORE_D_WIN})
list(APPEND CORE_D ${LDC_D} ${RUNTIME_DIR}/src/object_.d)
file(GLOB CORE_C ${RUNTIME_DIR}/src/core/stdc/*.c)
@@ -238,32 +238,6 @@ macro(dc input_d d_flags output_dir output_suffix outlist_o outlist_bc)
)
endmacro()
-# Builds a .di "header" file for a given D module. The path of the output
-# file is appended to outlist_header.
-macro(dc_header input_d d_flags outlist_header)
- file(RELATIVE_PATH output ${RUNTIME_DIR} ${input_d})
-
- string(REGEX REPLACE "src/ldc" "src/core" output ${output})
- string(REGEX REPLACE "^src/" "" di_output ${output})
-
- # If a hand-written .di file exists along the source in src/, just copy
- # it instead of running it through the compiler.
- if(NOT EXISTS "${input_d}i")
- set(out ${CMAKE_BINARY_DIR}/import/${di_output}i)
- list(APPEND ${outlist_header} ${out})
- add_custom_command(
- OUTPUT ${out}
- COMMAND ${LDC_LOC} ${DC_FLAGS} -c -I${RUNTIME_INCLUDE} -I${RUNTIME_GC_DIR} ${input_d} -Hf=${out} -o- ${d_flags}
- WORKING_DIRECTORY ${PROJECT_PARENT_DIR}
- DEPENDS ${LDC_LOC}
- ${input_d}
- ${LDC_IMPORTS}
- ${PROJECT_BINARY_DIR}/../bin/${LDC_EXE}.conf
- )
- endif()
-endmacro()
-
-
# Builds a copy of druntime/Phobos from the source files gathered above. The
# names of the added library targets are appended to outlist_targets.
macro(build_runtime d_flags c_flags ld_flags lib_suffix path_suffix outlist_targets)
@@ -533,28 +507,39 @@ else()
build_runtime_variants("" "${RT_CLAGS}" "${LD_FLAGS}" "${LIB_SUFFIX}" LIBS_TO_INSTALL)
endif()
-# Generate .di files.
-set(runtime_headers)
-foreach(f ${CORE_D_HEADERS})
- dc_header(${f} "${D_FLAGS}" runtime_headers)
+# Copy over druntime modules, preferring hand-written .di files.
+set(DRUNTIME_IMPORT_DIR ${CMAKE_BINARY_DIR}/import)
+set(DRUNTIME_PACKAGES core etc ldc)
+
+set(druntime_modules)
+foreach(p ${DRUNTIME_PACKAGES})
+ file(GLOB_RECURSE m ${RUNTIME_DIR}/src/${p}/*.d ${RUNTIME_DIR}/src/${p}/*.di)
+ list(APPEND druntime_modules ${m})
+endforeach()
+
+list(APPEND druntime_modules ${RUNTIME_DIR}/src/object.di)
+foreach(f ${druntime_modules})
+ if (NOT EXISTS "${f}i")
+ file(RELATIVE_PATH relpath ${RUNTIME_DIR}/src ${f})
+ configure_file(${f} ${DRUNTIME_IMPORT_DIR}/${relpath} COPYONLY)
+ endif()
endforeach()
-add_custom_target(generate-headers ALL DEPENDS ${runtime_headers})
#
# Install target.
#
-install(DIRECTORY ${CMAKE_BINARY_DIR}/import/core DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.di")
+install(FILES ${DRUNTIME_IMPORT_DIR}/object.di DESTINATION ${INCLUDE_INSTALL_DIR}/ldc)
+foreach(p ${DRUNTIME_PACKAGES})
+ install(DIRECTORY ${DRUNTIME_IMPORT_DIR}/${p} DESTINATION ${INCLUDE_INSTALL_DIR})
+endforeach()
if(PHOBOS2_DIR)
- install(DIRECTORY ${PHOBOS2_DIR}/std DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.d")
- install(DIRECTORY ${PHOBOS2_DIR}/etc DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.d")
- install(FILES ${PHOBOS2_DIR}/crc32.d DESTINATION ${INCLUDE_INSTALL_DIR})
+ install(DIRECTORY ${PHOBOS2_DIR}/std DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.d")
+ install(DIRECTORY ${PHOBOS2_DIR}/etc DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.d")
+ install(FILES ${PHOBOS2_DIR}/crc32.d DESTINATION ${INCLUDE_INSTALL_DIR})
endif()
-install(FILES ${RUNTIME_DIR}/src/object.di DESTINATION ${INCLUDE_INSTALL_DIR}/ldc)
-install(DIRECTORY ${RUNTIME_DIR}/src/ldc DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.di")
-install(DIRECTORY ${RUNTIME_DIR}/src/core DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.di")
-install(FILES ${GCCBUILTINS} DESTINATION ${INCLUDE_INSTALL_DIR}/ldc)
+install(FILES ${GCCBUILTINS} DESTINATION ${INCLUDE_INSTALL_DIR}/ldc)
foreach(libname ${LIBS_TO_INSTALL})
if(APPLE)
@@ -606,6 +591,11 @@ function(add_tests module_files)
if(${LDC_LLVM_VER} EQUAL 301 AND ${HOST_BITNESS} EQUAL 64 AND
"${testroot}" STREQUAL "phobos_std_exception")
testcase(release "-O1;-release")
+ # Building the std.range tests triggers an assertion error on
+ # every LLVM release before 3.3. See PR15608.
+ elseif(${LDC_LLVM_VER} LESS 303 AND
+ "${testroot}" STREQUAL "phobos_std_range")
+ testcase(release "-O1;-release")
else()
testcase(release "-O3;-release")
endif()
diff --git a/runtime/druntime b/runtime/druntime
index ca580226..34f9dcf7 160000
--- a/runtime/druntime
+++ b/runtime/druntime
@@ -1 +1 @@
-Subproject commit ca580226270573de2057295fdd3ef76dbc0adeb2
+Subproject commit 34f9dcf7aed758a3cce48cb77e4e77d7d877d676
diff --git a/runtime/phobos b/runtime/phobos
index ae03a521..c9efed91 160000
--- a/runtime/phobos
+++ b/runtime/phobos
@@ -1 +1 @@
-Subproject commit ae03a52195c98d56ee0b78f2a7928f20dbed4b33
+Subproject commit c9efed917c232ac7c79526abec5efab622064c93
diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite
index a7e9ed61..ea353f99 160000
--- a/tests/d2/dmd-testsuite
+++ b/tests/d2/dmd-testsuite
@@ -1 +1 @@
-Subproject commit a7e9ed61ed90e55f6235722c4b3338bcb1d332c7
+Subproject commit ea353f99b3e9bd3f003be2c165e1d2880cf6d39d