A testcase in the TM TS pointed out a couple of holes in our volatile
checking: we need to check for volatile accesses to general lvalues, not
just variables, and we need to check in transaction_safe functions as
well as transactions.
Tested x86_64-pc-linux-gnu. OK for trunk?
commit e946db577784ed4670944dd91e81666af16793b3
Author: Jason Merrill <ja...@redhat.com>
Date: Tue Sep 29 14:43:08 2015 -0400
Diagnose volatile accesses in transaction_safe function.
* trans-mem.c (volatile_lvalue_p): Rename from volatile_var_p.
(diagnose_tm_1_op): Also diagnose volatile accesses in
transaction_safe function.
diff --git a/gcc/testsuite/c-c++-common/tm/volatile-1.c b/gcc/testsuite/c-c++-common/tm/volatile-1.c
new file mode 100644
index 0000000..eb3799d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/tm/volatile-1.c
@@ -0,0 +1,10 @@
+// Transaction-unsafe testcase from TM TS.
+// { dg-options -fgnu-tm }
+
+volatile int * p = 0;
+__attribute ((transaction_safe))
+int f() {
+ int x = 0; // ok: not volatile
+ p = &x; // ok: the pointer is not volatile
+ int i = *p; // { dg-error "volatile" "read through volatile glvalue" }
+}
diff --git a/gcc/testsuite/gcc.dg/tm/pr46654.c b/gcc/testsuite/gcc.dg/tm/pr46654.c
index bb63b68..563474e 100644
--- a/gcc/testsuite/gcc.dg/tm/pr46654.c
+++ b/gcc/testsuite/gcc.dg/tm/pr46654.c
@@ -7,7 +7,7 @@ int y;
void foo(volatile int x)
{
__transaction_atomic {
- x = 5; /* { dg-error "invalid volatile use of 'x' inside transaction" } */
+ x = 5; /* { dg-error "invalid use of volatile lvalue inside transaction" } */
x += y;
y++;
}
@@ -20,7 +20,7 @@ volatile int i = 0;
void george()
{
__transaction_atomic {
- if (i == 2) /* { dg-error "invalid volatile use of 'i' inside transaction" } */
+ if (i == 2) /* { dg-error "invalid use of volatile lvalue inside transaction" } */
i = 1;
}
}
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index d9a681f..a73d4bc 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -594,12 +594,12 @@ struct diagnose_tm
gimple *stmt;
};
-/* Return true if T is a volatile variable of some kind. */
+/* Return true if T is a volatile lvalue of some kind. */
static bool
-volatile_var_p (tree t)
+volatile_lvalue_p (tree t)
{
- return (SSA_VAR_P (t)
+ return ((SSA_VAR_P (t) || REFERENCE_CLASS_P (t))
&& TREE_THIS_VOLATILE (TREE_TYPE (t)));
}
@@ -612,14 +612,19 @@ diagnose_tm_1_op (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct diagnose_tm *d = (struct diagnose_tm *) wi->info;
- if (volatile_var_p (*tp)
- && d->block_flags & DIAG_TM_SAFE
- && !d->saw_volatile)
+ if (TYPE_P (*tp))
+ *walk_subtrees = false;
+ else if (volatile_lvalue_p (*tp)
+ && !d->saw_volatile)
{
d->saw_volatile = 1;
- error_at (gimple_location (d->stmt),
- "invalid volatile use of %qD inside transaction",
- *tp);
+ if (d->block_flags & DIAG_TM_SAFE)
+ error_at (gimple_location (d->stmt),
+ "invalid use of volatile lvalue inside transaction");
+ else if (d->func_flags & DIAG_TM_SAFE)
+ error_at (gimple_location (d->stmt),
+ "invalid use of volatile lvalue inside %<transaction_safe%>"
+ "function");
}
return NULL_TREE;
@@ -4300,7 +4305,7 @@ ipa_tm_scan_irr_block (basic_block bb)
{
tree lhs = gimple_assign_lhs (stmt);
tree rhs = gimple_assign_rhs1 (stmt);
- if (volatile_var_p (lhs) || volatile_var_p (rhs))
+ if (volatile_lvalue_p (lhs) || volatile_lvalue_p (rhs))
return true;
}
break;
@@ -4308,7 +4313,7 @@ ipa_tm_scan_irr_block (basic_block bb)
case GIMPLE_CALL:
{
tree lhs = gimple_call_lhs (stmt);
- if (lhs && volatile_var_p (lhs))
+ if (lhs && volatile_lvalue_p (lhs))
return true;
if (is_tm_pure_call (stmt))