aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2003-12-04 07:04:01 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2003-12-04 07:04:01 +0000
commitafb0918a9b127a64098a1267f328908acc7e4d1d (patch)
treee0f05bad020e9fd6c620b6e6dec6e478ffafd699
parentaedec8ddd22c81f7afec5423accb4175cad874b0 (diff)
downloadgcc-afb0918a9b127a64098a1267f328908acc7e4d1d.zip
gcc-afb0918a9b127a64098a1267f328908acc7e4d1d.tar.gz
gcc-afb0918a9b127a64098a1267f328908acc7e4d1d.tar.bz2
re PR c++/9127 (Confusing diagnostic on specialization not introduced by "template<>")
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
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/parser.c35
-rw-r--r--gcc/cp/search.c10
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/error6.C13
6 files changed, 66 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 451b459..33a772f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 80414db..b02fb56 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9ec128c..1ce8cd78 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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;
}
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index dc8ef90..e10a3da 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 09e058d..55a94c9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..7560dcf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/error6.C
@@ -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;
+}
+