Commit 98ed9dae by Nathan Sidwell Committed by Nathan Sidwell

re PR c++/19497 (Invalid declaration in template diagnosed too late)

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.

From-SVN: r100757
parent cb6d4a9f
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
......
......@@ -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,
......
......@@ -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. */
......
......@@ -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))
......
......@@ -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;
......
......@@ -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"
......@@ -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. */
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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
......
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
......
// 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" }
};
// 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" }
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