Commit 7bdbfa05 by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (PUSH_GLOBAL): New macro.

	* 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.

From-SVN: r24812
parent 15914757
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.
1999-01-21 Jason Merrill <jason@yorick.cygnus.com> 1999-01-21 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (grokdeclarator): Fix lang_c -> lang_name_c typo. * decl.c (grokdeclarator): Fix lang_c -> lang_name_c typo.
1999-01-21 Mark Mitchell <mark@markmitchell.com> 1999-01-21 Mark Mitchell <mark@markmitchell.com>
* tree.c (build_cplus_array_type_1): Don't call build_array_type
for types involving template parameters.
* cp-tree.h (PARM_DECL_EXPR): Delete. * cp-tree.h (PARM_DECL_EXPR): Delete.
(convert_default_arg): Change prototype. (convert_default_arg): Change prototype.
(check_default_argument): Declare. (check_default_argument): Declare.
......
...@@ -2582,6 +2582,14 @@ extern tree current_class_name; /* IDENTIFIER_NODE: name of current class */ ...@@ -2582,6 +2582,14 @@ extern tree current_class_name; /* IDENTIFIER_NODE: name of current class */
another declaration of an existing another declaration of an existing
entity is seen. */ 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 /* Returns nonzero iff TYPE1 and TYPE2 are the same type, in the usual
sense of `same'. */ sense of `same'. */
#define same_type_p(type1, type2) \ #define same_type_p(type1, type2) \
...@@ -2692,6 +2700,7 @@ extern tree perform_qualification_conversions PROTO((tree, tree)); ...@@ -2692,6 +2700,7 @@ extern tree perform_qualification_conversions PROTO((tree, tree));
extern void set_identifier_local_value PROTO((tree, tree)); extern void set_identifier_local_value PROTO((tree, tree));
extern int global_bindings_p PROTO((void)); extern int global_bindings_p PROTO((void));
extern int toplevel_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 void keep_next_level PROTO((void));
extern int kept_level_p PROTO((void)); extern int kept_level_p PROTO((void));
extern void declare_parm_level PROTO((void)); extern void declare_parm_level PROTO((void));
...@@ -2816,6 +2825,7 @@ extern int check_static_variable_definition PROTO((tree, tree)); ...@@ -2816,6 +2825,7 @@ extern int check_static_variable_definition PROTO((tree, tree));
extern void push_local_binding PROTO((tree, tree)); extern void push_local_binding PROTO((tree, tree));
extern void push_class_binding PROTO((tree, tree)); extern void push_class_binding PROTO((tree, tree));
extern tree check_default_argument PROTO((tree, tree)); extern tree check_default_argument PROTO((tree, tree));
extern tree push_overloaded_decl PROTO((tree, int));
/* in decl2.c */ /* in decl2.c */
extern int check_java_method PROTO((tree)); extern int check_java_method PROTO((tree));
......
...@@ -135,7 +135,6 @@ static struct stack_level *decl_stack; ...@@ -135,7 +135,6 @@ static struct stack_level *decl_stack;
static tree grokparms PROTO((tree, int)); static tree grokparms PROTO((tree, int));
static tree lookup_nested_type PROTO((tree, tree)); static tree lookup_nested_type PROTO((tree, tree));
static char *redeclaration_error_message 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 *, static struct stack_level *push_decl_level PROTO((struct stack_level *,
struct obstack *)); struct obstack *));
...@@ -145,7 +144,6 @@ static void pop_binding_level PROTO((void)); ...@@ -145,7 +144,6 @@ static void pop_binding_level PROTO((void));
static void suspend_binding_level PROTO((void)); static void suspend_binding_level PROTO((void));
static void resume_binding_level PROTO((struct binding_level *)); static void resume_binding_level PROTO((struct binding_level *));
static struct binding_level *make_binding_level PROTO((void)); 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 declare_namespace_level PROTO((void));
static void signal_catch PROTO((int)) ATTRIBUTE_NORETURN; static void signal_catch PROTO((int)) ATTRIBUTE_NORETURN;
static void storedecls PROTO((tree)); static void storedecls PROTO((tree));
...@@ -922,7 +920,7 @@ toplevel_bindings_p () ...@@ -922,7 +920,7 @@ toplevel_bindings_p ()
/* Nonzero if this is a namespace scope. */ /* Nonzero if this is a namespace scope. */
static int int
namespace_bindings_p () namespace_bindings_p ()
{ {
return current_binding_level->namespace_p; return current_binding_level->namespace_p;
...@@ -2942,6 +2940,11 @@ duplicate_decls (newdecl, olddecl) ...@@ -2942,6 +2940,11 @@ duplicate_decls (newdecl, olddecl)
} }
else if (!types_match) 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) if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{ {
/* The name of a class template may not be declared to refer to /* The name of a class template may not be declared to refer to
...@@ -3655,7 +3658,7 @@ pushdecl (x) ...@@ -3655,7 +3658,7 @@ pushdecl (x)
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x)) if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
{ {
t = push_overloaded_decl (x, 1); t = push_overloaded_decl (x, PUSH_LOCAL);
if (t != x || DECL_LANGUAGE (x) == lang_c) if (t != x || DECL_LANGUAGE (x) == lang_c)
return t; return t;
if (!namespace_bindings_p ()) if (!namespace_bindings_p ())
...@@ -3665,7 +3668,7 @@ pushdecl (x) ...@@ -3665,7 +3668,7 @@ pushdecl (x)
need_new_binding = 0; need_new_binding = 0;
} }
else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x)) else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
return push_overloaded_decl (x, 0); return push_overloaded_decl (x, PUSH_GLOBAL);
/* If declaring a type as a typedef, copy the type (unless we're /* 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 at line 0), and install this TYPE_DECL as the new type's typedef
...@@ -4157,19 +4160,25 @@ push_using_directive (used) ...@@ -4157,19 +4160,25 @@ push_using_directive (used)
DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT
slot. It is dealt with the same way. 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 The value returned may be a previous declaration if we guessed wrong
about what language DECL should belong to (C or C++). Otherwise, about what language DECL should belong to (C or C++). Otherwise,
it's always DECL (and never something that's not a _DECL). */ it's always DECL (and never something that's not a _DECL). */
static tree tree
push_overloaded_decl (decl, forgettable) push_overloaded_decl (decl, flags)
tree decl; tree decl;
int forgettable; int flags;
{ {
tree name = DECL_NAME (decl); tree name = DECL_NAME (decl);
tree old; tree old;
tree new_binding; tree new_binding;
int doing_global = (namespace_bindings_p () || ! forgettable); int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL));
if (doing_global) if (doing_global)
{ {
...@@ -4202,9 +4211,19 @@ push_overloaded_decl (decl, forgettable) ...@@ -4202,9 +4211,19 @@ push_overloaded_decl (decl, forgettable)
tree tmp; tree tmp;
for (tmp = old; tmp; tmp = OVL_NEXT (tmp)) for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
if (decl == OVL_CURRENT (tmp) {
|| duplicate_decls (decl, OVL_CURRENT (tmp))) tree fn = OVL_CURRENT (tmp);
return 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 else
{ {
...@@ -5776,7 +5795,7 @@ static void ...@@ -5776,7 +5795,7 @@ static void
push_overloaded_decl_1 (x) push_overloaded_decl_1 (x)
tree x; tree x;
{ {
push_overloaded_decl (x, 0); push_overloaded_decl (x, PUSH_GLOBAL);
} }
#ifdef __GNUC__ #ifdef __GNUC__
......
...@@ -4703,6 +4703,16 @@ validate_nonmember_using_decl (decl, scope, name) ...@@ -4703,6 +4703,16 @@ validate_nonmember_using_decl (decl, scope, name)
if (TREE_CODE (decl) == SCOPE_REF if (TREE_CODE (decl) == SCOPE_REF
&& TREE_OPERAND (decl, 0) == std_node) && 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; *scope = global_namespace;
*name = TREE_OPERAND (decl, 1); *name = TREE_OPERAND (decl, 1);
} }
...@@ -4773,17 +4783,37 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype) ...@@ -4773,17 +4783,37 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
*newval = oldval; *newval = oldval;
for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp)) for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp))
{ {
/* Compare each new function with each old one. tree new_fn = OVL_CURRENT (tmp);
If the old function was also used, there is no conflict. */
/* [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)) for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
if (OVL_CURRENT (tmp) == OVL_CURRENT (tmp1)) {
break; tree old_fn = OVL_CURRENT (tmp1);
else if (OVL_USED (tmp1))
continue;
else if (duplicate_decls (OVL_CURRENT (tmp), OVL_CURRENT (tmp1)))
return;
/* Duplicate use, ignore */ 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) if (tmp1)
continue; continue;
...@@ -4856,7 +4886,20 @@ do_local_using_decl (decl) ...@@ -4856,7 +4886,20 @@ do_local_using_decl (decl)
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype); do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
if (newval) if (newval)
push_local_binding (name, 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) if (newtype)
set_identifier_type_value (name, newtype); set_identifier_type_value (name, newtype);
} }
......
...@@ -416,7 +416,9 @@ build_cplus_array_type_1 (elt_type, index_type) ...@@ -416,7 +416,9 @@ build_cplus_array_type_1 (elt_type, index_type)
saveable_obstack = &permanent_obstack; saveable_obstack = &permanent_obstack;
} }
if (processing_template_decl) if (processing_template_decl
|| uses_template_parms (elt_type)
|| uses_template_parms (index_type))
{ {
t = make_node (ARRAY_TYPE); t = make_node (ARRAY_TYPE);
TREE_TYPE (t) = elt_type; TREE_TYPE (t) = elt_type;
......
// Build don't link: // Build don't link:
namespace A{ namespace A{
void f(); // ERROR - .* void f();
} }
using A::f; using A::f;
......
// Build don't link: // Build don't link:
namespace A{ namespace A{
void f(){} // ERROR - previous declaration void f(){}
} }
using A::f; using A::f;
......
// 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
}
// 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;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment