This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH to support non-constexpr variable templates


Since nobody else seemed to be working on finishing up variable template support, I've gone ahead and done it. There were only a few tweaks needed.

For the pr59638.C issue, I'm throwing away the implicit template parameter list before we call start_decl so we don't actually create an implicit template. I expect that getting from there to doing type deduction from the initializer will be pretty simple; my guess is that it doesn't work as desired now mainly because type_uses_auto doesn't look into parameter types.

Jason
commit 9c0cd66186ac4159b7541ea5968eda6d599d3ab8
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Aug 22 16:34:08 2014 -0400

    	Allow non-constexpr variable templates.
    	* decl2.c (note_variable_template_instantiation): New.
    	* cp-tree.h: Declare it.
    	* pt.c (instantiate_decl): Call it.
    	(push_template_decl_real): Allow non-constexpr variable templates.
    	* semantics.c (finish_id_expression): Mark the variable template
    	instantiation as used.
    	* mangle.c (write_mangled_name): Variable template instantiations
    	are mangled.
    	* parser.c (cp_parser_init_declarator): Complain about
    	non-function implicit templates.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 81c7fd6..5d4df6b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5051,6 +5051,8 @@ variable_template_p (tree t)
 {
   if (TREE_CODE (t) != TEMPLATE_DECL)
     return false;
+  if (!PRIMARY_TEMPLATE_P (t))
+    return false;
   if (tree r = DECL_TEMPLATE_RESULT (t))
     return VAR_P (r);
   return false;
@@ -5393,6 +5395,7 @@ extern tree get_tls_wrapper_fn			(tree);
 extern void mark_needed				(tree);
 extern bool decl_needed_p			(tree);
 extern void note_vague_linkage_fn		(tree);
+extern void note_variable_template_instantiation (tree);
 extern tree build_artificial_parm		(tree, tree);
 extern bool possibly_inlined_p			(tree);
 extern int parm_index                           (tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 63583a8..74a10fb 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -787,6 +787,14 @@ note_vague_linkage_fn (tree decl)
   vec_safe_push (deferred_fns, decl);
 }
 
+/* As above, but for variable template instantiations.  */
+
+void
+note_variable_template_instantiation (tree decl)
+{
+  vec_safe_push (pending_statics, decl);
+}
+
 /* We have just processed the DECL, which is a static data member.
    The other parameters are as for cp_finish_decl.  */
 
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 40508ab..283983f 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -667,6 +667,8 @@ write_mangled_name (const tree decl, bool top_level)
 	}
     }
   else if (VAR_P (decl)
+	   /* Variable template instantiations are mangled.  */
+	   && !(DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
 	   /* The names of non-static global variables aren't mangled.  */
 	   && DECL_EXTERNAL_LINKAGE_P (decl)
 	   && (CP_DECL_CONTEXT (decl) == global_namespace
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4dc7c33..7d8b710 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -16779,6 +16779,8 @@ cp_parser_init_declarator (cp_parser* parser,
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
 
+  bool bogus_implicit_tmpl = false;
+
   if (function_declarator_p (declarator))
     {
       /* Check to see if the token indicates the start of a
@@ -16831,6 +16833,19 @@ cp_parser_init_declarator (cp_parser* parser,
 	  return decl;
 	}
     }
+  else if (parser->fully_implicit_function_template_p)
+    {
+      /* A non-template declaration involving a function parameter list
+	 containing an implicit template parameter will be made into a
+	 template.  If the resulting declaration is not going to be an
+	 actual function then finish the template scope here to prevent it.
+	 An error message will be issued once we have a decl to talk about.
+
+         FIXME probably we should do type deduction rather than create an
+         implicit template, but the standard currently doesn't allow it. */
+      bogus_implicit_tmpl = true;
+      finish_fully_implicit_template (parser, NULL_TREE);
+    }
 
   /* [dcl.dcl]
 
@@ -16996,21 +17011,10 @@ cp_parser_init_declarator (cp_parser* parser,
       warning (OPT_Wattributes,
 	       "attributes after parenthesized initializer ignored");
 
-  /* A non-template declaration involving a function parameter list containing
-     an implicit template parameter will have been made into a template.  If it
-     turns out that the resulting declaration is not an actual function then
-     finish the template declaration here.  An error message will already have
-     been issued.  */
-  if (parser->fully_implicit_function_template_p)
-    if (!function_declarator_p (declarator))
-      {
-	if (pushed_scope)
-	  {
-	    pop_scope (pushed_scope);
-	    pushed_scope = 0;
-	  }
-	finish_fully_implicit_template (parser, /*member_decl_opt=*/0);
-      }
+  /* And now complain about a non-function implicit template.  */
+  if (bogus_implicit_tmpl)
+    error_at (DECL_SOURCE_LOCATION (decl),
+	      "non-function %qD declared as implicit template", decl);
 
   /* For an in-class declaration, use `grokfield' to create the
      declaration.  */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 41fd424..14b5bfb 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -4777,14 +4777,7 @@ push_template_decl_real (tree decl, bool is_friend)
 	/* alias-declaration */
 	gcc_assert (!DECL_ARTIFICIAL (decl));
       else if (VAR_P (decl))
-        {
-          if (!DECL_DECLARED_CONSTEXPR_P (decl))
-            {
-              sorry ("template declaration of non-constexpr variable %qD",
-		     decl);
-              return error_mark_node;
-            }
-        }
+	/* C++14 variable template. */;
       else
 	{
 	  error ("template declaration of %q#D", decl);
@@ -20106,6 +20099,9 @@ instantiate_decl (tree d, int defer_ok,
 
       if (enter_context)
         pop_nested_class ();
+
+      if (variable_template_p (td))
+	note_variable_template_instantiation (d);
     }
   else if (TREE_CODE (d) == FUNCTION_DECL && DECL_DEFAULTED_FN (code_pattern))
     synthesize_method (d);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 531927e..aed820c 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3512,6 +3512,7 @@ finish_id_expression (tree id_expression,
 	       && variable_template_p (TREE_OPERAND (decl, 0)))
 	{
 	  decl = finish_template_variable (decl);
+	  mark_used (decl);
 	}
       else if (scope)
 	{
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59638.C b/gcc/testsuite/g++.dg/cpp1y/pr59638.C
index a4c63ac..ce90483 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr59638.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr59638.C
@@ -1,13 +1,12 @@
 // PR c++/59638
 // { dg-do compile { target c++1y } }
 // { dg-options "" }
-// { dg-excess-errors "sorry" }
 
-void (*a)(auto);         // { dg-error "" "" { xfail *-*-* } }
+void (*a)(auto);         // { dg-error "" }
 
-void (*b)(auto) = 0;     // { dg-error "" "" { xfail *-*-* } }
+void (*b)(auto) = 0;     // { dg-error "" }
 
-typedef void (*f)(auto); // { dg-error "template declaration" }
+typedef void (*f)(auto); // { dg-error "" }
 
 struct A
 {
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60626.C b/gcc/testsuite/g++.dg/cpp1y/pr60626.C
index 39ea438..314d6da 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr60626.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr60626.C
@@ -4,4 +4,4 @@
 
 struct A {};
 
-void (*A::p)(auto) = 0;  // { dg-error "static member|non-template" }
+void (*A::p)(auto) = 0;  // { dg-error "static member|template" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ7.C b/gcc/testsuite/g++.dg/cpp1y/var-templ7.C
new file mode 100644
index 0000000..1e59cf4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ7.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++1y } }
+
+template <class T> T var = 0;
+
+int main()
+{
+  var<int> = 42;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/var1.C b/gcc/testsuite/g++.old-deja/g++.pt/var1.C
index ec91bc4..08d65e9 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/var1.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/var1.C
@@ -1,5 +1,4 @@
 // { dg-do assemble  }
 // Origin: Jason Merrill <jason@cygnus.com>
-// { dg-excess-errors "sorry" }
 
-template <class T> T t; // template declaration of t
+template <class T> T t; // { dg-error "" "" { target { ! c++1y } } } template declaration of t

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]