diff mbox series

c++: erroneous partial spec vs primary tmpl [PR116064]

Message ID 20240807150900.1390001-1-ppalka@redhat.com
State New
Headers show
Series c++: erroneous partial spec vs primary tmpl [PR116064] | expand

Commit Message

Patrick Palka Aug. 7, 2024, 3:09 p.m. UTC
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
OK for trunk?

-- >8 --

When a partial specialization is deemed erroneous at parse time, we
currently flag the primary template as erroneous instead.  Later
at instantiation time we check if the primary template is erroneous
rather than the selected partial specialization, so at least we're
consistent.

But it's better not to conflate a partial specialization with the
primary template since they're instantiated independenty.  This avoids
rejecting the instantiation of A<int> in the below testcase.

	PR c++/116064

gcc/cp/ChangeLog:

	* error.cc (get_current_template): If the current scope is
	a partial specialization, return it instead of the primary
	template.
	* pt.cc (instantiate_class_template): Pass the partial
	specialization if any to maybe_diagnose_erroneous_template
	instead of the primary template.

gcc/testsuite/ChangeLog:

	* g++.dg/template/permissive-error2.C: New test.
---
 gcc/cp/error.cc                                   |  6 +++++-
 gcc/cp/pt.cc                                      |  2 +-
 gcc/testsuite/g++.dg/template/permissive-error2.C | 15 +++++++++++++++
 3 files changed, 21 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/permissive-error2.C

Comments

Jason Merrill Aug. 7, 2024, 3:48 p.m. UTC | #1
On 8/7/24 11:09 AM, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
> OK for trunk?

OK.

> -- >8 --
> 
> When a partial specialization is deemed erroneous at parse time, we
> currently flag the primary template as erroneous instead.  Later
> at instantiation time we check if the primary template is erroneous
> rather than the selected partial specialization, so at least we're
> consistent.
> 
> But it's better not to conflate a partial specialization with the
> primary template since they're instantiated independenty.  This avoids
> rejecting the instantiation of A<int> in the below testcase.
> 
> 	PR c++/116064
> 
> gcc/cp/ChangeLog:
> 
> 	* error.cc (get_current_template): If the current scope is
> 	a partial specialization, return it instead of the primary
> 	template.
> 	* pt.cc (instantiate_class_template): Pass the partial
> 	specialization if any to maybe_diagnose_erroneous_template
> 	instead of the primary template.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/template/permissive-error2.C: New test.
> ---
>   gcc/cp/error.cc                                   |  6 +++++-
>   gcc/cp/pt.cc                                      |  2 +-
>   gcc/testsuite/g++.dg/template/permissive-error2.C | 15 +++++++++++++++
>   3 files changed, 21 insertions(+), 2 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/template/permissive-error2.C
> 
> diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
> index 6c22ff55b46..879e5a115cf 100644
> --- a/gcc/cp/error.cc
> +++ b/gcc/cp/error.cc
> @@ -173,7 +173,11 @@ get_current_template ()
>   {
>     if (scope_chain && in_template_context && !current_instantiation ())
>       if (tree ti = get_template_info (current_scope ()))
> -      return TI_TEMPLATE (ti);
> +      {
> +	if (PRIMARY_TEMPLATE_P (TI_TEMPLATE (ti)) && TI_PARTIAL_INFO (ti))
> +	  ti = TI_PARTIAL_INFO (ti);
> +	return TI_TEMPLATE (ti);
> +      }
>   
>     return NULL_TREE;
>   }
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 542962b6387..3e55d5c0fea 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -12381,7 +12381,7 @@ instantiate_class_template (tree type)
>     if (! push_tinst_level (type))
>       return type;
>   
> -  maybe_diagnose_erroneous_template (templ);
> +  maybe_diagnose_erroneous_template (t ? TI_TEMPLATE (t) : templ);
>   
>     int saved_unevaluated_operand = cp_unevaluated_operand;
>     int saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
> diff --git a/gcc/testsuite/g++.dg/template/permissive-error2.C b/gcc/testsuite/g++.dg/template/permissive-error2.C
> new file mode 100644
> index 00000000000..692e7c7ac82
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/template/permissive-error2.C
> @@ -0,0 +1,15 @@
> +// PR c++/116064
> +// { dg-additional-options -fpermissive }
> +// Verify we correctly mark a partial specialization as erroneous
> +// instead its primary template.
> +
> +template<class T>
> +struct A { };
> +
> +template<class T>
> +struct A<T*> { // { dg-error "instantiating erroneous template" }
> +  void f(typename A::type); // { dg-warning "does not name a type" }
> +};
> +
> +A<int> a;  // { dg-bogus "" }
> +A<int*> b; // { dg-message "required from here" }
diff mbox series

Patch

diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 6c22ff55b46..879e5a115cf 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -173,7 +173,11 @@  get_current_template ()
 {
   if (scope_chain && in_template_context && !current_instantiation ())
     if (tree ti = get_template_info (current_scope ()))
-      return TI_TEMPLATE (ti);
+      {
+	if (PRIMARY_TEMPLATE_P (TI_TEMPLATE (ti)) && TI_PARTIAL_INFO (ti))
+	  ti = TI_PARTIAL_INFO (ti);
+	return TI_TEMPLATE (ti);
+      }
 
   return NULL_TREE;
 }
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 542962b6387..3e55d5c0fea 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -12381,7 +12381,7 @@  instantiate_class_template (tree type)
   if (! push_tinst_level (type))
     return type;
 
-  maybe_diagnose_erroneous_template (templ);
+  maybe_diagnose_erroneous_template (t ? TI_TEMPLATE (t) : templ);
 
   int saved_unevaluated_operand = cp_unevaluated_operand;
   int saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
diff --git a/gcc/testsuite/g++.dg/template/permissive-error2.C b/gcc/testsuite/g++.dg/template/permissive-error2.C
new file mode 100644
index 00000000000..692e7c7ac82
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/permissive-error2.C
@@ -0,0 +1,15 @@ 
+// PR c++/116064
+// { dg-additional-options -fpermissive }
+// Verify we correctly mark a partial specialization as erroneous
+// instead its primary template.
+
+template<class T>
+struct A { };
+
+template<class T>
+struct A<T*> { // { dg-error "instantiating erroneous template" }
+  void f(typename A::type); // { dg-warning "does not name a type" }
+};
+
+A<int> a;  // { dg-bogus "" }
+A<int*> b; // { dg-message "required from here" }