diff mbox

[GOMP4] SIMD-enabled functions (formerly Elemental functions) for C++

Message ID BF230D13CA30DD48930C31D4099330003A4B21A9@FMSMSX101.amr.corp.intel.com
State New
Headers show

Commit Message

Iyer, Balaji V Dec. 16, 2013, 4:53 a.m. UTC
Hello Everyone,
	The following changes mentioned in this thread (http://gcc.gnu.org/ml/gcc-patches/2013-12/msg01280.html) are also applicable to the C++ patch and the attached patch has been fixed accordingly:

1. Sharing the vectorlength parsing function between #pragma simd and SIMD enabled functions
2. Renaming the function that is parsing the SIMD enabled function attributes
3. Renaming "Cilk plus elementals" to "Cilk SIMD function" for the attribute name
4. Marking all the SIMD enabled function attributes with both "omp declare simd" and "cilk simd function."
5. Renaming an error message from "..SIMD-enabled function" to "Cilk Plus SIMD-enabled function..."

So, is this patch OK for branch/trunk?

Here are the ChangeLog entries:

Gcc/cp/ChangeLog:
2013-12-16  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * decl2.c (is_late_template_attribute): Added a check for SIMD-enabled
        functions attribute.  If found, return true.
        * parser.c (cp_parser_direct_declarator): When Cilk Plus is enabled
        see if there is an attribute after function decl.  If so, then
        parse them now.
        (cp_parser_late_return_type_opt): Handle parsing of Cilk Plus SIMD
        enabled function late parsing.
        (cp_parser_gnu_attribute_list): Parse all the tokens for the vector
        attribute for a SIMD-enabled function.
        (cp_parser_omp_all_clauses): Skip parsing to the end of pragma when
        the function is used by SIMD-enabled function (indicated by NULL
        pragma token).
        (cp_parser_cilk_simd_vectorlength): Modified this function to parse
        vectorlength attribute in SIMD-enabled function and #pragma SIMD's
        vectorlength clause.  Added a new parameter to pass in SIMD-enabled
        function's info.
        (cp_parser_cilk_simd_fn_vector_attrs): New function.
        (cp_parser_late_parsing_elem_fn_info): Likewise.
        * parser.h (cp_parser::elem_fn_info): New field.
        * decl.c (grokfndecl): Added a check if Cilk Plus is enabled and
        if so, adjust the Cilk Plus SIMD-enabled function attributes.

Gcc/testsuite/ChangeLog
2013-12-16  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * g++.dg/cilk-plus/cilk-plus.exp: Called the C/C++ common tests for
        SIMD enabled function.
        * g++.dg/cilk-plus/ef_test.C: New test.


Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Iyer, Balaji V
> Sent: Thursday, December 5, 2013 11:37 AM
> To: Jakub Jelinek
> Cc: Aldy Hernandez (aldyh@redhat.com); gcc-patches@gcc.gnu.org
> Subject: FW: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental
> functions) for C++
> 
> PING!
> 
> -Balaji V. Iyer.
> 
> > -----Original Message-----
> > From: Iyer, Balaji V
> > Sent: Saturday, November 30, 2013 11:53 PM
> > To: 'Jakub Jelinek'
> > Cc: Aldy Hernandez (aldyh@redhat.com); 'Jeff Law'; 'gcc-
> > patches@gcc.gnu.org'
> > Subject: RE: [GOMP4][PATCH] SIMD-enabled functions (formerly
> Elemental
> > functions) for C++
> >
> > Hello Everyone,
> > 	The changes mentioned in http://gcc.gnu.org/ml/gcc-patches/2013-
> > 11/msg03506.html is also applicable to my C++ patch. With this email,
> > I am attaching a fixed patch.
> >
> > Here are the ChangeLog entries:
> >
> > gcc/cp/ChangeLog
> > 2013-11-30  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> >
> >         * decl2.c (is_late_template_attribute): Added a check for SIMD-
> enabled
> >         functions attribute.  If found, return true.
> >         * parser.c (cp_parser_direct_declarator): When Cilk Plus is enabled
> >         see if there is an attribute after function decl.  If so, then
> >         parse them now.
> >         (cp_parser_late_return_type_opt): Handle parsing of Cilk Plus SIMD
> >         enabled function late parsing.
> >         (cp_parser_gnu_attribute_list): Parse all the tokens for the vector
> >         attribute for a SIMD-enabled function.
> >         (cp_parser_omp_all_clauses): Skip parsing to the end of pragma when
> >         the function is used by SIMD-enabled function (indicated by NULL
> >         pragma token).
> >         (cp_parser_elem_fn_vectorlength): New function.
> >         (cp_parser_elem_fn_expr_list): Likewise.
> >         (cp_parser_late_parsing_elem_fn_info): Likewise.
> >         * parser.h (cp_parser::elem_fn_info): New field.
> >         * decl.c (grokfndecl): Added a check if Cilk Plus is enabled and
> >         if so, adjust the Cilk Plus SIMD-enabled function attributes.
> >
> >
> > gcc/testsuite/ChangeLog
> > 2013-11-30  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> >
> >         * g++.dg/cilk-plus/cilk-plus.exp: Called the C/C++ common tests for
> >         SIMD enabled function.
> >         * g++.dg/cilk-plus/ef_test.C: New test.
> >
> > Is this OK for branch?
> >
> > Thanks,
> >
> > Balaji V. Iyer.
> >
> > > -----Original Message-----
> > > From: Iyer, Balaji V
> > > Sent: Wednesday, November 20, 2013 6:19 PM
> > > To: Jakub Jelinek
> > > Cc: Aldy Hernandez (aldyh@redhat.com); Jeff Law;
> > > gcc-patches@gcc.gnu.org
> > > Subject: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental
> > > functions) for C++
> > >
> > > Hello Everyone,
> > > 	Attached, please find a patch that will implement SIMD-enabled
> > > functions for C++ targeting the gomp-4_0-branch. Here are the
> > > Changelog entries. Is this OK to install?
> > >
> > > gcc/cp/ChangeLog
> > > 2013-11-20  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> > >
> > >         * parser.c (cp_parser_direct_declarator): When Cilk Plus is enabled
> > >         see if there is an attribute after function decl.  If so, then
> > >         parse them now.
> > >         (cp_parser_late_return_type_opt): Handle parsing of Cilk Plus SIMD
> > >         enabled function late parsing.
> > >         (cp_parser_gnu_attribute_list): Parse all the tokens for the vector
> > >         attribute for a SIMD-enabled function.
> > >         (cp_parser_omp_all_clauses): Skip parsing to the end of pragma
> when
> > >         the function is used by SIMD-enabled function (indicated by NULL
> > >         pragma token).
> > >         (cp_parser_elem_fn_vectorlength): New function.
> > >         (cp_parser_elem_fn_expr_list): Likewise.
> > >         (cp_parser_late_parsing_elem_fn_info): Likewise.
> > >         * parser.h (cp_parser::elem_fn_info): New field.
> > >
> > > gcc/testsuite/ChangeLog
> > > 2013-11-20  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> > >
> > >         * g++.dg/cilk-plus/cilk-plus.exp: Called the C/C++ common tests for
> > >         SIMD enabled function.
> > >         * g++.dg/cilk-plus/ef_test.C: New test.
> > >
> > >
> > > Thanking You,
> > >
> > > Yours Sincerely,
> > >
> > > Balaji V. Iyer.
diff mbox

Patch

Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 205562)
+++ gcc/cp/decl.c	(working copy)
@@ -7669,6 +7669,34 @@ 
 	}
     }
 
+  if (flag_enable_cilkplus)
+    {
+      /* Adjust "cilk simd function attribute" attributes.  */
+      tree ods = lookup_attribute ("cilk simd function", *attrlist);
+      if (ods)
+	{
+	  tree attr;
+	  for (attr = ods; attr; 
+	       attr = lookup_attribute ("cilk simd function",
+					TREE_CHAIN (attr)))
+	    {
+	      if (TREE_CODE (type) == METHOD_TYPE)
+		walk_tree (&TREE_VALUE (attr), declare_simd_adjust_this,
+			   DECL_ARGUMENTS (decl), NULL);
+	      if (TREE_VALUE (attr) != NULL_TREE)
+		{
+		  tree cl = TREE_VALUE (TREE_VALUE (attr));
+		  cl = c_omp_declare_simd_clauses_to_numbers
+						(DECL_ARGUMENTS (decl), cl);
+		  if (cl)
+		    TREE_VALUE (TREE_VALUE (attr)) = cl;
+		  else
+		    TREE_VALUE (attr) = NULL_TREE;
+		}
+	    }
+	}
+    }
+  
   /* Caller will do the rest of this.  */
   if (check < 0)
     return decl;
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 205562)
+++ gcc/cp/pt.c	(working copy)
@@ -8603,9 +8603,12 @@ 
 	    {
 	      *p = TREE_CHAIN (t);
 	      TREE_CHAIN (t) = NULL_TREE;
-	      if (flag_openmp
-		  && is_attribute_p ("omp declare simd",
-				     get_attribute_name (t))
+	      if (((flag_openmp
+		    && is_attribute_p ("omp declare simd",
+				       get_attribute_name (t)))
+		   || (flag_enable_cilkplus
+		       && is_attribute_p ("cilk simd function",
+					  get_attribute_name (t))))
 		  && TREE_VALUE (t))
 		{
 		  tree clauses = TREE_VALUE (TREE_VALUE (t));
Index: gcc/cp/decl2.c
===================================================================
--- gcc/cp/decl2.c	(revision 205562)
+++ gcc/cp/decl2.c	(working copy)
@@ -1124,6 +1124,10 @@ 
       && is_attribute_p ("omp declare simd", name))
     return true;
 
+  /* Ditto as above for Cilk Plus SIMD-enabled function attributes.  */
+  if (flag_enable_cilkplus && is_attribute_p ("cilk simd function", name))
+    return true;
+
   /* If any of the arguments are dependent expressions, we can't evaluate
      the attribute until instantiation time.  */
   for (arg = args; arg; arg = TREE_CHAIN (arg))
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 205562)
+++ gcc/cp/parser.c	(working copy)
@@ -241,6 +241,8 @@ 
   (cp_parser *, cp_token *);
 static bool cp_parser_omp_declare_reduction_exprs
   (tree, cp_parser *);
+static tree cp_parser_cilk_simd_vectorlength 
+  (cp_parser *, tree, cp_omp_declare_simd_data *);
 
 /* Manifest constants.  */
 #define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token))
@@ -2115,6 +2117,9 @@ 
 static tree cp_parser_late_parsing_omp_declare_simd
   (cp_parser *, tree);
 
+static tree cp_parser_late_parsing_cilk_simd_fn_info
+  (cp_parser *, tree);
+
 static tree synthesize_implicit_template_parm
   (cp_parser *);
 static tree finish_fully_implicit_template
@@ -17035,6 +17040,14 @@ 
 
 		  attrs = cp_parser_std_attribute_spec_seq (parser);
 
+		  /* In here, we handle cases where attribute is used after
+		     the function declaration.  For example:
+		     void func (int x) __attribute__((vector(..)));  */
+		  if (flag_enable_cilkplus
+		      && cp_lexer_next_token_is_keyword (parser->lexer,
+							 RID_ATTRIBUTE))
+		    attrs = chainon (cp_parser_gnu_attributes_opt (parser),
+				     attrs);
 		  late_return = (cp_parser_late_return_type_opt
 				 (parser, declarator,
 				  memfn ? cv_quals : -1));
@@ -17743,7 +17756,7 @@ 
    Returns the type indicated by the type-id.
 
    In addition to this this parses any queued up omp declare simd
-   clauses.
+   clauses and Cilk Plus SIMD-enabled function's vector attributes.
 
    QUALS is either a bitmask of cv_qualifiers or -1 for a non-member
    function.  */
@@ -17758,10 +17771,14 @@ 
 			 && declarator
 			 && declarator->kind == cdk_id);
 
+  bool cilk_simd_fn_vector_p = (parser->cilk_simd_fn_info
+			   && declarator
+			   && declarator->kind == cdk_id);
+  
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
   /* A late-specified return type is indicated by an initial '->'. */
-  if (token->type != CPP_DEREF && !declare_simd_p)
+  if (token->type != CPP_DEREF && !(declare_simd_p || cilk_simd_fn_vector_p))
     return NULL_TREE;
 
   tree save_ccp = current_class_ptr;
@@ -17780,6 +17797,10 @@ 
       type = cp_parser_trailing_type_id (parser);
     }
 
+  if (cilk_simd_fn_vector_p)
+    declarator->std_attributes
+      = cp_parser_late_parsing_cilk_simd_fn_info (parser,
+					     declarator->std_attributes);
   if (declare_simd_p)
     declarator->std_attributes
       = cp_parser_late_parsing_omp_declare_simd (parser,
@@ -21310,6 +21331,77 @@ 
   return cp_parser_std_attribute_spec_seq (parser);
 }
 
+cp_omp_declare_simd_data info;
+
+/* Parses the Cilk Plus SIMD-enabled function's attribute.  Syntax:
+   vector [(<clauses>)]  */
+
+static void
+cp_parser_cilk_simd_fn_vector_attrs (cp_parser *parser, cp_token *v_token)
+{  
+  bool first_p = parser->cilk_simd_fn_info == NULL;
+  cp_token *token = v_token;
+  if (first_p)
+    {
+      info.error_seen = false;
+      info.fndecl_seen = false;
+      info.tokens = vNULL;
+      parser->cilk_simd_fn_info = &info;
+    }
+  int paren_scope = 0;
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+    {
+      cp_lexer_consume_token (parser->lexer);
+      v_token = cp_lexer_peek_token (parser->lexer);
+      paren_scope++;
+    }
+  while (paren_scope > 0)
+    {
+      token = cp_lexer_peek_token (parser->lexer);
+      if (token->type == CPP_OPEN_PAREN)
+	paren_scope++;
+      else if (token->type == CPP_CLOSE_PAREN)
+	paren_scope--;
+      else if (token->type == CPP_NAME
+	  && TREE_CODE (token->u.value) == IDENTIFIER_NODE)
+	{
+	  tree val = token->u.value;
+	  if (simple_cst_equal (val, get_identifier ("mask")) == 1)
+	    token->u.value = get_identifier ("inbranch");
+	  else if (simple_cst_equal (val, get_identifier ("nomask")) == 1)
+	    token->u.value = get_identifier ("notinbranch");
+	  else if (simple_cst_equal (val, 
+				     get_identifier ("vectorlength")) == 1)
+	    {
+	      token->u.value = get_identifier ("simdlen");
+	      parser->lexer->next_token->u.value = token->u.value;
+	      cp_lexer_consume_token (parser->lexer);
+	      cp_parser_cilk_simd_vectorlength (parser, NULL_TREE, &info);
+	      /* The above function should parse till the end of 
+		 vectorlength's last parenthesis.  */
+	      continue;
+	    }
+	  /* linear and uniform are the same between SIMD-enabled functions
+	     and #pragma omp declare simd.  */
+	      
+	  /* We sometimes modify the next token, so reset the next token.  */
+	  parser->lexer->next_token->u.value = token->u.value;
+	}
+
+      /* Do not push the last ')'  */
+      if (!(token->type == CPP_CLOSE_PAREN && paren_scope == 0))
+	cp_lexer_consume_token (parser->lexer);
+    }
+
+  token->type = CPP_PRAGMA_EOL;
+  parser->lexer->next_token = token;
+  cp_lexer_consume_token (parser->lexer);
+
+  struct cp_token_cache *cp = 
+    cp_token_cache_new (v_token, cp_lexer_peek_token (parser->lexer));
+  parser->cilk_simd_fn_info->tokens.safe_push (cp);
+}
+
 /* Parse an (optional) series of attributes.
 
    attributes:
@@ -21406,8 +21498,9 @@ 
 	{
 	  tree arguments = NULL_TREE;
 
-	  /* Consume the token.  */
-	  token = cp_lexer_consume_token (parser->lexer);
+	  /* Consume the token, but save it since we need it for the
+	     SIMD enabled function parsing.  */
+	  cp_token *id_token = cp_lexer_consume_token (parser->lexer);
 
 	  /* Save away the identifier that indicates which attribute
 	     this is.  */
@@ -21415,7 +21508,7 @@ 
 	    /* For keywords, use the canonical spelling, not the
 	       parsed identifier.  */
 	    ? ridpointers[(int) token->keyword]
-	    : token->u.value;
+	    : id_token->u.value;
 	  
 	  attribute = build_tree_list (identifier, NULL_TREE);
 
@@ -21427,10 +21520,17 @@ 
 	      vec<tree, va_gc> *vec;
 	      int attr_flag = (attribute_takes_identifier_p (identifier)
 			       ? id_attr : normal_attr);
-	      vec = cp_parser_parenthesized_expression_list
-		    (parser, attr_flag, /*cast_p=*/false,
-		     /*allow_expansion_p=*/false,
-		     /*non_constant_p=*/NULL);
+	      if (simple_cst_equal (identifier,
+				    get_identifier ("vector")) == 1)
+		{
+		  cp_parser_cilk_simd_fn_vector_attrs (parser, id_token);
+		  continue;
+		}
+	      else
+		vec = cp_parser_parenthesized_expression_list 
+		  (parser, attr_flag, /*cast_p=*/false, 
+		   /*allow_expansion_p=*/false, 
+		   /*non_constant_p=*/NULL);
 	      if (vec == NULL)
 		arguments = error_mark_node;
 	      else
@@ -21441,6 +21541,12 @@ 
 	      /* Save the arguments away.  */
 	      TREE_VALUE (attribute) = arguments;
 	    }
+	  else if (simple_cst_equal (identifier,
+				     get_identifier ("vector")) == 1)
+	    {
+	      cp_parser_cilk_simd_fn_vector_attrs (parser, id_token);
+	      continue;
+	    }
 
 	  if (arguments != error_mark_node)
 	    {
@@ -28080,7 +28186,10 @@ 
 	}
     }
  saw_error:
-  cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+  /* In Cilk Plus SIMD enabled functions there is no pragma_token, so
+     no reason to skip to the end.  */
+  if (!(flag_enable_cilkplus && pragma_tok == NULL))
+    cp_parser_skip_to_pragma_eol (parser, pragma_tok);
   if (finish_p)
     return finish_omp_clauses (clauses);
   return clauses;
@@ -30078,6 +30187,67 @@ 
     }
 }
 
+/* Handles the delayed parsing of the Cilk Plus SIMD-enabled function.  
+   This function is modelled similar to the late parsing of omp declare 
+   simd.  */
+
+static tree
+cp_parser_late_parsing_cilk_simd_fn_info (cp_parser *parser, tree attrs)
+{
+  struct cp_token_cache *ce;
+  cp_omp_declare_simd_data *info = parser->cilk_simd_fn_info;
+  int ii = 0;
+
+  if (parser->omp_declare_simd != NULL)
+    {
+      error ("%<#pragma omp declare simd%> cannot be used in the same function"
+	     " marked as a Cilk Plus SIMD-enabled function");
+      parser->cilk_simd_fn_info = NULL;
+      return attrs;
+    }
+  if (!info->error_seen && info->fndecl_seen)
+    {
+      error ("vector attribute not immediately followed by a single function"
+	     " declaration or definition");
+      info->error_seen = true;
+    }
+  if (info->error_seen)
+    return attrs;
+
+  /* Vector attributes are converted to #pragma omp declare simd values and
+     so we need them enabled.  */
+  flag_openmp = 1;
+
+  FOR_EACH_VEC_ELT (info->tokens, ii, ce)
+    {
+      tree c, cl;
+
+      cp_parser_push_lexer_for_tokens (parser, ce);
+      parser->lexer->in_pragma = true;
+      cl = cp_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
+				      "SIMD-enabled functions attribute",
+				      NULL);
+      cp_parser_pop_lexer (parser);
+      if (cl)
+	cl = tree_cons (NULL_TREE, cl, NULL_TREE);
+
+      c = build_tree_list (get_identifier ("cilk simd function"), cl);
+      TREE_CHAIN (c) = attrs;
+      if (processing_template_decl)
+	ATTR_IS_DEPENDENT (c) = 1;
+      attrs = c;
+
+      c = build_tree_list (get_identifier ("omp declare simd"), cl);
+      TREE_CHAIN (c) = attrs;
+      if (processing_template_decl)
+	ATTR_IS_DEPENDENT (c) = 1;
+      attrs = c;
+    }
+  info->fndecl_seen = true;
+  parser->cilk_simd_fn_info = NULL;
+  return attrs;
+}
+
 /* Finalize #pragma omp declare simd clauses after direct declarator has
    been parsed, and put that into "omp declare simd" attribute.  */
 
@@ -31260,39 +31430,72 @@ 
   the_parser = NULL;
 }
 
-/* Parses the Cilk Plus #pragma simd vectorlength clause:
+/* Parses the Cilk Plus #pragma simd and SIMD-enabled function attribute's 
+   vectorlength clause:
    Syntax:
    vectorlength ( constant-expression )  */
 
 static tree
-cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses)
+cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses,
+				  cp_omp_declare_simd_data *info)
 {
+  bool parsing_simd_fn = true;
+  if (info == NULL) 
+    parsing_simd_fn = false;
+
   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
   tree expr;
   /* The vectorlength clause behaves exactly like OpenMP's safelen
      clause.  Thus, vectorlength is represented as OMP 4.0
      safelen.  */
-  check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength", loc);
+  if (!parsing_simd_fn) 
+    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;
+    {
+      if (parsing_simd_fn)
+	info->error_seen = true; 
+      return error_mark_node;
+    }
   
   expr = cp_parser_constant_expression (parser, false, NULL);
   expr = maybe_constant_value (expr);
-
+  if (parsing_simd_fn && expr == error_mark_node)
+    {
+      info->error_seen = true;
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+      return error_mark_node;
+    }
+  if (parsing_simd_fn && !processing_template_decl
+      && (!TREE_TYPE (expr) || !TREE_CONSTANT (expr) 
+	  || !INTEGRAL_TYPE_P (TREE_TYPE (expr))))
+    {
+      error_at (loc, "vectorlength must be an integer constant");
+      info->error_seen = true;
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+      return error_mark_node;
+    }
   if (TREE_CONSTANT (expr)
 	   && exact_log2 (TREE_INT_CST_LOW (expr)) == -1)
     error_at (loc, "vectorlength must be a power of 2");
   else if (expr != error_mark_node)
     {
-      tree c = build_omp_clause (loc, OMP_CLAUSE_SAFELEN);
-      OMP_CLAUSE_SAFELEN_EXPR (c) = expr;
-      OMP_CLAUSE_CHAIN (c) = clauses;
-      clauses = c;
+      if (!parsing_simd_fn)
+	{ 
+	  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;
+    { 
+      if (parsing_simd_fn) 
+	info->error_seen = true;
+      return error_mark_node;
+    }
   return clauses;
 }
 
@@ -31451,7 +31654,7 @@ 
       pragma_cilk_clause c_kind;
       c_kind = cp_parser_cilk_simd_clause_name (parser);
       if (c_kind == PRAGMA_CILK_CLAUSE_VECTORLENGTH)
-	clauses = cp_parser_cilk_simd_vectorlength (parser, clauses);
+	clauses = cp_parser_cilk_simd_vectorlength (parser, clauses, NULL);
       else if (c_kind == PRAGMA_CILK_CLAUSE_LINEAR)
 	clauses = cp_parser_cilk_simd_linear (parser, clauses);
       else if (c_kind == PRAGMA_CILK_CLAUSE_PRIVATE)
Index: gcc/cp/parser.h
===================================================================
--- gcc/cp/parser.h	(revision 205562)
+++ gcc/cp/parser.h	(working copy)
@@ -361,6 +361,13 @@ 
      data structure with everything needed for parsing the clauses.  */
   cp_omp_declare_simd_data * GTY((skip)) omp_declare_simd;
 
+  /* When parsing the vector attribute in Cilk Plus SIMD-enabled function,
+     this is a pointer to data structure with everything needed for parsing
+     the clauses.  The cp_omp_declare_simd_data struct will hold all the
+     necessary information, so creating another struct for this is not
+     necessary.  */
+  cp_omp_declare_simd_data * GTY((skip)) cilk_simd_fn_info;
+
   /* Nonzero if parsing a parameter list where 'auto' should trigger an implicit
      template parameter.  */
   bool auto_is_implicit_function_template_parm_p;
Index: gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp	(revision 205562)
+++ gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp	(working copy)
@@ -60,6 +60,12 @@ 
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O2 -ftree-vectorize -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O3 -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -g" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -O1" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -O2 -std=c++11" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -O2 -ftree-vectorize" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -O3 -g" " "
 dg-finish
 
 unset TEST_EXTRA_LIBS
Index: gcc/testsuite/g++.dg/cilk-plus/ef_test.C
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/ef_test.C	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/ef_test.C	(revision 0)
@@ -0,0 +1,38 @@ 
+/* { dg-do run }  */
+/* { dg-options "-fcilkplus" } */
+
+
+__attribute__((vector (nomask), vector(mask), vector(mask,linear(x:1))))
+int func (int x)
+{
+  return x+5;
+}
+
+
+__attribute__((vector(mask,uniform (y), linear(x:1))))
+__attribute__((vector (nomask, uniform (x), linear(y:1))))
+int func2 (int x, int y)
+{
+  return x+y;
+}
+
+int func4 (int x, int y) __attribute__((vector, vector (nomask), vector (uniform(y), linear(x:1))));
+
+
+template <class T, class R>
+__attribute__((vector, vector(mask,uniform (y), linear(x:1))))
+T func3 (T x, R y)
+{
+  return x+(T)y;
+}
+
+
+
+int main (void)
+{
+  if ((func3 (5, 4) + func2 (5, 4) + func (5) + (int) func3<long, int> (5, 4)) != 
+      (5 + 4) + (5 + 4) + (5 + 5) + (int) ((long)5 +(int)4))
+    __builtin_abort ();
+  return 0;
+}
+