aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@yorick.cygnus.com>1998-08-20 17:41:43 +0000
committerJason Merrill <jason@gcc.gnu.org>1998-08-20 13:41:43 -0400
commit50a6dbd707c86a270efa591413e9c944b470741e (patch)
tree170ce25cb6bd3fd7d83f00c25549721f52ebfc12 /gcc
parenta604b0f1db0ee1c21b28be926918d6b05b8fc1ca (diff)
downloadgcc-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/ChangeLog9
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c65
-rw-r--r--gcc/cp/method.c5
-rw-r--r--gcc/cp/pt.c26
-rw-r--r--gcc/cp/tree.c246
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