Re: c++: local externs in templates do not get template head
On 9/14/20 6:47 PM, Tobias Burnus wrote: This patch cause run-time fails for g++ -fopenmp libgomp/testsuite/libgomp.c++/udr-13.C The follow-up fix does not help. Namely, in udr-3.C:115: 115 if (t.s != 11 || v.v != 9 || q != 0 || d != 3.0) abort (); (gdb) p t.s oops, I forgot the runtime tests are there -- it was so long ago! This unbreaks it, while I go develop a more robust patch. Turns out I didn't get OMP reductions correct. To address those I need to do some reorganization, so this patch just reverts the OMP-specific pieces of the local decl changes. gcc/cp/ * pt.c (push_template_decl_real): OMP reductions retain a template header. (tsubst_function_decl): Likewise. pushed to trunk nathan -- Nathan Sidwell diff --git c/gcc/cp/pt.c w/gcc/cp/pt.c index c630ef5a070..1aea105edd5 100644 --- c/gcc/cp/pt.c +++ w/gcc/cp/pt.c @@ -6072,9 +6072,11 @@ push_template_decl_real (tree decl, bool is_friend) if (is_primary) retrofit_lang_decl (decl); if (DECL_LANG_SPECIFIC (decl) - && (!VAR_OR_FUNCTION_DECL_P (decl) - || !ctx - || !DECL_LOCAL_DECL_P (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_TEMPLATE_INFO (decl) = info; } @@ -13712,7 +13714,8 @@ 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)) + if (DECL_LOCAL_DECL_P (t) + && !DECL_OMP_DECLARE_REDUCTION_P (t)) { if (tree spec = retrieve_local_specialization (t)) return spec; @@ -13967,7 +13970,8 @@ 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)) + else if (DECL_LOCAL_DECL_P (r) + && !DECL_OMP_DECLARE_REDUCTION_P (r)) { if (!cp_unevaluated_operand) register_local_specialization (r, t);
Re: c++: local externs in templates do not get template head
This patch cause run-time fails for g++ -fopenmp libgomp/testsuite/libgomp.c++/udr-13.C The follow-up fix does not help. Namely, in udr-3.C:115: 115 if (t.s != 11 || v.v != 9 || q != 0 || d != 3.0) abort (); (gdb) p t.s $1 = 11 (gdb) p v.v $2 = 4 (gdb) p q $3 = 0 (gdb) p d $4 = 3 Could you check? Thanks, Tobias On 9/14/20 6:45 PM, Nathan Sidwell wrote: Now we consistently mark local externs with DECL_LOCAL_DECL_P, we can teach the template machinery not to give them a TEMPLATE_DECL head, and the instantiation machinery treat them as the local specialiations they are. (openmp UDRs also fall into this category, and are dealt with similarly.) gcc/cp/ * pt.c (push_template_decl_real): Don't attach a template head to local externs. (tsubst_function_decl): Add support for headless local extern decls. (tsubst_decl): Add support for headless local extern decls. pushed to trunk - Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander Walter
Re: c++: local externs in templates do not get template head
On Mon, Sep 14, 2020 at 12:53:18PM -0400, Nathan Sidwell wrote: > On 9/14/20 12:49 PM, Marek Polacek wrote: > > On Mon, Sep 14, 2020 at 12:45:33PM -0400, Nathan Sidwell wrote: > > > Now we consistently mark local externs with DECL_LOCAL_DECL_P, we can > > > teach the template machinery not to give them a TEMPLATE_DECL head, > > > and the instantiation machinery treat them as the local specialiations > > > they are. (openmp UDRs also fall into this category, and are dealt > > > with similarly.) > > > > > > gcc/cp/ > > > * pt.c (push_template_decl_real): Don't attach a template head to > > > local externs. > > > (tsubst_function_decl): Add support for headless local extern > > > decls. > > > (tsubst_decl): Add support for headless local extern decls. > > > > > > pushed to trunk > > > -- > > > Nathan Sidwell > > > > > diff --git i/gcc/cp/pt.c w/gcc/cp/pt.c > > > index 0f52a9ed77d..8124efcbe24 100644 > > > --- i/gcc/cp/pt.c > > > +++ w/gcc/cp/pt.c > > > @@ -6071,7 +6071,11 @@ push_template_decl_real (tree decl, bool is_friend) > > > { > > > if (is_primary) > > > retrofit_lang_decl (decl); > > > - if (DECL_LANG_SPECIFIC (decl)) > > > + if (DECL_LANG_SPECIFIC (decl) > > > + && ((TREE_CODE (decl) != VAR_DECL > > > +&& TREE_CODE (decl) != FUNCTION_DECL) > > > > This is !VAR_OR_FUNCTION_DECL_P. Want me to "fix" that as obvious? > > ah, thanks -- great. I knew of VAR_P and the lack of FUNCTION_P, but not > that one. (bah, who needs consistency!) Yup... I keep wishing we had ARRAY_TYPE_P, for example. Anyway, I just pushed this: gcc/cp/ChangeLog: * pt.c (push_template_decl_real): Use VAR_OR_FUNCTION_DECL_P. --- gcc/cp/pt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8124efcbe24..c630ef5a070 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6072,8 +6072,7 @@ push_template_decl_real (tree decl, bool is_friend) if (is_primary) retrofit_lang_decl (decl); if (DECL_LANG_SPECIFIC (decl) - && ((TREE_CODE (decl) != VAR_DECL - && TREE_CODE (decl) != FUNCTION_DECL) + && (!VAR_OR_FUNCTION_DECL_P (decl) || !ctx || !DECL_LOCAL_DECL_P (decl))) DECL_TEMPLATE_INFO (decl) = info; base-commit: 5bcc0fa05ef713594f6c6d55d5c837e13a9c9803 -- 2.26.2
Re: c++: local externs in templates do not get template head
On 9/14/20 12:49 PM, Marek Polacek wrote: On Mon, Sep 14, 2020 at 12:45:33PM -0400, Nathan Sidwell wrote: Now we consistently mark local externs with DECL_LOCAL_DECL_P, we can teach the template machinery not to give them a TEMPLATE_DECL head, and the instantiation machinery treat them as the local specialiations they are. (openmp UDRs also fall into this category, and are dealt with similarly.) gcc/cp/ * pt.c (push_template_decl_real): Don't attach a template head to local externs. (tsubst_function_decl): Add support for headless local extern decls. (tsubst_decl): Add support for headless local extern decls. pushed to trunk -- Nathan Sidwell diff --git i/gcc/cp/pt.c w/gcc/cp/pt.c index 0f52a9ed77d..8124efcbe24 100644 --- i/gcc/cp/pt.c +++ w/gcc/cp/pt.c @@ -6071,7 +6071,11 @@ push_template_decl_real (tree decl, bool is_friend) { if (is_primary) retrofit_lang_decl (decl); - if (DECL_LANG_SPECIFIC (decl)) + if (DECL_LANG_SPECIFIC (decl) + && ((TREE_CODE (decl) != VAR_DECL + && TREE_CODE (decl) != FUNCTION_DECL) This is !VAR_OR_FUNCTION_DECL_P. Want me to "fix" that as obvious? ah, thanks -- great. I knew of VAR_P and the lack of FUNCTION_P, but not that one. (bah, who needs consistency!) -- Nathan Sidwell
Re: c++: local externs in templates do not get template head
On Mon, Sep 14, 2020 at 12:45:33PM -0400, Nathan Sidwell wrote: > Now we consistently mark local externs with DECL_LOCAL_DECL_P, we can > teach the template machinery not to give them a TEMPLATE_DECL head, > and the instantiation machinery treat them as the local specialiations > they are. (openmp UDRs also fall into this category, and are dealt > with similarly.) > > gcc/cp/ > * pt.c (push_template_decl_real): Don't attach a template head to > local externs. > (tsubst_function_decl): Add support for headless local extern > decls. > (tsubst_decl): Add support for headless local extern decls. > > pushed to trunk > -- > Nathan Sidwell > diff --git i/gcc/cp/pt.c w/gcc/cp/pt.c > index 0f52a9ed77d..8124efcbe24 100644 > --- i/gcc/cp/pt.c > +++ w/gcc/cp/pt.c > @@ -6071,7 +6071,11 @@ push_template_decl_real (tree decl, bool is_friend) > { >if (is_primary) > retrofit_lang_decl (decl); > - if (DECL_LANG_SPECIFIC (decl)) > + if (DECL_LANG_SPECIFIC (decl) > + && ((TREE_CODE (decl) != VAR_DECL > +&& TREE_CODE (decl) != FUNCTION_DECL) This is !VAR_OR_FUNCTION_DECL_P. Want me to "fix" that as obvious? Marek
c++: local externs in templates do not get template head
Now we consistently mark local externs with DECL_LOCAL_DECL_P, we can teach the template machinery not to give them a TEMPLATE_DECL head, and the instantiation machinery treat them as the local specialiations they are. (openmp UDRs also fall into this category, and are dealt with similarly.) gcc/cp/ * pt.c (push_template_decl_real): Don't attach a template head to local externs. (tsubst_function_decl): Add support for headless local extern decls. (tsubst_decl): Add support for headless local extern decls. pushed to trunk -- Nathan Sidwell diff --git i/gcc/cp/pt.c w/gcc/cp/pt.c index 0f52a9ed77d..8124efcbe24 100644 --- i/gcc/cp/pt.c +++ w/gcc/cp/pt.c @@ -6071,7 +6071,11 @@ push_template_decl_real (tree decl, bool is_friend) { if (is_primary) retrofit_lang_decl (decl); - if (DECL_LANG_SPECIFIC (decl)) + if (DECL_LANG_SPECIFIC (decl) + && ((TREE_CODE (decl) != VAR_DECL + && TREE_CODE (decl) != FUNCTION_DECL) + || !ctx + || !DECL_LOCAL_DECL_P (decl))) DECL_TEMPLATE_INFO (decl) = info; } @@ -13701,14 +13705,20 @@ static tree tsubst_function_decl (tree t, tree args, tsubst_flags_t complain, tree lambda_fntype) { - tree gen_tmpl, argvec; + tree gen_tmpl = NULL_TREE, argvec = NULL_TREE; hashval_t hash = 0; tree in_decl = t; /* Nobody should be tsubst'ing into non-template functions. */ - gcc_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE); + gcc_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE + || DECL_LOCAL_DECL_P (t)); - if (TREE_CODE (DECL_TI_TEMPLATE (t)) == TEMPLATE_DECL) + if (DECL_LOCAL_DECL_P (t)) +{ + if (tree spec = retrieve_local_specialization (t)) + return spec; +} + else if (TREE_CODE (DECL_TI_TEMPLATE (t)) == TEMPLATE_DECL) { /* If T is not dependent, just return it. */ if (!uses_template_parms (DECL_TI_ARGS (t)) @@ -13958,6 +13968,11 @@ 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)) +{ + if (!cp_unevaluated_operand) + register_local_specialization (r, t); +} else DECL_TEMPLATE_INFO (r) = NULL_TREE; @@ -14503,11 +14518,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) { tree argvec = NULL_TREE; tree gen_tmpl = NULL_TREE; - tree spec; tree tmpl = NULL_TREE; - tree ctx; tree type = NULL_TREE; - bool local_p; if (TREE_TYPE (t) == error_mark_node) RETURN (error_mark_node); @@ -14529,19 +14541,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) /* Check to see if we already have the specialization we need. */ - spec = NULL_TREE; - if (DECL_CLASS_SCOPE_P (t) || DECL_NAMESPACE_SCOPE_P (t)) + tree spec = NULL_TREE; + bool local_p = false; + tree ctx = DECL_CONTEXT (t); + if (!(VAR_P (t) && DECL_LOCAL_DECL_P (t)) + && (DECL_CLASS_SCOPE_P (t) || DECL_NAMESPACE_SCOPE_P (t))) { - /* T is a static data member or namespace-scope entity. - We have to substitute into namespace-scope variables - (not just variable templates) because of cases like: - - template void f() { extern T t; } - - where the entity referenced is not known until - instantiation time. */ local_p = false; - ctx = DECL_CONTEXT (t); if (DECL_CLASS_SCOPE_P (t)) { ctx = tsubst_aggr_type (ctx, args, @@ -14581,10 +14587,11 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) } else { + if (!(VAR_P (t) && DECL_LOCAL_DECL_P (t))) + /* Subsequent calls to pushdecl will fill this in. */ + ctx = NULL_TREE; /* A local variable. */ local_p = true; - /* Subsequent calls to pushdecl will fill this in. */ - ctx = NULL_TREE; /* Unless this is a reference to a static variable from an enclosing function, in which case we need to fill it in now. */ if (TREE_STATIC (t))