Commit ad50e811 by Mark Mitchell Committed by Mark Mitchell

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
parent 4bc95009
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
......
......@@ -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));
......
......@@ -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
{
......
......@@ -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)
......
......@@ -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
......
......@@ -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;
}
// 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> >();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment