Usage of DECL_LANG_FLAG_?:
0: LABEL_VARIABLE_CASE (in LABEL_DECL).
DECL_BUILT_IN_CTFE (in FUNCTION_DECL).
- 1: DECL_IN_UNITTEST_CONDITION_P (in FUNCTION_DECL). */
+ 1: DECL_IN_UNITTEST_CONDITION_P (in FUNCTION_DECL).
+ 2: DECL_INSTANTIATED (in FUNCTION_DECL, VAR_DECL). */
+
+/* Language-specific tree checkers. */
+
+#define VAR_OR_FUNCTION_DECL_CHECK(NODE) \
+ TREE_CHECK2 (NODE, VAR_DECL, FUNCTION_DECL)
/* The kinds of scopes we recognize. */
#define DECL_IN_UNITTEST_CONDITION_P(NODE) \
(DECL_LANG_FLAG_1 (FUNCTION_DECL_CHECK (NODE)))
+/* True if the decl comes from a template instance. */
+#define DECL_INSTANTIATED(NODE) \
+ (DECL_LANG_FLAG_1 (VAR_OR_FUNCTION_DECL_CHECK (NODE)))
+
enum d_tree_index
{
DTI_VTABLE_ENTRY_TYPE,
extern tree build_artificial_decl (tree, tree, const char * = NULL);
extern tree create_field_decl (tree, const char *, int, int);
extern void build_type_decl (tree, Dsymbol *);
-extern void d_comdat_linkage (tree);
-extern void d_linkonce_linkage (tree);
+extern void set_linkage_for_decl (tree);
/* In expr.cc. */
extern tree build_expr (Expression *, bool = false, bool = false);
/* Generate static initializer. */
d->sinit = aggregate_initializer_decl (d);
DECL_INITIAL (d->sinit) = layout_struct_initializer (d);
-
- if (d->isInstantiated ())
- d_linkonce_linkage (d->sinit);
-
+ DECL_INSTANTIATED (d->sinit) = (d->isInstantiated () != NULL);
d_finish_decl (d->sinit);
/* Put out the members. There might be static constructors in the members
/* Generate static initializer. */
DECL_INITIAL (d->sinit) = layout_class_initializer (d);
- d_linkonce_linkage (d->sinit);
+ DECL_INSTANTIATED (d->sinit) = (d->isInstantiated () != NULL);
d_finish_decl (d->sinit);
/* Put out the TypeInfo. */
create_typeinfo (d->type, NULL);
DECL_INITIAL (d->csym) = layout_classinfo (d);
- d_linkonce_linkage (d->csym);
d_finish_decl (d->csym);
/* Put out the vtbl[]. */
DECL_INITIAL (d->vtblsym)
= build_constructor (TREE_TYPE (d->vtblsym), elms);
- d_comdat_linkage (d->vtblsym);
d_finish_decl (d->vtblsym);
/* Add this decl to the current binding level. */
}
DECL_INITIAL (d->csym) = layout_classinfo (d);
- d_linkonce_linkage (d->csym);
d_finish_decl (d->csym);
/* Add this decl to the current binding level. */
/* Generate static initializer. */
d->sinit = enum_initializer_decl (d);
DECL_INITIAL (d->sinit) = build_expr (tc->sym->defaultval, true);
-
- if (d->isInstantiated ())
- d_linkonce_linkage (d->sinit);
-
+ DECL_INSTANTIATED (d->sinit) = (d->isInstantiated () != NULL);
d_finish_decl (d->sinit);
}
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl->csym) = 1;
}
+ /* Mark compiler generated functions as artificial. */
+ if (fd->generated)
+ DECL_ARTIFICIAL (decl->csym) = 1;
+
/* Vector array operations are always compiler generated. */
if (fd->isArrayOp)
{
- TREE_PUBLIC (decl->csym) = 1;
DECL_ARTIFICIAL (decl->csym) = 1;
DECL_DECLARED_INLINE_P (decl->csym) = 1;
- d_comdat_linkage (decl->csym);
}
- /* And so are ensure and require contracts. */
+ /* Ensure and require contracts are lexically nested in the function they
+ part of, but are always publicly callable. */
if (fd->ident == Identifier::idPool ("ensure")
|| fd->ident == Identifier::idPool ("require"))
- {
- DECL_ARTIFICIAL (decl->csym) = 1;
- TREE_PUBLIC (decl->csym) = 1;
- }
+ TREE_PUBLIC (decl->csym) = 1;
if (decl->storage_class & STCfinal)
DECL_FINAL_P (decl->csym) = 1;
/* The decl has not been defined -- yet. */
DECL_EXTERNAL (decl->csym) = 1;
- if (decl->isInstantiated ())
- d_linkonce_linkage (decl->csym);
+ DECL_INSTANTIATED (decl->csym) = (decl->isInstantiated () != NULL);
+ set_linkage_for_decl (decl->csym);
}
/* Symbol is going in thread local storage. */
set_decl_tls_model (decl, decl_default_tls_model (decl));
relayout_decl (decl);
+ set_linkage_for_decl (decl);
if (flag_checking && DECL_INITIAL (decl))
{
/* Set DECL up to have the closest approximation of "initialized common"
linkage available. */
-void
+static void
d_comdat_linkage (tree decl)
{
- if (flag_weak)
+ /* COMDAT definitions have to be public. */
+ gcc_assert (TREE_PUBLIC (decl));
+
+ if (supports_one_only ())
make_decl_one_only (decl, d_comdat_group (decl));
- else if (TREE_CODE (decl) == FUNCTION_DECL
+ else if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INSTANTIATED (decl))
|| (VAR_P (decl) && DECL_ARTIFICIAL (decl)))
/* We can just emit function and compiler-generated variables statically;
having multiple copies is (for the most part) only a waste of space. */
/* Fallback, cannot have multiple copies. */
DECL_COMMON (decl) = 1;
- if (TREE_PUBLIC (decl))
+ if (TREE_PUBLIC (decl) && DECL_INSTANTIATED (decl))
DECL_COMDAT (decl) = 1;
}
-/* Set DECL up to have the closest approximation of "linkonce" linkage. */
+/* Set DECL up to have the closest approximation of "weak" linkage. */
-void
-d_linkonce_linkage (tree decl)
+static void
+d_weak_linkage (tree decl)
{
/* Weak definitions have to be public. */
+ gcc_assert (TREE_PUBLIC (decl));
+
+ /* Allow comdat linkage to be forced with the flag `-fno-weak-templates'. */
+ if (!flag_weak_templates || !TARGET_SUPPORTS_WEAK)
+ return d_comdat_linkage (decl);
+
+ declare_weak (decl);
+}
+
+/* DECL is a FUNCTION_DECL or a VAR_DECL with static storage. Set flags to
+ reflect the linkage that DECL will receive in the object file. */
+
+void
+set_linkage_for_decl (tree decl)
+{
+ gcc_assert (VAR_OR_FUNCTION_DECL_P (decl) && TREE_STATIC (decl));
+
+ /* Non-public decls keep their internal linkage. */
if (!TREE_PUBLIC (decl))
return;
- /* Necessary to allow DECL_ONE_ONLY or DECL_WEAK functions to be inlined. */
- if (TREE_CODE (decl) == FUNCTION_DECL)
- DECL_DECLARED_INLINE_P (decl) = 1;
+ /* Don't need to give private or protected symbols a special linkage. */
+ if ((TREE_PRIVATE (decl) || TREE_PROTECTED (decl))
+ && !DECL_INSTANTIATED (decl))
+ return;
+
+ /* Functions declared as `pragma(inline, true)' can appear in multiple
+ translation units. */
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl))
+ return d_comdat_linkage (decl);
- /* No weak support, fallback to COMDAT linkage. */
- if (!flag_weak)
- return d_comdat_linkage (decl);
+ /* Instantiated variables and functions need to be overridable by any other
+ symbol with the same name, so give them weak linkage. */
+ if (DECL_INSTANTIATED (decl))
+ return d_weak_linkage (decl);
- make_decl_one_only (decl, d_comdat_group (decl));
+ /* Compiler generated public symbols can appear in multiple contexts. */
+ if (DECL_ARTIFICIAL (decl))
+ return d_weak_linkage (decl);
}
by both module initialization and dso handlers. */
static FuncDeclaration *
-get_internal_fn (tree ident)
+get_internal_fn (tree ident, const Prot &prot)
{
Module *mod = current_module_decl;
const char *name = IDENTIFIER_POINTER (ident);
FuncDeclaration *fd = FuncDeclaration::genCfunc (NULL, Type::tvoid,
Identifier::idPool (name));
+ fd->generated = true;
fd->loc = Loc (mod->srcfile->toChars (), 1, 0);
fd->parent = mod;
- fd->protection.kind = Prot::private_;
+ fd->protection = prot;
fd->semanticRun = PASSsemantic3done;
return fd;
static tree
build_internal_fn (tree ident, tree expr)
{
- FuncDeclaration *fd = get_internal_fn (ident);
+ FuncDeclaration *fd = get_internal_fn (ident, Prot (Prot::private_));
tree decl = get_symbol_decl (fd);
tree old_context = start_function (fd);
}
}
*/
- FuncDeclaration *fd = get_internal_fn (get_identifier (name));
+ FuncDeclaration *fd = get_internal_fn (get_identifier (name),
+ Prot (Prot::public_));
tree decl = get_symbol_decl (fd);
TREE_PUBLIC (decl) = 1;
DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
DECL_VISIBILITY_SPECIFIED (decl) = 1;
- d_comdat_linkage (decl);
-
/* Start laying out the body. */
tree old_context = start_function (fd);
rest_of_decl_compilation (decl, 1, 0);
/* Declare dso_slot and dso_initialized. */
dso_slot_node = build_dso_registry_var (GDC_PREFIX ("dso_slot"),
ptr_type_node);
- DECL_EXTERNAL (dso_slot_node) = 0;
- d_comdat_linkage (dso_slot_node);
- rest_of_decl_compilation (dso_slot_node, 1, 0);
+ d_finish_decl (dso_slot_node);
dso_initialized_node = build_dso_registry_var (GDC_PREFIX ("dso_initialized"),
boolean_type_node);
- DECL_EXTERNAL (dso_initialized_node) = 0;
- d_comdat_linkage (dso_initialized_node);
- rest_of_decl_compilation (dso_initialized_node, 1, 0);
+ d_finish_decl (dso_initialized_node);
/* Declare dso_ctor() and dso_dtor(). */
tree dso_ctor = build_dso_cdtor_fn (true);