This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [gomp] Fix multiple threadprivate declarations (PR 24455)


On Thursday 20 October 2005 23:16, Daniel Berlin wrote:

> VAR_DECL is derived from struct tree_decl_with_vis, which has 11 empty
> bits if you needed them.
>
OK, thanks.

Richard, how about this version?  It adds a bitfield in tree_decl_with_vis 
that can be shared by C and C++.  It also fixes the hackery you had 
pointed out before in the merge code.

I tried adding the same error messages to the C++ front end but ran into 
more trouble than I could handle.  We fail g++.dg/tls/diag-1.C because:

struct A {
  static __thread int i;
};

__thread int A::i = 42;

that triggers the error message.  The 'i' inside struct A was marked with 
TLS_NONE while the 'i' in the A::i was marked with TLS_MODEL_LOCAL_EXEC.  
Perhaps I didn't place the check in the right spot, but I was getting lost 
in the C++ FE and this wasn't directly related to the bug I'm fixing.  So, 
I will leave this up to a C++ maintainer to deal with.

Thanks.
2005-10-21  Diego Novillo  <dnovillo@redhat.com>

gcc/
	PR 24455
	* tree.h (struct tree_decl_with_vis): Add bitfield
	threadprivate_p.
	(DECL_THREADPRIVATE_P): Define.
	* c-parser.c (c_parser_omp_threadprivate): Set it. 
	Do not error out if DECL_THREADPRIVATE_P is set already.
	* c-decl.c (diagnose_mismatched_decls): Do not diagnose TLS
	decls marked with #pragma omp threadprivate.
	(merge_decls): Merge DECL_THREADPRIVATE_P.

gcc/cp/
	PR 24455
	* decl.c (duplicate_decls): Merge DECL_THREADPRIVATE_P.
	* semantics.c (finish_omp_threadprivate): Set
	DECL_THREADPRIVATE_P.
	Do not error out if DECL_THREADPRIVATE_P is set already.

libgomp/
	PR 24455
	* testsuite/libgomp.c++/pr24455-1.C: New test.
	* testsuite/libgomp.c++/pr24455.C: New test.
	* testsuite/libgomp.dg/pr24455-1.c: New test.
	* testsuite/libgomp.dg/pr24455.c: New test.


Index: gcc/c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.662.4.12
diff -d -u -p -r1.662.4.12 c-decl.c
--- gcc/c-decl.c	9 Oct 2005 01:01:21 -0000	1.662.4.12
+++ gcc/c-decl.c	21 Oct 2005 04:00:12 -0000
@@ -1383,8 +1383,11 @@ diagnose_mismatched_decls (tree newdecl,
   else if (TREE_CODE (newdecl) == VAR_DECL)
     {
       /* Only variables can be thread-local, and all declarations must
-	 agree on this property.  */
-      if (DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl))
+	 agree on this property.  If OLDDECL had been declared
+	 threadprivate, then it need not be marked again, so this
+	 check is unnecessary.  */
+      if (DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl)
+	  && !DECL_THREADPRIVATE_P (olddecl))
 	{
 	  if (DECL_THREAD_LOCAL_P (newdecl))
 	    error ("thread-local declaration of %q+D follows "
@@ -1671,6 +1674,13 @@ merge_decls (tree newdecl, tree olddecl,
    if (DECL_INITIAL (newdecl) == 0)
     DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
 
+  /* Merge the threadprivate attribute.  */
+  if (TREE_CODE (olddecl) == VAR_DECL && DECL_THREADPRIVATE_P (olddecl))
+    {
+      DECL_TLS_MODEL (newdecl) = DECL_TLS_MODEL (olddecl);
+      DECL_THREADPRIVATE_P (newdecl) = 1;
+    }
+
    if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS))
      {
        /* Merge the unused-warning information.  */
Index: gcc/c-parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-parser.c,v
retrieving revision 2.17.4.36
diff -d -u -p -r2.17.4.36 c-parser.c
--- gcc/c-parser.c	20 Oct 2005 09:02:08 -0000	2.17.4.36
+++ gcc/c-parser.c	21 Oct 2005 04:00:13 -0000
@@ -7694,10 +7694,15 @@ c_parser_omp_threadprivate (c_parser *pa
     {
       tree v = TREE_PURPOSE (t);
 
-      if (TREE_USED (v))
+      /* If V had already been marked threadprivate, it doesn't matter
+	 whether it had been used prior to this point.  */
+      if (TREE_USED (v) && !DECL_THREADPRIVATE_P (v))
 	error ("%qE declared %<threadprivate%> after first use", v);
       else
-	DECL_TLS_MODEL (v) = decl_default_tls_model (v);
+	{
+	  DECL_TLS_MODEL (v) = decl_default_tls_model (v);
+	  DECL_THREADPRIVATE_P (v) = 1;
+	}
     }
 
   c_parser_skip_to_pragma_eol (parser);
Index: gcc/tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.735.4.23
diff -d -u -p -r1.735.4.23 tree.h
--- gcc/tree.h	20 Oct 2005 09:02:09 -0000	1.735.4.23
+++ gcc/tree.h	21 Oct 2005 04:00:14 -0000
@@ -2497,6 +2497,11 @@ struct tree_parm_decl GTY(())
 /* Used to indicate that the DECL is a dllimport.  */
 #define DECL_DLLIMPORT_P(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.dllimport_flag)
 
+/* Record whether a variable has been declared threadprivate by
+   #pragma omp threadprivate.  */
+#define DECL_THREADPRIVATE_P(DECL) \
+  VAR_DECL_CHECK (DECL)->decl_with_vis.threadprivate_p
+
 /* DECL_BASED_ON_RESTRICT_P records whether a VAR_DECL is a temporary
    based on a variable with a restrict qualified type.  If it is,
    DECL_RESTRICT_BASE returns the restrict qualified variable on which
@@ -2590,6 +2595,7 @@ struct tree_decl_with_vis GTY(())
  unsigned based_on_restrict_p : 1;
  /* Used by C++.  Might become a generic decl flag.  */
  unsigned shadowed_for_var_p : 1;
+ unsigned threadprivate_p : 1;
  
  /* Don't belong to VAR_DECL exclusively.  */
  unsigned in_system_header_flag : 1;
Index: gcc/cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1403.4.9
diff -d -u -p -r1.1403.4.9 decl.c
--- gcc/cp/decl.c	17 Oct 2005 00:40:49 -0000	1.1403.4.9
+++ gcc/cp/decl.c	21 Oct 2005 04:00:17 -0000
@@ -1546,6 +1546,13 @@ duplicate_decls (tree newdecl, tree oldd
 	    |= DECL_NONTRIVIALLY_INITIALIZED_P (olddecl);
 	  DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
 	    |= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
+
+	  /* Merge the threadprivate attribute from OLDDECL into NEWDECL.  */
+	  if (DECL_THREADPRIVATE_P (olddecl))
+	    {
+	      DECL_TLS_MODEL (newdecl) = DECL_TLS_MODEL (olddecl);
+	      DECL_THREADPRIVATE_P (newdecl) = 1;
+	    }
 	}
 
       /* Do this after calling `merge_types' so that default
Index: gcc/cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.475.4.12
diff -d -u -p -r1.475.4.12 semantics.c
--- gcc/cp/semantics.c	20 Oct 2005 09:54:19 -0000	1.475.4.12
+++ gcc/cp/semantics.c	21 Oct 2005 04:00:18 -0000
@@ -3534,10 +3534,15 @@ finish_omp_threadprivate (tree vars)
     {
       tree v = TREE_PURPOSE (t);
 
-      if (TREE_USED (v))
+      /* If V had already been marked threadprivate, it doesn't matter
+	 whether it had been used prior to this point.  */
+      if (TREE_USED (v) && !DECL_THREADPRIVATE_P (v))
 	error ("%qE declared %<threadprivate%> after first use", v);
       else
-	DECL_TLS_MODEL (v) = decl_default_tls_model (v);
+	{
+	  DECL_TLS_MODEL (v) = decl_default_tls_model (v);
+	  DECL_THREADPRIVATE_P (v) = 1;
+	}
     }
 }
 
Index: libgomp/testsuite/libgomp.c++/pr24455-1.C
===================================================================
RCS file: libgomp/testsuite/libgomp.c++/pr24455-1.C
diff -N libgomp/testsuite/libgomp.c++/pr24455-1.C
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libgomp/testsuite/libgomp.c++/pr24455-1.C	21 Oct 2005 04:00:20 -0000
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+extern int i;
+#pragma omp threadprivate (i)
+
+int i;
Index: libgomp/testsuite/libgomp.c++/pr24455.C
===================================================================
RCS file: libgomp/testsuite/libgomp.c++/pr24455.C
diff -N libgomp/testsuite/libgomp.c++/pr24455.C
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libgomp/testsuite/libgomp.c++/pr24455.C	21 Oct 2005 04:00:20 -0000
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-additional-sources pr24455-1.C } */
+
+extern "C" void abort (void);
+
+extern int i;
+#pragma omp threadprivate(i)
+
+int main()
+{
+  i = 0;
+
+#pragma omp parallel default(none) num_threads(10)
+    {
+      i++;
+#pragma omp barrier
+      if (i != 1)
+	abort ();
+    }
+
+    return 0;
+}
Index: libgomp/testsuite/libgomp.dg/pr24455-1.c
===================================================================
RCS file: libgomp/testsuite/libgomp.dg/pr24455-1.c
diff -N libgomp/testsuite/libgomp.dg/pr24455-1.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libgomp/testsuite/libgomp.dg/pr24455-1.c	21 Oct 2005 04:00:20 -0000
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+extern int i;
+#pragma omp threadprivate (i)
+
+int i;
Index: libgomp/testsuite/libgomp.dg/pr24455.c
===================================================================
RCS file: libgomp/testsuite/libgomp.dg/pr24455.c
diff -N libgomp/testsuite/libgomp.dg/pr24455.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libgomp/testsuite/libgomp.dg/pr24455.c	21 Oct 2005 04:00:20 -0000
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-additional-sources pr24455-1.c } */
+
+extern void abort (void);
+
+extern int i;
+#pragma omp threadprivate(i)
+
+int main()
+{
+  i = 0;
+
+#pragma omp parallel default(none) num_threads(10)
+    {
+      i++;
+#pragma omp barrier
+      if (i != 1)
+	abort ();
+    }
+
+    return 0;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]