Hi Jakub,
        Did you get a chance to look at this? Is it OK to install to trunk?

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: gcc-patches-ow...@gcc.gnu.org [mailto:gcc-patches-
> ow...@gcc.gnu.org] On Behalf Of Iyer, Balaji V
> Sent: Sunday, January 19, 2014 10:37 PM
> To: Jakub Jelinek
> Cc: 'Aldy Hernandez (al...@redhat.com)'; 'gcc-patches@gcc.gnu.org'
> Subject: RE: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental
> functions) for C++
> 
> Hi Jakub,
>       I have fixed all the issues you have mentioned below. I am also
> attaching a fixed patch along with ChangeLog entries.  I have also rebased the
> patch to the trunk revision r206786.
> 
>       Is this Ok to install?
> 
> Thanks,
> 
> Balaji V. Iyer.
> 
> > -----Original Message-----
> > From: Jakub Jelinek [mailto:ja...@redhat.com]
> > Sent: Friday, January 17, 2014 12:46 PM
> > To: Iyer, Balaji V
> > Cc: 'Aldy Hernandez (al...@redhat.com)'; 'gcc-patches@gcc.gnu.org'
> > Subject: Re: [GOMP4][PATCH] SIMD-enabled functions (formerly
> Elemental
> > functions) for C++
> >
> > On Thu, Dec 19, 2013 at 06:12:29PM +0000, Iyer, Balaji V wrote:
> > > 2013-12-19  Balaji V. Iyer  <balaji.v.i...@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).   Added 3 new clauses:
> PRAGMA_CILK_CLAUSE_MASK,
> > >         PRAGMA_CILK_CLAUSE_NOMASK and
> > PRAGMA_CILK_CLAUSE_VECTORLENGTH
> > >         (cp_parser_cilk_simd_vectorlength): Modified this function to 
> > > handle
> > >         vectorlength clause in SIMD-enabled function and #pragma SIMD's
> > >         vectorlength clause.  Added a new bool parameter to differentiate
> > >         between the two.
> > >         (cp_parser_cilk_simd_fn_vector_attrs): New function.
> > >         (is_cilkplus_vector_p): Likewise.
> > >         (cp_parser_late_parsing_elem_fn_info): Likewise.
> > >         (cp_parser_omp_clause_name): Added a check for "mask,"
> "nomask"
> >
> > The comma should have been after " .
> >
> 
> Fixed.
> 
> > > +           /* 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_next_tokens_can_be_attribute_p (parser))
> >
> > As you are just calling cp_parser_gnu_attributes_opt here and not
> > ..._std_..., I'd say the above should be
> > cp_next_tokens_can_be_gnu_attribute_p
> > rather than cp_next_tokens_can_be_attribute_p.  I think [[...]]
> > attributes at this position are ignored, so no need to handle them,
> > not sure about whether we allow e.g. combination of GNU and std
> attributes or vice versa.
> >
> 
> Fixed.
> 
> > > +             {
> > > +               cp_parser_parse_tentatively (parser);
> > > +               tree attr = cp_parser_gnu_attributes_opt (parser);
> > > +               if (cp_lexer_next_token_is_not (parser->lexer,
> > > +                                               CPP_SEMICOLON)
> > > +                   && cp_lexer_next_token_is_not (parser->lexer,
> > > +                                                  CPP_OPEN_BRACE))
> > > +                 cp_parser_abort_tentative_parse (parser);
> > > +               else if (!cp_parser_parse_definitely (parser))
> > > +                 ;
> > > +               else
> > > +                 attrs = chainon (attr, attrs);
> > > +             }
> > >             late_return = (cp_parser_late_return_type_opt
> > >                            (parser, declarator,
> > >                             memfn ? cv_quals : -1));
> >
> > > @@ -17842,6 +17868,10 @@ cp_parser_late_return_type_opt
> (cp_parser*
> > parser, cp_declarator *declarator,
> > >        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);
> >
> > Please make sure declarator is aligned below parser.
> >
> 
> Fixed.
> 
> > > +  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));
> >
> > The = should already go on the next line.
> >
> 
> Fixed.
> 
> > > +/* 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;
> >
> > This will leak parser->cilk_simd_fn_info memory.  Please XDELETE it first.
> >
> 
> Fixed
> 
> > > +      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;
> >
> > The C FE doesn't do this.  I thought all the omp-low.c spots are now
> > guarded by flag_openmp || flag_enable_cilkplus etc. conditions.
> 
> Fixed. The above "orring" was omitted in decl.c and pt.c . I have put them in.
> 
> >
> > > +      c = build_tree_list (get_identifier ("cilk simd function"),
> > > + cl);
> >
> > Please use NULL_TREE instead of cl here and please fix up the C FE as
> > well, the "cilk simd function" attribute should be just an attribute
> > without value, serving only as a boolean, if present, decl with "omp
> > declare simd" attribute is Cilk+, otherwise OpenMP.
> >
> > > +      TREE_CHAIN (c) = attrs;
> > > +      if (processing_template_decl)
> > > + ATTR_IS_DEPENDENT (c) = 1;
> >
> 
> Fixed.
> 
> > But, as a boolean attribute it doesn't and shouldn't be
> > ATTR_IS_DEPENDENT, there is nothing to adjust in it.
> > > --- a/gcc/cp/pt.c
> > > +++ b/gcc/cp/pt.c
> > > @@ -8602,9 +8602,12 @@ apply_late_template_attributes (tree *decl_p,
> > tree attributes, int attr_flags,
> > >       {
> > >         *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));
> >
> > And this change is unnecessary after the above suggested change.
> >
> 
> Fixed.
> 
> >     Jakub
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 4490210..bbf5287 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -12924,7 +12924,8 @@ c_finish_omp_declare_simd (c_parser *parser, tree 
fndecl, tree parms,
        c = tree_cons (NULL_TREE, c, NULL_TREE);
       if (is_cilkplus_cilk_simd_fn) 
        { 
-         tree k = build_tree_list (get_identifier ("cilk simd function"), c);
+         tree k = build_tree_list (get_identifier ("cilk simd function"), 
+                                   NULL_TREE);
          TREE_CHAIN (k) = DECL_ATTRIBUTES (fndecl);
          DECL_ATTRIBUTES (fndecl) = k;
        } 
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 5906653..9918416 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7674,7 +7674,7 @@ grokfndecl (tree ctype,
   if (TYPE_NOTHROW_P (type) || nothrow_libfn_p (decl))
     TREE_NOTHROW (decl) = 1;
 
-  if (flag_openmp)
+  if (flag_openmp || flag_enable_cilkplus)
     {
       /* Adjust "omp declare simd" attributes.  */
       tree ods = lookup_attribute ("omp declare simd", *attrlist);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c3016bc..971fe8f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -241,6 +241,8 @@ static void cp_parser_cilk_simd
   (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, bool);
 
 /* Manifest constants.  */
 #define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token))
@@ -2115,6 +2117,9 @@ static bool 
cp_parser_ctor_initializer_opt_and_function_body
 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
@@ -17121,6 +17126,24 @@ cp_parser_direct_declarator (cp_parser* parser,
 
                  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_next_tokens_can_be_gnu_attribute_p (parser))
+                   {
+                     cp_parser_parse_tentatively (parser);
+                     tree attr = cp_parser_gnu_attributes_opt (parser);
+                     if (cp_lexer_next_token_is_not (parser->lexer,
+                                                     CPP_SEMICOLON)
+                         && cp_lexer_next_token_is_not (parser->lexer,
+                                                        CPP_OPEN_BRACE))
+                       cp_parser_abort_tentative_parse (parser);
+                     else if (!cp_parser_parse_definitely (parser))
+                       ;
+                     else
+                       attrs = chainon (attr, attrs);
+                   }
                  late_return = (cp_parser_late_return_type_opt
                                 (parser, declarator,
                                  memfn ? cv_quals : -1));
@@ -17829,7 +17852,7 @@ parsing_nsdmi (void)
    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.  */
@@ -17844,10 +17867,13 @@ cp_parser_late_return_type_opt (cp_parser* parser, 
cp_declarator *declarator,
                         && 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;
@@ -17866,6 +17892,10 @@ cp_parser_late_return_type_opt (cp_parser* parser, 
cp_declarator *declarator,
       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,
@@ -21399,6 +21429,56 @@ cp_parser_attributes_opt (cp_parser *parser)
   return cp_parser_std_attribute_spec_seq (parser);
 }
 
+#define CILK_SIMD_FN_CLAUSE_MASK                                 \
+       ((OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_VECTORLENGTH)   \
+        | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_LINEAR)       \
+        | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_UNIFORM)      \
+        | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_MASK)         \
+        | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_NOMASK))
+
+/* 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)
+    {
+      parser->cilk_simd_fn_info = XNEW (cp_omp_declare_simd_data);
+      parser->cilk_simd_fn_info->error_seen = false;
+      parser->cilk_simd_fn_info->fndecl_seen = false;
+      parser->cilk_simd_fn_info->tokens = vNULL;
+    }
+  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--;
+      /* 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:
@@ -21457,6 +21537,17 @@ cp_parser_gnu_attributes_opt (cp_parser* parser)
   return attributes;
 }
 
+/* Returns true of NAME is an IDENTIFIER_NODE with identiifer "vector,"
+   "__vector" or "__vector__."  */
+
+static inline bool
+is_cilkplus_vector_p (tree name)
+{ 
+  if (flag_enable_cilkplus && is_attribute_p ("vector", name)) 
+    return true;
+  return false;
+}
+
 /* Parse a GNU attribute-list.
 
    attribute-list:
@@ -21495,8 +21586,9 @@ cp_parser_gnu_attribute_list (cp_parser* parser)
        {
          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.  */
@@ -21504,7 +21596,7 @@ cp_parser_gnu_attribute_list (cp_parser* parser)
            /* 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);
 
@@ -21516,10 +21608,16 @@ cp_parser_gnu_attribute_list (cp_parser* parser)
              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 (is_cilkplus_vector_p (identifier))
+               {
+                 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
@@ -21530,6 +21628,11 @@ cp_parser_gnu_attribute_list (cp_parser* parser)
              /* Save the arguments away.  */
              TREE_VALUE (attribute) = arguments;
            }
+         else if (is_cilkplus_vector_p (identifier))
+           {
+             cp_parser_cilk_simd_fn_vector_attrs (parser, id_token);
+             continue;
+           }
 
          if (arguments != error_mark_node)
            {
@@ -26809,12 +26912,16 @@ cp_parser_omp_clause_name (cp_parser *parser)
            result = PRAGMA_OMP_CLAUSE_MAP;
          else if (!strcmp ("mergeable", p))
            result = PRAGMA_OMP_CLAUSE_MERGEABLE;
+         else if (flag_enable_cilkplus && !strcmp ("mask", p))
+           result = PRAGMA_CILK_CLAUSE_MASK;
          break;
        case 'n':
          if (!strcmp ("notinbranch", p))
            result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
          else if (!strcmp ("nowait", p))
            result = PRAGMA_OMP_CLAUSE_NOWAIT;
+         else if (flag_enable_cilkplus && !strcmp ("nomask", p))
+           result = PRAGMA_CILK_CLAUSE_NOMASK;
          else if (!strcmp ("num_teams", p))
            result = PRAGMA_OMP_CLAUSE_NUM_TEAMS;
          else if (!strcmp ("num_threads", p))
@@ -26860,6 +26967,10 @@ cp_parser_omp_clause_name (cp_parser *parser)
          else if (!strcmp ("untied", p))
            result = PRAGMA_OMP_CLAUSE_UNTIED;
          break;
+       case 'v':
+         if (flag_enable_cilkplus && !strcmp ("vectorlength", p))
+           result = PRAGMA_CILK_CLAUSE_VECTORLENGTH;
+         break;
        }
     }
 
@@ -27612,7 +27723,8 @@ cp_parser_omp_clause_aligned (cp_parser *parser, tree 
list)
    linear ( variable-list : expression )  */
 
 static tree
-cp_parser_omp_clause_linear (cp_parser *parser, tree list)
+cp_parser_omp_clause_linear (cp_parser *parser, tree list, 
+                            bool is_cilk_simd_fn)
 {
   tree nlist, c, step = integer_one_node;
   bool colon;
@@ -27627,6 +27739,11 @@ cp_parser_omp_clause_linear (cp_parser *parser, tree 
list)
     {
       step = cp_parser_expression (parser, false, NULL);
 
+      if (is_cilk_simd_fn && TREE_CODE (step) == PARM_DECL)
+       {
+         sorry ("using parameters for %<linear%> step is not supported yet");
+         step = integer_one_node;
+       }
       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
        cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                               /*or_comma=*/false,
@@ -27948,6 +28065,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, 
omp_clause_mask mask,
   tree clauses = NULL;
   bool first = true;
   cp_token *token = NULL;
+  bool cilk_simd_fn = false;
 
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
     {
@@ -28044,11 +28162,13 @@ cp_parser_omp_all_clauses (cp_parser *parser, 
omp_clause_mask mask,
          c_name = "untied";
          break;
        case PRAGMA_OMP_CLAUSE_INBRANCH:
+       case PRAGMA_CILK_CLAUSE_MASK:
          clauses = cp_parser_omp_clause_branch (parser, OMP_CLAUSE_INBRANCH,
                                                 clauses, token->location);
          c_name = "inbranch";
          break;
        case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
+       case PRAGMA_CILK_CLAUSE_NOMASK:
          clauses = cp_parser_omp_clause_branch (parser,
                                                 OMP_CLAUSE_NOTINBRANCH,
                                                 clauses, token->location);
@@ -28117,7 +28237,9 @@ cp_parser_omp_all_clauses (cp_parser *parser, 
omp_clause_mask mask,
          c_name = "aligned";
          break;
        case PRAGMA_OMP_CLAUSE_LINEAR:
-         clauses = cp_parser_omp_clause_linear (parser, clauses);
+         if (((mask >> PRAGMA_CILK_CLAUSE_VECTORLENGTH) & 1) != 0)
+           cilk_simd_fn = true;
+         clauses = cp_parser_omp_clause_linear (parser, clauses, cilk_simd_fn);
          c_name = "linear";
          break;
        case PRAGMA_OMP_CLAUSE_DEPEND:
@@ -28153,6 +28275,10 @@ cp_parser_omp_all_clauses (cp_parser *parser, 
omp_clause_mask mask,
                                                  token->location);
          c_name = "simdlen";
          break;
+       case PRAGMA_CILK_CLAUSE_VECTORLENGTH:
+         clauses = cp_parser_cilk_simd_vectorlength (parser, clauses, true);
+         c_name = "simdlen";
+         break;
        default:
          cp_parser_error (parser, "expected %<#pragma omp%> clause");
          goto saw_error;
@@ -28169,7 +28295,10 @@ cp_parser_omp_all_clauses (cp_parser *parser, 
omp_clause_mask mask,
        }
     }
  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;
@@ -30171,6 +30300,63 @@ cp_parser_omp_declare_simd (cp_parser *parser, 
cp_token *pragma_tok,
     }
 }
 
+/* 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");
+      XDELETE (parser->cilk_simd_fn_info);
+      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;
+
+  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, CILK_SIMD_FN_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"), NULL_TREE);
+      TREE_CHAIN (c) = attrs;
+      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;
+  XDELETE (parser->cilk_simd_fn_info);
+  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.  */
 
@@ -31351,35 +31537,63 @@ c_parse_file (void)
   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,
+                                 bool is_simd_fn)
 {
   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);
-  
+  /* The vectorlength clause in #pragma simd behaves exactly like OpenMP's
+     safelen clause.  Thus, vectorlength is represented as OMP 4.0
+     safelen.  For SIMD-enabled function it is represented by OMP 4.0
+     simdlen.  */
+  if (!is_simd_fn)
+    check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength", 
+                              loc);
+  else
+    check_no_duplicate_clause (clauses, OMP_CLAUSE_SIMDLEN, "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 = maybe_constant_value (expr);
-
-  if (TREE_CONSTANT (expr)
+  
+  /* If expr == error_mark_node, then don't emit any errors nor
+     create a clause.  if any of the above functions returns
+     error mark node then they would have emitted an error message.  */
+  if (expr == error_mark_node)
+    ;
+  else if (!TREE_TYPE (expr)
+          || !TREE_CONSTANT (expr)
+          || !INTEGRAL_TYPE_P (TREE_TYPE (expr)))
+    error_at (loc, "vectorlength must be an integer constant");
+  else 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)
+  else 
     {
-      tree c = build_omp_clause (loc, OMP_CLAUSE_SAFELEN);
-      OMP_CLAUSE_SAFELEN_EXPR (c) = expr;
-      OMP_CLAUSE_CHAIN (c) = clauses;
-      clauses = c;
+      tree c;
+      if (!is_simd_fn)
+       { 
+         c = build_omp_clause (loc, OMP_CLAUSE_SAFELEN); 
+         OMP_CLAUSE_SAFELEN_EXPR (c) = expr; 
+         OMP_CLAUSE_CHAIN (c) = clauses; 
+         clauses = c;
+       }
+      else
+       {
+         c = build_omp_clause (loc, OMP_CLAUSE_SIMDLEN);
+         OMP_CLAUSE_SIMDLEN_EXPR (c) = expr;
+         OMP_CLAUSE_CHAIN (c) = clauses;
+         clauses = c;
+       }
     }
 
   if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
@@ -31542,7 +31756,7 @@ cp_parser_cilk_simd_all_clauses (cp_parser *parser, 
cp_token *pragma_token)
       pragma_omp_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, false);
       else if (c_kind == PRAGMA_CILK_CLAUSE_LINEAR)
        clauses = cp_parser_cilk_simd_linear (parser, clauses);
       else if (c_kind == PRAGMA_CILK_CLAUSE_PRIVATE)
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index 484a8cd..d558c60 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -362,6 +362,13 @@ typedef struct GTY(()) cp_parser {
      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;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2e7cf60..a91df4c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8613,7 +8613,7 @@ apply_late_template_attributes (tree *decl_p, tree 
attributes, int attr_flags,
            {
              *p = TREE_CHAIN (t);
              TREE_CHAIN (t) = NULL_TREE;
-             if (flag_openmp
+             if ((flag_openmp || flag_enable_cilkplus)
                  && is_attribute_p ("omp declare simd",
                                     get_attribute_name (t))
                  && TREE_VALUE (t))
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c 
b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c
index ab55fae..195e9f1 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c
@@ -1,9 +1,9 @@
 /* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
 /* { dg-options "-fcilkplus -Wall" } */
 
-__attribute__((vector (linear (x:y))))
+__attribute__((vector (linear (x:y)))) /* { dg-message "parameter" "" { target 
c++ } } */
 int func2 (int x, int y) 
-{ /* { dg-message "using parameters for" } */
+{ /* { dg-message "using parameters for" "" { target c } } */
   return (x+y);
 }
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c 
b/gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c
index 38d610a..1bcf2a2 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c
@@ -5,7 +5,8 @@
 
 int z = Q;
 
-__attribute__ ((vector (uniform(x), vectorlength (), linear (y:1) ))) /* { 
dg-error "expected expression" } */
+__attribute__ ((vector (uniform(x), vectorlength (), linear (y:1) ))) /* { 
dg-error "expected expression" "" { target c } } */ 
+     /* { dg-error "expected primary-expression" "" { target c++ }  8 } */ 
 int func2 (int x, int y)
 {
   int zq = 5;
@@ -19,7 +20,8 @@ int func3 (int x, int y)
   return x + (y*zq);
 }
 
-__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (z) ))) /* { 
dg-error "vectorlength must be an integer" } */
+__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (z) ))) /* { 
dg-error "vectorlength must be an integer" "" { target c } } */ 
+     /* { dg-error "constant" "" { target c++ } 23 } */
 int func4 (int x, int y)
 {
   int zq = 5;
@@ -33,7 +35,8 @@ int func5 (int x, int y)
   return x + (y*zq);
 }
 
-__attribute__ ((vector (uniform(x), vectorlength (z), linear (y:1)))) /* { 
dg-error "vectorlength must be an integer" } */
+__attribute__ ((vector (uniform(x), vectorlength (z), linear (y:1)))) /* { 
dg-error "vectorlength must be an integer" ""  { target c } } */ 
+     /* { dg-error "constant" "" { target c++ }  38 } */
 int func6 (int x, int y)
 {
   int zq = 5;
diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp 
b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
index 37b8ccb..204a754 100644
--- a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
@@ -33,6 +33,9 @@ set TEST_EXTRA_LIBS "-L${library_var}/libcilkrts/.libs"
 dg-init
 # Run the tests that are shared with C.
 g++-dg-runtest [lsort [glob -nocomplain 
$srcdir/c-c++-common/cilk-plus/PS/*.c]] ""
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] 
"-O3" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " 
" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] 
"-g -O2" " "
 # Run the C++ only tests.
 g++-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] ""
 dg-finish
diff --git a/gcc/testsuite/g++.dg/cilk-plus/ef_test.C 
b/gcc/testsuite/g++.dg/cilk-plus/ef_test.C
new file mode 100644
index 0000000..3e75cbd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/ef_test.C
@@ -0,0 +1,37 @@
+/* { 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;
+}

Attachment: ChangeLog.elem_fn
Description: ChangeLog.elem_fn

Reply via email to