diff options
author | nathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-06-08 11:49:23 +0000 |
---|---|---|
committer | nathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-06-08 11:49:23 +0000 |
commit | 094fb0d899aee3cbc8219bb030398ab86ee9f726 (patch) | |
tree | 33d1230b127cd93152bb163e84c576691088bbac /gcc | |
parent | f7d1c2eaa5f2ac6b0e3de2a2a03c7bbd47ab2a59 (diff) | |
download | gcc-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/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/cp/class.c | 50 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 8 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 10 | ||||
-rw-r--r-- | gcc/cp/cxx-pretty-print.c | 2 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 86 | ||||
-rw-r--r-- | gcc/cp/name-lookup.h | 1 | ||||
-rw-r--r-- | gcc/cp/pt.c | 26 | ||||
-rw-r--r-- | gcc/cp/search.c | 5 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/inherit/using5.C | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/inherit/using6.C | 15 |
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" } |