This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR c++/16964, c++/16904, c++/16929
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 11 Aug 2004 15:19:02 -0700
- Subject: C++ PATCH: PR c++/16964, c++/16904, c++/16929
- Reply-to: mark at codesourcery dot com
This patch fixes three little C++ regressions on the GCC 3.4 branch.
Tested on i686-pc-linux-gnu, applied on the branch and on the
mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2004-08-11 Mark Mitchell <mark@codesourcery.com>
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-11 Mark Mitchell <mark@codesourcery.com>
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.
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.233
diff -c -5 -p -r1.233 parser.c
*** cp/parser.c 11 Aug 2004 00:14:35 -0000 1.233
--- cp/parser.c 11 Aug 2004 20:01:51 -0000
*************** cp_parser_class_specifier (cp_parser* pa
*** 12306,12315 ****
--- 12306,12316 ----
tree attributes = NULL_TREE;
int has_trailing_semicolon;
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);
/* Parse the class-head. */
type = cp_parser_class_head (parser,
*************** cp_parser_class_specifier (cp_parser* pa
*** 12341,12351 ****
= parser->num_template_parameter_lists;
parser->num_template_parameter_lists = 0;
/* Start the class. */
if (nested_name_specifier_p)
! pop_p = push_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)));
type = begin_class_definition (type);
if (type == error_mark_node)
/* If the type is erroneous, skip the entire body of the class. */
cp_parser_skip_to_closing_brace (parser);
--- 12342,12355 ----
= parser->num_template_parameter_lists;
parser->num_template_parameter_lists = 0;
/* Start the class. */
if (nested_name_specifier_p)
! {
! scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type));
! pop_p = push_scope (scope);
! }
type = begin_class_definition (type);
if (type == error_mark_node)
/* If the type is erroneous, skip the entire body of the class. */
cp_parser_skip_to_closing_brace (parser);
*************** cp_parser_class_specifier (cp_parser* pa
*** 12366,12376 ****
attributes = chainon (attributes, sub_attr);
}
if (type != error_mark_node)
type = finish_struct (type, attributes);
if (pop_p)
! pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)));
/* 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
are not always processed immediately following the
class-specifier for that class. Consider:
--- 12370,12380 ----
attributes = chainon (attributes, sub_attr);
}
if (type != error_mark_node)
type = finish_struct (type, attributes);
if (pop_p)
! 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
are not always processed immediately following the
class-specifier for that class. Consider:
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.901
diff -c -5 -p -r1.901 pt.c
*** cp/pt.c 4 Aug 2004 05:27:51 -0000 1.901
--- cp/pt.c 11 Aug 2004 20:01:52 -0000
*************** tsubst_aggr_type (tree t,
*** 5940,5949 ****
--- 5940,5952 ----
FN), which has the indicated TYPE. */
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:
template <class T>
*************** tsubst_default_argument (tree fn, tree t
*** 5957,5972 ****
--- 5960,5990 ----
push_access_scope (fn);
/* The default argument expression should not be considered to be
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. */
arg = check_default_argument (type, arg);
*************** tsubst_copy_and_build (tree t,
*** 8493,8502 ****
--- 8511,8535 ----
{
qualified_name_lookup_error (TREE_TYPE (object), tmpl);
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);
return finish_class_member_access_expr (object, member);
}
Index: testsuite/g++.dg/parse/error16.C
===================================================================
RCS file: testsuite/g++.dg/parse/error16.C
diff -N testsuite/g++.dg/parse/error16.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/error16.C 11 Aug 2004 20:01:53 -0000
***************
*** 0 ****
--- 1,8 ----
+ // PR c++/16964
+
+ struct A
+ {
+ struct B {}; // { dg-error "" }
+ };
+
+ struct A::B{}; // { dg-error "" }
Index: testsuite/g++.dg/template/error14.C
===================================================================
RCS file: testsuite/g++.dg/template/error14.C
diff -N testsuite/g++.dg/template/error14.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/error14.C 11 Aug 2004 20:01:53 -0000
***************
*** 0 ****
--- 1,8 ----
+ // PR c++/16904
+
+ template<typename T> struct X
+ {
+ X() { this->T::i; } // { dg-error "" }
+ };
+
+ X<int> x;
Index: testsuite/g++.dg/template/error15.C
===================================================================
RCS file: testsuite/g++.dg/template/error15.C
diff -N testsuite/g++.dg/template/error15.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/error15.C 11 Aug 2004 20:01:53 -0000
***************
*** 0 ****
--- 1,24 ----
+ // PR c++/16929
+
+ template <class T>
+ class A {
+ int x;
+ };
+
+ template <class T>
+ class B {
+ protected:
+
+ A<T> a;
+
+ void f(const A<T> * a1 = &a);
+
+ void g(void);
+ };
+
+ template <class T>
+ void B<T>::g(void) {
+ f();
+ }
+
+ template class B<long>;