On 10/23/2015 01:25 PM, Cesar Philippidis wrote:
> On 10/22/2015 01:52 AM, Jakub Jelinek wrote:
>> On Wed, Oct 21, 2015 at 03:18:55PM -0400, Nathan Sidwell wrote:
>>> This patch is the C++ changes matching the C ones of patch 4.  In
>>> finish_omp_clauses, the gang, worker, & vector clauses are handled the same
>>> as OpenMP's 'num_threads' clause.  One change to num_threads is the
>>> augmentation of a diagnostic to add %<...%>  markers to the clause name.
>>
>> Indeed, lots of older OpenMP diagnostics is missing %<...%> markers around
>> keywords.  Something to fix eventually.
> 
> I updated omp tasks and teams in semantics.c.
> 
>>> 2015-10-20  Cesar Philippidis  <ce...@codesourcery.com>
>>>         Thomas Schwinge  <tho...@codesourcery.com>
>>>         James Norris  <jnor...@codesourcery.com>
>>>         Joseph Myers  <jos...@codesourcery.com>
>>>         Julian Brown  <jul...@codesourcery.com>
>>>         Nathan Sidwell <nat...@codesourcery.com>
>>>
>>>     * parser.c (cp_parser_omp_clause_name): Add auto, gang, seq,
>>>     vector, worker.
>>>     (cp_parser_oacc_simple_clause): New.
>>>     (cp_parser_oacc_shape_clause): New.
>>
>> What I've said for the C FE patch, plus:
>>
>>> +     if (cp_lexer_next_token_is (lexer, CPP_NAME)
>>> +         || cp_lexer_next_token_is (lexer, CPP_KEYWORD))
>>> +       {
>>> +         tree name_kind = cp_lexer_peek_token (lexer)->u.value;
>>> +         const char *p = IDENTIFIER_POINTER (name_kind);
>>> +         if (kind == OMP_CLAUSE_GANG && strcmp ("static", p) == 0)
>>
>> As static is a keyword, wouldn't it be better to just handle that case
>> using cp_lexer_next_token_is_keyword (lexer, RID_STATIC)?
>>
>> Also, what is the exact grammar of the shape arguments?
>> Would be nice to describe the grammar, in the grammar you just say
>> expression, at least for vector/worker, which is clearly not accurate.
>>
>> It seems the intent is that num: or length: or static: is optional, right?
>> But if that is the case, you should treat those as parsed only if followed
>> by :.  While static is a keyword, so you can't have a variable called like
>> that, having vector(length) or vector(num) should not be rejected.
>> So, I would have expected that it should test if it is RID_STATIC
>> followed by CPP_COLON (and only in that case consume those tokens),
>> or CPP_NAME of id followed by CPP_COLON (and only in that case consume those
>> tokens), otherwise parse it as assignment expression.
> 
> That function now peeks ahead to look for a colon, so now it can handle
> variables with the name of clause keywords.
> 
>> The C FE may have similar issue.  Plus of course there should be testsuite
>> coverage for all the weird cases.
> 
> I included a new test in a different patch because it's common to both c
> and c++.
> 
>>> +   case OMP_CLAUSE_GANG:
>>> +   case OMP_CLAUSE_VECTOR:
>>> +   case OMP_CLAUSE_WORKER:
>>> +     /* Operand 0 is the num: or length: argument.  */
>>> +     t = OMP_CLAUSE_OPERAND (c, 0);
>>> +     if (t == NULL_TREE)
>>> +       break;
>>> +
>>> +     t = maybe_convert_cond (t);
>>
>> Can you explain the maybe_convert_cond calls (in both cases here,
>> plus the preexisting in OMP_CLAUSE_VECTOR_LENGTH)?
>> The reason why it is used for OpenMP if and final clauses is that those have
>> a condition argument, either the condition is zero or non-zero (so
>> effectively it is turned into a bool).
>> But aren't the gang/vector/worker/vector_length arguments integers rather
>> than conditions?  I'd expect that finish_omp_clauses should verify
>> those operands are indeed integral expressions (if that is the requirement
>> in the standard), as it is something that for C++ can't be verified during
>> parsing, if arbitrary expressions are parsed there.
> 
> It's probably a copy-and-paste error. This functionality was added
> incrementally. I removed that check.
> 
>>> @@ -5959,32 +5990,58 @@ finish_omp_clauses (tree clauses, bool a
>>>       break;
>>>  
>>>     case OMP_CLAUSE_NUM_THREADS:
>>> -     t = OMP_CLAUSE_NUM_THREADS_EXPR (c);
>>> -     if (t == error_mark_node)
>>> -       remove = true;
>>> -     else if (!type_dependent_expression_p (t)
>>> -              && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
>>> -       {
>>> -         error ("num_threads expression must be integral");
>>> -         remove = true;
>>> -       }
>>> -     else
>>> -       {
>>> -         t = mark_rvalue_use (t);
>>> -         if (!processing_template_decl)
>>> -           {
>>> -             t = maybe_constant_value (t);
>>> -             if (TREE_CODE (t) == INTEGER_CST
>>> -                 && tree_int_cst_sgn (t) != 1)
>>> -               {
>>> -                 warning_at (OMP_CLAUSE_LOCATION (c), 0,
>>> -                             "%<num_threads%> value must be positive");
>>> -                 t = integer_one_node;
>>> -               }
>>> -             t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
>>> -           }
>>> -         OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
>>> -       }
>>> +   case OMP_CLAUSE_NUM_GANGS:
>>> +   case OMP_CLAUSE_NUM_WORKERS:
>>> +   case OMP_CLAUSE_VECTOR_LENGTH:
>>
>> If you are already merging some of the similar handling, please
>> handle OMP_CLAUSE_NUM_TEAMS and OMP_CLAUSE_NUM_TASKS the same way.
> 
> I did that, but I also had to adjust the expected errors in a couple of
> existing gomp test cases.
> 
> Is this patch OK for trunk?

This patch teaches the the loop shape function how to be more careful
with commas. Most of the errors in the c++ front end are similar their
counterparts in c, except for those when the c++ front end thinks a
stray colon is an errant scope resolution operation. For those types of
failures, I just used a generic regex for the dg-error. Consequently,
this patch shares the same loop-shape.c test case that I included in the
c patch.

Is this OK for trunk?

Cesar

2015-10-23  Cesar Philippidis  <ce...@codesourcery.com>
	    Thomas Schwinge  <tho...@codesourcery.com>
	    James Norris  <jnor...@codesourcery.com>
	    Joseph Myers  <jos...@codesourcery.com>
	    Julian Brown  <jul...@codesourcery.com>
	    Nathan Sidwell <nat...@codesourcery.com>
	    Bernd Schmidt  <bschm...@redhat.com>

	* parser.c (cp_parser_omp_clause_name): Add auto, gang, seq,
	vector, worker.
	(cp_parser_oacc_simple_clause): New.
	(cp_parser_oacc_shape_clause): New.
	(cp_parser_oacc_all_clauses): Add auto, gang, seq, vector, worker.
	(OACC_LOOP_CLAUSE_MASK): Likewise.
	* semantics.c (finish_omp_clauses): Add auto, gang, seq, vector,
	worker. Unify the handling to teams, tasks and vector_length with
	the other loop shape clauses.

2015-10-23  Nathan Sidwell <nat...@codesourcery.com>
	    Cesar Philippidis  <ce...@codesourcery.com>

	gcc/testsuite/
	* g++.dg/g++.dg/gomp/pr33372-1.C: Adjust diagnostic.
	* gcc/testsuite/g++.dg/gomp/pr33372-3.C: Likewise.


diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8dbff11..2970ec2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,14 @@
+2015-10-22  Jason Merrill  <ja...@redhat.com>
+
+	* call.c (add_template_conv_candidate): Pass DEDUCE_CALL.
+	(add_template_candidate_real): Handle it.
+	* pt.c (fn_type_unification): Handle it.
+
+	* call.c (add_conv_candidate): Remove first_arg parm.
+	(add_template_conv_candidate): Likewise.
+	(add_template_candidate_real): Don't pass it.
+	(build_op_call_1): Likewise.
+
 2015-10-22  Richard Biener  <rguent...@suse.de>
 
 	* semantics.c (cp_finish_omp_clause_depend_sink): Properly convert
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 55b3c8c..5b57dc9 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -178,9 +178,6 @@ static struct z_candidate *add_template_candidate
 static struct z_candidate *add_template_candidate_real
 	(struct z_candidate **, tree, tree, tree, tree, const vec<tree, va_gc> *,
 	 tree, tree, tree, int, tree, unification_kind_t, tsubst_flags_t);
-static struct z_candidate *add_template_conv_candidate
-	(struct z_candidate **, tree, tree, tree, const vec<tree, va_gc> *,
-	 tree, tree, tree, tsubst_flags_t);
 static void add_builtin_candidates
 	(struct z_candidate **, enum tree_code, enum tree_code,
 	 tree, tree *, int, tsubst_flags_t);
@@ -192,7 +189,7 @@ static void build_builtin_candidate
 	(struct z_candidate **, tree, tree, tree, tree *, tree *,
 	 int, tsubst_flags_t);
 static struct z_candidate *add_conv_candidate
-	(struct z_candidate **, tree, tree, tree, const vec<tree, va_gc> *, tree,
+	(struct z_candidate **, tree, tree, const vec<tree, va_gc> *, tree,
 	 tree, tsubst_flags_t);
 static struct z_candidate *add_function_candidate
 	(struct z_candidate **, tree, tree, tree, const vec<tree, va_gc> *, tree,
@@ -2176,7 +2173,7 @@ add_function_candidate (struct z_candidate **candidates,
 
 static struct z_candidate *
 add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
-		    tree first_arg, const vec<tree, va_gc> *arglist,
+		    const vec<tree, va_gc> *arglist,
 		    tree access_path, tree conversion_path,
 		    tsubst_flags_t complain)
 {
@@ -2190,7 +2187,7 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
     parmlist = TREE_TYPE (parmlist);
   parmlist = TYPE_ARG_TYPES (parmlist);
 
-  len = vec_safe_length (arglist) + (first_arg != NULL_TREE ? 1 : 0) + 1;
+  len = vec_safe_length (arglist) + 1;
   convs = alloc_conversions (len);
   parmnode = parmlist;
   viable = 1;
@@ -2208,10 +2205,8 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
 
       if (i == 0)
 	arg = obj;
-      else if (i == 1 && first_arg != NULL_TREE)
-	arg = first_arg;
       else
-	arg = (*arglist)[i - (first_arg != NULL_TREE ? 1 : 0) - 1];
+	arg = (*arglist)[i - 1];
       argtype = lvalue_type (arg);
 
       if (i == 0)
@@ -2260,7 +2255,7 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
       reason = arity_rejection (NULL_TREE, i + remaining, len);
     }
 
-  return add_candidate (candidates, totype, first_arg, arglist, len, convs,
+  return add_candidate (candidates, totype, obj, arglist, len, convs,
 			access_path, conversion_path, viable, reason, flags);
 }
 
@@ -3032,6 +3027,9 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
     {
       if (first_arg_without_in_chrg != NULL_TREE)
 	first_arg_without_in_chrg = NULL_TREE;
+      else if (return_type && strict == DEDUCE_CALL)
+	/* We're deducing for a call to the result of a template conversion
+	   function, so the args don't contain 'this'; leave them alone.  */;
       else
 	++skip_without_in_chrg;
     }
@@ -3122,7 +3120,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
 
   if (obj != NULL_TREE)
     /* Aha, this is a conversion function.  */
-    cand = add_conv_candidate (candidates, fn, obj, first_arg, arglist,
+    cand = add_conv_candidate (candidates, fn, obj, arglist,
 			       access_path, conversion_path, complain);
   else
     cand = add_function_candidate (candidates, fn, ctype,
@@ -3172,18 +3170,23 @@ add_template_candidate (struct z_candidate **candidates, tree tmpl, tree ctype,
 				 flags, NULL_TREE, strict, complain);
 }
 
+/* Create an overload candidate for the conversion function template TMPL,
+   returning RETURN_TYPE, which will be invoked for expression OBJ to produce a
+   pointer-to-function which will in turn be called with the argument list
+   ARGLIST, and add it to CANDIDATES.  This does not change ARGLIST.  FLAGS is
+   passed on to implicit_conversion.  */
 
 static struct z_candidate *
 add_template_conv_candidate (struct z_candidate **candidates, tree tmpl,
-			     tree obj, tree first_arg,
+			     tree obj,
 			     const vec<tree, va_gc> *arglist,
 			     tree return_type, tree access_path,
 			     tree conversion_path, tsubst_flags_t complain)
 {
   return
     add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
-				 first_arg, arglist, return_type, access_path,
-				 conversion_path, 0, obj, DEDUCE_CONV,
+				 NULL_TREE, arglist, return_type, access_path,
+				 conversion_path, 0, obj, DEDUCE_CALL,
 				 complain);
 }
 
@@ -4335,11 +4338,11 @@ build_op_call_1 (tree obj, vec<tree, va_gc> **args, tsubst_flags_t complain)
 
 	    if (TREE_CODE (fn) == TEMPLATE_DECL)
 	      add_template_conv_candidate
-		(&candidates, fn, obj, NULL_TREE, *args, totype,
+		(&candidates, fn, obj, *args, totype,
 		 /*access_path=*/NULL_TREE,
 		 /*conversion_path=*/NULL_TREE, complain);
 	    else
-	      add_conv_candidate (&candidates, fn, obj, NULL_TREE,
+	      add_conv_candidate (&candidates, fn, obj,
 				  *args, /*conversion_path=*/NULL_TREE,
 				  /*access_path=*/NULL_TREE, complain);
 	  }
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7555bf3..eaccf4b 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -29064,7 +29064,9 @@ cp_parser_omp_clause_name (cp_parser *parser)
 {
   pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
 
-  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_IF))
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO))
+    result = PRAGMA_OACC_CLAUSE_AUTO;
+  else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_IF))
     result = PRAGMA_OMP_CLAUSE_IF;
   else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_DEFAULT))
     result = PRAGMA_OMP_CLAUSE_DEFAULT;
@@ -29122,7 +29124,9 @@ cp_parser_omp_clause_name (cp_parser *parser)
 	    result = PRAGMA_OMP_CLAUSE_FROM;
 	  break;
 	case 'g':
-	  if (!strcmp ("grainsize", p))
+	  if (!strcmp ("gang", p))
+	    result = PRAGMA_OACC_CLAUSE_GANG;
+	  else if (!strcmp ("grainsize", p))
 	    result = PRAGMA_OMP_CLAUSE_GRAINSIZE;
 	  break;
 	case 'h':
@@ -29212,6 +29216,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
 	    result = PRAGMA_OMP_CLAUSE_SECTIONS;
 	  else if (!strcmp ("self", p))
 	    result = PRAGMA_OACC_CLAUSE_SELF;
+	  else if (!strcmp ("seq", p))
+	    result = PRAGMA_OACC_CLAUSE_SEQ;
 	  else if (!strcmp ("shared", p))
 	    result = PRAGMA_OMP_CLAUSE_SHARED;
 	  else if (!strcmp ("simd", p))
@@ -29238,7 +29244,9 @@ cp_parser_omp_clause_name (cp_parser *parser)
 	    result = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR;
 	  break;
 	case 'v':
-	  if (!strcmp ("vector_length", p))
+	  if (!strcmp ("vector", p))
+	    result = PRAGMA_OACC_CLAUSE_VECTOR;
+	  else if (!strcmp ("vector_length", p))
 	    result = PRAGMA_OACC_CLAUSE_VECTOR_LENGTH;
 	  else if (flag_cilkplus && !strcmp ("vectorlength", p))
 	    result = PRAGMA_CILK_CLAUSE_VECTORLENGTH;
@@ -29246,6 +29254,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
 	case 'w':
 	  if (!strcmp ("wait", p))
 	    result = PRAGMA_OACC_CLAUSE_WAIT;
+	  else if (!strcmp ("worker", p))
+	    result = PRAGMA_OACC_CLAUSE_WORKER;
 	  break;
 	}
     }
@@ -29582,6 +29592,158 @@ cp_parser_oacc_data_clause_deviceptr (cp_parser *parser, tree list)
   return list;
 }
 
+/* OpenACC 2.0:
+   auto
+   independent
+   nohost
+   seq */
+
+static tree
+cp_parser_oacc_simple_clause (cp_parser *ARG_UNUSED (parser),
+			      enum omp_clause_code code,
+			      tree list, location_t location)
+{
+  check_no_duplicate_clause (list, code, omp_clause_code_name[code], location);
+  tree c = build_omp_clause (location, code);
+  OMP_CLAUSE_CHAIN (c) = list;
+  return c;
+}
+
+/* OpenACC:
+
+    gang [( gang-arg-list )]
+    worker [( [num:] int-expr )]
+    vector [( [length:] int-expr )]
+
+  where gang-arg is one of:
+
+    [num:] int-expr
+    static: size-expr
+
+  and size-expr may be:
+
+    *
+    int-expr
+*/
+
+static tree
+cp_parser_oacc_shape_clause (cp_parser *parser, omp_clause_code kind,
+			     const char *str, tree list)
+{
+  const char *id = "num";
+  cp_lexer *lexer = parser->lexer;
+  tree op0 = NULL_TREE, op1 = NULL_TREE, c;
+  location_t loc = cp_lexer_peek_token (lexer)->location;
+
+  if (kind == OMP_CLAUSE_VECTOR)
+    id = "length";
+
+  if (cp_lexer_next_token_is (lexer, CPP_OPEN_PAREN))
+    {
+      tree *op_to_parse = &op0;
+      cp_token *next;
+
+      cp_lexer_consume_token (lexer);
+
+      do
+	{
+	  /* Consume a comma if present.  */
+	  if (cp_lexer_next_token_is (lexer, CPP_COMMA))
+	    {
+	      if (op0 == NULL && op1 == NULL)
+		{
+		  cp_parser_error (parser, "unexpected argument");
+		  goto cleanup_error;
+		}
+
+	      cp_lexer_consume_token (lexer);
+	    }
+
+	  next = cp_lexer_peek_token (lexer);
+	  loc = next->location;
+	  op_to_parse = &op0;
+
+	  /* First extract any length:, num: and static: arguments.  */
+
+	  /* Gang static argument.  */
+	  if (cp_lexer_next_token_is (lexer, CPP_KEYWORD)
+	      && cp_lexer_next_token_is_keyword (lexer, RID_STATIC))
+	    {
+	      if (kind != OMP_CLAUSE_GANG)
+		{
+		  cp_parser_error (parser, "invalid %<static%> argument");
+		  goto cleanup_error;
+		}
+
+	      cp_lexer_consume_token (lexer);
+
+	      if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+		goto cleanup_error;
+
+	      op_to_parse = &op1;
+	      if (*op_to_parse != NULL)
+		{
+		  cp_parser_error (parser, "too many %<static%> arguements");
+		  goto cleanup_error;
+		}
+
+	      /* Check for the '*' argument.  */
+	      if (cp_lexer_next_token_is (lexer, CPP_MULT))
+		{
+		  cp_lexer_consume_token (lexer);
+		  *op_to_parse = integer_minus_one_node;
+		  continue;
+		}
+	    }
+	  /* Worker num: argument and vector length: arguments.  */
+	  else if (cp_lexer_next_token_is (lexer, CPP_NAME)
+		   && strcmp (id, IDENTIFIER_POINTER (next->u.value)) == 0
+		   && cp_lexer_nth_token_is (lexer, 2, CPP_COLON))
+	    {
+	      cp_lexer_consume_token (lexer);  /* id  */
+	      cp_lexer_consume_token (lexer);  /* ':'  */
+	    }
+
+	  /* Now collect the actual argument.  */
+
+	  if (*op_to_parse != NULL_TREE)
+	    {
+	      cp_parser_error (parser, "unexpected argument");
+	      goto cleanup_error;
+	    }
+
+
+	  tree expr = cp_parser_assignment_expression (parser, NULL, false,
+						       false);
+	  if (expr == error_mark_node)
+	    goto cleanup_error;
+
+	  mark_exp_read (expr);
+	  *op_to_parse = expr;
+	}
+      while (cp_lexer_next_token_is (lexer, CPP_COMMA)
+	     && !cp_lexer_next_token_is (lexer, CPP_CLOSE_PAREN));
+
+      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+	goto cleanup_error;
+    }
+
+  check_no_duplicate_clause (list, kind, str, loc);
+
+  c = build_omp_clause (loc, kind);
+  if (op0)
+    OMP_CLAUSE_OPERAND (c, 0) = op0;
+  if (op1)
+    OMP_CLAUSE_OPERAND (c, 1) = op1;
+  OMP_CLAUSE_CHAIN (c) = list;
+
+  return c;
+
+ cleanup_error:
+  cp_parser_skip_to_closing_parenthesis (parser, false, false, true);
+  return list;
+}
+
 /* OpenACC:
    vector_length ( expression ) */
 
@@ -31306,6 +31468,11 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	  clauses = cp_parser_oacc_clause_async (parser, clauses);
 	  c_name = "async";
 	  break;
+	case PRAGMA_OACC_CLAUSE_AUTO:
+	  clauses = cp_parser_oacc_simple_clause (parser, OMP_CLAUSE_AUTO,
+						 clauses, here);
+	  c_name = "auto";
+	  break;
 	case PRAGMA_OACC_CLAUSE_COLLAPSE:
 	  clauses = cp_parser_omp_clause_collapse (parser, clauses, here);
 	  c_name = "collapse";
@@ -31338,6 +31505,11 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	  clauses = cp_parser_oacc_data_clause_deviceptr (parser, clauses);
 	  c_name = "deviceptr";
 	  break;
+	case PRAGMA_OACC_CLAUSE_GANG:
+	  c_name = "gang";
+	  clauses = cp_parser_oacc_shape_clause (parser, OMP_CLAUSE_GANG,
+						 c_name, clauses);
+	  break;
 	case PRAGMA_OACC_CLAUSE_HOST:
 	  clauses = cp_parser_oacc_data_clause (parser, c_kind, clauses);
 	  c_name = "host";
@@ -31382,6 +31554,16 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	  clauses = cp_parser_oacc_data_clause (parser, c_kind, clauses);
 	  c_name = "self";
 	  break;
+	case PRAGMA_OACC_CLAUSE_SEQ:
+	  clauses = cp_parser_oacc_simple_clause (parser, OMP_CLAUSE_SEQ,
+						 clauses, here);
+	  c_name = "seq";
+	  break;
+	case PRAGMA_OACC_CLAUSE_VECTOR:
+	  c_name = "vector";
+	  clauses = cp_parser_oacc_shape_clause (parser, OMP_CLAUSE_VECTOR,
+						 c_name, clauses);
+	  break;
 	case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH:
 	  clauses = cp_parser_oacc_clause_vector_length (parser, clauses);
 	  c_name = "vector_length";
@@ -31390,6 +31572,11 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	  clauses = cp_parser_oacc_clause_wait (parser, clauses);
 	  c_name = "wait";
 	  break;
+	case PRAGMA_OACC_CLAUSE_WORKER:
+	  c_name = "worker";
+	  clauses = cp_parser_oacc_shape_clause (parser, OMP_CLAUSE_WORKER,
+						 c_name, clauses);
+	  break;
 	default:
 	  cp_parser_error (parser, "expected %<#pragma acc%> clause");
 	  goto saw_error;
@@ -34339,6 +34526,11 @@ cp_parser_oacc_kernels (cp_parser *parser, cp_token *pragma_tok)
 
 #define OACC_LOOP_CLAUSE_MASK						\
 	( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COLLAPSE)		\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG)		\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR)		\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER)		\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_AUTO)		\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ)			\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION))
 
 static tree
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 142245a..ffe02da 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -17235,7 +17235,9 @@ pack_deducible_p (tree parm, tree fn)
 
    DEDUCE_CALL:
      We are deducing arguments for a function call, as in
-     [temp.deduct.call].
+     [temp.deduct.call].  If RETURN_TYPE is non-null, we are
+     deducing arguments for a call to the result of a conversion
+     function template, as in [over.call.object].
 
    DEDUCE_CONV:
      We are deducing arguments for a conversion function, as in
@@ -17402,7 +17404,15 @@ fn_type_unification (tree fn,
   /* Never do unification on the 'this' parameter.  */
   parms = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (fntype));
 
-  if (return_type)
+  if (return_type && strict == DEDUCE_CALL)
+    {
+      /* We're deducing for a call to the result of a template conversion
+         function.  The parms we really want are in return_type.  */
+      if (POINTER_TYPE_P (return_type))
+	return_type = TREE_TYPE (return_type);
+      parms = TYPE_ARG_TYPES (return_type);
+    }
+  else if (return_type)
     {
       tree *new_args;
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 11315d9..153a970 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5911,6 +5911,31 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
 	    bitmap_set_bit (&firstprivate_head, DECL_UID (t));
 	  goto handle_field_decl;
 
+	case OMP_CLAUSE_GANG:
+	case OMP_CLAUSE_VECTOR:
+	case OMP_CLAUSE_WORKER:
+	  /* Operand 0 is the num: or length: argument.  */
+	  t = OMP_CLAUSE_OPERAND (c, 0);
+	  if (t == NULL_TREE)
+	    break;
+
+	  if (!processing_template_decl)
+	    t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+	  OMP_CLAUSE_OPERAND (c, 0) = t;
+
+	  if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_GANG)
+	    break;
+
+	  /* Ooperand 1 is the gang static: argument.  */
+	  t = OMP_CLAUSE_OPERAND (c, 1);
+	  if (t == NULL_TREE)
+	    break;
+
+	  if (!processing_template_decl)
+	    t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+	  OMP_CLAUSE_OPERAND (c, 1) = t;
+	  break;
+
 	case OMP_CLAUSE_LASTPRIVATE:
 	  t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
 	  if (t)
@@ -5965,14 +5990,37 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
 	  OMP_CLAUSE_FINAL_EXPR (c) = t;
 	  break;
 
+	case OMP_CLAUSE_NUM_TASKS:
+	case OMP_CLAUSE_NUM_TEAMS:
 	case OMP_CLAUSE_NUM_THREADS:
-	  t = OMP_CLAUSE_NUM_THREADS_EXPR (c);
+	case OMP_CLAUSE_NUM_GANGS:
+	case OMP_CLAUSE_NUM_WORKERS:
+	case OMP_CLAUSE_VECTOR_LENGTH:
+	  t = OMP_CLAUSE_OPERAND (c, 0);
 	  if (t == error_mark_node)
 	    remove = true;
 	  else if (!type_dependent_expression_p (t)
 		   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
 	    {
-	      error ("num_threads expression must be integral");
+	     switch (OMP_CLAUSE_CODE (c))
+		{
+		case OMP_CLAUSE_NUM_TASKS:
+		  error ("%<num_tasks%> expression must be integral"); break;
+		case OMP_CLAUSE_NUM_TEAMS:
+		  error ("%<num_teams%> expression must be integral"); break;
+		case OMP_CLAUSE_NUM_THREADS:
+		  error ("%<num_threads%> expression must be integral"); break;
+		case OMP_CLAUSE_NUM_GANGS:
+		  error ("%<num_gangs%> expression must be integral"); break;
+		case OMP_CLAUSE_NUM_WORKERS:
+		  error ("%<num_workers%> expression must be integral");
+		  break;
+		case OMP_CLAUSE_VECTOR_LENGTH:
+		  error ("%<vector_length%> expression must be integral");
+		  break;
+		default:
+		  error ("invalid argument");
+		}
 	      remove = true;
 	    }
 	  else
@@ -5984,13 +6032,40 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
 		  if (TREE_CODE (t) == INTEGER_CST
 		      && tree_int_cst_sgn (t) != 1)
 		    {
-		      warning_at (OMP_CLAUSE_LOCATION (c), 0,
-				  "%<num_threads%> value must be positive");
+		      switch (OMP_CLAUSE_CODE (c))
+			{
+			case OMP_CLAUSE_NUM_TASKS:
+			  warning_at (OMP_CLAUSE_LOCATION (c), 0,
+				      "%<num_tasks%> value must be positive");
+			  break;
+			case OMP_CLAUSE_NUM_TEAMS:
+			  warning_at (OMP_CLAUSE_LOCATION (c), 0,
+				      "%<num_teams%> value must be positive");
+			  break;
+			case OMP_CLAUSE_NUM_THREADS:
+			  warning_at (OMP_CLAUSE_LOCATION (c), 0,
+				      "%<num_threads%> value must be"
+				      "positive"); break;
+			case OMP_CLAUSE_NUM_GANGS:
+			  warning_at (OMP_CLAUSE_LOCATION (c), 0,
+				      "%<num_gangs%> value must be positive");
+			  break;
+			case OMP_CLAUSE_NUM_WORKERS:
+			  warning_at (OMP_CLAUSE_LOCATION (c), 0,
+				      "%<num_workers%> value must be"
+				      "positive"); break;
+			case OMP_CLAUSE_VECTOR_LENGTH:
+			  warning_at (OMP_CLAUSE_LOCATION (c), 0,
+				      "%<vector_length%> value must be"
+				      "positive"); break;
+			default:
+			  error ("invalid argument");
+			}
 		      t = integer_one_node;
 		    }
 		  t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
 		}
-	      OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
+	      OMP_CLAUSE_OPERAND (c, 0) = t;
 	    }
 	  break;
 
@@ -6062,35 +6137,6 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
 	    }
 	  break;
 
-	case OMP_CLAUSE_NUM_TEAMS:
-	  t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
-	  if (t == error_mark_node)
-	    remove = true;
-	  else if (!type_dependent_expression_p (t)
-		   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
-	    {
-	      error ("%<num_teams%> expression must be integral");
-	      remove = true;
-	    }
-	  else
-	    {
-	      t = mark_rvalue_use (t);
-	      if (!processing_template_decl)
-		{
-		  t = maybe_constant_value (t);
-		  if (TREE_CODE (t) == INTEGER_CST
-		      && tree_int_cst_sgn (t) != 1)
-		    {
-		      warning_at (OMP_CLAUSE_LOCATION (c), 0,
-				  "%<num_teams%> value must be positive");
-		      t = integer_one_node;
-		    }
-		  t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
-		}
-	      OMP_CLAUSE_NUM_TEAMS_EXPR (c) = t;
-	    }
-	  break;
-
 	case OMP_CLAUSE_ASYNC:
 	  t = OMP_CLAUSE_ASYNC_EXPR (c);
 	  if (t == error_mark_node)
@@ -6110,16 +6156,6 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
 	    }
 	  break;
 
-	case OMP_CLAUSE_VECTOR_LENGTH:
-	  t = OMP_CLAUSE_VECTOR_LENGTH_EXPR (c);
-	  t = maybe_convert_cond (t);
-	  if (t == error_mark_node)
-	    remove = true;
-	  else if (!processing_template_decl)
-	    t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
-	  OMP_CLAUSE_VECTOR_LENGTH_EXPR (c) = t;
-	  break;
-
 	case OMP_CLAUSE_WAIT:
 	  t = OMP_CLAUSE_WAIT_EXPR (c);
 	  if (t == error_mark_node)
@@ -6547,35 +6583,6 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
 	    }
 	  goto check_dup_generic;
 
-	case OMP_CLAUSE_NUM_TASKS:
-	  t = OMP_CLAUSE_NUM_TASKS_EXPR (c);
-	  if (t == error_mark_node)
-	    remove = true;
-	  else if (!type_dependent_expression_p (t)
-		   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
-	    {
-	      error ("%<num_tasks%> expression must be integral");
-	      remove = true;
-	    }
-	  else
-	    {
-	      t = mark_rvalue_use (t);
-	      if (!processing_template_decl)
-		{
-		  t = maybe_constant_value (t);
-		  if (TREE_CODE (t) == INTEGER_CST
-		      && tree_int_cst_sgn (t) != 1)
-		    {
-		      warning_at (OMP_CLAUSE_LOCATION (c), 0,
-				  "%<num_tasks%> value must be positive");
-		      t = integer_one_node;
-		    }
-		  t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
-		}
-	      OMP_CLAUSE_NUM_TASKS_EXPR (c) = t;
-	    }
-	  break;
-
 	case OMP_CLAUSE_GRAINSIZE:
 	  t = OMP_CLAUSE_GRAINSIZE_EXPR (c);
 	  if (t == error_mark_node)
@@ -6694,6 +6701,8 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
 	case OMP_CLAUSE_SIMD:
 	case OMP_CLAUSE_DEFAULTMAP:
 	case OMP_CLAUSE__CILK_FOR_COUNT_:
+	case OMP_CLAUSE_AUTO:
+	case OMP_CLAUSE_SEQ:
 	  break;
 
 	case OMP_CLAUSE_INBRANCH:

Reply via email to