mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
Merged the last bits of dmdfe 2.059
This commit is contained in:
@@ -56,7 +56,7 @@ Dsymbols *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd)
|
|||||||
|
|
||||||
int AttribDeclaration::apply(Dsymbol_apply_ft_t fp, void *param)
|
int AttribDeclaration::apply(Dsymbol_apply_ft_t fp, void *param)
|
||||||
{
|
{
|
||||||
Dsymbols *d = include(NULL, NULL);
|
Dsymbols *d = include(scope, NULL);
|
||||||
|
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
@@ -1278,9 +1278,9 @@ void ConditionalDeclaration::emitComment(Scope *sc)
|
|||||||
|
|
||||||
Dsymbols *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd)
|
Dsymbols *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd)
|
||||||
{
|
{
|
||||||
//printf("ConditionalDeclaration::include()\n");
|
//printf("ConditionalDeclaration::include(sc = %p) scope = %p\n", sc, scope);
|
||||||
assert(condition);
|
assert(condition);
|
||||||
return condition->include(sc, sd) ? decl : elsedecl;
|
return condition->include(scope ? scope : sc, sd) ? decl : elsedecl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConditionalDeclaration::setScope(Scope *sc)
|
void ConditionalDeclaration::setScope(Scope *sc)
|
||||||
@@ -1440,6 +1440,9 @@ void StaticIfDeclaration::importAll(Scope *sc)
|
|||||||
void StaticIfDeclaration::setScope(Scope *sc)
|
void StaticIfDeclaration::setScope(Scope *sc)
|
||||||
{
|
{
|
||||||
// do not evaluate condition before semantic pass
|
// do not evaluate condition before semantic pass
|
||||||
|
|
||||||
|
// But do set the scope, in case we need it for forward referencing
|
||||||
|
Dsymbol::setScope(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StaticIfDeclaration::semantic(Scope *sc)
|
void StaticIfDeclaration::semantic(Scope *sc)
|
||||||
@@ -1471,6 +1474,8 @@ const char *StaticIfDeclaration::kind()
|
|||||||
|
|
||||||
/***************************** CompileDeclaration *****************************/
|
/***************************** CompileDeclaration *****************************/
|
||||||
|
|
||||||
|
// These are mixin declarations, like mixin("int x");
|
||||||
|
|
||||||
CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp)
|
CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp)
|
||||||
: AttribDeclaration(NULL)
|
: AttribDeclaration(NULL)
|
||||||
{
|
{
|
||||||
@@ -1544,3 +1549,10 @@ void CompileDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
buf->writestring(");");
|
buf->writestring(");");
|
||||||
buf->writenl();
|
buf->writenl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *CompileDeclaration::kind()
|
||||||
|
{
|
||||||
|
return "mixin";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -200,6 +200,7 @@ struct CompileDeclaration : AttribDeclaration
|
|||||||
void compileIt(Scope *sc);
|
void compileIt(Scope *sc);
|
||||||
void semantic(Scope *sc);
|
void semantic(Scope *sc);
|
||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
|
const char *kind();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DMD_ATTRIB_H */
|
#endif /* DMD_ATTRIB_H */
|
||||||
|
|||||||
29
dmd2/cond.c
29
dmd2/cond.c
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
#include "mtype.h"
|
#include "mtype.h"
|
||||||
#include "scope.h"
|
#include "scope.h"
|
||||||
|
#include "arraytypes.h"
|
||||||
|
|
||||||
int findCondition(Strings *ids, Identifier *ident)
|
int findCondition(Strings *ids, Identifier *ident)
|
||||||
{
|
{
|
||||||
@@ -29,7 +30,7 @@ int findCondition(Strings *ids, Identifier *ident)
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < ids->dim; i++)
|
for (size_t i = 0; i < ids->dim; i++)
|
||||||
{
|
{
|
||||||
const char *id = ids->tdata()[i];
|
const char *id = (*ids)[i];
|
||||||
|
|
||||||
if (strcmp(id, ident->toChars()) == 0)
|
if (strcmp(id, ident->toChars()) == 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -224,6 +225,7 @@ StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
|
|||||||
: Condition(loc)
|
: Condition(loc)
|
||||||
{
|
{
|
||||||
this->exp = exp;
|
this->exp = exp;
|
||||||
|
this->nest = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Condition *StaticIfCondition::syntaxCopy()
|
Condition *StaticIfCondition::syntaxCopy()
|
||||||
@@ -234,7 +236,7 @@ Condition *StaticIfCondition::syntaxCopy()
|
|||||||
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s);
|
printf("StaticIfCondition::include(sc = %p, s = %p) this=%p inc = %d\n", sc, s, this, inc);
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
|
printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
|
||||||
@@ -242,6 +244,15 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
|||||||
#endif
|
#endif
|
||||||
if (inc == 0)
|
if (inc == 0)
|
||||||
{
|
{
|
||||||
|
if (exp->op == TOKerror || nest > 100)
|
||||||
|
{
|
||||||
|
error(loc, (nest > 1000) ? "unresolvable circular static if expression"
|
||||||
|
: "error evaluating static if expression");
|
||||||
|
if (!global.gag)
|
||||||
|
inc = 2; // so we don't see the error message again
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!sc)
|
if (!sc)
|
||||||
{
|
{
|
||||||
error(loc, "static if conditional cannot be at global scope");
|
error(loc, "static if conditional cannot be at global scope");
|
||||||
@@ -249,13 +260,19 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++nest;
|
||||||
sc = sc->push(sc->scopesym);
|
sc = sc->push(sc->scopesym);
|
||||||
sc->sd = s; // s gets any addMember()
|
sc->sd = s; // s gets any addMember()
|
||||||
sc->flags |= SCOPEstaticif;
|
sc->flags |= SCOPEstaticif;
|
||||||
Expression *e = exp->semantic(sc);
|
Expression *e = exp->semantic(sc);
|
||||||
sc->pop();
|
sc->pop();
|
||||||
e = e->optimize(WANTvalue | WANTinterpret);
|
e = e->optimize(WANTvalue | WANTinterpret);
|
||||||
if (e->isBool(TRUE))
|
--nest;
|
||||||
|
if (e->op == TOKerror)
|
||||||
|
{ exp = e;
|
||||||
|
inc = 0;
|
||||||
|
}
|
||||||
|
else if (e->isBool(TRUE))
|
||||||
inc = 1;
|
inc = 1;
|
||||||
else if (e->isBool(FALSE))
|
else if (e->isBool(FALSE))
|
||||||
inc = 2;
|
inc = 2;
|
||||||
@@ -327,7 +344,7 @@ int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd)
|
|||||||
|
|
||||||
TemplateParameters parameters;
|
TemplateParameters parameters;
|
||||||
parameters.setDim(1);
|
parameters.setDim(1);
|
||||||
parameters.tdata()[0] = &tp;
|
parameters[0] = &tp;
|
||||||
|
|
||||||
Objects dedtypes;
|
Objects dedtypes;
|
||||||
dedtypes.setDim(1);
|
dedtypes.setDim(1);
|
||||||
@@ -339,7 +356,7 @@ int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
inc = 1;
|
inc = 1;
|
||||||
Type *tded = (Type *)dedtypes.tdata()[0];
|
Type *tded = (Type *)dedtypes[0];
|
||||||
if (!tded)
|
if (!tded)
|
||||||
tded = targ;
|
tded = targ;
|
||||||
Dsymbol *s = new AliasDeclaration(loc, id, tded);
|
Dsymbol *s = new AliasDeclaration(loc, id, tded);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -79,6 +79,7 @@ struct VersionCondition : DVCondition
|
|||||||
struct StaticIfCondition : Condition
|
struct StaticIfCondition : Condition
|
||||||
{
|
{
|
||||||
Expression *exp;
|
Expression *exp;
|
||||||
|
int nest; // limit circular dependencies
|
||||||
|
|
||||||
StaticIfCondition(Loc loc, Expression *exp);
|
StaticIfCondition(Loc loc, Expression *exp);
|
||||||
Condition *syntaxCopy();
|
Condition *syntaxCopy();
|
||||||
|
|||||||
@@ -796,6 +796,7 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
if (!type)
|
if (!type)
|
||||||
{ inuse++;
|
{ inuse++;
|
||||||
|
|
||||||
|
//printf("inferring type for %s with init %s\n", toChars(), init->toChars());
|
||||||
ArrayInitializer *ai = init->isArrayInitializer();
|
ArrayInitializer *ai = init->isArrayInitializer();
|
||||||
if (ai)
|
if (ai)
|
||||||
{ Expression *e;
|
{ Expression *e;
|
||||||
@@ -816,7 +817,6 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
else
|
else
|
||||||
type = init->inferType(sc);
|
type = init->inferType(sc);
|
||||||
|
|
||||||
//printf("test2: %s, %s, %s\n", toChars(), type->toChars(), type->deco);
|
|
||||||
// type = type->semantic(loc, sc);
|
// type = type->semantic(loc, sc);
|
||||||
|
|
||||||
inuse--;
|
inuse--;
|
||||||
@@ -883,7 +883,14 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
|
|
||||||
Type *tb = type->toBasetype();
|
Type *tb = type->toBasetype();
|
||||||
if (tb->ty == Tvoid && !(storage_class & STClazy))
|
if (tb->ty == Tvoid && !(storage_class & STClazy))
|
||||||
{ error("voids have no value");
|
{
|
||||||
|
if (inferred)
|
||||||
|
{
|
||||||
|
error("type %s is inferred from initializer %s, and variables cannot be of type void",
|
||||||
|
type->toChars(), init->toChars());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error("variables cannot be of type void");
|
||||||
type = Type::terror;
|
type = Type::terror;
|
||||||
tb = type;
|
tb = type;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -338,7 +338,15 @@ void checkPropertyCall(Expression *e, Expression *emsg)
|
|||||||
{ CallExp *ce = (CallExp *)e;
|
{ CallExp *ce = (CallExp *)e;
|
||||||
TypeFunction *tf;
|
TypeFunction *tf;
|
||||||
if (ce->f)
|
if (ce->f)
|
||||||
|
{
|
||||||
tf = (TypeFunction *)ce->f->type;
|
tf = (TypeFunction *)ce->f->type;
|
||||||
|
/* If a forward reference to ce->f, try to resolve it
|
||||||
|
*/
|
||||||
|
if (!tf->deco && ce->f->scope)
|
||||||
|
{ ce->f->semantic(ce->f->scope);
|
||||||
|
tf = (TypeFunction *)ce->f->type;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (ce->e1->type->ty == Tfunction)
|
else if (ce->e1->type->ty == Tfunction)
|
||||||
tf = (TypeFunction *)ce->e1->type;
|
tf = (TypeFunction *)ce->e1->type;
|
||||||
else if (ce->e1->type->ty == Tdelegate)
|
else if (ce->e1->type->ty == Tdelegate)
|
||||||
@@ -390,46 +398,54 @@ Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NU
|
|||||||
else
|
else
|
||||||
e = new DotIdExp(loc, e, ident);
|
e = new DotIdExp(loc, e, ident);
|
||||||
|
|
||||||
Expressions *arguments = new Expressions();
|
|
||||||
/* .f(e1, e2)
|
|
||||||
*/
|
|
||||||
if (e2)
|
if (e2)
|
||||||
{
|
{
|
||||||
arguments->setDim(2);
|
/* .f(e1) = e2
|
||||||
(*arguments)[0] = eleft;
|
*/
|
||||||
(*arguments)[1] = e2;
|
|
||||||
|
|
||||||
Expression *ex = e->syntaxCopy();
|
Expression *ex = e->syntaxCopy();
|
||||||
e = new CallExp(loc, e, arguments);
|
Expressions *a1 = new Expressions();
|
||||||
e = e->trySemantic(sc);
|
a1->setDim(1);
|
||||||
if (e)
|
(*a1)[0] = eleft;
|
||||||
{ checkPropertyCall(e, e1);
|
ex = new CallExp(loc, ex, a1);
|
||||||
return e->semantic(sc);
|
ex = ex->trySemantic(sc);
|
||||||
}
|
|
||||||
e = ex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* .f(e1)
|
/* .f(e1, e2)
|
||||||
* .f(e1) = e2
|
*/
|
||||||
*/
|
Expressions *a2 = new Expressions();
|
||||||
|
a2->setDim(2);
|
||||||
|
(*a2)[0] = eleft;
|
||||||
|
(*a2)[1] = e2;
|
||||||
|
e = new CallExp(loc, e, a2);
|
||||||
|
if (ex)
|
||||||
|
{ // if fallback setter exists, gag errors
|
||||||
|
e = e->trySemantic(sc);
|
||||||
|
if (!e)
|
||||||
|
{ checkPropertyCall(ex, e1);
|
||||||
|
ex = new AssignExp(loc, ex, e2);
|
||||||
|
return ex->semantic(sc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // strict setter prints errors if fails
|
||||||
|
e = e->semantic(sc);
|
||||||
|
}
|
||||||
|
checkPropertyCall(e, e1);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
|
/* .f(e1)
|
||||||
|
*/
|
||||||
|
Expressions *arguments = new Expressions();
|
||||||
arguments->setDim(1);
|
arguments->setDim(1);
|
||||||
(*arguments)[0] = eleft;
|
(*arguments)[0] = eleft;
|
||||||
e = new CallExp(loc, e, arguments);
|
e = new CallExp(loc, e, arguments);
|
||||||
e = e->trySemantic(sc);
|
e = e->semantic(sc);
|
||||||
if (!e)
|
|
||||||
goto Leprop;
|
|
||||||
checkPropertyCall(e, e1);
|
checkPropertyCall(e, e1);
|
||||||
if (e2)
|
|
||||||
e = new AssignExp(loc, e, e2);
|
|
||||||
return e->semantic(sc);
|
return e->semantic(sc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return e;
|
return e;
|
||||||
|
|
||||||
Leprop:
|
|
||||||
e1->error("not a property %s", e1->toChars());
|
|
||||||
return new ErrorExp();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************
|
/******************************
|
||||||
@@ -1045,7 +1061,37 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
|
|||||||
}
|
}
|
||||||
if (p->storageClass & STCref)
|
if (p->storageClass & STCref)
|
||||||
{
|
{
|
||||||
arg = arg->toLvalue(sc, arg);
|
if (arg->op == TOKstructliteral)
|
||||||
|
{
|
||||||
|
Identifier *idtmp = Lexer::uniqueId("__tmpsl");
|
||||||
|
VarDeclaration *tmp = new VarDeclaration(loc, arg->type, idtmp, new ExpInitializer(0, arg));
|
||||||
|
tmp->storage_class |= STCctfe;
|
||||||
|
Expression *ae = new DeclarationExp(loc, tmp);
|
||||||
|
Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp));
|
||||||
|
e = e->semantic(sc);
|
||||||
|
|
||||||
|
arg = e;
|
||||||
|
}
|
||||||
|
else if (arg->op == TOKcall)
|
||||||
|
{
|
||||||
|
CallExp *ce = (CallExp *)arg;
|
||||||
|
if (ce->e1->op == TOKdotvar &&
|
||||||
|
((DotVarExp *)ce->e1)->var->isCtorDeclaration())
|
||||||
|
{
|
||||||
|
DotVarExp *dve = (DotVarExp *)ce->e1;
|
||||||
|
assert(dve->e1->op == TOKcomma);
|
||||||
|
assert(((CommaExp *)dve->e1)->e2->op == TOKvar);
|
||||||
|
VarExp *ve = (VarExp *)((CommaExp *)dve->e1)->e2;
|
||||||
|
VarDeclaration *tmp = ve->var->isVarDeclaration();
|
||||||
|
|
||||||
|
arg = new CommaExp(arg->loc, arg, new VarExp(loc, tmp));
|
||||||
|
arg = arg->semantic(sc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
arg = arg->toLvalue(sc, arg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
arg = arg->toLvalue(sc, arg);
|
||||||
}
|
}
|
||||||
else if (p->storageClass & STCout)
|
else if (p->storageClass & STCout)
|
||||||
{
|
{
|
||||||
@@ -6753,9 +6799,29 @@ Expression *DotIdExp::semantic(Scope *sc, int flag)
|
|||||||
{ goto L2;
|
{ goto L2;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned errors = global.startGagging();
|
/* This would be much better if we added a "hasProperty" method to types,
|
||||||
|
* i.e. the gagging is a bad way.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (t1b->ty == Taarray)
|
||||||
|
{
|
||||||
|
TypeAArray *taa = (TypeAArray *)t1b;
|
||||||
|
if (!taa->impl &&
|
||||||
|
ident != Id::__sizeof &&
|
||||||
|
ident != Id::__xalignof &&
|
||||||
|
ident != Id::init &&
|
||||||
|
ident != Id::mangleof &&
|
||||||
|
ident != Id::stringof &&
|
||||||
|
ident != Id::offsetof)
|
||||||
|
{
|
||||||
|
// Find out about these errors when not gagged
|
||||||
|
taa->getImpl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Type *t1 = e1->type;
|
Type *t1 = e1->type;
|
||||||
e = e1->type->dotExp(sc, e1, ident);
|
unsigned errors = global.startGagging();
|
||||||
|
e = t1->dotExp(sc, e1, ident);
|
||||||
if (global.endGagging(errors)) // if failed to find the property
|
if (global.endGagging(errors)) // if failed to find the property
|
||||||
{
|
{
|
||||||
e1->type = t1; // kludge to restore type
|
e1->type = t1; // kludge to restore type
|
||||||
@@ -8841,6 +8907,8 @@ Expression *CastExp::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
to = to->semantic(loc, sc);
|
to = to->semantic(loc, sc);
|
||||||
|
if (to == Type::terror)
|
||||||
|
return new ErrorExp();
|
||||||
|
|
||||||
if (!to->equals(e1->type))
|
if (!to->equals(e1->type))
|
||||||
{
|
{
|
||||||
@@ -9091,7 +9159,9 @@ Expression *SliceExp::syntaxCopy()
|
|||||||
if (this->upr)
|
if (this->upr)
|
||||||
upr = this->upr->syntaxCopy();
|
upr = this->upr->syntaxCopy();
|
||||||
|
|
||||||
return new SliceExp(loc, e1->syntaxCopy(), lwr, upr);
|
SliceExp *se = new SliceExp(loc, e1->syntaxCopy(), lwr, upr);
|
||||||
|
se->lengthVar = this->lengthVar; // bug7871
|
||||||
|
return se;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression *SliceExp::semantic(Scope *sc)
|
Expression *SliceExp::semantic(Scope *sc)
|
||||||
@@ -9436,7 +9506,9 @@ ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args)
|
|||||||
|
|
||||||
Expression *ArrayExp::syntaxCopy()
|
Expression *ArrayExp::syntaxCopy()
|
||||||
{
|
{
|
||||||
return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
|
ArrayExp *ae = new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
|
||||||
|
ae->lengthVar = this->lengthVar; // bug7871
|
||||||
|
return ae;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression *ArrayExp::semantic(Scope *sc)
|
Expression *ArrayExp::semantic(Scope *sc)
|
||||||
@@ -9603,6 +9675,13 @@ IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2)
|
|||||||
modifiable = 0; // assume it is an rvalue
|
modifiable = 0; // assume it is an rvalue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expression *IndexExp::syntaxCopy()
|
||||||
|
{
|
||||||
|
IndexExp *ie = new IndexExp(loc, e1->syntaxCopy(), e2->syntaxCopy());
|
||||||
|
ie->lengthVar = this->lengthVar; // bug7871
|
||||||
|
return ie;
|
||||||
|
}
|
||||||
|
|
||||||
Expression *IndexExp::semantic(Scope *sc)
|
Expression *IndexExp::semantic(Scope *sc)
|
||||||
{ Expression *e;
|
{ Expression *e;
|
||||||
Type *t1;
|
Type *t1;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -1463,6 +1463,7 @@ struct IndexExp : BinExp
|
|||||||
int modifiable;
|
int modifiable;
|
||||||
|
|
||||||
IndexExp(Loc loc, Expression *e1, Expression *e2);
|
IndexExp(Loc loc, Expression *e1, Expression *e2);
|
||||||
|
Expression *syntaxCopy();
|
||||||
Expression *semantic(Scope *sc);
|
Expression *semantic(Scope *sc);
|
||||||
int isLvalue();
|
int isLvalue();
|
||||||
Expression *toLvalue(Scope *sc, Expression *e);
|
Expression *toLvalue(Scope *sc, Expression *e);
|
||||||
|
|||||||
55
dmd2/func.c
55
dmd2/func.c
@@ -190,6 +190,11 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
semanticRun = PASSsemantic;
|
semanticRun = PASSsemantic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (scope)
|
||||||
|
{ sc = scope;
|
||||||
|
scope = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned dprogress_save = Module::dprogress;
|
unsigned dprogress_save = Module::dprogress;
|
||||||
|
|
||||||
foverrides.setDim(0); // reset in case semantic() is being retried for this function
|
foverrides.setDim(0); // reset in case semantic() is being retried for this function
|
||||||
@@ -2895,6 +2900,9 @@ int FuncDeclaration::isImportedSymbol()
|
|||||||
|
|
||||||
int FuncDeclaration::isVirtual()
|
int FuncDeclaration::isVirtual()
|
||||||
{
|
{
|
||||||
|
if (toAliasFunc() != this)
|
||||||
|
return toAliasFunc()->isVirtual();
|
||||||
|
|
||||||
Dsymbol *p = toParent();
|
Dsymbol *p = toParent();
|
||||||
#if 0
|
#if 0
|
||||||
printf("FuncDeclaration::isVirtual(%s)\n", toChars());
|
printf("FuncDeclaration::isVirtual(%s)\n", toChars());
|
||||||
@@ -2915,6 +2923,9 @@ int FuncDeclaration::isVirtual()
|
|||||||
|
|
||||||
int FuncDeclaration::isVirtualMethod()
|
int FuncDeclaration::isVirtualMethod()
|
||||||
{
|
{
|
||||||
|
if (toAliasFunc() != this)
|
||||||
|
return toAliasFunc()->isVirtualMethod();
|
||||||
|
|
||||||
//printf("FuncDeclaration::isVirtualMethod() %s\n", toChars());
|
//printf("FuncDeclaration::isVirtualMethod() %s\n", toChars());
|
||||||
if (!isVirtual())
|
if (!isVirtual())
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2928,6 +2939,9 @@ int FuncDeclaration::isVirtualMethod()
|
|||||||
|
|
||||||
int FuncDeclaration::isFinal()
|
int FuncDeclaration::isFinal()
|
||||||
{
|
{
|
||||||
|
if (toAliasFunc() != this)
|
||||||
|
return toAliasFunc()->isFinal();
|
||||||
|
|
||||||
ClassDeclaration *cd;
|
ClassDeclaration *cd;
|
||||||
#if 0
|
#if 0
|
||||||
printf("FuncDeclaration::isFinal(%s), %x\n", toChars(), Declaration::isFinal());
|
printf("FuncDeclaration::isFinal(%s), %x\n", toChars(), Declaration::isFinal());
|
||||||
@@ -3444,6 +3458,11 @@ void CtorDeclaration::semantic(Scope *sc)
|
|||||||
TypeFunction *tf = (TypeFunction *)type;
|
TypeFunction *tf = (TypeFunction *)type;
|
||||||
assert(tf && tf->ty == Tfunction);
|
assert(tf && tf->ty == Tfunction);
|
||||||
|
|
||||||
|
if (scope)
|
||||||
|
{ sc = scope;
|
||||||
|
scope = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
sc = sc->push();
|
sc = sc->push();
|
||||||
sc->stc &= ~STCstatic; // not a static constructor
|
sc->stc &= ~STCstatic; // not a static constructor
|
||||||
sc->flags |= SCOPEctor;
|
sc->flags |= SCOPEctor;
|
||||||
@@ -3563,6 +3582,10 @@ void PostBlitDeclaration::semantic(Scope *sc)
|
|||||||
//printf("PostBlitDeclaration::semantic() %s\n", toChars());
|
//printf("PostBlitDeclaration::semantic() %s\n", toChars());
|
||||||
//printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
|
//printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
|
||||||
//printf("stc = x%llx\n", sc->stc);
|
//printf("stc = x%llx\n", sc->stc);
|
||||||
|
if (scope)
|
||||||
|
{ sc = scope;
|
||||||
|
scope = NULL;
|
||||||
|
}
|
||||||
parent = sc->parent;
|
parent = sc->parent;
|
||||||
Dsymbol *parent = toParent();
|
Dsymbol *parent = toParent();
|
||||||
StructDeclaration *ad = parent->isStructDeclaration();
|
StructDeclaration *ad = parent->isStructDeclaration();
|
||||||
@@ -3636,6 +3659,10 @@ void DtorDeclaration::semantic(Scope *sc)
|
|||||||
{
|
{
|
||||||
//printf("DtorDeclaration::semantic() %s\n", toChars());
|
//printf("DtorDeclaration::semantic() %s\n", toChars());
|
||||||
//printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
|
//printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
|
||||||
|
if (scope)
|
||||||
|
{ sc = scope;
|
||||||
|
scope = NULL;
|
||||||
|
}
|
||||||
parent = sc->parent;
|
parent = sc->parent;
|
||||||
Dsymbol *parent = toParent();
|
Dsymbol *parent = toParent();
|
||||||
AggregateDeclaration *ad = parent->isAggregateDeclaration();
|
AggregateDeclaration *ad = parent->isAggregateDeclaration();
|
||||||
@@ -3728,6 +3755,11 @@ void StaticCtorDeclaration::semantic(Scope *sc)
|
|||||||
{
|
{
|
||||||
//printf("StaticCtorDeclaration::semantic()\n");
|
//printf("StaticCtorDeclaration::semantic()\n");
|
||||||
|
|
||||||
|
if (scope)
|
||||||
|
{ sc = scope;
|
||||||
|
scope = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!type)
|
if (!type)
|
||||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
||||||
|
|
||||||
@@ -3856,6 +3888,11 @@ Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
|
|||||||
|
|
||||||
void StaticDtorDeclaration::semantic(Scope *sc)
|
void StaticDtorDeclaration::semantic(Scope *sc)
|
||||||
{
|
{
|
||||||
|
if (scope)
|
||||||
|
{ sc = scope;
|
||||||
|
scope = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ClassDeclaration *cd = sc->scopesym->isClassDeclaration();
|
ClassDeclaration *cd = sc->scopesym->isClassDeclaration();
|
||||||
|
|
||||||
if (!type)
|
if (!type)
|
||||||
@@ -3983,6 +4020,10 @@ Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
|
|||||||
|
|
||||||
void InvariantDeclaration::semantic(Scope *sc)
|
void InvariantDeclaration::semantic(Scope *sc)
|
||||||
{
|
{
|
||||||
|
if (scope)
|
||||||
|
{ sc = scope;
|
||||||
|
scope = NULL;
|
||||||
|
}
|
||||||
parent = sc->parent;
|
parent = sc->parent;
|
||||||
Dsymbol *parent = toParent();
|
Dsymbol *parent = toParent();
|
||||||
AggregateDeclaration *ad = parent->isAggregateDeclaration();
|
AggregateDeclaration *ad = parent->isAggregateDeclaration();
|
||||||
@@ -4063,6 +4104,10 @@ Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
|
|||||||
|
|
||||||
void UnitTestDeclaration::semantic(Scope *sc)
|
void UnitTestDeclaration::semantic(Scope *sc)
|
||||||
{
|
{
|
||||||
|
if (scope)
|
||||||
|
{ sc = scope;
|
||||||
|
scope = NULL;
|
||||||
|
}
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
if (global.params.useUnitTests && sc->module->isRoot)
|
if (global.params.useUnitTests && sc->module->isRoot)
|
||||||
#else
|
#else
|
||||||
@@ -4150,6 +4195,11 @@ void NewDeclaration::semantic(Scope *sc)
|
|||||||
{
|
{
|
||||||
//printf("NewDeclaration::semantic()\n");
|
//printf("NewDeclaration::semantic()\n");
|
||||||
|
|
||||||
|
if (scope)
|
||||||
|
{ sc = scope;
|
||||||
|
scope = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
parent = sc->parent;
|
parent = sc->parent;
|
||||||
Dsymbol *parent = toParent();
|
Dsymbol *parent = toParent();
|
||||||
ClassDeclaration *cd = parent->isClassDeclaration();
|
ClassDeclaration *cd = parent->isClassDeclaration();
|
||||||
@@ -4234,6 +4284,11 @@ void DeleteDeclaration::semantic(Scope *sc)
|
|||||||
{
|
{
|
||||||
//printf("DeleteDeclaration::semantic()\n");
|
//printf("DeleteDeclaration::semantic()\n");
|
||||||
|
|
||||||
|
if (scope)
|
||||||
|
{ sc = scope;
|
||||||
|
scope = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
parent = sc->parent;
|
parent = sc->parent;
|
||||||
Dsymbol *parent = toParent();
|
Dsymbol *parent = toParent();
|
||||||
ClassDeclaration *cd = parent->isClassDeclaration();
|
ClassDeclaration *cd = parent->isClassDeclaration();
|
||||||
|
|||||||
28
dmd2/init.c
28
dmd2/init.c
@@ -21,6 +21,7 @@
|
|||||||
#include "scope.h"
|
#include "scope.h"
|
||||||
#include "mtype.h"
|
#include "mtype.h"
|
||||||
#include "hdrgen.h"
|
#include "hdrgen.h"
|
||||||
|
#include "template.h"
|
||||||
|
|
||||||
/********************************** Initializer *******************************/
|
/********************************** Initializer *******************************/
|
||||||
|
|
||||||
@@ -160,8 +161,18 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
|||||||
if (ad->ctor)
|
if (ad->ctor)
|
||||||
error(loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead",
|
error(loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead",
|
||||||
ad->kind(), ad->toChars(), ad->toChars());
|
ad->kind(), ad->toChars(), ad->toChars());
|
||||||
size_t nfields = ad->fields.dim;
|
StructDeclaration *sd = ad->isStructDeclaration();
|
||||||
if (((StructDeclaration *)ad)->isnested) nfields--;
|
assert(sd);
|
||||||
|
sd->size(loc);
|
||||||
|
if (sd->sizeok != SIZEOKdone)
|
||||||
|
{
|
||||||
|
error(loc, "struct %s is forward referenced", sd->toChars());
|
||||||
|
errors = 1;
|
||||||
|
goto Lerror;
|
||||||
|
}
|
||||||
|
size_t nfields = sd->fields.dim;
|
||||||
|
if (sd->isnested)
|
||||||
|
nfields--;
|
||||||
for (size_t i = 0; i < field.dim; i++)
|
for (size_t i = 0; i < field.dim; i++)
|
||||||
{
|
{
|
||||||
Identifier *id = field[i];
|
Identifier *id = field[i];
|
||||||
@@ -244,6 +255,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
|||||||
error(loc, "a struct is not a valid initializer for a %s", t->toChars());
|
error(loc, "a struct is not a valid initializer for a %s", t->toChars());
|
||||||
errors = 1;
|
errors = 1;
|
||||||
}
|
}
|
||||||
|
Lerror:
|
||||||
if (errors)
|
if (errors)
|
||||||
{
|
{
|
||||||
field.setDim(0);
|
field.setDim(0);
|
||||||
@@ -264,12 +276,11 @@ Expression *StructInitializer::toExpression()
|
|||||||
|
|
||||||
//printf("StructInitializer::toExpression() %s\n", toChars());
|
//printf("StructInitializer::toExpression() %s\n", toChars());
|
||||||
if (!ad) // if fwd referenced
|
if (!ad) // if fwd referenced
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
StructDeclaration *sd = ad->isStructDeclaration();
|
StructDeclaration *sd = ad->isStructDeclaration();
|
||||||
if (!sd)
|
if (!sd)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Expressions *elements = new Expressions();
|
Expressions *elements = new Expressions();
|
||||||
size_t nfields = ad->fields.dim;
|
size_t nfields = ad->fields.dim;
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
@@ -870,6 +881,15 @@ Type *ExpInitializer::inferType(Scope *sc)
|
|||||||
//printf("ExpInitializer::inferType() %s\n", toChars());
|
//printf("ExpInitializer::inferType() %s\n", toChars());
|
||||||
exp = exp->semantic(sc);
|
exp = exp->semantic(sc);
|
||||||
exp = resolveProperties(sc, exp);
|
exp = resolveProperties(sc, exp);
|
||||||
|
if (exp->op == TOKimport)
|
||||||
|
{ ScopeExp *se = (ScopeExp *)exp;
|
||||||
|
TemplateInstance *ti = se->sds->isTemplateInstance();
|
||||||
|
if (ti && ti->semanticRun == PASSsemantic && !ti->aliasdecl)
|
||||||
|
se->error("cannot infer type from %s %s, possible circular dependency", se->sds->kind(), se->toChars());
|
||||||
|
else
|
||||||
|
se->error("cannot infer type from %s %s", se->sds->kind(), se->toChars());
|
||||||
|
return Type::terror;
|
||||||
|
}
|
||||||
|
|
||||||
// Give error for overloaded function addresses
|
// Give error for overloaded function addresses
|
||||||
if (exp->op == TOKsymoff)
|
if (exp->op == TOKsymoff)
|
||||||
|
|||||||
@@ -6786,7 +6786,8 @@ Expression *TypeStruct::voidInitLiteral(VarDeclaration *var)
|
|||||||
exps->setDim(sym->fields.dim);
|
exps->setDim(sym->fields.dim);
|
||||||
for (size_t i = 0; i < sym->fields.dim; i++)
|
for (size_t i = 0; i < sym->fields.dim; i++)
|
||||||
{
|
{
|
||||||
(*exps)[i] = new VoidInitExp(var, sym->fields[i]->type);
|
//(*exps)[i] = new VoidInitExp(var, sym->fields[i]->type);
|
||||||
|
(*exps)[i] = sym->fields[i]->type->voidInitLiteral(var);
|
||||||
}
|
}
|
||||||
StructLiteralExp *se = new StructLiteralExp(var->loc, sym, exps);
|
StructLiteralExp *se = new StructLiteralExp(var->loc, sym, exps);
|
||||||
se->type = this;
|
se->type = this;
|
||||||
|
|||||||
@@ -1000,6 +1000,8 @@ void Module::semantic2(Scope* unused_sc)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent);
|
//printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent);
|
||||||
|
if (semanticRun == 0) // semantic() not completed yet - could be recursive call
|
||||||
|
return;
|
||||||
if (semanticstarted >= 2)
|
if (semanticstarted >= 2)
|
||||||
return;
|
return;
|
||||||
assert(semanticstarted == 1);
|
assert(semanticstarted == 1);
|
||||||
|
|||||||
23
dmd2/mtype.c
23
dmd2/mtype.c
@@ -6066,6 +6066,19 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag)
|
|||||||
new IntegerExp(0, ((StringExp *)arg)->len,
|
new IntegerExp(0, ((StringExp *)arg)->len,
|
||||||
Type::tindex));
|
Type::tindex));
|
||||||
}
|
}
|
||||||
|
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
|
else
|
||||||
goto Nomatch;
|
goto Nomatch;
|
||||||
}
|
}
|
||||||
@@ -7933,7 +7946,15 @@ Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident)
|
|||||||
L1:
|
L1:
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
return noMember(sc, e, ident);
|
if (sym->scope) // it's a fwd ref, maybe we can resolve it
|
||||||
|
{
|
||||||
|
sym->semantic(NULL);
|
||||||
|
s = sym->search(e->loc, ident, 0);
|
||||||
|
if (!s)
|
||||||
|
return noMember(sc, e, ident);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return noMember(sc, e, ident);
|
||||||
}
|
}
|
||||||
if (!s->isFuncDeclaration()) // because of overloading
|
if (!s->isFuncDeclaration()) // because of overloading
|
||||||
s->checkDeprecated(e->loc, sc);
|
s->checkDeprecated(e->loc, sc);
|
||||||
|
|||||||
@@ -465,7 +465,7 @@ void StructDeclaration::semantic(Scope *sc)
|
|||||||
*/
|
*/
|
||||||
//if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident))
|
//if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident))
|
||||||
{
|
{
|
||||||
//printf("setScope %s %s\n", s->kind(), s->toChars());
|
//printf("struct: setScope %s %s\n", s->kind(), s->toChars());
|
||||||
s->setScope(sc2);
|
s->setScope(sc2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -487,7 +487,9 @@ void StructDeclaration::semantic(Scope *sc)
|
|||||||
// Ungag errors when not speculative
|
// Ungag errors when not speculative
|
||||||
unsigned oldgag = global.gag;
|
unsigned oldgag = global.gag;
|
||||||
if (global.isSpeculativeGagging() && !isSpeculative())
|
if (global.isSpeculativeGagging() && !isSpeculative())
|
||||||
|
{
|
||||||
global.gag = 0;
|
global.gag = 0;
|
||||||
|
}
|
||||||
s->semantic(sc2);
|
s->semantic(sc2);
|
||||||
global.gag = oldgag;
|
global.gag = oldgag;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1510,7 +1510,23 @@ Lretry:
|
|||||||
|
|
||||||
if (m && (fparam->storageClass & (STCref | STCauto)) == STCref)
|
if (m && (fparam->storageClass & (STCref | STCauto)) == STCref)
|
||||||
{ if (!farg->isLvalue())
|
{ if (!farg->isLvalue())
|
||||||
goto Lnomatch;
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (m && (fparam->storageClass & STCout))
|
if (m && (fparam->storageClass & STCout))
|
||||||
{ if (!farg->isLvalue())
|
{ if (!farg->isLvalue())
|
||||||
@@ -2326,7 +2342,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
|||||||
*wildmatch |= MODmutable;
|
*wildmatch |= MODmutable;
|
||||||
else
|
else
|
||||||
*wildmatch |= (mod & ~MODshared);
|
*wildmatch |= (mod & ~MODshared);
|
||||||
tt = mutableOf();
|
tt = mutableOf()->substWildTo(MODmutable);
|
||||||
dedtypes->tdata()[i] = tt;
|
dedtypes->tdata()[i] = tt;
|
||||||
goto Lconst;
|
goto Lconst;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -528,6 +528,11 @@ Expression *TraitsExp::semantic(Scope *sc)
|
|||||||
s1 = s1->toAlias();
|
s1 = s1->toAlias();
|
||||||
s2 = s2->toAlias();
|
s2 = s2->toAlias();
|
||||||
|
|
||||||
|
if (s1->isFuncAliasDeclaration())
|
||||||
|
s1 = ((FuncAliasDeclaration *)s1)->toAliasFunc();
|
||||||
|
if (s2->isFuncAliasDeclaration())
|
||||||
|
s2 = ((FuncAliasDeclaration *)s2)->toAliasFunc();
|
||||||
|
|
||||||
if (s1 == s2)
|
if (s1 == s2)
|
||||||
goto Ltrue;
|
goto Ltrue;
|
||||||
else
|
else
|
||||||
|
|||||||
Submodule runtime/druntime updated: 946b499bd6...90a1a8ae84
Submodule runtime/phobos updated: d857400952...2bc3677ac0
Reference in New Issue
Block a user