diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 451b459c323..33a772f1ec5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -5,6 +5,12 @@ 2003-12-03 Mark Mitchell + 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 80414db73a6..b02fb5699e0 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 9ec128c9edf..1ce8cd786f2 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 dc8ef9046ec..e10a3da8446 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 09e058d6e24..55a94c95bea 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2003-12-03 Mark Mitchell + + PR c++/9127 + * g++.dg/template/error6.C: New test. + 2003-12-03 Jakub Jelinek * 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 00000000000..7560dcfb51f --- /dev/null +++ b/gcc/testsuite/g++.dg/template/error6.C @@ -0,0 +1,13 @@ +template +struct tento { + enum {value = 10*tento::value}; +}; + +struct tento<0> { // { dg-error "" } + enum {value=1}; +}; + +int main() { + if (tento<4>::value != 10000) return -1; +} +