diff mbox series

c++: local externs in templates do not get template head

Message ID 0de116c2-d345-12fe-1efe-b4a545b4bd87@acm.org
State New
Headers show
Series c++: local externs in templates do not get template head | expand

Commit Message

Nathan Sidwell Sept. 14, 2020, 4:45 p.m. UTC
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

Comments

Marek Polacek Sept. 14, 2020, 4:49 p.m. UTC | #1
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
Nathan Sidwell Sept. 14, 2020, 4:53 p.m. UTC | #2
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!)
Marek Polacek Sept. 14, 2020, 7:04 p.m. UTC | #3
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
Tobias Burnus Sept. 14, 2020, 10:47 p.m. UTC | #4
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
Nathan Sidwell Sept. 15, 2020, 3 p.m. UTC | #5
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
diff mbox series

Patch

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 <class T> 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))