-2004-12-29 Mark Mitchell <mark@codesourcery.com>
+2004-12-30 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (cp_declarator): Split "name" field into
+ qualifying_scope and unqualified_name.
+ * decl.c (get_scope_of_declarator): Adjust accordingly.
+ (grokdeclarator): Likewise.
+ * decl2.c (grokfield): Likewise, and adjust call to
+ do_class_using_decl.
+ * name-lookup.c (do_class_using_decl): Split "decl" into
+ "scope" and "name". Remove unnecessary code.
+ * name-lookup.h (do_class_using_decl): Adjust declaration.
+ * parser.c (make_id_declarator): Split "id" into qualifying_scope
+ and unqualified_name.
+ (cp_parser_using_declaration): Adjust call to do_class_using_decl.
+ (cp_parser_direct_declarator): Adjust to handle the fact that
+ cp_parser_declarator_id no longer returns a SCOPE_REF.
+ (cp_parser_direct_declarator): Likewise.
+ (cp_parser_declarator_id): Do not create a SCOPE_REF for qualified
+ names.
+ (cp_parser_member_declaration): Adjust call to make_id_declarator.
+ (cp_parser_check_declarator_template_parameters): Do not expect a
+ SCOPE_REF.
+
+ * decl.c (duplicate_decls): Call ggc_free on declarations we will
+ not be needing any longer.
PR c++/19190
* cvt.c (convert_to_void): Do not use STRIP_NOPs.
union {
/* For identifiers. */
struct {
- /* The name of the function -- an IDENTIFIER_NODE, BIT_NOT_EXPR,
- TEMPLATE_ID_EXPR, or SCOPE_REF. */
- tree name;
+ /* If non-NULL, the qualifiying scope (a NAMESPACE_DECL or
+ *_TYPE) for this identifier. */
+ tree qualifying_scope;
+ /* The unqualified name of the entity -- an IDENTIFIER_NODE,
+ BIT_NOT_EXPR, or TEMPLATE_ID_EXPR. */
+ tree unqualified_name;
/* If this is the name of a function, what kind of special
function (if any). */
special_function_kind sfk;
DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
}
+ /* The DECL_LANG_SPECIFIC information in OLDDECL will be replaced
+ with that from NEWDECL below. */
+ if (DECL_LANG_SPECIFIC (olddecl))
+ {
+ gcc_assert (DECL_LANG_SPECIFIC (olddecl)
+ != DECL_LANG_SPECIFIC (newdecl));
+ ggc_free (DECL_LANG_SPECIFIC (olddecl));
+ }
+
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
int function_size;
&& TREE_STATIC (olddecl))))
make_decl_rtl (olddecl);
+ /* The NEWDECL will no longer be needed. Because every out-of-class
+ declaration of a member results in a call to duplicate_decls,
+ freeing these nodes represents in a significant savings. */
+ ggc_free (newdecl);
+
return olddecl;
}
\f
/* If the declarator-id is a SCOPE_REF, the scope in which the
declaration occurs is the first operand. */
if (declarator
- && declarator->u.id.name
- && TREE_CODE (declarator->u.id.name) == SCOPE_REF)
- return TREE_OPERAND (declarator->u.id.name, 0);
+ && declarator->u.id.qualifying_scope)
+ return declarator->u.id.qualifying_scope;
/* Otherwise, the declarator is not a qualified name; the entity will
be declared in the current scope. */
case cdk_id:
{
- tree decl = id_declarator->u.id.name;
+ tree qualifying_scope = id_declarator->u.id.qualifying_scope;
+ tree decl = id_declarator->u.id.unqualified_name;
if (!decl)
break;
- if (TREE_CODE (decl) == SCOPE_REF)
+ if (qualifying_scope)
{
- tree qualifying_scope = TREE_OPERAND (decl, 0);
-
- /* It is valid to write:
-
- class C { void f(); };
- typedef C D;
- void D::f();
-
- The standard is not clear about whether `typedef const C D' is
- legal; as of 2002-09-15 the committee is considering
- that question. EDG 3.0 allows that syntax.
- Therefore, we do as well. */
- if (qualifying_scope && TYPE_P (qualifying_scope))
+ if (TYPE_P (qualifying_scope))
{
- ctype = TYPE_MAIN_VARIANT (qualifying_scope);
+ ctype = qualifying_scope;
if (innermost_code != cdk_function
&& current_class_type
&& !UNIQUELY_DERIVED_FROM_P (ctype,
{
error ("type %qT is not derived from type %qT",
ctype, current_class_type);
- ctype = NULL_TREE;
+ return error_mark_node;
}
- TREE_OPERAND (decl, 0) = ctype;
}
else if (TREE_CODE (qualifying_scope) == NAMESPACE_DECL)
in_namespace = qualifying_scope;
- decl = TREE_OPERAND (decl, 1);
}
if (TREE_CODE (decl) == BASELINK)
decl = BASELINK_FUNCTIONS (decl);
{
/* Avoid trying to get an operand off an identifier node. */
if (declarator->kind != cdk_id)
- tmp = declarator->declarator->u.id.name;
+ tmp = declarator->declarator->u.id.unqualified_name;
else
- tmp = declarator->u.id.name;
+ tmp = declarator->u.id.unqualified_name;
op = IDENTIFIER_OPNAME_P (tmp);
if (IDENTIFIER_TYPENAME_P (tmp))
{
unqualified_id = NULL_TREE;
else
{
- unqualified_id = id_declarator->u.id.name;
- if (TREE_CODE (unqualified_id) == SCOPE_REF)
- unqualified_id = TREE_OPERAND (unqualified_id, 1);
+ unqualified_id = id_declarator->u.id.unqualified_name;
if (TREE_CODE (unqualified_id) == BASELINK)
unqualified_id = BASELINK_FUNCTIONS (unqualified_id);
switch (TREE_CODE (unqualified_id))
/* If DECLARATOR is non-NULL, we know it is a cdk_id declarator;
otherwise, we would not have exited the loop above. */
if (declarator
- && TREE_CODE (declarator->u.id.name) == SCOPE_REF
- /* If the qualifying scope was invalid, it will have been set to
- NULL_TREE above. */
- && TREE_OPERAND (declarator->u.id.name, 0)
- && TYPE_P (TREE_OPERAND (declarator->u.id.name, 0)))
+ && declarator->u.id.qualifying_scope
+ && TYPE_P (declarator->u.id.qualifying_scope))
{
tree t;
- ctype = TREE_OPERAND (declarator->u.id.name, 0);
- if (TYPE_P (ctype))
- ctype = TYPE_MAIN_VARIANT (ctype);
+ ctype = declarator->u.id.qualifying_scope;
+ ctype = TYPE_MAIN_VARIANT (ctype);
t = ctype;
while (t != NULL_TREE && CLASS_TYPE_P (t))
{
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
- tree sname = TREE_OPERAND (declarator->u.id.name, 1);
+ tree sname = declarator->u.id.unqualified_name;
if (TREE_CODE (sname) == IDENTIFIER_NODE
&& NEW_DELETE_OPNAME_P (sname))
if (!declspecs->any_specifiers_p
&& declarator->kind == cdk_id
- && TREE_CODE (declarator->u.id.name) == SCOPE_REF
- && (TREE_CODE (TREE_OPERAND (declarator->u.id.name, 1))
- == IDENTIFIER_NODE))
+ && declarator->u.id.qualifying_scope
+ && TREE_CODE (declarator->u.id.unqualified_name) == IDENTIFIER_NODE)
/* Access declaration */
- return do_class_using_decl (declarator->u.id.name);
+ return do_class_using_decl (declarator->u.id.qualifying_scope,
+ declarator->u.id.unqualified_name);
if (init
&& TREE_CODE (init) == TREE_LIST
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ok);
}
+/* Process "using SCOPE::NAME" in a class scope. Return the
+ USING_DECL created. */
+
tree
-do_class_using_decl (tree decl)
+do_class_using_decl (tree scope, tree name)
{
- tree name, value, scope, type;
+ tree value, type;
- if (TREE_CODE (decl) != SCOPE_REF
- || !TREE_OPERAND (decl, 0)
- || !TYPE_P (TREE_OPERAND (decl, 0)))
+ if (!scope || !TYPE_P (scope))
{
error ("using-declaration for non-member at class scope");
return NULL_TREE;
}
- scope = TREE_OPERAND (decl, 0);
- name = TREE_OPERAND (decl, 1);
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
error ("using-declaration cannot name destructor");
return NULL_TREE;
}
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
- else if (TREE_CODE (name) == TEMPLATE_DECL)
- name = DECL_NAME (name);
- else if (BASELINK_P (name))
- {
- tree fns = BASELINK_FUNCTIONS (name);
- name = DECL_NAME (get_first_fn (fns));
- }
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
extern void do_namespace_alias (tree, tree);
extern void do_toplevel_using_decl (tree, tree, tree);
extern void do_local_using_decl (tree, tree, tree);
-extern tree do_class_using_decl (tree);
+extern tree do_class_using_decl (tree, tree);
extern void do_using_directive (tree);
extern tree lookup_arg_dependent (tree, tree, tree);
extern bool is_associated_namespace (tree, tree);
Other parts of the front end that need to create entities (like
VAR_DECLs or FUNCTION_DECLs) should do that directly. */
-static cp_declarator *make_id_declarator
- (tree);
static cp_declarator *make_call_declarator
(cp_declarator *, cp_parameter_declarator *, cp_cv_quals, tree);
static cp_declarator *make_array_declarator
return declarator;
}
-/* Make a declarator for a generalized identifier. */
+/* Make a declarator for a generalized identifier. If non-NULL, the
+ identifier is QUALIFYING_SCOPE::UNQUALIFIED_NAME; otherwise, it is
+ just UNQUALIFIED_NAME. */
-cp_declarator *
-make_id_declarator (tree id)
+static cp_declarator *
+make_id_declarator (tree qualifying_scope, tree unqualified_name)
{
cp_declarator *declarator;
+ /* It is valid to write:
+
+ class C { void f(); };
+ typedef C D;
+ void D::f();
+
+ The standard is not clear about whether `typedef const C D' is
+ legal; as of 2002-09-15 the committee is considering that
+ question. EDG 3.0 allows that syntax. Therefore, we do as
+ well. */
+ if (qualifying_scope && TYPE_P (qualifying_scope))
+ qualifying_scope = TYPE_MAIN_VARIANT (qualifying_scope);
+
declarator = make_declarator (cdk_id);
- declarator->u.id.name = id;
+ declarator->u.id.qualifying_scope = qualifying_scope;
+ declarator->u.id.unqualified_name = unqualified_name;
declarator->u.id.sfk = sfk_none;
return declarator;
if (at_class_scope_p ())
{
/* Create the USING_DECL. */
- decl = do_class_using_decl (build_nt (SCOPE_REF,
- parser->scope,
- identifier));
+ decl = do_class_using_decl (parser->scope, identifier);
/* Add it to the list of members in this class. */
finish_member_declaration (decl);
}
}
else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
{
- tree id;
+ tree qualifying_scope;
+ tree unqualified_name;
/* Parse a declarator-id */
if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
cp_parser_parse_tentatively (parser);
- id = cp_parser_declarator_id (parser);
+ unqualified_name = cp_parser_declarator_id (parser);
+ qualifying_scope = parser->scope;
if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
{
if (!cp_parser_parse_definitely (parser))
- id = error_mark_node;
- else if (TREE_CODE (id) != IDENTIFIER_NODE)
+ unqualified_name = error_mark_node;
+ else if (qualifying_scope
+ || (TREE_CODE (unqualified_name)
+ != IDENTIFIER_NODE))
{
cp_parser_error (parser, "expected unqualified-id");
- id = error_mark_node;
+ unqualified_name = error_mark_node;
}
}
- if (id == error_mark_node)
+ if (unqualified_name == error_mark_node)
{
declarator = cp_error_declarator;
break;
}
- if (TREE_CODE (id) == SCOPE_REF && at_namespace_scope_p ())
+ if (qualifying_scope && at_namespace_scope_p ()
+ && TREE_CODE (qualifying_scope) == TYPENAME_TYPE)
{
- tree scope = TREE_OPERAND (id, 0);
-
/* In the declaration of a member of a template class
outside of the class itself, the SCOPE will sometimes
be a TYPENAME_TYPE. For example, given:
`S<T>::R' not a type. However, if `S' is
specialized, then this `i' will not be used, so there
is no harm in resolving the types here. */
- if (TREE_CODE (scope) == TYPENAME_TYPE)
- {
- tree type;
-
- /* Resolve the TYPENAME_TYPE. */
- type = resolve_typename_type (scope,
- /*only_current_p=*/false);
- /* If that failed, the declarator is invalid. */
- if (type == error_mark_node)
- error ("%<%T::%D%> is not a type",
- TYPE_CONTEXT (scope),
- TYPE_IDENTIFIER (scope));
- /* Build a new DECLARATOR. */
- id = build_nt (SCOPE_REF, type, TREE_OPERAND (id, 1));
- }
+ tree type;
+
+ /* Resolve the TYPENAME_TYPE. */
+ type = resolve_typename_type (qualifying_scope,
+ /*only_current_p=*/false);
+ /* If that failed, the declarator is invalid. */
+ if (type == error_mark_node)
+ error ("%<%T::%D%> is not a type",
+ TYPE_CONTEXT (qualifying_scope),
+ TYPE_IDENTIFIER (qualifying_scope));
+ qualifying_scope = type;
}
- declarator = make_id_declarator (id);
- if (id)
+ declarator = make_id_declarator (qualifying_scope,
+ unqualified_name);
+ if (unqualified_name)
{
tree class_type;
- tree unqualified_name;
- if (TREE_CODE (id) == SCOPE_REF
- && CLASS_TYPE_P (TREE_OPERAND (id, 0)))
- {
- class_type = TREE_OPERAND (id, 0);
- unqualified_name = TREE_OPERAND (id, 1);
- }
+ if (qualifying_scope
+ && CLASS_TYPE_P (qualifying_scope))
+ class_type = qualifying_scope;
else
- {
- class_type = current_class_type;
- unqualified_name = id;
- }
+ class_type = current_class_type;
if (class_type)
{
if (ctor_dtor_or_conv_p && declarator->u.id.sfk != sfk_none)
*ctor_dtor_or_conv_p = -1;
- if (TREE_CODE (id) == SCOPE_REF
+ if (qualifying_scope
&& TREE_CODE (unqualified_name) == TYPE_DECL
&& CLASSTYPE_USE_TEMPLATE (TREE_TYPE (unqualified_name)))
{
static tree
cp_parser_declarator_id (cp_parser* parser)
{
- tree id_expression;
-
/* The expression must be an id-expression. Assume that qualified
names are the names of types so that:
int S<T>::R<T>::i = 3;
will work, too. */
- id_expression = cp_parser_id_expression (parser,
- /*template_keyword_p=*/false,
- /*check_dependency_p=*/false,
- /*template_p=*/NULL,
- /*declarator_p=*/true);
- /* If the name was qualified, create a SCOPE_REF to represent
- that. */
- if (parser->scope)
- {
- id_expression = build_nt (SCOPE_REF, parser->scope, id_expression);
- parser->scope = NULL_TREE;
- }
-
- return id_expression;
+ return cp_parser_id_expression (parser,
+ /*template_keyword_p=*/false,
+ /*check_dependency_p=*/false,
+ /*template_p=*/NULL,
+ /*declarator_p=*/true);
}
/* Parse a type-id.
/* Create the bitfield declaration. */
decl = grokbitfield (identifier
- ? make_id_declarator (identifier)
+ ? make_id_declarator (NULL_TREE,
+ identifier)
: NULL,
&decl_specifiers,
width);
switch (declarator->kind)
{
case cdk_id:
- if (TREE_CODE (declarator->u.id.name) == SCOPE_REF)
+ if (declarator->u.id.qualifying_scope)
{
tree scope;
tree member;
- scope = TREE_OPERAND (declarator->u.id.name, 0);
- member = TREE_OPERAND (declarator->u.id.name, 1);
+ scope = declarator->u.id.qualifying_scope;
+ member = declarator->u.id.unqualified_name;
while (scope && CLASS_TYPE_P (scope))
{
scope = TYPE_CONTEXT (scope);
}
}
-
- /* If the DECLARATOR has the form `X<y>' then it uses one
- additional level of template parameters. */
- if (TREE_CODE (declarator->u.id.name) == TEMPLATE_ID_EXPR)
+ else if (TREE_CODE (declarator->u.id.unqualified_name)
+ == TEMPLATE_ID_EXPR)
+ /* If the DECLARATOR has the form `X<y>' then it uses one
+ additional level of template parameters. */
++num_templates;
return cp_parser_check_template_parameters (parser,