This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PRs 19395, 19367
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 30 Jan 2005 20:12:18 -0800
- Subject: C++ PATCH: PRs 19395, 19367
- Reply-to: mark at codesourcery dot com
PR 19395 reports that we were allowing qualified names in typedef
declarators at class scope. We already had code to issue appropriate
errors in non-class scopes; this was simply an oversight.
PR 19367 was a case where we got rather confused about
using-declarations when there was already a builtin declaration in the
namespace in which the using-declaration occurred. In particular, we
tried to overload the built-in with the new declaration, which is
incorrect; the using-declaration should supplant the built-in.
(Parenthetically, the way I think builtins ought to work is that when
name-lookup fails to find a name in a namespace scope, then we ought
to check if the name is a built-in, and create the built-in at that
time. That would entirely avoid DECL_ANTICIPATED and the myriad
complexities that come with it.)
Tested on x86_64-unknown-linux-gnu, applied on the mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2005-01-30 Mark Mitchell <mark@codesourcery.com>
PR c++/19395
* decl.c (grokdeclarator): Refactor code so that qualified names
are never allowed as the declarator in a typedef.
PR c++/19367
* name-lookup.c (do_nonmember_using_decl): Avoid overloading
builtin declarations.
2005-01-30 Mark Mitchell <mark@codesourcery.com>
PR c++/19395
* g++.dg/parse/error24.C: New test.
PR c++/19367
* g++.dg/lookup/builtin1.C: New test.
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1355
diff -c -5 -p -r1.1355 decl.c
*** cp/decl.c 27 Jan 2005 07:32:20 -0000 1.1355
--- cp/decl.c 31 Jan 2005 03:56:03 -0000
*************** grokdeclarator (const cp_declarator *dec
*** 7522,7543 ****
in typenames, fields or parameters. */
if (current_lang_name == lang_name_java)
TYPE_FOR_JAVA (type) = 1;
if (decl_context == FIELD)
! {
! if (constructor_name_p (unqualified_id, current_class_type))
! pedwarn ("ISO C++ forbids nested type %qD with same name "
! "as enclosing class",
! unqualified_id);
! decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
! }
else
{
- decl = build_decl (TYPE_DECL, unqualified_id, type);
- if (in_namespace || ctype)
- error ("%Jtypedef name may not be a nested-name-specifier", decl);
if (!current_function_decl)
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (current_function_decl)
|| (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P
(current_function_decl)))
--- 7522,7539 ----
in typenames, fields or parameters. */
if (current_lang_name == lang_name_java)
TYPE_FOR_JAVA (type) = 1;
if (decl_context == FIELD)
! decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
else
+ decl = build_decl (TYPE_DECL, unqualified_id, type);
+ if (id_declarator && declarator->u.id.qualifying_scope)
+ error ("%Jtypedef name may not be a nested-name-specifier", decl);
+
+ if (decl_context != FIELD)
{
if (!current_function_decl)
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (current_function_decl)
|| (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P
(current_function_decl)))
*************** grokdeclarator (const cp_declarator *dec
*** 7545,7554 ****
--- 7541,7554 ----
clones of this constructor/destructor, and there will
be copies of this TYPE_DECL generated in those
clones. */
DECL_ABSTRACT (decl) = 1;
}
+ else if (constructor_name_p (unqualified_id, current_class_type))
+ pedwarn ("ISO C++ forbids nested type %qD with same name "
+ "as enclosing class",
+ unqualified_id);
/* If the user declares "typedef struct {...} foo" then the
struct will have an anonymous name. Fill that name in now.
Nothing can refer to it, so nothing needs know about the name
change. */
Index: cp/name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.107
diff -c -5 -p -r1.107 name-lookup.c
*** cp/name-lookup.c 31 Jan 2005 01:16:59 -0000 1.107
--- cp/name-lookup.c 31 Jan 2005 03:56:05 -0000
*************** do_nonmember_using_decl (tree scope, tre
*** 2034,2043 ****
--- 2034,2052 ----
if (!DECL_IMPLICIT_TYPEDEF_P (oldval))
error ("%qD is already declared in this scope", name);
oldval = NULL_TREE;
}
+ /* It is impossible to overload a built-in function; any
+ explicit declaration eliminates the built-in declaration.
+ So, if OLDVAL is a built-in, then we can just pretend it
+ isn't there. */
+ if (oldval
+ && TREE_CODE (oldval) == FUNCTION_DECL
+ && DECL_ANTICIPATED (oldval))
+ oldval = NULL_TREE;
+
*newval = oldval;
for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp))
{
tree new_fn = OVL_CURRENT (tmp);
*************** do_nonmember_using_decl (tree scope, tre
*** 2057,2093 ****
else if (OVL_USED (tmp1))
continue; /* this is a using decl */
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
{
/* There was already a non-using declaration in
this scope with the same parameter types. If both
are the same extern "C" functions, that's ok. */
if (decls_match (new_fn, old_fn))
! {
! /* If the OLD_FN was a builtin, we've seen a real
! declaration in another namespace. Use it instead.
! Set tmp1 to NULL so we can use the existing
! OVERLOAD logic at the end of this inner loop.
! */
! if (DECL_ANTICIPATED (old_fn))
! {
! gcc_assert (! DECL_ANTICIPATED (new_fn));
! tmp1 = NULL;
! }
! break;
! }
! else if (!DECL_ANTICIPATED (old_fn))
! {
! /* If the OLD_FN was really declared, the
! declarations don't match. */
error ("%qD is already declared in this scope", name);
break;
}
-
- /* If the OLD_FN was not really there, just ignore
- it and keep going. */
}
}
/* If we broke out of the loop, there's no reason to add
this function to the using declarations for this
--- 2066,2087 ----
else if (OVL_USED (tmp1))
continue; /* this is a using decl */
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
{
+ gcc_assert (!DECL_ANTICIPATED (old_fn));
+
/* There was already a non-using declaration in
this scope with the same parameter types. If both
are the same extern "C" functions, that's ok. */
if (decls_match (new_fn, old_fn))
! break;
! else
! {
error ("%qD is already declared in this scope", name);
break;
}
}
}
/* If we broke out of the loop, there's no reason to add
this function to the using declarations for this
Index: testsuite/g++.dg/lookup/builtin1.C
===================================================================
RCS file: testsuite/g++.dg/lookup/builtin1.C
diff -N testsuite/g++.dg/lookup/builtin1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/lookup/builtin1.C 31 Jan 2005 03:56:05 -0000
***************
*** 0 ****
--- 1,12 ----
+ // PR c++/19367
+ // { dg-do link }
+
+ void abort (void) { throw 3; }
+
+ namespace std { using ::abort; }
+
+ int main ()
+ {
+ using std::abort;
+ abort();
+ }
Index: testsuite/g++.dg/parse/error24.C
===================================================================
RCS file: testsuite/g++.dg/parse/error24.C
diff -N testsuite/g++.dg/parse/error24.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/error24.C 31 Jan 2005 03:56:05 -0000
***************
*** 0 ****
--- 1,7 ----
+ // PR c++/19395
+
+ struct A {
+ typedef int ::X; // { dg-error "" }
+ };
+
+