diff options
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/c-decl.cc | 10 | ||||
-rw-r--r-- | gcc/c/c-parser.cc | 102 | ||||
-rw-r--r-- | gcc/c/c-parser.h | 1 |
3 files changed, 105 insertions, 8 deletions
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 33fb64d..0076725 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -5385,11 +5385,11 @@ c_decl_attributes (tree *node, tree attributes, int flags) { tree d = TREE_VALUE (a); gcc_assert (TREE_CODE (d) == C_TOKEN_VEC); -/* if (TREE_PUBLIC (d) - && (VAR_P (*decl) - || TREE_CODE (*decl) == FUNCTION_DECL) - && c_maybe_parse_omp_decl (*decl, d)) - continue; */ + if (TREE_PUBLIC (d) + && (VAR_P (*node) + || TREE_CODE (*node) == FUNCTION_DECL) + && c_maybe_parse_omp_decl (*node, d)) + continue; p = TREE_PUBLIC (d) ? "decl" : "directive"; } if (p && !diagnosed) diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 20efd4d..ba1e7e9 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -262,6 +262,10 @@ struct GTY(()) c_parser { attributes turned into pragma, vector of tokens created from that, otherwise NULL. */ vec<c_token, va_gc> *in_omp_attribute_pragma; + + /* Set for omp::decl attribute parsing to the decl to which it + appertains. */ + tree in_omp_decl_attribute; }; /* Return a pointer to the Nth token in PARSERs tokens_buf. */ @@ -5797,14 +5801,14 @@ c_parser_std_attribute (c_parser *parser, bool for_tm, parens.skip_until_found_close (parser); return attribute; } -/* else if (is_attribute_p ("decl", name)) + else if (is_attribute_p ("decl", name)) { TREE_VALUE (TREE_PURPOSE (attribute)) = get_identifier ("directive"); c_parser_omp_directive_args (parser, attribute, true); parens.skip_until_found_close (parser); return attribute; - } */ + } else if (is_attribute_p ("sequence", name)) { TREE_VALUE (TREE_PURPOSE (attribute)) @@ -15147,6 +15151,19 @@ c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind, /* The clauses location. */ location_t loc = c_parser_peek_token (parser)->location; + if (parser->in_omp_decl_attribute) + { + if (kind) + { + tree u = build_omp_clause (loc, kind); + OMP_CLAUSE_DECL (u) = parser->in_omp_decl_attribute; + OMP_CLAUSE_CHAIN (u) = list; + return u; + } + else + return tree_cons (parser->in_omp_decl_attribute, NULL_TREE, list); + } + matching_parens parens; if (parens.require_open (parser)) { @@ -24498,6 +24515,84 @@ c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms, clauses[0].type = CPP_PRAGMA; } +/* D should be C_TOKEN_VEC from omp::decl attribute. If it contains + a threadprivate, groupprivate, allocate or declare target directive, + return true and parse it for DECL. */ + +bool +c_maybe_parse_omp_decl (tree decl, tree d) +{ + gcc_assert (TREE_CODE (d) == C_TOKEN_VEC); + vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d); + c_token *first = toks->address (); + c_token *last = first + toks->length (); + const char *directive[3] = {}; + for (int j = 0; j < 3; j++) + { + tree id = NULL_TREE; + if (first + j == last) + break; + if (first[j].type == CPP_NAME) + id = first[j].value; + else if (first[j].type == CPP_KEYWORD) + id = ridpointers[(int) first[j].keyword]; + else + break; + directive[j] = IDENTIFIER_POINTER (id); + } + const c_omp_directive *dir = NULL; + if (directive[0]) + dir = c_omp_categorize_directive (directive[0], directive[1], + directive[2]); + if (dir == NULL) + { + error_at (first->location, + "unknown OpenMP directive name in " + "%qs attribute argument", "omp::decl"); + return false; + } + if (dir->id != PRAGMA_OMP_THREADPRIVATE + /* && dir->id != PRAGMA_OMP_GROUPPRIVATE */ + && dir->id != PRAGMA_OMP_ALLOCATE + && (dir->id != PRAGMA_OMP_DECLARE + || strcmp (directive[1], "target") != 0)) + return false; + + if (!flag_openmp && !dir->simd) + return true; + + c_parser *parser = the_parser; + unsigned int tokens_avail = parser->tokens_avail; + gcc_assert (parser->tokens == &parser->tokens_buf[0]); + toks = NULL; + vec_safe_reserve (toks, last - first + 2, true); + c_token tok = {}; + tok.type = CPP_PRAGMA; + tok.keyword = RID_MAX; + tok.pragma_kind = pragma_kind (dir->id); + tok.location = first->location; + toks->quick_push (tok); + while (++first < last) + toks->quick_push (*first); + tok = {}; + tok.type = CPP_PRAGMA_EOL; + tok.keyword = RID_MAX; + tok.location = last[-1].location; + toks->quick_push (tok); + tok = {}; + tok.type = CPP_EOF; + tok.keyword = RID_MAX; + tok.location = last[-1].location; + tok.flags = tokens_avail; + toks->quick_push (tok); + parser->in_omp_decl_attribute = decl; + parser->tokens = toks->address (); + parser->tokens_avail = toks->length (); + parser->in_omp_attribute_pragma = toks; + c_parser_pragma (parser, pragma_external, NULL); + parser->in_omp_decl_attribute = NULL_TREE; + return true; +} /* OpenMP 4.0: # pragma omp declare target new-line @@ -24526,7 +24621,8 @@ c_parser_omp_declare_target (c_parser *parser) && c_parser_peek_2nd_token (parser)->type == CPP_NAME)) clauses = c_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK, "#pragma omp declare target"); - else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + else if (parser->in_omp_decl_attribute + || c_parser_next_token_is (parser, CPP_OPEN_PAREN)) { clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ENTER, clauses); diff --git a/gcc/c/c-parser.h b/gcc/c/c-parser.h index f99d144..d6dca86 100644 --- a/gcc/c/c-parser.h +++ b/gcc/c/c-parser.h @@ -204,5 +204,6 @@ extern void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool, bool, bool, bool, bool, bool, enum c_lookahead_kind); extern struct c_type_name *c_parser_type_name (c_parser *, bool = false); +extern bool c_maybe_parse_omp_decl (tree, tree); #endif |