diff mbox

Fix PR c++/69098 (bogus errors with static data member template)

Message ID alpine.DEB.2.20.9.1602101635110.1231@idea
State New
Headers show

Commit Message

Patrick Palka Feb. 10, 2016, 9:37 p.m. UTC
On Wed, 10 Feb 2016, Jason Merrill wrote:

> On 02/10/2016 02:16 PM, Patrick Palka wrote:
>> ...in tsubst_qualified_id() I just copied the way variable templates are
>> handled in tsubst_copy_and_build [TEMPLATE_ID_EXPR].
>
> Let's factor that code out into another function rather than copy it.

Done.  Does this look OK?

-- >8 --

gcc/cp/ChangeLog:

 	PR c++/69098
 	* pt.c (lookup_and_finish_template_variable): New function,
 	extracted from ...
 	(tsubst_copy_and_build) [TEMPLATE_ID_EXPR]: ... here.
 	(tsubst_qualified_id): Consider that EXPR might be a variable
 	template.
 	* typeck.c (check_template_keyword): Don't emit an error
 	if DECL is a variable template.

gcc/testsuite/ChangeLog:

 	PR c++/69098
 	* g++.dg/cpp1y/69098.C: New test.
 	* g++.dg/cpp1y/69098-2.C: New test.
---
  gcc/cp/pt.c                          | 36 +++++++++++++++++++++---------
  gcc/cp/typeck.c                      | 10 ++++++++-
  gcc/testsuite/g++.dg/cpp1y/69098-2.C | 37 +++++++++++++++++++++++++++++++
  gcc/testsuite/g++.dg/cpp1y/69098.C   | 43 ++++++++++++++++++++++++++++++++++++
  4 files changed, 115 insertions(+), 11 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/69098-2.C
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/69098.C

Comments

Jason Merrill Feb. 10, 2016, 9:41 p.m. UTC | #1
OK.

Jason
diff mbox

Patch

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index eea3834..6776c74 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8698,6 +8698,24 @@  finish_template_variable (tree var, tsubst_flags_t complain)

    return instantiate_template (templ, arglist, complain);
  }
+
+/* Construct a TEMPLATE_ID_EXPR for the given variable template TEMPL having
+   TARGS template args, and instantiate it if it's not dependent.  */
+
+static tree
+lookup_and_finish_template_variable (tree templ, tree targs,
+				     tsubst_flags_t complain)
+{
+  templ = lookup_template_variable (templ, targs);
+  if (!any_dependent_template_arguments_p (targs))
+    {
+      templ = finish_template_variable (templ, complain);
+      mark_used (templ);
+    }
+
+  return convert_from_reference (templ);
+}
+

  struct pair_fn_data
  {
@@ -13726,7 +13744,13 @@  tsubst_qualified_id (tree qualified_id, tree args,
      }

    if (is_template)
-    expr = lookup_template_function (expr, template_args);
+    {
+      if (variable_template_p (expr))
+	expr = lookup_and_finish_template_variable (expr, template_args,
+						    complain);
+      else
+	expr = lookup_template_function (expr, template_args);
+    }

    if (expr == error_mark_node && complain & tf_error)
      qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
@@ -15906,15 +15930,7 @@  tsubst_copy_and_build (tree t,
  	  return error_mark_node;

  	if (variable_template_p (templ))
-	  {
-	    templ = lookup_template_variable (templ, targs);
-	    if (!any_dependent_template_arguments_p (targs))
-	      {
-		templ = finish_template_variable (templ, complain);
-		mark_used (templ);
-	      }
-	    RETURN (convert_from_reference (templ));
-	  }
+	  RETURN (lookup_and_finish_template_variable (templ, targs, complain));

  	if (TREE_CODE (templ) == COMPONENT_REF)
  	  {
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index c9fa112..fb2a2c4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2601,7 +2601,15 @@  check_template_keyword (tree decl)
    if (TREE_CODE (decl) != TEMPLATE_DECL
        && TREE_CODE (decl) != TEMPLATE_ID_EXPR)
      {
-      if (!is_overloaded_fn (decl))
+      if (VAR_P (decl))
+	{
+	  if (DECL_USE_TEMPLATE (decl)
+	      && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl)))
+	    ;
+	  else
+	    permerror (input_location, "%qD is not a template", decl);
+	}
+      else if (!is_overloaded_fn (decl))
  	permerror (input_location, "%qD is not a template", decl);
        else
  	{
diff --git a/gcc/testsuite/g++.dg/cpp1y/69098-2.C b/gcc/testsuite/g++.dg/cpp1y/69098-2.C
new file mode 100644
index 0000000..2e968bb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/69098-2.C
@@ -0,0 +1,37 @@ 
+// PR c++/69098
+// { dg-do compile { target c++14 } }
+
+struct A
+{
+  template <int>
+  static void *pf;
+};
+
+template <typename B>
+bool foo1 () {
+  return A::pf<false>;
+}
+
+template <typename B>
+bool foo2 () {
+  return B::template pf<false>;
+}
+
+template <typename B>
+bool foo3 () {
+  return &A::pf<false>;
+}
+
+template <typename B>
+bool foo4 () {
+  return &B::template pf<false>;
+}
+
+
+void bar () {
+  foo1<A>();
+  foo2<A>();
+  foo3<A>();
+  foo4<A>();
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp1y/69098.C b/gcc/testsuite/g++.dg/cpp1y/69098.C
new file mode 100644
index 0000000..afc4294
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/69098.C
@@ -0,0 +1,43 @@ 
+// PR c++/69098
+// { dg-do compile { target c++14 } }
+
+template<typename> struct SpecPerType;
+
+class Specializer
+{
+public:
+    template<bool> void MbrFnTempl() //Must be a template
+	{
+	}
+	template<unsigned> struct InnerClassTempl
+	{  //Had to be a template whenever I tested for it
+		static void InnerMemberFn();
+	};
+
+	void Trigger()
+	{
+		InnerClassTempl<0u>::InnerMemberFn();
+	}
+};
+
+template<> struct SpecPerType<Specializer>
+{
+	using FnType = void (Specializer::*)();
+    template<bool P> static constexpr FnType SpecMbrFnPtr =
+        &Specializer::template MbrFnTempl<P>;
+};
+
+template<bool> constexpr SpecPerType<Specializer>::FnType
+    SpecPerType<Specializer>::SpecMbrFnPtr; //Just a formalism
+
+template<unsigned X> void Specializer::InnerClassTempl<X>::InnerMemberFn()
+{
+	using Spec = SpecPerType<Specializer>;
+	typename Spec::FnType ErrorSite = Spec::template SpecMbrFnPtr<true>;
+    //ErrorSite would get called next in the original code
+    //(this should result in a call to MbrFnTempl)
+}
+
+int main()
+{
+}