Message ID | 66b1f32d.050a0220.e6a95.4239@mx.google.com |
---|---|
State | New |
Headers | show |
Series | c++: Improve fixits for incorrect explicit instantiations | expand |
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 --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" }
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