mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-12 02:14:55 +08:00
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:
parent
a604b0f1db
commit
50a6dbd707
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
26
gcc/cp/pt.c
26
gcc/cp/pt.c
@ -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))
|
||||
|
246
gcc/cp/tree.c
246
gcc/cp/tree.c
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user