public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/c++-modules] Local extern fns do not get template header
@ 2020-09-14 12:54 Nathan Sidwell
  0 siblings, 0 replies; only message in thread
From: Nathan Sidwell @ 2020-09-14 12:54 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:33be02f91858a4a2a5effdc1ee9c0e4506bc0be2

commit 33be02f91858a4a2a5effdc1ee9c0e4506bc0be2
Author: Nathan Sidwell <nathan@acm.org>
Date:   Fri Sep 11 08:50:16 2020 -0700

    Local extern fns do not get template header
    
            gcc/cp/
            * module.cc (trees_out::chained_decls): Also mark local fns for
            by-value walking.
            (trees_out::decl_node): Assert we don't meet a local var or fn.
            (trees_out::get_merge_kind): Local fns are also unique.
            * pt.c (push_template_decl_real): Local fns also lack a header.
            (tsubst_function_decl): Cope with local fns.
            (tsubst_decl): Adjust VAR_DECL tsubsting.
            gcc/testsuite/
            * g++.dg/modules/tpl-extern-{var,fn}-1_{a.H,b.C}: New.

Diff:
---
 ChangeLog.modules                                 | 14 +++++++
 gcc/cp/module.cc                                  | 14 ++++++-
 gcc/cp/pt.c                                       | 50 ++++++++++++-----------
 gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_a.H  | 16 ++++++++
 gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_b.C  |  8 ++++
 gcc/testsuite/g++.dg/modules/tpl-extern-var-1_a.H | 19 +++++++++
 gcc/testsuite/g++.dg/modules/tpl-extern-var-1_b.C |  8 ++++
 7 files changed, 103 insertions(+), 26 deletions(-)

diff --git a/ChangeLog.modules b/ChangeLog.modules
index a96a88c9747..9801ec197a9 100644
--- a/ChangeLog.modules
+++ b/ChangeLog.modules
@@ -1,3 +1,17 @@
+2020-09-11  Nathan Sidwell  <nathan@acm.org>
+
+	Local extern fns do not get template header
+	gcc/cp/
+	* module.cc (trees_out::chained_decls): Also mark local fns for
+	by-value walking.
+	(trees_out::decl_node): Assert we don't meet a local var or fn.
+	(trees_out::get_merge_kind): Local fns are also unique.
+	* pt.c (push_template_decl_real): Local fns also lack a header.
+	(tsubst_function_decl): Cope with local fns.
+	(tsubst_decl): Adjust VAR_DECL tsubsting.
+	gcc/testsuite/
+	* g++.dg/modules/tpl-extern-{var,fn}-1_{a.H,b.C}: New.
+
 2020-09-09  Nathan Sidwell  <nathan@acm.org>
 
 	Local extern vars do not get template header
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index cb8db32de51..af13b45b0c7 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -4853,7 +4853,9 @@ trees_out::chained_decls (tree decls)
 {
   for (; decls; decls = DECL_CHAIN (decls))
     {
-      if (TREE_CODE (decls) == VAR_DECL && DECL_LOCAL_DECL_P (decls))
+      if ((TREE_CODE (decls) == VAR_DECL
+	   || TREE_CODE (decls) == FUNCTION_DECL)
+	  && DECL_LOCAL_DECL_P (decls))
 	{
 	  /* Make sure this is the first encounter, and mark for
 	     walk-by-value.  */
@@ -8087,6 +8089,10 @@ trees_out::decl_node (tree decl, walk_kind ref)
     default:
       break;
 
+    case FUNCTION_DECL:
+      gcc_checking_assert (!DECL_LOCAL_DECL_P (decl));
+      break;
+
     case RESULT_DECL:
       // FIXME: Like a parm?
       return true;
@@ -8185,6 +8191,7 @@ trees_out::decl_node (tree decl, walk_kind ref)
       break;
 
     case VAR_DECL:
+      gcc_checking_assert (!DECL_LOCAL_DECL_P (decl));
       if (DECL_VTABLE_OR_VTT_P (decl))
 	{
 	  /* VTT or VTABLE, they are all on the vtables list.  */
@@ -9853,7 +9860,8 @@ trees_out::get_merge_kind (tree decl, depset *dep)
 {
   if (!dep)
     {
-      if (TREE_CODE (decl) == VAR_DECL
+      if ((TREE_CODE (decl) == VAR_DECL
+	   || TREE_CODE (decl) == FUNCTION_DECL)
 	  && DECL_LOCAL_DECL_P (decl))
 	return MK_unique;
 
@@ -12517,6 +12525,8 @@ specialization_add (bool decl_p, spec_entry *entry, void *data_)
        gcc_checking_assert (!check_mergeable_specialization (true, entry)
 			    == (decl_p || !DECL_ALIAS_TEMPLATE_P (entry->tmpl)));
     }
+  else if (VAR_P (entry->spec) || TREE_CODE (entry->spec) == FUNCTION_DECL)
+    gcc_checking_assert (!DECL_LOCAL_DECL_P (entry->spec));
 
   data->safe_push (entry);
 }
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bba24421f2d..484f697dc3d 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6095,8 +6095,10 @@ 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
-	      || !ctx || !DECL_LOCAL_DECL_P (decl)))
+	  && ((TREE_CODE (decl) != VAR_DECL
+	       && TREE_CODE (decl) != FUNCTION_DECL)
+	      || !ctx
+	      || !DECL_LOCAL_DECL_P (decl)))
 	DECL_TEMPLATE_INFO (decl) = info;
     }
 
@@ -13750,14 +13752,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))
@@ -14008,6 +14016,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;
 
@@ -14574,11 +14587,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);
@@ -14600,19 +14610,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,
@@ -14633,8 +14637,6 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 			 && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (t))))
 		  spec = t;
 	      }
-	    else if (!DECL_TEMPLATE_INFO (t))
-	      goto local;
 
 	    if (!spec)
 	      {
@@ -14654,9 +14656,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 	  }
 	else
 	  {
-	    /* Subsequent calls to pushdecl will fill this in.  */
-	    ctx = NULL_TREE;
-	  local:
+	    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;
 	    /* Unless this is a reference to a static variable from an
diff --git a/gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_a.H b/gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_a.H
new file mode 100644
index 00000000000..f0aba549dfd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_a.H
@@ -0,0 +1,16 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename T>
+inline void Foo ()
+{
+  {
+    void Frob ();
+  }
+  {
+    void Frob ();
+  }
+  {
+    void Frob ();
+  }
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_b.C b/gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_b.C
new file mode 100644
index 00000000000..8b093d4e15a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+import "tpl-extern-fn-1_a.H";
+
+int main ()
+{
+  Foo<int> ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-extern-var-1_a.H b/gcc/testsuite/g++.dg/modules/tpl-extern-var-1_a.H
new file mode 100644
index 00000000000..4a6437a85e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-extern-var-1_a.H
@@ -0,0 +1,19 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename T>
+inline void Foo ()
+{
+  {
+    extern int EXTERN_;
+    EXTERN_++;
+  }
+  {
+    extern int EXTERN_;
+    EXTERN_++;
+  }
+  {
+    extern int EXTERN_;
+    EXTERN_++;
+  }
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-extern-var-1_b.C b/gcc/testsuite/g++.dg/modules/tpl-extern-var-1_b.C
new file mode 100644
index 00000000000..222418128be
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-extern-var-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+import "tpl-extern-var-1_a.H";
+
+int main ()
+{
+  Foo<int> ();
+}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-09-14 12:54 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-14 12:54 [gcc/devel/c++-modules] Local extern fns do not get template header Nathan Sidwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).