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
This commit is contained in:
Mark Mitchell 2000-10-31 01:30:59 +00:00 committed by Mark Mitchell
parent 4bc950092b
commit ad50e811dc
7 changed files with 132 additions and 21 deletions

View 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

View 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));

View 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
{

View 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)

View 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

View 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;
}

View File

@ -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> >();
}