diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/cp/class.c | 8 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/decl.c | 205 | ||||
-rw-r--r-- | gcc/cp/parser.c | 66 | ||||
-rw-r--r-- | gcc/cp/tree.c | 3 |
6 files changed, 282 insertions, 18 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 87a78f20b60..55c3f0babe7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2019-10-30 Jakub Jelinek <jakub@redhat.com> + + * cp-tree.h (omp_declare_variant_finalize, build_local_temp): Declare. + * decl.c: Include omp-general.h. + (declare_simd_adjust_this): Add forward declaration. + (omp_declare_variant_finalize_one, omp_declare_variant_finalize): New + function. + (cp_finish_decl, finish_function): Call omp_declare_variant_finalize. + * parser.c (cp_finish_omp_declare_variant): Adjust parsing of the + variant id-expression and propagate enough information to + omp_declare_variant_finalize_one in the attribute so that it can + finalize it. + * class.c (finish_struct): Call omp_declare_variant_finalize. + * tree.c (build_local_temp): No longer static, remove forward + declaration. + 2019-10-30 Paolo Carlini <paolo.carlini@oracle.com> * typeck.c (cp_build_modify_expr): Prefer error + inform to diff --git a/gcc/cp/class.c b/gcc/cp/class.c index a66c25b65be..045b2e33dbb 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -7378,6 +7378,14 @@ finish_struct (tree t, tree attributes) else error ("trying to finish struct, but kicked out due to previous parse errors"); + if (flag_openmp) + for (tree decl = TYPE_FIELDS (t); decl; decl = DECL_CHAIN (decl)) + if (TREE_CODE (decl) == FUNCTION_DECL + && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) + if (tree attr = lookup_attribute ("omp declare variant base", + DECL_ATTRIBUTES (decl))) + omp_declare_variant_finalize (decl, attr); + if (processing_template_decl && at_function_scope_p () /* Lambdas are defined by the LAMBDA_EXPR. */ && !LAMBDA_TYPE_P (t)) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 37b954a6c6f..42e03a31e20 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6435,6 +6435,7 @@ extern tree groktypename (cp_decl_specifier_seq *, const cp_declarator *, bool extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, tree *); extern void start_decl_1 (tree, bool); extern bool check_array_initializer (tree, tree, tree); +extern void omp_declare_variant_finalize (tree, tree); extern void cp_finish_decl (tree, tree, bool, tree, int); extern tree lookup_decomp_type (tree); extern void cp_maybe_mangle_decomp (tree, tree, unsigned int); @@ -7293,6 +7294,7 @@ extern tree build_min_nt_call_vec (tree, vec<tree, va_gc> *); extern tree build_min_non_dep_call_vec (tree, tree, vec<tree, va_gc> *); extern vec<tree, va_gc>* vec_copy_and_insert (vec<tree, va_gc>*, tree, unsigned); extern tree build_cplus_new (tree, tree, tsubst_flags_t); +extern tree build_local_temp (tree); extern tree build_aggr_init_expr (tree, tree); extern tree get_target_expr (tree); extern tree get_target_expr_sfinae (tree, tsubst_flags_t); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 95c84159d7a..8320597c108 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "asan.h" #include "gcc-rich-location.h" #include "langhooks.h" +#include "omp-general.h" /* Possible cases of bad specifiers type used by bad_specifiers. */ enum bad_spec_place { @@ -7070,6 +7071,195 @@ decl_maybe_constant_destruction (tree decl, tree type) && type_has_constexpr_destructor (strip_array_types (type)))); } +static tree declare_simd_adjust_this (tree *, int *, void *); + +/* Helper function of omp_declare_variant_finalize. Finalize one + "omp declare variant base" attribute. Return true if it should be + removed. */ + +static bool +omp_declare_variant_finalize_one (tree decl, tree attr) +{ + if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) + walk_tree (&TREE_VALUE (TREE_VALUE (attr)), declare_simd_adjust_this, + DECL_ARGUMENTS (decl), NULL); + + tree ctx = TREE_VALUE (TREE_VALUE (attr)); + tree simd = c_omp_get_context_selector (ctx, "construct", "simd"); + if (simd) + { + TREE_VALUE (simd) + = c_omp_declare_simd_clauses_to_numbers (DECL_ARGUMENTS (decl), + TREE_VALUE (simd)); + /* FIXME, adjusting simd args unimplemented. */ + return true; + } + + tree chain = TREE_CHAIN (TREE_VALUE (attr)); + location_t varid_loc + = cp_expr_loc_or_input_loc (TREE_PURPOSE (TREE_CHAIN (chain))); + location_t match_loc = cp_expr_loc_or_input_loc (TREE_PURPOSE (chain)); + cp_id_kind idk = (cp_id_kind) tree_to_uhwi (TREE_VALUE (chain)); + tree variant = TREE_PURPOSE (TREE_VALUE (attr)); + + location_t save_loc = input_location; + input_location = varid_loc; + + releasing_vec args; + tree parm = DECL_ARGUMENTS (decl); + if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) + parm = DECL_CHAIN (parm); + for (; parm; parm = DECL_CHAIN (parm)) + if (type_dependent_expression_p (parm)) + vec_safe_push (args, build_constructor (TREE_TYPE (parm), NULL)); + else if (MAYBE_CLASS_TYPE_P (TREE_TYPE (parm))) + vec_safe_push (args, build_local_temp (TREE_TYPE (parm))); + else + vec_safe_push (args, build_zero_cst (TREE_TYPE (parm))); + + bool koenig_p = false; + if (idk == CP_ID_KIND_UNQUALIFIED || idk == CP_ID_KIND_TEMPLATE_ID) + { + if (identifier_p (variant) + /* In C++2A, we may need to perform ADL for a template + name. */ + || (TREE_CODE (variant) == TEMPLATE_ID_EXPR + && identifier_p (TREE_OPERAND (variant, 0)))) + { + if (!args->is_empty ()) + { + koenig_p = true; + if (!any_type_dependent_arguments_p (args)) + variant = perform_koenig_lookup (variant, args, + tf_warning_or_error); + } + else + variant = unqualified_fn_lookup_error (variant); + } + else if (!args->is_empty () && is_overloaded_fn (variant)) + { + tree fn = get_first_fn (variant); + fn = STRIP_TEMPLATE (fn); + if (!((TREE_CODE (fn) == USING_DECL && DECL_DEPENDENT_P (fn)) + || DECL_FUNCTION_MEMBER_P (fn) + || DECL_LOCAL_FUNCTION_P (fn))) + { + koenig_p = true; + if (!any_type_dependent_arguments_p (args)) + variant = perform_koenig_lookup (variant, args, + tf_warning_or_error); + } + } + } + + if (idk == CP_ID_KIND_QUALIFIED) + variant = finish_call_expr (variant, &args, /*disallow_virtual=*/true, + koenig_p, tf_warning_or_error); + else + variant = finish_call_expr (variant, &args, /*disallow_virtual=*/false, + koenig_p, tf_warning_or_error); + if (variant == error_mark_node && !processing_template_decl) + return true; + + variant = cp_get_callee_fndecl_nofold (variant); + + input_location = save_loc; + + if (variant) + { + const char *varname = IDENTIFIER_POINTER (DECL_NAME (variant)); + if (!comptypes (TREE_TYPE (decl), TREE_TYPE (variant), 0)) + { + error_at (varid_loc, "variant %qD and base %qD have incompatible " + "types", variant, decl); + return true; + } + if (fndecl_built_in_p (variant) + && (strncmp (varname, "__builtin_", strlen ("__builtin_")) == 0 + || strncmp (varname, "__sync_", strlen ("__sync_")) == 0 + || strncmp (varname, "__atomic_", strlen ("__atomic_")) == 0)) + { + error_at (varid_loc, "variant %qD is a built-in", variant); + return true; + } + else + { + tree construct = c_omp_get_context_selector (ctx, "construct", NULL); + c_omp_mark_declare_variant (match_loc, variant, construct); + if (!omp_context_selector_matches (ctx)) + return true; + TREE_PURPOSE (TREE_VALUE (attr)) = variant; + } + } + else if (!processing_template_decl) + { + error_at (varid_loc, "could not find variant %qD declaration", variant); + return true; + } + + return false; +} + +/* Helper function, finish up "omp declare variant base" attribute + now that there is a DECL. ATTR is the first "omp declare variant base" + attribute. */ + +void +omp_declare_variant_finalize (tree decl, tree attr) +{ + size_t attr_len = strlen ("omp declare variant base"); + tree *list = &DECL_ATTRIBUTES (decl); + bool remove_all = false; + location_t match_loc = DECL_SOURCE_LOCATION (decl); + if (TREE_CHAIN (TREE_VALUE (attr)) + && TREE_PURPOSE (TREE_CHAIN (TREE_VALUE (attr))) + && EXPR_HAS_LOCATION (TREE_PURPOSE (TREE_CHAIN (TREE_VALUE (attr))))) + match_loc = EXPR_LOCATION (TREE_PURPOSE (TREE_CHAIN (TREE_VALUE (attr)))); + if (DECL_CONSTRUCTOR_P (decl)) + { + error_at (match_loc, "%<declare variant%> on constructor %qD", decl); + remove_all = true; + } + else if (DECL_DESTRUCTOR_P (decl)) + { + error_at (match_loc, "%<declare variant%> on destructor %qD", decl); + remove_all = true; + } + else if (DECL_DEFAULTED_FN (decl)) + { + error_at (match_loc, "%<declare variant%> on defaulted %qD", decl); + remove_all = true; + } + else if (DECL_DELETED_FN (decl)) + { + error_at (match_loc, "%<declare variant%> on deleted %qD", decl); + remove_all = true; + } + else if (DECL_VIRTUAL_P (decl)) + { + error_at (match_loc, "%<declare variant%> on virtual %qD", decl); + remove_all = true; + } + /* This loop is like private_lookup_attribute, except that it works + with tree * rather than tree, as we might want to remove the + attributes that are diagnosed as errorneous. */ + while (*list) + { + tree attr = get_attribute_name (*list); + size_t ident_len = IDENTIFIER_LENGTH (attr); + if (cmp_attribs ("omp declare variant base", attr_len, + IDENTIFIER_POINTER (attr), ident_len)) + { + if (remove_all || omp_declare_variant_finalize_one (decl, *list)) + { + *list = TREE_CHAIN (*list); + continue; + } + } + list = &TREE_CHAIN (*list); + } +} + /* Finish processing of a declaration; install its line number and initial value. If the length of an array type is not known before, @@ -7235,6 +7425,16 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, } } + if (flag_openmp + && TREE_CODE (decl) == FUNCTION_DECL + /* #pragma omp declare variant on methods handled in finish_struct + instead. */ + && (!DECL_NONSTATIC_MEMBER_FUNCTION_P (decl) + || COMPLETE_TYPE_P (DECL_CONTEXT (decl)))) + if (tree attr = lookup_attribute ("omp declare variant base", + DECL_ATTRIBUTES (decl))) + omp_declare_variant_finalize (decl, attr); + if (processing_template_decl) { bool type_dependent_p; @@ -16475,6 +16675,11 @@ finish_function (bool inline_p) if (DECL_DECLARED_CONCEPT_P (fndecl)) check_function_concept (fndecl); + if (flag_openmp) + if (tree attr = lookup_attribute ("omp declare variant base", + DECL_ATTRIBUTES (fndecl))) + omp_declare_variant_finalize (fndecl, attr); + /* Lambda closure members are implicitly constexpr if possible. */ if (cxx_dialect >= cxx17 && LAMBDA_TYPE_P (CP_DECL_CONTEXT (fndecl))) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b394e2e1467..e29e99f418b 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -40666,25 +40666,53 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, return attrs; } - cp_token *token = cp_lexer_peek_token (parser->lexer); + bool template_p; + cp_id_kind idk = CP_ID_KIND_NONE; + cp_token *varid_token = cp_lexer_peek_token (parser->lexer); + cp_expr varid + = cp_parser_id_expression (parser, /*template_keyword_p=*/false, + /*check_dependency_p=*/true, + /*template_p=*/&template_p, + /*declarator_p=*/false, + /*optional_p=*/false); + parens.require_close (parser); + tree variant; - tree name = cp_parser_id_expression (parser, /*template_p=*/false, - /*check_dependency_p=*/true, - /*template_p=*/NULL, - /*declarator_p=*/false, - /*optional_p=*/false); - if (identifier_p (name)) - variant = cp_parser_lookup_name_simple (parser, name, token->location); + if (TREE_CODE (varid) == TEMPLATE_ID_EXPR + || TREE_CODE (varid) == TYPE_DECL + || varid == error_mark_node) + variant = varid; + else if (varid_token->type == CPP_NAME && varid_token->error_reported) + variant = NULL_TREE; else - variant = name; - if (variant == error_mark_node) { - cp_parser_name_lookup_error (parser, name, variant, NLE_NULL, - token->location); - variant = error_mark_node; + tree ambiguous_decls; + variant = cp_parser_lookup_name (parser, varid, none_type, + template_p, /*is_namespace=*/false, + /*check_dependency=*/true, + &ambiguous_decls, + varid.get_location ()); + if (ambiguous_decls) + variant = NULL_TREE; } - - parens.require_close (parser); + if (variant == NULL_TREE) + variant = error_mark_node; + else if (TREE_CODE (variant) != SCOPE_REF) + { + const char *error_msg; + variant + = finish_id_expression (varid, variant, parser->scope, + &idk, false, true, + &parser->non_integral_constant_expression_p, + template_p, true, false, false, &error_msg, + varid.get_location ()); + if (error_msg) + cp_parser_error (parser, error_msg); + } + location_t caret_loc = get_pure_location (varid.get_location ()); + location_t start_loc = get_start (varid_token->location); + location_t finish_loc = get_finish (varid.get_location ()); + location_t varid_loc = make_location (caret_loc, start_loc, finish_loc); const char *clause = ""; location_t match_loc = cp_lexer_peek_token (parser->lexer)->location; @@ -40707,8 +40735,14 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, ctx = c_omp_check_context_selector (match_loc, ctx); if (ctx != error_mark_node && variant != error_mark_node) { + tree match_loc_node = maybe_wrap_with_location (integer_zero_node, + match_loc); + tree loc_node = maybe_wrap_with_location (integer_zero_node, varid_loc); + loc_node = tree_cons (match_loc_node, + build_int_cst (integer_type_node, idk), + build_tree_list (loc_node, integer_zero_node)); attrs = tree_cons (get_identifier ("omp declare variant base"), - build_tree_list (variant, ctx), attrs); + tree_cons (variant, ctx, loc_node), attrs); if (processing_template_decl) ATTR_IS_DEPENDENT (attrs) = 1; } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 9d63736a394..ca4d3e2a48b 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -43,7 +43,6 @@ static hashval_t list_hash_pieces (tree, tree, tree); static tree build_target_expr (tree, tree, tsubst_flags_t); static tree count_trees_r (tree *, int *, void *); static tree verify_stmt_tree_r (tree *, int *, void *); -static tree build_local_temp (tree); static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *); static tree handle_abi_tag_attribute (tree *, tree, tree, int, bool *); @@ -525,7 +524,7 @@ build_target_expr (tree decl, tree value, tsubst_flags_t complain) /* Return an undeclared local temporary of type TYPE for use in building a TARGET_EXPR. */ -static tree +tree build_local_temp (tree type) { tree slot = build_decl (input_location, |