This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 7647
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 30 Mar 2003 14:36:18 -0800
- Subject: C++ PATCH: PR 7647
- Reply-to: mark at codesourcery dot com
This patch fixes PR C++/7647, a high-priority PR.
Tested on i686-pc-linux-gnu, applied on the mainline and on the
branch.
--
Mark Mitchell
CodeSourcery, LLC
mark at codesourcery dot com
2003-03-30 Mark Mitchell <mark at codesourcery dot com>
PR c++/7647
* decl.c (grokdeclarator): Tidy, slightly.
* search.c (lookup_field_1): Add want_type parameter.
(lookup_field_r): Adjust call to lookup_field_1.
2003-03-30 Mark Mitchell <mark at codesourcery dot com>
PR c++/7647
* g++.dg/lookup-class-member-2.C: New test.
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1029
diff -c -5 -p -r1.1029 decl.c
*** cp/decl.c 30 Mar 2003 16:00:38 -0000 1.1029
--- cp/decl.c 30 Mar 2003 22:25:56 -0000
*************** grokdeclarator (tree declarator,
*** 11549,11570 ****
declaration, to cause callers to completely
ignore this declaration. */
return void_type_node;
}
- /* 9.2p13 [class.mem] */
- if (constructor_name_p (declarator, current_class_type)
- /* The standard does not allow non-static data members
- here either, but we agreed at the 10/99 meeting
- to change that in TC 1 so that they are allowed in
- classes with no user-defined constructors. */
- && staticp)
- pedwarn ("ISO C++ forbids static data member `%D' with same name as enclosing class",
- declarator);
-
if (staticp)
{
/* C++ allows static class members. All other work
for this is done by grokfield. */
decl = build_lang_decl (VAR_DECL, declarator, type);
TREE_STATIC (decl) = 1;
/* In class context, 'static' means public access. */
--- 11549,11567 ----
declaration, to cause callers to completely
ignore this declaration. */
return void_type_node;
}
if (staticp)
{
+ /* [class.mem] forbids static data members with the
+ same name as the enclosing class. Non-static data
+ members are checked in check_field_decls. */
+ if (constructor_name_p (declarator, current_class_type))
+ pedwarn ("ISO C++ forbids static data member `%D' with same name as enclosing class",
+ declarator);
+
/* C++ allows static class members. All other work
for this is done by grokfield. */
decl = build_lang_decl (VAR_DECL, declarator, type);
TREE_STATIC (decl) = 1;
/* In class context, 'static' means public access. */
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.257
diff -c -5 -p -r1.257 search.c
*** cp/search.c 13 Mar 2003 21:39:38 -0000 1.257
--- cp/search.c 30 Mar 2003 22:25:57 -0000
*************** struct vbase_info
*** 79,89 ****
/* A pointer to a complete object of the indicated TYPE. */
tree decl_ptr;
tree inits;
};
! static tree lookup_field_1 (tree, tree);
static tree dfs_check_overlap (tree, void *);
static tree dfs_no_overlap_yet (tree, int, void *);
static base_kind lookup_base_r (tree, tree, base_access,
bool, bool, bool, tree *);
static int dynamic_cast_base_recurse (tree, tree, bool, tree *);
--- 79,89 ----
/* A pointer to a complete object of the indicated TYPE. */
tree decl_ptr;
tree inits;
};
! static tree lookup_field_1 (tree, tree, bool);
static tree dfs_check_overlap (tree, void *);
static tree dfs_no_overlap_yet (tree, int, void *);
static base_kind lookup_base_r (tree, tree, base_access,
bool, bool, bool, tree *);
static int dynamic_cast_base_recurse (tree, tree, bool, tree *);
*************** get_dynamic_cast_base_type (tree subtype
*** 418,438 ****
offset = build_int_2 (boff, -1);
TREE_TYPE (offset) = ssizetype;
return offset;
}
! /* Search for a member with name NAME in a multiple inheritance lattice
! specified by TYPE. If it does not exist, return NULL_TREE.
If the member is ambiguously referenced, return `error_mark_node'.
! Otherwise, return the FIELD_DECL. */
/* Do a 1-level search for NAME as a member of TYPE. The caller must
figure out whether it can access this field. (Since it is only one
level, this is reasonable.) */
static tree
! lookup_field_1 (tree type, tree name)
{
register tree field;
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
|| TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM
--- 418,439 ----
offset = build_int_2 (boff, -1);
TREE_TYPE (offset) = ssizetype;
return offset;
}
! /* Search for a member with name NAME in a multiple inheritance
! lattice specified by TYPE. If it does not exist, return NULL_TREE.
If the member is ambiguously referenced, return `error_mark_node'.
! Otherwise, return a DECL with the indicated name. If WANT_TYPE is
! true, type declarations are preferred. */
/* Do a 1-level search for NAME as a member of TYPE. The caller must
figure out whether it can access this field. (Since it is only one
level, this is reasonable.) */
static tree
! lookup_field_1 (tree type, tree name, bool want_type)
{
register tree field;
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
|| TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM
*************** lookup_field_1 (tree type, tree name)
*** 465,515 ****
hi = i;
else if (DECL_NAME (fields[i]) < name)
lo = i + 1;
else
{
/* We might have a nested class and a field with the
same name; we sorted them appropriately via
field_decl_cmp, so just look for the last field with
this name. */
! while (i + 1 < hi
! && DECL_NAME (fields[i+1]) == name)
! ++i;
! return fields[i];
}
}
return NULL_TREE;
}
field = TYPE_FIELDS (type);
#ifdef GATHER_STATISTICS
n_calls_lookup_field_1++;
#endif /* GATHER_STATISTICS */
! while (field)
{
#ifdef GATHER_STATISTICS
n_fields_searched++;
#endif /* GATHER_STATISTICS */
my_friendly_assert (DECL_P (field), 0);
if (DECL_NAME (field) == NULL_TREE
&& ANON_AGGR_TYPE_P (TREE_TYPE (field)))
{
! tree temp = lookup_field_1 (TREE_TYPE (field), name);
if (temp)
return temp;
}
if (TREE_CODE (field) == USING_DECL)
/* For now, we're just treating member using declarations as
old ARM-style access declarations. Thus, there's no reason
to return a USING_DECL, and the rest of the compiler can't
handle it. Once the class is defined, these are purged
from TYPE_FIELDS anyhow; see handle_using_decl. */
! ;
! else if (DECL_NAME (field) == name)
return field;
- field = TREE_CHAIN (field);
}
/* Not found. */
if (name == vptr_identifier)
{
/* Give the user what s/he thinks s/he wants. */
--- 466,529 ----
hi = i;
else if (DECL_NAME (fields[i]) < name)
lo = i + 1;
else
{
+ field = NULL_TREE;
+
/* We might have a nested class and a field with the
same name; we sorted them appropriately via
field_decl_cmp, so just look for the last field with
this name. */
! while (true)
! {
! if (!want_type
! || TREE_CODE (fields[i]) == TYPE_DECL
! || DECL_CLASS_TEMPLATE_P (fields[i]))
! field = fields[i];
! if (i + 1 == hi || DECL_NAME (fields[i+1]) != name)
! break;
! i++;
! }
!
! return field;
}
}
return NULL_TREE;
}
field = TYPE_FIELDS (type);
#ifdef GATHER_STATISTICS
n_calls_lookup_field_1++;
#endif /* GATHER_STATISTICS */
! for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
#ifdef GATHER_STATISTICS
n_fields_searched++;
#endif /* GATHER_STATISTICS */
my_friendly_assert (DECL_P (field), 0);
if (DECL_NAME (field) == NULL_TREE
&& ANON_AGGR_TYPE_P (TREE_TYPE (field)))
{
! tree temp = lookup_field_1 (TREE_TYPE (field), name, want_type);
if (temp)
return temp;
}
if (TREE_CODE (field) == USING_DECL)
/* For now, we're just treating member using declarations as
old ARM-style access declarations. Thus, there's no reason
to return a USING_DECL, and the rest of the compiler can't
handle it. Once the class is defined, these are purged
from TYPE_FIELDS anyhow; see handle_using_decl. */
! continue;
!
! if (DECL_NAME (field) == name
! && (!want_type
! || TREE_CODE (field) == TYPE_DECL
! || DECL_CLASS_TEMPLATE_P (field)))
return field;
}
/* Not found. */
if (name == vptr_identifier)
{
/* Give the user what s/he thinks s/he wants. */
*************** lookup_field_r (tree binfo, void *data)
*** 1077,1087 ****
nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
}
if (!nval)
/* Look for a data member or type. */
! nval = lookup_field_1 (type, lfi->name);
/* If there is no declaration with the indicated name in this type,
then there's nothing to do. */
if (!nval)
return NULL_TREE;
--- 1091,1101 ----
nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
}
if (!nval)
/* Look for a data member or type. */
! nval = lookup_field_1 (type, lfi->name, lfi->want_type);
/* If there is no declaration with the indicated name in this type,
then there's nothing to do. */
if (!nval)
return NULL_TREE;
Index: testsuite/g++.dg/lookup/class-member-2.C
===================================================================
RCS file: testsuite/g++.dg/lookup/class-member-2.C
diff -N testsuite/g++.dg/lookup/class-member-2.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/lookup/class-member-2.C 30 Mar 2003 22:25:57 -0000
***************
*** 0 ****
--- 1,7 ----
+ template <typename T> struct A
+ {
+ void foo () const {}
+ char A;
+ };
+
+ void bar() { A<void>().foo(); }