]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
* cp-tree.h (DECL_EXTERNAL_LINKAGE_P): New macro.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 31 Oct 2000 01:30:59 +0000 (01:30 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 31 Oct 2000 01:30:59 +0000 (01:30 +0000)
(linkage_kind): New enumeration.
(decl_linkage): New function.
* decl2.c (comdat_linkage): Extend comment.
* error.c (dump_function_decl): Print the arguments used to
instantiate a template, even when not printing the type of the
function.
* pt.c (convert_nontype_argument): Use DECL_EXTERNAL_LINKAGE_P,
not TREE_PUBLIC, to test for external linkage.
* tree.c (decl_linkage): New function.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@37150 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/testsuite/g++.old-deja/g++.other/linkage6.C [new file with mode: 0644]

index 21d670c766347468ded1fd98398fd6cb41050f05..9b560266f3384b9fbc04a966358a5f709e29d8b8 100644 (file)
@@ -1,3 +1,16 @@
+2000-10-30  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.h (DECL_EXTERNAL_LINKAGE_P): New macro.
+       (linkage_kind): New enumeration.
+       (decl_linkage): New function.
+       * decl2.c (comdat_linkage): Extend comment.
+       * error.c (dump_function_decl): Print the arguments used to
+       instantiate a template, even when not printing the type of the
+       function.
+       * pt.c (convert_nontype_argument): Use DECL_EXTERNAL_LINKAGE_P,
+       not TREE_PUBLIC, to test for external linkage.
+       * tree.c (decl_linkage): New function.
+
 2000-10-28  Mark Mitchell  <mark@codesourcery.com>
 
        * pt.c (instantiate_decl): Always instantiate static data members
index 54dbaa34da5ecb894069fa9b28e4cad834d00102..fc3cd86934d89255c605723b7c5e7491fd8bf9d7 100644 (file)
@@ -2498,6 +2498,13 @@ extern int flag_new_for_scope;
 #define DECL_UNINLINABLE(NODE) \
   (DECL_LANG_SPECIFIC (NODE)->decl_flags.uninlinable)
 
+/* Returns non-zero if DECL has external linkage, as specified by the
+   language standard.  (This predicate may hold even when the
+   corresponding entity is not actually given external linkage in the
+   object file; see decl_linkage for details.)  */
+#define DECL_EXTERNAL_LINKAGE_P(DECL) \
+  (decl_linkage (DECL) == lk_external)
+
 #define INTEGRAL_CODE_P(CODE) \
   (CODE == INTEGER_TYPE || CODE == ENUMERAL_TYPE || CODE == BOOLEAN_TYPE)
 
@@ -3145,6 +3152,29 @@ typedef enum special_function_kind {
   sfk_conversion           /* A conversion operator.  */
 } special_function_kind;
 
+/* The various kinds of linkage.  From [basic.link], 
+   
+      A name is said to have linkage when it might denote the same
+      object, reference, function, type, template, namespace or value
+      as a name introduced in another scope:
+
+      -- When a name has external linkage, the entity it denotes can
+         be referred to from scopes of other translation units or from
+        other scopes of the same translation unit.
+
+      -- When a name has internal linkage, the entity it denotes can
+         be referred to by names from other scopes in the same
+        translation unit.
+
+      -- When a name has no linkage, the entity it denotes cannot be
+         referred to by names from other scopes.  */
+
+typedef enum linkage_kind {
+  lk_none,                 /* No linkage.  */
+  lk_internal,             /* Internal linkage.  */
+  lk_external              /* External linkage.  */
+} linkage_kind;
+
 /* Bitmask flags to pass to instantiate_type.  */
 typedef enum instantiate_type_flags {
   itf_none = 0,               /* nothing special */
@@ -4443,6 +4473,7 @@ extern int count_trees                          PARAMS ((tree));
 extern int char_type_p                          PARAMS ((tree));
 extern void verify_stmt_tree                    PARAMS ((tree));
 extern tree find_tree                           PARAMS ((tree, tree));
+extern linkage_kind decl_linkage                PARAMS ((tree));
 
 /* in typeck.c */
 extern int string_conv_p                       PARAMS ((tree, tree, int));
index 766b45f8ac70a3087ace9927bd3360894c42ac85..0cfcc4dee586b84cc8c9599817d402499ca751bd 100644 (file)
@@ -2427,8 +2427,13 @@ comdat_linkage (decl)
   if (flag_weak)
     make_decl_one_only (decl);
   else if (TREE_CODE (decl) == FUNCTION_DECL || DECL_VIRTUAL_P (decl))
-    /* We can just emit functions and vtables statically; it doesn't really
-       matter if we have multiple copies.  */
+    /* We can just emit functions and vtables statically; having
+       multiple copies is (for the most part) only a waste of space.
+       There is at least one correctness issue, however: the address
+       of a template instantiation with external linkage should be the
+       same, independent of what translation unit asks for the
+       address, and this will not hold when we emit multiple copies of
+       the function.  However, there's little else we can do.  */
     TREE_PUBLIC (decl) = 0;
   else
     {
index 91c9f6e9f06a4767a8b2660b448f81cc7630ae4a..6e7a4ae3245428ed2f1eaf2a686d99de667bed04 100644 (file)
@@ -1284,27 +1284,28 @@ dump_function_decl (t, flags)
 
   dump_function_name (t, flags);
 
-  if (!(flags & TS_DECL_TYPE))
-    return;
-  if (TREE_CODE (fntype) == METHOD_TYPE && parmtypes)
-    /* Skip "this" parameter.  */
-    parmtypes = TREE_CHAIN (parmtypes);
+  if (flags & TS_DECL_TYPE) 
+    {
+      if (TREE_CODE (fntype) == METHOD_TYPE && parmtypes)
+       /* Skip "this" parameter.  */
+       parmtypes = TREE_CHAIN (parmtypes);
 
-  /* Skip past the "in_charge" parameter.  */
-  if (DECL_HAS_IN_CHARGE_PARM_P (t))
-    parmtypes = TREE_CHAIN (parmtypes);
+      /* Skip past the "in_charge" parameter.  */
+      if (DECL_HAS_IN_CHARGE_PARM_P (t))
+       parmtypes = TREE_CHAIN (parmtypes);
 
-  dump_parameters (parmtypes, flags);
+      dump_parameters (parmtypes, flags);
 
-  if (show_return)
-    dump_type_suffix (TREE_TYPE (fntype), flags);
+      if (show_return)
+       dump_type_suffix (TREE_TYPE (fntype), flags);
 
-  if (TREE_CODE (fntype) == METHOD_TYPE)
-    dump_qualifiers (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))),
-                    before);
+      if (TREE_CODE (fntype) == METHOD_TYPE)
+       dump_qualifiers (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))),
+                        before);
 
-  if (flags & TS_FUNC_THROW)
-    dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), flags);
+      if (flags & TS_FUNC_THROW)
+       dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), flags);
+    }
 
   /* If T is a template instantiation, dump the parameter binding.  */
   if (template_parms != NULL_TREE && template_args != NULL_TREE)
index 8ca2468a0b28c4a9938e1fc6260d77d96cfbaa1e..303a3c65becbf0c9bc53ca8317eb63879982487b 100644 (file)
@@ -2808,7 +2808,7 @@ convert_nontype_argument (type, expr)
        ;
       else if (TREE_CODE (referent) != VAR_DECL)
        goto bad_argument;
-      else if (!TREE_PUBLIC (referent))
+      else if (!DECL_EXTERNAL_LINKAGE_P (referent))
        {
          cp_error ("address of non-extern `%E' cannot be used as template argument", referent); 
          return error_mark_node;
@@ -2915,7 +2915,7 @@ convert_nontype_argument (type, expr)
            if (fn == error_mark_node)
              return error_mark_node;
 
-           if (!TREE_PUBLIC (fn))
+           if (!DECL_EXTERNAL_LINKAGE_P (fn))
              {
                if (really_overloaded_fn (fns))
                  return error_mark_node;
@@ -2980,7 +2980,7 @@ convert_nontype_argument (type, expr)
            if (fn == error_mark_node)
              return error_mark_node;
 
-           if (!TREE_PUBLIC (fn))
+           if (!DECL_EXTERNAL_LINKAGE_P (fn))
              {
                if (really_overloaded_fn (expr))
                  /* Don't issue an error here; we might get a different
index d6314d8196841ceef80a5088c9f69b7d1aa86f1a..db5e33deee5f4cbcaed2e84687eff81b826b870c 100644 (file)
@@ -2597,3 +2597,46 @@ char_type_p (type)
          || same_type_p (type, signed_char_type_node)
          || same_type_p (type, wchar_type_node));
 }
+
+/* Returns the kind of linkage associated with the indicated DECL.  Th
+   value returned is as specified by the language standard; it is
+   independent of implementation details regarding template
+   instantiation, etc.  For example, it is possible that a declaration
+   to which this function assigns external linkage would not show up
+   as a global symbol when you run `nm' on the resulting object file.  */
+
+linkage_kind
+decl_linkage (decl)
+     tree decl;
+{
+  /* This function doesn't attempt to calculate the linkage from first
+     principles as given in [basic.link].  Instead, it makes use of
+     the fact that we have already set TREE_PUBLIC appropriately, and
+     then handles a few special cases.  Ideally, we would calculate
+     linkage first, and then transform that into a concrete
+     implementation.  */
+
+  /* Things that don't have names have no linkage.  */
+  if (!DECL_NAME (decl))
+    return lk_none;
+
+  /* Things that are TREE_PUBLIC have external linkage.  */
+  if (TREE_PUBLIC (decl))
+    return lk_external;
+
+  /* Some things that are not TREE_PUBLIC have external linkage, too.
+     For example, on targets that don't have weak symbols, we make all
+     template instantiations have internal linkage (in the object
+     file), but the symbols should still be treated as having external
+     linkage from the point of view of the language.  */
+  if (DECL_LANG_SPECIFIC (decl) && DECL_COMDAT (decl))
+    return lk_external;
+
+  /* Things in local scope do not have linkage, if they don't have
+     TREE_PUBLIC set.  */
+  if (decl_function_context (decl))
+    return lk_none;
+
+  /* Everything else has internal linkage.  */
+  return lk_internal;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/linkage6.C b/gcc/testsuite/g++.old-deja/g++.other/linkage6.C
new file mode 100644 (file)
index 0000000..65374ca
--- /dev/null
@@ -0,0 +1,18 @@
+// Build don't link:
+// Special g++ Options: -fno-weak
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+template <typename T>
+void f ();
+
+void h () { f<int> (); }
+
+template <void (*X)()>
+void g () {}
+
+template <typename T>
+void f ()
+{
+   g<&f<T> >();
+}
+