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:
parent
4bc950092b
commit
ad50e811dc
7 changed files with 132 additions and 21 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
18
gcc/testsuite/g++.old-deja/g++.other/linkage6.C
Normal file
18
gcc/testsuite/g++.old-deja/g++.other/linkage6.C
Normal 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> >();
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue