aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2000-10-31 01:30:59 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2000-10-31 01:30:59 +0000
commitad50e811dc95387b52dddd7ab753db59512a3baf (patch)
tree62873128afbebb3b4075750f0c2dbc4160b90b4b /gcc
parent4bc950092b4a22757f6893f53c1d1ad8fd85381b (diff)
downloadgcc-ad50e811dc95387b52dddd7ab753db59512a3baf.zip
gcc-ad50e811dc95387b52dddd7ab753db59512a3baf.tar.gz
gcc-ad50e811dc95387b52dddd7ab753db59512a3baf.tar.bz2
cp-tree.h (DECL_EXTERNAL_LINKAGE_P): New macro.
* 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. From-SVN: r37150
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog13
-rw-r--r--gcc/cp/cp-tree.h31
-rw-r--r--gcc/cp/decl2.c9
-rw-r--r--gcc/cp/error.c33
-rw-r--r--gcc/cp/pt.c6
-rw-r--r--gcc/cp/tree.c43
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/linkage6.C18
7 files changed, 132 insertions, 21 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 21d670c..9b56026 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 54dbaa3..fc3cd86 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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));
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 766b45f..0cfcc4d 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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
{
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 91c9f6e..6e7a4ae 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -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)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 8ca2468..303a3c6 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index d6314d8..db5e33d 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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
index 0000000..65374ca
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/linkage6.C
@@ -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> >();
+}
+