/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010,
- 2011 Free Software Foundation, Inc.
+ 2011, 2012 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
#include "flags.h"
#include "cp-tree.h"
#include "decl.h"
-#include "output.h"
#include "toplev.h"
#include "timevar.h"
#include "cpplib.h"
#include "target.h"
#include "c-family/c-common.h"
#include "c-family/c-objc.h"
-#include "tree-mudflap.h"
#include "cgraph.h"
#include "tree-inline.h"
#include "c-family/c-pragma.h"
-#include "tree-dump.h"
+#include "dumpfile.h"
#include "intl.h"
#include "gimple.h"
#include "pointer-set.h"
static void import_export_class (tree);
static tree get_guard_bits (tree);
static void determine_visibility_from_class (tree, tree);
+static bool determine_hidden_inline (tree);
static bool decl_defined_p (tree);
/* A list of static class variables. This is needed, because a
tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
tree attrs = TYPE_ATTRIBUTES (fntype);
+ if (new_ret == error_mark_node)
+ return fntype;
+
if (same_type_p (new_ret, TREE_TYPE (fntype)))
return fntype;
}
else
newtype = build_method_type_directly
- (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))),
- new_ret, TREE_CHAIN (args));
+ (class_of_this_parm (fntype), new_ret, TREE_CHAIN (args));
if (raises)
newtype = build_exception_variant (newtype, raises);
if (attrs)
along the way. */
tree
-grok_array_decl (tree array_expr, tree index_exp)
+grok_array_decl (location_t loc, tree array_expr, tree index_exp)
{
tree type;
tree expr;
{
if (type_dependent_expression_p (array_expr)
|| type_dependent_expression_p (index_exp))
- return build_min_nt (ARRAY_REF, array_expr, index_exp,
- NULL_TREE, NULL_TREE);
+ return build_min_nt_loc (loc, ARRAY_REF, array_expr, index_exp,
+ NULL_TREE, NULL_TREE);
array_expr = build_non_dependent_expr (array_expr);
index_exp = build_non_dependent_expr (index_exp);
}
/* If they have an `operator[]', use that. */
if (MAYBE_CLASS_TYPE_P (type) || MAYBE_CLASS_TYPE_P (TREE_TYPE (index_exp)))
- expr = build_new_op (ARRAY_REF, LOOKUP_NORMAL,
- array_expr, index_exp, NULL_TREE,
- /*overloaded_p=*/NULL, tf_warning_or_error);
+ expr = build_new_op (loc, ARRAY_REF, LOOKUP_NORMAL, array_expr, index_exp,
+ NULL_TREE, /*overload=*/NULL, tf_warning_or_error);
else
{
tree p1, p2, i1, i2;
It is a little-known fact that, if `a' is an array and `i' is
an int, you can write `i[a]', which means the same thing as
`a[i]'. */
- if (TREE_CODE (type) == ARRAY_TYPE)
+ if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE)
p1 = array_expr;
else
p1 = build_expr_type_conversion (WANT_POINTER, array_expr, false);
}
/* An array can't have been allocated by new, so complain. */
- if (TREE_CODE (exp) == VAR_DECL
- && TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
- warning (0, "deleting array %q#D", exp);
+ if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+ warning (0, "deleting array %q#E", exp);
t = build_expr_type_conversion (WANT_POINTER, exp, true);
decl = DECL_TEMPLATE_RESULT (tmpl);
if (TREE_CODE (decl) == FUNCTION_DECL
+ || DECL_ALIAS_TEMPLATE_P (tmpl)
|| (TREE_CODE (decl) == TYPE_DECL
&& MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))))
{
if (! processing_template_decl)
VEC_safe_push (tree, gc, pending_statics, decl);
- if (LOCAL_CLASS_P (current_class_type))
+ if (LOCAL_CLASS_P (current_class_type)
+ /* We already complained about the template definition. */
+ && !DECL_TEMPLATE_INSTANTIATION (decl))
permerror (input_location, "local class %q#T shall not have static data member %q#D",
current_class_type, decl);
{
tree value;
const char *asmspec = 0;
- int flags = LOOKUP_ONLYCONVERTING;
+ int flags;
tree name;
if (init
DECL_NONLOCAL (value) = 1;
DECL_CONTEXT (value) = current_class_type;
- if (processing_template_decl)
- value = push_template_decl (value);
-
if (attrlist)
{
int attrflags = 0;
cplus_decl_attributes (&value, attrlist, attrflags);
}
- if (declspecs->specs[(int)ds_typedef]
+ if (decl_spec_seq_has_spec_p (declspecs, ds_typedef)
&& TREE_TYPE (value) != error_mark_node
&& TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
set_underlying_type (value);
+ /* It's important that push_template_decl below follows
+ set_underlying_type above so that the created template
+ carries the properly set type of VALUE. */
+ if (processing_template_decl)
+ value = push_template_decl (value);
+
+ record_locally_defined_typedef (value);
return value;
}
DECL_DECLARED_INLINE_P (value) = 1;
}
}
+ else if (TREE_CODE (init) == DEFAULT_ARG)
+ error ("invalid initializer for member function %qD", value);
else if (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE)
{
if (integer_zerop (init))
value);
}
}
- else if (pedantic && TREE_CODE (value) != VAR_DECL)
- /* Already complained in grokdeclarator. */
- init = NULL_TREE;
+ else if (TREE_CODE (value) == FIELD_DECL)
+ /* C++11 NSDMI, keep going. */;
+ else if (TREE_CODE (value) != VAR_DECL)
+ gcc_unreachable ();
else if (!processing_template_decl)
{
if (TREE_CODE (init) == CONSTRUCTOR)
- init = digest_init (TREE_TYPE (value), init);
+ init = digest_init (TREE_TYPE (value), init, tf_warning_or_error);
init = maybe_constant_init (init);
if (init != error_mark_node && !TREE_CONSTANT (init))
if (attrlist)
cplus_decl_attributes (&value, attrlist, 0);
+ if (init && BRACE_ENCLOSED_INITIALIZER_P (init)
+ && CONSTRUCTOR_IS_DIRECT_INIT (init))
+ flags = LOOKUP_NORMAL;
+ else
+ flags = LOOKUP_IMPLICIT;
+
switch (TREE_CODE (value))
{
case VAR_DECL:
init = error_mark_node;
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;
if (is_attribute_p ("weak", name))
return true;
+ /* Attribute unused is applied directly, as it appertains to
+ decls. */
+ if (is_attribute_p ("unused", name))
+ return false;
+
/* If any of the arguments are dependent expressions, we can't evaluate
the attribute until instantiation time. */
for (arg = args; arg; arg = TREE_CHAIN (arg))
old_attrs = *q;
- /* Place the late attributes at the beginning of the attribute
+ /* Merge the late attributes at the beginning with the attribute
list. */
- TREE_CHAIN (tree_last (late_attrs)) = *q;
+ late_attrs = merge_attributes (late_attrs, *q);
*q = late_attrs;
if (!DECL_P (*decl_p) && *decl_p == TYPE_MAIN_VARIANT (*decl_p))
so we must compensate by getting rid of it. */
outer
= build_method_type_directly
- (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))),
- inner,
+ (class_of_this_parm (type), inner,
TREE_CHAIN (TYPE_ARG_TYPES (type)));
}
else if (TREE_CODE (type) == OFFSET_TYPE)
/* Rather than write the code to handle the non-union case,
just give an error. */
if (TREE_CODE (type) != UNION_TYPE)
- error ("anonymous struct not inside named type");
+ {
+ error ("anonymous struct not inside named type");
+ return error_mark_node;
+ }
for (field = TYPE_FIELDS (type);
field != NULL_TREE;
permerror (input_location, "protected member %q+#D in anonymous union", field);
if (processing_template_decl)
- ref = build_min_nt (COMPONENT_REF, object,
- DECL_NAME (field), NULL_TREE);
+ ref = build_min_nt_loc (UNKNOWN_LOCATION, COMPONENT_REF, object,
+ DECL_NAME (field), NULL_TREE);
else
ref = build_class_member_access_expr (object, field, NULL_TREE,
false, tf_warning_or_error);
}
pushdecl (anon_union_decl);
- if (building_stmt_tree ()
- && at_function_scope_p ())
- add_decl_expr (anon_union_decl);
- else if (!processing_template_decl)
- rest_of_decl_compilation (anon_union_decl,
- toplevel_bindings_p (), at_eof);
+ cp_finish_decl (anon_union_decl, NULL_TREE, false, NULL_TREE, 0);
}
\f
/* Auxiliary functions to make type signatures for
DECL_COMDAT (decl) = 1;
/* Mark it needed so we don't forget to emit it. */
mark_decl_referenced (decl);
+ TREE_USED (decl) = 1;
}
}
}
void
mark_needed (tree decl)
{
- /* It's possible that we no longer need to set
- TREE_SYMBOL_REFERENCED here directly, but doing so is
- harmless. */
- TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = 1;
+ TREE_USED (decl) = 1;
mark_decl_referenced (decl);
}
return true;
/* If this entity was used, let the back end see it; it will decide
whether or not to emit it into the object file. */
- if (TREE_USED (decl)
- || (DECL_ASSEMBLER_NAME_SET_P (decl)
- && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+ if (TREE_USED (decl))
return true;
/* Functions marked "dllexport" must be emitted so that they are
visible to other DLLs. */
tree vtbl;
tree primary_vtbl;
int needed = 0;
- struct varpool_node *current = NULL, *last = NULL, *first = NULL;
+ struct varpool_node *current = NULL, *last = NULL;
/* If the vtables for this class have already been emitted there is
nothing more to do. */
if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
{
- tree expr = store_init_value (vtbl, DECL_INITIAL (vtbl), LOOKUP_NORMAL);
+ VEC(tree,gc)* cleanups = NULL;
+ tree expr = store_init_value (vtbl, DECL_INITIAL (vtbl), &cleanups,
+ LOOKUP_NORMAL);
/* It had better be all done at compile-time. */
- gcc_assert (!expr);
+ gcc_assert (!expr && !cleanups);
}
/* Write it out. */
actually marking the variable as written. */
if (flag_syntax_only)
TREE_ASM_WRITTEN (vtbl) = 1;
- else if (DECL_COMDAT (vtbl))
+ else if (DECL_ONE_ONLY (vtbl))
{
current = varpool_node (vtbl);
if (last)
- last->same_comdat_group = current;
+ symtab_add_to_same_comdat_group ((symtab_node) current, (symtab_node) last);
last = current;
- if (!first)
- first = current;
}
}
- if (first != last)
- last->same_comdat_group = first;
-
/* Since we're writing out the vtable here, also write the debug
info. */
note_debug_info_needed (ctype);
}
/* Limit the visibility of DECL to VISIBILITY, if not explicitly
- specified (or if VISIBILITY is static). */
+ specified (or if VISIBILITY is static). If TMPL is true, this
+ constraint is for a template argument, and takes precedence
+ over explicitly-specified visibility on the template. */
-static bool
-constrain_visibility (tree decl, int visibility)
+static void
+constrain_visibility (tree decl, int visibility, bool tmpl)
{
if (visibility == VISIBILITY_ANON)
{
}
}
else if (visibility > DECL_VISIBILITY (decl)
- && !DECL_VISIBILITY_SPECIFIED (decl))
+ && (tmpl || !DECL_VISIBILITY_SPECIFIED (decl)))
{
DECL_VISIBILITY (decl) = (enum symbol_visibility) visibility;
- return true;
+ /* This visibility was not specified. */
+ DECL_VISIBILITY_SPECIFIED (decl) = false;
}
- return false;
}
/* Constrain the visibility of DECL based on the visibility of its template
}
}
if (vis)
- constrain_visibility (decl, vis);
+ constrain_visibility (decl, vis, true);
}
}
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))
+ if (DECL_VISIBILITY_SPECIFIED (fn))
{
DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn);
DECL_VISIBILITY_SPECIFIED (decl) =
DECL_VISIBILITY_SPECIFIED (fn);
}
else
- determine_visibility_from_class (decl, DECL_CONTEXT (fn));
+ {
+ if (DECL_CLASS_SCOPE_P (fn))
+ determine_visibility_from_class (decl, DECL_CONTEXT (fn));
+ else if (determine_hidden_inline (fn))
+ {
+ DECL_VISIBILITY (decl) = default_visibility;
+ DECL_VISIBILITY_SPECIFIED (decl) =
+ visibility_options.inpragma;
+ }
+ else
+ {
+ DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn);
+ DECL_VISIBILITY_SPECIFIED (decl) =
+ DECL_VISIBILITY_SPECIFIED (fn);
+ }
+ }
/* Local classes in templates have CLASSTYPE_USE_TEMPLATE set,
but have no TEMPLATE_INFO, so don't try to check it. */
if (underlying_vis == VISIBILITY_ANON
|| (CLASS_TYPE_P (underlying_type)
&& CLASSTYPE_VISIBILITY_SPECIFIED (underlying_type)))
- constrain_visibility (decl, underlying_vis);
+ constrain_visibility (decl, underlying_vis, false);
else
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
}
{
/* tinfo visibility is based on the type it's for. */
constrain_visibility
- (decl, type_visibility (TREE_TYPE (DECL_NAME (decl))));
+ (decl, type_visibility (TREE_TYPE (DECL_NAME (decl))), false);
/* Give the target a chance to override the visibility associated
with DECL. */
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 (determine_hidden_inline (decl))
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ else
+ {
+ /* 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;
+ }
}
}
? TYPE_TEMPLATE_INFO (TREE_TYPE (decl))
: DECL_TEMPLATE_INFO (decl));
tree args = TI_ARGS (tinfo);
+ tree attribs = (TREE_CODE (decl) == TYPE_DECL
+ ? TYPE_ATTRIBUTES (TREE_TYPE (decl))
+ : DECL_ATTRIBUTES (decl));
if (args != error_mark_node)
{
- 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);
+ if (!DECL_VISIBILITY_SPECIFIED (pattern)
+ && determine_hidden_inline (decl))
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ else
+ {
+ 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 (args
+ /* Template argument visibility outweighs #pragma or namespace
+ visibility, but not an explicit attribute. */
+ && !lookup_attribute ("visibility", attribs))
+ {
+ int depth = TMPL_ARGS_DEPTH (args);
+ int class_depth = 0;
+ if (class_type && CLASSTYPE_TEMPLATE_INFO (class_type))
+ class_depth = TMPL_ARGS_DEPTH (CLASSTYPE_TI_ARGS (class_type));
+ if (DECL_VISIBILITY_SPECIFIED (decl))
+ {
+ /* A class template member with explicit visibility
+ overrides the class visibility, so we need to apply
+ all the levels of template args directly. */
+ int i;
+ for (i = 1; i <= depth; ++i)
+ {
+ tree lev = TMPL_ARGS_LEVEL (args, i);
+ constrain_visibility_for_template (decl, lev);
+ }
+ }
+ else if (depth > class_depth)
+ /* Limit visibility based on its template arguments. */
+ constrain_visibility_for_template (decl, args);
+ }
}
}
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);
+ constrain_visibility (decl, VISIBILITY_ANON, false);
else if (TREE_CODE (decl) != TYPE_DECL)
{
/* Propagate anonymity from type to decl. */
int tvis = type_visibility (TREE_TYPE (decl));
if (tvis == VISIBILITY_ANON
|| ! DECL_VISIBILITY_SPECIFIED (decl))
- constrain_visibility (decl, tvis);
+ constrain_visibility (decl, tvis, false);
}
else if (no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/true))
/* DR 757: A type without linkage shall not be used as the type of a
Since non-extern "C" decls need to be defined in the same
translation unit, we can make the type internal. */
- constrain_visibility (decl, VISIBILITY_ANON);
+ constrain_visibility (decl, VISIBILITY_ANON, false);
/* If visibility changed and DECL already has DECL_RTL, ensure
symbol flags are updated. */
if (DECL_VISIBILITY_SPECIFIED (decl))
return;
- 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
- && TREE_CODE (decl) == FUNCTION_DECL
- && DECL_DECLARED_INLINE_P (decl)
- && (! DECL_LANG_SPECIFIC (decl)
- || ! DECL_EXPLICIT_INSTANTIATION (decl)))
+ if (determine_hidden_inline (decl))
DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
else
{
targetm.cxx.determine_class_data_visibility (decl);
}
+/* Returns true iff DECL is an inline that should get hidden visibility
+ because of -fvisibility-inlines-hidden. */
+
+static bool
+determine_hidden_inline (tree decl)
+{
+ return (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
+ && TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (decl)
+ && (! DECL_LANG_SPECIFIC (decl)
+ || ! DECL_EXPLICIT_INSTANTIATION (decl)));
+}
+
/* Constrain the visibility of a class TYPE based on the visibility of its
field types. Warn if any fields require lesser visibility. */
it's DECL_CONTECT() properly set. */
static tree
fix_temporary_vars_context_r (tree *node,
- int *unused ATTRIBUTE_UNUSED,
- void *unused1 ATTRIBUTE_UNUSED)
+ int * /*unused*/,
+ void * /*unused1*/)
{
gcc_assert (current_function_decl);
return 0;
}
-/* Called via LANGHOOK_CALLGRAPH_ANALYZE_EXPR. It is supposed to mark
- decls referenced from front-end specific constructs; it will be called
- only for language-specific tree nodes.
-
- Here we must deal with member pointers. */
-
-tree
-cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED)
-{
- tree t = *tp;
-
- switch (TREE_CODE (t))
- {
- case PTRMEM_CST:
- if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
- cgraph_mark_address_taken_node (
- cgraph_get_create_node (PTRMEM_CST_MEMBER (t)));
- break;
- case BASELINK:
- if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL)
- cgraph_mark_address_taken_node (
- cgraph_get_create_node (BASELINK_FUNCTIONS (t)));
- break;
- case VAR_DECL:
- if (DECL_CONTEXT (t)
- && flag_use_repository
- && TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)
- /* If we need a static variable in a function, then we
- need the containing function. */
- mark_decl_referenced (DECL_CONTEXT (t));
- break;
- default:
- break;
- }
-
- return NULL;
-}
-
/* Java requires that we be able to reference a local address for a
method, and not be confused by PLT entries. If hidden aliases are
supported, collect and return all the functions for which we should
return candidates;
#endif
- for (node = cgraph_nodes; node ; node = node->next)
+ FOR_EACH_FUNCTION (node)
{
- tree fndecl = node->decl;
+ tree fndecl = node->symbol.decl;
if (DECL_CONTEXT (fndecl)
&& TYPE_P (DECL_CONTEXT (fndecl))
return;
#endif
- for (node = cgraph_nodes; node ; node = node->next)
+ FOR_EACH_FUNCTION (node)
{
- tree fndecl = node->decl;
+ tree fndecl = node->symbol.decl;
if (TREE_ASM_WRITTEN (fndecl)
&& pointer_set_contains (candidates, fndecl))
bool
decl_constant_var_p (tree decl)
{
- bool ret;
- tree type = TREE_TYPE (decl);
- if (TREE_CODE (decl) != VAR_DECL)
+ if (!decl_maybe_constant_var_p (decl))
return false;
- if (DECL_DECLARED_CONSTEXPR_P (decl)
- || (CP_TYPE_CONST_NON_VOLATILE_P (type)
- && INTEGRAL_OR_ENUMERATION_TYPE_P (type)))
- {
- /* We don't know if a template static data member is initialized with
- a constant expression until we instantiate its initializer. Even
- in the case of a constexpr variable, we can't treat it as a
- constant until its initializer is complete in case it's used in
- its own initializer. */
- mark_used (decl);
- ret = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl);
- }
- else
- ret = false;
- return ret;
+ /* We don't know if a template static data member is initialized with
+ a constant expression until we instantiate its initializer. Even
+ in the case of a constexpr variable, we can't treat it as a
+ constant until its initializer is complete in case it's used in
+ its own initializer. */
+ mark_used (decl);
+ return DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl);
}
/* Returns true if DECL could be a symbolic constant variable, depending on
collect_ada_namespace (global_namespace, source_file);
}
+/* Clear DECL_EXTERNAL for NODE. */
+
+static bool
+clear_decl_external (struct cgraph_node *node, void * /*data*/)
+{
+ DECL_EXTERNAL (node->symbol.decl) = 0;
+ return false;
+}
+
/* This routine is called at the end of compilation.
Its job is to create all the code needed to initialize and
destroy the global aggregates. We do the destruction
if (pch_file)
c_common_write_pch ();
+ cgraph_process_same_body_aliases ();
+
/* Handle -fdump-ada-spec[-slim] */
if (dump_enabled_p (TDI_ada))
{
/* FIXME - huh? was input_line -= 1;*/
+ timevar_start (TV_PHASE_DEFERRED);
+
/* We now have to write out all the stuff we put off writing out.
These include:
generating the initializer for an object may cause templates to be
instantiated, etc., etc. */
- timevar_push (TV_VARCONST);
-
emit_support_tinfos ();
do
&& DECL_INITIAL (decl)
&& decl_needed_p (decl))
{
- struct cgraph_node *node = cgraph_get_node (decl), *alias, *next;
+ struct cgraph_node *node, *next;
- DECL_EXTERNAL (decl) = 0;
- /* If we mark !DECL_EXTERNAL one of the same body aliases,
- we need to mark all of them that way. */
- if (node && node->same_body)
- {
- DECL_EXTERNAL (node->decl) = 0;
- for (alias = node->same_body; alias; alias = alias->next)
- DECL_EXTERNAL (alias->decl) = 0;
- }
+ node = cgraph_get_node (decl);
+ if (node->same_body_alias)
+ node = cgraph_alias_aliased_node (node);
+
+ cgraph_for_node_and_aliases (node, clear_decl_external,
+ NULL, true);
/* If we mark !DECL_EXTERNAL one of the symbols in some comdat
group, we need to mark all symbols in the same comdat group
that way. */
- if (node->same_comdat_group)
- for (next = node->same_comdat_group;
+ if (node->symbol.same_comdat_group)
+ for (next = cgraph (node->symbol.same_comdat_group);
next != node;
- next = next->same_comdat_group)
- {
- DECL_EXTERNAL (next->decl) = 0;
- if (next->same_body)
- {
- for (alias = next->same_body;
- alias;
- alias = alias->next)
- DECL_EXTERNAL (alias->decl) = 0;
- }
- }
+ next = cgraph (next->symbol.same_comdat_group))
+ cgraph_for_node_and_aliases (next, clear_decl_external,
+ NULL, true);
}
/* If we're going to need to write this function out, and
#pragma interface, etc.) we decided not to emit the
definition here. */
&& !DECL_INITIAL (decl)
- /* An explicit instantiation can be used to specify
- that the body is in another unit. It will have
- already verified there was a definition. */
- && !DECL_EXPLICIT_INSTANTIATION (decl))
+ /* Don't complain if the template was defined. */
+ && !(DECL_TEMPLATE_INSTANTIATION (decl)
+ && DECL_INITIAL (DECL_TEMPLATE_RESULT
+ (template_for_substitution (decl)))))
{
warning (0, "inline function %q+D used but never defined", decl);
/* Avoid a duplicate warning from check_global_declaration_1. */
/* Collect candidates for Java hidden aliases. */
candidates = collect_candidates_for_java_method_aliases ();
- cgraph_finalize_compilation_unit ();
+ timevar_stop (TV_PHASE_DEFERRED);
+ timevar_start (TV_PHASE_OPT_GEN);
+
+ finalize_compilation_unit ();
+
+ timevar_stop (TV_PHASE_OPT_GEN);
+ timevar_start (TV_PHASE_CHECK_DBGINFO);
/* Now, issue warnings about static, but not defined, functions,
etc., and emit debugging information. */
}
}
- timevar_pop (TV_VARCONST);
-
if (flag_detailed_statistics)
{
dump_tree_statistics ();
#ifdef ENABLE_CHECKING
validate_conversion_obstack ();
#endif /* ENABLE_CHECKING */
+
+ timevar_stop (TV_PHASE_CHECK_DBGINFO);
}
/* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the
ARGS. */
tree
-build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args)
+build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args,
+ tsubst_flags_t complain)
{
tree orig_fn;
VEC(tree,gc) *orig_args = NULL;
if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
{
if (TREE_CODE (fn) == DOTSTAR_EXPR)
- object = cp_build_addr_expr (object, tf_warning_or_error);
+ object = cp_build_addr_expr (object, complain);
VEC_safe_insert (tree, gc, *args, 0, object);
}
/* Now that the arguments are done, transform FN. */
void B::g() { (this->*p)(); } */
if (TREE_CODE (fn) == OFFSET_REF)
{
- tree object_addr = cp_build_addr_expr (object, tf_warning_or_error);
+ tree object_addr = cp_build_addr_expr (object, complain);
fn = TREE_OPERAND (fn, 1);
- fn = get_member_function_from_ptrfunc (&object_addr, fn);
+ fn = get_member_function_from_ptrfunc (&object_addr, fn,
+ complain);
VEC_safe_insert (tree, gc, *args, 0, object_addr);
}
if (CLASS_TYPE_P (TREE_TYPE (fn)))
- expr = build_op_call (fn, args, tf_warning_or_error);
+ expr = build_op_call (fn, args, complain);
else
- expr = cp_build_function_call_vec (fn, args, tf_warning_or_error);
+ expr = cp_build_function_call_vec (fn, args, complain);
if (processing_template_decl && expr != error_mark_node)
expr = build_min_non_dep_call_vec (expr, orig_fn, orig_args);
/* Mark DECL (either a _DECL or a BASELINK) as "used" in the program.
If DECL is a specialization or implicitly declared class member,
- generate the actual definition. */
+ generate the actual definition. Return false if something goes
+ wrong, true otherwise. */
-void
+bool
mark_used (tree decl)
{
/* If DECL is a BASELINK for a single function, then treat it just
like the DECL for the function. Otherwise, if the BASELINK is
for an overloaded function, we don't know which function was
actually used until after overload resolution. */
- if (TREE_CODE (decl) == BASELINK)
+ if (BASELINK_P (decl))
{
decl = BASELINK_FUNCTIONS (decl);
if (really_overloaded_fn (decl))
- return;
+ return true;
decl = OVL_CURRENT (decl);
}
if (DECL_CLONED_FUNCTION_P (decl))
TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
+ /* Mark enumeration types as used. */
+ if (TREE_CODE (decl) == CONST_DECL)
+ used_types_insert (DECL_CONTEXT (decl));
+
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DELETED_FN (decl))
{
generate it properly; see maybe_add_lambda_conv_op. */
sorry ("converting lambda which uses %<...%> to "
"function pointer");
- return;
+ return false;
}
}
error ("use of deleted function %qD", decl);
if (!maybe_explain_implicit_delete (decl))
error_at (DECL_SOURCE_LOCATION (decl), "declared here");
- return;
+ return false;
}
/* We can only check DECL_ODR_USED on variables or functions with
if ((TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
|| DECL_LANG_SPECIFIC (decl) == NULL
|| DECL_THUNK_P (decl))
- return;
+ {
+ if (!processing_template_decl && type_uses_auto (TREE_TYPE (decl)))
+ {
+ error ("use of %qD before deduction of %<auto%>", decl);
+ return false;
+ }
+ return true;
+ }
/* We only want to do this processing once. We don't need to keep trying
to instantiate inline templates, because unit-at-a-time will make sure
we get them compiled before functions that want to inline them. */
if (DECL_ODR_USED (decl))
- return;
+ return true;
/* If within finish_function, defer the rest until that function
finishes, otherwise it might recurse. */
if (defer_mark_used_calls)
{
VEC_safe_push (tree, gc, deferred_mark_used_calls, decl);
- return;
+ return true;
}
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ maybe_instantiate_noexcept (decl);
+
/* Normally, we can wait until instantiation-time to synthesize DECL.
However, if DECL is a static data member initialized with a constant
or a constexpr function, we need it right now because a reference to
- such a data member or a call to such function is not value-dependent. */
+ such a data member or a call to such function is not value-dependent.
+ For a function that uses auto in the return type, we need to instantiate
+ it to find out its type. */
if ((decl_maybe_constant_var_p (decl)
|| (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_DECLARED_CONSTEXPR_P (decl)))
- && !DECL_INITIAL (decl)
+ && (DECL_DECLARED_CONSTEXPR_P (decl)
+ || type_uses_auto (TREE_TYPE (TREE_TYPE (decl))))))
&& DECL_LANG_SPECIFIC (decl)
- && DECL_TEMPLATE_INSTANTIATION (decl))
+ && DECL_TEMPLATE_INFO (decl)
+ && !uses_template_parms (DECL_TI_ARGS (decl)))
{
/* Instantiating a function will result in garbage collection. We
must treat this situation as if we were within the body of a
--function_depth;
}
+ if (type_uses_auto (TREE_TYPE (decl)))
+ {
+ error ("use of %qD before deduction of %<auto%>", decl);
+ return false;
+ }
+
/* If we don't need a value, then we don't need to synthesize DECL. */
if (cp_unevaluated_operand != 0)
- return;
+ return true;
if (processing_template_decl)
- return;
+ return true;
/* Check this too in case we're within fold_non_dependent_expr. */
if (DECL_TEMPLATE_INFO (decl)
&& uses_template_parms (DECL_TI_ARGS (decl)))
- return;
+ return true;
DECL_ODR_USED (decl) = 1;
if (DECL_CLONED_FUNCTION_P (decl))
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
&& DECL_DEFAULTED_FN (decl)
+ /* A function defaulted outside the class is synthesized either by
+ cp_finish_decl or instantiate_decl. */
+ && !DECL_DEFAULTED_OUTSIDE_CLASS_P (decl)
&& ! DECL_INITIAL (decl))
{
+ /* Defer virtual destructors so that thunks get the right
+ linkage. */
+ if (DECL_VIRTUAL_P (decl) && !at_eof)
+ {
+ note_vague_linkage_fn (decl);
+ return true;
+ }
+
/* Remember the current location for a function we will end up
synthesizing. Then we can inform the user where it was
required in the case of error. */
on the stack (such as overload resolution candidates).
We could just let cp_write_global_declarations handle synthesizing
- this function, since we just added it to deferred_fns, but doing
+ this function by adding it to deferred_fns, but doing
it at the use site produces better error messages. */
++function_depth;
synthesize_method (decl);
times. Maintaining a stack of active functions is expensive,
and the inliner knows to instantiate any functions it might
need. Therefore, we always try to defer instantiation. */
- instantiate_decl (decl, /*defer_ok=*/true,
- /*expl_inst_class_mem_p=*/false);
+ {
+ ++function_depth;
+ instantiate_decl (decl, /*defer_ok=*/true,
+ /*expl_inst_class_mem_p=*/false);
+ --function_depth;
+ }
+
+ return true;
}
#include "gt-cp-decl2.h"