diff mbox series

c++: Improve fixits for incorrect explicit instantiations

Message ID 66b1f32d.050a0220.e6a95.4239@mx.google.com
State New
Headers show
Series c++: Improve fixits for incorrect explicit instantiations | expand

Commit Message

Nathaniel Shead Aug. 6, 2024, 9:55 a.m. UTC
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

When forgetting the '<>' on an explicit specialisation, the suggested
fixit hint suggests to add 'template <>', but naively applying will
cause nonsense results like 'template template <> struct S<int> {};'.

Instead check if we're currently parsing an explicit instantiation, and
if so inform about the issue (an instantiation cannot have a class body)
and suggest a fixit of simply '<>' to create a specialisation instead.

gcc/cp/ChangeLog:

	* parser.cc (cp_parser_class_head): Clarify error message for
	explicit instantiations.

gcc/testsuite/ChangeLog:

	* g++.dg/template/explicit-instantiation9.C: New test.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
---
 gcc/cp/parser.cc                              | 19 ++++++++++++++-----
 .../g++.dg/template/explicit-instantiation9.C |  6 ++++++
 2 files changed, 20 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/explicit-instantiation9.C

Comments

Jason Merrill Aug. 6, 2024, 5:11 p.m. UTC | #1
On 8/6/24 5:55 AM, Nathaniel Shead wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

OK.

> -- >8 --
> 
> When forgetting the '<>' on an explicit specialisation, the suggested
> fixit hint suggests to add 'template <>', but naively applying will
> cause nonsense results like 'template template <> struct S<int> {};'.
> 
> Instead check if we're currently parsing an explicit instantiation, and
> if so inform about the issue (an instantiation cannot have a class body)
> and suggest a fixit of simply '<>' to create a specialisation instead.
> 
> gcc/cp/ChangeLog:
> 
> 	* parser.cc (cp_parser_class_head): Clarify error message for
> 	explicit instantiations.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/template/explicit-instantiation9.C: New test.
> 
> Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
> ---
>   gcc/cp/parser.cc                              | 19 ++++++++++++++-----
>   .../g++.dg/template/explicit-instantiation9.C |  6 ++++++
>   2 files changed, 20 insertions(+), 5 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/template/explicit-instantiation9.C
> 
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index eb102dea829..4f2ad8201b7 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -27729,11 +27729,20 @@ cp_parser_class_head (cp_parser* parser,
>                            class_head_start_location,
>                            get_finish (type_start_token->location));
>         rich_location richloc (line_table, reported_loc);
> -      richloc.add_fixit_insert_before (class_head_start_location,
> -                                       "template <> ");
> -      error_at (&richloc,
> -		"an explicit specialization must be preceded by"
> -		" %<template <>%>");
> +      if (processing_explicit_instantiation)
> +	{
> +	  richloc.add_fixit_insert_before ("<> ");
> +	  error_at (&richloc,
> +		    "an explicit instantiation cannot have a definition;"
> +		    " use %<template <>%> to declare a specialization");
> +	}
> +      else
> +	{
> +	  richloc.add_fixit_insert_before ("template <> ");
> +	  error_at (&richloc,
> +		    "an explicit specialization must be preceded by"
> +		    " %<template <>%>");
> +	}
>         invalid_explicit_specialization_p = true;
>         /* Take the same action that would have been taken by
>   	 cp_parser_explicit_specialization.  */
> diff --git a/gcc/testsuite/g++.dg/template/explicit-instantiation9.C b/gcc/testsuite/g++.dg/template/explicit-instantiation9.C
> new file mode 100644
> index 00000000000..c4400226ef8
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/template/explicit-instantiation9.C
> @@ -0,0 +1,6 @@
> +// Fixits for specialisations are not valid for instantiations
> +
> +template <typename T>
> +struct S {};
> +
> +template struct S<int> {};  // { dg-error "explicit instantiation cannot have a definition" }
diff mbox series

Patch

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index eb102dea829..4f2ad8201b7 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -27729,11 +27729,20 @@  cp_parser_class_head (cp_parser* parser,
                          class_head_start_location,
                          get_finish (type_start_token->location));
       rich_location richloc (line_table, reported_loc);
-      richloc.add_fixit_insert_before (class_head_start_location,
-                                       "template <> ");
-      error_at (&richloc,
-		"an explicit specialization must be preceded by"
-		" %<template <>%>");
+      if (processing_explicit_instantiation)
+	{
+	  richloc.add_fixit_insert_before ("<> ");
+	  error_at (&richloc,
+		    "an explicit instantiation cannot have a definition;"
+		    " use %<template <>%> to declare a specialization");
+	}
+      else
+	{
+	  richloc.add_fixit_insert_before ("template <> ");
+	  error_at (&richloc,
+		    "an explicit specialization must be preceded by"
+		    " %<template <>%>");
+	}
       invalid_explicit_specialization_p = true;
       /* Take the same action that would have been taken by
 	 cp_parser_explicit_specialization.  */
diff --git a/gcc/testsuite/g++.dg/template/explicit-instantiation9.C b/gcc/testsuite/g++.dg/template/explicit-instantiation9.C
new file mode 100644
index 00000000000..c4400226ef8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/explicit-instantiation9.C
@@ -0,0 +1,6 @@ 
+// Fixits for specialisations are not valid for instantiations
+
+template <typename T>
+struct S {};
+
+template struct S<int> {};  // { dg-error "explicit instantiation cannot have a definition" }