summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2005-06-08 11:49:23 +0000
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2005-06-08 11:49:23 +0000
commit094fb0d899aee3cbc8219bb030398ab86ee9f726 (patch)
tree33d1230b127cd93152bb163e84c576691088bbac /gcc
parentf7d1c2eaa5f2ac6b0e3de2a2a03c7bbd47ab2a59 (diff)
downloadgcc-094fb0d899aee3cbc8219bb030398ab86ee9f726.tar.gz
cp:
PR c++/19497 * cp-tree.def (USING_DECL): Update documentation. * cp-tree.h (DECL_DEPENDENT_P): New. (USING_DECL_DECLS, USING_DECL_SCOPE): New. * class.c (handle_using_decl): Move most of the processing to ... * name-lookup.c (do_class_using_decl): ... here. Make stricter. (push_using_decl): Use USING_DECL_SCOPE. (cp_emit_debug_info_for_using): Make extern. * cxx-pretty-print.c (pp_cxx_statement) <USING_DECL case>: Adjust. * name-lookup.h (cp_emit_debug_info_for_using): Declare. * pt.c (tsubst_decl) <USING_DECL case>: Use do_class_using_decl when tsubsting. (tsubst_expr): Use USING_DECL_SCOPE. * search.c (lookup_field_1): Use DECL_DEPENDENT_P. * semantics.c (finish_member_declaration): Likewise. testsuite: PR c++/19497 * g++.dg/inherit/using5.C: New. * g++.dg/inherit/using6.C: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@100757 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog18
-rw-r--r--gcc/cp/class.c50
-rw-r--r--gcc/cp/cp-tree.def8
-rw-r--r--gcc/cp/cp-tree.h10
-rw-r--r--gcc/cp/cxx-pretty-print.c2
-rw-r--r--gcc/cp/name-lookup.c86
-rw-r--r--gcc/cp/name-lookup.h1
-rw-r--r--gcc/cp/pt.c26
-rw-r--r--gcc/cp/search.c5
-rw-r--r--gcc/cp/semantics.c2
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/inherit/using5.C17
-rw-r--r--gcc/testsuite/g++.dg/inherit/using6.C15
13 files changed, 163 insertions, 83 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c15f9b40433..f08a2c65803 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,21 @@
+2005-06-08 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/19497
+ * cp-tree.def (USING_DECL): Update documentation.
+ * cp-tree.h (DECL_DEPENDENT_P): New.
+ (USING_DECL_DECLS, USING_DECL_SCOPE): New.
+ * class.c (handle_using_decl): Move most of the processing to ...
+ * name-lookup.c (do_class_using_decl): ... here. Make stricter.
+ (push_using_decl): Use USING_DECL_SCOPE.
+ (cp_emit_debug_info_for_using): Make extern.
+ * cxx-pretty-print.c (pp_cxx_statement) <USING_DECL case>: Adjust.
+ * name-lookup.h (cp_emit_debug_info_for_using): Declare.
+ * pt.c (tsubst_decl) <USING_DECL case>: Use do_class_using_decl
+ when tsubsting.
+ (tsubst_expr): Use USING_DECL_SCOPE.
+ * search.c (lookup_field_1): Use DECL_DEPENDENT_P.
+ * semantics.c (finish_member_declaration): Likewise.
+
2005-06-08 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
PR c++/19894
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 8661931ac78..a790b561316 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1119,53 +1119,17 @@ alter_access (tree t, tree fdecl, tree access)
static void
handle_using_decl (tree using_decl, tree t)
{
- tree ctype = DECL_INITIAL (using_decl);
+ tree decl = USING_DECL_DECLS (using_decl);
tree name = DECL_NAME (using_decl);
tree access
= TREE_PRIVATE (using_decl) ? access_private_node
: TREE_PROTECTED (using_decl) ? access_protected_node
: access_public_node;
- tree fdecl, binfo;
tree flist = NULL_TREE;
tree old_value;
- if (ctype == error_mark_node)
- return;
-
- binfo = lookup_base (t, ctype, ba_any, NULL);
- if (! binfo)
- {
- location_t saved_loc = input_location;
-
- input_location = DECL_SOURCE_LOCATION (using_decl);
- error_not_base_type (ctype, t);
- input_location = saved_loc;
- return;
- }
-
- if (constructor_name_p (name, ctype))
- {
- cp_error_at ("%qD names constructor", using_decl);
- return;
- }
- if (constructor_name_p (name, t))
- {
- cp_error_at ("%qD invalid in %qT", using_decl, t);
- return;
- }
-
- fdecl = lookup_member (binfo, name, 0, false);
+ gcc_assert (!processing_template_decl && decl);
- if (!fdecl)
- {
- cp_error_at ("no members matching %qD in %q#T", using_decl, ctype);
- return;
- }
-
- if (BASELINK_P (fdecl))
- /* Ignore base type this came from. */
- fdecl = BASELINK_FUNCTIONS (fdecl);
-
old_value = lookup_member (t, name, /*protect=*/0, /*want_type=*/false);
if (old_value)
{
@@ -1177,9 +1141,11 @@ handle_using_decl (tree using_decl, tree t)
else
old_value = NULL_TREE;
}
-
- if (is_overloaded_fn (fdecl))
- flist = fdecl;
+
+ cp_emit_debug_info_for_using (decl, current_class_type);
+
+ if (is_overloaded_fn (decl))
+ flist = decl;
if (! old_value)
;
@@ -1211,7 +1177,7 @@ handle_using_decl (tree using_decl, tree t)
alter_access (t, OVL_CURRENT (flist), access);
}
else
- alter_access (t, fdecl, access);
+ alter_access (t, decl, access);
}
/* Run through the base classes of T, updating CANT_HAVE_CONST_CTOR_P,
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index aa0ea83b323..894b62db45c 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -197,10 +197,10 @@ DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm",
TYPE_NAME is an IDENTIFIER_NODE for `C', the member class template. */
DEFTREECODE (UNBOUND_CLASS_TEMPLATE, "unbound_class_template", tcc_type, 0)
-/* A using declaration. DECL_INITIAL contains the specified scope.
- This is not an alias, but is later expanded into multiple aliases.
- The decl will have a NULL_TYPE iff the scope is a dependent scope,
- otherwise it will have a void type. */
+/* A using declaration. USING_DECL_SCOPE contains the specified
+ scope. In a member using decl, unless DECL_DEPENDENT_P is true,
+ USING_DECL_DECLS contains the _DECL or OVERLOAD so named. This is
+ not an alias, but is later expanded into multiple aliases. */
DEFTREECODE (USING_DECL, "using_decl", tcc_declaration, 0)
/* A using directive. The operand is USING_STMT_NAMESPACE. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 90de20c1e63..bb234bb5e13 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -93,6 +93,7 @@ struct diagnostic_context;
DECL_TEMPLATE_PARM_P (in PARM_DECL, CONST_DECL, TYPE_DECL, or TEMPLATE_DECL)
DECL_LOCAL_FUNCTION_P (in FUNCTION_DECL)
DECL_MUTABLE_P (in FIELD_DECL)
+ DECL_DEPENDENT_P (in USING_DECL)
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
DECL_MEMBER_TEMPLATE_P (in TEMPLATE_DECL)
@@ -2039,6 +2040,15 @@ struct lang_decl GTY(())
directives */
#define TREE_INDIRECT_USING(NODE) (TREE_LIST_CHECK (NODE)->common.lang_flag_0)
+/* Non zero if this is a using decl for a dependent scope. */
+#define DECL_DEPENDENT_P(NODE) DECL_LANG_FLAG_0 (USING_DECL_CHECK (NODE))
+
+/* The scope named in a using decl. */
+#define USING_DECL_SCOPE(NODE) TREE_TYPE (USING_DECL_CHECK (NODE))
+
+/* The decls named by a using decl. */
+#define USING_DECL_DECLS(NODE) DECL_INITIAL (USING_DECL_CHECK (NODE))
+
/* In a VAR_DECL for a variable declared in a for statement,
this is the shadowed (local) variable. */
#define DECL_SHADOWED_FOR_VAR(NODE) DECL_RESULT_FLD(VAR_DECL_CHECK (NODE))
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index afa969f9f71..42435d026bc 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -1519,7 +1519,7 @@ pp_cxx_statement (cxx_pretty_printer *pp, tree t)
case USING_DECL:
pp_cxx_identifier (pp, "using");
- pp_cxx_nested_name_specifier (pp, DECL_INITIAL (t));
+ pp_cxx_nested_name_specifier (pp, USING_DECL_SCOPE (t));
pp_cxx_unqualified_id (pp, DECL_NAME (t));
break;
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 3197a41077d..7a878f68ec4 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -51,7 +51,6 @@ static bool qualified_lookup_using_namespace (tree, tree,
struct scope_binding *, int);
static tree lookup_type_current_level (tree);
static tree push_using_directive (tree);
-static void cp_emit_debug_info_for_using (tree, tree);
/* The :: namespace. */
@@ -1779,13 +1778,13 @@ push_using_decl (tree scope, tree name)
gcc_assert (TREE_CODE (scope) == NAMESPACE_DECL);
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl))
- if (DECL_INITIAL (decl) == scope && DECL_NAME (decl) == name)
+ if (USING_DECL_SCOPE (decl) == scope && DECL_NAME (decl) == name)
break;
if (decl)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
namespace_bindings_p () ? decl : NULL_TREE);
- decl = build_lang_decl (USING_DECL, name, void_type_node);
- DECL_INITIAL (decl) = scope;
+ decl = build_lang_decl (USING_DECL, name, NULL_TREE);
+ USING_DECL_SCOPE (decl) = scope;
TREE_CHAIN (decl) = current_binding_level->usings;
current_binding_level->usings = decl;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
@@ -2691,35 +2690,80 @@ push_class_level_binding (tree name, tree x)
tree
do_class_using_decl (tree scope, tree name)
{
- tree value, type;
+ tree value, decl, binfo;
+ base_kind b_kind;
+ bool dependent_p;
if (!scope || !TYPE_P (scope))
{
error ("using-declaration for non-member at class scope");
return NULL_TREE;
}
+
+ /* Make sure the scope is a base. */
+ dependent_p = dependent_type_p (scope);
+ if (!dependent_p)
+ binfo = lookup_base (current_class_type, scope, ba_any, &b_kind);
+ else
+ {
+ binfo = NULL;
+ if (same_type_p (current_class_type, scope))
+ b_kind = bk_same_type;
+ else
+ b_kind = bk_proper_base;
+ }
+
+ if (b_kind < bk_proper_base)
+ {
+ error_not_base_type (scope, current_class_type);
+ return NULL_TREE;
+ }
+
+ /* Make sure the name is not invalid */
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
- error ("using-declaration cannot name destructor");
+ error ("%<%T::%D%> names destructor", scope, name);
+ return NULL_TREE;
+ }
+ if (constructor_name_p (name, scope))
+ {
+ error ("%<%T::%D%> names constructor", scope, name);
+ return NULL_TREE;
+ }
+ if (constructor_name_p (name, current_class_type))
+ {
+ error ("%<%T::%D%> names constructor in %qT",
+ scope, name, current_class_type);
return NULL_TREE;
}
- gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
-
- /* Dependent using decls have a NULL type, non-dependent ones have a
- void type. */
- type = dependent_type_p (scope) ? NULL_TREE : void_type_node;
- value = build_lang_decl (USING_DECL, name, type);
- DECL_INITIAL (value) = scope;
+ if (!dependent_p
+ && IDENTIFIER_OPNAME_P (name) && dependent_type_p (TREE_TYPE (name)))
+ dependent_p = 1;
- if (scope && !processing_template_decl)
+ /* See if there are any members of the base. */
+ if (!dependent_p)
{
- tree r;
+ decl = lookup_member (binfo, name, 0, false);
+
+ if (!decl)
+ {
+ error ("no members matching %<%T::%D%> in %q#T", scope, name, scope);
+ return NULL_TREE;
+ }
+
+ if (BASELINK_P (decl))
+ /* Ignore base type this came from. */
+ decl = BASELINK_FUNCTIONS (decl);
+ }
+ else
+ decl = NULL_TREE;
+
+ value = build_lang_decl (USING_DECL, name, NULL_TREE);
+ USING_DECL_DECLS (value) = decl;
+ USING_DECL_SCOPE (value) = scope;
+ DECL_DEPENDENT_P (value) = dependent_p;
- r = lookup_qualified_name (scope, name, false, false);
- if (r && (DECL_P (r) || TREE_CODE (r) == OVERLOAD))
- cp_emit_debug_info_for_using (r, scope);
- }
return value;
}
@@ -4923,7 +4967,7 @@ pop_everything (void)
If input tree is overloaded fn then emit debug info for all
candidates. */
-static void
+void
cp_emit_debug_info_for_using (tree t, tree context)
{
/* Ignore this FUNCTION_DECL if it refers to a builtin declaration
@@ -4945,6 +4989,6 @@ cp_emit_debug_info_for_using (tree t, tree context)
for (t = OVL_CURRENT (t); t; t = OVL_NEXT (t))
if (TREE_CODE (t) != TEMPLATE_DECL)
(*debug_hooks->imported_module_or_decl) (t, context);
- }
+}
#include "gt-cp-name-lookup.h"
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index 19bcec0eba6..70c12a219f5 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -341,6 +341,7 @@ extern bool is_associated_namespace (tree, tree);
extern void parse_using_directive (tree, tree);
extern tree innermost_non_namespace_value (tree);
extern cxx_binding *outer_binding (tree, cxx_binding *, bool);
+extern void cp_emit_debug_info_for_using (tree, tree);
/* Set *DECL to the (non-hidden) declaration for ID at global scope,
if present and return true; otherwise return false. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 292dc0ae78b..8af0234f618 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6557,16 +6557,20 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
break;
case USING_DECL:
- {
- r = copy_node (t);
- /* It is not a dependent using decl any more. */
- TREE_TYPE (r) = void_type_node;
- DECL_INITIAL (r)
- = tsubst_copy (DECL_INITIAL (t), args, complain, in_decl);
- DECL_NAME (r)
- = tsubst_copy (DECL_NAME (t), args, complain, in_decl);
- TREE_CHAIN (r) = NULL_TREE;
- }
+ /* We reach here only for member using decls. */
+ if (DECL_DEPENDENT_P (t))
+ {
+ r = do_class_using_decl
+ (tsubst_copy (USING_DECL_SCOPE (t), args, complain, in_decl),
+ tsubst_copy (DECL_NAME (t), args, complain, in_decl));
+ if (!r)
+ r = error_mark_node;
+ }
+ else
+ {
+ r = copy_node (t);
+ TREE_CHAIN (r) = NULL_TREE;
+ }
break;
case TYPE_DECL:
@@ -8085,7 +8089,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
finish_label_decl (DECL_NAME (decl));
else if (TREE_CODE (decl) == USING_DECL)
{
- tree scope = DECL_INITIAL (decl);
+ tree scope = USING_DECL_SCOPE (decl);
tree name = DECL_NAME (decl);
tree decl;
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 45668a14a94..8dec18e7743 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -471,9 +471,8 @@ lookup_field_1 (tree type, tree name, bool want_type)
defined, USING_DECLs are purged from TYPE_FIELDS; see
handle_using_decl. However, we make special efforts to
make using-declarations in class templates and class
- template partial specializations work correctly noticing
- that dependent USING_DECL's do not have TREE_TYPE set. */
- if (TREE_TYPE (field))
+ template partial specializations work correctly. */
+ if (!DECL_DEPENDENT_P (field))
continue;
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 76464ad626a..298979b38e3 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2259,7 +2259,7 @@ finish_member_declaration (tree decl)
/*friend_p=*/0);
}
/* Enter the DECL into the scope of the class. */
- else if ((TREE_CODE (decl) == USING_DECL && TREE_TYPE (decl))
+ else if ((TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl))
|| pushdecl_class_level (decl))
{
/* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 05aa1b4f33c..8ac9bf504a2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2005-06-08 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/19497
+ * g++.dg/inherit/using5.C: New.
+ * g++.dg/inherit/using6.C: New.
+
2005-06-08 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
PR c++/19894
diff --git a/gcc/testsuite/g++.dg/inherit/using5.C b/gcc/testsuite/g++.dg/inherit/using5.C
new file mode 100644
index 00000000000..896c2d461de
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/using5.C
@@ -0,0 +1,17 @@
+// Copyright (C) 2005 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 8 Jun 2005 <nathan@codesourcery.com>
+
+// PR 19496: Missing error during parsing.
+// Origin: Volker Reichelt <reichelt@gcc.gnu.org>
+
+template<int> struct A
+{
+ A::A; // { dg-error "not a base" }
+};
+
+struct B
+{
+ void f ();
+ using B::f; // { dg-error "not a base" }
+};
+
diff --git a/gcc/testsuite/g++.dg/inherit/using6.C b/gcc/testsuite/g++.dg/inherit/using6.C
new file mode 100644
index 00000000000..46c23ce582e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/using6.C
@@ -0,0 +1,15 @@
+// Copyright (C) 2005 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 8 Jun 2005 <nathan@codesourcery.com>
+
+struct A
+{
+ operator int ();
+};
+
+template <typename T> struct TPL : A
+{
+ using A::operator T; // { dg-error "operator float" }
+};
+
+TPL<int> i;
+TPL<float> j; // { dg-error "instantiated" }