aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@markmitchell.com>1999-01-21 21:16:22 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1999-01-21 21:16:22 +0000
commit7bdbfa05dba783697d330f283a8427002667408f (patch)
treee6f14953b9b72129c669c461010c89a23823f94b
parent15914757c6d0717225a6d87035cb524fb06c5ac9 (diff)
downloadgcc-7bdbfa05dba783697d330f283a8427002667408f.zip
gcc-7bdbfa05dba783697d330f283a8427002667408f.tar.gz
gcc-7bdbfa05dba783697d330f283a8427002667408f.tar.bz2
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/ChangeLog23
-rw-r--r--gcc/cp/cp-tree.h10
-rw-r--r--gcc/cp/decl.c45
-rw-r--r--gcc/cp/decl2.c63
-rw-r--r--gcc/cp/tree.c4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.ns/overload4.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.ns/overload5.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.ns/using12.C19
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/array3.C5
9 files changed, 147 insertions, 26 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6db2122..280d14d 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 7dc06ff..e26a910 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 20b5374..39e07a4 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 3033644..ed9c11b 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 65ae47a..656cc52 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 24d0ced..ad96157 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 210f3b0..24a0a6d 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 0000000..edc863b
--- /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 0000000..ec5e1e0
--- /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;