summaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog16
-rw-r--r--gcc/cp/class.c8
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c205
-rw-r--r--gcc/cp/parser.c66
-rw-r--r--gcc/cp/tree.c3
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,