tree.c (search_tree, [...]): New fn.

* tree.c (search_tree, no_linkage_helper, no_linkage_check): New fn.
	* pt.c (coerce_template_parms): Use no_linkage_check.
	* decl.c (grokvardecl): Likewise.
	(grokfndecl): Likewise.  Members of anonymous types have no linkage.
	* method.c (process_overload_item): Remove useless code.

From-SVN: r21884
This commit is contained in:
Jason Merrill 1998-08-20 17:41:43 +00:00 committed by Jason Merrill
parent a604b0f1db
commit 50a6dbd707
6 changed files with 339 additions and 13 deletions

View File

@ -1,3 +1,12 @@
1998-08-20 Jason Merrill <jason@yorick.cygnus.com>
* tree.c (search_tree, no_linkage_helper, no_linkage_check): New fn.
* pt.c (coerce_template_parms): Use no_linkage_check.
* decl.c (grokvardecl): Likewise.
(grokfndecl): Likewise. Members of anonymous types have no linkage.
* method.c (process_overload_item): Remove useless code.
1998-08-20 Per Bothner <bothner@cygnus.com>
Handle new'ing of Java classes.

View File

@ -3042,6 +3042,7 @@ extern int really_overloaded_fn PROTO((tree));
extern int cp_tree_equal PROTO((tree, tree));
extern int can_free PROTO((struct obstack *, tree));
extern tree mapcar PROTO((tree, tree (*) (tree)));
extern tree no_linkage_check PROTO((tree));
extern void debug_binfo PROTO((tree));
extern void push_expression_obstack PROTO((void));
#define scratchalloc expralloc

View File

@ -6636,6 +6636,26 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
/* Corresponding pop_obstacks is done in `cp_finish_decl'. */
push_obstacks_nochange ();
/* [basic.link]: A name with no linkage (notably, the name of a class or
enumeration declared in a local scope) shall not be used to declare an
entity with linkage.
Only check this for public decls for now. */
if (TREE_PUBLIC (tem))
{
tree t = no_linkage_check (TREE_TYPE (tem));
if (t)
{
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
{
if (TREE_CODE (tem) == FUNCTION_DECL)
cp_pedwarn ("public decl `%#D' uses anonymous type", tem);
}
else
cp_pedwarn ("non-local decl `%#D' uses local type `%T'", tem, t);
}
}
#if 0
/* We have no way of knowing whether the initializer will need to be
evaluated at run-time or not until we've parsed it, so let's just put
@ -7897,7 +7917,28 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
inlinep = 0;
publicp = 1;
}
/* Members of anonymous types have no linkage; make them internal. */
if (ctype && ANON_AGGRNAME_P (TYPE_IDENTIFIER (ctype)))
publicp = 0;
if (publicp)
{
/* [basic.link]: A name with no linkage (notably, the name of a class
or enumeration declared in a local scope) shall not be used to
declare an entity with linkage.
Only check this for public decls for now. */
t = no_linkage_check (TREE_TYPE (decl));
if (t)
{
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
cp_pedwarn ("function `%#D' uses anonymous type", decl);
else
cp_pedwarn ("function `%#D' uses local type `%T'", decl, t);
}
}
TREE_PUBLIC (decl) = publicp;
if (! publicp)
{
@ -8157,6 +8198,25 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
TREE_STATIC (decl) = !! RIDBIT_SETP (RID_STATIC, specbits);
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
}
if (TREE_PUBLIC (decl))
{
/* [basic.link]: A name with no linkage (notably, the name of a class
or enumeration declared in a local scope) shall not be used to
declare an entity with linkage.
Only check this for public decls for now. */
tree t = no_linkage_check (TREE_TYPE (decl));
if (t)
{
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
/* Ignore for now; `enum { foo } e' is pretty common. */;
else
cp_pedwarn ("non-local variable `%#D' uses local type `%T'",
decl, t);
}
}
return decl;
}
@ -9991,6 +10051,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
DECL_ASSEMBLER_NAME (decl)
= get_identifier (build_overload_name (type, 1, 1));
DECL_CONTEXT (decl) = NULL_TREE;
/* FIXME remangle member functions; member functions of a
type with external linkage have external linkage. */
}
if (TREE_CODE (type) == OFFSET_TYPE || TREE_CODE (type) == METHOD_TYPE)

View File

@ -1411,11 +1411,6 @@ process_overload_item (parmtype, extra_Gcode)
{
tree name = TYPE_NAME (parmtype);
if (TREE_CODE (name) == IDENTIFIER_NODE)
{
build_overload_identifier (TYPE_NAME (parmtype));
break;
}
my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 248);
build_qualified_name (name);

View File

@ -2832,13 +2832,21 @@ coerce_template_parms (parms, arglist, in_decl,
val = groktypename (arg);
if (! processing_template_decl)
{
tree t = target_type (val);
if (((IS_AGGR_TYPE (t) && TREE_CODE (t) != TYPENAME_TYPE)
|| TREE_CODE (t) == ENUMERAL_TYPE)
&& decl_function_context (TYPE_MAIN_DECL (t)))
/* [basic.link]: A name with no linkage (notably, the
name of a class or enumeration declared in a local
scope) shall not be used to declare an entity with
linkage. This implies that names with no linkage
cannot be used as template arguments. */
tree t = no_linkage_check (val);
if (t)
{
cp_error ("type `%T' composed from a local type is not a valid template-argument",
val);
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
cp_pedwarn
("template-argument `%T' uses anonymous type", val);
else
cp_error
("template-argument `%T' uses local type `%T'",
val, t);
return error_mark_node;
}
}
@ -3435,7 +3443,11 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
{
DECL_ASSEMBLER_NAME (type_decl)
= get_identifier (build_overload_name (t, 1, 1));
/* For backwards compatibility; code that uses
-fexternal-templates expects looking up a template to
instantiate it. I think DDD still relies on this.
(jason 8/20/1998) */
if (TREE_CODE (t) != ENUMERAL_TYPE
&& flag_external_templates
&& CLASSTYPE_INTERFACE_KNOWN (TREE_TYPE (template))

View File

@ -1557,6 +1557,252 @@ copy_template_template_parm (t)
return t2;
}
/* Walk through the tree structure T, applying func. If func ever returns
non-null, return that value. */
static tree
search_tree (t, func)
tree t;
tree (*func) PROTO((tree));
{
#define TRY(ARG) if (tmp = walk_tree (ARG, func), tmp != NULL_TREE) return tmp
tree tmp;
if (t == NULL_TREE)
return t;
if (tmp = func (t), tmp != NULL_TREE)
return tmp;
switch (TREE_CODE (t))
{
case ERROR_MARK:
break;
case IDENTIFIER_NODE:
break;
case VAR_DECL:
case FUNCTION_DECL:
case CONST_DECL:
case TEMPLATE_DECL:
case NAMESPACE_DECL:
break;
case TYPE_DECL:
TRY (TREE_TYPE (t));
break;
case PARM_DECL:
TRY (TREE_TYPE (t));
TRY (TREE_CHAIN (t));
break;
case TREE_LIST:
TRY (TREE_PURPOSE (t));
TRY (TREE_VALUE (t));
TRY (TREE_CHAIN (t));
break;
case OVERLOAD:
TRY (OVL_FUNCTION (t));
TRY (OVL_CHAIN (t));
break;
case TREE_VEC:
{
int len = TREE_VEC_LENGTH (t);
t = copy_node (t);
while (len--)
TRY (TREE_VEC_ELT (t, len));
}
break;
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
case DEFAULT_ARG:
break;
case COND_EXPR:
case TARGET_EXPR:
case AGGR_INIT_EXPR:
case NEW_EXPR:
TRY (TREE_OPERAND (t, 0));
TRY (TREE_OPERAND (t, 1));
TRY (TREE_OPERAND (t, 2));
break;
case MODIFY_EXPR:
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
case TRUNC_DIV_EXPR:
case TRUNC_MOD_EXPR:
case MIN_EXPR:
case MAX_EXPR:
case LSHIFT_EXPR:
case RSHIFT_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
case BIT_AND_EXPR:
case BIT_ANDTC_EXPR:
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
case LT_EXPR:
case LE_EXPR:
case GT_EXPR:
case GE_EXPR:
case EQ_EXPR:
case NE_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case CEIL_MOD_EXPR:
case FLOOR_MOD_EXPR:
case ROUND_MOD_EXPR:
case COMPOUND_EXPR:
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
case ARRAY_REF:
case SCOPE_REF:
case TRY_CATCH_EXPR:
case WITH_CLEANUP_EXPR:
case CALL_EXPR:
TRY (TREE_OPERAND (t, 0));
TRY (TREE_OPERAND (t, 1));
break;
case SAVE_EXPR:
case CONVERT_EXPR:
case ADDR_EXPR:
case INDIRECT_REF:
case NEGATE_EXPR:
case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR:
case NOP_EXPR:
case NON_LVALUE_EXPR:
case COMPONENT_REF:
case CLEANUP_POINT_EXPR:
case LOOKUP_EXPR:
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
TRY (TREE_OPERAND (t, 0));
break;
case MODOP_EXPR:
case CAST_EXPR:
case REINTERPRET_CAST_EXPR:
case CONST_CAST_EXPR:
case STATIC_CAST_EXPR:
case DYNAMIC_CAST_EXPR:
case ARROW_EXPR:
case DOTSTAR_EXPR:
case TYPEID_EXPR:
break;
case COMPLEX_CST:
TRY (TREE_REALPART (t));
TRY (TREE_IMAGPART (t));
break;
case CONSTRUCTOR:
TRY (CONSTRUCTOR_ELTS (t));
break;
case TEMPLATE_TEMPLATE_PARM:
case TEMPLATE_PARM_INDEX:
case TEMPLATE_TYPE_PARM:
break;
case BIND_EXPR:
break;
case REAL_TYPE:
case COMPLEX_TYPE:
case VOID_TYPE:
case BOOLEAN_TYPE:
case TYPENAME_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
break;
case POINTER_TYPE:
case REFERENCE_TYPE:
TRY (TREE_TYPE (t));
break;
case FUNCTION_TYPE:
case METHOD_TYPE:
TRY (TREE_TYPE (t));
TRY (TYPE_ARG_TYPES (t));
break;
case ARRAY_TYPE:
TRY (TREE_TYPE (t));
TRY (TYPE_DOMAIN (t));
break;
case INTEGER_TYPE:
TRY (TYPE_MAX_VALUE (t));
break;
case OFFSET_TYPE:
TRY (TREE_TYPE (t));
TRY (TYPE_OFFSET_BASETYPE (t));
break;
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
TRY (TYPE_PTRMEMFUNC_FN_TYPE (t));
break;
/* This list is incomplete, but should suffice for now.
It is very important that `sorry' not call
`report_error_function'. That could cause an infinite loop. */
default:
sorry ("initializer contains unrecognized tree code");
return error_mark_node;
}
return NULL_TREE;
#undef TRY
}
/* Passed to search_tree. Checks for the use of types with no linkage. */
static tree
no_linkage_helper (t)
tree t;
{
if (TYPE_P (t)
&& (IS_AGGR_TYPE (t) || TREE_CODE (t) == ENUMERAL_TYPE)
&& (decl_function_context (TYPE_MAIN_DECL (t))
|| ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))))
return t;
return NULL_TREE;
}
/* Check if the type T depends on a type with no linkage and if so, return
it. */
tree
no_linkage_check (t)
tree t;
{
t = search_tree (t, no_linkage_helper);
if (t != error_mark_node)
return t;
return NULL_TREE;
}
/* Subroutine of copy_to_permanent
Assuming T is a node build bottom-up, make it all exist on