aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/pt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r--gcc/cp/pt.c293
1 files changed, 258 insertions, 35 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a350007..5721a68 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8545,6 +8545,8 @@ can_complete_type_without_circularity (tree type)
return 1;
}
+static tree tsubst_omp_clauses (tree, bool, tree, tsubst_flags_t, tree);
+
/* Apply any attributes which had to be deferred until instantiation
time. DECL_P, ATTRIBUTES and ATTR_FLAGS are as cplus_decl_attributes;
ARGS, COMPLAIN, IN_DECL are as tsubst. */
@@ -8586,14 +8588,32 @@ 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))
+ && TREE_VALUE (t))
+ {
+ tree clauses = TREE_VALUE (TREE_VALUE (t));
+ clauses = tsubst_omp_clauses (clauses, true, args,
+ complain, in_decl);
+ c_omp_declare_simd_clauses_to_decls (*decl_p, clauses);
+ clauses = finish_omp_clauses (clauses);
+ tree parms = DECL_ARGUMENTS (*decl_p);
+ clauses
+ = c_omp_declare_simd_clauses_to_numbers (parms, clauses);
+ if (clauses)
+ TREE_VALUE (TREE_VALUE (t)) = clauses;
+ else
+ TREE_VALUE (t) = NULL_TREE;
+ }
/* If the first attribute argument is an identifier, don't
pass it through tsubst. Attributes like mode, format,
cleanup and several target specific attributes expect it
unmodified. */
- if (TREE_VALUE (t)
- && TREE_CODE (TREE_VALUE (t)) == TREE_LIST
- && TREE_VALUE (TREE_VALUE (t))
- && (identifier_p (TREE_VALUE (TREE_VALUE (t)))))
+ else if (TREE_VALUE (t)
+ && TREE_CODE (TREE_VALUE (t)) == TREE_LIST
+ && TREE_VALUE (TREE_VALUE (t))
+ && identifier_p (TREE_VALUE (TREE_VALUE (t))))
{
tree chain
= tsubst_expr (TREE_CHAIN (TREE_VALUE (t)), args, complain,
@@ -8915,6 +8935,9 @@ instantiate_class_template_1 (tree type)
/* Instantiate members marked with attribute used. */
if (r != error_mark_node && DECL_PRESERVE_P (r))
mark_used (r);
+ if (TREE_CODE (r) == FUNCTION_DECL
+ && DECL_OMP_DECLARE_REDUCTION_P (r))
+ cp_check_omp_declare_reduction (r);
}
else
{
@@ -10383,6 +10406,24 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
DECL_INITIAL (r) = NULL_TREE;
DECL_CONTEXT (r) = ctx;
+ /* OpenMP UDRs have the only argument a reference to the declared
+ type. We want to diagnose if the declared type is a reference,
+ which is invalid, but as references to references are usually
+ quietly merged, diagnose it here. */
+ if (DECL_OMP_DECLARE_REDUCTION_P (t))
+ {
+ tree argtype
+ = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (t))));
+ argtype = tsubst (argtype, args, complain, in_decl);
+ if (TREE_CODE (argtype) == REFERENCE_TYPE)
+ error_at (DECL_SOURCE_LOCATION (t),
+ "reference type %qT in "
+ "%<#pragma omp declare reduction%>", argtype);
+ if (strchr (IDENTIFIER_POINTER (DECL_NAME (t)), '~') == NULL)
+ DECL_NAME (r) = omp_reduction_id (ERROR_MARK, DECL_NAME (t),
+ argtype);
+ }
+
if (member && DECL_CONV_FN_P (r))
/* Type-conversion operator. Reconstruct the name, in
case it's the name of one of the template's parameters. */
@@ -12815,8 +12856,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
/* Like tsubst_copy, but specifically for OpenMP clauses. */
static tree
-tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
- tree in_decl)
+tsubst_omp_clauses (tree clauses, bool declare_simd,
+ tree args, tsubst_flags_t complain, tree in_decl)
{
tree new_clauses = NULL, nc, oc;
@@ -12841,7 +12882,6 @@ tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_SHARED:
case OMP_CLAUSE_FIRSTPRIVATE:
- case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_COPYPRIVATE:
case OMP_CLAUSE_IF:
@@ -12849,22 +12889,73 @@ tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_FINAL:
+ case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_FROM:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_UNIFORM:
+ case OMP_CLAUSE_MAP:
+ case OMP_CLAUSE_DEVICE:
+ case OMP_CLAUSE_DIST_SCHEDULE:
+ case OMP_CLAUSE_NUM_TEAMS:
+ case OMP_CLAUSE_THREAD_LIMIT:
+ case OMP_CLAUSE_SAFELEN:
+ case OMP_CLAUSE_SIMDLEN:
OMP_CLAUSE_OPERAND (nc, 0)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
break;
+ case OMP_CLAUSE_REDUCTION:
+ if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (oc))
+ {
+ tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (oc);
+ if (TREE_CODE (placeholder) == SCOPE_REF)
+ {
+ tree scope = tsubst (TREE_OPERAND (placeholder, 0), args,
+ complain, in_decl);
+ OMP_CLAUSE_REDUCTION_PLACEHOLDER (nc)
+ = build_qualified_name (NULL_TREE, scope,
+ TREE_OPERAND (placeholder, 1),
+ false);
+ }
+ else
+ gcc_assert (identifier_p (placeholder));
+ }
+ OMP_CLAUSE_OPERAND (nc, 0)
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
+ break;
+ case OMP_CLAUSE_LINEAR:
+ case OMP_CLAUSE_ALIGNED:
+ OMP_CLAUSE_OPERAND (nc, 0)
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
+ OMP_CLAUSE_OPERAND (nc, 1)
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
+ break;
+
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_MERGEABLE:
+ case OMP_CLAUSE_INBRANCH:
+ case OMP_CLAUSE_NOTINBRANCH:
+ case OMP_CLAUSE_PROC_BIND:
+ case OMP_CLAUSE_FOR:
+ case OMP_CLAUSE_PARALLEL:
+ case OMP_CLAUSE_SECTIONS:
+ case OMP_CLAUSE_TASKGROUP:
break;
default:
gcc_unreachable ();
}
}
- return finish_omp_clauses (nreverse (new_clauses));
+ new_clauses = nreverse (new_clauses);
+ if (!declare_simd)
+ new_clauses = finish_omp_clauses (new_clauses);
+ return new_clauses;
}
/* Like tsubst_copy_and_build, but unshare TREE_LIST nodes. */
@@ -13169,6 +13260,15 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
}
else if (DECL_IMPLICIT_TYPEDEF_P (t))
/* We already did a pushtag. */;
+ else if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_OMP_DECLARE_REDUCTION_P (decl)
+ && DECL_FUNCTION_SCOPE_P (pattern_decl))
+ {
+ DECL_CONTEXT (decl) = NULL_TREE;
+ pushdecl (decl);
+ DECL_CONTEXT (decl) = current_function_decl;
+ cp_check_omp_declare_reduction (decl);
+ }
else
{
int const_init = false;
@@ -13440,7 +13540,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
break;
case OMP_PARALLEL:
- tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t),
+ tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t), false,
args, complain, in_decl);
stmt = begin_omp_parallel ();
RECUR (OMP_PARALLEL_BODY (t));
@@ -13449,7 +13549,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
break;
case OMP_TASK:
- tmp = tsubst_omp_clauses (OMP_TASK_CLAUSES (t),
+ tmp = tsubst_omp_clauses (OMP_TASK_CLAUSES (t), false,
args, complain, in_decl);
stmt = begin_omp_task ();
RECUR (OMP_TASK_BODY (t));
@@ -13457,17 +13557,23 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
break;
case OMP_FOR:
+ case OMP_SIMD:
+ case OMP_DISTRIBUTE:
{
tree clauses, body, pre_body;
- tree declv, initv, condv, incrv;
+ tree declv = NULL_TREE, initv = NULL_TREE, condv = NULL_TREE;
+ tree incrv = NULL_TREE;
int i;
- clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t),
+ clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t), false,
args, complain, in_decl);
- declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
- initv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
- condv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
- incrv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ if (OMP_FOR_INIT (t) != NULL_TREE)
+ {
+ declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ initv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ condv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ incrv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ }
stmt = begin_omp_structured_block ();
@@ -13475,17 +13581,29 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
RECUR (OMP_FOR_PRE_BODY (t));
pre_body = pop_stmt_list (pre_body);
- for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++)
- tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv,
- &clauses, args, complain, in_decl,
- integral_constant_expression_p);
+ if (OMP_FOR_INIT (t) != NULL_TREE)
+ for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++)
+ tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv,
+ &clauses, args, complain, in_decl,
+ integral_constant_expression_p);
body = push_stmt_list ();
RECUR (OMP_FOR_BODY (t));
body = pop_stmt_list (body);
- t = finish_omp_for (EXPR_LOCATION (t), declv, initv, condv, incrv,
- body, pre_body, clauses);
+ if (OMP_FOR_INIT (t) != NULL_TREE)
+ t = finish_omp_for (EXPR_LOCATION (t), TREE_CODE (t), declv, initv,
+ condv, incrv, body, pre_body, clauses);
+ else
+ {
+ t = make_node (TREE_CODE (t));
+ TREE_TYPE (t) = void_type_node;
+ OMP_FOR_BODY (t) = body;
+ OMP_FOR_PRE_BODY (t) = pre_body;
+ OMP_FOR_CLAUSES (t) = clauses;
+ SET_EXPR_LOCATION (t, EXPR_LOCATION (t));
+ add_stmt (t);
+ }
add_stmt (finish_omp_structured_block (stmt));
}
@@ -13493,7 +13611,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
case OMP_SECTIONS:
case OMP_SINGLE:
- tmp = tsubst_omp_clauses (OMP_CLAUSES (t), args, complain, in_decl);
+ case OMP_TEAMS:
+ case OMP_TARGET_DATA:
+ case OMP_TARGET:
+ tmp = tsubst_omp_clauses (OMP_CLAUSES (t), false,
+ args, complain, in_decl);
stmt = push_stmt_list ();
RECUR (OMP_BODY (t));
stmt = pop_stmt_list (stmt);
@@ -13504,9 +13626,18 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
add_stmt (t);
break;
+ case OMP_TARGET_UPDATE:
+ tmp = tsubst_omp_clauses (OMP_TARGET_UPDATE_CLAUSES (t), false,
+ args, complain, in_decl);
+ t = copy_node (t);
+ OMP_CLAUSES (t) = tmp;
+ add_stmt (t);
+ break;
+
case OMP_SECTION:
case OMP_CRITICAL:
case OMP_MASTER:
+ case OMP_TASKGROUP:
case OMP_ORDERED:
stmt = push_stmt_list ();
RECUR (OMP_BODY (t));
@@ -13532,7 +13663,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
lhs = RECUR (TREE_OPERAND (op1, 0));
rhs = RECUR (TREE_OPERAND (op1, 1));
finish_omp_atomic (OMP_ATOMIC, TREE_CODE (op1), lhs, rhs,
- NULL_TREE, NULL_TREE, rhs1);
+ NULL_TREE, NULL_TREE, rhs1,
+ OMP_ATOMIC_SEQ_CST (t));
}
else
{
@@ -13560,6 +13692,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
lhs = RECUR (TREE_OPERAND (op11, 0));
rhs = RECUR (TREE_OPERAND (op11, 1));
opcode = TREE_CODE (op11);
+ if (opcode == MODIFY_EXPR)
+ opcode = NOP_EXPR;
}
else
{
@@ -13567,7 +13701,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
lhs = RECUR (TREE_OPERAND (op1, 0));
rhs = RECUR (TREE_OPERAND (op1, 1));
}
- finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1);
+ finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1,
+ OMP_ATOMIC_SEQ_CST (t));
}
break;
@@ -13639,6 +13774,73 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
#undef RETURN
}
+/* Instantiate the special body of the artificial DECL_OMP_DECLARE_REDUCTION
+ function. For description of the body see comment above
+ cp_parser_omp_declare_reduction_exprs. */
+
+static void
+tsubst_omp_udr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
+{
+ if (t == NULL_TREE || t == error_mark_node)
+ return;
+
+ gcc_assert (TREE_CODE (t) == STATEMENT_LIST);
+
+ tree_stmt_iterator tsi;
+ int i;
+ tree stmts[7];
+ memset (stmts, 0, sizeof stmts);
+ for (i = 0, tsi = tsi_start (t);
+ i < 7 && !tsi_end_p (tsi);
+ i++, tsi_next (&tsi))
+ stmts[i] = tsi_stmt (tsi);
+ gcc_assert (tsi_end_p (tsi));
+
+ if (i >= 3)
+ {
+ gcc_assert (TREE_CODE (stmts[0]) == DECL_EXPR
+ && TREE_CODE (stmts[1]) == DECL_EXPR);
+ tree omp_out = tsubst (DECL_EXPR_DECL (stmts[0]),
+ args, complain, in_decl);
+ tree omp_in = tsubst (DECL_EXPR_DECL (stmts[1]),
+ args, complain, in_decl);
+ DECL_CONTEXT (omp_out) = current_function_decl;
+ DECL_CONTEXT (omp_in) = current_function_decl;
+ keep_next_level (true);
+ tree block = begin_omp_structured_block ();
+ tsubst_expr (stmts[2], args, complain, in_decl, false);
+ block = finish_omp_structured_block (block);
+ block = maybe_cleanup_point_expr_void (block);
+ add_decl_expr (omp_out);
+ if (TREE_NO_WARNING (DECL_EXPR_DECL (stmts[0])))
+ TREE_NO_WARNING (omp_out) = 1;
+ add_decl_expr (omp_in);
+ finish_expr_stmt (block);
+ }
+ if (i >= 6)
+ {
+ gcc_assert (TREE_CODE (stmts[3]) == DECL_EXPR
+ && TREE_CODE (stmts[4]) == DECL_EXPR);
+ tree omp_priv = tsubst (DECL_EXPR_DECL (stmts[3]),
+ args, complain, in_decl);
+ tree omp_orig = tsubst (DECL_EXPR_DECL (stmts[4]),
+ args, complain, in_decl);
+ DECL_CONTEXT (omp_priv) = current_function_decl;
+ DECL_CONTEXT (omp_orig) = current_function_decl;
+ keep_next_level (true);
+ tree block = begin_omp_structured_block ();
+ tsubst_expr (stmts[5], args, complain, in_decl, false);
+ block = finish_omp_structured_block (block);
+ block = maybe_cleanup_point_expr_void (block);
+ cp_walk_tree (&block, cp_remove_omp_priv_cleanup_stmt, omp_priv, NULL);
+ add_decl_expr (omp_priv);
+ add_decl_expr (omp_orig);
+ finish_expr_stmt (block);
+ if (i == 7)
+ add_decl_expr (omp_orig);
+ }
+}
+
/* T is a postfix-expression that is not being used in a function
call. Return the substituted version of T. */
@@ -19340,6 +19542,7 @@ instantiate_decl (tree d, int defer_ok,
tree subst_decl;
tree tmpl_parm;
tree spec_parm;
+ tree block = NULL_TREE;
/* Save away the current list, in case we are instantiating one
template from within the body of another. */
@@ -19349,7 +19552,11 @@ instantiate_decl (tree d, int defer_ok,
local_specializations = pointer_map_create ();
/* Set up context. */
- start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
+ if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern)
+ && TREE_CODE (DECL_CONTEXT (code_pattern)) == FUNCTION_DECL)
+ block = push_stmt_list ();
+ else
+ start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
/* Some typedefs referenced from within the template code need to be
access checked at template instantiation time, i.e now. These
@@ -19386,21 +19593,37 @@ instantiate_decl (tree d, int defer_ok,
gcc_assert (!spec_parm);
/* Substitute into the body of the function. */
- tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
- tf_warning_or_error, tmpl,
- /*integral_constant_expression_p=*/false);
-
- /* Set the current input_location to the end of the function
- so that finish_function knows where we are. */
- input_location = DECL_STRUCT_FUNCTION (code_pattern)->function_end_locus;
+ if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern))
+ tsubst_omp_udr (DECL_SAVED_TREE (code_pattern), args,
+ tf_warning_or_error, tmpl);
+ else
+ {
+ tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
+ tf_warning_or_error, tmpl,
+ /*integral_constant_expression_p=*/false);
+
+ /* Set the current input_location to the end of the function
+ so that finish_function knows where we are. */
+ input_location
+ = DECL_STRUCT_FUNCTION (code_pattern)->function_end_locus;
+ }
/* We don't need the local specializations any more. */
pointer_map_destroy (local_specializations);
local_specializations = saved_local_specializations;
/* Finish the function. */
- d = finish_function (0);
- expand_or_defer_fn (d);
+ if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern)
+ && TREE_CODE (DECL_CONTEXT (code_pattern)) == FUNCTION_DECL)
+ DECL_SAVED_TREE (d) = pop_stmt_list (block);
+ else
+ {
+ d = finish_function (0);
+ expand_or_defer_fn (d);
+ }
+
+ if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern))
+ cp_check_omp_declare_reduction (d);
}
/* We're not deferring instantiation any more. */