/* 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
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
-#include "rtl.h"
-#include "expr.h"
#include "flags.h"
#include "cp-tree.h"
#include "decl.h"
#include "output.h"
-#include "except.h"
#include "toplev.h"
#include "timevar.h"
#include "cpplib.h"
#include "target.h"
-#include "c-common.h"
+#include "c-family/c-common.h"
#include "tree-mudflap.h"
#include "cgraph.h"
#include "tree-inline.h"
-#include "c-pragma.h"
+#include "c-family/c-pragma.h"
#include "tree-dump.h"
#include "intl.h"
#include "gimple.h"
#include "pointer-set.h"
+#include "splay-tree.h"
+#include "langhooks.h"
+#include "c-family/c-ada-spec.h"
extern cpp_reader *parse_in;
return fntype;
}
+/* Return a variant of FNTYPE, a FUNCTION_TYPE or METHOD_TYPE, with its
+ return type changed to NEW_RET. */
+
+tree
+change_return_type (tree new_ret, tree fntype)
+{
+ tree newtype;
+ tree args = TYPE_ARG_TYPES (fntype);
+ tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
+ tree attrs = TYPE_ATTRIBUTES (fntype);
+
+ if (same_type_p (new_ret, TREE_TYPE (fntype)))
+ return fntype;
+
+ if (TREE_CODE (fntype) == FUNCTION_TYPE)
+ {
+ newtype = build_function_type (new_ret, args);
+ newtype = apply_memfn_quals (newtype, type_memfn_quals (fntype));
+ }
+ else
+ newtype = build_method_type_directly
+ (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))),
+ new_ret, TREE_CHAIN (args));
+ if (raises)
+ newtype = build_exception_variant (newtype, raises);
+ if (attrs)
+ newtype = cp_build_type_attribute_variant (newtype, attrs);
+
+ return newtype;
+}
+
/* Build a PARM_DECL with NAME and TYPE, and set DECL_ARG_TYPE
appropriately. */
basetype = TREE_TYPE (TREE_VALUE (arg_types));
arg_types = TREE_CHAIN (arg_types);
- parms = TREE_CHAIN (DECL_ARGUMENTS (fn));
+ parms = DECL_CHAIN (DECL_ARGUMENTS (fn));
/* If this is a subobject constructor or destructor, our caller will
pass us a pointer to our VTT. */
parm = build_artificial_parm (vtt_parm_identifier, vtt_parm_type);
/* First add it to DECL_ARGUMENTS between 'this' and the real args... */
- TREE_CHAIN (parm) = parms;
+ DECL_CHAIN (parm) = parms;
parms = parm;
/* ...and then to TYPE_ARG_TYPES. */
/* Then add the in-charge parm (before the VTT parm). */
parm = build_artificial_parm (in_charge_identifier, integer_type_node);
- TREE_CHAIN (parm) = parms;
+ DECL_CHAIN (parm) = parms;
parms = parm;
arg_types = hash_tree_chain (integer_type_node, arg_types);
/* Insert our new parameter(s) into the list. */
- TREE_CHAIN (DECL_ARGUMENTS (fn)) = parms;
+ DECL_CHAIN (DECL_ARGUMENTS (fn)) = parms;
/* And rebuild the function type. */
fntype = build_method_type_directly (basetype, TREE_TYPE (TREE_TYPE (fn)),
permerror (input_location, "local class %q#T shall not have static data member %q#D",
current_class_type, decl);
- /* Static consts need not be initialized in the class definition. */
- if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
- {
- static int explained = 0;
-
- error ("initializer invalid for static member with constructor");
- if (!explained)
- {
- error ("(an out of class initialization is required)");
- explained = 1;
- }
- init = NULL_TREE;
- }
-
- DECL_INITIAL (decl) = init;
DECL_IN_AGGR_P (decl) = 1;
+ if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
+ && TYPE_DOMAIN (TREE_TYPE (decl)) == NULL_TREE)
+ SET_VAR_HAD_UNKNOWN_BOUND (decl);
+
cp_finish_decl (decl, init, init_const_expr_p, asmspec_tree, flags);
}
}
else if (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE)
{
- gcc_assert (error_operand_p (init) || integer_zerop (init));
- DECL_PURE_VIRTUAL_P (value) = 1;
+ if (integer_zerop (init))
+ DECL_PURE_VIRTUAL_P (value) = 1;
+ else if (error_operand_p (init))
+ ; /* An error has already been reported. */
+ else
+ error ("invalid initializer for member function %qD",
+ value);
}
else
{
{
if (TREE_CODE (init) == CONSTRUCTOR)
init = digest_init (TREE_TYPE (value), init);
- else
- init = integral_constant_value (init);
+ init = maybe_constant_init (init);
if (init != error_mark_node && !TREE_CONSTANT (init))
{
if (width != error_mark_node)
{
+ /* The width must be an integer type. */
+ if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (width)))
+ error ("width of bit-field %qD has non-integral type %qT", value,
+ TREE_TYPE (width));
constant_expression_warning (width);
DECL_INITIAL (value) = width;
SET_DECL_C_BIT_FIELD (value);
{
inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
outer = build_function_type (inner, TYPE_ARG_TYPES (type));
+ outer = apply_memfn_quals (outer, type_memfn_quals (type));
}
else if (TREE_CODE (type) == METHOD_TYPE)
{
if (TYPE_ATTRIBUTES (type))
outer = cp_build_type_attribute_variant (outer, TYPE_ATTRIBUTES (type));
- return cp_build_qualified_type (outer, TYPE_QUALS (type));
+ return cp_build_qualified_type (outer, cp_type_quals (type));
}
/* Like decl_attributes, but handle C++ complexity. */
for (field = TYPE_FIELDS (type);
field != NULL_TREE;
- field = TREE_CHAIN (field))
+ field = DECL_CHAIN (field))
{
tree decl;
tree ref;
}
}
- if (DECL_LANG_SPECIFIC (decl))
- DECL_COMDAT (decl) = 1;
+ DECL_COMDAT (decl) = 1;
}
/* For win32 we also want to put explicit instantiations in
}
}
-/* Returns true iff DECL, a FUNCTION_DECL, has vague linkage. This
- predicate will give the right answer during parsing of the function,
- which other tests may not. */
+/* Returns true iff DECL, a FUNCTION_DECL or VAR_DECL, has vague linkage.
+ This predicate will give the right answer during parsing of the
+ function, which other tests may not. */
bool
-vague_linkage_fn_p (tree fn)
+vague_linkage_p (tree decl)
{
/* Unfortunately, import_export_decl has not always been called
before the function is processed, so we cannot simply check
DECL_COMDAT. */
- return (DECL_COMDAT (fn)
- || ((DECL_DECLARED_INLINE_P (fn)
- || DECL_TEMPLATE_INSTANTIATION (fn))
- && TREE_PUBLIC (fn)));
+ return (DECL_COMDAT (decl)
+ || (((TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (decl))
+ || (DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_INSTANTIATION (decl)))
+ && TREE_PUBLIC (decl)));
}
/* Determine whether or not we want to specifically import or export CTYPE,
tree vtbl;
tree primary_vtbl;
int needed = 0;
+ struct varpool_node *current = NULL, *last = NULL, *first = NULL;
/* If the vtables for this class have already been emitted there is
nothing more to do. */
determine_key_method (ctype);
/* See if any of the vtables are needed. */
- for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
+ for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = DECL_CHAIN (vtbl))
{
import_export_decl (vtbl);
if (DECL_NOT_REALLY_EXTERN (vtbl) && decl_needed_p (vtbl))
/* The ABI requires that we emit all of the vtables if we emit any
of them. */
- for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
+ for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = DECL_CHAIN (vtbl))
{
/* Mark entities references from the virtual table as used. */
mark_vtable_entries (vtbl);
actually marking the variable as written. */
if (flag_syntax_only)
TREE_ASM_WRITTEN (vtbl) = 1;
+ else if (DECL_COMDAT (vtbl))
+ {
+ current = varpool_node (vtbl);
+ if (last)
+ last->same_comdat_group = current;
+ 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);
if (CLASSTYPE_VISIBILITY_SPECIFIED (type))
vis = VISIBILITY_INTERNAL;
- for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
+ for (t = TYPE_FIELDS (type); t; t = DECL_CHAIN (t))
if (TREE_CODE (t) == FIELD_DECL && TREE_TYPE (t) != error_mark_node)
{
tree ftype = strip_pointer_or_array_types (TREE_TYPE (t));
TREE_PUBLIC (guard) = TREE_PUBLIC (decl);
TREE_STATIC (guard) = TREE_STATIC (decl);
DECL_COMMON (guard) = DECL_COMMON (decl);
- DECL_COMDAT_GROUP (guard) = DECL_COMDAT_GROUP (decl);
+ DECL_COMDAT (guard) = DECL_COMDAT (decl);
+ if (DECL_ONE_ONLY (decl))
+ make_decl_one_only (guard, cxx_comdat_group (guard));
if (TREE_PUBLIC (decl))
DECL_WEAK (guard) = DECL_WEAK (decl);
DECL_VISIBILITY (guard) = DECL_VISIBILITY (decl);
fndecl = build_lang_decl (FUNCTION_DECL,
get_file_function_name (type),
- build_function_type (void_type_node,
- void_list_node));
+ build_function_type_list (void_type_node,
+ NULL_TREE));
start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED);
TREE_PUBLIC (current_function_decl) = 0;
static tree
start_static_storage_duration_function (unsigned count)
{
- tree parm_types;
tree type;
tree body;
char id[sizeof (SSDF_IDENTIFIER) + 1 /* '\0' */ + 32];
SSDF_IDENTIFIER_<number>. */
sprintf (id, "%s_%u", SSDF_IDENTIFIER, count);
- /* Create the parameters. */
- parm_types = void_list_node;
- parm_types = tree_cons (NULL_TREE, integer_type_node, parm_types);
- parm_types = tree_cons (NULL_TREE, integer_type_node, parm_types);
- type = build_function_type (void_type_node, parm_types);
+ type = build_function_type_list (void_type_node,
+ integer_type_node, integer_type_node,
+ NULL_TREE);
/* Create the FUNCTION_DECL itself. */
ssdf_decl = build_lang_decl (FUNCTION_DECL,
DECL_CONTEXT (priority_decl) = ssdf_decl;
TREE_USED (priority_decl) = 1;
- TREE_CHAIN (initialize_p_decl) = priority_decl;
+ DECL_CHAIN (initialize_p_decl) = priority_decl;
DECL_ARGUMENTS (ssdf_decl) = initialize_p_decl;
/* Put the function in the global scope. */
{
tree var;
- for (var = BIND_EXPR_VARS (*node); var; var = TREE_CHAIN (var))
+ for (var = BIND_EXPR_VARS (*node); var; var = DECL_CHAIN (var))
if (TREE_CODE (var) == VAR_DECL
&& !DECL_NAME (var)
&& DECL_ARTIFICIAL (var)
location_t *locus)
{
char function_key;
- tree arguments;
tree fndecl;
tree body;
size_t i;
/* Call the static storage duration function with appropriate
arguments. */
- for (i = 0; VEC_iterate (tree, ssdf_decls, i, fndecl); ++i)
+ FOR_EACH_VEC_ELT (tree, ssdf_decls, i, fndecl)
{
/* Calls to pure or const functions will expand to nothing. */
if (! (flags_from_decl_or_type (fndecl) & (ECF_CONST | ECF_PURE)))
{
+ tree call;
+
if (! body)
body = start_objects (function_key, priority);
- arguments = tree_cons (NULL_TREE,
- build_int_cst (NULL_TREE, priority),
- NULL_TREE);
- arguments = tree_cons (NULL_TREE,
- build_int_cst (NULL_TREE, constructor_p),
- arguments);
- finish_expr_stmt (cp_build_function_call (fndecl, arguments,
- tf_warning_or_error));
+ call = cp_build_function_call_nary (fndecl, tf_warning_or_error,
+ build_int_cst (NULL_TREE,
+ constructor_p),
+ build_int_cst (NULL_TREE,
+ priority),
+ NULL_TREE);
+ finish_expr_stmt (call);
}
}
cgraph_mark_address_taken_node (cgraph_node (BASELINK_FUNCTIONS (t)));
break;
case VAR_DECL:
- if (DECL_VTABLE_OR_VTT_P (t))
- {
- /* The ABI requires that all virtual tables be emitted
- whenever one of them is. */
- tree vtbl;
- for (vtbl = CLASSTYPE_VTABLES (DECL_CONTEXT (t));
- vtbl;
- vtbl = TREE_CHAIN (vtbl))
- mark_decl_referenced (vtbl);
- }
- else if (DECL_CONTEXT (t)
- && flag_use_repository
- && TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_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));
}
}
+/* Return C++ property of T, based on given operation OP. */
+
+static int
+cpp_check (tree t, cpp_operation op)
+{
+ switch (op)
+ {
+ case IS_ABSTRACT:
+ return DECL_PURE_VIRTUAL_P (t);
+ case IS_CONSTRUCTOR:
+ return DECL_CONSTRUCTOR_P (t);
+ case IS_DESTRUCTOR:
+ return DECL_DESTRUCTOR_P (t);
+ case IS_COPY_CONSTRUCTOR:
+ return DECL_COPY_CONSTRUCTOR_P (t);
+ case IS_TEMPLATE:
+ return TREE_CODE (t) == TEMPLATE_DECL;
+ default:
+ return 0;
+ }
+}
+
+/* Collect source file references recursively, starting from NAMESPC. */
+
+static void
+collect_source_refs (tree namespc)
+{
+ tree t;
+
+ if (!namespc)
+ return;
+
+ /* Iterate over names in this name space. */
+ for (t = NAMESPACE_LEVEL (namespc)->names; t; t = TREE_CHAIN (t))
+ if (!DECL_IS_BUILTIN (t) )
+ collect_source_ref (DECL_SOURCE_FILE (t));
+
+ /* Dump siblings, if any */
+ collect_source_refs (TREE_CHAIN (namespc));
+
+ /* Dump children, if any */
+ collect_source_refs (NAMESPACE_LEVEL (namespc)->namespaces);
+}
+
+/* Collect decls relevant to SOURCE_FILE from all namespaces recursively,
+ starting from NAMESPC. */
+
+static void
+collect_ada_namespace (tree namespc, const char *source_file)
+{
+ if (!namespc)
+ return;
+
+ /* Collect decls from this namespace */
+ collect_ada_nodes (NAMESPACE_LEVEL (namespc)->names, source_file);
+
+ /* Collect siblings, if any */
+ collect_ada_namespace (TREE_CHAIN (namespc), source_file);
+
+ /* Collect children, if any */
+ collect_ada_namespace (NAMESPACE_LEVEL (namespc)->namespaces, source_file);
+}
+
/* Returns true iff there is a definition available for variable or
function DECL. */
}
}
+/* Nonzero for a VAR_DECL whose value can be used in a constant expression.
+
+ [expr.const]
+
+ An integral constant-expression can only involve ... const
+ variables of integral or enumeration types initialized with
+ constant expressions ...
+
+ C++0x also allows constexpr variables and temporaries initialized
+ with constant expressions. We handle the former here, but the latter
+ are just folded away in cxx_eval_constant_expression.
+
+ The standard does not require that the expression be non-volatile.
+ G++ implements the proposed correction in DR 457. */
+
+bool
+decl_constant_var_p (tree decl)
+{
+ bool ret;
+ tree type = TREE_TYPE (decl);
+ if (TREE_CODE (decl) != VAR_DECL)
+ return false;
+ if (DECL_DECLARED_CONSTEXPR_P (decl))
+ ret = true;
+ else if (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. */
+ mark_used (decl);
+ ret = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl);
+ }
+ else
+ ret = false;
+
+ gcc_assert (!ret || DECL_INITIAL (decl));
+ return ret;
+}
+
+/* Returns true if DECL could be a symbolic constant variable, depending on
+ its initializer. */
+
+bool
+decl_maybe_constant_var_p (tree decl)
+{
+ tree type = TREE_TYPE (decl);
+ if (TREE_CODE (decl) != VAR_DECL)
+ return false;
+ if (DECL_DECLARED_CONSTEXPR_P (decl))
+ return true;
+ return (CP_TYPE_CONST_NON_VOLATILE_P (type)
+ && INTEGRAL_OR_ENUMERATION_TYPE_P (type));
+}
+
/* Complain that DECL uses a type with no linkage but is never defined. */
static void
"is used but never defined", decl, t);
}
+/* Collect declarations from all namespaces relevant to SOURCE_FILE. */
+
+static void
+collect_all_refs (const char *source_file)
+{
+ collect_ada_namespace (global_namespace, source_file);
+}
+
/* 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
at_eof = 1;
/* Bad parse errors. Just forget about it. */
- if (! global_bindings_p () || current_class_type || decl_namespace_list)
+ if (! global_bindings_p () || current_class_type
+ || !VEC_empty (tree,decl_namespace_list))
return;
if (pch_file)
c_common_write_pch ();
+ /* Handle -fdump-ada-spec[-slim] */
+ if (dump_enabled_p (TDI_ada))
+ {
+ if (get_dump_file_info (TDI_ada)->flags & TDF_SLIM)
+ collect_source_ref (main_input_filename);
+ else
+ collect_source_refs (global_namespace);
+
+ dump_ada_specs (collect_all_refs, cpp_check);
+ }
+
/* FIXME - huh? was input_line -= 1;*/
/* We now have to write out all the stuff we put off writing out.
/* Go through the set of inline functions whose bodies have not
been emitted yet. If out-of-line copies of these functions
are required, emit them. */
- for (i = 0; VEC_iterate (tree, deferred_fns, i, decl); ++i)
+ FOR_EACH_VEC_ELT (tree, deferred_fns, i, decl)
{
/* Does it need synthesizing? */
if (DECL_DEFAULTED_FN (decl) && ! DECL_INITIAL (decl)
if (DECL_NOT_REALLY_EXTERN (decl)
&& DECL_INITIAL (decl)
&& decl_needed_p (decl))
- DECL_EXTERNAL (decl) = 0;
+ {
+ struct cgraph_node *node = cgraph_get_node (decl), *alias, *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;
+ }
+ /* 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;
+ 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;
+ }
+ }
+ }
/* If we're going to need to write this function out, and
there's already a body for it, create RTL for it now.
reconsider = true;
/* Static data members are just like namespace-scope globals. */
- for (i = 0; VEC_iterate (tree, pending_statics, i, decl); ++i)
+ FOR_EACH_VEC_ELT (tree, pending_statics, i, decl)
{
if (var_finalized_p (decl) || DECL_REALLY_EXTERN (decl)
/* Don't write it out if we haven't seen a definition. */
while (reconsider);
/* All used inline functions must have a definition at this point. */
- for (i = 0; VEC_iterate (tree, deferred_fns, i, decl); ++i)
+ FOR_EACH_VEC_ELT (tree, deferred_fns, i, decl)
{
if (/* Check online inline functions that were actually used. */
DECL_ODR_USED (decl) && DECL_DECLARED_INLINE_P (decl)
}
/* So must decls that use a type with no linkage. */
- for (i = 0; VEC_iterate (tree, no_linkage_decls, i, decl); ++i)
+ FOR_EACH_VEC_ELT (tree, no_linkage_decls, i, decl)
if (!decl_defined_p (decl))
no_linkage_error (decl);
+ /* Then, do the Objective-C stuff. This is where all the
+ Objective-C module stuff gets generated (symtab,
+ class/protocol/selector lists etc). This must be done after C++
+ templates, destructors etc. so that selectors used in C++
+ templates are properly allocated. */
+ if (c_dialect_objc ())
+ objc_write_global_declarations ();
+
/* We give C linkage to static constructors and destructors. */
push_lang_context (lang_name_c);
VEC_length (tree, pending_statics));
}
+ perform_deferred_noexcept_checks ();
+
/* Generate hidden aliases for Java. */
if (candidates)
{
make_args_non_dependent (*args);
object = build_non_dependent_expr (object);
if (TREE_CODE (fn) == DOTSTAR_EXPR)
- object = cp_build_unary_op (ADDR_EXPR, object, 0, tf_warning_or_error);
+ object = cp_build_addr_expr (object, tf_warning_or_error);
VEC_safe_insert (tree, gc, *args, 0, object);
/* Now that the arguments are done, transform FN. */
fn = build_non_dependent_expr (fn);
void B::g() { (this->*p)(); } */
if (TREE_CODE (fn) == OFFSET_REF)
{
- tree object_addr = cp_build_unary_op (ADDR_EXPR, object, 0,
- tf_warning_or_error);
+ tree object_addr = cp_build_addr_expr (object, tf_warning_or_error);
fn = TREE_OPERAND (fn, 1);
fn = get_member_function_from_ptrfunc (&object_addr, fn);
VEC_safe_insert (tree, gc, *args, 0, object_addr);
void
mark_used (tree decl)
{
- HOST_WIDE_INT saved_processing_template_decl = 0;
-
/* 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
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DELETED_FN (decl))
{
- error ("deleted function %q+D", decl);
- error ("used here");
+ if (DECL_ARTIFICIAL (decl))
+ {
+ if (DECL_OVERLOADED_OPERATOR_P (decl) == TYPE_EXPR
+ && LAMBDA_TYPE_P (DECL_CONTEXT (decl)))
+ {
+ /* We mark a lambda conversion op as deleted if we can't
+ generate it properly; see maybe_add_lambda_conv_op. */
+ sorry ("converting lambda which uses %<...%> to "
+ "function pointer");
+ return;
+ }
+ }
+ error ("use of deleted function %qD", decl);
+ if (!maybe_explain_implicit_delete (decl))
+ error_at (DECL_SOURCE_LOCATION (decl), "declared here");
return;
}
- /* If we don't need a value, then we don't need to synthesize DECL. */
- if (cp_unevaluated_operand != 0)
- return;
/* We can only check DECL_ODR_USED on variables or functions with
DECL_LANG_SPECIFIC set, and these are also the only decls that we
return;
}
- /* Normally, we can wait until instantiation-time to synthesize
- DECL. However, if DECL is a static data member initialized with
- a constant, we need the value right now because a reference to
- such a data member is not value-dependent. */
- if (TREE_CODE (decl) == VAR_DECL
- && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
- && DECL_CLASS_SCOPE_P (decl))
- {
- /* Don't try to instantiate members of dependent types. We
- cannot just use dependent_type_p here because this function
- may be called from fold_non_dependent_expr, and then we may
- see dependent types, even though processing_template_decl
- will not be set. */
- if (CLASSTYPE_TEMPLATE_INFO ((DECL_CONTEXT (decl)))
- && uses_template_parms (CLASSTYPE_TI_ARGS (DECL_CONTEXT (decl))))
- return;
- /* Pretend that we are not in a template, even if we are, so
- that the static data member initializer will be processed. */
- saved_processing_template_decl = processing_template_decl;
- processing_template_decl = 0;
+ /* 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. */
+ if ((decl_maybe_constant_var_p (decl)
+ || (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_DECLARED_CONSTEXPR_P (decl)))
+ && !DECL_INITIAL (decl)
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_INSTANTIATION (decl))
+ {
+ /* Instantiating a function will result in garbage collection. We
+ must treat this situation as if we were within the body of a
+ function so as to avoid collecting live data only referenced from
+ the stack (such as overload resolution candidates). */
+ ++function_depth;
+ instantiate_decl (decl, /*defer_ok=*/false,
+ /*expl_inst_class_mem_p=*/false);
+ --function_depth;
}
+ /* If we don't need a value, then we don't need to synthesize DECL. */
+ if (cp_unevaluated_operand != 0)
+ return;
+
if (processing_template_decl)
return;
+ /* 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;
+
DECL_ODR_USED (decl) = 1;
if (DECL_CLONED_FUNCTION_P (decl))
DECL_ODR_USED (DECL_CLONED_FUNCTION (decl)) = 1;
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;
}
#include "gt-cp-decl2.h"