tree.c (search_tree, [...]): New fn.
authorJason Merrill <jason@yorick.cygnus.com>
Thu, 20 Aug 1998 17:41:43 +0000 (17:41 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 20 Aug 1998 17:41:43 +0000 (13:41 -0400)
* 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

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/method.c
gcc/cp/pt.c
gcc/cp/tree.c

index 5b8c014ffb159c1e2ec62750686265ef071af7e8..c5f938b990f9f09aa6ae94b084a9dc5e7dd884f1 100644 (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.
index f96af15fcf6a045a3d128afb8174860b2f7525da..b567b950638eeafd26882888c1db6de480638936 100644 (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
index ad3585b20ab1f708f5d84ee4e974395d3bf00786..251cbef850838dc4669d5438fd56b9c78a1bc089 100644 (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)
index 7084810dcbc3a53c12576b0681597b1fec53278e..51ee80ca9f37acd6e30e6ba2f50c673f42ca7f1d 100644 (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);
index 73b00c715f17aee5362d32a6585d1f68782031be..b0202b13198bd598db14d69ee3ea36fb6020490b 100644 (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))
index 44d36b99f230d46f21550148df2e12e58d886a38..13d8a08fa0a4f25dca4b6c4c1ecba64bc256b2ba 100644 (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