aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2020-09-16 11:04:19 -0700
committerNathan Sidwell <nathan@acm.org>2020-09-16 12:16:11 -0700
commit8155316c6fc23045e8e056e91449a6e9863c357f (patch)
treeeb49f081f6ba90d0eda09fd14b4861a1af0ac019 /gcc/cp
parentd1339b519ae8cc4ae550baa127a21d8350462837 (diff)
downloadgcc-8155316c6fc23045e8e056e91449a6e9863c357f.zip
gcc-8155316c6fc23045e8e056e91449a6e9863c357f.tar.gz
gcc-8155316c6fc23045e8e056e91449a6e9863c357f.tar.bz2
c++: local-scope OMP UDR reductions have no template head
This corrects the earlier problems with removing the template header from local omp reductions. And it uncovered a latent bug. When we tsubst such a decl, we immediately tsubst its body. cp_check_omp_declare_reduction gets a success return value to gate that instantiation. udr-2.C got a further error, as the omp checking machinery doesn't appear to turn the reduction into an error mark when failing. I didn't dig into that further. udr-3.C appears to have been invalid and accidentally worked. gcc/cp/ * cp-tree.h (cp_check_omp_declare_reduction): Return bool. * semantics.c (cp_check_omp_declare_reduction): Return true on for success. * pt.c (push_template_decl_real): OMP reductions do not get a template header. (tsubst_function_decl): Remove special casing for local decl omp reductions. (tsubst_expr): Call instantiate_body for a local omp reduction. (instantiate_body): Add nested_p parm, and deal with such instantiations. (instantiate_decl): Reject FUNCTION_SCOPE entities, adjust instantiate_body call. gcc/testsuite/ * g++.dg/gomp/udr-2.C: Add additional expected error. libgomp/ * testsuite/libgomp.c++/udr-3.C: Add missing ctor.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/pt.c55
-rw-r--r--gcc/cp/semantics.c17
3 files changed, 41 insertions, 33 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 6e4de7d..5b72734 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7228,7 +7228,7 @@ extern void simplify_aggr_init_expr (tree *);
extern void finalize_nrv (tree *, tree, tree);
extern tree omp_reduction_id (enum tree_code, tree, tree);
extern tree cp_remove_omp_priv_cleanup_stmt (tree *, int *, void *);
-extern void cp_check_omp_declare_reduction (tree);
+extern bool cp_check_omp_declare_reduction (tree);
extern void finish_omp_declare_simd_methods (tree);
extern tree finish_omp_clauses (tree, enum c_omp_region_type);
extern tree push_omp_privatization_clauses (bool);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 289452a..cfe5ff4 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -227,6 +227,7 @@ static tree canonicalize_expr_argument (tree, tsubst_flags_t);
static tree make_argument_pack (tree);
static void register_parameter_specializations (tree, tree);
static tree enclosing_instantiation_of (tree tctx);
+static void instantiate_body (tree pattern, tree args, tree d, bool nested);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
@@ -6073,10 +6074,7 @@ push_template_decl_real (tree decl, bool is_friend)
retrofit_lang_decl (decl);
if (DECL_LANG_SPECIFIC (decl)
&& !(VAR_OR_FUNCTION_DECL_P (decl)
- && DECL_LOCAL_DECL_P (decl)
- /* OMP reductions still need a template header. */
- && !(TREE_CODE (decl) == FUNCTION_DECL
- && DECL_OMP_DECLARE_REDUCTION_P (decl))))
+ && DECL_LOCAL_DECL_P (decl)))
DECL_TEMPLATE_INFO (decl) = info;
}
@@ -13714,8 +13712,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
gcc_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE
|| DECL_LOCAL_DECL_P (t));
- if (DECL_LOCAL_DECL_P (t)
- && !DECL_OMP_DECLARE_REDUCTION_P (t))
+ if (DECL_LOCAL_DECL_P (t))
{
if (tree spec = retrieve_local_specialization (t))
return spec;
@@ -13970,8 +13967,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
&& !uses_template_parms (argvec))
tsubst_default_arguments (r, complain);
}
- else if (DECL_LOCAL_DECL_P (r)
- && !DECL_OMP_DECLARE_REDUCTION_P (r))
+ else if (DECL_LOCAL_DECL_P (r))
{
if (!cp_unevaluated_operand)
register_local_specialization (r, t);
@@ -18083,7 +18079,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
DECL_CONTEXT (decl) = global_namespace;
pushdecl (decl);
DECL_CONTEXT (decl) = current_function_decl;
- cp_check_omp_declare_reduction (decl);
+ if (cp_check_omp_declare_reduction (decl))
+ instantiate_body (pattern_decl, args, decl, true);
}
else
{
@@ -25448,15 +25445,24 @@ register_parameter_specializations (tree pattern, tree inst)
}
/* Instantiate the body of D using PATTERN with ARGS. We have
- already determined PATTERN is the correct template to use. */
+ already determined PATTERN is the correct template to use.
+ NESTED_P is true if this is a nested function, in which case
+ PATTERN will be a FUNCTION_DECL not a TEMPLATE_DECL. */
static void
-instantiate_body (tree pattern, tree args, tree d)
+instantiate_body (tree pattern, tree args, tree d, bool nested_p)
{
- gcc_checking_assert (TREE_CODE (pattern) == TEMPLATE_DECL);
-
- tree td = pattern;
- tree code_pattern = DECL_TEMPLATE_RESULT (td);
+ tree td = NULL_TREE;
+ tree code_pattern = pattern;
+
+ if (!nested_p)
+ {
+ td = pattern;
+ code_pattern = DECL_TEMPLATE_RESULT (td);
+ }
+ else
+ /* Only OMP reductions are nested. */
+ gcc_checking_assert (DECL_OMP_DECLARE_REDUCTION_P (code_pattern));
vec<tree> omp_privatization_save;
if (current_function_decl)
@@ -25489,9 +25495,10 @@ instantiate_body (tree pattern, tree args, tree d)
instantiate_decl do not try to instantiate it again. */
DECL_TEMPLATE_INSTANTIATED (d) = 1;
- /* Regenerate the declaration in case the template has been modified
- by a subsequent redeclaration. */
- regenerate_decl_from_template (d, td, args);
+ if (td)
+ /* Regenerate the declaration in case the template has been modified
+ by a subsequent redeclaration. */
+ regenerate_decl_from_template (d, td, args);
/* We already set the file and line above. Reset them now in case
they changed as a result of calling regenerate_decl_from_template. */
@@ -25540,8 +25547,7 @@ instantiate_body (tree pattern, tree args, tree d)
tree block = NULL_TREE;
/* Set up context. */
- if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern)
- && TREE_CODE (DECL_CONTEXT (code_pattern)) == FUNCTION_DECL)
+ if (nested_p)
block = push_stmt_list ();
else
start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
@@ -25554,7 +25560,7 @@ instantiate_body (tree pattern, tree args, tree d)
/* Substitute into the body of the function. */
if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern))
tsubst_omp_udr (DECL_SAVED_TREE (code_pattern), args,
- tf_warning_or_error, DECL_TI_TEMPLATE (d));
+ tf_warning_or_error, d);
else
{
tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
@@ -25572,8 +25578,7 @@ instantiate_body (tree pattern, tree args, tree d)
}
/* Finish the function. */
- if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern)
- && TREE_CODE (DECL_CONTEXT (code_pattern)) == FUNCTION_DECL)
+ if (nested_p)
DECL_SAVED_TREE (d) = pop_stmt_list (block);
else
{
@@ -25628,6 +25633,8 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
/* A concept is never instantiated. */
gcc_assert (!DECL_DECLARED_CONCEPT_P (d));
+ gcc_checking_assert (!DECL_FUNCTION_SCOPE_P (d));
+
/* Variables are never deferred; if instantiation is required, they
are instantiated right away. That allows for better code in the
case that an expression refers to the value of the variable --
@@ -25844,7 +25851,7 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
{
if (variable_template_p (gen_tmpl))
note_variable_template_instantiation (d);
- instantiate_body (td, args, d);
+ instantiate_body (td, args, d, false);
}
pop_deferring_access_checks ();
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 4ca2a2f..11996c9 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5679,7 +5679,7 @@ cp_check_omp_declare_reduction_r (tree *tp, int *, void *data)
/* Diagnose violation of OpenMP #pragma omp declare reduction restrictions. */
-void
+bool
cp_check_omp_declare_reduction (tree udr)
{
tree type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (udr)));
@@ -5689,7 +5689,7 @@ cp_check_omp_declare_reduction (tree udr)
location_t loc = DECL_SOURCE_LOCATION (udr);
if (type == error_mark_node)
- return;
+ return false;
if (ARITHMETIC_TYPE_P (type))
{
static enum tree_code predef_codes[]
@@ -5723,7 +5723,7 @@ cp_check_omp_declare_reduction (tree udr)
{
error_at (loc, "predeclared arithmetic type %qT in "
"%<#pragma omp declare reduction%>", type);
- return;
+ return false;
}
}
else if (FUNC_OR_METHOD_TYPE_P (type)
@@ -5731,24 +5731,24 @@ cp_check_omp_declare_reduction (tree udr)
{
error_at (loc, "function or array type %qT in "
"%<#pragma omp declare reduction%>", type);
- return;
+ return false;
}
else if (TYPE_REF_P (type))
{
error_at (loc, "reference type %qT in %<#pragma omp declare reduction%>",
type);
- return;
+ return false;
}
else if (TYPE_QUALS_NO_ADDR_SPACE (type))
{
error_at (loc, "%<const%>, %<volatile%> or %<__restrict%>-qualified "
"type %qT in %<#pragma omp declare reduction%>", type);
- return;
+ return false;
}
tree body = DECL_SAVED_TREE (udr);
if (body == NULL_TREE || TREE_CODE (body) != STATEMENT_LIST)
- return;
+ return true;
tree_stmt_iterator tsi;
struct cp_check_omp_declare_reduction_data data;
@@ -5764,7 +5764,7 @@ cp_check_omp_declare_reduction (tree udr)
gcc_assert (TREE_CODE (data.stmts[0]) == DECL_EXPR
&& TREE_CODE (data.stmts[1]) == DECL_EXPR);
if (TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0])))
- return;
+ return true;
data.combiner_p = true;
if (cp_walk_tree (&data.stmts[2], cp_check_omp_declare_reduction_r,
&data, NULL))
@@ -5783,6 +5783,7 @@ cp_check_omp_declare_reduction (tree udr)
if (i == 7)
gcc_assert (TREE_CODE (data.stmts[6]) == DECL_EXPR);
}
+ return true;
}
/* Helper function of finish_omp_clauses. Clone STMT as if we were making