This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] [Annotalysis] Add support for arrays in lock expressions
- From: Delesley Hutchins <delesley at google dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>, Diego Novillo <dnovillo at google dot com>, Ollie Wild <aaw at google dot com>
- Date: Thu, 3 Nov 2011 11:20:54 -0700
- Subject: [PATCH] [Annotalysis] Add support for arrays in lock expressions
This patch adds support for array indexing (i.e. operator []) in lock
expressions. The current version of gcc seems to emit these as
expressions involving pointer arithmetic, so we update
get_canonical_lock_expr() to handle such expressions.
Bootstrapped and passed gcc regression testsuite on
x86_64-unknown-linux-gnu. Okay for google/gcc-4_6?
-DeLesley
Changelog.google-4_6:
2011-11-03 DeLesley Hutchins <delesley@google.com>
* tree-threadsafe-analyze.c (get_canonical_lock_expr):
Add support for pointer arithmetic operations
testsuite/Changelog.google-4_6:
2011-11-02 DeLesley Hutchins <delesley@google.com>
* g++.dg/thread-ann/thread_annot_lock-84.C:
New regression test.
--
DeLesley Hutchins | Software Engineer | delesley@google.com | 505-206-0315
Index: testsuite/g++.dg/thread-ann/thread_annot_lock-84.C
===================================================================
--- testsuite/g++.dg/thread-ann/thread_annot_lock-84.C (revision 0)
+++ testsuite/g++.dg/thread-ann/thread_annot_lock-84.C (revision 0)
@@ -0,0 +1,29 @@
+// Test lock expressions involving array elements.
+// { dg-do compile }
+// { dg-options "-Wthread-safety" }
+
+#include "thread_annot_common.h"
+
+struct Foo {
+ Mutex mu_;
+ int a GUARDED_BY(mu_);
+
+ static void foo1(Foo* foos, int n);
+ static void foo2(Foo* foos, int n);
+};
+
+void Foo::foo1(Foo* foos, int n) {
+ for (int i = 0; i < n; ++i) {
+ foos[i].mu_.Lock();
+ foos[i].a = 0;
+ foos[i].mu_.Unlock();
+ }
+}
+
+void Foo::foo2(Foo* foos, int n) {
+ for (int i = 0; i < n-1; ++i) {
+ foos[i].mu_.Lock();
+ foos[i+1].a = 0; // { dg-warning "Writing to variable" }
+ foos[i].mu_.Unlock();
+ }
+}
Index: tree-threadsafe-analyze.c
===================================================================
--- tree-threadsafe-analyze.c (revision 180716)
+++ tree-threadsafe-analyze.c (working copy)
@@ -79,6 +79,7 @@ along with GCC; see the file COPYING3.
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "gimple.h"
#include "c-family/c-common.h"
#include "toplev.h"
#include "input.h"
@@ -804,12 +805,27 @@ get_canonical_lock_expr (tree lock, tree
&& !gimple_nop_p (SSA_NAME_DEF_STMT (lock)))
{
gimple def_stmt = SSA_NAME_DEF_STMT (lock);
- if (is_gimple_assign (def_stmt)
- && (get_gimple_rhs_class (gimple_assign_rhs_code (def_stmt))
- == GIMPLE_SINGLE_RHS))
- return get_canonical_lock_expr (gimple_assign_rhs1 (def_stmt),
- base_obj, is_temp_expr,
- NULL_TREE);
+ if (is_gimple_assign (def_stmt))
+ {
+ enum gimple_rhs_class gcls =
+ get_gimple_rhs_class (gimple_assign_rhs_code (def_stmt));
+ tree rhs = 0;
+
+ if (gcls == GIMPLE_SINGLE_RHS)
+ rhs = gimple_assign_rhs1 (def_stmt);
+ else if (gcls == GIMPLE_UNARY_RHS)
+ rhs = build1 (gimple_assign_rhs_code (def_stmt),
+ TREE_TYPE (gimple_assign_lhs (def_stmt)),
+ gimple_assign_rhs1 (def_stmt));
+ else if (gcls == GIMPLE_BINARY_RHS)
+ rhs = build2 (gimple_assign_rhs_code (def_stmt),
+ TREE_TYPE (gimple_assign_lhs (def_stmt)),
+ gimple_assign_rhs1 (def_stmt),
+ gimple_assign_rhs2 (def_stmt));
+ if (rhs)
+ return get_canonical_lock_expr (rhs, base_obj,
+ is_temp_expr, NULL_TREE);
+ }
else if (is_gimple_call (def_stmt))
{
tree fdecl = gimple_call_fndecl (def_stmt);
@@ -981,6 +997,24 @@ get_canonical_lock_expr (tree lock, tree
TREE_TYPE (TREE_TYPE (canon_base)), canon_base);
break;
}
+ case PLUS_EXPR:
+ case POINTER_PLUS_EXPR:
+ case MULT_EXPR:
+ {
+ tree left = TREE_OPERAND (lock, 0);
+ tree canon_left = get_canonical_lock_expr (left, base_obj,
+ true /* is_temp_expr */,
+ NULL_TREE);
+
+ tree right = TREE_OPERAND (lock, 1);
+ tree canon_right = get_canonical_lock_expr (right, base_obj,
+ true /* is_temp_expr */,
+ NULL_TREE);
+ if (left != canon_left || right != canon_right)
+ lock = build2 (TREE_CODE(lock), TREE_TYPE(lock),
+ canon_left, canon_right);
+ break;
+ }
default:
break;
}