Patchwork [gomp4/cilk-in-gomp/cilkplus] C++ parsing for Cilk plus <#pragma simd>

login
register
mail settings
Submitter Iyer, Balaji V
Date May 21, 2013, 3:46 p.m.
Message ID <BF230D13CA30DD48930C31D4099330003A426AA6@FMSMSX101.amr.corp.intel.com>
Download mbox | patch
Permalink /patch/245334/
State New
Headers show

Comments

Iyer, Balaji V - May 21, 2013, 3:46 p.m.
Hello Aldy et al.,	
	Attached, please find a patch on top of gomp4 branch that implements Cilk's <#pragma simd> for C++. This is done in the same fashion as Aldy did in: http://gcc.gnu.org/ml/gcc-patches/2013-05/msg00678.html (It creates OMP_SIMD trees and let omp-low do the rest).

This patch should be applied on Aldy's branch aldyh/cilk-in-gomp. I have also included testsuite code that will catch several errors.

Aldy, is this OK for your branch?

Thanks,

Balaji V. Iyer.
Aldy Hernandez - May 28, 2013, 9:17 p.m.
On 05/21/13 10:46, Iyer, Balaji V wrote:

Thank you for working on this!

> static tree
> find_invalid_stmts (tree *tp, int *walk_subtrees, void *data)
> {
>   bool *valid = (bool *) data;
>   location_t loc = EXPR_HAS_LOCATION (*tp) ? EXPR_LOCATION (*tp) :
>     UNKNOWN_LOCATION;
>   if (!tp || !*tp)
>     return NULL_TREE;
>   else if (TREE_CODE (*tp) == GOTO_EXPR)
>     {
>       error_at (loc, "goto statements are not allowed inside "
>                 "loops marked with #pragma simd");
>       *valid = false;
>       *walk_subtrees = 0;
>     }

As I've said in the comment to the analogous C function 
(find_invalid_stmts_in_loops), you can't just check for GOTO_EXPRs, 
since they can also be generated by switches and other loop constructs. 
  I will later add some generic code to check this sometime after the 
CFG is built.  For now, you can remove the check for GOTO_EXPR.

>   else if (TREE_CODE (*tp) == CALL_EXPR)
>     {
>       tree fndecl = CALL_EXPR_FN (*tp);
>
>       if (TREE_CODE (fndecl) == ADDR_EXPR)
>         fndecl = TREE_OPERAND (fndecl, 0);
>       if (TREE_CODE (fndecl) == FUNCTION_DECL)
>         {
>           if (setjmp_call_p (fndecl))
>             {
>               error_at (loc, "setjmps are not allowed inside loops marked with"
>                         " #pragma simd");
>               *valid = false;
>               *walk_subtrees = 0;
>             }
>         }

This is already checked in the C counterpart.  Can't you just call 
find_invalid_stmts_in_loops() from find_invalid_stmts since it checks 
for everything C/C++ related?  Ideally your find_invalid_stmts() 
function should only check the C++ specific stuff (throw, try, etc) and 
call find_invalid_stmts_in_loops.


>  else if (TREE_CODE (*tp) == THROW_EXPR)
>     {
>       error_at (loc, "throw expressions are not allowed inside the loop "
>                 "marked with pragma simd");

s/the loop/loops

>   else if (TREE_CODE (*tp) == TRY_BLOCK)
>     {
>       error_at (loc, "try statements are not allowed inside loop marked with "

s/loop/loops

> bool
> p_simd_valid_stmts_in_body_p (tree body)

Is there a reason for the p_ prefix?  If not, could you remove it?

> @@ -29458,6 +29472,7 @@ cp_parser_initial_pragma (cp_token *first_token)
>    cp_lexer_get_preprocessor_token (NULL, first_token);
>  }
>
> +
>  /* Normal parsing of a pragma token.  Here we can (and must) use the
>     regular lexer.  */

Whitespace.

> @@ -29605,6 +29620,11 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
>  		"%<#pragma omp sections%> construct");
>        break;
>
> +    case PRAGMA_CILK_SIMD:
> +      if (context == pragma_external)
> +	goto bad_stmt;
> +      cp_parser_cilk_simd_construct (parser, pragma_tok);
> +      return true;
>      default:
>

Please add an empty line after the return, since the previous code had a 
space there.

Can you put all the cp_parser_cilk_for* functions before 
cp_parser_cilk_simd_vectorlength and avoid the prototype for 
cp_parser_cilk_for?  Just curious, I don't know if there are any 
dependencies I'm not seeing.

> +/* Main entry-point for parsing Cilk Plus <#pragma simd> for loop.  */

s/loop/loops

> +  /* #pragma simd is build on top of OpenMP 4.0's OMP_SIMD treees.  Thus
> +     openmp must be enabled.  */

s/build/built
s/treees/trees
s/openmp/OpenMP

> +/* Returns the name of the next clause.  If the clause is not recognized, then
> +   PRAGMA_CILK_CLAUSE_NONE is returned and the next token is not consumed.
> +   Otherwise, the appropriate enum. value from the pragma_simd_clause is
> +   returned and the token is consumed.  */
> +
> +static pragma_cilk_clause
> +cp_parser_cilk_simd_clause_name (cp_parser *parser, tree *name)


Replace "enum. value" with "enum".

Also, you are not documenting the NAME argument.

> +  /* Vectorlength clause behaves exactly like Open MP 4.0's safelen clause.

s/Vectorlength/The vectorlength

Regarding the tests, I will merge trunk->cilk-in-gomp so we can reuse 
the c-c++-common infrastructure you wrote.  There is no sense having 
multiple tests for vectorlength, linear, etc.

Aldy
Iyer, Balaji V - May 28, 2013, 9:20 p.m.
> 
> Regarding the tests, I will merge trunk->cilk-in-gomp so we can reuse the c-c++-
> common infrastructure you wrote.  There is no sense having multiple tests for
> vectorlength, linear, etc.

Can you please add them under c-c++-common/cilk-plus/PS directory?

AN = Array Notation
PS = Pragma SIMD
CK = Cilk Keywords
EF = Elemental function.

This way, we don't have to monkey with the existing gcc.dg/cilk-plus/cilk-plus.exp script.

Thanks,
Balaji V. Iyer.

> 
> Aldy
Aldy Hernandez - May 28, 2013, 9:21 p.m.
On 05/28/13 16:20, Iyer, Balaji V wrote:
>>
>> Regarding the tests, I will merge trunk->cilk-in-gomp so we can reuse the c-c++-
>> common infrastructure you wrote.  There is no sense having multiple tests for
>> vectorlength, linear, etc.
>
> Can you please add them under c-c++-common/cilk-plus/PS directory?
>
> AN = Array Notation
> PS = Pragma SIMD
> CK = Cilk Keywords
> EF = Elemental function.

Sure can.

>
> This way, we don't have to monkey with the existing gcc.dg/cilk-plus/cilk-plus.exp script.

Thanks.  I'll get on this tomorrow.
Aldy Hernandez - May 29, 2013, 8 p.m.
On 05/28/13 16:20, Iyer, Balaji V wrote:
>>
>> Regarding the tests, I will merge trunk->cilk-in-gomp so we can reuse the c-c++-
>> common infrastructure you wrote.  There is no sense having multiple tests for
>> vectorlength, linear, etc.
>
> Can you please add them under c-c++-common/cilk-plus/PS directory?
>
> AN = Array Notation
> PS = Pragma SIMD
> CK = Cilk Keywords
> EF = Elemental function.
>
> This way, we don't have to monkey with the existing gcc.dg/cilk-plus/cilk-plus.exp script.
>
> Thanks,
> Balaji V. Iyer.
>
>>
>> Aldy

On second thought, it looks like you'll be busy working on the fallout 
from the array notation work.  I can take over this entire patch, fix 
things, and re-post the final version before committing to the branch.

Thanks for contributing this!

Aldy

Patch

diff --git gcc/ChangeLog.cilkplus gcc/ChangeLog.cilkplus
index 5e9fb79..8a7ed94 100644
--- gcc/ChangeLog.cilkplus
+++ gcc/ChangeLog.cilkplus
@@ -1,3 +1,8 @@ 
+2013-05-21  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+testsuite/
+	* g++.dg/cilk-plus: New directory and associated infrastructure.
+
 2013-05-13  Aldy Hernandez  <aldyh@redhat.com>
 
 	* Makefile.in (C_COMMON_OBJS): Depend on c-family/c-cilkplus.o.
diff --git gcc/cp/ChangeLog.cilkplus gcc/cp/ChangeLog.cilkplus
new file mode 100755
index 0000000..7254b81
--- /dev/null
+++ gcc/cp/ChangeLog.cilkplus
@@ -0,0 +1,18 @@ 
+2013-05-21  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* cp-tree.h (p_simd_valid_stmts_in_body_p): New prototype.
+	* parser.h (IN_CILK_P_SIMD_FOR): New #define.
+	* Make-lang.in (CXX_AND_OBJCXX_OBJS): Added new obj-file cp-cilkplus.o
+	* cp-cilkplus.c: New file.
+	* parser.c (cp_parser_pragma): Added a PRAGMA_CILK_SIMD case.
+	(cp_parser_cilk_simd_vectorlength): New function.
+	(cp_parser_cilk_simd_linear): Likewise.
+	(cp_parser_cilk_simd_clause_name): Likewise.
+	(cp_parser_cilk_simd_all_clauses): Likewise.
+	(cp_parser_cilk_simd_construct): Likewise.
+	(cp_parser_simd_for_init_statement): Likewise.
+	(cp_parser_cilk_for_expression_iterator): Likewise.
+	(cp_parser_cilk_for_condition): Likewise.
+	(cp_parser_cilk_for): Likewise.
+	(cp_parser_jump_statement): Added a IN_CILK_P_SIMD_FOR case.
+
diff --git gcc/cp/Make-lang.in gcc/cp/Make-lang.in
index cda4897..55ed6d4 100644
--- gcc/cp/Make-lang.in
+++ gcc/cp/Make-lang.in
@@ -80,7 +80,7 @@  CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
  cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \
  cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \
  cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o \
- cp/cp-gimplify.o $(CXX_C_OBJS)
+ cp/cp-gimplify.o cp/cp-cilkplus.o $(CXX_C_OBJS)
 
 # Language-specific object files for C++.
 CXX_OBJS = cp/cp-lang.o c-family/stub-objc.o $(CXX_AND_OBJCXX_OBJS)
@@ -345,3 +345,5 @@  cp/name-lookup.o: cp/name-lookup.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
 
 cp/cxx-pretty-print.o: cp/cxx-pretty-print.c $(CXX_PRETTY_PRINT_H) \
   $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h $(CXX_TREE_H) tree-pretty-print.h
+cp/cp-cilkplus.o: cp/cp-cilkplus.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+    $(CXX_TREE_H) $(DIAGNOSTIC_CORE_H)
diff --git gcc/cp/cp-cilkplus.c gcc/cp/cp-cilkplus.c
new file mode 100755
index 0000000..118fd58
--- /dev/null
+++ gcc/cp/cp-cilkplus.c
@@ -0,0 +1,98 @@ 
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+   This file contains routines to handle Cilk Plus specific
+   routines for the C++ Compiler.
+   Copyright (C) 2013  Free Software Foundation, Inc.
+   Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+		  Aldy Hernandez <aldyh@redhat.com>.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "cp-tree.h"
+#include "diagnostic-core.h"
+
+
+/* This function is passed in as a function pointer to walk_tree.  *TP is
+   the current tree pointer, *WALK_SUBTREES is set to 0 by this function if
+   recursing into TP's subtrees is unnecessary. *DATA is a bool variable that
+   is set to false if an error has occured.  */
+
+static tree
+find_invalid_stmts (tree *tp, int *walk_subtrees, void *data)
+{
+  bool *valid = (bool *) data;
+  location_t loc = EXPR_HAS_LOCATION (*tp) ? EXPR_LOCATION (*tp) :
+    UNKNOWN_LOCATION;
+  if (!tp || !*tp)
+    return NULL_TREE;
+  else if (TREE_CODE (*tp) == GOTO_EXPR)
+    {
+      error_at (loc, "goto statements are not allowed inside "
+		"loops marked with #pragma simd");
+      *valid = false;
+      *walk_subtrees = 0;
+    }
+  else if (TREE_CODE (*tp) == THROW_EXPR)
+    {
+      error_at (loc, "throw expressions are not allowed inside the loop "
+		"marked with pragma simd");
+      *walk_subtrees = 0;
+      *valid = false;
+    }
+  else if (TREE_CODE (*tp) == TRY_BLOCK)
+    {
+      error_at (loc, "try statements are not allowed inside loop marked with "
+		"#pragma simd");
+      *valid = false;
+      *walk_subtrees = 0;
+    }
+  else if (TREE_CODE (*tp) == CALL_EXPR)
+    {
+      tree fndecl = CALL_EXPR_FN (*tp);
+
+      if (TREE_CODE (fndecl) == ADDR_EXPR)
+	fndecl = TREE_OPERAND (fndecl, 0);
+      if (TREE_CODE (fndecl) == FUNCTION_DECL)
+	{
+	  if (setjmp_call_p (fndecl))
+	    {
+	      error_at (loc, "setjmps are not allowed inside loops marked with"
+			" #pragma simd");
+	      *valid = false;
+	      *walk_subtrees = 0;
+	    }
+	}
+    }
+    /* FIXME: Add a check for TREE_CODE (*tp) == CILK_FOR_STMT and flag them as
+       invalid when cilk keywords are adopted.  */
+  return NULL_TREE;
+}  
+
+
+/* Walks through all the subtrees of BODY using walk_tree to make sure invalid
+   statements/expressions are not found inside BODY.  Returns false if any
+   invalid statements are found.  */
+
+bool
+p_simd_valid_stmts_in_body_p (tree body)
+{
+  bool valid = true;
+  cp_walk_tree (&body, find_invalid_stmts, (void *) &valid, NULL);
+  return valid;
+}
diff --git gcc/cp/cp-tree.h gcc/cp/cp-tree.h
old mode 100644
new mode 100755
index 1e2230b..7c0cfeb
--- gcc/cp/cp-tree.h
+++ gcc/cp/cp-tree.h
@@ -6140,6 +6140,9 @@  extern bool cxx_omp_privatize_by_reference	(const_tree);
 extern void suggest_alternatives_for            (location_t, tree);
 extern tree strip_using_decl                    (tree);
 
+/* in cp-cilkplus.c */
+extern bool p_simd_valid_stmts_in_body_p        (tree);
+
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
diff --git gcc/cp/parser.c gcc/cp/parser.c
old mode 100644
new mode 100755
index 8882a83..1dba40f
--- gcc/cp/parser.c
+++ gcc/cp/parser.c
@@ -231,6 +231,12 @@  static void cp_parser_initial_pragma
 static tree cp_literal_operator_id
   (const char *);
 
+static void cp_parser_cilk_simd_construct
+  (cp_parser *, cp_token *);
+static tree cp_parser_cilk_for
+  (cp_parser *, enum rid, tree);
+
+
 /* Manifest constants.  */
 #define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token))
 #define CP_SAVED_TOKEN_STACK 5
@@ -10297,6 +10303,10 @@  cp_parser_jump_statement (cp_parser* parser)
 	case IN_OMP_FOR:
 	  error_at (token->location, "break statement used with OpenMP for loop");
 	  break;
+	case IN_CILK_P_SIMD_FOR:
+	  error_at (token->location, "break statements are not allowed inside"  
+		    " <#pragma simd> loop body");
+	  break;
 	}
       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
       break;
@@ -10314,6 +10324,10 @@  cp_parser_jump_statement (cp_parser* parser)
 	case IN_OMP_BLOCK:
 	  error_at (token->location, "invalid exit from OpenMP structured block");
 	  break;
+	case IN_CILK_P_SIMD_FOR:
+	  error_at (token->location, "continue statements are not allowed" 
+		    " inside <#pragma simd> loop body");
+	  break;
 	default:
 	  gcc_unreachable ();
 	}
@@ -29458,6 +29472,7 @@  cp_parser_initial_pragma (cp_token *first_token)
   cp_lexer_get_preprocessor_token (NULL, first_token);
 }
 
+
 /* Normal parsing of a pragma token.  Here we can (and must) use the
    regular lexer.  */
 
@@ -29605,6 +29620,11 @@  cp_parser_pragma (cp_parser *parser, enum pragma_context context)
 		"%<#pragma omp sections%> construct");
       break;
 
+    case PRAGMA_CILK_SIMD:
+      if (context == pragma_external)
+	goto bad_stmt;
+      cp_parser_cilk_simd_construct (parser, pragma_tok);
+      return true;
     default:
       gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
       c_invoke_pragma_handler (id);
@@ -29670,4 +29690,663 @@  c_parse_file (void)
   the_parser = NULL;
 }
 
+
+/* Parses the Cilk Plus #pragma simd vectorlength clause:
+   Syntax:
+   vectorlength ( constant-expression )  */
+
+static tree
+cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses)
+{
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+  tree expr;
+  /* Vectorlength clause behaves exactly like Open MP 4.0's safelen clause.
+     Thus, vectorlength is represented as OMP 4.0 safelen.  */
+  check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength", loc);
+  
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+    return error_mark_node;
+  
+  expr = cp_parser_constant_expression (parser, false, NULL);
+  expr = fold_non_dependent_expr (expr);
+
+  if (!TREE_TYPE (expr) || !TREE_CONSTANT (expr)
+      || TREE_CODE (expr) == VAR_DECL || TREE_CODE (expr) == PARM_DECL
+      || !INTEGRAL_TYPE_P (TREE_TYPE (expr)))
+    error_at (loc, "vectorlength must be an integer constant");
+  else if (exact_log2 (TREE_INT_CST_LOW (expr)) == -1)
+    error_at (loc, "vectorlength must be a power of 2");
+  else
+    {
+      tree c = build_omp_clause (loc, OMP_CLAUSE_SAFELEN);
+      OMP_CLAUSE_SAFELEN_EXPR (c) = expr;
+      OMP_CLAUSE_CHAIN (c) = clauses;
+      clauses = c;
+    }
+
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+    return error_mark_node;
+  return clauses;
+}
+
+/* Handles the Cilk Plus #pragma simd linear clause.
+   Syntax:
+   linear ( simd-linear-variable-list )
+
+   simd-linear-variable-list:
+     simd-linear-variable
+     simd-linear-variable-list , simd-linear-variable
+
+   simd-linear-variable:
+     id-expression
+     id-expression : simd-linear-step
+
+   simd-linear-step:
+   conditional-expression */
+
+static tree
+cp_parser_cilk_simd_linear (cp_parser *parser, tree clauses)
+{
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+  
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+    return clauses;
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+    {
+      cp_parser_error (parser, "expected identifier");
+      cp_parser_skip_to_closing_parenthesis (parser, false, false, true);
+      return error_mark_node;
+    }
+
+  while (1)
+    {
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+	{
+	  cp_parser_error (parser, "expected variable-name");
+	  clauses = error_mark_node;
+	  break;
+	}
+
+      tree var_name = cp_parser_id_expression (parser, false, true, NULL,
+					       false, false);
+      tree decl = cp_parser_lookup_name_simple (parser, var_name,
+						token->location);
+      if (decl == error_mark_node)
+	{
+	  cp_parser_name_lookup_error (parser, var_name, decl, NLE_NULL,
+				       token->location);
+	  clauses = error_mark_node;
+	}
+      else
+	{
+	  tree e = NULL_TREE;
+	  tree step_size = integer_one_node;
+
+	  /* If present, parse the linear step.  Otherwise, assume the default
+	     value of 1.  */
+	  if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
+	    {
+	      cp_lexer_consume_token (parser->lexer);
+
+	      e = cp_parser_constant_expression (parser, false, NULL);
+	      e = fold_non_dependent_expr (e);
+
+	      if (e == error_mark_node)
+		{
+		  /* If an error has occurred,  then the whole pragma is
+		     considered ill-formed.  Thus, no reason to keep
+		     parsing.  */
+		  clauses = error_mark_node;
+		  break;
+		}
+	      else if (!TREE_TYPE (e) || !TREE_CONSTANT (e)
+		       || !INTEGRAL_TYPE_P (TREE_TYPE (e)))
+		cp_parser_error (parser,
+				 "step size must be an integer constant");
+	      else
+		step_size = e;
+	    }
+
+	  /* Use the OMP_CLAUSE_LINEAR,  which has the same semantics.  */
+	  tree l = build_omp_clause (loc, OMP_CLAUSE_LINEAR);
+	  OMP_CLAUSE_DECL (l) = decl;
+	  OMP_CLAUSE_LINEAR_STEP (l) = step_size;
+	  OMP_CLAUSE_CHAIN (l) = clauses;
+	  clauses = l;
+	}
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+	cp_lexer_consume_token (parser->lexer);
+      else if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+	break;
+      else
+	{
+	  error_at (cp_lexer_peek_token (parser->lexer)->location,
+		    "expected %<,%> or %<)%> after %qE", decl);
+	  clauses = error_mark_node;
+	  break;
+	}
+    }
+  cp_parser_skip_to_closing_parenthesis (parser, false, false, true);
+  return clauses;
+}
+
+/* Returns the name of the next clause.  If the clause is not recognized, then
+   PRAGMA_CILK_CLAUSE_NONE is returned and the next token is not consumed.
+   Otherwise, the appropriate enum. value from the pragma_simd_clause is
+   returned and the token is consumed.  */
+
+static pragma_cilk_clause
+cp_parser_cilk_simd_clause_name (cp_parser *parser, tree *name)
+{
+  pragma_cilk_clause clause_type;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  if (!token->u.value || token->type != CPP_NAME)
+    return PRAGMA_CILK_CLAUSE_NONE;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "vectorlength"))
+    clause_type = PRAGMA_CILK_CLAUSE_VECTORLENGTH;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "linear"))
+    clause_type = PRAGMA_CILK_CLAUSE_LINEAR;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "private"))
+    clause_type = PRAGMA_CILK_CLAUSE_PRIVATE;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "firstprivate"))
+    clause_type = PRAGMA_CILK_CLAUSE_FIRSTPRIVATE;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "lastprivate"))
+    clause_type = PRAGMA_CILK_CLAUSE_LASTPRIVATE;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "reduction"))
+    clause_type = PRAGMA_CILK_CLAUSE_REDUCTION;
+  else
+    {
+      *name = token->u.value;
+      return PRAGMA_CILK_CLAUSE_NONE;
+    }
+
+  *name = token->u.value;
+  cp_lexer_consume_token (parser->lexer);
+  return clause_type;
+}
+
+/* Parses all the #pragma simd clauses.  Returns a list of clauses found.  */
+
+static tree
+cp_parser_cilk_simd_all_clauses (cp_parser *parser, cp_token *pragma_token)
+{
+  tree clauses = NULL_TREE;
+  tree name = NULL_TREE;
+  while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)
+	 && clauses != error_mark_node)
+    {
+      pragma_cilk_clause c_kind;
+      c_kind = cp_parser_cilk_simd_clause_name (parser, &name);
+      if (c_kind == PRAGMA_CILK_CLAUSE_VECTORLENGTH)
+	clauses = cp_parser_cilk_simd_vectorlength (parser, clauses);
+      else if (c_kind == PRAGMA_CILK_CLAUSE_LINEAR)
+	clauses = cp_parser_cilk_simd_linear (parser, clauses);
+      else if (c_kind == PRAGMA_CILK_CLAUSE_PRIVATE)
+	/* Use the OpenMP 4.0 equivalent function.  */
+	clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_PRIVATE, clauses);
+      else if (c_kind == PRAGMA_CILK_CLAUSE_FIRSTPRIVATE)
+	/* Use the OpenMP 4.0 equivalent function.  */
+	clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FIRSTPRIVATE,
+					  clauses);
+      else if (c_kind == PRAGMA_CILK_CLAUSE_LASTPRIVATE)
+	/* Use the OMP 4.0 equivalent function.  */
+	clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_LASTPRIVATE,
+					  clauses);
+      else if (c_kind == PRAGMA_CILK_CLAUSE_REDUCTION)
+	/* Use the OMP 4.0 equivalent function.  */
+	clauses = cp_parser_omp_clause_reduction (parser, clauses);
+      else
+	{
+	  clauses = error_mark_node;
+	  error_at (cp_lexer_peek_token (parser->lexer)->location,
+		    "invalid/unimplemented %<#pragma simd%> clause: %qE",
+		    name);
+	  break;
+	}
+    }
+
+  cp_parser_skip_to_pragma_eol (parser, pragma_token);
+
+  if (clauses == error_mark_node)
+    return error_mark_node;
+  else
+    return c_finish_cilk_clauses (clauses);
+}
+
+/* Main entry-point for parsing Cilk Plus <#pragma simd> for loop.  */
+
+static void
+cp_parser_cilk_simd_construct (cp_parser *parser, cp_token *pragma_token)
+{
+  tree sb;
+  int save;
+  tree clauses = cp_parser_cilk_simd_all_clauses (parser, pragma_token);
+
+  if (clauses == error_mark_node)
+    return;
+  
+  if (cp_lexer_next_token_is_not_keyword (parser->lexer, RID_FOR))
+    {
+      error_at (cp_lexer_peek_token (parser->lexer)->location,
+		"expected for-statement after %<#pragma simd%> clauses");
+      return;
+    }
+
+  /* #pragma simd is build on top of OpenMP 4.0's OMP_SIMD treees.  Thus
+     openmp must be enabled.  */
+  if (!flag_openmp)
+    flag_openmp = true;
+  sb = begin_omp_structured_block ();
+  save = cp_parser_begin_omp_structured_block (parser);
+  cp_parser_cilk_for (parser, RID_FOR, clauses);
+  cp_parser_end_omp_structured_block (parser, save);
+  add_stmt (finish_omp_structured_block (sb));
+  return;
+}
+
+/* Parses the initializer of a for/_Cilk_for statement.  The initial value is
+   stored in *INIT, and the inital value's declaration is stored as  DECL_EXPR
+   in *PRE_BODY.  */
+
+static tree
+cp_parser_simd_for_init_statement (cp_parser *parser, tree *init,
+				   tree *pre_body)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+  tree decl = NULL_TREE;
+  cp_decl_specifier_seq type_specifiers;
+  tree this_pre_body = push_stmt_list ();
+  if (token->type == CPP_SEMICOLON)
+    {
+      error_at (loc, "for-loop initializer must declare variable");
+      return error_mark_node;
+    }
+  cp_parser_parse_tentatively (parser);
+  cp_parser_type_specifier_seq (parser, true, false, &type_specifiers);
+  if (cp_parser_parse_definitely (parser))
+    {
+      cp_declarator *cp_decl;
+      tree asm_spec, attr;
+      cp_decl = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, NULL,
+				      NULL, false);
+      attr = cp_parser_attributes_opt (parser);
+      asm_spec = cp_parser_asm_specification_opt (parser);
+      if (cp_decl == cp_error_declarator)
+	cp_parser_skip_to_end_of_statement (parser);
+      else
+	{
+	  tree pushed_scope, auto_node;
+	  decl = start_decl (cp_decl, &type_specifiers, SD_INITIALIZED, attr,
+			     NULL_TREE, &pushed_scope);
+	  auto_node = type_uses_auto (TREE_TYPE (decl));
+	  if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
+	    {
+	      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+		error_at (loc, "parenthesized initialization is not allowed in"
+			  " for-loop");
+	      else
+		{	  
+		  if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+		    decl = error_mark_node;
+		}
+
+	      *init = error_mark_node;
+	      cp_parser_skip_to_end_of_statement (parser);
+	    }
+	  else if (CLASS_TYPE_P (TREE_TYPE (decl)) || auto_node
+		   || type_dependent_expression_p (decl))
+	    {
+	      bool is_direct_init, is_non_constant_init;
+	      *init = cp_parser_initializer (parser, &is_direct_init,
+					    &is_non_constant_init);
+	      if (auto_node)
+		{
+		  TREE_TYPE (decl) = do_auto_deduction (TREE_TYPE (decl), *init,
+							auto_node);
+		  if (!CLASS_TYPE_P (TREE_TYPE (decl))
+		      && !type_dependent_expression_p (decl))
+		    goto non_class;
+		}
+	      cp_finish_decl (decl, *init, !is_non_constant_init, asm_spec,
+			      LOOKUP_ONLYCONVERTING);
+	      if (CLASS_TYPE_P (TREE_TYPE (decl)))
+		*init = NULL_TREE;
+	      else
+		*init = pop_stmt_list (this_pre_body);
+	      this_pre_body = NULL_TREE;
+	    }
+	  else
+	    {
+	      /* Consume the '='.  */
+	      cp_lexer_consume_token (parser->lexer);
+	      *init = cp_parser_assignment_expression (parser, false, NULL);
+	    non_class:
+	      if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
+		*init = error_mark_node;
+	      else
+		cp_finish_decl (decl, NULL_TREE, false, asm_spec,
+				LOOKUP_ONLYCONVERTING);
+	      DECL_INITIAL (decl) = (*init || *init != error_mark_node) ?
+		*init : NULL_TREE;
+	    }
+	  if (pushed_scope)
+	    pop_scope (pushed_scope);
+	}
+    }
+  else
+    {
+      cp_id_kind idk;
+      cp_parser_parse_tentatively (parser);
+      decl = cp_parser_primary_expression (parser, false, false, false, &idk);
+      if (!cp_parser_error_occurred (parser) && decl && DECL_P (decl)
+	  && CLASS_TYPE_P (TREE_TYPE (decl)))
+	{
+	  tree rhs, new_expr;
+	  cp_parser_parse_definitely (parser);
+	  cp_parser_require (parser, CPP_EQ, RT_EQ);
+	  rhs = cp_parser_assignment_expression (parser, false, NULL);
+	  new_expr = build_x_modify_expr (EXPR_LOCATION (rhs), decl, NOP_EXPR,
+					  rhs, tf_warning_or_error);
+	  finish_expr_stmt (new_expr);
+	}
+      else
+	{
+	  decl = NULL_TREE;
+	  cp_parser_abort_tentative_parse (parser);
+	  *init = cp_parser_expression (parser, false, NULL);
+	}
+    }
+  
+  if (this_pre_body)
+    this_pre_body = pop_stmt_list (this_pre_body);
+
+  *pre_body = this_pre_body;
+  return decl;
+}
+  
+
+/* Parses the increment expresion for a cilk_for or for statement with
+   #pragma simd.  */
+
+static tree
+cp_parser_cilk_for_expression_iterator (cp_parser *parser)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  tree name = NULL_TREE, expr = NULL_TREE;
+  enum tree_code t_code = NOP_EXPR;
+
+  if (token->type == CPP_SEMICOLON)
+    {
+      error_at (token->location, "missing loop expression");
+      return error_mark_node;
+    }
+  if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
+    {
+      cp_lexer_consume_token (parser->lexer);
+      token = cp_lexer_peek_token (parser->lexer);
+      t_code = token->type == CPP_PLUS_PLUS ? PREINCREMENT_EXPR
+	: PREDECREMENT_EXPR;
+    }
+
+  if (token->type != CPP_NAME)
+    {
+      error_at (token->location, "invalid loop expression");
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
+    }
+
+  name = cp_parser_lookup_name (parser, token->u.value, none_type, false, false,
+				false, NULL, token->location);
+  if (name == error_mark_node)
+    return error_mark_node;
+
+  /* If name is not a declaration, then the loop is not valid.  */
+  if (!DECL_P (name))
+    {
+      error_at (token->location, "invalid loop increment expression");
+      return error_mark_node;
+    }
+  cp_lexer_consume_token (parser->lexer);
+  token = cp_lexer_peek_token (parser->lexer);
+
+  if (t_code != NOP_EXPR)
+    {
+      if (token->type != CPP_CLOSE_PAREN)
+	{
+	  error_at (token->location, "invalid loop expression");
+	  return error_mark_node;
+	}
+      return build2 (t_code, void_type_node, name, NULL_TREE);
+    }
+
+  if (token->type == CPP_CLOSE_PAREN)
+    {
+      error_at (token->location,
+		"loop expression must modify control variable");
+      return error_mark_node;
+    }
+
+  cp_lexer_consume_token (parser->lexer);
+  if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
+    return build2 (token->type == CPP_PLUS_PLUS ? POSTINCREMENT_EXPR
+		   : POSTDECREMENT_EXPR, void_type_node, name, NULL_TREE);
+  else if (token->type == CPP_EQ)
+    {
+      sorry ("loop with = operator");
+      return error_mark_node;
+    }
+  else if (token->type == CPP_PLUS_EQ || token->type == CPP_MINUS_EQ)
+    t_code = token->type == CPP_PLUS_EQ  ? PLUS_EXPR : MINUS_EXPR;
+  else if (token->type == CPP_MOD_EQ || token->type == CPP_XOR_EQ
+	   || token->type == CPP_DIV_EQ || token->type == CPP_AND_EQ
+	   || token->type == CPP_OR_EQ || token->type == CPP_AND_EQ
+	   || token->type == CPP_LSHIFT_EQ || token->type == CPP_RSHIFT_EQ)
+    {
+      error_at (token->location, "invalid loop increment operation");
+      return error_mark_node;
+    }
+  else
+    {
+      error_at (token->location, "invalid loop expression");
+      return error_mark_node;
+    }
+  expr = cp_parser_binary_expression (parser, false, false, PREC_NOT_OPERATOR,
+				      NULL);
+  if (expr == error_mark_node)
+    return expr;
+
+  return build2 (MODIFY_EXPR, void_type_node, name,
+		 build2 (t_code, TREE_TYPE (name), name, expr));
+}
+
+/* Parses the condition for a for-loop with pragma simd or _Cilk_for loop.  */
+
+static tree
+cp_parser_cilk_for_condition (cp_parser *parser)
+{
+  tree lhs, rhs;
+  enum tree_code code = ERROR_MARK;
+
+  lhs = cp_parser_binary_expression (parser, false, false,
+				     PREC_SHIFT_EXPRESSION, NULL);
+  switch (cp_lexer_peek_token (parser->lexer)->type)
+    {
+    case CPP_NOT_EQ:
+      code = NE_EXPR;
+      break;    
+    case CPP_LESS:
+      code = LT_EXPR;
+      break;
+    case CPP_LESS_EQ:
+      code = LE_EXPR;
+      break;
+    case CPP_GREATER_EQ:
+      code = GE_EXPR;
+      break;
+    case CPP_GREATER:
+      code = GT_EXPR;
+      break;
+    case CPP_EQ_EQ:
+      error_at (cp_lexer_peek_token (parser->lexer)->location,
+		"equality test not permitted in the Cilk_for loop");
+      break;
+    default:
+      error_at (cp_lexer_peek_token (parser->lexer)->location,
+		"missing comparison operator in the loop condition");
+    }
+  cp_lexer_consume_token (parser->lexer);
+
+  rhs = cp_parser_binary_expression (parser, false, false,
+				     PREC_SHIFT_EXPRESSION, NULL);
+  parser->scope = NULL_TREE;
+  parser->qualifying_scope = NULL_TREE;
+  parser->object_scope = NULL_TREE;
+
+  if (code == ERROR_MARK || lhs == error_mark_node || rhs == error_mark_node)
+    return error_mark_node;
+
+  return build2 (code, boolean_type_node, lhs, rhs);
+}
+   
+/* Top-level function to parse _Cilk_for and for statements.  */
+
+static tree
+cp_parser_cilk_for (cp_parser *parser, enum rid for_keyword, tree clauses)
+{
+  bool valid = true;
+  tree cond = NULL_TREE;
+  tree incr_expr = NULL_TREE;
+  tree init = NULL_TREE, pre_body = NULL_TREE, decl;
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+  
+  /* FIXME: Allow CILK_FOR into this function.  That is, use this function to
+     parse _Cilk_for statments also.  To do this correctly, add another param.
+     called "grain" to hold the grainsize.  */
+
+  gcc_assert (for_keyword == RID_FOR);
+
+  if (!cp_lexer_next_token_is_keyword (parser->lexer, for_keyword))
+    {
+      if (for_keyword == RID_FOR)
+	cp_parser_error (parser, "for statement expected");
+      else
+	cp_parser_error (parser, "_Cilk_for statement expected");
+      return error_mark_node;
+    }
+  cp_lexer_consume_token (parser->lexer);
+
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+    {
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
+    }
+
+  if (for_keyword == RID_FOR)
+    decl = cp_parser_simd_for_init_statement (parser, &init, &pre_body);
+
+  if (decl == error_mark_node)
+    valid = false;
+  else if (!decl || (TREE_CODE (decl) != VAR_DECL
+		     && TREE_CODE (decl) != DECL_EXPR))
+    {
+      error_at (loc, "%s-loop initializer does not declare a variable",
+		for_keyword == RID_FOR ? "for" : "_Cilk_for");
+      valid = false;
+      decl = error_mark_node;
+    }
+  else if (!processing_template_decl
+	   && !DECL_NONTRIVIALLY_INITIALIZED_P (decl)
+	   && !DECL_INITIAL (decl)
+	   && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+    {
+      error_at (loc, "control variable for the %s-loop needs to be initialized",
+		for_keyword == RID_FOR ? "for" : "_Cilk_for");
+      valid = false;
+    }
+  if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+    {
+      error_at (loc, "%s-loop initializer cannot have multiple variable "
+		"declarations", for_keyword == RID_FOR ? "for" : "_Cilk_for");
+      cp_parser_skip_to_end_of_statement (parser);
+      valid = false;
+    }
+
+  if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
+    return error_mark_node;
+  if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+    {
+      error_at (loc, "%s-loop requires a condition",
+		for_keyword == RID_FOR ? "for" : "_Cilk_for");
+      cond = error_mark_node;
+    }
+  else
+    cond = cp_parser_cilk_for_condition (parser);
+
+  if (cond == error_mark_node)
+    valid = false;
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+  
+  if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+    {
+      error_at (loc, "%s-loop requires an increment expression",
+		for_keyword == RID_FOR ? "for" : "_Cilk_for");
+      incr_expr = error_mark_node;
+    }
+  else
+    incr_expr = cp_parser_cilk_for_expression_iterator (parser);
+  
+  if (incr_expr == error_mark_node)
+    {
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, false);
+      valid = false;
+    }
+
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+    {
+      cp_parser_skip_to_end_of_statement (parser);
+      valid = false;
+    }
+  
+  if (!valid)
+    {
+      gcc_assert (sorrycount || errorcount);
+      return error_mark_node;
+    }
+
+  if (for_keyword == RID_FOR)
+    {
+      tree initv, incrv, condv, declv, omp_simd_node, body = NULL_TREE;
+
+      parser->in_statement = IN_CILK_P_SIMD_FOR;
+      body = push_stmt_list ();
+      cp_parser_statement (parser, NULL_TREE, false, NULL);
+      body = pop_stmt_list (body);
+
+      /* Check if the body satisfies all the requirement of a #pragma simd for
+	 body.  If it is invalid, then do not make the openmp nodes, just return
+	 an error mark node.  */
+      if (!p_simd_valid_stmts_in_body_p (body))
+	return error_mark_node;
+      
+      /* Now pass all the information into finish_omp_for.  */
+      initv = make_tree_vec (1);
+      condv = make_tree_vec (1);
+      incrv = make_tree_vec (1);
+      declv = make_tree_vec (1);
+      TREE_VEC_ELT (initv, 0) = init;
+      TREE_VEC_ELT (condv, 0) = cond;
+      TREE_VEC_ELT (incrv, 0) = incr_expr;
+      TREE_VEC_ELT (declv, 0) = decl;
+      omp_simd_node = finish_omp_for (loc, OMP_SIMD, declv, initv, condv, incrv,
+				      body, pre_body, clauses);
+      return omp_simd_node;
+    }
+  else
+    /* Fix this when _Cilk_for is added into the mix.  */
+    return NULL_TREE;
+}
+
 #include "gt-cp-parser.h"
diff --git gcc/cp/parser.h gcc/cp/parser.h
index 6d9f1fb..48ec8dd 100644
--- gcc/cp/parser.h
+++ gcc/cp/parser.h
@@ -292,6 +292,7 @@  typedef struct GTY(()) cp_parser {
 #define IN_OMP_BLOCK		4
 #define IN_OMP_FOR		8
 #define IN_IF_STMT             16
+#define IN_CILK_P_SIMD_FOR     32
   unsigned char in_statement;
 
   /* TRUE if we are presently parsing the body of a switch statement.
diff --git gcc/testsuite/g++.dg/cilk-plus/errors/cilkplus_CPP_PS_errors.exp gcc/testsuite/g++.dg/cilk-plus/errors/cilkplus_CPP_PS_errors.exp
new file mode 100644
index 0000000..1f8ace8
--- /dev/null
+++ gcc/testsuite/g++.dg/cilk-plus/errors/cilkplus_CPP_PS_errors.exp
@@ -0,0 +1,23 @@ 
+#   Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+load_lib gcc-dg.exp
+
+set OPTS "-fcilkplus -c -ftree-vectorize"
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] " $OPTS" " "
+dg-finish
diff --git gcc/testsuite/g++.dg/cilk-plus/errors/for_body_errors.cc gcc/testsuite/g++.dg/cilk-plus/errors/for_body_errors.cc
new file mode 100644
index 0000000..797cb89
--- /dev/null
+++ gcc/testsuite/g++.dg/cilk-plus/errors/for_body_errors.cc
@@ -0,0 +1,62 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+#include <setjmp.h>
+int main(void)
+{
+  int q = 0;
+#pragma simd
+  for (int ii = 0; ii < 1000; ii++)
+    break; /* { dg-error "break statements are not allowed" } */
+
+#pragma simd linear (q)
+  for (int ii = 0; ii < 1000; ii++) {
+    if (q)
+      continue; /* { dg-error "continue statements are not allowed" } */
+   }
+#pragma simd
+  for (int ii = 0; ii < 1000; ii++)
+    {
+L5:
+      goto L5;  /* { dg-error "goto statements are not allowed" } */ 
+    }
+
+#pragma simd
+  for (int ii = 0; ii < 1000; ii++)
+    {
+      try { /* { dg-error "try statements are not allowed" } */
+	  ii = ii %2;
+      }
+      catch (...)
+	{
+	}
+    }
+
+#pragma simd
+  for (int ii = 0; ii < 1000; ii++)
+  {
+    while (ii % 2) {
+	ii++; 
+	throw; /* { dg-error "throw expressions are not allowed" } */
+    }
+  }
+
+#pragma simd
+  for (int ii = 0; ii < 1000; ii++)
+    {
+      jmp_buf x;
+      if (!setjmp (x)) /* { dg-error "setjmps are not allowed inside"  } */
+	ii++;
+    }
+
+  for (int ii = 0; ii < 1000; ii++)
+    {
+      try { /*  This is OK! */
+	  ii = ii %2;
+      }
+      catch (...)
+	{
+	}
+    }
+  return 5;
+}
diff --git gcc/testsuite/g++.dg/cilk-plus/errors/general_errors.cc gcc/testsuite/g++.dg/cilk-plus/errors/general_errors.cc
new file mode 100644
index 0000000..b9a2711
--- /dev/null
+++ gcc/testsuite/g++.dg/cilk-plus/errors/general_errors.cc
@@ -0,0 +1,58 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+int main (void)
+{
+  int x[10];
+  int z = 0;
+#pragma simd something /* { dg-error "invalid/unimplemented" } */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = 5;
+  }
+  int q = 0;
+#pragma simd
+  while (q < 5) { /* { dg-error "expected for-statement after" } */
+    x[q] = 5;
+    q++;
+  }
+#pragma simd 
+  for (int ii; ii < 10; ii++) { /* { dg-error "expected '=' before" } */
+
+    x[q] = 5;
+  }
+
+  int iii = 0;
+#pragma simd
+  for (iii; iii < 10; iii++) { /* { dg-error "for-loop initializer does not declare" } */
+    x[iii] = 5;
+  }
+#pragma simd
+  for (; iii < 10; iii++) { /* { dg-error "for-loop initializer must declare" } */
+    x[iii] = 5;
+  }
+
+#pragma simd 
+  for (int ii = 0; ii < 10; ) /* { dg-error "for-loop requires an increment expression" } */
+      x[q] = 5;
+
+#pragma simd 
+  for (int ii = 0, int jj = 0; ii < 10; ii++ )  /* { dg-error "for-loop initializer cannot have multiple" } */
+      x[q] = 5;
+
+#pragma simd 
+  for (int ii = 0; ii == 10; ii++) /* { dg-error "equality test not permitted" } */
+      x[q] = 5;
+
+#pragma simd
+  for (int ii = 0; ii < 10; ii++,jj++) /* { dg-error "expected '\\)' before" } */
+      x[q] = 5;
+
+#pragma simd /* This is OK!  */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = 5;
+  }
+
+  return x[9];
+}
+
diff --git gcc/testsuite/g++.dg/cilk-plus/errors/general_errors_tplt.cc gcc/testsuite/g++.dg/cilk-plus/errors/general_errors_tplt.cc
new file mode 100644
index 0000000..7b8859b
--- /dev/null
+++ gcc/testsuite/g++.dg/cilk-plus/errors/general_errors_tplt.cc
@@ -0,0 +1,64 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+template <class TPLT>
+TPLT main2 (int argc, char **argv)
+{
+  TPLT x[10];
+  TPLT z = 0;
+
+#pragma simd something /* { dg-error "invalid/unimplemented" } */
+  for (TPLT ii = 0; ii < 10; ii++) {
+    x[ii] = 5;
+  }
+  TPLT q = 0;
+#pragma simd
+  while (q < 5) { /* { dg-error "expected for-statement after" } */
+    x[q] = 5;
+    q++;
+  }
+#pragma simd 
+  for (TPLT ii; ii < 10; ii++) { /* { dg-error "expected" } */
+    x[q] = 5;
+  }
+
+  TPLT iii = 0;
+#pragma simd 
+  for (iii; iii < 10; iii++) { /* { dg-error "for-loop initializer does not declare" } */
+    x[iii] = 5;
+  }
+#pragma simd 
+  for (; iii < 10; iii++) { /* { dg-error "for-loop initializer must declare" } */
+    x[iii] = 5;
+  }
+
+#pragma simd 
+  for (TPLT ii = 0; ii < 10; ) /* { dg-error "for-loop requires an increment expression" } */
+      x[q] = 5;
+
+#pragma simd 
+  for (TPLT ii = 0, TPLT jj = 0; ii < 10; ii++ ) /* { dg-error "for-loop initializer cannot have multiple" } */
+      x[q] = 5;
+
+#pragma simd 
+  for (TPLT ii = 0; ii == 10; ii++) /* { dg-error "equality test not permitted" } */
+      x[q] = 5;
+
+#pragma simd 
+  for (TPLT ii = 0; ii != 10; ii++,jj++) /* { dg-error "expected" } */
+      x[q] = 5;
+
+#pragma simd /* This is OK!  */
+  for (TPLT ii = 0; ii < 10; ii++) {
+    x[ii] = 5;
+  }
+  return x[9];
+}
+
+int main (int argc, char **argv)
+{
+  main2 <int> (argc, argv);
+  return 0;
+}
+
diff --git gcc/testsuite/g++.dg/cilk-plus/errors/linear_error.cc gcc/testsuite/g++.dg/cilk-plus/errors/linear_error.cc
new file mode 100644
index 0000000..addabdf
--- /dev/null
+++ gcc/testsuite/g++.dg/cilk-plus/errors/linear_error.cc
@@ -0,0 +1,61 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+int main (void)
+{
+  int x[10];
+  int z = 0,  y = 5;
+
+#pragma simd linear (5) /* { dg-error "expected identifier before" } */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = z;
+  }
+
+#pragma simd linear (:5) /* { dg-error "expected identifier before" } */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = z;
+  }
+
+#pragma simd linear (z:) /* { dg-error "expected primary-expression before" } */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = z;
+  }
+
+#pragma simd linear (z) /* This is OK!  */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = z;
+  }
+
+#pragma simd linear (x, z) /* This is OK!  */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = z;
+  }
+
+#pragma simd linear (x:1, z) /* This is OK!  */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = z;
+  }
+
+#pragma simd linear (y, x:1, z:2) /* This is OK!  */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = y + z;
+  }
+
+#pragma simd linear (q) /* { dg-error "has not been declared" } */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = z;
+  }
+
+#pragma simd linear (y, :5) /* { dg-error "expected variable-name" } */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = (z + y);
+  }
+
+#pragma simd linear (y,5) /* { dg-error "expected variable-name before numeric" } */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = (z + y);
+  }
+  return x[9];
+}
+
diff --git gcc/testsuite/g++.dg/cilk-plus/errors/vlength_error.cc gcc/testsuite/g++.dg/cilk-plus/errors/vlength_error.cc
new file mode 100644
index 0000000..3de33c5
--- /dev/null
+++ gcc/testsuite/g++.dg/cilk-plus/errors/vlength_error.cc
@@ -0,0 +1,41 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+int main (void)
+{
+  int x[10];
+  int z = 0;
+  const int zz = 0;
+#pragma simd vectorlength (4, 8) /* { dg-error "expected" } */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = 5;
+  }
+#pragma simd vectorlength (5) /* { dg-error "vectorlength must be a power" } */
+  for (int ii = 0; ii < 10; ii++) { 
+      x[ii] = 5; 
+  }
+
+#pragma simd vectorlength (5.2) /* { dg-error "vectorlength must be an integer" } */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = 5;
+  }
+
+#pragma simd vectorlength (zz) /* { dg-error "vectorlength must be an integer" } */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = 5;
+  }
+
+#pragma simd vectorlength 4 /* { dg-error "before numeric" } */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = 5;
+  }
+
+#pragma simd vectorlength (4 /* { dg-error "before end of" } */
+  for (int ii = 0; ii < 10; ii++) {
+    x[ii] = 5;
+  }
+
+  return x[9];
+}
+