Move Expression.checkXXX functions to expressionsem.d (#20764)

This commit is contained in:
Dennis 2025-01-23 14:48:47 +01:00 committed by GitHub
parent 279f3054bf
commit 864b5747e6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 104 additions and 111 deletions

View file

@ -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.

View file

@ -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.