diff mbox

[PR,c/71381] C/C++ OpenACC cache directive rejects valid syntax (was: [gomp4] OpenACC cache directive for C.)

Message ID 877fe7sthf.fsf@kepler.schwinge.homeip.net
State New
Headers show

Commit Message

Thomas Schwinge June 2, 2016, 11:47 a.m. UTC
Hi!

On Wed, 05 Nov 2014 17:29:19 +0100, I wrote:
> In r217145, I applied Jim's patch to gomp-4_0-branch:
> 
> commit 4361f9b6b2c74c2961c3a5290a4945abe2d7a444
> Author: tschwinge <tschwinge@138bc75d-0d04-0410-961f-82ee72b054a4>
> Date:   Wed Nov 5 16:26:47 2014 +0000
> 
>     OpenACC cache directive for C.

(That, and the corresponding C++ changes later made it into trunk.)

> --- gcc/c/c-parser.c
> +++ gcc/c/c-parser.c
> @@ -10053,6 +10053,14 @@ c_parser_omp_variable_list (c_parser *parser,
>  	{
>  	  switch (kind)
>  	    {
> +	    case OMP_NO_CLAUSE_CACHE:
> +	      if (c_parser_peek_token (parser)->type != CPP_OPEN_SQUARE)
> +		{
> +		  c_parser_error (parser, "expected %<[%>");
> +		  t = error_mark_node;
> +		  break;
> +		}
> +	      /* FALL THROUGH.  */
>  	    case OMP_CLAUSE_MAP:
>  	    case OMP_CLAUSE_FROM:
>  	    case OMP_CLAUSE_TO:

Strictly speaking (OpenACC 2.0a specification), that is correct: the
OpenACC cache directive explicitly only allows "array elements or
subarrays".  However, I wonder if it would make sense to allow complete
arrays as a GNU extension?  That is, syntactic sugar to allow "cache (a)"
to mean "cache (a[0:LENGTH])"?

> @@ -10091,6 +10099,29 @@ c_parser_omp_variable_list (c_parser *parser,
>  		      t = error_mark_node;
>  		      break;
>  		    }
> +
> +		  if (kind == OMP_NO_CLAUSE_CACHE)
> +		    {
> +		      mark_exp_read (low_bound);
> +		      mark_exp_read (length);
> +
> +		      if (TREE_CODE (low_bound) != INTEGER_CST
> +			  && !TREE_READONLY (low_bound))
> +			{
> +			  error_at (clause_loc,
> +					"%qD is not a constant", low_bound);
> +			  t = error_mark_node;
> +			}

WHile OpenACC 2.0a specifies that "the lower bound is a constant", it
also permits the lower bound to be a "loop invariant, or the for loop
index variable plus or minus a constant or loop invariant".  So, we're
rejecting valid syntax here.

> +
> +		      if (TREE_CODE (length) != INTEGER_CST
> +			  && !TREE_READONLY (length))
> +			{
> +			  error_at (clause_loc,
> +					"%qD is not a constant", length);
> +			  t = error_mark_node;
> +			}
> +		    }

The idea is correct (OpenACC 2.0a: "the length is a constant"), but we
can't reliably check that here; for example:

    #pragma acc cache (a[0:n + 1])

... will run into an ICE, "tree check: expected tree that contains 'decl
minimal' structure, have 'plus_expr' in [...]".

Currently we're discarding the OpenACC cache directive in the middle end;
I expect checking of the lower bound and length will come automatically
as soon as we start to do something with OACC_CACHE/OMP_CLAUSE__CACHE_.
Until then, I propose we simple remove these checks from the front ends.
OK for trunk and gcc-6-branch?

commit a620ebe6fa509ec6441ba87276e55078eb2d00fc
Author: Thomas Schwinge <thomas@codesourcery.com>
Date:   Thu Jun 2 12:19:49 2016 +0200

    [PR c/71381] C/C++ OpenACC cache directive rejects valid syntax
    
    	gcc/c/
    	PR c/71381
    	* c-parser.c (c_parser_omp_variable_list) <OMP_CLAUSE__CACHE_>:
    	Loosen checking.
    	gcc/cp/
    	PR c/71381
    	* parser.c (cp_parser_omp_var_list_no_open) <OMP_CLAUSE__CACHE_>:
    	Loosen checking.
    	gcc/fortran/
    	PR c/71381
    	* openmp.c (gfc_match_oacc_cache): Add comment.
    	gcc/testsuite/
    	PR c/71381
    	* c-c++-common/goacc/cache-1.c: Update.  Move invalid usage tests
    	to...
    	* c-c++-common/goacc/cache-2.c: ... this new file.
    	* gfortran.dg/goacc/cache-1.f95: Move invalid usage tests to...
    	* gfortran.dg/goacc/cache-2.f95: ... this new file.
    	* gfortran.dg/goacc/coarray.f95: Update OpenACC cache directive
    	usage.
    	* gfortran.dg/goacc/cray.f95: Likewise.
    	* gfortran.dg/goacc/loop-1.f95: Likewise.
    	libgomp/
    	PR c/71381
    	* testsuite/libgomp.oacc-c-c++-common/cache-1.c: #include
    	"../../../gcc/testsuite/c-c++-common/goacc/cache-1.c".
    	* testsuite/libgomp.oacc-fortran/cache-1.f95: New file.
    
    	gcc/
    	* omp-low.c (scan_sharing_clauses): Don't expect
    	OMP_CLAUSE__CACHE_.
---
 gcc/c/c-parser.c                                   | 22 +-------
 gcc/cp/parser.c                                    | 22 +-------
 gcc/fortran/openmp.c                               |  5 ++
 gcc/omp-low.c                                      |  6 --
 gcc/testsuite/c-c++-common/goacc/cache-1.c         | 66 ++++++++--------------
 .../c-c++-common/goacc/{cache-1.c => cache-2.c}    | 39 ++-----------
 gcc/testsuite/gfortran.dg/goacc/cache-1.f95        |  7 +--
 gcc/testsuite/gfortran.dg/goacc/cache-2.f95        | 12 ++++
 gcc/testsuite/gfortran.dg/goacc/coarray.f95        |  2 +-
 gcc/testsuite/gfortran.dg/goacc/cray.f95           |  3 +-
 gcc/testsuite/gfortran.dg/goacc/loop-1.f95         |  7 ++-
 .../testsuite/libgomp.oacc-c-c++-common/cache-1.c  | 49 +---------------
 libgomp/testsuite/libgomp.oacc-fortran/cache-1.f95 |  5 ++
 13 files changed, 66 insertions(+), 179 deletions(-)



Grüße
 Thomas

Comments

Thomas Schwinge June 8, 2016, 1:28 p.m. UTC | #1
Hi!

Ping.

On Thu, 2 Jun 2016 13:47:08 +0200, I wrote:
> On Wed, 05 Nov 2014 17:29:19 +0100, I wrote:
> > In r217145, I applied Jim's patch to gomp-4_0-branch:
> > 
> > commit 4361f9b6b2c74c2961c3a5290a4945abe2d7a444
> > Author: tschwinge <tschwinge@138bc75d-0d04-0410-961f-82ee72b054a4>
> > Date:   Wed Nov 5 16:26:47 2014 +0000
> > 
> >     OpenACC cache directive for C.
> 
> (That, and the corresponding C++ changes later made it into trunk.)
> 
> > --- gcc/c/c-parser.c
> > +++ gcc/c/c-parser.c
> > @@ -10053,6 +10053,14 @@ c_parser_omp_variable_list (c_parser *parser,
> >  	{
> >  	  switch (kind)
> >  	    {
> > +	    case OMP_NO_CLAUSE_CACHE:
> > +	      if (c_parser_peek_token (parser)->type != CPP_OPEN_SQUARE)
> > +		{
> > +		  c_parser_error (parser, "expected %<[%>");
> > +		  t = error_mark_node;
> > +		  break;
> > +		}
> > +	      /* FALL THROUGH.  */
> >  	    case OMP_CLAUSE_MAP:
> >  	    case OMP_CLAUSE_FROM:
> >  	    case OMP_CLAUSE_TO:
> 
> Strictly speaking (OpenACC 2.0a specification), that is correct: the
> OpenACC cache directive explicitly only allows "array elements or
> subarrays".  However, I wonder if it would make sense to allow complete
> arrays as a GNU extension?  That is, syntactic sugar to allow "cache (a)"
> to mean "cache (a[0:LENGTH])"?
> 
> > @@ -10091,6 +10099,29 @@ c_parser_omp_variable_list (c_parser *parser,
> >  		      t = error_mark_node;
> >  		      break;
> >  		    }
> > +
> > +		  if (kind == OMP_NO_CLAUSE_CACHE)
> > +		    {
> > +		      mark_exp_read (low_bound);
> > +		      mark_exp_read (length);
> > +
> > +		      if (TREE_CODE (low_bound) != INTEGER_CST
> > +			  && !TREE_READONLY (low_bound))
> > +			{
> > +			  error_at (clause_loc,
> > +					"%qD is not a constant", low_bound);
> > +			  t = error_mark_node;
> > +			}
> 
> WHile OpenACC 2.0a specifies that "the lower bound is a constant", it
> also permits the lower bound to be a "loop invariant, or the for loop
> index variable plus or minus a constant or loop invariant".  So, we're
> rejecting valid syntax here.
> 
> > +
> > +		      if (TREE_CODE (length) != INTEGER_CST
> > +			  && !TREE_READONLY (length))
> > +			{
> > +			  error_at (clause_loc,
> > +					"%qD is not a constant", length);
> > +			  t = error_mark_node;
> > +			}
> > +		    }
> 
> The idea is correct (OpenACC 2.0a: "the length is a constant"), but we
> can't reliably check that here; for example:
> 
>     #pragma acc cache (a[0:n + 1])
> 
> ... will run into an ICE, "tree check: expected tree that contains 'decl
> minimal' structure, have 'plus_expr' in [...]".
> 
> Currently we're discarding the OpenACC cache directive in the middle end;
> I expect checking of the lower bound and length will come automatically
> as soon as we start to do something with OACC_CACHE/OMP_CLAUSE__CACHE_.
> Until then, I propose we simple remove these checks from the front ends.
> OK for trunk and gcc-6-branch?
> 
> commit a620ebe6fa509ec6441ba87276e55078eb2d00fc
> Author: Thomas Schwinge <thomas@codesourcery.com>
> Date:   Thu Jun 2 12:19:49 2016 +0200
> 
>     [PR c/71381] C/C++ OpenACC cache directive rejects valid syntax
>     
>     	gcc/c/
>     	PR c/71381
>     	* c-parser.c (c_parser_omp_variable_list) <OMP_CLAUSE__CACHE_>:
>     	Loosen checking.
>     	gcc/cp/
>     	PR c/71381
>     	* parser.c (cp_parser_omp_var_list_no_open) <OMP_CLAUSE__CACHE_>:
>     	Loosen checking.
>     	gcc/fortran/
>     	PR c/71381
>     	* openmp.c (gfc_match_oacc_cache): Add comment.
>     	gcc/testsuite/
>     	PR c/71381
>     	* c-c++-common/goacc/cache-1.c: Update.  Move invalid usage tests
>     	to...
>     	* c-c++-common/goacc/cache-2.c: ... this new file.
>     	* gfortran.dg/goacc/cache-1.f95: Move invalid usage tests to...
>     	* gfortran.dg/goacc/cache-2.f95: ... this new file.
>     	* gfortran.dg/goacc/coarray.f95: Update OpenACC cache directive
>     	usage.
>     	* gfortran.dg/goacc/cray.f95: Likewise.
>     	* gfortran.dg/goacc/loop-1.f95: Likewise.
>     	libgomp/
>     	PR c/71381
>     	* testsuite/libgomp.oacc-c-c++-common/cache-1.c: #include
>     	"../../../gcc/testsuite/c-c++-common/goacc/cache-1.c".
>     	* testsuite/libgomp.oacc-fortran/cache-1.f95: New file.
>     
>     	gcc/
>     	* omp-low.c (scan_sharing_clauses): Don't expect
>     	OMP_CLAUSE__CACHE_.
> ---
>  gcc/c/c-parser.c                                   | 22 +-------
>  gcc/cp/parser.c                                    | 22 +-------
>  gcc/fortran/openmp.c                               |  5 ++
>  gcc/omp-low.c                                      |  6 --
>  gcc/testsuite/c-c++-common/goacc/cache-1.c         | 66 ++++++++--------------
>  .../c-c++-common/goacc/{cache-1.c => cache-2.c}    | 39 ++-----------
>  gcc/testsuite/gfortran.dg/goacc/cache-1.f95        |  7 +--
>  gcc/testsuite/gfortran.dg/goacc/cache-2.f95        | 12 ++++
>  gcc/testsuite/gfortran.dg/goacc/coarray.f95        |  2 +-
>  gcc/testsuite/gfortran.dg/goacc/cray.f95           |  3 +-
>  gcc/testsuite/gfortran.dg/goacc/loop-1.f95         |  7 ++-
>  .../testsuite/libgomp.oacc-c-c++-common/cache-1.c  | 49 +---------------
>  libgomp/testsuite/libgomp.oacc-fortran/cache-1.f95 |  5 ++
>  13 files changed, 66 insertions(+), 179 deletions(-)
> 
> diff --git gcc/c/c-parser.c gcc/c/c-parser.c
> index bca8653..1db1886 100644
> --- gcc/c/c-parser.c
> +++ gcc/c/c-parser.c
> @@ -10601,6 +10601,9 @@ c_parser_omp_variable_list (c_parser *parser,
>  	  switch (kind)
>  	    {
>  	    case OMP_CLAUSE__CACHE_:
> +	      /* The OpenACC cache directive explicitly only allows "array
> +		 elements or subarrays".  Would it make sense to allow complete
> +		 arrays as a GNU extension?  */
>  	      if (c_parser_peek_token (parser)->type != CPP_OPEN_SQUARE)
>  		{
>  		  c_parser_error (parser, "expected %<[%>");
> @@ -10663,25 +10666,6 @@ c_parser_omp_variable_list (c_parser *parser,
>  		      break;
>  		    }
>  
> -		  if (kind == OMP_CLAUSE__CACHE_)
> -		    {
> -		      if (TREE_CODE (low_bound) != INTEGER_CST
> -			  && !TREE_READONLY (low_bound))
> -			{
> -			  error_at (clause_loc,
> -				    "%qD is not a constant", low_bound);
> -			  t = error_mark_node;
> -			}
> -
> -		      if (TREE_CODE (length) != INTEGER_CST
> -			  && !TREE_READONLY (length))
> -			{
> -			  error_at (clause_loc,
> -				    "%qD is not a constant", length);
> -			  t = error_mark_node;
> -			}
> -		    }
> -
>  		  t = tree_cons (low_bound, length, t);
>  		}
>  	      break;
> diff --git gcc/cp/parser.c gcc/cp/parser.c
> index 29a1b80..826277d 100644
> --- gcc/cp/parser.c
> +++ gcc/cp/parser.c
> @@ -29984,6 +29984,9 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
>  	  switch (kind)
>  	    {
>  	    case OMP_CLAUSE__CACHE_:
> +	      /* The OpenACC cache directive explicitly only allows "array
> +		 elements or subarrays".  Would it make sense to allow complete
> +		 arrays as a GNU extension?  */
>  	      if (cp_lexer_peek_token (parser->lexer)->type != CPP_OPEN_SQUARE)
>  		{
>  		  error_at (token->location, "expected %<[%>");
> @@ -30035,25 +30038,6 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
>  					  RT_CLOSE_SQUARE))
>  		    goto skip_comma;
>  
> -		  if (kind == OMP_CLAUSE__CACHE_)
> -		    {
> -		      if (TREE_CODE (low_bound) != INTEGER_CST
> -			  && !TREE_READONLY (low_bound))
> -			{
> -			  error_at (token->location,
> -				    "%qD is not a constant", low_bound);
> -			  decl = error_mark_node;
> -			}
> -
> -		      if (TREE_CODE (length) != INTEGER_CST
> -			  && !TREE_READONLY (length))
> -			{
> -			  error_at (token->location,
> -				    "%qD is not a constant", length);
> -			  decl = error_mark_node;
> -			}
> -		    }
> -
>  		  decl = tree_cons (low_bound, length, decl);
>  		}
>  	      break;
> diff --git gcc/fortran/openmp.c gcc/fortran/openmp.c
> index 2689d30..d97c193 100644
> --- gcc/fortran/openmp.c
> +++ gcc/fortran/openmp.c
> @@ -1688,6 +1688,11 @@ match
>  gfc_match_oacc_cache (void)
>  {
>    gfc_omp_clauses *c = gfc_get_omp_clauses ();
> +  /* The OpenACC cache directive explicitly only allows "array elements or
> +     subarrays", which we're currently not checking here.  Either check this
> +     after the call of gfc_match_omp_variable_list, or add something like a
> +     only_sections variant next to its allow_sections parameter.  Or, would it
> +     make sense to allow complete arrays as a GNU extension?  */
>    match m = gfc_match_omp_variable_list (" (",
>  					 &c->lists[OMP_LIST_CACHE], true,
>  					 NULL, NULL, true);
> diff --git gcc/omp-low.c gcc/omp-low.c
> index 77bdb18..91d5fcf 100644
> --- gcc/omp-low.c
> +++ gcc/omp-low.c
> @@ -2201,9 +2201,6 @@ scan_sharing_clauses (tree clauses, omp_context *ctx,
>  	  break;
>  
>  	case OMP_CLAUSE__CACHE_:
> -	  sorry ("Clause not supported yet");
> -	  break;
> -
>  	default:
>  	  gcc_unreachable ();
>  	}
> @@ -2368,9 +2365,6 @@ scan_sharing_clauses (tree clauses, omp_context *ctx,
>  	  break;
>  
>  	case OMP_CLAUSE__CACHE_:
> -	  sorry ("Clause not supported yet");
> -	  break;
> -
>  	default:
>  	  gcc_unreachable ();
>  	}
> diff --git gcc/testsuite/c-c++-common/goacc/cache-1.c gcc/testsuite/c-c++-common/goacc/cache-1.c
> index 9503341..1d4759e 100644
> --- gcc/testsuite/c-c++-common/goacc/cache-1.c
> +++ gcc/testsuite/c-c++-common/goacc/cache-1.c
> @@ -1,3 +1,7 @@
> +/* OpenACC cache directive: valid usage.  */
> +/* For execution testing, this file is "#include"d from
> +   libgomp/testsuite/libgomp.oacc-c-c++-common/cache-1.c.  */
> +
>  int
>  main (int argc, char **argv)
>  {
> @@ -21,57 +25,31 @@ main (int argc, char **argv)
>          int n = 1;
>          const int len = n;
>  
> -#pragma acc cache /* { dg-error "expected '\\\(' before end of line" } */
> -
> -#pragma acc cache a[0:N] /* { dg-error "expected '\\\(' before 'a'" } */
> -	/* { dg-bogus "expected end of line before 'a'" "" { xfail c++ } 26 } */
> -
> -#pragma acc cache (a) /* { dg-error "expected '\\\['" } */
> -
> -#pragma acc cache ( /* { dg-error "expected (identifier|unqualified-id) before end of line" } */
> -
> -#pragma acc cache () /* { dg-error "expected (identifier|unqualified-id) before '\\\)' token" } */
> -
> -#pragma acc cache (,) /* { dg-error "expected (identifier|unqualified-id) before '(,|\\\))' token" } */
> -
> -#pragma acc cache (a[0:N] /* { dg-error "expected '\\\)' before end of line" } */
> -
> -#pragma acc cache (a[0:N],) /* { dg-error "expected (identifier|unqualified-id) before '(,|\\\))' token" "" { xfail c } } */
> -
> -#pragma acc cache (a[0:N]) copyin (a[0:N]) /* { dg-error "expected end of line before 'copyin'" } */
> -
> -#pragma acc cache () /* { dg-error "expected (identifier|unqualified-id) before '\\\)' token" } */
> -
> -#pragma acc cache (a[0:N] b[0:N]) /* { dg-error "expected '\\\)' before 'b'" } */
> -
> -#pragma acc cache (a[0:N] b[0:N}) /* { dg-error "expected '\\\)' before 'b'" } */
> -	/* { dg-bogus "expected end of line before '\\\}' token" "" { xfail c++ } 47 } */
> -
> -#pragma acc cache (a[0:N] /* { dg-error "expected '\\\)' before end of line" } */
> -
> -#pragma acc cache (a[ii]) /* { dg-error "'ii' is not a constant" } */
> -
> -#pragma acc cache (a[idx:n]) /* { dg-error "'n' is not a constant" } */
> -
> -#pragma acc cache (a[0:N]) ( /* { dg-error "expected end of line before '\\(' token" } */
> -
> -#pragma acc cache (a[0:N]) ii /* { dg-error "expected end of line before 'ii'" } */
> -
> -#pragma acc cache (a[0:N] ii) /* { dg-error "expected '\\)' before 'ii'" } */
> -
> +	/* Have at it, GCC!  */
>  #pragma acc cache (a[0:N])
> -
>  #pragma acc cache (a[0:N], a[0:N])
> -
>  #pragma acc cache (a[0:N], b[0:N])
> -
>  #pragma acc cache (a[0])
> -
>  #pragma acc cache (a[0], a[1], b[0:N])
> -
> +#pragma acc cache (a[i - 5])
> +#pragma acc cache (a[i + 5:len])
> +#pragma acc cache (a[i + 5:len - 1])
> +#pragma acc cache (b[i])
> +#pragma acc cache (b[i:len])
> +#pragma acc cache (a[ii])
> +#pragma acc cache (a[ii:len])
> +#pragma acc cache (b[ii - 1])
> +#pragma acc cache (b[ii - 1:len])
> +#pragma acc cache (b[i - ii + 1])
> +#pragma acc cache (b[i + ii - 1:len])
> +#pragma acc cache (b[i * ii - 1:len + 1])
> +#pragma acc cache (a[idx + 2])
> +#pragma acc cache (a[idx:len + 2])
>  #pragma acc cache (a[idx])
> -
>  #pragma acc cache (a[idx:len])
> +#pragma acc cache (a[idx + 2:len])
> +#pragma acc cache (a[idx + 2 + i:len])
> +#pragma acc cache (a[idx + 2 + i + ii:len])
>  
>          b[ii] = a[ii];
>      }
> diff --git gcc/testsuite/c-c++-common/goacc/cache-1.c gcc/testsuite/c-c++-common/goacc/cache-2.c
> similarity index 83%
> copy from gcc/testsuite/c-c++-common/goacc/cache-1.c
> copy to gcc/testsuite/c-c++-common/goacc/cache-2.c
> index 9503341..f717515 100644
> --- gcc/testsuite/c-c++-common/goacc/cache-1.c
> +++ gcc/testsuite/c-c++-common/goacc/cache-2.c
> @@ -1,3 +1,5 @@
> +/* OpenACC cache directive: invalid usage.  */
> +
>  int
>  main (int argc, char **argv)
>  {
> @@ -22,57 +24,24 @@ main (int argc, char **argv)
>          const int len = n;
>  
>  #pragma acc cache /* { dg-error "expected '\\\(' before end of line" } */
> -
>  #pragma acc cache a[0:N] /* { dg-error "expected '\\\(' before 'a'" } */
> -	/* { dg-bogus "expected end of line before 'a'" "" { xfail c++ } 26 } */
> -
> +	/* { dg-bogus "expected end of line before 'a'" "" { xfail c++ } 27 } */
>  #pragma acc cache (a) /* { dg-error "expected '\\\['" } */
> -
>  #pragma acc cache ( /* { dg-error "expected (identifier|unqualified-id) before end of line" } */
> -
>  #pragma acc cache () /* { dg-error "expected (identifier|unqualified-id) before '\\\)' token" } */
> -
>  #pragma acc cache (,) /* { dg-error "expected (identifier|unqualified-id) before '(,|\\\))' token" } */
> -
>  #pragma acc cache (a[0:N] /* { dg-error "expected '\\\)' before end of line" } */
> -
>  #pragma acc cache (a[0:N],) /* { dg-error "expected (identifier|unqualified-id) before '(,|\\\))' token" "" { xfail c } } */
> -
>  #pragma acc cache (a[0:N]) copyin (a[0:N]) /* { dg-error "expected end of line before 'copyin'" } */
> -
>  #pragma acc cache () /* { dg-error "expected (identifier|unqualified-id) before '\\\)' token" } */
> -
>  #pragma acc cache (a[0:N] b[0:N]) /* { dg-error "expected '\\\)' before 'b'" } */
> -
>  #pragma acc cache (a[0:N] b[0:N}) /* { dg-error "expected '\\\)' before 'b'" } */
> -	/* { dg-bogus "expected end of line before '\\\}' token" "" { xfail c++ } 47 } */
> -
> +	/* { dg-bogus "expected end of line before '\\\}' token" "" { xfail c++ } 38 } */
>  #pragma acc cache (a[0:N] /* { dg-error "expected '\\\)' before end of line" } */
> -
> -#pragma acc cache (a[ii]) /* { dg-error "'ii' is not a constant" } */
> -
> -#pragma acc cache (a[idx:n]) /* { dg-error "'n' is not a constant" } */
> -
>  #pragma acc cache (a[0:N]) ( /* { dg-error "expected end of line before '\\(' token" } */
> -
>  #pragma acc cache (a[0:N]) ii /* { dg-error "expected end of line before 'ii'" } */
> -
>  #pragma acc cache (a[0:N] ii) /* { dg-error "expected '\\)' before 'ii'" } */
>  
> -#pragma acc cache (a[0:N])
> -
> -#pragma acc cache (a[0:N], a[0:N])
> -
> -#pragma acc cache (a[0:N], b[0:N])
> -
> -#pragma acc cache (a[0])
> -
> -#pragma acc cache (a[0], a[1], b[0:N])
> -
> -#pragma acc cache (a[idx])
> -
> -#pragma acc cache (a[idx:len])
> -
>          b[ii] = a[ii];
>      }
>  }
> diff --git gcc/testsuite/gfortran.dg/goacc/cache-1.f95 gcc/testsuite/gfortran.dg/goacc/cache-1.f95
> index 2aa9e05..39fbf2c 100644
> --- gcc/testsuite/gfortran.dg/goacc/cache-1.f95
> +++ gcc/testsuite/gfortran.dg/goacc/cache-1.f95
> @@ -1,4 +1,6 @@
> -! { dg-do compile }
> +! OpenACC cache directive: valid usage.
> +! For execution testing, this file is "#include"d from
> +! libgomp/testsuite/libgomp.oacc-fortran/cache-1.f95.
>  ! { dg-additional-options "-std=f2008" }
>  
>  program test
> @@ -6,11 +8,8 @@ program test
>    integer :: i, d(10), e(5,13)
>  
>    do concurrent (i=1:5)
> -    !$acc cache (d)
>      !$acc cache (d(1:3))
>      !$acc cache (d(i:i+2))
> -
> -    !$acc cache (e)
>      !$acc cache (e(1:3,2:4))
>      !$acc cache (e(i:i+2,i+1:i+3))
>    enddo
> diff --git gcc/testsuite/gfortran.dg/goacc/cache-2.f95 gcc/testsuite/gfortran.dg/goacc/cache-2.f95
> new file mode 100644
> index 0000000..be81878
> --- /dev/null
> +++ gcc/testsuite/gfortran.dg/goacc/cache-2.f95
> @@ -0,0 +1,12 @@
> +! OpenACC cache directive: invalid usage.
> +! { dg-additional-options "-std=f2008" }
> +
> +program test
> +  implicit none
> +  integer :: i, d(10), e(5,13)
> +
> +  do concurrent (i=1:5)
> +    !$acc cache (d) ! { dg-error "" "TODO" { xfail *-*-* } }
> +    !$acc cache (e) ! { dg-error "" "TODO" { xfail *-*-* } }
> +  enddo
> +end
> diff --git gcc/testsuite/gfortran.dg/goacc/coarray.f95 gcc/testsuite/gfortran.dg/goacc/coarray.f95
> index 932e1f7..f30917b8 100644
> --- gcc/testsuite/gfortran.dg/goacc/coarray.f95
> +++ gcc/testsuite/gfortran.dg/goacc/coarray.f95
> @@ -24,7 +24,7 @@ contains
>      !$acc end parallel loop
>      !$acc parallel loop
>      do i = 1,5
> -      !$acc cache (a)
> +      !$acc cache (a) ! { dg-error "" "TODO" { xfail *-*-* } }
>      enddo
>      !$acc end parallel loop
>      !$acc update device (a)
> diff --git gcc/testsuite/gfortran.dg/goacc/cray.f95 gcc/testsuite/gfortran.dg/goacc/cray.f95
> index a35ab0d..705c18c 100644
> --- gcc/testsuite/gfortran.dg/goacc/cray.f95
> +++ gcc/testsuite/gfortran.dg/goacc/cray.f95
> @@ -44,7 +44,8 @@ contains
>      !$acc end parallel loop
>      !$acc parallel loop
>      do i = 1,5
> -      !$acc cache (ptr) ! TODO: This must fail, as in openacc-1_0-branch
> +      !TODO: This must fail, as in openacc-1_0-branch.
> +      !$acc cache (ptr) ! { dg-error "" "TODO" { xfail *-*-* } }
>      enddo
>      !$acc end parallel loop
>      !$acc update device (ptr)
> diff --git gcc/testsuite/gfortran.dg/goacc/loop-1.f95 gcc/testsuite/gfortran.dg/goacc/loop-1.f95
> index b5f9e03..a605f03 100644
> --- gcc/testsuite/gfortran.dg/goacc/loop-1.f95
> +++ gcc/testsuite/gfortran.dg/goacc/loop-1.f95
> @@ -158,15 +158,16 @@ subroutine test1
>    enddo
>  
>  
> -  !$acc cache (a) ! { dg-error "inside of loop" }
> +  !$acc cache (a(1:10)) ! { dg-error "ACC CACHE directive must be inside of loop" }
>  
>    do i = 1,10
> -    !$acc cache(a)
> +    !$acc cache(a(i:i+1))
>    enddo
>  
>    do i = 1,10
> +    !$acc cache(a(i:i+1))
>      a(i) = i
> -    !$acc cache(a) 
> +    !$acc cache(a(i+2:i+2+1))
>    enddo
>  
>  end subroutine test1
> diff --git libgomp/testsuite/libgomp.oacc-c-c++-common/cache-1.c libgomp/testsuite/libgomp.oacc-c-c++-common/cache-1.c
> index 3f1f0bb..16aaed5 100644
> --- libgomp/testsuite/libgomp.oacc-c-c++-common/cache-1.c
> +++ libgomp/testsuite/libgomp.oacc-c-c++-common/cache-1.c
> @@ -1,48 +1,3 @@
> -int
> -main (int argc, char **argv)
> -{
> -#define N   2
> -    int a[N], b[N];
> -    int i;
> +/* OpenACC cache directive.  */
>  
> -    for (i = 0; i < N; i++)
> -    {
> -        a[i] = 3;
> -        b[i] = 0;
> -    }
> -
> -#pragma acc parallel copyin (a[0:N]) copyout (b[0:N])
> -{
> -    int ii;
> -
> -    for (ii = 0; ii < N; ii++)
> -    {
> -        const int idx = ii;
> -        int n = 1;
> -        const int len = n;
> -
> -#pragma acc cache (a[0:N])
> -
> -#pragma acc cache (a[0:N], b[0:N])
> -
> -#pragma acc cache (a[0])
> -
> -#pragma acc cache (a[0], a[1], b[0:N])
> -
> -#pragma acc cache (a[idx])
> -
> -#pragma acc cache (a[idx:len])
> -
> -        b[ii] = a[ii];
> -    }
> -}
> -
> -
> -    for (i = 0; i < N; i++)
> -    {
> -        if (a[i] != b[i])
> -            __builtin_abort ();
> -    }
> -
> -    return 0;
> -}
> +#include "../../../gcc/testsuite/c-c++-common/goacc/cache-1.c"
> diff --git libgomp/testsuite/libgomp.oacc-fortran/cache-1.f95 libgomp/testsuite/libgomp.oacc-fortran/cache-1.f95
> new file mode 100644
> index 0000000..a68c970
> --- /dev/null
> +++ libgomp/testsuite/libgomp.oacc-fortran/cache-1.f95
> @@ -0,0 +1,5 @@
> +! OpenACC cache directive.
> +! { dg-additional-options "-std=f2008" }
> +! { dg-additional-options "-cpp" }
> +
> +#include "../../../gcc/testsuite/gfortran.dg/goacc/cache-1.f95"


Grüße
 Thomas
Jakub Jelinek June 8, 2016, 2:07 p.m. UTC | #2
On Wed, Jun 08, 2016 at 03:28:57PM +0200, Thomas Schwinge wrote:
> >     [PR c/71381] C/C++ OpenACC cache directive rejects valid syntax
> >     
> >     	gcc/c/
> >     	PR c/71381
> >     	* c-parser.c (c_parser_omp_variable_list) <OMP_CLAUSE__CACHE_>:
> >     	Loosen checking.
> >     	gcc/cp/
> >     	PR c/71381
> >     	* parser.c (cp_parser_omp_var_list_no_open) <OMP_CLAUSE__CACHE_>:
> >     	Loosen checking.
> >     	gcc/fortran/
> >     	PR c/71381
> >     	* openmp.c (gfc_match_oacc_cache): Add comment.
> >     	gcc/testsuite/
> >     	PR c/71381
> >     	* c-c++-common/goacc/cache-1.c: Update.  Move invalid usage tests
> >     	to...
> >     	* c-c++-common/goacc/cache-2.c: ... this new file.
> >     	* gfortran.dg/goacc/cache-1.f95: Move invalid usage tests to...
> >     	* gfortran.dg/goacc/cache-2.f95: ... this new file.
> >     	* gfortran.dg/goacc/coarray.f95: Update OpenACC cache directive
> >     	usage.
> >     	* gfortran.dg/goacc/cray.f95: Likewise.
> >     	* gfortran.dg/goacc/loop-1.f95: Likewise.
> >     	libgomp/
> >     	PR c/71381
> >     	* testsuite/libgomp.oacc-c-c++-common/cache-1.c: #include
> >     	"../../../gcc/testsuite/c-c++-common/goacc/cache-1.c".
> >     	* testsuite/libgomp.oacc-fortran/cache-1.f95: New file.
> >     
> >     	gcc/
> >     	* omp-low.c (scan_sharing_clauses): Don't expect
> >     	OMP_CLAUSE__CACHE_.

Ok.

> > --- gcc/c/c-parser.c
> > +++ gcc/c/c-parser.c
> > @@ -10601,6 +10601,9 @@ c_parser_omp_variable_list (c_parser *parser,
> >  	  switch (kind)
> >  	    {
> >  	    case OMP_CLAUSE__CACHE_:
> > +	      /* The OpenACC cache directive explicitly only allows "array
> > +		 elements or subarrays".  Would it make sense to allow complete
> > +		 arrays as a GNU extension?  */

Please try to not add GNU extensions on top of OpenACC, unless strictly
necessary.
It is better if the compiler is strict and there is interoperability.
If you think it should accept something that it doesn't, talk to the OpenACC
committee.

	Jakub
diff mbox

Patch

diff --git gcc/c/c-parser.c gcc/c/c-parser.c
index bca8653..1db1886 100644
--- gcc/c/c-parser.c
+++ gcc/c/c-parser.c
@@ -10601,6 +10601,9 @@  c_parser_omp_variable_list (c_parser *parser,
 	  switch (kind)
 	    {
 	    case OMP_CLAUSE__CACHE_:
+	      /* The OpenACC cache directive explicitly only allows "array
+		 elements or subarrays".  Would it make sense to allow complete
+		 arrays as a GNU extension?  */
 	      if (c_parser_peek_token (parser)->type != CPP_OPEN_SQUARE)
 		{
 		  c_parser_error (parser, "expected %<[%>");
@@ -10663,25 +10666,6 @@  c_parser_omp_variable_list (c_parser *parser,
 		      break;
 		    }
 
-		  if (kind == OMP_CLAUSE__CACHE_)
-		    {
-		      if (TREE_CODE (low_bound) != INTEGER_CST
-			  && !TREE_READONLY (low_bound))
-			{
-			  error_at (clause_loc,
-				    "%qD is not a constant", low_bound);
-			  t = error_mark_node;
-			}
-
-		      if (TREE_CODE (length) != INTEGER_CST
-			  && !TREE_READONLY (length))
-			{
-			  error_at (clause_loc,
-				    "%qD is not a constant", length);
-			  t = error_mark_node;
-			}
-		    }
-
 		  t = tree_cons (low_bound, length, t);
 		}
 	      break;
diff --git gcc/cp/parser.c gcc/cp/parser.c
index 29a1b80..826277d 100644
--- gcc/cp/parser.c
+++ gcc/cp/parser.c
@@ -29984,6 +29984,9 @@  cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 	  switch (kind)
 	    {
 	    case OMP_CLAUSE__CACHE_:
+	      /* The OpenACC cache directive explicitly only allows "array
+		 elements or subarrays".  Would it make sense to allow complete
+		 arrays as a GNU extension?  */
 	      if (cp_lexer_peek_token (parser->lexer)->type != CPP_OPEN_SQUARE)
 		{
 		  error_at (token->location, "expected %<[%>");
@@ -30035,25 +30038,6 @@  cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 					  RT_CLOSE_SQUARE))
 		    goto skip_comma;
 
-		  if (kind == OMP_CLAUSE__CACHE_)
-		    {
-		      if (TREE_CODE (low_bound) != INTEGER_CST
-			  && !TREE_READONLY (low_bound))
-			{
-			  error_at (token->location,
-				    "%qD is not a constant", low_bound);
-			  decl = error_mark_node;
-			}
-
-		      if (TREE_CODE (length) != INTEGER_CST
-			  && !TREE_READONLY (length))
-			{
-			  error_at (token->location,
-				    "%qD is not a constant", length);
-			  decl = error_mark_node;
-			}
-		    }
-
 		  decl = tree_cons (low_bound, length, decl);
 		}
 	      break;
diff --git gcc/fortran/openmp.c gcc/fortran/openmp.c
index 2689d30..d97c193 100644
--- gcc/fortran/openmp.c
+++ gcc/fortran/openmp.c
@@ -1688,6 +1688,11 @@  match
 gfc_match_oacc_cache (void)
 {
   gfc_omp_clauses *c = gfc_get_omp_clauses ();
+  /* The OpenACC cache directive explicitly only allows "array elements or
+     subarrays", which we're currently not checking here.  Either check this
+     after the call of gfc_match_omp_variable_list, or add something like a
+     only_sections variant next to its allow_sections parameter.  Or, would it
+     make sense to allow complete arrays as a GNU extension?  */
   match m = gfc_match_omp_variable_list (" (",
 					 &c->lists[OMP_LIST_CACHE], true,
 					 NULL, NULL, true);
diff --git gcc/omp-low.c gcc/omp-low.c
index 77bdb18..91d5fcf 100644
--- gcc/omp-low.c
+++ gcc/omp-low.c
@@ -2201,9 +2201,6 @@  scan_sharing_clauses (tree clauses, omp_context *ctx,
 	  break;
 
 	case OMP_CLAUSE__CACHE_:
-	  sorry ("Clause not supported yet");
-	  break;
-
 	default:
 	  gcc_unreachable ();
 	}
@@ -2368,9 +2365,6 @@  scan_sharing_clauses (tree clauses, omp_context *ctx,
 	  break;
 
 	case OMP_CLAUSE__CACHE_:
-	  sorry ("Clause not supported yet");
-	  break;
-
 	default:
 	  gcc_unreachable ();
 	}
diff --git gcc/testsuite/c-c++-common/goacc/cache-1.c gcc/testsuite/c-c++-common/goacc/cache-1.c
index 9503341..1d4759e 100644
--- gcc/testsuite/c-c++-common/goacc/cache-1.c
+++ gcc/testsuite/c-c++-common/goacc/cache-1.c
@@ -1,3 +1,7 @@ 
+/* OpenACC cache directive: valid usage.  */
+/* For execution testing, this file is "#include"d from
+   libgomp/testsuite/libgomp.oacc-c-c++-common/cache-1.c.  */
+
 int
 main (int argc, char **argv)
 {
@@ -21,57 +25,31 @@  main (int argc, char **argv)
         int n = 1;
         const int len = n;
 
-#pragma acc cache /* { dg-error "expected '\\\(' before end of line" } */
-
-#pragma acc cache a[0:N] /* { dg-error "expected '\\\(' before 'a'" } */
-	/* { dg-bogus "expected end of line before 'a'" "" { xfail c++ } 26 } */
-
-#pragma acc cache (a) /* { dg-error "expected '\\\['" } */
-
-#pragma acc cache ( /* { dg-error "expected (identifier|unqualified-id) before end of line" } */
-
-#pragma acc cache () /* { dg-error "expected (identifier|unqualified-id) before '\\\)' token" } */
-
-#pragma acc cache (,) /* { dg-error "expected (identifier|unqualified-id) before '(,|\\\))' token" } */
-
-#pragma acc cache (a[0:N] /* { dg-error "expected '\\\)' before end of line" } */
-
-#pragma acc cache (a[0:N],) /* { dg-error "expected (identifier|unqualified-id) before '(,|\\\))' token" "" { xfail c } } */
-
-#pragma acc cache (a[0:N]) copyin (a[0:N]) /* { dg-error "expected end of line before 'copyin'" } */
-
-#pragma acc cache () /* { dg-error "expected (identifier|unqualified-id) before '\\\)' token" } */
-
-#pragma acc cache (a[0:N] b[0:N]) /* { dg-error "expected '\\\)' before 'b'" } */
-
-#pragma acc cache (a[0:N] b[0:N}) /* { dg-error "expected '\\\)' before 'b'" } */
-	/* { dg-bogus "expected end of line before '\\\}' token" "" { xfail c++ } 47 } */
-
-#pragma acc cache (a[0:N] /* { dg-error "expected '\\\)' before end of line" } */
-
-#pragma acc cache (a[ii]) /* { dg-error "'ii' is not a constant" } */
-
-#pragma acc cache (a[idx:n]) /* { dg-error "'n' is not a constant" } */
-
-#pragma acc cache (a[0:N]) ( /* { dg-error "expected end of line before '\\(' token" } */
-
-#pragma acc cache (a[0:N]) ii /* { dg-error "expected end of line before 'ii'" } */
-
-#pragma acc cache (a[0:N] ii) /* { dg-error "expected '\\)' before 'ii'" } */
-
+	/* Have at it, GCC!  */
 #pragma acc cache (a[0:N])
-
 #pragma acc cache (a[0:N], a[0:N])
-
 #pragma acc cache (a[0:N], b[0:N])
-
 #pragma acc cache (a[0])
-
 #pragma acc cache (a[0], a[1], b[0:N])
-
+#pragma acc cache (a[i - 5])
+#pragma acc cache (a[i + 5:len])
+#pragma acc cache (a[i + 5:len - 1])
+#pragma acc cache (b[i])
+#pragma acc cache (b[i:len])
+#pragma acc cache (a[ii])
+#pragma acc cache (a[ii:len])
+#pragma acc cache (b[ii - 1])
+#pragma acc cache (b[ii - 1:len])
+#pragma acc cache (b[i - ii + 1])
+#pragma acc cache (b[i + ii - 1:len])
+#pragma acc cache (b[i * ii - 1:len + 1])
+#pragma acc cache (a[idx + 2])
+#pragma acc cache (a[idx:len + 2])
 #pragma acc cache (a[idx])
-
 #pragma acc cache (a[idx:len])
+#pragma acc cache (a[idx + 2:len])
+#pragma acc cache (a[idx + 2 + i:len])
+#pragma acc cache (a[idx + 2 + i + ii:len])
 
         b[ii] = a[ii];
     }
diff --git gcc/testsuite/c-c++-common/goacc/cache-1.c gcc/testsuite/c-c++-common/goacc/cache-2.c
similarity index 83%
copy from gcc/testsuite/c-c++-common/goacc/cache-1.c
copy to gcc/testsuite/c-c++-common/goacc/cache-2.c
index 9503341..f717515 100644
--- gcc/testsuite/c-c++-common/goacc/cache-1.c
+++ gcc/testsuite/c-c++-common/goacc/cache-2.c
@@ -1,3 +1,5 @@ 
+/* OpenACC cache directive: invalid usage.  */
+
 int
 main (int argc, char **argv)
 {
@@ -22,57 +24,24 @@  main (int argc, char **argv)
         const int len = n;
 
 #pragma acc cache /* { dg-error "expected '\\\(' before end of line" } */
-
 #pragma acc cache a[0:N] /* { dg-error "expected '\\\(' before 'a'" } */
-	/* { dg-bogus "expected end of line before 'a'" "" { xfail c++ } 26 } */
-
+	/* { dg-bogus "expected end of line before 'a'" "" { xfail c++ } 27 } */
 #pragma acc cache (a) /* { dg-error "expected '\\\['" } */
-
 #pragma acc cache ( /* { dg-error "expected (identifier|unqualified-id) before end of line" } */
-
 #pragma acc cache () /* { dg-error "expected (identifier|unqualified-id) before '\\\)' token" } */
-
 #pragma acc cache (,) /* { dg-error "expected (identifier|unqualified-id) before '(,|\\\))' token" } */
-
 #pragma acc cache (a[0:N] /* { dg-error "expected '\\\)' before end of line" } */
-
 #pragma acc cache (a[0:N],) /* { dg-error "expected (identifier|unqualified-id) before '(,|\\\))' token" "" { xfail c } } */
-
 #pragma acc cache (a[0:N]) copyin (a[0:N]) /* { dg-error "expected end of line before 'copyin'" } */
-
 #pragma acc cache () /* { dg-error "expected (identifier|unqualified-id) before '\\\)' token" } */
-
 #pragma acc cache (a[0:N] b[0:N]) /* { dg-error "expected '\\\)' before 'b'" } */
-
 #pragma acc cache (a[0:N] b[0:N}) /* { dg-error "expected '\\\)' before 'b'" } */
-	/* { dg-bogus "expected end of line before '\\\}' token" "" { xfail c++ } 47 } */
-
+	/* { dg-bogus "expected end of line before '\\\}' token" "" { xfail c++ } 38 } */
 #pragma acc cache (a[0:N] /* { dg-error "expected '\\\)' before end of line" } */
-
-#pragma acc cache (a[ii]) /* { dg-error "'ii' is not a constant" } */
-
-#pragma acc cache (a[idx:n]) /* { dg-error "'n' is not a constant" } */
-
 #pragma acc cache (a[0:N]) ( /* { dg-error "expected end of line before '\\(' token" } */
-
 #pragma acc cache (a[0:N]) ii /* { dg-error "expected end of line before 'ii'" } */
-
 #pragma acc cache (a[0:N] ii) /* { dg-error "expected '\\)' before 'ii'" } */
 
-#pragma acc cache (a[0:N])
-
-#pragma acc cache (a[0:N], a[0:N])
-
-#pragma acc cache (a[0:N], b[0:N])
-
-#pragma acc cache (a[0])
-
-#pragma acc cache (a[0], a[1], b[0:N])
-
-#pragma acc cache (a[idx])
-
-#pragma acc cache (a[idx:len])
-
         b[ii] = a[ii];
     }
 }
diff --git gcc/testsuite/gfortran.dg/goacc/cache-1.f95 gcc/testsuite/gfortran.dg/goacc/cache-1.f95
index 2aa9e05..39fbf2c 100644
--- gcc/testsuite/gfortran.dg/goacc/cache-1.f95
+++ gcc/testsuite/gfortran.dg/goacc/cache-1.f95
@@ -1,4 +1,6 @@ 
-! { dg-do compile }
+! OpenACC cache directive: valid usage.
+! For execution testing, this file is "#include"d from
+! libgomp/testsuite/libgomp.oacc-fortran/cache-1.f95.
 ! { dg-additional-options "-std=f2008" }
 
 program test
@@ -6,11 +8,8 @@  program test
   integer :: i, d(10), e(5,13)
 
   do concurrent (i=1:5)
-    !$acc cache (d)
     !$acc cache (d(1:3))
     !$acc cache (d(i:i+2))
-
-    !$acc cache (e)
     !$acc cache (e(1:3,2:4))
     !$acc cache (e(i:i+2,i+1:i+3))
   enddo
diff --git gcc/testsuite/gfortran.dg/goacc/cache-2.f95 gcc/testsuite/gfortran.dg/goacc/cache-2.f95
new file mode 100644
index 0000000..be81878
--- /dev/null
+++ gcc/testsuite/gfortran.dg/goacc/cache-2.f95
@@ -0,0 +1,12 @@ 
+! OpenACC cache directive: invalid usage.
+! { dg-additional-options "-std=f2008" }
+
+program test
+  implicit none
+  integer :: i, d(10), e(5,13)
+
+  do concurrent (i=1:5)
+    !$acc cache (d) ! { dg-error "" "TODO" { xfail *-*-* } }
+    !$acc cache (e) ! { dg-error "" "TODO" { xfail *-*-* } }
+  enddo
+end
diff --git gcc/testsuite/gfortran.dg/goacc/coarray.f95 gcc/testsuite/gfortran.dg/goacc/coarray.f95
index 932e1f7..f30917b8 100644
--- gcc/testsuite/gfortran.dg/goacc/coarray.f95
+++ gcc/testsuite/gfortran.dg/goacc/coarray.f95
@@ -24,7 +24,7 @@  contains
     !$acc end parallel loop
     !$acc parallel loop
     do i = 1,5
-      !$acc cache (a)
+      !$acc cache (a) ! { dg-error "" "TODO" { xfail *-*-* } }
     enddo
     !$acc end parallel loop
     !$acc update device (a)
diff --git gcc/testsuite/gfortran.dg/goacc/cray.f95 gcc/testsuite/gfortran.dg/goacc/cray.f95
index a35ab0d..705c18c 100644
--- gcc/testsuite/gfortran.dg/goacc/cray.f95
+++ gcc/testsuite/gfortran.dg/goacc/cray.f95
@@ -44,7 +44,8 @@  contains
     !$acc end parallel loop
     !$acc parallel loop
     do i = 1,5
-      !$acc cache (ptr) ! TODO: This must fail, as in openacc-1_0-branch
+      !TODO: This must fail, as in openacc-1_0-branch.
+      !$acc cache (ptr) ! { dg-error "" "TODO" { xfail *-*-* } }
     enddo
     !$acc end parallel loop
     !$acc update device (ptr)
diff --git gcc/testsuite/gfortran.dg/goacc/loop-1.f95 gcc/testsuite/gfortran.dg/goacc/loop-1.f95
index b5f9e03..a605f03 100644
--- gcc/testsuite/gfortran.dg/goacc/loop-1.f95
+++ gcc/testsuite/gfortran.dg/goacc/loop-1.f95
@@ -158,15 +158,16 @@  subroutine test1
   enddo
 
 
-  !$acc cache (a) ! { dg-error "inside of loop" }
+  !$acc cache (a(1:10)) ! { dg-error "ACC CACHE directive must be inside of loop" }
 
   do i = 1,10
-    !$acc cache(a)
+    !$acc cache(a(i:i+1))
   enddo
 
   do i = 1,10
+    !$acc cache(a(i:i+1))
     a(i) = i
-    !$acc cache(a) 
+    !$acc cache(a(i+2:i+2+1))
   enddo
 
 end subroutine test1
diff --git libgomp/testsuite/libgomp.oacc-c-c++-common/cache-1.c libgomp/testsuite/libgomp.oacc-c-c++-common/cache-1.c
index 3f1f0bb..16aaed5 100644
--- libgomp/testsuite/libgomp.oacc-c-c++-common/cache-1.c
+++ libgomp/testsuite/libgomp.oacc-c-c++-common/cache-1.c
@@ -1,48 +1,3 @@ 
-int
-main (int argc, char **argv)
-{
-#define N   2
-    int a[N], b[N];
-    int i;
+/* OpenACC cache directive.  */
 
-    for (i = 0; i < N; i++)
-    {
-        a[i] = 3;
-        b[i] = 0;
-    }
-
-#pragma acc parallel copyin (a[0:N]) copyout (b[0:N])
-{
-    int ii;
-
-    for (ii = 0; ii < N; ii++)
-    {
-        const int idx = ii;
-        int n = 1;
-        const int len = n;
-
-#pragma acc cache (a[0:N])
-
-#pragma acc cache (a[0:N], b[0:N])
-
-#pragma acc cache (a[0])
-
-#pragma acc cache (a[0], a[1], b[0:N])
-
-#pragma acc cache (a[idx])
-
-#pragma acc cache (a[idx:len])
-
-        b[ii] = a[ii];
-    }
-}
-
-
-    for (i = 0; i < N; i++)
-    {
-        if (a[i] != b[i])
-            __builtin_abort ();
-    }
-
-    return 0;
-}
+#include "../../../gcc/testsuite/c-c++-common/goacc/cache-1.c"
diff --git libgomp/testsuite/libgomp.oacc-fortran/cache-1.f95 libgomp/testsuite/libgomp.oacc-fortran/cache-1.f95
new file mode 100644
index 0000000..a68c970
--- /dev/null
+++ libgomp/testsuite/libgomp.oacc-fortran/cache-1.f95
@@ -0,0 +1,5 @@ 
+! OpenACC cache directive.
+! { dg-additional-options "-std=f2008" }
+! { dg-additional-options "-cpp" }
+
+#include "../../../gcc/testsuite/gfortran.dg/goacc/cache-1.f95"