static void write_out_vars (tree);
static void import_export_class (tree);
static tree get_guard_bits (tree);
+static void determine_visibility_from_class (tree, tree);
/* A list of static class variables. This is needed, because a
static class variable can be declared inside the class without
tree static_dtors;
\f
-/* Incorporate `const' and `volatile' qualifiers for member functions.
- FUNCTION is a TYPE_DECL or a FUNCTION_DECL.
- QUALS is a list of qualifiers. Returns any explicit
- top-level qualifiers of the method's this pointer, anything other than
- TYPE_UNQUALIFIED will be an extension. */
-
-int
-grok_method_quals (tree ctype, tree function, cp_cv_quals quals)
+
+/* Return a member function type (a METHOD_TYPE), given FNTYPE (a
+ FUNCTION_TYPE), CTYPE (class type), and QUALS (the cv-qualifiers
+ that apply to the function). */
+
+tree
+build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals)
{
- tree fntype = TREE_TYPE (function);
- tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
- int type_quals = TYPE_UNQUALIFIED;
- int this_quals = TYPE_UNQUALIFIED;
+ tree raises;
+ int type_quals;
- type_quals = quals & ~TYPE_QUAL_RESTRICT;
- this_quals = quals & TYPE_QUAL_RESTRICT;
+ if (fntype == error_mark_node || ctype == error_mark_node)
+ return error_mark_node;
+ type_quals = quals & ~TYPE_QUAL_RESTRICT;
ctype = cp_build_qualified_type (ctype, type_quals);
fntype = build_method_type_directly (ctype, TREE_TYPE (fntype),
(TREE_CODE (fntype) == METHOD_TYPE
? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
: TYPE_ARG_TYPES (fntype)));
+ raises = TYPE_RAISES_EXCEPTIONS (fntype);
if (raises)
fntype = build_exception_variant (fntype, raises);
- TREE_TYPE (function) = fntype;
- return this_quals;
+ return fntype;
}
/* Build a PARM_DECL with NAME and TYPE, and set DECL_ARG_TYPE
/* Returns a PARM_DECL for a parameter of the indicated TYPE, with the
indicated NAME. */
-static tree
+tree
build_artificial_parm (tree name, tree type)
{
tree parm = cp_build_parm_decl (name, type);
QUALS are the qualifiers for the this pointer. */
void
-grokclassfn (tree ctype, tree function, enum overload_flags flags,
- cp_cv_quals quals)
+grokclassfn (tree ctype, tree function, enum overload_flags flags)
{
tree fn_name = DECL_NAME (function);
- cp_cv_quals this_quals = TYPE_UNQUALIFIED;
/* Even within an `extern "C"' block, members get C++ linkage. See
[dcl.link] for details. */
DECL_NAME (function) = fn_name;
}
- if (quals)
- this_quals = grok_method_quals (ctype, function, quals);
-
- if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
- {
- /* Must add the class instance variable up front. */
- /* Right now we just make this a pointer. But later
- we may wish to make it special. */
- tree type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (function)));
- tree qual_type;
- tree parm;
-
- /* The `this' parameter is implicitly `const'; it cannot be
- assigned to. */
- this_quals |= TYPE_QUAL_CONST;
- qual_type = cp_build_qualified_type (type, this_quals);
- parm = build_artificial_parm (this_identifier, qual_type);
- cp_apply_type_quals_to_decl (this_quals, parm);
- TREE_CHAIN (parm) = DECL_ARGUMENTS (function);
- DECL_ARGUMENTS (function) = parm;
- }
-
DECL_CONTEXT (function) = ctype;
if (flags == DTOR_FLAG)
error ("invalid declaration of member template %q#D in local class",
decl);
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl))
- {
- /* 14.5.2.3 [temp.mem]
-
- A member function template shall not be virtual. */
- error
- ("invalid use of %<virtual%> in template declaration of %q#D",
- decl);
- DECL_VIRTUAL_P (decl) = 0;
- }
+ /* The parser rejects any use of virtual in a function template. */
+ gcc_assert (!(TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_VIRTUAL_P (decl)));
/* The debug-information generating code doesn't know what to do
with member templates. */
static bool
acceptable_java_type (tree type)
{
+ if (type == error_mark_node)
+ return false;
+
if (TREE_CODE (type) == VOID_TYPE || TYPE_FOR_JAVA (type))
- return 1;
+ return true;
if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)
{
type = TREE_TYPE (type);
tree type = TREE_VALUE (arg_types);
if (!acceptable_java_type (type))
{
- error ("Java method %qD has non-Java parameter type %qT",
- method, type);
+ if (type != error_mark_node)
+ error ("Java method %qD has non-Java parameter type %qT",
+ method, type);
jerr = true;
}
}
{
int ix;
bool is_template;
-
+ tree pushed_scope;
+
if (DECL_USE_TEMPLATE (function)
&& !(TREE_CODE (function) == TEMPLATE_DECL
&& DECL_TEMPLATE_SPECIALIZATION (function))
/* OK, is this a definition of a member template? */
is_template = (template_parms != NULL_TREE);
+ /* We must enter the scope here, because conversion operators are
+ named by target type, and type equivalence relies on typenames
+ resolving within the scope of CTYPE. */
+ pushed_scope = push_scope (ctype);
ix = class_method_index_for_fn (complete_type (ctype), function);
if (ix >= 0)
{
VEC(tree,gc) *methods = CLASSTYPE_METHOD_VEC (ctype);
tree fndecls, fndecl = 0;
bool is_conv_op;
- tree pushed_scope;
const char *format = NULL;
- pushed_scope = push_scope (ctype);
for (fndecls = VEC_index (tree, methods, ix);
fndecls; fndecls = OVL_NEXT (fndecls))
{
== DECL_TI_TEMPLATE (fndecl))))
break;
}
- if (pushed_scope)
- pop_scope (pushed_scope);
if (fndecls)
- return OVL_CURRENT (fndecls);
+ {
+ if (pushed_scope)
+ pop_scope (pushed_scope);
+ return OVL_CURRENT (fndecls);
+ }
+
error ("prototype for %q#D does not match any in class %qT",
function, ctype);
is_conv_op = DECL_CONV_FN_P (fndecl);
properly within the class. */
if (COMPLETE_TYPE_P (ctype))
add_method (ctype, function, NULL_TREE);
+
+ if (pushed_scope)
+ pop_scope (pushed_scope);
return NULL_TREE;
}
}
}
-/* Like note_vague_linkage_fn but for variables. */
-
-static void
-note_vague_linkage_var (tree var)
-{
- VEC_safe_push (tree, gc, pending_statics, var);
-}
-
/* We have just processed the DECL, which is a static data member.
- Its initializer, if present, is INIT. The ASMSPEC_TREE, if
- present, is the assembly-language name for the data member.
- FLAGS is as for cp_finish_decl. */
+ The other parameters are as for cp_finish_decl. */
void
-finish_static_data_member_decl (tree decl, tree init, tree asmspec_tree,
+finish_static_data_member_decl (tree decl,
+ tree init, bool init_const_expr_p,
+ tree asmspec_tree,
int flags)
{
- gcc_assert (TREE_PUBLIC (decl));
-
DECL_CONTEXT (decl) = current_class_type;
/* We cannot call pushdecl here, because that would fill in the
TREE_CHAIN of our decl. Instead, we modify cp_finish_decl to do
the right thing, namely, to put this decl out straight away. */
- /* current_class_type can be NULL_TREE in case of error. */
- if (!asmspec_tree && current_class_type)
- DECL_INITIAL (decl) = error_mark_node;
if (! processing_template_decl)
- note_vague_linkage_var (decl);
+ VEC_safe_push (tree, gc, pending_statics, decl);
if (LOCAL_CLASS_P (current_class_type))
pedwarn ("local class %q#T shall not have static data member %q#D",
DECL_INITIAL (decl) = init;
DECL_IN_AGGR_P (decl) = 1;
- cp_finish_decl (decl, init, asmspec_tree, flags);
+ cp_finish_decl (decl, init, init_const_expr_p, asmspec_tree, flags);
}
-/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
- of a structure component, returning a _DECL node.
- QUALS is a list of type qualifiers for this decl (such as for declaring
- const member functions).
-
- This is done during the parsing of the struct declaration.
- The _DECL nodes are chained together and the lot of them
- are ultimately passed to `build_struct' to make the RECORD_TYPE node.
-
- If class A defines that certain functions in class B are friends, then
- the way I have set things up, it is B who is interested in permission
- granted by A. However, it is in A's context that these declarations
- are parsed. By returning a void_type_node, class A does not attempt
- to incorporate the declarations of the friends within its structure.
-
- DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING
- CHANGES TO CODE IN `start_method'. */
+/* DECLARATOR and DECLSPECS correspond to a class member. The other
+ parameters are as for cp_finish_decl. Return the DECL for the
+ class member declared. */
tree
grokfield (const cp_declarator *declarator,
cp_decl_specifier_seq *declspecs,
- tree init, tree asmspec_tree,
+ tree init, bool init_const_expr_p,
+ tree asmspec_tree,
tree attrlist)
{
tree value;
if (!declspecs->any_specifiers_p
&& declarator->kind == cdk_id
&& declarator->u.id.qualifying_scope
+ && TYPE_P (declarator->u.id.qualifying_scope)
+ && IS_AGGR_TYPE (declarator->u.id.qualifying_scope)
&& TREE_CODE (declarator->u.id.unqualified_name) == IDENTIFIER_NODE)
/* Access declaration */
return do_class_using_decl (declarator->u.id.qualifying_scope,
return void_type_node;
}
- if (asmspec_tree)
+ if (asmspec_tree && asmspec_tree != error_mark_node)
asmspec = TREE_STRING_POINTER (asmspec_tree);
if (init)
switch (TREE_CODE (value))
{
case VAR_DECL:
- finish_static_data_member_decl (value, init, asmspec_tree,
- flags);
+ finish_static_data_member_decl (value, init, init_const_expr_p,
+ asmspec_tree, flags);
return value;
case FIELD_DECL:
error ("%<asm%> specifiers are not permitted on non-static data members");
if (DECL_INITIAL (value) == error_mark_node)
init = error_mark_node;
- cp_finish_decl (value, init, NULL_TREE, flags);
+ cp_finish_decl (value, init, /*init_const_expr_p=*/false,
+ NULL_TREE, flags);
DECL_INITIAL (value) = init;
DECL_IN_AGGR_P (value) = 1;
return value;
case FUNCTION_DECL:
if (asmspec)
set_user_assembler_name (value, asmspec);
- if (!DECL_FRIEND_P (value))
- grok_special_member_properties (value);
- cp_finish_decl (value, init, asmspec_tree, flags);
+ cp_finish_decl (value,
+ /*init=*/NULL_TREE,
+ /*init_const_expr_p=*/false,
+ asmspec_tree, flags);
/* Pass friends back this way. */
if (DECL_FRIEND_P (value))
{
tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL);
- if (! value) return NULL_TREE; /* friends went bad. */
+ if (value == error_mark_node)
+ return NULL_TREE; /* friends went bad. */
/* Pass friendly classes back. */
if (TREE_CODE (value) == VOID_TYPE)
error ("static member %qD cannot be a bit-field", value);
return NULL_TREE;
}
- cp_finish_decl (value, NULL_TREE, NULL_TREE, 0);
+ finish_decl (value, NULL_TREE, NULL_TREE);
if (width != error_mark_node)
{
void
cplus_decl_attributes (tree *decl, tree attributes, int flags)
{
- if (*decl == NULL_TREE || *decl == void_type_node)
+ if (*decl == NULL_TREE || *decl == void_type_node
+ || *decl == error_mark_node)
return;
if (TREE_CODE (*decl) == TEMPLATE_DECL)
}
main_decl = build_anon_union_vars (type, anon_union_decl);
+ if (main_decl == error_mark_node)
+ return;
if (main_decl == NULL_TREE)
{
warning (0, "anonymous union with no members");
return true;
}
+/* A special return value from type_visibility meaning internal
+ linkage. */
+
+enum { VISIBILITY_ANON = VISIBILITY_INTERNAL+1 };
+
+/* walk_tree helper function for type_visibility. */
+
+static tree
+min_vis_r (tree *tp, int *walk_subtrees, void *data)
+{
+ int *vis_p = (int *)data;
+ if (! TYPE_P (*tp))
+ {
+ *walk_subtrees = 0;
+ }
+ else if (CLASS_TYPE_P (*tp))
+ {
+ if (!TREE_PUBLIC (TYPE_MAIN_DECL (*tp)))
+ {
+ *vis_p = VISIBILITY_ANON;
+ return *tp;
+ }
+ else if (CLASSTYPE_VISIBILITY (*tp) > *vis_p)
+ *vis_p = CLASSTYPE_VISIBILITY (*tp);
+ }
+ return NULL;
+}
+
+/* Returns the visibility of TYPE, which is the minimum visibility of its
+ component types. */
+
+static int
+type_visibility (tree type)
+{
+ int vis = VISIBILITY_DEFAULT;
+ walk_tree_without_duplicates (&type, min_vis_r, &vis);
+ return vis;
+}
+
+/* Limit the visibility of DECL to VISIBILITY, if not explicitly
+ specified (or if VISIBILITY is static). */
+
+static bool
+constrain_visibility (tree decl, int visibility)
+{
+ if (visibility == VISIBILITY_ANON)
+ {
+ /* extern "C" declarations aren't affected by the anonymous
+ namespace. */
+ if (!DECL_EXTERN_C_P (decl))
+ {
+ TREE_PUBLIC (decl) = 0;
+ DECL_INTERFACE_KNOWN (decl) = 1;
+ if (DECL_LANG_SPECIFIC (decl))
+ DECL_NOT_REALLY_EXTERN (decl) = 1;
+ }
+ }
+ else if (visibility > DECL_VISIBILITY (decl)
+ && !DECL_VISIBILITY_SPECIFIED (decl))
+ {
+ DECL_VISIBILITY (decl) = visibility;
+ return true;
+ }
+ return false;
+}
+
+/* Constrain the visibility of DECL based on the visibility of its template
+ arguments. */
+
+static void
+constrain_visibility_for_template (tree decl, tree targs)
+{
+ /* If this is a template instantiation, check the innermost
+ template args for visibility constraints. The outer template
+ args are covered by the class check. */
+ tree args = INNERMOST_TEMPLATE_ARGS (targs);
+ int i;
+ for (i = TREE_VEC_LENGTH (args); i > 0; --i)
+ {
+ int vis = 0;
+
+ tree arg = TREE_VEC_ELT (args, i-1);
+ if (TYPE_P (arg))
+ vis = type_visibility (arg);
+ else if (TREE_TYPE (arg) && POINTER_TYPE_P (TREE_TYPE (arg)))
+ {
+ STRIP_NOPS (arg);
+ if (TREE_CODE (arg) == ADDR_EXPR)
+ arg = TREE_OPERAND (arg, 0);
+ if (TREE_CODE (arg) == VAR_DECL
+ || TREE_CODE (arg) == FUNCTION_DECL)
+ {
+ if (! TREE_PUBLIC (arg))
+ vis = VISIBILITY_ANON;
+ else
+ vis = DECL_VISIBILITY (arg);
+ }
+ }
+ if (vis)
+ constrain_visibility (decl, vis);
+ }
+}
+
/* Like c_determine_visibility, but with additional C++-specific
- behavior. */
+ behavior.
+
+ Function-scope entities can rely on the function's visibility because
+ it is set in start_preparsed_function.
+
+ Class-scope entities cannot rely on the class's visibility until the end
+ of the enclosing class definition.
+
+ Note that because namespaces have multiple independent definitions,
+ namespace visibility is handled elsewhere using the #pragma visibility
+ machinery rather than by decorating the namespace declaration.
+
+ The goal is for constraints from the type to give a diagnostic, and
+ other constraints to be applied silently. */
void
determine_visibility (tree decl)
{
- tree class_type;
+ tree class_type = NULL_TREE;
+ bool use_template;
+
+ /* Remember that all decls get VISIBILITY_DEFAULT when built. */
+
+ /* Only relevant for names with external linkage. */
+ if (!TREE_PUBLIC (decl))
+ return;
/* Cloned constructors and destructors get the same visibility as
the underlying function. That should be set up in
maybe_clone_body. */
gcc_assert (!DECL_CLONED_FUNCTION_P (decl));
- /* Give the common code a chance to make a determination. */
- if (c_determine_visibility (decl))
- return;
+ if (TREE_CODE (decl) == TYPE_DECL)
+ {
+ if (CLASS_TYPE_P (TREE_TYPE (decl)))
+ use_template = CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl));
+ else if (TYPE_TEMPLATE_INFO (TREE_TYPE (decl)))
+ use_template = 1;
+ else
+ use_template = 0;
+ }
+ else if (DECL_LANG_SPECIFIC (decl))
+ use_template = DECL_USE_TEMPLATE (decl);
+ else
+ use_template = 0;
+
+ /* Anything that is exported must have default visibility. */
+ if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+ && lookup_attribute ("dllexport",
+ TREE_CODE (decl) == TYPE_DECL
+ ? TYPE_ATTRIBUTES (TREE_TYPE (decl))
+ : DECL_ATTRIBUTES (decl)))
+ {
+ DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+ DECL_VISIBILITY_SPECIFIED (decl) = 1;
+ }
/* If DECL is a member of a class, visibility specifiers on the
class can influence the visibility of the DECL. */
class_type = TREE_TYPE (DECL_NAME (decl));
else
{
+ /* Not a class member. */
+
/* Virtual tables have DECL_CONTEXT set to their associated class,
so they are automatically handled above. */
gcc_assert (TREE_CODE (decl) != VAR_DECL
|| !DECL_VTABLE_OR_VTT_P (decl));
- /* Entities not associated with any class just get the
- visibility specified by their attributes. */
- return;
- }
- /* By default, static data members and function members receive
- the visibility of their containing class. */
- if (class_type)
- {
- if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
- && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class_type)))
- {
- DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
- DECL_VISIBILITY_SPECIFIED (decl) = 1;
- }
- else if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_DECLARED_INLINE_P (decl)
- && visibility_options.inlines_hidden)
+ if (DECL_FUNCTION_SCOPE_P (decl) && ! DECL_VISIBILITY_SPECIFIED (decl))
{
- /* Don't change it if it has been set explicitly by user. */
- if (!DECL_VISIBILITY_SPECIFIED (decl))
+ /* Local statics and classes get the visibility of their
+ containing function by default, except that
+ -fvisibility-inlines-hidden doesn't affect them. */
+ tree fn = DECL_CONTEXT (decl);
+ if (DECL_VISIBILITY_SPECIFIED (fn) || ! DECL_CLASS_SCOPE_P (fn))
{
- DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
- DECL_VISIBILITY_SPECIFIED (decl) = 1;
+ DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn);
+ DECL_VISIBILITY_SPECIFIED (decl) =
+ DECL_VISIBILITY_SPECIFIED (fn);
}
+ else
+ determine_visibility_from_class (decl, DECL_CONTEXT (fn));
+
+ /* Local classes in templates have CLASSTYPE_USE_TEMPLATE set,
+ but have no TEMPLATE_INFO, so don't try to check it. */
+ use_template = 0;
}
- else if (CLASSTYPE_VISIBILITY_SPECIFIED (class_type))
+ else if (TREE_CODE (decl) == VAR_DECL && DECL_TINFO_P (decl))
{
- DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
- DECL_VISIBILITY_SPECIFIED (decl) = 1;
+ /* tinfo visibility is based on the type it's for. */
+ constrain_visibility
+ (decl, type_visibility (TREE_TYPE (DECL_NAME (decl))));
}
- else if (!DECL_VISIBILITY_SPECIFIED (decl))
+ else if (use_template)
+ /* Template instantiations and specializations get visibility based
+ on their template unless they override it with an attribute. */;
+ else if (! DECL_VISIBILITY_SPECIFIED (decl))
+ {
+ /* Set default visibility to whatever the user supplied with
+ #pragma GCC visibility or a namespace visibility attribute. */
+ DECL_VISIBILITY (decl) = default_visibility;
+ DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+ }
+ }
+
+ if (use_template)
+ {
+ /* If the specialization doesn't specify visibility, use the
+ visibility from the template. */
+ tree tinfo = (TREE_CODE (decl) == TYPE_DECL
+ ? TYPE_TEMPLATE_INFO (TREE_TYPE (decl))
+ : DECL_TEMPLATE_INFO (decl));
+ tree args = TI_ARGS (tinfo);
+
+ if (args != error_mark_node)
{
- DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
- DECL_VISIBILITY_SPECIFIED (decl) = 0;
+ int depth = TMPL_ARGS_DEPTH (args);
+ tree pattern = DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo));
+
+ if (!DECL_VISIBILITY_SPECIFIED (decl))
+ {
+ DECL_VISIBILITY (decl) = DECL_VISIBILITY (pattern);
+ DECL_VISIBILITY_SPECIFIED (decl)
+ = DECL_VISIBILITY_SPECIFIED (pattern);
+ }
+
+ /* FIXME should TMPL_ARGS_DEPTH really return 1 for null input? */
+ if (args && depth > template_class_depth (class_type))
+ /* Limit visibility based on its template arguments. */
+ constrain_visibility_for_template (decl, args);
}
}
+
+ if (class_type)
+ determine_visibility_from_class (decl, class_type);
+
+ if (decl_anon_ns_mem_p (decl))
+ /* Names in an anonymous namespace get internal linkage.
+ This might change once we implement export. */
+ constrain_visibility (decl, VISIBILITY_ANON);
+ else if (TREE_CODE (decl) != TYPE_DECL)
+ {
+ /* Propagate anonymity from type to decl. */
+ int tvis = type_visibility (TREE_TYPE (decl));
+ if (tvis == VISIBILITY_ANON)
+ constrain_visibility (decl, tvis);
+ }
+}
+
+/* By default, static data members and function members receive
+ the visibility of their containing class. */
+
+static void
+determine_visibility_from_class (tree decl, tree class_type)
+{
+ if (visibility_options.inlines_hidden
+ /* Don't do this for inline templates; specializations might not be
+ inline, and we don't want them to inherit the hidden
+ visibility. We'll set it here for all inline instantiations. */
+ && !processing_template_decl
+ && ! DECL_VISIBILITY_SPECIFIED (decl)
+ && TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (decl)
+ && (! DECL_LANG_SPECIFIC (decl)
+ || ! DECL_EXPLICIT_INSTANTIATION (decl)))
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ else if (!DECL_VISIBILITY_SPECIFIED (decl))
+ {
+ /* Default to the class visibility. */
+ DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
+ DECL_VISIBILITY_SPECIFIED (decl)
+ = CLASSTYPE_VISIBILITY_SPECIFIED (class_type);
+ }
+
+ /* Give the target a chance to override the visibility associated
+ with DECL. */
+ if (TREE_CODE (decl) == VAR_DECL
+ && (DECL_TINFO_P (decl)
+ || (DECL_VTABLE_OR_VTT_P (decl)
+ /* Construction virtual tables are not exported because
+ they cannot be referred to from other object files;
+ their name is not standardized by the ABI. */
+ && !DECL_CONSTRUCTION_VTABLE_P (decl)))
+ && TREE_PUBLIC (decl)
+ && !DECL_REALLY_EXTERN (decl)
+ && !DECL_VISIBILITY_SPECIFIED (decl)
+ && !CLASSTYPE_VISIBILITY_SPECIFIED (class_type))
+ targetm.cxx.determine_class_data_visibility (decl);
+}
+
+/* Constrain the visibility of a class TYPE based on the visibility of its
+ field types. Warn if any fields require lesser visibility. */
+
+void
+constrain_class_visibility (tree type)
+{
+ tree binfo;
+ tree t;
+ int i;
+
+ int vis = type_visibility (type);
+
+ if (vis == VISIBILITY_ANON
+ || DECL_IN_SYSTEM_HEADER (TYPE_MAIN_DECL (type)))
+ return;
+
+ /* Don't warn about visibility if the class has explicit visibility. */
+ if (CLASSTYPE_VISIBILITY_SPECIFIED (type))
+ vis = VISIBILITY_INTERNAL;
+
+ for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
+ if (TREE_CODE (t) == FIELD_DECL && TREE_TYPE (t) != error_mark_node)
+ {
+ tree ftype = strip_array_types (TREE_TYPE (t));
+ int subvis = type_visibility (ftype);
+
+ if (subvis == VISIBILITY_ANON)
+ warning (0, "\
+%qT has a field %qD whose type uses the anonymous namespace",
+ type, t);
+ else if (IS_AGGR_TYPE (ftype)
+ && vis < VISIBILITY_HIDDEN
+ && subvis >= VISIBILITY_HIDDEN)
+ warning (OPT_Wattributes, "\
+%qT declared with greater visibility than the type of its field %qD",
+ type, t);
+ }
+
+ binfo = TYPE_BINFO (type);
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, t); ++i)
+ {
+ int subvis = type_visibility (TREE_TYPE (t));
+
+ if (subvis == VISIBILITY_ANON)
+ warning (0, "\
+%qT has a base %qT whose type uses the anonymous namespace",
+ type, TREE_TYPE (t));
+ else if (vis < VISIBILITY_HIDDEN
+ && subvis >= VISIBILITY_HIDDEN)
+ warning (OPT_Wattributes, "\
+%qT declared with greater visibility than its base %qT",
+ type, TREE_TYPE (t));
+ }
}
/* DECL is a FUNCTION_DECL or VAR_DECL. If the object file linkage
/* The generic C++ ABI says that class data is always
COMDAT, even if there is a key function. Some
variants (e.g., the ARM EABI) says that class data
- only has COMDAT linkage if the class data might
- be emitted in more than one translation unit. */
+ only has COMDAT linkage if the class data might be
+ emitted in more than one translation unit. When the
+ key method can be inline and is inline, we still have
+ to arrange for comdat even though
+ class_data_always_comdat is false. */
if (!CLASSTYPE_KEY_METHOD (class_type)
+ || DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (class_type))
|| targetm.cxx.class_data_always_comdat ())
{
/* The ABI requires COMDAT linkage. Normally, we
if (CLASSTYPE_INTERFACE_KNOWN (type)
&& !CLASSTYPE_INTERFACE_ONLY (type))
{
- comdat_p = targetm.cxx.class_data_always_comdat ();
+ comdat_p = (targetm.cxx.class_data_always_comdat ()
+ || (CLASSTYPE_KEY_METHOD (type)
+ && DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (type))));
mark_needed (decl);
if (!flag_weak)
{
comdat_linkage (decl);
}
- /* Give the target a chance to override the visibility associated
- with DECL. */
- if (TREE_CODE (decl) == VAR_DECL
- && (DECL_TINFO_P (decl)
- || (DECL_VTABLE_OR_VTT_P (decl)
- /* Construction virtual tables are not exported because
- they cannot be referred to from other object files;
- their name is not standardized by the ABI. */
- && !DECL_CONSTRUCTION_VTABLE_P (decl)))
- && TREE_PUBLIC (decl)
- && !DECL_REALLY_EXTERN (decl)
- && DECL_VISIBILITY_SPECIFIED (decl)
- && (!class_type || !CLASSTYPE_VISIBILITY_SPECIFIED (class_type)))
- targetm.cxx.determine_class_data_visibility (decl);
-
DECL_INTERFACE_KNOWN (decl) = 1;
}
/* We cannot allow these functions to be elided, even if they do not
have external linkage. And, there's no point in deferring
- compilation of thes functions; they're all going to have to be
+ compilation of these functions; they're all going to have to be
out anyhow. */
DECL_INLINE (current_function_decl) = 0;
DECL_UNINLINABLE (current_function_decl) = 1;
if (initp)
{
if (init)
- finish_expr_stmt (init);
+ finish_expr_stmt (init);
/* If we're using __cxa_atexit, register a function that calls the
- destructor for the object. */
+ destructor for the object. */
if (flag_use_cxa_atexit)
- finish_expr_stmt (register_dtor_fn (decl));
+ finish_expr_stmt (register_dtor_fn (decl));
}
else
finish_expr_stmt (build_cleanup (decl));
node = TREE_CHAIN (node))
/* Do one initialization or destruction. */
one_static_initialization_or_destruction (TREE_VALUE (node),
- TREE_PURPOSE (node), initp);
+ TREE_PURPOSE (node), initp);
/* Finish up the priority if-stmt body. */
finish_then_clause (priority_if_stmt);
static int
generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
{
- location_t *locus = data;
+ location_t *locus = (location_t *) data;
int priority = (int) n->key;
priority_info pi = (priority_info) n->value;
DECL_EXTERNAL appropriately, so there's no need to check
again, and we do not want to clear DECL_EXTERNAL if a
previous call to import_export_decl set it.
-
+
This is done in a separate for cycle, because if some
deferred function is contained in another deferred
function later in deferred_fns varray,
else
{
/* If we have a ctor or this is obj-c++ and we need a static init,
- call generate_ctor_or_dtor_function. */
+ call generate_ctor_or_dtor_function. */
if (static_ctors || (c_dialect_objc () && objc_static_init_needed_p ()))
generate_ctor_or_dtor_function (/*constructor_p=*/true,
DEFAULT_INIT_PRIORITY, &locus);
if (VEC_length (tree, pending_statics) != 0)
{
check_global_declarations (VEC_address (tree, pending_statics),
- VEC_length (tree, pending_statics));
+ VEC_length (tree, pending_statics));
emit_debug_global_declarations (VEC_address (tree, pending_statics),
VEC_length (tree, pending_statics));
}
else if (saw_def)
{
error ("default argument missing for parameter %P of %q+#D", i, x);
- break;
+ TREE_PURPOSE (arg) = error_mark_node;
}
}
}
}
TREE_USED (decl) = 1;
- /* If we don't need a value, then we don't need to synthesize DECL. */
+ if (DECL_CLONED_FUNCTION_P (decl))
+ TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
+ /* If we don't need a value, then we don't need to synthesize DECL. */
if (skip_evaluation)
return;
/* Normally, we can wait until instantiation-time to synthesize
saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
}
-
+
if (processing_template_decl)
- return;
+ return;
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
&& !TREE_ASM_WRITTEN (decl))
{
synthesize_method (decl);
/* If we've already synthesized the method we don't need to
- instantiate it, so we can return right away. */
- return;
- }
-
- /* If this is a function or variable that is an instance of some
- template, we now know that we will need to actually do the
- instantiation. We check that DECL is not an explicit
- instantiation because that is not checked in instantiate_decl. */
- if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
- && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
- && (!DECL_EXPLICIT_INSTANTIATION (decl)
- || (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_INLINE (DECL_TEMPLATE_RESULT
- (template_for_substitution (decl))))
- /* We need to instantiate static data members so that there
- initializers are available in integral constant
- expressions. */
- || (TREE_CODE (decl) == VAR_DECL
- && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))))
- /* We put off instantiating functions in order to improve compile
+ do the instantiation test below. */
+ }
+ else if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
+ && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
+ && (!DECL_EXPLICIT_INSTANTIATION (decl)
+ || (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_INLINE (DECL_TEMPLATE_RESULT
+ (template_for_substitution (decl))))
+ /* We need to instantiate static data members so that there
+ initializers are available in integral constant
+ expressions. */
+ || (TREE_CODE (decl) == VAR_DECL
+ && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))))
+ /* If this is a function or variable that is an instance of some
+ template, we now know that we will need to actually do the
+ instantiation. We check that DECL is not an explicit
+ instantiation because that is not checked in instantiate_decl.
+
+ We put off instantiating functions in order to improve compile
times. Maintaining a stack of active functions is expensive,
and the inliner knows to instantiate any functions it might
- need. */
- instantiate_decl (decl, /*defer_ok=*/true,
+ need. Therefore, we always try to defer instantiation. */
+ instantiate_decl (decl, /*defer_ok=*/true,
/*expl_inst_class_mem_p=*/false);
processing_template_decl = saved_processing_template_decl;