diff options
author | Mark Mitchell <mark@markmitchell.com> | 1999-01-21 21:16:22 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1999-01-21 21:16:22 +0000 |
commit | 7bdbfa05dba783697d330f283a8427002667408f (patch) | |
tree | e6f14953b9b72129c669c461010c89a23823f94b | |
parent | 15914757c6d0717225a6d87035cb524fb06c5ac9 (diff) | |
download | gcc-7bdbfa05dba783697d330f283a8427002667408f.tar.gz |
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
-rw-r--r-- | gcc/cp/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 10 | ||||
-rw-r--r-- | gcc/cp/decl.c | 45 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 63 | ||||
-rw-r--r-- | gcc/cp/tree.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.ns/overload4.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.ns/overload5.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.ns/using12.C | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/array3.C | 5 |
9 files changed, 147 insertions, 26 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6db2122751f..280d14db9ad 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,9 +1,32 @@ +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> * decl.c (grokdeclarator): Fix lang_c -> lang_name_c typo. 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. (convert_default_arg): Change prototype. (check_default_argument): Declare. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 7dc06ff2edb..e26a910cc67 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2582,6 +2582,14 @@ extern tree current_class_name; /* IDENTIFIER_NODE: name of current class */ 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) \ @@ -2692,6 +2700,7 @@ extern tree perform_qualification_conversions PROTO((tree, tree)); 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)); @@ -2816,6 +2825,7 @@ extern int check_static_variable_definition PROTO((tree, tree)); 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)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 20b53743d87..39e07a4ba6e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -135,7 +135,6 @@ static struct stack_level *decl_stack; 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 *)); @@ -145,7 +144,6 @@ static void pop_binding_level PROTO((void)); 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)); @@ -922,7 +920,7 @@ toplevel_bindings_p () /* Nonzero if this is a namespace scope. */ -static int +int namespace_bindings_p () { return current_binding_level->namespace_p; @@ -2942,6 +2940,11 @@ duplicate_decls (newdecl, olddecl) } 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 @@ -3655,7 +3658,7 @@ pushdecl (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) return t; if (!namespace_bindings_p ()) @@ -3665,7 +3668,7 @@ pushdecl (x) need_new_binding = 0; } 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 at line 0), and install this TYPE_DECL as the new type's typedef @@ -4157,19 +4160,25 @@ push_using_directive (used) 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). */ -static tree -push_overloaded_decl (decl, forgettable) +tree +push_overloaded_decl (decl, flags) tree decl; - int forgettable; + int flags; { tree name = DECL_NAME (decl); tree old; tree new_binding; - int doing_global = (namespace_bindings_p () || ! forgettable); + int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL)); if (doing_global) { @@ -4202,9 +4211,19 @@ push_overloaded_decl (decl, forgettable) 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); + { + 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 { @@ -5776,7 +5795,7 @@ static void push_overloaded_decl_1 (x) tree x; { - push_overloaded_decl (x, 0); + push_overloaded_decl (x, PUSH_GLOBAL); } #ifdef __GNUC__ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 303364453a7..ed9c11b3824 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -4703,6 +4703,16 @@ validate_nonmember_using_decl (decl, scope, name) 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); } @@ -4773,17 +4783,37 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype) *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. */ + 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)) - 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; + { + tree old_fn = OVL_CURRENT (tmp1); - /* 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) continue; @@ -4856,7 +4886,20 @@ do_local_using_decl (decl) do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype); 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) set_identifier_type_value (name, newtype); } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 65ae47a7f63..656cc52d036 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -416,7 +416,9 @@ build_cplus_array_type_1 (elt_type, index_type) 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); TREE_TYPE (t) = elt_type; diff --git a/gcc/testsuite/g++.old-deja/g++.ns/overload4.C b/gcc/testsuite/g++.old-deja/g++.ns/overload4.C index 24d0ced19a5..ad961576419 100644 --- a/gcc/testsuite/g++.old-deja/g++.ns/overload4.C +++ b/gcc/testsuite/g++.old-deja/g++.ns/overload4.C @@ -1,6 +1,6 @@ // Build don't link: namespace A{ - void f(); // ERROR - .* + void f(); } using A::f; diff --git a/gcc/testsuite/g++.old-deja/g++.ns/overload5.C b/gcc/testsuite/g++.old-deja/g++.ns/overload5.C index 210f3b0eb59..24a0a6df4da 100644 --- a/gcc/testsuite/g++.old-deja/g++.ns/overload5.C +++ b/gcc/testsuite/g++.old-deja/g++.ns/overload5.C @@ -1,6 +1,6 @@ // Build don't link: namespace A{ - void f(){} // ERROR - previous declaration + void f(){} } using A::f; diff --git a/gcc/testsuite/g++.old-deja/g++.ns/using12.C b/gcc/testsuite/g++.old-deja/g++.ns/using12.C new file mode 100644 index 00000000000..edc863b08bf --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.ns/using12.C @@ -0,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 +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/array3.C b/gcc/testsuite/g++.old-deja/g++.pt/array3.C new file mode 100644 index 00000000000..ec5e1e0e3a7 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/array3.C @@ -0,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; |