This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix #pragma omp atomic in templates (PR c++/33894)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Jason Merrill <jason at redhat dot com>, Richard Henderson <rth at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org, Paolo Bonzini <bonzini at gnu dot org>
- Date: Fri, 26 Oct 2007 15:37:40 -0400
- Subject: [PATCH] Fix #pragma omp atomic in templates (PR c++/33894)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
The
2007-02-05 Paolo Bonzini <bonzini@gnu.org>
* cp-tree.h (OMP_ATOMIC_CODE): Delete.
(OMP_ATOMIC_DEPENDENT_P): Rewrite.
* pt.c (tsubst_expr): Adjust for new format of dependent OMP_ATOMIC
expressions.
* semantics.c (finish_omp_atomic): Store a whole expression node
in operand 1, and integer_zero_node in operand 0, for dependent
OMP_ATOMIC. Rewrite to make flow easier to understand.
patch broke #pragma omp atomic in templates if not type dependent.
Before that change if #pragma omp atomic was seen in a template,
but neither lhs nor rhs was type dependent, g++ called c_finish_omp_atomic
on build_non_dependent_expr guarded arguments to diagnose broken usage
in templates and if that returned error_mark_node, would just remove it.
But if that call succeeded, it created OMP_ATOMIC_DEPENDENT_P OMP_ATOMIC
anyway.
After this patch it just sticks a normal OMP_ATOMIC into the template
body, but the arguments are possibly NON_DEPENDENT_EXPRs.
Furthermore the changed pt.c just threw all non-OMP_ATOMIC_DEPENDENT_P
OMP_ATOMIC statements on the floor.
The following patch fixes this by reverting to the old handling, except
for a different representation of OMP_ATOMIC_DEPENDENT_P OMP_ATOMIC.
Ok for trunk?
2007-10-26 Jakub Jelinek <jakub@redhat.com>
PR c++/33894
* cp-tree.h: Update comment - TYPE_LANG_FLAG_0 is not
OMP_ATOMIC_DEPENDENT_P in OMP_ATOMIC.
* pt.c (tsubst_expr): Assert OMP_ATOMIC_DEPENDENT_P.
* semantics.c (finish_omp_atomic): Revert most of the
2007-02-05 changes, just keep the new representation of
OMP_ATOMIC_DEPENDENT_P OMP_ATOMIC.
* testsuite/libgomp.c++/atomic-1.C: New test.
--- gcc/cp/cp-tree.h.jj 2007-10-26 13:45:43.000000000 +0200
+++ gcc/cp/cp-tree.h 2007-10-26 19:34:47.000000000 +0200
@@ -53,7 +53,6 @@ struct diagnostic_info;
TYPENAME_IS_ENUM_P (in TYPENAME_TYPE)
REFERENCE_REF_P (in INDIRECT_EXPR)
QUALIFIED_NAME_IS_TEMPLATE (in SCOPE_REF)
- OMP_ATOMIC_DEPENDENT_P (in OMP_ATOMIC)
OMP_FOR_GIMPLIFYING_P (in OMP_FOR)
BASELINK_QUALIFIED_P (in BASELINK)
TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR)
--- gcc/cp/pt.c.jj 2007-10-22 21:08:38.000000000 +0200
+++ gcc/cp/pt.c 2007-10-26 21:14:11.000000000 +0200
@@ -10302,13 +10302,13 @@ tsubst_expr (tree t, tree args, tsubst_f
break;
case OMP_ATOMIC:
- if (OMP_ATOMIC_DEPENDENT_P (t))
- {
- tree op1 = TREE_OPERAND (t, 1);
- tree lhs = RECUR (TREE_OPERAND (op1, 0));
- tree rhs = RECUR (TREE_OPERAND (op1, 1));
- finish_omp_atomic (TREE_CODE (op1), lhs, rhs);
- }
+ gcc_assert (OMP_ATOMIC_DEPENDENT_P (t));
+ {
+ tree op1 = TREE_OPERAND (t, 1);
+ tree lhs = RECUR (TREE_OPERAND (op1, 0));
+ tree rhs = RECUR (TREE_OPERAND (op1, 1));
+ finish_omp_atomic (TREE_CODE (op1), lhs, rhs);
+ }
break;
case EXPR_PACK_EXPANSION:
--- gcc/cp/semantics.c.jj 2007-10-22 04:38:45.000000000 +0200
+++ gcc/cp/semantics.c 2007-10-26 20:56:26.000000000 +0200
@@ -3909,28 +3909,38 @@ finish_omp_for (location_t locus, tree d
void
finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
{
+ tree orig_lhs;
+ tree orig_rhs;
+ bool dependent_p;
tree stmt;
- if (processing_template_decl
- && (type_dependent_expression_p (lhs)
- || type_dependent_expression_p (rhs)))
- stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node,
- build2 (code, void_type_node, lhs, rhs));
- else
+ orig_lhs = lhs;
+ orig_rhs = rhs;
+ dependent_p = false;
+ stmt = NULL_TREE;
+
+ /* Even in a template, we can detect invalid uses of the atomic
+ pragma if neither LHS nor RHS is type-dependent. */
+ if (processing_template_decl)
{
- /* Even in a template, we can detect invalid uses of the atomic
- pragma if neither LHS nor RHS is type-dependent. */
- if (processing_template_decl)
+ dependent_p = (type_dependent_expression_p (lhs)
+ || type_dependent_expression_p (rhs));
+ if (!dependent_p)
{
lhs = build_non_dependent_expr (lhs);
rhs = build_non_dependent_expr (rhs);
}
-
+ }
+ if (!dependent_p)
+ {
stmt = c_finish_omp_atomic (code, lhs, rhs);
+ if (stmt == error_mark_node)
+ return;
}
-
- if (stmt != error_mark_node)
- add_stmt (stmt);
+ if (processing_template_decl)
+ stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node,
+ build2 (code, void_type_node, orig_lhs, orig_rhs));
+ add_stmt (stmt);
}
void
--- libgomp/testsuite/libgomp.c++/atomic-1.C.jj 2007-10-26 19:35:58.000000000 +0200
+++ libgomp/testsuite/libgomp.c++/atomic-1.C 2007-10-26 19:42:25.000000000 +0200
@@ -0,0 +1,53 @@
+// PR c++/33894
+// { dg-do run }
+// { dg-options "-O2" }
+
+extern "C" void abort ();
+
+int check;
+
+template<typename T> void
+foo ()
+{
+ #pragma omp atomic
+ check |= sizeof (T);
+}
+
+template<typename T> void
+bar (T *x, T y)
+{
+ #pragma omp atomic
+ *x += y;
+}
+
+template<typename T> void
+baz ()
+{
+ #pragma omp atomic
+ check++;
+}
+
+int
+main ()
+{
+ int i = 0;
+ long l = 0;
+
+ check = 0;
+ foo<char> ();
+ if (check != sizeof (char))
+ abort ();
+ foo<short> ();
+ if (check != (sizeof (char) | sizeof (short)))
+ abort ();
+ bar(&i, 4);
+ bar(&l, 8L);
+ if (i != 4 || l != 8L)
+ abort ();
+ baz<char> ();
+ if (check != (sizeof (char) | sizeof (short)) + 1)
+ abort ();
+ baz<long double> ();
+ if (check != (sizeof (char) | sizeof (short)) + 2)
+ abort ();
+}
Jakub