From: Mark Mitchell Date: Wed, 11 Aug 2004 22:13:32 +0000 (+0000) Subject: re PR c++/16964 (ICE in cp_parser_class_specifier due to redefinition) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2436b51feb8a5cf7ca694eb4bf13bcb1e6899217;p=gcc.git re PR c++/16964 (ICE in cp_parser_class_specifier due to redefinition) PR c++/16964 * parser.c (cp_parser_class_specifier): Robustify. PR c++/16904 * pt.c (tsubst_copy_and_build): Complain about invalid qualification. PR c++/16929 * pt.c (tsubst_default_argument): Clear out current_class_ptr and current_class_ref while tsubsting. PR c++/16964 * g++.dg/parse/error16.C: New test. PR c++/16904 * g++.dg/template/error14.C: New test. PR c++/16929 * g++.dg/template/error15.C: New test. From-SVN: r85824 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 269b20bd15e..d15b6faff70 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2004-08-11 Mark Mitchell + + PR c++/16964 + * parser.c (cp_parser_class_specifier): Robustify. + + PR c++/16904 + * pt.c (tsubst_copy_and_build): Complain about invalid + qualification. + + PR c++/16929 + * pt.c (tsubst_default_argument): Clear out current_class_ptr and + current_class_ref while tsubsting. + 2004-08-10 Mark Mitchell PR c++/16971 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 2176e05eece..65872c8de5e 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -12308,6 +12308,7 @@ cp_parser_class_specifier (cp_parser* parser) bool nested_name_specifier_p; unsigned saved_num_template_parameter_lists; bool pop_p = false; + tree scope = NULL_TREE; push_deferring_access_checks (dk_no_deferred); @@ -12343,7 +12344,10 @@ cp_parser_class_specifier (cp_parser* parser) /* Start the class. */ if (nested_name_specifier_p) - pop_p = push_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (type))); + { + scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)); + pop_p = push_scope (scope); + } type = begin_class_definition (type); if (type == error_mark_node) @@ -12368,7 +12372,7 @@ cp_parser_class_specifier (cp_parser* parser) if (type != error_mark_node) type = finish_struct (type, attributes); if (pop_p) - pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (type))); + pop_scope (scope); /* If this class is not itself within the scope of another class, then we need to parse the bodies of all of the queued function definitions. Note that the queued functions defined in a class diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 14b0c837cf2..0574f44f1ad 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5942,6 +5942,9 @@ tsubst_aggr_type (tree t, tree tsubst_default_argument (tree fn, tree type, tree arg) { + tree saved_class_ptr = NULL_TREE; + tree saved_class_ref = NULL_TREE; + /* This default argument came from a template. Instantiate the default argument here, not in tsubst. In the case of something like: @@ -5959,12 +5962,27 @@ tsubst_default_argument (tree fn, tree type, tree arg) within the scope of FN. Since push_access_scope sets current_function_decl, we must explicitly clear it here. */ current_function_decl = NULL_TREE; + /* The "this" pointer is not valid in a default argument. */ + if (cfun) + { + saved_class_ptr = current_class_ptr; + cp_function_chain->x_current_class_ptr = NULL_TREE; + saved_class_ref = current_class_ref; + cp_function_chain->x_current_class_ref = NULL_TREE; + } push_deferring_access_checks(dk_no_deferred); arg = tsubst_expr (arg, DECL_TI_ARGS (fn), tf_error | tf_warning, NULL_TREE); pop_deferring_access_checks(); + /* Restore the "this" pointer. */ + if (cfun) + { + cp_function_chain->x_current_class_ptr = saved_class_ptr; + cp_function_chain->x_current_class_ref = saved_class_ref; + } + pop_access_scope (fn); /* Make sure the default argument is reasonable. */ @@ -8495,6 +8513,21 @@ tsubst_copy_and_build (tree t, return error_mark_node; } } + else if (TREE_CODE (member) == SCOPE_REF + && !CLASS_TYPE_P (TREE_OPERAND (member, 0)) + && TREE_CODE (TREE_OPERAND (member, 0)) != NAMESPACE_DECL) + { + if (complain & tf_error) + { + if (TYPE_P (TREE_OPERAND (member, 0))) + error ("`%T' is not a class or namespace", + TREE_OPERAND (member, 0)); + else + error ("`%D' is not a class or namespace", + TREE_OPERAND (member, 0)); + } + return error_mark_node; + } else if (TREE_CODE (member) == FIELD_DECL) return finish_non_static_data_member (member, object, NULL_TREE); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c4226dc7b0a..9959a9d1709 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2004-08-11 Mark Mitchell + + PR c++/16964 + * g++.dg/parse/error16.C: New test. + + PR c++/16904 + * g++.dg/template/error14.C: New test. + + PR c++/16929 + * g++.dg/template/error15.C: New test. + 2004-08-11 Devang Patel * gcc.dg/darwin-ld-20040809-1.c: New test. diff --git a/gcc/testsuite/g++.dg/parse/error16.C b/gcc/testsuite/g++.dg/parse/error16.C new file mode 100644 index 00000000000..afc790e072e --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/error16.C @@ -0,0 +1,8 @@ +// PR c++/16964 + +struct A +{ + struct B {}; // { dg-error "" } +}; + +struct A::B{}; // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/template/error14.C b/gcc/testsuite/g++.dg/template/error14.C new file mode 100644 index 00000000000..c5043cfb4cb --- /dev/null +++ b/gcc/testsuite/g++.dg/template/error14.C @@ -0,0 +1,8 @@ +// PR c++/16904 + +template struct X +{ + X() { this->T::i; } // { dg-error "" } +}; + +X x; diff --git a/gcc/testsuite/g++.dg/template/error15.C b/gcc/testsuite/g++.dg/template/error15.C new file mode 100644 index 00000000000..5a1a3227dda --- /dev/null +++ b/gcc/testsuite/g++.dg/template/error15.C @@ -0,0 +1,24 @@ +// PR c++/16929 + +template +class A { + int x; +}; + +template +class B { +protected: + + A a; // { dg-error "" } + + void f(const A * a1 = &a); + + void g(void); +}; + +template +void B::g(void) { + f(); // { dg-error "" } +} + +template class B; // { dg-error "" }