--- gcc/c/c-typeck.c.jj	2013-10-08 08:45:30.000000000 +0200
+++ gcc/c/c-typeck.c	2013-10-10 15:08:08.347366495 +0200
@@ -10865,8 +10865,8 @@ handle_omp_array_sections_1 (tree c, tre
 	      || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE))
 	{
 	  error_at (OMP_CLAUSE_LOCATION (c),
-		    "for unknown bound array type length expression is "
-		    "not optional");
+		    "for unknown bound array type length expression must "
+		    "be specified");
 	  return error_mark_node;
 	}
       if (TREE_CODE (low_bound) == INTEGER_CST
@@ -10970,7 +10970,7 @@ handle_omp_array_sections_1 (tree c, tre
       if (length == NULL_TREE)
 	{
 	  error_at (OMP_CLAUSE_LOCATION (c),
-		    "for pointer type length expression is not optional");
+		    "for pointer type length expression must be specified");
 	  return error_mark_node;
 	}
       /* If there is a pointer type anywhere but in the very first
@@ -11400,7 +11400,8 @@ c_finish_omp_clauses (tree clauses)
 	      && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE)
 	    {
 	      error_at (OMP_CLAUSE_LOCATION (c),
-			"linear clause applied to non-integral non-pointer");
+			"linear clause applied to non-integral non-pointer "
+			"variable with type %qT", TREE_TYPE (t));
 	      remove = true;
 	      break;
 	    }
--- gcc/c/c-parser.c.jj	2013-09-25 09:51:45.000000000 +0200
+++ gcc/c/c-parser.c	2013-10-10 15:51:24.055946648 +0200
@@ -12388,6 +12388,8 @@ c_finish_omp_declare_simd (c_parser *par
       tree c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
 					 "#pragma omp declare simd");
       c = c_omp_declare_simd_clauses_to_numbers (parms, c);
+      if (c != NULL_TREE)
+	c = tree_cons (NULL_TREE, c, NULL_TREE);
       c = build_tree_list (get_identifier ("omp declare simd"), c);
       TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
       DECL_ATTRIBUTES (fndecl) = c;
--- gcc/cp/decl.c.jj	2013-10-09 17:41:58.000000000 +0200
+++ gcc/cp/decl.c	2013-10-10 15:50:41.097173300 +0200
@@ -7658,9 +7658,16 @@ grokfndecl (tree ctype,
 	      if (TREE_CODE (type) == METHOD_TYPE)
 		walk_tree (&TREE_VALUE (attr), declare_simd_adjust_this,
 			   DECL_ARGUMENTS (decl), NULL);
-	      TREE_VALUE (attr)
-		= c_omp_declare_simd_clauses_to_numbers (DECL_ARGUMENTS (decl),
-							 TREE_VALUE (attr));
+	      if (TREE_VALUE (attr) != NULL_TREE)
+		{
+		  tree cl = TREE_VALUE (TREE_VALUE (attr));
+		  cl = c_omp_declare_simd_clauses_to_numbers
+						(DECL_ARGUMENTS (decl), cl);
+		  if (cl)
+		    TREE_VALUE (TREE_VALUE (attr)) = cl;
+		  else
+		    TREE_VALUE (attr) = NULL_TREE;
+		}
 	    }
 	}
     }
--- gcc/cp/parser.c.jj	2013-10-10 10:06:22.000000000 +0200
+++ gcc/cp/parser.c	2013-10-10 15:28:41.225994083 +0200
@@ -29816,6 +29816,8 @@ cp_parser_late_parsing_omp_declare_simd
       cl = cp_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
 				      "#pragma omp declare simd", pragma_tok);
       cp_parser_pop_lexer (parser);
+      if (cl)
+	cl = tree_cons (NULL_TREE, cl, NULL_TREE);
       c = build_tree_list (get_identifier ("omp declare simd"), cl);
       TREE_CHAIN (c) = attrs;
       if (processing_template_decl)
@@ -29837,7 +29839,7 @@ static void
 cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok)
 {
   cp_parser_skip_to_pragma_eol (parser, pragma_tok);
-  current_omp_declare_target_attribute++;
+  scope_chain->omp_declare_target_attribute++;
 }
 
 static void
@@ -29874,12 +29876,12 @@ cp_parser_omp_end_declare_target (cp_par
       return;
     }
   cp_parser_skip_to_pragma_eol (parser, pragma_tok);
-  if (!current_omp_declare_target_attribute)
+  if (!scope_chain->omp_declare_target_attribute)
     error_at (pragma_tok->location,
 	      "%<#pragma omp end declare target%> without corresponding "
 	      "%<#pragma omp declare target%>");
   else
-    current_omp_declare_target_attribute--;
+    scope_chain->omp_declare_target_attribute--;
 }
 
 /* Helper function of cp_parser_omp_declare_reduction.  Parse the combiner
--- gcc/cp/pt.c.jj	2013-10-07 23:29:44.000000000 +0200
+++ gcc/cp/pt.c	2013-10-10 15:48:34.153821267 +0200
@@ -8593,14 +8593,18 @@ apply_late_template_attributes (tree *de
 				     get_attribute_name (t))
 		  && TREE_VALUE (t))
 		{
-		  tree clauses = TREE_VALUE (t);
+		  tree clauses = TREE_VALUE (TREE_VALUE (t));
 		  clauses = tsubst_omp_clauses (clauses, true, args,
 						complain, in_decl);
 		  c_omp_declare_simd_clauses_to_decls (*decl_p, clauses);
 		  clauses = finish_omp_clauses (clauses);
 		  tree parms = DECL_ARGUMENTS (*decl_p);
-		  TREE_VALUE (t)
+		  clauses
 		    = c_omp_declare_simd_clauses_to_numbers (parms, clauses);
+		  if (clauses)
+		    TREE_VALUE (TREE_VALUE (t)) = clauses;
+		  else
+		    TREE_VALUE (t) = NULL_TREE;
 		}
 	      /* If the first attribute argument is an identifier, don't
 		 pass it through tsubst.  Attributes like mode, format,
--- gcc/cp/cp-tree.h.jj	2013-09-25 09:51:45.000000000 +0200
+++ gcc/cp/cp-tree.h	2013-10-10 14:55:10.784413598 +0200
@@ -1037,6 +1037,7 @@ struct GTY(()) saved_scope {
 
   int unevaluated_operand;
   int inhibit_evaluation_warnings;
+  int omp_declare_target_attribute;
 
   struct stmt_tree_s x_stmt_tree;
 
@@ -4433,10 +4434,6 @@ extern GTY(()) vec<tree, va_gc> *local_c
 
 extern int at_eof;
 
-/* If non-zero, implicit "omp declare target" attribute is added into the
-   attribute lists.  */
-extern GTY(()) int current_omp_declare_target_attribute;
-
 /* A list of namespace-scope objects which have constructors or
    destructors which reside in the global scope.  The decl is stored
    in the TREE_VALUE slot and the initializer is stored in the
--- gcc/cp/cp-gimplify.c.jj	2013-10-07 23:29:44.000000000 +0200
+++ gcc/cp/cp-gimplify.c	2013-10-10 10:16:00.413080072 +0200
@@ -936,6 +936,9 @@ cp_genericize_r (tree *stmt_p, int *walk
 	  *walk_subtrees = 0;
 	break;
       case OMP_CLAUSE_REDUCTION:
+	/* Don't dereference an invisiref in reduction clause's
+	   OMP_CLAUSE_DECL either.  OMP_CLAUSE_REDUCTION_{INIT,MERGE}
+	   still needs to be genericized.  */
 	if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
 	  {
 	    *walk_subtrees = 0;
--- gcc/cp/decl2.c.jj	2013-10-10 10:07:16.000000000 +0200
+++ gcc/cp/decl2.c	2013-10-10 15:25:06.130091601 +0200
@@ -101,10 +101,6 @@ static GTY(()) vec<tree, va_gc> *no_link
 /* Nonzero if we're done parsing and into end-of-file activities.  */
 
 int at_eof;
-
-/* If non-zero, implicit "omp declare target" attribute is added into the
-   attribute lists.  */
-int current_omp_declare_target_attribute;
 
 
 /* Return a member function type (a METHOD_TYPE), given FNTYPE (a
@@ -1138,7 +1134,7 @@ is_late_template_attribute (tree attr, t
   if (is_attribute_p ("unused", name))
     return false;
 
-  /* #pragma omp declare simd attribute needs to be always finalized.  */
+  /* #pragma omp declare simd attribute needs to be always deferred.  */
   if (flag_openmp
       && is_attribute_p ("omp declare simd", name))
     return true;
@@ -1335,9 +1331,6 @@ cp_check_const_attributes (tree attribut
   for (attr = attributes; attr; attr = TREE_CHAIN (attr))
     {
       tree arg;
-      if (TREE_VALUE (attr) == NULL_TREE
-	  || TREE_CODE (TREE_VALUE (attr)) != TREE_LIST)
-	continue;
       for (arg = TREE_VALUE (attr); arg; arg = TREE_CHAIN (arg))
 	{
 	  tree expr = TREE_VALUE (arg);
@@ -1385,16 +1378,16 @@ cplus_decl_attributes (tree *decl, tree
     return;
 
   /* Add implicit "omp declare target" attribute if requested.  */
-  if (current_omp_declare_target_attribute
+  if (scope_chain->omp_declare_target_attribute
       && ((TREE_CODE (*decl) == VAR_DECL && TREE_STATIC (*decl))
 	  || TREE_CODE (*decl) == FUNCTION_DECL))
     {
       if (TREE_CODE (*decl) == VAR_DECL
-	  && RECORD_OR_UNION_CODE_P (TREE_CODE (CP_DECL_CONTEXT (*decl))))
+	  && DECL_CLASS_SCOPE_P (*decl))
 	error ("%q+D static data member inside of declare target directive",
 	       *decl);
       else if (TREE_CODE (*decl) == VAR_DECL
-	       && (TREE_CODE (CP_DECL_CONTEXT (*decl)) == FUNCTION_DECL
+	       && (DECL_FUNCTION_SCOPE_P (*decl)
 		   || (current_function_decl && !DECL_EXTERNAL (*decl))))
 	error ("%q+D in block scope inside of declare target directive",
 	       *decl);
--- gcc/cp/semantics.c.jj	2013-10-09 19:10:23.000000000 +0200
+++ gcc/cp/semantics.c	2013-10-10 16:31:39.718584627 +0200
@@ -4199,8 +4199,8 @@ handle_omp_array_sections_1 (tree c, tre
 	      || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE))
 	{
 	  error_at (OMP_CLAUSE_LOCATION (c),
-		    "for unknown bound array type length expression is "
-		    "not optional");
+		    "for unknown bound array type length expression must "
+		    "be specified");
 	  return error_mark_node;
 	}
       if (TREE_CODE (low_bound) == INTEGER_CST
@@ -4304,7 +4304,7 @@ handle_omp_array_sections_1 (tree c, tre
       if (length == NULL_TREE)
 	{
 	  error_at (OMP_CLAUSE_LOCATION (c),
-		    "for pointer type length expression is not optional");
+		    "for pointer type length expression must be specified");
 	  return error_mark_node;
 	}
       /* If there is a pointer type anywhere but in the very first
@@ -5034,17 +5034,15 @@ finish_omp_reduction_clause (tree c, boo
 	      tree omp_in = convert_from_reference (OMP_CLAUSE_DECL (c));
 	      if (need_static_cast)
 		{
-		  tree ptype = build_pointer_type (atype);
-		  omp_out = build_fold_addr_expr (omp_out);
-		  omp_out = build_static_cast (ptype, omp_out,
+		  tree rtype = build_reference_type (atype);
+		  omp_out = build_static_cast (rtype, omp_out,
 					       tf_warning_or_error);
-		  omp_in = build_fold_addr_expr (omp_in);
-		  omp_in = build_static_cast (ptype, omp_in,
+		  omp_in = build_static_cast (rtype, omp_in,
 					      tf_warning_or_error);
 		  if (omp_out == error_mark_node || omp_in == error_mark_node)
 		    return true;
-		  omp_out = build1 (INDIRECT_REF, atype, omp_out);
-		  omp_in = build1 (INDIRECT_REF, atype, omp_in);
+		  omp_out = convert_from_reference (omp_out);
+		  omp_in = convert_from_reference (omp_in);
 		}
 	      OMP_CLAUSE_REDUCTION_MERGE (c)
 		= clone_omp_udr (stmts[2], DECL_EXPR_DECL (stmts[0]),
@@ -5069,18 +5067,16 @@ finish_omp_reduction_clause (tree c, boo
 				"initializer for base class %qT", atype);
 		      return true;
 		    }
-		  tree ptype = build_pointer_type (atype);
-		  omp_priv = build_fold_addr_expr (omp_priv);
-		  omp_priv = build_static_cast (ptype, omp_priv,
+		  tree rtype = build_reference_type (atype);
+		  omp_priv = build_static_cast (rtype, omp_priv,
 						tf_warning_or_error);
-		  omp_orig = build_fold_addr_expr (omp_orig);
-		  omp_orig = build_static_cast (ptype, omp_orig,
+		  omp_orig = build_static_cast (rtype, omp_orig,
 						tf_warning_or_error);
 		  if (omp_priv == error_mark_node
 		      || omp_orig == error_mark_node)
 		    return true;
-		  omp_priv = build1 (INDIRECT_REF, atype, omp_priv);
-		  omp_orig = build1 (INDIRECT_REF, atype, omp_orig);
+		  omp_priv = convert_from_reference (omp_priv);
+		  omp_orig = convert_from_reference (omp_orig);
 		}
 	      if (i == 6)
 		*need_default_ctor = true;
@@ -5161,7 +5157,8 @@ finish_omp_clauses (tree clauses)
 	      && !INTEGRAL_TYPE_P (TREE_TYPE (t))
 	      && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE)
 	    {
-	      error ("linear clause applied to non-integral non-pointer");
+	      error ("linear clause applied to non-integral non-pointer "
+		     "variable with %qT type", TREE_TYPE (t));
 	      remove = true;
 	      break;
 	    }
--- gcc/tree.c.jj	2013-10-07 14:06:29.000000000 +0200
+++ gcc/tree.c	2013-10-10 15:45:32.414765635 +0200
@@ -4654,8 +4654,18 @@ omp_remove_redundant_declare_simd_attrs
 	  if (is_attribute_p ("omp declare simd", TREE_PURPOSE (*pc)))
 	    {
 	      last_attr = TREE_CHAIN (*pc);
-	      if (omp_declare_simd_clauses_equal (TREE_VALUE (*pc),
-						  TREE_VALUE (attr)))
+	      if (TREE_VALUE (attr) == NULL_TREE)
+		{
+		  if (TREE_VALUE (*pc) == NULL_TREE)
+		    {
+		      *pc = TREE_CHAIN (*pc);
+		      continue;
+		    }
+		}
+	      else if (TREE_VALUE (*pc) != NULL_TREE
+		       && omp_declare_simd_clauses_equal
+				(TREE_VALUE (TREE_VALUE (*pc)),
+				 TREE_VALUE (TREE_VALUE (attr))))
 		{
 		  *pc = TREE_CHAIN (*pc);
 		  continue;
--- gcc/testsuite/g++.dg/gomp/depend-1.C.jj	2013-06-04 20:55:56.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/depend-1.C	2013-10-10 15:03:49.154718340 +0200
@@ -27,7 +27,7 @@ foo (int g[3][10], int h[4][8], int i[2]
     ;
   #pragma omp task depend(in: o[2:5]) // { dg-error "does not have pointer or array type" }
     ;
-  #pragma omp task depend(out: a[:][2:4]) // { dg-error "array type length expression is not optional" }
+  #pragma omp task depend(out: a[:][2:4]) // { dg-error "array type length expression must be specified" }
     ;
   #pragma omp task depend(in: d[11:]) // { dg-error "low bound \[^\n\r]* above array section size" }
     ;
@@ -35,7 +35,7 @@ foo (int g[3][10], int h[4][8], int i[2]
     ;
   #pragma omp task depend(out: f[1:10]) // { dg-error "high bound \[^\n\r]* above array section size" }
     ;
-  #pragma omp task depend(in: g[:][2:4]) // { dg-error "for pointer type length expression is not optional" }
+  #pragma omp task depend(in: g[:][2:4]) // { dg-error "for pointer type length expression must be specified" }
     ;
   #pragma omp task depend(out: i[:1][11:]) // { dg-error "low bound \[^\n\r]* above array section size" }
     ;
--- gcc/testsuite/g++.dg/gomp/depend-2.C.jj	2013-06-04 20:55:56.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/depend-2.C	2013-10-10 15:03:59.049677806 +0200
@@ -29,7 +29,7 @@ foo (int g[3][10], int h[4][8], int i[2]
     ;
   #pragma omp task depend(in: o[2:5]) // { dg-error "does not have pointer or array type" }
     ;
-  #pragma omp task depend(out: a[:][2:4]) // { dg-error "array type length expression is not optional" }
+  #pragma omp task depend(out: a[:][2:4]) // { dg-error "array type length expression must be specified" }
     ;
   #pragma omp task depend(inout: b[-1:]) // { dg-error "negative low bound in array section" }
     ;
@@ -41,7 +41,7 @@ foo (int g[3][10], int h[4][8], int i[2]
     ;
   #pragma omp task depend(out: f[1:10]) // { dg-error "high bound \[^\n\r]* above array section size" }
     ;
-  #pragma omp task depend(in: g[:][2:4]) // { dg-error "for pointer type length expression is not optional" }
+  #pragma omp task depend(in: g[:][2:4]) // { dg-error "for pointer type length expression must be specified" }
     ;
   #pragma omp task depend(in: h[2:2][-1:]) // { dg-error "negative low bound in array section" }
     ;
--- gcc/testsuite/c-c++-common/gomp/depend-1.c.jj	2013-07-06 19:18:08.000000000 +0200
+++ gcc/testsuite/c-c++-common/gomp/depend-1.c	2013-10-10 15:03:07.154934731 +0200
@@ -28,7 +28,7 @@ foo (int g[3][10], int h[4][8], int i[2]
     ;
   #pragma omp task depend(in: o[2:5]) /* { dg-error "does not have pointer or array type" } */
     ;
-  #pragma omp task depend(out: a[:][2:4]) /* { dg-error "array type length expression is not optional" } */
+  #pragma omp task depend(out: a[:][2:4]) /* { dg-error "array type length expression must be specified" } */
     ;
   #pragma omp task depend(inout: b[-1:]) /* { dg-error "negative low bound in array section" } */
     ;
@@ -40,7 +40,7 @@ foo (int g[3][10], int h[4][8], int i[2]
     ;
   #pragma omp task depend(out: f[1:10]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
     ;
-  #pragma omp task depend(in: g[:][2:4]) /* { dg-error "for pointer type length expression is not optional" } */
+  #pragma omp task depend(in: g[:][2:4]) /* { dg-error "for pointer type length expression must be specified" } */
     ;
   #pragma omp task depend(in: h[2:2][-1:]) /* { dg-error "negative low bound in array section" } */
     ;
--- gcc/testsuite/c-c++-common/gomp/map-1.c.jj	2013-09-05 09:19:03.000000000 +0200
+++ gcc/testsuite/c-c++-common/gomp/map-1.c	2013-10-10 15:03:24.696845405 +0200
@@ -32,7 +32,7 @@ foo (int g[3][10], int h[4][8], int i[2]
     ;
   #pragma omp target map(to: o[2:5]) /* { dg-error "does not have pointer or array type" } */
     ;
-  #pragma omp target map(to: a[:][:]) /* { dg-error "array type length expression is not optional" } */
+  #pragma omp target map(to: a[:][:]) /* { dg-error "array type length expression must be specified" } */
     bar (&a[0][0]); /* { dg-error "referenced in target region does not have a mappable type" } */
   #pragma omp target map(tofrom: b[-1:]) /* { dg-error "negative low bound in array section" } */
     bar (b);
@@ -44,7 +44,7 @@ foo (int g[3][10], int h[4][8], int i[2]
     bar (e);
   #pragma omp target map(to: f[1:10]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
     bar (f);
-  #pragma omp target map(from: g[:][0:10]) /* { dg-error "for pointer type length expression is not optional" } */
+  #pragma omp target map(from: g[:][0:10]) /* { dg-error "for pointer type length expression must be specified" } */
     bar (&g[0][0]);
   #pragma omp target map(from: h[2:1][-1:]) /* { dg-error "negative low bound in array section" } */
     bar (&h[0][0]);
