https://gcc.gnu.org/g:b7f719612515a86d1d2a36e24b02ade3f0904e10

commit r15-2778-gb7f719612515a86d1d2a36e24b02ade3f0904e10
Author: Nathaniel Shead <nathanielosh...@gmail.com>
Date:   Mon Mar 4 22:59:56 2024 +1100

    c++: Improve fixits for incorrect explicit instantiations
    
    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 <nathanielosh...@gmail.com>

Diff:
---
 gcc/cp/parser.cc                                      | 19 ++++++++++++++-----
 .../g++.dg/template/explicit-instantiation9.C         |  6 ++++++
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index f625b0a310c8..82f3903838e2 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -27721,11 +27721,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 000000000000..c4400226ef83
--- /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" }

Reply via email to