Skip to content

Commit

Permalink
Merge pull request #3701 from 9rnsr/fix13003
Browse files Browse the repository at this point in the history
Issue 13003 - Lack of read-modify-write operation check on shared object field
  • Loading branch information
AndrejMitrovic committed Jun 29, 2014
2 parents 968566c + 9df19d7 commit b79c18f
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 61 deletions.
50 changes: 22 additions & 28 deletions src/expression.c
Expand Up @@ -2118,11 +2118,6 @@ int Expression::checkModifiable(Scope *sc, int flag)
return type ? 1 : 0; // default modifiable
}

bool Expression::checkReadModifyWrite()
{
return !type->isShared();
}

Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
{
//printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
Expand All @@ -2145,20 +2140,26 @@ Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
return toLvalue(sc, e);
}

Expression *Expression::readModifyWrite(TOK rmwOp, Expression *ex)
/*******************************
* Check whether the expression allows RMW operations, error with rmw operator diagnostic if not.
* exp is the RHS expression, or NULL if ++/-- is used (for diagnostics)
*/
Expression *Expression::checkReadModifyWrite(TOK rmwOp, Expression *ex)
{
//printf("Expression::readModifyWrite() %s %s", toChars(), ex ? ex->toChars() : "");
if (checkReadModifyWrite())
return this;
//printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex->toChars() : "");
if (!type || !type->isShared())
return NULL;

// atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal.
switch (rmwOp)
{
case TOKplusplus: case TOKpreplusplus:
case TOKplusplus:
case TOKpreplusplus:
rmwOp = TOKaddass;
break;

case TOKminusminus: case TOKpreminusminus:
case TOKminusminus:
case TOKpreminusminus:
rmwOp = TOKminass;
break;

Expand All @@ -2169,13 +2170,12 @@ Expression *Expression::readModifyWrite(TOK rmwOp, Expression *ex)
deprecation("Read-modify-write operations are not allowed for shared variables. "
"Use core.atomic.atomicOp!\"%s\"(%s, %s) instead.",
Token::tochars[rmwOp], toChars(), ex ? ex->toChars() : "1");
return this;
return NULL;

// note: enable when deprecation becomes an error.
// return new ErrorExp();
}


/************************************
* Detect cases where pointers to the stack can 'escape' the
* lifetime of the stack frame.
Expand Down Expand Up @@ -5316,12 +5316,6 @@ int VarExp::checkModifiable(Scope *sc, int flag)
return var->checkModify(loc, sc, type, NULL, flag);
}

bool VarExp::checkReadModifyWrite()
{
//printf("VarExp::checkReadModifyWrite %s", toChars());
return (var->storage_class & STCshared) == 0;
}

Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e)
{
//printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
Expand Down Expand Up @@ -6727,7 +6721,9 @@ Expression *BinAssignExp::semantic(Scope *sc)
if (e)
return e;

e1->readModifyWrite(op, e2);
e = e1->checkReadModifyWrite(op, e2);
if (e)
return e;

if (e1->op == TOKarraylength)
{
Expand Down Expand Up @@ -7705,12 +7701,6 @@ int DotVarExp::checkModifiable(Scope *sc, int flag)
return e1->checkModifiable(sc, flag);
}

bool DotVarExp::checkReadModifyWrite()
{
//printf("DotVarExp::checkReadModifyWrite %s", toChars());
return (var->storage_class & STCshared) == 0;
}

Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
{
#if 0
Expand Down Expand Up @@ -10846,7 +10836,9 @@ Expression *PostExp::semantic(Scope *sc)
if (e)
return e;

e1->readModifyWrite(op); // check whether rmw operation is allowed
e = e1->checkReadModifyWrite(op);
if (e)
return e;

if (e1->op == TOKslice)
{
Expand Down Expand Up @@ -12042,7 +12034,9 @@ Expression *PowAssignExp::semantic(Scope *sc)
if (e)
return e;

e1->readModifyWrite(op, e2); // check whether rmw operation is allowed
e = e1->checkReadModifyWrite(op, e2);
if (e)
return e;

assert(e1->type && e2->type);
if (e1->op == TOKslice || e1->type->ty == Tarray || e1->type->ty == Tsarray)
Expand Down
7 changes: 1 addition & 6 deletions src/expression.h
Expand Up @@ -205,19 +205,14 @@ class Expression : public RootObject
void checkNoBool();
Expression *checkIntegral();
Expression *checkArithmetic();
Expression *checkReadModifyWrite(TOK rmwOp, Expression *exp = NULL);
void checkDeprecated(Scope *sc, Dsymbol *s);
void checkPurity(Scope *sc, FuncDeclaration *f);
void checkPurity(Scope *sc, VarDeclaration *v);
void checkSafety(Scope *sc, FuncDeclaration *f);
void checkNogc(Scope *sc, FuncDeclaration *f);
bool checkPostblit(Scope *sc, Type *t);
virtual int checkModifiable(Scope *sc, int flag = 0);

// check whether the expression allows RMW operations, error with rmw operator diagnostic if not.
// exp is the RHS expression, or NULL if ++/-- is used (for diagnostics)
Expression *readModifyWrite(TOK rmwOp, Expression *exp = NULL);
virtual bool checkReadModifyWrite(); // return true if the expression allows RMW operations.

virtual Expression *checkToBoolean(Scope *sc);
virtual Expression *addDtorHook(Scope *sc);
Expression *checkToPointer();
Expand Down
48 changes: 21 additions & 27 deletions test/fail_compilation/diag3672.d
Expand Up @@ -3,35 +3,33 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag3672.d(38): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(x, 1) instead.
fail_compilation/diag3672.d(39): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(x, 1) instead.
fail_compilation/diag3672.d(40): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"-="(x, 1) instead.
fail_compilation/diag3672.d(41): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"-="(x, 1) instead.
fail_compilation/diag3672.d(42): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(x, 1) instead.
fail_compilation/diag3672.d(43): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(x, 2) instead.
fail_compilation/diag3672.d(44): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"-="(x, 3) instead.
fail_compilation/diag3672.d(45): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"|="(x, y) instead.
fail_compilation/diag3672.d(46): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"*="(x, y) instead.
fail_compilation/diag3672.d(47): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"/="(x, y) instead.
fail_compilation/diag3672.d(48): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"%="(x, y) instead.
fail_compilation/diag3672.d(49): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"&="(x, y) instead.
fail_compilation/diag3672.d(50): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"^="(x, y) instead.
fail_compilation/diag3672.d(51): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"<<="(x, y) instead.
fail_compilation/diag3672.d(52): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!">>="(x, y) instead.
fail_compilation/diag3672.d(53): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!">>>="(x, y) instead.
fail_compilation/diag3672.d(54): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"^^="(x, y) instead.
fail_compilation/diag3672.d(55): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(ptr, 1) instead.
fail_compilation/diag3672.d(56): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(ptr, 1) instead.
fail_compilation/diag3672.d(57): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"-="(ptr, 1) instead.
fail_compilation/diag3672.d(58): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"-="(ptr, 1) instead.
fail_compilation/diag3672.d(36): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(x, 1) instead.
fail_compilation/diag3672.d(37): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(x, 1) instead.
fail_compilation/diag3672.d(38): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"-="(x, 1) instead.
fail_compilation/diag3672.d(39): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"-="(x, 1) instead.
fail_compilation/diag3672.d(40): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(x, 1) instead.
fail_compilation/diag3672.d(41): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(x, 2) instead.
fail_compilation/diag3672.d(42): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"-="(x, 3) instead.
fail_compilation/diag3672.d(43): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"|="(x, y) instead.
fail_compilation/diag3672.d(44): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"*="(x, y) instead.
fail_compilation/diag3672.d(45): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"/="(x, y) instead.
fail_compilation/diag3672.d(46): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"%="(x, y) instead.
fail_compilation/diag3672.d(47): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"&="(x, y) instead.
fail_compilation/diag3672.d(48): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"^="(x, y) instead.
fail_compilation/diag3672.d(49): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"<<="(x, y) instead.
fail_compilation/diag3672.d(50): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!">>="(x, y) instead.
fail_compilation/diag3672.d(51): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!">>>="(x, y) instead.
fail_compilation/diag3672.d(52): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"^^="(x, y) instead.
fail_compilation/diag3672.d(53): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(ptr, 1) instead.
fail_compilation/diag3672.d(54): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(ptr, 1) instead.
fail_compilation/diag3672.d(55): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"-="(ptr, 1) instead.
fail_compilation/diag3672.d(56): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"-="(ptr, 1) instead.
---
*/
shared int x;
shared int y;
shared int* ptr;
shared static this() { ptr = new int; } // silence null-dereference errors
class NS { shared int x; }
shared class S { int sx; }

void main()
{
Expand All @@ -56,8 +54,4 @@ void main()
ptr++;
--ptr;
ptr--;
NS ns = new NS;
ns.x++;
S s = new S;
s.sx++;
}
34 changes: 34 additions & 0 deletions test/fail_compilation/diag3672a.d
@@ -0,0 +1,34 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -de
/*
TEST_OUTPUT:
---
fail_compilation/diag3672a.d(16): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(ns.x, 1) instead.
fail_compilation/diag3672a.d(18): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(s.sx, 1) instead.
---
*/
class NS { shared int x; }
shared class S { int sx; }

void main()
{
NS ns = new NS;
ns.x++;
S s = new S;
s.sx++;
}

/*
TEST_OUTPUT:
---
fail_compilation/diag3672a.d(32): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(s.var, 1) instead.
fail_compilation/diag3672a.d(33): Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"-="(s.var, 2) instead.
---
*/
void test13003()
{
struct S { int var; }
shared S s;
s.var++;
s.var -= 2;
}

0 comments on commit b79c18f

Please sign in to comment.