c++: Improve fixits for incorrect explicit instantiations
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-arm |
success
|
Test passed
|
Commit Message
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
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" }
@@ -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. */
new file mode 100644
@@ -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" }