re PR c++/9127 (Confusing diagnostic on specialization not introduced by "template<>")
authorMark Mitchell <mark@codesourcery.com>
Thu, 4 Dec 2003 07:04:01 +0000 (07:04 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 4 Dec 2003 07:04:01 +0000 (07:04 +0000)
PR c++/9127
* cp-tree.h (at_namespace_scope_p): New function.
* parser.c (cp_parser_class_head): Handle invalid explicit
specializations.
* search.c (at_namespace_scope_p): New function.

PR c++/9127
* g++.dg/template/error6.C: New test.

From-SVN: r74274

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/search.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/error6.C [new file with mode: 0644]

index 451b459c323f44d0c9d56ff474a86fbb3dddfb9f..33a772f1ec54e2126800e91093216c00fb0cde10 100644 (file)
@@ -5,6 +5,12 @@
 
 2003-12-03  Mark Mitchell  <mark@codesourcery.com>
 
+       PR c++/9127
+       * cp-tree.h (at_namespace_scope_p): New function.
+       * parser.c (cp_parser_class_head): Handle invalid explicit
+       specializations.
+       * search.c (at_namespace_scope_p): New function.
+
        PR c++/13179
        * semantics.c (finish_handler_parms): Do not call eh_type_info for
        types used in templates.
index 80414db73a676262936742b4e8764a1463c7ca1e..b02fb5699e0a111e4bb66135da68495446c32c9e 100644 (file)
@@ -3966,6 +3966,7 @@ extern void reinit_search_statistics              (void);
 extern tree current_scope                      (void);
 extern int at_function_scope_p                  (void);
 extern bool at_class_scope_p                    (void);
+extern bool at_namespace_scope_p                (void);
 extern tree context_for_name_lookup            (tree);
 extern tree lookup_conversions                 (tree);
 extern tree binfo_for_vtable                   (tree);
index 9ec128c9edfc7c6b8443a538f27873f6a5fd9c32..1ce8cd786f2455e55b3c2b4f4f2102794901a28f 100644 (file)
@@ -11584,6 +11584,7 @@ cp_parser_class_head (cp_parser* parser,
   bool template_id_p = false;
   bool qualified_p = false;
   bool invalid_nested_name_p = false;
+  bool invalid_explicit_specialization_p = false;
   unsigned num_templates;
 
   /* Assume no nested-name-specifier will be present.  */
@@ -11732,12 +11733,31 @@ cp_parser_class_head (cp_parser* parser,
   else if (invalid_nested_name_p)
     cp_parser_error (parser,
                     "qualified name does not name a class");
+  /* An explicit-specialization must be preceded by "template <>".  If
+     it is not, try to recover gracefully.  */
+  if (at_namespace_scope_p () 
+      && parser->num_template_parameter_lists == 0
+      && num_templates == 1)
+    {
+      error ("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.  */
+      ++parser->num_template_parameter_lists;
+      begin_specialization ();
+    }
+  /* There must be no "return" statements between this point and the
+     end of this function; set "type "to the correct return value and
+     use "goto done;" to return.  */
   /* Make sure that the right number of template parameters were
      present.  */
   if (!cp_parser_check_template_parameters (parser, num_templates))
-    /* If something went wrong, there is no point in even trying to
-       process the class-definition.  */
-    return NULL_TREE;
+    {
+      /* If something went wrong, there is no point in even trying to
+        process the class-definition.  */
+      type = NULL_TREE;
+      goto done;
+    }
 
   /* Look up the type.  */
   if (template_id_p)
@@ -11789,7 +11809,8 @@ cp_parser_class_head (cp_parser* parser,
        {
          error ("declaration of `%D' in `%D' which does not "
                 "enclose `%D'", type, scope, nested_name_specifier);
-         return NULL_TREE;
+         type = NULL_TREE;
+         goto done;
        }
       /* [dcl.meaning]
 
@@ -11848,6 +11869,12 @@ cp_parser_class_head (cp_parser* parser,
   if (nested_name_specifier)
     pop_scope (nested_name_specifier);
 
+ done:
+  if (invalid_explicit_specialization_p)
+    {
+      end_specialization ();
+      --parser->num_template_parameter_lists;
+    }
   return type;
 }
 
index dc8ef9046ecf61f7426808a0fb24f4f814b65538..e10a3da84469e7145dc3e0cf5ef9e6f0cd63e352 100644 (file)
@@ -580,6 +580,16 @@ at_class_scope_p (void)
   return cs && TYPE_P (cs);
 }
 
+/* Returns true if the innermost active scope is a namespace scope.  */
+
+bool
+at_namespace_scope_p (void)
+{
+  /* We are in a namespace scope if we are not it a class scope or a
+     function scope.  */
+  return !current_scope();
+}
+
 /* Return the scope of DECL, as appropriate when doing name-lookup.  */
 
 tree
index 09e058d6e244b3fec363c2d1fdece0981631c31b..55a94c95bead0bf12fc00fa27e93c7bbefe697b6 100644 (file)
@@ -1,3 +1,8 @@
+2003-12-03  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/9127
+       * g++.dg/template/error6.C: New test.
+
 2003-12-03  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.dg/20031202-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/template/error6.C b/gcc/testsuite/g++.dg/template/error6.C
new file mode 100644 (file)
index 0000000..7560dcf
--- /dev/null
@@ -0,0 +1,13 @@
+template<int n>
+struct tento {
+  enum {value = 10*tento<n-1>::value};
+};
+
+struct tento<0> { // { dg-error "" }
+   enum {value=1};
+};
+
+int main() {
+  if (tento<4>::value != 10000) return -1;
+}
+