--- gcc/cp/semantics.c.jj	2011-05-25 16:30:03.000000000 +0200
+++ gcc/cp/semantics.c	2011-05-30 13:33:08.000000000 +0200
@@ -4041,12 +4041,13 @@ finish_omp_clauses (tree clauses)
 	  break;
 	}
 
-      if (need_complete_non_reference)
+      if (need_complete_non_reference || need_copy_assignment)
 	{
 	  t = require_complete_type (t);
 	  if (t == error_mark_node)
 	    remove = true;
-	  else if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
+	  else if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE
+		   && need_complete_non_reference)
 	    {
 	      error ("%qE has reference type for %qs", t, name);
 	      remove = true;
@@ -4088,6 +4090,7 @@ finish_omp_clauses (tree clauses)
 	 Save the results, because later we won't be in the right context
 	 for making these queries.  */
       if (CLASS_TYPE_P (inner_type)
+	  && COMPLETE_TYPE_P (inner_type)
 	  && (need_default_ctor || need_copy_ctor || need_copy_assignment)
 	  && !type_dependent_expression_p (t)
 	  && cxx_omp_create_clause_info (c, inner_type, need_default_ctor,
--- gcc/testsuite/g++.dg/gomp/pr49223-1.C.jj	2011-05-30 13:38:40.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/pr49223-1.C	2011-05-30 13:38:08.000000000 +0200
@@ -0,0 +1,28 @@
+// PR c++/49223
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+template <int N>
+struct V
+{
+  V () {}
+  ~V () {}
+};
+
+template <int N>
+struct S
+{
+  void foo ()
+  {
+    V <0> v;
+    #pragma omp parallel private (v)
+      ;
+  }
+};
+
+void
+bar (void)
+{
+  S <0> s;
+  s.foo ();
+}
--- gcc/testsuite/g++.dg/gomp/pr49223-2.C.jj	2011-05-30 13:40:59.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/pr49223-2.C	2011-05-30 13:46:05.000000000 +0200
@@ -0,0 +1,16 @@
+// PR c++/49223
+// { dg-do compile }
+// { dg-require-effective-target tls }
+// { dg-options "-fopenmp" }
+
+struct S;			// { dg-error "forward declaration" }
+extern __thread struct S s;	// { dg-error "has incomplete type" }
+struct T;
+extern __thread struct T t;
+
+void
+foo ()
+{
+  #pragma omp parallel copyin (s)
+    ;
+}
