C++ PATCHes for using decls/arrays
Mark Mitchell
mark@markmitchell.com
Thu Jan 21 21:16:00 GMT 1999
Brendan turned up a couple more regressions:
We issued a bogus error on:
template <int x> int foo(char[4][x]) { return x; }
int (*bar)(char[4][3]) = &foo;
And failed to issue an error on:
namespace foo
{
void x (bool);
void x (char);
void x (int);
void x (double);
}
namespace baz { void x (int); }
void fn (int i)
{
using foo::x;
using baz::x;
x(i);
}
Some of the handling of using declarations was a little suspect in
that it was relying on what was essentially a bug in dupliate_decls.
I've cleaned it up.
--
Mark Mitchell mark@markmitchell.com
Mark Mitchell Consulting http://www.markmitchell.com
1999-01-21 Mark Mitchell <mark@markmitchell.com>
* cp-tree.h (PUSH_GLOBAL): New macro.
(PUSH_LOCAL): Likewise.
(PUSH_USING): Likewise.
(namespace_bindings_p): Declare.
(push_overloaded_decl): Likewise.
* decl.c (push_overloaded_decl): Don't make it static. Check for
illegal declarations after using declarations here.
(namespace_bindings_p): Likewise.
(duplicate_decls): Don't consider declarations from different
namespaces to be the same.
(pushdecl): Use symbolic PUSH_ constants in calls to
push_overloaded_decl.
(push_overloaded_decl_1): Likewise.
* decl2.c (validate_nonmember_using_decl): Tweak `std' handling.
(do_nonmember_using_decl): Check for illegal using declarations
after ordinary declarations here.
(do_local_using_decl): Call pushdecl to insert declarations.
* tree.c (build_cplus_array_type_1): Don't call build_array_type
for types involving template parameters.
Index: testsuite/g++.old-deja/g++.ns/using12.C
===================================================================
RCS file: using12.C
diff -N using12.C
*** /dev/null Sat Dec 5 20:30:03 1998
--- using12.C Thu Jan 21 21:02:03 1999
***************
*** 0 ****
--- 1,19 ----
+ // Build don't link:
+ // Origin: Brendan Kehoe <brendan@cygnus.com>
+
+ namespace foo
+ {
+ void x (bool); // ERROR - candidates
+ void x (char); // ERROR - candidates
+ void x (int); // ERROR - candidates
+ void x (double); // ERROR - candidates
+ }
+
+ namespace baz { void x (int); } // ERROR - candidates
+
+ void fn (int i)
+ {
+ using foo::x;
+ using baz::x;
+ x(i); // ERROR - ambiguous
+ }
Index: testsuite/g++.old-deja/g++.pt/array3.C
===================================================================
RCS file: array3.C
diff -N array3.C
*** /dev/null Sat Dec 5 20:30:03 1998
--- array3.C Thu Jan 21 21:02:04 1999
***************
*** 0 ****
--- 1,5 ----
+ // Build don't link:
+ // Origin: Brendan Kehoe <brendan@cygnus.com>
+
+ template <int x> int foo(char[4][x]) { return x; }
+ int (*bar)(char[4][3]) = &foo;
Index: testsuite/g++.old-deja/g++.ns/overload4.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.ns/overload4.C,v
retrieving revision 1.2
diff -c -p -r1.2 overload4.C
*** overload4.C 1998/12/16 21:51:00 1.2
--- overload4.C 1999/01/22 05:02:48
***************
*** 1,6 ****
// Build don't link:
namespace A{
! void f(); // ERROR - .*
}
using A::f;
--- 1,6 ----
// Build don't link:
namespace A{
! void f();
}
using A::f;
Index: testsuite/g++.old-deja/g++.ns/overload5.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.ns/overload5.C,v
retrieving revision 1.2
diff -c -p -r1.2 overload5.C
*** overload5.C 1998/12/16 21:51:01 1.2
--- overload5.C 1999/01/22 05:02:48
***************
*** 1,6 ****
// Build don't link:
namespace A{
! void f(){} // ERROR - previous declaration
}
using A::f;
--- 1,6 ----
// Build don't link:
namespace A{
! void f(){}
}
using A::f;
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.189
diff -c -p -r1.189 cp-tree.h
*** cp-tree.h 1999/01/21 14:29:23 1.189
--- cp-tree.h 1999/01/22 04:53:16
*************** extern tree current_class_name; /* IDENT
*** 2582,2587 ****
--- 2582,2595 ----
another declaration of an existing
entity is seen. */
+ /* Used with push_overloaded_decl. */
+ #define PUSH_GLOBAL 0 /* Push the DECL into namespace scope,
+ regardless of the current scope. */
+ #define PUSH_LOCAL 1 /* Push the DECL into the current
+ scope. */
+ #define PUSH_USING 2 /* We are pushing this DECL as the
+ result of a using declaration. */
+
/* Returns nonzero iff TYPE1 and TYPE2 are the same type, in the usual
sense of `same'. */
#define same_type_p(type1, type2) \
*************** extern tree perform_qualification_conver
*** 2692,2697 ****
--- 2700,2706 ----
extern void set_identifier_local_value PROTO((tree, tree));
extern int global_bindings_p PROTO((void));
extern int toplevel_bindings_p PROTO((void));
+ extern int namespace_bindings_p PROTO((void));
extern void keep_next_level PROTO((void));
extern int kept_level_p PROTO((void));
extern void declare_parm_level PROTO((void));
*************** extern int check_static_variable_definit
*** 2816,2821 ****
--- 2825,2831 ----
extern void push_local_binding PROTO((tree, tree));
extern void push_class_binding PROTO((tree, tree));
extern tree check_default_argument PROTO((tree, tree));
+ extern tree push_overloaded_decl PROTO((tree, int));
/* in decl2.c */
extern int check_java_method PROTO((tree));
Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.297
diff -c -p -r1.297 decl.c
*** decl.c 1999/01/21 14:29:26 1.297
--- decl.c 1999/01/22 04:53:25
*************** static struct stack_level *decl_stack;
*** 135,141 ****
static tree grokparms PROTO((tree, int));
static tree lookup_nested_type PROTO((tree, tree));
static char *redeclaration_error_message PROTO((tree, tree));
- static tree push_overloaded_decl PROTO((tree, int));
static struct stack_level *push_decl_level PROTO((struct stack_level *,
struct obstack *));
--- 135,140 ----
*************** static void pop_binding_level PROTO((voi
*** 145,151 ****
static void suspend_binding_level PROTO((void));
static void resume_binding_level PROTO((struct binding_level *));
static struct binding_level *make_binding_level PROTO((void));
- static int namespace_bindings_p PROTO((void));
static void declare_namespace_level PROTO((void));
static void signal_catch PROTO((int)) ATTRIBUTE_NORETURN;
static void storedecls PROTO((tree));
--- 144,149 ----
*************** toplevel_bindings_p ()
*** 922,928 ****
/* Nonzero if this is a namespace scope. */
! static int
namespace_bindings_p ()
{
return current_binding_level->namespace_p;
--- 920,926 ----
/* Nonzero if this is a namespace scope. */
! int
namespace_bindings_p ()
{
return current_binding_level->namespace_p;
*************** duplicate_decls (newdecl, olddecl)
*** 2942,2947 ****
--- 2940,2950 ----
}
else if (!types_match)
{
+ if (DECL_REAL_CONTEXT (newdecl) != DECL_REAL_CONTEXT (olddecl))
+ /* These are certainly not duplicate declarations; they're
+ from different scopes. */
+ return 0;
+
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
/* The name of a class template may not be declared to refer to
*************** pushdecl (x)
*** 3655,3661 ****
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
{
! t = push_overloaded_decl (x, 1);
if (t != x || DECL_LANGUAGE (x) == lang_c)
return t;
if (!namespace_bindings_p ())
--- 3658,3664 ----
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
{
! t = push_overloaded_decl (x, PUSH_LOCAL);
if (t != x || DECL_LANGUAGE (x) == lang_c)
return t;
if (!namespace_bindings_p ())
*************** pushdecl (x)
*** 3665,3671 ****
need_new_binding = 0;
}
else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
! return push_overloaded_decl (x, 0);
/* If declaring a type as a typedef, copy the type (unless we're
at line 0), and install this TYPE_DECL as the new type's typedef
--- 3668,3674 ----
need_new_binding = 0;
}
else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
! return push_overloaded_decl (x, PUSH_GLOBAL);
/* If declaring a type as a typedef, copy the type (unless we're
at line 0), and install this TYPE_DECL as the new type's typedef
*************** push_using_directive (used)
*** 4157,4175 ****
DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT
slot. It is dealt with the same way.
The value returned may be a previous declaration if we guessed wrong
about what language DECL should belong to (C or C++). Otherwise,
it's always DECL (and never something that's not a _DECL). */
! static tree
! push_overloaded_decl (decl, forgettable)
tree decl;
! int forgettable;
{
tree name = DECL_NAME (decl);
tree old;
tree new_binding;
! int doing_global = (namespace_bindings_p () || ! forgettable);
if (doing_global)
{
--- 4160,4184 ----
DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT
slot. It is dealt with the same way.
+ FLAGS is a bitwise-or of the following values:
+ PUSH_LOCAL: Bind DECL in the current scope, rather than at
+ namespace scope.
+ PUSH_USING: DECL is being pushed as the result of a using
+ declaration.
+
The value returned may be a previous declaration if we guessed wrong
about what language DECL should belong to (C or C++). Otherwise,
it's always DECL (and never something that's not a _DECL). */
! tree
! push_overloaded_decl (decl, flags)
tree decl;
! int flags;
{
tree name = DECL_NAME (decl);
tree old;
tree new_binding;
! int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL));
if (doing_global)
{
*************** push_overloaded_decl (decl, forgettable)
*** 4202,4210 ****
tree tmp;
for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
! if (decl == OVL_CURRENT (tmp)
! || duplicate_decls (decl, OVL_CURRENT (tmp)))
! return OVL_CURRENT (tmp);
}
else
{
--- 4211,4229 ----
tree tmp;
for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
! {
! tree fn = OVL_CURRENT (tmp);
!
! if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp)
! && !(flags & PUSH_USING)
! && compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
! TYPE_ARG_TYPES (TREE_TYPE (decl))))
! cp_error ("`%#D' conflicts with previous using declaration `%#D'",
! decl, fn);
!
! if (duplicate_decls (decl, fn))
! return fn;
! }
}
else
{
*************** static void
*** 5776,5782 ****
push_overloaded_decl_1 (x)
tree x;
{
! push_overloaded_decl (x, 0);
}
#ifdef __GNUC__
--- 5795,5801 ----
push_overloaded_decl_1 (x)
tree x;
{
! push_overloaded_decl (x, PUSH_GLOBAL);
}
#ifdef __GNUC__
Index: decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.172
diff -c -p -r1.172 decl2.c
*** decl2.c 1999/01/18 12:49:19 1.172
--- decl2.c 1999/01/22 04:53:28
*************** validate_nonmember_using_decl (decl, sco
*** 4703,4708 ****
--- 4703,4718 ----
if (TREE_CODE (decl) == SCOPE_REF
&& TREE_OPERAND (decl, 0) == std_node)
{
+ if (namespace_bindings_p ()
+ && current_namespace == global_namespace)
+ /* There's no need for a using declaration at all, here,
+ since `std' is the same as `::'. We can't just pass this
+ on because we'll complain later about declaring something
+ in the same scope as a using declaration with the same
+ name. We return NULL_TREE which indicates to the caller
+ that there's no need to do any further processing. */
+ return NULL_TREE;
+
*scope = global_namespace;
*name = TREE_OPERAND (decl, 1);
}
*************** do_nonmember_using_decl (scope, name, ol
*** 4773,4789 ****
*newval = oldval;
for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp))
{
! /* Compare each new function with each old one.
! If the old function was also used, there is no conflict. */
for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
! if (OVL_CURRENT (tmp) == OVL_CURRENT (tmp1))
! break;
! else if (OVL_USED (tmp1))
! continue;
! else if (duplicate_decls (OVL_CURRENT (tmp), OVL_CURRENT (tmp1)))
! return;
! /* Duplicate use, ignore */
if (tmp1)
continue;
--- 4783,4819 ----
*newval = oldval;
for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp))
{
! tree new_fn = OVL_CURRENT (tmp);
!
! /* [namespace.udecl]
!
! If a function declaration in namespace scope or block
! scope has the same name and the same parameter types as a
! function introduced by a using declaration the program is
! ill-formed. */
for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
! {
! tree old_fn = OVL_CURRENT (tmp1);
! if (!OVL_USED (tmp1)
! && 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. */
! cp_error ("`%D' is already declared in this scope",
! name);
! break;
! }
! else if (duplicate_decls (new_fn, old_fn))
! /* We're re-using something we already used
! before. We don't need to add it again. */
! break;
! }
!
! /* If we broke out of the loop, there's no reason to add
! this function to the using declarations for this
! scope. */
if (tmp1)
continue;
*************** do_local_using_decl (decl)
*** 4856,4862 ****
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
if (newval)
! push_local_binding (name, newval);
if (newtype)
set_identifier_type_value (name, newtype);
}
--- 4886,4905 ----
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
if (newval)
! {
! if (is_overloaded_fn (newval))
! {
! tree fn;
!
! /* We only need to push declarations for those functions
! that were not already bound in the current level. */
! for (fn = newval; fn != oldval; fn = OVL_NEXT (fn))
! push_overloaded_decl (OVL_CURRENT (fn),
! PUSH_LOCAL | PUSH_USING);
! }
! else
! push_local_binding (name, newval);
! }
if (newtype)
set_identifier_type_value (name, newtype);
}
Index: tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.91
diff -c -p -r1.91 tree.c
*** tree.c 1999/01/21 14:29:32 1.91
--- tree.c 1999/01/22 04:53:37
*************** build_cplus_array_type_1 (elt_type, inde
*** 416,422 ****
saveable_obstack = &permanent_obstack;
}
! if (processing_template_decl)
{
t = make_node (ARRAY_TYPE);
TREE_TYPE (t) = elt_type;
--- 416,424 ----
saveable_obstack = &permanent_obstack;
}
! if (processing_template_decl
! || uses_template_parms (elt_type)
! || uses_template_parms (index_type))
{
t = make_node (ARRAY_TYPE);
TREE_TYPE (t) = elt_type;
More information about the Gcc-patches
mailing list