mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-05-02 16:31:29 +02:00
Merge dmdfe 2.053beta
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -487,7 +487,7 @@ void preFunctionParameters(Loc loc, Scope *sc, Expressions *exps)
|
||||
* Call copy constructor for struct value argument.
|
||||
*/
|
||||
#if DMDV2
|
||||
Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
|
||||
Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope)
|
||||
{
|
||||
Type *tb = e->type->toBasetype();
|
||||
assert(tb->ty == Tstruct);
|
||||
@@ -500,9 +500,10 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
|
||||
* This is not the most efficent, ideally tmp would be constructed
|
||||
* directly onto the stack.
|
||||
*/
|
||||
Identifier *idtmp = Lexer::uniqueId("__tmp");
|
||||
Identifier *idtmp = Lexer::uniqueId("__cpcttmp");
|
||||
VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e));
|
||||
tmp->storage_class |= STCctfe;
|
||||
tmp->noscope = noscope;
|
||||
Expression *ae = new DeclarationExp(loc, tmp);
|
||||
e = new CommaExp(loc, ae, new VarExp(loc, tmp));
|
||||
e = e->semantic(sc);
|
||||
@@ -706,10 +707,41 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
|
||||
#if DMDV2
|
||||
if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
|
||||
{
|
||||
arg = callCpCtor(loc, sc, arg);
|
||||
if (arg->op == TOKcall)
|
||||
{
|
||||
/* The struct value returned from the function is transferred
|
||||
* to the function, so the callee should not call the destructor
|
||||
* on it.
|
||||
* ((S _ctmp = S.init), _ctmp).this(...)
|
||||
*/
|
||||
CallExp *ce = (CallExp *)arg;
|
||||
if (ce->e1->op == TOKdotvar)
|
||||
{ DotVarExp *dve = (DotVarExp *)ce->e1;
|
||||
if (dve->var->isCtorDeclaration())
|
||||
{ // It's a constructor call
|
||||
if (dve->e1->op == TOKcomma)
|
||||
{ CommaExp *comma = (CommaExp *)dve->e1;
|
||||
if (comma->e2->op == TOKvar)
|
||||
{ VarExp *ve = (VarExp *)comma->e2;
|
||||
VarDeclaration *ctmp = ve->var->isVarDeclaration();
|
||||
if (ctmp)
|
||||
ctmp->noscope = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* Not transferring it, so call the copy constructor
|
||||
*/
|
||||
arg = callCpCtor(loc, sc, arg, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//printf("arg: %s\n", arg->toChars());
|
||||
//printf("type: %s\n", arg->type->toChars());
|
||||
|
||||
// Convert lazy argument to a delegate
|
||||
if (p->storageClass & STClazy)
|
||||
{
|
||||
@@ -770,7 +802,12 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
|
||||
}
|
||||
}
|
||||
|
||||
// Do not allow types that need destructors
|
||||
if (arg->type->needsDestruction())
|
||||
arg->error("cannot pass types that need destruction as variadic arguments");
|
||||
|
||||
// Convert static arrays to dynamic arrays
|
||||
// BUG: I don't think this is right for D2
|
||||
tb = arg->type->toBasetype();
|
||||
if (tb->ty == Tsarray)
|
||||
{ TypeSArray *ts = (TypeSArray *)tb;
|
||||
@@ -783,7 +820,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
|
||||
#if DMDV2
|
||||
if (tb->ty == Tstruct)
|
||||
{
|
||||
arg = callCpCtor(loc, sc, arg);
|
||||
arg = callCpCtor(loc, sc, arg, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1251,6 +1288,7 @@ void Expression::checkPurity(Scope *sc, FuncDeclaration *f)
|
||||
// If the caller has a pure parent, then either the called func must be pure,
|
||||
// OR, they must have the same pure parent.
|
||||
if (outerfunc->isPure() && !sc->intypeof &&
|
||||
!(sc->flags & SCOPEdebug) &&
|
||||
!(f->isPure() || (calledparent == outerfunc)))
|
||||
{
|
||||
error("pure function '%s' cannot call impure function '%s'",
|
||||
@@ -1464,6 +1502,55 @@ Expressions *Expression::arraySyntaxCopy(Expressions *exps)
|
||||
return a;
|
||||
}
|
||||
|
||||
/***************************************************
|
||||
* Recognize expressions of the form:
|
||||
* ((T v = init), v)
|
||||
* where v is a temp.
|
||||
* This is used in optimizing out unnecessary temporary generation.
|
||||
* Returns initializer expression of v if so, NULL if not.
|
||||
*/
|
||||
|
||||
Expression *Expression::isTemp()
|
||||
{
|
||||
//printf("isTemp() %s\n", toChars());
|
||||
if (op == TOKcomma)
|
||||
{ CommaExp *ec = (CommaExp *)this;
|
||||
if (ec->e1->op == TOKdeclaration &&
|
||||
ec->e2->op == TOKvar)
|
||||
{ DeclarationExp *de = (DeclarationExp *)ec->e1;
|
||||
VarExp *ve = (VarExp *)ec->e2;
|
||||
if (ve->var == de->declaration && ve->var->storage_class & STCctfe)
|
||||
{ VarDeclaration *v = ve->var->isVarDeclaration();
|
||||
if (v && v->init)
|
||||
{
|
||||
ExpInitializer *ei = v->init->isExpInitializer();
|
||||
if (ei)
|
||||
{ Expression *e = ei->exp;
|
||||
if (e->op == TOKconstruct)
|
||||
{ ConstructExp *ce = (ConstructExp *)e;
|
||||
if (ce->e1->op == TOKvar && ((VarExp *)ce->e1)->var == ve->var)
|
||||
e = ce->e2;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
* Destructors are attached to VarDeclarations.
|
||||
* Hence, if expression returns a temp that needs a destructor,
|
||||
* make sure and create a VarDeclaration for that temp.
|
||||
*/
|
||||
|
||||
Expression *Expression::addDtorHook(Scope *sc)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/******************************** IntegerExp **************************/
|
||||
|
||||
IntegerExp::IntegerExp(Loc loc, dinteger_t value, Type *type)
|
||||
@@ -3433,17 +3520,21 @@ Expression *StructLiteralExp::semantic(Scope *sc)
|
||||
else
|
||||
{
|
||||
if (v->init)
|
||||
{ e = v->init->toExpression();
|
||||
if (!e)
|
||||
{ error("cannot make expression out of initializer for %s", v->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
else if (v->scope)
|
||||
{ // Do deferred semantic analysis
|
||||
Initializer *i2 = v->init->syntaxCopy();
|
||||
i2 = i2->semantic(v->scope, v->type);
|
||||
e = i2->toExpression();
|
||||
v->scope = NULL;
|
||||
{ if (v->init->isVoidInitializer())
|
||||
e = NULL;
|
||||
else
|
||||
{ e = v->init->toExpression();
|
||||
if (!e)
|
||||
{ error("cannot make expression out of initializer for %s", v->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
else if (v->scope)
|
||||
{ // Do deferred semantic analysis
|
||||
Initializer *i2 = v->init->syntaxCopy();
|
||||
i2 = i2->semantic(v->scope, v->type, WANTinterpret);
|
||||
e = i2->toExpression();
|
||||
v->scope = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -3454,6 +3545,22 @@ Expression *StructLiteralExp::semantic(Scope *sc)
|
||||
}
|
||||
|
||||
type = stype ? stype : sd->type;
|
||||
|
||||
/* If struct requires a destructor, rewrite as:
|
||||
* (S tmp = S()),tmp
|
||||
* so that the destructor can be hung on tmp.
|
||||
*/
|
||||
if (sd->dtor)
|
||||
{
|
||||
Identifier *idtmp = Lexer::uniqueId("__sl");
|
||||
VarDeclaration *tmp = new VarDeclaration(loc, type, idtmp, new ExpInitializer(0, this));
|
||||
tmp->storage_class |= STCctfe;
|
||||
Expression *ae = new DeclarationExp(loc, tmp);
|
||||
Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp));
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -3481,7 +3588,7 @@ Expression *StructLiteralExp::getField(Type *type, unsigned offset)
|
||||
/* If type is a static array, and e is an initializer for that array,
|
||||
* then the field initializer should be an array literal of e.
|
||||
*/
|
||||
if (e->type != type && type->ty == Tsarray)
|
||||
if (e->type->castMod(0) != type->castMod(0) && type->ty == Tsarray)
|
||||
{ TypeSArray *tsa = (TypeSArray *)type;
|
||||
uinteger_t length = tsa->dim->toInteger();
|
||||
Expressions *z = new Expressions;
|
||||
@@ -3696,6 +3803,8 @@ Lagain:
|
||||
}
|
||||
//printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
|
||||
}
|
||||
if (global.errors)
|
||||
return new ErrorExp();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4344,7 +4453,7 @@ Expression *VarExp::semantic(Scope *sc)
|
||||
v->checkNestedReference(sc, loc);
|
||||
#if DMDV2
|
||||
#if 1
|
||||
if (sc->func && !sc->intypeof)
|
||||
if (sc->func && !sc->intypeof && !(sc->flags & SCOPEdebug))
|
||||
{
|
||||
/* Given:
|
||||
* void f()
|
||||
@@ -4551,7 +4660,8 @@ TupleExp::TupleExp(Loc loc, TupleDeclaration *tup)
|
||||
if (o->dyncast() == DYNCAST_EXPRESSION)
|
||||
{
|
||||
Expression *e = (Expression *)o;
|
||||
e = e->syntaxCopy();
|
||||
if (e->op == TOKdsymbol)
|
||||
e = e->syntaxCopy();
|
||||
exps->push(e);
|
||||
}
|
||||
else if (o->dyncast() == DYNCAST_DSYMBOL)
|
||||
@@ -5051,8 +5161,8 @@ Expression *IsExp::semantic(Scope *sc)
|
||||
*/
|
||||
|
||||
//printf("IsExp::semantic(%s)\n", toChars());
|
||||
if (id && !(sc->flags & SCOPEstaticif))
|
||||
{ error("can only declare type aliases within static if conditionals");
|
||||
if (id && !(sc->flags & (SCOPEstaticif | SCOPEstaticassert)))
|
||||
{ error("can only declare type aliases within static if conditionals or static asserts");
|
||||
return new ErrorExp();
|
||||
}
|
||||
|
||||
@@ -5693,6 +5803,8 @@ Expression *CompileExp::semantic(Scope *sc)
|
||||
#endif
|
||||
UnaExp::semantic(sc);
|
||||
e1 = resolveProperties(sc, e1);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (!e1->type->isString())
|
||||
{
|
||||
error("argument to mixin must be a string type, not %s\n", e1->type->toChars());
|
||||
@@ -5740,7 +5852,7 @@ Expression *FileExp::semantic(Scope *sc)
|
||||
#endif
|
||||
UnaExp::semantic(sc);
|
||||
e1 = resolveProperties(sc, e1);
|
||||
e1 = e1->optimize(WANTvalue);
|
||||
e1 = e1->optimize(WANTvalue | WANTinterpret);
|
||||
if (e1->op != TOKstring)
|
||||
{ error("file name argument must be a string, not (%s)", e1->toChars());
|
||||
goto Lerror;
|
||||
@@ -6266,6 +6378,7 @@ 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
|
||||
@@ -6435,6 +6548,8 @@ Expression *DotTemplateInstanceExp::semantic(Scope *sc)
|
||||
Expression *e = new DotIdExp(loc, e1, ti->name);
|
||||
L1:
|
||||
e = e->semantic(sc);
|
||||
if (e->op == TOKerror)
|
||||
return e;
|
||||
if (e->op == TOKdottd)
|
||||
{
|
||||
if (global.errors)
|
||||
@@ -7219,7 +7334,7 @@ Lagain:
|
||||
{ TypeDelegate *td = (TypeDelegate *)t1;
|
||||
assert(td->next->ty == Tfunction);
|
||||
tf = (TypeFunction *)(td->next);
|
||||
if (sc->func && sc->func->isPure() && !tf->purity)
|
||||
if (sc->func && sc->func->isPure() && !tf->purity && !(sc->flags & SCOPEdebug))
|
||||
{
|
||||
error("pure function '%s' cannot call impure delegate '%s'", sc->func->toChars(), e1->toChars());
|
||||
}
|
||||
@@ -7233,7 +7348,7 @@ Lagain:
|
||||
{
|
||||
Expression *e = new PtrExp(loc, e1);
|
||||
t1 = ((TypePointer *)t1)->next;
|
||||
if (sc->func && sc->func->isPure() && !((TypeFunction *)t1)->purity)
|
||||
if (sc->func && sc->func->isPure() && !((TypeFunction *)t1)->purity && !(sc->flags & SCOPEdebug))
|
||||
{
|
||||
error("pure function '%s' cannot call impure function pointer '%s'", sc->func->toChars(), e1->toChars());
|
||||
}
|
||||
@@ -7356,9 +7471,9 @@ int CallExp::checkSideEffect(int flag)
|
||||
* then this expression has no side effects.
|
||||
*/
|
||||
Type *t = e1->type->toBasetype();
|
||||
if (t->ty == Tfunction && ((TypeFunction *)t)->purity)
|
||||
if (t->ty == Tfunction && ((TypeFunction *)t)->purity > PUREweak)
|
||||
return 0;
|
||||
if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->purity)
|
||||
if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->purity > PUREweak)
|
||||
return 0;
|
||||
#endif
|
||||
return 1;
|
||||
@@ -7417,6 +7532,51 @@ Expression *CallExp::toLvalue(Scope *sc, Expression *e)
|
||||
return Expression::toLvalue(sc, e);
|
||||
}
|
||||
|
||||
Expression *CallExp::addDtorHook(Scope *sc)
|
||||
{
|
||||
/* Only need to add dtor hook if it's a type that needs destruction.
|
||||
* Use same logic as VarDeclaration::callScopeDtor()
|
||||
*/
|
||||
|
||||
if (e1->type && e1->type->ty == Tfunction)
|
||||
{
|
||||
TypeFunction *tf = (TypeFunction *)e1->type;
|
||||
if (tf->isref)
|
||||
return this;
|
||||
}
|
||||
|
||||
Type *tv = type->toBasetype();
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->dtor)
|
||||
{ /* Type needs destruction, so declare a tmp
|
||||
* which the back end will recognize and call dtor on
|
||||
*/
|
||||
if (e1->op == TOKdotvar)
|
||||
{
|
||||
DotVarExp* dve = (DotVarExp*)e1;
|
||||
if (dve->e1->isTemp() != NULL)
|
||||
goto Lnone; // already got a tmp
|
||||
}
|
||||
|
||||
Identifier *idtmp = Lexer::uniqueId("__tmpfordtor");
|
||||
VarDeclaration *tmp = new VarDeclaration(loc, type, idtmp, new ExpInitializer(loc, this));
|
||||
tmp->storage_class |= STCctfe;
|
||||
Expression *ae = new DeclarationExp(loc, tmp);
|
||||
Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp));
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
Lnone:
|
||||
return this;
|
||||
}
|
||||
|
||||
void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (e1->op == TOKtype)
|
||||
@@ -7779,6 +7939,8 @@ Expression *DeleteExp::semantic(Scope *sc)
|
||||
UnaExp::semantic(sc);
|
||||
e1 = resolveProperties(sc, e1);
|
||||
e1 = e1->toLvalue(sc, NULL);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
type = Type::tvoid;
|
||||
|
||||
tb = e1->type->toBasetype();
|
||||
@@ -8591,6 +8753,7 @@ Expression *CommaExp::semantic(Scope *sc)
|
||||
{
|
||||
if (!type)
|
||||
{ BinExp::semanticp(sc);
|
||||
e1 = e1->addDtorHook(sc);
|
||||
type = e2->type;
|
||||
}
|
||||
return this;
|
||||
@@ -8656,6 +8819,12 @@ int CommaExp::checkSideEffect(int flag)
|
||||
}
|
||||
}
|
||||
|
||||
Expression *CommaExp::addDtorHook(Scope *sc)
|
||||
{
|
||||
e2 = e2->addDtorHook(sc);
|
||||
return this;
|
||||
}
|
||||
|
||||
/************************** IndexExp **********************************/
|
||||
|
||||
// e1 [ e2 ]
|
||||
@@ -8894,7 +9063,7 @@ Expression *PostExp::semantic(Scope *sc)
|
||||
/* Rewrite as:
|
||||
* auto tmp = e1; ++e1; tmp
|
||||
*/
|
||||
Identifier *id = Lexer::uniqueId("__tmp");
|
||||
Identifier *id = Lexer::uniqueId("__pitmp");
|
||||
ExpInitializer *ei = new ExpInitializer(loc, e1);
|
||||
VarDeclaration *tmp = new VarDeclaration(loc, e1->type, id, ei);
|
||||
Expression *ea = new DeclarationExp(loc, tmp);
|
||||
@@ -9180,16 +9349,28 @@ Expression *AssignExp::semantic(Scope *sc)
|
||||
sd->cpctor)
|
||||
{ /* We have a copy constructor for this
|
||||
*/
|
||||
// Scan past commma's
|
||||
Expression *ec = NULL;
|
||||
while (e2->op == TOKcomma)
|
||||
{ CommaExp *ecomma = (CommaExp *)e2;
|
||||
e2 = ecomma->e2;
|
||||
if (ec)
|
||||
ec = new CommaExp(ecomma->loc, ec, ecomma->e1);
|
||||
else
|
||||
ec = ecomma->e1;
|
||||
}
|
||||
if (e2->op == TOKquestion)
|
||||
{ /* Write as:
|
||||
* a ? e1 = b : e1 = c;
|
||||
*/
|
||||
CondExp *ec = (CondExp *)e2;
|
||||
AssignExp *ea1 = new AssignExp(ec->e1->loc, e1, ec->e1);
|
||||
CondExp *econd = (CondExp *)e2;
|
||||
AssignExp *ea1 = new AssignExp(econd->e1->loc, e1, econd->e1);
|
||||
ea1->op = op;
|
||||
AssignExp *ea2 = new AssignExp(ec->e1->loc, e1, ec->e2);
|
||||
AssignExp *ea2 = new AssignExp(econd->e1->loc, e1, econd->e2);
|
||||
ea2->op = op;
|
||||
Expression *e = new CondExp(loc, ec->econd, ea1, ea2);
|
||||
Expression *e = new CondExp(loc, econd->econd, ea1, ea2);
|
||||
if (ec)
|
||||
e = new CommaExp(loc, ec, e);
|
||||
return e->semantic(sc);
|
||||
}
|
||||
else if (e2->op == TOKvar ||
|
||||
@@ -9202,8 +9383,33 @@ Expression *AssignExp::semantic(Scope *sc)
|
||||
*/
|
||||
Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0);
|
||||
e = new CallExp(loc, e, e2);
|
||||
if (ec)
|
||||
e = new CommaExp(loc, ec, e);
|
||||
return e->semantic(sc);
|
||||
}
|
||||
else if (e2->op == TOKcall)
|
||||
{
|
||||
/* The struct value returned from the function is transferred
|
||||
* so should not call the destructor on it.
|
||||
* ((S _ctmp = S.init), _ctmp).this(...)
|
||||
*/
|
||||
CallExp *ce = (CallExp *)e2;
|
||||
if (ce->e1->op == TOKdotvar)
|
||||
{ DotVarExp *dve = (DotVarExp *)ce->e1;
|
||||
if (dve->var->isCtorDeclaration())
|
||||
{ // It's a constructor call
|
||||
if (dve->e1->op == TOKcomma)
|
||||
{ CommaExp *comma = (CommaExp *)dve->e1;
|
||||
if (comma->e2->op == TOKvar)
|
||||
{ VarExp *ve = (VarExp *)comma->e2;
|
||||
VarDeclaration *ctmp = ve->var->isVarDeclaration();
|
||||
if (ctmp)
|
||||
ctmp->noscope = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9560,6 +9766,7 @@ Expression *CatAssignExp::semantic(Scope *sc)
|
||||
}
|
||||
else if (tb1->ty == Tarray &&
|
||||
(tb1next->ty == Tchar || tb1next->ty == Twchar) &&
|
||||
e2->type->ty != tb1next->ty &&
|
||||
e2->implicitConvTo(Type::tdchar)
|
||||
)
|
||||
{ // Append dchar to char[] or wchar[]
|
||||
@@ -10448,6 +10655,35 @@ Expression *PowExp::semantic(Scope *sc)
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
// Replace x ^^ 0 or x^^0.0 by (x, 1)
|
||||
if ((e2->op == TOKint64 && e2->toInteger() == 0) ||
|
||||
(e2->op == TOKfloat64 && e2->toReal() == 0.0))
|
||||
{
|
||||
if (e1->op == TOKint64)
|
||||
e = new IntegerExp(loc, 1, e1->type);
|
||||
else
|
||||
e = new RealExp(loc, 1.0, e1->type);
|
||||
|
||||
typeCombine(sc);
|
||||
e = new CommaExp(loc, e1, e);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
// Replace x ^^ 1 or x^^1.0 by (x)
|
||||
if ((e2->op == TOKint64 && e2->toInteger() == 1) ||
|
||||
(e2->op == TOKfloat64 && e2->toReal() == 1.0))
|
||||
{
|
||||
typeCombine(sc);
|
||||
return e1;
|
||||
}
|
||||
// Replace x ^^ -1.0 by (1.0 / x)
|
||||
if ((e2->op == TOKfloat64 && e2->toReal() == -1.0))
|
||||
{
|
||||
typeCombine(sc);
|
||||
e = new DivExp(loc, new RealExp(loc, 1.0, e2->type), e1);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
// All other negative integral powers are illegal
|
||||
if ((e1->type->isintegral()) && (e2->op == TOKint64) && (sinteger_t)e2->toInteger() < 0)
|
||||
{
|
||||
@@ -10469,7 +10705,7 @@ Expression *PowExp::semantic(Scope *sc)
|
||||
typeCombine(sc);
|
||||
// Replace x^^2 with (tmp = x, tmp*tmp)
|
||||
// Replace x^^3 with (tmp = x, tmp*tmp*tmp)
|
||||
Identifier *idtmp = Lexer::uniqueId("__tmp");
|
||||
Identifier *idtmp = Lexer::uniqueId("__powtmp");
|
||||
VarDeclaration *tmp = new VarDeclaration(loc, e1->type->toBasetype(), idtmp, new ExpInitializer(0, e1));
|
||||
tmp->storage_class = STCctfe;
|
||||
Expression *ve = new VarExp(loc, tmp);
|
||||
@@ -10744,13 +10980,21 @@ Expression *OrOrExp::semantic(Scope *sc)
|
||||
e2 = resolveProperties(sc, e2);
|
||||
e2 = e2->checkToPointer();
|
||||
|
||||
type = Type::tboolean;
|
||||
if (e2->type->ty == Tvoid)
|
||||
type = Type::tvoid;
|
||||
else
|
||||
{
|
||||
e2 = e2->checkToBoolean(sc);
|
||||
type = Type::tboolean;
|
||||
}
|
||||
if (e2->op == TOKtype || e2->op == TOKimport)
|
||||
{ error("%s is not an expression", e2->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (e2->op == TOKerror)
|
||||
return e2;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -10811,13 +11055,21 @@ Expression *AndAndExp::semantic(Scope *sc)
|
||||
e2 = resolveProperties(sc, e2);
|
||||
e2 = e2->checkToPointer();
|
||||
|
||||
type = Type::tboolean;
|
||||
if (e2->type->ty == Tvoid)
|
||||
type = Type::tvoid;
|
||||
else
|
||||
{
|
||||
e2 = e2->checkToBoolean(sc);
|
||||
type = Type::tboolean;
|
||||
}
|
||||
if (e2->op == TOKtype || e2->op == TOKimport)
|
||||
{ error("%s is not an expression", e2->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (e2->op == TOKerror)
|
||||
return e2;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user