diff options
author | Jason Merrill <jason@yorick.cygnus.com> | 1998-08-20 17:41:43 +0000 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 1998-08-20 13:41:43 -0400 |
commit | 50a6dbd707c86a270efa591413e9c944b470741e (patch) | |
tree | 170ce25cb6bd3fd7d83f00c25549721f52ebfc12 /gcc | |
parent | a604b0f1db0ee1c21b28be926918d6b05b8fc1ca (diff) | |
download | gcc-50a6dbd707c86a270efa591413e9c944b470741e.zip gcc-50a6dbd707c86a270efa591413e9c944b470741e.tar.gz gcc-50a6dbd707c86a270efa591413e9c944b470741e.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/decl.c | 65 | ||||
-rw-r--r-- | gcc/cp/method.c | 5 | ||||
-rw-r--r-- | gcc/cp/pt.c | 26 | ||||
-rw-r--r-- | gcc/cp/tree.c | 246 |
6 files changed, 339 insertions, 13 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5b8c014..c5f938b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f96af15..b567b95 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index ad3585b..251cbef 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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) diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 7084810..51ee80c 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -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); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 73b00c7..b0202b1 100644 --- a/gcc/cp/pt.c +++ b/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)) diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 44d36b9..13d8a08 100644 --- a/gcc/cp/tree.c +++ b/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 |