mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00
Move Expression.checkXXX functions to expressionsem.d (#20764)
This commit is contained in:
parent
279f3054bf
commit
864b5747e6
2 changed files with 104 additions and 111 deletions
|
@ -535,105 +535,6 @@ extern (C++) abstract class Expression : ASTNode
|
|||
return false;
|
||||
}
|
||||
|
||||
extern (D) final bool checkScalar()
|
||||
{
|
||||
if (op == EXP.error)
|
||||
return true;
|
||||
if (type.toBasetype().ty == Terror)
|
||||
return true;
|
||||
if (!type.isScalar())
|
||||
{
|
||||
error(loc, "`%s` is not a scalar, it is a `%s`", toChars(), type.toChars());
|
||||
return true;
|
||||
}
|
||||
return checkValue();
|
||||
}
|
||||
|
||||
extern (D) final bool checkNoBool()
|
||||
{
|
||||
if (op == EXP.error)
|
||||
return true;
|
||||
if (type.toBasetype().ty == Terror)
|
||||
return true;
|
||||
if (type.toBasetype().ty == Tbool)
|
||||
{
|
||||
error(loc, "operation not allowed on `bool` `%s`", toChars());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
extern (D) final bool checkIntegral()
|
||||
{
|
||||
if (op == EXP.error)
|
||||
return true;
|
||||
if (type.toBasetype().ty == Terror)
|
||||
return true;
|
||||
if (!type.isIntegral())
|
||||
{
|
||||
error(loc, "`%s` is not of integral type, it is a `%s`", toChars(), type.toChars());
|
||||
return true;
|
||||
}
|
||||
return checkValue();
|
||||
}
|
||||
|
||||
extern (D) final bool checkArithmetic(EXP op)
|
||||
{
|
||||
if (op == EXP.error)
|
||||
return true;
|
||||
if (type.toBasetype().ty == Terror)
|
||||
return true;
|
||||
if (!type.isIntegral() && !type.isFloating())
|
||||
{
|
||||
// unary aggregate ops error here
|
||||
const char* msg = type.isAggregate() ?
|
||||
"operator `%s` is not defined for `%s` of type `%s`" :
|
||||
"illegal operator `%s` for `%s` of type `%s`";
|
||||
error(loc, msg, EXPtoString(op).ptr, toChars(), type.toChars());
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: Existing code relies on adding / subtracting types in typeof() expressions:
|
||||
// alias I = ulong; alias U = typeof(I + 1u);
|
||||
// https://github.com/dlang/dmd/issues/20763
|
||||
if (op == EXP.add || op == EXP.min)
|
||||
return false;
|
||||
|
||||
return checkValue();
|
||||
}
|
||||
|
||||
/*******************************
|
||||
* Check whether the expression allows RMW operations, error with rmw operator diagnostic if not.
|
||||
* ex is the RHS expression, or NULL if ++/-- is used (for diagnostics)
|
||||
* Returns true if error occurs.
|
||||
*/
|
||||
extern (D) final bool checkReadModifyWrite(EXP rmwOp, Expression ex = null)
|
||||
{
|
||||
//printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex.toChars() : "");
|
||||
if (!type || !type.isShared() || type.isTypeStruct() || type.isTypeClass())
|
||||
return false;
|
||||
|
||||
// atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal.
|
||||
switch (rmwOp)
|
||||
{
|
||||
case EXP.plusPlus:
|
||||
case EXP.prePlusPlus:
|
||||
rmwOp = EXP.addAssign;
|
||||
break;
|
||||
case EXP.minusMinus:
|
||||
case EXP.preMinusMinus:
|
||||
rmwOp = EXP.minAssign;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
error(loc, "read-modify-write operations are not allowed for `shared` variables");
|
||||
errorSupplemental(loc, "Use `core.atomic.atomicOp!\"%s\"(%s, %s)` instead",
|
||||
EXPtoString(rmwOp).ptr, toChars(), ex ? ex.toChars() : "1");
|
||||
return true;
|
||||
}
|
||||
|
||||
/******************************
|
||||
* Take address of expression.
|
||||
*/
|
||||
|
@ -3065,18 +2966,6 @@ extern (C++) abstract class BinExp : Expression
|
|||
return e;
|
||||
}
|
||||
|
||||
extern (D) final bool checkIntegralBin()
|
||||
{
|
||||
bool r1 = e1.checkIntegral();
|
||||
bool r2 = e2.checkIntegral();
|
||||
return (r1 || r2);
|
||||
}
|
||||
|
||||
extern (D) final bool checkArithmeticBin()
|
||||
{
|
||||
return e1.checkArithmetic(this.op) || e2.checkArithmetic(this.op);
|
||||
}
|
||||
|
||||
/*********************
|
||||
* Mark the operands as will never be dereferenced,
|
||||
* which is useful info for @safe checks.
|
||||
|
|
|
@ -14683,6 +14683,98 @@ MATCH matchType(FuncExp funcExp, Type to, Scope* sc, FuncExp* presult, ErrorSink
|
|||
return m;
|
||||
}
|
||||
|
||||
private bool checkScalar(Expression e)
|
||||
{
|
||||
if (e.op == EXP.error)
|
||||
return true;
|
||||
if (e.type.toBasetype().ty == Terror)
|
||||
return true;
|
||||
if (!e.type.isScalar())
|
||||
{
|
||||
error(e.loc, "`%s` is not a scalar, it is a `%s`", e.toChars(), e.type.toChars());
|
||||
return true;
|
||||
}
|
||||
return e.checkValue();
|
||||
}
|
||||
|
||||
private bool checkNoBool(Expression e)
|
||||
{
|
||||
if (e.op == EXP.error)
|
||||
return true;
|
||||
if (e.type.toBasetype().ty == Terror)
|
||||
return true;
|
||||
if (e.type.toBasetype().ty == Tbool)
|
||||
{
|
||||
error(e.loc, "operation not allowed on `bool` `%s`", e.toChars());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool checkIntegral(Expression e)
|
||||
{
|
||||
if (e.op == EXP.error)
|
||||
return true;
|
||||
if (e.type.toBasetype().ty == Terror)
|
||||
return true;
|
||||
if (!e.type.isIntegral())
|
||||
{
|
||||
error(e.loc, "`%s` is not of integral type, it is a `%s`", e.toChars(), e.type.toChars());
|
||||
return true;
|
||||
}
|
||||
return e.checkValue();
|
||||
}
|
||||
|
||||
private bool checkArithmetic(Expression e, EXP op)
|
||||
{
|
||||
if (op == EXP.error)
|
||||
return true;
|
||||
if (e.type.toBasetype().ty == Terror)
|
||||
return true;
|
||||
if (!e.type.isIntegral() && !e.type.isFloating())
|
||||
{
|
||||
// unary aggregate ops error here
|
||||
const char* msg = e.type.isAggregate() ?
|
||||
"operator `%s` is not defined for `%s` of type `%s`" :
|
||||
"illegal operator `%s` for `%s` of type `%s`";
|
||||
error(e.loc, msg, EXPtoString(op).ptr, e.toChars(), e.type.toChars());
|
||||
return true;
|
||||
}
|
||||
return e.checkValue();
|
||||
}
|
||||
|
||||
/*******************************
|
||||
* Check whether the expression allows RMW operations, error with rmw operator diagnostic if not.
|
||||
* ex is the RHS expression, or NULL if ++/-- is used (for diagnostics)
|
||||
* Returns true if error occurs.
|
||||
*/
|
||||
private bool checkReadModifyWrite(Expression e, EXP rmwOp, Expression ex = null)
|
||||
{
|
||||
//printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex.toChars() : "");
|
||||
if (!e.type || !e.type.isShared() || e.type.isTypeStruct() || e.type.isTypeClass())
|
||||
return false;
|
||||
|
||||
// atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal.
|
||||
switch (rmwOp)
|
||||
{
|
||||
case EXP.plusPlus:
|
||||
case EXP.prePlusPlus:
|
||||
rmwOp = EXP.addAssign;
|
||||
break;
|
||||
case EXP.minusMinus:
|
||||
case EXP.preMinusMinus:
|
||||
rmwOp = EXP.minAssign;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
error(e.loc, "read-modify-write operations are not allowed for `shared` variables");
|
||||
errorSupplemental(e.loc, "Use `core.atomic.atomicOp!\"%s\"(%s, %s)` instead",
|
||||
EXPtoString(rmwOp).ptr, e.toChars(), ex ? ex.toChars() : "1");
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool checkSharedAccessBin(BinExp binExp, Scope* sc)
|
||||
{
|
||||
const r1 = binExp.e1.checkSharedAccess(sc);
|
||||
|
@ -14690,6 +14782,18 @@ private bool checkSharedAccessBin(BinExp binExp, Scope* sc)
|
|||
return (r1 || r2);
|
||||
}
|
||||
|
||||
private bool checkIntegralBin(BinExp e)
|
||||
{
|
||||
bool r1 = e.e1.checkIntegral();
|
||||
bool r2 = e.e2.checkIntegral();
|
||||
return (r1 || r2);
|
||||
}
|
||||
|
||||
private bool checkArithmeticBin(BinExp e)
|
||||
{
|
||||
return (e.e1.checkArithmetic(e.op) || e.e2.checkArithmetic(e.op));
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* If expression is shared, check that we can access it.
|
||||
* Give error message if not.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue