public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Fix PR c++/69098 (bogus errors with static data member template)
@ 2016-02-10 19:16 Patrick Palka
  2016-02-10 19:25 ` Patrick Palka
  2016-02-10 21:02 ` Jason Merrill
  0 siblings, 2 replies; 5+ messages in thread
From: Patrick Palka @ 2016-02-10 19:16 UTC (permalink / raw)
  To: gcc-patches; +Cc: jason, Patrick Palka

tsubst_qualified_id() is currently not prepared to handle a SCOPED_REF
whose RHS is a variable template.  r226642 made this deficiency more
obvious by marking all variable templates as dependent (thus forcing
them to be wrapped in a SCOPED_REF) but before that it was also possible
to trigger a bogus error if the scope of the variable template was
dependent (e.g. foo2 in the test case 69098-2.C fails to compile even
before r226642, whereas foo1 fails to compile only after r226642).

Further, check_template_keyword() is currently not prepared to handle
variable templates as well.  And again r226642 helped to expose this
issue but it was already possible to trigger before that (e.g. foo4
always failed to compile whereas foo3 only fails after r226642).

This patch makes tsubst_qualified_id() and check_template_keyword()
handle variable templates accordingly.  The changes in
check_template_keyword() are fairly straightforward, and in
tsubst_qualified_id() I just copied the way variable templates are
handled in tsubst_copy_and_build [TEMPLATE_ID_EXPR].

Boostrap + regtest in progress on x86_64-pc-linux-gnu, Ok to commit
after testing?

gcc/cp/ChangeLog:

	PR c++/69098
	* pt.c (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                          | 15 ++++++++++++-
 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, 103 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/69098-2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/69098.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 725adba..6780a98 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13726,7 +13726,20 @@ 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_template_variable (expr, template_args);
+	  if (!any_dependent_template_arguments_p (template_args))
+	    {
+	      expr = finish_template_variable (expr, complain);
+	      mark_used (expr);
+	    }
+	  expr = convert_from_reference (expr);
+	}
+      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),
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d2c23f4..959dc5a 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()
+{
+}
-- 
2.7.1.257.g925a48d

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Fix PR c++/69098 (bogus errors with static data member template)
  2016-02-10 19:16 [PATCH] Fix PR c++/69098 (bogus errors with static data member template) Patrick Palka
@ 2016-02-10 19:25 ` Patrick Palka
  2016-02-10 21:02 ` Jason Merrill
  1 sibling, 0 replies; 5+ messages in thread
From: Patrick Palka @ 2016-02-10 19:25 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jason Merrill, Patrick Palka

On Wed, Feb 10, 2016 at 2:16 PM, Patrick Palka <patrick@parcs.ath.cx> wrote:
> tsubst_qualified_id() is currently not prepared to handle a SCOPED_REF
> whose RHS is a variable template.  r226642 made this deficiency more
> obvious by marking all variable templates as dependent (thus forcing
> them to be wrapped in a SCOPED_REF) but before that it was also possible
> to trigger a bogus error if the scope of the variable template was
> dependent (e.g. foo2 in the test case 69098-2.C fails to compile even
> before r226642, whereas foo1 fails to compile only after r226642).
>
> Further, check_template_keyword() is currently not prepared to handle
> variable templates as well.  And again r226642 helped to expose this
> issue but it was already possible to trigger before that (e.g. foo4
> always failed to compile whereas foo3 only fails after r226642).

Err, sorry, disregard this last sentence, including the parenthetical.
Both tsubst_qualified_id() and check_template_keyword() must be fixed
in order for foo2 to compile.  For foo1 to compile, only
tsubst_qualified_id() must be fixed.  foo3 and foo4 are just examples
for which an earlier iteration of this patch caused an ICE.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Fix PR c++/69098 (bogus errors with static data member template)
  2016-02-10 19:16 [PATCH] Fix PR c++/69098 (bogus errors with static data member template) Patrick Palka
  2016-02-10 19:25 ` Patrick Palka
@ 2016-02-10 21:02 ` Jason Merrill
  2016-02-10 21:37   ` Patrick Palka
  1 sibling, 1 reply; 5+ messages in thread
From: Jason Merrill @ 2016-02-10 21:02 UTC (permalink / raw)
  To: Patrick Palka, gcc-patches

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.

Jason

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Fix PR c++/69098 (bogus errors with static data member template)
  2016-02-10 21:02 ` Jason Merrill
@ 2016-02-10 21:37   ` Patrick Palka
  2016-02-10 21:41     ` Jason Merrill
  0 siblings, 1 reply; 5+ messages in thread
From: Patrick Palka @ 2016-02-10 21:37 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Patrick Palka, gcc-patches

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

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()
+{
+}
-- 
2.7.1.257.g925a48d

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Fix PR c++/69098 (bogus errors with static data member template)
  2016-02-10 21:37   ` Patrick Palka
@ 2016-02-10 21:41     ` Jason Merrill
  0 siblings, 0 replies; 5+ messages in thread
From: Jason Merrill @ 2016-02-10 21:41 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches

OK.

Jason

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-02-10 21:41 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-10 19:16 [PATCH] Fix PR c++/69098 (bogus errors with static data member template) Patrick Palka
2016-02-10 19:25 ` Patrick Palka
2016-02-10 21:02 ` Jason Merrill
2016-02-10 21:37   ` Patrick Palka
2016-02-10 21:41     ` Jason Merrill

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).